From 526db89c04975636d74acd71e0ff069f9d78ed15 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Mon, 22 Jan 2018 16:50:27 -0500 Subject: [PATCH] [gatsby-transformer-remark] Add `htmlAst` field (#3596) This implements a GraphQL field that presents the rehype AST as JSON, allowing for this information to be consumed from a page template and presented dynamically. --- .../gatsby-transformer-remark/package.json | 2 + .../src/extend-node-type.js | 40 +++++++++++++++---- yarn.lock | 2 +- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/gatsby-transformer-remark/package.json b/packages/gatsby-transformer-remark/package.json index 2b021bfe1f803..8aadbaaff7d74 100644 --- a/packages/gatsby-transformer-remark/package.json +++ b/packages/gatsby-transformer-remark/package.json @@ -6,6 +6,7 @@ "dependencies": { "babel-runtime": "^6.26.0", "bluebird": "^3.5.0", + "graphql-type-json": "^0.1.4", "gray-matter": "^3.0.0", "hast-util-to-html": "^3.0.0", "lodash": "^4.17.4", @@ -19,6 +20,7 @@ "sanitize-html": "^1.14.1", "underscore.string": "^3.3.4", "unified": "^6.1.5", + "unist-util-remove-position": "^1.1.1", "unist-util-select": "^1.5.0", "unist-util-visit": "^1.1.1" }, diff --git a/packages/gatsby-transformer-remark/src/extend-node-type.js b/packages/gatsby-transformer-remark/src/extend-node-type.js index c71155eb0b7e6..fa50d90805e7a 100644 --- a/packages/gatsby-transformer-remark/src/extend-node-type.js +++ b/packages/gatsby-transformer-remark/src/extend-node-type.js @@ -20,6 +20,8 @@ const parse = require(`remark-parse`) const stringify = require(`remark-stringify`) const english = require(`retext-english`) const remark2retext = require(`remark-retext`) +const GraphQlJson = require(`graphql-type-json`) +const stripPosition = require(`unist-util-remove-position`) let pluginsCacheStr = `` const astCacheKey = node => @@ -30,6 +32,10 @@ const htmlCacheKey = node => `transformer-remark-markdown-html-${ node.internal.contentDigest }-${pluginsCacheStr}` +const htmlAstCacheKey = node => + `transformer-remark-markdown-html-ast-${ + node.internal.contentDigest + }-${pluginsCacheStr}` const headingsCacheKey = node => `transformer-remark-markdown-headings-${ node.internal.contentDigest @@ -213,19 +219,29 @@ module.exports = ( } } + 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 }) + + // Save new HTML AST to cache and return + cache.set(htmlAstCacheKey(markdownNode), htmlAst) + return htmlAst + } + } + async function getHTML(markdownNode) { const cachedHTML = await cache.get(htmlCacheKey(markdownNode)) if (cachedHTML) { return cachedHTML } else { - const html = await new Promise((resolve, reject) => { - getAST(markdownNode).then(ast => { - resolve( - hastToHTML(toHAST(ast, { allowDangerousHTML: true }), { - allowDangerousHTML: true, - }) - ) - }) + const ast = await getHTMLAst(markdownNode) + // Save new HTML to cache and return + const html = hastToHTML(ast, { + allowDangerousHTML: true, }) // Save new HTML to cache and return @@ -271,6 +287,14 @@ module.exports = ( return getHTML(markdownNode) }, }, + htmlAst: { + type: GraphQlJson, + resolve(markdownNode) { + const ast = _.clone(getHTMLAst(markdownNode)) + stripPosition(ast, true) + return ast + }, + }, excerpt: { type: GraphQLString, args: { diff --git a/yarn.lock b/yarn.lock index 4c75b331f81ad..56c4a4b456999 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13469,7 +13469,7 @@ unist-util-position@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.0.tgz#e6e1e03eeeb81c5e1afe553e8d4adfbd7c0d8f82" -unist-util-remove-position@^1.0.0: +unist-util-remove-position@^1.0.0, unist-util-remove-position@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" dependencies: