Skip to content

Commit

Permalink
feat(gatsby-remark-images): support markdownCaptions in mdx + fix for…
Browse files Browse the repository at this point in the history
… remark (#21188)

* pass compiler to gatsby-remark-* plugins in the mdx plugin

* make getImageCaption async

* use async mdx compiler

* fix for using compiler

* don't mutate the node multiple times

* convert markdown ast to html ast

Co-authored-by: vladar
  • Loading branch information
mathieudutour authored Apr 22, 2020
1 parent 3beca2e commit 82c05aa
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 46 deletions.
4 changes: 4 additions & 0 deletions packages/gatsby-plugin-mdx/utils/gen-mdx.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ export const _frontmatter = ${JSON.stringify(data)}`
reporter,
cache,
pathPrefix,
compiler: {
parseString: compiler.parse.bind(compiler),
generateHTML: ast => mdx(ast, options),
},
...helpers,
}
)
Expand Down
6 changes: 3 additions & 3 deletions packages/gatsby-remark-images/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module.exports = (
}
}

const getImageCaption = (node, overWrites) => {
const getImageCaption = async (node, overWrites) => {
const getCaptionString = () => {
const captionOptions = Array.isArray(options.showCaptions)
? options.showCaptions
Expand Down Expand Up @@ -115,7 +115,7 @@ module.exports = (
return _.escape(captionString)
}

return compiler.generateHTML(compiler.parseString(captionString))
return compiler.generateHTML(await compiler.parseString(captionString))
}

// Takes a node and generates the needed images and then returns
Expand Down Expand Up @@ -288,7 +288,7 @@ module.exports = (

// Construct new image node w/ aspect ratio placeholder
const imageCaption =
options.showCaptions && getImageCaption(node, overWrites)
options.showCaptions && (await getImageCaption(node, overWrites))

let removeBgImage = false
if (options.disableBgImageOnAlpha) {
Expand Down
101 changes: 58 additions & 43 deletions packages/gatsby-transformer-remark/src/extend-node-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,35 +165,21 @@ module.exports = (
}
}

async function getMarkdownAST(markdownNode) {
if (process.env.NODE_ENV !== `production` || !fileNodes) {
fileNodes = getNodesByType(`File`)
// Parse a markdown string and its AST representation,
// applying the remark plugins if necesserary
async function parseString(string, markdownNode) {
// compiler to inject in the remark plugins
// so that they can use our parser/generator
// with all the options and plugins from the user
const compiler = {
parseString: string => parseString(string, markdownNode),
generateHTML: ast =>
hastToHTML(markdownASTToHTMLAst(ast), {
allowDangerousHTML: true,
}),
}
// Use Bluebird's Promise function "each" to run remark plugins serially.
await Promise.each(pluginOptions.plugins, plugin => {
const requiredPlugin = require(plugin.resolve)
if (_.isFunction(requiredPlugin.mutateSource)) {
return requiredPlugin.mutateSource(
{
markdownNode,
files: fileNodes,
getNode,
reporter,
cache: getCache(plugin.name),
getCache,
compiler: {
parseString: remark.parse.bind(remark),
generateHTML: getHTML,
},
...rest,
},
plugin.pluginOptions
)
} else {
return Promise.resolve()
}
})
const markdownAST = remark.parse(markdownNode.internal.content)

const markdownAST = remark.parse(string)

if (basePath) {
// Ensure relative links include `pathPrefix`
Expand Down Expand Up @@ -232,10 +218,7 @@ module.exports = (
reporter,
cache: getCache(plugin.name),
getCache,
compiler: {
parseString: remark.parse.bind(remark),
generateHTML: getHTML,
},
compiler,
...rest,
},
plugin.pluginOptions
Expand All @@ -248,6 +231,38 @@ module.exports = (
return markdownAST
}

async function getMarkdownAST(markdownNode) {
if (process.env.NODE_ENV !== `production` || !fileNodes) {
fileNodes = getNodesByType(`File`)
}

// Execute the remark plugins that can mutate the node
// before parsing its content
//
// Use Bluebird's Promise function "each" to run remark plugins serially.
await Promise.each(pluginOptions.plugins, plugin => {
const requiredPlugin = require(plugin.resolve)
if (_.isFunction(requiredPlugin.mutateSource)) {
return requiredPlugin.mutateSource(
{
markdownNode,
files: fileNodes,
getNode,
reporter,
cache: getCache(plugin.name),
getCache,
...rest,
},
plugin.pluginOptions
)
} else {
return Promise.resolve()
}
})

return parseString(markdownNode.internal.content, markdownNode)
}

async function getHeadings(markdownNode) {
const cachedHeadings = await cache.get(headingsCacheKey(markdownNode))
if (cachedHeadings) {
Expand Down Expand Up @@ -323,16 +338,20 @@ module.exports = (
}
}

async function markdownASTToHTMLAst(ast) {
return toHAST(ast, {
allowDangerousHTML: true,
handlers: { code: codeHandler },
})
}

async function getHTMLAst(markdownNode) {
const cachedAst = await cache.get(htmlAstCacheKey(markdownNode))
if (cachedAst) {
return cachedAst
} else {
const ast = await getAST(markdownNode)
const htmlAst = toHAST(ast, {
allowDangerousHTML: true,
handlers: { code: codeHandler },
})
const htmlAst = markdownASTToHTMLAst(ast)

// Save new HTML AST to cache and return
cache.set(htmlAstCacheKey(markdownNode), htmlAst)
Expand All @@ -341,9 +360,7 @@ module.exports = (
}

async function getHTML(markdownNode) {
const shouldCache = markdownNode && markdownNode.internal
const cachedHTML =
shouldCache && (await cache.get(htmlCacheKey(markdownNode)))
const cachedHTML = await cache.get(htmlCacheKey(markdownNode))
if (cachedHTML) {
return cachedHTML
} else {
Expand All @@ -353,10 +370,8 @@ module.exports = (
allowDangerousHTML: true,
})

if (shouldCache) {
// Save new HTML to cache
cache.set(htmlCacheKey(markdownNode), html)
}
// Save new HTML to cache
cache.set(htmlCacheKey(markdownNode), html)

return html
}
Expand Down

0 comments on commit 82c05aa

Please sign in to comment.