From 13d23d9c6c35e13a5608c1d9ed7ca20edec7a71a Mon Sep 17 00:00:00 2001 From: jasongao97 Date: Wed, 24 Jan 2024 14:28:44 +0800 Subject: [PATCH] add `Example` endpoint --- gatsby/create-resolvers.js | 20 +++++++++++++++ gatsby/lib/parse-content.mjs | 47 +++++++++++++++++++++++++++++------- gatsby/on-create-node.js | 27 ++++++++++++++++++--- 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/gatsby/create-resolvers.js b/gatsby/create-resolvers.js index 2ef50ac..d702a68 100644 --- a/gatsby/create-resolvers.js +++ b/gatsby/create-resolvers.js @@ -20,6 +20,26 @@ module.exports = ({ createResolvers }) => { }, }, }, + + Example: { + screenshot: { + type: 'File', + resolve: async (source, args, context, info) => { + const screenshot = await context.nodeModel.findOne({ + type: 'File', + query: { + filter: { + relativeDirectory: { + eq: source.relativeDirectory, + }, + internal: { mediaType: { regex: '/^(image)/' } }, + }, + }, + }); + return screenshot; + }, + }, + }, }; createResolvers(resolvers); }; diff --git a/gatsby/lib/parse-content.mjs b/gatsby/lib/parse-content.mjs index 5d14737..9903a07 100644 --- a/gatsby/lib/parse-content.mjs +++ b/gatsby/lib/parse-content.mjs @@ -67,15 +67,6 @@ export function parseContent(html) { const ast = unified().use(rehypeParse, { fragment: true }).parse(html); - const transformedAst = unified() - .use(replaceMedia) - .use(externalLinkInNewTab) - .use(rehypeCodesplit) - .use(rehypeHighlight) - .use(rehypeSlug) - .use(rehypeKatex) - .runSync(ast); - /** * Generate Table of Content */ @@ -88,8 +79,46 @@ export function parseContent(html) { }); }); + /** + * List all examples + */ + const examples = []; + visit(ast, { tagName: 'div' }, (node) => { + if (node.properties.dataType !== 'example') { + return; + } + + // Locate the h3 element within the current node's children + const titleNode = node.children.find((child) => child.tagName === 'h3'); + const slug = titleNode && titleNode.properties.id; + const title = + titleNode && titleNode.children.length > 0 + ? titleNode.children[0].value + : ''; + + visit(node, { tagName: 'div' }, (embedDivNode) => { + if (embedDivNode.properties.dataType !== 'embed') return; + examples.push({ + title, + slug, + relativeDirectory: embedDivNode.properties.dataExamplePath, + webEditorURL: embedDivNode.properties.dataP5Editor, + }); + }); + }); + + const transformedAst = unified() + .use(replaceMedia) + .use(externalLinkInNewTab) + .use(rehypeCodesplit) + .use(rehypeHighlight) + .use(rehypeSlug) + .use(rehypeKatex) + .runSync(ast); + return { ast: transformedAst, toc, + examples, }; } diff --git a/gatsby/on-create-node.js b/gatsby/on-create-node.js index c9a7996..0212ad0 100644 --- a/gatsby/on-create-node.js +++ b/gatsby/on-create-node.js @@ -1,5 +1,11 @@ -module.exports = async ({ node, actions, loadNodeContent }) => { - const { createNodeField } = actions; +module.exports = async ({ + node, + actions, + loadNodeContent, + createContentDigest, + createNodeId, +}) => { + const { createNodeField, createNode, createParentChildLink } = actions; if (node.internal.mediaType !== `text/html`) { return; @@ -9,7 +15,7 @@ module.exports = async ({ node, actions, loadNodeContent }) => { // load the html source to every HTML file node const content = await loadNodeContent(node); - const { ast, toc } = parseContent(content); + const { ast, toc, examples } = parseContent(content); createNodeField({ node, @@ -22,4 +28,19 @@ module.exports = async ({ node, actions, loadNodeContent }) => { name: 'toc', value: JSON.stringify(toc), }); + + for (let example of examples) { + const exampleNode = { + id: createNodeId(example.relativeDirectory), + parent: node.id, + internal: { + type: 'Example', + contentDigest: createContentDigest(example), + }, + ...example, + }; + + createNode(exampleNode); + createParentChildLink({ parent: node, child: exampleNode }); + } };