Skip to content

Commit

Permalink
feat(v2): export frontMatter as an object within MDX file (#1451)
Browse files Browse the repository at this point in the history
* refactor. Don't confuse metadata & frontmatter

* export frontMatter in content itself

* nits

* nits name

* dont truncate first four lines in blog
  • Loading branch information
endiliey authored and yangshun committed May 13, 2019
1 parent 1cf714a commit 08be07b
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 110 deletions.
1 change: 1 addition & 0 deletions packages/docusaurus-mdx-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@mdx-js/mdx": "^1.0.18",
"@mdx-js/react": "^1.0.16",
"github-slugger": "^1.2.1",
"gray-matter": "^4.0.2",
"loader-utils": "^1.2.3",
"mdast-util-to-string": "^1.0.5",
"prism-themes": "^1.1.0",
Expand Down
6 changes: 5 additions & 1 deletion packages/docusaurus-mdx-loader/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const mdx = require('@mdx-js/mdx');
const rehypePrism = require('@mapbox/rehype-prism');
const emoji = require('remark-emoji');
const slug = require('rehype-slug');
const matter = require('gray-matter');
const stringifyObject = require('stringify-object');
const linkHeadings = require('./linkHeadings');
const rightToc = require('./rightToc');

Expand All @@ -19,9 +21,10 @@ const DEFAULT_OPTIONS = {
prismTheme: 'prism-themes/themes/prism-atom-dark.css',
};

module.exports = async function(content) {
module.exports = async function(fileString) {
const callback = this.async();

const {data, content} = matter(fileString);
const options = Object.assign(DEFAULT_OPTIONS, getOptions(this), {
filepath: this.resourcePath,
});
Expand All @@ -43,6 +46,7 @@ module.exports = async function(content) {
import React from 'react';
import { mdx } from '@mdx-js/react';
${importStr}
export const frontMatter = ${stringifyObject(data)};
${result}
`;

Expand Down
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-blog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"@docusaurus/utils": "^2.0.0-alpha.13",
"fs-extra": "^7.0.1",
"globby": "^9.1.0",
"gray-matter": "^4.0.2",
"loader-utils": "^1.2.3"
},
"peerDependencies": {
Expand Down
54 changes: 15 additions & 39 deletions packages/docusaurus-plugin-content-blog/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class DocusaurusPluginContentBlog {
);

const fileString = await fs.readFile(source, 'utf-8');
const {frontMatter, excerpt: description} = parse(fileString);
const {frontMatter, excerpt} = parse(fileString);

blogPosts.push({
id: blogFileName,
Expand All @@ -85,10 +85,10 @@ class DocusaurusPluginContentBlog {
fileToUrl(blogFileName),
]),
source,
description,
description: frontMatter.description || excerpt,
date,
title: frontMatter.title || blogFileName,
},
frontMatter,
});
}),
);
Expand Down Expand Up @@ -141,21 +141,13 @@ class DocusaurusPluginContentBlog {
// Create routes for blog entries.
const blogItems = await Promise.all(
blogPosts.map(async blogPost => {
const {id, frontMatter, metadata} = blogPost;
const {id, metadata} = blogPost;
const {permalink} = metadata;
const [frontMatterPath, metadataPath] = await Promise.all([
createData(
`${docuHash(`${permalink}-frontmatter`)}.json`,
JSON.stringify(frontMatter, null, 2),
),
createData(
`${docuHash(`${permalink}-metadata`)}.json`,
JSON.stringify(metadata, null, 2),
),
]);
const metadataPath = await createData(
`${docuHash(permalink)}.json`,
JSON.stringify(metadata, null, 2),
);
const temp = {
frontMatter,
frontMatterPath,
metadata,
metadataPath,
};
Expand All @@ -169,7 +161,7 @@ class DocusaurusPluginContentBlog {
const prevItem = index > 0 ? blogItems[index - 1] : null;
const nextItem =
index < blogItems.length - 1 ? blogItems[index + 1] : null;
const {frontMatterPath, metadata, metadataPath} = blogItem;
const {metadata, metadataPath} = blogItem;
const {source, permalink} = metadata;

addRoute({
Expand All @@ -178,22 +170,9 @@ class DocusaurusPluginContentBlog {
exact: true,
modules: {
content: source,
frontMatter: frontMatterPath,
metadata: metadataPath,
prevItem:
prevItem != null
? {
metadata: prevItem.metadataPath,
frontMatter: prevItem.frontMatterPath,
}
: null,
nextItem:
nextItem != null
? {
metadata: nextItem.metadataPath,
frontMatter: nextItem.frontMatterPath,
}
: null,
prevItem: prevItem && prevItem.metadataPath,
nextItem: nextItem && nextItem.metadataPath,
},
});
});
Expand All @@ -204,7 +183,7 @@ class DocusaurusPluginContentBlog {
const {metadata, items} = listPage;
const {permalink} = metadata;
const pageMetadataPath = await createData(
`${docuHash(`${permalink}-metadata`)}.json`,
`${docuHash(permalink)}.json`,
JSON.stringify(metadata, null, 2),
);

Expand All @@ -214,11 +193,9 @@ class DocusaurusPluginContentBlog {
exact: true,
modules: {
items: items.map(postID => {
const {
frontMatterPath,
metadata: postMetadata,
metadataPath,
} = blogItemsToModules[postID];
const {metadata: postMetadata, metadataPath} = blogItemsToModules[
postID
];
// To tell routes.js this is an import and not a nested object to recurse.
return {
content: {
Expand All @@ -229,7 +206,6 @@ class DocusaurusPluginContentBlog {
},
},
metadata: metadataPath,
frontMatter: frontMatterPath,
};
}),
metadata: pageMetadataPath,
Expand Down
20 changes: 5 additions & 15 deletions packages/docusaurus-plugin-content-blog/src/markdownLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,20 @@
* LICENSE file in the root directory of this source tree.
*/

const matter = require('gray-matter');
const {parseQuery} = require('loader-utils');

const TRUNCATE_MARKER = /<!--\s*truncate\s*-->/;

module.exports = async function(fileString) {
const callback = this.async();

// Extract content of markdown (without frontmatter).
let {content} = matter(fileString);
let finalContent = fileString;

// Truncate content if requested (e.g: file.md?truncated=true)
const {truncated} = this.resourceQuery && parseQuery(this.resourceQuery);
if (truncated) {
if (TRUNCATE_MARKER.test(content)) {
// eslint-disable-next-line
content = content.split(TRUNCATE_MARKER)[0];
} else {
// Return first 4 lines of the content as summary
content = content
.split('\n')
.slice(0, 4)
.join('\n');
}
if (truncated && TRUNCATE_MARKER.test(fileString)) {
// eslint-disable-next-line
finalContent = fileString.split(TRUNCATE_MARKER)[0];
}
return callback(null, content);
return callback(null, finalContent);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@ function BlogListPage(props) {
<div className="row">
<div className="col col--8 col--offset-2">
{items.map(
({
content: BlogPostContent,
frontMatter,
metadata: blogPostMetadata,
}) => (
({content: BlogPostContent, metadata: blogPostMetadata}) => (
<div
className="margin-bottom--xl"
key={blogPostMetadata.permalink}>
<BlogPostItem
frontMatter={frontMatter}
frontMatter={BlogPostContent.frontMatter}
metadata={blogPostMetadata}
truncated>
<BlogPostContent />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,10 @@ import BlogPostItem from '@theme/BlogPostItem';
import BlogPostPaginator from '../BlogPostPaginator';

function BlogPostPage(props) {
const {
content: BlogPostContents,
frontMatter,
metadata,
nextItem,
prevItem,
} = props;

const {content: BlogPostContents, metadata, nextItem, prevItem} = props;
const {frontMatter} = BlogPostContents;
return (
<Layout title={frontMatter.title} description={frontMatter.description}>
<Layout title={metadata.title} description={metadata.description}>
{BlogPostContents && (
<div className="container margin-vert--xl">
<div className="row">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,15 @@ function BlogPostPaginator(props) {
<div className="row">
<div className="col col--6">
{prevItem && (
<Link
className="button button--secondary"
to={prevItem.metadata.permalink}>
{prevItem.frontMatter.title}
<Link className="button button--secondary" to={prevItem.permalink}>
{prevItem.title}
</Link>
)}
</div>
<div className="col col--6 text--right">
{nextItem && (
<Link
className="button button--secondary"
to={nextItem.metadata.permalink}>
{nextItem.frontMatter.title}
<Link className="button button--secondary" to={nextItem.permalink}>
{nextItem.title}
</Link>
)}
</div>
Expand Down
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@docusaurus/utils": "^2.0.0-alpha.13",
"fs-extra": "^7.0.1",
"globby": "^9.1.0",
"gray-matter": "^4.0.2",
"import-fresh": "^3.0.0",
"loader-utils": "^1.2.3"
},
Expand Down
6 changes: 2 additions & 4 deletions packages/docusaurus-plugin-content-docs/src/markdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/

const matter = require('gray-matter');
const {getOptions} = require('loader-utils');
const {resolve} = require('url');

Expand All @@ -16,16 +15,15 @@ module.exports = async function(fileString) {
});
const {docsDir, sourceToPermalink} = options;

// Extract content of markdown (without frontmatter).
let {content} = matter(fileString);

// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
let sourceDir;
const thisSource = this.resourcePath;
if (thisSource.startsWith(docsDir)) {
sourceDir = docsDir;
}

let content = fileString;

// Replace internal markdown linking (except in fenced blocks).
if (sourceDir) {
let fencedBlock = false;
Expand Down
48 changes: 22 additions & 26 deletions packages/docusaurus-plugin-content-docs/src/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,70 +18,66 @@ module.exports = async function processMetadata(
) {
const filepath = path.resolve(refDir, source);
const fileString = await fs.readFile(filepath, 'utf-8');
const {frontMatter = {}, excerpt} = parse(fileString);
const {frontMatter: metadata = {}, excerpt} = parse(fileString);

// Default id is the file name.
if (!frontMatter.id) {
frontMatter.id = path.basename(source, path.extname(source));
if (!metadata.id) {
metadata.id = path.basename(source, path.extname(source));
}
if (frontMatter.id.includes('/')) {
if (metadata.id.includes('/')) {
throw new Error('Document id cannot include "/".');
}

// Default title is the id.
if (!frontMatter.title) {
frontMatter.title = frontMatter.id;
if (!metadata.title) {
metadata.title = metadata.id;
}

if (!frontMatter.description) {
frontMatter.description = excerpt;
if (!metadata.description) {
metadata.description = excerpt;
}

const dirName = path.dirname(source);
if (dirName !== '.') {
const prefix = dirName;
if (prefix) {
frontMatter.id = `${prefix}/${frontMatter.id}`;
metadata.id = `${prefix}/${metadata.id}`;
}
}

// The docs absolute file source.
// e.g: `/end/docs/hello.md` or `/end/website/versioned_docs/version-1.0.0/hello.md`
frontMatter.source = path.join(refDir, source);
metadata.source = path.join(refDir, source);

// Build the permalink.
const {baseUrl} = siteConfig;

// If user has own custom permalink defined in frontmatter
// e.g: :baseUrl:docsUrl/:langPart/:versionPart/endiliey/:id
if (frontMatter.permalink) {
frontMatter.permalink = path.resolve(
frontMatter.permalink
if (metadata.permalink) {
metadata.permalink = path.resolve(
metadata.permalink
.replace(/:baseUrl/, baseUrl)
.replace(/:docsUrl/, docsBasePath)
.replace(/:id/, frontMatter.id),
.replace(/:id/, metadata.id),
);
} else {
frontMatter.permalink = normalizeUrl([
baseUrl,
docsBasePath,
frontMatter.id,
]);
metadata.permalink = normalizeUrl([baseUrl, docsBasePath, metadata.id]);
}

// Determine order.
const {id} = frontMatter;
const {id} = metadata;
if (order[id]) {
frontMatter.sidebar = order[id].sidebar;
frontMatter.category = order[id].category;
frontMatter.subCategory = order[id].subCategory;
metadata.sidebar = order[id].sidebar;
metadata.category = order[id].category;
metadata.subCategory = order[id].subCategory;
if (order[id].next) {
frontMatter.next = order[id].next;
metadata.next = order[id].next;
}
if (order[id].previous) {
frontMatter.previous = order[id].previous;
metadata.previous = order[id].previous;
}
}

return frontMatter;
return metadata;
};
2 changes: 2 additions & 0 deletions website-1.x/blog/2018-12-14-Happy-First-Birthday-Slash.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ authorTwitter: JoelMarcey

Docusaurus [went live](https://docusaurus.io/blog/2017/12/14/introducing-docusaurus) on December 14, 2017. At the time, we had [8 early adopters](https://docusaurus.io/blog/2017/12/14/introducing-docusaurus#acknowledgements).

<!--truncate-->

We now have nearly [60 known users of Docusaurus](https://docusaurus.io/en/users), and probably more that we don't know about. We have [9K GitHub stars](https://github.com/facebook/docusaurus) and an active community, particularly [Yangshun Tay](https://twitter.com/yangshunz) and [Endilie Yacop Sucipto](https://twitter.com/endiliey), both of whom are the lead maintainers helping keep this project [moving forward](https://docusaurus.io/blog/2018/09/11/Towards-Docusaurus-2).

Thank you to everyone for your support and use of this project! I am super proud of how far this project has come in just a year.
Expand Down

0 comments on commit 08be07b

Please sign in to comment.