-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…ration-docs-blog MDX Integration for docs and blog pages
- Loading branch information
Showing
148 changed files
with
5,536 additions
and
241 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
const { resolve: r } = require("path"); | ||
|
||
const { nodeFields } = require("../src/config/internal/nodes"); | ||
const { ROUTE_BLOG, ROUTE_DOCS, ROUTE_LANDING, ROUTE_ROOT } = require("../src/config/routes/mappings"); | ||
|
||
const TemplateBlogPost = r(__dirname, "../src/components/templates/blog/BlogPost.jsx"); | ||
const TemplateDocsPage = r(__dirname, "../src/components/templates/docs/DocsPage.jsx"); | ||
|
||
const mdxQuery = ` | ||
{ | ||
allMdx { | ||
edges { | ||
node { | ||
code { | ||
scope | ||
} | ||
fields { | ||
${Object.keys(nodeFields).map(nf => nf.replace(",", "\n"))} | ||
} | ||
frontmatter { | ||
draft | ||
} | ||
id | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
|
||
/** | ||
* Implementation of the Gatsby Node "createPages" API which tells plugins to add pages. | ||
* This extension point is called only after the initial sourcing and transformation of nodes and | ||
* when the creation of the GraphQL schema is complete to allow to query data in order to create pages. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://next.gatsbyjs.org/docs/node-apis/#createPages | ||
* @see https://next.gatsbyjs.org/docs/node-apis/#createPage | ||
* @see https://github.com/ChristopherBiscardi/gatsby-mdx | ||
*/ | ||
const createPages = async ({ graphql, actions }) => { | ||
const { createPage, createRedirect } = actions; | ||
const isProductionMode = process.env.NODE_ENV === "production"; | ||
|
||
/* Always redirect from the landing page to the root route. */ | ||
createRedirect({ | ||
fromPath: ROUTE_LANDING, | ||
redirectInBrowser: true, | ||
toPath: ROUTE_ROOT | ||
}); | ||
|
||
const mdxQueryResult = await graphql(mdxQuery); | ||
if (mdxQueryResult.errors) { | ||
throw Error("Error while running GraphQL query for MDX!", mdxQueryResult.errors); | ||
} | ||
|
||
mdxQueryResult.data.allMdx.edges.forEach(({ node }) => { | ||
const { id } = node; | ||
const { contentSourceType, date, relativeDirectory, slug, slugParentRoute } = node.fields; | ||
const { draft, publishTime } = node.frontmatter; | ||
|
||
/* Only create non-draft pages in production mode while also create draft pages during development. */ | ||
if (draft && isProductionMode) return; | ||
|
||
let template; | ||
switch (slugParentRoute) { | ||
case ROUTE_BLOG: | ||
template = TemplateBlogPost; | ||
break; | ||
case ROUTE_DOCS: | ||
template = TemplateDocsPage; | ||
break; | ||
default: | ||
throw Error(`No matching template found while creating page for node with path ${slugParentRoute}${slug}!`); | ||
} | ||
|
||
createPage({ | ||
path: `${slugParentRoute}${slug}`, | ||
component: template, | ||
/* | ||
* Make the specified fields available as variables in page queries. | ||
* | ||
* @see https://graphql.org/learn/queries/#variables | ||
* @see https://www.gatsbyjs.org/docs/graphql-reference/#query-variables | ||
*/ | ||
context: { | ||
contentSourceType, | ||
date, | ||
id, | ||
publishTime, | ||
relativeDirectory, | ||
slug, | ||
slugParentRoute | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
module.exports = createPages; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
const glob = require("glob"); | ||
const { createFilePath } = require("gatsby-source-filesystem"); | ||
const { dirname } = require("path"); | ||
const { existsSync } = require("fs"); | ||
|
||
const { | ||
nodeFields, | ||
optionalBlogPostImages, | ||
optionalBlogPostVideos, | ||
sourceInstanceTypes, | ||
requiredBlogPostImages | ||
} = require("../src/config/internal/nodes"); | ||
const { BASE_DIR_CONTENT, NODE_TYPE_MDX, REGEX_BLOG_POST_DATE } = require("../src/config/internal/constants"); | ||
const { ROUTE_BLOG, ROUTE_DOCS } = require("../src/config/routes/mappings"); | ||
|
||
/** | ||
* Extracts the date of a blog post from the given path using the `REGEX_BLOG_POST_DATE` regular expression. | ||
* The exact time of the day will be parsed from the blog posts frontmatter "publishTime" field. | ||
* | ||
* @private | ||
* @method extractBlogPostDateFromPath | ||
* @param {string} path The path from which the blog post date should be extracted. | ||
* @return {string|null} The extracted blog post date if the given path matches the regular expression, | ||
* `null` otherwise. | ||
*/ | ||
const extractBlogPostDateFromPath = path => { | ||
const date = REGEX_BLOG_POST_DATE.exec(path); | ||
return date ? `${date[1]}-${date[2]}-${date[3]}` : null; | ||
}; | ||
|
||
/** | ||
* Implementation of the Gatsby Node "onCreateNode" API which gets called when a new node is created. | ||
* Allows plugins to extend or transform nodes created by other plugins. | ||
* | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://next.gatsbyjs.org/docs/node-apis/#onCreateNode | ||
* @see https://next.gatsbyjs.org/docs/actions/#createNode | ||
* @see https://next.gatsbyjs.org/docs/actions/#createNodeField | ||
* @see https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-filesystem#createfilepath | ||
*/ | ||
const onCreateNode = ({ node, getNode, actions }) => { | ||
const { createNodeField } = actions; | ||
if (node.internal.type === NODE_TYPE_MDX) { | ||
const contentFileResourceSlug = createFilePath({ | ||
node, | ||
getNode, | ||
basePath: `${BASE_DIR_CONTENT}`, | ||
trailingSlash: false | ||
}); | ||
const { absolutePath, relativeDirectory, relativePath, sourceInstanceName } = getNode(node.parent); | ||
|
||
if (sourceInstanceName === sourceInstanceTypes.blog.id) { | ||
const date = extractBlogPostDateFromPath(relativePath); | ||
|
||
if (!date) { | ||
throw Error( | ||
`Blog post content resource path '${relativePath}' doesn't match the required date-based directory structure: ${REGEX_BLOG_POST_DATE}` | ||
); | ||
} | ||
|
||
/* Check for required blog post images and generate node fields. */ | ||
Object.keys(requiredBlogPostImages).forEach(image => { | ||
const { name, nodeFieldName } = requiredBlogPostImages[image]; | ||
const matches = glob.sync(`${dirname(absolutePath)}/${name}.?(png|jpg|jpeg)`); | ||
|
||
if (!matches.length) { | ||
throw Error(`Required '${name}.(png|jpg|jpeg)' image not found for blog post '${relativeDirectory}'!`); | ||
} | ||
if (existsSync(matches[0])) { | ||
createNodeField({ | ||
node, | ||
name: nodeFieldName, | ||
value: matches[0] | ||
}); | ||
} | ||
}); | ||
|
||
/* Check for optional blog post images and generate node fields. */ | ||
Object.keys(optionalBlogPostImages).forEach(image => { | ||
const { name, nodeFieldName } = optionalBlogPostImages[image]; | ||
const matches = glob.sync(`${dirname(absolutePath)}/${name}.?(png|jpg|jpeg)`); | ||
|
||
if (existsSync(matches[0])) { | ||
createNodeField({ | ||
node, | ||
name: nodeFieldName, | ||
value: matches[0] | ||
}); | ||
} | ||
}); | ||
|
||
/* Check for optional blog post videos and generate node fields. */ | ||
Object.keys(optionalBlogPostVideos).forEach(video => { | ||
const { name, nodeFieldName } = optionalBlogPostVideos[video]; | ||
const matches = glob.sync(`${dirname(absolutePath)}/${name}.?(mp4|webm)`); | ||
if (existsSync(matches[0])) { | ||
createNodeField({ | ||
node, | ||
name: nodeFieldName, | ||
value: matches[0] | ||
}); | ||
} | ||
}); | ||
|
||
createNodeField({ | ||
node, | ||
name: `${nodeFields.date.name}`, | ||
value: date | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.contentSourceType.name}`, | ||
value: `${sourceInstanceTypes.blog.id}` | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.relativeDirectory.name}`, | ||
value: `${relativeDirectory}` | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.slug.name}`, | ||
value: `${contentFileResourceSlug}` | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.slugParentRoute.name}`, | ||
value: `${ROUTE_BLOG}` | ||
}); | ||
} | ||
|
||
if (sourceInstanceName === sourceInstanceTypes.docs.id) { | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.contentSourceType.name}`, | ||
value: `${sourceInstanceTypes.docs.id}` | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.relativeDirectory.name}`, | ||
value: `${relativeDirectory}` | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.slug.name}`, | ||
value: contentFileResourceSlug | ||
}); | ||
createNodeField({ | ||
node, | ||
name: `${nodeFields.slugParentRoute.name}`, | ||
value: `${ROUTE_DOCS}` | ||
}); | ||
} | ||
} | ||
}; | ||
|
||
module.exports = onCreateNode; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
/** | ||
* @file The configuration for the Gatsby plugin `gatsby-mdx`. | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://mdxjs.com | ||
* @see https://github.com/ChristopherBiscardi/gatsby-mdx | ||
*/ | ||
|
||
const remarkBreaks = require("remark-breaks"); | ||
const remarkGitHub = require("remark-github"); | ||
const rehypeSlug = require("rehype-slug"); | ||
|
||
const { metadataNordDocs } = require("../../src/data/project"); | ||
|
||
const remarkGitHubOptions = { | ||
repository: `${metadataNordDocs.repository.url}`, | ||
mentionStrong: false | ||
}; | ||
|
||
module.exports = { | ||
defaultLayouts: { | ||
blog: require.resolve("../../src/components/templates/blog/BlogPost.jsx"), | ||
docs: require.resolve("../../src/components/templates/docs/DocsPage.jsx") | ||
}, | ||
footnotes: true, | ||
gatsbyRemarkPlugins: [], | ||
hastPlugins: [rehypeSlug], | ||
mdPlugins: [remarkBreaks, [remarkGitHub, remarkGitHubOptions]] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (C) 2018-present Arctic Ice Studio <[email protected]> | ||
* Copyright (C) 2018-present Sven Greb <[email protected]> | ||
* | ||
* Project: Nord Docs | ||
* Repository: https://github.com/arcticicestudio/nord-docs | ||
* License: MIT | ||
*/ | ||
|
||
/** | ||
* The Visual Studio Code debug configuration for Gatsby. | ||
* @author Arctic Ice Studio <[email protected]> | ||
* @author Sven Greb <[email protected]> | ||
* @since 0.10.0 | ||
* @see https://github.com/Microsoft/vscode-recipes/tree/master/Gatsby-js | ||
* @see https://www.gatsbyjs.org/docs/debugging-the-build-process | ||
*/ | ||
{ | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "node", | ||
"request": "launch", | ||
"name": "Gatsby Development Build Process", | ||
"program": "${workspaceRoot}/node_modules/gatsby/dist/bin/gatsby", | ||
"args": ["develop"], | ||
"runtimeArgs": [ | ||
/* | ||
* For performance reasons Node.js parses functions lazily on first access. | ||
* As a consequence, breakpoints don't work in source code areas that haven't been parsed by Node.js. | ||
* The `--nolazy` flag prevents the delayed parsing and ensures that breakpoints can be validated before | ||
* running the code. | ||
* | ||
* @see https://nodejs.org/api/cli.html#cli_v8_options | ||
*/ | ||
"--nolazy" | ||
], | ||
"stopOnEntry": false, | ||
"sourceMaps": false, | ||
"internalConsoleOptions": "openOnSessionStart" | ||
} | ||
] | ||
} |
This file was deleted.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const frontmatter = { | ||
title: "GraphQL query error draft stub", | ||
introduction: "This file must be kept to prevent GraphQL queries to fail when no blog posts are in the filesystem.", | ||
publishTime: "00:00:00+0000", | ||
coverTitleColor: "", | ||
draft: true | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const frontmatter = { | ||
title: "GraphQL query error draft stub", | ||
subline: "This file must be kept to prevent GraphQL queries to fail when no docs pages are in the filesystem.", | ||
draft: true | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.