From 2c7041c8fba9b23b40a3bc304a87a03f7f0129ee Mon Sep 17 00:00:00 2001 From: "qingwei.li" Date: Mon, 29 May 2017 19:21:08 +0800 Subject: [PATCH] refactor(router): dupports multiple mode --- package.json | 2 +- src/core/event/scroll.js | 2 +- src/core/event/sidebar.js | 2 +- src/core/fetch/index.js | 8 +- src/core/global-api.js | 2 +- src/core/index.js | 4 +- src/core/init/index.js | 4 +- src/core/render/compiler.js | 269 ++++++++++++++-------------- src/core/render/index.js | 27 +-- src/core/route/index.js | 52 ------ src/core/{route => router}/hash.js | 0 src/core/router/history/abstract.js | 8 + src/core/router/history/base.js | 44 +++++ src/core/router/history/hash.js | 78 ++++++++ src/core/router/history/html5.js | 8 + src/core/router/index.js | 44 +++++ src/core/{route => router}/util.js | 0 src/core/util/env.js | 17 ++ src/plugins/ga.js | 24 +-- src/plugins/search/search.js | 2 +- 20 files changed, 377 insertions(+), 220 deletions(-) delete mode 100644 src/core/route/index.js rename src/core/{route => router}/hash.js (100%) create mode 100644 src/core/router/history/abstract.js create mode 100644 src/core/router/history/base.js create mode 100644 src/core/router/history/hash.js create mode 100644 src/core/router/history/html5.js create mode 100644 src/core/router/index.js rename src/core/{route => router}/util.js (100%) diff --git a/package.json b/package.json index 96b42994..5d836f0e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "build": "rm -rf lib themes && node build/build.js && mkdir lib/themes && mkdir themes && node build/build-css.js", "dev:build": "rm -rf lib themes && mkdir themes && node build/build.js --dev && node build/build-css.js --dev", "dev": "node app.js & nodemon -w src -e js,css --exec 'npm run dev:build'", - "test": "eslint src" + "test": "eslint src --fix" }, "dependencies": { "marked": "^0.3.6", diff --git a/src/core/event/scroll.js b/src/core/event/scroll.js index 98197efa..9019d338 100644 --- a/src/core/event/scroll.js +++ b/src/core/event/scroll.js @@ -1,6 +1,6 @@ import { isMobile } from '../util/env' import * as dom from '../util/dom' -import { parse } from '../route/hash' +import { parse } from '../router/hash' const nav = {} let hoverOver = false diff --git a/src/core/event/sidebar.js b/src/core/event/sidebar.js index 16401ea9..32ae19c7 100644 --- a/src/core/event/sidebar.js +++ b/src/core/event/sidebar.js @@ -1,6 +1,6 @@ import { isMobile } from '../util/env' import * as dom from '../util/dom' -import { getHash } from '../route/hash' +import { getHash } from '../router/hash' const title = dom.$.title /** diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index 2fc23b9f..79839719 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -1,6 +1,6 @@ import { get } from './ajax' import { callHook } from '../init/lifecycle' -import { getParentPath } from '../route/util' +import { getParentPath } from '../router/util' import { noop } from '../util/core' function loadNested (path, file, next, vm, first) { @@ -9,7 +9,7 @@ function loadNested (path, file, next, vm, first) { if (!path) return - get(vm.$getFile(path + file)) + get(vm.router.getFile(path + file)) .then(next, _ => loadNested(path, file, next, vm)) } @@ -22,7 +22,7 @@ export function fetchMixin (proto) { // Abort last request last && last.abort && last.abort() - last = get(this.$getFile(path), true) + last = get(this.router.getFile(path), true) // Current page is html this.isHTML = /\.html$/g.test(path) @@ -47,7 +47,7 @@ export function fetchMixin (proto) { proto._fetchCover = function () { const { coverpage } = this.config const root = getParentPath(this.route.path) - const path = this.$getFile(root + coverpage) + const path = this.router.getFile(root + coverpage) if (this.route.path !== '/' || !coverpage) { this._renderCover() diff --git a/src/core/global-api.js b/src/core/global-api.js index b5565d9c..e73bbe42 100644 --- a/src/core/global-api.js +++ b/src/core/global-api.js @@ -1,7 +1,7 @@ import * as util from './util' import * as dom from './util/dom' import * as render from './render/compiler' -import * as route from './route/hash' +import * as route from './router/hash' import { slugify } from './render/slugify' import { get } from './fetch/ajax' import marked from 'marked' diff --git a/src/core/index.js b/src/core/index.js index d72e96ad..ce5c746d 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -1,5 +1,5 @@ import { initMixin } from './init' -import { routeMixin } from './route' +import { routerMixin } from './router' import { renderMixin } from './render' import { fetchMixin } from './fetch' import { eventMixin } from './event' @@ -12,7 +12,7 @@ function Docsify () { const proto = Docsify.prototype initMixin(proto) -routeMixin(proto) +routerMixin(proto) renderMixin(proto) fetchMixin(proto) eventMixin(proto) diff --git a/src/core/init/index.js b/src/core/init/index.js index 7f0416c1..fdc57d5c 100644 --- a/src/core/init/index.js +++ b/src/core/init/index.js @@ -1,7 +1,7 @@ import config from '../config' import { initLifecycle, callHook } from './lifecycle' import { initRender } from '../render' -import { initRoute } from '../route' +import { initRouter } from '../router' import { initEvent } from '../event' import { initFetch } from '../fetch' import { isFn } from '../util/core' @@ -14,9 +14,9 @@ export function initMixin (proto) { initLifecycle(vm) // Init hooks initPlugin(vm) // Install plugins callHook(vm, 'init') + initRouter(vm) // Add router initRender(vm) // Render base DOM initEvent(vm) // Bind events - initRoute(vm) // Add hashchange eventListener initFetch(vm) // Fetch data callHook(vm, 'mounted') } diff --git a/src/core/render/compiler.js b/src/core/render/compiler.js index 26ae4a4a..9ae3c9c4 100644 --- a/src/core/render/compiler.js +++ b/src/core/render/compiler.js @@ -4,160 +4,165 @@ import { helper as helperTpl, tree as treeTpl } from './tpl' import { genTree } from './gen-tree' import { slugify } from './slugify' import { emojify } from './emojify' -import { toURL, parse } from '../route/hash' -import { getBasePath, isAbsolutePath, getPath } from '../route/util' +import { getBasePath, isAbsolutePath, getPath } from '../router/util' import { isFn, merge, cached } from '../util/core' -let markdownCompiler = marked -let contentBase = '' -let currentPath = '' -let linkTarget = '_blank' -let renderer = new marked.Renderer() -const cacheTree = {} -let toc = [] +export class Compiler { + constructor (config, router) { + this.config = config + this.router = router + this.cacheTree = {} + this.toc = [] + this.linkTarget = config.externalLinkTarget || '_blank' + this.contentBase = getBasePath(config.base) -/** - * Compile markdown content - */ -export const markdown = cached(text => { - let html = '' + const renderer = this._initRenderer() + let runner + const mdConf = config.markdown || {} - if (!text) return text + if (isFn(mdConf)) { + runner = mdConf(marked, renderer) + } else { + marked.setOptions(merge(mdConf, { + renderer: merge(renderer, mdConf.renderer) + })) + runner = marked + } - html = markdownCompiler(text) - html = emojify(html) - slugify.clear() + this.runner = cached(text => { + let html = '' - return html -}) + if (!text) return text -markdown.renderer = renderer + html = runner(text) + html = emojify(html) + slugify.clear() -markdown.init = function (config = {}, { - base = window.location.pathname, - externalLinkTarget -}) { - contentBase = getBasePath(base) - linkTarget = externalLinkTarget || linkTarget - - if (isFn(config)) { - markdownCompiler = config(marked, renderer) - } else { - renderer = merge(renderer, config.renderer) - marked.setOptions(merge(config, { renderer })) - } -} - -markdown.update = function () { - currentPath = parse().path -} - -/** - * render anchor tag - * @link https://github.com/chjj/marked#overriding-renderer-methods - */ -renderer.heading = function (text, level) { - const nextToc = { level, title: text } - - if (/{docsify-ignore}/g.test(text)) { - text = text.replace('{docsify-ignore}', '') - nextToc.title = text - nextToc.ignoreSubHeading = true + return html + }) } - if (/{docsify-ignore-all}/g.test(text)) { - text = text.replace('{docsify-ignore-all}', '') - nextToc.title = text - nextToc.ignoreAllSubs = true + _initRenderer () { + const renderer = new marked.Renderer() + const { linkTarget, router, toc } = this + /** + * render anchor tag + * @link https://github.com/chjj/marked#overriding-renderer-methods + */ + renderer.heading = function (text, level) { + const nextToc = { level, title: text } + + if (/{docsify-ignore}/g.test(text)) { + text = text.replace('{docsify-ignore}', '') + nextToc.title = text + nextToc.ignoreSubHeading = true + } + + if (/{docsify-ignore-all}/g.test(text)) { + text = text.replace('{docsify-ignore-all}', '') + nextToc.title = text + nextToc.ignoreAllSubs = true + } + + const slug = slugify(text) + const url = router.toURL(router.getCurrentPath(), { id: slug }) + nextToc.slug = url + toc.push(nextToc) + + return `${text}` + } + // highlight code + renderer.code = function (code, lang = '') { + const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup) + + return `
${hl}
` + } + renderer.link = function (href, title, text) { + let blank = '' + if (!/:|(\/{2})/.test(href)) { + href = router.toURL(href, null, router.getCurrentPath()) + } else { + blank = ` target="${linkTarget}"` + } + if (title) { + title = ` title="${title}"` + } + return `${text}` + } + renderer.paragraph = function (text) { + if (/^!>/.test(text)) { + return helperTpl('tip', text) + } else if (/^\?>/.test(text)) { + return helperTpl('warn', text) + } + return `

${text}

` + } + renderer.image = function (href, title, text) { + let url = href + const titleHTML = title ? ` title="${title}"` : '' + + if (!isAbsolutePath(href)) { + url = getPath(this.contentBase, href) + } + + return `${text}` + } + + return renderer } - const slug = slugify(text) - const url = toURL(currentPath, { id: slug }) - nextToc.slug = url - toc.push(nextToc) + /** + * Compile sidebar + */ + sidebar (text, level) { + const currentPath = this.router.getCurrentPath() + let html = '' - return `${text}` -} -// highlight code -renderer.code = function (code, lang = '') { - const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup) + if (text) { + html = this.runner(text) + html = html.match(/]*>([\s\S]+)<\/ul>/g)[0] + } else { + const tree = this.cacheTree[currentPath] || genTree(this.toc, level) + html = treeTpl(tree, '