feat(v2): meta description (#1447)

* feat(v2): meta description

* add description for blog as well

* fix non-descriptive text link

* remove font awesome

* switch front-matter -> gray-matter
This commit is contained in:
Endi 2019-05-10 22:37:56 +07:00 committed by GitHub
parent 34195e4c30
commit 6136fbe1d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 82 additions and 58 deletions

View file

@ -10,9 +10,9 @@
"dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.13",
"@docusaurus/utils": "^2.0.0-alpha.13",
"front-matter": "^3.0.1",
"fs-extra": "^7.0.1",
"globby": "^9.1.0",
"gray-matter": "^4.0.2",
"loader-utils": "^1.2.3"
},
"peerDependencies": {

View file

@ -75,7 +75,7 @@ class DocusaurusPluginContentBlog {
);
const fileString = await fs.readFile(source, 'utf-8');
const {metadata: rawMetadata} = parse(fileString);
const {metadata: rawMetadata, excerpt: description} = parse(fileString);
const metadata = {
permalink: normalizeUrl([
@ -84,6 +84,7 @@ class DocusaurusPluginContentBlog {
fileToUrl(blogFileName),
]),
source,
description,
...rawMetadata,
date,
};

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
const fm = require('front-matter');
const matter = require('gray-matter');
const {parseQuery} = require('loader-utils');
const TRUNCATE_MARKER = /<!--\s*truncate\s*-->/;
@ -14,7 +14,7 @@ module.exports = async function(fileString) {
const callback = this.async();
// Extract content of markdown (without frontmatter).
let {body: content} = fm(fileString);
let {content} = matter(fileString);
// Truncate content if requested (e.g: file.md?truncated=true)
const {truncated} = this.resourceQuery && parseQuery(this.resourceQuery);

View file

@ -17,7 +17,7 @@ function BlogListPage(props) {
} = props;
return (
<Layout title="Blog">
<Layout title="Blog" description="Blog">
<div className="container margin-vert--xl">
<div className="row">
<div className="col col--6 col--offset-3">

View file

@ -14,7 +14,7 @@ function BlogPostPage(props) {
const {content: BlogPostContents, metadata} = props;
return (
<Layout title={metadata.title}>
<Layout title={metadata.title} description={metadata.description}>
{BlogPostContents && (
<div className="container margin-vert--xl">
<div className="row">

View file

@ -11,9 +11,9 @@
"@babel/polyfill": "^7.4.0",
"@docusaurus/mdx-loader": "^2.0.0-alpha.13",
"@docusaurus/utils": "^2.0.0-alpha.13",
"front-matter": "^3.0.1",
"fs-extra": "^7.0.1",
"globby": "^9.1.0",
"gray-matter": "^4.0.2",
"import-fresh": "^3.0.0",
"loader-utils": "^1.2.3"
},

View file

@ -1,6 +1,7 @@
---
id: bar
title: Bar
description: This is custom description
---
# Remarkable

View file

@ -39,6 +39,7 @@ describe('loadDocs', () => {
sidebar: 'docs',
source: path.join(docsDir, 'hello.md'),
title: 'Hello, World !',
description: `Hi, Endilie here :)`,
});
expect(docsMetadata['foo/bar']).toEqual({
category: 'Test',
@ -49,6 +50,7 @@ describe('loadDocs', () => {
sidebar: 'docs',
source: path.join(docsDir, 'foo', 'bar.md'),
title: 'Bar',
description: 'This is custom description',
});
});
});

View file

@ -40,12 +40,14 @@ describe('processMetadata', () => {
permalink: '/docs/foo/bar',
source: path.join(docsDir, sourceA),
title: 'Bar',
description: 'This is custom description',
});
expect(dataB).toEqual({
id: 'hello',
permalink: '/docs/hello',
source: path.join(docsDir, sourceB),
title: 'Hello, World !',
description: `Hi, Endilie here :)`,
});
});
@ -57,6 +59,7 @@ describe('processMetadata', () => {
permalink: '/docs/endiliey/permalink',
source: path.join(docsDir, source),
title: 'Permalink',
description: 'This has a different permalink',
});
});
});

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
const fm = require('front-matter');
const matter = require('gray-matter');
const {getOptions} = require('loader-utils');
const {resolve} = require('url');
@ -17,7 +17,7 @@ module.exports = async function(fileString) {
const {docsDir, sourceToPermalink} = options;
// Extract content of markdown (without frontmatter).
const {body} = fm(fileString);
let {content} = matter(fileString);
// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
let sourceDir;
@ -27,10 +27,9 @@ module.exports = async function(fileString) {
}
// Replace internal markdown linking (except in fenced blocks).
let content = body;
if (sourceDir) {
let fencedBlock = false;
const lines = body.split('\n').map(line => {
const lines = content.split('\n').map(line => {
if (line.trim().startsWith('```')) {
fencedBlock = !fencedBlock;
}

View file

@ -18,7 +18,7 @@ module.exports = async function processMetadata(
) {
const filepath = path.resolve(refDir, source);
const fileString = await fs.readFile(filepath, 'utf-8');
const {metadata} = parse(fileString);
const {metadata = {}, excerpt} = parse(fileString);
// Default id is the file name.
if (!metadata.id) {
@ -33,6 +33,10 @@ module.exports = async function processMetadata(
metadata.title = metadata.id;
}
if (!metadata.description) {
metadata.description = excerpt;
}
const dirName = path.dirname(source);
if (dirName !== '.') {
const prefix = dirName;

View file

@ -14,13 +14,19 @@ import DocSidebar from '@theme/DocSidebar';
function DocPage(props) {
const {route, docsMetadata, location} = props;
const {permalinkToId} = docsMetadata;
const id =
permalinkToId[location.pathname] ||
permalinkToId[location.pathname.replace(/\/$/, '')];
const metadata = docsMetadata.docs[id] || {};
const {sidebar, description} = metadata;
return (
<Layout noFooter>
<Layout noFooter description={description}>
<div className="container container--fluid">
<div className="row">
<div className="col col--3">
<DocSidebar docsMetadata={docsMetadata} location={location} />
<DocSidebar docsMetadata={docsMetadata} sidebar={sidebar} />
</div>
<div className="col col--9">
{renderRoutes(route.routes, {docsMetadata})}

View file

@ -12,13 +12,7 @@ import Link from '@docusaurus/Link'; // eslint-disable-line
import './styles.css';
function DocSidebar(props) {
const {docsMetadata, location} = props;
const id =
docsMetadata.permalinkToId[location.pathname] ||
docsMetadata.permalinkToId[location.pathname.replace(/\/$/, '')];
const metadata = docsMetadata.docs[id] || {};
const {sidebar} = metadata;
const {docsMetadata, sidebar} = props;
if (!sidebar) {
return null;

View file

@ -17,12 +17,16 @@ function Layout(props) {
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
const {baseUrl, favicon, tagline, title: defaultTitle} = siteConfig;
const {children, title, noFooter} = props;
const {children, title, noFooter, description} = props;
return (
<React.Fragment>
<Head defaultTitle={`${defaultTitle} · ${tagline}`}>
{title && <title>{`${title} · ${tagline}`}</title>}
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
</Head>
<Navbar />
{children}

View file

@ -9,8 +9,8 @@
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^1.0.5",
"front-matter": "^3.0.1",
"fs-extra": "^7.0.0",
"gray-matter": "^4.0.2",
"lodash": "^4.17.11"
}
}

View file

@ -6,7 +6,7 @@
*/
const path = require('path');
const fm = require('front-matter');
const matter = require('gray-matter');
const {createHash} = require('crypto');
const _ = require(`lodash`);
@ -163,15 +163,19 @@ function getSubFolder(file, refDir) {
/**
* @param {string} fileString
* @returns {*}
* @returns {Object}
*/
function parse(fileString) {
if (!fm.test(fileString)) {
return {metadata: null, content: fileString};
}
const {attributes: metadata, body: content} = fm(fileString);
return {metadata, content};
const {data: metadata, content, excerpt} = matter(fileString, {
excerpt(file) {
// eslint-disable-next-line no-param-reassign
file.excerpt = file.content
.trim()
.split('\n', 1)
.shift();
},
});
return {metadata, content, excerpt};
}
/**

View file

@ -47,7 +47,6 @@
"ejs": "^2.6.1",
"envinfo": "^7.2.0",
"express": "^4.16.4",
"front-matter": "^3.0.1",
"fs-extra": "^7.0.0",
"globby": "^9.1.0",
"html-webpack-plugin": "^4.0.0-beta.5",

View file

@ -19,13 +19,6 @@ function App() {
<DocusaurusContext.Provider value={{siteConfig}}>
{/* TODO: this link stylesheet to infima is temporary */}
<Head>
<link
crossOrigin="anonymous"
href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
preload
rel="stylesheet"
/>
<link
href="https://infima-dev.netlify.com/css/default/default.min.css"
preload

View file

@ -13,12 +13,16 @@ function Layout(props) {
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
const {baseUrl, favicon, tagline, title: defaultTitle} = siteConfig;
const {children, title} = props;
const {children, title, description} = props;
return (
<React.Fragment>
<Head defaultTitle={`${defaultTitle} · ${tagline}`}>
{title && <title>{`${title} · ${tagline}`}</title>}
{favicon && <link rel="shortcut icon" href={baseUrl + favicon} />}
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
</Head>
{children}
</React.Fragment>

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import React, {useContext, useEffect} from 'react';
import React, {useContext} from 'react';
import Head from '@docusaurus/Head';
import DocusaurusContext from '@docusaurus/context';
import Link from '@docusaurus/Link';
@ -68,14 +68,8 @@ function Home() {
const feedbackUrl = `${siteConfig.baseUrl}feedback/`;
const gettingStartedUrl = `${siteConfig.baseUrl}docs/introduction`;
useEffect(() => {
// Prefetch feedback pages & getting started pages
window.docusaurus.prefetch(feedbackUrl);
window.docusaurus.prefetch(gettingStartedUrl);
}, []);
return (
<Layout>
<Layout description={'Docusaurus makes it easy to build websites'}>
<div className={styles['index-hero']}>
<div className={styles['index-hero-inner']}>
<h1 className={styles['index-hero-project-tagline']}>
@ -115,8 +109,8 @@ function Home() {
<a href="https://github.com/facebook/Docusaurus/issues/789">
Docusaurus 2
</a>
, contribute to its roadmap by suggesting features or giving feedback{' '}
<Link to={feedbackUrl}>here</Link>!
, contribute to its roadmap by suggesting features or giving{' '}
<Link to={feedbackUrl}>feedback here</Link>!
</div>
</div>
<div className={styles.section}>

View file

@ -5858,13 +5858,6 @@ front-matter@^2.3.0:
dependencies:
js-yaml "^3.10.0"
front-matter@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-3.0.2.tgz#2401cd05fcf22bd0de48a104ffb4efb1ff5c8465"
integrity sha512-iBGZaWyzqgsrPGsqrXZP6N4hp5FzSKDi18nfAoYpgz3qK5sAwFv/ojmn3VS60SOgLvq6CtojNqy0y6ZNz05IzQ==
dependencies:
js-yaml "^3.13.1"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
@ -6330,6 +6323,16 @@ gray-matter@^2.1.0:
js-yaml "^3.8.1"
toml "^2.3.2"
gray-matter@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454"
integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==
dependencies:
js-yaml "^3.11.0"
kind-of "^6.0.2"
section-matter "^1.0.0"
strip-bom-string "^1.0.0"
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@ -8095,7 +8098,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.10.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.8.1, js-yaml@^3.9.1:
js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.8.1, js-yaml@^3.9.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@ -11991,6 +11994,14 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
section-matter@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167"
integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==
dependencies:
extend-shallow "^2.0.1"
kind-of "^6.0.0"
seek-bzip@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
@ -12737,6 +12748,11 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0:
dependencies:
ansi-regex "^4.1.0"
strip-bom-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92"
integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"