Compare commits

...
36 Commits
Author SHA1 Message Date
qingwei.li e737a42f75 chore: add changelog 4.6.7 2018-03-03 23:29:17 +08:00
qingwei.li a850b29545 [build] 4.6.7 2018-03-03 23:29:16 +08:00
qingwei.li aeb692ed6b fix: layout css, fixed #409 2018-03-03 23:28:33 +08:00
qingwei.li 01140ceb54 chore: add changelog 4.6.6 2018-03-03 23:21:12 +08:00
qingwei.li 87129c0fb2 [build] 4.6.6 2018-03-03 23:21:11 +08:00
qingwei.li 95e95bd23b chore: remove fuck cssnano-cli 2018-03-03 23:20:07 +08:00
qingwei.li 8974f3964e chore: add changelog 4.6.5 2018-03-03 22:57:35 +08:00
qingwei.li 75222209da [build] 4.6.5 2018-03-03 22:57:34 +08:00
cinwell.liandGitHub 8352a1e489 refactor: build config (#408)
* refactor: build config

* chore: fix conflict

* fix: 404 page path
2018-03-03 22:51:27 +08:00
Romain Lenzottiandcinwell.li 9b3b4454de feat(config): Add 404 page options. (#406)
This feature add the notFoundPage options to customize the default 404 page
with a markdown file. It also support the localisation.
2018-03-03 22:09:01 +08:00
Romain Lenzottiandcinwell.li 0933445e89 fix(navbar): Now Navbar isn't append to DOM when loadNavbar is falsy (#407) 2018-03-03 21:34:42 +08:00
qingwei.li ec8daca3ec chore: add changelog 4.6.4 2018-03-01 22:42:48 +08:00
qingwei.li 1335baa22f [build] 4.6.4 2018-03-01 22:42:48 +08:00
qingwei.li 123c516836 docs: add fallbackLanguages 2018-03-01 22:40:55 +08:00
Romain Lenzottiandcinwell.li ecc0e04c70 feat(fetch): Add fallback languages configuration. (#402)
fallbackLanguages give the possibility to configure a list of languages which must used the default language when a page is missing in the requested language.
2018-03-01 22:37:30 +08:00
Romain Lenzottiandcinwell.li 278a75ebd5 fix(render): Disable markdown parsing when the file is an HTML (#403) 2018-03-01 22:27:30 +08:00
Romain Lenzottiandcinwell.li b8a4e6ba1b chore: Update dev task in package.json (#404)
- Add rimraf to remove file (Windows/Unix/Mac compliant)
- Add concurrently module to run node app and nodemon concurrently
2018-03-01 22:21:14 +08:00
qingwei.li 01bbbaaf92 fix typo 2018-02-23 11:56:51 +08:00
qingwei.li e5c64a3d8f fix typo 2018-02-23 11:56:12 +08:00
qingwei.li e5ae6e8d25 Merge branch 'master' of github.com:qingwei-li/docsify 2018-02-15 18:36:03 +08:00
qingwei.li 702bb5b715 chore: add changelog 4.6.3 2018-02-15 18:34:48 +08:00
qingwei.li 7cdf751cc5 [build] 4.6.3 2018-02-15 18:34:47 +08:00
qingwei.li 6a09059645 fix(hook): beforeEach don\'t work, fixed #393 2018-02-15 18:34:19 +08:00
Jingjie Yang 杨竞颉andcinwell.li 84f7b5c7c2 chore: typo (#392)
> Only coverpage is loaded when ~~When~~ visiting the home page.
2018-02-15 08:57:17 +08:00
qingwei.li fd14e14022 chore: add changelog 4.6.2 2018-02-14 13:17:26 +08:00
qingwei.li 4b5185f0d7 [build] 4.6.2 2018-02-14 13:17:25 +08:00
qingwei.li 45a7464d23 fix(embed): broken in IE, fixed #389, fixed #391 2018-02-14 13:16:38 +08:00
qingwei.li 222cfdbbe4 chore: update readme 2018-02-13 17:18:53 +08:00
qingwei.li 890a7bf9b6 fix(embed): init value 2018-02-12 16:45:24 +08:00
qingwei.li edc3201367 chore: update changelog 2018-02-12 16:30:17 +08:00
qingwei.li 8dd4378e89 chore: add changelog 4.6.1 2018-02-12 16:28:38 +08:00
qingwei.li 149d9929f8 [build] 4.6.1 2018-02-12 16:28:37 +08:00
qingwei.li 50fe22563b chore: fix lint 2018-02-12 16:28:10 +08:00
qingwei.li 4aafde85fb chore: remove console.log 2018-02-12 16:25:28 +08:00
qingwei.li dc0c3ced4e fix(embed): compatible ssr 2018-02-12 16:25:28 +08:00
qingwei.li 62ce447fc3 refactor(embed): async fetch embed files, fixed #387 2018-02-12 16:25:28 +08:00
92 changed files with 5562 additions and 6108 deletions
+4 -2
View File
@@ -1,3 +1,5 @@
.git/
.git
packages/docsify-server-renderer/build.js
node_modules
node_modules
build
server.js
+14 -9
View File
@@ -1,15 +1,20 @@
{
"extends": [
"vue"
],
"parserOptions": {
"ecmaVersion": 8
},
"env": {
"browser": true
"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",
"no-warning-comments": "off"
},
"globals": {
"Docsify": true,
"$docsify": true
"$docsify": true,
"process": true
}
}
+1
View File
@@ -3,3 +3,4 @@
/themes/
node_modules
/lib/
.idea
+136 -173
View File
@@ -1,7 +1,82 @@
<a name="4.6.0"></a>
# [4.6.0](https://github.com/QingWei-Li/docsify/compare/v4.5.9...v4.6.0) (2018-02-11)
<a name="4.6.7"></a>
## [4.6.7](https://github.com/QingWei-Li/docsify/compare/v4.6.6...v4.6.7) (2018-03-03)
### Bug Fixes
* layout css, fixed [#409](https://github.com/QingWei-Li/docsify/issues/409) ([aeb692e](https://github.com/QingWei-Li/docsify/commit/aeb692e))
<a name="4.6.6"></a>
## [4.6.6](https://github.com/QingWei-Li/docsify/compare/v4.6.5...v4.6.6) (2018-03-03)
<a name="4.6.5"></a>
## [4.6.5](https://github.com/QingWei-Li/docsify/compare/v4.6.4...v4.6.5) (2018-03-03)
### Bug Fixes
* **navbar:** Now Navbar isn't append to DOM when loadNavbar is falsy ([#407](https://github.com/QingWei-Li/docsify/issues/407)) ([0933445](https://github.com/QingWei-Li/docsify/commit/0933445))
### Features
* **config:** Add 404 page options. ([#406](https://github.com/QingWei-Li/docsify/issues/406)) ([9b3b445](https://github.com/QingWei-Li/docsify/commit/9b3b445))
<a name="4.6.4"></a>
## [4.6.4](https://github.com/QingWei-Li/docsify/compare/v4.6.3...v4.6.4) (2018-03-01)
### Bug Fixes
* **render:** Disable markdown parsing when the file is an HTML ([#403](https://github.com/QingWei-Li/docsify/issues/403)) ([278a75e](https://github.com/QingWei-Li/docsify/commit/278a75e))
### Features
* **fetch:** Add fallback languages configuration. ([#402](https://github.com/QingWei-Li/docsify/issues/402)) ([ecc0e04](https://github.com/QingWei-Li/docsify/commit/ecc0e04))
<a name="4.6.3"></a>
## [4.6.3](https://github.com/QingWei-Li/docsify/compare/v4.6.2...v4.6.3) (2018-02-15)
### Bug Fixes
* **hook:** beforeEach don\'t work, fixed [#393](https://github.com/QingWei-Li/docsify/issues/393) ([6a09059](https://github.com/QingWei-Li/docsify/commit/6a09059))
<a name="4.6.2"></a>
## [4.6.2](https://github.com/QingWei-Li/docsify/compare/v4.6.1...v4.6.2) (2018-02-14)
### Bug Fixes
* **embed:** broken in IE, fixed [#389](https://github.com/QingWei-Li/docsify/issues/389), fixed [#391](https://github.com/QingWei-Li/docsify/issues/391) ([45a7464](https://github.com/QingWei-Li/docsify/commit/45a7464))
* **embed:** init value ([890a7bf](https://github.com/QingWei-Li/docsify/commit/890a7bf))
<a name="4.6.1"></a>
## [4.6.1](https://github.com/QingWei-Li/docsify/compare/v4.6.0...v4.6.1) (2018-02-12)
### Bug Fixes
* **embed** compatible ssr ([dc0c3ce](https://github.com/QingWei-Li/docsify/commit/dc0c3ce))
* **embed** async fetch embed files, fixed [#387](https://github.com/QingWei-Li/docsify/issues/387)
<a name="4.6.0"></a>
# [4.6.0](https://github.com/QingWei-Li/docsify/compare/v4.5.9...v4.6.0) (2018-02-11)
### Bug Fixes
* **search:** custom clear button, fixed [#271](https://github.com/QingWei-Li/docsify/issues/271) ([864aa18](https://github.com/QingWei-Li/docsify/commit/864aa18))
@@ -15,7 +90,6 @@
* ssr compatible embedd ([ebc10c4](https://github.com/QingWei-Li/docsify/commit/ebc10c4))
* ssr coverpage, fixed [#273](https://github.com/QingWei-Li/docsify/issues/273) ([9e824a4](https://github.com/QingWei-Li/docsify/commit/9e824a4))
### Features
* click sidebar menu add collapse and expand, close [#294](https://github.com/QingWei-Li/docsify/issues/294) ([5e161a1](https://github.com/QingWei-Li/docsify/commit/5e161a1))
@@ -26,21 +100,17 @@
* **render:** add ext option for custom file extenstion, close [#340](https://github.com/QingWei-Li/docsify/issues/340) ([248aa72](https://github.com/QingWei-Li/docsify/commit/248aa72))
* **render:** mutilple coverpage, close [#315](https://github.com/QingWei-Li/docsify/issues/315) ([f68ddf5](https://github.com/QingWei-Li/docsify/commit/f68ddf5))
<a name="4.5.9"></a>
## [4.5.9](https://github.com/QingWei-Li/docsify/compare/v4.5.8...v4.5.9) (2018-02-07)
## [4.5.9](https://github.com/QingWei-Li/docsify/compare/v4.5.8...v4.5.9) (2018-02-07)
### Bug Fixes
* upgrade marked ([4157173](https://github.com/QingWei-Li/docsify/commit/4157173))
<a name="4.5.8"></a>
## [4.5.8](https://github.com/QingWei-Li/docsify/compare/v4.5.6...v4.5.8) (2018-02-07)
## [4.5.8](https://github.com/QingWei-Li/docsify/compare/v4.5.6...v4.5.8) (2018-02-07)
### Bug Fixes
@@ -48,440 +118,360 @@
* updated deps ([#337](https://github.com/QingWei-Li/docsify/issues/337)) ([a12d393](https://github.com/QingWei-Li/docsify/commit/a12d393))
<a name="4.5.7"></a>
## [4.5.7](https://github.com/QingWei-Li/docsify/compare/v4.5.6...v4.5.7) (2017-12-29)
## [4.5.7](https://github.com/QingWei-Li/docsify/compare/v4.5.6...v4.5.7) (2017-12-29)
### Features
* add navigation plugin, closed [#180](https://github.com/QingWei-Li/docsify/issues/180) ([f78be4c](https://github.com/QingWei-Li/docsify/commit/f78be4c))
<a name="4.5.6"></a>
## [4.5.6](https://github.com/QingWei-Li/docsify/compare/v4.5.3...v4.5.6) (2017-12-14)
## [4.5.6](https://github.com/QingWei-Li/docsify/compare/v4.5.3...v4.5.6) (2017-12-14)
### Bug Fixes
* **style:** increase the tap targets of menu button, fixed [#325](https://github.com/QingWei-Li/docsify/issues/325) ([888f217](https://github.com/QingWei-Li/docsify/commit/888f217))
<a name="4.5.5"></a>
## [4.5.5](https://github.com/QingWei-Li/docsify/compare/v4.5.4...v4.5.5) (2017-11-30)
## [4.5.5](https://github.com/QingWei-Li/docsify/compare/v4.5.4...v4.5.5) (2017-11-30)
### Bug Fixes
* disqus plugin issue ([#318](https://github.com/QingWei-Li/docsify/issues/318)) ([041b33e](https://github.com/QingWei-Li/docsify/commit/041b33e)), closes [#317](https://github.com/QingWei-Li/docsify/issues/317)
<a name="4.5.4"></a>
## [4.5.4](https://github.com/QingWei-Li/docsify/compare/v4.5.2...v4.5.4) (2017-11-29)
## [4.5.4](https://github.com/QingWei-Li/docsify/compare/v4.5.2...v4.5.4) (2017-11-29)
### Bug Fixes
* **compiler:** task lists style, fixed [#215](https://github.com/QingWei-Li/docsify/issues/215) ([e43ded4](https://github.com/QingWei-Li/docsify/commit/e43ded4))
### Features
* add gitalk plugin ([#306](https://github.com/QingWei-Li/docsify/issues/306)) ([9208e64](https://github.com/QingWei-Li/docsify/commit/9208e64))
<a name="4.5.3"></a>
## [4.5.3](https://github.com/QingWei-Li/docsify/compare/v4.5.2...v4.5.3) (2017-11-11)
## [4.5.3](https://github.com/QingWei-Li/docsify/compare/v4.5.2...v4.5.3) (2017-11-11)
### Features
* add gitalk plugin ([#306](https://github.com/QingWei-Li/docsify/issues/306)) ([9208e64](https://github.com/QingWei-Li/docsify/commit/9208e64))
<a name="4.5.2"></a>
## [4.5.2](https://github.com/QingWei-Li/docsify/compare/v4.5.1...v4.5.2) (2017-11-09)
## [4.5.2](https://github.com/QingWei-Li/docsify/compare/v4.5.1...v4.5.2) (2017-11-09)
### Features
* github task lists, close [#215](https://github.com/QingWei-Li/docsify/issues/215) ([#305](https://github.com/QingWei-Li/docsify/issues/305)) ([d486eef](https://github.com/QingWei-Li/docsify/commit/d486eef))
<a name="4.5.1"></a>
## [4.5.1](https://github.com/QingWei-Li/docsify/compare/v4.5.0...v4.5.1) (2017-11-07)
## [4.5.1](https://github.com/QingWei-Li/docsify/compare/v4.5.0...v4.5.1) (2017-11-07)
### Features
* fetch files with the query params, fixed [#303](https://github.com/QingWei-Li/docsify/issues/303) ([2a2ed96](https://github.com/QingWei-Li/docsify/commit/2a2ed96))
<a name="4.5.0"></a>
# [4.5.0](https://github.com/QingWei-Li/docsify/compare/v4.4.1...v4.5.0) (2017-11-04)
# [4.5.0](https://github.com/QingWei-Li/docsify/compare/v4.4.1...v4.5.0) (2017-11-04)
### Features
* add disqus plugin, closed [#123](https://github.com/QingWei-Li/docsify/issues/123) ([fd7d4e0](https://github.com/QingWei-Li/docsify/commit/fd7d4e0))
<a name="4.4.1"></a>
## [4.4.1](https://github.com/QingWei-Li/docsify/compare/v4.4.0...v4.4.1) (2017-10-31)
## [4.4.1](https://github.com/QingWei-Li/docsify/compare/v4.4.0...v4.4.1) (2017-10-31)
### Bug Fixes
* {docsify-ignore-all} and {docsify-ignore} bug ([#299](https://github.com/QingWei-Li/docsify/issues/299)) ([cc98f56](https://github.com/QingWei-Li/docsify/commit/cc98f56))
* zoom image plugin issue, fixed [#187](https://github.com/QingWei-Li/docsify/issues/187) ([#300](https://github.com/QingWei-Li/docsify/issues/300)) ([fa772cf](https://github.com/QingWei-Li/docsify/commit/fa772cf))
<a name="4.4.0"></a>
# [4.4.0](https://github.com/QingWei-Li/docsify/compare/v4.3.15...v4.4.0) (2017-10-30)
# [4.4.0](https://github.com/QingWei-Li/docsify/compare/v4.3.15...v4.4.0) (2017-10-30)
### Bug Fixes
* sidebar style issue on firefox, fixed [#184](https://github.com/QingWei-Li/docsify/issues/184) ([#297](https://github.com/QingWei-Li/docsify/issues/297)) ([36bfc9d](https://github.com/QingWei-Li/docsify/commit/36bfc9d))
### Features
* add helper for disabled link, fixed [#295](https://github.com/QingWei-Li/docsify/issues/295) ([#296](https://github.com/QingWei-Li/docsify/issues/296)) ([4ad96f3](https://github.com/QingWei-Li/docsify/commit/4ad96f3))
<a name="4.3.15"></a>
## [4.3.15](https://github.com/QingWei-Li/docsify/compare/v4.3.14...v4.3.15) (2017-10-20)
## [4.3.15](https://github.com/QingWei-Li/docsify/compare/v4.3.14...v4.3.15) (2017-10-20)
### Bug Fixes
* scroll active sidebar ([a2b8eae](https://github.com/QingWei-Li/docsify/commit/a2b8eae))
<a name="4.3.14"></a>
## [4.3.14](https://github.com/QingWei-Li/docsify/compare/v4.3.13...v4.3.14) (2017-10-20)
## [4.3.14](https://github.com/QingWei-Li/docsify/compare/v4.3.13...v4.3.14) (2017-10-20)
### Bug Fixes
* codesponsor style ([ab68268](https://github.com/QingWei-Li/docsify/commit/ab68268))
<a name="4.3.13"></a>
## [4.3.13](https://github.com/QingWei-Li/docsify/compare/v4.3.12...v4.3.13) (2017-10-17)
## [4.3.13](https://github.com/QingWei-Li/docsify/compare/v4.3.12...v4.3.13) (2017-10-17)
### Bug Fixes
* duplicate results in search fixed [#257](https://github.com/QingWei-Li/docsify/issues/257) ([#284](https://github.com/QingWei-Li/docsify/issues/284)) ([3476f6f](https://github.com/QingWei-Li/docsify/commit/3476f6f))
* duplicate results in search fixed [#257](https://github.com/QingWei-Li/docsify/issues/257) ([#284](https://github.com/QingWei-Li/docsify/issues/284)) ([3476f6f](https://github.com/QingWei-Li/docsify/commit/3476f6f))
### Features
* make whole search result clickable ([#285](https://github.com/QingWei-Li/docsify/issues/285)) ([1b91227](https://github.com/QingWei-Li/docsify/commit/1b91227))
<a name="4.3.12"></a>
## [4.3.12](https://github.com/QingWei-Li/docsify/compare/v4.3.11...v4.3.12) (2017-10-15)
## [4.3.12](https://github.com/QingWei-Li/docsify/compare/v4.3.11...v4.3.12) (2017-10-15)
### Bug Fixes
* incorrect active link ([#281](https://github.com/QingWei-Li/docsify/issues/281)) ([a3ab379](https://github.com/QingWei-Li/docsify/commit/a3ab379))
<a name="4.3.11"></a>
## [4.3.11](https://github.com/QingWei-Li/docsify/compare/v4.3.10...v4.3.11) (2017-10-15)
## [4.3.11](https://github.com/QingWei-Li/docsify/compare/v4.3.10...v4.3.11) (2017-10-15)
### Bug Fixes
* broken links to same page heading, fix [#278](https://github.com/QingWei-Li/docsify/issues/278), fix [#279](https://github.com/QingWei-Li/docsify/issues/279) ([91d6337](https://github.com/QingWei-Li/docsify/commit/91d6337))
<a name="4.3.10"></a>
## [4.3.10](https://github.com/QingWei-Li/docsify/compare/v4.3.9...v4.3.10) (2017-10-12)
## [4.3.10](https://github.com/QingWei-Li/docsify/compare/v4.3.9...v4.3.10) (2017-10-12)
### Bug Fixes
* link render issue after page refreshing ([#276](https://github.com/QingWei-Li/docsify/issues/276)) ([abd885e](https://github.com/QingWei-Li/docsify/commit/abd885e))
<a name="4.3.9"></a>
## [4.3.9](https://github.com/QingWei-Li/docsify/compare/v4.3.8...v4.3.9) (2017-10-11)
## [4.3.9](https://github.com/QingWei-Li/docsify/compare/v4.3.8...v4.3.9) (2017-10-11)
### Bug Fixes
* scroll issue in IE ([#275](https://github.com/QingWei-Li/docsify/issues/275)) ([3e94cb6](https://github.com/QingWei-Li/docsify/commit/3e94cb6))
<a name="4.3.8"></a>
## [4.3.8](https://github.com/QingWei-Li/docsify/compare/v4.3.7...v4.3.8) (2017-10-07)
## [4.3.8](https://github.com/QingWei-Li/docsify/compare/v4.3.7...v4.3.8) (2017-10-07)
### Bug Fixes
* **slugify:** GitHub compatible heading links, fixed [#272](https://github.com/QingWei-Li/docsify/issues/272) ([9b4e666](https://github.com/QingWei-Li/docsify/commit/9b4e666))
<a name="4.3.7"></a>
## [4.3.7](https://github.com/QingWei-Li/docsify/compare/v4.3.6...v4.3.7) (2017-10-02)
## [4.3.7](https://github.com/QingWei-Li/docsify/compare/v4.3.6...v4.3.7) (2017-10-02)
### Bug Fixes
* **slugify:** GitHub compatible heading links, fixed [#267](https://github.com/QingWei-Li/docsify/issues/267) ([c195d2d](https://github.com/QingWei-Li/docsify/commit/c195d2d))
<a name="4.3.6"></a>
## [4.3.6](https://github.com/QingWei-Li/docsify/compare/v4.3.5...v4.3.6) (2017-09-21)
## [4.3.6](https://github.com/QingWei-Li/docsify/compare/v4.3.5...v4.3.6) (2017-09-21)
### Bug Fixes
* style for codesponsor plugin ([08afec7](https://github.com/QingWei-Li/docsify/commit/08afec7))
<a name="4.3.5"></a>
## [4.3.5](https://github.com/QingWei-Li/docsify/compare/v4.3.4...v4.3.5) (2017-09-20)
## [4.3.5](https://github.com/QingWei-Li/docsify/compare/v4.3.4...v4.3.5) (2017-09-20)
### Bug Fixes
* missed symbol ([#254](https://github.com/QingWei-Li/docsify/issues/254)) ([6c702d3](https://github.com/QingWei-Li/docsify/commit/6c702d3))
### Features
* **plugin:** add codesponsor plugin ([46ac4c3](https://github.com/QingWei-Li/docsify/commit/46ac4c3))
<a name="4.3.4"></a>
## [4.3.4](https://github.com/QingWei-Li/docsify/compare/v4.3.3...v4.3.4) (2017-09-07)
## [4.3.4](https://github.com/QingWei-Li/docsify/compare/v4.3.3...v4.3.4) (2017-09-07)
### Bug Fixes
* scroll position issue, fixed [#234](https://github.com/QingWei-Li/docsify/issues/234) ([388ed3d](https://github.com/QingWei-Li/docsify/commit/388ed3d))
<a name="4.3.3"></a>
## [4.3.3](https://github.com/QingWei-Li/docsify/compare/v4.3.2...v4.3.3) (2017-09-06)
## [4.3.3](https://github.com/QingWei-Li/docsify/compare/v4.3.2...v4.3.3) (2017-09-06)
### Bug Fixes
* **buble.css:** tweaks code block style, fixed [#249](https://github.com/QingWei-Li/docsify/issues/249) ([9d43051](https://github.com/QingWei-Li/docsify/commit/9d43051))
### Features
* add doc for react and vue demo box plugin ([#247](https://github.com/QingWei-Li/docsify/issues/247)) ([f0aca19](https://github.com/QingWei-Li/docsify/commit/f0aca19))
<a name="4.3.2"></a>
## [4.3.2](https://github.com/QingWei-Li/docsify/compare/v4.3.1...v4.3.2) (2017-09-01)
## [4.3.2](https://github.com/QingWei-Li/docsify/compare/v4.3.1...v4.3.2) (2017-09-01)
### Bug Fixes
* sidebar highlight ([f82f419](https://github.com/QingWei-Li/docsify/commit/f82f419))
### Features
* add Edit on github plugin (thanks [@njleonzhang](https://github.com/njleonzhang)) ([a0e1ea8](https://github.com/QingWei-Li/docsify/commit/a0e1ea8))
<a name="4.3.1"></a>
## [4.3.1](https://github.com/QingWei-Li/docsify/compare/v4.2.9...v4.3.1) (2017-08-30)
### Features
* **markdown:** supports mermaid [#137](https://github.com/QingWei-Li/docsify/issues/137) ([f4800e0](https://github.com/QingWei-Li/docsify/commit/f4800e0))
<a name="4.3.0"></a>
# [4.3.0](https://github.com/QingWei-Li/docsify/compare/v4.2.9...v4.3.0) (2017-08-17)
# [4.3.0](https://github.com/QingWei-Li/docsify/compare/v4.2.9...v4.3.0) (2017-08-17)
### Features
* **markdown:** supports mermaid [#137](https://github.com/QingWei-Li/docsify/issues/137) ([f4800e0](https://github.com/QingWei-Li/docsify/commit/f4800e0))
<a name="4.2.9"></a>
## [4.2.9](https://github.com/QingWei-Li/docsify/compare/v4.2.8...v4.2.9) (2017-08-15)
## [4.2.9](https://github.com/QingWei-Li/docsify/compare/v4.2.8...v4.2.9) (2017-08-15)
### Bug Fixes
* ensure document ready before init Docsify [#233](https://github.com/QingWei-Li/docsify/issues/233)
<a name="4.2.8"></a>
## [4.2.8](https://github.com/QingWei-Li/docsify/compare/v4.2.7...v4.2.8) (2017-08-10)
## [4.2.8](https://github.com/QingWei-Li/docsify/compare/v4.2.7...v4.2.8) (2017-08-10)
### Features
* **compiler:** support for setting target attribute for link, fixed [#230](https://github.com/QingWei-Li/docsify/issues/230) ([7f270f9](https://github.com/QingWei-Li/docsify/commit/7f270f9))
<a name="4.2.7"></a>
## [4.2.7](https://github.com/QingWei-Li/docsify/compare/v4.2.4...v4.2.7) (2017-08-05)
## [4.2.7](https://github.com/QingWei-Li/docsify/compare/v4.2.4...v4.2.7) (2017-08-05)
### Bug Fixes
* **release:** release shell ([628e211](https://github.com/QingWei-Li/docsify/commit/628e211))
* **style:** nowrap => pre-wrap, fixed [#228](https://github.com/QingWei-Li/docsify/issues/228) ([a88252c](https://github.com/QingWei-Li/docsify/commit/a88252c))
<a name="4.2.6"></a>
## [4.2.6](https://github.com/QingWei-Li/docsify/compare/v4.2.4...v4.2.6) (2017-07-27)
## [4.2.6](https://github.com/QingWei-Li/docsify/compare/v4.2.4...v4.2.6) (2017-07-27)
### Bug Fixes
* **css:** hide the nav when the content has not yet been loaded ([1fa1619](https://github.com/QingWei-Li/docsify/commit/1fa1619))
* **release:** release shell ([628e211](https://github.com/QingWei-Li/docsify/commit/628e211))
<a name="4.2.4"></a>
## [4.2.4](https://github.com/QingWei-Li/docsify/compare/v4.2.2...v4.2.4) (2017-07-26)
## [4.2.4](https://github.com/QingWei-Li/docsify/compare/v4.2.2...v4.2.4) (2017-07-26)
### Bug Fixes
* **render:** Remove getRootNode to be compatible with the lower version of Chrome, fixed [#225](https://github.com/QingWei-Li/docsify/issues/225) ([b8dd346](https://github.com/QingWei-Li/docsify/commit/b8dd346))
<a name="4.2.3"></a>
## [4.2.3](https://github.com/QingWei-Li/docsify/compare/v4.2.2...v4.2.3) (2017-07-26)
## [4.2.3](https://github.com/QingWei-Li/docsify/compare/v4.2.2...v4.2.3) (2017-07-26)
### Features
* **search:** Supports the max depth of the search headline, fixed [#223](https://github.com/QingWei-Li/docsify/issues/223), resolve [#129](https://github.com/QingWei-Li/docsify/issues/129) ([b7b589b](https://github.com/QingWei-Li/docsify/commit/b7b589b))
<a name="4.2.2"></a>
## [4.2.2](https://github.com/QingWei-Li/docsify/compare/v4.2.1...v4.2.2) (2017-07-24)
## [4.2.2](https://github.com/QingWei-Li/docsify/compare/v4.2.1...v4.2.2) (2017-07-24)
### Bug Fixes
* style rerender due to setting themeColor ([17ff3d1](https://github.com/QingWei-Li/docsify/commit/17ff3d1))
<a name="4.2.1"></a>
## [4.2.1](https://github.com/QingWei-Li/docsify/compare/v4.2.0...v4.2.1) (2017-07-19)
- give the navbar some line-height (#216)
- Remove unnecessary moduleName option from rollup config for plugins (#209)
* give the navbar some line-height (#216)
* Remove unnecessary moduleName option from rollup config for plugins (#209)
<a name="4.2.0"></a>
# [4.2.0](https://github.com/QingWei-Li/docsify/compare/v4.1.14...v4.2.0) (2017-07-10)
# [4.2.0](https://github.com/QingWei-Li/docsify/compare/v4.1.14...v4.2.0) (2017-07-10)
### Bug Fixes
* not found page ([9af8559](https://github.com/QingWei-Li/docsify/commit/9af8559))
### Features
* alias option supports regexp, resolve [#183](https://github.com/QingWei-Li/docsify/issues/183) ([c4aa22c](https://github.com/QingWei-Li/docsify/commit/c4aa22c))
* ignore to compiled link, fixed [#203](https://github.com/QingWei-Li/docsify/issues/203) ([#204](https://github.com/QingWei-Li/docsify/issues/204)) ([2e00f4c](https://github.com/QingWei-Li/docsify/commit/2e00f4c))
<a name="4.1.14"></a>
## [4.1.14](https://github.com/QingWei-Li/docsify/compare/v4.1.13...v4.1.14) (2017-06-24)
## [4.1.14](https://github.com/QingWei-Li/docsify/compare/v4.1.13...v4.1.14) (2017-06-24)
### Bug Fixes
* get file path, fixed jrappen/sublime-distractionless/commit/81bfadd391428823191cc03eca956a2312e04d13#commitcomment-22427070 ([e8117e5](https://github.com/QingWei-Li/docsify/commit/e8117e5)), closes [jrappen/sublime-distractionless/commit/81bfadd391428823191cc03eca956a2312e04d13#commitcomment-22427070](https://github.com/jrappen/sublime-distractionless/commit/81bfadd391428823191cc03eca956a2312e04d13/issues/commitcomment-22427070)
### Features
* add context attribute, fixed [#191](https://github.com/QingWei-Li/docsify/issues/191) ([ce0e9ac](https://github.com/QingWei-Li/docsify/commit/ce0e9ac))
<a name="4.1.13"></a>
## [4.1.13](https://github.com/QingWei-Li/docsify/compare/v4.1.12...v4.1.13) (2017-06-11)
<a name="4.1.12"></a>
## [4.1.12](https://github.com/QingWei-Li/docsify/compare/v4.1.11...v4.1.12) (2017-06-03)
## [4.1.12](https://github.com/QingWei-Li/docsify/compare/v4.1.11...v4.1.12) (2017-06-03)
### Bug Fixes
* **render:** subtitle in side bar shows undefined, fixed [#182](https://github.com/QingWei-Li/docsify/issues/182) ([d087d57](https://github.com/QingWei-Li/docsify/commit/d087d57))
<a name="4.1.11"></a>
## [4.1.11](https://github.com/QingWei-Li/docsify/compare/v4.1.10...v4.1.11) (2017-06-02)
## [4.1.11](https://github.com/QingWei-Li/docsify/compare/v4.1.10...v4.1.11) (2017-06-02)
### Bug Fixes
* **compiler:** force reset toc when rendering sidebar fixed [#181](https://github.com/QingWei-Li/docsify/issues/181) ([ccf4c7c](https://github.com/QingWei-Li/docsify/commit/ccf4c7c))
* **render:** autoHeader does not work ([1304d2e](https://github.com/QingWei-Li/docsify/commit/1304d2e))
<a name="4.1.10"></a>
## [4.1.10](https://github.com/QingWei-Li/docsify/compare/v4.1.9...v4.1.10) (2017-06-02)
## [4.1.10](https://github.com/QingWei-Li/docsify/compare/v4.1.9...v4.1.10) (2017-06-02)
### Bug Fixes
* **hash:** hash routing crashes when url has querystring ([6d48ce1](https://github.com/QingWei-Li/docsify/commit/6d48ce1))
<a name="4.1.9"></a>
## [4.1.9](https://github.com/QingWei-Li/docsify/compare/v4.1.8...v4.1.9) (2017-05-31)
## [4.1.9](https://github.com/QingWei-Li/docsify/compare/v4.1.8...v4.1.9) (2017-05-31)
### Bug Fixes
@@ -489,136 +479,109 @@
* **lifecycle:** continue to handle data ([955d3d5](https://github.com/QingWei-Li/docsify/commit/955d3d5))
* **render:** broken name link, fixed [#167](https://github.com/QingWei-Li/docsify/issues/167) ([91b66a5](https://github.com/QingWei-Li/docsify/commit/91b66a5))
<a name="4.1.8"></a>
## [4.1.8](https://github.com/QingWei-Li/docsify/compare/v4.1.7...v4.1.8) (2017-05-31)
## [4.1.8](https://github.com/QingWei-Li/docsify/compare/v4.1.7...v4.1.8) (2017-05-31)
### Bug Fixes
* auto replace version ([22b50f0](https://github.com/QingWei-Li/docsify/commit/22b50f0))
* update edit button demo ([ec887c1](https://github.com/QingWei-Li/docsify/commit/ec887c1))
### Features
* add edit button demo ([a64cee1](https://github.com/QingWei-Li/docsify/commit/a64cee1))
* add edit button demo, close [#162](https://github.com/QingWei-Li/docsify/issues/162) ([036fdac](https://github.com/QingWei-Li/docsify/commit/036fdac))
<a name="4.1.7"></a>
## [4.1.7](https://github.com/QingWei-Li/docsify/compare/v4.1.6...v4.1.7) (2017-05-30)
## [4.1.7](https://github.com/QingWei-Li/docsify/compare/v4.1.6...v4.1.7) (2017-05-30)
### Bug Fixes
* **ssr:** clean files ([0014895](https://github.com/QingWei-Li/docsify/commit/0014895))
<a name="4.1.6"></a>
## [4.1.6](https://github.com/QingWei-Li/docsify/compare/v4.1.5...v4.1.6) (2017-05-30)
## [4.1.6](https://github.com/QingWei-Li/docsify/compare/v4.1.5...v4.1.6) (2017-05-30)
### Bug Fixes
* **ssr:** add debug ([6b9e092](https://github.com/QingWei-Li/docsify/commit/6b9e092))
<a name="4.1.5"></a>
## [4.1.5](https://github.com/QingWei-Li/docsify/compare/v4.1.4...v4.1.5) (2017-05-30)
## [4.1.5](https://github.com/QingWei-Li/docsify/compare/v4.1.4...v4.1.5) (2017-05-30)
### Bug Fixes
* **ssr:** missing package ([6db8c9e](https://github.com/QingWei-Li/docsify/commit/6db8c9e))
* **ssr:** missing package ([6db8c9e](https://github.com/QingWei-Li/docsify/commit/6db8c9e))
<a name="4.1.4"></a>
## [4.1.4](https://github.com/QingWei-Li/docsify/compare/v4.1.3...v4.1.4) (2017-05-30)
## [4.1.4](https://github.com/QingWei-Li/docsify/compare/v4.1.3...v4.1.4) (2017-05-30)
### Bug Fixes
* **ssr:** file path ([79a83bc](https://github.com/QingWei-Li/docsify/commit/79a83bc))
<a name="4.1.3"></a>
## [4.1.3](https://github.com/QingWei-Li/docsify/compare/v4.1.2...v4.1.3) (2017-05-30)
## [4.1.3](https://github.com/QingWei-Li/docsify/compare/v4.1.2...v4.1.3) (2017-05-30)
### Bug Fixes
* update babel config ([9825db4](https://github.com/QingWei-Li/docsify/commit/9825db4))
<a name="4.1.2"></a>
## [4.1.2](https://github.com/QingWei-Li/docsify/compare/v4.1.1...v4.1.2) (2017-05-30)
## [4.1.2](https://github.com/QingWei-Li/docsify/compare/v4.1.1...v4.1.2) (2017-05-30)
### Bug Fixes
* update babel config ([80dba19](https://github.com/QingWei-Li/docsify/commit/80dba19))
<a name="4.1.1"></a>
## [4.1.1](https://github.com/QingWei-Li/docsify/compare/v4.1.0...v4.1.1) (2017-05-30)
## [4.1.1](https://github.com/QingWei-Li/docsify/compare/v4.1.0...v4.1.1) (2017-05-30)
### Bug Fixes
* build for ssr package ([4cb20a5](https://github.com/QingWei-Li/docsify/commit/4cb20a5))
* remove history mode ([0e74e6c](https://github.com/QingWei-Li/docsify/commit/0e74e6c))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/QingWei-Li/docsify/compare/v4.0.2...v4.1.0) (2017-05-30)
<a name="4.0.2"></a>
## [4.0.2](https://github.com/QingWei-Li/docsify/compare/v4.0.1...v4.0.2) (2017-05-30)
## [4.0.2](https://github.com/QingWei-Li/docsify/compare/v4.0.1...v4.0.2) (2017-05-30)
### Bug Fixes
* basePath for history mode ([fc1cd3f](https://github.com/QingWei-Li/docsify/commit/fc1cd3f))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/QingWei-Li/docsify/compare/v4.0.0...v4.0.1) (2017-05-29)
## [4.0.1](https://github.com/QingWei-Li/docsify/compare/v4.0.0...v4.0.1) (2017-05-29)
### Bug Fixes
* **ssr:** remove context ([4626157](https://github.com/QingWei-Li/docsify/commit/4626157))
* lint ([b764b6e](https://github.com/QingWei-Li/docsify/commit/b764b6e))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/QingWei-Li/docsify/compare/v3.7.3...v4.0.0) (2017-05-29)
# [4.0.0](https://github.com/QingWei-Li/docsify/compare/v3.7.3...v4.0.0) (2017-05-29)
### Bug Fixes
* **render:** init event in ssr ([eba1c98](https://github.com/QingWei-Li/docsify/commit/eba1c98))
* lint ([1f4514d](https://github.com/QingWei-Li/docsify/commit/1f4514d))
### Features
* finish ssr ([3444884](https://github.com/QingWei-Li/docsify/commit/3444884))
* init ocsify-server-renderer ([6dea685](https://github.com/QingWei-Li/docsify/commit/6dea685))
* support history mode ([f095eb8](https://github.com/QingWei-Li/docsify/commit/f095eb8))
+1 -1
View File
@@ -40,6 +40,7 @@
* Useful plugin API
* Compatible with IE10+
* Support SSR ([example](https://github.com/QingWei-Li/docsify-ssr-demo))
* Support embedded files
## Quick start
@@ -70,7 +71,6 @@ Move to [awesome-docsify](https://github.com/QingWei-Li/awesome-docsify)
```bash
npm run bootstrap && npm run dev
open http://localhost:3000
```
## Backers
-53
View File
@@ -1,53 +0,0 @@
var serveStatic = require('serve-static')
var http = require('http')
var fs = require('fs')
var Renderer = require('./packages/docsify-server-renderer/build.js')
var renderer = new Renderer({
template: `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="/themes/vue.css" title="vue">
</head>
<body>
<!--inject-app-->
<!--inject-config-->
<script src="/lib/docsify.js"></script>
</body>
</html>`,
config: {
name: 'docsify',
repo: 'qingwei-li/docsify',
basePath: 'https://docsify.js.org/',
loadNavbar: true,
loadSidebar: true,
subMaxLevel: 3,
auto2top: true,
alias: {
'/de-de/changelog': '/changelog',
'/zh-cn/changelog': '/changelog',
'/changelog':
'https://raw.githubusercontent.com/QingWei-Li/docsify/master/CHANGELOG'
}
},
path: './'
})
http
.createServer(function (req, res) {
serveStatic('.')(req, res, function () {
// TEST SSR
// renderer.renderToString(req.url)
// .then(html => res.end(html))
res.writeHead(404, { 'Content-Type': 'text/html' })
res.end(fs.readFileSync('dev.html'))
})
})
.listen(3000, '0.0.0.0')
console.log(`\nListening at http://0.0.0.0:3000\n`)
-50
View File
@@ -1,50 +0,0 @@
var fs = require('fs')
var cssnano = require('cssnano').process
var resolve = require('path').resolve
var postcss = require('postcss')
var isProd = process.argv[process.argv.length - 1] !== '--dev'
var processor = postcss([
require('postcss-salad')({
features: {
precss: {
properties: {
preserve: true
}
}
}
})
])
var saveMin = function (file, content) {
fs.writeFileSync(resolve(__dirname, '../lib/themes/', file), content)
}
var save = function (file, content) {
fs.writeFileSync(resolve(__dirname, '../themes/', file), content)
}
var load = function (file) {
return fs.readFileSync(resolve(__dirname, '../src/themes/', file)).toString()
}
var loadLib = function (file) {
return fs.readFileSync(resolve(__dirname, '../themes/', file)).toString()
}
var list = fs.readdirSync(resolve(__dirname, '../src/themes'))
list.forEach(function (file) {
if (!/\.css$/.test(file)) return
processor
.process(load(file), { from: resolve(__dirname, '../src/themes/', file) })
.then(function (result) {
save(file, result.css)
console.log('salad - ' + file)
isProd &&
cssnano(loadLib(file)).then(function (result) {
saveMin(file, result.css)
console.log('cssnao - ' + file)
})
})
.catch(function (err) {
console.log(err)
})
})
+86 -45
View File
@@ -1,19 +1,19 @@
var rollup = require('rollup')
var buble = require('rollup-plugin-buble')
var commonjs = require('rollup-plugin-commonjs')
var nodeResolve = require('rollup-plugin-node-resolve')
var string = require('rollup-plugin-string')
var uglify = require('rollup-plugin-uglify')
var replace = require('rollup-plugin-replace')
var isProd = process.argv[process.argv.length - 1] !== '--dev'
var version = process.env.VERSION || require('../package.json').version
const rollup = require('rollup')
const buble = require('rollup-plugin-buble')
const commonjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const uglify = require('rollup-plugin-uglify')
const replace = require('rollup-plugin-replace')
const isProd = process.env.NODE_ENV === 'production'
const version = process.env.VERSION || require('../package.json').version
const chokidar = require('chokidar')
const path = require('path')
var build = function (opts) {
const build = function(opts) {
rollup
.rollup({
input: 'src/' + opts.entry,
input: opts.input,
plugins: (opts.plugins || []).concat([
string({ include: '**/*.css' }),
buble(),
commonjs(),
nodeResolve(),
@@ -23,8 +23,8 @@ var build = function (opts) {
})
])
})
.then(function (bundle) {
var dest = 'lib/' + (opts.output || opts.entry)
.then(function(bundle) {
var dest = 'lib/' + (opts.output || opts.input)
console.log(dest)
bundle.write({
@@ -33,45 +33,86 @@ var build = function (opts) {
strict: false
})
})
.catch(function (err) {
.catch(function(err) {
console.error(err)
})
}
build({
entry: 'core/index.js',
output: 'docsify.js'
})
var plugins = [
{ name: 'search', entry: 'search/index.js' },
{ name: 'ga', entry: 'ga.js' },
{ name: 'emoji', entry: 'emoji.js' },
{ name: 'external-script', entry: 'external-script.js' },
{ name: 'front-matter', entry: 'front-matter/index.js' },
{ name: 'zoom-image', entry: 'zoom-image.js' },
{ name: 'disqus', entry: 'disqus.js' },
{ name: 'gitalk', entry: 'gitalk.js' }
]
plugins.forEach(item => {
const buildCore = function() {
build({
entry: 'plugins/' + item.entry,
output: 'plugins/' + item.name + '.js'
input: 'src/core/index.js',
output: 'docsify.js'
})
})
if (isProd) {
build({
entry: 'core/index.js',
output: 'docsify.min.js',
plugins: [uglify()]
})
plugins.forEach(item => {
if (isProd) {
build({
entry: 'plugins/' + item.entry,
output: 'plugins/' + item.name + '.min.js',
input: 'src/core/index.js',
output: 'docsify.min.js',
plugins: [uglify()]
})
}
}
const buildAllPlugin = function() {
var plugins = [
{name: 'search', input: 'search/index.js'},
{name: 'ga', input: 'ga.js'},
{name: 'emoji', input: 'emoji.js'},
{name: 'external-script', input: 'external-script.js'},
{name: 'front-matter', input: 'front-matter/index.js'},
{name: 'zoom-image', input: 'zoom-image.js'},
{name: 'disqus', input: 'disqus.js'},
{name: 'gitalk', input: 'gitalk.js'}
]
plugins.forEach(item => {
build({
input: 'src/plugins/' + item.input,
output: 'plugins/' + item.name + '.js'
})
})
if (isProd) {
plugins.forEach(item => {
build({
input: 'src/plugins/' + item.input,
output: 'plugins/' + item.name + '.min.js',
plugins: [uglify()]
})
})
}
}
if (!isProd) {
chokidar
.watch(['src/core', 'src/plugins'], {
atomic: true,
awaitWriteFinish: {
stabilityThreshold: 1000,
pollInterval: 100
}
})
.on('change', p => {
console.log('[watch] ', p)
const dirs = p.split(path.sep)
if (dirs[1] === 'core') {
buildCore()
} else if (dirs[2]) {
const name = path.basename(dirs[2], '.js')
const input = `src/plugins/${name}${
/\.js/.test(dirs[2]) ? '' : '/index'
}.js`
build({
input,
output: 'plugins/' + name + '.js'
})
}
})
.on('ready', () => {
console.log('[start]')
buildCore()
buildAllPlugin()
})
} else {
buildCore()
buildAllPlugin()
}
+12
View File
@@ -0,0 +1,12 @@
const cssnano = require('cssnano').process
const path = require('path')
const fs = require('fs')
files = fs.readdirSync(path.resolve('lib/themes'))
files.forEach(file => {
file = path.resolve('lib/themes', file)
cssnano(fs.readFileSync(file)).then(result => {
fs.writeFileSync(file, result.css)
})
})
View File
+1 -1
View File
@@ -1,6 +1,6 @@
![logo](_media/icon.svg)
# docsify <small>4.6.0</small>
# docsify <small>4.6.7</small>
> A magical documentation site generator.
+1 -1
View File
@@ -21,7 +21,7 @@
* [Vue compatibility](vue.md)
* [CDN](cdn.md)
* [Offline Mode(PWA)](pwa.md)
* [Server-client renderer(SSR)](ssr.md)
* [Server-Side Rendering(SSR)](ssr.md)
* [Embed Files <sup style="color:red">(new)<sup>](embed-files.md)
* [Awesome docsify](awesome.md)
+54 -1
View File
@@ -380,7 +380,7 @@ window.$docsify = {
* type: `Boolean`
Only coverpage is loaded when When visiting the home page.
Only coverpage is loaded when visiting the home page.
```js
window.$docsify = {
@@ -413,3 +413,56 @@ window.$docsify = {
ext: '.md'
};
```
## fallbackLanguages
* type: `Array<string>`
List of languages that will fallback to the default language when a page is request and didn't exists for the given local.
Example:
- try to fetch the page of `/de/overview`. If this page exists, it'll be displayed
- then try to fetch the default page `/overview` (depending on the default language). If this page exists, it'll be displayed
- then display 404 page.
```js
window.$docsify = {
fallbackLanguages: [
"fr",
"de"
]
};
```
## notFoundPage
* type: `Boolean` | `String` | `Object`
Load the `_404.md` file:
```js
window.$docsify = {
notFoundPage: true
};
```
Load the customised path of the 404 page:
```js
window.$docsify = {
notFoundPage: 'my404.md'
};
```
Load the right 404 page according to the localisation:
```js
window.$docsify = {
notFoundPage: {
'/': '_404.md',
'/de': 'de/_404.md',
}
};
```
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
+1 -1
View File
@@ -21,7 +21,7 @@
* [Vue Kompatibilität](de-de/vue.md)
* [CDN](de-de/cdn.md)
* [Offline Modus (PWA)](de-de/pwa.md)
* [Server-client renderer (SSR)](de-de/ssr.md)
* [Server-Side Rendering (SSR)](de-de/ssr.md)
* [Embed Files <sup style="color:red">(new)<sup>](de-de/embed-files.md)
* [Awesome docsify](de-de/awesome.md)
+47
View File
@@ -401,3 +401,50 @@ window.$docsify = {
ext: '.md'
};
```
## fallbackLanguages
* type: `Array<string>`
List of languages that will fallback to the default language when a page is request and didn't exists for the given local.
Example:
* try to fetch the page of `/de/overview`. If this page exists, it'll be displayed
* then try to fetch the default page `/overview` (depending on the default language). If this page exists, it'll be displayed
* then display 404 page.
```js
window.$docsify = {
fallbackLanguages: ['fr', 'de']
};
```
## notFoundPage
* type: `Boolean` | `String` | `Object`
Load the `_404.md` file:
```js
window.$docsify = {
notFoundPage: true
};
```
Load the customised path of the 404 page:
```js
window.$docsify = {
notFoundPage: 'my404.md'
};
```
Load the right 404 page according to the localisation:
```js
window.$docsify = {
notFoundPage: {
'/': '_404.md',
'/de': 'de/_404.md',
}
};
```
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
+1 -1
View File
@@ -1,4 +1,4 @@
# Server client renderer
# Server-Side Rendering
See https://docsify.now.sh
+1 -1
View File
@@ -1,4 +1,4 @@
# Server client renderer
# Server-Side Rendering
See https://docsify.now.sh
+49
View File
@@ -413,3 +413,52 @@ window.$docsify = {
ext: '.md'
};
```
## fallbackLanguages
* type: `Array<string>`
List of languages that will fallback to the default language when a page is request and didn't exists for the given local.
Example:
* try to fetch the page of `/de/overview`. If this page exists, it'll be displayed
* then try to fetch the default page `/overview` (depending on the default language). If this page exists, it'll be displayed
* then display 404 page.
```js
window.$docsify = {
fallbackLanguages: ['fr', 'de']
};
```
## notFoundPage
* type: `Boolean` | `String` | `Object`
Load the `_404.md` file:
```js
window.$docsify = {
notFoundPage: true
};
```
Load the customised path of the 404 page:
```js
window.$docsify = {
notFoundPage: 'my404.md'
};
```
Load the right 404 page according to the localisation:
```js
window.$docsify = {
notFoundPage: {
'/': '_404.md',
'/de': 'de/_404.md',
}
};
```
> Note: The options with fallbackLanguages didn't work with the `notFoundPage` options.
+7 -3
View File
@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify</title>
@@ -14,6 +15,7 @@
}
</style>
</head>
<body>
<div id="app"></div>
<script>
@@ -22,6 +24,7 @@
'.*?/changelog': 'https://raw.githubusercontent.com/QingWei-Li/docsify/master/CHANGELOG',
'/.*/_navbar.md': '/_navbar.md'
},
notFoundPage: '_404.html',
auto2top: true,
basePath: '/docs/',
executeScript: true,
@@ -33,11 +36,11 @@
mergeNavbar: true,
formatUpdated: '{MM}/{DD} {HH}:{mm}',
plugins: [
function(hook, vm) {
function (hook, vm) {
hook.beforeEach(function (html) {
var url = 'https://github.com/QingWei-Li/docsify/blob/master/' + vm.route.file
var editHtml = '[:memo: Edit Document](' + url + ')\n'
return editHtml
+ html
+ '\n----\n'
@@ -50,4 +53,5 @@
</script>
<script src="/lib/docsify.js"></script>
</body>
</html>
</html>
+592 -277
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -4,7 +4,7 @@ if (fixedPath !== location.href) {
location.href = fixedPath;
}
function install (hook, vm) {
function install(hook, vm) {
var dom = Docsify.dom;
var disqus = vm.config.disqus;
if (!disqus) {
@@ -16,7 +16,7 @@ function install (hook, vm) {
script.async = true;
script.src = "https://" + disqus + ".disqus.com/embed.js";
script.setAttribute('data-timestamp', +new Date());
script.setAttribute('data-timestamp', Number(new Date()));
dom.appendTo(dom.body, script);
});
+1 -1
View File
@@ -1 +1 @@
!function(){var i=location.href.replace("/-/","/#/");i!==location.href&&(location.href=i);$docsify.plugins=[].concat(function(i,t){var e=Docsify.dom,o=t.config.disqus;if(!o)throw Error("$docsify.disqus is required");i.init(function(i){var t=e.create("script");t.async=!0,t.src="https://"+o+".disqus.com/embed.js",t.setAttribute("data-timestamp",+new Date),e.appendTo(e.body,t)}),i.mounted(function(i){var o=e.create("div");o.id="disqus_thread";var n=e.getNode("#main");o.style="width: "+n.clientWidth+"px; margin: 0 auto 20px;",e.appendTo(e.find(".content"),o),window.disqus_config=function(){this.page.url=location.origin+"/-"+t.route.path,this.page.identifier=t.route.path,this.page.title=document.title}}),i.doneEach(function(i){void 0!==window.DISQUS&&window.DISQUS.reset({reload:!0,config:function(){this.page.url=location.origin+"/-"+t.route.path,this.page.identifier=t.route.path,this.page.title=document.title}})})},$docsify.plugins)}();
!function(){var i=location.href.replace("/-/","/#/");i!==location.href&&(location.href=i);$docsify.plugins=[].concat(function(i,t){var e=Docsify.dom,o=t.config.disqus;if(!o)throw Error("$docsify.disqus is required");i.init(function(i){var t=e.create("script");t.async=!0,t.src="https://"+o+".disqus.com/embed.js",t.setAttribute("data-timestamp",Number(new Date)),e.appendTo(e.body,t)}),i.mounted(function(i){var o=e.create("div");o.id="disqus_thread";var n=e.getNode("#main");o.style="width: "+n.clientWidth+"px; margin: 0 auto 20px;",e.appendTo(e.find(".content"),o),window.disqus_config=function(){this.page.url=location.origin+"/-"+t.route.path,this.page.identifier=t.route.path,this.page.title=document.title}}),i.doneEach(function(i){void 0!==window.DISQUS&&window.DISQUS.reset({reload:!0,config:function(){this.page.url=location.origin+"/-"+t.route.path,this.page.identifier=t.route.path,this.page.title=document.title}})})},$docsify.plugins)}();
+4 -4
View File
@@ -888,12 +888,12 @@ var AllGithubEmoji = [
'zzz'
];
// emoji from All-Github-Emoji-Icons
// 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://assets-cdn.github.com/images/icons/emoji/' +
return AllGithubEmoji.indexOf($1) === -1 ?
match :
'<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' +
$1 +
'.png" alt="' +
$1 +
+1 -1
View File
@@ -1,5 +1,5 @@
(function () {
function handleExternalScript () {
function handleExternalScript() {
var container = Docsify.dom.getNode('#main');
var scripts = Docsify.dom.findAll(container, 'script');
+3 -3
View File
@@ -1,13 +1,13 @@
(function () {
// From https://github.com/egoist/vue-ga/blob/master/src/index.js
function appendScript () {
function appendScript() {
var script = document.createElement('script');
script.async = true;
script.src = 'https://www.google-analytics.com/analytics.js';
document.body.appendChild(script);
}
function init (id) {
function init(id) {
appendScript();
window.ga =
window.ga ||
@@ -18,7 +18,7 @@ function init (id) {
window.ga('create', id, 'auto');
}
function collect () {
function collect() {
if (!window.ga) {
init($docsify.ga);
}
+1 -1
View File
@@ -1,5 +1,5 @@
(function () {
function install (hook, vm) {
function install(hook) {
var dom = Docsify.dom;
hook.mounted(function (_) {
+1 -1
View File
@@ -1 +1 @@
!function(){$docsify.plugins=[].concat(function(n,t){var i=Docsify.dom;n.mounted(function(n){var t=i.create("div");t.id="gitalk-container";var e=i.getNode("#main");t.style="width: "+e.clientWidth+"px; margin: 0 auto 20px;",i.appendTo(i.find(".content"),t);var o=i.create("script");o.textContent="gitalk.render('gitalk-container')",i.appendTo(i.body,o)})},$docsify.plugins)}();
!function(){$docsify.plugins=[].concat(function(n){var t=Docsify.dom;n.mounted(function(n){var i=t.create("div");i.id="gitalk-container";var e=t.getNode("#main");i.style="width: "+e.clientWidth+"px; margin: 0 auto 20px;",t.appendTo(t.find(".content"),i);var o=t.create("script");o.textContent="gitalk.render('gitalk-container')",t.appendTo(t.body,o)})},$docsify.plugins)}();
+41 -33
View File
@@ -2,23 +2,23 @@
var INDEXS = {};
var helper;
function escapeHtml (string) {
function escapeHtml(string) {
var entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'\'': '&#39;',
'/': '&#x2F;'
};
return String(string).replace(/[&<>"'\/]/g, function (s) { return entityMap[s]; })
return String(string).replace(/[&<>"'/]/g, function (s) { return entityMap[s]; })
}
function getAllPaths (router) {
function getAllPaths(router) {
var paths = [];
helper.dom.findAll('a:not([data-nosearch])').map(function (node) {
helper.dom.findAll('a:not([data-nosearch])').forEach(function (node) {
var href = node.href;
var originHref = node.getAttribute('href');
var path = router.parse(href).path;
@@ -35,12 +35,12 @@ function getAllPaths (router) {
return paths
}
function saveData (maxAge) {
function saveData(maxAge) {
localStorage.setItem('docsify.search.expires', Date.now() + maxAge);
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS));
}
function genIndex (path, content, router, depth) {
function genIndex(path, content, router, depth) {
if ( content === void 0 ) content = '';
var tokens = window.marked.lexer(content);
@@ -50,18 +50,18 @@ function genIndex (path, content, router, depth) {
tokens.forEach(function (token) {
if (token.type === 'heading' && token.depth <= depth) {
slug = router.toURL(path, { id: slugify(token.text) });
index[slug] = { slug: slug, title: token.text, body: '' };
slug = router.toURL(path, {id: slugify(token.text)});
index[slug] = {slug: slug, title: token.text, body: ''};
} else {
if (!slug) { return }
if (!slug) {
return
}
if (!index[slug]) {
index[slug] = { slug: slug, title: '', body: '' };
index[slug] = {slug: slug, title: '', body: ''};
} else if (index[slug].body) {
index[slug].body += '\n' + (token.text || '');
} else {
if (index[slug].body) {
index[slug].body += '\n' + (token.text || '');
} else {
index[slug].body = token.text;
}
index[slug].body = token.text;
}
}
});
@@ -73,7 +73,7 @@ function genIndex (path, content, router, depth) {
* @param {String} query
* @returns {Array}
*/
function search (query) {
function search(query) {
var matchingResults = [];
var data = [];
Object.keys(INDEXS).forEach(function (key) {
@@ -81,7 +81,7 @@ function search (query) {
});
query = query.trim();
var keywords = query.split(/[\s\-\\\/]+/);
var keywords = query.split(/[\s\-\\/]+/);
if (keywords.length !== 1) {
keywords = [].concat(query, keywords);
}
@@ -95,7 +95,7 @@ function search (query) {
var postUrl = post.slug || '';
if (postTitle && postContent) {
keywords.forEach(function (keyword, i) {
keywords.forEach(function (keyword) {
// From https://github.com/sindresorhus/escape-string-regexp
var regEx = new RegExp(
keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
@@ -111,7 +111,9 @@ function search (query) {
isMatch = false;
} else {
isMatch = true;
if (indexContent < 0) { indexContent = 0; }
if (indexContent < 0) {
indexContent = 0;
}
var start = 0;
var end = 0;
@@ -119,7 +121,9 @@ function search (query) {
start = indexContent < 11 ? 0 : indexContent - 10;
end = start === 0 ? 70 : indexContent + keyword.length + 60;
if (end > postContent.length) { end = postContent.length; }
if (end > postContent.length) {
end = postContent.length;
}
var matchContent =
'...' +
@@ -149,7 +153,7 @@ function search (query) {
return matchingResults
}
function init$1 (config, vm) {
function init$1(config, vm) {
helper = Docsify;
var isAuto = config.paths === 'auto';
@@ -168,7 +172,9 @@ function init$1 (config, vm) {
var count = 0;
paths.forEach(function (path) {
if (INDEXS[path]) { return count++ }
if (INDEXS[path]) {
return count++
}
helper
.get(vm.router.getFile(path), false, vm.config.requestHeaders)
@@ -181,13 +187,13 @@ function init$1 (config, vm) {
var NO_DATA_TEXT = '';
function style () {
function style() {
var code = "\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0 7px;\n line-height: 36px;\n font-size: 14px;\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.search .clear-button {\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}";
Docsify.dom.style(code);
}
function tpl (opts, defaultValue) {
function tpl(opts, defaultValue) {
if ( defaultValue === void 0 ) defaultValue = '';
var html =
@@ -199,7 +205,7 @@ function tpl (opts, defaultValue) {
Docsify.dom.before(aside, el);
}
function doSearch (value) {
function doSearch(value) {
var $search = Docsify.dom.find('div.search');
var $panel = Docsify.dom.find($search, '.results-panel');
var $clearBtn = Docsify.dom.find($search, '.clear-button');
@@ -222,7 +228,7 @@ function doSearch (value) {
$panel.innerHTML = html || ("<p class=\"empty\">" + NO_DATA_TEXT + "</p>");
}
function bindEvents () {
function bindEvents() {
var $search = Docsify.dom.find('div.search');
var $input = Docsify.dom.find($search, 'input');
var $inputWrap = Docsify.dom.find($search, '.input-wrap');
@@ -239,7 +245,7 @@ function bindEvents () {
timeId = setTimeout(function (_) { return doSearch(e.target.value.trim()); }, 100);
});
Docsify.dom.on($inputWrap, 'click', function (e) {
// click input outside
// Click input outside
if (e.target.tagName !== 'INPUT') {
$input.value = '';
doSearch();
@@ -247,10 +253,12 @@ function bindEvents () {
});
}
function updatePlaceholder (text, path) {
function updatePlaceholder(text, path) {
var $input = Docsify.dom.getNode('.search input[type="search"]');
if (!$input) { return }
if (!$input) {
return
}
if (typeof text === 'string') {
$input.placeholder = text;
} else {
@@ -259,7 +267,7 @@ function updatePlaceholder (text, path) {
}
}
function updateNoData (text, path) {
function updateNoData(text, path) {
if (typeof text === 'string') {
NO_DATA_TEXT = text;
} else {
@@ -268,7 +276,7 @@ function updateNoData (text, path) {
}
}
function init (opts, vm) {
function init(opts, vm) {
var keywords = vm.router.parse().query.s;
style();
@@ -277,7 +285,7 @@ function init (opts, vm) {
keywords && setTimeout(function (_) { return doSearch(keywords); }, 500);
}
function update (opts, vm) {
function update(opts, vm) {
updatePlaceholder(opts.placeholder, vm.route.path);
updateNoData(opts.noData, vm.route.path);
}
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2467 -3442
View File
File diff suppressed because it is too large Load Diff
+26 -15
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "4.6.0",
"version": "4.6.7",
"description": "A magical documentation generator.",
"author": {
"name": "qingwei-li",
@@ -21,42 +21,53 @@
],
"scripts": {
"bootstrap": "npm i && lerna bootstrap && npm run build:ssr",
"build": "rm -rf lib themes && node build/build && mkdir lib/themes && mkdir themes && node build/build-css && npm run build:ssr && node build/build-cover",
"dev:build": "rm -rf lib themes && mkdir themes && node build/build --dev && node build/build-css --dev",
"dev": "node app & nodemon -w src -e js,css --exec 'npm run dev:build'",
"build:ssr": "node build/build-ssr",
"test": "eslint {src,packages} --fix",
"pub:next": "RELEASE_TAG=next sh build/release.sh",
"serve": "node server",
"serve:ssr": "cross-env SSR=1 node server",
"dev": "run-p serve watch:*",
"dev:ssr": "run-p serve:ssr watch:*",
"lint": "eslint {src,packages} --fix",
"test": "run-p lint",
"css": "stylus src/themes/*.styl -u autoprefixer-stylus",
"watch:css": "run-p 'css -- -o themes -w'",
"watch:js": "node build/build.js",
"build:css:min": "mkdir lib/themes && run-p 'css -- -o lib/themes' && node build/mincss.js",
"build:css": "mkdir themes && run-p 'css -- -o themes'",
"build:js": "cross-env NODE_ENV=production node build/build.js",
"build:ssr": "node build/ssr.js",
"build:cover": "node build/cover.js",
"build": "rimraf lib themes && run-s build:js build:css build:css:min build:ssr build:cover",
"pub:next": "cross-env RELEASE_TAG=next sh build/release.sh",
"pub": "sh build/release.sh",
"postinstall": "opencollective postinstall"
},
"dependencies": {
"marked": "^0.3.12",
"opencollective": "^1.0.3",
"medium-zoom": "^0.3.0",
"opencollective": "^1.0.3",
"prismjs": "^1.9.0",
"tinydate": "^1.0.0",
"tweezer.js": "^1.4.0"
},
"devDependencies": {
"autoprefixer-stylus": "^0.14.0",
"chokidar": "^2.0.2",
"conventional-changelog-cli": "^1.3.5",
"cross-env": "^5.1.3",
"cssnano": "^3.10.0",
"eslint": "^4.14.0",
"eslint-config-vue": "^2.0.2",
"eslint-plugin-vue": "^4.0.1",
"eslint-config-xo-space": "^0.18.0",
"lerna": "^2.5.1",
"nodemon": "^1.14.7",
"postcss": "^5.2.16",
"postcss-salad": "^1.0.8",
"live-server": "^1.2.0",
"npm-run-all": "^4.1.2",
"rimraf": "^2.6.2",
"rollup": "^0.53.3",
"rollup-plugin-async": "^1.2.0",
"rollup-plugin-buble": "^0.18.0",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-string": "^2.0.2",
"rollup-plugin-uglify": "^2.0.1",
"serve-static": "^1.13.1"
"stylus": "^0.54.5"
},
"keywords": [
"doc",
+38 -18
View File
@@ -1,18 +1,19 @@
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 {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'
function cwd (...args) {
function cwd(...args) {
return resolve(process.cwd(), ...args)
}
function mainTpl (config) {
function mainTpl(config) {
let html = `<nav class="app-nav${
config.repo ? '' : ' no-badge'
}"><!--navbar--></nav>`
@@ -30,7 +31,7 @@ function mainTpl (config) {
}
export default class Renderer {
constructor ({ template, config, cache }) {
constructor({template, config, cache}) {
this.html = template
this.config = config = Object.assign({}, config, {
routerMode: 'history'
@@ -50,18 +51,18 @@ export default class Renderer {
this.template = this.html
}
_getPath (url) {
_getPath(url) {
const file = this.router.getFile(url)
return isAbsolutePath(file) ? file : cwd(`./${file}`)
}
async renderToString (url) {
async renderToString(url) {
this.url = url = this.router.parse(url).path
const { loadSidebar, loadNavbar, coverpage } = this.config
const {loadSidebar, loadNavbar, coverpage} = this.config
const mainFile = this._getPath(url)
this._renderHtml('main', await this._render(mainFile))
this._renderHtml('main', await this._render(mainFile, 'main'))
if (loadSidebar) {
const name = loadSidebar === true ? '_sidebar.md' : loadSidebar
@@ -99,15 +100,16 @@ export default class Renderer {
return html
}
_renderHtml (match, content) {
_renderHtml(match, content) {
this.html = this.html.replace(new RegExp(`<!--${match}-->`, 'g'), content)
return this.html
}
async _render (path, type) {
async _render(path, type) {
let html = await this._loadFile(path)
const { subMaxLevel, maxLevel } = this.config
const {subMaxLevel, maxLevel} = this.config
let tokens
switch (type) {
case 'sidebar':
@@ -120,6 +122,19 @@ export default class Renderer {
case 'cover':
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
},
r
)
})
html = this.compiler.compile(tokens)
break
case 'navbar':
case 'article':
default:
@@ -130,13 +145,15 @@ export default class Renderer {
return html
}
async _loadFile (filePath) {
async _loadFile(filePath) {
debug('docsify')(`load > ${filePath}`)
let content
try {
if (isAbsolutePath(filePath)) {
const res = await fetch(filePath)
if (!res.ok) throw Error()
if (!res.ok) {
throw Error()
}
content = await res.text()
this.lock = 0
} else {
@@ -152,8 +169,11 @@ export default class Renderer {
}
const fileName = basename(filePath)
const result = await this._loadFile(
resolvePathname(`../${fileName}`, filePath)
)
return await this._loadFile(resolvePathname(`../${fileName}`, filePath))
return result
}
}
}
+1 -1
View File
@@ -37,5 +37,5 @@
"integrity": "sha1-6DWIAbhrg7F1YNTjw4LXrvIQCUQ="
}
},
"version": "4.6.0"
"version": "4.6.7"
}
@@ -1,6 +1,6 @@
{
"name": "docsify-server-renderer",
"version": "4.6.0",
"version": "4.6.7",
"description": "docsify server renderer",
"author": {
"name": "qingwei-li",
+55
View File
@@ -0,0 +1,55 @@
const liveServer = require('live-server')
const isSSR = !!process.env.SSR
const middleware = []
if (isSSR) {
const Renderer = require('./packages/docsify-server-renderer/build.js')
const renderer = new Renderer({
template: `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="/themes/vue.css" title="vue">
</head>
<body>
<!--inject-app-->
<!--inject-config-->
<script src="/lib/docsify.js"></script>
</body>
</html>`,
config: {
name: 'docsify',
repo: 'qingwei-li/docsify',
basePath: 'https://docsify.js.org/',
loadNavbar: true,
loadSidebar: true,
subMaxLevel: 3,
auto2top: true,
alias: {
'/de-de/changelog': '/changelog',
'/zh-cn/changelog': '/changelog',
'/changelog':
'https://raw.githubusercontent.com/QingWei-Li/docsify/master/CHANGELOG'
}
},
path: './'
})
middleware.push(function(req, res, next) {
if (/\.(css|js)$/.test(req.url)) {
return next()
}
renderer.renderToString(req.url).then(html => res.end(html))
})
}
const params = {
port: 3000,
watch: ['lib', 'docs', 'themes'],
middleware
}
liveServer.start(params)
+21 -9
View File
@@ -1,4 +1,4 @@
import { merge, hyphenate, isPrimitive } from './util/core'
import {merge, hyphenate, isPrimitive, hasOwn} from './util/core'
const config = merge(
{
@@ -37,18 +37,30 @@ const script =
if (script) {
for (const prop in config) {
const val = script.getAttribute('data-' + hyphenate(prop))
if (hasOwn.call(config, prop)) {
const val = script.getAttribute('data-' + hyphenate(prop))
if (isPrimitive(val)) {
config[prop] = val === '' ? true : val
if (isPrimitive(val)) {
config[prop] = val === '' ? true : val
}
}
}
if (config.loadSidebar === true) config.loadSidebar = '_sidebar' + config.ext
if (config.loadNavbar === true) config.loadNavbar = '_navbar' + config.ext
if (config.coverpage === true) config.coverpage = '_coverpage' + config.ext
if (config.repo === true) config.repo = ''
if (config.name === true) config.name = ''
if (config.loadSidebar === true) {
config.loadSidebar = '_sidebar' + config.ext
}
if (config.loadNavbar === true) {
config.loadNavbar = '_navbar' + config.ext
}
if (config.coverpage === true) {
config.coverpage = '_coverpage' + config.ext
}
if (config.repo === true) {
config.repo = ''
}
if (config.name === true) {
config.name = ''
}
}
window.$docsify = config
+9 -6
View File
@@ -1,16 +1,19 @@
import { isMobile } from '../util/env'
import { body, on } from '../util/dom'
import {isMobile} from '../util/env'
import {body, on} from '../util/dom'
import * as sidebar from './sidebar'
import { scrollIntoView } from './scroll'
import {scrollIntoView} from './scroll'
export function eventMixin (proto) {
export function eventMixin(proto) {
proto.$resetEvents = function () {
scrollIntoView(this.route.path, this.route.query.id)
sidebar.getAndActive(this.router, 'nav')
if (this.config.loadNavbar) {
sidebar.getAndActive(this.router, 'nav')
}
}
}
export function initEvent (vm) {
export function initEvent(vm) {
// Bind toggle button
sidebar.btn('button.sidebar-toggle', vm.router)
sidebar.collapse('.sidebar', vm.router)
+39 -19
View File
@@ -1,4 +1,4 @@
import { isMobile } from '../util/env'
import {isMobile} from '../util/env'
import * as dom from '../util/dom'
import Tweezer from 'tweezer.js'
@@ -8,8 +8,10 @@ let scroller = null
let enableScrollEvent = true
let coverHeight = 0
function scrollTo (el) {
if (scroller) scroller.stop()
function scrollTo(el) {
if (scroller) {
scroller.stop()
}
enableScrollEvent = false
scroller = new Tweezer({
start: window.pageYOffset,
@@ -24,8 +26,10 @@ function scrollTo (el) {
.begin()
}
function highlight (path) {
if (!enableScrollEvent) return
function highlight(path) {
if (!enableScrollEvent) {
return
}
const sidebar = dom.getNode('.sidebar')
const anchors = dom.findAll('.anchor')
const wrap = dom.find(sidebar, '.sidebar-nav')
@@ -38,22 +42,28 @@ function highlight (path) {
const node = anchors[i]
if (node.offsetTop > top) {
if (!last) last = node
if (!last) {
last = node
}
break
} else {
last = node
}
}
if (!last) return
if (!last) {
return
}
const li = nav[getNavKey(path, last.getAttribute('data-id'))]
if (!li || li === active) return
if (!li || li === active) {
return
}
active && active.classList.remove('active')
li.classList.add('active')
active = li
// scroll into view
// 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
@@ -68,11 +78,11 @@ function highlight (path) {
}
}
function getNavKey (path, id) {
function getNavKey(path, id) {
return `${path}?id=${id}`
}
export function scrollActiveSidebar (router) {
export function scrollActiveSidebar(router) {
const cover = dom.find('.cover.show')
coverHeight = cover ? cover.offsetHeight : 0
@@ -82,18 +92,26 @@ export function scrollActiveSidebar (router) {
for (let i = 0, len = lis.length; i < len; i += 1) {
const li = lis[i]
const a = li.querySelector('a')
if (!a) continue
if (!a) {
continue
}
let href = a.getAttribute('href')
if (href !== '/') {
const { query: { id }, path } = router.parse(href)
if (id) href = getNavKey(path, id)
const {query: {id}, path} = router.parse(href)
if (id) {
href = getNavKey(path, id)
}
}
if (href) nav[decodeURIComponent(href)] = li
if (href) {
nav[decodeURIComponent(href)] = li
}
}
if (isMobile) return
if (isMobile) {
return
}
const path = router.getCurrentPath()
dom.off('scroll', () => highlight(path))
dom.on('scroll', () => highlight(path))
@@ -105,8 +123,10 @@ export function scrollActiveSidebar (router) {
})
}
export function scrollIntoView (path, id) {
if (!id) return
export function scrollIntoView(path, id) {
if (!id) {
return
}
const section = dom.find('#' + id)
section && scrollTo(section)
@@ -120,6 +140,6 @@ export function scrollIntoView (path, id) {
const scrollEl = dom.$.scrollingElement || dom.$.documentElement
export function scroll2Top (offset = 0) {
export function scroll2Top(offset = 0) {
scrollEl.scrollTop = offset === true ? 0 : Number(offset)
}
+9 -7
View File
@@ -1,11 +1,11 @@
import { isMobile } from '../util/env'
import {isMobile} from '../util/env'
import * as dom from '../util/dom'
const title = dom.$.title
/**
* Toggle button
*/
export function btn (el, router) {
export function btn(el) {
const toggle = _ => dom.body.classList.toggle('close')
el = dom.getNode(el)
@@ -22,10 +22,10 @@ export function btn (el, router) {
)
}
export function collapse (el, router) {
export function collapse(el) {
el = dom.getNode(el)
dom.on(el, 'click', ({ target }) => {
dom.on(el, 'click', ({target}) => {
if (
target.nodeName === 'A' &&
target.nextSibling &&
@@ -36,9 +36,11 @@ export function collapse (el, router) {
})
}
export function sticky () {
export function sticky() {
const cover = dom.getNode('section.cover')
if (!cover) return
if (!cover) {
return
}
const coverHeight = cover.getBoundingClientRect().height
if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) {
@@ -56,7 +58,7 @@ export function sticky () {
* @param {Boolean} autoTitle auto set title
* @return {element}
*/
export function getAndActive (router, el, isParent, autoTitle) {
export function getAndActive(router, el, isParent, autoTitle) {
el = dom.getNode(el)
const links = dom.findAll(el, 'a')
+7 -5
View File
@@ -1,5 +1,5 @@
import progressbar from '../render/progressbar'
import { noop } from '../util/core'
import {noop, hasOwn} from '../util/core'
const cache = {}
@@ -9,7 +9,7 @@ const cache = {}
* @param {boolean} [hasBar=false] has progress bar
* @return { then(resolve, reject), abort }
*/
export function get (url, hasBar = false, headers = {}) {
export function get(url, hasBar = false, headers = {}) {
const xhr = new XMLHttpRequest()
const on = function () {
xhr.addEventListener.apply(xhr, arguments)
@@ -17,12 +17,14 @@ export function get (url, hasBar = false, headers = {}) {
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)
for (const i in headers) {
xhr.setRequestHeader(i, headers[i])
if (hasOwn.call(headers, i)) {
xhr.setRequestHeader(i, headers[i])
}
}
xhr.send()
@@ -45,7 +47,7 @@ export function get (url, hasBar = false, headers = {}) {
}
on('error', error)
on('load', ({ target }) => {
on('load', ({target}) => {
if (target.status >= 400) {
error(target)
} else {
+128 -32
View File
@@ -1,14 +1,16 @@
import { get } from './ajax'
import { callHook } from '../init/lifecycle'
import { getParentPath, stringifyQuery } from '../router/util'
import { noop } from '../util/core'
import { getAndActive } from '../event/sidebar'
import {get} from './ajax'
import {callHook} from '../init/lifecycle'
import {getParentPath, stringifyQuery} from '../router/util'
import {noop} from '../util/core'
import {getAndActive} from '../event/sidebar'
function loadNested (path, qs, file, next, vm, first) {
function loadNested(path, qs, file, next, vm, first) {
path = first ? path : path.replace(/\/$/, '')
path = getParentPath(path)
if (!path) return
if (!path) {
return
}
get(
vm.router.getFile(path + file) + qs,
@@ -17,23 +19,50 @@ function loadNested (path, qs, file, next, vm, first) {
).then(next, _ => loadNested(path, qs, file, next, vm))
}
export function fetchMixin (proto) {
export function fetchMixin(proto) {
let last
proto._fetch = function (cb = noop) {
const { path, query } = this.route
const qs = stringifyQuery(query, ['id'])
const { loadNavbar, loadSidebar, requestHeaders } = this.config
// Abort last request
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
}
last = get(this.router.getFile(path) + qs, true, requestHeaders)
const get404Path = (path, config) => {
const {notFoundPage, ext} = config
const defaultPath = '_404' + (ext || '.md')
let key
let path404
// Current page is html
this.isHTML = /\.html$/g.test(path)
switch (typeof notFoundPage) {
case 'boolean':
path404 = defaultPath
break
case 'string':
path404 = notFoundPage
break
const loadSideAndNav = () => {
if (!loadSidebar) return cb()
case 'object':
key = Object.keys(notFoundPage)
.sort((a, b) => b.length - a.length)
.find(key => path.match(new RegExp('^' + key)))
path404 = (key && notFoundPage[key]) || defaultPath
break
default:
break
}
return path404
}
proto._loadSideAndNav = function (path, qs, loadSidebar, cb) {
return () => {
if (!loadSidebar) {
return cb()
}
const fn = result => {
this._renderSidebar(result)
@@ -43,16 +72,30 @@ export function fetchMixin (proto) {
// Load sidebar
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
// Abort last request
const file = this.router.getFile(path)
const req = request(file + qs, true, requestHeaders)
// Current page is html
this.isHTML = /\.html$/g.test(file)
// Load main content
last.then(
(text, opt) => {
this._renderMain(text, opt)
loadSideAndNav()
},
req.then(
(text, opt) =>
this._renderMain(
text,
opt,
this._loadSideAndNav(path, qs, loadSidebar, cb)
),
_ => {
this._renderMain(null)
loadSideAndNav()
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb)
}
)
@@ -69,7 +112,7 @@ export function fetchMixin (proto) {
}
proto._fetchCover = function () {
const { coverpage, requestHeaders } = this.config
const {coverpage, requestHeaders} = this.config
const query = this.route.query
const root = getParentPath(this.route.path)
@@ -87,7 +130,7 @@ export function fetchMixin (proto) {
path = cover === true ? '_coverpage' : cover
}
const coverOnly = !!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)
@@ -112,18 +155,71 @@ export function fetchMixin (proto) {
if (onlyCover) {
done()
} else {
this._fetch(result => {
this._fetch(() => {
this.$resetEvents()
done()
})
}
}
proto._fetchFallbackPage = function (path, qs, cb = noop) {
const {requestHeaders, fallbackLanguages, loadSidebar} = this.config
if (!fallbackLanguages) {
return false
}
const local = path.split('/')[1]
if (fallbackLanguages.indexOf(local) === -1) {
return false
}
const newPath = path.replace(new RegExp(`^/${local}`), '')
const req = request(newPath + qs, true, requestHeaders)
req.then(
(text, opt) =>
this._renderMain(
text,
opt,
this._loadSideAndNav(path, qs, loadSidebar, cb)
),
() => this._fetch404(path, qs, cb)
)
return true
}
/**
* Load the 404 page
* @param path
* @param qs
* @param cb
* @returns {*}
* @private
*/
proto._fetch404 = function (path, qs, cb = noop) {
const {loadSidebar, requestHeaders, notFoundPage} = this.config
const fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb)
if (notFoundPage) {
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
}
this._renderMain(null, {}, fnLoadSideAndNav)
return false
}
}
export function initFetch (vm) {
const { loadSidebar } = vm.config
export function initFetch(vm) {
const {loadSidebar} = vm.config
// server-client renderer
// Server-Side Rendering
if (vm.rendered) {
const activeEl = getAndActive(vm.router, '.sidebar-nav', true, true)
if (loadSidebar && activeEl) {
+4 -4
View File
@@ -1,13 +1,13 @@
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 {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 () {
window.Docsify = { util, dom, get, slugify }
window.Docsify = {util, dom, get, slugify}
window.DocsifyCompiler = Compiler
window.marked = marked
window.Prism = prism
+7 -7
View File
@@ -1,14 +1,14 @@
import { initMixin } from './init'
import { routerMixin } from './router'
import { renderMixin } from './render'
import { fetchMixin } from './fetch'
import { eventMixin } from './event'
import {initMixin} from './init'
import {routerMixin} from './router'
import {renderMixin} from './render'
import {fetchMixin} from './fetch'
import {eventMixin} from './event'
import initGlobalAPI from './global-api'
/**
* Fork https://github.com/bendrucker/document-ready/blob/master/index.js
*/
function ready (callback) {
function ready(callback) {
const state = document.readyState
if (state === 'complete' || state === 'interactive') {
@@ -18,7 +18,7 @@ function ready (callback) {
document.addEventListener('DOMContentLoaded', callback)
}
function Docsify () {
function Docsify() {
this._init()
}
+8 -8
View File
@@ -1,12 +1,12 @@
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 {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'
export function initMixin (proto) {
export function initMixin(proto) {
proto._init = function () {
const vm = this
vm.config = config || {}
@@ -22,6 +22,6 @@ export function initMixin (proto) {
}
}
function initPlugin (vm) {
function initPlugin(vm) {
[].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm._lifecycle, vm))
}
+12 -14
View File
@@ -1,6 +1,6 @@
import { noop } from '../util/core'
import {noop} from '../util/core'
export function initLifecycle (vm) {
export function initLifecycle(vm) {
const hooks = [
'init',
'mounted',
@@ -18,28 +18,26 @@ export function initLifecycle (vm) {
})
}
export function callHook (vm, hook, data, next = noop) {
export function callHook(vm, hook, data, next = noop) {
const queue = vm._hooks[hook]
const step = function (index) {
const hook = queue[index]
if (index >= queue.length) {
next(data)
} else {
if (typeof hook === 'function') {
if (hook.length === 2) {
hook(data, result => {
data = result
step(index + 1)
})
} else {
const result = hook(data)
data = result !== undefined ? result : data
} else if (typeof hook === 'function') {
if (hook.length === 2) {
hook(data, result => {
data = result
step(index + 1)
}
})
} else {
const result = hook(data)
data = result === undefined ? data : result
step(index + 1)
}
} else {
step(index + 1)
}
}
+102 -104
View File
@@ -1,17 +1,15 @@
import marked from 'marked'
import Prism from 'prismjs'
import { helper as helperTpl, tree as treeTpl } from './tpl'
import { genTree } from './gen-tree'
import { slugify } from './slugify'
import { emojify } from './emojify'
import { isAbsolutePath, getPath } from '../router/util'
import { isFn, merge, cached } from '../util/core'
import { get } from '../fetch/ajax'
import {helper as helperTpl, tree as treeTpl} from './tpl'
import {genTree} from './gen-tree'
import {slugify} from './slugify'
import {emojify} from './emojify'
import {isAbsolutePath, getPath} from '../router/util'
import {isFn, merge, cached, isPrimitive} from '../util/core'
const cachedLinks = {}
let uid = 0
function getAndRemoveConfig (str = '') {
export function getAndRemoveConfig(str = '') {
const config = {}
if (str) {
@@ -23,70 +21,47 @@ function getAndRemoveConfig (str = '') {
.trim()
}
return { str, config }
return {str, config}
}
const compileMedia = {
markdown (url) {
const id = `docsify-get-${uid++}`
if (!process.env.SSR) {
get(url, false).then(text => {
document.getElementById(id).innerHTML = this.compile(text)
})
return `<div data-origin="${url}" id=${id}></div>`
} else {
return `<div data-origin="${url}" id=${uid}></div>
<script>
var compile = window.__current_docsify_compiler__
Docsify.get('${url}', false).then(function(text) {
document.getElementById('${uid}').innerHTML = compile(text)
})
</script>`
markdown(url) {
return {
url
}
},
iframe (url, title) {
return `<iframe src="${url}" ${title || 'width=100% height=400'}></iframe>`
iframe(url, title) {
return {
code: `<iframe src="${url}" ${title || 'width=100% height=400'}></iframe>`
}
},
video (url, title) {
return `<video src="${url}" ${title || 'controls'}>Not Support</video>`
video(url, title) {
return {
code: `<video src="${url}" ${title || 'controls'}>Not Support</video>`
}
},
audio (url, title) {
return `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`
audio(url, title) {
return {
code: `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`
}
},
code (url, title) {
const id = `docsify-get-${uid++}`
let ext = url.match(/\.(\w+)$/)
code(url, title) {
let lang = url.match(/\.(\w+)$/)
ext = title || (ext && ext[1])
if (ext === 'md') ext = 'markdown'
lang = title || (lang && lang[1])
if (lang === 'md') {
lang = 'markdown'
}
if (!process.env.SSR) {
get(url, false).then(text => {
document.getElementById(id).innerHTML = this.compile(
'```' + ext + '\n' + text.replace(/`/g, '@qm@') + '\n```\n'
).replace(/@qm@/g, '`')
})
return `<div data-origin="${url}" id=${id}></div>`
} else {
return `<div data-origin="${url}" id=${id}></div>
<script>
setTimeout(() => {
var compiler = window.__current_docsify_compiler__
Docsify.get('${url}', false).then(function(text) {
document.getElementById('${id}').innerHTML = compiler
.compile('\`\`\`${ext}\\n' + text.replace(/\`/g, '@qm@') + '\\n\`\`\`\\n')
.replace(/@qm@/g, '\`')
})
})
</script>`
return {
url,
lang
}
}
}
export class Compiler {
constructor (config, router) {
constructor(config, router) {
this.config = config
this.router = router
this.cacheTree = {}
@@ -109,12 +84,20 @@ export class Compiler {
compile = marked
}
this._marked = compile
this.compile = cached(text => {
let html = ''
if (!text) return text
if (!text) {
return text
}
if (isPrimitive(text)) {
html = compile(text)
} else {
html = compile.parser(text)
}
html = compile(text)
html = config.noEmoji ? html : emojify(html)
slugify.clear()
@@ -122,7 +105,40 @@ export class Compiler {
})
}
matchNotCompileLink (link) {
compileEmbed(href, title) {
const {str, config} = getAndRemoveConfig(title)
let embed
title = str
if (config.include) {
if (!isAbsolutePath(href)) {
href = getPath(process.env.SSR ? '' : this.contentBase, href)
}
let media
if (config.type && (media = compileMedia[config.type])) {
embed = media.call(this, href, title)
embed.type = config.type
} else {
let type = 'code'
if (/\.(md|markdown)/.test(href)) {
type = 'markdown'
} else if (/\.html?/.test(href)) {
type = 'iframe'
} else if (/\.(mp4|ogg)/.test(href)) {
type = 'video'
} else if (/\.mp3/.test(href)) {
type = 'audio'
}
embed = compileMedia[type].call(this, href, title)
embed.type = type
}
return embed
}
}
_matchNotCompileLink(link) {
const links = this.config.noCompileLinks || []
for (var i = 0; i < links.length; i++) {
@@ -135,18 +151,18 @@ export class Compiler {
}
}
_initRenderer () {
_initRenderer() {
const renderer = new marked.Renderer()
const { linkTarget, router, contentBase } = this
const {linkTarget, router, contentBase} = this
const _self = this
const origin = {}
/**
* render anchor tag
* Render anchor tag
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
origin.heading = renderer.heading = function (text, level) {
const nextToc = { level, title: text }
const nextToc = {level, title: text}
if (/{docsify-ignore}/g.test(text)) {
text = text.replace('{docsify-ignore}', '')
@@ -161,14 +177,15 @@ export class Compiler {
}
const slug = slugify(text)
const url = router.toURL(router.getCurrentPath(), { id: slug })
const url = router.toURL(router.getCurrentPath(), {id: slug})
nextToc.slug = url
_self.toc.push(nextToc)
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
}
// highlight code
// Highlight code
origin.code = renderer.code = function (code, lang = '') {
code = code.replace(/@DOCSIFY_QM@/g, '`')
const hl = Prism.highlight(
code,
Prism.languages[lang] || Prism.languages.markup
@@ -179,39 +196,17 @@ export class Compiler {
origin.link = renderer.link = function (href, title = '', text) {
let attrs = ''
const { str, config } = getAndRemoveConfig(title)
const {str, config} = getAndRemoveConfig(title)
title = str
if (config.include) {
if (!isAbsolutePath(href)) {
href = getPath(contentBase, href)
}
let media
if (config.type && (media = compileMedia[config.type])) {
return media.call(_self, href, title)
}
let type = 'code'
if (/\.(md|markdown)/.test(href)) {
type = 'markdown'
} else if (/\.html?/.test(href)) {
type = 'iframe'
} else if (/\.(mp4|ogg)/.test(href)) {
type = 'video'
} else if (/\.mp3/.test(href)) {
type = 'audio'
}
return compileMedia[type].call(_self, href, title)
}
if (
!/:|(\/{2})/.test(href) &&
!_self.matchNotCompileLink(href) &&
!_self._matchNotCompileLink(href) &&
!config.ignore
) {
if (href === _self.config.homepage) href = 'README'
if (href === _self.config.homepage) {
href = 'README'
}
href = router.toURL(href, null, router.getCurrentPath())
} else {
attrs += ` target="${linkTarget}"`
@@ -233,18 +228,21 @@ export class Compiler {
return `<a href="${href}"${attrs}>${text}</a>`
}
origin.paragraph = renderer.paragraph = function (text) {
let result
if (/^!&gt;/.test(text)) {
return helperTpl('tip', text)
result = helperTpl('tip', text)
} else if (/^\?&gt;/.test(text)) {
return helperTpl('warn', text)
result = helperTpl('warn', text)
} else {
result = `<p>${text}</p>`
}
return `<p>${text}</p>`
return result
}
origin.image = renderer.image = function (href, title, text) {
let url = href
let attrs = ''
const { str, config } = getAndRemoveConfig(title)
const {str, config} = getAndRemoveConfig(title)
title = str
if (config['no-zoom']) {
@@ -282,7 +280,7 @@ export class Compiler {
/**
* Compile sidebar
*/
sidebar (text, level) {
sidebar(text, level) {
const currentPath = this.router.getCurrentPath()
let html = ''
@@ -301,13 +299,13 @@ export class Compiler {
/**
* Compile sub sidebar
*/
subSidebar (level) {
subSidebar(level) {
if (!level) {
this.toc = []
return
}
const currentPath = this.router.getCurrentPath()
const { cacheTree, toc } = this
const {cacheTree, toc} = this
toc[0] && toc[0].ignoreAllSubs && toc.splice(0)
toc[0] && toc[0].level === 1 && toc.shift()
@@ -323,14 +321,14 @@ export class Compiler {
return treeTpl(tree, '<ul class="app-sub-sidebar">')
}
article (text) {
article(text) {
return this.compile(text)
}
/**
* Compile cover page
*/
cover (text) {
cover(text) {
const cacheToc = this.toc.slice()
const html = this.compile(text)
+91
View File
@@ -0,0 +1,91 @@
import {get} from '../fetch/ajax'
import {merge} from '../util/core'
const cached = {}
function walkFetchEmbed({step = 0, embedTokens, compile, fetch}, cb) {
const token = embedTokens[step]
if (!token) {
return cb({})
}
const next = text => {
let embedToken
if (text) {
if (token.embed.type === 'markdown') {
embedToken = compile.lexer(text)
} else if (token.embed.type === 'code') {
embedToken = compile.lexer(
'```' +
token.embed.lang +
'\n' +
text.replace(/`/g, '@DOCSIFY_QM@') +
'\n```\n'
)
}
}
cb({token, embedToken})
walkFetchEmbed({step: ++step, compile, embedTokens, fetch}, cb)
}
if (process.env.SSR) {
fetch(token.embed.url).then(next)
} else {
get(token.embed.url).then(next)
}
}
export function prerenderEmbed({compiler, raw = '', fetch}, done) {
let hit
if ((hit = cached[raw])) {
return done(hit)
}
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)
if (embed) {
if (embed.type === 'markdown' || embed.type === 'code') {
embedTokens.push({
index,
embed
})
}
return embed.code
}
return src
}
)
}
})
let moveIndex = 0
walkFetchEmbed({compile, embedTokens, fetch}, ({embedToken, token}) => {
if (token) {
const index = token.index + moveIndex
merge(links, embedToken.links)
tokens = tokens
.slice(0, index)
.concat(embedToken, tokens.slice(index + 1))
moveIndex += embedToken.length - 1
} else {
cached[raw] = tokens.concat()
tokens.links = cached[raw].links = links
done(tokens)
}
})
}
+3 -3
View File
@@ -1,10 +1,10 @@
import { inBrowser } from '../util/env'
import {inBrowser} from '../util/env'
function replace (m, $1) {
function replace(m, $1) {
return '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
}
export function emojify (text) {
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)
+5 -3
View File
@@ -1,11 +1,11 @@
/**
* gen toc tree
* Gen toc tree
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
* @param {Array} toc
* @param {Number} maxLevel
* @return {Array}
*/
export function genTree (toc, maxLevel) {
export function genTree(toc, maxLevel) {
const headlines = []
const last = {}
@@ -13,7 +13,9 @@ export function genTree (toc, maxLevel) {
const level = headline.level || 1
const len = level - 1
if (level > maxLevel) return
if (level > maxLevel) {
return
}
if (last[len]) {
last[len].children = (last[len].children || []).concat(headline)
} else {
+68 -37
View File
@@ -2,47 +2,51 @@ 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 {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'
function executeScript () {
function executeScript() {
const script = dom
.findAll('.markdown-section>script')
.filter(s => !/template/.test(s.type))[0]
if (!script) return false
if (!script) {
return false
}
const code = script.innerText.trim()
if (!code) return false
if (!code) {
return false
}
setTimeout(_ => {
window.__EXECUTE_RESULT__ = new Function(code)()
}, 0)
}
function formatUpdated (html, updated, fn) {
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)
}
function renderMain (html) {
function renderMain(html) {
if (!html) {
// TODO: Custom 404 page
html = 'not found'
html = '<h1>404 - Not found</h1>'
}
this._renderTo('.markdown-section', html)
// Render sidebar with the TOC
!this.config.loadSidebar && this._renderSidebar()
// execute script
// Execute script
if (
this.config.executeScript !== false &&
typeof window.Vue !== 'undefined' &&
@@ -58,12 +62,14 @@ function renderMain (html) {
}
}
function renderNameLink (vm) {
function renderNameLink(vm) {
const el = dom.getNode('.app-name-link')
const nameLink = vm.config.nameLink
const path = vm.route.path
if (!el) return
if (!el) {
return
}
if (isPrimitive(vm.config.nameLink)) {
el.setAttribute('href', nameLink)
@@ -74,14 +80,16 @@ function renderNameLink (vm) {
}
}
export function renderMixin (proto) {
export function renderMixin(proto) {
proto._renderTo = function (el, content, replace) {
const node = dom.getNode(el)
if (node) node[replace ? 'outerHTML' : 'innerHTML'] = content
if (node) {
node[replace ? 'outerHTML' : 'innerHTML'] = content
}
}
proto._renderSidebar = function (text) {
const { maxLevel, subMaxLevel, loadSidebar } = this.config
const {maxLevel, subMaxLevel, loadSidebar} = this.config
this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel))
const activeEl = getAndActive(this.router, '.sidebar-nav', true, true)
@@ -89,15 +97,15 @@ export function renderMixin (proto) {
activeEl.parentNode.innerHTML +=
this.compiler.subSidebar(subMaxLevel) || ''
} else {
// reset toc
// Reset toc
this.compiler.subSidebar()
}
// bind event
// Bind event
this._bindEventOnRendered(activeEl)
}
proto._bindEventOnRendered = function (activeEl) {
const { autoHeader, auto2top } = this.config
const {autoHeader, auto2top} = this.config
scrollActiveSidebar(this.router)
@@ -116,21 +124,42 @@ export function renderMixin (proto) {
proto._renderNav = function (text) {
text && this._renderTo('nav', this.compiler.compile(text))
getAndActive(this.router, 'nav')
if (this.config.loadNavbar) {
getAndActive(this.router, 'nav')
}
}
proto._renderMain = function (text, opt = {}) {
proto._renderMain = function (text, opt = {}, next) {
if (!text) {
return renderMain.call(this, text)
}
callHook(this, 'beforeEach', text, result => {
let html = this.isHTML ? result : this.compiler.compile(result)
if (opt.updatedAt) {
html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated)
}
let html
const callback = () => {
if (opt.updatedAt) {
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()
} else {
prerenderEmbed(
{
compiler: this.compiler,
raw: result
},
tokens => {
html = this.compiler.compile(tokens)
callback()
next()
}
)
}
})
}
@@ -171,18 +200,18 @@ export function renderMixin (proto) {
}
proto._updateRender = function () {
// render name link
// Render name link
renderNameLink(this)
}
}
export function initRender (vm) {
export function initRender(vm) {
const config = vm.config
// Init markdown compiler
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'
@@ -218,7 +247,9 @@ export function initRender (vm) {
}
// Add nav
dom.before(navAppendToTarget, navEl)
if (config.loadNavbar) {
dom.before(navAppendToTarget, navEl)
}
if (config.themeColor) {
dom.$.head.appendChild(
+2 -2
View File
@@ -6,7 +6,7 @@ let timeId
/**
* Init progress component
*/
function init () {
function init() {
const div = dom.create('div')
div.classList.add('progress')
@@ -16,7 +16,7 @@ function init () {
/**
* Render progress bar
*/
export default function ({ loaded, total, step }) {
export default function ({loaded, total, step}) {
let num
!barEl && init()
+10 -6
View File
@@ -1,12 +1,16 @@
let cache = {}
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g
import {hasOwn} from '../util/core'
function lower (string) {
let cache = {}
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g
function lower(string) {
return string.toLowerCase()
}
export function slugify (str) {
if (typeof str !== 'string') return ''
export function slugify(str) {
if (typeof str !== 'string') {
return ''
}
let slug = str
.trim()
@@ -18,7 +22,7 @@ export function slugify (str) {
.replace(/^(\d)/, '_$1')
let count = cache[slug]
count = cache.hasOwnProperty(slug) ? count + 1 : 0
count = hasOwn.call(cache, slug) ? count + 1 : 0
cache[slug] = count
if (count) {
+19 -13
View File
@@ -1,12 +1,16 @@
import { isMobile } from '../util/env'
import {isMobile} from '../util/env'
/**
* Render github corner
* @param {Object} data
* @return {String}
*/
export function corner (data) {
if (!data) return ''
if (!/\/\//.test(data)) data = 'https://github.com/' + data
export function corner(data) {
if (!data) {
return ''
}
if (!/\/\//.test(data)) {
data = 'https://github.com/' + data
}
data = data.replace(/^git\+/, '')
return (
@@ -23,7 +27,7 @@ export function corner (data) {
/**
* Render main content
*/
export function main (config) {
export function main(config) {
const aside =
'<button class="sidebar-toggle">' +
'<div class="sidebar-toggle-button">' +
@@ -31,9 +35,9 @@ export function main (config) {
'</div>' +
'</button>' +
'<aside class="sidebar">' +
(config.name
? `<h1><a class="app-name-link" data-nosearch>${config.name}</a></h1>`
: '') +
(config.name ?
`<h1><a class="app-name-link" data-nosearch>${config.name}</a></h1>` :
'') +
'<div class="sidebar-nav"><!--sidebar--></div>' +
'</aside>'
@@ -49,7 +53,7 @@ export function main (config) {
/**
* Cover Page
*/
export function cover () {
export function cover() {
const SL = ', 100%, 85%'
const bgc =
'linear-gradient(to left bottom, ' +
@@ -70,8 +74,10 @@ export function cover () {
* @param {String} tpl
* @return {String}
*/
export function tree (toc, tpl = '') {
if (!toc || !toc.length) return ''
export function tree(toc, tpl = '') {
if (!toc || !toc.length) {
return ''
}
toc.forEach(node => {
tpl += `<li><a class="section-link" href="${node.slug}">${
@@ -85,10 +91,10 @@ export function tree (toc, tpl = '') {
return tpl
}
export function helper (className, content) {
export function helper(className, content) {
return `<p class="${className}">${content.slice(5).trim()}</p>`
}
export function theme (color) {
export function theme(color) {
return `<style>:root{--theme-color: ${color};}</style>`
}
+4 -4
View File
@@ -1,13 +1,13 @@
import { History } from './base'
import { parseQuery } from '../util'
import {History} from './base'
import {parseQuery} from '../util'
export class AbstractHistory extends History {
constructor (config) {
constructor(config) {
super(config)
this.mode = 'abstract'
}
parse (path) {
parse(path) {
let query = ''
const queryIndex = path.indexOf('?')
+19 -19
View File
@@ -5,40 +5,40 @@ import {
cleanPath,
replaceSlug
} from '../util'
import { noop, merge } from '../../util/core'
import {noop, merge} from '../../util/core'
const cached = {}
function getAlias (path, alias, last) {
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]
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}`
function getFileName(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) {
constructor(config) {
this.config = config
}
getBasePath () {
getBasePath() {
return this.config.basePath
}
getFile (path = this.getCurrentPath(), isRelative) {
const { config } = this
getFile(path = this.getCurrentPath(), isRelative) {
const {config} = this
const base = this.getBasePath()
const ext = typeof config.ext !== 'string' ? '.md' : config.ext
const ext = typeof config.ext === 'string' ? config.ext : '.md'
path = config.alias ? getAlias(path, config.alias) : path
path = getFileName(path, ext)
@@ -52,17 +52,17 @@ export class History {
return path
}
onchange (cb = noop) {
onchange(cb = noop) {
cb()
}
getCurrentPath () {}
getCurrentPath() {}
normalize () {}
normalize() {}
parse () {}
parse() {}
toURL (path, params, currentRoute) {
toURL(path, params, currentRoute) {
const local = currentRoute && path[0] === '#'
const route = this.parse(replaceSlug(path))
+15 -13
View File
@@ -1,27 +1,27 @@
import { History } from './base'
import { noop } from '../../util/core'
import { on } from '../../util/dom'
import { parseQuery, cleanPath, replaceSlug } from '../util'
import {History} from './base'
import {noop} from '../../util/core'
import {on} from '../../util/dom'
import {parseQuery, cleanPath, replaceSlug} from '../util'
function replaceHash (path) {
function replaceHash(path) {
const i = location.href.indexOf('#')
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path)
}
export class HashHistory extends History {
constructor (config) {
constructor(config) {
super(config)
this.mode = 'hash'
}
getBasePath () {
getBasePath() {
const path = window.location.pathname || ''
const base = this.config.basePath
return /^(\/|https?:)/g.test(base) ? base : cleanPath(path + '/' + base)
}
getCurrentPath () {
getCurrentPath() {
// We can't use location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = location.href
@@ -29,16 +29,18 @@ export class HashHistory extends History {
return index === -1 ? '' : href.slice(index + 1)
}
onchange (cb = noop) {
onchange(cb = noop) {
on('hashchange', cb)
}
normalize () {
normalize() {
let path = this.getCurrentPath()
path = replaceSlug(path)
if (path.charAt(0) === '/') return replaceHash(path)
if (path.charAt(0) === '/') {
return replaceHash(path)
}
replaceHash('/' + path)
}
@@ -47,7 +49,7 @@ export class HashHistory extends History {
* @param {string} [path=location.herf]
* @return {object} { path, query }
*/
parse (path = location.href) {
parse(path = location.href) {
let query = ''
const hashIndex = path.indexOf('#')
@@ -68,7 +70,7 @@ export class HashHistory extends History {
}
}
toURL (path, params, currentRoute) {
toURL(path, params, currentRoute) {
return '#' + super.toURL(path, params, currentRoute)
}
}
+9 -9
View File
@@ -1,15 +1,15 @@
import { History } from './base'
import { noop } from '../../util/core'
import { on } from '../../util/dom'
import { parseQuery, getPath } from '../util'
import {History} from './base'
import {noop} from '../../util/core'
import {on} from '../../util/dom'
import {parseQuery, getPath} from '../util'
export class HTML5History extends History {
constructor (config) {
constructor(config) {
super(config)
this.mode = 'history'
}
getCurrentPath () {
getCurrentPath() {
const base = this.getBasePath()
let path = window.location.pathname
@@ -20,14 +20,14 @@ export class HTML5History extends History {
return (path || '/') + window.location.search + window.location.hash
}
onchange (cb = noop) {
onchange(cb = noop) {
on('click', e => {
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)
window.history.pushState({key: url}, '', url)
cb()
}
})
@@ -40,7 +40,7 @@ export class HTML5History extends History {
* @param {string} [path=location.href]
* @return {object} { path, query }
*/
parse (path = location.href) {
parse(path = location.href) {
let query = ''
const queryIndex = path.indexOf('?')
+6 -6
View File
@@ -1,21 +1,21 @@
import { HashHistory } from './history/hash'
import { HTML5History } from './history/html5'
import { supportsPushState } from '../util/env'
import {HashHistory} from './history/hash'
import {HTML5History} from './history/html5'
import {supportsPushState} from '../util/env'
import * as dom from '../util/dom'
export function routerMixin (proto) {
export function routerMixin(proto) {
proto.route = {}
}
let lastRoute = {}
function updateRender (vm) {
function updateRender(vm) {
vm.router.normalize()
vm.route = vm.router.parse()
dom.body.setAttribute('data-page', vm.route.file)
}
export function initRouter (vm) {
export function initRouter(vm) {
const config = vm.config
const mode = config.routerMode || 'hash'
let router
+16 -14
View File
@@ -1,9 +1,9 @@
import { cached } from '../util/core'
import {cached} from '../util/core'
const decode = decodeURIComponent
const encode = encodeURIComponent
export function parseQuery (query) {
export function parseQuery(query) {
const res = {}
query = query.trim().replace(/^(\?|#|&)/, '')
@@ -22,39 +22,41 @@ export function parseQuery (query) {
return res
}
export function stringifyQuery (obj, ignores = []) {
export function stringifyQuery(obj, ignores = []) {
const qs = []
for (const key in obj) {
if (ignores.indexOf(key) > -1) continue
if (ignores.indexOf(key) > -1) {
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('&')}` : ''
}
export function getPath (...args) {
return cleanPath(args.join('/'))
}
export const isAbsolutePath = cached(path => {
return /(:|(\/{2}))/g.test(path)
})
export const getParentPath = cached(path => {
return /\/$/g.test(path)
? path
: (path = path.match(/(\S*\/)[^\/]+$/)) ? path[1] : ''
return /\/$/g.test(path) ?
path :
(path = path.match(/(\S*\/)[^/]+$/)) ? path[1] : ''
})
export const cleanPath = cached(path => {
return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/')
})
export function getPath(...args) {
return cleanPath(args.join('/'))
}
export const replaceSlug = cached(path => {
return path.replace('#', '?id=')
})
+10 -9
View File
@@ -1,11 +1,12 @@
/**
* Create a cached version of a pure function.
*/
export function cached (fn) {
export function cached(fn) {
const cache = Object.create(null)
return function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
return function (str) {
const key = isPrimitive(str) ? str : JSON.stringify(str)
const hit = cache[key]
return hit || (cache[key] = fn(str))
}
}
@@ -16,14 +17,14 @@ export const hyphenate = cached(str => {
return str.replace(/([A-Z])/g, m => '-' + m.toLowerCase())
})
export const hasOwn = Object.prototype.hasOwnProperty
/**
* Simple Object.assign polyfill
*/
export const merge =
Object.assign ||
function (to) {
const hasOwn = Object.prototype.hasOwnProperty
for (let i = 1; i < arguments.length; i++) {
const from = Object(arguments[i])
@@ -40,18 +41,18 @@ export const merge =
/**
* Check if value is primitive
*/
export function isPrimitive (value) {
export function isPrimitive(value) {
return typeof value === 'string' || typeof value === 'number'
}
/**
* Perform no operation.
*/
export function noop () {}
export function noop() {}
/**
* Check if value is function
*/
export function isFn (obj) {
export function isFn(obj) {
return typeof obj === 'function'
}
+21 -19
View File
@@ -1,5 +1,5 @@
import { isFn } from '../util/core'
import { inBrowser } from './env'
import {isFn} from '../util/core'
import {inBrowser} from './env'
const cacheNode = {}
@@ -9,7 +9,7 @@ const cacheNode = {}
* @param {Boolean} noCache
* @return {Element}
*/
export function getNode (el, noCache = false) {
export function getNode(el, noCache = false) {
if (typeof el === 'string') {
if (typeof window.Vue !== 'undefined') {
return find(el)
@@ -32,7 +32,7 @@ export const head = inBrowser && $.head
* find('nav') => document.querySelector('nav')
* find(nav, 'a') => nav.querySelector('a')
*/
export function find (el, node) {
export function find(el, node) {
return node ? el.querySelector(node) : $.querySelector(el)
}
@@ -42,36 +42,38 @@ export function find (el, node) {
* findAll('a') => [].slice.call(document.querySelectorAll('a'))
* findAll(nav, 'a') => [].slice.call(nav.querySelectorAll('a'))
*/
export function findAll (el, node) {
export function findAll(el, node) {
return [].slice.call(
node ? el.querySelectorAll(node) : $.querySelectorAll(el)
)
}
export function create (node, tpl) {
export function create(node, tpl) {
node = $.createElement(node)
if (tpl) node.innerHTML = tpl
if (tpl) {
node.innerHTML = tpl
}
return node
}
export function appendTo (target, el) {
export function appendTo(target, el) {
return target.appendChild(el)
}
export function before (target, el) {
export function before(target, el) {
return target.insertBefore(el, target.children[0])
}
export function on (el, type, handler) {
isFn(type)
? window.addEventListener(el, type)
: el.addEventListener(type, handler)
export function on(el, 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)
export function off(el, type, handler) {
isFn(type) ?
window.removeEventListener(el, type) :
el.removeEventListener(type, handler)
}
/**
@@ -81,10 +83,10 @@ export function off (el, type, handler) {
* toggleClass(el, 'active') => el.classList.toggle('active')
* toggleClass(el, 'add', 'active') => el.classList.add('active')
*/
export function toggleClass (el, type, val) {
export function toggleClass(el, type, val) {
el && el.classList[val ? type : 'toggle'](val || type)
}
export function style (content) {
export function style(content) {
appendTo(head, create('style', content))
}
+1 -1
View File
@@ -13,7 +13,7 @@ export const supportsPushState =
window.history &&
window.history.pushState &&
window.history.replaceState &&
// pushState isnt reliable on iOS until 5.
// PushState isnt reliable on iOS until 5.
!navigator.userAgent.match(
/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/
)
+10 -6
View File
@@ -1,7 +1,7 @@
import * as dom from '../dom'
import { get } from '../../fetch/ajax'
import {get} from '../../fetch/ajax'
function replaceVar (block, color) {
function replaceVar(block, color) {
block.innerHTML = block.innerHTML.replace(
/var\(\s*--theme-color.*?\)/g,
color
@@ -10,16 +10,20 @@ function replaceVar (block, color) {
export default function (color) {
// Variable support
if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) { return }
if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) {
return
}
const styleBlocks = dom.findAll('style:not(.inserted),link')
;[].forEach.call(styleBlocks, block => {
const styleBlocks = dom.findAll('style:not(.inserted),link');
[].forEach.call(styleBlocks, block => {
if (block.nodeName === 'STYLE') {
replaceVar(block, color)
} else if (block.nodeName === 'LINK') {
const href = block.getAttribute('href')
if (!/\.css$/.test(href)) return
if (!/\.css$/.test(href)) {
return
}
get(href).then(res => {
const style = dom.create('style', res)
+2 -2
View File
@@ -3,7 +3,7 @@ if (fixedPath !== location.href) {
location.href = fixedPath
}
function install (hook, vm) {
function install(hook, vm) {
const dom = Docsify.dom
const disqus = vm.config.disqus
if (!disqus) {
@@ -15,7 +15,7 @@ function install (hook, vm) {
script.async = true
script.src = `https://${disqus}.disqus.com/embed.js`
script.setAttribute('data-timestamp', +new Date())
script.setAttribute('data-timestamp', Number(new Date()))
dom.appendTo(dom.body, script)
})
+4 -4
View File
@@ -887,12 +887,12 @@ const AllGithubEmoji = [
'zzz'
]
// emoji from All-Github-Emoji-Icons
// 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://assets-cdn.github.com/images/icons/emoji/' +
return AllGithubEmoji.indexOf($1) === -1 ?
match :
'<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' +
$1 +
'.png" alt="' +
$1 +
+1 -1
View File
@@ -1,4 +1,4 @@
function handleExternalScript () {
function handleExternalScript() {
const container = Docsify.dom.getNode('#main')
const scripts = Docsify.dom.findAll(container, 'script')
+1 -1
View File
@@ -2,7 +2,7 @@ import parser from './parser'
const install = function (hook, vm) {
hook.beforeEach(content => {
const { attributes, body } = parser(content)
const {attributes, body} = parser(content)
Docsify.util.merge(vm.config, attributes.config)
+4 -4
View File
@@ -1,23 +1,23 @@
// From https://github.com/egoist/vue-ga/blob/master/src/index.js
function appendScript () {
function appendScript() {
const script = document.createElement('script')
script.async = true
script.src = 'https://www.google-analytics.com/analytics.js'
document.body.appendChild(script)
}
function init (id) {
function init(id) {
appendScript()
window.ga =
window.ga ||
function () {
;(window.ga.q = window.ga.q || []).push(arguments)
(window.ga.q = window.ga.q || []).push(arguments)
}
window.ga.l = Number(new Date())
window.ga('create', id, 'auto')
}
function collect () {
function collect() {
if (!window.ga) {
init($docsify.ga)
}
+1 -1
View File
@@ -1,4 +1,4 @@
function install (hook, vm) {
function install(hook) {
const dom = Docsify.dom
hook.mounted(_ => {
+13 -11
View File
@@ -1,8 +1,8 @@
import { search } from './search'
import {search} from './search'
let NO_DATA_TEXT = ''
function style () {
function style() {
const code = `
.sidebar {
padding-top: 0;
@@ -91,7 +91,7 @@ function style () {
Docsify.dom.style(code)
}
function tpl (opts, defaultValue = '') {
function tpl(opts, defaultValue = '') {
const html =
`<div class="input-wrap">
<input type="search" value="${defaultValue}" />
@@ -112,7 +112,7 @@ function tpl (opts, defaultValue = '') {
Docsify.dom.before(aside, el)
}
function doSearch (value) {
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')
@@ -140,7 +140,7 @@ function doSearch (value) {
$panel.innerHTML = html || `<p class="empty">${NO_DATA_TEXT}</p>`
}
function bindEvents () {
function bindEvents() {
const $search = Docsify.dom.find('div.search')
const $input = Docsify.dom.find($search, 'input')
const $inputWrap = Docsify.dom.find($search, '.input-wrap')
@@ -157,7 +157,7 @@ function bindEvents () {
timeId = setTimeout(_ => doSearch(e.target.value.trim()), 100)
})
Docsify.dom.on($inputWrap, 'click', e => {
// click input outside
// Click input outside
if (e.target.tagName !== 'INPUT') {
$input.value = ''
doSearch()
@@ -165,10 +165,12 @@ function bindEvents () {
})
}
function updatePlaceholder (text, path) {
function updatePlaceholder(text, path) {
const $input = Docsify.dom.getNode('.search input[type="search"]')
if (!$input) return
if (!$input) {
return
}
if (typeof text === 'string') {
$input.placeholder = text
} else {
@@ -177,7 +179,7 @@ function updatePlaceholder (text, path) {
}
}
function updateNoData (text, path) {
function updateNoData(text, path) {
if (typeof text === 'string') {
NO_DATA_TEXT = text
} else {
@@ -186,7 +188,7 @@ function updateNoData (text, path) {
}
}
export function init (opts, vm) {
export function init(opts, vm) {
const keywords = vm.router.parse().query.s
style()
@@ -195,7 +197,7 @@ export function init (opts, vm) {
keywords && setTimeout(_ => doSearch(keywords), 500)
}
export function update (opts, vm) {
export function update(opts, vm) {
updatePlaceholder(opts.placeholder, vm.route.path)
updateNoData(opts.noData, vm.route.path)
}
+3 -3
View File
@@ -1,5 +1,5 @@
import { init as initComponet, update as updateComponent } from './component'
import { init as initSearch } from './search'
import {init as initComponet, update as updateComponent} from './component'
import {init as initSearch} from './search'
const CONFIG = {
placeholder: 'Type to search',
@@ -10,7 +10,7 @@ const CONFIG = {
}
const install = function (hook, vm) {
const { util } = Docsify
const {util} = Docsify
const opts = vm.config.search || CONFIG
if (Array.isArray(opts)) {
+29 -23
View File
@@ -1,23 +1,23 @@
let INDEXS = {}
let helper
function escapeHtml (string) {
function escapeHtml(string) {
const entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'\'': '&#39;',
'/': '&#x2F;'
}
return String(string).replace(/[&<>"'\/]/g, s => entityMap[s])
return String(string).replace(/[&<>"'/]/g, s => entityMap[s])
}
function getAllPaths (router) {
function getAllPaths(router) {
const paths = []
helper.dom.findAll('a:not([data-nosearch])').map(node => {
helper.dom.findAll('a:not([data-nosearch])').forEach(node => {
const href = node.href
const originHref = node.getAttribute('href')
const path = router.parse(href).path
@@ -34,12 +34,12 @@ function getAllPaths (router) {
return paths
}
function saveData (maxAge) {
function saveData(maxAge) {
localStorage.setItem('docsify.search.expires', Date.now() + maxAge)
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS))
}
export function genIndex (path, content = '', router, depth) {
export function genIndex(path, content = '', router, depth) {
const tokens = window.marked.lexer(content)
const slugify = window.Docsify.slugify
const index = {}
@@ -47,18 +47,18 @@ export function genIndex (path, content = '', router, depth) {
tokens.forEach(token => {
if (token.type === 'heading' && token.depth <= depth) {
slug = router.toURL(path, { id: slugify(token.text) })
index[slug] = { slug, title: token.text, body: '' }
slug = router.toURL(path, {id: slugify(token.text)})
index[slug] = {slug, title: token.text, body: ''}
} else {
if (!slug) return
if (!slug) {
return
}
if (!index[slug]) {
index[slug] = { slug, title: '', body: '' }
index[slug] = {slug, title: '', body: ''}
} else if (index[slug].body) {
index[slug].body += '\n' + (token.text || '')
} else {
if (index[slug].body) {
index[slug].body += '\n' + (token.text || '')
} else {
index[slug].body = token.text
}
index[slug].body = token.text
}
}
})
@@ -70,7 +70,7 @@ export function genIndex (path, content = '', router, depth) {
* @param {String} query
* @returns {Array}
*/
export function search (query) {
export function search(query) {
const matchingResults = []
let data = []
Object.keys(INDEXS).forEach(key => {
@@ -78,7 +78,7 @@ export function search (query) {
})
query = query.trim()
let keywords = query.split(/[\s\-\\\/]+/)
let keywords = query.split(/[\s\-\\/]+/)
if (keywords.length !== 1) {
keywords = [].concat(query, keywords)
}
@@ -92,7 +92,7 @@ export function search (query) {
const postUrl = post.slug || ''
if (postTitle && postContent) {
keywords.forEach((keyword, i) => {
keywords.forEach(keyword => {
// From https://github.com/sindresorhus/escape-string-regexp
const regEx = new RegExp(
keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
@@ -108,7 +108,9 @@ export function search (query) {
isMatch = false
} else {
isMatch = true
if (indexContent < 0) indexContent = 0
if (indexContent < 0) {
indexContent = 0
}
let start = 0
let end = 0
@@ -116,7 +118,9 @@ export function search (query) {
start = indexContent < 11 ? 0 : indexContent - 10
end = start === 0 ? 70 : indexContent + keyword.length + 60
if (end > postContent.length) end = postContent.length
if (end > postContent.length) {
end = postContent.length
}
const matchContent =
'...' +
@@ -144,7 +148,7 @@ export function search (query) {
return matchingResults
}
export function init (config, vm) {
export function init(config, vm) {
helper = Docsify
const isAuto = config.paths === 'auto'
@@ -163,7 +167,9 @@ export function init (config, vm) {
let count = 0
paths.forEach(path => {
if (INDEXS[path]) return count++
if (INDEXS[path]) {
return count++
}
helper
.get(vm.router.getFile(path), false, vm.config.requestHeaders)
+1 -1
View File
@@ -1,6 +1,6 @@
import mediumZoom from 'medium-zoom'
function install (hook) {
function install(hook) {
let zoom
hook.doneEach(_ => {
-112
View File
@@ -1,112 +0,0 @@
section.cover {
align-items: center;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
display: none;
&.show {
display: flex;
}
&.has-mask .mask {
background-color: $color-bg;
opacity: 0.8;
position: absolute;
top: 0;
size: 100%;
}
.cover-main {
flex: 1;
margin: -20px 16px 0;
text-align: center;
z-index: 1;
}
a {
color: inherit;
text-decoration: none;
&:hover {
text-decoration: none;
}
}
p {
line-height: 1.5rem;
margin: 1em 0;
}
h1 {
color: inherit;
font-size: 2.5rem;
font-weight: 300;
margin: 0.625rem 0 2.5rem;
position: relative;
text-align: center;
a {
display: block;
}
small {
bottom: -0.4375rem;
font-size: 1rem;
position: absolute;
}
}
blockquote {
font-size: 1.5rem;
text-align: center;
}
ul {
line-height: 1.8;
list-style-type: none;
margin: 1em auto;
max-width: 500px;
padding: 0;
}
.cover-main > p:last-child a {
border-color: var(--theme-color, $color-primary);
border-radius: 2rem;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: var(--theme-color, $color-primary);
display: inline-block;
font-size: 1.05rem;
letter-spacing: 0.1rem;
margin: 0.5rem 1rem;
padding: 0.75em 2rem;
text-decoration: none;
transition: all 0.15s ease;
&:last-child {
background-color: var(--theme-color, $color-primary);
color: #fff;
&:hover {
color: inherit;
opacity: 0.8;
}
}
&:hover {
color: inherit;
}
}
blockquote > p > a {
border-bottom: 2px solid var(--theme-color, $color-primary);
transition: color 0.3s;
&:hover {
color: var(--theme-color, $color-primary);
}
}
}
+95
View File
@@ -0,0 +1,95 @@
section.cover
align-items center
background-position center center
background-repeat no-repeat
background-size cover
height 100vh
display none
&.show
display flex
&.has-mask .mask
background-color $color-bg
opacity 0.8
position absolute
top 0
height 100%
width 100%
.cover-main
flex 1
margin -20px 16px 0
text-align center
z-index 1
a
color inherit
text-decoration none
&:hover
text-decoration none
p
line-height 1.5rem
margin 1em 0
h1
color inherit
font-size 2.5rem
font-weight 300
margin 0.625rem 0 2.5rem
position relative
text-align center
a
display block
small
bottom -0.4375rem
font-size 1rem
position absolute
blockquote
font-size 1.5rem
text-align center
ul
line-height 1.8
list-style-type none
margin 1em auto
max-width 500px
padding 0
.cover-main > p:last-child a
border-color var(--theme-color, $color-primary)
border-radius 2rem
border-style solid
border-width 1px
box-sizing border-box
color var(--theme-color, $color-primary)
display inline-block
font-size 1.05rem
letter-spacing 0.1rem
margin 0.5rem 1rem
padding 0.75em 2rem
text-decoration none
transition all 0.15s ease
&:last-child
background-color var(--theme-color, $color-primary)
color #fff
&:hover
color inherit
opacity 0.8
&:hover
color inherit
blockquote > p > a
border-bottom 2px solid var(--theme-color, $color-primary)
transition color 0.3s
&:hover
color var(--theme-color, $color-primary)
-571
View File
@@ -1,571 +0,0 @@
* {
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
box-sizing: border-box;
}
body:not(.ready) {
overflow: hidden;
[data-cloak],
.app-nav,
> nav {
display: none;
}
}
div#app {
font-size: 30px;
font-weight: lighter;
margin: 40vh auto;
text-align: center;
&:empty::before {
content: 'Loading...';
}
}
.emoji {
height: 1.2rem;
vertical-align: middle;
}
.progress {
background-color: var(--theme-color, $color-primary);
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
.search a:hover {
color: var(--theme-color, $color-primary);
}
.search .search-keyword {
color: var(--theme-color, $color-primary);
font-style: normal;
font-weight: bold;
}
html,
body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: $color-text;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
a[disabled] {
cursor: not-allowed;
opacity: 0.6;
}
kbd {
border: solid 1px #ccc;
border-radius: 3px;
display: inline-block;
font-size: 12px !important;
line-height: 12px;
margin-bottom: 3px;
padding: 3px 5px;
vertical-align: middle;
}
.task-list-item {
list-style-type: none;
}
li input[type='checkbox'] {
margin: 0 0.2em 0.25em -1.6em;
vertical-align: middle;
}
/* navbar */
.app-nav {
margin: 25px 60px 0 0;
position: absolute;
right: 0;
text-align: right;
z-index: 10;
&.no-badge {
margin-right: 25px;
}
p {
margin: 0;
}
> a {
margin: 0 1rem;
padding: 5px 0;
}
ul,
li {
display: inline-block;
list-style: none;
margin: 0;
}
a {
color: inherit;
font-size: 16px;
text-decoration: none;
transition: color 0.3s;
&:hover {
color: var(--theme-color, $color-primary);
}
&.active {
border-bottom: 2px solid var(--theme-color, $color-primary);
color: var(--theme-color, $color-primary);
}
}
/* navbar dropdown */
li {
display: inline-block;
margin: 0 1rem;
padding: 5px 0;
position: relative;
ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 4px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: auto;
padding: 10px 0;
position: absolute;
right: -15px;
text-align: left;
top: 100%;
white-space: nowrap;
li {
display: block;
font-size: 14px;
line-height: 1rem;
margin: 0;
margin: 8px 14px;
white-space: nowrap;
}
a {
display: block;
font-size: inherit;
margin: 0;
padding: 0;
&.active {
border-bottom: 0;
}
}
}
&:hover ul {
display: block;
}
}
}
/* github corner */
.github-corner {
border-bottom: 0;
position: fixed;
right: 0;
text-decoration: none;
top: 0;
z-index: 1;
&:hover .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
svg {
color: $color-bg;
fill: var(--theme-color, $color-primary);
height: 80px;
width: 80px;
}
}
/* main */
main {
display: block;
position: relative;
size: 100vw 100%;
z-index: 0;
}
main.hidden {
display: none;
}
.anchor {
display: inline-block;
text-decoration: none;
transition: all 0.3s;
span {
color: $color-text;
}
&:hover {
text-decoration: underline;
}
}
/* sidebar */
.sidebar {
border-right: 1px solid rgba(0, 0, 0, 0.07);
overflow-y: auto;
padding: 40px 0 0;
position: absolute 0 * 0 0;
transition: transform 250ms ease-out;
width: $sidebar-width;
z-index: 20;
> h1 {
margin: 0 auto 1rem;
font-size: 1.5rem;
font-weight: 300;
text-align: center;
a {
color: inherit;
text-decoration: none;
}
.app-nav {
display: block;
position: static;
}
}
.sidebar-nav {
line-height: 2em;
padding-bottom: 40px;
}
li.collapse {
.app-sub-sidebar {
display: none;
}
}
ul {
margin: 0;
padding: 0;
}
li > p {
font-weight: 700;
margin: 0;
}
ul,
ul li {
list-style: none;
}
ul li a {
border-bottom: none;
display: block;
}
ul li ul {
padding-left: 20px;
}
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px;
}
&:hover::-webkit-scrollbar-thumb {
background: rgba(136, 136, 136, 0.4);
}
&:hover::-webkit-scrollbar-track {
background: rgba(136, 136, 136, 0.1);
}
}
/* sidebar toggle */
.sidebar-toggle {
background-color: transparent;
background-color: rgba($color-bg, 0.8);
border: 0;
outline: none;
outline: none;
padding: 10px;
position: absolute * * 0 0;
text-align: center;
transition: opacity 0.3s;
width: 30px;
width: calc($sidebar-width - 16px);
z-index: 30;
.sidebar-toggle-button:hover {
opacity: 0.4;
}
span {
background-color: var(--theme-color, $color-primary);
display: block;
margin-bottom: 4px;
size: 16px 2px;
}
}
body.sticky {
.sidebar,
.sidebar-toggle {
position: fixed;
}
}
/* main content */
.content {
padding-top: 60px;
position: absolute 0 0 0 $sidebar-width;
transition: left 250ms ease;
}
/* markdown content found on pages */
.markdown-section {
margin: 0 auto;
max-width: 800px;
padding: 30px 15px 40px 15px;
position: relative;
> * {
box-sizing: border-box;
font-size: inherit;
}
> :first-child {
margin-top: 0 !important;
}
}
.markdown-section hr {
border: none;
border-bottom: 1px solid #eee;
margin: 2em 0;
}
.markdown-section iframe {
border: 1px solid #eee;
}
.markdown-section table {
border-collapse: collapse;
border-spacing: 0;
display: block;
margin-bottom: 1rem;
overflow: auto;
width: 100%;
}
.markdown-section th {
border: 1px solid #ddd;
font-weight: bold;
padding: 6px 13px;
}
.markdown-section td {
border: 1px solid #ddd;
padding: 6px 13px;
}
.markdown-section tr {
border-top: 1px solid #ccc;
&:nth-child(2n) {
background-color: #f8f8f8;
}
}
.markdown-section p.tip {
background-color: #f8f8f8;
border-bottom-right-radius: 2px;
border-left: 4px solid #f66;
border-top-right-radius: 2px;
margin: 2em 0;
padding: 12px 24px 12px 30px;
position: relative;
&:before {
background-color: #f66;
border-radius: 100%;
color: $color-bg;
content: '!';
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
font-weight: bold;
left: -12px;
line-height: 20px;
position: absolute;
size: 20px;
text-align: center;
top: 14px;
}
code {
background-color: #efefef;
}
em {
color: $color-text;
}
}
.markdown-section p.warn {
background: rgba($color-primary, 0.1);
border-radius: 2px;
padding: 1rem;
}
body.close {
.sidebar {
transform: translateX(-$sidebar-width);
}
.sidebar-toggle {
width: auto;
}
.content {
left: 0;
}
}
@media print {
.github-corner,
.sidebar-toggle,
.sidebar,
.app-nav {
display: none;
}
}
@media screen and (max-width: 768px) {
.github-corner,
.sidebar-toggle,
.sidebar {
position: fixed;
}
.app-nav {
margin-top: 16px;
}
.app-nav li ul {
top: 30px;
}
main {
height: auto;
overflow-x: hidden;
}
.sidebar {
left: -$sidebar-width;
transition: transform 250ms ease-out;
}
.content {
left: 0;
max-width: 100vw;
position: static;
padding-top: 20px;
transition: transform 250ms ease;
}
.app-nav,
.github-corner {
transition: transform 250ms ease-out;
}
.sidebar-toggle {
background-color: transparent;
width: auto;
padding: 30px 30px 10px 10px;
}
body.close {
.sidebar {
transform: translateX($sidebar-width);
}
.sidebar-toggle {
background-color: rgba($color-bg, 0.8);
transition: 1s background-color;
width: calc($sidebar-width - 16px);
padding: 10px;
}
.content {
transform: translateX($sidebar-width);
}
.app-nav,
.github-corner {
display: none;
}
}
.github-corner {
&:hover .octo-arm {
animation: none;
}
.octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
}
@keyframes octocat-wave {
0%,
100% {
transform: rotate(0);
}
20%,
60% {
transform: rotate(-25deg);
}
40%,
80% {
transform: rotate(10deg);
}
}
+467
View File
@@ -0,0 +1,467 @@
*
-webkit-font-smoothing antialiased
-webkit-overflow-scrolling touch
-webkit-tap-highlight-color rgba(0, 0, 0, 0)
-webkit-text-size-adjust none
-webkit-touch-callout none
box-sizing border-box
body:not(.ready)
overflow hidden
[data-cloak], .app-nav, > nav
display none
div#app
font-size 30px
font-weight lighter
margin 40vh auto
text-align center
&:empty::before
content 'Loading...'
.emoji
height 1.2rem
vertical-align middle
.progress
background-color var(--theme-color, $color-primary)
height 2px
left 0px
position fixed
right 0px
top 0px
transition width 0.2s, opacity 0.4s
width 0%
z-index 999999
.search a:hover
color var(--theme-color, $color-primary)
.search .search-keyword
color var(--theme-color, $color-primary)
font-style normal
font-weight bold
html, body
height 100%
body
-moz-osx-font-smoothing grayscale
-webkit-font-smoothing antialiased
color $color-text
font-family 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif
font-size 15px
letter-spacing 0
margin 0
overflow-x hidden
img
max-width 100%
a[disabled]
cursor not-allowed
opacity 0.6
kbd
border solid 1px #ccc
border-radius 3px
display inline-block
font-size 12px !important
line-height 12px
margin-bottom 3px
padding 3px 5px
vertical-align middle
.task-list-item
list-style-type none
li input[type='checkbox']
margin 0 0.2em 0.25em -1.6em
vertical-align middle
/* navbar */
.app-nav
margin 25px 60px 0 0
position absolute
right 0
text-align right
z-index 10
&.no-badge
margin-right 25px
p
margin 0
> a
margin 0 1rem
padding 5px 0
ul, li
display inline-block
list-style none
margin 0
a
color inherit
font-size 16px
text-decoration none
transition color 0.3s
&:hover
color var(--theme-color, $color-primary)
&.active
border-bottom 2px solid var(--theme-color, $color-primary)
color var(--theme-color, $color-primary)
/* navbar dropdown */
li
display inline-block
margin 0 1rem
padding 5px 0
position relative
ul
background-color #fff
border 1px solid #ddd
border-bottom-color #ccc
border-radius 4px
box-sizing border-box
display none
max-height calc(100vh - 61px)
overflow-y auto
padding 10px 0
position absolute
right -15px
text-align left
top 100%
white-space nowrap
li
display block
font-size 14px
line-height 1rem
margin 0
margin 8px 14px
white-space nowrap
a
display block
font-size inherit
margin 0
padding 0
&.active
border-bottom 0
&:hover ul
display block
/* github corner */
.github-corner
border-bottom 0
position fixed
right 0
text-decoration none
top 0
z-index 1
&:hover .octo-arm
animation octocat-wave 560ms ease-in-out
svg
color $color-bg
fill var(--theme-color, $color-primary)
height 80px
width 80px
/* main */
main
display block
position relative
width 100vw
height 100%
z-index 0
main.hidden
display none
.anchor
display inline-block
text-decoration none
transition all 0.3s
span
color $color-text
&:hover
text-decoration underline
/* sidebar */
.sidebar
border-right 1px solid rgba(0, 0, 0, 0.07)
overflow-y auto
padding 40px 0 0
position absolute
top 0
bottom 0
left 0
transition transform 250ms ease-out
width $sidebar-width
z-index 20
> h1
margin 0 auto 1rem
font-size 1.5rem
font-weight 300
text-align center
a
color inherit
text-decoration none
.app-nav
display block
position static
.sidebar-nav
line-height 2em
padding-bottom 40px
li.collapse
.app-sub-sidebar
display none
ul
margin 0
padding 0
li > p
font-weight 700
margin 0
ul, ul li
list-style none
ul li a
border-bottom none
display block
ul li ul
padding-left 20px
&::-webkit-scrollbar
width 4px
&::-webkit-scrollbar-thumb
background transparent
border-radius 4px
&:hover::-webkit-scrollbar-thumb
background rgba(136, 136, 136, 0.4)
&:hover::-webkit-scrollbar-track
background rgba(136, 136, 136, 0.1)
/* sidebar toggle */
.sidebar-toggle
background-color transparent
background-color rgba($color-bg, 0.8)
border 0
outline none
padding 10px
position absolute
bottom 0
left 0
text-align center
transition opacity 0.3s
width $sidebar-width - 16px
z-index 30
.sidebar-toggle-button:hover
opacity 0.4
span
background-color var(--theme-color, $color-primary)
display block
margin-bottom 4px
width 16px
height 2px
body.sticky
.sidebar, .sidebar-toggle
position fixed
/* main content */
.content
padding-top 60px
position absolute
top 0
right 0
bottom 0
left $sidebar-width
transition left 250ms ease
/* markdown content found on pages */
.markdown-section
margin 0 auto
max-width 800px
padding 30px 15px 40px 15px
position relative
> *
box-sizing border-box
font-size inherit
> :first-child
margin-top 0 !important
.markdown-section hr
border none
border-bottom 1px solid #eee
margin 2em 0
.markdown-section iframe
border 1px solid #eee
.markdown-section table
border-collapse collapse
border-spacing 0
display block
margin-bottom 1rem
overflow auto
width 100%
.markdown-section th
border 1px solid #ddd
font-weight bold
padding 6px 13px
.markdown-section td
border 1px solid #ddd
padding 6px 13px
.markdown-section tr
border-top 1px solid #ccc
&:nth-child(2n)
background-color #f8f8f8
.markdown-section p.tip
background-color #f8f8f8
border-bottom-right-radius 2px
border-left 4px solid #f66
border-top-right-radius 2px
margin 2em 0
padding 12px 24px 12px 30px
position relative
&:before
background-color #f66
border-radius 100%
color $color-bg
content '!'
font-family 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif
font-size 14px
font-weight bold
left -12px
line-height 20px
position absolute
height 20px
width 20px
text-align center
top 14px
code
background-color #efefef
em
color $color-text
.markdown-section p.warn
background rgba($color-primary, 0.1)
border-radius 2px
padding 1rem
body.close
.sidebar
transform translateX(- $sidebar-width)
.sidebar-toggle
width auto
.content
left 0
@media print
.github-corner, .sidebar-toggle, .sidebar, .app-nav
display none
@media screen and (max-width: 768px)
.github-corner, .sidebar-toggle, .sidebar
position fixed
.app-nav
margin-top 16px
.app-nav li ul
top 30px
main
height auto
overflow-x hidden
.sidebar
left - $sidebar-width
transition transform 250ms ease-out
.content
left 0
max-width 100vw
position static
padding-top 20px
transition transform 250ms ease
.app-nav, .github-corner
transition transform 250ms ease-out
.sidebar-toggle
background-color transparent
width auto
padding 30px 30px 10px 10px
body.close
.sidebar
transform translateX($sidebar-width)
.sidebar-toggle
background-color rgba($color-bg, 0.8)
transition 1s background-color
width $sidebar-width - 16px
padding 10px
.content
transform translateX($sidebar-width)
.app-nav, .github-corner
display none
.github-corner
&:hover .octo-arm
animation none
.octo-arm
animation octocat-wave 560ms ease-in-out
@keyframes octocat-wave
0%, 100%
transform rotate(0)
20%, 60%
transform rotate(-25deg)
40%, 80%
transform rotate(10deg)
-241
View File
@@ -1,241 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
$color-primary: #0074d9;
$color-bg: #fff;
$color-text: #34495e;
$sidebar-width: 16rem;
@import 'basic/layout';
@import 'basic/coverpage';
/* sidebar */
.sidebar {
color: #364149;
background-color: $color-bg;
a {
color: #666;
text-decoration: none;
}
li {
list-style: none;
margin: 0;
padding: 0.2em 0 0.2em 1rem;
}
ul li ul {
padding: 0;
}
li.active {
a {
color: #333;
}
background-color: #eee;
}
}
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #333;
font-weight: 400;
}
.markdown-section a {
color: var(--theme-color, $color-primary);
font-weight: 400;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
margin: 0 0 1em 0;
word-spacing: 0.05rem;
}
.markdown-section h1 {
font-size: 2rem;
font-weight: 500;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.8rem;
font-weight: 400;
margin: 0 0 1rem 0;
padding: 1rem 0 0 0;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 52px 0 1.2rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
margin: 1.2em 0;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section li {
line-height: 1.5;
margin: 0;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, $color-primary);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code {
background-color: #f9f9f9;
border-radius: 3px;
font-family: Inconsolata;
padding: 0.2em 0.4rem;
white-space: nowrap;
}
.markdown-section pre {
background-color: #f9f9f9;
border-left: 2px solid #eee;
font-family: Inconsolata;
font-size: 16px;
margin: 0 0 1em 0;
padding: 8px;
padding: 0 10px 12px 0;
overflow: auto;
word-wrap: normal;
}
/* code highlight */
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog {
color: #93a1a1; /* base1 */
}
.token.punctuation {
color: #586e75; /* base01 */
}
.namespace {
opacity: 0.7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #268bd2; /* blue */
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.url,
.token.inserted {
color: #2aa198; /* cyan */
}
.token.entity {
color: #657b83; /* base00 */
background: #eee8d5; /* base2 */
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #a11; /* green */
}
.token.function {
color: #b58900; /* yellow */
}
.token.regex,
.token.important,
.token.variable {
color: #cb4b16; /* orange */
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.markdown-section pre > code {
background-color: #f8f8f8;
border-radius: 2px;
display: block;
font-family: Inconsolata;
line-height: 1.1rem;
max-width: inherit;
overflow: inherit;
padding: 20px 0.8em 20px;
position: relative;
white-space: inherit;
}
.markdown-section code::after,
.markdown-section code::before {
letter-spacing: 0.05rem;
}
code .token {
-webkit-font-smoothing: initial;
-moz-osx-font-smoothing: initial;
min-height: 1.5rem;
}
+172
View File
@@ -0,0 +1,172 @@
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold')
$color-primary = #0074d9
$color-bg = #fff
$color-text = #34495e
$sidebar-width = 16rem
@import 'basic/_layout'
@import 'basic/_coverpage'
/* sidebar */
.sidebar
color #364149
background-color $color-bg
a
color #666
text-decoration none
li
list-style none
margin 0
padding 0.2em 0 0.2em 1rem
ul li ul
padding 0
li.active
a
color #333
background-color #eee
.markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4, .markdown-section strong
color #333
font-weight 400
.markdown-section a
color var(--theme-color, $color-primary)
font-weight 400
.markdown-section p, .markdown-section ul, .markdown-section ol
line-height 1.6rem
margin 0 0 1em 0
word-spacing 0.05rem
.markdown-section h1
font-size 2rem
font-weight 500
margin 0 0 1rem
.markdown-section h2
font-size 1.8rem
font-weight 400
margin 0 0 1rem 0
padding 1rem 0 0 0
.markdown-section h3
font-size 1.5rem
margin 52px 0 1.2rem
.markdown-section h4
font-size 1.25rem
.markdown-section h5
font-size 1rem
.markdown-section h6
color #777
font-size 1rem
.markdown-section figure, .markdown-section p, .markdown-section ul, .markdown-section ol
margin 1.2em 0
.markdown-section ul, .markdown-section ol
padding-left 1.5rem
.markdown-section li
line-height 1.5
margin 0
.markdown-section blockquote
border-left 4px solid var(--theme-color, $color-primary)
color #858585
margin 2em 0
padding-left 20px
.markdown-section blockquote p
font-weight 600
margin-left 0
.markdown-section iframe
margin 1em 0
.markdown-section em
color #7f8c8d
.markdown-section code
background-color #f9f9f9
border-radius 3px
font-family Inconsolata
padding 0.2em 0.4rem
white-space nowrap
.markdown-section pre
background-color #f9f9f9
border-left 2px solid #eee
font-family Inconsolata
font-size 16px
margin 0 0 1em 0
padding 8px
padding 0 10px 12px 0
overflow auto
word-wrap normal
/* code highlight */
.token.cdata, .token.comment, .token.doctype, .token.prolog
color #93a1a1 /* base1 */
.token.punctuation
color #586e75 /* base01 */
.namespace
opacity 0.7
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted
color #268bd2 /* blue */
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.url, .token.inserted
color #2aa198 /* cyan */
.token.entity
color #657b83 /* base00 */
background #eee8d5 /* base2 */
.token.atrule, .token.attr-value, .token.keyword
color #a11 /* green */
.token.function
color #b58900 /* yellow */
.token.regex, .token.important, .token.variable
color #cb4b16 /* orange */
.token.important, .token.bold
font-weight bold
.token.italic
font-style italic
.token.entity
cursor help
.markdown-section pre > code
background-color #f8f8f8
border-radius 2px
display block
font-family Inconsolata
line-height 1.1rem
max-width inherit
overflow inherit
padding 20px 0.8em 20px
position relative
white-space inherit
.markdown-section code::after, .markdown-section code::before
letter-spacing 0.05rem
code .token
-webkit-font-smoothing initial
-moz-osx-font-smoothing initial
min-height 1.5rem
-300
View File
@@ -1,300 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
$color-primary: #ea6f5a;
$color-bg: #3f3f3f;
$color-text: #c8c8c8;
$sidebar-width: 300px;
@import 'basic/layout';
@import 'basic/coverpage';
body {
background-color: $color-bg;
}
/* sidebar */
.sidebar {
background-color: $color-bg;
color: #c8c8c8;
li {
margin: 6px 15px;
}
ul li a {
color: #c8c8c8;
font-size: 14px;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
text-decoration: underline;
}
}
ul li ul {
padding: 0;
}
ul li.active > a {
color: var(--theme-color, $color-primary);
font-weight: 600;
}
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #657b83;
font-weight: 600;
}
.markdown-section a {
color: var(--theme-color, $color-primary);
font-weight: 600;
}
.markdown-section h1 {
font-size: 2rem;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.75rem;
margin: 45px 0 0.8rem;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 0.6rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, $color-primary);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code {
background-color: #282828;
border-radius: 2px;
color: #657b83;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap;
}
.markdown-section pre {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #282828;
font-family: 'Roboto Mono', Monaco, courier, monospace;
line-height: 1.5rem;
margin: 1.2em 0;
overflow: auto;
padding: 0 1.4rem;
position: relative;
word-wrap: normal;
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8e908c;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.number {
color: #c76b29;
}
.token.punctuation {
color: #525252;
}
.token.property {
color: #c08b30;
}
.token.tag {
color: #2973b7;
}
.token.string {
color: var(--theme-color, $color-primary);
}
.token.selector {
color: #6679cc;
}
.token.attr-name {
color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
color: var(--theme-color, $color-primary);
}
.token.keyword {
color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
color: #22a2c9;
}
.token.placeholder,
.token.variable {
color: #3d8fd1;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #c94922;
}
.token.entity {
cursor: help;
}
.markdown-section pre > code {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #282828;
border-radius: 2px;
color: #657b83;
display: block;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit;
}
.markdown-section code::after,
.markdown-section code::before {
letter-spacing: 0.05rem;
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem;
}
pre::after {
color: #ccc;
content: attr(data-lang);
font-size: 0.6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
.markdown-section p.tip {
background-color: #282828;
color: #657b83;
}
input[type='search'] {
background: #4f4f4f;
border-color: #4f4f4f;
color: #c8c8c8;
}
+225
View File
@@ -0,0 +1,225 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600')
$color-primary = #ea6f5a
$color-bg = #3f3f3f
$color-text = #c8c8c8
$sidebar-width = 300px
@import 'basic/_layout'
@import 'basic/_coverpage'
body
background-color $color-bg
/* sidebar */
.sidebar
background-color $color-bg
color #c8c8c8
li
margin 6px 15px
ul li a
color #c8c8c8
font-size 14px
overflow hidden
text-decoration none
text-overflow ellipsis
white-space nowrap
&:hover
text-decoration underline
ul li ul
padding 0
ul li.active > a
color var(--theme-color, $color-primary)
font-weight 600
/* markdown content found on pages */
.markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4, .markdown-section strong
color #657b83
font-weight 600
.markdown-section a
color var(--theme-color, $color-primary)
font-weight 600
.markdown-section h1
font-size 2rem
margin 0 0 1rem
.markdown-section h2
font-size 1.75rem
margin 45px 0 0.8rem
.markdown-section h3
font-size 1.5rem
margin 40px 0 0.6rem
.markdown-section h4
font-size 1.25rem
.markdown-section h5
font-size 1rem
.markdown-section h6
color #777
font-size 1rem
.markdown-section figure, .markdown-section p, .markdown-section ul, .markdown-section ol
margin 1.2em 0
.markdown-section p, .markdown-section ul, .markdown-section ol
line-height 1.6rem
word-spacing 0.05rem
.markdown-section ul, .markdown-section ol
padding-left 1.5rem
.markdown-section blockquote
border-left 4px solid var(--theme-color, $color-primary)
color #858585
margin 2em 0
padding-left 20px
.markdown-section blockquote p
font-weight 600
margin-left 0
.markdown-section iframe
margin 1em 0
.markdown-section em
color #7f8c8d
.markdown-section code
background-color #282828
border-radius 2px
color #657b83
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
margin 0 2px
padding 3px 5px
white-space pre-wrap
.markdown-section pre
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #282828
font-family 'Roboto Mono', Monaco, courier, monospace
line-height 1.5rem
margin 1.2em 0
overflow auto
padding 0 1.4rem
position relative
word-wrap normal
/* code highlight */
.token.comment, .token.prolog, .token.doctype, .token.cdata
color #8e908c
.token.namespace
opacity 0.7
.token.boolean, .token.number
color #c76b29
.token.punctuation
color #525252
.token.property
color #c08b30
.token.tag
color #2973b7
.token.string
color var(--theme-color, $color-primary)
.token.selector
color #6679cc
.token.attr-name
color #2973b7
.token.entity, .token.url, .language-css .token.string, .style .token.string
color #22a2c9
.token.attr-value, .token.control, .token.directive, .token.unit
color var(--theme-color, $color-primary)
.token.keyword
color #e96900
.token.statement, .token.regex, .token.atrule
color #22a2c9
.token.placeholder, .token.variable
color #3d8fd1
.token.deleted
text-decoration line-through
.token.inserted
border-bottom 1px dotted #202746
text-decoration none
.token.italic
font-style italic
.token.important, .token.bold
font-weight bold
.token.important
color #c94922
.token.entity
cursor help
.markdown-section pre > code
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #282828
border-radius 2px
color #657b83
display block
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
line-height inherit
margin 0 2px
max-width inherit
overflow inherit
padding 2.2em 5px
white-space inherit
.markdown-section code::after, .markdown-section code::before
letter-spacing 0.05rem
code .token
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
min-height 1.5rem
pre::after
color #ccc
content attr(data-lang)
font-size 0.6rem
font-weight 600
height 15px
line-height 15px
padding 5px 10px 0
position absolute
right 0
text-align right
top 0
.markdown-section p.tip
background-color #282828
color #657b83
input[type='search']
background #4f4f4f
border-color #4f4f4f
color #c8c8c8
-6
View File
@@ -1,6 +0,0 @@
$color-primary: #000;
$color-bg: #fff;
$color-text: #000;
$sidebar-width: 300px;
@import 'basic/layout';
@import 'basic/coverpage';
+7
View File
@@ -0,0 +1,7 @@
$color-primary = #000
$color-bg = #fff
$color-text = #000
$sidebar-width = 300px
@import 'basic/_layout'
@import 'basic/_coverpage'
-299
View File
@@ -1,299 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
$color-primary: #42b983;
$color-bg: #fff;
$color-text: #34495e;
$sidebar-width: 300px;
@import 'basic/layout';
@import 'basic/coverpage';
body {
background-color: $color-bg;
}
/* sidebar */
.sidebar {
background-color: $color-bg;
color: #364149;
li {
margin: 6px 0 6px 15px;
}
ul li a {
color: #505d6b;
font-size: 14px;
font-weight: normal;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
text-decoration: underline;
}
}
ul li ul {
padding: 0;
}
ul li.active > a {
border-right: 2px solid;
color: var(--theme-color, $color-primary);
font-weight: 600;
}
}
.app-sub-sidebar {
li {
&::before {
content: '-';
padding-right: 4px;
float: left;
}
}
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #2c3e50;
font-weight: 600;
}
.markdown-section a {
color: var(--theme-color, $color-primary);
font-weight: 600;
}
.markdown-section h1 {
font-size: 2rem;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.75rem;
margin: 45px 0 0.8rem;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 0.6rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, $color-primary);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code {
background-color: #f8f8f8;
border-radius: 2px;
color: #e96900;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap;
}
.markdown-section pre {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
font-family: 'Roboto Mono', Monaco, courier, monospace;
line-height: 1.5rem;
margin: 1.2em 0;
overflow: auto;
padding: 0 1.4rem;
position: relative;
word-wrap: normal;
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8e908c;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.number {
color: #c76b29;
}
.token.punctuation {
color: #525252;
}
.token.property {
color: #c08b30;
}
.token.tag {
color: #2973b7;
}
.token.string {
color: var(--theme-color, $color-primary);
}
.token.selector {
color: #6679cc;
}
.token.attr-name {
color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
color: var(--theme-color, $color-primary);
}
.token.keyword {
color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
color: #22a2c9;
}
.token.placeholder,
.token.variable {
color: #3d8fd1;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #c94922;
}
.token.entity {
cursor: help;
}
.markdown-section pre > code {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
border-radius: 2px;
color: #525252;
display: block;
font-family: 'Roboto Mono', Monaco, courier, monospace;
font-size: 0.8rem;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit;
}
.markdown-section code::after,
.markdown-section code::before {
letter-spacing: 0.05rem;
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem;
}
pre::after {
color: #ccc;
content: attr(data-lang);
font-size: 0.6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
+225
View File
@@ -0,0 +1,225 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600')
$color-primary = #42b983
$color-bg = #fff
$color-text = #34495e
$sidebar-width = 300px
@import 'basic/_layout'
@import 'basic/_coverpage'
body
background-color $color-bg
/* sidebar */
.sidebar
background-color $color-bg
color #364149
li
margin 6px 0 6px 15px
ul li a
color #505d6b
font-size 14px
font-weight normal
overflow hidden
text-decoration none
text-overflow ellipsis
white-space nowrap
&:hover
text-decoration underline
ul li ul
padding 0
ul li.active > a
border-right 2px solid
color var(--theme-color, $color-primary)
font-weight 600
.app-sub-sidebar
li
&::before
content '-'
padding-right 4px
float left
/* markdown content found on pages */
.markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4, .markdown-section strong
color #2c3e50
font-weight 600
.markdown-section a
color var(--theme-color, $color-primary)
font-weight 600
.markdown-section h1
font-size 2rem
margin 0 0 1rem
.markdown-section h2
font-size 1.75rem
margin 45px 0 0.8rem
.markdown-section h3
font-size 1.5rem
margin 40px 0 0.6rem
.markdown-section h4
font-size 1.25rem
.markdown-section h5
font-size 1rem
.markdown-section h6
color #777
font-size 1rem
.markdown-section figure, .markdown-section p
margin 1.2em 0
.markdown-section p, .markdown-section ul, .markdown-section ol
line-height 1.6rem
word-spacing 0.05rem
.markdown-section ul, .markdown-section ol
padding-left 1.5rem
.markdown-section blockquote
border-left 4px solid var(--theme-color, $color-primary)
color #858585
margin 2em 0
padding-left 20px
.markdown-section blockquote p
font-weight 600
margin-left 0
.markdown-section iframe
margin 1em 0
.markdown-section em
color #7f8c8d
.markdown-section code
background-color #f8f8f8
border-radius 2px
color #e96900
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
margin 0 2px
padding 3px 5px
white-space pre-wrap
.markdown-section pre
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #f8f8f8
font-family 'Roboto Mono', Monaco, courier, monospace
line-height 1.5rem
margin 1.2em 0
overflow auto
padding 0 1.4rem
position relative
word-wrap normal
/* code highlight */
.token.comment, .token.prolog, .token.doctype, .token.cdata
color #8e908c
.token.namespace
opacity 0.7
.token.boolean, .token.number
color #c76b29
.token.punctuation
color #525252
.token.property
color #c08b30
.token.tag
color #2973b7
.token.string
color var(--theme-color, $color-primary)
.token.selector
color #6679cc
.token.attr-name
color #2973b7
.token.entity, .token.url, .language-css .token.string, .style .token.string
color #22a2c9
.token.attr-value, .token.control, .token.directive, .token.unit
color var(--theme-color, $color-primary)
.token.keyword
color #e96900
.token.statement, .token.regex, .token.atrule
color #22a2c9
.token.placeholder, .token.variable
color #3d8fd1
.token.deleted
text-decoration line-through
.token.inserted
border-bottom 1px dotted #202746
text-decoration none
.token.italic
font-style italic
.token.important, .token.bold
font-weight bold
.token.important
color #c94922
.token.entity
cursor help
.markdown-section pre > code
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #f8f8f8
border-radius 2px
color #525252
display block
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
line-height inherit
margin 0 2px
max-width inherit
overflow inherit
padding 2.2em 5px
white-space inherit
.markdown-section code::after, .markdown-section code::before
letter-spacing 0.05rem
code .token
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
min-height 1.5rem
pre::after
color #ccc
content attr(data-lang)
font-size 0.6rem
font-weight 600
height 15px
line-height 15px
padding 5px 10px 0
position absolute
right 0
text-align right
top 0