feat(v2): blog slug frontmatter (#3284)

This commit is contained in:
Jean-Marc Saad 2020-08-20 15:59:54 +03:00 committed by GitHub
parent 0f357606cd
commit 3ea2f8cfde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 107 additions and 27 deletions

View file

@ -34,6 +34,24 @@ authorTwitter: JoelMarcey
Lorem Ipsum... Lorem Ipsum...
``` ```
Adding slug will override the url of the blog post.
For example:
```yml
---
slug: introducing-docusaurus
title: Introducing Docusaurus
author: Joel Marcey
authorURL: http://twitter.com/JoelMarcey
authorFBID: 611217057
authorTwitter: JoelMarcey
---
Lorem Ipsum...
```
Will be available at `https://website/blog/introducing-docusaurus`
## Header Options ## Header Options
The only required field is `title`; however, we provide options to add author information to your blog post as well along with other options. The only required field is `title`; however, we provide options to add author information to your blog post as well along with other options.
@ -43,6 +61,7 @@ The only required field is `title`; however, we provide options to add author in
- `authorFBID` - The Facebook profile ID that is used to fetch the profile picture. - `authorFBID` - The Facebook profile ID that is used to fetch the profile picture.
- `authorImageURL` - The URL to the author's image. (Note: If you use both `authorFBID` and `authorImageURL`, `authorFBID` will take precedence. Don't include `authorFBID` if you want `authorImageURL` to appear.) - `authorImageURL` - The URL to the author's image. (Note: If you use both `authorFBID` and `authorImageURL`, `authorFBID` will take precedence. Don't include `authorFBID` if you want `authorImageURL` to appear.)
- `title` - The blog post title. - `title` - The blog post title.
- `slug` - The blog post url slug. Example: `/blog/my-test-slug`. When not specified, the blog url slug will be extracted from the file name.
- `unlisted` - The post will be accessible by directly visiting the URL but will not show up in the sidebar in the final build; during local development, the post will still be listed. Useful in situations where you want to share a WIP post with others for feedback. - `unlisted` - The post will be accessible by directly visiting the URL but will not show up in the sidebar in the final build; during local development, the post will still be listed. Useful in situations where you want to share a WIP post with others for feedback.
## Summary Truncation ## Summary Truncation

View file

@ -1,5 +1,5 @@
--- ---
id: hola slug: hola
title: Hola title: Hola
author: Gao Wei author: Gao Wei
author_title: Docusaurus Core Team author_title: Docusaurus Core Team

View file

@ -1,5 +1,5 @@
--- ---
id: hello-world slug: hello-world
title: Hello title: Hello
author: Endilie Yacop Sucipto author: Endilie Yacop Sucipto
author_title: Maintainer of Docusaurus author_title: Maintainer of Docusaurus

View file

@ -1,5 +1,5 @@
--- ---
id: welcome slug: welcome
title: Welcome title: Welcome
author: Yangshun Tay author: Yangshun Tay
author_title: Front End Engineer @ Facebook author_title: Front End Engineer @ Facebook

View file

@ -1,5 +1,5 @@
--- ---
id: hola slug: hola
title: Hola title: Hola
author: Gao Wei author: Gao Wei
author_title: Docusaurus Core Team author_title: Docusaurus Core Team

View file

@ -1,5 +1,5 @@
--- ---
id: hello-world slug: hello-world
title: Hello title: Hello
author: Endilie Yacop Sucipto author: Endilie Yacop Sucipto
author_title: Maintainer of Docusaurus author_title: Maintainer of Docusaurus

View file

@ -1,5 +1,5 @@
--- ---
id: welcome slug: welcome
title: Welcome title: Welcome
author: Yangshun Tay author: Yangshun Tay
author_title: Front End Engineer @ Facebook author_title: Front End Engineer @ Facebook

View file

@ -1,5 +1,5 @@
--- ---
id: hola slug: hola
title: Hola title: Hola
author: Gao Wei author: Gao Wei
author_title: Docusaurus Core Team author_title: Docusaurus Core Team

View file

@ -1,5 +1,5 @@
--- ---
id: hello-world slug: hello-world
title: Hello title: Hello
author: Endilie Yacop Sucipto author: Endilie Yacop Sucipto
author_title: Maintainer of Docusaurus author_title: Maintainer of Docusaurus

View file

@ -1,5 +1,5 @@
--- ---
id: welcome slug: welcome
title: Welcome title: Welcome
author: Yangshun Tay author: Yangshun Tay
author_title: Front End Engineer @ Facebook author_title: Front End Engineer @ Facebook

View file

@ -23,6 +23,7 @@
"@docusaurus/utils-validation": "^2.0.0-alpha.61", "@docusaurus/utils-validation": "^2.0.0-alpha.61",
"@hapi/joi": "^17.1.1", "@hapi/joi": "^17.1.1",
"feed": "^4.1.0", "feed": "^4.1.0",
"chalk": "^3.0.0",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"globby": "^10.0.1", "globby": "^10.0.1",
"loader-utils": "^1.2.3", "loader-utils": "^1.2.3",

View file

@ -0,0 +1,7 @@
---
slug: /hey/my super path/héllô
title: Complex Slug
date: 2020-08-16
---
complex url slug

View file

@ -0,0 +1,7 @@
---
slug: /simple/slug
title: Simple Slug
date: 2020-08-16
---
simple url slug

View file

@ -28,14 +28,14 @@ exports[`blogFeed atom shows feed item for each post 1`] = `
<entry> <entry>
<title type=\\"html\\"><![CDATA[draft]]></title> <title type=\\"html\\"><![CDATA[draft]]></title>
<id>draft</id> <id>draft</id>
<link href=\\"https://docusaurus.io/blog/2020/02/27/draft\\"/> <link href=\\"https://docusaurus.io/blog/draft\\"/>
<updated>2020-02-27T00:00:00.000Z</updated> <updated>2020-02-27T00:00:00.000Z</updated>
<summary type=\\"html\\"><![CDATA[this post should not be published yet]]></summary> <summary type=\\"html\\"><![CDATA[this post should not be published yet]]></summary>
</entry> </entry>
<entry> <entry>
<title type=\\"html\\"><![CDATA[date-matter]]></title> <title type=\\"html\\"><![CDATA[date-matter]]></title>
<id>date-matter</id> <id>date-matter</id>
<link href=\\"https://docusaurus.io/blog/2019/01/01/date-matter\\"/> <link href=\\"https://docusaurus.io/blog/date-matter\\"/>
<updated>2019-01-01T00:00:00.000Z</updated> <updated>2019-01-01T00:00:00.000Z</updated>
<summary type=\\"html\\"><![CDATA[date inside front matter]]></summary> <summary type=\\"html\\"><![CDATA[date inside front matter]]></summary>
</entry> </entry>
@ -77,14 +77,14 @@ exports[`blogFeed rss shows feed item for each post 1`] = `
<copyright>Copyright</copyright> <copyright>Copyright</copyright>
<item> <item>
<title><![CDATA[draft]]></title> <title><![CDATA[draft]]></title>
<link>https://docusaurus.io/blog/2020/02/27/draft</link> <link>https://docusaurus.io/blog/draft</link>
<guid>draft</guid> <guid>draft</guid>
<pubDate>Thu, 27 Feb 2020 00:00:00 GMT</pubDate> <pubDate>Thu, 27 Feb 2020 00:00:00 GMT</pubDate>
<description><![CDATA[this post should not be published yet]]></description> <description><![CDATA[this post should not be published yet]]></description>
</item> </item>
<item> <item>
<title><![CDATA[date-matter]]></title> <title><![CDATA[date-matter]]></title>
<link>https://docusaurus.io/blog/2019/01/01/date-matter</link> <link>https://docusaurus.io/blog/date-matter</link>
<guid>date-matter</guid> <guid>date-matter</guid>
<pubDate>Tue, 01 Jan 2019 00:00:00 GMT</pubDate> <pubDate>Tue, 01 Jan 2019 00:00:00 GMT</pubDate>
<description><![CDATA[date inside front matter]]></description> <description><![CDATA[date inside front matter]]></description>

View file

@ -53,10 +53,6 @@ describe('loadBlog', () => {
const noDateSourceBirthTime = ( const noDateSourceBirthTime = (
await fs.stat(noDateSource.replace('@site', siteDir)) await fs.stat(noDateSource.replace('@site', siteDir))
).birthtime; ).birthtime;
const noDatePermalink = `/blog/${noDateSourceBirthTime
.toISOString()
.substr(0, '2019-01-01'.length)
.replace(/-/g, '/')}/no date`;
expect({ expect({
...blogPosts.find((v) => v.metadata.title === 'date-matter').metadata, ...blogPosts.find((v) => v.metadata.title === 'date-matter').metadata,
@ -64,7 +60,7 @@ describe('loadBlog', () => {
}).toEqual({ }).toEqual({
editUrl: editUrl:
'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/date-matter.md', 'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/date-matter.md',
permalink: '/blog/2019/01/01/date-matter', permalink: '/blog/date-matter',
readingTime: 0.02, readingTime: 0.02,
source: path.join('@site', pluginPath, 'date-matter.md'), source: path.join('@site', pluginPath, 'date-matter.md'),
title: 'date-matter', title: 'date-matter',
@ -97,7 +93,7 @@ describe('loadBlog', () => {
date: new Date('2018-12-14'), date: new Date('2018-12-14'),
tags: [], tags: [],
prevItem: { prevItem: {
permalink: '/blog/2019/01/01/date-matter', permalink: '/blog/date-matter',
title: 'date-matter', title: 'date-matter',
}, },
truncated: false, truncated: false,
@ -109,7 +105,7 @@ describe('loadBlog', () => {
}).toEqual({ }).toEqual({
editUrl: editUrl:
'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/no date.md', 'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/no date.md',
permalink: noDatePermalink, permalink: '/blog/no date',
readingTime: 0.01, readingTime: 0.01,
source: noDateSource, source: noDateSource,
title: 'no date', title: 'no date',
@ -118,9 +114,51 @@ describe('loadBlog', () => {
tags: [], tags: [],
prevItem: undefined, prevItem: undefined,
nextItem: { nextItem: {
permalink: '/blog/2020/02/27/draft', permalink: '/blog/hey/my super path/héllô',
title: 'Complex Slug',
},
truncated: false,
});
expect({
...blogPosts.find((v) => v.metadata.title === 'Complex Slug').metadata,
...{prevItem: undefined},
}).toEqual({
editUrl:
'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/complex-slug.md',
permalink: '/blog/hey/my super path/héllô',
readingTime: 0.015,
source: path.join('@site', pluginPath, 'complex-slug.md'),
title: 'Complex Slug',
description: `complex url slug`,
prevItem: undefined,
nextItem: {
permalink: '/blog/simple/slug',
title: 'Simple Slug',
},
date: new Date('2020-08-16'),
tags: [],
truncated: false,
});
expect({
...blogPosts.find((v) => v.metadata.title === 'Simple Slug').metadata,
...{prevItem: undefined},
}).toEqual({
editUrl:
'https://github.com/facebook/docusaurus/edit/master/website-1x/blog/simple-slug.md',
permalink: '/blog/simple/slug',
readingTime: 0.015,
source: path.join('@site', pluginPath, 'simple-slug.md'),
title: 'Simple Slug',
description: `simple url slug`,
prevItem: undefined,
nextItem: {
permalink: '/blog/draft',
title: 'draft', title: 'draft',
}, },
date: new Date('2020-08-16'),
tags: [],
truncated: false, truncated: false,
}); });
}); });

View file

@ -7,6 +7,7 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import globby from 'globby'; import globby from 'globby';
import chalk from 'chalk';
import path from 'path'; import path from 'path';
import readingTime from 'reading-time'; import readingTime from 'reading-time';
import {Feed} from 'feed'; import {Feed} from 'feed';
@ -126,6 +127,14 @@ export async function generateBlogPosts(
return; return;
} }
if (frontMatter.id) {
console.warn(
chalk.yellow(
`${blogFileName} - 'id' header option is deprecated. Please use 'slug' option instead.`,
),
);
}
let date; let date;
// Extract date and title from filename. // Extract date and title from filename.
const match = blogFileName.match(FILENAME_PATTERN); const match = blogFileName.match(FILENAME_PATTERN);
@ -144,16 +153,15 @@ export async function generateBlogPosts(
// Use file create time for blog. // Use file create time for blog.
date = date || (await fs.stat(source)).birthtime; date = date || (await fs.stat(source)).birthtime;
const slug =
frontMatter.slug || (match ? toUrl({date, link: linkName}) : linkName);
frontMatter.title = frontMatter.title || linkName; frontMatter.title = frontMatter.title || linkName;
blogPosts.push({ blogPosts.push({
id: frontMatter.id || frontMatter.title, id: frontMatter.slug || frontMatter.title,
metadata: { metadata: {
permalink: normalizeUrl([ permalink: normalizeUrl([baseUrl, routeBasePath, slug]),
baseUrl,
routeBasePath,
frontMatter.id || toUrl({date, link: linkName}),
]),
editUrl: editBlogUrl, editUrl: editBlogUrl,
source: aliasedSource, source: aliasedSource,
description: frontMatter.description || excerpt, description: frontMatter.description || excerpt,