diff --git a/packages/gatsby-remark-images/package.json b/packages/gatsby-remark-images/package.json index 07be9a75590ee..7fabab416130e 100644 --- a/packages/gatsby-remark-images/package.json +++ b/packages/gatsby-remark-images/package.json @@ -12,7 +12,8 @@ "is-relative-url": "^2.0.0", "lodash": "^4.17.4", "slash": "^1.0.0", - "unist-util-select": "^1.5.0" + "unist-util-select": "^1.5.0", + "unist-util-visit-parents": "^2.0.1" }, "devDependencies": { "@babel/cli": "7.0.0-beta.52", diff --git a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap index 1739a79db4e72..2b6a2ce33edab 100644 --- a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap @@ -1,5 +1,75 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`it handles goofy nesting properly 1`] = ` +" + + + \\"test\\" + + + " +`; + +exports[`it leaves images that are already linked alone 1`] = ` +" + + + \\"img\\" + + + " +`; + +exports[`it leaves linked HTML img tags alone 1`] = ` +" + + + + \\"this + + + +" +`; + +exports[`it leaves single-line linked HTML img tags alone 1`] = ` +" + + + \\"this + + + " +`; + exports[`it transforms HTML img tags 1`] = ` " diff --git a/packages/gatsby-remark-images/src/__tests__/index.js b/packages/gatsby-remark-images/src/__tests__/index.js index dc66744e49448..40d30dcfa61e3 100644 --- a/packages/gatsby-remark-images/src/__tests__/index.js +++ b/packages/gatsby-remark-images/src/__tests__/index.js @@ -146,3 +146,64 @@ test(`it leaves non-relative HTML img tags alone`, async () => { const nodes = await plugin(createPluginOptions(content, imagePath)) expect(nodes[0].value).toBe(content) }) + +test(`it leaves images that are already linked alone`, async () => { + const imagePath = `image/my-image.jpg` + const content = ` +[![img](./${imagePath})](https://google.com) +` + + const nodes = await plugin(createPluginOptions(content, imagePath)) + const node = nodes.pop() + + expect(node.type).toBe(`html`) + expect(node.value).toMatchSnapshot() + expect(node.value).not.toMatch(``) +}) + +test(`it leaves linked HTML img tags alone`, async () => { + const imagePath = `images/this-image-already-has-a-link.jpeg` + + const content = ` + + + + `.trim() + + const nodes = await plugin(createPluginOptions(content, imagePath)) + const node = nodes.pop() + + expect(node.type).toBe(`html`) + expect(node.value).toMatchSnapshot() + expect(node.value).not.toMatch(``) +}) + +test(`it leaves single-line linked HTML img tags alone`, async () => { + const imagePath = `images/this-image-already-has-a-link.jpeg` + + const content = ` + + `.trim() + + const nodes = await plugin(createPluginOptions(content, imagePath)) + const node = nodes.pop() + + expect(node.type).toBe(`html`) + expect(node.value).toMatchSnapshot() + expect(node.value).not.toMatch(``) +}) + +test(`it handles goofy nesting properly`, async () => { + const imagePath = `images/this-image-already-has-a-link.jpeg` + + const content = ` + **![test](./${imagePath})** + `.trim() + + const nodes = await plugin(createPluginOptions(content, imagePath)) + const node = nodes.pop() + + expect(node.type).toBe(`html`) + expect(node.value).toMatchSnapshot() + expect(node.value).not.toMatch(``) +}) diff --git a/packages/gatsby-remark-images/src/index.js b/packages/gatsby-remark-images/src/index.js index 36a00d1bfd2df..b1f30caa64b03 100644 --- a/packages/gatsby-remark-images/src/index.js +++ b/packages/gatsby-remark-images/src/index.js @@ -1,4 +1,5 @@ -const select = require(`unist-util-select`) +// const select = require(`unist-util-select`) +const visitWithParents = require(`unist-util-visit-parents`) const path = require(`path`) const isRelativeUrl = require(`is-relative-url`) const _ = require(`lodash`) @@ -29,15 +30,34 @@ module.exports = ( const options = _.defaults(pluginOptions, defaults) + const findParentLinks = ({ children }) => + children.some( + node => + (node.type === `html` && !!node.value.match(/ { + const inLink = ancestors.some(findParentLinks) + + rawHtmlNodes.push({ node, inLink }) + }) + // This will only work for markdown syntax image tags - const markdownImageNodes = select(markdownAST, `image`) + let markdownImageNodes = [] + + visitWithParents(markdownAST, `image`, (node, ancestors) => { + const inLink = ancestors.some(findParentLinks) - // This will also allow the use of html image tags - const rawHtmlNodes = select(markdownAST, `html`) + markdownImageNodes.push({ node, inLink }) + }) // Takes a node and generates the needed images and then returns // the needed HTML replacement for the image - const generateImagesAndUpdateNode = async function(node, resolve) { + const generateImagesAndUpdateNode = async function(node, resolve, inLink) { // Check if this markdownNode has a File parent. This plugin // won't work if the image isn't hosted locally. const parentNode = getNode(markdownNode.parent) @@ -138,7 +158,7 @@ module.exports = ( ${node.alt ? node.alt : defaultAlt} + ({ node, inLink }) => new Promise(async (resolve, reject) => { const fileType = node.url.slice(-3) @@ -207,7 +227,11 @@ module.exports = ( fileType !== `gif` && fileType !== `svg` ) { - const rawHTML = await generateImagesAndUpdateNode(node, resolve) + const rawHTML = await generateImagesAndUpdateNode( + node, + resolve, + inLink + ) if (rawHTML) { // Replace the image node with an inline HTML node. @@ -226,7 +250,7 @@ module.exports = ( Promise.all( // Complex because HTML nodes can contain multiple images rawHtmlNodes.map( - node => + ({ node, inLink }) => new Promise(async (resolve, reject) => { if (!node.value) { return resolve() @@ -265,7 +289,8 @@ module.exports = ( ) { const rawHTML = await generateImagesAndUpdateNode( formattedImgTag, - resolve + resolve, + inLink ) if (rawHTML) {