Skip to content

Commit fe88c15

Browse files
committed
refactor(core): and markdown compiler
1 parent 30da0d5 commit fe88c15

12 files changed

Lines changed: 189 additions & 227 deletions

File tree

.eslintrc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,5 @@
22
"extends": ["vue"],
33
"env": {
44
"browser": true
5-
},
6-
"globals": {
7-
"$docsify": true
85
}
96
}

src/core/fetch/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { get } from './ajax'
22
import { callHook } from '../init/lifecycle'
3-
import { getCurrentRoot } from '../route/util'
3+
import { getRoot } from '../route/util'
4+
import { noop } from '../util/core'
45

56
export function fetchMixin (Docsify) {
67
let last
78

8-
Docsify.prototype._fetch = function (cb) {
9+
Docsify.prototype._fetch = function (cb = noop) {
910
const { path } = this.route
1011
const { loadNavbar, loadSidebar } = this.config
11-
const currentRoot = getCurrentRoot(path)
12+
const root = getRoot(path)
1213

1314
// Abort last request
1415
last && last.abort && last.abort()
@@ -21,14 +22,14 @@ export function fetchMixin (Docsify) {
2122
const fn = result => { this._renderSidebar(result); cb() }
2223

2324
// Load sidebar
24-
get(this.$getFile(currentRoot + loadSidebar))
25+
get(this.$getFile(root + loadSidebar))
2526
.then(fn, _ => get(loadSidebar).then(fn))
2627
},
2728
_ => this._renderMain(null))
2829

2930
// Load nav
3031
loadNavbar &&
31-
get(this.$getFile(currentRoot + loadNavbar))
32+
get(this.$getFile(root + loadNavbar))
3233
.then(
3334
this._renderNav,
3435
_ => get(loadNavbar).then(this._renderNav)

src/core/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ initGlobalAPI()
2323
/**
2424
* Run Docsify
2525
*/
26-
setTimeout(() => new Docsify(), 0)
26+
new Docsify()

src/core/render/compiler.js

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,56 @@
11
import marked from 'marked'
22
import Prism from 'prismjs'
3+
import { helper as helperTpl } from './tpl'
4+
import { slugify, clearSlugCache } from './slugify'
5+
import { emojify } from './emojify'
6+
import { toURL } from '../route/hash'
7+
import { isFn, merge, cached } from '../util/core'
38

4-
export const renderer = new marked.Renderer()
9+
let markdownCompiler = marked
10+
let contentBase = ''
11+
let renderer = new marked.Renderer()
512

6-
export function markdown () {
13+
const toc = []
714

8-
}
15+
/**
16+
* Compile markdown content
17+
*/
18+
export const markdown = cached(text => {
19+
let html = ''
920

10-
const toc = []
21+
if (!text) return text
22+
23+
html = markdownCompiler(text)
24+
html = emojify(html)
25+
clearSlugCache()
26+
27+
return html
28+
})
29+
30+
markdown.renderer = renderer
31+
32+
markdown.init = function (config = {}, context = window.location.pathname) {
33+
contentBase = context
34+
35+
if (isFn(config)) {
36+
markdownCompiler = config(marked, renderer)
37+
} else {
38+
renderer = merge(renderer, config.renderer)
39+
marked.setOptions(merge(config, { renderer }))
40+
}
41+
}
1142

1243
/**
1344
* render anchor tag
1445
* @link https://github.com/chjj/marked#overriding-renderer-methods
1546
*/
1647
renderer.heading = function (text, level) {
1748
const slug = slugify(text)
18-
let route = ''
49+
const url = toURL(contentBase, { id: slug })
1950

20-
route = `#/${getRoute()}`
21-
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
51+
toc.push({ level, slug: url, title: text })
2252

23-
return `<h${level} id="${slug}"><a href="${route}#${slug}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
53+
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
2454
}
2555
// highlight code
2656
renderer.code = function (code, lang = '') {
@@ -30,21 +60,31 @@ renderer.code = function (code, lang = '') {
3060
}
3161
renderer.link = function (href, title, text) {
3262
if (!/:|(\/{2})/.test(href)) {
63+
// TODO
3364
href = `#/${href}`.replace(/\/+/g, '/')
3465
}
3566
return `<a href="${href}" title="${title || ''}">${text}</a>`
3667
}
3768
renderer.paragraph = function (text) {
3869
if (/^!&gt;/.test(text)) {
39-
return tpl.helper('tip', text)
70+
return helperTpl('tip', text)
4071
} else if (/^\?&gt;/.test(text)) {
41-
return tpl.helper('warn', text)
72+
return helperTpl('warn', text)
4273
}
4374
return `<p>${text}</p>`
4475
}
4576
renderer.image = function (href, title, text) {
46-
const url = /:|(\/{2})/.test(href) ? href : ($docsify.basePath + href).replace(/\/+/g, '/')
47-
const titleHTML = title ? ` title="${title}"` : ''
77+
// TODO
78+
// get base path
79+
// const url = /:|(\/{2})/.test(href) ? href : ($docsify.basePath + href).replace(/\/+/g, '/')
80+
// const titleHTML = title ? ` title="${title}"` : ''
81+
82+
// return `<img src="${url}" alt="${text}"${titleHTML} />`
83+
}
84+
85+
/**
86+
* Compile sidebar
87+
*/
88+
export function sidebar (text) {
4889

49-
return `<img src="${url}" alt="${text}"${titleHTML} />`
5090
}

src/core/render/emojify.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export function emojify (text) {
2+
return text
3+
.replace(/<(pre|template)[^>]*?>([\s\S]+)<\/(pre|template)>/g, m => m.replace(/:/g, '__colon__'))
4+
.replace(/:(\w+?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
5+
.replace(/__colon__/g, ':')
6+
}

src/core/render/gen-tree.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* gen toc tree
3+
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
4+
* @param {Array} toc
5+
* @param {Number} maxLevel
6+
* @return {Array}
7+
*/
8+
export function genTree (toc, maxLevel) {
9+
const headlines = []
10+
const last = {}
11+
12+
toc.forEach(headline => {
13+
const level = headline.level || 1
14+
const len = level - 1
15+
16+
if (level > maxLevel) return
17+
if (last[len]) {
18+
last[len].children = last[len].children || []
19+
last[len].children.push(headline)
20+
} else {
21+
headlines.push(headline)
22+
}
23+
last[level] = headline
24+
})
25+
26+
return headlines
27+
}

src/core/render/index.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,47 @@
11
import * as dom from '../util/dom'
22
import cssVars from '../util/polyfill/css-vars'
33
import * as tpl from './tpl'
4+
import { markdown, sidebar } from './compiler'
5+
import { callHook } from '../init/lifecycle'
46

5-
function renderMain () {
6-
7-
}
8-
9-
function renderNav () {
10-
}
11-
12-
function renderSidebar () {
7+
function renderMain (html) {
8+
if (!html) {
9+
// TODO: Custom 404 page
10+
}
11+
this._renderTo('.markdown-section', html)
1312
}
1413

1514
export function renderMixin (Docsify) {
16-
Docsify.prototype._renderTo = function (el, content, replace) {
15+
const proto = Docsify.prototype
16+
17+
proto._renderTo = function (el, content, replace) {
1718
const node = dom.getNode(el)
1819
if (node) node[replace ? 'outerHTML' : 'innerHTML'] = content
1920
}
2021

21-
Docsify.prototype._renderSidebar = renderSidebar
22-
Docsify.prototype._renderNav = renderNav
23-
Docsify.prototype._renderMain = renderMain
22+
proto._renderSidebar = function (text) {
23+
this._renderTo('.sidebar-nav', sidebar(text))
24+
// bind event
25+
}
26+
27+
proto._renderNav = function (text) {
28+
this._renderTo('nav', markdown(text))
29+
}
30+
31+
proto._renderMain = function (text) {
32+
callHook(this, 'beforeEach', text, result => {
33+
const html = markdown(result)
34+
callHook(this, 'afterEach', html, text => renderMain.call(this, text))
35+
})
36+
}
2437
}
2538

2639
export function initRender (vm) {
2740
const config = vm.config
41+
42+
// Init markdown compiler
43+
markdown.init(vm.config.markdown)
44+
2845
const id = config.el || '#app'
2946
const navEl = dom.find('nav') || dom.create('nav')
3047

src/core/render/slugify.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
let cache = {}
2+
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g
3+
4+
export function slugify (str) {
5+
if (typeof str !== 'string') return ''
6+
7+
let slug = str.toLowerCase().trim()
8+
.replace(/<[^>\d]+>/g, '')
9+
.replace(re, '')
10+
.replace(/\s/g, '-')
11+
.replace(/-+/g, '-')
12+
.replace(/^(\d)/, '_$1')
13+
let count = cache[slug]
14+
15+
count = cache.hasOwnProperty(slug) ? (count + 1) : 0
16+
cache[slug] = count
17+
18+
if (count) {
19+
slug = slug + '-' + count
20+
}
21+
22+
return slug
23+
}
24+
25+
export function clearSlugCache () {
26+
cache = {}
27+
}

src/core/route/hash.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { parseQuery } from './util'
1+
import { merge } from '../util/core'
2+
import { parseQuery, stringifyQuery, cleanPath } from './util'
23

34
function replaceHash (path) {
45
const i = window.location.href.indexOf('#')
@@ -34,11 +35,11 @@ export function getHash () {
3435
}
3536

3637
/**
37-
* Parse the current url
38+
* Parse the url
39+
* @param {string} [path=window.location.herf]
3840
* @return {object} { path, query }
3941
*/
40-
export function parse () {
41-
let path = window.location.href
42+
export function parse (path = window.location.href) {
4243
let query = ''
4344

4445
const queryIndex = path.indexOf('?')
@@ -57,9 +58,14 @@ export function parse () {
5758

5859
/**
5960
* to URL
60-
* @param {String} path
61-
* @param {String} qs query string
61+
* @param {string} path
62+
* @param {object} qs query params
6263
*/
63-
export function toURL (path, qs) {
64+
export function toURL (path, params) {
65+
const route = parse(path)
6466

67+
route.query = merge({}, route.query, params)
68+
path = route.path + stringifyQuery(route.query)
69+
70+
return '#' + path
6571
}

src/core/route/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ export function routeMixin (Docsify) {
3030
}
3131
}
3232

33+
let lastRoute = {}
34+
3335
export function initRoute (vm) {
3436
normalize()
35-
vm.route = parse()
37+
lastRoute = vm.route = parse()
3638

3739
on('hashchange', _ => {
3840
normalize()
39-
vm.route = parse()
41+
lastRoute = vm.route = parse()
42+
if (lastRoute.path === vm.route.path) {
43+
// TODO: goto xxx
44+
return
45+
}
4046
vm._fetch()
4147
})
4248
}

0 commit comments

Comments
 (0)