mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
chore: added new linter config (#1028)
* chore: added new linter config * chore: linting fixes * chore: refactore in linting config and minor linting fixes
This commit is contained in:
parent
a111df9980
commit
75c72e917b
@ -5,3 +5,7 @@ build
|
||||
server.js
|
||||
cypress
|
||||
lib
|
||||
themes
|
||||
build
|
||||
docs/
|
||||
**/*.md
|
||||
34
.eslintrc
34
.eslintrc
@ -1,34 +0,0 @@
|
||||
{
|
||||
"extends": "xo-space/browser",
|
||||
"rules": {
|
||||
"semi": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"no-return-assign": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-new-func": "off",
|
||||
"no-multi-assign": "off",
|
||||
"no-mixed-operators": "off",
|
||||
"max-params": "off",
|
||||
"no-script-url": "off",
|
||||
"camelcase": "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
|
||||
}
|
||||
}
|
||||
63
.eslintrc.js
Normal file
63
.eslintrc.js
Normal file
@ -0,0 +1,63 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2019,
|
||||
},
|
||||
env: {
|
||||
jest: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
plugins: ['prettier', 'import'],
|
||||
extends: ['eslint:recommended', 'plugin:import/recommended'],
|
||||
settings: {
|
||||
'import/ignore': ['node_modules', '.json$'],
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': ['error'],
|
||||
camelcase: ['warn'],
|
||||
curly: ['error', 'all'],
|
||||
'dot-notation': ['error'],
|
||||
eqeqeq: ['error'],
|
||||
'handle-callback-err': ['error'],
|
||||
'new-cap': ['error'],
|
||||
'no-alert': ['error'],
|
||||
'no-caller': ['error'],
|
||||
'no-eval': ['error'],
|
||||
'no-labels': ['error'],
|
||||
'no-lonely-if': ['error'],
|
||||
'no-new': ['error'],
|
||||
'no-proto': ['error'],
|
||||
'no-return-assign': ['error'],
|
||||
'no-self-compare': ['error'],
|
||||
'no-shadow': ['warn'],
|
||||
'no-shadow-restricted-names': ['error'],
|
||||
'no-useless-call': ['error'],
|
||||
'no-var': ['error'],
|
||||
'no-void': ['error'],
|
||||
'no-with': ['error'],
|
||||
radix: ['error'],
|
||||
'spaced-comment': ['error', 'always'],
|
||||
strict: ['error', 'global'],
|
||||
yoda: ['error', 'never'],
|
||||
|
||||
// Import rules
|
||||
// Search way how integrate with `lerna`
|
||||
'import/no-unresolved': 'off',
|
||||
'import/imports-first': ['error'],
|
||||
'import/newline-after-import': ['error'],
|
||||
'import/no-duplicates': ['error'],
|
||||
'import/no-mutable-exports': ['error'],
|
||||
'import/no-named-as-default': ['error'],
|
||||
'import/no-named-as-default-member': ['error'],
|
||||
'import/order': ['warn'],
|
||||
},
|
||||
globals: {
|
||||
Docsify: 'writable',
|
||||
$docsify: 'writable',
|
||||
dom: 'writable',
|
||||
},
|
||||
};
|
||||
4
.prettierrc.js
Normal file
4
.prettierrc.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
singleQuote: true,
|
||||
trailingComma: 'es5',
|
||||
};
|
||||
580
package-lock.json
generated
580
package-lock.json
generated
@ -13,6 +13,61 @@
|
||||
"@babel/highlight": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
|
||||
"integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.8.3",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.13",
|
||||
"source-map": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
|
||||
"integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-get-function-arity": "^7.8.3",
|
||||
"@babel/template": "^7.8.3",
|
||||
"@babel/types": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/helper-get-function-arity": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
|
||||
"integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/helper-split-export-declaration": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
|
||||
"integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
|
||||
@ -24,6 +79,95 @@
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
|
||||
"integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
|
||||
"integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@babel/parser": "^7.8.3",
|
||||
"@babel/types": "^7.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
|
||||
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
|
||||
"integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@babel/generator": "^7.8.4",
|
||||
"@babel/helper-function-name": "^7.8.3",
|
||||
"@babel/helper-split-export-declaration": "^7.8.3",
|
||||
"@babel/parser": "^7.8.4",
|
||||
"@babel/types": "^7.8.3",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
|
||||
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
|
||||
"integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.13",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@cypress/listr-verbose-renderer": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
|
||||
@ -1888,6 +2032,96 @@
|
||||
"integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=",
|
||||
"dev": true
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
|
||||
"integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.0",
|
||||
"is-string": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.17.4",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz",
|
||||
"integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.1.5",
|
||||
"is-regex": "^1.0.5",
|
||||
"object-inspect": "^1.7.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.0",
|
||||
"string.prototype.trimleft": "^2.1.1",
|
||||
"string.prototype.trimright": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
|
||||
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
|
||||
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
|
||||
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
|
||||
"dev": true
|
||||
},
|
||||
"string.prototype.trimleft": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
|
||||
"integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"string.prototype.trimright": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
|
||||
"integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"array-union": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
||||
@ -1909,6 +2143,95 @@
|
||||
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
|
||||
"dev": true
|
||||
},
|
||||
"array.prototype.flat": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
|
||||
"integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.0-next.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.17.4",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz",
|
||||
"integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.1.5",
|
||||
"is-regex": "^1.0.5",
|
||||
"object-inspect": "^1.7.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.0",
|
||||
"string.prototype.trimleft": "^2.1.1",
|
||||
"string.prototype.trimright": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"es-to-primitive": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
|
||||
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
|
||||
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
|
||||
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
|
||||
"dev": true
|
||||
},
|
||||
"string.prototype.trimleft": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
|
||||
"integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"string.prototype.trimright": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
|
||||
"integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"arrify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
|
||||
@ -2042,6 +2365,20 @@
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz",
|
||||
"integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/traverse": "^7.0.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
@ -2860,6 +3197,12 @@
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"dev": true
|
||||
},
|
||||
"contains-path": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
|
||||
"integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
|
||||
"dev": true
|
||||
},
|
||||
"conventional-changelog": {
|
||||
"version": "3.1.12",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.12.tgz",
|
||||
@ -4597,19 +4940,189 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-config-xo": {
|
||||
"version": "0.26.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.26.0.tgz",
|
||||
"integrity": "sha512-l+93kmBSNr5rMrsqwC6xVWsi8LI4He3z6jSk38e9bAkMNsVsQ8XYO+qzXfJFgFX4i/+hiTswyHtl+nDut9rPaA==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-config-xo-space": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-xo-space/-/eslint-config-xo-space-0.21.0.tgz",
|
||||
"integrity": "sha512-4/Ko662Ghi1hgAF5H9Z37isg7WAeW1eGaY85pf/KLdLaif5qSPqpRZzaFzKjfCgkz3tU1GgpUIYYcMpLetNdyQ==",
|
||||
"eslint-import-resolver-node": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz",
|
||||
"integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-config-xo": "^0.26.0"
|
||||
"debug": "^2.6.9",
|
||||
"resolve": "^1.13.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
|
||||
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-module-utils": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz",
|
||||
"integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^2.6.9",
|
||||
"pkg-dir": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
|
||||
"integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz",
|
||||
"integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-includes": "^3.0.3",
|
||||
"array.prototype.flat": "^1.2.1",
|
||||
"contains-path": "^0.1.0",
|
||||
"debug": "^2.6.9",
|
||||
"doctrine": "1.5.0",
|
||||
"eslint-import-resolver-node": "^0.3.2",
|
||||
"eslint-module-utils": "^2.4.1",
|
||||
"has": "^1.0.3",
|
||||
"minimatch": "^3.0.4",
|
||||
"object.values": "^1.1.0",
|
||||
"read-pkg-up": "^2.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
|
||||
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"isarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"parse-json": "^2.2.0",
|
||||
"pify": "^2.0.0",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
|
||||
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"path-type": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
|
||||
"integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||
"integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"load-json-file": "^2.0.0",
|
||||
"normalize-package-data": "^2.3.2",
|
||||
"path-type": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^2.0.0",
|
||||
"read-pkg": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-prettier": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz",
|
||||
"integrity": "sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prettier-linter-helpers": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"eslint-scope": {
|
||||
@ -5026,6 +5539,12 @@
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-diff": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
|
||||
@ -6826,6 +7345,12 @@
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
|
||||
"dev": true
|
||||
},
|
||||
"is-string": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
|
||||
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-svg": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz",
|
||||
@ -9389,6 +9914,18 @@
|
||||
"isobject": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"object.assign": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
"has-symbols": "^1.0.0",
|
||||
"object-keys": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"object.getownpropertydescriptors": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
@ -10655,6 +11192,21 @@
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
|
||||
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier-linter-helpers": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
|
||||
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-diff": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"prismjs": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
|
||||
@ -12626,6 +13178,12 @@
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
||||
"dev": true
|
||||
},
|
||||
"to-object-path": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
|
||||
|
||||
@ -70,6 +70,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer-stylus": "^1.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"chai": "^4.2.0",
|
||||
"chokidar": "^3.2.1",
|
||||
"conventional-changelog-cli": "^2.0.25",
|
||||
@ -80,7 +81,8 @@
|
||||
"cypress": "^3.8.1",
|
||||
"cypress-image-snapshot": "^3.1.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-xo-space": "^0.21.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"esm": "^3.1.4",
|
||||
"husky": "^3.1.0",
|
||||
"jsdom": "^15.1.1",
|
||||
@ -90,6 +92,7 @@
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.2.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^1.19.1",
|
||||
"rimraf": "^3.0.0",
|
||||
"rollup": "^1.23.1",
|
||||
"rollup-plugin-async": "^1.2.0",
|
||||
|
||||
@ -1,116 +1,116 @@
|
||||
import * as tpl from '../../src/core/render/tpl'
|
||||
import fetch from 'node-fetch'
|
||||
import {AbstractHistory} from '../../src/core/router/history/abstract'
|
||||
import {Compiler} from '../../src/core/render/compiler'
|
||||
import {isAbsolutePath} from '../../src/core/router/util'
|
||||
import {readFileSync} from 'fs'
|
||||
import {resolve, basename} from 'path'
|
||||
import resolvePathname from 'resolve-pathname'
|
||||
import debug from 'debug'
|
||||
import {prerenderEmbed} from '../../src/core/render/embed'
|
||||
import { readFileSync } from 'fs';
|
||||
import { resolve, basename } from 'path';
|
||||
import { AbstractHistory } from '../../src/core/router/history/abstract';
|
||||
import { Compiler } from '../../src/core/render/compiler';
|
||||
import { isAbsolutePath } from '../../src/core/router/util';
|
||||
import * as tpl from '../../src/core/render/tpl';
|
||||
import { prerenderEmbed } from '../../src/core/render/embed';
|
||||
import resolvePathname from 'resolve-pathname';
|
||||
import debug from 'debug';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
function cwd(...args) {
|
||||
return resolve(process.cwd(), ...args)
|
||||
return resolve(process.cwd(), ...args);
|
||||
}
|
||||
|
||||
function mainTpl(config) {
|
||||
let html = `<nav class="app-nav${
|
||||
config.repo ? '' : ' no-badge'
|
||||
}"><!--navbar--></nav>`
|
||||
}"><!--navbar--></nav>`;
|
||||
|
||||
if (config.repo) {
|
||||
html += tpl.corner(config.repo)
|
||||
html += tpl.corner(config.repo);
|
||||
}
|
||||
|
||||
if (config.coverpage) {
|
||||
html += tpl.cover()
|
||||
html += tpl.cover();
|
||||
}
|
||||
|
||||
html += tpl.main(config)
|
||||
html += tpl.main(config);
|
||||
|
||||
return html
|
||||
return html;
|
||||
}
|
||||
|
||||
export default class Renderer {
|
||||
constructor({template, config, cache}) {
|
||||
this.html = template
|
||||
constructor({ template, config, cache }) {
|
||||
this.html = template;
|
||||
this.config = config = Object.assign({}, config, {
|
||||
routerMode: 'history'
|
||||
})
|
||||
this.cache = cache
|
||||
routerMode: 'history',
|
||||
});
|
||||
this.cache = cache;
|
||||
|
||||
this.router = new AbstractHistory(config)
|
||||
this.compiler = new Compiler(config, this.router)
|
||||
this.router = new AbstractHistory(config);
|
||||
this.compiler = new Compiler(config, this.router);
|
||||
|
||||
this.router.getCurrentPath = () => this.url
|
||||
this.router.getCurrentPath = () => this.url;
|
||||
this._renderHtml(
|
||||
'inject-config',
|
||||
`<script>window.$docsify = ${JSON.stringify(config)}</script>`
|
||||
)
|
||||
this._renderHtml('inject-app', mainTpl(config))
|
||||
);
|
||||
this._renderHtml('inject-app', mainTpl(config));
|
||||
|
||||
this.template = this.html
|
||||
this.template = this.html;
|
||||
}
|
||||
|
||||
_getPath(url) {
|
||||
const file = this.router.getFile(url)
|
||||
const file = this.router.getFile(url);
|
||||
|
||||
return isAbsolutePath(file) ? file : cwd(`./${file}`)
|
||||
return isAbsolutePath(file) ? file : cwd(`./${file}`);
|
||||
}
|
||||
|
||||
async renderToString(url) {
|
||||
this.url = url = this.router.parse(url).path
|
||||
const {loadSidebar, loadNavbar, coverpage} = this.config
|
||||
this.url = url = this.router.parse(url).path;
|
||||
const { loadSidebar, loadNavbar, coverpage } = this.config;
|
||||
|
||||
const mainFile = this._getPath(url)
|
||||
this._renderHtml('main', await this._render(mainFile, 'main'))
|
||||
const mainFile = this._getPath(url);
|
||||
this._renderHtml('main', await this._render(mainFile, 'main'));
|
||||
|
||||
if (loadSidebar) {
|
||||
const name = loadSidebar === true ? '_sidebar.md' : loadSidebar
|
||||
const sidebarFile = this._getPath(resolve(url, `./${name}`))
|
||||
this._renderHtml('sidebar', await this._render(sidebarFile, 'sidebar'))
|
||||
const name = loadSidebar === true ? '_sidebar.md' : loadSidebar;
|
||||
const sidebarFile = this._getPath(resolve(url, `./${name}`));
|
||||
this._renderHtml('sidebar', await this._render(sidebarFile, 'sidebar'));
|
||||
}
|
||||
|
||||
if (loadNavbar) {
|
||||
const name = loadNavbar === true ? '_navbar.md' : loadNavbar
|
||||
const navbarFile = this._getPath(resolve(url, `./${name}`))
|
||||
this._renderHtml('navbar', await this._render(navbarFile, 'navbar'))
|
||||
const name = loadNavbar === true ? '_navbar.md' : loadNavbar;
|
||||
const navbarFile = this._getPath(resolve(url, `./${name}`));
|
||||
this._renderHtml('navbar', await this._render(navbarFile, 'navbar'));
|
||||
}
|
||||
|
||||
if (coverpage) {
|
||||
let path = null
|
||||
let path = null;
|
||||
if (typeof coverpage === 'string') {
|
||||
if (url === '/') {
|
||||
path = coverpage
|
||||
path = coverpage;
|
||||
}
|
||||
} else if (Array.isArray(coverpage)) {
|
||||
path = coverpage.indexOf(url) > -1 && '_coverpage.md'
|
||||
path = coverpage.indexOf(url) > -1 && '_coverpage.md';
|
||||
} else {
|
||||
const cover = coverpage[url]
|
||||
path = cover === true ? '_coverpage.md' : cover
|
||||
const cover = coverpage[url];
|
||||
path = cover === true ? '_coverpage.md' : cover;
|
||||
}
|
||||
|
||||
const coverFile = this._getPath(resolve(url, `./${path}`))
|
||||
const coverFile = this._getPath(resolve(url, `./${path}`));
|
||||
|
||||
this._renderHtml('cover', await this._render(coverFile), 'cover')
|
||||
this._renderHtml('cover', await this._render(coverFile), 'cover');
|
||||
}
|
||||
|
||||
const html = this.html
|
||||
this.html = this.template
|
||||
const html = this.html;
|
||||
this.html = this.template;
|
||||
|
||||
return html
|
||||
return html;
|
||||
}
|
||||
|
||||
_renderHtml(match, content) {
|
||||
this.html = this.html.replace(new RegExp(`<!--${match}-->`, 'g'), content)
|
||||
this.html = this.html.replace(new RegExp(`<!--${match}-->`, 'g'), content);
|
||||
|
||||
return this.html
|
||||
return this.html;
|
||||
}
|
||||
|
||||
async _render(path, type) {
|
||||
let html = await this._loadFile(path)
|
||||
const {subMaxLevel, maxLevel} = this.config
|
||||
let tokens
|
||||
let html = await this._loadFile(path);
|
||||
const { subMaxLevel, maxLevel } = this.config;
|
||||
let tokens;
|
||||
|
||||
switch (type) {
|
||||
case 'sidebar':
|
||||
@ -118,67 +118,67 @@ export default class Renderer {
|
||||
this.compiler.sidebar(html, maxLevel) +
|
||||
`<script>window.__SUB_SIDEBAR__ = ${JSON.stringify(
|
||||
this.compiler.subSidebar(subMaxLevel)
|
||||
)}</script>`
|
||||
break
|
||||
)}</script>`;
|
||||
break;
|
||||
case 'cover':
|
||||
html = this.compiler.cover(html)
|
||||
break
|
||||
html = this.compiler.cover(html);
|
||||
break;
|
||||
case 'main':
|
||||
tokens = await new Promise(r => {
|
||||
prerenderEmbed(
|
||||
{
|
||||
fetch: url => this._loadFile(this._getPath(url)),
|
||||
compiler: this.compiler,
|
||||
raw: html
|
||||
raw: html,
|
||||
},
|
||||
r
|
||||
)
|
||||
})
|
||||
html = this.compiler.compile(tokens)
|
||||
break
|
||||
);
|
||||
});
|
||||
html = this.compiler.compile(tokens);
|
||||
break;
|
||||
case 'navbar':
|
||||
case 'article':
|
||||
default:
|
||||
html = this.compiler.compile(html)
|
||||
break
|
||||
html = this.compiler.compile(html);
|
||||
break;
|
||||
}
|
||||
|
||||
return html
|
||||
return html;
|
||||
}
|
||||
|
||||
async _loadFile(filePath) {
|
||||
debug('docsify')(`load > ${filePath}`)
|
||||
let content
|
||||
debug('docsify')(`load > ${filePath}`);
|
||||
let content;
|
||||
try {
|
||||
if (isAbsolutePath(filePath)) {
|
||||
const res = await fetch(filePath)
|
||||
const res = await fetch(filePath);
|
||||
if (!res.ok) {
|
||||
throw Error()
|
||||
throw Error();
|
||||
}
|
||||
|
||||
content = await res.text()
|
||||
this.lock = 0
|
||||
content = await res.text();
|
||||
this.lock = 0;
|
||||
} else {
|
||||
content = await readFileSync(filePath, 'utf8')
|
||||
this.lock = 0
|
||||
content = await readFileSync(filePath, 'utf8');
|
||||
this.lock = 0;
|
||||
}
|
||||
|
||||
return content
|
||||
return content;
|
||||
} catch (e) {
|
||||
this.lock = this.lock || 0
|
||||
this.lock = this.lock || 0;
|
||||
if (++this.lock > 10) {
|
||||
this.lock = 0
|
||||
return
|
||||
this.lock = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const fileName = basename(filePath)
|
||||
const fileName = basename(filePath);
|
||||
const result = await this._loadFile(
|
||||
resolvePathname(`../${fileName}`, filePath)
|
||||
)
|
||||
);
|
||||
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Renderer.version = '__VERSION__'
|
||||
Renderer.version = '__VERSION__';
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {merge, hyphenate, isPrimitive, hasOwn} from './util/core'
|
||||
import { merge, hyphenate, isPrimitive, hasOwn } from './util/core';
|
||||
|
||||
const currentScript = document.currentScript
|
||||
const currentScript = document.currentScript;
|
||||
|
||||
export default function () {
|
||||
export default function() {
|
||||
const config = merge(
|
||||
{
|
||||
el: '#app',
|
||||
@ -32,50 +32,50 @@ export default function () {
|
||||
externalLinkRel: 'noopener',
|
||||
routerMode: 'hash',
|
||||
noCompileLinks: [],
|
||||
relativePath: false
|
||||
relativePath: false,
|
||||
},
|
||||
window.$docsify
|
||||
)
|
||||
);
|
||||
|
||||
const script =
|
||||
currentScript ||
|
||||
[].slice
|
||||
.call(document.getElementsByTagName('script'))
|
||||
.filter(n => /docsify\./.test(n.src))[0]
|
||||
.filter(n => /docsify\./.test(n.src))[0];
|
||||
|
||||
if (script) {
|
||||
for (const prop in config) {
|
||||
if (hasOwn.call(config, prop)) {
|
||||
const val = script.getAttribute('data-' + hyphenate(prop))
|
||||
const val = script.getAttribute('data-' + hyphenate(prop));
|
||||
|
||||
if (isPrimitive(val)) {
|
||||
config[prop] = val === '' ? true : val
|
||||
config[prop] = val === '' ? true : val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.loadSidebar === true) {
|
||||
config.loadSidebar = '_sidebar' + config.ext
|
||||
config.loadSidebar = '_sidebar' + config.ext;
|
||||
}
|
||||
|
||||
if (config.loadNavbar === true) {
|
||||
config.loadNavbar = '_navbar' + config.ext
|
||||
config.loadNavbar = '_navbar' + config.ext;
|
||||
}
|
||||
|
||||
if (config.coverpage === true) {
|
||||
config.coverpage = '_coverpage' + config.ext
|
||||
config.coverpage = '_coverpage' + config.ext;
|
||||
}
|
||||
|
||||
if (config.repo === true) {
|
||||
config.repo = ''
|
||||
config.repo = '';
|
||||
}
|
||||
|
||||
if (config.name === true) {
|
||||
config.name = ''
|
||||
config.name = '';
|
||||
}
|
||||
|
||||
window.$docsify = config
|
||||
window.$docsify = config;
|
||||
|
||||
return config
|
||||
return config;
|
||||
}
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
import {isMobile} from '../util/env'
|
||||
import {body, on} from '../util/dom'
|
||||
import * as sidebar from './sidebar'
|
||||
import {scrollIntoView} from './scroll'
|
||||
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.path, this.route.query.id)
|
||||
proto.$resetEvents = function() {
|
||||
scrollIntoView(this.route.path, this.route.query.id);
|
||||
|
||||
if (this.config.loadNavbar) {
|
||||
sidebar.getAndActive(this.router, 'nav')
|
||||
}
|
||||
sidebar.getAndActive(this.router, 'nav');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function initEvent(vm) {
|
||||
// Bind toggle button
|
||||
sidebar.btn('button.sidebar-toggle', vm.router)
|
||||
sidebar.collapse('.sidebar', vm.router)
|
||||
sidebar.btn('button.sidebar-toggle', vm.router);
|
||||
sidebar.collapse('.sidebar', vm.router);
|
||||
// Bind sticky effect
|
||||
if (vm.config.coverpage) {
|
||||
!isMobile && on('scroll', sidebar.sticky)
|
||||
!isMobile && on('scroll', sidebar.sticky);
|
||||
} else {
|
||||
body.classList.add('sticky')
|
||||
body.classList.add('sticky');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,156 +1,160 @@
|
||||
import { isMobile } from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
import Tweezer from 'tweezer.js'
|
||||
import cssEscape from 'css.escape'
|
||||
import { isMobile } from '../util/env';
|
||||
import * as dom from '../util/dom';
|
||||
import Tweezer from 'tweezer.js';
|
||||
import cssEscape from 'css.escape';
|
||||
|
||||
const nav = {}
|
||||
let hoverOver = false
|
||||
let scroller = null
|
||||
let enableScrollEvent = true
|
||||
let coverHeight = 0
|
||||
const nav = {};
|
||||
let hoverOver = false;
|
||||
let scroller = null;
|
||||
let enableScrollEvent = true;
|
||||
let coverHeight = 0;
|
||||
|
||||
function scrollTo(el) {
|
||||
if (scroller) {
|
||||
scroller.stop()
|
||||
scroller.stop();
|
||||
}
|
||||
|
||||
enableScrollEvent = false
|
||||
enableScrollEvent = false;
|
||||
scroller = new Tweezer({
|
||||
start: window.pageYOffset,
|
||||
end: el.getBoundingClientRect().top + window.pageYOffset,
|
||||
duration: 500
|
||||
duration: 500,
|
||||
})
|
||||
.on('tick', v => window.scrollTo(0, v))
|
||||
.on('done', () => {
|
||||
enableScrollEvent = true
|
||||
scroller = null
|
||||
enableScrollEvent = true;
|
||||
scroller = null;
|
||||
})
|
||||
.begin()
|
||||
.begin();
|
||||
}
|
||||
|
||||
function highlight(path) {
|
||||
if (!enableScrollEvent) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const sidebar = dom.getNode('.sidebar')
|
||||
const anchors = dom.findAll('.anchor')
|
||||
const wrap = dom.find(sidebar, '.sidebar-nav')
|
||||
let active = dom.find(sidebar, 'li.active')
|
||||
const doc = document.documentElement
|
||||
const top = ((doc && doc.scrollTop) || document.body.scrollTop) - coverHeight
|
||||
let last
|
||||
const sidebar = dom.getNode('.sidebar');
|
||||
const anchors = dom.findAll('.anchor');
|
||||
const wrap = dom.find(sidebar, '.sidebar-nav');
|
||||
let active = dom.find(sidebar, 'li.active');
|
||||
const doc = document.documentElement;
|
||||
const top = ((doc && doc.scrollTop) || document.body.scrollTop) - coverHeight;
|
||||
let last;
|
||||
|
||||
for (let i = 0, len = anchors.length; i < len; i += 1) {
|
||||
const node = anchors[i]
|
||||
const node = anchors[i];
|
||||
|
||||
if (node.offsetTop > top) {
|
||||
if (!last) {
|
||||
last = node
|
||||
last = node;
|
||||
}
|
||||
|
||||
break
|
||||
break;
|
||||
} else {
|
||||
last = node
|
||||
last = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (!last) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const li = nav[getNavKey(decodeURIComponent(path), last.getAttribute('data-id'))]
|
||||
const li =
|
||||
nav[getNavKey(decodeURIComponent(path), last.getAttribute('data-id'))];
|
||||
|
||||
if (!li || li === active) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
active && active.classList.remove('active')
|
||||
li.classList.add('active')
|
||||
active = li
|
||||
active && active.classList.remove('active');
|
||||
li.classList.add('active');
|
||||
active = li;
|
||||
|
||||
// Scroll into view
|
||||
// https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297
|
||||
if (!hoverOver && dom.body.classList.contains('sticky')) {
|
||||
const height = sidebar.clientHeight
|
||||
const curOffset = 0
|
||||
const cur = active.offsetTop + active.clientHeight + 40
|
||||
const height = sidebar.clientHeight;
|
||||
const curOffset = 0;
|
||||
const cur = active.offsetTop + active.clientHeight + 40;
|
||||
const isInView =
|
||||
active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height
|
||||
const notThan = cur - curOffset < height
|
||||
const top = isInView ? wrap.scrollTop : notThan ? curOffset : cur - height
|
||||
active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height;
|
||||
const notThan = cur - curOffset < height;
|
||||
const top = isInView ? wrap.scrollTop : notThan ? curOffset : cur - height;
|
||||
|
||||
sidebar.scrollTop = top
|
||||
sidebar.scrollTop = top;
|
||||
}
|
||||
}
|
||||
|
||||
function getNavKey(path, id) {
|
||||
return `${path}?id=${id}`
|
||||
return `${path}?id=${id}`;
|
||||
}
|
||||
|
||||
export function scrollActiveSidebar(router) {
|
||||
const cover = dom.find('.cover.show')
|
||||
coverHeight = cover ? cover.offsetHeight : 0
|
||||
const cover = dom.find('.cover.show');
|
||||
coverHeight = cover ? cover.offsetHeight : 0;
|
||||
|
||||
const sidebar = dom.getNode('.sidebar')
|
||||
let lis = []
|
||||
const sidebar = dom.getNode('.sidebar');
|
||||
let lis = [];
|
||||
if (sidebar !== null && sidebar !== undefined) {
|
||||
lis = dom.findAll(sidebar, 'li')
|
||||
lis = dom.findAll(sidebar, 'li');
|
||||
}
|
||||
|
||||
for (let i = 0, len = lis.length; i < len; i += 1) {
|
||||
const li = lis[i]
|
||||
const a = li.querySelector('a')
|
||||
const li = lis[i];
|
||||
const a = li.querySelector('a');
|
||||
if (!a) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
let href = a.getAttribute('href')
|
||||
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)
|
||||
href = getNavKey(path, id);
|
||||
}
|
||||
}
|
||||
|
||||
if (href) {
|
||||
nav[decodeURIComponent(href)] = li
|
||||
nav[decodeURIComponent(href)] = li;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const path = router.getCurrentPath()
|
||||
dom.off('scroll', () => highlight(path))
|
||||
dom.on('scroll', () => highlight(path))
|
||||
const path = router.getCurrentPath();
|
||||
dom.off('scroll', () => highlight(path));
|
||||
dom.on('scroll', () => highlight(path));
|
||||
dom.on(sidebar, 'mouseover', () => {
|
||||
hoverOver = true
|
||||
})
|
||||
hoverOver = true;
|
||||
});
|
||||
dom.on(sidebar, 'mouseleave', () => {
|
||||
hoverOver = false
|
||||
})
|
||||
hoverOver = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function scrollIntoView(path, id) {
|
||||
if (!id) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const section = dom.find('#' + cssEscape(id))
|
||||
section && scrollTo(section)
|
||||
const section = dom.find('#' + cssEscape(id));
|
||||
section && scrollTo(section);
|
||||
|
||||
const li = nav[getNavKey(path, id)]
|
||||
const sidebar = dom.getNode('.sidebar')
|
||||
const active = dom.find(sidebar, 'li.active')
|
||||
active && active.classList.remove('active')
|
||||
li && li.classList.add('active')
|
||||
const li = nav[getNavKey(path, id)];
|
||||
const sidebar = dom.getNode('.sidebar');
|
||||
const active = dom.find(sidebar, 'li.active');
|
||||
active && active.classList.remove('active');
|
||||
li && li.classList.add('active');
|
||||
}
|
||||
|
||||
const scrollEl = dom.$.scrollingElement || dom.$.documentElement
|
||||
const scrollEl = dom.$.scrollingElement || dom.$.documentElement;
|
||||
|
||||
export function scroll2Top(offset = 0) {
|
||||
scrollEl.scrollTop = offset === true ? 0 : Number(offset)
|
||||
scrollEl.scrollTop = offset === true ? 0 : Number(offset);
|
||||
}
|
||||
|
||||
@ -1,37 +1,38 @@
|
||||
import { isMobile } from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { isMobile } from '../util/env';
|
||||
import * as dom from '../util/dom';
|
||||
|
||||
const title = dom.$.title
|
||||
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')
|
||||
const toggle = _ => dom.body.classList.toggle('close');
|
||||
|
||||
el = dom.getNode(el)
|
||||
el = dom.getNode(el);
|
||||
if (el === null || el === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
dom.on(el, 'click', e => {
|
||||
e.stopPropagation()
|
||||
toggle()
|
||||
})
|
||||
e.stopPropagation();
|
||||
toggle();
|
||||
});
|
||||
|
||||
isMobile &&
|
||||
dom.on(
|
||||
dom.body,
|
||||
'click',
|
||||
_ => dom.body.classList.contains('close') && toggle()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function collapse(el) {
|
||||
el = dom.getNode(el)
|
||||
el = dom.getNode(el);
|
||||
if (el === null || el === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
dom.on(el, 'click', ({ target }) => {
|
||||
@ -40,23 +41,23 @@ export function collapse(el) {
|
||||
target.nextSibling &&
|
||||
target.nextSibling.classList.contains('app-sub-sidebar')
|
||||
) {
|
||||
dom.toggleClass(target.parentNode, 'collapse')
|
||||
dom.toggleClass(target.parentNode, 'collapse');
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export function sticky() {
|
||||
const cover = dom.getNode('section.cover')
|
||||
const cover = dom.getNode('section.cover');
|
||||
if (!cover) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const coverHeight = cover.getBoundingClientRect().height
|
||||
const coverHeight = cover.getBoundingClientRect().height;
|
||||
|
||||
if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) {
|
||||
dom.toggleClass(dom.body, 'add', 'sticky')
|
||||
dom.toggleClass(dom.body, 'add', 'sticky');
|
||||
} else {
|
||||
dom.toggleClass(dom.body, 'remove', 'sticky')
|
||||
dom.toggleClass(dom.body, 'remove', 'sticky');
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,30 +70,34 @@ export function sticky() {
|
||||
* @return {Element} Active element
|
||||
*/
|
||||
export function getAndActive(router, el, isParent, autoTitle) {
|
||||
el = dom.getNode(el)
|
||||
let links = []
|
||||
el = dom.getNode(el);
|
||||
let links = [];
|
||||
if (el !== null && el !== undefined) {
|
||||
links = dom.findAll(el, 'a')
|
||||
links = dom.findAll(el, 'a');
|
||||
}
|
||||
|
||||
const hash = decodeURI(router.toURL(router.getCurrentPath()))
|
||||
let target
|
||||
const hash = decodeURI(router.toURL(router.getCurrentPath()));
|
||||
let target;
|
||||
|
||||
links.sort((a, b) => b.href.length - a.href.length).forEach(a => {
|
||||
const href = a.getAttribute('href')
|
||||
const node = isParent ? a.parentNode : a
|
||||
links
|
||||
.sort((a, b) => b.href.length - a.href.length)
|
||||
.forEach(a => {
|
||||
const href = a.getAttribute('href');
|
||||
const node = isParent ? a.parentNode : a;
|
||||
|
||||
if (hash.indexOf(href) === 0 && !target) {
|
||||
target = a
|
||||
dom.toggleClass(node, 'add', 'active')
|
||||
target = a;
|
||||
dom.toggleClass(node, 'add', 'active');
|
||||
} else {
|
||||
dom.toggleClass(node, 'remove', 'active')
|
||||
dom.toggleClass(node, 'remove', 'active');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (autoTitle) {
|
||||
dom.$.title = target ? (target.title || `${target.innerText} - ${title}`) : title
|
||||
dom.$.title = target
|
||||
? target.title || `${target.innerText} - ${title}`
|
||||
: title;
|
||||
}
|
||||
|
||||
return target
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import progressbar from '../render/progressbar'
|
||||
import { noop, hasOwn } from '../util/core'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import progressbar from '../render/progressbar';
|
||||
import { noop, hasOwn } from '../util/core';
|
||||
|
||||
const cache = {}
|
||||
const cache = {};
|
||||
|
||||
/**
|
||||
* Ajax GET implmentation
|
||||
@ -11,60 +12,60 @@ const cache = {}
|
||||
* @return {Promise} Promise response
|
||||
*/
|
||||
export function get(url, hasBar = false, headers = {}) {
|
||||
const xhr = new XMLHttpRequest()
|
||||
const on = function () {
|
||||
xhr.addEventListener.apply(xhr, arguments)
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
const on = function() {
|
||||
xhr.addEventListener.apply(xhr, arguments);
|
||||
};
|
||||
|
||||
const cached = cache[url]
|
||||
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)
|
||||
xhr.open('GET', url);
|
||||
for (const i in headers) {
|
||||
if (hasOwn.call(headers, i)) {
|
||||
xhr.setRequestHeader(i, headers[i])
|
||||
xhr.setRequestHeader(i, headers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send()
|
||||
xhr.send();
|
||||
|
||||
return {
|
||||
then: function (success, error = noop) {
|
||||
then: function(success, error = noop) {
|
||||
if (hasBar) {
|
||||
const id = setInterval(
|
||||
_ =>
|
||||
progressbar({
|
||||
step: Math.floor(Math.random() * 5 + 1)
|
||||
step: Math.floor(Math.random() * 5 + 1),
|
||||
}),
|
||||
500
|
||||
)
|
||||
);
|
||||
|
||||
on('progress', progressbar)
|
||||
on('progress', progressbar);
|
||||
on('loadend', evt => {
|
||||
progressbar(evt)
|
||||
clearInterval(id)
|
||||
})
|
||||
progressbar(evt);
|
||||
clearInterval(id);
|
||||
});
|
||||
}
|
||||
|
||||
on('error', error)
|
||||
on('error', error);
|
||||
on('load', ({ target }) => {
|
||||
if (target.status >= 400) {
|
||||
error(target)
|
||||
error(target);
|
||||
} else {
|
||||
const result = (cache[url] = {
|
||||
content: target.response,
|
||||
opt: {
|
||||
updatedAt: xhr.getResponseHeader('last-modified')
|
||||
}
|
||||
})
|
||||
|
||||
success(result.content, result.opt)
|
||||
}
|
||||
})
|
||||
updatedAt: xhr.getResponseHeader('last-modified'),
|
||||
},
|
||||
abort: _ => xhr.readyState !== 4 && xhr.abort()
|
||||
});
|
||||
|
||||
success(result.content, result.opt);
|
||||
}
|
||||
});
|
||||
},
|
||||
abort: _ => xhr.readyState !== 4 && xhr.abort(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,90 +1,91 @@
|
||||
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'
|
||||
/* eslint-disable no-unused-vars */
|
||||
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';
|
||||
|
||||
function loadNested(path, qs, file, next, vm, first) {
|
||||
path = first ? path : path.replace(/\/$/, '')
|
||||
path = getParentPath(path)
|
||||
path = first ? path : path.replace(/\/$/, '');
|
||||
path = getParentPath(path);
|
||||
|
||||
if (!path) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
get(
|
||||
vm.router.getFile(path + file) + qs,
|
||||
false,
|
||||
vm.config.requestHeaders
|
||||
).then(next, _ => loadNested(path, qs, file, next, vm))
|
||||
).then(next, _ => loadNested(path, qs, file, next, vm));
|
||||
}
|
||||
|
||||
export function fetchMixin(proto) {
|
||||
let last
|
||||
let last;
|
||||
|
||||
const abort = () => last && last.abort && last.abort()
|
||||
const abort = () => last && last.abort && last.abort();
|
||||
const request = (url, hasbar, requestHeaders) => {
|
||||
abort()
|
||||
last = get(url, true, requestHeaders)
|
||||
return last
|
||||
}
|
||||
abort();
|
||||
last = get(url, true, requestHeaders);
|
||||
return last;
|
||||
};
|
||||
|
||||
const get404Path = (path, config) => {
|
||||
const { notFoundPage, ext } = config
|
||||
const defaultPath = '_404' + (ext || '.md')
|
||||
let key
|
||||
let path404
|
||||
const { notFoundPage, ext } = config;
|
||||
const defaultPath = '_404' + (ext || '.md');
|
||||
let key;
|
||||
let path404;
|
||||
|
||||
switch (typeof notFoundPage) {
|
||||
case 'boolean':
|
||||
path404 = defaultPath
|
||||
break
|
||||
path404 = defaultPath;
|
||||
break;
|
||||
case 'string':
|
||||
path404 = notFoundPage
|
||||
break
|
||||
path404 = notFoundPage;
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
key = Object.keys(notFoundPage)
|
||||
.sort((a, b) => b.length - a.length)
|
||||
.find(key => path.match(new RegExp('^' + key)))
|
||||
.find(key => path.match(new RegExp('^' + key)));
|
||||
|
||||
path404 = (key && notFoundPage[key]) || defaultPath
|
||||
break
|
||||
path404 = (key && notFoundPage[key]) || defaultPath;
|
||||
break;
|
||||
|
||||
default:
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
return path404
|
||||
}
|
||||
return path404;
|
||||
};
|
||||
|
||||
proto._loadSideAndNav = function (path, qs, loadSidebar, cb) {
|
||||
proto._loadSideAndNav = function(path, qs, loadSidebar, cb) {
|
||||
return () => {
|
||||
if (!loadSidebar) {
|
||||
return cb()
|
||||
return cb();
|
||||
}
|
||||
|
||||
const fn = result => {
|
||||
this._renderSidebar(result)
|
||||
cb()
|
||||
}
|
||||
this._renderSidebar(result);
|
||||
cb();
|
||||
};
|
||||
|
||||
// Load sidebar
|
||||
loadNested(path, qs, loadSidebar, fn, this, true)
|
||||
}
|
||||
}
|
||||
loadNested(path, qs, loadSidebar, fn, this, true);
|
||||
};
|
||||
};
|
||||
|
||||
proto._fetch = function (cb = noop) {
|
||||
const { path, query } = this.route
|
||||
const qs = stringifyQuery(query, ['id'])
|
||||
const { loadNavbar, requestHeaders, loadSidebar } = this.config
|
||||
proto._fetch = function(cb = noop) {
|
||||
const { path, query } = this.route;
|
||||
const qs = stringifyQuery(query, ['id']);
|
||||
const { loadNavbar, requestHeaders, loadSidebar } = this.config;
|
||||
// Abort last request
|
||||
|
||||
const file = this.router.getFile(path)
|
||||
const req = request(file + qs, true, requestHeaders)
|
||||
const file = this.router.getFile(path);
|
||||
const req = request(file + qs, true, requestHeaders);
|
||||
|
||||
// Current page is html
|
||||
this.isHTML = /\.html$/g.test(file)
|
||||
this.isHTML = /\.html$/g.test(file);
|
||||
|
||||
// Load main content
|
||||
req.then(
|
||||
@ -95,9 +96,9 @@ export function fetchMixin(proto) {
|
||||
this._loadSideAndNav(path, qs, loadSidebar, cb)
|
||||
),
|
||||
_ => {
|
||||
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb)
|
||||
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Load nav
|
||||
loadNavbar &&
|
||||
@ -108,76 +109,78 @@ export function fetchMixin(proto) {
|
||||
text => this._renderNav(text),
|
||||
this,
|
||||
true
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
proto._fetchCover = function () {
|
||||
const { coverpage, requestHeaders } = this.config
|
||||
const query = this.route.query
|
||||
const root = getParentPath(this.route.path)
|
||||
proto._fetchCover = function() {
|
||||
const { coverpage, requestHeaders } = this.config;
|
||||
const query = this.route.query;
|
||||
const root = getParentPath(this.route.path);
|
||||
|
||||
if (coverpage) {
|
||||
let path = null
|
||||
const routePath = this.route.path
|
||||
let path = null;
|
||||
const routePath = this.route.path;
|
||||
if (typeof coverpage === 'string') {
|
||||
if (routePath === '/') {
|
||||
path = coverpage
|
||||
path = coverpage;
|
||||
}
|
||||
} else if (Array.isArray(coverpage)) {
|
||||
path = coverpage.indexOf(routePath) > -1 && '_coverpage'
|
||||
path = coverpage.indexOf(routePath) > -1 && '_coverpage';
|
||||
} else {
|
||||
const cover = coverpage[routePath]
|
||||
path = cover === true ? '_coverpage' : cover
|
||||
const cover = coverpage[routePath];
|
||||
path = cover === true ? '_coverpage' : cover;
|
||||
}
|
||||
|
||||
const coverOnly = Boolean(path) && this.config.onlyCover
|
||||
const coverOnly = Boolean(path) && this.config.onlyCover;
|
||||
if (path) {
|
||||
path = this.router.getFile(root + path)
|
||||
this.coverIsHTML = /\.html$/g.test(path)
|
||||
get(path + stringifyQuery(query, ['id']), false, requestHeaders).then(
|
||||
text => this._renderCover(text, coverOnly)
|
||||
)
|
||||
path = this.router.getFile(root + path);
|
||||
this.coverIsHTML = /\.html$/g.test(path);
|
||||
get(
|
||||
path + stringifyQuery(query, ['id']),
|
||||
false,
|
||||
requestHeaders
|
||||
).then(text => this._renderCover(text, coverOnly));
|
||||
} else {
|
||||
this._renderCover(null, coverOnly)
|
||||
this._renderCover(null, coverOnly);
|
||||
}
|
||||
|
||||
return coverOnly
|
||||
}
|
||||
return coverOnly;
|
||||
}
|
||||
};
|
||||
|
||||
proto.$fetch = function (cb = noop) {
|
||||
proto.$fetch = function(cb = noop) {
|
||||
const done = () => {
|
||||
callHook(this, 'doneEach')
|
||||
cb()
|
||||
}
|
||||
callHook(this, 'doneEach');
|
||||
cb();
|
||||
};
|
||||
|
||||
const onlyCover = this._fetchCover()
|
||||
const onlyCover = this._fetchCover();
|
||||
|
||||
if (onlyCover) {
|
||||
done()
|
||||
done();
|
||||
} else {
|
||||
this._fetch(() => {
|
||||
this.$resetEvents()
|
||||
done()
|
||||
})
|
||||
}
|
||||
this.$resetEvents();
|
||||
done();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
proto._fetchFallbackPage = function (path, qs, cb = noop) {
|
||||
const { requestHeaders, fallbackLanguages, loadSidebar } = this.config
|
||||
proto._fetchFallbackPage = function(path, qs, cb = noop) {
|
||||
const { requestHeaders, fallbackLanguages, loadSidebar } = this.config;
|
||||
|
||||
if (!fallbackLanguages) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
const local = path.split('/')[1]
|
||||
const local = path.split('/')[1];
|
||||
|
||||
if (fallbackLanguages.indexOf(local) === -1) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
const newPath = path.replace(new RegExp(`^/${local}`), '')
|
||||
const req = request(newPath + qs, true, requestHeaders)
|
||||
const newPath = path.replace(new RegExp(`^/${local}`), '');
|
||||
const req = request(newPath + qs, true, requestHeaders);
|
||||
|
||||
req.then(
|
||||
(text, opt) =>
|
||||
@ -187,10 +190,10 @@ export function fetchMixin(proto) {
|
||||
this._loadSideAndNav(path, qs, loadSidebar, cb)
|
||||
),
|
||||
() => this._fetch404(path, qs, cb)
|
||||
)
|
||||
);
|
||||
|
||||
return true
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the 404 page
|
||||
@ -200,40 +203,40 @@ export function fetchMixin(proto) {
|
||||
* @returns {Boolean} True if the requested page is not found
|
||||
* @private
|
||||
*/
|
||||
proto._fetch404 = function (path, qs, cb = noop) {
|
||||
const { loadSidebar, requestHeaders, notFoundPage } = this.config
|
||||
proto._fetch404 = function(path, qs, cb = noop) {
|
||||
const { loadSidebar, requestHeaders, notFoundPage } = this.config;
|
||||
|
||||
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb)
|
||||
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb);
|
||||
if (notFoundPage) {
|
||||
const path404 = get404Path(path, this.config)
|
||||
const path404 = get404Path(path, this.config);
|
||||
|
||||
request(this.router.getFile(path404), true, requestHeaders).then(
|
||||
(text, opt) => this._renderMain(text, opt, fnLoadSideAndNav),
|
||||
() => this._renderMain(null, {}, fnLoadSideAndNav)
|
||||
)
|
||||
return true
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
this._renderMain(null, {}, fnLoadSideAndNav)
|
||||
return false
|
||||
}
|
||||
this._renderMain(null, {}, fnLoadSideAndNav);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
export function initFetch(vm) {
|
||||
const { loadSidebar } = vm.config
|
||||
const { loadSidebar } = vm.config;
|
||||
|
||||
// Server-Side Rendering
|
||||
if (vm.rendered) {
|
||||
const activeEl = getAndActive(vm.router, '.sidebar-nav', true, true)
|
||||
const activeEl = getAndActive(vm.router, '.sidebar-nav', true, true);
|
||||
if (loadSidebar && activeEl) {
|
||||
activeEl.parentNode.innerHTML += window.__SUB_SIDEBAR__
|
||||
activeEl.parentNode.innerHTML += window.__SUB_SIDEBAR__;
|
||||
}
|
||||
|
||||
vm._bindEventOnRendered(activeEl)
|
||||
vm.$resetEvents()
|
||||
callHook(vm, 'doneEach')
|
||||
callHook(vm, 'ready')
|
||||
vm._bindEventOnRendered(activeEl);
|
||||
vm.$resetEvents();
|
||||
callHook(vm, 'doneEach');
|
||||
callHook(vm, 'ready');
|
||||
} else {
|
||||
vm.$fetch(_ => callHook(vm, 'ready'))
|
||||
vm.$fetch(_ => callHook(vm, 'ready'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
import * as util from './util'
|
||||
import * as dom from './util/dom'
|
||||
import {Compiler} from './render/compiler'
|
||||
import {slugify} from './render/slugify'
|
||||
import {get} from './fetch/ajax'
|
||||
import marked from 'marked'
|
||||
import prism from 'prismjs'
|
||||
import * as util from './util';
|
||||
import * as dom from './util/dom';
|
||||
import { Compiler } from './render/compiler';
|
||||
import { slugify } from './render/slugify';
|
||||
import { get } from './fetch/ajax';
|
||||
import marked from 'marked';
|
||||
import prism from 'prismjs';
|
||||
|
||||
export default function () {
|
||||
export default function() {
|
||||
window.Docsify = {
|
||||
util,
|
||||
dom,
|
||||
get,
|
||||
slugify,
|
||||
version: '__VERSION__'
|
||||
}
|
||||
window.DocsifyCompiler = Compiler
|
||||
window.marked = marked
|
||||
window.Prism = prism
|
||||
version: '__VERSION__',
|
||||
};
|
||||
window.DocsifyCompiler = Compiler;
|
||||
window.marked = marked;
|
||||
window.Prism = prism;
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
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'
|
||||
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
|
||||
@ -12,33 +12,34 @@ import initGlobalAPI from './global-api'
|
||||
* otherwise it only attaches the callback to the DOMContentLoaded event
|
||||
*/
|
||||
function ready(callback) {
|
||||
const state = document.readyState
|
||||
const state = document.readyState;
|
||||
|
||||
if (state === 'complete' || state === 'interactive') {
|
||||
return setTimeout(callback, 0)
|
||||
return setTimeout(callback, 0);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', callback)
|
||||
document.addEventListener('DOMContentLoaded', callback);
|
||||
}
|
||||
|
||||
function Docsify() {
|
||||
this._init()
|
||||
this._init();
|
||||
}
|
||||
|
||||
const proto = Docsify.prototype
|
||||
const proto = Docsify.prototype;
|
||||
|
||||
initMixin(proto)
|
||||
routerMixin(proto)
|
||||
renderMixin(proto)
|
||||
fetchMixin(proto)
|
||||
eventMixin(proto)
|
||||
initMixin(proto);
|
||||
routerMixin(proto);
|
||||
renderMixin(proto);
|
||||
fetchMixin(proto);
|
||||
eventMixin(proto);
|
||||
|
||||
/**
|
||||
* Global API
|
||||
*/
|
||||
initGlobalAPI()
|
||||
initGlobalAPI();
|
||||
|
||||
/**
|
||||
* Run Docsify
|
||||
*/
|
||||
ready(_ => new Docsify())
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
ready(_ => new Docsify());
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
import config from '../config'
|
||||
import {initLifecycle, callHook} from './lifecycle'
|
||||
import {initRender} from '../render'
|
||||
import {initRouter} from '../router'
|
||||
import {initEvent} from '../event'
|
||||
import {initFetch} from '../fetch'
|
||||
import {isFn} from '../util/core'
|
||||
import config from '../config';
|
||||
import { initRender } from '../render';
|
||||
import { initRouter } from '../router';
|
||||
import { initEvent } from '../event';
|
||||
import { initFetch } from '../fetch';
|
||||
import { isFn } from '../util/core';
|
||||
import { initLifecycle, callHook } from './lifecycle';
|
||||
|
||||
export function initMixin(proto) {
|
||||
proto._init = function () {
|
||||
const vm = this
|
||||
vm.config = config()
|
||||
proto._init = function() {
|
||||
const vm = this;
|
||||
vm.config = config();
|
||||
|
||||
initLifecycle(vm) // Init hooks
|
||||
initPlugin(vm) // Install plugins
|
||||
callHook(vm, 'init')
|
||||
initRouter(vm) // Add router
|
||||
initRender(vm) // Render base DOM
|
||||
initEvent(vm) // Bind events
|
||||
initFetch(vm) // Fetch data
|
||||
callHook(vm, 'mounted')
|
||||
}
|
||||
initLifecycle(vm); // Init hooks
|
||||
initPlugin(vm); // Install plugins
|
||||
callHook(vm, 'init');
|
||||
initRouter(vm); // Add router
|
||||
initRender(vm); // Render base DOM
|
||||
initEvent(vm); // Bind events
|
||||
initFetch(vm); // Fetch data
|
||||
callHook(vm, 'mounted');
|
||||
};
|
||||
}
|
||||
|
||||
function initPlugin(vm) {
|
||||
[].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm._lifecycle, vm))
|
||||
[].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm._lifecycle, vm));
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {noop} from '../util/core'
|
||||
import { noop } from '../util/core';
|
||||
|
||||
export function initLifecycle(vm) {
|
||||
const hooks = [
|
||||
@ -7,39 +7,39 @@ export function initLifecycle(vm) {
|
||||
'beforeEach',
|
||||
'afterEach',
|
||||
'doneEach',
|
||||
'ready'
|
||||
]
|
||||
'ready',
|
||||
];
|
||||
|
||||
vm._hooks = {}
|
||||
vm._lifecycle = {}
|
||||
vm._hooks = {};
|
||||
vm._lifecycle = {};
|
||||
hooks.forEach(hook => {
|
||||
const arr = (vm._hooks[hook] = [])
|
||||
vm._lifecycle[hook] = fn => arr.push(fn)
|
||||
})
|
||||
const arr = (vm._hooks[hook] = []);
|
||||
vm._lifecycle[hook] = fn => arr.push(fn);
|
||||
});
|
||||
}
|
||||
|
||||
export function callHook(vm, hook, data, next = noop) {
|
||||
const queue = vm._hooks[hook]
|
||||
const queue = vm._hooks[hook];
|
||||
|
||||
const step = function (index) {
|
||||
const hook = queue[index]
|
||||
const step = function(index) {
|
||||
const hook = queue[index];
|
||||
if (index >= queue.length) {
|
||||
next(data)
|
||||
next(data);
|
||||
} else if (typeof hook === 'function') {
|
||||
if (hook.length === 2) {
|
||||
hook(data, result => {
|
||||
data = result
|
||||
step(index + 1)
|
||||
})
|
||||
data = result;
|
||||
step(index + 1);
|
||||
});
|
||||
} else {
|
||||
const result = hook(data)
|
||||
data = result === undefined ? data : result
|
||||
step(index + 1)
|
||||
const result = hook(data);
|
||||
data = result === undefined ? data : result;
|
||||
step(index + 1);
|
||||
}
|
||||
} else {
|
||||
step(index + 1)
|
||||
}
|
||||
step(index + 1);
|
||||
}
|
||||
};
|
||||
|
||||
step(0)
|
||||
step(0);
|
||||
}
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import { 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 { imageCompiler } from './compiler/image'
|
||||
import { highlightCodeCompiler } from './compiler/code'
|
||||
import { paragraphCompiler } from './compiler/paragraph'
|
||||
import { taskListCompiler } from './compiler/taskList'
|
||||
import { taskListItemCompiler } from './compiler/taskListItem'
|
||||
import { linkCompiler } from './compiler/link'
|
||||
import marked from 'marked'
|
||||
import { isAbsolutePath, getPath, getParentPath } from '../router/util';
|
||||
import { isFn, merge, cached, isPrimitive } from '../util/core';
|
||||
import { tree as treeTpl } from './tpl';
|
||||
import { genTree } from './gen-tree';
|
||||
import { slugify } from './slugify';
|
||||
import { emojify } from './emojify';
|
||||
import { imageCompiler } from './compiler/image';
|
||||
import { highlightCodeCompiler } from './compiler/code';
|
||||
import { paragraphCompiler } from './compiler/paragraph';
|
||||
import { taskListCompiler } from './compiler/taskList';
|
||||
import { taskListItemCompiler } from './compiler/taskListItem';
|
||||
import { linkCompiler } from './compiler/link';
|
||||
import marked from 'marked';
|
||||
|
||||
const cachedLinks = {}
|
||||
const cachedLinks = {};
|
||||
|
||||
export function getAndRemoveConfig(str = '') {
|
||||
const config = {}
|
||||
const config = {};
|
||||
|
||||
if (str) {
|
||||
str = str
|
||||
@ -23,125 +23,128 @@ export function getAndRemoveConfig(str = '') {
|
||||
.replace(/'$/, '')
|
||||
.replace(/(?:^|\s):([\w-]+:?)=?([\w-]+)?/g, (m, key, value) => {
|
||||
if (key.indexOf(':') === -1) {
|
||||
config[key] = (value && value.replace(/"/g, '')) || true
|
||||
return ''
|
||||
config[key] = (value && value.replace(/"/g, '')) || true;
|
||||
return '';
|
||||
}
|
||||
|
||||
return m
|
||||
return m;
|
||||
})
|
||||
.trim()
|
||||
.trim();
|
||||
}
|
||||
|
||||
return { str, config }
|
||||
return { str, config };
|
||||
}
|
||||
|
||||
const compileMedia = {
|
||||
markdown(url) {
|
||||
return {
|
||||
url
|
||||
}
|
||||
url,
|
||||
};
|
||||
},
|
||||
mermaid(url) {
|
||||
return {
|
||||
url
|
||||
}
|
||||
url,
|
||||
};
|
||||
},
|
||||
iframe(url, title) {
|
||||
return {
|
||||
html: `<iframe src="${url}" ${title || 'width=100% height=400'}></iframe>`
|
||||
}
|
||||
html: `<iframe src="${url}" ${title ||
|
||||
'width=100% height=400'}></iframe>`,
|
||||
};
|
||||
},
|
||||
video(url, title) {
|
||||
return {
|
||||
html: `<video src="${url}" ${title || 'controls'}>Not Support</video>`
|
||||
}
|
||||
html: `<video src="${url}" ${title || 'controls'}>Not Support</video>`,
|
||||
};
|
||||
},
|
||||
audio(url, title) {
|
||||
return {
|
||||
html: `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`
|
||||
}
|
||||
html: `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`,
|
||||
};
|
||||
},
|
||||
code(url, title) {
|
||||
let lang = url.match(/\.(\w+)$/)
|
||||
let lang = url.match(/\.(\w+)$/);
|
||||
|
||||
lang = title || (lang && lang[1])
|
||||
lang = title || (lang && lang[1]);
|
||||
if (lang === 'md') {
|
||||
lang = 'markdown'
|
||||
lang = 'markdown';
|
||||
}
|
||||
|
||||
return {
|
||||
url,
|
||||
lang
|
||||
}
|
||||
}
|
||||
}
|
||||
lang,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export class Compiler {
|
||||
constructor(config, router) {
|
||||
this.config = config
|
||||
this.router = router
|
||||
this.cacheTree = {}
|
||||
this.toc = []
|
||||
this.cacheTOC = {}
|
||||
this.linkTarget = config.externalLinkTarget || '_blank'
|
||||
this.linkRel = this.linkTarget === '_blank' ? (config.externalLinkRel || 'noopener') : ''
|
||||
this.contentBase = router.getBasePath()
|
||||
this.config = config;
|
||||
this.router = router;
|
||||
this.cacheTree = {};
|
||||
this.toc = [];
|
||||
this.cacheTOC = {};
|
||||
this.linkTarget = config.externalLinkTarget || '_blank';
|
||||
this.linkRel =
|
||||
this.linkTarget === '_blank' ? config.externalLinkRel || 'noopener' : '';
|
||||
this.contentBase = router.getBasePath();
|
||||
|
||||
const renderer = this._initRenderer()
|
||||
this.heading = renderer.heading
|
||||
let compile
|
||||
const mdConf = config.markdown || {}
|
||||
const renderer = this._initRenderer();
|
||||
this.heading = renderer.heading;
|
||||
let compile;
|
||||
const mdConf = config.markdown || {};
|
||||
|
||||
if (isFn(mdConf)) {
|
||||
compile = mdConf(marked, renderer)
|
||||
compile = mdConf(marked, renderer);
|
||||
} else {
|
||||
marked.setOptions(
|
||||
merge(mdConf, {
|
||||
renderer: merge(renderer, mdConf.renderer)
|
||||
renderer: merge(renderer, mdConf.renderer),
|
||||
})
|
||||
)
|
||||
compile = marked
|
||||
);
|
||||
compile = marked;
|
||||
}
|
||||
|
||||
this._marked = compile
|
||||
this._marked = compile;
|
||||
this.compile = text => {
|
||||
let isCached = true
|
||||
let isCached = true;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const result = cached(_ => {
|
||||
isCached = false
|
||||
let html = ''
|
||||
isCached = false;
|
||||
let html = '';
|
||||
|
||||
if (!text) {
|
||||
return text
|
||||
return text;
|
||||
}
|
||||
|
||||
if (isPrimitive(text)) {
|
||||
html = compile(text)
|
||||
html = compile(text);
|
||||
} else {
|
||||
html = compile.parser(text)
|
||||
html = compile.parser(text);
|
||||
}
|
||||
|
||||
html = config.noEmoji ? html : emojify(html)
|
||||
slugify.clear()
|
||||
html = config.noEmoji ? html : emojify(html);
|
||||
slugify.clear();
|
||||
|
||||
return html
|
||||
})(text)
|
||||
return html;
|
||||
})(text);
|
||||
|
||||
const curFileName = this.router.parse().file
|
||||
const curFileName = this.router.parse().file;
|
||||
|
||||
if (isCached) {
|
||||
this.toc = this.cacheTOC[curFileName]
|
||||
this.toc = this.cacheTOC[curFileName];
|
||||
} else {
|
||||
this.cacheTOC[curFileName] = [...this.toc]
|
||||
this.cacheTOC[curFileName] = [...this.toc];
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
compileEmbed(href, title) {
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
let embed
|
||||
title = str
|
||||
const { str, config } = getAndRemoveConfig(title);
|
||||
let embed;
|
||||
title = str;
|
||||
|
||||
if (config.include) {
|
||||
if (!isAbsolutePath(href)) {
|
||||
@ -149,55 +152,55 @@ export class Compiler {
|
||||
process.env.SSR ? '' : this.contentBase,
|
||||
getParentPath(this.router.getCurrentPath()),
|
||||
href
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let media
|
||||
let media;
|
||||
if (config.type && (media = compileMedia[config.type])) {
|
||||
embed = media.call(this, href, title)
|
||||
embed.type = config.type
|
||||
embed = media.call(this, href, title);
|
||||
embed.type = config.type;
|
||||
} else {
|
||||
let type = 'code'
|
||||
let type = 'code';
|
||||
if (/\.(md|markdown)/.test(href)) {
|
||||
type = 'markdown'
|
||||
type = 'markdown';
|
||||
} else if (/\.mmd/.test(href)) {
|
||||
type = 'mermaid'
|
||||
type = 'mermaid';
|
||||
} else if (/\.html?/.test(href)) {
|
||||
type = 'iframe'
|
||||
type = 'iframe';
|
||||
} else if (/\.(mp4|ogg)/.test(href)) {
|
||||
type = 'video'
|
||||
type = 'video';
|
||||
} else if (/\.mp3/.test(href)) {
|
||||
type = 'audio'
|
||||
type = 'audio';
|
||||
}
|
||||
|
||||
embed = compileMedia[type].call(this, href, title)
|
||||
embed.type = type
|
||||
embed = compileMedia[type].call(this, href, title);
|
||||
embed.type = type;
|
||||
}
|
||||
|
||||
embed.fragment = config.fragment
|
||||
embed.fragment = config.fragment;
|
||||
|
||||
return embed
|
||||
return embed;
|
||||
}
|
||||
}
|
||||
|
||||
_matchNotCompileLink(link) {
|
||||
const links = this.config.noCompileLinks || []
|
||||
const links = this.config.noCompileLinks || [];
|
||||
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
const n = links[i]
|
||||
const re = cachedLinks[n] || (cachedLinks[n] = new RegExp(`^${n}$`))
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
const n = links[i];
|
||||
const re = cachedLinks[n] || (cachedLinks[n] = new RegExp(`^${n}$`));
|
||||
|
||||
if (re.test(link)) {
|
||||
return link
|
||||
return link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_initRenderer() {
|
||||
const renderer = new marked.Renderer()
|
||||
const { linkTarget, router, contentBase } = this
|
||||
const _self = this
|
||||
const origin = {}
|
||||
const renderer = new marked.Renderer();
|
||||
const { linkTarget, router, contentBase } = this;
|
||||
const _self = this;
|
||||
const origin = {};
|
||||
|
||||
/**
|
||||
* Render anchor tag
|
||||
@ -206,40 +209,45 @@ export class Compiler {
|
||||
* @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 }
|
||||
origin.heading = renderer.heading = function(text, level) {
|
||||
let { str, config } = getAndRemoveConfig(text);
|
||||
const nextToc = { level, title: str };
|
||||
|
||||
if (/{docsify-ignore}/g.test(str)) {
|
||||
str = str.replace('{docsify-ignore}', '')
|
||||
nextToc.title = str
|
||||
nextToc.ignoreSubHeading = true
|
||||
str = str.replace('{docsify-ignore}', '');
|
||||
nextToc.title = str;
|
||||
nextToc.ignoreSubHeading = true;
|
||||
}
|
||||
|
||||
if (/{docsify-ignore-all}/g.test(str)) {
|
||||
str = str.replace('{docsify-ignore-all}', '')
|
||||
nextToc.title = str
|
||||
nextToc.ignoreAllSubs = true
|
||||
str = str.replace('{docsify-ignore-all}', '');
|
||||
nextToc.title = str;
|
||||
nextToc.ignoreAllSubs = true;
|
||||
}
|
||||
|
||||
const slug = slugify(config.id || str)
|
||||
const url = router.toURL(router.getCurrentPath(), { id: slug })
|
||||
nextToc.slug = url
|
||||
_self.toc.push(nextToc)
|
||||
const slug = slugify(config.id || str);
|
||||
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}>`
|
||||
}
|
||||
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${str}</span></a></h${level}>`;
|
||||
};
|
||||
|
||||
origin.code = highlightCodeCompiler({ renderer })
|
||||
origin.link = linkCompiler({ renderer, router, linkTarget, compilerClass: _self })
|
||||
origin.paragraph = paragraphCompiler({ renderer })
|
||||
origin.image = imageCompiler({ renderer, contentBase, router })
|
||||
origin.list = taskListCompiler({ renderer })
|
||||
origin.listitem = taskListItemCompiler({ renderer })
|
||||
origin.code = highlightCodeCompiler({ renderer });
|
||||
origin.link = linkCompiler({
|
||||
renderer,
|
||||
router,
|
||||
linkTarget,
|
||||
compilerClass: _self,
|
||||
});
|
||||
origin.paragraph = paragraphCompiler({ renderer });
|
||||
origin.image = imageCompiler({ renderer, contentBase, router });
|
||||
origin.list = taskListCompiler({ renderer });
|
||||
origin.listitem = taskListItemCompiler({ renderer });
|
||||
|
||||
renderer.origin = origin
|
||||
renderer.origin = origin;
|
||||
|
||||
return renderer
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,32 +257,36 @@ export class Compiler {
|
||||
* @returns {String} Sidebar element
|
||||
*/
|
||||
sidebar(text, level) {
|
||||
const { toc } = this
|
||||
const currentPath = this.router.getCurrentPath()
|
||||
let html = ''
|
||||
const { toc } = this;
|
||||
const currentPath = this.router.getCurrentPath();
|
||||
let html = '';
|
||||
|
||||
if (text) {
|
||||
html = this.compile(text)
|
||||
html = this.compile(text);
|
||||
} else {
|
||||
for (let i = 0; i < toc.length; i++) {
|
||||
if (toc[i].ignoreSubHeading) {
|
||||
const deletedHeaderLevel = toc[i].level
|
||||
toc.splice(i, 1)
|
||||
const deletedHeaderLevel = toc[i].level;
|
||||
toc.splice(i, 1);
|
||||
// Remove headers who are under current header
|
||||
for (let j = i; deletedHeaderLevel < toc[j].level && j < toc.length; j++) {
|
||||
toc.splice(j, 1) && j-- && i++
|
||||
for (
|
||||
let j = i;
|
||||
deletedHeaderLevel < toc[j].level && j < toc.length;
|
||||
j++
|
||||
) {
|
||||
toc.splice(j, 1) && j-- && i++;
|
||||
}
|
||||
|
||||
i--
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
const tree = this.cacheTree[currentPath] || genTree(toc, level)
|
||||
html = treeTpl(tree, '<ul>{inner}</ul>')
|
||||
this.cacheTree[currentPath] = tree
|
||||
const tree = this.cacheTree[currentPath] || genTree(toc, level);
|
||||
html = treeTpl(tree, '<ul>{inner}</ul>');
|
||||
this.cacheTree[currentPath] = tree;
|
||||
}
|
||||
|
||||
return html
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,33 +296,33 @@ export class Compiler {
|
||||
*/
|
||||
subSidebar(level) {
|
||||
if (!level) {
|
||||
this.toc = []
|
||||
return
|
||||
this.toc = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPath = this.router.getCurrentPath()
|
||||
const { cacheTree, toc } = this
|
||||
const currentPath = this.router.getCurrentPath();
|
||||
const { cacheTree, toc } = this;
|
||||
|
||||
toc[0] && toc[0].ignoreAllSubs && toc.splice(0)
|
||||
toc[0] && toc[0].level === 1 && toc.shift()
|
||||
toc[0] && toc[0].ignoreAllSubs && toc.splice(0);
|
||||
toc[0] && toc[0].level === 1 && toc.shift();
|
||||
|
||||
for (let i = 0; i < toc.length; i++) {
|
||||
toc[i].ignoreSubHeading && toc.splice(i, 1) && i--
|
||||
toc[i].ignoreSubHeading && toc.splice(i, 1) && i--;
|
||||
}
|
||||
|
||||
const tree = cacheTree[currentPath] || genTree(toc, level)
|
||||
const tree = cacheTree[currentPath] || genTree(toc, level);
|
||||
|
||||
cacheTree[currentPath] = tree
|
||||
this.toc = []
|
||||
return treeTpl(tree)
|
||||
cacheTree[currentPath] = tree;
|
||||
this.toc = [];
|
||||
return treeTpl(tree);
|
||||
}
|
||||
|
||||
header(text, level) {
|
||||
return this.heading(text, level)
|
||||
return this.heading(text, level);
|
||||
}
|
||||
|
||||
article(text) {
|
||||
return this.compile(text)
|
||||
return this.compile(text);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,11 +331,11 @@ export class Compiler {
|
||||
* @returns {String} Cover page
|
||||
*/
|
||||
cover(text) {
|
||||
const cacheToc = this.toc.slice()
|
||||
const html = this.compile(text)
|
||||
const cacheToc = this.toc.slice();
|
||||
const html = this.compile(text);
|
||||
|
||||
this.toc = cacheToc.slice()
|
||||
this.toc = cacheToc.slice();
|
||||
|
||||
return html
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import Prism from 'prismjs'
|
||||
import Prism from 'prismjs';
|
||||
// See https://github.com/PrismJS/prism/pull/1367
|
||||
import 'prismjs/components/prism-markup-templating'
|
||||
import 'prismjs/components/prism-markup-templating';
|
||||
|
||||
export const highlightCodeCompiler = ({ renderer }) => renderer.code = function (code, lang = '') {
|
||||
const langOrMarkup = Prism.languages[lang] || Prism.languages.markup
|
||||
const text = Prism.highlight(code.replace(/@DOCSIFY_QM@/g, '`'), langOrMarkup)
|
||||
export const highlightCodeCompiler = ({ renderer }) =>
|
||||
(renderer.code = function(code, lang = '') {
|
||||
const langOrMarkup = Prism.languages[lang] || Prism.languages.markup;
|
||||
const text = Prism.highlight(
|
||||
code.replace(/@DOCSIFY_QM@/g, '`'),
|
||||
langOrMarkup
|
||||
);
|
||||
|
||||
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${text}</code></pre>`
|
||||
}
|
||||
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${text}</code></pre>`;
|
||||
});
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
import { getAndRemoveConfig } from '../compiler';
|
||||
import { slugify } from './slugify';
|
||||
|
||||
import { getAndRemoveConfig } from '../compiler'
|
||||
import { slugify } from './slugify'
|
||||
|
||||
export const headingCompiler = ({ renderer, router, _self }) => renderer.code = (text, level) => {
|
||||
let { str, config } = getAndRemoveConfig(text)
|
||||
const nextToc = { level, title: str }
|
||||
export const headingCompiler = ({ renderer, router, _self }) =>
|
||||
(renderer.code = (text, level) => {
|
||||
let { str, config } = getAndRemoveConfig(text);
|
||||
const nextToc = { level, title: str };
|
||||
|
||||
if (/{docsify-ignore}/g.test(str)) {
|
||||
str = str.replace('{docsify-ignore}', '')
|
||||
nextToc.title = str
|
||||
nextToc.ignoreSubHeading = true
|
||||
str = str.replace('{docsify-ignore}', '');
|
||||
nextToc.title = str;
|
||||
nextToc.ignoreSubHeading = true;
|
||||
}
|
||||
|
||||
if (/{docsify-ignore-all}/g.test(str)) {
|
||||
str = str.replace('{docsify-ignore-all}', '')
|
||||
nextToc.title = str
|
||||
nextToc.ignoreAllSubs = true
|
||||
str = str.replace('{docsify-ignore-all}', '');
|
||||
nextToc.title = str;
|
||||
nextToc.ignoreAllSubs = true;
|
||||
}
|
||||
|
||||
const slug = slugify(config.id || str)
|
||||
const url = router.toURL(router.getCurrentPath(), { id: slug })
|
||||
nextToc.slug = url
|
||||
_self.toc.push(nextToc)
|
||||
const slug = slugify(config.id || str);
|
||||
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}>`
|
||||
}
|
||||
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${str}</span></a></h${level}>`;
|
||||
});
|
||||
|
||||
@ -1,42 +1,44 @@
|
||||
import { getAndRemoveConfig } from '../compiler'
|
||||
import { isAbsolutePath, getPath, getParentPath } from '../../router/util'
|
||||
import { getAndRemoveConfig } from '../compiler';
|
||||
import { isAbsolutePath, getPath, getParentPath } from '../../router/util';
|
||||
|
||||
export const imageCompiler = ({ renderer, contentBase, router }) => renderer.image = (href, title, text) => {
|
||||
let url = href
|
||||
let attrs = []
|
||||
export const imageCompiler = ({ renderer, contentBase, router }) =>
|
||||
(renderer.image = (href, title, text) => {
|
||||
let url = href;
|
||||
let attrs = [];
|
||||
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
title = str
|
||||
const { str, config } = getAndRemoveConfig(title);
|
||||
title = str;
|
||||
|
||||
if (config['no-zoom']) {
|
||||
attrs.push('data-no-zoom')
|
||||
attrs.push('data-no-zoom');
|
||||
}
|
||||
|
||||
if (title) {
|
||||
attrs.push(`title="${title}"`)
|
||||
attrs.push(`title="${title}"`);
|
||||
}
|
||||
|
||||
if (config.size) {
|
||||
const [width, height] = config.size.split('x')
|
||||
const [width, height] = config.size.split('x');
|
||||
if (height) {
|
||||
attrs.push(`width="${width}" height="${height}"`)
|
||||
attrs.push(`width="${width}" height="${height}"`);
|
||||
} else {
|
||||
attrs.push(`width="${width}" height="${width}"`)
|
||||
attrs.push(`width="${width}" height="${width}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.class) {
|
||||
attrs.push(`class="${config.class}"`)
|
||||
attrs.push(`class="${config.class}"`);
|
||||
}
|
||||
|
||||
if (config.id) {
|
||||
attrs.push(`id="${config.id}"`)
|
||||
attrs.push(`id="${config.id}"`);
|
||||
}
|
||||
|
||||
if (!isAbsolutePath(href)) {
|
||||
url = getPath(contentBase, getParentPath(router.getCurrentPath()), href)
|
||||
url = getPath(contentBase, getParentPath(router.getCurrentPath()), href);
|
||||
}
|
||||
|
||||
return `<img src="${url}" data-origin="${href}" alt="${text}" ${attrs.join(' ')} />`
|
||||
}
|
||||
|
||||
return `<img src="${url}" data-origin="${href}" alt="${text}" ${attrs.join(
|
||||
' '
|
||||
)} />`;
|
||||
});
|
||||
|
||||
@ -1,42 +1,47 @@
|
||||
import { getAndRemoveConfig } from '../compiler'
|
||||
import { isAbsolutePath } from '../../router/util'
|
||||
import { getAndRemoveConfig } from '../compiler';
|
||||
import { isAbsolutePath } from '../../router/util';
|
||||
|
||||
export const linkCompiler = ({ renderer, router, linkTarget, compilerClass }) => renderer.link = (href, title = '', text) => {
|
||||
let attrs = []
|
||||
const { str, config } = getAndRemoveConfig(title)
|
||||
export const linkCompiler = ({ renderer, router, linkTarget, compilerClass }) =>
|
||||
(renderer.link = (href, title = '', text) => {
|
||||
let attrs = [];
|
||||
const { str, config } = getAndRemoveConfig(title);
|
||||
|
||||
title = str
|
||||
title = str;
|
||||
|
||||
if (!isAbsolutePath(href) && !compilerClass._matchNotCompileLink(href) && !config.ignore) {
|
||||
if (
|
||||
!isAbsolutePath(href) &&
|
||||
!compilerClass._matchNotCompileLink(href) &&
|
||||
!config.ignore
|
||||
) {
|
||||
if (href === compilerClass.config.homepage) {
|
||||
href = 'README'
|
||||
href = 'README';
|
||||
}
|
||||
|
||||
href = router.toURL(href, null, router.getCurrentPath())
|
||||
href = router.toURL(href, null, router.getCurrentPath());
|
||||
} else {
|
||||
attrs.push(href.indexOf('mailto:') === 0 ? '' : `target="${linkTarget}"`)
|
||||
attrs.push(href.indexOf('mailto:') === 0 ? '' : `target="${linkTarget}"`);
|
||||
}
|
||||
|
||||
if (config.target) {
|
||||
attrs.push(`target="${config.target}"`)
|
||||
attrs.push(`target="${config.target}"`);
|
||||
}
|
||||
|
||||
if (config.disabled) {
|
||||
attrs.push('disabled')
|
||||
href = 'javascript:void(0)'
|
||||
attrs.push('disabled');
|
||||
href = 'javascript:void(0)';
|
||||
}
|
||||
|
||||
if (config.class) {
|
||||
attrs.push(`class="${config.class}"`)
|
||||
attrs.push(`class="${config.class}"`);
|
||||
}
|
||||
|
||||
if (config.id) {
|
||||
attrs.push(`id="${config.id}"`)
|
||||
attrs.push(`id="${config.id}"`);
|
||||
}
|
||||
|
||||
if (title) {
|
||||
attrs.push(`title="${title}"`)
|
||||
attrs.push(`title="${title}"`);
|
||||
}
|
||||
|
||||
return `<a href="${href}" ${attrs.join(' ')}>${text}</a>`
|
||||
}
|
||||
return `<a href="${href}" ${attrs.join(' ')}>${text}</a>`;
|
||||
});
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { helper as helperTpl } from '../tpl'
|
||||
import { helper as helperTpl } from '../tpl';
|
||||
|
||||
export const paragraphCompiler = ({ renderer }) => renderer.paragraph = text => {
|
||||
let result
|
||||
export const paragraphCompiler = ({ renderer }) =>
|
||||
(renderer.paragraph = text => {
|
||||
let result;
|
||||
if (/^!>/.test(text)) {
|
||||
result = helperTpl('tip', text)
|
||||
result = helperTpl('tip', text);
|
||||
} else if (/^\?>/.test(text)) {
|
||||
result = helperTpl('warn', text)
|
||||
result = helperTpl('warn', text);
|
||||
} else {
|
||||
result = `<p>${text}</p>`
|
||||
result = `<p>${text}</p>`;
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
export const taskListCompiler = ({renderer}) => renderer.list = (body, ordered, start) => {
|
||||
const isTaskList = /<li class="task-list-item">/.test(body.split('class="task-list"')[0])
|
||||
const isStartReq = start && start > 1
|
||||
const tag = ordered ? 'ol' : 'ul'
|
||||
export const taskListCompiler = ({ renderer }) =>
|
||||
(renderer.list = (body, ordered, start) => {
|
||||
const isTaskList = /<li class="task-list-item">/.test(
|
||||
body.split('class="task-list"')[0]
|
||||
);
|
||||
const isStartReq = start && start > 1;
|
||||
const tag = ordered ? 'ol' : 'ul';
|
||||
const tagAttrs = [
|
||||
(isTaskList ? 'class="task-list"' : ''),
|
||||
(isStartReq ? `start="${start}"` : '')
|
||||
isTaskList ? 'class="task-list"' : '',
|
||||
isStartReq ? `start="${start}"` : '',
|
||||
]
|
||||
.join(' ')
|
||||
.trim()
|
||||
.trim();
|
||||
|
||||
return `<${tag} ${tagAttrs}>${body}</${tag}>`
|
||||
}
|
||||
return `<${tag} ${tagAttrs}>${body}</${tag}>`;
|
||||
});
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
export const taskListItemCompiler = ({ renderer }) => renderer.listitem = text => {
|
||||
const isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text)
|
||||
const html = isTaskItem ? `<li class="task-list-item"><label>${text}</label></li>` : `<li>${text}</li>`
|
||||
export const taskListItemCompiler = ({ renderer }) =>
|
||||
(renderer.listitem = text => {
|
||||
const isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text);
|
||||
const html = isTaskItem
|
||||
? `<li class="task-list-item"><label>${text}</label></li>`
|
||||
: `<li>${text}</li>`;
|
||||
|
||||
return html
|
||||
}
|
||||
return html;
|
||||
});
|
||||
|
||||
@ -1,30 +1,32 @@
|
||||
import { get } from '../fetch/ajax'
|
||||
import { merge } from '../util/core'
|
||||
import stripIndent from 'strip-indent'
|
||||
import { get } from '../fetch/ajax';
|
||||
import { merge } from '../util/core';
|
||||
import stripIndent from 'strip-indent';
|
||||
|
||||
const cached = {}
|
||||
const cached = {};
|
||||
|
||||
function walkFetchEmbed({ embedTokens, compile, fetch }, cb) {
|
||||
let token
|
||||
let step = 0
|
||||
let count = 1
|
||||
let token;
|
||||
let step = 0;
|
||||
let count = 1;
|
||||
|
||||
if (!embedTokens.length) {
|
||||
return cb({})
|
||||
return cb({});
|
||||
}
|
||||
|
||||
while ((token = embedTokens[step++])) {
|
||||
const next = (function (token) {
|
||||
const next = (function(token) {
|
||||
return text => {
|
||||
let embedToken
|
||||
let embedToken;
|
||||
if (text) {
|
||||
if (token.embed.type === 'markdown') {
|
||||
embedToken = compile.lexer(text)
|
||||
embedToken = compile.lexer(text);
|
||||
} else if (token.embed.type === 'code') {
|
||||
if (token.embed.fragment) {
|
||||
const fragment = token.embed.fragment
|
||||
const pattern = new RegExp(`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`)
|
||||
text = stripIndent((text.match(pattern) || [])[1] || '').trim()
|
||||
const fragment = token.embed.fragment;
|
||||
const pattern = new RegExp(
|
||||
`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`
|
||||
);
|
||||
text = stripIndent((text.match(pattern) || [])[1] || '').trim();
|
||||
}
|
||||
|
||||
embedToken = compile.lexer(
|
||||
@ -33,86 +35,86 @@ function walkFetchEmbed({ embedTokens, compile, fetch }, cb) {
|
||||
'\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>` }
|
||||
]
|
||||
embedToken.links = {}
|
||||
{ type: 'html', text: `<div class="mermaid">\n${text}\n</div>` },
|
||||
];
|
||||
embedToken.links = {};
|
||||
} else {
|
||||
embedToken = [{ type: 'html', text }]
|
||||
embedToken.links = {}
|
||||
embedToken = [{ type: 'html', text }];
|
||||
embedToken.links = {};
|
||||
}
|
||||
}
|
||||
|
||||
cb({ token, embedToken })
|
||||
cb({ token, embedToken });
|
||||
if (++count >= step) {
|
||||
cb({})
|
||||
cb({});
|
||||
}
|
||||
}
|
||||
})(token)
|
||||
};
|
||||
})(token);
|
||||
|
||||
if (token.embed.url) {
|
||||
if (process.env.SSR) {
|
||||
fetch(token.embed.url).then(next)
|
||||
fetch(token.embed.url).then(next);
|
||||
} else {
|
||||
get(token.embed.url).then(next)
|
||||
get(token.embed.url).then(next);
|
||||
}
|
||||
} else {
|
||||
next(token.embed.html)
|
||||
next(token.embed.html);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function prerenderEmbed({ compiler, raw = '', fetch }, done) {
|
||||
let hit = cached[raw]
|
||||
let hit = cached[raw];
|
||||
if (hit) {
|
||||
const copy = hit.slice()
|
||||
copy.links = hit.links
|
||||
return done(copy)
|
||||
const copy = hit.slice();
|
||||
copy.links = hit.links;
|
||||
return done(copy);
|
||||
}
|
||||
|
||||
const compile = compiler._marked
|
||||
let tokens = compile.lexer(raw)
|
||||
const embedTokens = []
|
||||
const linkRE = compile.InlineLexer.rules.link
|
||||
const links = tokens.links
|
||||
const compile = compiler._marked;
|
||||
let tokens = compile.lexer(raw);
|
||||
const embedTokens = [];
|
||||
const linkRE = compile.InlineLexer.rules.link;
|
||||
const links = tokens.links;
|
||||
|
||||
tokens.forEach((token, index) => {
|
||||
if (token.type === 'paragraph') {
|
||||
token.text = token.text.replace(
|
||||
new RegExp(linkRE.source, 'g'),
|
||||
(src, filename, href, title) => {
|
||||
const embed = compiler.compileEmbed(href, title)
|
||||
const embed = compiler.compileEmbed(href, title);
|
||||
|
||||
if (embed) {
|
||||
embedTokens.push({
|
||||
index,
|
||||
embed
|
||||
})
|
||||
embed,
|
||||
});
|
||||
}
|
||||
|
||||
return src
|
||||
return src;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let moveIndex = 0
|
||||
let moveIndex = 0;
|
||||
walkFetchEmbed({ compile, embedTokens, fetch }, ({ embedToken, token }) => {
|
||||
if (token) {
|
||||
const index = token.index + moveIndex
|
||||
const index = token.index + moveIndex;
|
||||
|
||||
merge(links, embedToken.links)
|
||||
merge(links, embedToken.links);
|
||||
|
||||
tokens = tokens
|
||||
.slice(0, index)
|
||||
.concat(embedToken, tokens.slice(index + 1))
|
||||
moveIndex += embedToken.length - 1
|
||||
.concat(embedToken, tokens.slice(index + 1));
|
||||
moveIndex += embedToken.length - 1;
|
||||
} else {
|
||||
cached[raw] = tokens.concat()
|
||||
tokens.links = cached[raw].links = links
|
||||
done(tokens)
|
||||
cached[raw] = tokens.concat();
|
||||
tokens.links = cached[raw].links = links;
|
||||
done(tokens);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
import {inBrowser} from '../util/env'
|
||||
import { inBrowser } from '../util/env';
|
||||
|
||||
function replace(m, $1) {
|
||||
return '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
|
||||
return (
|
||||
'<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
|
||||
$1 +
|
||||
'.png" alt="' +
|
||||
$1 +
|
||||
'" />'
|
||||
);
|
||||
}
|
||||
|
||||
export function emojify(text) {
|
||||
return text
|
||||
.replace(/<(pre|template|code)[^>]*?>[\s\S]+?<\/(pre|template|code)>/g, m => m.replace(/:/g, '__colon__'))
|
||||
.replace(/:(\w+?):/ig, (inBrowser && window.emojify) || replace)
|
||||
.replace(/__colon__/g, ':')
|
||||
.replace(/<(pre|template|code)[^>]*?>[\s\S]+?<\/(pre|template|code)>/g, m =>
|
||||
m.replace(/:/g, '__colon__')
|
||||
)
|
||||
.replace(/:(\w+?):/gi, (inBrowser && window.emojify) || replace)
|
||||
.replace(/__colon__/g, ':');
|
||||
}
|
||||
|
||||
@ -6,25 +6,25 @@
|
||||
* @return {Array} Headlines
|
||||
*/
|
||||
export function genTree(toc, maxLevel) {
|
||||
const headlines = []
|
||||
const last = {}
|
||||
const headlines = [];
|
||||
const last = {};
|
||||
|
||||
toc.forEach(headline => {
|
||||
const level = headline.level || 1
|
||||
const len = level - 1
|
||||
const level = headline.level || 1;
|
||||
const len = level - 1;
|
||||
|
||||
if (level > maxLevel) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (last[len]) {
|
||||
last[len].children = (last[len].children || []).concat(headline)
|
||||
last[len].children = (last[len].children || []).concat(headline);
|
||||
} else {
|
||||
headlines.push(headline)
|
||||
headlines.push(headline);
|
||||
}
|
||||
|
||||
last[level] = headline
|
||||
})
|
||||
last[level] = headline;
|
||||
});
|
||||
|
||||
return headlines
|
||||
return headlines;
|
||||
}
|
||||
|
||||
@ -1,53 +1,54 @@
|
||||
import * as dom from '../util/dom'
|
||||
import * as tpl from './tpl'
|
||||
import cssVars from '../util/polyfill/css-vars'
|
||||
import tinydate from 'tinydate'
|
||||
import {callHook} from '../init/lifecycle'
|
||||
import {Compiler} from './compiler'
|
||||
import {getAndActive, sticky} from '../event/sidebar'
|
||||
import {getPath, isAbsolutePath} from '../router/util'
|
||||
import {isMobile, inBrowser} from '../util/env'
|
||||
import {isPrimitive} from '../util/core'
|
||||
import {scrollActiveSidebar, scroll2Top} from '../event/scroll'
|
||||
import {prerenderEmbed} from './embed'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import * as dom from '../util/dom';
|
||||
import cssVars from '../util/polyfill/css-vars';
|
||||
import { callHook } from '../init/lifecycle';
|
||||
import { getAndActive, sticky } from '../event/sidebar';
|
||||
import { getPath, isAbsolutePath } from '../router/util';
|
||||
import { isMobile, inBrowser } from '../util/env';
|
||||
import { isPrimitive } from '../util/core';
|
||||
import { scrollActiveSidebar, scroll2Top } from '../event/scroll';
|
||||
import { Compiler } from './compiler';
|
||||
import * as tpl from './tpl';
|
||||
import { prerenderEmbed } from './embed';
|
||||
import tinydate from 'tinydate';
|
||||
|
||||
function executeScript() {
|
||||
const script = dom
|
||||
.findAll('.markdown-section>script')
|
||||
.filter(s => !/template/.test(s.type))[0]
|
||||
.filter(s => !/template/.test(s.type))[0];
|
||||
if (!script) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
const code = script.innerText.trim()
|
||||
const code = script.innerText.trim();
|
||||
if (!code) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
setTimeout(_ => {
|
||||
window.__EXECUTE_RESULT__ = new Function(code)()
|
||||
}, 0)
|
||||
window.__EXECUTE_RESULT__ = new Function(code)();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function formatUpdated(html, updated, fn) {
|
||||
updated =
|
||||
typeof fn === 'function' ?
|
||||
fn(updated) :
|
||||
typeof fn === 'string' ?
|
||||
tinydate(fn)(new Date(updated)) :
|
||||
updated
|
||||
typeof fn === 'function'
|
||||
? fn(updated)
|
||||
: typeof fn === 'string'
|
||||
? tinydate(fn)(new Date(updated))
|
||||
: updated;
|
||||
|
||||
return html.replace(/{docsify-updated}/g, updated)
|
||||
return html.replace(/{docsify-updated}/g, updated);
|
||||
}
|
||||
|
||||
function renderMain(html) {
|
||||
if (!html) {
|
||||
html = '<h1>404 - Not found</h1>'
|
||||
html = '<h1>404 - Not found</h1>';
|
||||
}
|
||||
|
||||
this._renderTo('.markdown-section', html)
|
||||
this._renderTo('.markdown-section', html);
|
||||
// Render sidebar with the TOC
|
||||
!this.config.loadSidebar && this._renderSidebar()
|
||||
!this.config.loadSidebar && this._renderSidebar();
|
||||
|
||||
// Execute script
|
||||
if (
|
||||
@ -56,229 +57,235 @@ function renderMain(html) {
|
||||
!executeScript()
|
||||
) {
|
||||
setTimeout(_ => {
|
||||
const vueVM = window.__EXECUTE_RESULT__
|
||||
vueVM && vueVM.$destroy && vueVM.$destroy()
|
||||
window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main')
|
||||
}, 0)
|
||||
const vueVM = window.__EXECUTE_RESULT__;
|
||||
vueVM && vueVM.$destroy && vueVM.$destroy();
|
||||
window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main');
|
||||
}, 0);
|
||||
} else {
|
||||
this.config.executeScript && executeScript()
|
||||
this.config.executeScript && executeScript();
|
||||
}
|
||||
}
|
||||
|
||||
function renderNameLink(vm) {
|
||||
const el = dom.getNode('.app-name-link')
|
||||
const nameLink = vm.config.nameLink
|
||||
const path = vm.route.path
|
||||
const el = dom.getNode('.app-name-link');
|
||||
const nameLink = vm.config.nameLink;
|
||||
const path = vm.route.path;
|
||||
|
||||
if (!el) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPrimitive(vm.config.nameLink)) {
|
||||
el.setAttribute('href', nameLink)
|
||||
el.setAttribute('href', nameLink);
|
||||
} else if (typeof nameLink === 'object') {
|
||||
const match = Object.keys(nameLink).filter(key => path.indexOf(key) > -1)[0]
|
||||
const match = Object.keys(nameLink).filter(
|
||||
key => path.indexOf(key) > -1
|
||||
)[0];
|
||||
|
||||
el.setAttribute('href', nameLink[match])
|
||||
el.setAttribute('href', nameLink[match]);
|
||||
}
|
||||
}
|
||||
|
||||
export function renderMixin(proto) {
|
||||
proto._renderTo = function (el, content, replace) {
|
||||
const node = dom.getNode(el)
|
||||
proto._renderTo = function(el, content, replace) {
|
||||
const node = dom.getNode(el);
|
||||
if (node) {
|
||||
node[replace ? 'outerHTML' : 'innerHTML'] = content
|
||||
}
|
||||
node[replace ? 'outerHTML' : 'innerHTML'] = content;
|
||||
}
|
||||
};
|
||||
|
||||
proto._renderSidebar = function (text) {
|
||||
const {maxLevel, subMaxLevel, loadSidebar} = this.config
|
||||
proto._renderSidebar = function(text) {
|
||||
const { maxLevel, subMaxLevel, loadSidebar } = this.config;
|
||||
|
||||
this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel))
|
||||
const activeEl = getAndActive(this.router, '.sidebar-nav', true, true)
|
||||
this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel));
|
||||
const activeEl = getAndActive(this.router, '.sidebar-nav', true, true);
|
||||
if (loadSidebar && activeEl) {
|
||||
activeEl.parentNode.innerHTML +=
|
||||
this.compiler.subSidebar(subMaxLevel) || ''
|
||||
this.compiler.subSidebar(subMaxLevel) || '';
|
||||
} else {
|
||||
// Reset toc
|
||||
this.compiler.subSidebar()
|
||||
this.compiler.subSidebar();
|
||||
}
|
||||
|
||||
// Bind event
|
||||
this._bindEventOnRendered(activeEl)
|
||||
}
|
||||
this._bindEventOnRendered(activeEl);
|
||||
};
|
||||
|
||||
proto._bindEventOnRendered = function (activeEl) {
|
||||
const {autoHeader, auto2top} = this.config
|
||||
proto._bindEventOnRendered = function(activeEl) {
|
||||
const { autoHeader, auto2top } = this.config;
|
||||
|
||||
scrollActiveSidebar(this.router)
|
||||
scrollActiveSidebar(this.router);
|
||||
|
||||
if (autoHeader && activeEl) {
|
||||
const main = dom.getNode('#main')
|
||||
const firstNode = main.children[0]
|
||||
const main = dom.getNode('#main');
|
||||
const firstNode = main.children[0];
|
||||
if (firstNode && firstNode.tagName !== 'H1') {
|
||||
const h1 = this.compiler.header(activeEl.innerText, 1)
|
||||
const wrapper = dom.create('div', h1)
|
||||
dom.before(main, wrapper.children[0])
|
||||
const h1 = this.compiler.header(activeEl.innerText, 1);
|
||||
const wrapper = dom.create('div', h1);
|
||||
dom.before(main, wrapper.children[0]);
|
||||
}
|
||||
}
|
||||
|
||||
auto2top && scroll2Top(auto2top)
|
||||
}
|
||||
auto2top && scroll2Top(auto2top);
|
||||
};
|
||||
|
||||
proto._renderNav = function (text) {
|
||||
text && this._renderTo('nav', this.compiler.compile(text))
|
||||
proto._renderNav = function(text) {
|
||||
text && this._renderTo('nav', this.compiler.compile(text));
|
||||
if (this.config.loadNavbar) {
|
||||
getAndActive(this.router, 'nav')
|
||||
}
|
||||
getAndActive(this.router, 'nav');
|
||||
}
|
||||
};
|
||||
|
||||
proto._renderMain = function (text, opt = {}, next) {
|
||||
proto._renderMain = function(text, opt = {}, next) {
|
||||
if (!text) {
|
||||
return renderMain.call(this, text)
|
||||
return renderMain.call(this, text);
|
||||
}
|
||||
|
||||
callHook(this, 'beforeEach', text, result => {
|
||||
let html
|
||||
let html;
|
||||
const callback = () => {
|
||||
if (opt.updatedAt) {
|
||||
html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated)
|
||||
html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated);
|
||||
}
|
||||
|
||||
callHook(this, 'afterEach', html, text => renderMain.call(this, text))
|
||||
}
|
||||
callHook(this, 'afterEach', html, text => renderMain.call(this, text));
|
||||
};
|
||||
|
||||
if (this.isHTML) {
|
||||
html = this.result = text
|
||||
callback()
|
||||
next()
|
||||
html = this.result = text;
|
||||
callback();
|
||||
next();
|
||||
} else {
|
||||
prerenderEmbed(
|
||||
{
|
||||
compiler: this.compiler,
|
||||
raw: result
|
||||
raw: result,
|
||||
},
|
||||
tokens => {
|
||||
html = this.compiler.compile(tokens)
|
||||
callback()
|
||||
next()
|
||||
html = this.compiler.compile(tokens);
|
||||
callback();
|
||||
next();
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
proto._renderCover = function (text, coverOnly) {
|
||||
const el = dom.getNode('.cover')
|
||||
proto._renderCover = function(text, coverOnly) {
|
||||
const el = dom.getNode('.cover');
|
||||
|
||||
dom.toggleClass(dom.getNode('main'), coverOnly ? 'add' : 'remove', 'hidden')
|
||||
dom.toggleClass(
|
||||
dom.getNode('main'),
|
||||
coverOnly ? 'add' : 'remove',
|
||||
'hidden'
|
||||
);
|
||||
if (!text) {
|
||||
dom.toggleClass(el, 'remove', 'show')
|
||||
return
|
||||
dom.toggleClass(el, 'remove', 'show');
|
||||
return;
|
||||
}
|
||||
|
||||
dom.toggleClass(el, 'add', 'show')
|
||||
dom.toggleClass(el, 'add', 'show');
|
||||
|
||||
let html = this.coverIsHTML ? text : this.compiler.cover(text)
|
||||
let html = this.coverIsHTML ? text : this.compiler.cover(text);
|
||||
|
||||
const m = html
|
||||
.trim()
|
||||
.match('<p><img.*?data-origin="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$')
|
||||
.match('<p><img.*?data-origin="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$');
|
||||
|
||||
if (m) {
|
||||
if (m[2] === 'color') {
|
||||
el.style.background = m[1] + (m[3] || '')
|
||||
el.style.background = m[1] + (m[3] || '');
|
||||
} else {
|
||||
let path = m[1]
|
||||
let path = m[1];
|
||||
|
||||
dom.toggleClass(el, 'add', 'has-mask')
|
||||
dom.toggleClass(el, 'add', 'has-mask');
|
||||
if (!isAbsolutePath(m[1])) {
|
||||
path = getPath(this.router.getBasePath(), m[1])
|
||||
path = getPath(this.router.getBasePath(), m[1]);
|
||||
}
|
||||
|
||||
el.style.backgroundImage = `url(${path})`
|
||||
el.style.backgroundSize = 'cover'
|
||||
el.style.backgroundPosition = 'center center'
|
||||
el.style.backgroundImage = `url(${path})`;
|
||||
el.style.backgroundSize = 'cover';
|
||||
el.style.backgroundPosition = 'center center';
|
||||
}
|
||||
|
||||
html = html.replace(m[0], '')
|
||||
html = html.replace(m[0], '');
|
||||
}
|
||||
|
||||
this._renderTo('.cover-main', html)
|
||||
sticky()
|
||||
}
|
||||
this._renderTo('.cover-main', html);
|
||||
sticky();
|
||||
};
|
||||
|
||||
proto._updateRender = function () {
|
||||
proto._updateRender = function() {
|
||||
// Render name link
|
||||
renderNameLink(this)
|
||||
}
|
||||
renderNameLink(this);
|
||||
};
|
||||
}
|
||||
|
||||
export function initRender(vm) {
|
||||
const config = vm.config
|
||||
const config = vm.config;
|
||||
|
||||
// Init markdown compiler
|
||||
vm.compiler = new Compiler(config, vm.router)
|
||||
vm.compiler = new Compiler(config, vm.router);
|
||||
if (inBrowser) {
|
||||
window.__current_docsify_compiler__ = vm.compiler
|
||||
window.__current_docsify_compiler__ = vm.compiler;
|
||||
}
|
||||
|
||||
const id = config.el || '#app'
|
||||
const navEl = dom.find('nav') || dom.create('nav')
|
||||
const id = config.el || '#app';
|
||||
const navEl = dom.find('nav') || dom.create('nav');
|
||||
|
||||
const el = dom.find(id)
|
||||
let html = ''
|
||||
let navAppendToTarget = dom.body
|
||||
const el = dom.find(id);
|
||||
let html = '';
|
||||
let navAppendToTarget = dom.body;
|
||||
|
||||
if (el) {
|
||||
if (config.repo) {
|
||||
html += tpl.corner(config.repo, config.cornerExternalLinkTarge)
|
||||
html += tpl.corner(config.repo, config.cornerExternalLinkTarge);
|
||||
}
|
||||
|
||||
if (config.coverpage) {
|
||||
html += tpl.cover()
|
||||
html += tpl.cover();
|
||||
}
|
||||
|
||||
if (config.logo) {
|
||||
const isBase64 = /^data:image/.test(config.logo)
|
||||
const isExternal = /(?:http[s]?:)?\/\//.test(config.logo)
|
||||
const isRelative = /^\./.test(config.logo)
|
||||
const isBase64 = /^data:image/.test(config.logo);
|
||||
const isExternal = /(?:http[s]?:)?\/\//.test(config.logo);
|
||||
const isRelative = /^\./.test(config.logo);
|
||||
|
||||
if (!isBase64 && !isExternal && !isRelative) {
|
||||
config.logo = getPath(vm.router.getBasePath(), config.logo)
|
||||
config.logo = getPath(vm.router.getBasePath(), config.logo);
|
||||
}
|
||||
}
|
||||
|
||||
html += tpl.main(config)
|
||||
html += tpl.main(config);
|
||||
// Render main app
|
||||
vm._renderTo(el, html, true)
|
||||
vm._renderTo(el, html, true);
|
||||
} else {
|
||||
vm.rendered = true
|
||||
vm.rendered = true;
|
||||
}
|
||||
|
||||
if (config.mergeNavbar && isMobile) {
|
||||
navAppendToTarget = dom.find('.sidebar')
|
||||
navAppendToTarget = dom.find('.sidebar');
|
||||
} else {
|
||||
navEl.classList.add('app-nav')
|
||||
navEl.classList.add('app-nav');
|
||||
|
||||
if (!config.repo) {
|
||||
navEl.classList.add('no-badge')
|
||||
navEl.classList.add('no-badge');
|
||||
}
|
||||
}
|
||||
|
||||
// Add nav
|
||||
if (config.loadNavbar) {
|
||||
dom.before(navAppendToTarget, navEl)
|
||||
dom.before(navAppendToTarget, navEl);
|
||||
}
|
||||
|
||||
if (config.themeColor) {
|
||||
dom.$.head.appendChild(
|
||||
dom.create('div', tpl.theme(config.themeColor)).firstElementChild
|
||||
)
|
||||
);
|
||||
// Polyfll
|
||||
cssVars(config.themeColor)
|
||||
cssVars(config.themeColor);
|
||||
}
|
||||
|
||||
vm._updateRender()
|
||||
dom.toggleClass(dom.body, 'ready')
|
||||
vm._updateRender();
|
||||
dom.toggleClass(dom.body, 'ready');
|
||||
}
|
||||
|
||||
@ -1,42 +1,43 @@
|
||||
import * as dom from '../util/dom'
|
||||
import * as dom from '../util/dom';
|
||||
|
||||
let barEl
|
||||
let timeId
|
||||
let barEl;
|
||||
let timeId;
|
||||
|
||||
/**
|
||||
* Init progress component
|
||||
*/
|
||||
function init() {
|
||||
const div = dom.create('div')
|
||||
const div = dom.create('div');
|
||||
|
||||
div.classList.add('progress')
|
||||
dom.appendTo(dom.body, div)
|
||||
barEl = div
|
||||
div.classList.add('progress');
|
||||
dom.appendTo(dom.body, div);
|
||||
barEl = div;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render progress bar
|
||||
*/
|
||||
export default function ({loaded, total, step}) {
|
||||
let num
|
||||
export default function({ loaded, total, step }) {
|
||||
let num;
|
||||
|
||||
!barEl && init()
|
||||
!barEl && init();
|
||||
|
||||
if (step) {
|
||||
num = parseInt(barEl.style.width || 0, 10) + step
|
||||
num = num > 80 ? 80 : num
|
||||
num = parseInt(barEl.style.width || 0, 10) + step;
|
||||
num = num > 80 ? 80 : num;
|
||||
} else {
|
||||
num = Math.floor(loaded / total * 100)
|
||||
num = Math.floor((loaded / total) * 100);
|
||||
}
|
||||
|
||||
barEl.style.opacity = 1
|
||||
barEl.style.width = num >= 95 ? '100%' : num + '%'
|
||||
barEl.style.opacity = 1;
|
||||
barEl.style.width = num >= 95 ? '100%' : num + '%';
|
||||
|
||||
if (num >= 95) {
|
||||
clearTimeout(timeId)
|
||||
clearTimeout(timeId);
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
timeId = setTimeout(_ => {
|
||||
barEl.style.opacity = 0
|
||||
barEl.style.width = '0%'
|
||||
}, 200)
|
||||
barEl.style.opacity = 0;
|
||||
barEl.style.width = '0%';
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import {hasOwn} from '../util/core'
|
||||
import { hasOwn } from '../util/core';
|
||||
|
||||
let cache = {}
|
||||
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g
|
||||
let cache = {};
|
||||
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g;
|
||||
|
||||
function lower(string) {
|
||||
return string.toLowerCase()
|
||||
return string.toLowerCase();
|
||||
}
|
||||
|
||||
export function slugify(str) {
|
||||
if (typeof str !== 'string') {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
|
||||
let slug = str
|
||||
@ -18,19 +18,19 @@ export function slugify(str) {
|
||||
.replace(/<[^>\d]+>/g, '')
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
let count = cache[slug]
|
||||
.replace(/-+/g, '-');
|
||||
let count = cache[slug];
|
||||
|
||||
count = hasOwn.call(cache, slug) ? count + 1 : 0
|
||||
cache[slug] = count
|
||||
count = hasOwn.call(cache, slug) ? count + 1 : 0;
|
||||
cache[slug] = count;
|
||||
|
||||
if (count) {
|
||||
slug = slug + '-' + count
|
||||
slug = slug + '-' + count;
|
||||
}
|
||||
|
||||
return slug
|
||||
return slug;
|
||||
}
|
||||
|
||||
slugify.clear = function () {
|
||||
cache = {}
|
||||
}
|
||||
slugify.clear = function() {
|
||||
cache = {};
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { isMobile } from '../util/env'
|
||||
import { isMobile } from '../util/env';
|
||||
/**
|
||||
* Render github corner
|
||||
* @param {Object} data URL for the View Source on Github link
|
||||
@ -7,16 +7,16 @@ import { isMobile } from '../util/env'
|
||||
*/
|
||||
export function corner(data, cornerExternalLinkTarge) {
|
||||
if (!data) {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!/\/\//.test(data)) {
|
||||
data = 'https://github.com/' + data
|
||||
data = 'https://github.com/' + data;
|
||||
}
|
||||
|
||||
data = data.replace(/^git\+/, '')
|
||||
data = data.replace(/^git\+/, '');
|
||||
// Double check
|
||||
cornerExternalLinkTarge = cornerExternalLinkTarge || '_blank'
|
||||
cornerExternalLinkTarge = cornerExternalLinkTarge || '_blank';
|
||||
|
||||
return (
|
||||
`<a href="${data}" target="${cornerExternalLinkTarge}" class="github-corner" aria-label="View source on Github">` +
|
||||
@ -26,7 +26,7 @@ export function corner(data, cornerExternalLinkTarge) {
|
||||
'<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>' +
|
||||
'</svg>' +
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,7 +35,7 @@ export function corner(data, cornerExternalLinkTarge) {
|
||||
* @returns {String} HTML of the main content
|
||||
*/
|
||||
export function main(config) {
|
||||
const name = config.name ? config.name : ''
|
||||
const name = config.name ? config.name : '';
|
||||
|
||||
const aside =
|
||||
'<button class="sidebar-toggle" aria-label="Menu">' +
|
||||
@ -44,13 +44,13 @@ export function main(config) {
|
||||
'</div>' +
|
||||
'</button>' +
|
||||
'<aside class="sidebar">' +
|
||||
(config.name ?
|
||||
`<h1 class="app-name"><a class="app-name-link" data-nosearch>${
|
||||
(config.name
|
||||
? `<h1 class="app-name"><a class="app-name-link" data-nosearch>${
|
||||
config.logo ? `<img alt="${name}" src=${config.logo}>` : name
|
||||
}</a></h1>` :
|
||||
'') +
|
||||
}</a></h1>`
|
||||
: '') +
|
||||
'<div class="sidebar-nav"><!--sidebar--></div>' +
|
||||
'</aside>'
|
||||
'</aside>';
|
||||
|
||||
return (
|
||||
(isMobile ? `${aside}<main>` : `<main>${aside}`) +
|
||||
@ -58,7 +58,7 @@ export function main(config) {
|
||||
'<article class="markdown-section" id="main"><!--main--></article>' +
|
||||
'</section>' +
|
||||
'</main>'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,18 +66,18 @@ export function main(config) {
|
||||
* @returns {String} Cover page
|
||||
*/
|
||||
export function cover() {
|
||||
const SL = ', 100%, 85%'
|
||||
const SL = ', 100%, 85%';
|
||||
const bgc =
|
||||
'linear-gradient(to left bottom, ' +
|
||||
`hsl(${Math.floor(Math.random() * 255) + SL}) 0%,` +
|
||||
`hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`
|
||||
`hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`;
|
||||
|
||||
return (
|
||||
`<section class="cover show" style="background: ${bgc}">` +
|
||||
'<div class="cover-main"><!--cover--></div>' +
|
||||
'<div class="mask"></div>' +
|
||||
'</section>'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,23 +88,23 @@ export function cover() {
|
||||
*/
|
||||
export function tree(toc, tpl = '<ul class="app-sub-sidebar">{inner}</ul>') {
|
||||
if (!toc || !toc.length) {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
|
||||
let innerHTML = ''
|
||||
let innerHTML = '';
|
||||
toc.forEach(node => {
|
||||
innerHTML += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
|
||||
innerHTML += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`;
|
||||
if (node.children) {
|
||||
innerHTML += tree(node.children, tpl)
|
||||
innerHTML += tree(node.children, tpl);
|
||||
}
|
||||
})
|
||||
return tpl.replace('{inner}', innerHTML)
|
||||
});
|
||||
return tpl.replace('{inner}', innerHTML);
|
||||
}
|
||||
|
||||
export function helper(className, content) {
|
||||
return `<p class="${className}">${content.slice(5).trim()}</p>`
|
||||
return `<p class="${className}">${content.slice(5).trim()}</p>`;
|
||||
}
|
||||
|
||||
export function theme(color) {
|
||||
return `<style>:root{--theme-color: ${color};}</style>`
|
||||
return `<style>:root{--theme-color: ${color};}</style>`;
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
import {History} from './base'
|
||||
import {parseQuery} from '../util'
|
||||
import { parseQuery } from '../util';
|
||||
import { History } from './base';
|
||||
|
||||
export class AbstractHistory extends History {
|
||||
constructor(config) {
|
||||
super(config)
|
||||
this.mode = 'abstract'
|
||||
super(config);
|
||||
this.mode = 'abstract';
|
||||
}
|
||||
|
||||
parse(path) {
|
||||
let query = ''
|
||||
let query = '';
|
||||
|
||||
const queryIndex = path.indexOf('?')
|
||||
const queryIndex = path.indexOf('?');
|
||||
if (queryIndex >= 0) {
|
||||
query = path.slice(queryIndex + 1)
|
||||
path = path.slice(0, queryIndex)
|
||||
query = path.slice(queryIndex + 1);
|
||||
path = path.slice(0, queryIndex);
|
||||
}
|
||||
|
||||
return {
|
||||
path,
|
||||
file: this.getFile(path),
|
||||
query: parseQuery(query)
|
||||
}
|
||||
query: parseQuery(query),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,57 +4,59 @@ import {
|
||||
stringifyQuery,
|
||||
cleanPath,
|
||||
replaceSlug,
|
||||
resolvePath
|
||||
} from '../util'
|
||||
import {noop, merge} from '../../util/core'
|
||||
resolvePath,
|
||||
} from '../util';
|
||||
import { noop, merge } from '../../util/core';
|
||||
|
||||
const cached = {}
|
||||
const cached = {};
|
||||
|
||||
function getAlias(path, alias, last) {
|
||||
const match = Object.keys(alias).filter(key => {
|
||||
const re = cached[key] || (cached[key] = new RegExp(`^${key}$`))
|
||||
return re.test(path) && path !== last
|
||||
})[0]
|
||||
const re = cached[key] || (cached[key] = new RegExp(`^${key}$`));
|
||||
return re.test(path) && path !== last;
|
||||
})[0];
|
||||
|
||||
return match ?
|
||||
getAlias(path.replace(cached[match], alias[match]), alias, path) :
|
||||
path
|
||||
return match
|
||||
? getAlias(path.replace(cached[match], alias[match]), alias, path)
|
||||
: path;
|
||||
}
|
||||
|
||||
function getFileName(path, ext) {
|
||||
return new RegExp(`\\.(${ext.replace(/^\./, '')}|html)$`, 'g').test(path) ?
|
||||
path :
|
||||
/\/$/g.test(path) ? `${path}README${ext}` : `${path}${ext}`
|
||||
return new RegExp(`\\.(${ext.replace(/^\./, '')}|html)$`, 'g').test(path)
|
||||
? path
|
||||
: /\/$/g.test(path)
|
||||
? `${path}README${ext}`
|
||||
: `${path}${ext}`;
|
||||
}
|
||||
|
||||
export class History {
|
||||
constructor(config) {
|
||||
this.config = config
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
getBasePath() {
|
||||
return this.config.basePath
|
||||
return this.config.basePath;
|
||||
}
|
||||
|
||||
getFile(path = this.getCurrentPath(), isRelative) {
|
||||
const {config} = this
|
||||
const base = this.getBasePath()
|
||||
const ext = typeof config.ext === 'string' ? config.ext : '.md'
|
||||
const { config } = this;
|
||||
const base = this.getBasePath();
|
||||
const ext = typeof config.ext === 'string' ? config.ext : '.md';
|
||||
|
||||
path = config.alias ? getAlias(path, config.alias) : path
|
||||
path = getFileName(path, ext)
|
||||
path = path === `/README${ext}` ? config.homepage || path : path
|
||||
path = isAbsolutePath(path) ? path : getPath(base, path)
|
||||
path = config.alias ? getAlias(path, config.alias) : path;
|
||||
path = getFileName(path, ext);
|
||||
path = path === `/README${ext}` ? config.homepage || path : path;
|
||||
path = isAbsolutePath(path) ? path : getPath(base, path);
|
||||
|
||||
if (isRelative) {
|
||||
path = path.replace(new RegExp(`^${base}`), '')
|
||||
path = path.replace(new RegExp(`^${base}`), '');
|
||||
}
|
||||
|
||||
return path
|
||||
return path;
|
||||
}
|
||||
|
||||
onchange(cb = noop) {
|
||||
cb()
|
||||
cb();
|
||||
}
|
||||
|
||||
getCurrentPath() {}
|
||||
@ -64,24 +66,28 @@ export class History {
|
||||
parse() {}
|
||||
|
||||
toURL(path, params, currentRoute) {
|
||||
const local = currentRoute && path[0] === '#'
|
||||
const route = this.parse(replaceSlug(path))
|
||||
const local = currentRoute && path[0] === '#';
|
||||
const route = this.parse(replaceSlug(path));
|
||||
|
||||
route.query = merge({}, route.query, params)
|
||||
path = route.path + stringifyQuery(route.query)
|
||||
path = path.replace(/\.md(\?)|\.md$/, '$1')
|
||||
route.query = merge({}, route.query, params);
|
||||
path = route.path + stringifyQuery(route.query);
|
||||
path = path.replace(/\.md(\?)|\.md$/, '$1');
|
||||
|
||||
if (local) {
|
||||
const idIndex = currentRoute.indexOf('?')
|
||||
const idIndex = currentRoute.indexOf('?');
|
||||
path =
|
||||
(idIndex > 0 ? currentRoute.substring(0, idIndex) : currentRoute) + path
|
||||
(idIndex > 0 ? currentRoute.substring(0, idIndex) : currentRoute) +
|
||||
path;
|
||||
}
|
||||
|
||||
if (this.config.relativePath && path.indexOf('/') !== 0) {
|
||||
const currentDir = currentRoute.substring(0, currentRoute.lastIndexOf('/') + 1)
|
||||
return cleanPath(resolvePath(currentDir + path))
|
||||
const currentDir = currentRoute.substring(
|
||||
0,
|
||||
currentRoute.lastIndexOf('/') + 1
|
||||
);
|
||||
return cleanPath(resolvePath(currentDir + path));
|
||||
}
|
||||
|
||||
return cleanPath('/' + path)
|
||||
return cleanPath('/' + path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,48 +1,48 @@
|
||||
import { History } from './base'
|
||||
import { noop } from '../../util/core'
|
||||
import { on } from '../../util/dom'
|
||||
import { parseQuery, cleanPath, replaceSlug } from '../util'
|
||||
import { noop } from '../../util/core';
|
||||
import { on } from '../../util/dom';
|
||||
import { parseQuery, cleanPath, replaceSlug } from '../util';
|
||||
import { History } from './base';
|
||||
|
||||
function replaceHash(path) {
|
||||
const i = location.href.indexOf('#')
|
||||
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path)
|
||||
const i = location.href.indexOf('#');
|
||||
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path);
|
||||
}
|
||||
|
||||
export class HashHistory extends History {
|
||||
constructor(config) {
|
||||
super(config)
|
||||
this.mode = 'hash'
|
||||
super(config);
|
||||
this.mode = 'hash';
|
||||
}
|
||||
|
||||
getBasePath() {
|
||||
const path = window.location.pathname || ''
|
||||
const base = this.config.basePath
|
||||
const path = window.location.pathname || '';
|
||||
const base = this.config.basePath;
|
||||
|
||||
return /^(\/|https?:)/g.test(base) ? base : cleanPath(path + '/' + base)
|
||||
return /^(\/|https?:)/g.test(base) ? base : cleanPath(path + '/' + base);
|
||||
}
|
||||
|
||||
getCurrentPath() {
|
||||
// We can't use location.hash here because it's not
|
||||
// consistent across browsers - Firefox will pre-decode it!
|
||||
const href = location.href
|
||||
const index = href.indexOf('#')
|
||||
return index === -1 ? '' : href.slice(index + 1)
|
||||
const href = location.href;
|
||||
const index = href.indexOf('#');
|
||||
return index === -1 ? '' : href.slice(index + 1);
|
||||
}
|
||||
|
||||
onchange(cb = noop) {
|
||||
on('hashchange', cb)
|
||||
on('hashchange', cb);
|
||||
}
|
||||
|
||||
normalize() {
|
||||
let path = this.getCurrentPath()
|
||||
let path = this.getCurrentPath();
|
||||
|
||||
path = replaceSlug(path)
|
||||
path = replaceSlug(path);
|
||||
|
||||
if (path.charAt(0) === '/') {
|
||||
return replaceHash(path)
|
||||
return replaceHash(path);
|
||||
}
|
||||
|
||||
replaceHash('/' + path)
|
||||
replaceHash('/' + path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,27 +51,27 @@ export class HashHistory extends History {
|
||||
* @return {object} { path, query }
|
||||
*/
|
||||
parse(path = location.href) {
|
||||
let query = ''
|
||||
let query = '';
|
||||
|
||||
const hashIndex = path.indexOf('#')
|
||||
const hashIndex = path.indexOf('#');
|
||||
if (hashIndex >= 0) {
|
||||
path = path.slice(hashIndex + 1)
|
||||
path = path.slice(hashIndex + 1);
|
||||
}
|
||||
|
||||
const queryIndex = path.indexOf('?')
|
||||
const queryIndex = path.indexOf('?');
|
||||
if (queryIndex >= 0) {
|
||||
query = path.slice(queryIndex + 1)
|
||||
path = path.slice(0, queryIndex)
|
||||
query = path.slice(queryIndex + 1);
|
||||
path = path.slice(0, queryIndex);
|
||||
}
|
||||
|
||||
return {
|
||||
path,
|
||||
file: this.getFile(path, true),
|
||||
query: parseQuery(query)
|
||||
}
|
||||
query: parseQuery(query),
|
||||
};
|
||||
}
|
||||
|
||||
toURL(path, params, currentRoute) {
|
||||
return '#' + super.toURL(path, params, currentRoute)
|
||||
return '#' + super.toURL(path, params, currentRoute);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
import { History } from './base'
|
||||
import { noop } from '../../util/core'
|
||||
import { on } from '../../util/dom'
|
||||
import { parseQuery, getPath } from '../util'
|
||||
import { noop } from '../../util/core';
|
||||
import { on } from '../../util/dom';
|
||||
import { parseQuery, getPath } from '../util';
|
||||
import { History } from './base';
|
||||
|
||||
export class HTML5History extends History {
|
||||
constructor(config) {
|
||||
super(config)
|
||||
this.mode = 'history'
|
||||
super(config);
|
||||
this.mode = 'history';
|
||||
}
|
||||
|
||||
getCurrentPath() {
|
||||
const base = this.getBasePath()
|
||||
let path = window.location.pathname
|
||||
const base = this.getBasePath();
|
||||
let path = window.location.pathname;
|
||||
|
||||
if (base && path.indexOf(base) === 0) {
|
||||
path = path.slice(base.length)
|
||||
path = path.slice(base.length);
|
||||
}
|
||||
|
||||
return (path || '/') + window.location.search + window.location.hash
|
||||
return (path || '/') + window.location.search + window.location.hash;
|
||||
}
|
||||
|
||||
onchange(cb = noop) {
|
||||
on('click', e => {
|
||||
const el = e.target.tagName === 'A' ? e.target : e.target.parentNode
|
||||
const el = e.target.tagName === 'A' ? e.target : e.target.parentNode;
|
||||
|
||||
if (el.tagName === 'A' && !/_blank/.test(el.target)) {
|
||||
e.preventDefault()
|
||||
const url = el.href
|
||||
window.history.pushState({ key: url }, '', url)
|
||||
cb()
|
||||
e.preventDefault();
|
||||
const url = el.href;
|
||||
window.history.pushState({ key: url }, '', url);
|
||||
cb();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
on('popstate', cb)
|
||||
on('popstate', cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,25 +41,25 @@ export class HTML5History extends History {
|
||||
* @return {object} { path, query }
|
||||
*/
|
||||
parse(path = location.href) {
|
||||
let query = ''
|
||||
let query = '';
|
||||
|
||||
const queryIndex = path.indexOf('?')
|
||||
const queryIndex = path.indexOf('?');
|
||||
if (queryIndex >= 0) {
|
||||
query = path.slice(queryIndex + 1)
|
||||
path = path.slice(0, queryIndex)
|
||||
query = path.slice(queryIndex + 1);
|
||||
path = path.slice(0, queryIndex);
|
||||
}
|
||||
|
||||
const base = getPath(location.origin)
|
||||
const baseIndex = path.indexOf(base)
|
||||
const base = getPath(location.origin);
|
||||
const baseIndex = path.indexOf(base);
|
||||
|
||||
if (baseIndex > -1) {
|
||||
path = path.slice(baseIndex + base.length)
|
||||
path = path.slice(baseIndex + base.length);
|
||||
}
|
||||
|
||||
return {
|
||||
path,
|
||||
file: this.getFile(path),
|
||||
query: parseQuery(query)
|
||||
}
|
||||
query: parseQuery(query),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,45 +1,46 @@
|
||||
import {HashHistory} from './history/hash'
|
||||
import {HTML5History} from './history/html5'
|
||||
import {supportsPushState} from '../util/env'
|
||||
import * as dom from '../util/dom'
|
||||
import { supportsPushState } from '../util/env';
|
||||
import * as dom from '../util/dom';
|
||||
import { HashHistory } from './history/hash';
|
||||
import { HTML5History } from './history/html5';
|
||||
|
||||
export function routerMixin(proto) {
|
||||
proto.route = {}
|
||||
proto.route = {};
|
||||
}
|
||||
|
||||
let lastRoute = {}
|
||||
let lastRoute = {};
|
||||
|
||||
function updateRender(vm) {
|
||||
vm.router.normalize()
|
||||
vm.route = vm.router.parse()
|
||||
dom.body.setAttribute('data-page', vm.route.file)
|
||||
vm.router.normalize();
|
||||
vm.route = vm.router.parse();
|
||||
dom.body.setAttribute('data-page', vm.route.file);
|
||||
}
|
||||
|
||||
export function initRouter(vm) {
|
||||
const config = vm.config
|
||||
const mode = config.routerMode || 'hash'
|
||||
let router
|
||||
const config = vm.config;
|
||||
const mode = config.routerMode || 'hash';
|
||||
let router;
|
||||
|
||||
if (mode === 'history' && supportsPushState) {
|
||||
router = new HTML5History(config)
|
||||
router = new HTML5History(config);
|
||||
} else {
|
||||
router = new HashHistory(config)
|
||||
router = new HashHistory(config);
|
||||
}
|
||||
|
||||
vm.router = router
|
||||
updateRender(vm)
|
||||
lastRoute = vm.route
|
||||
vm.router = router;
|
||||
updateRender(vm);
|
||||
lastRoute = vm.route;
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
router.onchange(_ => {
|
||||
updateRender(vm)
|
||||
vm._updateRender()
|
||||
updateRender(vm);
|
||||
vm._updateRender();
|
||||
|
||||
if (lastRoute.path === vm.route.path) {
|
||||
vm.$resetEvents()
|
||||
return
|
||||
vm.$resetEvents();
|
||||
return;
|
||||
}
|
||||
|
||||
vm.$fetch()
|
||||
lastRoute = vm.route
|
||||
})
|
||||
vm.$fetch();
|
||||
lastRoute = vm.route;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,81 +1,81 @@
|
||||
import { cached } from '../util/core'
|
||||
import { cached } from '../util/core';
|
||||
|
||||
const decode = decodeURIComponent
|
||||
const encode = encodeURIComponent
|
||||
const decode = decodeURIComponent;
|
||||
const encode = encodeURIComponent;
|
||||
|
||||
export function parseQuery(query) {
|
||||
const res = {}
|
||||
const res = {};
|
||||
|
||||
query = query.trim().replace(/^(\?|#|&)/, '')
|
||||
query = query.trim().replace(/^(\?|#|&)/, '');
|
||||
|
||||
if (!query) {
|
||||
return res
|
||||
return res;
|
||||
}
|
||||
|
||||
// Simple parse
|
||||
query.split('&').forEach(function (param) {
|
||||
const parts = param.replace(/\+/g, ' ').split('=')
|
||||
query.split('&').forEach(function(param) {
|
||||
const parts = param.replace(/\+/g, ' ').split('=');
|
||||
|
||||
res[parts[0]] = parts[1] && decode(parts[1])
|
||||
})
|
||||
res[parts[0]] = parts[1] && decode(parts[1]);
|
||||
});
|
||||
|
||||
return res
|
||||
return res;
|
||||
}
|
||||
|
||||
export function stringifyQuery(obj, ignores = []) {
|
||||
const qs = []
|
||||
const qs = [];
|
||||
|
||||
for (const key in obj) {
|
||||
if (ignores.indexOf(key) > -1) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
qs.push(
|
||||
obj[key] ?
|
||||
`${encode(key)}=${encode(obj[key])}`.toLowerCase() :
|
||||
encode(key)
|
||||
)
|
||||
obj[key]
|
||||
? `${encode(key)}=${encode(obj[key])}`.toLowerCase()
|
||||
: encode(key)
|
||||
);
|
||||
}
|
||||
|
||||
return qs.length ? `?${qs.join('&')}` : ''
|
||||
return qs.length ? `?${qs.join('&')}` : '';
|
||||
}
|
||||
|
||||
export const isAbsolutePath = cached(path => {
|
||||
return /(:|(\/{2}))/g.test(path)
|
||||
})
|
||||
return /(:|(\/{2}))/g.test(path);
|
||||
});
|
||||
|
||||
export const getParentPath = cached(path => {
|
||||
if (/\/$/g.test(path)) {
|
||||
return path
|
||||
return path;
|
||||
}
|
||||
|
||||
const matchingParts = path.match(/(\S*\/)[^/]+$/)
|
||||
return matchingParts ? matchingParts[1] : ''
|
||||
})
|
||||
const matchingParts = path.match(/(\S*\/)[^/]+$/);
|
||||
return matchingParts ? matchingParts[1] : '';
|
||||
});
|
||||
|
||||
export const cleanPath = cached(path => {
|
||||
return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/')
|
||||
})
|
||||
return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/');
|
||||
});
|
||||
|
||||
export const resolvePath = cached(path => {
|
||||
const segments = path.replace(/^\//, '').split('/')
|
||||
let resolved = []
|
||||
const segments = path.replace(/^\//, '').split('/');
|
||||
let resolved = [];
|
||||
for (let i = 0, len = segments.length; i < len; i++) {
|
||||
const segment = segments[i]
|
||||
const segment = segments[i];
|
||||
if (segment === '..') {
|
||||
resolved.pop()
|
||||
resolved.pop();
|
||||
} else if (segment !== '.') {
|
||||
resolved.push(segment)
|
||||
resolved.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
return '/' + resolved.join('/')
|
||||
})
|
||||
return '/' + resolved.join('/');
|
||||
});
|
||||
|
||||
export function getPath(...args) {
|
||||
return cleanPath(args.join('/'))
|
||||
return cleanPath(args.join('/'));
|
||||
}
|
||||
|
||||
export const replaceSlug = cached(path => {
|
||||
return path.replace('#', '?id=')
|
||||
})
|
||||
return path.replace('#', '?id=');
|
||||
});
|
||||
|
||||
@ -5,22 +5,22 @@
|
||||
*/
|
||||
|
||||
export function cached(fn) {
|
||||
const cache = Object.create(null)
|
||||
return function (str) {
|
||||
const key = isPrimitive(str) ? str : JSON.stringify(str)
|
||||
const hit = cache[key]
|
||||
return hit || (cache[key] = fn(str))
|
||||
}
|
||||
const cache = Object.create(null);
|
||||
return function(str) {
|
||||
const key = isPrimitive(str) ? str : JSON.stringify(str);
|
||||
const hit = cache[key];
|
||||
return hit || (cache[key] = fn(str));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hyphenate a camelCase string.
|
||||
*/
|
||||
export const hyphenate = cached(str => {
|
||||
return str.replace(/([A-Z])/g, m => '-' + m.toLowerCase())
|
||||
})
|
||||
return str.replace(/([A-Z])/g, m => '-' + m.toLowerCase());
|
||||
});
|
||||
|
||||
export const hasOwn = Object.prototype.hasOwnProperty
|
||||
export const hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Simple Object.assign polyfill
|
||||
@ -29,19 +29,19 @@ export const hasOwn = Object.prototype.hasOwnProperty
|
||||
*/
|
||||
export const merge =
|
||||
Object.assign ||
|
||||
function (to) {
|
||||
function(to) {
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
const from = Object(arguments[i])
|
||||
const from = Object(arguments[i]);
|
||||
|
||||
for (const key in from) {
|
||||
if (hasOwn.call(from, key)) {
|
||||
to[key] = from[key]
|
||||
to[key] = from[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to
|
||||
}
|
||||
return to;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if value is primitive
|
||||
@ -49,14 +49,14 @@ export const merge =
|
||||
* @returns {Boolean} Result of the check
|
||||
*/
|
||||
export function isPrimitive(value) {
|
||||
return typeof value === 'string' || typeof value === 'number'
|
||||
return typeof value === 'string' || typeof value === 'number';
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs no operation.
|
||||
* @void
|
||||
*/
|
||||
export function noop() { }
|
||||
export function noop() {}
|
||||
|
||||
/**
|
||||
* Check if value is function
|
||||
@ -64,6 +64,5 @@ export function noop() { }
|
||||
* @returns {Boolean} True if the passed-in value is a function
|
||||
*/
|
||||
export function isFn(obj) {
|
||||
return typeof obj === 'function'
|
||||
return typeof obj === 'function';
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { isFn } from '../util/core'
|
||||
import { inBrowser } from './env'
|
||||
import { isFn } from '../util/core';
|
||||
import { inBrowser } from './env';
|
||||
|
||||
const cacheNode = {}
|
||||
const cacheNode = {};
|
||||
|
||||
/**
|
||||
* Get Node
|
||||
@ -12,20 +12,20 @@ const cacheNode = {}
|
||||
export function getNode(el, noCache = false) {
|
||||
if (typeof el === 'string') {
|
||||
if (typeof window.Vue !== 'undefined') {
|
||||
return find(el)
|
||||
return find(el);
|
||||
}
|
||||
|
||||
el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el))
|
||||
el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el));
|
||||
}
|
||||
|
||||
return el
|
||||
return el;
|
||||
}
|
||||
|
||||
export const $ = inBrowser && document
|
||||
export const $ = inBrowser && document;
|
||||
|
||||
export const body = inBrowser && $.body
|
||||
export const body = inBrowser && $.body;
|
||||
|
||||
export const head = inBrowser && $.head
|
||||
export const head = inBrowser && $.head;
|
||||
|
||||
/**
|
||||
* Find elements
|
||||
@ -37,7 +37,7 @@ export const head = inBrowser && $.head
|
||||
* find(nav, 'a') => nav.querySelector('a')
|
||||
*/
|
||||
export function find(el, node) {
|
||||
return node ? el.querySelector(node) : $.querySelector(el)
|
||||
return node ? el.querySelector(node) : $.querySelector(el);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,36 +52,36 @@ export function find(el, node) {
|
||||
export function findAll(el, node) {
|
||||
return [].slice.call(
|
||||
node ? el.querySelectorAll(node) : $.querySelectorAll(el)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function create(node, tpl) {
|
||||
node = $.createElement(node)
|
||||
node = $.createElement(node);
|
||||
if (tpl) {
|
||||
node.innerHTML = tpl
|
||||
node.innerHTML = tpl;
|
||||
}
|
||||
|
||||
return node
|
||||
return node;
|
||||
}
|
||||
|
||||
export function appendTo(target, el) {
|
||||
return target.appendChild(el)
|
||||
return target.appendChild(el);
|
||||
}
|
||||
|
||||
export function before(target, el) {
|
||||
return target.insertBefore(el, target.children[0])
|
||||
return target.insertBefore(el, target.children[0]);
|
||||
}
|
||||
|
||||
export function on(el, type, handler) {
|
||||
isFn(type) ?
|
||||
window.addEventListener(el, type) :
|
||||
el.addEventListener(type, handler)
|
||||
isFn(type)
|
||||
? window.addEventListener(el, type)
|
||||
: el.addEventListener(type, handler);
|
||||
}
|
||||
|
||||
export function off(el, type, handler) {
|
||||
isFn(type) ?
|
||||
window.removeEventListener(el, type) :
|
||||
el.removeEventListener(type, handler)
|
||||
isFn(type)
|
||||
? window.removeEventListener(el, type)
|
||||
: el.removeEventListener(type, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,9 +95,9 @@ export function off(el, type, handler) {
|
||||
* toggleClass(el, 'add', 'active') => el.classList.add('active')
|
||||
*/
|
||||
export function toggleClass(el, type, val) {
|
||||
el && el.classList[val ? type : 'toggle'](val || type)
|
||||
el && el.classList[val ? type : 'toggle'](val || type);
|
||||
}
|
||||
|
||||
export function style(content) {
|
||||
appendTo(head, create('style', content))
|
||||
appendTo(head, create('style', content));
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
export const inBrowser = !process.env.SSR
|
||||
export const inBrowser = !process.env.SSR;
|
||||
|
||||
export const isMobile = inBrowser && document.body.clientWidth <= 600
|
||||
export const isMobile = inBrowser && document.body.clientWidth <= 600;
|
||||
|
||||
/**
|
||||
* @see https://github.com/MoOx/pjax/blob/master/lib/is-supported.js
|
||||
*/
|
||||
export const supportsPushState =
|
||||
inBrowser &&
|
||||
(function () {
|
||||
(function() {
|
||||
// Borrowed wholesale from https://github.com/defunkt/jquery-pjax
|
||||
return (
|
||||
window.history &&
|
||||
@ -17,5 +17,5 @@ export const supportsPushState =
|
||||
!navigator.userAgent.match(
|
||||
/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/
|
||||
)
|
||||
)
|
||||
})()
|
||||
);
|
||||
})();
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
export * from './core'
|
||||
export * from './env'
|
||||
export * from '../router/util'
|
||||
export * from './core';
|
||||
export * from './env';
|
||||
export * from '../router/util';
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
import * as dom from '../dom'
|
||||
import {get} from '../../fetch/ajax'
|
||||
import * as dom from '../dom';
|
||||
import { get } from '../../fetch/ajax';
|
||||
|
||||
function replaceVar(block, color) {
|
||||
block.innerHTML = block.innerHTML.replace(
|
||||
/var\(\s*--theme-color.*?\)/g,
|
||||
color
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default function (color) {
|
||||
export default function(color) {
|
||||
// Variable support
|
||||
if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const styleBlocks = dom.findAll('style:not(.inserted),link');
|
||||
[].forEach.call(styleBlocks, block => {
|
||||
if (block.nodeName === 'STYLE') {
|
||||
replaceVar(block, color)
|
||||
replaceVar(block, color);
|
||||
} else if (block.nodeName === 'LINK') {
|
||||
const href = block.getAttribute('href')
|
||||
const href = block.getAttribute('href');
|
||||
|
||||
if (!/\.css$/.test(href)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
get(href).then(res => {
|
||||
const style = dom.create('style', res)
|
||||
const style = dom.create('style', res);
|
||||
|
||||
dom.head.appendChild(style)
|
||||
replaceVar(style, color)
|
||||
})
|
||||
dom.head.appendChild(style);
|
||||
replaceVar(style, color);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,51 +1,52 @@
|
||||
const fixedPath = location.href.replace('/-/', '/#/')
|
||||
/* eslint-disable no-unused-vars */
|
||||
const fixedPath = location.href.replace('/-/', '/#/');
|
||||
if (fixedPath !== location.href) {
|
||||
location.href = fixedPath
|
||||
location.href = fixedPath;
|
||||
}
|
||||
|
||||
function install(hook, vm) {
|
||||
const dom = Docsify.dom
|
||||
const disqus = vm.config.disqus
|
||||
const dom = Docsify.dom;
|
||||
const disqus = vm.config.disqus;
|
||||
if (!disqus) {
|
||||
throw Error('$docsify.disqus is required')
|
||||
throw Error('$docsify.disqus is required');
|
||||
}
|
||||
|
||||
hook.init(_ => {
|
||||
const script = dom.create('script')
|
||||
const script = dom.create('script');
|
||||
|
||||
script.async = true
|
||||
script.src = `https://${disqus}.disqus.com/embed.js`
|
||||
script.setAttribute('data-timestamp', Number(new Date()))
|
||||
dom.appendTo(dom.body, script)
|
||||
})
|
||||
script.async = true;
|
||||
script.src = `https://${disqus}.disqus.com/embed.js`;
|
||||
script.setAttribute('data-timestamp', Number(new Date()));
|
||||
dom.appendTo(dom.body, script);
|
||||
});
|
||||
|
||||
hook.mounted(_ => {
|
||||
const div = dom.create('div')
|
||||
div.id = 'disqus_thread'
|
||||
const main = dom.getNode('#main')
|
||||
div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`
|
||||
dom.appendTo(dom.find('.content'), div)
|
||||
const div = dom.create('div');
|
||||
div.id = 'disqus_thread';
|
||||
const main = dom.getNode('#main');
|
||||
div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`;
|
||||
dom.appendTo(dom.find('.content'), div);
|
||||
|
||||
// eslint-disable-next-line
|
||||
window.disqus_config = function() {
|
||||
this.page.url = location.origin + '/-' + vm.route.path
|
||||
this.page.identifier = vm.route.path
|
||||
this.page.title = document.title
|
||||
}
|
||||
})
|
||||
this.page.url = location.origin + '/-' + vm.route.path;
|
||||
this.page.identifier = vm.route.path;
|
||||
this.page.title = document.title;
|
||||
};
|
||||
});
|
||||
|
||||
hook.doneEach(_ => {
|
||||
if (typeof window.DISQUS !== 'undefined') {
|
||||
window.DISQUS.reset({
|
||||
reload: true,
|
||||
config: function () {
|
||||
this.page.url = location.origin + '/-' + vm.route.path
|
||||
this.page.identifier = vm.route.path
|
||||
this.page.title = document.title
|
||||
config: function() {
|
||||
this.page.url = location.origin + '/-' + vm.route.path;
|
||||
this.page.identifier = vm.route.path;
|
||||
this.page.title = document.title;
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1508,17 +1508,17 @@ const AllGithubEmoji = [
|
||||
'zero',
|
||||
'zimbabwe',
|
||||
'zipper_mouth_face',
|
||||
'zzz'
|
||||
]
|
||||
'zzz',
|
||||
];
|
||||
|
||||
// Emoji from All-Github-Emoji-Icons
|
||||
// https://github.com/scotch-io/All-Github-Emoji-Icons
|
||||
window.emojify = function (match, $1) {
|
||||
return AllGithubEmoji.indexOf($1) === -1 ?
|
||||
match :
|
||||
'<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
|
||||
window.emojify = function(match, $1) {
|
||||
return AllGithubEmoji.indexOf($1) === -1
|
||||
? match
|
||||
: '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
|
||||
$1 +
|
||||
'.png" alt="' +
|
||||
$1 +
|
||||
'" />'
|
||||
}
|
||||
'" />';
|
||||
};
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
function handleExternalScript() {
|
||||
const container = Docsify.dom.getNode('#main')
|
||||
const scripts = Docsify.dom.findAll(container, 'script')
|
||||
const container = Docsify.dom.getNode('#main');
|
||||
const scripts = Docsify.dom.findAll(container, 'script');
|
||||
|
||||
for (let i = scripts.length; i--;) {
|
||||
const script = scripts[i]
|
||||
for (let i = scripts.length; i--; ) {
|
||||
const script = scripts[i];
|
||||
|
||||
if (script && script.src) {
|
||||
const newScript = document.createElement('script')
|
||||
const newScript = document.createElement('script');
|
||||
|
||||
Array.prototype.slice.call(script.attributes).forEach(attribute => {
|
||||
newScript[attribute.name] = attribute.value
|
||||
})
|
||||
newScript[attribute.name] = attribute.value;
|
||||
});
|
||||
|
||||
script.parentNode.insertBefore(newScript, script)
|
||||
script.parentNode.removeChild(script)
|
||||
script.parentNode.insertBefore(newScript, script);
|
||||
script.parentNode.removeChild(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const install = function (hook) {
|
||||
hook.doneEach(handleExternalScript)
|
||||
}
|
||||
const install = function(hook) {
|
||||
hook.doneEach(handleExternalScript);
|
||||
};
|
||||
|
||||
window.$docsify.plugins = [].concat(install, window.$docsify.plugins)
|
||||
window.$docsify.plugins = [].concat(install, window.$docsify.plugins);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import parser from './parser'
|
||||
import parser from './parser';
|
||||
|
||||
const install = function (hook, vm) {
|
||||
const install = function(hook, vm) {
|
||||
hook.beforeEach(content => {
|
||||
const {attributes, body} = parser(content)
|
||||
const { attributes, body } = parser(content);
|
||||
|
||||
vm.frontmatter = attributes
|
||||
vm.frontmatter = attributes;
|
||||
|
||||
return body
|
||||
})
|
||||
}
|
||||
return body;
|
||||
});
|
||||
};
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1,39 +1,40 @@
|
||||
/* eslint-disable no-console */
|
||||
// From https://github.com/egoist/vue-ga/blob/master/src/index.js
|
||||
function appendScript() {
|
||||
const script = document.createElement('script')
|
||||
script.async = true
|
||||
script.src = 'https://www.google-analytics.com/analytics.js'
|
||||
document.body.appendChild(script)
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = 'https://www.google-analytics.com/analytics.js';
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
function init(id) {
|
||||
appendScript()
|
||||
appendScript();
|
||||
window.ga =
|
||||
window.ga ||
|
||||
function () {
|
||||
(window.ga.q = window.ga.q || []).push(arguments)
|
||||
}
|
||||
function() {
|
||||
(window.ga.q = window.ga.q || []).push(arguments);
|
||||
};
|
||||
|
||||
window.ga.l = Number(new Date())
|
||||
window.ga('create', id, 'auto')
|
||||
window.ga.l = Number(new Date());
|
||||
window.ga('create', id, 'auto');
|
||||
}
|
||||
|
||||
function collect() {
|
||||
if (!window.ga) {
|
||||
init($docsify.ga)
|
||||
init($docsify.ga);
|
||||
}
|
||||
|
||||
window.ga('set', 'page', location.hash)
|
||||
window.ga('send', 'pageview')
|
||||
window.ga('set', 'page', location.hash);
|
||||
window.ga('send', 'pageview');
|
||||
}
|
||||
|
||||
const install = function (hook) {
|
||||
const install = function(hook) {
|
||||
if (!$docsify.ga) {
|
||||
console.error('[Docsify] ga is required.')
|
||||
return
|
||||
console.error('[Docsify] ga is required.');
|
||||
return;
|
||||
}
|
||||
|
||||
hook.beforeEach(collect)
|
||||
}
|
||||
hook.beforeEach(collect);
|
||||
};
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
function install(hook) {
|
||||
const dom = Docsify.dom
|
||||
const dom = Docsify.dom;
|
||||
|
||||
hook.mounted(_ => {
|
||||
const div = dom.create('div')
|
||||
div.id = 'gitalk-container'
|
||||
const main = dom.getNode('#main')
|
||||
div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`
|
||||
dom.appendTo(dom.find('.content'), div)
|
||||
})
|
||||
const div = dom.create('div');
|
||||
div.id = 'gitalk-container';
|
||||
const main = dom.getNode('#main');
|
||||
div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`;
|
||||
dom.appendTo(dom.find('.content'), div);
|
||||
});
|
||||
|
||||
hook.doneEach(_ => {
|
||||
const el = document.getElementById('gitalk-container')
|
||||
const el = document.getElementById('gitalk-container');
|
||||
while (el.hasChildNodes()) {
|
||||
el.removeChild(el.firstChild)
|
||||
el.removeChild(el.firstChild);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
gitalk.render('gitalk-container')
|
||||
})
|
||||
gitalk.render('gitalk-container');
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1,38 +1,39 @@
|
||||
function appendScript(options) {
|
||||
const script = document.createElement('script')
|
||||
script.async = true
|
||||
script.src = options.host + '/matomo.js'
|
||||
document.body.appendChild(script)
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = options.host + '/matomo.js';
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
function init(options) {
|
||||
window._paq = window._paq || []
|
||||
window._paq.push(['trackPageView'])
|
||||
window._paq.push(['enableLinkTracking'])
|
||||
setTimeout(function () {
|
||||
appendScript(options)
|
||||
window._paq.push(['setTrackerUrl', options.host + '/matomo.php'])
|
||||
window._paq.push(['setSiteId', String(options.id)])
|
||||
}, 0)
|
||||
window._paq = window._paq || [];
|
||||
window._paq.push(['trackPageView']);
|
||||
window._paq.push(['enableLinkTracking']);
|
||||
setTimeout(function() {
|
||||
appendScript(options);
|
||||
window._paq.push(['setTrackerUrl', options.host + '/matomo.php']);
|
||||
window._paq.push(['setSiteId', String(options.id)]);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function collect() {
|
||||
if (!window._paq) {
|
||||
init($docsify.matomo)
|
||||
init($docsify.matomo);
|
||||
}
|
||||
|
||||
window._paq.push(['setCustomUrl', window.location.hash.substr(1)])
|
||||
window._paq.push(['setDocumentTitle', document.title])
|
||||
window._paq.push(['trackPageView'])
|
||||
window._paq.push(['setCustomUrl', window.location.hash.substr(1)]);
|
||||
window._paq.push(['setDocumentTitle', document.title]);
|
||||
window._paq.push(['trackPageView']);
|
||||
}
|
||||
|
||||
const install = function (hook) {
|
||||
const install = function(hook) {
|
||||
if (!$docsify.matomo) {
|
||||
console.error('[Docsify] matomo is required.')
|
||||
return
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[Docsify] matomo is required.');
|
||||
return;
|
||||
}
|
||||
|
||||
hook.beforeEach(collect)
|
||||
}
|
||||
hook.beforeEach(collect);
|
||||
};
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import {search} from './search'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { search } from './search';
|
||||
|
||||
let NO_DATA_TEXT = ''
|
||||
let options
|
||||
let NO_DATA_TEXT = '';
|
||||
let options;
|
||||
|
||||
function style() {
|
||||
const code = `
|
||||
@ -97,14 +98,13 @@ function style() {
|
||||
|
||||
.app-name.hide, .sidebar-nav.hide {
|
||||
display: none;
|
||||
}`
|
||||
}`;
|
||||
|
||||
Docsify.dom.style(code)
|
||||
Docsify.dom.style(code);
|
||||
}
|
||||
|
||||
function tpl(defaultValue = '') {
|
||||
const html =
|
||||
`<div class="input-wrap">
|
||||
const html = `<div class="input-wrap">
|
||||
<input type="search" value="${defaultValue}" aria-label="Search text" />
|
||||
<div class="clear-button">
|
||||
<svg width="26" height="24">
|
||||
@ -115,120 +115,120 @@ function tpl(defaultValue = '') {
|
||||
</div>
|
||||
</div>
|
||||
<div class="results-panel"></div>
|
||||
</div>`
|
||||
const el = Docsify.dom.create('div', html)
|
||||
const aside = Docsify.dom.find('aside')
|
||||
</div>`;
|
||||
const el = Docsify.dom.create('div', html);
|
||||
const aside = Docsify.dom.find('aside');
|
||||
|
||||
Docsify.dom.toggleClass(el, 'search')
|
||||
Docsify.dom.before(aside, el)
|
||||
Docsify.dom.toggleClass(el, 'search');
|
||||
Docsify.dom.before(aside, el);
|
||||
}
|
||||
|
||||
function doSearch(value) {
|
||||
const $search = Docsify.dom.find('div.search')
|
||||
const $panel = Docsify.dom.find($search, '.results-panel')
|
||||
const $clearBtn = Docsify.dom.find($search, '.clear-button')
|
||||
const $sidebarNav = Docsify.dom.find('.sidebar-nav')
|
||||
const $appName = Docsify.dom.find('.app-name')
|
||||
const $search = Docsify.dom.find('div.search');
|
||||
const $panel = Docsify.dom.find($search, '.results-panel');
|
||||
const $clearBtn = Docsify.dom.find($search, '.clear-button');
|
||||
const $sidebarNav = Docsify.dom.find('.sidebar-nav');
|
||||
const $appName = Docsify.dom.find('.app-name');
|
||||
|
||||
if (!value) {
|
||||
$panel.classList.remove('show')
|
||||
$clearBtn.classList.remove('show')
|
||||
$panel.innerHTML = ''
|
||||
$panel.classList.remove('show');
|
||||
$clearBtn.classList.remove('show');
|
||||
$panel.innerHTML = '';
|
||||
|
||||
if (options.hideOtherSidebarContent) {
|
||||
$sidebarNav.classList.remove('hide')
|
||||
$appName.classList.remove('hide')
|
||||
$sidebarNav.classList.remove('hide');
|
||||
$appName.classList.remove('hide');
|
||||
}
|
||||
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const matchs = search(value)
|
||||
const matchs = search(value);
|
||||
|
||||
let html = ''
|
||||
let html = '';
|
||||
matchs.forEach(post => {
|
||||
html += `<div class="matching-post">
|
||||
<a href="${post.url}">
|
||||
<h2>${post.title}</h2>
|
||||
<p>${post.content}</p>
|
||||
</a>
|
||||
</div>`
|
||||
})
|
||||
</div>`;
|
||||
});
|
||||
|
||||
$panel.classList.add('show')
|
||||
$clearBtn.classList.add('show')
|
||||
$panel.innerHTML = html || `<p class="empty">${NO_DATA_TEXT}</p>`
|
||||
$panel.classList.add('show');
|
||||
$clearBtn.classList.add('show');
|
||||
$panel.innerHTML = html || `<p class="empty">${NO_DATA_TEXT}</p>`;
|
||||
if (options.hideOtherSidebarContent) {
|
||||
$sidebarNav.classList.add('hide')
|
||||
$appName.classList.add('hide')
|
||||
$sidebarNav.classList.add('hide');
|
||||
$appName.classList.add('hide');
|
||||
}
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
const $search = Docsify.dom.find('div.search')
|
||||
const $input = Docsify.dom.find($search, 'input')
|
||||
const $inputWrap = Docsify.dom.find($search, '.input-wrap')
|
||||
const $search = Docsify.dom.find('div.search');
|
||||
const $input = Docsify.dom.find($search, 'input');
|
||||
const $inputWrap = Docsify.dom.find($search, '.input-wrap');
|
||||
|
||||
let timeId
|
||||
let timeId;
|
||||
// Prevent to Fold sidebar
|
||||
Docsify.dom.on(
|
||||
$search,
|
||||
'click',
|
||||
e => e.target.tagName !== 'A' && e.stopPropagation()
|
||||
)
|
||||
);
|
||||
Docsify.dom.on($input, 'input', e => {
|
||||
clearTimeout(timeId)
|
||||
timeId = setTimeout(_ => doSearch(e.target.value.trim()), 100)
|
||||
})
|
||||
clearTimeout(timeId);
|
||||
timeId = setTimeout(_ => doSearch(e.target.value.trim()), 100);
|
||||
});
|
||||
Docsify.dom.on($inputWrap, 'click', e => {
|
||||
// Click input outside
|
||||
if (e.target.tagName !== 'INPUT') {
|
||||
$input.value = ''
|
||||
doSearch()
|
||||
$input.value = '';
|
||||
doSearch();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function updatePlaceholder(text, path) {
|
||||
const $input = Docsify.dom.getNode('.search input[type="search"]')
|
||||
const $input = Docsify.dom.getNode('.search input[type="search"]');
|
||||
|
||||
if (!$input) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof text === 'string') {
|
||||
$input.placeholder = text
|
||||
$input.placeholder = text;
|
||||
} else {
|
||||
const match = Object.keys(text).filter(key => path.indexOf(key) > -1)[0]
|
||||
$input.placeholder = text[match]
|
||||
const match = Object.keys(text).filter(key => path.indexOf(key) > -1)[0];
|
||||
$input.placeholder = text[match];
|
||||
}
|
||||
}
|
||||
|
||||
function updateNoData(text, path) {
|
||||
if (typeof text === 'string') {
|
||||
NO_DATA_TEXT = text
|
||||
NO_DATA_TEXT = text;
|
||||
} else {
|
||||
const match = Object.keys(text).filter(key => path.indexOf(key) > -1)[0]
|
||||
NO_DATA_TEXT = text[match]
|
||||
const match = Object.keys(text).filter(key => path.indexOf(key) > -1)[0];
|
||||
NO_DATA_TEXT = text[match];
|
||||
}
|
||||
}
|
||||
|
||||
function updateOptions(opts) {
|
||||
options = opts
|
||||
options = opts;
|
||||
}
|
||||
|
||||
export function init(opts, vm) {
|
||||
const keywords = vm.router.parse().query.s
|
||||
const keywords = vm.router.parse().query.s;
|
||||
|
||||
updateOptions(opts)
|
||||
style()
|
||||
tpl(keywords)
|
||||
bindEvents()
|
||||
keywords && setTimeout(_ => doSearch(keywords), 500)
|
||||
updateOptions(opts);
|
||||
style();
|
||||
tpl(keywords);
|
||||
bindEvents();
|
||||
keywords && setTimeout(_ => doSearch(keywords), 500);
|
||||
}
|
||||
|
||||
export function update(opts, vm) {
|
||||
updateOptions(opts)
|
||||
updatePlaceholder(opts.placeholder, vm.route.path)
|
||||
updateNoData(opts.noData, vm.route.path)
|
||||
updateOptions(opts);
|
||||
updatePlaceholder(opts.placeholder, vm.route.path);
|
||||
updateNoData(opts.noData, vm.route.path);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {init as initComponet, update as updateComponent} from './component'
|
||||
import {init as initSearch} from './search'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { init as initComponet, update as updateComponent } from './component';
|
||||
import { init as initSearch } from './search';
|
||||
|
||||
const CONFIG = {
|
||||
placeholder: 'Type to search',
|
||||
@ -8,35 +9,36 @@ const CONFIG = {
|
||||
depth: 2,
|
||||
maxAge: 86400000, // 1 day
|
||||
hideOtherSidebarContent: false,
|
||||
namespace: undefined
|
||||
}
|
||||
namespace: undefined,
|
||||
};
|
||||
|
||||
const install = function (hook, vm) {
|
||||
const {util} = Docsify
|
||||
const opts = vm.config.search || CONFIG
|
||||
const install = function(hook, vm) {
|
||||
const { util } = Docsify;
|
||||
const opts = vm.config.search || CONFIG;
|
||||
|
||||
if (Array.isArray(opts)) {
|
||||
CONFIG.paths = opts
|
||||
CONFIG.paths = opts;
|
||||
} else if (typeof opts === 'object') {
|
||||
CONFIG.paths = Array.isArray(opts.paths) ? opts.paths : 'auto'
|
||||
CONFIG.maxAge = util.isPrimitive(opts.maxAge) ? opts.maxAge : CONFIG.maxAge
|
||||
CONFIG.placeholder = opts.placeholder || CONFIG.placeholder
|
||||
CONFIG.noData = opts.noData || CONFIG.noData
|
||||
CONFIG.depth = opts.depth || CONFIG.depth
|
||||
CONFIG.hideOtherSidebarContent = opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent
|
||||
CONFIG.namespace = opts.namespace || CONFIG.namespace
|
||||
CONFIG.paths = Array.isArray(opts.paths) ? opts.paths : 'auto';
|
||||
CONFIG.maxAge = util.isPrimitive(opts.maxAge) ? opts.maxAge : CONFIG.maxAge;
|
||||
CONFIG.placeholder = opts.placeholder || CONFIG.placeholder;
|
||||
CONFIG.noData = opts.noData || CONFIG.noData;
|
||||
CONFIG.depth = opts.depth || CONFIG.depth;
|
||||
CONFIG.hideOtherSidebarContent =
|
||||
opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent;
|
||||
CONFIG.namespace = opts.namespace || CONFIG.namespace;
|
||||
}
|
||||
|
||||
const isAuto = CONFIG.paths === 'auto'
|
||||
const isAuto = CONFIG.paths === 'auto';
|
||||
|
||||
hook.mounted(_ => {
|
||||
initComponet(CONFIG, vm)
|
||||
!isAuto && initSearch(CONFIG, vm)
|
||||
})
|
||||
initComponet(CONFIG, vm);
|
||||
!isAuto && initSearch(CONFIG, vm);
|
||||
});
|
||||
hook.doneEach(_ => {
|
||||
updateComponent(CONFIG, vm)
|
||||
isAuto && initSearch(CONFIG, vm)
|
||||
})
|
||||
}
|
||||
updateComponent(CONFIG, vm);
|
||||
isAuto && initSearch(CONFIG, vm);
|
||||
});
|
||||
};
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
let INDEXS = {}
|
||||
/* eslint-disable no-unused-vars */
|
||||
let INDEXS = {};
|
||||
|
||||
const LOCAL_STORAGE = {
|
||||
EXPIRE_KEY: 'docsify.search.expires',
|
||||
INDEX_KEY: 'docsify.search.index'
|
||||
}
|
||||
INDEX_KEY: 'docsify.search.index',
|
||||
};
|
||||
|
||||
function resolveExpireKey(namespace) {
|
||||
return namespace ? `${LOCAL_STORAGE.EXPIRE_KEY}/${namespace}` : LOCAL_STORAGE.EXPIRE_KEY
|
||||
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
|
||||
return namespace
|
||||
? `${LOCAL_STORAGE.INDEX_KEY}/${namespace}`
|
||||
: LOCAL_STORAGE.INDEX_KEY;
|
||||
}
|
||||
|
||||
function escapeHtml(string) {
|
||||
@ -19,72 +24,78 @@ function escapeHtml(string) {
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'/': '/'
|
||||
}
|
||||
"'": ''',
|
||||
'/': '/',
|
||||
};
|
||||
|
||||
return String(string).replace(/[&<>"'/]/g, s => entityMap[s])
|
||||
return String(string).replace(/[&<>"'/]/g, s => entityMap[s]);
|
||||
}
|
||||
|
||||
function getAllPaths(router) {
|
||||
const paths = []
|
||||
const paths = [];
|
||||
|
||||
Docsify.dom.findAll('.sidebar-nav a:not(.section-link):not([data-nosearch])').forEach(node => {
|
||||
const href = node.href
|
||||
const originHref = node.getAttribute('href')
|
||||
const path = router.parse(href).path
|
||||
Docsify.dom
|
||||
.findAll('.sidebar-nav a:not(.section-link):not([data-nosearch])')
|
||||
.forEach(node => {
|
||||
const href = node.href;
|
||||
const originHref = node.getAttribute('href');
|
||||
const path = router.parse(href).path;
|
||||
|
||||
if (
|
||||
path &&
|
||||
paths.indexOf(path) === -1 &&
|
||||
!Docsify.util.isAbsolutePath(originHref)
|
||||
) {
|
||||
paths.push(path)
|
||||
paths.push(path);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return paths
|
||||
return paths;
|
||||
}
|
||||
|
||||
function saveData(maxAge, expireKey, indexKey) {
|
||||
localStorage.setItem(expireKey, Date.now() + maxAge)
|
||||
localStorage.setItem(indexKey, JSON.stringify(INDEXS))
|
||||
localStorage.setItem(expireKey, Date.now() + maxAge);
|
||||
localStorage.setItem(indexKey, JSON.stringify(INDEXS));
|
||||
}
|
||||
|
||||
export function genIndex(path, content = '', router, depth) {
|
||||
const tokens = window.marked.lexer(content)
|
||||
const slugify = window.Docsify.slugify
|
||||
const index = {}
|
||||
let slug
|
||||
const tokens = window.marked.lexer(content);
|
||||
const slugify = window.Docsify.slugify;
|
||||
const index = {};
|
||||
let slug;
|
||||
|
||||
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
|
||||
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 || '')
|
||||
index[slug].body += '\n' + (token.text || '');
|
||||
} else {
|
||||
if (!token.text) {
|
||||
if (token.type === 'table') {
|
||||
token.text = token.cells.map(function (rows) {
|
||||
return rows.join(' | ')
|
||||
}).join(' |\n ')
|
||||
token.text = token.cells
|
||||
.map(function(rows) {
|
||||
return rows.join(' | ');
|
||||
})
|
||||
.join(' |\n ');
|
||||
}
|
||||
}
|
||||
|
||||
index[slug].body = (index[slug].body ? index[slug].body + token.text : token.text)
|
||||
index[slug].body = index[slug].body
|
||||
? index[slug].body + token.text
|
||||
: token.text;
|
||||
}
|
||||
}
|
||||
})
|
||||
slugify.clear()
|
||||
return index
|
||||
});
|
||||
slugify.clear();
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,25 +103,25 @@ export function genIndex(path, content = '', router, depth) {
|
||||
* @returns {Array} Array of results
|
||||
*/
|
||||
export function search(query) {
|
||||
const matchingResults = []
|
||||
let data = []
|
||||
const matchingResults = [];
|
||||
let data = [];
|
||||
Object.keys(INDEXS).forEach(key => {
|
||||
data = data.concat(Object.keys(INDEXS[key]).map(page => INDEXS[key][page]))
|
||||
})
|
||||
data = data.concat(Object.keys(INDEXS[key]).map(page => INDEXS[key][page]));
|
||||
});
|
||||
|
||||
query = query.trim()
|
||||
let keywords = query.split(/[\s\-,\\/]+/)
|
||||
query = query.trim();
|
||||
let keywords = query.split(/[\s\-,\\/]+/);
|
||||
if (keywords.length !== 1) {
|
||||
keywords = [].concat(query, keywords)
|
||||
keywords = [].concat(query, keywords);
|
||||
}
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const post = data[i]
|
||||
let matchesScore = 0
|
||||
let resultStr = ''
|
||||
const postTitle = post.title && post.title.trim()
|
||||
const postContent = post.body && post.body.trim()
|
||||
const postUrl = post.slug || ''
|
||||
const post = data[i];
|
||||
let matchesScore = 0;
|
||||
let resultStr = '';
|
||||
const postTitle = post.title && post.title.trim();
|
||||
const postContent = post.body && post.body.trim();
|
||||
const postUrl = post.slug || '';
|
||||
|
||||
if (postTitle) {
|
||||
keywords.forEach(keyword => {
|
||||
@ -118,27 +129,27 @@ export function search(query) {
|
||||
const regEx = new RegExp(
|
||||
keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
|
||||
'gi'
|
||||
)
|
||||
let indexTitle = -1
|
||||
let indexContent = -1
|
||||
);
|
||||
let indexTitle = -1;
|
||||
let indexContent = -1;
|
||||
|
||||
indexTitle = postTitle ? postTitle.search(regEx) : -1
|
||||
indexContent = postContent ? postContent.search(regEx) : -1
|
||||
indexTitle = postTitle ? postTitle.search(regEx) : -1;
|
||||
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
|
||||
indexContent = 0;
|
||||
}
|
||||
|
||||
let start = 0
|
||||
let end = 0
|
||||
let start = 0;
|
||||
let end = 0;
|
||||
|
||||
start = indexContent < 11 ? 0 : indexContent - 10
|
||||
end = start === 0 ? 70 : indexContent + keyword.length + 60
|
||||
start = indexContent < 11 ? 0 : indexContent - 10;
|
||||
end = start === 0 ? 70 : indexContent + keyword.length + 60;
|
||||
|
||||
if (postContent && end > postContent.length) {
|
||||
end = postContent.length
|
||||
end = postContent.length;
|
||||
}
|
||||
|
||||
const matchContent =
|
||||
@ -146,58 +157,58 @@ export function search(query) {
|
||||
escapeHtml(postContent)
|
||||
.substring(start, end)
|
||||
.replace(regEx, `<em class="search-keyword">${keyword}</em>`) +
|
||||
'...'
|
||||
'...';
|
||||
|
||||
resultStr += matchContent
|
||||
resultStr += matchContent;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (matchesScore > 0) {
|
||||
const matchingPost = {
|
||||
title: escapeHtml(postTitle),
|
||||
content: postContent ? resultStr : '',
|
||||
url: postUrl,
|
||||
score: matchesScore
|
||||
}
|
||||
score: matchesScore,
|
||||
};
|
||||
|
||||
matchingResults.push(matchingPost)
|
||||
matchingResults.push(matchingPost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingResults.sort((r1, r2) => r2.score - r1.score)
|
||||
return matchingResults.sort((r1, r2) => r2.score - r1.score);
|
||||
}
|
||||
|
||||
export function init(config, vm) {
|
||||
const isAuto = config.paths === 'auto'
|
||||
const isAuto = config.paths === 'auto';
|
||||
|
||||
const expireKey = resolveExpireKey(config.namespace)
|
||||
const indexKey = resolveIndexKey(config.namespace)
|
||||
const expireKey = resolveExpireKey(config.namespace);
|
||||
const indexKey = resolveIndexKey(config.namespace);
|
||||
|
||||
const isExpired = localStorage.getItem(expireKey) < Date.now()
|
||||
const isExpired = localStorage.getItem(expireKey) < Date.now();
|
||||
|
||||
INDEXS = JSON.parse(localStorage.getItem(indexKey))
|
||||
INDEXS = JSON.parse(localStorage.getItem(indexKey));
|
||||
|
||||
if (isExpired) {
|
||||
INDEXS = {}
|
||||
INDEXS = {};
|
||||
} else if (!isAuto) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const paths = isAuto ? getAllPaths(vm.router) : config.paths
|
||||
const len = paths.length
|
||||
let count = 0
|
||||
const paths = isAuto ? getAllPaths(vm.router) : config.paths;
|
||||
const len = paths.length;
|
||||
let count = 0;
|
||||
|
||||
paths.forEach(path => {
|
||||
if (INDEXS[path]) {
|
||||
return count++
|
||||
return count++;
|
||||
}
|
||||
|
||||
Docsify
|
||||
.get(vm.router.getFile(path), false, vm.config.requestHeaders)
|
||||
.then(result => {
|
||||
INDEXS[path] = genIndex(path, result, vm.router, config.depth)
|
||||
len === ++count && saveData(config.maxAge, expireKey, indexKey)
|
||||
})
|
||||
})
|
||||
Docsify.get(vm.router.getFile(path), false, vm.config.requestHeaders).then(
|
||||
result => {
|
||||
INDEXS[path] = genIndex(path, result, vm.router, config.depth);
|
||||
len === ++count && saveData(config.maxAge, expireKey, indexKey);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,21 +1,30 @@
|
||||
import mediumZoom from 'medium-zoom'
|
||||
/* eslint-disable no-unused-vars */
|
||||
import mediumZoom from 'medium-zoom';
|
||||
|
||||
const matchesSelector = Element.prototype.matches || Element.prototype.webkitMatchesSelector || Element.prototype.msMatchesSelector
|
||||
const matchesSelector =
|
||||
Element.prototype.matches ||
|
||||
Element.prototype.webkitMatchesSelector ||
|
||||
Element.prototype.msMatchesSelector;
|
||||
|
||||
function install(hook) {
|
||||
let zoom
|
||||
let zoom;
|
||||
|
||||
hook.doneEach(_ => {
|
||||
let elms = Array.apply(null, document.querySelectorAll('.markdown-section img:not(.emoji):not([data-no-zoom])'))
|
||||
let elms = Array.apply(
|
||||
null,
|
||||
document.querySelectorAll(
|
||||
'.markdown-section img:not(.emoji):not([data-no-zoom])'
|
||||
)
|
||||
);
|
||||
|
||||
elms = elms.filter(elm => matchesSelector.call(elm, 'a img') === false)
|
||||
elms = elms.filter(elm => matchesSelector.call(elm, 'a img') === false);
|
||||
|
||||
if (zoom) {
|
||||
zoom.detach()
|
||||
zoom.detach();
|
||||
}
|
||||
|
||||
zoom = mediumZoom(elms)
|
||||
})
|
||||
zoom = mediumZoom(elms);
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins)
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
|
||||
100
test/_helper.js
100
test/_helper.js
@ -1,22 +1,29 @@
|
||||
/* eslint-disable no-global-assign */
|
||||
// Load ES6 modules in Node.js on the fly
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
require = require('esm')(
|
||||
module /* , options */
|
||||
); /* eslint-disable-line no-global-assign */
|
||||
|
||||
const path = require('path')
|
||||
const { expect } = require('chai')
|
||||
const path = require('path');
|
||||
const { expect } = require('chai');
|
||||
|
||||
const { JSDOM } = require('jsdom')
|
||||
const { JSDOM } = require('jsdom');
|
||||
|
||||
function ready(callback) {
|
||||
const state = document.readyState
|
||||
const state = document.readyState;
|
||||
|
||||
if (state === 'complete' || state === 'interactive') {
|
||||
return setTimeout(callback, 0)
|
||||
return setTimeout(callback, 0);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', callback)
|
||||
document.addEventListener('DOMContentLoaded', callback);
|
||||
}
|
||||
|
||||
module.exports.init = function (fixture = 'default', config = {}, markup = null) {
|
||||
module.exports.init = function(
|
||||
fixture = 'default',
|
||||
config = {},
|
||||
markup = null
|
||||
) {
|
||||
if (markup === null || markup === undefined) {
|
||||
markup = `<!DOCTYPE html>
|
||||
<html>
|
||||
@ -27,64 +34,67 @@ module.exports.init = function (fixture = 'default', config = {}, markup = null)
|
||||
window.$docsify = ${JSON.stringify(config, null, 2)}
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
</html>`;
|
||||
}
|
||||
|
||||
const rootPath = path.join(__dirname, 'fixtures', fixture)
|
||||
const rootPath = path.join(__dirname, 'fixtures', fixture);
|
||||
|
||||
const dom = new JSDOM(markup)
|
||||
dom.reconfigure({ url: 'file:///' + rootPath })
|
||||
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
|
||||
global.window = dom.window;
|
||||
global.document = dom.window.document;
|
||||
global.navigator = dom.window.navigator;
|
||||
global.location = dom.window.location;
|
||||
global.XMLHttpRequest = dom.window.XMLHttpRequest;
|
||||
|
||||
// Mimic src/core/index.js but for Node.js
|
||||
function Docsify() {
|
||||
this._init()
|
||||
this._init();
|
||||
}
|
||||
|
||||
const proto = Docsify.prototype
|
||||
const proto = Docsify.prototype;
|
||||
|
||||
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')
|
||||
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');
|
||||
|
||||
initMixin(proto)
|
||||
routerMixin(proto)
|
||||
renderMixin(proto)
|
||||
fetchMixin(proto)
|
||||
eventMixin(proto)
|
||||
initMixin(proto);
|
||||
routerMixin(proto);
|
||||
renderMixin(proto);
|
||||
fetchMixin(proto);
|
||||
eventMixin(proto);
|
||||
|
||||
const NOT_INIT_PATTERN = '<!--main-->'
|
||||
const NOT_INIT_PATTERN = '<!--main-->';
|
||||
|
||||
return new Promise(resolve => {
|
||||
ready(() => {
|
||||
const docsify = new Docsify()
|
||||
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)
|
||||
if (
|
||||
dom.window.document.body.innerHTML.indexOf(NOT_INIT_PATTERN) === -1
|
||||
) {
|
||||
clearInterval(id);
|
||||
return resolve({
|
||||
docsify: docsify,
|
||||
dom: dom
|
||||
})
|
||||
dom: dom,
|
||||
});
|
||||
}
|
||||
}, 10)
|
||||
})
|
||||
})
|
||||
}
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.expectSameDom = function (actual, expected) {
|
||||
const WHITESPACES_BETWEEN_TAGS = />(\s\s+)</g
|
||||
module.exports.expectSameDom = function(actual, expected) {
|
||||
const WHITESPACES_BETWEEN_TAGS = />(\s\s+)</g;
|
||||
function replacer(match, group1) {
|
||||
return match.replace(group1, '')
|
||||
return match.replace(group1, '');
|
||||
}
|
||||
|
||||
expect(actual.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
.equal(expected.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
|
||||
}
|
||||
expect(actual.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim()).equal(
|
||||
expected.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim()
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
const { init } = require('../_helper')
|
||||
// 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)
|
||||
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,9 +1,9 @@
|
||||
const { init } = require('../_helper')
|
||||
const { init } = require('../_helper');
|
||||
|
||||
describe('router', function () {
|
||||
it('TODO: trigger to load another page', async function () {
|
||||
await init()
|
||||
window.location = '/?foo=bar'
|
||||
describe('router', function() {
|
||||
it('TODO: trigger to load another page', async function() {
|
||||
await init();
|
||||
window.location = '/?foo=bar';
|
||||
// TODO: add some expectations
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,61 +1,64 @@
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
const { expect } = require('chai')
|
||||
const { History } = require('../../src/core/router/history/base')
|
||||
/* eslint-disable no-global-assign */
|
||||
require = require('esm')(
|
||||
module /* , options */
|
||||
); /* eslint-disable-line no-global-assign */
|
||||
const { History } = require('../../src/core/router/history/base');
|
||||
const { expect } = require('chai');
|
||||
|
||||
class MockHistory extends History {
|
||||
parse(path) {
|
||||
return { path }
|
||||
return { path };
|
||||
}
|
||||
}
|
||||
|
||||
describe('router/history/base', function () {
|
||||
describe('relativePath true', function () {
|
||||
var history
|
||||
describe('router/history/base', function() {
|
||||
describe('relativePath true', function() {
|
||||
let history;
|
||||
|
||||
beforeEach(function () {
|
||||
history = new MockHistory({ relativePath: true })
|
||||
})
|
||||
beforeEach(function() {
|
||||
history = new MockHistory({ relativePath: true });
|
||||
});
|
||||
|
||||
it('toURL', function () {
|
||||
it('toURL', function() {
|
||||
// WHEN
|
||||
const url = history.toURL('guide.md', {}, '/zh-ch/')
|
||||
const url = history.toURL('guide.md', {}, '/zh-ch/');
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/guide')
|
||||
})
|
||||
expect(url).equal('/zh-ch/guide');
|
||||
});
|
||||
|
||||
it('toURL with double dot', function () {
|
||||
it('toURL with double dot', function() {
|
||||
// WHEN
|
||||
const url = history.toURL('../README.md', {}, '/zh-ch/')
|
||||
const url = history.toURL('../README.md', {}, '/zh-ch/');
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
expect(url).equal('/README');
|
||||
});
|
||||
|
||||
it('toURL child path', function () {
|
||||
it('toURL child path', function() {
|
||||
// WHEN
|
||||
const url = history.toURL('config/example.md', {}, '/zh-ch/')
|
||||
const url = history.toURL('config/example.md', {}, '/zh-ch/');
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/zh-ch/config/example')
|
||||
})
|
||||
expect(url).equal('/zh-ch/config/example');
|
||||
});
|
||||
|
||||
it('toURL absolute path', function () {
|
||||
it('toURL absolute path', function() {
|
||||
// WHEN
|
||||
const url = history.toURL('/README', {}, '/zh-ch/')
|
||||
const url = history.toURL('/README', {}, '/zh-ch/');
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
expect(url).equal('/README');
|
||||
});
|
||||
});
|
||||
|
||||
it('toURL without relative path', function () {
|
||||
const history = new MockHistory({ relativePath: false })
|
||||
it('toURL without relative path', function() {
|
||||
const history = new MockHistory({ relativePath: false });
|
||||
|
||||
// WHEN
|
||||
const url = history.toURL('README', {}, '/zh-ch/')
|
||||
const url = history.toURL('README', {}, '/zh-ch/');
|
||||
|
||||
// THEN
|
||||
expect(url).equal('/README')
|
||||
})
|
||||
})
|
||||
expect(url).equal('/README');
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,78 +1,93 @@
|
||||
const { expect } = require('chai')
|
||||
const { init, expectSameDom } = require('../_helper');
|
||||
const { expect } = require('chai');
|
||||
|
||||
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 } = 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 } = await init()
|
||||
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">
|
||||
- [ ] Task 3`);
|
||||
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>`)
|
||||
})
|
||||
</ul>`
|
||||
);
|
||||
});
|
||||
|
||||
it('as ordered task list', async function () {
|
||||
const { docsify } = await init()
|
||||
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">
|
||||
2. [x] Task 2`);
|
||||
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>`)
|
||||
})
|
||||
</ol>`
|
||||
);
|
||||
});
|
||||
|
||||
it('normal unordered', async function () {
|
||||
const { docsify } = await init()
|
||||
it('normal unordered', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(`
|
||||
- [linktext](link)
|
||||
- just text`)
|
||||
expectSameDom(output, `<ul >
|
||||
- just text`);
|
||||
expectSameDom(
|
||||
output,
|
||||
`<ul >
|
||||
<li><a href="#/link" >linktext</a></li>
|
||||
<li>just text</li>
|
||||
</ul>`)
|
||||
})
|
||||
</ul>`
|
||||
);
|
||||
});
|
||||
|
||||
it('unordered with custom start', async function () {
|
||||
const { docsify } = await init()
|
||||
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 >
|
||||
3. third`);
|
||||
expectSameDom(
|
||||
output,
|
||||
`<ol >
|
||||
<li>first</li>
|
||||
<li>second</li>
|
||||
</ol>
|
||||
<p>text</p>
|
||||
<ol start="3">
|
||||
<li>third</li>
|
||||
</ol>`)
|
||||
})
|
||||
</ol>`
|
||||
);
|
||||
});
|
||||
|
||||
it('nested', async function () {
|
||||
const { docsify } = await init()
|
||||
it('nested', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(`
|
||||
- 1
|
||||
- 2
|
||||
- 2 a
|
||||
- 2 b
|
||||
- 3`)
|
||||
expectSameDom(output, `<ul >
|
||||
- 3`);
|
||||
expectSameDom(
|
||||
output,
|
||||
`<ul >
|
||||
<li>1</li>
|
||||
<li>2<ul >
|
||||
<li>2 a</li>
|
||||
@ -80,158 +95,228 @@ text
|
||||
</ul>
|
||||
</li>
|
||||
<li>3</li>
|
||||
</ul>`)
|
||||
})
|
||||
})
|
||||
</ul>`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('image', function () {
|
||||
it('regular', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
describe('image', function() {
|
||||
it('regular', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('');
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" /></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('class', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
it('class', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
""
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" class="someCssClass" /></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" class="someCssClass" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('id', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
it('id', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
""
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" id="someCssID" /></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" id="someCssID" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('no-zoom', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
it('no-zoom', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
""
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" data-no-zoom /></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" data-no-zoom /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
describe('size', function () {
|
||||
it('width and height', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
describe('size', function() {
|
||||
it('width and height', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
""
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" width="WIDTH" height="HEIGHT" /></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" width="WIDTH" height="HEIGHT" /></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('width', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('')
|
||||
it('width', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
""
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" width="50" height="50" /></p>')
|
||||
})
|
||||
})
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><img src="http://imageUrl" data-origin="http://imageUrl" alt="alt text" width="50" height="50" /></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('heading', function () {
|
||||
it('h1', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('# h1 tag')
|
||||
expectSameDom(output, `
|
||||
describe('heading', function() {
|
||||
it('h1', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('# h1 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h1 id="h1-tag">
|
||||
<a href="#/?id=h1-tag" data-id="h1-tag" class="anchor">
|
||||
<span>h1 tag</span>
|
||||
</a>
|
||||
</h1>`)
|
||||
})
|
||||
</h1>`
|
||||
);
|
||||
});
|
||||
|
||||
it('h2', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('## h2 tag')
|
||||
expectSameDom(output, `
|
||||
it('h2', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('## h2 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h2 id="h2-tag">
|
||||
<a href="#/?id=h2-tag" data-id="h2-tag" class="anchor">
|
||||
<span>h2 tag</span>
|
||||
</a>
|
||||
</h2>`)
|
||||
})
|
||||
</h2>`
|
||||
);
|
||||
});
|
||||
|
||||
it('h3', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('### h3 tag')
|
||||
expectSameDom(output, `
|
||||
it('h3', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('### h3 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h3 id="h3-tag">
|
||||
<a href="#/?id=h3-tag" data-id="h3-tag" class="anchor">
|
||||
<span>h3 tag</span>
|
||||
</a>
|
||||
</h3>`)
|
||||
})
|
||||
</h3>`
|
||||
);
|
||||
});
|
||||
|
||||
it('h4', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('#### h4 tag')
|
||||
expectSameDom(output, `
|
||||
it('h4', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('#### h4 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h4 id="h4-tag">
|
||||
<a href="#/?id=h4-tag" data-id="h4-tag" class="anchor">
|
||||
<span>h4 tag</span>
|
||||
</a>
|
||||
</h4>`)
|
||||
})
|
||||
</h4>`
|
||||
);
|
||||
});
|
||||
|
||||
it('h5', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('##### h5 tag')
|
||||
expectSameDom(output, `
|
||||
it('h5', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('##### h5 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h5 id="h5-tag">
|
||||
<a href="#/?id=h5-tag" data-id="h5-tag" class="anchor">
|
||||
<span>h5 tag</span>
|
||||
</a>
|
||||
</h5>`)
|
||||
})
|
||||
</h5>`
|
||||
);
|
||||
});
|
||||
|
||||
it('h6', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('###### h6 tag')
|
||||
expectSameDom(output, `
|
||||
it('h6', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('###### h6 tag');
|
||||
expectSameDom(
|
||||
output,
|
||||
`
|
||||
<h6 id="h6-tag">
|
||||
<a href="#/?id=h6-tag" data-id="h6-tag" class="anchor">
|
||||
<span>h6 tag</span>
|
||||
</a>
|
||||
</h6>`)
|
||||
})
|
||||
})
|
||||
</h6>`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('link', function () {
|
||||
it('regular', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('[alt text](http://url)')
|
||||
describe('link', function() {
|
||||
it('regular', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile('[alt text](http://url)');
|
||||
|
||||
expectSameDom(output, '<p><a href="http://url" target="_blank">alt text</a></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><a href="http://url" target="_blank">alt text</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('disabled', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('[alt text](http://url \':disabled\')')
|
||||
it('disabled', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
"[alt text](http://url ':disabled')"
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><a href="javascript:void(0)" target="_blank" disabled>alt text</a></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><a href="javascript:void(0)" target="_blank" disabled>alt text</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('target', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('[alt text](http://url \':target=_self\')')
|
||||
it('target', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
"[alt text](http://url ':target=_self')"
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><a href="http://url" target="_blank" target="_self">alt text</a></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><a href="http://url" target="_blank" target="_self">alt text</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('class', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('[alt text](http://url \':class=someCssClass\')')
|
||||
it('class', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
"[alt text](http://url ':class=someCssClass')"
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><a href="http://url" target="_blank" class="someCssClass">alt text</a></p>')
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><a href="http://url" target="_blank" class="someCssClass">alt text</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
it('id', async function () {
|
||||
const { docsify } = await init()
|
||||
const output = docsify.compiler.compile('[alt text](http://url \':id=someCssID\')')
|
||||
it('id', async function() {
|
||||
const { docsify } = await init();
|
||||
const output = docsify.compiler.compile(
|
||||
"[alt text](http://url ':id=someCssID')"
|
||||
);
|
||||
|
||||
expectSameDom(output, '<p><a href="http://url" target="_blank" id="someCssID">alt text</a></p>')
|
||||
})
|
||||
})
|
||||
})
|
||||
expectSameDom(
|
||||
output,
|
||||
'<p><a href="http://url" target="_blank" id="someCssID">alt text</a></p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,29 +1,32 @@
|
||||
require = require('esm')(module/* , options */) /* eslint-disable-line no-global-assign */
|
||||
const { expect } = require('chai')
|
||||
const { resolvePath } = require('../../src/core/router/util')
|
||||
/* eslint-disable no-global-assign */
|
||||
require = require('esm')(
|
||||
module /* , options */
|
||||
); /* eslint-disable-line no-global-assign */
|
||||
const { resolvePath } = require('../../src/core/router/util');
|
||||
const { expect } = require('chai');
|
||||
|
||||
describe('router/util', function () {
|
||||
it('resolvePath', async function () {
|
||||
describe('router/util', function() {
|
||||
it('resolvePath', async function() {
|
||||
// WHEN
|
||||
const result = resolvePath('hello.md')
|
||||
const result = resolvePath('hello.md');
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
expect(result).equal('/hello.md');
|
||||
});
|
||||
|
||||
it('resolvePath with dot', async function () {
|
||||
it('resolvePath with dot', async function() {
|
||||
// WHEN
|
||||
const result = resolvePath('./hello.md')
|
||||
const result = resolvePath('./hello.md');
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
expect(result).equal('/hello.md');
|
||||
});
|
||||
|
||||
it('resolvePath with two dots', async function () {
|
||||
it('resolvePath with two dots', async function() {
|
||||
// WHEN
|
||||
const result = resolvePath('test/../hello.md')
|
||||
const result = resolvePath('test/../hello.md');
|
||||
|
||||
// THEN
|
||||
expect(result).equal('/hello.md')
|
||||
})
|
||||
})
|
||||
expect(result).equal('/hello.md');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user