refactor(router): clean global api

This commit is contained in:
qingwei.li 2017-05-29 19:55:28 +08:00 • committed by cinwell.li
commit 8741c746df
12 changed files with 46 additions and 126 deletions

View file

@ -6,13 +6,13 @@ import { scrollIntoView } from './scroll'
export function eventMixin (proto) { export function eventMixin (proto) {
proto.$resetEvents = function () { proto.$resetEvents = function () {
scrollIntoView(this.route.query.id) scrollIntoView(this.route.query.id)
sidebar.getAndActive('nav') sidebar.getAndActive(this.router, 'nav')
} }
} }
export function initEvent (vm) { export function initEvent (vm) {
// Bind toggle button // Bind toggle button
sidebar.btn('button.sidebar-toggle') sidebar.btn('button.sidebar-toggle', vm.router)
// Bind sticky effect // Bind sticky effect
if (vm.config.coverpage) { if (vm.config.coverpage) {
!isMobile && on('scroll', sidebar.sticky) !isMobile && on('scroll', sidebar.sticky)

View file

@ -1,6 +1,5 @@
import { isMobile } from '../util/env' import { isMobile } from '../util/env'
import * as dom from '../util/dom' import * as dom from '../util/dom'
import { parse } from '../router/hash'
const nav = {} const nav = {}
let hoverOver = false let hoverOver = false
@ -53,7 +52,7 @@ function highlight () {
} }
} }
export function scrollActiveSidebar () { export function scrollActiveSidebar (router) {
if (isMobile) return if (isMobile) return
const sidebar = dom.getNode('.sidebar') const sidebar = dom.getNode('.sidebar')
@ -66,7 +65,7 @@ export function scrollActiveSidebar () {
let href = a.getAttribute('href') let href = a.getAttribute('href')
if (href !== '/') { if (href !== '/') {
href = parse(href).query.id href = router.parse(href).query.id
} }
nav[decodeURIComponent(href)] = li nav[decodeURIComponent(href)] = li

View file

@ -1,12 +1,11 @@
import { isMobile } from '../util/env' import { isMobile } from '../util/env'
import * as dom from '../util/dom' import * as dom from '../util/dom'
import { getHash } from '../router/hash'
const title = dom.$.title const title = dom.$.title
/** /**
* Toggle button * Toggle button
*/ */
export function btn (el) { export function btn (el, router) {
const toggle = _ => dom.body.classList.toggle('close') const toggle = _ => dom.body.classList.toggle('close')
el = dom.getNode(el) el = dom.getNode(el)
@ -21,7 +20,7 @@ export function btn (el) {
dom.body.classList.contains('close') && toggle() dom.body.classList.contains('close') && toggle()
) )
dom.on(sidebar, 'click', _ => dom.on(sidebar, 'click', _ =>
setTimeout((_ => getAndActive(sidebar, true, true), 0)) setTimeout((_ => getAndActive(router, sidebar, true, true), 0))
) )
} }
@ -39,16 +38,17 @@ export function sticky () {
/** /**
* Get and active link * Get and active link
* @param {object} router
* @param {string|element} el * @param {string|element} el
* @param {Boolean} isParent acitve parent * @param {Boolean} isParent acitve parent
* @param {Boolean} autoTitle auto set title * @param {Boolean} autoTitle auto set title
* @return {element} * @return {element}
*/ */
export function getAndActive (el, isParent, autoTitle) { export function getAndActive (router, el, isParent, autoTitle) {
el = dom.getNode(el) el = dom.getNode(el)
const links = dom.findAll(el, 'a') const links = dom.findAll(el, 'a')
const hash = '#' + getHash() const hash = router.toURL(router.getCurrentPath())
let target let target
links links

View file

@ -1,14 +1,14 @@
import * as util from './util' import * as util from './util'
import * as dom from './util/dom' import * as dom from './util/dom'
import * as render from './render/compiler' import { Compiler } from './render/compiler'
import * as route from './router/hash'
import { slugify } from './render/slugify' import { slugify } from './render/slugify'
import { get } from './fetch/ajax' import { get } from './fetch/ajax'
import marked from 'marked' import marked from 'marked'
import prism from 'prismjs' import prism from 'prismjs'
export default function () { export default function () {
window.Docsify = { util, dom, render, route, get, slugify } window.Docsify = { util, dom, get, slugify }
window.DocsifyCompiler = Compiler
window.marked = marked window.marked = marked
window.Prism = prism window.Prism = prism
} }

View file

@ -17,24 +17,24 @@ export class Compiler {
this.contentBase = getBasePath(config.base) this.contentBase = getBasePath(config.base)
const renderer = this._initRenderer() const renderer = this._initRenderer()
let runner let compile
const mdConf = config.markdown || {} const mdConf = config.markdown || {}
if (isFn(mdConf)) { if (isFn(mdConf)) {
runner = mdConf(marked, renderer) compile = mdConf(marked, renderer)
} else { } else {
marked.setOptions(merge(mdConf, { marked.setOptions(merge(mdConf, {
renderer: merge(renderer, mdConf.renderer) renderer: merge(renderer, mdConf.renderer)
})) }))
runner = marked compile = marked
} }
this.runner = cached(text => { this.compile = cached(text => {
let html = '' let html = ''
if (!text) return text if (!text) return text
html = runner(text) html = compile(text)
html = emojify(html) html = emojify(html)
slugify.clear() slugify.clear()
@ -119,7 +119,7 @@ export class Compiler {
let html = '' let html = ''
if (text) { if (text) {
html = this.runner(text) html = this.compile(text)
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0] html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
} else { } else {
const tree = this.cacheTree[currentPath] || genTree(this.toc, level) const tree = this.cacheTree[currentPath] || genTree(this.toc, level)
@ -151,7 +151,7 @@ export class Compiler {
} }
article (text) { article (text) {
return this.runner(text) return this.compile(text)
} }
/** /**
@ -159,7 +159,7 @@ export class Compiler {
*/ */
cover (text) { cover (text) {
const cacheToc = this.toc.slice() const cacheToc = this.toc.slice()
const html = this.runner(text) const html = this.compile(text)
this.toc = cacheToc.slice() this.toc = cacheToc.slice()

View file

@ -1,14 +1,14 @@
import * as dom from '../util/dom' import * as dom from '../util/dom'
import { getAndActive, sticky } from '../event/sidebar'
import { scrollActiveSidebar, scroll2Top } from '../event/scroll'
import cssVars from '../util/polyfill/css-vars'
import * as tpl from './tpl' import * as tpl from './tpl'
import { Compiler } from './compiler' import cssVars from '../util/polyfill/css-vars'
import { callHook } from '../init/lifecycle'
import { getBasePath, getPath, isAbsolutePath } from '../router/util'
import { isPrimitive } from '../util/core'
import { isMobile } from '../util/env'
import tinydate from 'tinydate' import tinydate from 'tinydate'
import { callHook } from '../init/lifecycle'
import { Compiler } from './compiler'
import { getAndActive, sticky } from '../event/sidebar'
import { getBasePath, getPath, isAbsolutePath } from '../router/util'
import { isMobile } from '../util/env'
import { isPrimitive } from '../util/core'
import { scrollActiveSidebar, scroll2Top } from '../event/scroll'
function executeScript () { function executeScript () {
const script = dom.findAll('.markdown-section>script') const script = dom.findAll('.markdown-section>script')
@ -86,13 +86,13 @@ export function renderMixin (proto) {
const { maxLevel, subMaxLevel, autoHeader, loadSidebar } = this.config const { maxLevel, subMaxLevel, autoHeader, loadSidebar } = this.config
this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel)) this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel))
const activeEl = getAndActive('.sidebar-nav', true, true) const activeEl = getAndActive(this.router, '.sidebar-nav', true, true)
if (loadSidebar && activeEl) { if (loadSidebar && activeEl) {
activeEl.parentNode.innerHTML += this.compiler.subSidebar(subMaxLevel) activeEl.parentNode.innerHTML += this.compiler.subSidebar(subMaxLevel)
} }
// bind event // bind event
this.activeLink = activeEl this.activeLink = activeEl
scrollActiveSidebar() scrollActiveSidebar(this.router)
if (autoHeader && activeEl) { if (autoHeader && activeEl) {
const main = dom.getNode('#main') const main = dom.getNode('#main')
@ -106,13 +106,13 @@ export function renderMixin (proto) {
} }
proto._renderNav = function (text) { proto._renderNav = function (text) {
text && this._renderTo('nav', this.compiler.runner(text)) text && this._renderTo('nav', this.compiler.compile(text))
getAndActive('nav') getAndActive(this.router, 'nav')
} }
proto._renderMain = function (text, opt = {}) { proto._renderMain = function (text, opt = {}) {
callHook(this, 'beforeEach', text, result => { callHook(this, 'beforeEach', text, result => {
let html = this.isHTML ? result : this.compiler.runner(result) let html = this.isHTML ? result : this.compiler.compile(result)
if (opt.updatedAt) { if (opt.updatedAt) {
html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated) html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated)
} }

View file

@ -1,80 +0,0 @@
import { merge, cached } from '../util/core'
import { parseQuery, stringifyQuery, cleanPath } from './util'
export * from './util'
function replaceHash (path) {
const i = window.location.href.indexOf('#')
window.location.replace(
window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
)
}
const replaceSlug = cached(path => {
return path
.replace('#', '?id=')
// .replace(/\?(\w+)=/g, (_, slug) => slug === 'id' ? '?id=' : `&${slug}=`)
})
/**
* Normalize the current url
*
* @example
* domain.com/docs/ => domain.com/docs/#/
* domain.com/docs/#/#slug => domain.com/docs/#/?id=slug
*/
export function normalize () {
let path = getHash()
path = replaceSlug(path)
if (path.charAt(0) === '/') return replaceHash(path)
replaceHash('/' + path)
}
export function getHash () {
// We can't use window.location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = window.location.href
const index = href.indexOf('#')
return index === -1 ? '' : href.slice(index + 1)
}
/**
* Parse the url
* @param {string} [path=window.location.herf]
* @return {object} { path, query }
*/
export function parse (path = window.location.href) {
let query = ''
const queryIndex = path.indexOf('?')
if (queryIndex >= 0) {
query = path.slice(queryIndex + 1)
path = path.slice(0, queryIndex)
}
const hashIndex = path.indexOf('#')
if (hashIndex) {
path = path.slice(hashIndex + 1)
}
return { path, query: parseQuery(query) }
}
/**
* to URL
* @param {string} path
* @param {object} qs query params
* @param {string} currentRoute optional current route
*/
export function toURL (path, params, currentRoute) {
const local = currentRoute && path[0] === '#'
const route = parse(replaceSlug(path))
route.query = merge({}, route.query, params)
path = route.path + stringifyQuery(route.query)
path = path.replace(/\.md(\?)|\.md$/, '$1')
if (local) path = currentRoute + path
return cleanPath('#/' + path)
}

View file

@ -1,7 +1,7 @@
import { History } from './base' import { History } from './base'
import { merge, cached, noop } from '../../util/core' import { merge, cached, noop } from '../../util/core'
import { parseQuery, stringifyQuery, cleanPath } from '../util'
import { on } from '../../util/dom' import { on } from '../../util/dom'
import { parseQuery, stringifyQuery, cleanPath } from '../util'
function replaceHash (path) { function replaceHash (path) {
const i = location.href.indexOf('#') const i = location.href.indexOf('#')

View file

@ -1,2 +1,3 @@
export * from './core' export * from './core'
export * from './env' export * from './env'
export * from '../router/util'

View file

@ -138,9 +138,9 @@ function updateNoData (text, path) {
} }
} }
export function init (opts) { export function init (opts, vm) {
dom = Docsify.dom dom = Docsify.dom
const keywords = Docsify.route.parse().query.s const keywords = vm.router.parse().query.s
style() style()
tpl(opts, keywords) tpl(opts, keywords)

View file

@ -24,7 +24,7 @@ const install = function (hook, vm) {
const isAuto = CONFIG.paths === 'auto' const isAuto = CONFIG.paths === 'auto'
hook.mounted(_ => { hook.mounted(_ => {
initComponet(CONFIG) initComponet(CONFIG, vm)
!isAuto && initSearch(CONFIG, vm) !isAuto && initSearch(CONFIG, vm)
}) })
hook.doneEach(_ => { hook.doneEach(_ => {
@ -33,4 +33,4 @@ const install = function (hook, vm) {
}) })
} }
window.$docsify.plugins = [].concat(install, window.$docsify.plugins) $docsify.plugins = [].concat(install, $docsify.plugins)

View file

@ -14,18 +14,18 @@ function escapeHtml (string) {
return String(string).replace(/[&<>"'\/]/g, s => entityMap[s]) return String(string).replace(/[&<>"'\/]/g, s => entityMap[s])
} }
function getAllPaths () { function getAllPaths (router) {
const paths = [] const paths = []
helper.dom.findAll('a:not([data-nosearch])') helper.dom.findAll('a:not([data-nosearch])')
.map(node => { .map(node => {
const href = node.href const href = node.href
const originHref = node.getAttribute('href') const originHref = node.getAttribute('href')
const path = helper.route.parse(href).path const path = router.parse(href).path
if (path && if (path &&
paths.indexOf(path) === -1 && paths.indexOf(path) === -1 &&
!helper.route.isAbsolutePath(originHref)) { !Docsify.util.isAbsolutePath(originHref)) {
paths.push(path) paths.push(path)
} }
}) })
@ -38,10 +38,10 @@ function saveData (maxAge) {
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS)) localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS))
} }
export function genIndex (path, content = '') { export function genIndex (path, content = '', router) {
const tokens = window.marked.lexer(content) const tokens = window.marked.lexer(content)
const slugify = window.Docsify.slugify const slugify = window.Docsify.slugify
const toURL = Docsify.route.toURL const toURL = router.toURL
const index = {} const index = {}
let slug let slug
@ -145,7 +145,7 @@ export function init (config, vm) {
return return
} }
const paths = isAuto ? getAllPaths() : config.paths const paths = isAuto ? getAllPaths(vm.router) : config.paths
const len = paths.length const len = paths.length
let count = 0 let count = 0
@ -155,7 +155,7 @@ export function init (config, vm) {
helper helper
.get(vm.router.getFile(path)) .get(vm.router.getFile(path))
.then(result => { .then(result => {
INDEXS[path] = genIndex(path, result) INDEXS[path] = genIndex(path, result, vm.router)
len === ++count && saveData(config.maxAge) len === ++count && saveData(config.maxAge)
}) })
}) })