Skip to content

Commit 3444884

Browse files
committed
feat: finish ssr
1 parent 6dea685 commit 3444884

File tree

12 files changed

+163
-40
lines changed

12 files changed

+163
-40
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.git/
2+
packages/docsify-server-renderer/build.js

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
"themes"
2121
],
2222
"scripts": {
23-
"build": "rm -rf lib themes && node build/build.js && mkdir lib/themes && mkdir themes && node build/build-css.js",
24-
"dev:build": "rm -rf lib themes && mkdir themes && node build/build.js --dev && node build/build-css.js --dev",
25-
"dev": "node app.js & nodemon -w src -e js,css --exec 'npm run dev:build'",
23+
"build": "rm -rf lib themes && node build/build && mkdir lib/themes && mkdir themes && node build/build-css",
24+
"dev:build": "rm -rf lib themes && mkdir themes && node build/build --dev && node build/build-css --dev",
25+
"dev": "node app & nodemon -w src -e js,css --exec 'npm run dev:build'",
2626
"build:ssr": "node build/build-ssr",
27-
"test": "eslint src --fix"
27+
"test": "eslint {src,packages} --fix"
2828
},
2929
"dependencies": {
3030
"marked": "^0.3.6",

packages/docsify-server-renderer/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ renderer.renderToString({ url })
4141
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css" title="buble" disabled>
4242
</head>
4343
<body>
44-
<div id="app"></div>
45-
<!--inject-docsify-config-->
44+
<!--inject-app-->
45+
<!--inject-config-->
4646
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
4747
</body>
4848
</html>
+92-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
import { Compiler } from '../../src/core/render/compiler'
22
import { AbstractHistory } from '../../src/core/router/history/abstract'
3-
import path from 'path'
4-
import fs from 'fs'
3+
import { resolve, basename } from 'path'
4+
import { readFileSync } from 'fs'
5+
import * as tpl from '../../src/core/render/tpl'
6+
7+
function cwd (...args) {
8+
return resolve(process.cwd(), ...args)
9+
}
10+
11+
function mainTpl (config) {
12+
let html = `<nav class="app-nav${config.repo ? '' : 'no-badge'}"><!--navbar--></nav>`
13+
14+
if (config.repo) {
15+
html += tpl.corner(config.repo)
16+
}
17+
if (config.coverpage) {
18+
html += tpl.cover()
19+
}
20+
21+
html += tpl.main(config)
22+
23+
return html
24+
}
525

626
export default class Renderer {
727
constructor ({
@@ -10,16 +30,80 @@ export default class Renderer {
1030
config,
1131
cache
1232
}) {
13-
this.template = template
14-
this.path = path
15-
this.config = config
33+
this.html = this.template = template
34+
this.path = cwd(path)
35+
this.config = Object.assign(config, {
36+
routerMode: 'history'
37+
})
1638
this.cache = cache
1739

18-
this.router = new AbstractHistory()
40+
this.router = new AbstractHistory(config)
1941
this.compiler = new Compiler(config, this.router)
42+
43+
this.router.getCurrentPath = () => this.url
44+
this._renderHtml('inject-config', `<script>window.$docsify = ${JSON.stringify(config)}</script>`)
45+
this._renderHtml('inject-app', mainTpl(config))
46+
}
47+
48+
renderToString (url) {
49+
this.url = url
50+
// TODO render cover page
51+
const { loadSidebar, loadNavbar } = this.config
52+
53+
const mainFile = cwd(this.path, `./${this.router.getFile(url)}`)
54+
this._renderHtml('main', this._render(mainFile))
55+
56+
if (loadSidebar) {
57+
const name = loadSidebar === true ? '_sidebar.md' : loadSidebar
58+
const sidebarFile = cwd(mainFile, '..', name)
59+
this._renderHtml('sidebar', this._render(sidebarFile, 'sidebar'))
60+
}
61+
62+
if (loadNavbar) {
63+
const name = loadNavbar === true ? '_navbar.md' : loadNavbar
64+
const navbarFile = cwd(mainFile, '..', name)
65+
this._renderHtml('navbar', this._render(navbarFile, 'navbar'))
66+
}
67+
68+
return this.html
69+
}
70+
71+
_renderHtml (match, content) {
72+
this.html = this.html.replace(new RegExp(`<!--${match}-->`, 'g'), content)
2073
}
2174

22-
renderToString(url) {
23-
console.log(url)
75+
_render (path, type) {
76+
let html = this._loadFile(path)
77+
78+
switch (type) {
79+
case 'sidebar':
80+
html = this.compiler.sidebar(html)
81+
break
82+
case 'cover':
83+
html = this.compiler.cover(html)
84+
break
85+
case 'navbar':
86+
case 'article':
87+
default:
88+
html = this.compiler.compile(html)
89+
break
90+
}
91+
92+
return html
93+
}
94+
95+
_loadFile (filePath) {
96+
try {
97+
return readFileSync(filePath, 'utf8')
98+
} catch (e) {
99+
const fileName = basename(filePath)
100+
const parentPath = cwd(filePath, '../..')
101+
102+
if (this.path.length < parentPath.length) {
103+
throw Error(`Not found file ${fileName}`)
104+
}
105+
106+
this._loadFile(cwd(filePath, '../..', fileName))
107+
}
24108
}
25109
}

src/core/fetch/index.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,12 @@ export function fetchMixin (proto) {
7070
}
7171

7272
export function initFetch (vm) {
73-
vm.$fetch(_ => callHook(vm, 'ready'))
73+
if (vm.rendered) {
74+
vm._fetchCover()
75+
vm.$resetEvents()
76+
callHook(vm, 'doneEach')
77+
callHook(vm, 'ready')
78+
} else {
79+
vm.$fetch(_ => callHook(vm, 'ready'))
80+
}
7481
}

src/core/render/compiler.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class Compiler {
3535
if (!text) return text
3636

3737
html = compile(text)
38-
html = emojify(html)
38+
html = config.noEmoji ? html : emojify(html)
3939
slugify.clear()
4040

4141
return html

src/core/render/emojify.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { inBrowser } from '../util/env'
2+
13
function replace (m, $1) {
24
return '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
35
}
46

57
export function emojify (text) {
6-
return $docsify.noEmoji ? text : text
8+
return text
79
.replace(/<(pre|template|code)[^>]*?>[\s\S]+?<\/(pre|template|code)>/g, m => m.replace(/:/g, '__colon__'))
8-
.replace(/:(\w+?):/ig, window.emojify || replace)
10+
.replace(/:(\w+?):/ig, (inBrowser && window.emojify) || replace)
911
.replace(/__colon__/g, ':')
1012
}

src/core/render/index.js

+13-13
Original file line numberDiff line numberDiff line change
@@ -172,20 +172,20 @@ export function initRender (vm) {
172172
let html = ''
173173
let navAppendToTarget = dom.body
174174

175-
if (!el) {
176-
el = dom.create(id)
177-
dom.appendTo(dom.body, el)
178-
}
179-
if (config.repo) {
180-
html += tpl.corner(config.repo)
181-
}
182-
if (config.coverpage) {
183-
html += tpl.cover()
184-
}
175+
if (el) {
176+
if (config.repo) {
177+
html += tpl.corner(config.repo)
178+
}
179+
if (config.coverpage) {
180+
html += tpl.cover()
181+
}
185182

186-
html += tpl.main(config)
187-
// Render main app
188-
vm._renderTo(el, html, true)
183+
html += tpl.main(config)
184+
// Render main app
185+
vm._renderTo(el, html, true)
186+
} else {
187+
vm.rendered = true
188+
}
189189

190190
if (config.mergeNavbar && isMobile) {
191191
navAppendToTarget = dom.find('.sidebar')

src/core/render/tpl.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ export function main (config) {
3333
(config.name
3434
? `<h1><a class="app-name-link" data-nosearch>${config.name}</a></h1>`
3535
: '') +
36-
'<div class="sidebar-nav"></div>' +
36+
'<div class="sidebar-nav"><!--sidebar--></div>' +
3737
'</aside>')
3838

3939
return (isMobile ? `${aside}<main>` : `<main>${aside}`) +
4040
'<section class="content">' +
41-
'<article class="markdown-section" id="main"></article>' +
41+
'<article class="markdown-section" id="main"><!--main--></article>' +
4242
'</section>' +
4343
'</main>'
4444
}

src/core/router/history/abstract.js

+27
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
11
import { History } from './base'
2+
import { parseQuery, stringifyQuery, cleanPath } from '../util'
3+
import { merge } from '../../util/core'
24

35
export class AbstractHistory extends History {
46
constructor (config) {
57
super(config)
68
this.mode = 'abstract'
79
}
10+
11+
parse (path) {
12+
let query = ''
13+
14+
const queryIndex = path.indexOf('?')
15+
if (queryIndex >= 0) {
16+
query = path.slice(queryIndex + 1)
17+
path = path.slice(0, queryIndex)
18+
}
19+
20+
return { path, query: parseQuery(query) }
21+
}
22+
23+
toURL (path, params, currentRoute) {
24+
const local = currentRoute && path[0] === '#'
25+
const route = this.parse(path)
26+
27+
route.query = merge({}, route.query, params)
28+
path = route.path + stringifyQuery(route.query)
29+
path = path.replace(/\.md(\?)|\.md$/, '$1')
30+
31+
if (local) path = currentRoute + path
32+
33+
return cleanPath('/' + path)
34+
}
835
}

src/core/router/util.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { cached } from '../util/core'
2+
import { inBrowser } from '../util/env'
23

34
const decode = decodeURIComponent
45
const encode = encodeURIComponent
@@ -31,10 +32,13 @@ export function stringifyQuery (obj) {
3132
return qs.length ? `?${qs.join('&')}` : ''
3233
}
3334

34-
export const getBasePath = cached(base => {
35+
export const getBasePath = cached((base = '') => {
36+
// TODO
37+
const path = inBrowser ? window.location.pathname : ''
38+
3539
return /^(\/|https?:)/g.test(base)
3640
? base
37-
: cleanPath(window.location.pathname + '/' + base)
41+
: cleanPath(path + '/' + base)
3842
})
3943

4044
export function getPath (...args) {

src/core/util/env.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
export const UA = window.navigator.userAgent.toLowerCase()
1+
export const inBrowser = typeof window !== 'undefined'
22

3-
export const isIE = UA && /msie|trident/.test(UA)
4-
5-
export const isMobile = document.body.clientWidth <= 600
3+
export const isMobile = inBrowser && document.body.clientWidth <= 600
64

75
/**
86
* @see https://github.com/MoOx/pjax/blob/master/lib/is-supported.js
97
*/
10-
export const supportsPushState = (function () {
8+
export const supportsPushState = inBrowser && (function () {
119
// Borrowed wholesale from https://github.com/defunkt/jquery-pjax
1210
return window.history &&
1311
window.history.pushState &&

0 commit comments

Comments
 (0)