Skip to content

Commit 9b3b445

Browse files
RomakitaQingWei-Li
authored andcommitted
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.
1 parent 0933445 commit 9b3b445

File tree

5 files changed

+189
-49
lines changed

5 files changed

+189
-49
lines changed

Diff for: docs/configuration.md

+31
Original file line numberDiff line numberDiff line change
@@ -435,3 +435,34 @@ window.$docsify = {
435435
]
436436
};
437437
```
438+
439+
440+
## notFoundPage
441+
442+
* type: `Boolean` | `String` | `Object`
443+
444+
Load the `_404.md` file:
445+
```js
446+
window.$docsify = {
447+
notFoundPage: true
448+
};
449+
```
450+
451+
Load the customised path of the 404 page:
452+
```js
453+
window.$docsify = {
454+
notFoundPage: 'my404.md'
455+
};
456+
```
457+
458+
Load the right 404 page according to the localisation:
459+
```js
460+
window.$docsify = {
461+
notFoundPage: {
462+
'/': '_404.md',
463+
'/de': 'de/_404.md',
464+
}
465+
};
466+
```
467+
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
468+

Diff for: docs/de-de/configuration.md

+29
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,32 @@ window.$docsify = {
419419
fallbackLanguages: ['fr', 'de']
420420
};
421421
```
422+
423+
## notFoundPage
424+
425+
* type: `Boolean` | `String` | `Object`
426+
427+
Load the `_404.md` file:
428+
```js
429+
window.$docsify = {
430+
notFoundPage: true
431+
};
432+
```
433+
434+
Load the customised path of the 404 page:
435+
```js
436+
window.$docsify = {
437+
notFoundPage: 'my404.md'
438+
};
439+
```
440+
441+
Load the right 404 page according to the localisation:
442+
```js
443+
window.$docsify = {
444+
notFoundPage: {
445+
'/': '_404.md',
446+
'/de': 'de/_404.md',
447+
}
448+
};
449+
```
450+
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.

Diff for: docs/zh-cn/configuration.md

+31
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,34 @@ window.$docsify = {
431431
fallbackLanguages: ['fr', 'de']
432432
};
433433
```
434+
435+
## notFoundPage
436+
437+
* type: `Boolean` | `String` | `Object`
438+
439+
Load the `_404.md` file:
440+
```js
441+
window.$docsify = {
442+
notFoundPage: true
443+
};
444+
```
445+
446+
Load the customised path of the 404 page:
447+
```js
448+
window.$docsify = {
449+
notFoundPage: 'my404.md'
450+
};
451+
```
452+
453+
Load the right 404 page according to the localisation:
454+
```js
455+
window.$docsify = {
456+
notFoundPage: {
457+
'/': '_404.md',
458+
'/de': 'de/_404.md',
459+
}
460+
};
461+
```
462+
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
463+
464+

Diff for: src/core/fetch/index.js

+97-47
Original file line numberDiff line numberDiff line change
@@ -19,44 +19,35 @@ function loadNested (path, qs, file, next, vm, first) {
1919

2020
export function fetchMixin (proto) {
2121
let last
22-
proto._fetch = function (cb = noop) {
23-
const { path, query } = this.route
24-
const qs = stringifyQuery(query, ['id'])
25-
const { loadNavbar, loadSidebar, requestHeaders, fallbackLanguages } = this.config
26-
// Abort last request
27-
last && last.abort && last.abort()
28-
29-
const file = this.router.getFile(path)
30-
last = get(file + qs, true, requestHeaders)
31-
32-
// Current page is html
33-
this.isHTML = /\.html$/g.test(file)
34-
35-
const getFallBackPage = (file) => {
36-
if (!fallbackLanguages) {
37-
return false
38-
}
3922

40-
const local = file.split('/')[1]
41-
42-
if (fallbackLanguages.indexOf(local) === -1) {
43-
return false
44-
}
45-
46-
file = file.replace(new RegExp(`^/${local}`), '')
23+
const abort = () => last && last.abort && last.abort()
24+
const request = (url, hasbar, requestHeaders) => {
25+
abort()
26+
last = get(url, true, requestHeaders)
27+
return last
28+
}
4729

48-
return get(file + qs, true, requestHeaders)
49-
.then(
50-
(text, opt) => {
51-
this._renderMain(text, opt, loadSideAndNav)
52-
},
53-
_ => {
54-
return this._renderMain(null, {}, loadSideAndNav)
55-
}
56-
)
30+
const get404Path = (path, config) => {
31+
const { notFoundPage, ext } = config
32+
const defaultPath = '_404' + (ext || '.md')
33+
34+
switch (typeof notFoundPage) {
35+
case 'boolean':
36+
return defaultPath
37+
case 'string':
38+
return notFoundPage
39+
case 'object':
40+
const key = Object
41+
.keys(notFoundPage)
42+
.sort((a, b) => b.length - a.length)
43+
.find((key) => path.match(new RegExp('^' + key)))
44+
45+
return key && notFoundPage[key] || defaultPath
5746
}
47+
}
5848

59-
const loadSideAndNav = () => {
49+
proto._loadSideAndNav = function (path, qs, loadSidebar, cb) {
50+
return () => {
6051
if (!loadSidebar) return cb()
6152

6253
const fn = result => {
@@ -67,28 +58,39 @@ export function fetchMixin (proto) {
6758
// Load sidebar
6859
loadNested(path, qs, loadSidebar, fn, this, true)
6960
}
61+
}
62+
63+
proto._fetch = function (cb = noop) {
64+
const { path, query } = this.route
65+
const qs = stringifyQuery(query, ['id'])
66+
const { loadNavbar, requestHeaders, loadSidebar } = this.config
67+
// Abort last request
68+
69+
const file = this.router.getFile(path)
70+
const req = request(file + qs, true, requestHeaders)
71+
72+
// Current page is html
73+
this.isHTML = /\.html$/g.test(file)
7074

7175
// Load main content
72-
last
76+
req
7377
.then(
74-
(text, opt) => {
75-
this._renderMain(text, opt, loadSideAndNav)
76-
},
78+
(text, opt) => this._renderMain(text, opt, this._loadSideAndNav(path, qs, loadSidebar, cb)),
7779
_ => {
78-
return getFallBackPage(file) || this._renderMain(null, {}, loadSideAndNav)
80+
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb)
7981
}
8082
)
8183

8284
// Load nav
8385
loadNavbar &&
84-
loadNested(
85-
path,
86-
qs,
87-
loadNavbar,
88-
text => this._renderNav(text),
89-
this,
90-
true
91-
)
86+
loadNested(
87+
path,
88+
qs,
89+
loadNavbar,
90+
text => this._renderNav(text),
91+
this,
92+
true
93+
)
9294
}
9395

9496
proto._fetchCover = function () {
@@ -141,6 +143,54 @@ export function fetchMixin (proto) {
141143
})
142144
}
143145
}
146+
147+
proto._fetchFallbackPage = function (path, qs, cb = noop) {
148+
const { requestHeaders, fallbackLanguages, loadSidebar } = this.config
149+
150+
if (!fallbackLanguages) {
151+
return false
152+
}
153+
154+
const local = path.split('/')[1]
155+
156+
if (fallbackLanguages.indexOf(local) === -1) {
157+
return false
158+
}
159+
const newPath = path.replace(new RegExp(`^/${local}`), '')
160+
const req = request(newPath + qs, true, requestHeaders)
161+
162+
req.then(
163+
(text, opt) => this._renderMain(text, opt, this._loadSideAndNav(path, qs, loadSidebar, cb)),
164+
() => this._fetch404(path, qs, cb)
165+
)
166+
167+
return true
168+
}
169+
/**
170+
* Load the 404 page
171+
* @param path
172+
* @param qs
173+
* @param cb
174+
* @returns {*}
175+
* @private
176+
*/
177+
proto._fetch404 = function (path, qs, cb = noop) {
178+
const { loadSidebar, requestHeaders, notFoundPage } = this.config
179+
180+
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb)
181+
182+
if (notFoundPage) {
183+
request(get404Path(path, this.config), true, requestHeaders)
184+
.then(
185+
(text, opt) => this._renderMain(text, opt, fnLoadSideAndNav),
186+
() => this._renderMain(null, {}, fnLoadSideAndNav)
187+
)
188+
return true
189+
}
190+
191+
this._renderMain(null, {}, fnLoadSideAndNav)
192+
return false
193+
}
144194
}
145195

146196
export function initFetch (vm) {

Diff for: src/core/render/index.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ function formatUpdated (html, updated, fn) {
3535

3636
function renderMain (html) {
3737
if (!html) {
38-
// TODO: Custom 404 page
39-
html = 'not found'
38+
html = '<h1>404 - Not found</h1>'
4039
}
4140

4241
this._renderTo('.markdown-section', html)

0 commit comments

Comments
 (0)