refactor(core): fix route path
This commit is contained in:
parent
8cae16539d
commit
e2b7b976cf
16 changed files with 125 additions and 444 deletions
|
|
@ -1,6 +1,14 @@
|
|||
import { isMobile } from '../util/env'
|
||||
import { body, on } from '../util/dom'
|
||||
import * as sidebar from './sidebar'
|
||||
import { scrollIntoView } from './scroll'
|
||||
|
||||
export function eventMixin (proto) {
|
||||
proto.$resetEvents = function () {
|
||||
scrollIntoView(this.route.query.id)
|
||||
sidebar.getAndActive('nav')
|
||||
}
|
||||
}
|
||||
|
||||
export function initEvent (vm) {
|
||||
// Bind toggle button
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { isMobile } from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
import { parse } from '../route/hash'
|
||||
|
||||
export function scrollActiveSidebar () {
|
||||
if (isMobile) return
|
||||
|
|
@ -21,8 +22,7 @@ export function scrollActiveSidebar () {
|
|||
let href = a.getAttribute('href')
|
||||
|
||||
if (href !== '/') {
|
||||
const match = href.match('#([^#]+)$')
|
||||
if (match && match.length) href = match[0].slice(1)
|
||||
href = parse(href).query.id
|
||||
}
|
||||
|
||||
nav[decodeURIComponent(href)] = li
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ export function get (url, hasBar = false) {
|
|||
return {
|
||||
then: function (success, error = noop) {
|
||||
if (hasBar) {
|
||||
const id = setInterval(_ => progressbar({}), 500)
|
||||
const id = setInterval(_ => progressbar({
|
||||
step: Math.floor(Math.random() * 5 + 1)
|
||||
}), 500)
|
||||
|
||||
on('progress', progressbar)
|
||||
on('loadend', evt => {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,10 @@ import { get } from './ajax'
|
|||
import { callHook } from '../init/lifecycle'
|
||||
import { getRoot } from '../route/util'
|
||||
import { noop } from '../util/core'
|
||||
import { scrollIntoView } from '../event/scroll'
|
||||
import { getAndActive } from '../event/sidebar'
|
||||
|
||||
export function fetchMixin (Docsify) {
|
||||
export function fetchMixin (proto) {
|
||||
let last
|
||||
|
||||
Docsify.prototype._fetch = function (cb = noop) {
|
||||
proto._fetch = function (cb = noop) {
|
||||
const { path } = this.route
|
||||
const { loadNavbar, loadSidebar } = this.config
|
||||
const root = getRoot(path)
|
||||
|
|
@ -42,7 +39,7 @@ export function fetchMixin (Docsify) {
|
|||
)
|
||||
}
|
||||
|
||||
Docsify.prototype._fetchCover = function () {
|
||||
proto._fetchCover = function () {
|
||||
const { coverpage } = this.config
|
||||
const root = getRoot(this.route.path)
|
||||
|
||||
|
|
@ -54,13 +51,16 @@ export function fetchMixin (Docsify) {
|
|||
get(this.$getFile(root + coverpage))
|
||||
.then(text => this._renderCover(text))
|
||||
}
|
||||
|
||||
proto.$fetch = function () {
|
||||
this._fetchCover()
|
||||
this._fetch(result => {
|
||||
this.$resetEvents()
|
||||
callHook(this, 'doneEach')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function initFetch (vm) {
|
||||
vm._fetchCover(vm)
|
||||
vm._fetch(result => {
|
||||
scrollIntoView(vm.route.query.id)
|
||||
getAndActive('nav')
|
||||
callHook(vm, 'doneEach')
|
||||
})
|
||||
vm.$fetch()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,20 @@ import { initMixin } from './init'
|
|||
import { routeMixin } from './route'
|
||||
import { renderMixin } from './render'
|
||||
import { fetchMixin } from './fetch'
|
||||
import { eventMixin } from './event'
|
||||
import initGlobalAPI from './global-api'
|
||||
|
||||
function Docsify () {
|
||||
this._init()
|
||||
}
|
||||
|
||||
initMixin(Docsify)
|
||||
routeMixin(Docsify)
|
||||
renderMixin(Docsify)
|
||||
fetchMixin(Docsify)
|
||||
const proto = Docsify.prototype
|
||||
|
||||
initMixin(proto)
|
||||
routeMixin(proto)
|
||||
renderMixin(proto)
|
||||
fetchMixin(proto)
|
||||
eventMixin(proto)
|
||||
|
||||
/**
|
||||
* Global API
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import { initEvent } from '../event'
|
|||
import { initFetch } from '../fetch'
|
||||
import { isFn } from '../util/core'
|
||||
|
||||
export function initMixin (Docsify) {
|
||||
Docsify.prototype._init = function () {
|
||||
export function initMixin (proto) {
|
||||
proto._init = function () {
|
||||
const vm = this
|
||||
vm.config = config || {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ import { helper as helperTpl, tree as treeTpl } from './tpl'
|
|||
import { genTree } from './gen-tree'
|
||||
import { slugify, clearSlugCache } from './slugify'
|
||||
import { emojify } from './emojify'
|
||||
import { toURL } from '../route/hash'
|
||||
import { isFn, merge, cached, noop } from '../util/core'
|
||||
import { toURL, parse } from '../route/hash'
|
||||
import { getBasePath, getPath } from '../route/util'
|
||||
import { isFn, merge, cached } from '../util/core'
|
||||
|
||||
let markdownCompiler = marked
|
||||
let contentBase = ''
|
||||
let currentPath = ''
|
||||
let renderer = new marked.Renderer()
|
||||
const TOC = {}
|
||||
let toc = []
|
||||
|
||||
/**
|
||||
|
|
@ -30,7 +33,8 @@ export const markdown = cached(text => {
|
|||
markdown.renderer = renderer
|
||||
|
||||
markdown.init = function (config = {}, base = window.location.pathname) {
|
||||
contentBase = base
|
||||
contentBase = getBasePath(base)
|
||||
currentPath = parse().path
|
||||
|
||||
if (isFn(config)) {
|
||||
markdownCompiler = config(marked, renderer)
|
||||
|
|
@ -40,13 +44,17 @@ markdown.init = function (config = {}, base = window.location.pathname) {
|
|||
}
|
||||
}
|
||||
|
||||
markdown.update = function () {
|
||||
currentPath = parse().path
|
||||
}
|
||||
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = slugify(text)
|
||||
const url = toURL(contentBase, { id: slug })
|
||||
const url = toURL(currentPath, { id: slug })
|
||||
|
||||
toc.push({ level, slug: url, title: text })
|
||||
|
||||
|
|
@ -60,8 +68,7 @@ renderer.code = function (code, lang = '') {
|
|||
}
|
||||
renderer.link = function (href, title, text) {
|
||||
if (!/:|(\/{2})/.test(href)) {
|
||||
// TODO
|
||||
href = `#/${href}`.replace(/\/+/g, '/')
|
||||
href = toURL(href)
|
||||
}
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
}
|
||||
|
|
@ -74,12 +81,10 @@ renderer.paragraph = function (text) {
|
|||
return `<p>${text}</p>`
|
||||
}
|
||||
renderer.image = function (href, title, text) {
|
||||
// TODO
|
||||
// get base path
|
||||
// const url = /:|(\/{2})/.test(href) ? href : ($docsify.basePath + href).replace(/\/+/g, '/')
|
||||
// const titleHTML = title ? ` title="${title}"` : ''
|
||||
const url = getPath(contentBase, href)
|
||||
const titleHTML = title ? ` title="${title}"` : ''
|
||||
|
||||
// return `<img src="${url}" alt="${text}"${titleHTML} />`
|
||||
return `<img src="${url}" data-origin="${href}" alt="${text}"${titleHTML}>`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -105,8 +110,11 @@ export function sidebar (text, level) {
|
|||
export function subSidebar (el, level) {
|
||||
if (el) {
|
||||
toc[0] && toc[0].level === 1 && toc.shift()
|
||||
const tree = genTree(toc, level)
|
||||
el.parentNode.innerHTML += treeTpl(tree, '<ul>')
|
||||
const tree = genTree(TOC[currentPath] || toc, level)
|
||||
el.parentNode.innerHTML += treeTpl(tree, '<ul class="app-sub-sidebar">')
|
||||
}
|
||||
if (toc.length) {
|
||||
TOC[currentPath] = toc.slice()
|
||||
}
|
||||
toc = []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
import * as dom from '../util/dom'
|
||||
import { getAndActive, sticky } from '../event/sidebar'
|
||||
import { scrollActiveSidebar } from '../event/scroll'
|
||||
import { scrollActiveSidebar, scroll2Top } from '../event/scroll'
|
||||
import cssVars from '../util/polyfill/css-vars'
|
||||
import * as tpl from './tpl'
|
||||
import { markdown, sidebar, subSidebar, cover } from './compiler'
|
||||
import { callHook } from '../init/lifecycle'
|
||||
import { getBasePath, getPath } from '../route/util'
|
||||
|
||||
function executeScript () {
|
||||
const script = dom.findAll('.markdown-section>script')
|
||||
.filter(s => !/template/.test(s.type))[0]
|
||||
if (!script) return false
|
||||
const code = script.innerText.trim()
|
||||
if (!code) return false
|
||||
|
||||
window.__EXECUTE_RESULT__ = new Function('return ' + code)()
|
||||
}
|
||||
|
||||
function renderMain (html) {
|
||||
if (!html) {
|
||||
|
|
@ -14,11 +25,21 @@ function renderMain (html) {
|
|||
this._renderTo('.markdown-section', html)
|
||||
// Render sidebar with the TOC
|
||||
!this.config.loadSidebar && this._renderSidebar()
|
||||
// execute script
|
||||
this.config.executeScript && executeScript()
|
||||
|
||||
if (!this.config.executeScript
|
||||
&& typeof window.Vue !== 'undefined'
|
||||
&& !executeScript()) {
|
||||
window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main')
|
||||
}
|
||||
|
||||
if (this.config.auto2top) {
|
||||
setTimeout(() => scroll2Top(this.config.auto2top), 0)
|
||||
}
|
||||
}
|
||||
|
||||
export function renderMixin (Docsify) {
|
||||
const proto = Docsify.prototype
|
||||
|
||||
export function renderMixin (proto) {
|
||||
proto._renderTo = function (el, content, replace) {
|
||||
const node = dom.getNode(el)
|
||||
if (node) node[replace ? 'outerHTML' : 'innerHTML'] = content
|
||||
|
|
@ -54,14 +75,14 @@ export function renderMixin (Docsify) {
|
|||
dom.toggleClass(el, 'add', 'show')
|
||||
|
||||
let html = cover(text)
|
||||
const m = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$')
|
||||
const m = html.trim().match('<p><img.*?data-origin="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$')
|
||||
|
||||
if (m) {
|
||||
if (m[2] === 'color') {
|
||||
el.style.background = m[1] + (m[3] || '')
|
||||
} else {
|
||||
dom.toggleClass(el, 'add', 'has-mask')
|
||||
el.style.backgroundImage = `url(${m[1]})`
|
||||
el.style.backgroundImage = `url(${getPath(getBasePath(this.config.basePath), m[1])})`
|
||||
}
|
||||
html = html.replace(m[0], '')
|
||||
}
|
||||
|
|
@ -69,13 +90,17 @@ export function renderMixin (Docsify) {
|
|||
this._renderTo('.cover-main', html)
|
||||
sticky()
|
||||
}
|
||||
|
||||
proto._updateRender = function () {
|
||||
markdown.update()
|
||||
}
|
||||
}
|
||||
|
||||
export function initRender (vm) {
|
||||
const config = vm.config
|
||||
|
||||
// Init markdown compiler
|
||||
markdown.init(vm.config.markdown)
|
||||
markdown.init(config.markdown, config.basePath)
|
||||
|
||||
const id = config.el || '#app'
|
||||
const navEl = dom.find('nav') || dom.create('nav')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import * as dom from '../util/dom'
|
||||
import { isPrimitive } from '../util/core'
|
||||
|
||||
let barEl
|
||||
let timeId
|
||||
|
|
@ -22,11 +21,8 @@ export default function ({ loaded, total, step }) {
|
|||
|
||||
!barEl && init()
|
||||
|
||||
if (!isPrimitive(step)) {
|
||||
step = Math.floor(Math.random() * 5 + 1)
|
||||
}
|
||||
if (step) {
|
||||
num = parseInt(barEl.style.width, 10) + step
|
||||
num = parseInt(barEl.style.width || 0, 10) + step
|
||||
num = num > 80 ? 80 : num
|
||||
} else {
|
||||
num = Math.floor(loaded / total * 100)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function main (config) {
|
|||
|
||||
return (isMobile ? `${aside}<main>` : `<main>${aside}`) +
|
||||
'<section class="content">' +
|
||||
'<article class="markdown-section"></article>' +
|
||||
'<article class="markdown-section" id="main"></article>' +
|
||||
'</section>' +
|
||||
'</main>'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { merge } from '../util/core'
|
||||
import { merge, cached } from '../util/core'
|
||||
import { parseQuery, stringifyQuery } from './util'
|
||||
|
||||
function replaceHash (path) {
|
||||
|
|
@ -8,6 +8,11 @@ function replaceHash (path) {
|
|||
)
|
||||
}
|
||||
|
||||
const replaceSlug = cached(path => {
|
||||
return path
|
||||
.replace('#', '?id=')
|
||||
.replace(/\?(\w+)=/g, (_, slug) => slug === 'id' ? '?id=' : `&${slug}=`)
|
||||
})
|
||||
/**
|
||||
* Normalize the current url
|
||||
*
|
||||
|
|
@ -18,9 +23,7 @@ function replaceHash (path) {
|
|||
export function normalize () {
|
||||
let path = getHash()
|
||||
|
||||
path = path
|
||||
.replace('#', '?id=')
|
||||
.replace(/\?(\w+)=/g, (_, slug) => slug === 'id' ? '?id=' : `&${slug}=`)
|
||||
path = replaceSlug(path)
|
||||
|
||||
if (path.charAt(0) === '/') return replaceHash(path)
|
||||
replaceHash('/' + path)
|
||||
|
|
@ -62,7 +65,7 @@ export function parse (path = window.location.href) {
|
|||
* @param {object} qs query params
|
||||
*/
|
||||
export function toURL (path, params) {
|
||||
const route = parse(path)
|
||||
const route = parse(replaceSlug(path))
|
||||
|
||||
route.query = merge({}, route.query, params)
|
||||
path = route.path + stringifyQuery(route.query)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { normalize, parse } from './hash'
|
||||
import { getBasePath, cleanPath } from './util'
|
||||
import { getBasePath, getPath } from './util'
|
||||
import { on } from '../util/dom'
|
||||
|
||||
function getAlias (path, alias) {
|
||||
|
|
@ -15,16 +15,16 @@ function getFileName (path) {
|
|||
: `${path}.md`
|
||||
}
|
||||
|
||||
export function routeMixin (Docsify) {
|
||||
Docsify.prototype.route = {}
|
||||
Docsify.prototype.$getFile = function (path) {
|
||||
export function routeMixin (proto) {
|
||||
proto.route = {}
|
||||
proto.$getFile = function (path) {
|
||||
const { config } = this
|
||||
const base = getBasePath(config.basePath)
|
||||
|
||||
path = getAlias(path, config.alias)
|
||||
path = getFileName(path)
|
||||
path = path === '/README.md' ? ('/' + config.homepage || path) : path
|
||||
path = cleanPath(base + path)
|
||||
path = getPath(base, path)
|
||||
|
||||
return path
|
||||
}
|
||||
|
|
@ -39,14 +39,14 @@ export function initRoute (vm) {
|
|||
on('hashchange', _ => {
|
||||
normalize()
|
||||
vm.route = parse()
|
||||
vm._updateRender()
|
||||
|
||||
if (lastRoute.path === vm.route.path) {
|
||||
// TODO: goto xxx
|
||||
vm.$resetEvents()
|
||||
return
|
||||
}
|
||||
|
||||
vm._fetchCover()
|
||||
vm._fetch()
|
||||
vm.$fetch()
|
||||
lastRoute = vm.route
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { cached } from '../util/core'
|
|||
const decode = decodeURIComponent
|
||||
const encode = encodeURIComponent
|
||||
|
||||
export const parseQuery = cached(query => {
|
||||
export function parseQuery (query) {
|
||||
const res = {}
|
||||
|
||||
query = query.trim().replace(/^(\?|#|&)/, '')
|
||||
|
|
@ -19,7 +19,7 @@ export const parseQuery = cached(query => {
|
|||
res[parts[0]] = decode(parts[1])
|
||||
})
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
export function stringifyQuery (obj) {
|
||||
const qs = []
|
||||
|
|
@ -37,6 +37,14 @@ export const getBasePath = cached(base => {
|
|||
: cleanPath(window.location.pathname + '/' + base)
|
||||
})
|
||||
|
||||
export function getPath (...args) {
|
||||
const path = args.find(path => /:|(\/{2})/.test(path))
|
||||
|
||||
if (path) return path
|
||||
|
||||
return cleanPath(args.join('/'))
|
||||
}
|
||||
|
||||
export const getRoot = cached(path => {
|
||||
return /\/$/g.test(path) ? path : path.match(/(\S*\/)[^\/]+$/)[1]
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue