feat(config): Add 404 page options. (#406)
This feature add the notFoundPage options to customize the default 404 page with a markdown file. It also support the localisation.
This commit is contained in:
parent
0933445e89
commit
9b3b4454de
5 changed files with 187 additions and 47 deletions
|
|
@ -435,3 +435,34 @@ window.$docsify = {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## notFoundPage
|
||||||
|
|
||||||
|
* type: `Boolean` | `String` | `Object`
|
||||||
|
|
||||||
|
Load the `_404.md` file:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the customised path of the 404 page:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: 'my404.md'
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the right 404 page according to the localisation:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: {
|
||||||
|
'/': '_404.md',
|
||||||
|
'/de': 'de/_404.md',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -419,3 +419,32 @@ window.$docsify = {
|
||||||
fallbackLanguages: ['fr', 'de']
|
fallbackLanguages: ['fr', 'de']
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## notFoundPage
|
||||||
|
|
||||||
|
* type: `Boolean` | `String` | `Object`
|
||||||
|
|
||||||
|
Load the `_404.md` file:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the customised path of the 404 page:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: 'my404.md'
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the right 404 page according to the localisation:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: {
|
||||||
|
'/': '_404.md',
|
||||||
|
'/de': 'de/_404.md',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
|
||||||
|
|
|
||||||
|
|
@ -431,3 +431,34 @@ window.$docsify = {
|
||||||
fallbackLanguages: ['fr', 'de']
|
fallbackLanguages: ['fr', 'de']
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## notFoundPage
|
||||||
|
|
||||||
|
* type: `Boolean` | `String` | `Object`
|
||||||
|
|
||||||
|
Load the `_404.md` file:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the customised path of the 404 page:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: 'my404.md'
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Load the right 404 page according to the localisation:
|
||||||
|
```js
|
||||||
|
window.$docsify = {
|
||||||
|
notFoundPage: {
|
||||||
|
'/': '_404.md',
|
||||||
|
'/de': 'de/_404.md',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,44 +19,35 @@ function loadNested (path, qs, file, next, vm, first) {
|
||||||
|
|
||||||
export function fetchMixin (proto) {
|
export function fetchMixin (proto) {
|
||||||
let last
|
let last
|
||||||
proto._fetch = function (cb = noop) {
|
|
||||||
const { path, query } = this.route
|
|
||||||
const qs = stringifyQuery(query, ['id'])
|
|
||||||
const { loadNavbar, loadSidebar, requestHeaders, fallbackLanguages } = this.config
|
|
||||||
// Abort last request
|
|
||||||
last && last.abort && last.abort()
|
|
||||||
|
|
||||||
const file = this.router.getFile(path)
|
const abort = () => last && last.abort && last.abort()
|
||||||
last = get(file + qs, true, requestHeaders)
|
const request = (url, hasbar, requestHeaders) => {
|
||||||
|
abort()
|
||||||
|
last = get(url, true, requestHeaders)
|
||||||
|
return last
|
||||||
|
}
|
||||||
|
|
||||||
// Current page is html
|
const get404Path = (path, config) => {
|
||||||
this.isHTML = /\.html$/g.test(file)
|
const { notFoundPage, ext } = config
|
||||||
|
const defaultPath = '_404' + (ext || '.md')
|
||||||
|
|
||||||
const getFallBackPage = (file) => {
|
switch (typeof notFoundPage) {
|
||||||
if (!fallbackLanguages) {
|
case 'boolean':
|
||||||
return false
|
return defaultPath
|
||||||
}
|
case 'string':
|
||||||
|
return notFoundPage
|
||||||
|
case 'object':
|
||||||
|
const key = Object
|
||||||
|
.keys(notFoundPage)
|
||||||
|
.sort((a, b) => b.length - a.length)
|
||||||
|
.find((key) => path.match(new RegExp('^' + key)))
|
||||||
|
|
||||||
const local = file.split('/')[1]
|
return key && notFoundPage[key] || defaultPath
|
||||||
|
|
||||||
if (fallbackLanguages.indexOf(local) === -1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
file = file.replace(new RegExp(`^/${local}`), '')
|
|
||||||
|
|
||||||
return get(file + qs, true, requestHeaders)
|
|
||||||
.then(
|
|
||||||
(text, opt) => {
|
|
||||||
this._renderMain(text, opt, loadSideAndNav)
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
return this._renderMain(null, {}, loadSideAndNav)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const loadSideAndNav = () => {
|
proto._loadSideAndNav = function (path, qs, loadSidebar, cb) {
|
||||||
|
return () => {
|
||||||
if (!loadSidebar) return cb()
|
if (!loadSidebar) return cb()
|
||||||
|
|
||||||
const fn = result => {
|
const fn = result => {
|
||||||
|
|
@ -67,28 +58,39 @@ export function fetchMixin (proto) {
|
||||||
// Load sidebar
|
// Load sidebar
|
||||||
loadNested(path, qs, loadSidebar, fn, this, true)
|
loadNested(path, qs, loadSidebar, fn, this, true)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proto._fetch = function (cb = noop) {
|
||||||
|
const { path, query } = this.route
|
||||||
|
const qs = stringifyQuery(query, ['id'])
|
||||||
|
const { loadNavbar, requestHeaders, loadSidebar } = this.config
|
||||||
|
// Abort last request
|
||||||
|
|
||||||
|
const file = this.router.getFile(path)
|
||||||
|
const req = request(file + qs, true, requestHeaders)
|
||||||
|
|
||||||
|
// Current page is html
|
||||||
|
this.isHTML = /\.html$/g.test(file)
|
||||||
|
|
||||||
// Load main content
|
// Load main content
|
||||||
last
|
req
|
||||||
.then(
|
.then(
|
||||||
(text, opt) => {
|
(text, opt) => this._renderMain(text, opt, this._loadSideAndNav(path, qs, loadSidebar, cb)),
|
||||||
this._renderMain(text, opt, loadSideAndNav)
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
return getFallBackPage(file) || this._renderMain(null, {}, loadSideAndNav)
|
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Load nav
|
// Load nav
|
||||||
loadNavbar &&
|
loadNavbar &&
|
||||||
loadNested(
|
loadNested(
|
||||||
path,
|
path,
|
||||||
qs,
|
qs,
|
||||||
loadNavbar,
|
loadNavbar,
|
||||||
text => this._renderNav(text),
|
text => this._renderNav(text),
|
||||||
this,
|
this,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
proto._fetchCover = function () {
|
proto._fetchCover = function () {
|
||||||
|
|
@ -141,6 +143,54 @@ export function fetchMixin (proto) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proto._fetchFallbackPage = function (path, qs, cb = noop) {
|
||||||
|
const { requestHeaders, fallbackLanguages, loadSidebar } = this.config
|
||||||
|
|
||||||
|
if (!fallbackLanguages) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const local = path.split('/')[1]
|
||||||
|
|
||||||
|
if (fallbackLanguages.indexOf(local) === -1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const newPath = path.replace(new RegExp(`^/${local}`), '')
|
||||||
|
const req = request(newPath + qs, true, requestHeaders)
|
||||||
|
|
||||||
|
req.then(
|
||||||
|
(text, opt) => this._renderMain(text, opt, this._loadSideAndNav(path, qs, loadSidebar, cb)),
|
||||||
|
() => this._fetch404(path, qs, cb)
|
||||||
|
)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Load the 404 page
|
||||||
|
* @param path
|
||||||
|
* @param qs
|
||||||
|
* @param cb
|
||||||
|
* @returns {*}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
proto._fetch404 = function (path, qs, cb = noop) {
|
||||||
|
const { loadSidebar, requestHeaders, notFoundPage } = this.config
|
||||||
|
|
||||||
|
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb)
|
||||||
|
|
||||||
|
if (notFoundPage) {
|
||||||
|
request(get404Path(path, this.config), true, requestHeaders)
|
||||||
|
.then(
|
||||||
|
(text, opt) => this._renderMain(text, opt, fnLoadSideAndNav),
|
||||||
|
() => this._renderMain(null, {}, fnLoadSideAndNav)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
this._renderMain(null, {}, fnLoadSideAndNav)
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initFetch (vm) {
|
export function initFetch (vm) {
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,7 @@ function formatUpdated (html, updated, fn) {
|
||||||
|
|
||||||
function renderMain (html) {
|
function renderMain (html) {
|
||||||
if (!html) {
|
if (!html) {
|
||||||
// TODO: Custom 404 page
|
html = '<h1>404 - Not found</h1>'
|
||||||
html = 'not found'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._renderTo('.markdown-section', html)
|
this._renderTo('.markdown-section', html)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue