From 59d527edb0efe5cd742fe15c9b45d5d7ada09c75 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Sat, 14 Sep 2019 12:32:47 +0300 Subject: [PATCH 01/10] Prototype snippet nodes --- gatsby-node.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 9e8c21e72..7822edc05 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -8,7 +8,7 @@ const toKebabCase = 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.createPages = ({ graphql, actions }) => { const { createPage } = actions; @@ -99,9 +99,9 @@ exports.createPages = ({ graphql, actions }) => { return null; }); }; - +*/ exports.onCreateNode = ({ node, actions, getNode }) => { - const { createNodeField } = actions; + const { createNodeField, createNode } = actions; if (node.internal.type === `MarkdownRemark`) { const value = createFilePath({ node, getNode }); @@ -111,4 +111,56 @@ exports.onCreateNode = ({ node, actions, getNode }) => { value, }); } + }; + +exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByType }) => { + const { createTypes, createNode } = actions; + const typeDefs = ` + type Snippet implements Node { + html: String + tags: [String] + title: String + code: String + id: String + } + `; + createTypes(typeDefs); + + const markdownNodes = getNodesByType('MarkdownRemark'); + const snippetDataNodes = getNodesByType('SnippetDataJson'); + + markdownNodes.forEach(mnode => { + let nodeContent = { + html: mnode.html, + tags: (mnode.frontmatter.tags || '').split(','), + title: mnode.frontmatter.title, + }; + createNode({ + id: createNodeId(`snippet-${mnode.id}`), + 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 html; + } + } + } +}); From d7013dd17ccceaa67b3d430018278232672e9e95 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Sat, 14 Sep 2019 13:14:47 +0300 Subject: [PATCH 02/10] Setup snippet schema initial load logic Use dynamic imports to load all the JSON files specified in config, read data from both sources, output the proper data in the new Snippet type nodes. --- config.js | 5 +++++ gatsby-node.js | 33 +++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/config.js b/config.js index d41211a32..9688bd476 100644 --- a/config.js +++ b/config.js @@ -21,4 +21,9 @@ module.exports = { moduleName: `_30s`, rollupInputFile: `imports.temp.js`, testModuleFile: `test/_30s.js`, + // Requirable JSONs + requirables: [ + `snippets.json`, + `archivedSnippets.json` + ] }; diff --git a/gatsby-node.js b/gatsby-node.js index 7822edc05..3b9919f37 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,6 +2,12 @@ const path = require(`path`); const { createFilePath } = require(`gatsby-source-filesystem`); const config = require('./config'); +const requirables = []; + +config.requirables.forEach(fileName => { + requirables.push(require(`./snippet_data/${fileName}`)); +}) + const toKebabCase = str => str && str @@ -128,16 +134,31 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT createTypes(typeDefs); const markdownNodes = getNodesByType('MarkdownRemark'); - const snippetDataNodes = getNodesByType('SnippetDataJson'); - markdownNodes.forEach(mnode => { + const snippetNodes = requirables + .reduce((acc, sArr) => { + return ({ + ...acc, + ...sArr.data.reduce((snippets, snippet) => { + return ({ + ...snippets, + [snippet.id]: snippet + }); + }, {}) + }); + }, {}); + + Object.entries(snippetNodes).forEach(([id, sNode]) => { + let mNode = markdownNodes.find(mN => mN.frontmatter.title === id); let nodeContent = { - html: mnode.html, - tags: (mnode.frontmatter.tags || '').split(','), - title: mnode.frontmatter.title, + id, + html: mNode.html, + tags: sNode.attributes.tags, + title: mNode.frontmatter.title, + code: sNode.attributes.codeBlocks.es6 }; createNode({ - id: createNodeId(`snippet-${mnode.id}`), + id: createNodeId(`snippet-${sNode.meta.hash}`), parent: null, children: [], internal: { From 25ae41220863d8493a8b666f9b03b8eed194c067 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Sat, 14 Sep 2019 14:06:51 +0300 Subject: [PATCH 03/10] Enrich Snippet schema Add all the parsed data used on the pages, now parsed on boot. --- gatsby-node.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 3b9919f37..4454ce2c6 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,6 +2,8 @@ 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 => { @@ -124,12 +126,19 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT const { createTypes, createNode } = actions; const typeDefs = ` type Snippet implements Node { - html: String + html: HtmlData tags: [String] title: String code: String id: String } + + type HtmlData @infer { + full: String + text: String + code: String + example: String + } `; createTypes(typeDefs); @@ -152,7 +161,6 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT let mNode = markdownNodes.find(mN => mN.frontmatter.title === id); let nodeContent = { id, - html: mNode.html, tags: sNode.attributes.tags, title: mNode.frontmatter.title, code: sNode.attributes.codeBlocks.es6 @@ -180,7 +188,12 @@ exports.createResolvers = ({ createResolvers }) => createResolvers({ 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 html; + return { + full: `${html}`, + text: `${getTextualContent(html)}`, + code: `${optimizeAllNodes(getCodeBlocks(html).code)}`, + example: `${optimizeAllNodes(getCodeBlocks(html).example)}` + }; } } } From df0329c7d5cde2399912869136936ce978c4240f Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 16 Sep 2019 21:33:14 +0300 Subject: [PATCH 04/10] Enrich snippet schema, probably finalize structure --- gatsby-node.js | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 4454ce2c6..94c55dc4d 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -127,10 +127,13 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT const typeDefs = ` type Snippet implements Node { html: HtmlData - tags: [String] + tags: TagData title: String - code: String + code: CodeData id: String + slug: String + path: String + text: TextData } type HtmlData @infer { @@ -139,6 +142,21 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT 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); @@ -161,9 +179,21 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT let mNode = markdownNodes.find(mN => mN.frontmatter.title === id); let nodeContent = { id, - tags: sNode.attributes.tags, + tags: { + all: sNode.attributes.tags, + primary: sNode.attributes.tags[0] + }, title: mNode.frontmatter.title, - code: sNode.attributes.codeBlocks.es6 + 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')) + } }; createNode({ id: createNodeId(`snippet-${sNode.meta.hash}`), From e4569284ebacb18f57910cd664a0f5b7f2069ee8 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 16 Sep 2019 22:09:38 +0300 Subject: [PATCH 05/10] Update createPages to use new schemas Breaks archive snippet pages, needs some investigation --- gatsby-node.js | 203 ++++++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 97 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 94c55dc4d..9a8fc3304 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,13 +2,13 @@ const path = require(`path`); const { createFilePath } = require(`gatsby-source-filesystem`); const config = require('./config'); -const { getTextualContent, getCodeBlocks, optimizeAllNodes } = require(`./src/docs/util`); +const { getTextualContent, getCodeBlocks, optimizeAllNodes } = require(`./src/docs/util`); const requirables = []; config.requirables.forEach(fileName => { requirables.push(require(`./snippet_data/${fileName}`)); -}) +}); const toKebabCase = str => str && @@ -16,100 +16,9 @@ const toKebabCase = 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.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( - ` - { - allMarkdownRemark( - sort: { fields: [frontmatter___title], order: ASC } - limit: 1000 - ) { - edges { - node { - fields { - slug - } - frontmatter { - tags - } - fileAbsolutePath - } - } - } - } - `, - ).then(result => { - if (result.errors) { - throw result.errors; - } - - // Create individual snippet pages. - const snippets = result.data.allMarkdownRemark.edges; - - snippets.forEach((post, index) => { - if(post.node.fileAbsolutePath.indexOf('README') !== -1) - return; - if (post.node.fileAbsolutePath.indexOf(config.snippetArchivePath) === -1) - createPage({ - path: `/snippet${post.node.fields.slug}`, - component: snippetPage, - context: { - slug: post.node.fields.slug, - scope: `./snippets`, - }, - }); - else - createPage({ - path: `/archive${post.node.fields.slug}`, - component: snippetPage, - context: { - slug: post.node.fields.slug, - scope: `./snippets_archive`, - }, - }); - }); - - // Create tag pages. - const tags = snippets.reduce((acc, post) => { - if (!post.node.frontmatter || !post.node.frontmatter.tags) return acc; - const primaryTag = post.node.frontmatter.tags.split(',')[0]; - if (!acc.includes(primaryTag)) acc.push(primaryTag); - return acc; - }, []); - - tags.forEach(tag => { - const tagPath = `/tag/${toKebabCase(tag)}/`; - const tagRegex = `/^\\s*${tag}/`; - createPage({ - path: tagPath, - component: tagPage, - context: { - tag, - tagRegex, - }, - }); - }); - - createPage({ - path: `/beginner`, - component: tagPage, - context: { - tag: `beginner snippets`, - tagRegex: `/beginner/`, - }, - }); - - return null; - }); -}; -*/ exports.onCreateNode = ({ node, actions, getNode }) => { - const { createNodeField, createNode } = actions; + const { createNodeField } = actions; if (node.internal.type === `MarkdownRemark`) { const value = createFilePath({ node, getNode }); @@ -119,7 +28,6 @@ exports.onCreateNode = ({ node, actions, getNode }) => { value, }); } - }; exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByType }) => { @@ -134,6 +42,7 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT slug: String path: String text: TextData + archived: Boolean } type HtmlData @infer { @@ -164,12 +73,13 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT 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 + [snippet.id]: { ...snippet, archived: archivedScope} }); }, {}) }); @@ -193,7 +103,8 @@ exports.sourceNodes = ({ actions, createNodeId, createContentDigest, getNodesByT 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}`), @@ -228,3 +139,101 @@ exports.createResolvers = ({ createResolvers }) => createResolvers({ } } }); + +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.archived) { + createPage({ + path: `/snippet${snippet.node.slug}`, + component: snippetPage, + context: { + slug: snippet.node.slug, + scope: `./snippets` + } + }); + } else { + createPage({ + path: `/archive${snippet.node.slug}`, + component: snippetPage, + context: { + slug: snippet.node.slug, + scope: `./snippets_archive` + } + }); + } + }); + + // Create tag pages. + const tags = [...new Set(snippets.map(snippet => snippet.tags.primary))].sort((a,b) => a.localeCompare(b)); + + tags.forEach(tag => { + const tagPath = `/tag/${toKebabCase(tag)}/`; + const tagRegex = `/^\\s*${tag}/`; + createPage({ + path: tagPath, + component: tagPage, + context: { + tag, + tagRegex, + }, + }); + }); + + createPage({ + path: `/beginner`, + component: tagPage, + context: { + tag: `beginner snippets`, + tagRegex: `/beginner/`, + }, + }); + + return null; + }); +}; From 31dee63aa3540c5fd177a47c12502f12ee0c0470 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 16 Sep 2019 22:43:14 +0300 Subject: [PATCH 06/10] Update individual snippet pages Reduce data sizes and load times, improve performance --- gatsby-node.js | 8 +++- src/docs/components/SnippetCard.js | 19 +++------ src/docs/templates/SnippetPage.js | 67 +++++++++++------------------- 3 files changed, 35 insertions(+), 59 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 9a8fc3304..5ca532f28 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -188,7 +188,7 @@ exports.createPages = ({ graphql, actions }) => { const snippets = result.data.allSnippet.edges; snippets.forEach(snippet => { - if(!snippet.archived) { + if (!snippet.node.archived) { createPage({ path: `/snippet${snippet.node.slug}`, component: snippetPage, @@ -210,7 +210,11 @@ exports.createPages = ({ graphql, actions }) => { }); // Create tag pages. - const tags = [...new Set(snippets.map(snippet => snippet.tags.primary))].sort((a,b) => a.localeCompare(b)); + const tags = [...new Set( + snippets.map(snippet => (snippet.tags || {primary: null}).primary) + )] + .filter(Boolean) + .sort((a, b) => a.localeCompare(b)); tags.forEach(tag => { const tagPath = `/tag/${toKebabCase(tag)}/`; diff --git a/src/docs/components/SnippetCard.js b/src/docs/components/SnippetCard.js index e2088ec20..0b02ab6e4 100644 --- a/src/docs/components/SnippetCard.js +++ b/src/docs/components/SnippetCard.js @@ -42,24 +42,18 @@ const CardCorner = ({ difficulty = 'intermediate' }) => ( // =================================================== const FullCard = ({ snippetData, difficulty, isDarkMode }) => { const [examplesOpen, setExamplesOpen] = React.useState(false); - const tags = snippetData.tags; - let cardCodeHtml = `${optimizeAllNodes( - getCodeBlocks(snippetData.html).code, - )}`; - let cardExamplesHtml = `${optimizeAllNodes( - getCodeBlocks(snippetData.html).example, - )}`; + return (

{snippetData.title}

- {tags.map(tag => ( + {snippetData.tags.map(tag => ( {tag} ))}
@@ -83,12 +77,9 @@ const FullCard = ({ snippetData, difficulty, isDarkMode }) => { aria-label='Copy to clipboard' /> - {/* */}
         
diff --git a/src/docs/templates/SnippetPage.js b/src/docs/templates/SnippetPage.js index 996e996f8..9ab06301c 100644 --- a/src/docs/templates/SnippetPage.js +++ b/src/docs/templates/SnippetPage.js @@ -11,14 +11,11 @@ import BackArrowIcon from '../components/SVGs/BackArrowIcon'; // Individual snippet page template // =================================================== const SnippetPage = props => { - const post = props.data.markdownRemark; - const postData = props.data.snippetDataJson.data.find( - v => v.title === post.frontmatter.title, - ); + const snippet = props.data.snippet; return ( <> - + { @@ -52,7 +52,7 @@ export default connect( )(SnippetPage); export const pageQuery = graphql` - query BlogPostBySlug($slug: String!, $scope: String!) { + query SnippetBySlug($slug: String!) { logo: file(absolutePath: { regex: "/logo_reverse_md.png/" }) { id childImageSharp { @@ -61,42 +61,23 @@ export const pageQuery = graphql` } } } - allMarkdownRemark { - edges { - node { - fields { - slug - } - fileAbsolutePath - frontmatter { - title - } - } + snippet (slug: {eq: $slug }) { + title + html { + full + code + example + text } - } - markdownRemark(fields: { slug: { eq: $slug } }) { - id - fields { - slug + code { + src } - excerpt(pruneLength: 160) - html - frontmatter { - title + tags { + all } - } - snippetDataJson(meta: { type: { eq: "snippetArray" }, scope: {eq: $scope} }) { - data { - title - id - attributes { - text - codeBlocks { - es6 - example - } - tags - } + title + text { + short } } } From f39cba0ce0e8726af1b38bd6ff36d335aeb1eb4b Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 16 Sep 2019 23:02:41 +0300 Subject: [PATCH 07/10] Further optimize snippet pages Clean up queries, query only once --- gatsby-node.js | 6 ++---- src/docs/templates/SnippetPage.js | 34 +------------------------------ 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 5ca532f28..72d4f2206 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -193,8 +193,7 @@ exports.createPages = ({ graphql, actions }) => { path: `/snippet${snippet.node.slug}`, component: snippetPage, context: { - slug: snippet.node.slug, - scope: `./snippets` + snippet: snippet.node } }); } else { @@ -202,8 +201,7 @@ exports.createPages = ({ graphql, actions }) => { path: `/archive${snippet.node.slug}`, component: snippetPage, context: { - slug: snippet.node.slug, - scope: `./snippets_archive` + snippet: snippet.node } }); } diff --git a/src/docs/templates/SnippetPage.js b/src/docs/templates/SnippetPage.js index 9ab06301c..7db74c381 100644 --- a/src/docs/templates/SnippetPage.js +++ b/src/docs/templates/SnippetPage.js @@ -11,7 +11,7 @@ import BackArrowIcon from '../components/SVGs/BackArrowIcon'; // Individual snippet page template // =================================================== const SnippetPage = props => { - const snippet = props.data.snippet; + const snippet = props.pageContext.snippet; return ( <> @@ -50,35 +50,3 @@ export default connect( }), null, )(SnippetPage); - -export const pageQuery = graphql` - query SnippetBySlug($slug: String!) { - logo: file(absolutePath: { regex: "/logo_reverse_md.png/" }) { - id - childImageSharp { - fixed(height: 45, width: 45) { - src - } - } - } - snippet (slug: {eq: $slug }) { - title - html { - full - code - example - text - } - code { - src - } - tags { - all - } - title - text { - short - } - } - } -`; From 75c4b3321b93e4a46eb558bee49bcf13914bf7f0 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Mon, 16 Sep 2019 23:38:26 +0300 Subject: [PATCH 08/10] Update tag pages Improve speed, move all of the querying to node --- gatsby-node.js | 17 ++++++++++--- src/docs/components/SnippetCard.js | 3 +-- src/docs/templates/TagPage.js | 41 ++++++------------------------ 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 72d4f2206..336855526 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -131,7 +131,7 @@ exports.createResolvers = ({ createResolvers }) => createResolvers({ const html = await resolver(node, args); return { full: `${html}`, - text: `${getTextualContent(html)}`, + text: `${getTextualContent(html, true)}`, code: `${optimizeAllNodes(getCodeBlocks(html).code)}`, example: `${optimizeAllNodes(getCodeBlocks(html).example)}` }; @@ -209,20 +209,29 @@ exports.createPages = ({ graphql, actions }) => { // Create tag pages. const tags = [...new Set( - snippets.map(snippet => (snippet.tags || {primary: null}).primary) + 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) + })); const tagRegex = `/^\\s*${tag}/`; createPage({ path: tagPath, component: tagPage, context: { tag, - tagRegex, + snippets: taggedSnippets }, }); }); diff --git a/src/docs/components/SnippetCard.js b/src/docs/components/SnippetCard.js index 0b02ab6e4..071ac8a97 100644 --- a/src/docs/components/SnippetCard.js +++ b/src/docs/components/SnippetCard.js @@ -115,13 +115,12 @@ const ShortCard = ({

- {snippetData.title}

diff --git a/src/docs/templates/TagPage.js b/src/docs/templates/TagPage.js index 101605ad2..0c7a5a802 100644 --- a/src/docs/templates/TagPage.js +++ b/src/docs/templates/TagPage.js @@ -13,8 +13,8 @@ import { capitalize, getRawCodeBlocks as getCodeBlocks } from '../util'; // Individual snippet category/tag page // =================================================== const TagRoute = props => { - const posts = props.data.allMarkdownRemark.edges; const tag = props.pageContext.tag; + const snippets = props.pageContext.snippets; React.useEffect(() => { props.dispatch(pushNewPage(capitalize(tag), props.path)); @@ -26,16 +26,16 @@ const TagRoute = props => {

{capitalize(tag)}

Click on a snippet card to view the snippet.

- {posts && - posts.map(({ node }) => ( + {snippets && + snippets.map(snippet => ( v.trim()), - id: node.fields.slug.slice(1), + title: snippet.title, + html: snippet.html, + tags: snippet.tags, + id: snippet.id, }} isDarkMode={props.isDarkMode} /> @@ -54,28 +54,3 @@ export default connect( }), null, )(TagRoute); - -export const tagPageQuery = graphql` - query TagPage($tagRegex: String) { - allMarkdownRemark( - limit: 1000 - sort: { fields: [frontmatter___title], order: ASC } - filter: { fileAbsolutePath: { regex: "/snippets(?!_archive)/" }, frontmatter: { tags: { regex: $tagRegex } } } - ) { - totalCount - edges { - node { - id - html - fields { - slug - } - frontmatter { - title - tags - } - } - } - } - } -`; From 48f921b97561b8294a205b60b32a41aae06ddb8c Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 17 Sep 2019 00:15:31 +0300 Subject: [PATCH 09/10] Update remaining pages Everything that used remark and JSON now uses the new Snippet schema --- gatsby-node.js | 13 ++++- src/docs/pages/index.js | 47 ++++++++---------- src/docs/pages/list.js | 100 +++++++++++++++++++-------------------- src/docs/pages/search.js | 49 ++++++++----------- 4 files changed, 101 insertions(+), 108 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 336855526..570b87f07 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -225,7 +225,6 @@ exports.createPages = ({ graphql, actions }) => { tags: node.tags.all, id: node.slug.slice(1) })); - const tagRegex = `/^\\s*${tag}/`; createPage({ path: tagPath, component: tagPage, @@ -236,12 +235,22 @@ exports.createPages = ({ graphql, actions }) => { }); }); + 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`, - tagRegex: `/beginner/`, + snippets: beginnerSnippets }, }); diff --git a/src/docs/pages/index.js b/src/docs/pages/index.js index fbeff5b2d..a13bd4aae 100644 --- a/src/docs/pages/index.js +++ b/src/docs/pages/index.js @@ -13,14 +13,7 @@ import SimpleCard from '../components/SimpleCard'; // Home page (splash and search) // =================================================== const IndexPage = props => { - const snippets = props.data.snippetDataJson.data.map(snippet => ({ - title: snippet.title, - html: props.data.allMarkdownRemark.edges.find( - v => v.node.frontmatter.title === snippet.title, - ).node.html, - tags: snippet.attributes.tags, - id: snippet.id - })); + const snippets = props.data.allSnippet.edges; const [searchQuery, setSearchQuery] = React.useState(props.searchQuery); const [searchResults, setSearchResults] = React.useState(snippets); @@ -31,9 +24,9 @@ const IndexPage = props => { let results = snippets; if (q.trim().length) results = snippets.filter( - v => - v.tags.filter(t => t.indexOf(q) !== -1).length || - v.title.toLowerCase().indexOf(q) !== -1, + ({node}) => + node.tags.all.filter(t => t.indexOf(q) !== -1).length || + node.title.toLowerCase().indexOf(q) !== -1, ); setSearchResults(results); }, [searchQuery]); @@ -80,11 +73,16 @@ const IndexPage = props => { Click on a snippet card to view the snippet.

Search results

- {searchResults.map(snippet => ( + {searchResults.map(({node}) => ( ))} @@ -139,22 +137,17 @@ export const indexPageQuery = graphql` } } } - snippetDataJson(meta: { type: { eq: "snippetListingArray" }, scope: {eq: "./snippets"} }) { - data { - id - title - attributes { - tags - } - } - } - allMarkdownRemark { + allSnippet { edges { node { - html - frontmatter { - title + title + html { + text } + tags { + all + } + id } } } diff --git a/src/docs/pages/list.js b/src/docs/pages/list.js index 18e0dfd43..fb7b462aa 100644 --- a/src/docs/pages/list.js +++ b/src/docs/pages/list.js @@ -15,28 +15,15 @@ import SimpleCard from '../components/SimpleCard'; // Snippet list page // =================================================== const ListPage = props => { - const snippets = props.data.snippetDataJson.data.map(snippet => ({ - title: snippet.title, - html: props.data.allMarkdownRemark.edges.find( - v => v.node.frontmatter.title === snippet.title, - ).node.html, - tags: snippet.attributes.tags, - id: snippet.id, - })); - const archivedSnippets = props.data.snippetsArchiveDataJson.data.map(snippet => ({ - title: snippet.title, - html: props.data.allMarkdownRemark.edges.find( - v => v.node.frontmatter.title === snippet.title, - ).node.html, - tags: snippet.attributes.tags, - id: snippet.id, - })); - const tags = snippets.reduce((acc, snippet) => { - if (!snippet.tags) return acc; - const primaryTag = snippet.tags[0]; - if (!acc.includes(primaryTag)) acc.push(primaryTag); - return acc; - }, []); + const snippets = props.data.allSnippet.edges; + const archivedSnippets = props.data.allArchivedSnippet.edges; + + const tags = [...new Set( + snippets.map(snippet => (snippet.node.tags || { primary: null }).primary) + )] + .filter(Boolean) + .sort((a, b) => a.localeCompare(b)); + const staticPages = [ { url: 'beginner', @@ -79,12 +66,17 @@ const ListPage = props => { {snippets - .filter(snippet => snippet.tags[0] === tag) - .map(snippet => ( + .filter(({node}) => node.tags.primary === tag) + .map(({node}) => ( ))} @@ -95,12 +87,17 @@ const ListPage = props => { Archived snippets {archivedSnippets - .map(snippet => ( + .map(({node}) => ( ))}
@@ -131,31 +128,32 @@ export default connect( export const listPageQuery = graphql` query snippetListing { - snippetDataJson(meta: { type: { eq: "snippetListingArray" }, scope: {eq: "./snippets"} }) { - data { - id - title - attributes { - tags - } - } - } - snippetsArchiveDataJson : snippetDataJson(meta: { type: { eq: "snippetListingArray" }, scope: {eq: "./snippets_archive"} }) { - data { - id - title - attributes { - tags - } - } - } - allMarkdownRemark { + allSnippet(filter: {archived: {eq: false}}) { edges { node { - html - frontmatter { - title + title + html { + text } + tags { + all + primary + } + id + } + } + } + allArchivedSnippet: allSnippet(filter: {archived: {eq: true}}) { + edges { + node { + title + html { + text + } + tags { + all + } + id } } } diff --git a/src/docs/pages/search.js b/src/docs/pages/search.js index 7e582ce60..7f19d78a7 100644 --- a/src/docs/pages/search.js +++ b/src/docs/pages/search.js @@ -12,14 +12,7 @@ import SnippetCard from '../components/SnippetCard'; // Search page // =================================================== const SearchPage = props => { - const snippets = props.data.snippetDataJson.data.map(snippet => ({ - title: snippet.title, - html: props.data.allMarkdownRemark.edges.find( - v => v.node.frontmatter.title === snippet.title, - ).node.html, - tags: snippet.attributes.tags, - id: snippet.id, - })); + const snippets = props.data.allSnippet.edges; const [searchQuery, setSearchQuery] = React.useState(props.searchQuery); const [searchResults, setSearchResults] = React.useState(snippets); @@ -30,9 +23,9 @@ const SearchPage = props => { let results = snippets; if (q.trim().length) results = snippets.filter( - v => - v.tags.filter(t => t.indexOf(q) !== -1).length || - v.title.toLowerCase().indexOf(q) !== -1, + ({ node }) => + node.tags.all.filter(t => t.indexOf(q) !== -1).length || + node.title.toLowerCase().indexOf(q) !== -1, ); setSearchResults(results); }, [searchQuery]); @@ -75,11 +68,16 @@ const SearchPage = props => { ) : ( <>

Search results

- {searchResults.map(snippet => ( + {searchResults.map(({node}) => ( ))} @@ -102,22 +100,17 @@ export default connect( export const searchPageQuery = graphql` query searchSnippetList { - snippetDataJson(meta: { type: { eq: "snippetListingArray" }, scope: {eq: "./snippets"} }) { - data { - id - title - attributes { - tags - } - } - } - allMarkdownRemark { + allSnippet { edges { - node { - html - frontmatter { - title + node { + title + html { + text } + tags { + all + } + id } } } From 51dbd4cda3e9c3c05c1672761ae954f7dbafff22 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Fri, 20 Sep 2019 19:54:59 +0300 Subject: [PATCH 10/10] Fix archive page --- src/docs/pages/archive.js | 40 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/docs/pages/archive.js b/src/docs/pages/archive.js index b48aa13e8..12814f0bb 100644 --- a/src/docs/pages/archive.js +++ b/src/docs/pages/archive.js @@ -11,7 +11,7 @@ import SnippetCard from '../components/SnippetCard' // Individual snippet category/tag page // =================================================== const ArchivePage = props => { - const posts = props.data.allMarkdownRemark.edges; + const snippets = props.data.allSnippet.edges; React.useEffect(() => { props.dispatch(pushNewPage('Archived', props.path)); @@ -24,17 +24,17 @@ const ArchivePage = props => {

Archived snippets

These snippets, while useful and interesting, didn't quite make it into the repository due to either having very specific use-cases or being outdated. However we felt like they might still be useful to some readers, so here they are.

Click on a snippet card to view the snippet.

- {posts && - posts.map(({ node }) => ( + {snippets && + snippets.map(({ node }) => ( v.trim()), - id: node.fields.slug.slice(1), + title: node.title, + html: node.html.text, + tags: node.tags.all, + id: node.id }} isDarkMode={props.isDarkMode} /> @@ -55,25 +55,19 @@ export default connect( )(ArchivePage); export const archivePageQuery = graphql` - query ArchivePage { - allMarkdownRemark( - limit: 1000 - sort: { fields: [frontmatter___title], order: ASC } - filter: { fileAbsolutePath: { regex: "/snippets_archive/" }, frontmatter: {title: { ne: "" } } } - ) { - totalCount + query archiveListing { + allSnippet(filter: {archived: {eq: true}}) { edges { node { + title + html { + text + } + tags { + all + primary + } id - html - rawMarkdownBody - fields { - slug - } - frontmatter { - title - tags - } } } }