Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Initial support for MDX #179

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/gatsby/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@
"sharp": "0.22.0"
},
"dependencies": {
"@mdx-js/mdx": "^1.0.19",
"@mdx-js/react": "^1.0.16",
"@mdx-js/tag": "^0.20.3",
"classnames": "^2.2.6",
"gatsby-cli": "^2.5.7",
"gatsby-image": "^2.0.38",
"gatsby-mdx": "^0.6.3",
"gatsby-plugin-catch-links": "^2.0.13",
"gatsby-plugin-feed": "^2.1.0",
"gatsby-plugin-google-analytics": "^2.0.18",
Expand Down
9 changes: 9 additions & 0 deletions modules/gatsby/src/gatsby-config/get-gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ module.exports = function getGatsbyConfig(config) {
}
},

// Handles MDX files
{
resolve: 'gatsby-mdx',
options: {
extensions: ['.mdx']
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just want to point out that this is precisely where ocular-gatsby is useful. existing sites just have to upgrade ocular-gatsby, not change their manual configurations or add new dependencies :)


// Handles MD files
// Transforms markdown (.md) nodes, converting the raw markdown to HTML
{
resolve: 'gatsby-transformer-remark',
Expand Down
6 changes: 6 additions & 0 deletions modules/gatsby/src/gatsby-node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
cleanupMarkdownNode,
addSiblingNodes
} = require('./process-nodes/process-nodes-markdown');
const {processNewMDXNode} = require('./process-nodes/process-nodes-mdx');
const {processNewDocsJsonNode} = require('./process-nodes/process-nodes-json');
const {sourceNodes} = require('./source-nodes');

Expand All @@ -34,11 +35,16 @@ function onCreateNode({node, actions, getNode}) {
processNewMarkdownNode({node, actions, getNode}, docNodes, tocNode);
break;

case 'Mdx':
processNewMDXNode({node, actions, getNode}, docNodes, tocNode);
break;

case 'DocsJson':
tocNode = processNewDocsJsonNode({node, actions, getNode}, docNodes);
break;

default:
console.log(node.internal.type, node.fileAbsolutePath);
}
}

Expand Down
69 changes: 69 additions & 0 deletions modules/gatsby/src/gatsby-node/pages/create-doc-pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ function queryMarkdownDocs(graphql) {
});
}

function queryMdxDocs(graphql) {
return graphql(
`
{
allMdx {
edges {
node {
fileAbsolutePath
code {
body
}
}
}
}
}
`
).then(result => {
if (result.errors) {
/* eslint no-console: "off" */
console.log(result.errors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no logger?

throw new Error(result.errors);
}
return result;
});
}

// Walks all markdown nodes and creates a doc page for each node
function createDocMarkdownPages({ graphql, actions }) {
const { createPage } = actions;
Expand Down Expand Up @@ -139,7 +165,50 @@ function createDocMarkdownPages({ graphql, actions }) {
});
}

// Walks all markdown nodes and creates a doc page for each node
function createDocMdxPages({ graphql, actions }) {
const { createPage } = actions;

return queryMdxDocs(graphql)
.then(result => {
// const rootFolder = result.data.site.siteMetadata.config.ROOT_FOLDER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why comment it out? is that temporary?

// const pathToSlug = result.data.allMarkdownRemark.edges.map(({ node }) => ({
// source: node.fileAbsolutePath,
// target: node.fields.slug
// }));

// let relativeLinks = {};
// result.data.allMdx.edges.forEach(edge => {
// pathToSlug.forEach(({ source, target }) => {
// relativeLinks = addToRelativeLinks({
// source,
// target,
// rootFolder,
// edge,
// relativeLinks
// });
// });
// });

result.data.allMdx.edges.forEach(edge => {
console.log('Creating MDX page at', edge.node.fields.path);

const componentUrl = getPageTemplateUrl('DOC_MDX_PAGE_URL');

createPage({
path: edge.node.fields.path,
component: componentUrl,
context: {
// relativeLinks,
slug: edge.node.fields.path,
toc: 'docs'
}
});
});
});
}

module.exports = function createDocPages({ graphql, actions }) {
createDocMarkdownPages({ graphql, actions });
createDocMdxPages({ graphql, actions });
};
2 changes: 2 additions & 0 deletions modules/gatsby/src/gatsby-node/pages/get-page-template-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const assert = require('assert');
const INDEX_PAGE_URL = path.resolve(__dirname, '../../templates/index.jsx');

const DOC_MARKDOWN_PAGE_URL = path.resolve(__dirname, '../../templates/doc-page-markdown.jsx');
const DOC_MDX_PAGE_URL = path.resolve(__dirname, '../../templates/doc-page-mdx.jsx');

const EXAMPLE_GALLERY_PAGE_URL = path.resolve(__dirname, '../../templates/examples.jsx');
const EXAMPLE_PAGE_URL = path.resolve(__dirname, '../../templates/example-n.jsx');
Expand All @@ -16,6 +17,7 @@ const PAGE_TEMPLATES = {
INDEX_PAGE_URL,

DOC_MARKDOWN_PAGE_URL,
DOC_MDX_PAGE_URL,

EXAMPLE_GALLERY_PAGE_URL,
EXAMPLE_PAGE_URL,
Expand Down
92 changes: 92 additions & 0 deletions modules/gatsby/src/gatsby-node/process-nodes/process-nodes-mdx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
module.exports.processNewMDXNode = function processNewMDXNode(
{ node, actions, getNode },
docNodes,
tocNode
) {
debugger
console.log('MDX Node', JSON.stringify(node, null, 2));
/*
const { createNodeField } = actions;

const fileNode = getNode(node.parent);
const parsedFilePath = path.parse(fileNode.relativePath);
const hasTitle =
Object.prototype.hasOwnProperty.call(node, 'frontmatter') &&
Object.prototype.hasOwnProperty.call(node.frontmatter, 'title');

let slug;
if (hasTitle) {
slug = `/${_.kebabCase(node.frontmatter.title)}`;
} else if (parsedFilePath.name !== 'index' && parsedFilePath.dir !== '') {
slug = `/${parsedFilePath.dir}/${parsedFilePath.name}/`;
} else if (parsedFilePath.dir === '') {
slug = `/${parsedFilePath.name}/`;
} else {
slug = `/${parsedFilePath.dir}/`;
}

/*
if (Object.prototype.hasOwnProperty.call(node, 'frontmatter')) {
if (Object.prototype.hasOwnProperty.call(node.frontmatter, 'slug'))
slug = `/${_.kebabCase(node.frontmatter.slug)}`;
if (Object.prototype.hasOwnProperty.call(node.frontmatter, 'date')) {
const date = moment(node.frontmatter.date, siteConfig.dateFromFormat);
if (!date.isValid)
console.warn(`WARNING: Invalid date.`, node.frontmatter);

createNodeField({
node,
name: 'date',
value: date.toISOString()
});
}
}

// createNodeField({ node, name: 'slug', value: slug });
// postNodes.push(node);

// Update path
let relPath = node.fields.slug;
if (node.fileAbsolutePath) {
const index = node.fileAbsolutePath.indexOf('docs');
if (index !== -1) {
relPath = node.fileAbsolutePath.slice(index);
}

// relPath = path.relative(siteConfig.ROOT_FOLDER, node.fileAbsolutePath);
const basename = path.basename(relPath, '.md');
const dirname = path.dirname(relPath);
relPath = basename === 'README' ? dirname : `${dirname}/${basename}`;

createNodeField({ node, name: 'path', value: relPath });
createNodeField({ node, name: 'slug', value: relPath });
node.frontmatter.path = relPath;
}
if (tocNode) {
// this means toc node has been created. Any markdown file processed beyond this point wouldn't have its info
// in the toc.
// but we can inject it afterwards

// the regular toc node generation process adds the full content of each markdown node to the toc.
// we don't need as much. The app will only use the title and slug of the corresponding markdown
// node for each toc entry.

const nodeToEdit = parseToc([tocNode], relPath);
if (nodeToEdit) {
nodeToEdit.childMarkdownRemark = {
fields: {
slug: relPath
},
frontmatter: {
title: node.frontmatter.title
},
};
}
log.log({ color: COLOR.YELLOW }, `putting ${relPath} back in the TOC`)();
} else {
// while toc node isn't created, we can add the docs nodes to docNodes, which is used to add data to the TOC
// once the toc node is created, there is no reason to keep doing that
docNodes[relPath] = node;
}
*/
};
55 changes: 55 additions & 0 deletions modules/gatsby/src/templates/doc-page-mdx.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { graphql } from 'gatsby';
// import { MDXRenderer } from 'gatsby-mdx';

// Query for the markdown doc by slug
// (Note: We could just search the allMarkdown from WebsiteConfig ourselves)
export const query = graphql`
query mdxDocById($id: String) {
mdx(id: { eq: $id }) {
code {
body
}
}
}
`;

// function replaceLinks(props) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI I'm considering extending this functionality to more elements for the "regular" doc file (ie replacing h1, h2, pre, table etc. DOM elements generated by markdown and whose styling depends on scss by styled components).

// const { body } = props.data.mdx.code;
// const { code, relativeLinks } = props.pageContext;

// return html.replace(/href="([^"]+)"/g, (link, href) => {
// // don't rewrite external links, don't rewrite links to anchors
// if (href.startsWith('http') || href.startsWith('#')) {
// // TODO - we could style them differently though
// return link;
// }
// const hrefWithoutLeadingSlash = href.startsWith('/') ? href.slice(1) : href;
// // replace links to:
// // - known physical files, either relative to this file or relative to root
// // - known routes, either relative to the route of this page or to the home page
// // by a link to their corresponding route, expresed relative to the home page
// return `href="${relativeLinks[hrefWithoutLeadingSlash]}"`;
// });
// }

export default class DocTemplate extends React.Component {
constructor(props) {
debugger
super(props);
this.state = { html: 'works' };
console.error('markdown rendering with props', JSON.stringify(this.props, null, 2));
}

render() {
const { html } = this.state;
return (
<div>
<div
className="markdown-body"
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>
);
}
}
Loading