mirror of
https://gitee.com/docsifyjs/docsify.git
synced 2024-11-30 02:58:37 +08:00
Eslint fixes for v4x (#989)
* UPDATE .eslintrc * UPDATE lint task * FIX lint errors * CLEANUP * FIX no-eq-null warning * FIX many jsdoc warnings * FIX jsdoc issues * FIX jsdoc warnings * FIX jsdoc * FIX eqeq and no-eq-null * ADD lint to travis * UPDATE test env for eslint
This commit is contained in:
parent
157973c509
commit
db97a1d22a
20
.eslintrc
20
.eslintrc
@ -1,7 +1,10 @@
|
||||
{
|
||||
"extends": "xo-space/browser",
|
||||
"rules": {
|
||||
"semi": [2, "never"],
|
||||
"semi": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"no-return-assign": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-new-func": "off",
|
||||
@ -10,11 +13,22 @@
|
||||
"max-params": "off",
|
||||
"no-script-url": "off",
|
||||
"camelcase": "off",
|
||||
"no-warning-comments": "off"
|
||||
"object-curly-spacing": "off",
|
||||
"no-warning-comments": "off",
|
||||
"no-negated-condition": "off",
|
||||
"eqeqeq": "warn",
|
||||
"no-eq-null": "warn",
|
||||
"max-statements-per-line": "warn"
|
||||
},
|
||||
"globals": {
|
||||
"Docsify": true,
|
||||
"$docsify": true,
|
||||
"process": true
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"amd": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js: stable
|
||||
|
||||
script:
|
||||
- npm run lint
|
||||
|
@ -5,12 +5,12 @@ const PORT = 8080
|
||||
|
||||
/// [demo]
|
||||
const result = fetch(`${URL}:${PORT}`)
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
.then(function (response) {
|
||||
return response.json()
|
||||
})
|
||||
.then(function (myJson) {
|
||||
console.log(JSON.stringify(myJson))
|
||||
})
|
||||
.then(function(myJson) {
|
||||
console.log(JSON.stringify(myJson));
|
||||
});
|
||||
/// [demo]
|
||||
|
||||
result.then(console.log).catch(console.error)
|
||||
|
@ -26,7 +26,7 @@
|
||||
"serve:ssr": "cross-env SSR=1 node server",
|
||||
"dev": "run-p serve watch:*",
|
||||
"dev:ssr": "run-p serve:ssr watch:*",
|
||||
"lint": "eslint {src,packages} --fix",
|
||||
"lint": "eslint . --fix",
|
||||
"test": "mocha test/*/**",
|
||||
"css": "node build/css",
|
||||
"watch:css": "npm run css -- -o themes -w",
|
||||
@ -48,8 +48,8 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"npm run lint",
|
||||
"git add"
|
||||
"npm run lint",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
@ -98,4 +98,4 @@
|
||||
"collective": {
|
||||
"url": "https://opencollective.com/docsify"
|
||||
}
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ function mainTpl(config) {
|
||||
if (config.repo) {
|
||||
html += tpl.corner(config.repo)
|
||||
}
|
||||
|
||||
if (config.coverpage) {
|
||||
html += tpl.cover()
|
||||
}
|
||||
@ -154,12 +155,14 @@ export default class Renderer {
|
||||
if (!res.ok) {
|
||||
throw Error()
|
||||
}
|
||||
|
||||
content = await res.text()
|
||||
this.lock = 0
|
||||
} else {
|
||||
content = await readFileSync(filePath, 'utf8')
|
||||
this.lock = 0
|
||||
}
|
||||
|
||||
return content
|
||||
} catch (e) {
|
||||
this.lock = this.lock || 0
|
||||
|
@ -23,9 +23,9 @@ export default function () {
|
||||
ext: '.md',
|
||||
mergeNavbar: false,
|
||||
formatUpdated: '',
|
||||
// this config for the links inside markdown
|
||||
// This config for the links inside markdown
|
||||
externalLinkTarget: '_blank',
|
||||
// this config for the corner
|
||||
// This config for the corner
|
||||
cornerExternalLinkTarget: '_blank',
|
||||
externalLinkRel: 'noopener',
|
||||
routerMode: 'hash',
|
||||
@ -55,15 +55,19 @@ export default function () {
|
||||
if (config.loadSidebar === true) {
|
||||
config.loadSidebar = '_sidebar' + config.ext
|
||||
}
|
||||
|
||||
if (config.loadNavbar === true) {
|
||||
config.loadNavbar = '_navbar' + config.ext
|
||||
}
|
||||
|
||||
if (config.coverpage === true) {
|
||||
config.coverpage = '_coverpage' + config.ext
|
||||
}
|
||||
|
||||
if (config.repo === true) {
|
||||
config.repo = ''
|
||||
}
|
||||
|
||||
if (config.name === true) {
|
||||
config.name = ''
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {isMobile} from '../util/env'
|
||||
import { isMobile } from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
import Tweezer from 'tweezer.js'
|
||||
|
||||
@ -12,6 +12,7 @@ function scrollTo(el) {
|
||||
if (scroller) {
|
||||
scroller.stop()
|
||||
}
|
||||
|
||||
enableScrollEvent = false
|
||||
scroller = new Tweezer({
|
||||
start: window.pageYOffset,
|
||||
@ -30,6 +31,7 @@ function highlight(path) {
|
||||
if (!enableScrollEvent) {
|
||||
return
|
||||
}
|
||||
|
||||
const sidebar = dom.getNode('.sidebar')
|
||||
const anchors = dom.findAll('.anchor')
|
||||
const wrap = dom.find(sidebar, '.sidebar-nav')
|
||||
@ -45,14 +47,17 @@ function highlight(path) {
|
||||
if (!last) {
|
||||
last = node
|
||||
}
|
||||
|
||||
break
|
||||
} else {
|
||||
last = node
|
||||
}
|
||||
}
|
||||
|
||||
if (!last) {
|
||||
return
|
||||
}
|
||||
|
||||
const li = nav[getNavKey(decodeURIComponent(path), last.getAttribute('data-id'))]
|
||||
|
||||
if (!li || li === active) {
|
||||
@ -88,7 +93,7 @@ export function scrollActiveSidebar(router) {
|
||||
|
||||
const sidebar = dom.getNode('.sidebar')
|
||||
let lis = []
|
||||
if (sidebar != null) {
|
||||
if (sidebar !== null && sidebar !== undefined) {
|
||||
lis = dom.findAll(sidebar, 'li')
|
||||
}
|
||||
|
||||
@ -98,10 +103,11 @@ export function scrollActiveSidebar(router) {
|
||||
if (!a) {
|
||||
continue
|
||||
}
|
||||
|
||||
let href = a.getAttribute('href')
|
||||
|
||||
if (href !== '/') {
|
||||
const {query: {id}, path} = router.parse(href)
|
||||
const { query: { id }, path } = router.parse(href)
|
||||
if (id) {
|
||||
href = getNavKey(path, id)
|
||||
}
|
||||
@ -115,6 +121,7 @@ export function scrollActiveSidebar(router) {
|
||||
if (isMobile) {
|
||||
return
|
||||
}
|
||||
|
||||
const path = router.getCurrentPath()
|
||||
dom.off('scroll', () => highlight(path))
|
||||
dom.on('scroll', () => highlight(path))
|
||||
|
@ -1,17 +1,20 @@
|
||||
import {isMobile} from '../util/env'
|
||||
import { isMobile } from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
|
||||
const title = dom.$.title
|
||||
/**
|
||||
* Toggle button
|
||||
* @param {Element} el Button to be toggled
|
||||
* @void
|
||||
*/
|
||||
export function btn(el) {
|
||||
const toggle = _ => dom.body.classList.toggle('close')
|
||||
|
||||
el = dom.getNode(el)
|
||||
if (el == null) {
|
||||
if (el === null || el === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
dom.on(el, 'click', e => {
|
||||
e.stopPropagation()
|
||||
toggle()
|
||||
@ -27,10 +30,11 @@ export function btn(el) {
|
||||
|
||||
export function collapse(el) {
|
||||
el = dom.getNode(el)
|
||||
if (el == null) {
|
||||
if (el === null || el === undefined) {
|
||||
return
|
||||
}
|
||||
dom.on(el, 'click', ({target}) => {
|
||||
|
||||
dom.on(el, 'click', ({ target }) => {
|
||||
if (
|
||||
target.nodeName === 'A' &&
|
||||
target.nextSibling &&
|
||||
@ -46,6 +50,7 @@ export function sticky() {
|
||||
if (!cover) {
|
||||
return
|
||||
}
|
||||
|
||||
const coverHeight = cover.getBoundingClientRect().height
|
||||
|
||||
if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) {
|
||||
@ -57,18 +62,19 @@ export function sticky() {
|
||||
|
||||
/**
|
||||
* Get and active link
|
||||
* @param {object} router
|
||||
* @param {string|element} el
|
||||
* @param {Boolean} isParent acitve parent
|
||||
* @param {Boolean} autoTitle auto set title
|
||||
* @return {element}
|
||||
* @param {Object} router Router
|
||||
* @param {String|Element} el Target element
|
||||
* @param {Boolean} isParent Active parent
|
||||
* @param {Boolean} autoTitle Automatically set title
|
||||
* @return {Element} Active element
|
||||
*/
|
||||
export function getAndActive(router, el, isParent, autoTitle) {
|
||||
el = dom.getNode(el)
|
||||
let links = []
|
||||
if (el != null) {
|
||||
if (el !== null && el !== undefined) {
|
||||
links = dom.findAll(el, 'a')
|
||||
}
|
||||
|
||||
const hash = decodeURI(router.toURL(router.getCurrentPath()))
|
||||
let target
|
||||
|
||||
|
@ -1,23 +1,25 @@
|
||||
import progressbar from '../render/progressbar'
|
||||
import {noop, hasOwn} from '../util/core'
|
||||
import { noop, hasOwn } from '../util/core'
|
||||
|
||||
const cache = {}
|
||||
|
||||
/**
|
||||
* Simple ajax get
|
||||
* @param {string} url
|
||||
* @param {boolean} [hasBar=false] has progress bar
|
||||
* @return { then(resolve, reject), abort }
|
||||
* Ajax GET implmentation
|
||||
* @param {string} url Resource URL
|
||||
* @param {boolean} [hasBar=false] Has progress bar
|
||||
* @param {String[]} headers Array of headers
|
||||
* @return {Promise} Promise response
|
||||
*/
|
||||
export function get(url, hasBar = false, headers = {}) {
|
||||
const xhr = new XMLHttpRequest()
|
||||
const on = function () {
|
||||
xhr.addEventListener.apply(xhr, arguments)
|
||||
}
|
||||
|
||||
const cached = cache[url]
|
||||
|
||||
if (cached) {
|
||||
return {then: cb => cb(cached.content, cached.opt), abort: noop}
|
||||
return { then: cb => cb(cached.content, cached.opt), abort: noop }
|
||||
}
|
||||
|
||||
xhr.open('GET', url)
|
||||
@ -26,6 +28,7 @@ export function get(url, hasBar = false, headers = {}) {
|
||||
xhr.setRequestHeader(i, headers[i])
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send()
|
||||
|
||||
return {
|
||||
@ -47,7 +50,7 @@ export function get(url, hasBar = false, headers = {}) {
|
||||
}
|
||||
|
||||
on('error', error)
|
||||
on('load', ({target}) => {
|
||||
on('load', ({ target }) => {
|
||||
if (target.status >= 400) {
|
||||
error(target)
|
||||
} else {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {get} from './ajax'
|
||||
import {callHook} from '../init/lifecycle'
|
||||
import {getParentPath, stringifyQuery} from '../router/util'
|
||||
import {noop} from '../util/core'
|
||||
import {getAndActive} from '../event/sidebar'
|
||||
import { get } from './ajax'
|
||||
import { callHook } from '../init/lifecycle'
|
||||
import { getParentPath, stringifyQuery } from '../router/util'
|
||||
import { noop } from '../util/core'
|
||||
import { getAndActive } from '../event/sidebar'
|
||||
|
||||
function loadNested(path, qs, file, next, vm, first) {
|
||||
path = first ? path : path.replace(/\/$/, '')
|
||||
@ -30,7 +30,7 @@ export function fetchMixin(proto) {
|
||||
}
|
||||
|
||||
const get404Path = (path, config) => {
|
||||
const {notFoundPage, ext} = config
|
||||
const { notFoundPage, ext } = config
|
||||
const defaultPath = '_404' + (ext || '.md')
|
||||
let key
|
||||
let path404
|
||||
@ -75,9 +75,9 @@ export function fetchMixin(proto) {
|
||||
}
|
||||
|
||||
proto._fetch = function (cb = noop) {
|
||||
const {path, query} = this.route
|
||||
const { path, query } = this.route
|
||||
const qs = stringifyQuery(query, ['id'])
|
||||
const {loadNavbar, requestHeaders, loadSidebar} = this.config
|
||||
const { loadNavbar, requestHeaders, loadSidebar } = this.config
|
||||
// Abort last request
|
||||
|
||||
const file = this.router.getFile(path)
|
||||
@ -112,7 +112,7 @@ export function fetchMixin(proto) {
|
||||
}
|
||||
|
||||
proto._fetchCover = function () {
|
||||
const {coverpage, requestHeaders} = this.config
|
||||
const { coverpage, requestHeaders } = this.config
|
||||
const query = this.route.query
|
||||
const root = getParentPath(this.route.path)
|
||||
|
||||
@ -140,6 +140,7 @@ export function fetchMixin(proto) {
|
||||
} else {
|
||||
this._renderCover(null, coverOnly)
|
||||
}
|
||||
|
||||
return coverOnly
|
||||
}
|
||||
}
|
||||
@ -163,7 +164,7 @@ export function fetchMixin(proto) {
|
||||
}
|
||||
|
||||
proto._fetchFallbackPage = function (path, qs, cb = noop) {
|
||||
const {requestHeaders, fallbackLanguages, loadSidebar} = this.config
|
||||
const { requestHeaders, fallbackLanguages, loadSidebar } = this.config
|
||||
|
||||
if (!fallbackLanguages) {
|
||||
return false
|
||||
@ -174,6 +175,7 @@ export function fetchMixin(proto) {
|
||||
if (fallbackLanguages.indexOf(local) === -1) {
|
||||
return false
|
||||
}
|
||||
|
||||
const newPath = path.replace(new RegExp(`^/${local}`), '')
|
||||
const req = request(newPath + qs, true, requestHeaders)
|
||||
|
||||
@ -189,16 +191,17 @@ export function fetchMixin(proto) {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the 404 page
|
||||
* @param path
|
||||
* @param qs
|
||||
* @param cb
|
||||
* @returns {*}
|
||||
* @param {String} path URL to be loaded
|
||||
* @param {*} qs TODO: define
|
||||
* @param {Function} cb Callback
|
||||
* @returns {Boolean} True if the requested page is not found
|
||||
* @private
|
||||
*/
|
||||
proto._fetch404 = function (path, qs, cb = noop) {
|
||||
const {loadSidebar, requestHeaders, notFoundPage} = this.config
|
||||
const { loadSidebar, requestHeaders, notFoundPage } = this.config
|
||||
|
||||
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb)
|
||||
if (notFoundPage) {
|
||||
@ -217,7 +220,7 @@ export function fetchMixin(proto) {
|
||||
}
|
||||
|
||||
export function initFetch(vm) {
|
||||
const {loadSidebar} = vm.config
|
||||
const { loadSidebar } = vm.config
|
||||
|
||||
// Server-Side Rendering
|
||||
if (vm.rendered) {
|
||||
@ -225,6 +228,7 @@ export function initFetch(vm) {
|
||||
if (loadSidebar && activeEl) {
|
||||
activeEl.parentNode.innerHTML += window.__SUB_SIDEBAR__
|
||||
}
|
||||
|
||||
vm._bindEventOnRendered(activeEl)
|
||||
vm.$resetEvents()
|
||||
callHook(vm, 'doneEach')
|
||||
|
@ -1,12 +1,15 @@
|
||||
import {initMixin} from './init'
|
||||
import {routerMixin} from './router'
|
||||
import {renderMixin} from './render'
|
||||
import {fetchMixin} from './fetch'
|
||||
import {eventMixin} from './event'
|
||||
import { initMixin } from './init'
|
||||
import { routerMixin } from './router'
|
||||
import { renderMixin } from './render'
|
||||
import { fetchMixin } from './fetch'
|
||||
import { eventMixin } from './event'
|
||||
import initGlobalAPI from './global-api'
|
||||
|
||||
/**
|
||||
* Fork https://github.com/bendrucker/document-ready/blob/master/index.js
|
||||
* @param {Function} callback The callbacack to be called when the page is loaded
|
||||
* @returns {Number|void} If the page is already laoded returns the result of the setTimeout callback,
|
||||
* otherwise it only attaches the callback to the DOMContentLoaded event
|
||||
*/
|
||||
function ready(callback) {
|
||||
const state = document.readyState
|
||||
|
@ -1,11 +1,11 @@
|
||||
import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import {helper as helperTpl, tree as treeTpl} from './tpl'
|
||||
import {genTree} from './gen-tree'
|
||||
import {slugify} from './slugify'
|
||||
import {emojify} from './emojify'
|
||||
import {isAbsolutePath, getPath, getParentPath} from '../router/util'
|
||||
import {isFn, merge, cached, isPrimitive} from '../util/core'
|
||||
import { helper as helperTpl, tree as treeTpl } from './tpl'
|
||||
import { genTree } from './gen-tree'
|
||||
import { slugify } from './slugify'
|
||||
import { emojify } from './emojify'
|
||||
import { isAbsolutePath, getPath, getParentPath } from '../router/util'
|
||||
import { isFn, merge, cached, isPrimitive } from '../util/core'
|
||||
|
||||
// See https://github.com/PrismJS/prism/pull/1367
|
||||
import 'prismjs/components/prism-markup-templating'
|
||||
@ -26,7 +26,7 @@ export function getAndRemoveConfig(str = '') {
|
||||
.trim()
|
||||
}
|
||||
|
||||
return {str, config}
|
||||
return { str, config }
|
||||
}
|
||||
|
||||
const compileMedia = {
|
||||
@ -132,7 +132,7 @@ export class Compiler {
|
||||
}
|
||||
|
||||
compileEmbed(href, title) {
|
||||
const {str, config} = getAndRemoveConfig(title)
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
let embed
|
||||
title = str
|
||||
|
||||
@ -162,9 +162,11 @@ export class Compiler {
|
||||
} else if (/\.mp3/.test(href)) {
|
||||
type = 'audio'
|
||||
}
|
||||
|
||||
embed = compileMedia[type].call(this, href, title)
|
||||
embed.type = type
|
||||
}
|
||||
|
||||
embed.fragment = config.fragment
|
||||
|
||||
return embed
|
||||
@ -186,17 +188,20 @@ export class Compiler {
|
||||
|
||||
_initRenderer() {
|
||||
const renderer = new marked.Renderer()
|
||||
const {linkTarget, linkRel, router, contentBase} = this
|
||||
const { linkTarget, linkRel, router, contentBase } = this
|
||||
const _self = this
|
||||
const origin = {}
|
||||
|
||||
/**
|
||||
* Render anchor tag
|
||||
* @link https://github.com/markedjs/marked#overriding-renderer-methods
|
||||
* @param {String} text Text content
|
||||
* @param {Number} level Type of heading (h<level> tag)
|
||||
* @returns {String} Heading element
|
||||
*/
|
||||
origin.heading = renderer.heading = function (text, level) {
|
||||
let {str, config} = getAndRemoveConfig(text)
|
||||
const nextToc = {level, title: str}
|
||||
let { str, config } = getAndRemoveConfig(text)
|
||||
const nextToc = { level, title: str }
|
||||
|
||||
if (/{docsify-ignore}/g.test(str)) {
|
||||
str = str.replace('{docsify-ignore}', '')
|
||||
@ -211,12 +216,13 @@ export class Compiler {
|
||||
}
|
||||
|
||||
const slug = slugify(config.id || str)
|
||||
const url = router.toURL(router.getCurrentPath(), {id: slug})
|
||||
const url = router.toURL(router.getCurrentPath(), { id: slug })
|
||||
nextToc.slug = url
|
||||
_self.toc.push(nextToc)
|
||||
|
||||
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${str}</span></a></h${level}>`
|
||||
}
|
||||
|
||||
// Highlight code
|
||||
origin.code = renderer.code = function (code, lang = '') {
|
||||
code = code.replace(/@DOCSIFY_QM@/g, '`')
|
||||
@ -227,10 +233,11 @@ export class Compiler {
|
||||
|
||||
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${hl}</code></pre>`
|
||||
}
|
||||
|
||||
origin.link = renderer.link = function (href, title = '', text) {
|
||||
let attrs = ''
|
||||
|
||||
const {str, config} = getAndRemoveConfig(title)
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
title = str
|
||||
|
||||
if (
|
||||
@ -241,6 +248,7 @@ export class Compiler {
|
||||
if (href === _self.config.homepage) {
|
||||
href = 'README'
|
||||
}
|
||||
|
||||
href = router.toURL(href, null, router.getCurrentPath())
|
||||
} else {
|
||||
attrs += href.indexOf('mailto:') === 0 ? '' : ` target="${linkTarget}"`
|
||||
@ -262,6 +270,7 @@ export class Compiler {
|
||||
|
||||
return `<a href="${href}"${attrs}>${text}</a>`
|
||||
}
|
||||
|
||||
origin.paragraph = renderer.paragraph = function (text) {
|
||||
let result
|
||||
if (/^!>/.test(text)) {
|
||||
@ -271,13 +280,15 @@ export class Compiler {
|
||||
} else {
|
||||
result = `<p>${text}</p>`
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
origin.image = renderer.image = function (href, title, text) {
|
||||
let url = href
|
||||
let attrs = ''
|
||||
|
||||
const {str, config} = getAndRemoveConfig(title)
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
title = str
|
||||
|
||||
if (config['no-zoom']) {
|
||||
@ -304,6 +315,7 @@ export class Compiler {
|
||||
|
||||
return `<img src="${url}"data-origin="${href}" alt="${text}"${attrs}>`
|
||||
}
|
||||
|
||||
origin.list = renderer.list = function (body, ordered, start) {
|
||||
const isTaskList = /<li class="task-list-item">/.test(body.split('class="task-list"')[0])
|
||||
const isStartReq = start && start > 1
|
||||
@ -315,6 +327,7 @@ export class Compiler {
|
||||
|
||||
return `<${tag} ${tagAttrs}>${body}</${tag}>`
|
||||
}
|
||||
|
||||
origin.listitem = renderer.listitem = function (text) {
|
||||
const isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text)
|
||||
const html = isTaskItem ? `<li class="task-list-item"><label>${text}</label></li>` : `<li>${text}</li>`
|
||||
@ -329,9 +342,12 @@ export class Compiler {
|
||||
|
||||
/**
|
||||
* Compile sidebar
|
||||
* @param {String} text Text content
|
||||
* @param {Number} level Type of heading (h<level> tag)
|
||||
* @returns {String} Sidebar element
|
||||
*/
|
||||
sidebar(text, level) {
|
||||
const {toc} = this
|
||||
const { toc } = this
|
||||
const currentPath = this.router.getCurrentPath()
|
||||
let html = ''
|
||||
|
||||
@ -346,9 +362,11 @@ export class Compiler {
|
||||
for (let j = i; deletedHeaderLevel < toc[j].level && j < toc.length; j++) {
|
||||
toc.splice(j, 1) && j-- && i++
|
||||
}
|
||||
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
const tree = this.cacheTree[currentPath] || genTree(toc, level)
|
||||
html = treeTpl(tree, '<ul>{inner}</ul>')
|
||||
this.cacheTree[currentPath] = tree
|
||||
@ -359,14 +377,17 @@ export class Compiler {
|
||||
|
||||
/**
|
||||
* Compile sub sidebar
|
||||
* @param {Number} level Type of heading (h<level> tag)
|
||||
* @returns {String} Sub-sidebar element
|
||||
*/
|
||||
subSidebar(level) {
|
||||
if (!level) {
|
||||
this.toc = []
|
||||
return
|
||||
}
|
||||
|
||||
const currentPath = this.router.getCurrentPath()
|
||||
const {cacheTree, toc} = this
|
||||
const { cacheTree, toc } = this
|
||||
|
||||
toc[0] && toc[0].ignoreAllSubs && toc.splice(0)
|
||||
toc[0] && toc[0].level === 1 && toc.shift()
|
||||
@ -374,6 +395,7 @@ export class Compiler {
|
||||
for (let i = 0; i < toc.length; i++) {
|
||||
toc[i].ignoreSubHeading && toc.splice(i, 1) && i--
|
||||
}
|
||||
|
||||
const tree = cacheTree[currentPath] || genTree(toc, level)
|
||||
|
||||
cacheTree[currentPath] = tree
|
||||
@ -387,6 +409,8 @@ export class Compiler {
|
||||
|
||||
/**
|
||||
* Compile cover page
|
||||
* @param {Text} text Text content
|
||||
* @returns {String} Cover page
|
||||
*/
|
||||
cover(text) {
|
||||
const cacheToc = this.toc.slice()
|
||||
|
@ -1,9 +1,9 @@
|
||||
import {get} from '../fetch/ajax'
|
||||
import {merge} from '../util/core'
|
||||
import { get } from '../fetch/ajax'
|
||||
import { merge } from '../util/core'
|
||||
|
||||
const cached = {}
|
||||
|
||||
function walkFetchEmbed({embedTokens, compile, fetch}, cb) {
|
||||
function walkFetchEmbed({ embedTokens, compile, fetch }, cb) {
|
||||
let token
|
||||
let step = 0
|
||||
let count = 1
|
||||
@ -23,26 +23,28 @@ function walkFetchEmbed({embedTokens, compile, fetch}, cb) {
|
||||
if (token.embed.fragment) {
|
||||
const fragment = token.embed.fragment
|
||||
const pattern = new RegExp(`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`)
|
||||
text = ((text.match(pattern) || [])[1] || '').trim()
|
||||
text = ((text.match(pattern) || [])[1] || '').trim()
|
||||
}
|
||||
|
||||
embedToken = compile.lexer(
|
||||
'```' +
|
||||
token.embed.lang +
|
||||
'\n' +
|
||||
text.replace(/`/g, '@DOCSIFY_QM@') +
|
||||
'\n```\n'
|
||||
token.embed.lang +
|
||||
'\n' +
|
||||
text.replace(/`/g, '@DOCSIFY_QM@') +
|
||||
'\n```\n'
|
||||
)
|
||||
} else if (token.embed.type === 'mermaid') {
|
||||
embedToken = [
|
||||
{type: 'html', text: `<div class="mermaid">\n${text}\n</div>`}
|
||||
{ type: 'html', text: `<div class="mermaid">\n${text}\n</div>` }
|
||||
]
|
||||
embedToken.links = {}
|
||||
} else {
|
||||
embedToken = [{type: 'html', text}]
|
||||
embedToken = [{ type: 'html', text }]
|
||||
embedToken.links = {}
|
||||
}
|
||||
}
|
||||
cb({token, embedToken})
|
||||
|
||||
cb({ token, embedToken })
|
||||
if (++count >= step) {
|
||||
cb({})
|
||||
}
|
||||
@ -61,7 +63,7 @@ function walkFetchEmbed({embedTokens, compile, fetch}, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
export function prerenderEmbed({compiler, raw = '', fetch}, done) {
|
||||
export function prerenderEmbed({ compiler, raw = '', fetch }, done) {
|
||||
let hit = cached[raw]
|
||||
if (hit) {
|
||||
const copy = hit.slice()
|
||||
@ -96,7 +98,7 @@ export function prerenderEmbed({compiler, raw = '', fetch}, done) {
|
||||
})
|
||||
|
||||
let moveIndex = 0
|
||||
walkFetchEmbed({compile, embedTokens, fetch}, ({embedToken, token}) => {
|
||||
walkFetchEmbed({ compile, embedTokens, fetch }, ({ embedToken, token }) => {
|
||||
if (token) {
|
||||
const index = token.index + moveIndex
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Gen toc tree
|
||||
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
|
||||
* @param {Array} toc
|
||||
* @param {Number} maxLevel
|
||||
* @return {Array}
|
||||
* @param {Array} toc List of TOC elements
|
||||
* @param {Number} maxLevel Deep level
|
||||
* @return {Array} Headlines
|
||||
*/
|
||||
export function genTree(toc, maxLevel) {
|
||||
const headlines = []
|
||||
@ -16,11 +16,13 @@ export function genTree(toc, maxLevel) {
|
||||
if (level > maxLevel) {
|
||||
return
|
||||
}
|
||||
|
||||
if (last[len]) {
|
||||
last[len].children = (last[len].children || []).concat(headline)
|
||||
} else {
|
||||
headlines.push(headline)
|
||||
}
|
||||
|
||||
last[level] = headline
|
||||
})
|
||||
|
||||
|
@ -18,6 +18,7 @@ function executeScript() {
|
||||
if (!script) {
|
||||
return false
|
||||
}
|
||||
|
||||
const code = script.innerText.trim()
|
||||
if (!code) {
|
||||
return false
|
||||
@ -102,6 +103,7 @@ export function renderMixin(proto) {
|
||||
// Reset toc
|
||||
this.compiler.subSidebar()
|
||||
}
|
||||
|
||||
// Bind event
|
||||
this._bindEventOnRendered(activeEl)
|
||||
}
|
||||
@ -145,6 +147,7 @@ export function renderMixin(proto) {
|
||||
|
||||
callHook(this, 'afterEach', html, text => renderMain.call(this, text))
|
||||
}
|
||||
|
||||
if (this.isHTML) {
|
||||
html = this.result = text
|
||||
callback()
|
||||
@ -173,6 +176,7 @@ export function renderMixin(proto) {
|
||||
dom.toggleClass(el, 'remove', 'show')
|
||||
return
|
||||
}
|
||||
|
||||
dom.toggleClass(el, 'add', 'show')
|
||||
|
||||
let html = this.coverIsHTML ? text : this.compiler.cover(text)
|
||||
@ -191,10 +195,12 @@ export function renderMixin(proto) {
|
||||
if (!isAbsolutePath(m[1])) {
|
||||
path = getPath(this.router.getBasePath(), m[1])
|
||||
}
|
||||
|
||||
el.style.backgroundImage = `url(${path})`
|
||||
el.style.backgroundSize = 'cover'
|
||||
el.style.backgroundPosition = 'center center'
|
||||
}
|
||||
|
||||
html = html.replace(m[0], '')
|
||||
}
|
||||
|
||||
@ -228,6 +234,7 @@ export function initRender(vm) {
|
||||
if (config.repo) {
|
||||
html += tpl.corner(config.repo, config.cornerExternalLinkTarge)
|
||||
}
|
||||
|
||||
if (config.coverpage) {
|
||||
html += tpl.cover()
|
||||
}
|
||||
@ -271,6 +278,7 @@ export function initRender(vm) {
|
||||
// Polyfll
|
||||
cssVars(config.themeColor)
|
||||
}
|
||||
|
||||
vm._updateRender()
|
||||
dom.toggleClass(dom.body, 'ready')
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ function init() {
|
||||
dom.appendTo(dom.body, div)
|
||||
barEl = div
|
||||
}
|
||||
|
||||
/**
|
||||
* Render progress bar
|
||||
*/
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { isMobile } from '../util/env'
|
||||
/**
|
||||
* Render github corner
|
||||
* @param {Object} data
|
||||
* @return {String}
|
||||
* @param {Object} data URL for the View Source on Github link
|
||||
* @param {String} cornerExternalLinkTarge value of the target attribute of the link
|
||||
* @return {String} SVG element as string
|
||||
*/
|
||||
export function corner(data, cornerExternalLinkTarge) {
|
||||
if (!data) {
|
||||
@ -29,7 +30,9 @@ export function corner(data, cornerExternalLinkTarge) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render main content
|
||||
* Renders main content
|
||||
* @param {Object} config Configuration object
|
||||
* @returns {String} HTML of the main content
|
||||
*/
|
||||
export function main(config) {
|
||||
const name = config.name ? config.name : ''
|
||||
@ -41,11 +44,11 @@ export function main(config) {
|
||||
'</div>' +
|
||||
'</button>' +
|
||||
'<aside class="sidebar">' +
|
||||
(config.name
|
||||
? `<h1 class="app-name"><a class="app-name-link" data-nosearch>${
|
||||
config.logo ? `<img alt="${name}" src=${config.logo}>` : name
|
||||
}</a></h1>`
|
||||
: '') +
|
||||
(config.name ?
|
||||
`<h1 class="app-name"><a class="app-name-link" data-nosearch>${
|
||||
config.logo ? `<img alt="${name}" src=${config.logo}>` : name
|
||||
}</a></h1>` :
|
||||
'') +
|
||||
'<div class="sidebar-nav"><!--sidebar--></div>' +
|
||||
'</aside>'
|
||||
|
||||
@ -60,6 +63,7 @@ export function main(config) {
|
||||
|
||||
/**
|
||||
* Cover Page
|
||||
* @returns {String} Cover page
|
||||
*/
|
||||
export function cover() {
|
||||
const SL = ', 100%, 85%'
|
||||
@ -78,9 +82,9 @@ export function cover() {
|
||||
|
||||
/**
|
||||
* Render tree
|
||||
* @param {Array} tree
|
||||
* @param {String} tpl
|
||||
* @return {String}
|
||||
* @param {Array} toc Array of TOC section links
|
||||
* @param {String} tpl TPL list
|
||||
* @return {String} Rendered tree
|
||||
*/
|
||||
export function tree(toc, tpl = '<ul class="app-sub-sidebar">{inner}</ul>') {
|
||||
if (!toc || !toc.length) {
|
||||
|
@ -81,6 +81,7 @@ export class History {
|
||||
const currentDir = currentRoute.substring(0, currentRoute.lastIndexOf('/') + 1)
|
||||
return cleanPath(resolvePath(currentDir + path))
|
||||
}
|
||||
|
||||
return cleanPath('/' + path)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {History} from './base'
|
||||
import {noop} from '../../util/core'
|
||||
import {on} from '../../util/dom'
|
||||
import {parseQuery, cleanPath, replaceSlug} from '../util'
|
||||
import { History } from './base'
|
||||
import { noop } from '../../util/core'
|
||||
import { on } from '../../util/dom'
|
||||
import { parseQuery, cleanPath, replaceSlug } from '../util'
|
||||
|
||||
function replaceHash(path) {
|
||||
const i = location.href.indexOf('#')
|
||||
@ -41,12 +41,13 @@ export class HashHistory extends History {
|
||||
if (path.charAt(0) === '/') {
|
||||
return replaceHash(path)
|
||||
}
|
||||
|
||||
replaceHash('/' + path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the url
|
||||
* @param {string} [path=location.herf]
|
||||
* @param {string} [path=location.herf] URL to be parsed
|
||||
* @return {object} { path, query }
|
||||
*/
|
||||
parse(path = location.href) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {History} from './base'
|
||||
import {noop} from '../../util/core'
|
||||
import {on} from '../../util/dom'
|
||||
import {parseQuery, getPath} from '../util'
|
||||
import { History } from './base'
|
||||
import { noop } from '../../util/core'
|
||||
import { on } from '../../util/dom'
|
||||
import { parseQuery, getPath } from '../util'
|
||||
|
||||
export class HTML5History extends History {
|
||||
constructor(config) {
|
||||
@ -27,7 +27,7 @@ export class HTML5History extends History {
|
||||
if (el.tagName === 'A' && !/_blank/.test(el.target)) {
|
||||
e.preventDefault()
|
||||
const url = el.href
|
||||
window.history.pushState({key: url}, '', url)
|
||||
window.history.pushState({ key: url }, '', url)
|
||||
cb()
|
||||
}
|
||||
})
|
||||
@ -37,7 +37,7 @@ export class HTML5History extends History {
|
||||
|
||||
/**
|
||||
* Parse the url
|
||||
* @param {string} [path=location.href]
|
||||
* @param {string} [path=location.href] URL to be parsed
|
||||
* @return {object} { path, query }
|
||||
*/
|
||||
parse(path = location.href) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {cached} from '../util/core'
|
||||
import { cached } from '../util/core'
|
||||
|
||||
const decode = decodeURIComponent
|
||||
const encode = encodeURIComponent
|
||||
@ -29,6 +29,7 @@ export function stringifyQuery(obj, ignores = []) {
|
||||
if (ignores.indexOf(key) > -1) {
|
||||
continue
|
||||
}
|
||||
|
||||
qs.push(
|
||||
obj[key] ?
|
||||
`${encode(key)}=${encode(obj[key])}`.toLowerCase() :
|
||||
@ -44,9 +45,12 @@ export const isAbsolutePath = cached(path => {
|
||||
})
|
||||
|
||||
export const getParentPath = cached(path => {
|
||||
return /\/$/g.test(path) ?
|
||||
path :
|
||||
(path = path.match(/(\S*\/)[^/]+$/)) ? path[1] : ''
|
||||
if (/\/$/g.test(path)) {
|
||||
return path
|
||||
}
|
||||
|
||||
const matchingParts = path.match(/(\S*\/)[^/]+$/)
|
||||
return matchingParts ? matchingParts[1] : ''
|
||||
})
|
||||
|
||||
export const cleanPath = cached(path => {
|
||||
@ -64,6 +68,7 @@ export const resolvePath = cached(path => {
|
||||
resolved.push(segment)
|
||||
}
|
||||
}
|
||||
|
||||
return '/' + resolved.join('/')
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Create a cached version of a pure function.
|
||||
* @param {*} fn The function call to be cached
|
||||
* @void
|
||||
*/
|
||||
|
||||
export function cached(fn) {
|
||||
const cache = Object.create(null)
|
||||
return function (str) {
|
||||
@ -21,6 +24,8 @@ export const hasOwn = Object.prototype.hasOwnProperty
|
||||
|
||||
/**
|
||||
* Simple Object.assign polyfill
|
||||
* @param {Object} to The object to be merged with
|
||||
* @returns {Object} The merged object
|
||||
*/
|
||||
export const merge =
|
||||
Object.assign ||
|
||||
@ -40,18 +45,23 @@ export const merge =
|
||||
|
||||
/**
|
||||
* Check if value is primitive
|
||||
* @param {*} value Checks if a value is primitive
|
||||
* @returns {Boolean} Result of the check
|
||||
*/
|
||||
export function isPrimitive(value) {
|
||||
return typeof value === 'string' || typeof value === 'number'
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform no operation.
|
||||
* Performs no operation.
|
||||
* @void
|
||||
*/
|
||||
export function noop() {}
|
||||
export function noop() { }
|
||||
|
||||
/**
|
||||
* Check if value is function
|
||||
* @param {*} obj Any javascript object
|
||||
* @returns {Boolean} True if the passed-in value is a function
|
||||
*/
|
||||
export function isFn(obj) {
|
||||
return typeof obj === 'function'
|
||||
|
@ -1,19 +1,20 @@
|
||||
import {isFn} from '../util/core'
|
||||
import {inBrowser} from './env'
|
||||
import { isFn } from '../util/core'
|
||||
import { inBrowser } from './env'
|
||||
|
||||
const cacheNode = {}
|
||||
|
||||
/**
|
||||
* Get Node
|
||||
* @param {String|Element} el
|
||||
* @param {Boolean} noCache
|
||||
* @return {Element}
|
||||
* @param {String|Element} el A DOM element
|
||||
* @param {Boolean} noCache Flag to use or not use the cache
|
||||
* @return {Element} The found node element
|
||||
*/
|
||||
export function getNode(el, noCache = false) {
|
||||
if (typeof el === 'string') {
|
||||
if (typeof window.Vue !== 'undefined') {
|
||||
return find(el)
|
||||
}
|
||||
|
||||
el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el))
|
||||
}
|
||||
|
||||
@ -27,7 +28,10 @@ export const body = inBrowser && $.body
|
||||
export const head = inBrowser && $.head
|
||||
|
||||
/**
|
||||
* Find element
|
||||
* Find elements
|
||||
* @param {String|Element} el The root element where to perform the search from
|
||||
* @param {Element} node The query
|
||||
* @returns {Element} The found DOM element
|
||||
* @example
|
||||
* find('nav') => document.querySelector('nav')
|
||||
* find(nav, 'a') => nav.querySelector('a')
|
||||
@ -38,6 +42,9 @@ export function find(el, node) {
|
||||
|
||||
/**
|
||||
* Find all elements
|
||||
* @param {String|Element} el The root element where to perform the search from
|
||||
* @param {Element} node The query
|
||||
* @returns {Array<Element>} An array of DOM elements
|
||||
* @example
|
||||
* findAll('a') => [].slice.call(document.querySelectorAll('a'))
|
||||
* findAll(nav, 'a') => [].slice.call(nav.querySelectorAll('a'))
|
||||
@ -53,6 +60,7 @@ export function create(node, tpl) {
|
||||
if (tpl) {
|
||||
node.innerHTML = tpl
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
@ -78,7 +86,10 @@ export function off(el, type, handler) {
|
||||
|
||||
/**
|
||||
* Toggle class
|
||||
*
|
||||
* @param {String|Element} el The element that needs the class to be toggled
|
||||
* @param {Element} type The type of action to be performed on the classList (toggle by default)
|
||||
* @param {String} val Name of the class to be toggled
|
||||
* @void
|
||||
* @example
|
||||
* toggleClass(el, 'active') => el.classList.toggle('active')
|
||||
* toggleClass(el, 'add', 'active') => el.classList.add('active')
|
||||
|
@ -13,6 +13,7 @@ function init(id) {
|
||||
function () {
|
||||
(window.ga.q = window.ga.q || []).push(arguments)
|
||||
}
|
||||
|
||||
window.ga.l = Number(new Date())
|
||||
window.ga('create', id, 'auto')
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ function init(options) {
|
||||
window._paq = window._paq || []
|
||||
window._paq.push(['trackPageView'])
|
||||
window._paq.push(['enableLinkTracking'])
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
appendScript(options)
|
||||
window._paq.push(['setTrackerUrl', options.host + '/matomo.php'])
|
||||
window._paq.push(['setSiteId', options.id + ''])
|
||||
window._paq.push(['setSiteId', String(options.id)])
|
||||
}, 0)
|
||||
}
|
||||
|
||||
@ -20,7 +20,8 @@ function collect() {
|
||||
if (!window._paq) {
|
||||
init($docsify.matomo)
|
||||
}
|
||||
window._paq.push(['setCustomUrl', window.location.hash.substr(1)])
|
||||
|
||||
window._paq.push(['setCustomUrl', window.location.hash.substr(1)])
|
||||
window._paq.push(['setDocumentTitle', document.title])
|
||||
window._paq.push(['trackPageView'])
|
||||
}
|
||||
|
@ -139,8 +139,10 @@ function doSearch(value) {
|
||||
$sidebarNav.classList.remove('hide')
|
||||
$appName.classList.remove('hide')
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const matchs = search(value)
|
||||
|
||||
let html = ''
|
||||
@ -193,6 +195,7 @@ function updatePlaceholder(text, path) {
|
||||
if (!$input) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof text === 'string') {
|
||||
$input.placeholder = text
|
||||
} else {
|
||||
|
@ -8,6 +8,7 @@ const LOCAL_STORAGE = {
|
||||
function resolveExpireKey(namespace) {
|
||||
return namespace ? `${LOCAL_STORAGE.EXPIRE_KEY}/${namespace}` : LOCAL_STORAGE.EXPIRE_KEY
|
||||
}
|
||||
|
||||
function resolveIndexKey(namespace) {
|
||||
return namespace ? `${LOCAL_STORAGE.INDEX_KEY}/${namespace}` : LOCAL_STORAGE.INDEX_KEY
|
||||
}
|
||||
@ -58,14 +59,15 @@ export function genIndex(path, content = '', router, depth) {
|
||||
|
||||
tokens.forEach(token => {
|
||||
if (token.type === 'heading' && token.depth <= depth) {
|
||||
slug = router.toURL(path, {id: slugify(token.text)})
|
||||
index[slug] = {slug, title: token.text, body: ''}
|
||||
slug = router.toURL(path, { id: slugify(token.text) })
|
||||
index[slug] = { slug, title: token.text, body: '' }
|
||||
} else {
|
||||
if (!slug) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!index[slug]) {
|
||||
index[slug] = {slug, title: '', body: ''}
|
||||
index[slug] = { slug, title: '', body: '' }
|
||||
} else if (index[slug].body) {
|
||||
index[slug].body += '\n' + (token.text || '')
|
||||
} else {
|
||||
@ -78,8 +80,8 @@ export function genIndex(path, content = '', router, depth) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} query
|
||||
* @returns {Array}
|
||||
* @param {String} query Search query
|
||||
* @returns {Array} Array of results
|
||||
*/
|
||||
export function search(query) {
|
||||
const matchingResults = []
|
||||
@ -103,12 +105,12 @@ export function search(query) {
|
||||
const postUrl = post.slug || ''
|
||||
|
||||
if (postTitle) {
|
||||
keywords.forEach( keyword => {
|
||||
keywords.forEach(keyword => {
|
||||
// From https://github.com/sindresorhus/escape-string-regexp
|
||||
const regEx = new RegExp(
|
||||
keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
|
||||
'gi'
|
||||
);
|
||||
)
|
||||
let indexTitle = -1
|
||||
let indexContent = -1
|
||||
|
||||
@ -116,7 +118,7 @@ export function search(query) {
|
||||
indexContent = postContent ? postContent.search(regEx) : -1
|
||||
|
||||
if (indexTitle >= 0 || indexContent >= 0) {
|
||||
matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0;
|
||||
matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0
|
||||
if (indexContent < 0) {
|
||||
indexContent = 0
|
||||
}
|
||||
@ -155,7 +157,7 @@ export function search(query) {
|
||||
}
|
||||
}
|
||||
|
||||
return matchingResults.sort((r1, r2) => r2.score - r1.score);
|
||||
return matchingResults.sort((r1, r2) => r2.score - r1.score)
|
||||
}
|
||||
|
||||
export function init(config, vm) {
|
||||
|
115
test/_helper.js
115
test/_helper.js
@ -1,10 +1,10 @@
|
||||
// load ES6 modules in Node.js on the fly
|
||||
require = require('esm')(module/*, options*/)
|
||||
// Load ES6 modules in Node.js on the fly
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
|
||||
const path = require('path')
|
||||
const {expect} = require('chai')
|
||||
const { expect } = require('chai')
|
||||
|
||||
const {JSDOM} = require('jsdom')
|
||||
const { JSDOM } = require('jsdom')
|
||||
|
||||
function ready(callback) {
|
||||
const state = document.readyState
|
||||
@ -15,9 +15,10 @@ function ready(callback) {
|
||||
|
||||
document.addEventListener('DOMContentLoaded', callback)
|
||||
}
|
||||
module.exports.init = function(fixture = 'default', config = {}, markup) {
|
||||
if (markup == null) {
|
||||
markup = `<!DOCTYPE html>
|
||||
|
||||
module.exports.init = function (fixture = 'default', config = {}, markup = null) {
|
||||
if (markup === null || markup === undefined) {
|
||||
markup = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
@ -27,61 +28,63 @@ module.exports.init = function(fixture = 'default', config = {}, markup) {
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
}
|
||||
const rootPath = path.join(__dirname, 'fixtures', fixture)
|
||||
|
||||
const dom = new JSDOM(markup)
|
||||
dom.reconfigure({ url: 'file:///' + rootPath })
|
||||
}
|
||||
|
||||
global.window = dom.window
|
||||
global.document = dom.window.document
|
||||
global.navigator = dom.window.navigator
|
||||
global.location = dom.window.location
|
||||
global.XMLHttpRequest = dom.window.XMLHttpRequest
|
||||
const rootPath = path.join(__dirname, 'fixtures', fixture)
|
||||
|
||||
// mimic src/core/index.js but for Node.js
|
||||
function Docsify() {
|
||||
this._init()
|
||||
}
|
||||
const dom = new JSDOM(markup)
|
||||
dom.reconfigure({ url: 'file:///' + rootPath })
|
||||
|
||||
const proto = Docsify.prototype
|
||||
global.window = dom.window
|
||||
global.document = dom.window.document
|
||||
global.navigator = dom.window.navigator
|
||||
global.location = dom.window.location
|
||||
global.XMLHttpRequest = dom.window.XMLHttpRequest
|
||||
|
||||
const {initMixin} = require('../src/core/init')
|
||||
const {routerMixin} = require('../src/core//router')
|
||||
const {renderMixin} = require('../src/core//render')
|
||||
const {fetchMixin} = require('../src/core/fetch')
|
||||
const {eventMixin} = require('../src/core//event')
|
||||
// Mimic src/core/index.js but for Node.js
|
||||
function Docsify() {
|
||||
this._init()
|
||||
}
|
||||
|
||||
initMixin(proto)
|
||||
routerMixin(proto)
|
||||
renderMixin(proto)
|
||||
fetchMixin(proto)
|
||||
eventMixin(proto)
|
||||
const proto = Docsify.prototype
|
||||
|
||||
const NOT_INIT_PATTERN = '<!--main-->'
|
||||
const { initMixin } = require('../src/core/init')
|
||||
const { routerMixin } = require('../src/core//router')
|
||||
const { renderMixin } = require('../src/core//render')
|
||||
const { fetchMixin } = require('../src/core/fetch')
|
||||
const { eventMixin } = require('../src/core//event')
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ready(() => {
|
||||
const docsify = new Docsify()
|
||||
// NOTE: I was not able to get it working with a callback, but polling works usually at the first time
|
||||
const id = setInterval(() => {
|
||||
if (dom.window.document.body.innerHTML.indexOf(NOT_INIT_PATTERN) == -1) {
|
||||
clearInterval(id)
|
||||
return resolve({
|
||||
docsify: docsify,
|
||||
dom: dom
|
||||
})
|
||||
}
|
||||
}, 10)
|
||||
})
|
||||
|
||||
})
|
||||
initMixin(proto)
|
||||
routerMixin(proto)
|
||||
renderMixin(proto)
|
||||
fetchMixin(proto)
|
||||
eventMixin(proto)
|
||||
|
||||
const NOT_INIT_PATTERN = '<!--main-->'
|
||||
|
||||
return new Promise(resolve => {
|
||||
ready(() => {
|
||||
const docsify = new Docsify()
|
||||
// NOTE: I was not able to get it working with a callback, but polling works usually at the first time
|
||||
const id = setInterval(() => {
|
||||
if (dom.window.document.body.innerHTML.indexOf(NOT_INIT_PATTERN) === -1) {
|
||||
clearInterval(id)
|
||||
return resolve({
|
||||
docsify: docsify,
|
||||
dom: dom
|
||||
})
|
||||
}
|
||||
}, 10)
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports.expectSameDom = function(actual, expected) {
|
||||
const WHITESPACES_BETWEEN_TAGS = />(\s\s+)</g
|
||||
function replacer(match, group1) {
|
||||
return match.replace(group1, '')
|
||||
}
|
||||
expect(actual.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
.equal(expected.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
|
||||
module.exports.expectSameDom = function (actual, expected) {
|
||||
const WHITESPACES_BETWEEN_TAGS = />(\s\s+)</g
|
||||
function replacer(match, group1) {
|
||||
return match.replace(group1, '')
|
||||
}
|
||||
|
||||
expect(actual.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
.equal(expected.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
const path = require('path')
|
||||
|
||||
const {expect} = require('chai')
|
||||
|
||||
const {init, expectSameDom} = require('../_helper')
|
||||
|
||||
describe('full docsify initialization', function() {
|
||||
it('TODO: check generated markup', async function() {
|
||||
const {docsify, dom} = await init('simple', {loadSidebar: true})
|
||||
console.log(dom.window.document.body.innerHTML)
|
||||
// TODO: add some expectations
|
||||
})
|
||||
const { init } = require('../_helper')
|
||||
|
||||
describe('full docsify initialization', function () {
|
||||
it('TODO: check generated markup', async function () {
|
||||
const { dom } = await init('simple', { loadSidebar: true })
|
||||
console.log(dom.window.document.body.innerHTML)
|
||||
// TODO: add some expectations
|
||||
})
|
||||
})
|
||||
|
@ -1,14 +1,9 @@
|
||||
const path = require('path')
|
||||
|
||||
const {expect} = require('chai')
|
||||
|
||||
const {init, expectSameDom} = require('../_helper')
|
||||
|
||||
describe('router', function() {
|
||||
it('TODO: trigger to load another page', async function() {
|
||||
const {docsify} = await init()
|
||||
window.location = '/?foo=bar'
|
||||
// TODO: add some expectations
|
||||
})
|
||||
const { init } = require('../_helper')
|
||||
|
||||
describe('router', function () {
|
||||
it('TODO: trigger to load another page', async function () {
|
||||
await init()
|
||||
window.location = '/?foo=bar'
|
||||
// TODO: add some expectations
|
||||
})
|
||||
})
|
||||
|
@ -1,62 +1,61 @@
|
||||
/* eslint-env node, chai, mocha */
|
||||
require = require('esm')(module/*, options*/)
|
||||
const {expect} = require('chai')
|
||||
const {History} = require('../../src/core/router/history/base')
|
||||
|
||||
class MockHistory extends History {
|
||||
parse(path) {
|
||||
return {path}
|
||||
}
|
||||
}
|
||||
|
||||
describe('router/history/base', function () {
|
||||
describe('relativePath true', function () {
|
||||
var history
|
||||
|
||||
beforeEach(function () {
|
||||
history = new MockHistory({relativePath: true})
|
||||
})
|
||||
|
||||
it('toURL', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('guide.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/guide')
|
||||
})
|
||||
|
||||
it('toURL with double dot', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('../README.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
|
||||
it('toURL child path', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('config/example.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/config/example')
|
||||
})
|
||||
|
||||
it('toURL absolute path', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('/README', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
|
||||
it('toURL without relative path', function () {
|
||||
const history = new MockHistory({relativePath: false})
|
||||
|
||||
// WHEN
|
||||
const url = history.toURL('README', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
const { expect } = require('chai')
|
||||
const { History } = require('../../src/core/router/history/base')
|
||||
|
||||
class MockHistory extends History {
|
||||
parse(path) {
|
||||
return { path }
|
||||
}
|
||||
}
|
||||
|
||||
describe('router/history/base', function () {
|
||||
describe('relativePath true', function () {
|
||||
var history
|
||||
|
||||
beforeEach(function () {
|
||||
history = new MockHistory({ relativePath: true })
|
||||
})
|
||||
|
||||
it('toURL', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('guide.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/guide')
|
||||
})
|
||||
|
||||
it('toURL with double dot', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('../README.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
|
||||
it('toURL child path', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('config/example.md', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/config/example')
|
||||
})
|
||||
|
||||
it('toURL absolute path', function () {
|
||||
// WHEN
|
||||
const url = history.toURL('/README', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
|
||||
it('toURL without relative path', function () {
|
||||
const history = new MockHistory({ relativePath: false })
|
||||
|
||||
// WHEN
|
||||
const url = history.toURL('README', {}, '/zh-ch/')
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
|
@ -1,62 +1,60 @@
|
||||
const path = require('path')
|
||||
const { expect } = require('chai')
|
||||
|
||||
const {expect} = require('chai')
|
||||
const { init, expectSameDom } = require('../_helper')
|
||||
|
||||
const {init, expectSameDom} = require('../_helper')
|
||||
describe('render', function () {
|
||||
it('important content (tips)', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('!> **Time** is money, my friend!')
|
||||
expect(output).equal('<p class="tip"><strong>Time</strong> is money, my friend!</p>')
|
||||
})
|
||||
|
||||
describe('render', function() {
|
||||
it('important content (tips)', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile('!> **Time** is money, my friend!')
|
||||
expect(output).equal('<p class="tip"><strong>Time</strong> is money, my friend!</p>')
|
||||
})
|
||||
|
||||
describe('lists', function() {
|
||||
it('as unordered task list', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
describe('lists', function () {
|
||||
it('as unordered task list', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
- [x] Task 1
|
||||
- [ ] Task 2
|
||||
- [ ] Task 3`)
|
||||
expect(output, `<ul class="task-list">
|
||||
expect(output, `<ul class="task-list">
|
||||
<li class="task-list-item"><label><input checked="" disabled="" type="checkbox"> Task 1</label></li>
|
||||
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 2</label></li>
|
||||
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 3</label></li>
|
||||
</ul>`)
|
||||
})
|
||||
})
|
||||
|
||||
it('as ordered task list', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
it('as ordered task list', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
1. [ ] Task 1
|
||||
2. [x] Task 2`)
|
||||
expectSameDom(output, `<ol class="task-list">
|
||||
expectSameDom(output, `<ol class="task-list">
|
||||
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 1</label></li>
|
||||
<li class="task-list-item"><label><input checked="" disabled="" type="checkbox"> Task 2</label></li>
|
||||
</ol>`)
|
||||
})
|
||||
})
|
||||
|
||||
it('normal unordered', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
it('normal unordered', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
- [linktext](link)
|
||||
- just text`)
|
||||
expectSameDom(output, `<ul >
|
||||
expectSameDom(output, `<ul >
|
||||
<li><a href="#/link">linktext</a></li>
|
||||
<li>just text</li>
|
||||
</ul>`)
|
||||
})
|
||||
})
|
||||
|
||||
it('unordered with custom start', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
it('unordered with custom start', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
1. first
|
||||
2. second
|
||||
|
||||
text
|
||||
|
||||
3. third`)
|
||||
expectSameDom(output, `<ol >
|
||||
expectSameDom(output, `<ol >
|
||||
<li>first</li>
|
||||
<li>second</li>
|
||||
</ol>
|
||||
@ -64,17 +62,17 @@ text
|
||||
<ol start="3">
|
||||
<li>third</li>
|
||||
</ol>`)
|
||||
})
|
||||
})
|
||||
|
||||
it('nested', async function() {
|
||||
const {docsify, dom} = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
it('nested', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile(`
|
||||
- 1
|
||||
- 2
|
||||
- 2 a
|
||||
- 2 b
|
||||
- 3`)
|
||||
expectSameDom(output, `<ul >
|
||||
expectSameDom(output, `<ul >
|
||||
<li>1</li>
|
||||
<li>2<ul >
|
||||
<li>2 a</li>
|
||||
@ -83,7 +81,6 @@ text
|
||||
</li>
|
||||
<li>3</li>
|
||||
</ul>`)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,30 +1,29 @@
|
||||
/* eslint-env node, chai, mocha */
|
||||
require = require('esm')(module/*, options*/)
|
||||
const {expect} = require('chai')
|
||||
const {resolvePath} = require('../../src/core/router/util')
|
||||
|
||||
describe('router/util', function () {
|
||||
it('resolvePath', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
|
||||
it('resolvePath with dot', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('./hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
|
||||
it('resolvePath with two dots', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('test/../hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
})
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
const { expect } = require('chai')
|
||||
const { resolvePath } = require('../../src/core/router/util')
|
||||
|
||||
describe('router/util', function () {
|
||||
it('resolvePath', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
|
||||
it('resolvePath with dot', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('./hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
|
||||
it('resolvePath with two dots', async function () {
|
||||
// WHEN
|
||||
const result = resolvePath('test/../hello.md')
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user