diff --git a/lib/core/blog/index.js b/lib/core/blog/index.js
new file mode 100644
index 0000000000..f5f1bf7b69
--- /dev/null
+++ b/lib/core/blog/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import MarkdownBlock from '../markdown';
+
+class Docs extends React.Component {
+ render() {
+ const {content, siteConfig} = this.props;
+ return {content};
+ }
+}
+
+module.exports = Docs;
diff --git a/lib/core/blogPost.js b/lib/core/blogPost.js
deleted file mode 100644
index 0698cf6581..0000000000
--- a/lib/core/blogPost.js
+++ /dev/null
@@ -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
{post && post.content}
;
- }
-}
-
-module.exports = BlogPost;
diff --git a/lib/core/devEntry.js b/lib/core/devEntry.js
index 8fb024c577..ebf7322b07 100644
--- a/lib/core/devEntry.js
+++ b/lib/core/devEntry.js
@@ -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 ;
+};
+const renderDocs = props => {
+ const metadata = docsMetadata.find(doc => doc.path === props.match.path);
+ return ;
+};
class App extends React.Component {
render() {
@@ -10,17 +21,13 @@ class App extends React.Component {
- {blogDatas.map(({path}) => (
-
+ {blogMetadata.map(({path, content}) => (
+
+ ))}
+ {docsMetadata.map(({path}) => (
+
))}
-
- {blogDatas.map(({path}) => (
-
- {path}
-
- ))}
-
);
diff --git a/lib/core/docs/index.js b/lib/core/docs/index.js
new file mode 100644
index 0000000000..1134a6e8d3
--- /dev/null
+++ b/lib/core/docs/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import MarkdownBlock from '../markdown';
+
+class Blog extends React.Component {
+ render() {
+ const {content, siteConfig} = this.props;
+ return {content};
+ }
+}
+
+module.exports = Blog;
diff --git a/lib/core/markdown/index.js b/lib/core/markdown/index.js
index 038765c7e3..c50ab500bf 100644
--- a/lib/core/markdown/index.js
+++ b/lib/core/markdown/index.js
@@ -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 {this.content()}
;
+ }
return {this.content()};
}
}
diff --git a/lib/loader/blog.js b/lib/loader/blog.js
index 13dbda3faf..da54415a74 100644
--- a/lib/loader/blog.js
+++ b/lib/loader/blog.js
@@ -36,8 +36,7 @@ async function loadBlog(siteDir) {
return {
path: fileToPath(file),
content,
- title: metadata.title,
- date: metadata.date
+ ...metadata
};
})
);
diff --git a/lib/loader/config.js b/lib/loader/config.js
index 6656aab290..557edef3e2 100644
--- a/lib/loader/config.js
+++ b/lib/loader/config.js
@@ -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];
}
diff --git a/lib/loader/docs.js b/lib/loader/docs.js
new file mode 100644
index 0000000000..a117b5deeb
--- /dev/null
+++ b/lib/loader/docs.js
@@ -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;
diff --git a/lib/loader/index.js b/lib/loader/index.js
index b9cc66eda0..cd56932b5a 100644
--- a/lib/loader/index.js
+++ b/lib/loader/index.js
@@ -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
};
};
diff --git a/lib/webpack/base.js b/lib/webpack/base.js
index 29bffe0567..b84a05d719 100644
--- a/lib/webpack/base.js
+++ b/lib/webpack/base.js
@@ -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)
diff --git a/package.json b/package.json
index 4218cdff92..374f2436dd 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/yarn.lock b/yarn.lock
index 88553e302e..31940932f2 100644
--- a/yarn.lock
+++ b/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"