diff --git a/blog/foo/bar.md b/blog/foo/bar.md
new file mode 100644
index 0000000000..4b28a826e3
--- /dev/null
+++ b/blog/foo/bar.md
@@ -0,0 +1,6 @@
+---
+title: Lorem ipsum
+date: 2018-06-20
+---
+
+Lorem ipsumsdsdsad
diff --git a/blog/foo/baz.md b/blog/foo/baz.md
new file mode 100644
index 0000000000..c4e0cbf40d
--- /dev/null
+++ b/blog/foo/baz.md
@@ -0,0 +1,5 @@
+---
+title: Baz
+date: 2018-05-20
+---
+Life is so good
diff --git a/lib/core/blogPost.js b/lib/core/blogPost.js
new file mode 100644
index 0000000000..d3611ade2f
--- /dev/null
+++ b/lib/core/blogPost.js
@@ -0,0 +1,13 @@
+const React = require('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/index.js b/lib/core/index.js
index dbe96b255c..2a4a5fc3ed 100644
--- a/lib/core/index.js
+++ b/lib/core/index.js
@@ -1,30 +1,30 @@
import React from 'react';
import {render} from 'react-dom';
-import {BrowserRouter, Route, Switch} from 'react-router-dom';
-import Hello from '@theme/hello';
-import Layout from '@theme/layout';
+import {BrowserRouter, Route, Switch, Link} from 'react-router-dom';
+import BlogPost from './blogPost';
+import blogDatas from '@generated/blogDatas';
class App extends React.Component {
render() {
- const routes = [
- {
- path: '/',
- component: Hello
- },
- {
- path: '/layout',
- component: Layout
- }
- ];
-
return (
- {routes.map(({path, component}) => (
-
+ {blogDatas.map(({path}) => (
+
))}
+
+ {blogDatas.map(({path}) => {
+ return (
+
+
+ {path}
+
+
+ );
+ })}
+
);
diff --git a/lib/dev.js b/lib/dev.js
index 7517b23d39..949048b135 100644
--- a/lib/dev.js
+++ b/lib/dev.js
@@ -3,11 +3,22 @@ const fs = require('fs-extra');
const chalk = require('chalk');
const webpack = require('webpack');
const chokidar = require('chokidar');
+const convert = require('koa-connect')
+const range = require('koa-range')
+const history = require('connect-history-api-fallback')
+const portfinder = require('portfinder')
const serve = require('webpack-serve');
const webpackNiceLog = require('webpack-nicelog');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
const load = require('./loader');
const createDevConfig = require('./webpack/dev');
+async function getPort (port) {
+ portfinder.basePort = parseInt(port) || 8080
+ port = await portfinder.getPortPromise()
+ return port
+}
+
module.exports = async function dev(sourceDir, cliOptions = {}) {
// load site props from preprocessed files in source directory
const props = await load(sourceDir);
@@ -18,7 +29,7 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
console.error(chalk.red(err.stack));
});
};
- const fsWatcher = chokidar.watch(['**/*.md'], {
+ const fsWatcher = chokidar.watch(['**/*.md', '.blogi/config.js'], {
cwd: sourceDir,
ignoreInitial: true
});
@@ -31,7 +42,7 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
// resolve webpack config
let config = createDevConfig(props);
- const port = cliOptions.port || 8080;
+ const port = await getPort(cliOptions.port);
const {publicPath} = props;
config.plugin('WebpackNiceLog').use(webpackNiceLog, [
@@ -46,6 +57,15 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
}
]);
+ config.plugin('html-webpack-plugin').use(HtmlWebpackPlugin, [
+ {
+ inject: false,
+ hash: true,
+ template: path.resolve(__dirname, 'core/index.html'),
+ filename: 'index.html'
+ }
+ ]);
+
// create compiler from generated webpack config
config = config.toConfig();
const compiler = webpack(config);
@@ -65,7 +85,15 @@ module.exports = async function dev(sourceDir, cliOptions = {}) {
logLevel: 'error'
},
logLevel: 'error',
- port
+ port,
+ add: app => {
+ app.use(range) // enable range request https://tools.ietf.org/html/rfc7233
+ app.use(convert(history({
+ rewrites: [
+ { from: /\.html$/, to: '/' }
+ ]
+ })))
+ }
}
);
};
diff --git a/lib/loader/index.js b/lib/loader/index.js
index a808bf23dc..274c06f206 100644
--- a/lib/loader/index.js
+++ b/lib/loader/index.js
@@ -10,6 +10,15 @@ module.exports = async function load(sourceDir) {
// extract data from all blog files
const blogDatas = await loadBlog(sourceDir);
+ fs.writeFile(
+ path.resolve(__dirname, '../generated/blogDatas.js'),
+ `${'/**\n' +
+ ' * @' +
+ 'generated\n' +
+ ' */\n' +
+ 'module.exports = '}${JSON.stringify(blogDatas, null, 2)};\n`
+ );
+
// resolve outDir
const outDir = siteConfig.dest
? path.resolve(siteConfig.dest)
diff --git a/lib/webpack/base.js b/lib/webpack/base.js
index 995f7f22de..9133a9ff7d 100644
--- a/lib/webpack/base.js
+++ b/lib/webpack/base.js
@@ -1,6 +1,5 @@
const Config = require('webpack-chain');
const path = require('path');
-const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = function createBaseConfig(props) {
const {outDir, themePath, sourceDir, publicPath} = props;
@@ -43,14 +42,5 @@ module.exports = function createBaseConfig(props) {
presets: ['env', 'react']
});
- config.plugin('html-webpack-plugin').use(HtmlWebpackPlugin, [
- {
- inject: false,
- hash: true,
- template: path.resolve(__dirname, '../core/index.html'),
- filename: 'index.html'
- }
- ]);
-
return config;
};
diff --git a/package.json b/package.json
index e7cf981cd8..933d0467ed 100644
--- a/package.json
+++ b/package.json
@@ -46,10 +46,14 @@
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"commander": "^2.16.0",
+ "connect-history-api-fallback": "^1.5.0",
"front-matter": "^2.3.0",
"fs-extra": "^7.0.0",
"globby": "^8.0.1",
"html-webpack-plugin": "^3.2.0",
+ "koa-connect": "^2.0.1",
+ "koa-range": "^0.3.0",
+ "portfinder": "^1.0.13",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1",
diff --git a/yarn.lock b/yarn.lock
index 3e081ced09..045cd34d26 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -499,7 +499,7 @@ async-limiter@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
-async@^1.4.0:
+async@^1.4.0, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@@ -1598,6 +1598,10 @@ configstore@^3.0.0:
write-file-atomic "^2.0.0"
xdg-basedir "^3.0.0"
+connect-history-api-fallback@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a"
+
console-browserify@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
@@ -3989,6 +3993,10 @@ koa-compose@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877"
+koa-connect@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/koa-connect/-/koa-connect-2.0.1.tgz#2acad159c33862de1d73aa4562a48de13f137c0f"
+
koa-convert@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0"
@@ -4000,6 +4008,12 @@ koa-is-json@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
+koa-range@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/koa-range/-/koa-range-0.3.0.tgz#3588e3496473a839a1bd264d2a42b1d85bd7feac"
+ dependencies:
+ stream-slice "^0.1.2"
+
koa-webpack@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/koa-webpack/-/koa-webpack-5.1.0.tgz#7b9f04ea85c43c4d7ad845d0de01f0ed495eb5c0"
@@ -4435,7 +4449,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
+mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
@@ -5057,6 +5071,14 @@ pn@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+portfinder@^1.0.13:
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
+ dependencies:
+ async "^1.5.2"
+ debug "^2.2.0"
+ mkdirp "0.5.x"
+
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@@ -5975,6 +5997,10 @@ stream-shift@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+stream-slice@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/stream-slice/-/stream-slice-0.1.2.tgz#2dc4f4e1b936fb13f3eb39a2def1932798d07a4b"
+
string-length@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"