const path = require(`path`); const { createFilePath } = require(`gatsby-source-filesystem`); const config = require('./config'); const { getTextualContent, getCodeBlocks, optimizeAllNodes } = require(`./src/docs/util`); const requirables = []; config.requirables.forEach(fileName => { requirables.push(require(`./snippet_data/${fileName}`)); }); const toKebabCase = str => str && str .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) .map(x => x.toLowerCase()) .join('-'); exports.onCreateNode = ({ node, actions, getNode }) => { const { createNodeField } = actions; if (node.internal.type === `MarkdownRemark`) { const value = createFilePath({ node, getNode }); createNodeField({ name: `slug`, node, value, }); } }; exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByType }) => { const { createTypes, createNode } = actions; const typeDefs = ` type Snippet implements Node { html: HtmlData tags: TagData title: String code: CodeData id: String slug: String path: String text: TextData archived: Boolean } type HtmlData @infer { full: String text: String code: String example: String } type CodeData @infer { src: String example: String } type TextData @infer { full: String short: String } type TagData @infer { primary: String all: [String] } `; createTypes(typeDefs); const markdownNodes = getNodesByType('MarkdownRemark'); const snippetNodes = requirables .reduce((acc, sArr) => { const archivedScope = sArr.meta.scope.indexOf('archive') !== -1; return ({ ...acc, ...sArr.data.reduce((snippets, snippet) => { return ({ ...snippets, [snippet.id]: { ...snippet, archived: archivedScope} }); }, {}) }); }, {}); Object.entries(snippetNodes).forEach(([id, sNode]) => { let mNode = markdownNodes.find(mN => mN.frontmatter.title === id); let nodeContent = { id, tags: { all: sNode.attributes.tags, primary: sNode.attributes.tags[0] }, title: mNode.frontmatter.title, code: { src: sNode.attributes.codeBlocks.es6, example: sNode.attributes.codeBlocks.example }, slug: mNode.fields.slug, path: mNode.fileAbsolutePath, text: { full: sNode.attributes.text, short: sNode.attributes.text.slice(0, sNode.attributes.text.indexOf('\n\n')) }, archived: sNode.archived }; createNode({ id: createNodeId(`snippet-${sNode.meta.hash}`), parent: null, children: [], internal: { type: 'Snippet', content: JSON.stringify(nodeContent), contentDigest: createContentDigest(nodeContent) }, ...nodeContent }); }); }; exports.createResolvers = ({ createResolvers }) => createResolvers({ Snippet: { html: { resolve: async (source, _, context, info) => { const resolver = info.schema.getType("MarkdownRemark").getFields()["html"].resolve; const node = await context.nodeModel.nodeStore.getNodesByType('MarkdownRemark').filter(v => v.frontmatter.title === source.title)[0]; const args = {}; // arguments passed to the resolver const html = await resolver(node, args); return { full: `${html}`, text: `${getTextualContent(html, true)}`, code: `${optimizeAllNodes(getCodeBlocks(html).code)}`, example: `${optimizeAllNodes(getCodeBlocks(html).example)}` }; } } } }); exports.createPages = ({ graphql, actions }) => { const { createPage } = actions; const snippetPage = path.resolve(`./src/docs/templates/SnippetPage.js`); const tagPage = path.resolve(`./src/docs/templates/TagPage.js`); return graphql( ` { allSnippet(sort: {fields: id}) { edges { node { id slug tags { all primary } text { full short } title html { code example full text } code { src example } archived } } } } `, ).then(result => { if (result.errors) { throw result.errors; } // Create individual snippet pages. const snippets = result.data.allSnippet.edges; snippets.forEach(snippet => { if (!snippet.node.archived) { createPage({ path: `/snippet${snippet.node.slug}`, component: snippetPage, context: { snippet: snippet.node } }); } else { createPage({ path: `/archive${snippet.node.slug}`, component: snippetPage, context: { snippet: snippet.node } }); } }); // Create tag pages. const tags = [...new Set( snippets.map(snippet => (snippet.node.tags || {primary: null}).primary) )] .filter(Boolean) .sort((a, b) => a.localeCompare(b)); tags.forEach(tag => { const tagPath = `/tag/${toKebabCase(tag)}/`; const taggedSnippets = snippets .filter(snippet => snippet.node.tags.primary === tag) .filter(snippet => !snippet.node.archived) .map(({node}) => ({ title: node.title, html: node.html.text, tags: node.tags.all, id: node.slug.slice(1) })); createPage({ path: tagPath, component: tagPage, context: { tag, snippets: taggedSnippets }, }); }); const beginnerSnippets = snippets .filter(({ node }) => node.tags.all.includes('beginner')) .filter(snippet => !snippet.node.archived) .map(({ node }) => ({ title: node.title, html: node.html.text, tags: node.tags.all, id: node.slug.slice(1) })); createPage({ path: `/beginner`, component: tagPage, context: { tag: `beginner snippets`, snippets: beginnerSnippets }, }); return null; }); };