mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-12 16:47:26 +02:00
feat: prototype blog & docs generation on dev
This commit is contained in:
parent
187a46d9b6
commit
221023fd51
12 changed files with 181 additions and 37 deletions
11
lib/core/blog/index.js
Normal file
11
lib/core/blog/index.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
import MarkdownBlock from '../markdown';
|
||||
|
||||
class Docs extends React.Component {
|
||||
render() {
|
||||
const {content, siteConfig} = this.props;
|
||||
return <MarkdownBlock siteConfig={siteConfig}>{content}</MarkdownBlock>;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Docs;
|
|
@ -1,13 +0,0 @@
|
|||
import React from 'react';
|
||||
import blogDatas from '@generated/blogDatas';
|
||||
|
||||
// inner blog component for the article itself, without sidebar/header/footer
|
||||
class BlogPost extends React.Component {
|
||||
render() {
|
||||
const {match} = this.props;
|
||||
const post = blogDatas.find(blog => blog.path === match.path);
|
||||
return <div className="post">{post && post.content}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlogPost;
|
|
@ -1,8 +1,19 @@
|
|||
import React from 'react';
|
||||
import {render} from 'react-dom';
|
||||
import {BrowserRouter, Route, Switch, Link} from 'react-router-dom';
|
||||
import blogDatas from '@generated/blogDatas';
|
||||
import BlogPost from './blogPost';
|
||||
import blogMetadata from '@generated/blogMetadata';
|
||||
import docsMetadata from '@generated/docsMetadata';
|
||||
import Blog from './blog';
|
||||
import Docs from './docs';
|
||||
|
||||
const renderBlog = props => {
|
||||
const metadata = blogMetadata.find(blog => blog.path === props.match.path);
|
||||
return <Blog content={metadata.content} {...props} />;
|
||||
};
|
||||
const renderDocs = props => {
|
||||
const metadata = docsMetadata.find(doc => doc.path === props.match.path);
|
||||
return <Docs content={metadata.content} {...props} />;
|
||||
};
|
||||
|
||||
class App extends React.Component {
|
||||
render() {
|
||||
|
@ -10,17 +21,13 @@ class App extends React.Component {
|
|||
<BrowserRouter>
|
||||
<div>
|
||||
<Switch>
|
||||
{blogDatas.map(({path}) => (
|
||||
<Route key={path} exact path={path} component={BlogPost} />
|
||||
{blogMetadata.map(({path, content}) => (
|
||||
<Route key={path} exact path={path} render={renderBlog} />
|
||||
))}
|
||||
{docsMetadata.map(({path}) => (
|
||||
<Route key={path} exact path={path} render={renderDocs} />
|
||||
))}
|
||||
</Switch>
|
||||
<div>
|
||||
{blogDatas.map(({path}) => (
|
||||
<div key={path}>
|
||||
<Link to={path}>{path}</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
|
11
lib/core/docs/index.js
Normal file
11
lib/core/docs/index.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
import MarkdownBlock from '../markdown';
|
||||
|
||||
class Blog extends React.Component {
|
||||
render() {
|
||||
const {content, siteConfig} = this.props;
|
||||
return <MarkdownBlock siteConfig={siteConfig}>{content}</MarkdownBlock>;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Blog;
|
|
@ -10,6 +10,7 @@ class MarkdownBlock extends React.Component {
|
|||
const alias = {
|
||||
js: 'jsx'
|
||||
};
|
||||
const {siteConfig} = this.props;
|
||||
const md = new Markdown({
|
||||
langPrefix: 'hljs css language-',
|
||||
highlight(str, lang) {
|
||||
|
@ -99,6 +100,9 @@ class MarkdownBlock extends React.Component {
|
|||
|
||||
render() {
|
||||
const Container = this.props.container;
|
||||
if (!Container) {
|
||||
return <div>{this.content()}</div>;
|
||||
}
|
||||
return <Container>{this.content()}</Container>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ async function loadBlog(siteDir) {
|
|||
return {
|
||||
path: fileToPath(file),
|
||||
content,
|
||||
title: metadata.title,
|
||||
date: metadata.date
|
||||
...metadata
|
||||
};
|
||||
})
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@ const fs = require('fs-extra');
|
|||
const path = require('path');
|
||||
|
||||
module.exports = function loadConfig(siteDir, deleteCache = true) {
|
||||
const configPath = path.resolve(siteDir, 'config.js');
|
||||
const configPath = path.resolve(siteDir, 'siteConfig.js');
|
||||
if (deleteCache) {
|
||||
delete require.cache[configPath];
|
||||
}
|
||||
|
|
47
lib/loader/docs.js
Normal file
47
lib/loader/docs.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const fm = require('front-matter');
|
||||
const globby = require('globby');
|
||||
|
||||
const indexRE = /(^|.*\/)index\.md$/i;
|
||||
const mdRE = /\.md$/;
|
||||
|
||||
function fileToPath(file) {
|
||||
if (indexRE.test(file)) {
|
||||
return file.replace(indexRE, '/$1');
|
||||
}
|
||||
return `/${file.replace(mdRE, '').replace(/\\/g, '/')}.html`;
|
||||
}
|
||||
|
||||
function parse(fileString) {
|
||||
if (!fm.test(fileString)) {
|
||||
return {metadata: null, content: fileString};
|
||||
}
|
||||
const {attributes: metadata, body: content} = fm(fileString);
|
||||
|
||||
return {metadata, content};
|
||||
}
|
||||
|
||||
async function loadDocs(siteDir) {
|
||||
const blogFiles = await globby(['**/*.md'], {
|
||||
cwd: siteDir
|
||||
});
|
||||
|
||||
const blogDatas = await Promise.all(
|
||||
blogFiles.map(async file => {
|
||||
const filepath = path.resolve(siteDir, file);
|
||||
const fileString = await fs.readFile(filepath, 'utf-8');
|
||||
const {metadata, content} = parse(fileString);
|
||||
|
||||
return {
|
||||
path: fileToPath(file),
|
||||
content,
|
||||
...metadata
|
||||
};
|
||||
})
|
||||
);
|
||||
blogDatas.sort((a, b) => b.date - a.date);
|
||||
return blogDatas;
|
||||
}
|
||||
|
||||
module.exports = loadDocs;
|
|
@ -2,19 +2,33 @@ const fs = require('fs-extra');
|
|||
const path = require('path');
|
||||
const loadConfig = require('./config');
|
||||
const loadBlog = require('./blog');
|
||||
const loadDocs = require('./docs');
|
||||
const {generate} = require('../helpers');
|
||||
|
||||
module.exports = async function load(siteDir) {
|
||||
// load siteConfig
|
||||
const siteConfig = loadConfig(siteDir);
|
||||
|
||||
// extract data from all blog files
|
||||
const blogDatas = await loadBlog(siteDir);
|
||||
|
||||
// docs
|
||||
const docsRelativeDir = siteConfig.customDocsPath || 'docs';
|
||||
const docsMetadata = await loadDocs(
|
||||
path.resolve(siteDir, '..', docsRelativeDir)
|
||||
);
|
||||
await generate(
|
||||
'blogDatas.js',
|
||||
'docsMetadata.js',
|
||||
`${'/**\n * @generated\n */\n' + 'module.exports = '}${JSON.stringify(
|
||||
blogDatas,
|
||||
docsMetadata,
|
||||
null,
|
||||
2
|
||||
)};\n`
|
||||
);
|
||||
|
||||
// blog
|
||||
const blogMetadata = await loadBlog(path.resolve(siteDir, 'blog'));
|
||||
await generate(
|
||||
'blogMetadata.js',
|
||||
`${'/**\n * @generated\n */\n' + 'module.exports = '}${JSON.stringify(
|
||||
blogMetadata,
|
||||
null,
|
||||
2
|
||||
)};\n`
|
||||
|
@ -32,14 +46,13 @@ module.exports = async function load(siteDir) {
|
|||
? path.resolve(__dirname, '../ui')
|
||||
: siteConfig.uiPath;
|
||||
|
||||
const publicPath = siteConfig.base || '/';
|
||||
const baseUrl = siteConfig.baseUrl || '/';
|
||||
|
||||
return {
|
||||
siteConfig,
|
||||
blogDatas,
|
||||
siteDir,
|
||||
outDir,
|
||||
uiPath,
|
||||
publicPath
|
||||
baseUrl
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ const Config = require('webpack-chain');
|
|||
const path = require('path');
|
||||
|
||||
module.exports = function createBaseConfig(props) {
|
||||
const {outDir, uiPath, siteDir, publicPath} = props;
|
||||
const {outDir, uiPath, siteDir, baseUrl} = props;
|
||||
|
||||
const config = new Config();
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
@ -13,7 +13,7 @@ module.exports = function createBaseConfig(props) {
|
|||
.filename(
|
||||
isProd ? 'static/js/[name].[chunkhash].js' : 'static/js/[name].js'
|
||||
)
|
||||
.publicPath(isProd ? publicPath : '/');
|
||||
.publicPath(isProd ? baseUrl : '/');
|
||||
|
||||
config.resolve
|
||||
.set('symlinks', true)
|
||||
|
|
|
@ -51,15 +51,18 @@
|
|||
"front-matter": "^2.3.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
"globby": "^8.0.1",
|
||||
"highlight.js": "^9.12.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"koa-connect": "^2.0.1",
|
||||
"koa-mount": "^3.0.0",
|
||||
"koa-range": "^0.3.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"portfinder": "^1.0.13",
|
||||
"prismjs": "^1.15.0",
|
||||
"react": "^16.4.1",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"remarkable": "^1.7.1",
|
||||
"semver": "^5.5.0",
|
||||
"webpack": "^4.16.3",
|
||||
"webpack-chain": "^4.8.0",
|
||||
|
|
62
yarn.lock
62
yarn.lock
|
@ -379,6 +379,13 @@ argparse@^1.0.7:
|
|||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
argparse@~0.1.15:
|
||||
version "0.1.16"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c"
|
||||
dependencies:
|
||||
underscore "~1.7.0"
|
||||
underscore.string "~2.4.0"
|
||||
|
||||
aria-query@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
|
||||
|
@ -517,6 +524,10 @@ atob@^2.1.1:
|
|||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
|
||||
|
||||
autolinker@~0.15.0:
|
||||
version "0.15.3"
|
||||
resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.15.3.tgz#342417d8f2f3461b14cf09088d5edf8791dc9832"
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
|
@ -1492,6 +1503,14 @@ cli-width@^2.0.0:
|
|||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
||||
|
||||
clipboard@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a"
|
||||
dependencies:
|
||||
good-listener "^1.2.2"
|
||||
select "^1.1.2"
|
||||
tiny-emitter "^2.0.0"
|
||||
|
||||
clipboardy@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef"
|
||||
|
@ -1895,6 +1914,10 @@ delayed-stream@~1.0.0:
|
|||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
|
||||
delegate@^3.1.2:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
|
@ -2846,6 +2869,12 @@ globby@^8.0.1:
|
|||
pify "^3.0.0"
|
||||
slash "^1.0.0"
|
||||
|
||||
good-listener@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
|
||||
dependencies:
|
||||
delegate "^3.1.2"
|
||||
|
||||
got@^6.7.1:
|
||||
version "6.7.1"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
|
||||
|
@ -2970,6 +2999,10 @@ he@1.1.x:
|
|||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
|
||||
highlight.js@^9.12.0:
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
|
||||
|
||||
history@^4.7.2:
|
||||
version "4.7.2"
|
||||
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
|
||||
|
@ -5132,6 +5165,12 @@ pretty-time@^1.0.0:
|
|||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"
|
||||
|
||||
prismjs@^1.15.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9"
|
||||
optionalDependencies:
|
||||
clipboard "^2.0.0"
|
||||
|
||||
private@^0.1.6, private@^0.1.8:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
||||
|
@ -5505,6 +5544,13 @@ relateurl@0.2.x:
|
|||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
|
||||
|
||||
remarkable@^1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.1.tgz#aaca4972100b66a642a63a1021ca4bac1be3bff6"
|
||||
dependencies:
|
||||
argparse "~0.1.15"
|
||||
autolinker "~0.15.0"
|
||||
|
||||
remove-array-items@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-array-items/-/remove-array-items-1.0.0.tgz#07bf42cb332f4cf6e85ead83b5e4e896d2326b21"
|
||||
|
@ -5737,6 +5783,10 @@ schema-utils@^0.4.4, schema-utils@^0.4.5:
|
|||
ajv "^6.1.0"
|
||||
ajv-keywords "^3.1.0"
|
||||
|
||||
select@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
||||
|
||||
semver-diff@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
|
||||
|
@ -6211,6 +6261,10 @@ timers-browserify@^2.0.4:
|
|||
dependencies:
|
||||
setimmediate "^1.0.4"
|
||||
|
||||
tiny-emitter@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
|
@ -6361,6 +6415,14 @@ uglifyjs-webpack-plugin@^1.2.4:
|
|||
webpack-sources "^1.1.0"
|
||||
worker-farm "^1.5.2"
|
||||
|
||||
underscore.string@~2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b"
|
||||
|
||||
underscore@~1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
|
||||
union-value@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue