Compare commits

..

No commits in common. "develop" and "v1.0.3" have entirely different histories.

136 changed files with 4500 additions and 19945 deletions

View file

@ -1,5 +0,0 @@
.git
packages/docsify-server-renderer/build.js
node_modules
build
server.js

View file

@ -1,20 +1,6 @@
{
"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"
},
"extends": ["vue"],
"globals": {
"Docsify": true,
"$docsify": true,
"process": true
"XMLHttpRequest": true
}
}

View file

@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
<!-- Please don't delete this template or we'll close your issue -->
<!-- Please use English language -->
<!-- Before creating an issue please make sure you are using the latest version of Docsify. -->
<!-- Please ask questions on StackOverflow: https://stackoverflow.com/questions/ask?tags=docsify -->
## Bug Report
#### Steps to reproduce
#### What is current behaviour
#### What is the expected behaviour
#### Other relevant information
<!-- (Update "[ ]" to "[x]" to check a box) -->
- [ ] Bug does still occur when all/other plugins are disabled?
- Your OS:
- Node.js version:
- npm/yarn version:
- Browser version:
- Docsify version:
- Docsify plugins:
<!-- Love docsify? Please consider supporting our collective:
👉 https://opencollective.com/docsify/donate -->

View file

@ -1,25 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
<!-- Please don't delete this template or we'll close your issue -->
<!-- Please use English language -->
<!-- Before creating an issue please make sure you are using the latest version of Docsify. -->
<!-- Please ask questions on StackOverflow 👉 https://stackoverflow.com/questions/ask?tags=docsify -->
## Feature request
#### What problem does this feature solve?
#### What does the proposed API look like?
#### How should this be implemented in your opinion?
#### Are you willing to work on this yourself?

View file

@ -1,54 +0,0 @@
<!-- Please use English language -->
<!-- Please don't delete this template -->
<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->
**Summary**
**What kind of change does this PR introduce?** (check at least one)
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Docs
- [ ] Build-related changes
- [ ] Other, please describe:
If changing the UI of default theme, please provide the **before/after** screenshot:
**Does this PR introduce a breaking change?** (check one)
- [ ] Yes
- [ ] No
If yes, please describe the impact and migration path for existing applications:
**The PR fulfills these requirements:**
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
You have tested in the following browsers: (Providing a detailed version will be better.)
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Edge
- [ ] IE
If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature
- [ ] Related documents have been updated
- [ ] Related tests have been updated
To avoid wasting your time, it's best to open a **feature request issue** first and wait for approval before working on it.
**Other information:**
---
* [ ] DO NOT include files inside `lib` directory.

9
.gitignore vendored
View file

@ -1,9 +1,4 @@
*.log
.DS_Store
.idea
node_modules
themes/
lib/
# exceptions
!.gitkeep
yarn.lock
/themes

View file

@ -1,5 +0,0 @@
.eslintignore
.eslintrc
.github/
.gitignore
.travis.yml

View file

@ -1,3 +0,0 @@
{
"prettier.eslintIntegration": true
}

12
404.dev.html Normal file
View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
</head>
<body class="">
<div id="app"></div>
</body>
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-sidebar-toggle data-router></script>
</html>

View file

@ -1,753 +1,83 @@
<a name="4.9.4"></a>
## [4.9.4](https://github.com/docsifyjs/docsify/compare/v4.9.2...v4.9.4) (2019-05-05)
## 1.0.3
### Bug fixes
- Fix cache
## 1.0.2
### Bug fixes
- Fix binding events bug, fixed #24
- Fix regular expression, fixed #23
## 1.0.1
### Bug fixes
- `img` style
<a name="4.9.2"></a>
## [4.9.2](https://github.com/docsifyjs/docsify/compare/v4.9.1...v4.9.2) (2019-04-21)
## 1.0.0
## Features
- Support hash router
### Bug fixes
- Improved scrolling on mobile
### Bug Fixes
## 0.7.0
### Breaking change
- `themes/` was removed, only exists in the npm package.
* re-render gitalk when router changed ([11ea1f8](https://github.com/docsifyjs/docsify/commit/11ea1f8))
### Bug fixes
- Fix style.
- Fix sidebar animation again.
## 0.6.1
### Bug fixes
- In the mobile, it should collapse the sidebar when toggle is clicked.
- Fix the dropdown list style.
- Fix sidebar animation.
## 0.6.0
### Features
- Navbar support dropdown list, #6
- Sidebar with toggle
* allows relative path, fixed [#590](https://github.com/docsifyjs/docsify/issues/590) ([31654f1](https://github.com/docsifyjs/docsify/commit/31654f1))
<a name="4.9.1"></a>
## [4.9.1](https://github.com/docsifyjs/docsify/compare/v4.9.0...v4.9.1) (2019-02-21)
### Bug Fixes
* github assets url ([#774](https://github.com/docsifyjs/docsify/issues/774)) ([140bf10](https://github.com/docsifyjs/docsify/commit/140bf10))
<a name="4.9.0"></a>
# [4.9.0](https://github.com/docsifyjs/docsify/compare/v4.8.6...v4.9.0) (2019-02-19)
### Bug Fixes
* task list rendering (Fix [#749](https://github.com/docsifyjs/docsify/issues/749)) ([#757](https://github.com/docsifyjs/docsify/issues/757)) ([69ef489](https://github.com/docsifyjs/docsify/commit/69ef489))
* upgrade npm-run-all ([049726e](https://github.com/docsifyjs/docsify/commit/049726e))
### Bug fixes
- Fix ineffective option, fixed #10
## 0.5.0
### Features
- Custom sidebars and navbars by markdown file
* **search-plugin:** add namespace option ([#706](https://github.com/docsifyjs/docsify/issues/706)) ([28beff8](https://github.com/docsifyjs/docsify/commit/28beff8))
* Add new theme "dolphin" ([#735](https://github.com/docsifyjs/docsify/issues/735)) ([c3345ba](https://github.com/docsifyjs/docsify/commit/c3345ba))
* Provide code fragments feature ([#748](https://github.com/docsifyjs/docsify/issues/748)) ([1447c8a](https://github.com/docsifyjs/docsify/commit/1447c8a))
## 0.4.2
### Bug fixes
- Correct catch ajax error
## 0.4.1
### Bug fixes
- catch ajax error
<a name="4.8.6"></a>
## [4.8.6](https://github.com/docsifyjs/docsify/compare/v4.8.5...v4.8.6) (2018-11-12)
### Bug Fixes
* IE10 compatibility ([#691](https://github.com/docsifyjs/docsify/issues/691)) ([4db8cd6](https://github.com/docsifyjs/docsify/commit/4db8cd6))
<a name="4.8.5"></a>
## [4.8.5](https://github.com/docsifyjs/docsify/compare/v4.8.4...v4.8.5) (2018-11-02)
### Bug Fixes
* expose version info for Docsify, fixed [#641](https://github.com/docsifyjs/docsify/issues/641) ([aa719e3](https://github.com/docsifyjs/docsify/commit/aa719e3))
<a name="4.8.4"></a>
## [4.8.4](https://github.com/docsifyjs/docsify/compare/v4.8.3...v4.8.4) (2018-11-01)
### Bug Fixes
* **cover:** Compatible with legacy styles, fixed [#677](https://github.com/docsifyjs/docsify/issues/677) ([#678](https://github.com/docsifyjs/docsify/issues/678)) ([1a945d4](https://github.com/docsifyjs/docsify/commit/1a945d4))
<a name="4.8.3"></a>
## [4.8.3](https://github.com/docsifyjs/docsify/compare/v4.8.2...v4.8.3) (2018-11-01)
Fix the last release files has the old version marked...
<a name="4.8.2"></a>
## [4.8.2](https://github.com/docsifyjs/docsify/compare/v4.8.1...v4.8.2) (2018-11-01)
### Bug Fixes
- cover button style, fixed [#670](https://github.com/docsifyjs/docsify/issues/670), fixed [#665](https://github.com/docsifyjs/docsify/issues/665) ([#675](https://github.com/docsifyjs/docsify/issues/675)) ([fcd1087](https://github.com/docsifyjs/docsify/commit/fcd1087))
- update match regex ([#669](https://github.com/docsifyjs/docsify/issues/669)) ([2edf47e](https://github.com/docsifyjs/docsify/commit/2edf47e))
- use copy of cached value ([#668](https://github.com/docsifyjs/docsify/issues/668)) ([5fcf210](https://github.com/docsifyjs/docsify/commit/5fcf210))
- **compiler:** import prism-markup-templating, fixed [#672](https://github.com/docsifyjs/docsify/issues/672) ([#676](https://github.com/docsifyjs/docsify/issues/676)) ([fdd8826](https://github.com/docsifyjs/docsify/commit/fdd8826))
## 0.4.0
### Features
- Custom sidebar
- add heading config id ([#671](https://github.com/docsifyjs/docsify/issues/671)) ([ab19b13](https://github.com/docsifyjs/docsify/commit/ab19b13))
### Bug fixes
- Fix undefined language
<a name="4.8.1"></a>
## [4.8.1](https://github.com/docsifyjs/docsify/compare/v4.8.0...v4.8.1) (2018-10-31)
### Bug Fixes
- ssr package dep, fixed [#605](https://github.com/docsifyjs/docsify/issues/605) ([2bc880d](https://github.com/docsifyjs/docsify/commit/2bc880d))
- **compiler:** extra quotes for codeblock ([4f588e0](https://github.com/docsifyjs/docsify/commit/4f588e0))
- **compiler:** prevent render of html code in paragraph, fixed [#663](https://github.com/docsifyjs/docsify/issues/663) ([d35059d](https://github.com/docsifyjs/docsify/commit/d35059d))
## 0.3.1
### Bug fixes
- Strip HTML tag when rendering the headings
## 0.3.0
### Features
- Add minified css files
- Add max level option
- Add pure.css
- upgrade PrismJS, fixed [#534](https://github.com/docsifyjs/docsify/issues/534) ([4805cb5](https://github.com/docsifyjs/docsify/commit/4805cb5))
## 0.2.1
### Bug fixes
- Fix vue.css
<a name="4.8.0"></a>
# [4.8.0](https://github.com/docsifyjs/docsify/compare/v4.7.1...v4.8.0) (2018-10-31)
### Bug Fixes
- Cache TOC for later usage in the case of cached file html ([#649](https://github.com/docsifyjs/docsify/issues/649)) ([9e86017](https://github.com/docsifyjs/docsify/commit/9e86017))
- improve external script plugin ([#632](https://github.com/docsifyjs/docsify/issues/632)) ([50c2434](https://github.com/docsifyjs/docsify/commit/50c2434))
- missing variable declaration ([#660](https://github.com/docsifyjs/docsify/issues/660)) ([1ce37bd](https://github.com/docsifyjs/docsify/commit/1ce37bd))
- Remove target for mailto links ([#652](https://github.com/docsifyjs/docsify/issues/652)) ([18f0f03](https://github.com/docsifyjs/docsify/commit/18f0f03))
- Update getAllPath query selector ([#653](https://github.com/docsifyjs/docsify/issues/653)) ([f6f4e32](https://github.com/docsifyjs/docsify/commit/f6f4e32))
- Update vue.styl ([#634](https://github.com/docsifyjs/docsify/issues/634)) ([bf060be](https://github.com/docsifyjs/docsify/commit/bf060be))
## 0.2.0
### Bug fixes
- Fix route
- Remove dynamic title
## 0.1.0
### Features
- Add docsify version to $window.docsify object ([#641](https://github.com/docsifyjs/docsify/issues/641)) ([94bc415](https://github.com/docsifyjs/docsify/commit/94bc415)), closes [#521](https://github.com/docsifyjs/docsify/issues/521)
- **compiler:** support embedded mermaid ([#629](https://github.com/docsifyjs/docsify/issues/629)) ([42ea8af](https://github.com/docsifyjs/docsify/commit/42ea8af))
- Add hideOtherSidebarContent option ([#661](https://github.com/docsifyjs/docsify/issues/661)) ([4a23c4a](https://github.com/docsifyjs/docsify/commit/4a23c4a))
- Allow base64, external, and relative logo values ([#642](https://github.com/docsifyjs/docsify/issues/642)) ([0a0802a](https://github.com/docsifyjs/docsify/commit/0a0802a)), closes [#577](https://github.com/docsifyjs/docsify/issues/577)
- upgrade marked to 0.5.x, fixed [#645](https://github.com/docsifyjs/docsify/issues/645), close [#644](https://github.com/docsifyjs/docsify/issues/644) ([#662](https://github.com/docsifyjs/docsify/issues/662)) ([a39b214](https://github.com/docsifyjs/docsify/commit/a39b214))
<a name="4.7.1"></a>
## [4.7.1](https://github.com/docsifyjs/docsify/compare/v4.7.0...v4.7.1) (2018-08-30)
<a name="4.7.0"></a>
# [4.7.0](https://github.com/QingWei-Li/docsify/compare/v4.6.9...v4.7.0) (2018-06-29)
### Bug Fixes
- alldow addition content in sidebar, fix [#518](https://github.com/QingWei-Li/docsify/issues/518), fix 539 ([#543](https://github.com/QingWei-Li/docsify/issues/543)) ([04b36b0](https://github.com/QingWei-Li/docsify/commit/04b36b0))
- async install config, fixed [#425](https://github.com/QingWei-Li/docsify/issues/425) ([e4e011c](https://github.com/QingWei-Li/docsify/commit/e4e011c))
- loading embed files synchronously, fixed [#525](https://github.com/QingWei-Li/docsify/issues/525), fixed [#527](https://github.com/QingWei-Li/docsify/issues/527) ([#544](https://github.com/QingWei-Li/docsify/issues/544)) ([feea7f9](https://github.com/QingWei-Li/docsify/commit/feea7f9))
- path include chinese character cause hilight bug ([#556](https://github.com/QingWei-Li/docsify/issues/556)) ([a5f333a](https://github.com/QingWei-Li/docsify/commit/a5f333a))
### Features
- add logo option, [#264](https://github.com/QingWei-Li/docsify/issues/264) ([#541](https://github.com/QingWei-Li/docsify/issues/541)) ([ee72dd0](https://github.com/QingWei-Li/docsify/commit/ee72dd0))
- add unpkg field, close [#531](https://github.com/QingWei-Li/docsify/issues/531) ([#558](https://github.com/QingWei-Li/docsify/issues/558)) ([5c0de0a](https://github.com/QingWei-Li/docsify/commit/5c0de0a))
- support image resizing, resolve [#508](https://github.com/QingWei-Li/docsify/issues/508) ([#545](https://github.com/QingWei-Li/docsify/issues/545)) ([3a7ad62](https://github.com/QingWei-Li/docsify/commit/3a7ad62))
<a name="4.6.10"></a>
## [4.6.10](https://github.com/QingWei-Li/docsify/compare/v4.6.9...v4.6.10) (2018-03-25)
### Bug Fixes
- async install config, fixed [#425](https://github.com/QingWei-Li/docsify/issues/425) ([e4e011c](https://github.com/QingWei-Li/docsify/commit/e4e011c))
<a name="4.6.9"></a>
## [4.6.9](https://github.com/QingWei-Li/docsify/compare/v4.6.8...v4.6.9) (2018-03-10)
### Bug Fixes
- upgrade medium-zoom, fixed [#417](https://github.com/QingWei-Li/docsify/issues/417) ([6a3d69a](https://github.com/QingWei-Li/docsify/commit/6a3d69a))
<a name="4.6.8"></a>
## [4.6.8](https://github.com/QingWei-Li/docsify/compare/v4.6.7...v4.6.8) (2018-03-06)
### Bug Fixes
- resolve path of image and embed files, fixed [#412](https://github.com/QingWei-Li/docsify/issues/412) ([bfd0d18](https://github.com/QingWei-Li/docsify/commit/bfd0d18))
<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))
- **search:** escape special characters for search, fixed [#369](https://github.com/QingWei-Li/docsify/issues/369) ([9755439](https://github.com/QingWei-Li/docsify/commit/9755439))
- build config ([342438f](https://github.com/QingWei-Li/docsify/commit/342438f))
- button style for coverpage, fixed [#362](https://github.com/QingWei-Li/docsify/issues/362) ([85428ef](https://github.com/QingWei-Li/docsify/commit/85428ef))
- dropdown scroll style, fixed [#346](https://github.com/QingWei-Li/docsify/issues/346) ([c4d83f2](https://github.com/QingWei-Li/docsify/commit/c4d83f2))
- highlight homepage link, fixed [#304](https://github.com/QingWei-Li/docsify/issues/304) ([f960c19](https://github.com/QingWei-Li/docsify/commit/f960c19))
- homepage link ([e097f88](https://github.com/QingWei-Li/docsify/commit/e097f88))
- onlyCover ([033be4f](https://github.com/QingWei-Li/docsify/commit/033be4f))
- 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))
- **compiler:** support embedded file as code block, close [#134](https://github.com/QingWei-Li/docsify/issues/134) ([761ccc2](https://github.com/QingWei-Li/docsify/commit/761ccc2))
- **compiler:** support embedded markdown, html, video, etc files, close [#383](https://github.com/QingWei-Li/docsify/issues/383), close [#333](https://github.com/QingWei-Li/docsify/issues/333) ([524f52f](https://github.com/QingWei-Li/docsify/commit/524f52f))
- **cover:** add onlyCover option, close [#382](https://github.com/QingWei-Li/docsify/issues/382) ([b265fdd](https://github.com/QingWei-Li/docsify/commit/b265fdd))
- **fetch:** add requestHeaders option, fixed [#336](https://github.com/QingWei-Li/docsify/issues/336) ([54ab4c9](https://github.com/QingWei-Li/docsify/commit/54ab4c9))
- **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)
### 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)
### Bug Fixes
- cover style, fixed [#381](https://github.com/QingWei-Li/docsify/issues/381) ([368754e](https://github.com/QingWei-Li/docsify/commit/368754e))
- 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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))
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
<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)
### 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)
### 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)
### 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)
### 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)
### 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)
### Bug Fixes
- can't render toc on first load ([d9b487e](https://github.com/QingWei-Li/docsify/commit/d9b487e))
- **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)
### 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)
### 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)
### 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)
### Bug Fixes
- **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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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)
### 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))
- Add buble.css

View file

@ -1,67 +0,0 @@
# Contribute
## Introduction
First, thank you for considering contributing to docsify! It's people like you that make the open source community such a great community! 😊
We welcome any type of contribution, not only code. You can help with
- **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
- **Marketing**: writing blog posts, howto's, printing stickers, ...
- **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
- **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them.
- **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/docsify).
## Your First Contribution
Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
## Submitting code
Any code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests.
## Code review process
The bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge.
It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?
## Financial contributions
We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/docsify).
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
## Questions
If you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
You can also reach us at hello@docsify.opencollective.com.
## Credits
### Contributors
Thank you to all the people who have already contributed to docsify!
<a href="graphs/contributors"><img src="https://opencollective.com/docsify/contributors.svg?width=890" /></a>
### Backers
Thank you to all our backers! [[Become a backer](https://opencollective.com/docsify#backer)]
<a href="https://opencollective.com/docsify#backers" target="_blank"><img src="https://opencollective.com/docsify/backers.svg?width=890"></a>
### Sponsors
Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/docsify#sponsor))
<a href="https://opencollective.com/docsify/sponsor/0/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/1/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/2/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/3/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/4/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/5/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/6/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/7/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/8/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/docsify/sponsor/9/website" target="_blank"><img src="https://opencollective.com/docsify/sponsor/9/avatar.svg"></a>
<!-- This `CONTRIBUTING.md` is based on @nayafia's template https://github.com/nayafia/contributing-template -->

View file

@ -1,736 +0,0 @@
<a name="3.7.3"></a>
## [3.7.3](https://github.com/QingWei-Li/docsify/compare/v3.7.2...v3.7.3) (2017-05-22)
### Bug Fixes
* **render:** find => filter ([eca3368](https://github.com/QingWei-Li/docsify/commit/eca3368))
<a name="3.7.2"></a>
## [3.7.2](https://github.com/QingWei-Li/docsify/compare/v3.7.1...v3.7.2) (2017-05-19)
<a name="3.7.1"></a>
## [3.7.1](https://github.com/QingWei-Li/docsify/compare/v3.7.0...v3.7.1) (2017-05-19)
### Bug Fixes
* docsify-updated is undefined ([b2b4742](https://github.com/QingWei-Li/docsify/commit/b2b4742))
<a name="3.7.0"></a>
# [3.7.0](https://github.com/QingWei-Li/docsify/compare/v3.6.6...v3.7.0) (2017-05-16)
### Features
* add docsify-updated, close [#158](https://github.com/QingWei-Li/docsify/issues/158) ([d2be5ae](https://github.com/QingWei-Li/docsify/commit/d2be5ae))
* add externalLinkTarget, close [#149](https://github.com/QingWei-Li/docsify/issues/149) ([2d73285](https://github.com/QingWei-Li/docsify/commit/2d73285))
<a name="3.6.6"></a>
## [3.6.6](https://github.com/QingWei-Li/docsify/compare/v3.6.5...v3.6.6) (2017-05-06)
### Features
* support query string for the search, fixed [#156](https://github.com/QingWei-Li/docsify/issues/156) ([da75d70](https://github.com/QingWei-Li/docsify/commit/da75d70))
<a name="3.6.5"></a>
## [3.6.5](https://github.com/QingWei-Li/docsify/compare/v3.6.4...v3.6.5) (2017-04-28)
### Bug Fixes
* **util:** fix crash, fixed [#154](https://github.com/QingWei-Li/docsify/issues/154) ([51832d3](https://github.com/QingWei-Li/docsify/commit/51832d3))
<a name="3.6.4"></a>
## [3.6.4](https://github.com/QingWei-Li/docsify/compare/v3.6.3...v3.6.4) (2017-04-28)
### Bug Fixes
* **util:** correctly clean up duplicate slashes, fixed [#153](https://github.com/QingWei-Li/docsify/issues/153) ([76c041a](https://github.com/QingWei-Li/docsify/commit/76c041a))
<a name="3.6.3"></a>
## [3.6.3](https://github.com/QingWei-Li/docsify/compare/v3.6.2...v3.6.3) (2017-04-25)
### Bug Fixes
* **external-script:** script attrs ([2653849](https://github.com/QingWei-Li/docsify/commit/2653849))
<a name="3.6.2"></a>
## [3.6.2](https://github.com/QingWei-Li/docsify/compare/v3.6.0...v3.6.2) (2017-04-12)
### Features
* **event:** Collapse the sidebar when click outside element in the small screen ([9b7e5f5](https://github.com/QingWei-Li/docsify/commit/9b7e5f5))
* **external-script:** detect more than one script dom, fixed [#146](https://github.com/QingWei-Li/docsify/issues/146) ([94d6603](https://github.com/QingWei-Li/docsify/commit/94d6603))
<a name="3.6.0"></a>
# [3.6.0](https://github.com/QingWei-Li/docsify/compare/v3.5.2...v3.6.0) (2017-04-09)
### Features
* **render:** add mergeNavbar option, close [#125](https://github.com/QingWei-Li/docsify/issues/125), [#124](https://github.com/QingWei-Li/docsify/issues/124) ([#145](https://github.com/QingWei-Li/docsify/issues/145)) ([9220523](https://github.com/QingWei-Li/docsify/commit/9220523))
<a name="3.5.2"></a>
## [3.5.2](https://github.com/QingWei-Li/docsify/compare/v3.5.1...v3.5.2) (2017-04-05)
<a name="3.5.1"></a>
## [3.5.1](https://github.com/QingWei-Li/docsify/compare/v3.5.0...v3.5.1) (2017-03-25)
### Bug Fixes
* .md file extension regex ([594299f](https://github.com/QingWei-Li/docsify/commit/594299f))
<a name="3.5.0"></a>
# [3.5.0](https://github.com/QingWei-Li/docsify/compare/v3.4.4...v3.5.0) (2017-03-25)
### Bug Fixes
* adjust display on small screens ([bf35471](https://github.com/QingWei-Li/docsify/commit/bf35471))
* navbar labels for German ([b022aaf](https://github.com/QingWei-Li/docsify/commit/b022aaf))
### Features
* **route:** auto remove .md extension ([8f11653](https://github.com/QingWei-Li/docsify/commit/8f11653))
<a name="3.4.4"></a>
## [3.4.4](https://github.com/QingWei-Li/docsify/compare/v3.4.3...v3.4.4) (2017-03-17)
### Bug Fixes
* **search:** fix input style ([2d6a51b](https://github.com/QingWei-Li/docsify/commit/2d6a51b))
<a name="3.4.3"></a>
## [3.4.3](https://github.com/QingWei-Li/docsify/compare/v3.4.2...v3.4.3) (2017-03-16)
<a name="3.4.2"></a>
## [3.4.2](https://github.com/QingWei-Li/docsify/compare/v3.4.1...v3.4.2) (2017-03-11)
### Features
* **emojify:** add no-emoji option ([3aef37a](https://github.com/QingWei-Li/docsify/commit/3aef37a))
<a name="3.4.1"></a>
## [3.4.1](https://github.com/QingWei-Li/docsify/compare/v3.4.0...v3.4.1) (2017-03-10)
### Bug Fixes
* **dom:** Disable the dom cache when vue is present, fixed [#119](https://github.com/QingWei-Li/docsify/issues/119) ([b9a7275](https://github.com/QingWei-Li/docsify/commit/b9a7275))
<a name="3.4.0"></a>
# [3.4.0](https://github.com/QingWei-Li/docsify/compare/v3.3.0...v3.4.0) (2017-03-09)
### Features
* **zoom-image:** add plugin ([50fa6fc](https://github.com/QingWei-Li/docsify/commit/50fa6fc))
<a name="3.3.0"></a>
# [3.3.0](https://github.com/QingWei-Li/docsify/compare/v3.2.0...v3.3.0) (2017-03-07)
<a name="3.2.0"></a>
# [3.2.0](https://github.com/QingWei-Li/docsify/compare/v3.1.2...v3.2.0) (2017-02-28)
### Bug Fixes
* **fetch:** load sidebar and navbar for parent path, fixed [#100](https://github.com/QingWei-Li/docsify/issues/100) ([f3fc596](https://github.com/QingWei-Li/docsify/commit/f3fc596))
* **render:** Toc rendering error, fixed [#106](https://github.com/QingWei-Li/docsify/issues/106) ([0d59ee9](https://github.com/QingWei-Li/docsify/commit/0d59ee9))
### Features
* **search:** Localization for no data tip, close [#103](https://github.com/QingWei-Li/docsify/issues/103) ([d3c9fbd](https://github.com/QingWei-Li/docsify/commit/d3c9fbd))
<a name="3.1.2"></a>
## [3.1.2](https://github.com/QingWei-Li/docsify/compare/v3.1.1...v3.1.2) (2017-02-27)
<a name="3.1.1"></a>
## [3.1.1](https://github.com/QingWei-Li/docsify/compare/v3.1.0...v3.1.1) (2017-02-24)
### Bug Fixes
* **render:** custom cover background image ([8f9bf29](https://github.com/QingWei-Li/docsify/commit/8f9bf29))
* **search:** don't search nameLink, fixed [#102](https://github.com/QingWei-Li/docsify/issues/102) ([507d9e8](https://github.com/QingWei-Li/docsify/commit/507d9e8))
* **tpl:** extra character, fixed [#101](https://github.com/QingWei-Li/docsify/issues/101) ([d67d25f](https://github.com/QingWei-Li/docsify/commit/d67d25f))
<a name="3.1.0"></a>
# [3.1.0](https://github.com/QingWei-Li/docsify/compare/v3.0.5...v3.1.0) (2017-02-22)
### Bug Fixes
* **search:** incorrect anchor link, fixed [#90](https://github.com/QingWei-Li/docsify/issues/90) ([b8a3d8f](https://github.com/QingWei-Li/docsify/commit/b8a3d8f))
* **sw:** update white list ([f2975a5](https://github.com/QingWei-Li/docsify/commit/f2975a5))
### Features
* **emoji:** add emoji plugin ([855c450](https://github.com/QingWei-Li/docsify/commit/855c450))
<a name="3.0.5"></a>
## [3.0.5](https://github.com/QingWei-Li/docsify/compare/v3.0.4...v3.0.5) (2017-02-21)
### Bug Fixes
* **event:** highlight sidebar when clicked, fixed [#86](https://github.com/QingWei-Li/docsify/issues/86) ([2a1157a](https://github.com/QingWei-Li/docsify/commit/2a1157a))
* **gen-tree:** cache toc list, fixed [#88](https://github.com/QingWei-Li/docsify/issues/88) ([3394ebb](https://github.com/QingWei-Li/docsify/commit/3394ebb))
* **layout.css:** loading style ([42b2dba](https://github.com/QingWei-Li/docsify/commit/42b2dba))
### Features
* **pwa:** add sw.js ([f7111b5](https://github.com/QingWei-Li/docsify/commit/f7111b5))
<a name="3.0.4"></a>
## [3.0.4](https://github.com/QingWei-Li/docsify/compare/v3.0.3...v3.0.4) (2017-02-20)
### Bug Fixes
* **render:** disable rendering sub list when loadSidebar is false ([35dd2e1](https://github.com/QingWei-Li/docsify/commit/35dd2e1))
* **render:** execute script ([780c1e5](https://github.com/QingWei-Li/docsify/commit/780c1e5))
<a name="3.0.3"></a>
## [3.0.3](https://github.com/QingWei-Li/docsify/compare/v3.0.2...v3.0.3) (2017-02-19)
<a name="3.0.2"></a>
## [3.0.2](https://github.com/QingWei-Li/docsify/compare/v3.0.1...v3.0.2) (2017-02-19)
### Bug Fixes
* **compiler:** link ([3b127a1](https://github.com/QingWei-Li/docsify/commit/3b127a1))
* **search:** add lazy input ([bf593a7](https://github.com/QingWei-Li/docsify/commit/bf593a7))
<a name="3.0.1"></a>
## [3.0.1](https://github.com/QingWei-Li/docsify/compare/v3.0.0...v3.0.1) (2017-02-19)
### Bug Fixes
* **route:** empty alias ([cd99b52](https://github.com/QingWei-Li/docsify/commit/cd99b52))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/QingWei-Li/docsify/compare/v2.4.3...v3.0.0) (2017-02-19)
### Bug Fixes
* **compiler:** link ([c7e09c3](https://github.com/QingWei-Li/docsify/commit/c7e09c3))
* **render:** support html file ([7b6a2ac](https://github.com/QingWei-Li/docsify/commit/7b6a2ac))
* **search:** escape html ([fcb66e8](https://github.com/QingWei-Li/docsify/commit/fcb66e8))
* **search:** fix default config ([2efd859](https://github.com/QingWei-Li/docsify/commit/2efd859))
### Features
* **front-matter:** add front matter[WIP] ([dbb9278](https://github.com/QingWei-Li/docsify/commit/dbb9278))
* **render:** add auto header ([b7768b1](https://github.com/QingWei-Li/docsify/commit/b7768b1))
* **search:** Localization for search placeholder, close [#80](https://github.com/QingWei-Li/docsify/issues/80) ([2351c3e](https://github.com/QingWei-Li/docsify/commit/2351c3e))
* **themes:** add loading info ([86594a3](https://github.com/QingWei-Li/docsify/commit/86594a3))
<a name="2.4.3"></a>
## [2.4.3](https://github.com/QingWei-Li/docsify/compare/v2.4.2...v2.4.3) (2017-02-15)
<a name="2.4.2"></a>
## [2.4.2](https://github.com/QingWei-Li/docsify/compare/v2.4.1...v2.4.2) (2017-02-14)
### Bug Fixes
* **index:** load file path error ([dc536a3](https://github.com/QingWei-Li/docsify/commit/dc536a3))
<a name="2.4.1"></a>
## [2.4.1](https://github.com/QingWei-Li/docsify/compare/v2.4.0...v2.4.1) (2017-02-13)
### Bug Fixes
* **index:** cover page ([dd0c84b](https://github.com/QingWei-Li/docsify/commit/dd0c84b))
<a name="2.4.0"></a>
# [2.4.0](https://github.com/QingWei-Li/docsify/compare/v2.3.0...v2.4.0) (2017-02-13)
### Features
* **hook:** add doneEach ([c6f7602](https://github.com/QingWei-Li/docsify/commit/c6f7602))
<a name="2.3.0"></a>
# [2.3.0](https://github.com/QingWei-Li/docsify/compare/v2.2.1...v2.3.0) (2017-02-13)
### Bug Fixes
* **event:** has no effect on a FF mobile browser, fixed [#67](https://github.com/QingWei-Li/docsify/issues/67) ([0ff36c2](https://github.com/QingWei-Li/docsify/commit/0ff36c2))
* **render:** custom marked renderer ([bf559b4](https://github.com/QingWei-Li/docsify/commit/bf559b4))
* **render:** fix render link ([a866744](https://github.com/QingWei-Li/docsify/commit/a866744))
* **render:** image url ([6f87529](https://github.com/QingWei-Li/docsify/commit/6f87529))
* **render:** render link ([38ea660](https://github.com/QingWei-Li/docsify/commit/38ea660))
* **src:** fix route ([324301a](https://github.com/QingWei-Li/docsify/commit/324301a))
* **src:** get alias ([784173e](https://github.com/QingWei-Li/docsify/commit/784173e))
* **src:** get alias ([ce99a04](https://github.com/QingWei-Li/docsify/commit/ce99a04))
* **themes:** fix navbar style ([fa54b52](https://github.com/QingWei-Li/docsify/commit/fa54b52))
* **themes:** update navbar style ([4864d1b](https://github.com/QingWei-Li/docsify/commit/4864d1b))
### Features
* **hook:** support custom plugin ([9e81a59](https://github.com/QingWei-Li/docsify/commit/9e81a59))
* **src:** add alias feature ([24412cd](https://github.com/QingWei-Li/docsify/commit/24412cd))
* **src:** dynamic title and fix sidebar style ([6b30eb6](https://github.com/QingWei-Li/docsify/commit/6b30eb6))
<a name="2.2.1"></a>
## [2.2.1](https://github.com/QingWei-Li/docsify/compare/v2.2.0...v2.2.1) (2017-02-11)
### Bug Fixes
* **event:** scroll active sidebar ([50f5fc2](https://github.com/QingWei-Li/docsify/commit/50f5fc2))
* **search:** crash when not content, fixed [#68](https://github.com/QingWei-Li/docsify/issues/68) ([9d3cc89](https://github.com/QingWei-Li/docsify/commit/9d3cc89))
* **search:** not work in mobile ([3941304](https://github.com/QingWei-Li/docsify/commit/3941304))
<a name="2.2.0"></a>
# [2.2.0](https://github.com/QingWei-Li/docsify/compare/v2.1.0...v2.2.0) (2017-02-09)
### Features
* **plugins:** add Google Analytics plugin ([#66](https://github.com/QingWei-Li/docsify/issues/66)) ([ac61bb0](https://github.com/QingWei-Li/docsify/commit/ac61bb0))
<a name="2.1.0"></a>
# [2.1.0](https://github.com/QingWei-Li/docsify/compare/v2.0.3...v2.1.0) (2017-02-09)
### Bug Fixes
* render name ([12e2479](https://github.com/QingWei-Li/docsify/commit/12e2479))
* **vue.css:** update sidebar style ([fc140ef](https://github.com/QingWei-Li/docsify/commit/fc140ef))
### Features
* add search, close [#43](https://github.com/QingWei-Li/docsify/issues/43) ([eb5ff3e](https://github.com/QingWei-Li/docsify/commit/eb5ff3e))
<a name="2.0.3"></a>
## [2.0.3](https://github.com/QingWei-Li/docsify/compare/v2.0.2...v2.0.3) (2017-02-07)
### Bug Fixes
* css var polyfill ([8cd386a](https://github.com/QingWei-Li/docsify/commit/8cd386a))
* css var polyfill ([cbaee21](https://github.com/QingWei-Li/docsify/commit/cbaee21))
* rendering emojis ([8c7e4d7](https://github.com/QingWei-Li/docsify/commit/8c7e4d7))
<a name="2.0.2"></a>
## [2.0.2](https://github.com/QingWei-Li/docsify/compare/v2.0.1...v2.0.2) (2017-02-05)
### Bug Fixes
* button style in cover page ([4470855](https://github.com/QingWei-Li/docsify/commit/4470855))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/QingWei-Li/docsify/compare/v2.0.0...v2.0.1) (2017-02-05)
<a name="2.0.0"></a>
# [2.0.0](https://github.com/QingWei-Li/docsify/compare/v1.10.5...v2.0.0) (2017-02-05)
### Features
* customize the theme color ([5cc9f05](https://github.com/QingWei-Li/docsify/commit/5cc9f05))
<a name="1.10.5"></a>
## [1.10.5](https://github.com/QingWei-Li/docsify/compare/v1.10.4...v1.10.5) (2017-01-28)
<a name="1.10.4"></a>
## [1.10.4](https://github.com/QingWei-Li/docsify/compare/v1.10.3...v1.10.4) (2017-01-27)
<a name="1.10.3"></a>
## [1.10.3](https://github.com/QingWei-Li/docsify/compare/v1.10.2...v1.10.3) (2017-01-27)
<a name="1.10.2"></a>
## [1.10.2](https://github.com/QingWei-Li/docsify/compare/v1.10.1...v1.10.2) (2017-01-25)
<a name="1.10.1"></a>
## [1.10.1](https://github.com/QingWei-Li/docsify/compare/v1.10.0...v1.10.1) (2017-01-25)
<a name="1.10.0"></a>
# [1.10.0](https://github.com/QingWei-Li/docsify/compare/v1.9.0...v1.10.0) (2017-01-25)
<a name="1.9.0"></a>
# [1.9.0](https://github.com/QingWei-Li/docsify/compare/v1.8.0...v1.9.0) (2017-01-24)
<a name="1.8.0"></a>
# [1.8.0](https://github.com/QingWei-Li/docsify/compare/v1.7.4...v1.8.0) (2017-01-24)
<a name="1.7.4"></a>
## [1.7.4](https://github.com/QingWei-Li/docsify/compare/v1.7.3...v1.7.4) (2017-01-13)
<a name="1.7.3"></a>
## [1.7.3](https://github.com/QingWei-Li/docsify/compare/v1.7.2...v1.7.3) (2017-01-13)
<a name="1.7.2"></a>
## [1.7.2](https://github.com/QingWei-Li/docsify/compare/v1.7.1...v1.7.2) (2017-01-12)
<a name="1.7.1"></a>
## [1.7.1](https://github.com/QingWei-Li/docsify/compare/v1.7.0...v1.7.1) (2017-01-12)
<a name="1.7.0"></a>
# [1.7.0](https://github.com/QingWei-Li/docsify/compare/v1.6.1...v1.7.0) (2017-01-12)
<a name="1.6.1"></a>
## [1.6.1](https://github.com/QingWei-Li/docsify/compare/v1.6.0...v1.6.1) (2017-01-10)
<a name="1.6.0"></a>
# [1.6.0](https://github.com/QingWei-Li/docsify/compare/v1.5.2...v1.6.0) (2017-01-10)
<a name="1.5.2"></a>
## [1.5.2](https://github.com/QingWei-Li/docsify/compare/v1.5.1...v1.5.2) (2017-01-10)
<a name="1.5.1"></a>
## [1.5.1](https://github.com/QingWei-Li/docsify/compare/v1.5.0...v1.5.1) (2017-01-09)
<a name="1.5.0"></a>
# [1.5.0](https://github.com/QingWei-Li/docsify/compare/v1.4.3...v1.5.0) (2017-01-04)
### Features
* Markdown parser is configurable, [#42](https://github.com/QingWei-Li/docsify/issues/42) ([8b1000a](https://github.com/QingWei-Li/docsify/commit/8b1000a))
<a name="1.4.3"></a>
## [1.4.3](https://github.com/QingWei-Li/docsify/compare/v1.4.2...v1.4.3) (2017-01-01)
<a name="1.4.2"></a>
## [1.4.2](https://github.com/QingWei-Li/docsify/compare/v1.4.1...v1.4.2) (2016-12-31)
<a name="1.4.1"></a>
## [1.4.1](https://github.com/QingWei-Li/docsify/compare/v1.4.0...v1.4.1) (2016-12-31)
<a name="1.4.0"></a>
# [1.4.0](https://github.com/QingWei-Li/docsify/compare/v1.3.5...v1.4.0) (2016-12-31)
<a name="1.3.5"></a>
## [1.3.5](https://github.com/QingWei-Li/docsify/compare/v1.3.4...v1.3.5) (2016-12-25)
<a name="1.3.4"></a>
## [1.3.4](https://github.com/QingWei-Li/docsify/compare/v1.3.3...v1.3.4) (2016-12-25)
<a name="1.3.3"></a>
## [1.3.3](https://github.com/QingWei-Li/docsify/compare/v1.3.2...v1.3.3) (2016-12-23)
<a name="1.3.2"></a>
## [1.3.2](https://github.com/QingWei-Li/docsify/compare/v1.3.1...v1.3.2) (2016-12-22)
<a name="1.3.1"></a>
## [1.3.1](https://github.com/QingWei-Li/docsify/compare/v1.3.0...v1.3.1) (2016-12-22)
<a name="1.3.0"></a>
# [1.3.0](https://github.com/QingWei-Li/docsify/compare/v1.2.0...v1.3.0) (2016-12-21)
<a name="1.2.0"></a>
# [1.2.0](https://github.com/QingWei-Li/docsify/compare/v1.1.7...v1.2.0) (2016-12-20)
<a name="1.1.7"></a>
## [1.1.7](https://github.com/QingWei-Li/docsify/compare/v1.1.6...v1.1.7) (2016-12-19)
<a name="1.1.6"></a>
## [1.1.6](https://github.com/QingWei-Li/docsify/compare/v1.1.5...v1.1.6) (2016-12-18)
<a name="1.1.5"></a>
## [1.1.5](https://github.com/QingWei-Li/docsify/compare/v1.1.4...v1.1.5) (2016-12-18)
<a name="1.1.4"></a>
## [1.1.4](https://github.com/QingWei-Li/docsify/compare/v1.1.3...v1.1.4) (2016-12-17)
<a name="1.1.3"></a>
## [1.1.3](https://github.com/QingWei-Li/docsify/compare/v1.1.2...v1.1.3) (2016-12-17)
<a name="1.1.2"></a>
## [1.1.2](https://github.com/QingWei-Li/docsify/compare/v1.1.1...v1.1.2) (2016-12-17)
<a name="1.1.1"></a>
## [1.1.1](https://github.com/QingWei-Li/docsify/compare/v1.1.0...v1.1.1) (2016-12-17)
<a name="1.1.0"></a>
# [1.1.0](https://github.com/QingWei-Li/docsify/compare/v1.0.3...v1.1.0) (2016-12-16)
<a name="1.0.3"></a>
## [1.0.3](https://github.com/QingWei-Li/docsify/compare/v1.0.2...v1.0.3) (2016-12-13)
<a name="1.0.2"></a>
## [1.0.2](https://github.com/QingWei-Li/docsify/compare/v1.0.1...v1.0.2) (2016-12-13)
<a name="1.0.1"></a>
## [1.0.1](https://github.com/QingWei-Li/docsify/compare/v1.0.0...v1.0.1) (2016-12-08)
<a name="1.0.0"></a>
# [1.0.0](https://github.com/QingWei-Li/docsify/compare/v0.7.0...v1.0.0) (2016-12-08)
<a name="0.7.0"></a>
# [0.7.0](https://github.com/QingWei-Li/docsify/compare/v0.6.1...v0.7.0) (2016-11-30)
<a name="0.6.1"></a>
## [0.6.1](https://github.com/QingWei-Li/docsify/compare/v0.6.0...v0.6.1) (2016-11-29)
<a name="0.6.0"></a>
# [0.6.0](https://github.com/QingWei-Li/docsify/compare/v0.5.0...v0.6.0) (2016-11-29)
<a name="0.5.0"></a>
# [0.5.0](https://github.com/QingWei-Li/docsify/compare/v0.4.2...v0.5.0) (2016-11-28)
<a name="0.4.2"></a>
## [0.4.2](https://github.com/QingWei-Li/docsify/compare/v0.4.1...v0.4.2) (2016-11-28)
<a name="0.4.1"></a>
## [0.4.1](https://github.com/QingWei-Li/docsify/compare/v0.4.0...v0.4.1) (2016-11-28)
<a name="0.4.0"></a>
# [0.4.0](https://github.com/QingWei-Li/docsify/compare/v0.3.1...v0.4.0) (2016-11-27)
### Features
* custom sidebar, [#4](https://github.com/QingWei-Li/docsify/issues/4) ([#5](https://github.com/QingWei-Li/docsify/issues/5)) ([37e7984](https://github.com/QingWei-Li/docsify/commit/37e7984))
<a name="0.3.1"></a>
## [0.3.1](https://github.com/QingWei-Li/docsify/compare/v0.3.0...v0.3.1) (2016-11-27)
<a name="0.3.0"></a>
# [0.3.0](https://github.com/QingWei-Li/docsify/compare/v0.2.1...v0.3.0) (2016-11-27)
<a name="0.2.1"></a>
## [0.2.1](https://github.com/QingWei-Li/docsify/compare/v0.2.0...v0.2.1) (2016-11-26)
<a name="0.2.0"></a>
# [0.2.0](https://github.com/QingWei-Li/docsify/compare/v0.1.0...v0.2.0) (2016-11-26)
<a name="0.1.0"></a>
# [0.1.0](https://github.com/QingWei-Li/docsify/compare/v0.0.5...v0.1.0) (2016-11-26)
<a name="0.0.5"></a>
## [0.0.5](https://github.com/QingWei-Li/docsify/compare/v0.0.4...v0.0.5) (2016-11-24)
<a name="0.0.4"></a>
## [0.0.4](https://github.com/QingWei-Li/docsify/compare/v0.0.3...v0.0.4) (2016-11-22)
<a name="0.0.3"></a>
## [0.0.3](https://github.com/QingWei-Li/docsify/compare/v0.0.2...v0.0.3) (2016-11-20)
<a name="0.0.2"></a>
## [0.0.2](https://github.com/QingWei-Li/docsify/compare/v0.0.1...v0.0.2) (2016-11-20)
<a name="0.0.1"></a>
## 0.0.1 (2016-11-20)

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016 - present cinwell.li
Copyright (c) 2016 cinwell.li
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

133
README.md
View file

@ -1,111 +1,62 @@
<p align="center">
<a href="https://docsify.js.org">
<img alt="docsify" src="./docs/_media/icon.svg">
</a>
</p>
# docsify
[![Build Status](https://travis-ci.org/QingWei-Li/docsify.svg?branch=master)](https://travis-ci.org/QingWei-Li/docsify)
[![npm](https://img.shields.io/npm/v/docsify.svg)](https://www.npmjs.com/package/docsify)
<p align="center">
A magical documentation site generator.
</p>
<p align="center">
<a href="#backers"><img alt="Backers on Open Collective" src="https://opencollective.com/docsify/backers/badge.svg?style=flat-square"></a>
<a href="#sponsors"><img alt="Sponsors on Open Collective" src="https://opencollective.com/docsify/sponsors/badge.svg?style=flat-square"></a>
<a href="https://travis-ci.org/docsifyjs/docsify"><img alt="Travis Status" src="https://img.shields.io/travis/docsifyjs/docsify/master.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/docsify"><img alt="npm" src="https://img.shields.io/npm/v/docsify.svg?style=flat-square"></a>
<a href="https://github.com/QingWei-Li/donate"><img alt="donate" src="https://img.shields.io/badge/%24-donate-ff69b4.svg?style=flat-square"></a>
<a href="https://gitter.im/docsifyjs/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link"><img alt="gitter" src="https://img.shields.io/gitter/room/docsifyjs/docsify.svg?style=flat-square"></a>
</p>
<p align="center">Gold Sponsor via <a href="https://opencollective.com/docsify">Open Collective</a></p>
<p align="center">
<a href="https://opencollective.com/docsify/order/3254">
<img src="https://opencollective.com/docsify/tiers/gold-sponsor.svg?avatarHeight=36">
</a>
</p>
>🃏 A magical documentation site generator.
## Links
- [`develop` branch preview](https://docsifyjs.netlify.com/)
- [Documentation](https://docsify.js.org)
- [CLI](https://github.com/docsifyjs/docsify-cli)
- CDN: [UNPKG](https://unpkg.com/docsify/) | [jsDelivr](https://cdn.jsdelivr.net/npm/docsify/) | [cdnjs](https://cdnjs.com/libraries/docsify)
- [Awesome docsify](https://github.com/docsifyjs/awesome-docsify)
- [Community chat](https://gitter.im/docsifyjs/Lobby)
- [CLI](https://github.com/QingWei-Li/docsify-cli)
## Features
- No statically built html files
- Simple and lightweight (~21kB gzipped)
- Smart full-text search plugin
- Multiple themes
- Useful plugin API
- Compatible with IE11
- Support SSR ([example](https://github.com/docsifyjs/docsify-ssr-demo))
- Support embedded files
- Easy and lightweight
- Custom themes
- No build
## Quick start
Create a `404.html` and `README.md` into `/docs`.
Look at [this tutorial](https://docsify.js.org/#/quickstart)
404.html
[![Edit 307qqv236](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/307qqv236)
## Showcase
These projects are using docsify to generate their sites. Pull requests welcome :blush:
Move to [awesome-docsify](https://github.com/docsifyjs/awesome-docsify#showcase)
## Similar projects
| Project | Description |
| ------------------------------------------------ | ---------------------------------------- |
| [docute](https://github.com/egoist/docute) | 📜 Effortlessly documentation done right |
| [docpress](https://github.com/docpress/docpress) | Documentation website generator |
## Contributing
- Fork it!
- Create your feature branch: `git checkout -b my-new-feature`
- Commit your changes: `git commit -am 'Add some feature'`
- Push to the branch: `git push origin my-new-feature`
- Submit a pull request
## Development
```bash
npm run bootstrap && npm run dev
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body></body>
<script src="//unpkg.com/docsify"></script>
</html>
```
## Backers
Or Create a `index.html` and using `hash router`.
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/docsify#backers)]
index.html
<a href="https://opencollective.com/docsify#backers" target="_blank"><img src="https://opencollective.com/docsify/backers.svg?width=890"></a>
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body></body>
<script src="//unpkg.com/docsify" data-router></script>
</html>
```
## Sponsors
## Showcase
These open-source projects are using docsify to generate their sites. Pull requests welcome : )
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/docsify#silver-sponsors)]
- [docsify](https://docsify.js.org) - A magical documentation site generator.
- [Snipaste](https://docs.snipaste.com/) - A new way to boost your productivity.
<a href="https://opencollective.com/docsify/silver-sponsors/0/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/0/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/1/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/1/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/2/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/2/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/3/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/3/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/4/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/4/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/5/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/5/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/6/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/6/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/7/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/7/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/8/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/8/avatar.svg"></a>
<a href="https://opencollective.com/docsify/silver-sponsors/9/website" target="_blank"><img src="https://opencollective.com/docsify/silver-sponsors/9/avatar.svg"></a>
## How to contribute
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/docsifyjs/docsify/graphs/contributors"><img src="https://opencollective.com/docsify/contributors.svg?width=890" /></a>
- Fork it!
- Run `npm i && npm run dev`
- open `localhost:3000`
## License
[MIT](LICENSE)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fdocsifyjs%2Fdocsify.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fdocsifyjs%2Fdocsify?ref=badge_large)
MIT

12
app.js Normal file
View file

@ -0,0 +1,12 @@
var serveStatic = require('serve-static')
var http = require('http')
var fs = require('fs')
http.createServer(function (req, res) {
serveStatic('.')(req, res, function () {
res.writeHead(404, { 'Content-Type': 'text/html' })
res.end(fs.readFileSync('404.dev.html'))
})
}).listen(3000, '0.0.0.0')
console.log(`\nListening at http://0.0.0.0:3000\n`)

38
build/build-css.js Normal file
View file

@ -0,0 +1,38 @@
var fs = require('fs')
var cssnano = require('cssnano').process
var resolve = require('path').resolve
var postcss = require('postcss')
var processor = postcss([require('postcss-salad')])
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)
cssnano(loadLib(file))
.then(function (result) {
saveMin(file, result.css)
console.log('cssnao - ' + file)
})
}).catch(function (err) {
console.log(err)
})
})

View file

@ -1,119 +1,37 @@
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 rollup = require('rollup')
var buble = require('rollup-plugin-buble')
var commonjs = require('rollup-plugin-commonjs')
var nodeResolve = require('rollup-plugin-node-resolve')
var uglify = require('rollup-plugin-uglify')
const build = function (opts) {
var build = function (opts) {
rollup
.rollup({
input: opts.input,
plugins: (opts.plugins || []).concat([
buble(),
commonjs(),
nodeResolve(),
replace({
__VERSION__: version,
'process.env.SSR': false
})
])
entry: 'src/' + opts.entry,
plugins: [buble()].concat(opts.plugins || [])
})
.then(function (bundle) {
var dest = 'lib/' + (opts.output || opts.input)
var dest = 'lib/' + (opts.output || opts.entry)
console.log(dest)
bundle.write({
format: 'iife',
file: dest,
strict: false
moduleName: opts.moduleName || 'Docsify',
dest: dest
})
})
.catch(function (err) {
console.error(err)
})
}
const buildCore = function () {
build({
input: 'src/core/index.js',
output: 'docsify.js'
})
if (isProd) {
build({
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: 'matomo', input: 'matomo.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()
}
build({
entry: 'index.js',
output: 'docsify.js',
plugins: [commonjs(), nodeResolve()]
})
build({
entry: 'index.js',
output: 'docsify.min.js',
plugins: [commonjs(), nodeResolve(), uglify()]
})

View file

@ -1,14 +0,0 @@
var fs = require('fs')
var read = fs.readFileSync
var write = fs.writeFileSync
var version = process.env.VERSION || require('../package.json').version
var file = __dirname + '/../docs/_coverpage.md'
var cover = read(file, 'utf8').toString()
console.log('Replace version number in cover page...')
cover = cover.replace(
/<small>(\S+)?<\/small>/g,
'<small>' + version + '</small>'
)
write(file, cover)

View file

@ -1,12 +0,0 @@
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,50 +0,0 @@
set -e
if [[ -z $1 ]]; then
echo "Enter new version: "
read VERSION
else
VERSION=$1
fi
read -p "Releasing $VERSION $RELEASE_TAG - are you sure? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Releasing $VERSION ..."
npm run test
# build
VERSION=$VERSION npm run build
# update packages
cd packages/docsify-server-renderer
npm version $VERSION
if [[ -z $RELEASE_TAG ]]; then
npm publish
else
npm publish --tag $RELEASE_TAG
fi
cd -
# commit
git add -A
git commit -m "[build] $VERSION $RELEASE_TAG"
npm --no-git-tag-version version $VERSION --message "[release] $VERSION $RELEASE_TAG"
# changelog
node_modules/.bin/conventional-changelog -p angular -i CHANGELOG.md -s
git add .
git commit -m "chore: add changelog $VERSION"
# publish
git tag v$VERSION
git push origin refs/tags/v$VERSION
git push
if [[ -z $RELEASE_TAG ]]; then
npm publish
else
npm publish --tag $RELEASE_TAG
fi
fi

View file

@ -1,34 +0,0 @@
var rollup = require('rollup')
var buble = require('rollup-plugin-buble')
var async = require('rollup-plugin-async')
var replace = require('rollup-plugin-replace')
rollup
.rollup({
input: 'packages/docsify-server-renderer/index.js',
plugins: [
async(),
replace({
__VERSION__: process.env.VERSION || require('../package.json').version,
'process.env.SSR': true
}),
buble({
transforms: {
generator: false
}
})
],
onwarn: function () {}
})
.then(function (bundle) {
var dest = 'packages/docsify-server-renderer/build.js'
console.log(dest)
bundle.write({
format: 'cjs',
file: dest
})
})
.catch(function (err) {
console.error(err)
})

View file

View file

@ -1,32 +1,222 @@
## docsify
# docsify
> A magical documentation site generator.
## What it is
docsify generates your documentation website on the fly. Unlike GitBook, it does not generate static html files. Instead, it smartly loads and parses your Markdown files and displays them as a website. To start using it, all you need to do is create an `index.html` and [deploy it on GitHub Pages](deploy.md).
See the [Quick start](quickstart.md) guide for more details.
## Features
- Easy and lightweight
- Custom themes
- No build
- No statically built html files
- Simple and lightweight (~21kB gzipped)
- Smart full-text search plugin
- Multiple themes
- Useful plugin API
- Emoji support
- Compatible with IE11
- Support server-side rendering ([example](https://github.com/docsifyjs/docsify-ssr-demo))
## Quick Start
## Examples
### Create a project
First create a project, then create a `docs` folder
```shell
mkdir my-project && cd my-project
mkdir docs && cd docs
```
Check out the [Showcase](https://github.com/docsifyjs/awesome-docsify#showcase) to see docsify in use.
### Create entry file
Create a `404.html` file
## Donate
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify"></script>
</html>
```
Please consider donating if you think docsify is helpful to you or that my work is valuable. I am happy if you can help me [buy a cup of coffee](https://github.com/QingWei-Li/donate). :heart:
Create `README.md` as the main page
## Community
```
# Title
Users and the development team are usually in the [Gitter chat room](https://gitter.im/docsifyjs/Lobby).
## balabala
```
### Deploy!
Push and open the **GitHub Pages** feature
![image](https://cloud.githubusercontent.com/assets/7565692/20639058/e65e6d22-b3f3-11e6-9b8b-6309c89826f2.png)
## CLI
Easy to setup and preivew a docs.
### Install
```shell
npm i docsify-cli -g
```
### Setup
Setup a boilerplate docs
```shell
docsify init docs
```
### Preview
Preview and serve your docs using
```shell
docsify serve docs
```
Read more [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
## Themes
Currently available `vue.css` and `buble.css`
```html
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
```
Minified files
```html
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
```
## More
### Multiple pages
If you need other pages, directly create the markdown file, such as `guide.md` is `/guide`.
### Navbar
Code in `404.html`
```html
<nav>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
</nav>
```
### Options
#### repo
Display the [GitHub Corner](http://tholman.com/github-corners/) widget.
```html
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
```
#### max-level
Toc level.
```html
<script src="//unpkg.com/docsify" data-max-level="6"></script>
```
#### el
Root element.
```html
<script src="//unpkg.com/docsify" data-el="#app"></script>
```
#### sidebar-toggle
Sidebar with toggle
```html
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on the `data-sidebar`.
![image](https://cloud.githubusercontent.com/assets/7565692/20647425/de5ab1c2-b4ce-11e6-863a-135868f2f9b4.png)
```html
<script>
window.sidebar = [
{ slug: '/', title: 'Home' },
{
slug: '/pageA',
title: 'page A',
children: [
{ slug: '/pageA/childrenB', title: 'children B' }
]
},
{ slug: '/PageC', title: 'Page C' }
]
</script>
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
```
#### load-sidebar
Load sidebar markdown file. If it is configured, load the current directory `_sidebar.md` by default. If the file isn't exist, sidebar will appear TOC.
```html
<script src="/lib/docsify.js" data-load-sidebar></script>
```
You can specify a file:
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
The contents of the file can be:
```markdown
- [Home](/)
- [Installation](/installation)
- Essentials
- [Getting Started](/getting-started)
- [Dynamic Route Matching](/dynamic-matching)
- [Nested Routes](/nested-routes)
- [Programmatic Navigation](/navigation)
- [Named Routes](/named-routes)
- [Named Views](/named-views)
- [Redirect and Alias](/redirect-and-alias)
- [HTML5 History Mode](/history-mode)
```
#### load-navbar
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
```html
<script src="/lib/docsify.js" data-load-navbar></script>
```
You can specify a file:
```html
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
The contents of the file can be:
```markdown
- [en](/)
- [chinese](/zh-cn)
```
If you write a sub level list, it will generate a dropdown list.
```markdown
- [download](/download)
- language
- [en](/)
- [chinese](/zh-cn)
```
### router
Hash router. You can replace `404.html` with `index.html`.
```html
<script src="/lib/docsify.js" data-router></script>
```

View file

@ -1,12 +0,0 @@
![logo](_media/icon.svg)
# docsify <small>4.9.4</small>
> A magical documentation site generator.
- Simple and lightweight (~21kB gzipped)
- No statically built html files
- Multiple themes
[GitHub](https://github.com/docsifyjs/docsify/)
[Getting Started](#docsify)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

View file

@ -1 +0,0 @@
<h1>To infinity and Beyond!</h1>

View file

@ -1,16 +0,0 @@
import fetch from 'fetch'
const URL = 'https://example.com'
const PORT = 8080
/// [demo]
const result = fetch(`${URL}:${PORT}`)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});
/// [demo]
result.then(console.log).catch(console.error)

View file

@ -1 +0,0 @@
> This is from the `example.md`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View file

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="122px" height="94px" viewBox="0 0 122 94" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M144.453286,104 C177.038086,104 203.453286,77.5848002 203.453286,45 C203.453286,12.4151998 177.038086,-14 144.453286,-14 C111.868486,-14 114.603207,13.6754846 114.603207,46.2602848 C114.603207,78.845085 111.868486,104 144.453286,104 Z" id="path-1"></path>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="7" dy="-10" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
<feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
</filter>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-98.000000, 2.000000)">
<g id="body" transform="translate(159.000000, 45.000000) rotate(-90.000000) translate(-159.000000, -45.000000) ">
<use fill="#2ECE53" fill-rule="evenodd" xlink:href="#path-1"></use>
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use stroke="#0E1320" stroke-width="4" xlink:href="#path-1"></use>
</g>
<circle id="left-eye" fill="#000000" cx="139" cy="38" r="7"></circle>
<circle id="right-eye" fill="#000000" cx="183" cy="38" r="7"></circle>
<g id="light" transform="translate(112.000000, 10.000000)" fill="#FFFFFF">
<circle cx="2" cy="28" r="2"></circle>
<path d="M12.2551528,-1.65016666 C12.1154537,-2.17684986 12.4455583,-2.60381096 13.011574,-2.60381096 L14.9928363,-2.60381096 C15.5502953,-2.60381096 16.1214654,-2.16566487 16.2594657,-1.64268776 C16.2594657,-1.64268776 17.4280152,2.48668594 17.9030739,6.45786647 C18.3781327,10.429047 18.3171359,10.4652901 18.3171359,12.1782569 C18.3171359,16.9413523 16.2076398,26.4389164 16.2076398,26.4389164 C16.0941814,26.9676035 15.558852,27.396189 14.9928363,27.396189 L13.011574,27.396189 C12.454115,27.396189 12.1166642,26.9691757 12.2568366,26.4301177 C12.2568366,26.4301177 13.4260575,22.2288768 13.9640759,17.9859148 C14.5020943,13.7429529 14.309594,15.2982629 14.5626609,12.3723978 C14.9355337,8.06138047 12.2551528,-1.65016666 12.2551528,-1.65016666 Z" id="light-line" transform="translate(15.271433, 12.396189) scale(-1, 1) rotate(-48.000000) translate(-15.271433, -12.396189) "></path>
</g>
<path d="M159.5,78.3050108 C169.164983,78.3050108 177,70.4699939 177,60.8050108 C177,51.1400277 169.688728,56.4616841 160.023745,56.4616841 C150.358762,56.4616841 142,51.1400277 142,60.8050108 C142,70.4699939 149.835017,78.3050108 159.5,78.3050108 Z" id="mouth" fill="#000000"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,6 +0,0 @@
- Translations
- [:uk: English](/)
- [:cn: 中文](/zh-cn/)
- [:de: Deutsch](/de-de/)
- [:es: Spanish](/es/)
- [:ru: Russian](/ru/)

View file

@ -1,28 +0,0 @@
- Getting started
- [Quick start](quickstart.md)
- [Writing more pages](more-pages.md)
- [Custom navbar](custom-navbar.md)
- [Cover page](cover.md)
- Customization
- [Configuration](configuration.md)
- [Themes](themes.md)
- [List of Plugins](plugins.md)
- [Write a Plugin](write-a-plugin.md)
- [Markdown configuration](markdown.md)
- [Language highlighting](language-highlight.md)
- Guide
- [Deploy](deploy.md)
- [Helpers](helpers.md)
- [Vue compatibility](vue.md)
- [CDN](cdn.md)
- [Offline Mode(PWA)](pwa.md)
- [Server-Side Rendering(SSR)](ssr.md)
- [Embed Files](embed-files.md)
- [Awesome docsify](awesome.md)
- [Changelog](changelog.md)

View file

@ -1,50 +0,0 @@
# CDN
Recommended: [unpkg](//unpkg.com), which will reflect the latest version as soon as it is published to npm. You can also browse the source of the npm package at [unpkg.com/docsify/](//unpkg.com/docsify/).
## Latest version
```html
<!-- load css -->
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
<!-- load script -->
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
```
Alternatively, use [compressed files](#compressed-file).
## Specific version
```html
<!-- load css -->
<link rel="stylesheet" href="//unpkg.com/docsify@2.0.0/themes/vue.css">
<!-- load script -->
<script src="//unpkg.com/docsify@2.0.0/lib/docsify.js"></script>
```
## Compressed file
```html
<!-- load css -->
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<!-- load script -->
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
```html
<!-- load css -->
<link rel="stylesheet" href="//unpkg.com/docsify@2.0.0/lib/themes/vue.css">
<!-- load script -->
<script src="//unpkg.com/docsify@2.0.0/lib/docsify.min.js"></script>
```
## Other CDN
- http://www.bootcdn.cn/docsify
- https://cdn.jsdelivr.net/npm/docsify/
- https://cdnjs.com/libraries/docsify

View file

@ -1,518 +0,0 @@
# Configuration
You can configure the `window.$docsify`.
```html
<script>
window.$docsify = {
repo: 'docsifyjs/docsify',
maxLevel: 3,
coverpage: true
}
</script>
```
## el
- Type: `String`
- Default: `#app`
The DOM element to be mounted on initialization. It can be a CSS selector string or an actual HTMLElement.
```js
window.$docsify = {
el: '#app'
};
```
## repo
- Type: `String`
- Default: `null`
Configure the repository url or a string of `username/repo` can add the [GitHub Corner](http://tholman.com/github-corners/) widget in the top right corner of the site.
```js
window.$docsify = {
repo: 'docsifyjs/docsify',
// or
repo: 'https://github.com/docsifyjs/docsify/'
};
```
## maxLevel
- Type: `Number`
- Default: `6`
Maximum Table of content level.
```js
window.$docsify = {
maxLevel: 4
};
```
## loadNavbar
- Type: `Boolean|String`
- Default: `false`
Loads navbar from the Markdown file `_navbar.md` if **true**, or else from the path specified.
```js
window.$docsify = {
// load from _navbar.md
loadNavbar: true,
// load from nav.md
loadNavbar: 'nav.md'
};
```
## loadSidebar
- Type: `Boolean|String`
- Default: `false`
Loads sidebar from the Markdown file `_sidebar.md` if **true**, or else from the path specified.
```js
window.$docsify = {
// load from _sidebar.md
loadSidebar: true,
// load from summary.md
loadSidebar: 'summary.md'
};
```
## subMaxLevel
- Type: `Number`
- Default: `0`
Add table of contents (TOC) in custom sidebar.
```js
window.$docsify = {
subMaxLevel: 2
};
```
## auto2top
- Type: `Boolean`
- Default: `false`
Scrolls to the top of the screen when the route is changed.
```js
window.$docsify = {
auto2top: true
};
```
## homepage
- Type: `String`
- Default: `README.md`
`README.md` in your docs folder will be treated as homepage for your website, but sometimes you may need to serve another file as your homepage.
```js
window.$docsify = {
// Change to /home.md
homepage: 'home.md',
// Or use the readme in your repo
homepage:
'https://raw.githubusercontent.com/docsifyjs/docsify/master/README.md'
};
```
## basePath
- Type: `String`
Base path of the website. You can set it to another directory or another domain name.
```js
window.$docsify = {
basePath: '/path/',
// Load the files from another site
basePath: 'https://docsify.js.org/',
// Even can load files from other repo
basePath:
'https://raw.githubusercontent.com/ryanmcdermott/clean-code-javascript/master/'
};
```
## relativePath
- Type: `Boolean`
- Default: `false`
If **true** links are relative to the current context.
For example, the directory structure is as follows:
```text
.
└── docs
├── README.md
├── guide.md
└── zh-cn
├── README.md
├── guide.md
└── config
└── example.md
```
With relative path **enabled** and current URL `http://domain.com/zh-cn/README`, given links will resolve to:
```text
guide.md => http://domain.com/zh-cn/guide
config/example.md => http://domain.com/zh-cn/config/example
../README.md => http://domain.com/README
/README.md => http://domain.com/README
```
```js
window.$docsify = {
// Relative path enabled
relativePath: true,
// Relative path disabled (default value)
relativePath: false
};
```
## coverpage
- Type: `Boolean|String|String[]|Object`
- Default: `false`
Activate the [cover feature](cover.md). If true, it will load from `_coverpage.md`.
```js
window.$docsify = {
coverpage: true,
// Custom file name
coverpage: 'cover.md',
// mutiple covers
coverpage: ['/', '/zh-cn/'],
// mutiple covers and custom file name
coverpage: {
'/': 'cover.md',
'/zh-cn/': 'cover.md'
}
};
```
## logo
- Type: `String`
Website logo as it appears in the sidebar, you can resize by CSS.
```js
window.$docsify = {
logo: '/_media/icon.svg'
};
```
## name
- Type: `String`
Website name as it appears in the sidebar.
```js
window.$docsify = {
name: 'docsify'
};
```
## nameLink
- Type: `String`
- Default: `window.location.pathname`
The name of the link.
```js
window.$docsify = {
nameLink: '/',
// For each route
nameLink: {
'/zh-cn/': '/zh-cn/',
'/': '/'
}
};
```
## markdown
- Type: `Function`
See [Markdown configuration](markdown.md).
```js
window.$docsify = {
// object
markdown: {
smartypants: true,
renderer: {
link: function() {
// ...
}
}
},
// function
markdown: function(marked, renderer) {
// ...
return marked;
}
};
```
## themeColor
- Type: `String`
Customize the theme color. Use [CSS3 variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) feature and polyfill in old browser.
```js
window.$docsify = {
themeColor: '#3F51B5'
};
```
## alias
- Type: `Object`
Set the route alias. You can freely manage routing rules. Supports RegExp.
```js
window.$docsify = {
alias: {
'/foo/(+*)': '/bar/$1', // supports regexp
'/zh-cn/changelog': '/changelog',
'/changelog':
'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG',
'/.*/_sidebar.md': '/_sidebar.md' // See #301
}
};
```
## autoHeader
- type: `Boolean`
If `loadSidebar` and `autoHeader` are both enabled, for each link in `_sidebar.md`, prepend a header to the page before converting it to html. Compare [#78](https://github.com/docsifyjs/docsify/issues/78).
```js
window.$docsify = {
loadSidebar: true,
autoHeader: true
};
```
## executeScript
- type: `Boolean`
Execute the script on the page. Only parse the first script tag([demo](themes)). If Vue is present, it is turned on by default.
```js
window.$docsify = {
executeScript: true
};
```
```markdown
## This is test
<script>
console.log(2333)
</script>
```
Note that if you are running an external script, e.g. an embedded jsfiddle demo, make sure to include the [external-script](plugins.md?id=external-script) plugin.
## noEmoji
- type: `Boolean`
Disabled emoji parse.
```js
window.$docsify = {
noEmoji: true
};
```
## mergeNavbar
- type: `Boolean`
Navbar will be merged with the sidebar on smaller screens.
```js
window.$docsify = {
mergeNavbar: true
};
```
## formatUpdated
- type: `String|Function`
We can display the file update date through **{docsify-updated<span>}</span>** variable. And format it by `formatUpdated`.
See https://github.com/lukeed/tinydate#patterns
```js
window.$docsify = {
formatUpdated: '{MM}/{DD} {HH}:{mm}',
formatUpdated: function(time) {
// ...
return time;
}
};
```
## externalLinkTarget
- type: `String`
- default: `_blank`
Target to open external links. Default `'_blank'` (new window/tab)
```js
window.$docsify = {
externalLinkTarget: '_self' // default: '_blank'
};
```
## routerMode
- type: `String`
- default: `hash`
```js
window.$docsify = {
routerMode: 'history' // default: 'hash'
};
```
## noCompileLinks
- type: `Array`
Sometimes we do not want docsify to handle our links. See [#203](https://github.com/docsifyjs/docsify/issues/203)
```js
window.$docsify = {
noCompileLinks: ['/foo', '/bar/.*']
};
```
## onlyCover
- type: `Boolean`
Only coverpage is loaded when visiting the home page.
```js
window.$docsify = {
onlyCover: false
};
```
## requestHeaders
- type: `Object`
Set the request resource headers.
```js
window.$docsify = {
requestHeaders: {
'x-token': 'xxx'
}
};
```
## ext
- type: `String`
Request file extension.
```js
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.

View file

@ -1,99 +0,0 @@
# Cover
Activate the cover feature by setting `coverpage` to **true**, compare [coverpage configuration](configuration.md#coverpage).
## Basic usage
Set `coverpage` to **true**, and create a `_coverpage.md`:
```html
<!-- index.html -->
<script>
window.$docsify = {
coverpage: true
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
```markdown
<!-- _coverpage.md -->
![logo](_media/icon.svg)
# docsify <small>3.5</small>
> A magical documentation site generator.
- Simple and lightweight (~21kB gzipped)
- No statically built html files
- Multiple themes
[GitHub](https://github.com/docsifyjs/docsify/)
[Get Started](#docsify)
```
!> A document site can have only one coverpage!
## Custom background
The background color is generated randomly by default. You can customize the background color or a background image:
```markdown
<!-- _coverpage.md -->
# docsify <small>3.5</small>
[GitHub](https://github.com/docsifyjs/docsify/)
[Get Started](#quick-start)
<!-- background image -->
![](_media/bg.png)
<!-- background color -->
![color](#f0f0f0)
```
## Coverpage as homepage
Normally, the coverpage and the homepage appear at the same time. Of course, you can also separate the coverpage by [onlyCover option](configuration.md#onlycover).
## Multiple covers
If your docs site is in more than one language, it may be useful to set multiple covers.
For example, your docs structure is like this
```text
.
└── docs
├── README.md
├── guide.md
├── _coverpage.md
└── zh-cn
├── README.md
└── guide.md
└── _coverpage.md
```
Now, you can set
```js
window.$docsify = {
coverpage: ['/', '/zh-cn/']
};
```
Or a special file name
```js
window.$docsify = {
coverpage: {
'/': 'cover.md',
'/zh-cn/': 'cover.md'
}
};
```

View file

@ -1,96 +0,0 @@
# Custom navbar
## HTML
If you need custom navigation, you can create a HTML-based navigation bar.
!> Note that documentation links begin with `#/`.
```html
<!-- index.html -->
<body>
<nav>
<a href="#/">EN</a>
<a href="#/zh-cn/">中文</a>
</nav>
<div id="app"></div>
</body>
```
## Markdown
Alternatively, you can create a custom markdown-based navigation file by setting `loadNavbar` to **true** and creating `_navbar.md`, compare [loadNavbar configuration](configuration.md#loadnavbar).
```html
<!-- index.html -->
<script>
window.$docsify = {
loadNavbar: true
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
```markdown
<!-- _navbar.md -->
* [En](/)
* [chinese](/zh-cn/)
```
!> You need to create a `.nojekyll` in `./docs` to prevent GitHub Pages from ignoring files that begin with an underscore.
`_navbar.md` is loaded from each level directory. If the current directory doesn't have `_navbar.md`, it will fall back to the parent directory. If, for example, the current path is `/guide/quick-start`, the `_navbar.md` will be loaded from `/guide/_navbar.md`.
## Nesting
You can create sub-lists by indenting items that are under a certain parent.
```markdown
<!-- _navbar.md -->
* Getting started
* [Quick start](quickstart.md)
* [Writing more pages](more-pages.md)
* [Custom navbar](custom-navbar.md)
* [Cover page](cover.md)
* Configuration
* [Configuration](configuration.md)
* [Themes](themes.md)
* [Using plugins](plugins.md)
* [Markdown configuration](markdown.md)
* [Language highlight](language-highlight.md)
```
renders as
![Nesting navbar](_images/nested-navbar.png 'Nesting navbar')
## Combining custom navbars with the emoji plugin
If you use the [emoji plugin](plugins#emoji):
```html
<!-- index.html -->
<script>
window.$docsify = {
// ...
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/emoji.min.js"></script>
```
you could, for example, use flag emojis in your custom navbar Markdown file:
```markdown
<!-- _navbar.md -->
* [:us:, :uk:](/)
* [:cn:](/zh-cn/)
```

View file

@ -1,131 +0,0 @@
# Deploy
Similar to [GitBook](https://www.gitbook.com), you can deploy files to GitHub Pages, GitLab Pages or VPS.
## GitHub Pages
There're three places to populate your docs for your Github repository:
- `docs/` folder
- master branch
- gh-pages branch
It is recommended that you save your files to the `./docs` subfolder of the `master` branch of your repository. Then select `master branch /docs folder` as your Github Pages source in your repositories' settings page.
![github pages](_images/deploy-github-pages.png)
!> You can also save files in the root directory and select `master branch`.
You'll need to place a `.nojekyll` file in the deploy location (such as `/docs` or the gh-pages branch)
## GitLab Pages
If you are deploying your master branch, include `.gitlab-ci.yml` with the following script:
?> The `.public` workaround is so `cp` doesn't also copy `public/` to itself in an infinite loop.
```YAML
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
only:
- master
```
!> You can replace script with `- cp -r docs/. public`, if `./docs` is your Docsify subfolder.
## Firebase Hosting
!> You'll need to install the Firebase CLI using `npm i -g firebase-tools` after signing into the [Firebase Console](https://console.firebase.google.com) using a Google Account.
Using Terminal determine and navigate to the directory for your Firebase Project - this could be `~/Projects/Docs` etc. From there, run `firebase init`, choosing `Hosting` from the menu (use **space** to select, **arrow keys** to change options and **enter** to confirm). Follow the setup instructions.
You should have your `firebase.json` file looking similar to this (I changed the deployment directory from `public` to `site`):
```json
{
"hosting": {
"public": "site",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
}
}
```
Once finished, build the starting template by running `docsify init ./site` (replacing site with the deployment directory you determined when running `firebase init` - public by default). Add/edit the documentation, then run `firebase deploy` from the base project directory.
## VPS
Try following nginx config.
```nginx
server {
listen 80;
server_name your.domain.com;
location / {
alias /path/to/dir/of/docs/;
index index.html;
}
}
```
## Netlify
1. Login to your [Netlify](https://www.netlify.com/) account.
2. In the [dashboard](https://app.netlify.com/) page, click **New site from Git**.
3. Choose a repository where you store your docs, leave the **Build Command** area blank, fill in the Publish directory area with the directory of your `index.html`, for example it should be docs if you populated it at `docs/index.html`.
### HTML5 router
When using the HTML5 router, you need to set up redirect rules that redirect all requests to your `index.html`, it's pretty simple when you're using Netlify, populate a `\redirects` file in the docs directory and you're all set:
```sh
/* /index.html 200
```
## AWS Amplify
1. Set the routerMode in the Docsify project `index.html` to *history* mode.
```html
<script>
window.$docsify = {
loadSidebar: true,
routerMode: 'history'
}
</script>
```
2. Login to your [AWS Console](https://aws.amazon.com).
3. Go to the [AWS Amplify Dashboard](https://aws.amazon.com/amplify).
4. Choose the **Deploy** route to setup your project.
5. When prompted, keep the build settings empty if you're serving your docs within the root directory. If you're serving your docs from a different directory, customise your amplify.yml
```yml
version: 0.1
frontend:
phases:
build:
commands:
- echo "Nothing to build"
artifacts:
baseDirectory: /docs
files:
- '**/*'
cache:
paths: []
```
6. Add the following Redirect rules in their displayed order.
| Source address | Target address | Type |
|----------------|----------------|---------------|
| /<*>.md | /<*>.md | 200 (Rewrite) |
| /<*> | /index.html | 200 (Rewrite) |

View file

@ -1,81 +0,0 @@
# Embed files
With docsify 4.6 it is now possible to embed any type of file.
You can embed these files as video, audio, iframes, or code blocks, and even Markdown files can even be embedded directly into the document.
For example, here embedded a Markdown file. You only need to do this:
```markdown
[filename](_media/example.md ':include')
```
Then the content of `example.md` will be displayed directly here
[filename](_media/example.md ':include')
You can check the original content for [example.md](_media/example.md ':ignore').
Normally, this will compiled into a link, but in docsify, if you add `:include` it will be embedded.
## Embedded file type
Currently, file extension are automatically recognized and embedded in different ways.
This is a supported embedding type:
* **iframe** `.html`, `.htm`
* **markdown** `.markdown`, `.md`
* **audio** `.mp3`
* **video** `.mp4`, `.ogg`
* **code** other file extension
Of course, you can force the specified. For example, you want to Markdown file as code block embedded.
```markdown
[filename](_media/example.md ':include :type=code')
```
You will get it
[filename](_media/example.md ':include :type=code')
## Embedded code fragments
Sometimes you don't want to embed a whole file. Maybe because you need just a few lines but you want to compile and test the file in CI.
```markdown
[filename](_media/example.js ':include :type=code :fragment=demo')
```
In your code file you need to surround the fragment between `/// [demo]` lines (before and after the fragment).
Alternatively you can use `### [demo]`.
Example:
[filename](_media/example.js ':include :type=code :fragment=demo')
## Tag attribute
If you embed the file as `iframe`, `audio` and `video`, then you may need to set the attributes of these tags.
```markdown
[cinwell website](https://cinwell.com ':include :type=iframe width=100% height=400px')
```
[cinwell website](https://cinwell.com ':include :type=iframe width=100% height=400px')
Did you see it? You only need to write directly. You can check [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) for these attributes.
## The code block highlight
Embedding any type of source code file, you can specify the highlighted language or automatically identify.
```markdown
[](_media/example.html ':include :type=code text')
```
⬇️
[](_media/example.html ':include :type=code text')
?> How to set highlight? You can see [here](language-highlight.md).

View file

@ -1,145 +0,0 @@
# Doc helper
docsify extends Markdown syntax to make your documents more readable.
## important content
Important content like:
```markdown
!> **Time** is money, my friend!
```
is rendered as:
!> **Time** is money, my friend!
## General tips
General tips like:
```markdown
?> _TODO_ unit test
```
are rendered as:
?> _TODO_ unit test
## Ignore to compile link
Some time we will put some other relative path to the link, you have to need to tell docsify you don't need to compile this link. For example
```md
[link](/demo/)
```
It will be compiled to `<a href="/#/demo/">link</a>` and will be loaded `/demo/README.md`. Maybe you want to jump to `/demo/index.html`.
Now you can do that
```md
[link](/demo/ ':ignore')
```
You will get `<a href="/demo/">link</a>`html. Do not worry, you can still set title for link.
```md
[link](/demo/ ':ignore title')
<a href="/demo/" title="title">link</a>
```
## Set target attribute for link
```md
[link](/demo ':target=_blank')
[link](/demo2 ':target=_self')
```
## Disable link
```md
[link](/demo ':disabled')
```
## Github Task Lists
```md
- [ ] foo
- bar
- [x] baz
- [] bam <~ not working
- [ ] bim
- [ ] lim
```
- [ ] foo
- bar
- [x] baz
- [] bam <~ not working
- [ ] bim
- [ ] lim
## Image resizing
```md
![logo](https://docsify.js.org/_media/icon.svg ':size=50x100')
![logo](https://docsify.js.org/_media/icon.svg ':size=100')
<!-- Support percentage -->
![logo](https://docsify.js.org/_media/icon.svg ':size=10%')
```
![logo](https://docsify.js.org/_media/icon.svg ':size=50x100')
![logo](https://docsify.js.org/_media/icon.svg ':size=100')
![logo](https://docsify.js.org/_media/icon.svg ':size=10%')
## Customise ID for headings
```md
### 你好,世界! :id=hello-world
```
## Markdown in html tag
You need to insert a space between the html and markdown content.
This is useful for rendering markdown content in the details element.
```markdown
<details>
<summary>Self-assessment (Click to expand)</summary>
- Abc
- Abc
</details>
```
<details>
<summary>Self-assessment (Click to expand)</summary>
- Abc
- Abc
</details>
Or markdown content can be wrapped in html tag.
```markdown
<div style='color: red'>
- listitem
- listitem
- listitem
</div>
```
<div style='color: red'>
- Abc
- Abc
</div>

View file

@ -1,104 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify</title>
<link rel="icon" href="_media/favicon.ico">
<meta name="google-site-verification" content="6t0LoIeFksrjF4c9sqUEsVXiQNxLp2hgoqo0KryT-sE" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="keywords" content="doc,docs,documentation,gitbook,creator,generator,github,jekyll,github-pages">
<title>docsify - A magical documentation site generator.</title>
<meta name="description" content="A magical documentation generator.">
<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="//unpkg.com/docsify/lib/themes/vue.css" title="vue">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/dark.css" title="dark" disabled>
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css" title="buble" disabled>
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/pure.css" title="pure" disabled>
<script src="//unpkg.com/docsify-plugin-codefund/index.js"></script>
<style>
nav.app-nav li ul {
min-width: 100px;
}
</style>
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
</head>
<body>
<div id="app">Loading ...</div>
<script>
window.$docsify = {
alias: {
'.*?/awesome': 'https://raw.githubusercontent.com/docsifyjs/awesome-docsify/master/README.md',
'.*?/changelog': 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG.md',
'/.*/_navbar.md': '/_navbar.md',
'/zh-cn/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-zh/master/$1',
'/de-de/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-de/master/$1',
'/ru/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-ru/master/$1',
'/es/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-es/master/$1'
},
auto2top: true,
coverpage: true,
executeScript: true,
loadSidebar: true,
loadNavbar: true,
mergeNavbar: true,
maxLevel: 4,
subMaxLevel: 2,
ga: 'UA-106147152-1',
matomo: {
host: '//matomo.thunderwave.de',
id: 6
},
name: 'docsify',
search: {
noData: {
'/de-de/': 'Keine Ergebnisse!',
'/zh-cn/': '没有结果!',
'/': 'No results!'
},
paths: 'auto',
placeholder: {
'/de-de/': 'Suche',
'/zh-cn/': '搜索',
'/': 'Search'
}
},
formatUpdated: '{MM}/{DD} {HH}:{mm}',
plugins: [
function (hook, vm) {
hook.beforeEach(function (html) {
if (/githubusercontent\.com/.test(vm.route.file)) {
url = vm.route.file
.replace('raw.githubusercontent.com', 'github.com')
.replace(/\/master/, '/blob/master')
} else {
url = 'https://github.com/docsifyjs/docsify/blob/master/docs/' + vm.route.file
}
var editHtml = '[:memo: Edit Document](' + url + ')\n'
return editHtml
+ html
+ '\n\n----\n\n'
+ '<a href="https://docsify.js.org" target="_blank" style="color: inherit; font-weight: normal; text-decoration: none;">Powered by docsify</a>'
})
},
DocsifyCodefund.create('fae1f9a4-870c-4c25-b8e0-c80464f7a95c')
]
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/matomo.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-nginx.min.js"></script>
<script>
((window.gitter = {}).chat = {}).options = {
room: 'docsifyjs/Lobby'
};
</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
<nav>
<a href="#/">En</a>
<a href="#/zh-cn">中文</a>
</nav>
<div id="app"></div>
</body>
<script
src="//unpkg.com/docsify/lib/docsify.min.js"
data-repo="qingwei-li/docsify"
data-max-level="3"
data-sidebar-toggle
data-router></script>
</html>

View file

@ -1,11 +0,0 @@
# language highlight
**docsify** uses [Prism](https://github.com/PrismJS/prism) to highlight code blocks in your pages. By default it only supports CSS, JavaScript and HTML. You can make **Prism** load additional languages:
```html
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-php.min.js"></script>
```
?> Check the [component files](https://github.com/PrismJS/prism/tree/gh-pages/components) list for more options.

View file

@ -1,56 +0,0 @@
# Markdown configuration
**docsify** uses [marked](https://github.com/markedjs/marked) as its Markdown parser. You can customize how it renders your Markdown content to HTML by customizing `renderer`:
```js
window.$docsify = {
markdown: {
smartypants: true,
renderer: {
link: function() {
// ...
}
}
}
}
```
?> Configuration Options Reference [marked documentation](https://marked.js.org/#/USING_ADVANCED.md)
Even you can completely customize the parsing rules.
```js
window.$docsify = {
markdown: function(marked, renderer) {
// ...
return marked
}
}
```
## Supports mermaid
```js
// Import mermaid
// <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.css">
// <script src="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
var num = 0;
mermaid.initialize({ startOnLoad: false });
window.$docsify = {
markdown: {
renderer: {
code: function(code, lang) {
if (lang === "mermaid") {
return (
'<div class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + "</div>"
);
}
return this.origin.code.apply(this, arguments);
}
}
}
}
```

View file

@ -1,125 +0,0 @@
# More pages
If you need more pages, you can simply create more markdown files in your docsify directory. If you create a file named `guide.md`, then it is accessible via `/#/guide`.
For example, the directory structure is as follows:
```text
.
└── docs
├── README.md
├── guide.md
└── zh-cn
├── README.md
└── guide.md
```
Matching routes
```text
docs/README.md => http://domain.com
docs/guide.md => http://domain.com/guide
docs/zh-cn/README.md => http://domain.com/zh-cn/
docs/zh-cn/guide.md => http://domain.com/zh-cn/guide
```
## Sidebar
In order to have sidebar, then you can create your own `_sidebar.md` (see [this documentation's sidebar](https://github.com/docsifyjs/docsify/blob/master/docs/_sidebar.md) for an example):
First, you need to set `loadSidebar` to **true**. Details are available in the [configuration paragraph](configuration.md#loadsidebar).
```html
<!-- index.html -->
<script>
window.$docsify = {
loadSidebar: true
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
Create the `_sidebar.md`:
```markdown
<!-- docs/_sidebar.md -->
* [Home](/)
* [Guide](guide.md)
```
You need to create a `.nojekyll` in `./docs` to prevent GitHub Pages from ignoring files that begin with an underscore.
## Nested Sidebars
You may want the sidebar to update with only navigation to reflect the current directory. This can be done by adding a `_sidebar.md` file to each folder.
`_sidebar.md` is loaded from each level directory. If the current directory doesn't have `_sidebar.md`, it will fall back to the parent directory. If, for example, the current path is `/guide/quick-start`, the `_sidebar.md` will be loaded from `/guide/_sidebar.md`.
You can specify `alias` to avoid unnecessary fallback.
```html
<script>
window.$docsify = {
loadSidebar: true,
alias: {
'/.*/_sidebar.md': '/_sidebar.md'
}
}
</script>
```
!> You can create a `README.md` file in a subdirectory to use it as the landing page for the route.
## Set Page Titles from Sidebar Selection
A page's `title` tag is generated from the _selected_ sidebar item name. For better SEO, you can customize the title by specifying a string after the filename.
```markdown
<!-- docs/_sidebar.md -->
* [Home](/)
* [Guide](guide.md "The greatest guide in the world")
```
## Table of Contents
Once you've created `_sidebar.md`, the sidebar content is automatically generated based on the headers in the markdown files.
A custom sidebar can also automatically generate a table of contents by setting a `subMaxLevel`, compare [subMaxLevel configuration](configuration.md#submaxlevel).
```html
<!-- index.html -->
<script>
window.$docsify = {
loadSidebar: true,
subMaxLevel: 2
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
## Ignoring Subheaders
When `subMaxLevel` is set, each header is automatically added to the table of contents by default. If you want to ignore a specific header, add `{docsify-ignore}` to it.
```markdown
# Getting Started
## Header {docsify-ignore}
This header won't appear in the sidebar table of contents.
```
To ignore all headers on a specific page, you can use `{docsify-ignore-all}` on the first header of the page.
```markdown
# Getting Started {docsify-ignore-all}
## Header
This header won't appear in the sidebar table of contents.
```
Both `{docsify-ignore}` and `{docsify-ignore-all}` will not be rendered on the page when used.

View file

@ -1,197 +0,0 @@
# List of Plugins
## Full text search
By default, the hyperlink on the current page is recognized and the content is saved in `localStorage`. You can also specify the path to the files.
```html
<script>
window.$docsify = {
search: 'auto', // default
search : [
'/', // => /README.md
'/guide', // => /guide.md
'/get-started', // => /get-started.md
'/zh-cn/', // => /zh-cn/README.md
],
// complete configuration parameters
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: [], // or 'auto'
placeholder: 'Type to search',
// Localization
placeholder: {
'/zh-cn/': '搜索',
'/': 'Type to search'
},
noData: 'No Results!',
// Localization
noData: {
'/zh-cn/': '找不到结果',
'/': 'No Results'
},
// Headline depth, 1 - 6
depth: 2,
hideOtherSidebarContent: false, // whether or not to hide other sidebar content
// To avoid search index collision
// between multiple websites under the same domain
namespace: 'website-1',
}
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
```
## Google Analytics
Install the plugin and configure the track id.
```html
<script>
window.$docsify = {
ga: 'UA-XXXXX-Y'
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script>
```
Configure by `data-ga`.
```html
<script src="//unpkg.com/docsify/lib/docsify.min.js" data-ga="UA-XXXXX-Y"></script>
<script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script>
```
## emoji
The default is to support parsing emoji. For example `:100:` will be parsed to :100:. But it is not precise because there is no matching non-emoji string. If you need to correctly parse the emoji string, you need install this plugin.
```html
<script src="//unpkg.com/docsify/lib/plugins/emoji.min.js"></script>
```
## External Script
If the script on the page is an external one (imports a js file via `src` attribute), you'll need this plugin to make it work.
```html
<script src="//unpkg.com/docsify/lib/plugins/external-script.min.js"></script>
```
## Zoom image
Medium's image zoom. Based on [medium-zoom](https://github.com/francoischalifour/medium-zoom).
```html
<script src="//unpkg.com/docsify/lib/plugins/zoom-image.min.js"></script>
```
Exclude the special image
```markdown
![](image.png ":no-zoom")
```
## Edit on github
Add `Edit on github` button on every pages. Provided by [@njleonzhang](https://github.com/njleonzhang), check [document](https://github.com/njleonzhang/docsify-edit-on-github)
## Demo code with instant preview and jsfiddle integration
With this plugin, sample code can be rendered on the page instantly, so that the readers can see the preview immediately.
When readers expand the demo box, the source code and description are shown there. if they click the button `Try in Jsfiddle`,
`jsfiddle.net` will be open with the code of this sample, which allow readers to revise the code and try on their own.
[Vue](https://njleonzhang.github.io/docsify-demo-box-vue/) and [React](https://njleonzhang.github.io/docsify-demo-box-react/) are both supported.
## Copy to Clipboard
Add a simple `Click to copy` button to all preformatted code blocks to effortlessly allow users to copy example code from your docs. Provided by [@jperasmus](https://github.com/jperasmus)
```html
<script src="//unpkg.com/docsify-copy-code"></script>
```
See [here](https://github.com/jperasmus/docsify-copy-code/blob/master/README.md) for more details.
## Disqus
Disqus comments. https://disqus.com/
```html
<script>
window.$docsify = {
disqus: 'shortname'
}
</script>
<script src="//unpkg.com/docsify/lib/plugins/disqus.min.js"></script>
```
## Gitalk
[Gitalk](https://github.com/gitalk/gitalk) is a modern comment component based on Github Issue and Preact.
```html
<link rel="stylesheet" href="//unpkg.com/gitalk/dist/gitalk.css">
<script src="//unpkg.com/docsify/lib/plugins/gitalk.min.js"></script>
<script src="//unpkg.com/gitalk/dist/gitalk.min.js"></script>
<script>
const gitalk = new Gitalk({
clientID: 'Github Application Client ID',
clientSecret: 'Github Application Client Secret',
repo: 'Github repo',
owner: 'Github repo owner',
admin: ['Github repo collaborators, only these guys can initialize github issues'],
// facebook-like distraction free mode
distractionFreeMode: false
})
</script>
```
## Pagination
Pagination for docsify. By [@imyelo](https://github.com/imyelo)
```html
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
```
## codefund
a [plugin](https://github.com/njleonzhang/docsify-plugin-codefund) to make it easy to join up [codefund](https://codefund.io/)
> codefund is formerly known as "codesponsor"
```
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
window.$docsify = {
plugins: [
DocsifyCodefund.create('xxxx-xxx-xxx') // change to your codefund id
]
}
```
## Tabs
A docsify.js plugin for displaying tabbed content from markdown.
- [Documentation & Demos](https://jhildenbiddle.github.io/docsify-tabs)
Provided by [@jhildenbiddle](https://github.com/jhildenbiddle/docsify-tabs).
## More plugins
See [awesome-docsify](awesome?id=plugins)

View file

@ -1,115 +0,0 @@
# Offline Mode
[Progressive Web Apps](https://developers.google.com/web/progressive-web-apps/) (PWA) are experiences that combine the best of the web with the best of apps. We can enhance our website with service workers to work **offline** or on low-quality networks.
It is also very easy to use it.
## Create serviceWorker
Create a `sw.js` file in your documents root directory and copy the following code:
*sw.js*
```js
/* ===========================================================
* docsify sw.js
* ===========================================================
* Copyright 2016 @huxpro
* Licensed under Apache 2.0
* Register service worker.
* ========================================================== */
const RUNTIME = 'docsify'
const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'unpkg.com'
]
// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)
// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol
// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}
/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})
/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', event => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then(resp => resp.clone())
// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If theres nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch(_ => cached), cached])
.then(resp => resp || fetched)
.catch(_ => { /* eat any errors */ })
)
// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open(RUNTIME)])
.then(([response, cache]) => response.ok && cache.put(event.request, response))
.catch(_ => { /* eat any errors */ })
)
}
})
```
## Register
Now, register it in your `index.html`. It only works on some modern browsers, so we need to judge:
*index.html*
```html
<script>
if (typeof navigator.serviceWorker !== 'undefined') {
navigator.serviceWorker.register('sw.js')
}
</script>
```
## Enjoy it
Release your website and start experiencing magical offline feature. :ghost: You can turn off Wi-Fi and refresh the current site to experience it.

View file

@ -1,94 +0,0 @@
# Quick start
It is recommended to install `docsify-cli` globally, which helps initializing and previewing the website locally.
```bash
npm i docsify-cli -g
```
## Initialize
If you want to write the documentation in the `./docs` subdirectory, you can use the `init` command.
```bash
docsify init ./docs
```
## Writing content
After the `init` is complete, you can see the file list in the `./docs` subdirectory.
* `index.html` as the entry file
* `README.md` as the home page
* `.nojekyll` prevents GitHub Pages from ignoring files that begin with an underscore
You can easily update the documentation in `./docs/README.md`, of course you can add [more pages](more-pages.md).
## Preview your site
Run the local server with `docsify serve`. You can preview your site in your browser on `http://localhost:3000`.
```bash
docsify serve docs
```
?> For more use cases of `docsify-cli`, head over to the [docsify-cli documentation](https://github.com/docsifyjs/docsify-cli).
## Manual initialization
If you don't like `npm` or have trouble installing the tool, you can manually create `index.html`:
```html
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
//...
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
</body>
</html>
```
If you installed python on your system, you can easily use it to run a static server to preview your site.
```bash
cd docs && python -m SimpleHTTPServer 3000
```
## Loading dialog
If you want, you can show a loading dialog before docsify starts to render your documentation:
```html
<!-- index.html -->
<div id="app">Please wait...</div>
```
You should set the `data-app` attribute if you changed `el`:
```html
<!-- index.html -->
<div data-app id="main">Please wait...</div>
<script>
window.$docsify = {
el: '#main'
}
</script>
```
Compare [el configuration](configuration.md#el).

View file

@ -1,124 +0,0 @@
# Server-Side Rendering
See https://docsify.now.sh
Repo in https://github.com/docsifyjs/docsify-ssr-demo
## Why SSR?
- Better SEO
- Feeling cool
## Quick start
Install `now` and `docsify-cli` in your project.
```bash
npm i now docsify-cli -D
```
Edit `package.json`. If the documentation in `./docs` subdirectory.
```json
{
"name": "my-project",
"scripts": {
"start": "docsify start . -c ssr.config.js",
"deploy": "now -p"
},
"files": [
"docs"
],
"docsify": {
"config": {
"basePath": "https://docsify.js.org/",
"loadSidebar": true,
"loadNavbar": true,
"coverpage": true,
"name": "docsify"
}
}
}
```
!> The `basePath` just like webpack `publicPath`. We can use local or remote files.
We can preview in the local to see if it works.
```bash
npm start
# open http://localhost:4000
```
Publish it!
```bash
now -p
```
Now, You have a support for SSR the docs site.
## Custom template
You can provide a template for entire page's HTML. such as
```html
<!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="//unpkg.com/docsify/themes/vue.css" title="vue">
</head>
<body>
<!--inject-app-->
<!--inject-config-->
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-nginx.min.js"></script>
</body>
</html>
```
The template should contain these comments for rendered app content.
- `<!--inject-app-->`
- `<!--inject-config-->`
## Configuration
You can configure it in a special config file, or `package.json`.
```js
module.exports = {
template: './ssr.html',
maxAge: 60 * 60 * 1000, // lru-cache config
config: {
// docsify config
}
}
```
## Deploy for your VPS
You can run `docsify start` directly on your Node server, or write your own server app with `docsify-server-renderer`.
```js
var Renderer = require('docsify-server-renderer')
var readFileSync = require('fs').readFileSync
// init
var renderer = new Renderer({
template: readFileSync('./docs/index.template.html', 'utf-8'),
config: {
name: 'docsify',
repo: 'docsifyjs/docsify'
}
})
renderer.renderToString(url)
.then(html => {})
.catch(err => {})
```

View file

@ -1,60 +0,0 @@
# Themes
There are currently three themes available. Copy [Vue](//vuejs.org) and [buble](//buble.surge.sh) website custom theme and [@liril-net](https://github.com/liril-net) contribution to the theme of the black style.
```html
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/dark.css">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/pure.css">
```
!> Compressed files are available in `/lib/themes/`.
```html
<!-- compressed -->
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/dark.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/pure.css">
```
If you have any ideas or would like to develop a new theme, you are welcome to submit a [pull request](https://github.com/docsifyjs/docsify/pulls).
#### Click to preview
<div class="demo-theme-preview">
<a data-theme="vue">vue.css</a>
<a data-theme="buble">buble.css</a>
<a data-theme="dark">dark.css</a>
<a data-theme="pure">pure.css</a>
</div>
<style>
.demo-theme-preview a {
padding-right: 10px;
}
.demo-theme-preview a:hover {
cursor: pointer;
text-decoration: underline;
}
</style>
<script>
var preview = Docsify.dom.find('.demo-theme-preview');
var themes = Docsify.dom.findAll('[rel="stylesheet"]');
preview.onclick = function (e) {
var title = e.target.getAttribute('data-theme')
themes.forEach(function (theme) {
theme.disabled = theme.title !== title
});
};
</script>
## Other themes
- [docsify-themeable](https://jhildenbiddle.github.io/docsify-themeable/#/) A delightfully simple theme system for docsify.

View file

@ -1,99 +0,0 @@
# Compatible with Vue
You can write Vue components directly in the Markdown file, and it will be parsed. You can use this feature to write vue demo and documentation together.
## Basic usage
Load the Vue in `./index.html`.
```html
<script src="//unpkg.com/vue"></script>
<script src="//unpkg.com/docsify"></script>
<!-- Or use the compressed files -->
<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
Then you can immediately write Vue code at Markdown file. `new Vue({ el: '#main' })` script is executed by default to create instance.
*README.md*
````markdown
# Vue guide
`v-for` usage.
```html
<ul>
<li v-for="i in 10">{{ i }}</li>
</ul>
```
<ul>
<li v-for="i in 10">{{ i }}</li>
</ul>
````
You can manually initialize a Vue instance.
*README.md*
```markdown
# Vue demo
<div id="main">hello {{ msg }}</div>
<script>
new Vue({
el: '#main',
data: { msg: 'Vue' }
})
</script>
```
!> In a Markdown file, only the script within the first script tag is executed.
## Combine Vuep to write playground
[Vuep](https://github.com/QingWei-Li/vuep) is a component for rendering Vue components with live editor and preview. Supports Vue component spec and JSX.
*index.html*
```html
<!-- Inject CSS file -->
<link rel="stylesheet" href="//unpkg.com/vuep/dist/vuep.css">
<!-- Inject JavaScript file -->
<script src="//unpkg.com/vue"></script>
<script src="//unpkg.com/vuep"></script>
<script src="//unpkg.com/docsify"></script>
<!-- or use the compressed files -->
<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/vuep/dist/vuep.min.js"></script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
```
*README.md*
```markdown
# Vuep
<vuep template="#example"></vuep>
<script v-pre type="text/x-template" id="example">
<template>
<div>Hello, {{ name }}!</div>
</template>
<script>
module.exports = {
data: function () {
return { name: 'Vue' }
}
}
</script>
</script>
```
?> Example Refer to the [Vuep documentation](https://qingwei-li.github.io/vuep/).

View file

@ -1,111 +0,0 @@
# Write a plugin
A plugin is simply a function that takes `hook` as an argument. The hook supports handling of asynchronous tasks.
## Full configuration
```js
window.$docsify = {
plugins: [
function(hook, vm) {
hook.init(function() {
// Called when the script starts running, only trigger once, no arguments,
});
hook.beforeEach(function(content) {
// Invoked each time before parsing the Markdown file.
// ...
return content;
});
hook.afterEach(function(html, next) {
// Invoked each time after the Markdown file is parsed.
// beforeEach and afterEach support asynchronous。
// ...
// call `next(html)` when task is done.
next(html);
});
hook.doneEach(function() {
// Invoked each time after the data is fully loaded, no arguments,
// ...
});
hook.mounted(function() {
// Called after initial completion. Only trigger once, no arguments.
});
hook.ready(function() {
// Called after initial completion, no arguments.
});
}
]
};
```
!> You can get internal methods through `window.Docsify`. Get the current instance through the second argument.
## Example
#### footer
Add footer component in each pages.
```js
window.$docsify = {
plugins: [
function(hook) {
var footer = [
'<hr/>',
'<footer>',
'<span><a href="https://github.com/QingWei-Li">cinwell</a> &copy;2017.</span>',
'<span>Proudly published with <a href="https://github.com/docsifyjs/docsify" target="_blank">docsify</a>.</span>',
'</footer>'
].join('');
hook.afterEach(function(html) {
return html + footer;
});
}
]
};
```
### Edit Button
```js
window.$docsify = {
plugins: [
function(hook, vm) {
hook.beforeEach(function(html) {
var url =
'https://github.com/docsifyjs/docsify/blob/master/docs/' +
vm.route.file;
var editHtml = '[📝 EDIT DOCUMENT](' + url + ')\n';
return (
editHtml +
html +
'\n----\n' +
'Last modified {docsify-updated} ' +
editHtml
);
});
}
]
};
```
## Tips
### Get docsify version
```
console.log(window.Docsify.version)
```
Current version: <span id='tip-version'>loading</span>
<script>
document.getElementById('tip-version').innerText = Docsify.version
</script>

223
docs/zh-cn.md Normal file
View file

@ -0,0 +1,223 @@
# docsify
> 无需构建快速生成文档页
## 特性
- 无需构建,写完 markdown 直接发布
- 支持自定义主题
- 容易使用并且轻量
## 快速上手
### 创建项目
新建一个空项目,接着创建一个 `docs` 目录并进入到 docs 目录下
```shell
mkdir my-project && cd my-project
mkdir docs && cd docs
```
### 创建入口文件
创建一个 `404.html` 文件,内容为
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify"></script>
</html>
```
新建 `README.md` 文件,作为主页面
```
# Title
## balabala
```
### 部署!
将项目 `push` 到 GitHub 仓库后到设置页面开启 **GitHub Pages** 功能,选择 `docs/` 选项
![image](https://cloud.githubusercontent.com/assets/7565692/20639058/e65e6d22-b3f3-11e6-9b8b-6309c89826f2.png)
## 命令行工具
方便快速创建文档目录,会读取项目的 `package.json` 里的选项作为 docsify 的配置,支持本地预览。
### 安装
```shell
npm i docsify-cli -g
```
### 初始化文档
默认初始化在当前目录,推荐将文档放在 `docs` 目录下
```shell
docsify init docs
```
### 启动本地服务
启动一个 server 方便预览,打开 http://localhost:3000
```shell
docsify serve docs
```
更多选项参考 [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
## 主题
目前提供 vue.css 和 buble.css直接修改 `404.html` 里的 cdn 地址即可
```html
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
```
压缩版
```html
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
```
## 更多功能
### 多页面
`README.md` 作为主页面,如果需要其他页面,直接在文档目录下创建对应的 `*.md` 文件,例如创建一个 `guide.md` 那么对应的路由就是 `/guide`
### 导航
导航需要自己写在 `404.html` 文件里,效果参考本文档
```html
<nav>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
</nav>
```
### CDN
目前可用的 CDN 有 [UNPKG](unpkg.com/docsify),如果觉得访问较慢可以将文件放到 Pages 的目录下。
### 配置参数
#### repo
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
```html
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
```
#### max-level
目录最大展开层级,默认值为 6
```html
<script src="//unpkg.com/docsify" data-max-level="6"></script>
```
#### el
替换节点元素,默认为 `#app`
```html
<script src="//unpkg.com/docsify" data-el="#app"></script>
```
#### sidebar-toggle
Sidebar 开关按钮
```html
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
设置后 TOC 功能将不可用,适合导航较多的文档,`data-sidebar` 传入全局变量名。
![image](https://cloud.githubusercontent.com/assets/7565692/20647425/de5ab1c2-b4ce-11e6-863a-135868f2f9b4.png)
```html
<script>
window.sidebar = [
{ slug: '/', title: 'Home' },
{
slug: '/pageA',
title: 'page A',
children: [
{ slug: '/pageA/childrenB', title: 'children B' }
]
},
{ slug: '/PageC', title: 'Page C' }
]
</script>
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
```
#### load-sidebar
读取侧边栏配置文件,如果配置,默认加载当前目录下的 `_sidebar.md`。如果文件不存在,会显示 TOC 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
```html
<script src="/lib/docsify.js" data-load-sidebar></script>
```
你可以指定侧边栏文件名
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
`_sidebar.md` 的内容可以是这样的
```markdown
- [Home](/)
- [Installation](/installation)
- Essentials
- [Getting Started](/getting-started)
- [Dynamic Route Matching](/dynamic-matching)
- [Nested Routes](/nested-routes)
- [Programmatic Navigation](/navigation)
- [Named Routes](/named-routes)
- [Named Views](/named-views)
- [Redirect and Alias](/redirect-and-alias)
- [HTML5 History Mode](/history-mode)
```
#### load-navbar
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
```html
<script src="/lib/docsify.js" data-load-navbar></script>
```
你可以指定导航栏文件名
```html
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
`_navbar.md` 的内容可以是这样
```markdown
- [en](/)
- [中文](/zh-cn)
```
当然也支持二级列表,将生成一个下拉列表
```markdown
- [download](/download)
- language
- [en](/)
- [中文](/zh-cn)
```
### router
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
```html
<script src="/lib/docsify.js" data-router></script>
```

View file

@ -1,84 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/themes/vue.css" title="vue">
<link rel="stylesheet" href="/themes/dark.css" title="dark" disabled>
<link rel="stylesheet" href="/themes/buble.css" title="buble" disabled>
<style>
nav.app-nav li ul {
min-width: 100px;
}
</style>
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
alias: {
'.*?/awesome': 'https://raw.githubusercontent.com/docsifyjs/awesome-docsify/master/README.md',
'.*?/changelog': 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG.md',
'/.*/_navbar.md': '/_navbar.md',
'/zh-cn/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-zh/master/$1',
'/de-de/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-de/master/$1',
'/ru/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-ru/master/$1',
'/es/(.*)': 'https://raw.githubusercontent.com/docsifyjs/docs-es/master/$1'
},
auto2top: true,
basePath: '/docs/',
coverpage: true,
executeScript: true,
loadSidebar: true,
loadNavbar: true,
mergeNavbar: true,
maxLevel: 4,
subMaxLevel: 2,
name: 'docsify',
search: {
noData: {
'/de-de/': 'Keine Ergebnisse!',
'/zh-cn/': '没有结果!',
'/': 'No results!'
},
paths: 'auto',
placeholder: {
'/de-de/': 'Suche',
'/zh-cn/': '搜索',
'/': 'Search'
}
},
formatUpdated: '{MM}/{DD} {HH}:{mm}',
plugins: [
function (hook, vm) {
hook.beforeEach(function (html) {
if (/githubusercontent\.com/.test(vm.route.file)) {
url = vm.route.file
.replace('raw.githubusercontent.com', 'github.com')
.replace(/\/master/, '/blob/master')
} else {
url = 'https://github.com/docsifyjs/docsify/blob/master/docs/' + vm.route.file
}
var editHtml = '[:memo: Edit Document](' + url + ')\n'
return editHtml
+ html
+ '\n\n----\n\n'
+ '<a href="https://docsify.js.org" target="_blank" style="color: inherit; font-weight: normal; text-decoration: none;">Powered by docsify</a>'
})
},
]
}
</script>
<script src="/lib/docsify.js"></script>
<script src="/lib/plugins/search.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-nginx.min.js"></script>
</body>
</html>

View file

@ -1,7 +0,0 @@
{
"lerna": "2.0.0-rc.5",
"packages": [
"packages/*"
],
"version": "0.0.0"
}

2533
lib/docsify.js Normal file

File diff suppressed because it is too large Load diff

2
lib/docsify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
lib/themes/buble.css Normal file

File diff suppressed because one or more lines are too long

1
lib/themes/pure.css Normal file

File diff suppressed because one or more lines are too long

1
lib/themes/vue.css Normal file

File diff suppressed because one or more lines are too long

8914
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,78 +1,21 @@
{
"name": "docsify",
"version": "4.9.4",
"version": "1.0.3",
"description": "A magical documentation generator.",
"author": {
"name": "qingwei-li",
"email": "cinwell.li@gmail.com",
"url": "https://github.com/QingWei-Li"
},
"homepage": "https://docsify.js.org",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/docsifyjs/docsify.git"
},
"main": "lib/docsify.js",
"unpkg": "lib/docsify.min.js",
"files": [
"lib",
"src",
"themes"
],
"scripts": {
"bootstrap": "npm i && lerna bootstrap && npm run build:ssr",
"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": "mocha test/*/**",
"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 -p 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"
"build": "rm -rf lib themes && node build/build.js && mkdir lib/themes && mkdir themes && node build/build-css.js",
"dev": "node app.js & nodemon -w src --exec 'npm run build'",
"test": "eslint src test"
},
"dependencies": {
"marked": "^0.5.1",
"medium-zoom": "^0.4.0",
"opencollective": "^1.0.3",
"prismjs": "^1.15.0",
"tinydate": "^1.0.0",
"tweezer.js": "^1.4.0"
},
"devDependencies": {
"autoprefixer-stylus": "^0.14.0",
"chai": "^4.2.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-xo-space": "^0.18.0",
"esm": "^3.1.4",
"jsdom": "^13.2.0",
"lerna": "^2.5.1",
"live-server": "^1.2.1",
"mocha": "^5.2.0",
"npm-run-all": "^4.1.5",
"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-uglify": "^2.0.1",
"stylus": "^0.54.5"
"repository": {
"type": "git",
"url": "https://github.com/QingWei-Li/docsify.git"
},
"keywords": [
"doc",
@ -81,9 +24,26 @@
"creator",
"generator"
],
"collective": {
"type": "opencollective",
"url": "https://opencollective.com/docsify",
"logo": "https://docsify.js.org/_media/icon.svg"
"author": "qingwei-li <cinwell.li@gmail.com> (https://github.com/QingWei-Li)",
"homepage": "https://docsify.js.org",
"license": "MIT",
"devDependencies": {
"cssnano": "^3.8.1",
"eslint": "^3.10.2",
"eslint-config-vue": "^2.0.1",
"eslint-plugin-vue": "^1.0.0",
"nodemon": "^1.11.0",
"postcss": "^5.2.6",
"postcss-salad": "^1.0.5",
"rollup": "^0.36.3",
"rollup-plugin-buble": "^0.14.0",
"rollup-plugin-commonjs": "^5.0.5",
"rollup-plugin-node-resolve": "^2.0.0",
"rollup-plugin-uglify": "^1.0.1",
"serve-static": "^1.11.1"
},
"dependencies": {
"marked": "^0.3.6",
"prismjs": "^1.5.1"
}
}

View file

@ -1,4 +0,0 @@
build.js
node_modules
*.log
.git

View file

@ -1,46 +0,0 @@
# docsify-server-renderer
## Install
```bash
yarn add docsify-server-renderer
```
## Usage
```js
var Renderer = require('docsify-server-renderer')
var readFileSync = require('fs').readFileSync
// init
var renderer = new Renderer({
template: readFileSync('./docs/index.template.html', 'utf-8').,
config: {
name: 'docsify',
repo: 'docsifyjs/docsify'
}
})
renderer.renderToString(url)
.then(html => {})
.catch(err => {})
```
*index.template.html*
```html
<!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="//unpkg.com/docsify/themes/buble.css" title="buble" disabled>
</head>
<body>
<!--inject-app-->
<!--inject-config-->
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
</body>
</html>
```

View file

@ -1,181 +0,0 @@
import * as tpl from '../../src/core/render/tpl'
import fetch from 'node-fetch'
import {AbstractHistory} from '../../src/core/router/history/abstract'
import {Compiler} from '../../src/core/render/compiler'
import {isAbsolutePath} from '../../src/core/router/util'
import {readFileSync} from 'fs'
import {resolve, basename} from 'path'
import resolvePathname from 'resolve-pathname'
import debug from 'debug'
import {prerenderEmbed} from '../../src/core/render/embed'
function cwd(...args) {
return resolve(process.cwd(), ...args)
}
function mainTpl(config) {
let html = `<nav class="app-nav${
config.repo ? '' : ' no-badge'
}"><!--navbar--></nav>`
if (config.repo) {
html += tpl.corner(config.repo)
}
if (config.coverpage) {
html += tpl.cover()
}
html += tpl.main(config)
return html
}
export default class Renderer {
constructor({template, config, cache}) {
this.html = template
this.config = config = Object.assign({}, config, {
routerMode: 'history'
})
this.cache = cache
this.router = new AbstractHistory(config)
this.compiler = new Compiler(config, this.router)
this.router.getCurrentPath = () => this.url
this._renderHtml(
'inject-config',
`<script>window.$docsify = ${JSON.stringify(config)}</script>`
)
this._renderHtml('inject-app', mainTpl(config))
this.template = this.html
}
_getPath(url) {
const file = this.router.getFile(url)
return isAbsolutePath(file) ? file : cwd(`./${file}`)
}
async renderToString(url) {
this.url = url = this.router.parse(url).path
const {loadSidebar, loadNavbar, coverpage} = this.config
const mainFile = this._getPath(url)
this._renderHtml('main', await this._render(mainFile, 'main'))
if (loadSidebar) {
const name = loadSidebar === true ? '_sidebar.md' : loadSidebar
const sidebarFile = this._getPath(resolve(url, `./${name}`))
this._renderHtml('sidebar', await this._render(sidebarFile, 'sidebar'))
}
if (loadNavbar) {
const name = loadNavbar === true ? '_navbar.md' : loadNavbar
const navbarFile = this._getPath(resolve(url, `./${name}`))
this._renderHtml('navbar', await this._render(navbarFile, 'navbar'))
}
if (coverpage) {
let path = null
if (typeof coverpage === 'string') {
if (url === '/') {
path = coverpage
}
} else if (Array.isArray(coverpage)) {
path = coverpage.indexOf(url) > -1 && '_coverpage.md'
} else {
const cover = coverpage[url]
path = cover === true ? '_coverpage.md' : cover
}
const coverFile = this._getPath(resolve(url, `./${path}`))
this._renderHtml('cover', await this._render(coverFile), 'cover')
}
const html = this.html
this.html = this.template
return html
}
_renderHtml(match, content) {
this.html = this.html.replace(new RegExp(`<!--${match}-->`, 'g'), content)
return this.html
}
async _render(path, type) {
let html = await this._loadFile(path)
const {subMaxLevel, maxLevel} = this.config
let tokens
switch (type) {
case 'sidebar':
html =
this.compiler.sidebar(html, maxLevel) +
`<script>window.__SUB_SIDEBAR__ = ${JSON.stringify(
this.compiler.subSidebar(subMaxLevel)
)}</script>`
break
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:
html = this.compiler.compile(html)
break
}
return html
}
async _loadFile(filePath) {
debug('docsify')(`load > ${filePath}`)
let content
try {
if (isAbsolutePath(filePath)) {
const res = await fetch(filePath)
if (!res.ok) {
throw Error()
}
content = await res.text()
this.lock = 0
} else {
content = await readFileSync(filePath, 'utf8')
this.lock = 0
}
return content
} catch (e) {
this.lock = this.lock || 0
if (++this.lock > 10) {
this.lock = 0
return
}
const fileName = basename(filePath)
const result = await this._loadFile(
resolvePathname(`../${fileName}`, filePath)
)
return result
}
}
}
Renderer.version = '__VERSION__'

View file

@ -1,41 +0,0 @@
{
"lockfileVersion": 1,
"dependencies": {
"debug": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw="
},
"encoding": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s="
},
"iconv-lite": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
"integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA=="
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node-fetch": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz",
"integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ=="
},
"resolve-pathname": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.1.0.tgz",
"integrity": "sha1-6DWIAbhrg7F1YNTjw4LXrvIQCUQ="
}
},
"version": "4.9.4"
}

View file

@ -1,23 +0,0 @@
{
"name": "docsify-server-renderer",
"version": "4.9.4",
"description": "docsify server renderer",
"author": {
"name": "qingwei-li",
"email": "cinwell.li@gmail.com",
"url": "https://github.com/QingWei-Li"
},
"homepage": "https://docsify.js.org",
"license": "MIT",
"repository": "docsifyjs/docsify",
"main": "build.js",
"scripts": {
"test": "echo 'hello'"
},
"dependencies": {
"debug": "^2.6.8",
"docsify": "^4.8.0",
"node-fetch": "^1.7.0",
"resolve-pathname": "^2.1.0"
}
}

View file

@ -1,55 +0,0 @@
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: 'docsifyjs/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/docsifyjs/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)

View file

@ -1,71 +0,0 @@
import {merge, hyphenate, isPrimitive, hasOwn} from './util/core'
export default function () {
const config = merge(
{
el: '#app',
repo: '',
maxLevel: 6,
subMaxLevel: 0,
loadSidebar: null,
loadNavbar: null,
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false,
name: '',
themeColor: '',
nameLink: window.location.pathname,
autoHeader: false,
executeScript: null,
noEmoji: false,
ga: '',
ext: '.md',
mergeNavbar: false,
formatUpdated: '',
externalLinkTarget: '_blank',
routerMode: 'hash',
noCompileLinks: [],
relativePath: false
},
window.$docsify
)
const script =
document.currentScript ||
[].slice
.call(document.getElementsByTagName('script'))
.filter(n => /docsify\./.test(n.src))[0]
if (script) {
for (const prop in config) {
if (hasOwn.call(config, prop)) {
const val = script.getAttribute('data-' + hyphenate(prop))
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 = ''
}
}
window.$docsify = config
return config
}

View file

@ -1,26 +0,0 @@
import {isMobile} from '../util/env'
import {body, on} from '../util/dom'
import * as sidebar from './sidebar'
import {scrollIntoView} from './scroll'
export function eventMixin(proto) {
proto.$resetEvents = function () {
scrollIntoView(this.route.path, this.route.query.id)
if (this.config.loadNavbar) {
sidebar.getAndActive(this.router, 'nav')
}
}
}
export function initEvent(vm) {
// Bind toggle button
sidebar.btn('button.sidebar-toggle', vm.router)
sidebar.collapse('.sidebar', vm.router)
// Bind sticky effect
if (vm.config.coverpage) {
!isMobile && on('scroll', sidebar.sticky)
} else {
body.classList.add('sticky')
}
}

View file

@ -1,148 +0,0 @@
import {isMobile} from '../util/env'
import * as dom from '../util/dom'
import Tweezer from 'tweezer.js'
const nav = {}
let hoverOver = false
let scroller = null
let enableScrollEvent = true
let coverHeight = 0
function scrollTo(el) {
if (scroller) {
scroller.stop()
}
enableScrollEvent = false
scroller = new Tweezer({
start: window.pageYOffset,
end: el.getBoundingClientRect().top + window.pageYOffset,
duration: 500
})
.on('tick', v => window.scrollTo(0, v))
.on('done', () => {
enableScrollEvent = true
scroller = null
})
.begin()
}
function highlight(path) {
if (!enableScrollEvent) {
return
}
const sidebar = dom.getNode('.sidebar')
const anchors = dom.findAll('.anchor')
const wrap = dom.find(sidebar, '.sidebar-nav')
let active = dom.find(sidebar, 'li.active')
const doc = document.documentElement
const top = ((doc && doc.scrollTop) || document.body.scrollTop) - coverHeight
let last
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i]
if (node.offsetTop > top) {
if (!last) {
last = node
}
break
} else {
last = node
}
}
if (!last) {
return
}
const li = nav[getNavKey(decodeURIComponent(path), last.getAttribute('data-id'))]
if (!li || li === active) {
return
}
active && active.classList.remove('active')
li.classList.add('active')
active = li
// Scroll into view
// https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297
if (!hoverOver && dom.body.classList.contains('sticky')) {
const height = sidebar.clientHeight
const curOffset = 0
const cur = active.offsetTop + active.clientHeight + 40
const isInView =
active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height
const notThan = cur - curOffset < height
const top = isInView ? wrap.scrollTop : notThan ? curOffset : cur - height
sidebar.scrollTop = top
}
}
function getNavKey(path, id) {
return `${path}?id=${id}`
}
export function scrollActiveSidebar(router) {
const cover = dom.find('.cover.show')
coverHeight = cover ? cover.offsetHeight : 0
const sidebar = dom.getNode('.sidebar')
let lis = []
if (sidebar != null) {
lis = dom.findAll(sidebar, 'li')
}
for (let i = 0, len = lis.length; i < len; i += 1) {
const li = lis[i]
const a = li.querySelector('a')
if (!a) {
continue
}
let href = a.getAttribute('href')
if (href !== '/') {
const {query: {id}, path} = router.parse(href)
if (id) {
href = getNavKey(path, id)
}
}
if (href) {
nav[decodeURIComponent(href)] = li
}
}
if (isMobile) {
return
}
const path = router.getCurrentPath()
dom.off('scroll', () => highlight(path))
dom.on('scroll', () => highlight(path))
dom.on(sidebar, 'mouseover', () => {
hoverOver = true
})
dom.on(sidebar, 'mouseleave', () => {
hoverOver = false
})
}
export function scrollIntoView(path, id) {
if (!id) {
return
}
const section = dom.find('#' + id)
section && scrollTo(section)
const li = nav[getNavKey(path, id)]
const sidebar = dom.getNode('.sidebar')
const active = dom.find(sidebar, 'li.active')
active && active.classList.remove('active')
li && li.classList.add('active')
}
const scrollEl = dom.$.scrollingElement || dom.$.documentElement
export function scroll2Top(offset = 0) {
scrollEl.scrollTop = offset === true ? 0 : Number(offset)
}

View file

@ -1,92 +0,0 @@
import {isMobile} from '../util/env'
import * as dom from '../util/dom'
const title = dom.$.title
/**
* Toggle button
*/
export function btn(el) {
const toggle = _ => dom.body.classList.toggle('close')
el = dom.getNode(el)
if (el == null) {
return
}
dom.on(el, 'click', e => {
e.stopPropagation()
toggle()
})
isMobile &&
dom.on(
dom.body,
'click',
_ => dom.body.classList.contains('close') && toggle()
)
}
export function collapse(el) {
el = dom.getNode(el)
if (el == null) {
return
}
dom.on(el, 'click', ({target}) => {
if (
target.nodeName === 'A' &&
target.nextSibling &&
target.nextSibling.classList.contains('app-sub-sidebar')
) {
dom.toggleClass(target.parentNode, 'collapse')
}
})
}
export function sticky() {
const cover = dom.getNode('section.cover')
if (!cover) {
return
}
const coverHeight = cover.getBoundingClientRect().height
if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) {
dom.toggleClass(dom.body, 'add', 'sticky')
} else {
dom.toggleClass(dom.body, 'remove', 'sticky')
}
}
/**
* Get and active link
* @param {object} router
* @param {string|element} el
* @param {Boolean} isParent acitve parent
* @param {Boolean} autoTitle auto set title
* @return {element}
*/
export function getAndActive(router, el, isParent, autoTitle) {
el = dom.getNode(el)
let links = []
if (el != null) {
links = dom.findAll(el, 'a')
}
const hash = decodeURI(router.toURL(router.getCurrentPath()))
let target
links.sort((a, b) => b.href.length - a.href.length).forEach(a => {
const href = a.getAttribute('href')
const node = isParent ? a.parentNode : a
if (hash.indexOf(href) === 0 && !target) {
target = a
dom.toggleClass(node, 'add', 'active')
} else {
dom.toggleClass(node, 'remove', 'active')
}
})
if (autoTitle) {
dom.$.title = target ? (target.title || `${target.innerText} - ${title}`) : title
}
return target
}

View file

@ -1,67 +0,0 @@
import progressbar from '../render/progressbar'
import {noop, hasOwn} from '../util/core'
const cache = {}
/**
* Simple ajax get
* @param {string} url
* @param {boolean} [hasBar=false] has progress bar
* @return { then(resolve, reject), abort }
*/
export function get(url, hasBar = false, headers = {}) {
const xhr = new XMLHttpRequest()
const on = function () {
xhr.addEventListener.apply(xhr, arguments)
}
const cached = cache[url]
if (cached) {
return {then: cb => cb(cached.content, cached.opt), abort: noop}
}
xhr.open('GET', url)
for (const i in headers) {
if (hasOwn.call(headers, i)) {
xhr.setRequestHeader(i, headers[i])
}
}
xhr.send()
return {
then: function (success, error = noop) {
if (hasBar) {
const id = setInterval(
_ =>
progressbar({
step: Math.floor(Math.random() * 5 + 1)
}),
500
)
on('progress', progressbar)
on('loadend', evt => {
progressbar(evt)
clearInterval(id)
})
}
on('error', error)
on('load', ({target}) => {
if (target.status >= 400) {
error(target)
} else {
const result = (cache[url] = {
content: target.response,
opt: {
updatedAt: xhr.getResponseHeader('last-modified')
}
})
success(result.content, result.opt)
}
})
},
abort: _ => xhr.readyState !== 4 && xhr.abort()
}
}

View file

@ -1,235 +0,0 @@
import {get} from './ajax'
import {callHook} from '../init/lifecycle'
import {getParentPath, stringifyQuery} from '../router/util'
import {noop} from '../util/core'
import {getAndActive} from '../event/sidebar'
function loadNested(path, qs, file, next, vm, first) {
path = first ? path : path.replace(/\/$/, '')
path = getParentPath(path)
if (!path) {
return
}
get(
vm.router.getFile(path + file) + qs,
false,
vm.config.requestHeaders
).then(next, _ => loadNested(path, qs, file, next, vm))
}
export function fetchMixin(proto) {
let last
const abort = () => last && last.abort && last.abort()
const request = (url, hasbar, requestHeaders) => {
abort()
last = get(url, true, requestHeaders)
return last
}
const get404Path = (path, config) => {
const {notFoundPage, ext} = config
const defaultPath = '_404' + (ext || '.md')
let key
let path404
switch (typeof notFoundPage) {
case 'boolean':
path404 = defaultPath
break
case 'string':
path404 = notFoundPage
break
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)
cb()
}
// 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
req.then(
(text, opt) =>
this._renderMain(
text,
opt,
this._loadSideAndNav(path, qs, loadSidebar, cb)
),
_ => {
this._fetchFallbackPage(file, qs, cb) || this._fetch404(file, qs, cb)
}
)
// Load nav
loadNavbar &&
loadNested(
path,
qs,
loadNavbar,
text => this._renderNav(text),
this,
true
)
}
proto._fetchCover = function () {
const {coverpage, requestHeaders} = this.config
const query = this.route.query
const root = getParentPath(this.route.path)
if (coverpage) {
let path = null
const routePath = this.route.path
if (typeof coverpage === 'string') {
if (routePath === '/') {
path = coverpage
}
} else if (Array.isArray(coverpage)) {
path = coverpage.indexOf(routePath) > -1 && '_coverpage'
} else {
const cover = coverpage[routePath]
path = cover === true ? '_coverpage' : cover
}
const coverOnly = Boolean(path) && this.config.onlyCover
if (path) {
path = this.router.getFile(root + path)
this.coverIsHTML = /\.html$/g.test(path)
get(path + stringifyQuery(query, ['id']), false, requestHeaders).then(
text => this._renderCover(text, coverOnly)
)
} else {
this._renderCover(null, coverOnly)
}
return coverOnly
}
}
proto.$fetch = function (cb = noop) {
const done = () => {
callHook(this, 'doneEach')
cb()
}
const onlyCover = this._fetchCover()
if (onlyCover) {
done()
} else {
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
// Server-Side Rendering
if (vm.rendered) {
const activeEl = getAndActive(vm.router, '.sidebar-nav', true, true)
if (loadSidebar && activeEl) {
activeEl.parentNode.innerHTML += window.__SUB_SIDEBAR__
}
vm._bindEventOnRendered(activeEl)
vm.$resetEvents()
callHook(vm, 'doneEach')
callHook(vm, 'ready')
} else {
vm.$fetch(_ => callHook(vm, 'ready'))
}
}

View file

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

View file

@ -1,41 +0,0 @@
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) {
const state = document.readyState
if (state === 'complete' || state === 'interactive') {
return setTimeout(callback, 0)
}
document.addEventListener('DOMContentLoaded', callback)
}
function Docsify() {
this._init()
}
const proto = Docsify.prototype
initMixin(proto)
routerMixin(proto)
renderMixin(proto)
fetchMixin(proto)
eventMixin(proto)
/**
* Global API
*/
initGlobalAPI()
/**
* Run Docsify
*/
ready(_ => new Docsify())

View file

@ -1,27 +0,0 @@
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'
export function initMixin(proto) {
proto._init = function () {
const vm = this
vm.config = config()
initLifecycle(vm) // Init hooks
initPlugin(vm) // Install plugins
callHook(vm, 'init')
initRouter(vm) // Add router
initRender(vm) // Render base DOM
initEvent(vm) // Bind events
initFetch(vm) // Fetch data
callHook(vm, 'mounted')
}
}
function initPlugin(vm) {
[].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm._lifecycle, vm))
}

View file

@ -1,45 +0,0 @@
import {noop} from '../util/core'
export function initLifecycle(vm) {
const hooks = [
'init',
'mounted',
'beforeEach',
'afterEach',
'doneEach',
'ready'
]
vm._hooks = {}
vm._lifecycle = {}
hooks.forEach(hook => {
const arr = (vm._hooks[hook] = [])
vm._lifecycle[hook] = fn => arr.push(fn)
})
}
export function callHook(vm, hook, data, next = noop) {
const queue = vm._hooks[hook]
const 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 ? data : result
step(index + 1)
}
} else {
step(index + 1)
}
}
step(0)
}

View file

@ -1,397 +0,0 @@
import marked from 'marked'
import Prism from 'prismjs'
import {helper as helperTpl, tree as treeTpl} from './tpl'
import {genTree} from './gen-tree'
import {slugify} from './slugify'
import {emojify} from './emojify'
import {isAbsolutePath, getPath, getParentPath} from '../router/util'
import {isFn, merge, cached, isPrimitive} from '../util/core'
// See https://github.com/PrismJS/prism/pull/1367
import 'prismjs/components/prism-markup-templating'
const cachedLinks = {}
export function getAndRemoveConfig(str = '') {
const config = {}
if (str) {
str = str
.replace(/^'/, '')
.replace(/'$/, '')
.replace(/(?:^|\s):([\w-]+)=?([\w-]+)?/g, (m, key, value) => {
config[key] = (value && value.replace(/&quot;/g, '')) || true
return ''
})
.trim()
}
return {str, config}
}
const compileMedia = {
markdown(url) {
return {
url
}
},
mermaid(url) {
return {
url
}
},
iframe(url, title) {
return {
html: `<iframe src="${url}" ${title || 'width=100% height=400'}></iframe>`
}
},
video(url, title) {
return {
html: `<video src="${url}" ${title || 'controls'}>Not Support</video>`
}
},
audio(url, title) {
return {
html: `<audio src="${url}" ${title || 'controls'}>Not Support</audio>`
}
},
code(url, title) {
let lang = url.match(/\.(\w+)$/)
lang = title || (lang && lang[1])
if (lang === 'md') {
lang = 'markdown'
}
return {
url,
lang
}
}
}
export class Compiler {
constructor(config, router) {
this.config = config
this.router = router
this.cacheTree = {}
this.toc = []
this.cacheTOC = {}
this.linkTarget = config.externalLinkTarget || '_blank'
this.contentBase = router.getBasePath()
const renderer = this._initRenderer()
let compile
const mdConf = config.markdown || {}
if (isFn(mdConf)) {
compile = mdConf(marked, renderer)
} else {
marked.setOptions(
merge(mdConf, {
renderer: merge(renderer, mdConf.renderer)
})
)
compile = marked
}
this._marked = compile
this.compile = text => {
let isCached = true
const result = cached(_ => {
isCached = false
let html = ''
if (!text) {
return text
}
if (isPrimitive(text)) {
html = compile(text)
} else {
html = compile.parser(text)
}
html = config.noEmoji ? html : emojify(html)
slugify.clear()
return html
})(text)
const curFileName = this.router.parse().file
if (isCached) {
this.toc = this.cacheTOC[curFileName]
} else {
this.cacheTOC[curFileName] = [...this.toc]
}
return result
}
}
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,
getParentPath(this.router.getCurrentPath()),
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 (/\.mmd/.test(href)) {
type = 'mermaid'
} 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
}
embed.fragment = config.fragment
return embed
}
}
_matchNotCompileLink(link) {
const links = this.config.noCompileLinks || []
for (var i = 0; i < links.length; i++) {
const n = links[i]
const re = cachedLinks[n] || (cachedLinks[n] = new RegExp(`^${n}$`))
if (re.test(link)) {
return link
}
}
}
_initRenderer() {
const renderer = new marked.Renderer()
const {linkTarget, router, contentBase} = this
const _self = this
const origin = {}
/**
* Render anchor tag
* @link https://github.com/markedjs/marked#overriding-renderer-methods
*/
origin.heading = renderer.heading = function (text, level) {
let {str, config} = getAndRemoveConfig(text)
const nextToc = {level, title: str}
if (/{docsify-ignore}/g.test(str)) {
str = str.replace('{docsify-ignore}', '')
nextToc.title = str
nextToc.ignoreSubHeading = true
}
if (/{docsify-ignore-all}/g.test(str)) {
str = str.replace('{docsify-ignore-all}', '')
nextToc.title = str
nextToc.ignoreAllSubs = true
}
const slug = slugify(config.id || str)
const url = router.toURL(router.getCurrentPath(), {id: slug})
nextToc.slug = url
_self.toc.push(nextToc)
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${str}</span></a></h${level}>`
}
// Highlight code
origin.code = renderer.code = function (code, lang = '') {
code = code.replace(/@DOCSIFY_QM@/g, '`')
const hl = Prism.highlight(
code,
Prism.languages[lang] || Prism.languages.markup
)
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${hl}</code></pre>`
}
origin.link = renderer.link = function (href, title = '', text) {
let attrs = ''
const {str, config} = getAndRemoveConfig(title)
title = str
if (
!isAbsolutePath(href) &&
!_self._matchNotCompileLink(href) &&
!config.ignore
) {
if (href === _self.config.homepage) {
href = 'README'
}
href = router.toURL(href, null, router.getCurrentPath())
} else {
attrs += href.indexOf('mailto:') === 0 ? '' : ` target="${linkTarget}"`
}
if (config.target) {
attrs += ' target=' + config.target
}
if (config.disabled) {
attrs += ' disabled'
href = 'javascript:void(0)'
}
if (title) {
attrs += ` title="${title}"`
}
return `<a href="${href}"${attrs}>${text}</a>`
}
origin.paragraph = renderer.paragraph = function (text) {
let result
if (/^!&gt;/.test(text)) {
result = helperTpl('tip', text)
} else if (/^\?&gt;/.test(text)) {
result = helperTpl('warn', text)
} else {
result = `<p>${text}</p>`
}
return result
}
origin.image = renderer.image = function (href, title, text) {
let url = href
let attrs = ''
const {str, config} = getAndRemoveConfig(title)
title = str
if (config['no-zoom']) {
attrs += ' data-no-zoom'
}
if (title) {
attrs += ` title="${title}"`
}
const size = config.size
if (size) {
const sizes = size.split('x')
if (sizes[1]) {
attrs += 'width=' + sizes[0] + ' height=' + sizes[1]
} else {
attrs += 'width=' + sizes[0]
}
}
if (!isAbsolutePath(href)) {
url = getPath(contentBase, getParentPath(router.getCurrentPath()), href)
}
return `<img src="${url}"data-origin="${href}" alt="${text}"${attrs}>`
}
origin.list = renderer.list = function (body, ordered, start) {
const isTaskList = /<li class="task-list-item">/.test(body.split('class="task-list"')[0])
const isStartReq = start && start > 1
const tag = ordered ? 'ol' : 'ul'
const tagAttrs = [
(isTaskList ? 'class="task-list"' : ''),
(isStartReq ? `start="${start}"` : '')
].join(' ').trim()
return `<${tag} ${tagAttrs}>${body}</${tag}>`
}
origin.listitem = renderer.listitem = function (text) {
const isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text)
const html = isTaskItem ? `<li class="task-list-item"><label>${text}</label></li>` : `<li>${text}</li>`
return html
}
renderer.origin = origin
return renderer
}
/**
* Compile sidebar
*/
sidebar(text, level) {
const {toc} = this
const currentPath = this.router.getCurrentPath()
let html = ''
if (text) {
html = this.compile(text)
} else {
for (let i = 0; i < toc.length; i++) {
if (toc[i].ignoreSubHeading) {
const deletedHeaderLevel = toc[i].level
toc.splice(i, 1)
// Remove headers who are under current header
for (let j = i; deletedHeaderLevel < toc[j].level && j < toc.length; j++) {
toc.splice(j, 1) && j-- && i++
}
i--
}
}
const tree = this.cacheTree[currentPath] || genTree(toc, level)
html = treeTpl(tree, '<ul>{inner}</ul>')
this.cacheTree[currentPath] = tree
}
return html
}
/**
* Compile sub sidebar
*/
subSidebar(level) {
if (!level) {
this.toc = []
return
}
const currentPath = this.router.getCurrentPath()
const {cacheTree, toc} = this
toc[0] && toc[0].ignoreAllSubs && toc.splice(0)
toc[0] && toc[0].level === 1 && toc.shift()
for (let i = 0; i < toc.length; i++) {
toc[i].ignoreSubHeading && toc.splice(i, 1) && i--
}
const tree = cacheTree[currentPath] || genTree(toc, level)
cacheTree[currentPath] = tree
this.toc = []
return treeTpl(tree)
}
article(text) {
return this.compile(text)
}
/**
* Compile cover page
*/
cover(text) {
const cacheToc = this.toc.slice()
const html = this.compile(text)
this.toc = cacheToc.slice()
return html
}
}

View file

@ -1,115 +0,0 @@
import {get} from '../fetch/ajax'
import {merge} from '../util/core'
const cached = {}
function walkFetchEmbed({embedTokens, compile, fetch}, cb) {
let token
let step = 0
let count = 1
if (!embedTokens.length) {
return cb({})
}
while ((token = embedTokens[step++])) {
const next = (function (token) {
return text => {
let embedToken
if (text) {
if (token.embed.type === 'markdown') {
embedToken = compile.lexer(text)
} else if (token.embed.type === 'code') {
if (token.embed.fragment) {
const fragment = token.embed.fragment
const pattern = new RegExp(`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`)
text = ((text.match(pattern) || [])[1] || '').trim()
}
embedToken = compile.lexer(
'```' +
token.embed.lang +
'\n' +
text.replace(/`/g, '@DOCSIFY_QM@') +
'\n```\n'
)
} else if (token.embed.type === 'mermaid') {
embedToken = [
{type: 'html', text: `<div class="mermaid">\n${text}\n</div>`}
]
embedToken.links = {}
} else {
embedToken = [{type: 'html', text}]
embedToken.links = {}
}
}
cb({token, embedToken})
if (++count >= step) {
cb({})
}
}
})(token)
if (token.embed.url) {
if (process.env.SSR) {
fetch(token.embed.url).then(next)
} else {
get(token.embed.url).then(next)
}
} else {
next(token.embed.html)
}
}
}
export function prerenderEmbed({compiler, raw = '', fetch}, done) {
let hit = cached[raw]
if (hit) {
const copy = hit.slice()
copy.links = hit.links
return done(copy)
}
const compile = compiler._marked
let tokens = compile.lexer(raw)
const embedTokens = []
const linkRE = compile.InlineLexer.rules.link
const links = tokens.links
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) {
embedTokens.push({
index,
embed
})
}
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)
}
})
}

View file

@ -1,12 +0,0 @@
import {inBrowser} from '../util/env'
function replace(m, $1) {
return '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
}
export function emojify(text) {
return text
.replace(/<(pre|template|code)[^>]*?>[\s\S]+?<\/(pre|template|code)>/g, m => m.replace(/:/g, '__colon__'))
.replace(/:(\w+?):/ig, (inBrowser && window.emojify) || replace)
.replace(/__colon__/g, ':')
}

View file

@ -1,28 +0,0 @@
/**
* 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) {
const headlines = []
const last = {}
toc.forEach(headline => {
const level = headline.level || 1
const len = level - 1
if (level > maxLevel) {
return
}
if (last[len]) {
last[len].children = (last[len].children || []).concat(headline)
} else {
headlines.push(headline)
}
last[level] = headline
})
return headlines
}

View file

@ -1,276 +0,0 @@
import * as dom from '../util/dom'
import * as tpl from './tpl'
import cssVars from '../util/polyfill/css-vars'
import tinydate from 'tinydate'
import {callHook} from '../init/lifecycle'
import {Compiler} from './compiler'
import {getAndActive, sticky} from '../event/sidebar'
import {getPath, isAbsolutePath} from '../router/util'
import {isMobile, inBrowser} from '../util/env'
import {isPrimitive} from '../util/core'
import {scrollActiveSidebar, scroll2Top} from '../event/scroll'
import {prerenderEmbed} from './embed'
function executeScript() {
const script = dom
.findAll('.markdown-section>script')
.filter(s => !/template/.test(s.type))[0]
if (!script) {
return false
}
const code = script.innerText.trim()
if (!code) {
return false
}
setTimeout(_ => {
window.__EXECUTE_RESULT__ = new Function(code)()
}, 0)
}
function formatUpdated(html, updated, fn) {
updated =
typeof fn === 'function' ?
fn(updated) :
typeof fn === 'string' ?
tinydate(fn)(new Date(updated)) :
updated
return html.replace(/{docsify-updated}/g, updated)
}
function renderMain(html) {
if (!html) {
html = '<h1>404 - Not found</h1>'
}
this._renderTo('.markdown-section', html)
// Render sidebar with the TOC
!this.config.loadSidebar && this._renderSidebar()
// Execute script
if (
this.config.executeScript !== false &&
typeof window.Vue !== 'undefined' &&
!executeScript()
) {
setTimeout(_ => {
const vueVM = window.__EXECUTE_RESULT__
vueVM && vueVM.$destroy && vueVM.$destroy()
window.__EXECUTE_RESULT__ = new window.Vue().$mount('#main')
}, 0)
} else {
this.config.executeScript && executeScript()
}
}
function renderNameLink(vm) {
const el = dom.getNode('.app-name-link')
const nameLink = vm.config.nameLink
const path = vm.route.path
if (!el) {
return
}
if (isPrimitive(vm.config.nameLink)) {
el.setAttribute('href', nameLink)
} else if (typeof nameLink === 'object') {
const match = Object.keys(nameLink).filter(key => path.indexOf(key) > -1)[0]
el.setAttribute('href', nameLink[match])
}
}
export function renderMixin(proto) {
proto._renderTo = function (el, content, replace) {
const node = dom.getNode(el)
if (node) {
node[replace ? 'outerHTML' : 'innerHTML'] = content
}
}
proto._renderSidebar = function (text) {
const {maxLevel, subMaxLevel, loadSidebar} = this.config
this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel))
const activeEl = getAndActive(this.router, '.sidebar-nav', true, true)
if (loadSidebar && activeEl) {
activeEl.parentNode.innerHTML +=
this.compiler.subSidebar(subMaxLevel) || ''
} else {
// Reset toc
this.compiler.subSidebar()
}
// Bind event
this._bindEventOnRendered(activeEl)
}
proto._bindEventOnRendered = function (activeEl) {
const {autoHeader, auto2top} = this.config
scrollActiveSidebar(this.router)
if (autoHeader && activeEl) {
const main = dom.getNode('#main')
const firstNode = main.children[0]
if (firstNode && firstNode.tagName !== 'H1') {
const h1 = dom.create('h1')
h1.innerText = activeEl.innerText
dom.before(main, h1)
}
}
auto2top && scroll2Top(auto2top)
}
proto._renderNav = function (text) {
text && this._renderTo('nav', this.compiler.compile(text))
if (this.config.loadNavbar) {
getAndActive(this.router, 'nav')
}
}
proto._renderMain = function (text, opt = {}, next) {
if (!text) {
return renderMain.call(this, text)
}
callHook(this, 'beforeEach', text, result => {
let html
const callback = () => {
if (opt.updatedAt) {
html = formatUpdated(html, opt.updatedAt, this.config.formatUpdated)
}
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()
}
)
}
})
}
proto._renderCover = function (text, coverOnly) {
const el = dom.getNode('.cover')
dom.toggleClass(dom.getNode('main'), coverOnly ? 'add' : 'remove', 'hidden')
if (!text) {
dom.toggleClass(el, 'remove', 'show')
return
}
dom.toggleClass(el, 'add', 'show')
let html = this.coverIsHTML ? text : this.compiler.cover(text)
const m = html
.trim()
.match('<p><img.*?data-origin="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$')
if (m) {
if (m[2] === 'color') {
el.style.background = m[1] + (m[3] || '')
} else {
let path = m[1]
dom.toggleClass(el, 'add', 'has-mask')
if (!isAbsolutePath(m[1])) {
path = getPath(this.router.getBasePath(), m[1])
}
el.style.backgroundImage = `url(${path})`
el.style.backgroundSize = 'cover'
el.style.backgroundPosition = 'center center'
}
html = html.replace(m[0], '')
}
this._renderTo('.cover-main', html)
sticky()
}
proto._updateRender = function () {
// Render name link
renderNameLink(this)
}
}
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
}
const id = config.el || '#app'
const navEl = dom.find('nav') || dom.create('nav')
const el = dom.find(id)
let html = ''
let navAppendToTarget = dom.body
if (el) {
if (config.repo) {
html += tpl.corner(config.repo)
}
if (config.coverpage) {
html += tpl.cover()
}
if (config.logo) {
const isBase64 = /^data:image/.test(config.logo)
const isExternal = /(?:http[s]?:)?\/\//.test(config.logo)
const isRelative = /^\./.test(config.logo)
if (!isBase64 && !isExternal && !isRelative) {
config.logo = getPath(vm.router.getBasePath(), config.logo)
}
}
html += tpl.main(config)
// Render main app
vm._renderTo(el, html, true)
} else {
vm.rendered = true
}
if (config.mergeNavbar && isMobile) {
navAppendToTarget = dom.find('.sidebar')
} else {
navEl.classList.add('app-nav')
if (!config.repo) {
navEl.classList.add('no-badge')
}
}
// Add nav
if (config.loadNavbar) {
dom.before(navAppendToTarget, navEl)
}
if (config.themeColor) {
dom.$.head.appendChild(
dom.create('div', tpl.theme(config.themeColor)).firstElementChild
)
// Polyfll
cssVars(config.themeColor)
}
vm._updateRender()
dom.toggleClass(dom.body, 'ready')
}

View file

@ -1,41 +0,0 @@
import * as dom from '../util/dom'
let barEl
let timeId
/**
* Init progress component
*/
function init() {
const div = dom.create('div')
div.classList.add('progress')
dom.appendTo(dom.body, div)
barEl = div
}
/**
* Render progress bar
*/
export default function ({loaded, total, step}) {
let num
!barEl && init()
if (step) {
num = parseInt(barEl.style.width || 0, 10) + step
num = num > 80 ? 80 : num
} else {
num = Math.floor(loaded / total * 100)
}
barEl.style.opacity = 1
barEl.style.width = num >= 95 ? '100%' : num + '%'
if (num >= 95) {
clearTimeout(timeId)
timeId = setTimeout(_ => {
barEl.style.opacity = 0
barEl.style.width = '0%'
}, 200)
}
}

View file

@ -1,37 +0,0 @@
import {hasOwn} from '../util/core'
let cache = {}
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g
function lower(string) {
return string.toLowerCase()
}
export function slugify(str) {
if (typeof str !== 'string') {
return ''
}
let slug = str
.trim()
.replace(/[A-Z]+/g, lower)
.replace(/<[^>\d]+>/g, '')
.replace(re, '')
.replace(/\s/g, '-')
.replace(/-+/g, '-')
.replace(/^(\d)/, '_$1')
let count = cache[slug]
count = hasOwn.call(cache, slug) ? count + 1 : 0
cache[slug] = count
if (count) {
slug = slug + '-' + count
}
return slug
}
slugify.clear = function () {
cache = {}
}

View file

@ -1,101 +0,0 @@
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
}
data = data.replace(/^git\+/, '')
return (
`<a href="${data}" class="github-corner" aria-label="View source on Github">` +
'<svg viewBox="0 0 250 250" aria-hidden="true">' +
'<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>' +
'<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>' +
'<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>' +
'</svg>' +
'</a>'
)
}
/**
* Render main content
*/
export function main(config) {
const aside =
'<button class="sidebar-toggle">' +
'<div class="sidebar-toggle-button">' +
'<span></span><span></span><span></span>' +
'</div>' +
'</button>' +
'<aside class="sidebar">' +
(config.name ?
`<h1 class="app-name"><a class="app-name-link" data-nosearch>${
config.logo ?
`<img alt=${config.name} src=${config.logo}>` :
config.name
}</a></h1>` :
'') +
'<div class="sidebar-nav"><!--sidebar--></div>' +
'</aside>'
return (
(isMobile ? `${aside}<main>` : `<main>${aside}`) +
'<section class="content">' +
'<article class="markdown-section" id="main"><!--main--></article>' +
'</section>' +
'</main>'
)
}
/**
* Cover Page
*/
export function cover() {
const SL = ', 100%, 85%'
const bgc =
'linear-gradient(to left bottom, ' +
`hsl(${Math.floor(Math.random() * 255) + SL}) 0%,` +
`hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`
return (
`<section class="cover show" style="background: ${bgc}">` +
'<div class="cover-main"><!--cover--></div>' +
'<div class="mask"></div>' +
'</section>'
)
}
/**
* Render tree
* @param {Array} tree
* @param {String} tpl
* @return {String}
*/
export function tree(toc, tpl = '<ul class="app-sub-sidebar">{inner}</ul>') {
if (!toc || !toc.length) {
return ''
}
let innerHTML = ''
toc.forEach(node => {
innerHTML += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
if (node.children) {
innerHTML += tree(node.children, tpl)
}
})
return tpl.replace('{inner}', innerHTML)
}
export function helper(className, content) {
return `<p class="${className}">${content.slice(5).trim()}</p>`
}
export function theme(color) {
return `<style>:root{--theme-color: ${color};}</style>`
}

View file

@ -1,25 +0,0 @@
import {History} from './base'
import {parseQuery} from '../util'
export class AbstractHistory extends History {
constructor(config) {
super(config)
this.mode = 'abstract'
}
parse(path) {
let query = ''
const queryIndex = path.indexOf('?')
if (queryIndex >= 0) {
query = path.slice(queryIndex + 1)
path = path.slice(0, queryIndex)
}
return {
path,
file: this.getFile(path),
query: parseQuery(query)
}
}
}

View file

@ -1,86 +0,0 @@
import {
getPath,
isAbsolutePath,
stringifyQuery,
cleanPath,
replaceSlug,
resolvePath
} from '../util'
import {noop, merge} from '../../util/core'
const cached = {}
function getAlias(path, alias, last) {
const match = Object.keys(alias).filter(key => {
const re = cached[key] || (cached[key] = new RegExp(`^${key}$`))
return re.test(path) && path !== last
})[0]
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}`
}
export class History {
constructor(config) {
this.config = config
}
getBasePath() {
return this.config.basePath
}
getFile(path = this.getCurrentPath(), isRelative) {
const {config} = this
const base = this.getBasePath()
const ext = typeof config.ext === 'string' ? config.ext : '.md'
path = config.alias ? getAlias(path, config.alias) : path
path = getFileName(path, ext)
path = path === `/README${ext}` ? config.homepage || path : path
path = isAbsolutePath(path) ? path : getPath(base, path)
if (isRelative) {
path = path.replace(new RegExp(`^${base}`), '')
}
return path
}
onchange(cb = noop) {
cb()
}
getCurrentPath() {}
normalize() {}
parse() {}
toURL(path, params, currentRoute) {
const local = currentRoute && path[0] === '#'
const route = this.parse(replaceSlug(path))
route.query = merge({}, route.query, params)
path = route.path + stringifyQuery(route.query)
path = path.replace(/\.md(\?)|\.md$/, '$1')
if (local) {
const idIndex = currentRoute.indexOf('?')
path =
(idIndex > 0 ? currentRoute.substring(0, idIndex) : currentRoute) + path
}
if (this.config.relativePath && path.indexOf('/') !== 0) {
const currentDir = currentRoute.substring(0, currentRoute.lastIndexOf('/') + 1)
return cleanPath(resolvePath(currentDir + path))
}
return cleanPath('/' + path)
}
}

View file

@ -1,76 +0,0 @@
import {History} from './base'
import {noop} from '../../util/core'
import {on} from '../../util/dom'
import {parseQuery, cleanPath, replaceSlug} from '../util'
function replaceHash(path) {
const i = location.href.indexOf('#')
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path)
}
export class HashHistory extends History {
constructor(config) {
super(config)
this.mode = 'hash'
}
getBasePath() {
const path = window.location.pathname || ''
const base = this.config.basePath
return /^(\/|https?:)/g.test(base) ? base : cleanPath(path + '/' + base)
}
getCurrentPath() {
// We can't use location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = location.href
const index = href.indexOf('#')
return index === -1 ? '' : href.slice(index + 1)
}
onchange(cb = noop) {
on('hashchange', cb)
}
normalize() {
let path = this.getCurrentPath()
path = replaceSlug(path)
if (path.charAt(0) === '/') {
return replaceHash(path)
}
replaceHash('/' + path)
}
/**
* Parse the url
* @param {string} [path=location.herf]
* @return {object} { path, query }
*/
parse(path = location.href) {
let query = ''
const hashIndex = path.indexOf('#')
if (hashIndex >= 0) {
path = path.slice(hashIndex + 1)
}
const queryIndex = path.indexOf('?')
if (queryIndex >= 0) {
query = path.slice(queryIndex + 1)
path = path.slice(0, queryIndex)
}
return {
path,
file: this.getFile(path, true),
query: parseQuery(query)
}
}
toURL(path, params, currentRoute) {
return '#' + super.toURL(path, params, currentRoute)
}
}

View file

@ -1,65 +0,0 @@
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) {
super(config)
this.mode = 'history'
}
getCurrentPath() {
const base = this.getBasePath()
let path = window.location.pathname
if (base && path.indexOf(base) === 0) {
path = path.slice(base.length)
}
return (path || '/') + window.location.search + window.location.hash
}
onchange(cb = noop) {
on('click', e => {
const el = e.target.tagName === 'A' ? e.target : e.target.parentNode
if (el.tagName === 'A' && !/_blank/.test(el.target)) {
e.preventDefault()
const url = el.href
window.history.pushState({key: url}, '', url)
cb()
}
})
on('popstate', cb)
}
/**
* Parse the url
* @param {string} [path=location.href]
* @return {object} { path, query }
*/
parse(path = location.href) {
let query = ''
const queryIndex = path.indexOf('?')
if (queryIndex >= 0) {
query = path.slice(queryIndex + 1)
path = path.slice(0, queryIndex)
}
const base = getPath(location.origin)
const baseIndex = path.indexOf(base)
if (baseIndex > -1) {
path = path.slice(baseIndex + base.length)
}
return {
path,
file: this.getFile(path),
query: parseQuery(query)
}
}
}

View file

@ -1,45 +0,0 @@
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) {
proto.route = {}
}
let lastRoute = {}
function updateRender(vm) {
vm.router.normalize()
vm.route = vm.router.parse()
dom.body.setAttribute('data-page', vm.route.file)
}
export function initRouter(vm) {
const config = vm.config
const mode = config.routerMode || 'hash'
let router
if (mode === 'history' && supportsPushState) {
router = new HTML5History(config)
} else {
router = new HashHistory(config)
}
vm.router = router
updateRender(vm)
lastRoute = vm.route
router.onchange(_ => {
updateRender(vm)
vm._updateRender()
if (lastRoute.path === vm.route.path) {
vm.$resetEvents()
return
}
vm.$fetch()
lastRoute = vm.route
})
}

View file

@ -1,76 +0,0 @@
import {cached} from '../util/core'
const decode = decodeURIComponent
const encode = encodeURIComponent
export function parseQuery(query) {
const res = {}
query = query.trim().replace(/^(\?|#|&)/, '')
if (!query) {
return res
}
// Simple parse
query.split('&').forEach(function (param) {
const parts = param.replace(/\+/g, ' ').split('=')
res[parts[0]] = parts[1] && decode(parts[1])
})
return res
}
export function stringifyQuery(obj, ignores = []) {
const qs = []
for (const key in obj) {
if (ignores.indexOf(key) > -1) {
continue
}
qs.push(
obj[key] ?
`${encode(key)}=${encode(obj[key])}`.toLowerCase() :
encode(key)
)
}
return qs.length ? `?${qs.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] : ''
})
export const cleanPath = cached(path => {
return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/')
})
export const resolvePath = cached(path => {
const segments = path.replace(/^\//, '').split('/')
let resolved = []
for (let i = 0, len = segments.length; i < len; i++) {
const segment = segments[i]
if (segment === '..') {
resolved.pop()
} else if (segment !== '.') {
resolved.push(segment)
}
}
return '/' + resolved.join('/')
})
export function getPath(...args) {
return cleanPath(args.join('/'))
}
export const replaceSlug = cached(path => {
return path.replace('#', '?id=')
})

View file

@ -1,58 +0,0 @@
/**
* Create a cached version of a pure function.
*/
export function cached(fn) {
const cache = Object.create(null)
return function (str) {
const key = isPrimitive(str) ? str : JSON.stringify(str)
const hit = cache[key]
return hit || (cache[key] = fn(str))
}
}
/**
* Hyphenate a camelCase string.
*/
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) {
for (let i = 1; i < arguments.length; i++) {
const from = Object(arguments[i])
for (const key in from) {
if (hasOwn.call(from, key)) {
to[key] = from[key]
}
}
}
return to
}
/**
* Check if value is primitive
*/
export function isPrimitive(value) {
return typeof value === 'string' || typeof value === 'number'
}
/**
* Perform no operation.
*/
export function noop() {}
/**
* Check if value is function
*/
export function isFn(obj) {
return typeof obj === 'function'
}

View file

@ -1,92 +0,0 @@
import {isFn} from '../util/core'
import {inBrowser} from './env'
const cacheNode = {}
/**
* Get Node
* @param {String|Element} el
* @param {Boolean} noCache
* @return {Element}
*/
export function getNode(el, noCache = false) {
if (typeof el === 'string') {
if (typeof window.Vue !== 'undefined') {
return find(el)
}
el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el))
}
return el
}
export const $ = inBrowser && document
export const body = inBrowser && $.body
export const head = inBrowser && $.head
/**
* Find element
* @example
* find('nav') => document.querySelector('nav')
* find(nav, 'a') => nav.querySelector('a')
*/
export function find(el, node) {
return node ? el.querySelector(node) : $.querySelector(el)
}
/**
* Find all elements
* @example
* findAll('a') => [].slice.call(document.querySelectorAll('a'))
* findAll(nav, 'a') => [].slice.call(nav.querySelectorAll('a'))
*/
export function findAll(el, node) {
return [].slice.call(
node ? el.querySelectorAll(node) : $.querySelectorAll(el)
)
}
export function create(node, tpl) {
node = $.createElement(node)
if (tpl) {
node.innerHTML = tpl
}
return node
}
export function appendTo(target, el) {
return target.appendChild(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 off(el, type, handler) {
isFn(type) ?
window.removeEventListener(el, type) :
el.removeEventListener(type, handler)
}
/**
* Toggle class
*
* @example
* toggleClass(el, 'active') => el.classList.toggle('active')
* toggleClass(el, 'add', 'active') => el.classList.add('active')
*/
export function toggleClass(el, type, val) {
el && el.classList[val ? type : 'toggle'](val || type)
}
export function style(content) {
appendTo(head, create('style', content))
}

View file

@ -1,21 +0,0 @@
export const inBrowser = !process.env.SSR
export const isMobile = inBrowser && document.body.clientWidth <= 600
/**
* @see https://github.com/MoOx/pjax/blob/master/lib/is-supported.js
*/
export const supportsPushState =
inBrowser &&
(function () {
// Borrowed wholesale from https://github.com/defunkt/jquery-pjax
return (
window.history &&
window.history.pushState &&
window.history.replaceState &&
// PushState isnt reliable on iOS until 5.
!navigator.userAgent.match(
/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/
)
)
})()

View file

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

View file

@ -1,36 +0,0 @@
import * as dom from '../dom'
import {get} from '../../fetch/ajax'
function replaceVar(block, color) {
block.innerHTML = block.innerHTML.replace(
/var\(\s*--theme-color.*?\)/g,
color
)
}
export default function (color) {
// Variable support
if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) {
return
}
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
}
get(href).then(res => {
const style = dom.create('style', res)
dom.head.appendChild(style)
replaceVar(style, color)
})
}
})
}

92
src/event.js Normal file
View file

@ -0,0 +1,92 @@
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
*/
export function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) return
const anchors = document.querySelectorAll('.anchor')
const nav = {}
const lis = document.querySelectorAll('.sidebar li')
let active = null
for (let i = 0, len = lis.length; i < len; i += 1) {
const li = lis[i]
let href = li.querySelector('a').getAttribute('href')
if (href !== '/') href = href.match(/#([^#]+)$/g)[0].slice(1)
nav[href] = li
}
function highlight () {
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i].parentNode
const bcr = node.getBoundingClientRect()
if (bcr.top < 10 && bcr.bottom > 10) {
const li = nav[node.id]
if (!li || li === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
}
}
}
const dom = document.querySelector('main .content')
dom.removeEventListener('scroll', highlight)
dom.addEventListener('scroll', highlight)
highlight()
}
export function scrollIntoView () {
const id = window.location.hash.match(/#[^#\/]+$/g)
if (!id || !id.length) return
const section = document.querySelector(id[0])
if (section) section.scrollIntoView()
}
/**
* Acitve link
*/
export function activeLink (dom, activeParent) {
const host = window.location.href
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
if (!dom) return
;[].slice.call(dom.querySelectorAll('a')).forEach(node => {
if (node.href === host) {
activeParent
? node.parentNode.setAttribute('class', 'active')
: node.setAttribute('class', 'active')
} else {
activeParent
? node.parentNode.removeAttribute('class')
: node.removeAttribute('class')
}
})
}
/**
* sidebar toggle
*/
export function bindToggle (dom) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
if (!dom) return
const body = document.body
dom.addEventListener('click', () => body.classList.toggle('close'))
if (!/mobile/i.test(navigator.userAgent)) return
document.querySelector('aside').addEventListener('click', event => {
body.classList.toggle('close')
})
}

91
src/index.js Normal file
View file

@ -0,0 +1,91 @@
import { load, camel2kebab, isNil, getRoute } from './util'
import { activeLink, scrollIntoView } from './event'
import * as render from './render'
const OPTIONS = {
el: '#app',
repo: '',
maxLevel: 6,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false
}
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
// load configuration for script attribute
if (script) {
for (const prop in OPTIONS) {
const val = script.getAttribute('data-' + camel2kebab(prop))
OPTIONS[prop] = isNil(val) ? OPTIONS[prop] : (val || true)
}
if (OPTIONS.loadSidebar === true) OPTIONS.loadSidebar = '_sidebar.md'
if (OPTIONS.loadNavbar === true) OPTIONS.loadNavbar = '_navbar.md'
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
}
// load options
render.config(OPTIONS)
let cacheRoute = null
const mainRender = function (cb) {
const route = getRoute()
if (cacheRoute === route) return cb()
let wait
let basePath = cacheRoute = route
if (!/\//.test(basePath)) {
basePath = ''
} else if (basePath && !/\/$/.test(basePath)) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1]
}
// Render markdown file
load((!route || /\/$/.test(route)) ? `${route}README.md` : `${route}.md`)
.then(result => {
render.renderArticle(result)
if (OPTIONS.loadSidebar) {
if (wait === false) cb()
wait = false
} else {
cb()
}
}, _ => render.renderArticle(null))
// Render sidebar
if (OPTIONS.loadSidebar) {
load(basePath + OPTIONS.loadSidebar).then(result => {
render.renderSidebar(result)
if (wait === false) cb()
wait = false
})
}
// Render navbar
if (OPTIONS.loadNavbar) {
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar)
}
}
const Docsify = function () {
const dom = document.querySelector(OPTIONS.el) || document.body
const replace = dom !== document.body
const main = function () {
mainRender(_ => {
activeLink('aside.sidebar', true)
scrollIntoView()
})
}
// Render app
render.renderApp(dom, replace)
main()
if (OPTIONS.router) {
if (!/^#\//.test(window.location.hash)) window.location.hash = '#/'
window.addEventListener('hashchange', main)
}
}
export default Docsify()

View file

@ -1,51 +0,0 @@
const fixedPath = location.href.replace('/-/', '/#/')
if (fixedPath !== location.href) {
location.href = fixedPath
}
function install(hook, vm) {
const dom = Docsify.dom
const disqus = vm.config.disqus
if (!disqus) {
throw Error('$docsify.disqus is required')
}
hook.init(_ => {
const script = dom.create('script')
script.async = true
script.src = `https://${disqus}.disqus.com/embed.js`
script.setAttribute('data-timestamp', Number(new Date()))
dom.appendTo(dom.body, script)
})
hook.mounted(_ => {
const div = dom.create('div')
div.id = 'disqus_thread'
const main = dom.getNode('#main')
div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`
dom.appendTo(dom.find('.content'), div)
// eslint-disable-next-line
window.disqus_config = function() {
this.page.url = location.origin + '/-' + vm.route.path
this.page.identifier = vm.route.path
this.page.title = document.title
}
})
hook.doneEach(_ => {
if (typeof window.DISQUS !== 'undefined') {
window.DISQUS.reset({
reload: true,
config: function () {
this.page.url = location.origin + '/-' + vm.route.path
this.page.identifier = vm.route.path
this.page.title = document.title
}
})
}
})
}
$docsify.plugins = [].concat(install, $docsify.plugins)

Some files were not shown because too many files have changed in this diff Show more