Compare commits

...
136 Commits
Author SHA1 Message Date
qingwei.li b15b286c5c -> v1.4.1 2016-12-31 14:16:54 +08:00
qingwei.li 5ab86271c2 bump 1.4.1 2016-12-31 14:16:39 +08:00
qingwei.li 9638eee50d fix generate slug, fixed #45 2016-12-31 14:16:15 +08:00
qingwei.li 375a1dd3e1 -> v1.4.0 2016-12-31 13:47:28 +08:00
qingwei.li 3069ad3928 bump 1.4.0 2016-12-31 13:47:16 +08:00
qingwei.li b287f57c86 Add custom cover background 2016-12-31 13:40:29 +08:00
qingwei.li e932ff66b9 max-sub-level => sub-max-level 2016-12-31 11:50:30 +08:00
nsinaandcinwell.li 7a10e4aecf Readme/homepage cleanup 2016-12-31 10:22:31 +08:00
qingwei.li 41e7ef6863 Add docs 2016-12-30 18:09:13 +08:00
qingwei.li 7ce166501b Add render sub menu 2016-12-30 17:58:39 +08:00
qingwei.li b9aeb4a922 Fix scroll highlight when Vue exist 2016-12-27 23:58:26 +08:00
qingwei.li 9ac8293c0a Update docs 2016-12-26 23:47:26 +08:00
qingwei.li aa3121eca2 Bye 🎅 2016-12-25 20:59:08 +08:00
qingwei.li 0e615abbdc -> v1.3.5 2016-12-25 20:13:21 +08:00
qingwei.li cb2b191ba1 bump 1.3.5 2016-12-25 20:13:11 +08:00
qingwei.li 6adcfffba9 fix vue 2016-12-25 20:12:03 +08:00
qingwei.li f165470265 -> v1.3.4 2016-12-25 18:34:14 +08:00
qingwei.li bbb7b4a9d6 bump 1.3.4 2016-12-25 18:33:57 +08:00
qingwei.li 540095ee35 Support vuep 2016-12-25 18:33:12 +08:00
qingwei.li bd354094c0 🎄 Merry Christmas 2016-12-24 20:32:04 +08:00
qingwei.li 6e81e66441 404.dev => dev 2016-12-24 19:50:41 +08:00
qingwei.li 67f9083ff7 Remove 404.html 2016-12-24 19:50:04 +08:00
qingwei.li 383b976ddd Update docs 2016-12-24 11:33:48 +08:00
qingwei.li 54ba970552 -> v1.3.3 2016-12-23 21:47:42 +08:00
qingwei.li 16623c9301 bump 1.3.3 2016-12-23 21:47:31 +08:00
qingwei.li 668c5ca714 fix lint 2016-12-23 21:47:15 +08:00
qingwei.li d0861d7427 Fixed cover rendering timing 2016-12-23 21:46:12 +08:00
qingwei.li 97669e0d28 Add similar projects into readme 2016-12-23 09:25:30 +08:00
qingwei.li a0408b7a38 -> v1.3.2 2016-12-23 01:20:57 +08:00
qingwei.li f917da8214 bump 1.3.2 2016-12-23 01:20:47 +08:00
qingwei.li 64309beee9 Fixed render link 2016-12-23 01:20:28 +08:00
qingwei.li 4c8c0349e6 -> v1.3.1 2016-12-23 00:25:05 +08:00
qingwei.li 91b6720219 bump 1.3.1 2016-12-23 00:24:45 +08:00
qingwei.li c93ba1ea16 Fixed cover page style 2016-12-23 00:24:24 +08:00
qingwei.li 4f5a150c17 update cdn 2016-12-22 01:03:52 +08:00
qingwei.li 801df6ae3e Update changelog
Update changelog
2016-12-22 00:30:30 +08:00
qingwei.li 6c2e7dca99 -> v1.3.0 2016-12-22 00:26:23 +08:00
qingwei.li a39eddba74 bump 1.3.0 2016-12-22 00:26:06 +08:00
cinwell.liandGitHub 50addfdac6 1.3 (#38)
* Add cover page

* Update doc

* Add kbd style, resolve #37

* headling can cliked, resolve #36

* Update change log, close #35

* Update docs
2016-12-22 00:24:54 +08:00
qingwei.li b14fcf7d1c Update readme 2016-12-20 22:34:13 +08:00
qingwei.li 3b02b8fc39 Update features 2016-12-20 22:32:56 +08:00
qingwei.li 039c7a7a6f Remove donate 2016-12-20 22:19:12 +08:00
qingwei.li 0101492dd4 Update doc 2016-12-20 22:04:55 +08:00
qingwei.li 60fc73c691 update cdn 2016-12-20 21:44:02 +08:00
qingwei.li 476d49bc1f -> v1.2.0 2016-12-20 21:20:18 +08:00
qingwei.li 73456e6fac bump 1.2.0 2016-12-20 21:20:08 +08:00
cinwell.liandGitHub f9d75ab931 Feat/1.2 (#33)
* Add homepage option, fixed #30

* Add custom basePath support, resolve #31
2016-12-20 21:18:52 +08:00
qingwei.li f93f9ceb09 Add cdn 2016-12-20 10:20:56 +08:00
qingwei.li b57712dd5a Add .nojekyll 2016-12-19 23:05:47 +08:00
qingwei.li f2d894932b -> v1.1.7 2016-12-19 21:53:42 +08:00
qingwei.li 48912a0b79 bump 1.1.7 2016-12-19 21:53:25 +08:00
qingwei.li 73a193d602 Optimize progress bar 2016-12-19 21:52:33 +08:00
qingwei.li 30b6644f21 fix typo 2016-12-19 20:38:35 +08:00
qingwei.li d343ff5b21 Update badges 2016-12-18 19:43:58 +08:00
qingwei.li 3bf932a81c -> v1.1.6 2016-12-18 15:37:57 +08:00
qingwei.li c8bb66955d bump 1.1.6 2016-12-18 15:37:47 +08:00
qingwei.li e5e1e07e1a Fixed highlight sidebar using chinese ids 2016-12-18 15:37:24 +08:00
cinwell.liandGitHub 9ba989c86c Add logo (#28)
* Fix table style

* Add logo

* Update index.html

* Update doc
2016-12-18 15:30:50 +08:00
qingwei.li ab34cc97f9 -> v1.1.5 2016-12-18 10:50:37 +08:00
qingwei.li 3fbcd876ae bump 1.1.5 2016-12-18 10:50:02 +08:00
qingwei.li 3af5ca5cd4 Correct calculation of whether the mobile browser 2016-12-18 10:49:21 +08:00
qingwei.li 74ee0cf6bc Add table style 2016-12-18 10:37:34 +08:00
qingwei.li 46dd542b48 -> v1.1.4 2016-12-17 16:08:45 +08:00
qingwei.li cc7bdf5df2 bump 1.1.4 2016-12-17 15:56:55 +08:00
qingwei.li 9a1db6ed43 Fix chinese auchor link 2016-12-17 15:56:01 +08:00
qingwei.li 9d30ac7435 -> v1.1.3 2016-12-17 15:38:59 +08:00
qingwei.li f8a68b87c7 bump 1.1.3 2016-12-17 15:38:00 +08:00
qingwei.li 7dc47cc4d4 Optimize progress bar again 2016-12-17 15:37:32 +08:00
qingwei.li 7d995d8362 Update readme 2016-12-17 15:25:03 +08:00
qingwei.li 1fdfaf0b6b -> v1.1.2 2016-12-17 15:18:04 +08:00
qingwei.li fe33e2d506 bump 1.1.2 2016-12-17 15:17:20 +08:00
qingwei.li 6463dd3bae Optimize progress bar again 2016-12-17 15:14:52 +08:00
qingwei.li 299c31dff9 Fix auto2top in mobile 2016-12-17 15:08:44 +08:00
qingwei.li aa1d84b513 1.1.1 2016-12-17 09:07:15 +08:00
qingwei.li 14a4c2f77d bump 1.1.1 2016-12-17 09:01:41 +08:00
qingwei.li e58c17fdc6 Optimize progress bar 2016-12-17 09:01:21 +08:00
qingwei.li 8b719238e6 -> v1.1.0 2016-12-16 22:38:53 +08:00
qingwei.li 7f0b1089c0 bump 1.1.0 2016-12-16 22:38:44 +08:00
cinwell.liandGitHub 2610e25040 Add progress bar and auto2top (#27)
* Add progress bar

* Add abort ajax

* Remove console

* Add cache folder

* Add auto2top
2016-12-16 22:37:21 +08:00
cinwell.li ec53f1e307 Add Beerpay's badge 2016-12-15 19:11:15 +08:00
qingwei.li 670cc68a28 -> v1.0.3 2016-12-13 22:27:36 +08:00
qingwei.li 844ba3e022 bump 1.0.3 2016-12-13 22:27:26 +08:00
qingwei.li 9092b22246 Fix cache sidebar content 2016-12-13 22:26:56 +08:00
qingwei.li d175ba6913 -> v1.0.2 2016-12-13 22:12:18 +08:00
qingwei.li 2574778605 bump 1.0.2 2016-12-13 22:11:50 +08:00
cinwell.liandGitHub 44a255103c Fix/1.0.2 (#25)
* Fix regular expression, fixed #23

* Fix repeat binding events

* Add content cache

* Add changelog
2016-12-13 22:10:58 +08:00
qingwei.li 440635aeeb -> v1.0.1 2016-12-08 21:24:05 +08:00
qingwei.li a8cc8e46cd bump 1.0.1 2016-12-08 21:23:38 +08:00
qingwei.li 626227be4d Update changelog 2016-12-08 21:22:33 +08:00
qingwei.li c4f02027a8 Fix img style 2016-12-08 21:20:37 +08:00
qingwei.li 8f3eb17dbf Update doc 2016-12-08 21:18:01 +08:00
qingwei.li 61d2474202 -> v1.0.0 2016-12-08 21:13:04 +08:00
qingwei.li 41be8176a6 bump 1.0.0 2016-12-08 21:12:33 +08:00
cinwell.liandGitHub 864935bfc1 1.0 features (#21)
* feat: hash routing, close #2

* Fix router bug

* Remove console

* Add hash router docs

* Improved scrolling on mobile

* Add change log

* Use hash router
2016-12-08 21:11:18 +08:00
qingwei.li b977715d42 Add Snipaste into showcase 2016-12-01 10:18:00 +08:00
qingwei.li 84871ca09e -> v0.7.0 2016-11-30 21:55:46 +08:00
qingwei.li 200dcf61ce bump 0.7.0 2016-11-30 21:53:16 +08:00
qingwei.li 816b6e2035 fix vue.css headling 2016-11-30 21:42:06 +08:00
qingwei.li e4a35d9dcf Add changelog 2016-11-30 21:35:14 +08:00
cinwell.liandGitHub 02a0adb872 0.7.0 (#16)
* add ignore

* Use postcss

* delete themes/

* fix build script

* fix css, fixed #15, fixed #13

* Add changelog

* Fix horizontal scroll for code block, fixed #11

* Fix sidebar animation
2016-11-30 21:33:44 +08:00
qingwei.li e48518b42a -> v0.6.1 2016-11-29 23:11:24 +08:00
qingwei.li 4d56be2f10 bump 0.6.1 2016-11-29 23:11:12 +08:00
cinwell.liandGitHub 19bf043cf8 Fix sidebar animation (#14) 2016-11-29 23:09:59 +08:00
qingwei.li a74cf6ceaf -> v0.6.0 2016-11-29 21:43:39 +08:00
qingwei.li 0f966e2eb1 bump 0.6.0 2016-11-29 21:43:29 +08:00
cinwell.liandGitHub d07ddaa85d 0.6.0 (#12)
* Fix ineffective option, fixed #10

* Feat: dropdown list, #6

* Fix repo url

* Feat: sidebar with toggle

* Update doc
2016-11-29 21:42:48 +08:00
qingwei.li dd361b34b9 -> v0.5.0 2016-11-29 01:11:12 +08:00
qingwei.li 1a7c6c094c bump 0.5.0 2016-11-29 01:11:02 +08:00
cinwell.liandGitHub 35d3bd1647 customize sidebar and navbar via markdown file, #6 (#8)
* Refactor: use iife

* Feat: customize sidebar and navbar via markdown file, #6

* Add changelog
2016-11-29 01:07:47 +08:00
qingwei.li e09b6f218f fix url 2016-11-28 15:39:35 +08:00
qingwei.li 4d7772035f add showcase 2016-11-28 14:03:54 +08:00
qingwei.li 6540e7370d -> v0.4.2 2016-11-28 12:34:05 +08:00
qingwei.li f3853d8e7f bump 0.4.2 2016-11-28 12:33:54 +08:00
qingwei.li 93ddf08615 fix code error 2016-11-28 12:33:25 +08:00
qingwei.li 7c05d729b4 -> v0.4.1 2016-11-28 12:24:14 +08:00
qingwei.li 5953ef7739 bump 0.4.1 2016-11-28 12:23:43 +08:00
qingwei.li d556282471 add docsify.js.org
fix cdn
2016-11-28 12:22:47 +08:00
qingwei.li ec58149aad add catch ajax error 2016-11-28 12:17:57 +08:00
qingwei.li e15c53a6b8 fix site
remove cname

remove cdn

remove cdn
2016-11-28 12:14:24 +08:00
qingwei.li f450b118ee use docsify.js.org 2016-11-28 11:27:28 +08:00
qingwei.li 6ac7d4f66f Add changelog 2016-11-27 19:06:14 +08:00
qingwei.li 17806def5a -> v0.4.0 2016-11-27 18:57:06 +08:00
qingwei.li ea03583d3d bump 0.4.0 2016-11-27 18:56:25 +08:00
cinwell.liandGitHub 37e7984e7e feat: custom sidebar, #4 (#5)
* feat: custom sidebar, #4

* fix dev html

* fix doc

* fix doc
2016-11-27 18:53:31 +08:00
qingwei.li fc2e5b6fb9 fix undefined language 2016-11-27 15:24:07 +08:00
qingwei.li 94f00053d7 -> v0.3.1 2016-11-27 14:02:07 +08:00
qingwei.li 029f92e341 bump 0.3.1 2016-11-27 14:01:47 +08:00
qingwei.li 8041c82e6d Strip HTML tag when rendering the headling 2016-11-27 14:01:05 +08:00
qingwei.li 5e38b702cd -> v0.3.0 2016-11-27 13:36:18 +08:00
qingwei.li 136ef2881e bump 0.3.0 2016-11-27 13:35:31 +08:00
qingwei.li 50006d2ceb fix cdn path 2016-11-27 13:35:10 +08:00
qingwei.li 657ad7d59c Add minified css files 2016-11-27 13:30:40 +08:00
qingwei.li eba21726d7 Add max level option 2016-11-27 13:09:18 +08:00
qingwei.li e789fb2b18 -> v0.2.1 2016-11-26 21:08:34 +08:00
qingwei.li 6e4b9d4cad bump 0.2.1 2016-11-26 21:08:21 +08:00
qingwei.li 824e64ae48 Fix style 2016-11-26 21:07:47 +08:00
37 changed files with 2518 additions and 800 deletions
+2
View File
@@ -1,3 +1,5 @@
.DS_Store
*.log
node_modules
yarn.lock
/themes
+3
View File
@@ -1,3 +1,6 @@
sudo: false
cache:
directories:
- $HOME/.yarn-cache
language: node_js
node_js: stable
+179
View File
@@ -0,0 +1,179 @@
## 1.4.1
### Bug fixes
- Fix generate slug.
## 1.4.0 Happly new year 🎉
### Features
- Display TOC in the custom sidebar, `data-sub-max-level`.
- Custom background in coverpage.
### Bug fixes
- Fix scroll highlight when Vue exist.
## 1.3.5
### Bug fixes
- Fix vue
## 1.3.4
### Bug fixes
- Supports [vuep](https://github.com/QingWei-Li/vuep)
## 1.3.3
### Bug fixes
- Fixed cover rendering timing
## 1.3.2
### Bug fixes
- Fixed render link
## 1.3.1
### Bug fixes
- Fixed cover page style
- Generate the correct link when rendering the article
## 1.3.0
### Features
- Add cover page
- add `<kbd>` style
- headling can be cliked
### Bug fixes
- sidebar highlight
### break change
- Navbar no longer fixed at the top
## 1.2.0
### Features
- custom basePath
- custom homepage
## 1.1.7
### Bug fixes
- Optimize progress bar
## 1.1.6
### Features
- Add logo 😂
### Bug fixes
- Remove table background color
- Fixed highlight sidebar using chinese ids
## 1.1.5
### Features
- Add table style
### Bug fixes
- Not fixed position of hte navbar in the mobile browser
- Correct calculation of whether the mobile browser
## 1.1.4
### Bug fixes
- Fixed chinese auchor link
## 1.1.3
### Bug fixes
- Optimize progress bar again
## 1.1.2
### Bug fixes
- fix failed `auto2top` in mobile
## 1.1.1
### Bug fixes
- Optimize progress bar
## 1.1.0
## Features
- Add progress bar
- Add `auto2top` option for hash router
## 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
## 1.0.0
## Features
- Support hash router
### Bug fixes
- Improved scrolling on mobile
## 0.7.0
### Breaking change
- `themes/` was removed, only exists in the npm package.
### 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
### Bug fixes
- Fix ineffective option, fixed #10
## 0.5.0
### Features
- Custom sidebars and navbars by markdown file
## 0.4.2
### Bug fixes
- Correct catch ajax error
## 0.4.1
### Bug fixes
- catch ajax error
## 0.4.0
### Features
- Custom sidebar
### Bug fixes
- Fix undefined language
## 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
## 0.2.1
### Bug fixes
- Fix vue.css
## 0.2.0
### Bug fixes
- Fix route
- Remove dynamic title
## 0.1.0
### Features
- Add buble.css
+53 -15
View File
@@ -1,22 +1,32 @@
# 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 href="https://docsify.js.org">
<img alt="docsify" src="./media/docsify.png">
</a>
</p>
>🃏 A magical documentation site generator.
<p align="center">
A magical documentation site generator.
</p>
<p align="center">
<a href="https://travis-ci.org/QingWei-Li/docsify"><img alt="Travis Status" src="https://img.shields.io/travis/rust-lang/rust/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/vuejs/vue"><img alt="code style" src="https://img.shields.io/badge/code%20style-vue-orange.svg?style=flat-square"></a>
</p>
## Links
- [Documentation](https://qingwei-li.github.io/docsify)
- [Documentation](https://docsify.js.org)
- [CLI](https://github.com/QingWei-Li/docsify-cli)
## Features
- Easy and lightweight
- Custom themes
- No build
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
## Quick start
Create `404.html` and `README.md` into `/docs`.
Create a `index.html` and using `hash router`.
404.html
index.html
```html
<!DOCTYPE html>
@@ -25,15 +35,43 @@ Create `404.html` and `README.md` into `/docs`.
<meta charset="UTF-8">
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
</head>
<body></body>
<script src="//unpkg.com/docsify"></script>
<body>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify" data-router></script>
</html>
```
## How to contribute
## CDN
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
- Fork it and clone!
- Run `npm i && npm run dev`
## Showcase
These open-source projects are using docsify to generate their sites. Pull requests welcome : )
- [docsify](https://docsify.js.org) - A magical documentation site generator.
- [Snipaste](https://docs.snipaste.com/) - A new way to boost your productivity.
## Similar projects
- [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 :D
## Development
```shell
npm i && npm run dev
open http://localhost:3000
```
## License
MIT
+3 -5
View File
@@ -2,13 +2,11 @@ var serveStatic = require('serve-static')
var http = require('http')
var fs = require('fs')
var notfound = fs.readFileSync('404.dev.html')
http.createServer(function (req, res) {
serveStatic('.')(req, res, function () {
res.writeHead(404, { 'Content-Type': 'text/html' })
res.end(notfound)
res.end(fs.readFileSync('dev.html'))
})
}).listen(3000)
}).listen(3000, '0.0.0.0')
console.log(`\nListening at http://localhost:3000\n`)
console.log(`\nListening at http://0.0.0.0:3000\n`)
+38
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)
})
})
+4 -1
View File
@@ -15,11 +15,14 @@ var build = function (opts) {
console.log(dest)
bundle.write({
format: 'umd',
format: 'iife',
moduleName: opts.moduleName || 'Docsify',
dest: dest
})
})
.catch(function (err) {
console.error(err)
})
}
build({
+4 -6
View File
@@ -5,12 +5,10 @@
<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>
<nav>
<a href="/">En</a>
<a href="/zh-cn">中文</a>
</nav>
<body class="">
<div id="app"></div>
</body>
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify"></script>
<script src=//unpkg.com/vue></script>
<script src=//unpkg.com/vuep></script>
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-auto2top data-sidebar-toggle data-router></script>
</html>
View File
-18
View File
@@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Docsify</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/themes/vue.css">
</head>
<body>
<nav>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
</nav>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify" data-repo="qingwei-li/docsify"></script>
</html>
+1
View File
@@ -0,0 +1 @@
docsify.js.org
+232 -19
View File
@@ -1,12 +1,3 @@
# docsify
> A magical documentation site generator.
## Features
- Easy and lightweight
- Custom themes
- No build
## Quick Start
### Create a project
@@ -17,7 +8,7 @@ mkdir docs && cd docs
```
### Create entry file
Create a `404.html` file
Create a `index.html` file
```html
<!DOCTYPE html>
@@ -29,7 +20,7 @@ Create a `404.html` file
<body>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify"></script>
<script src="//unpkg.com/docsify" data-router></script>
</html>
```
@@ -38,7 +29,7 @@ Create `README.md` as the main page
```
# Title
## balabala
## blabla
```
### Deploy!
@@ -47,7 +38,7 @@ Push and open the **GitHub Pages** feature
## CLI
Easy to setup and preivew a docs.
Easy to setup and preview a docs.
### Install
```shell
@@ -76,23 +67,245 @@ Currently available `vue.css` and `buble.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`.
If you need other pages, directly create the markdown file, such as `guide.md` is `/#/guide`.
### Navbar
Code in `404.html`
Code in `index.html`
```html
<nav>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
<a href="/#/docsify/">En</a>
<a href="/#/docsify/zh-cn">中文</a>
</nav>
```
### GitHub Corner
Modify your `404.html`
### CDN
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
### Cover Page
Generate a cover page through with markdown. Create a `_coverpage.md` and set `data-coverpage` in script tag.
```markdown
![logo](_media/icon.svg)
# docsify <small>1.2.0</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
```
#### Custom background
Currently the background of cover page is generated randomly. We can customize the background, just using the syntax to add image.
```markdown
# docsify <small>1.2.0</small>
> xxx
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
<!-- background image -->
![](_media/bg.png)
<!-- background color -->
![color](#f0f0f0)
```
### 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's set, the TOC will be disabled. 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 as a TOC.
** you should add `.nojekyll` into docs folder to prevent GitHub Pages from ignoring the `_sidebar.md`**
```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)
```
#### sub-max-level
Display TOC in the custom sidebar. The default value is 0.
```html
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
```
![image](https://cloud.githubusercontent.com/assets/7565692/21563209/a8894512-ceba-11e6-80eb-fef00b80625c.png)
#### 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.
```html
<script src="/lib/docsify.js" data-router></script>
```
#### auto2top
Scroll to the top on changing hash.
```html
<script src="/lib/docsify.js" data-auto2top></script>
```
#### homepage
`README.md` will be rendered as a homepage for your website in the docs folder, but sometimes we want to specify another file as a homepage, or even use the `README.md` in your repo. We can use (need `data-router`):
```html
<script src="/lib/docsify.js" data-homepage="https://raw.githubusercontent.com/QingWei-Li/docsify/master/README.md"></script>
<!-- Or using `Welcome.md` as homepge -->
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
```
#### basePath
If your HTML entry file and the markdown files are in different directories, we can use:
```html
<script src="/lib/docsify.js" data-base-path="/base/"></script>
<!-- Even if the docs is on another site 😄 -->
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
```
#### coverpage
Generate cover page.
```html
<script src="/lib/docsify.js" data-coverpage></script>
<!-- or -->
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
```
+13
View File
@@ -0,0 +1,13 @@
![logo](_media/icon.svg)
# docsify <small>1.3.3</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
+30
View File
@@ -0,0 +1,30 @@
<?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>

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify - A magical documentation site generator.</title>
<link rel="icon" href="favicon.ico">
<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">
</head>
<body>
<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-max-level="4"
data-sidebar-toggle
data-coverpage
data-router></script>
</html>
+229 -13
View File
@@ -1,11 +1,8 @@
# docsify
> 无需构建快速生成文档页
## 特性
- 无需构建,写完 markdown 直接发布
- 支持自定义主题
- 容易使用并且轻量
- 容易使用并且轻量 (~12kb gzipped)
## 快速上手
@@ -17,7 +14,7 @@ mkdir docs && cd docs
```
### 创建入口文件
创建一个 `404.html` 文件,内容为
创建一个 `index.html` 文件,内容为
```html
<!DOCTYPE html>
<html>
@@ -28,7 +25,7 @@ mkdir docs && cd docs
<body>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify"></script>
<script src="//unpkg.com/docsify" data-router></script>
</html>
```
@@ -69,32 +66,251 @@ docsify serve docs
更多选项参考 [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
## 主题
目前提供 vue.css 和 buble.css,直接修改 `404.html` 里的 cdn 地址即可
目前提供 vue.css 和 buble.css,直接修改 `index.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`
`README.md` 作为主页面,如果需要其他页面,直接在文档目录下创建对应的 `*.md` 文件,例如创建一个 `guide.md` 那么对应的路由就是 `/#/guide`
### 导航
导航需要自己写在 `404.html` 文件里,效果参考本文档
导航需要自己写在 `index.html` 文件里,效果参考本文档
```html
<nav>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
<a href="/#/docsify/">En</a>
<a href="/#/docsify/zh-cn">中文</a>
</nav>
```
### GitHub Corner
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
### CDN
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
### 封面
只需要写几行简单的 markdown 就可以拥有一页精致的封面,通过添加 `data-coverpage` 属性,并创建 `_coverpage.md`,按照下面的格式书写即可。
```markdown
![logo](_media/icon.svg)
# docsify <small>1.2.0</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
```
#### 自定义封面背景
默认的背景是随机生成的,你可以自定义背景色或者背景图片。只需要在文档末尾用添加图片的 Markdown 语法
```markdown
# docsify <small>1.2.0</small>
> xxx
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
<!-- 背景图片 -->
![](_media/bg.png)
<!-- 背景色 -->
![color](#f0f0f0)
```
### 配置参数
#### repo
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `index.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 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
**如果用 `_` 开头作为文件名,你应该在文档目录下添加 `.nojekyll`,阻止 GitHub Pages 忽略下划线开头的文件。**
```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)
```
#### sub-max-level
显示 TOC 在自定义的侧边栏里,默认最大显示 0 层。
```html
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
```
![image](https://cloud.githubusercontent.com/assets/7565692/21563209/a8894512-ceba-11e6-80eb-fef00b80625c.png)
#### 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 功能,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
```html
<script src="/lib/docsify.js" data-router></script>
```
#### auto2top
切换路由时自动跳转到页面顶部
```html
<script src="/lib/docsify.js" data-auto2top></script>
```
#### homepage
默认情况下网站会将根目录下 `README.md` 作为首页渲染,但是有些时候我们想指定其他文件,甚至想直接将 repo 下的 README 作为首页。你可以这样做(需要设置 `data-router`):
```html
<script src="/lib/docsify.js" data-homepage="https://raw.githubusercontent.com/QingWei-Li/docsify/master/README.md"></script>
<!-- 或者将 Welcome.md 作为首页 -->
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
```
#### basePath
指定加载文档的路径,如果你的 HTML 入口文件和文档是放在不同地方,你可以设置:
```html
<script src="/lib/docsify.js" data-base-path="/base/"></script>
<!-- 甚至文档是在其他站点下 😄 -->
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
```
#### coverpage
生成封面,参考 [#封面](/zh-cn#封面).
```html
<script src="/lib/docsify.js" data-coverpage></script>
<!-- or -->
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
```
+557 -150
View File
@@ -1,21 +1,267 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Docsify = factory());
}(this, (function () { 'use strict';
var Docsify = (function () {
'use strict';
var ajax = function (url, options) {
if ( options === void 0 ) options = {};
/**
* Simple ajax
* @param {String} url
* @param {String} [method=GET]
* @param {Function} [loading] handle loading
* @return {Promise}
*/
function load (url, method, loading) {
if ( method === void 0 ) method = 'GET';
var xhr = new XMLHttpRequest();
xhr.open(options.method || 'get', url);
xhr.open(method, url);
xhr.send();
return {
then: function (cb) { return xhr.addEventListener('load', cb); }
then: function (success, error) {
if ( error === void 0 ) error = function () {};
if (loading) {
var id = setInterval(function (_) { return loading({ step: Math.floor(Math.random() * 5 + 1) }); },
500);
xhr.addEventListener('progress', loading);
xhr.addEventListener('loadend', function (evt) {
loading(evt);
clearInterval(id);
});
}
xhr.addEventListener('error', error);
xhr.addEventListener('load', function (ref) {
var target = ref.target;
target.status >= 400 ? error(target) : success(target.response);
});
},
abort: function () { return xhr.readyState !== 4 && xhr.abort(); }
}
};
}
/**
* 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}
*/
function genTree (toc, maxLevel) {
var headlines = [];
var last = {};
toc.forEach(function (headline) {
var level = headline.level || 1;
var len = level - 1;
if (level > maxLevel) { return }
if (last[len]) {
last[len].children = last[len].children || [];
last[len].children.push(headline);
} else {
headlines.push(headline);
}
last[level] = headline;
});
return headlines
}
/**
* camel to kebab
* @link https://github.com/bokuweb/kebab2camel/blob/master/index.js
* @param {String} str
* @return {String}
*/
function camel2kebab (str) {
return str.replace(/([A-Z])/g, function (m) { return '-' + m.toLowerCase(); })
}
/**
* is nil
* @param {Object} object
* @return {Boolean}
*/
function isNil (o) {
return o === null || o === undefined
}
var cacheRoute$1 = null;
var cacheHash = null;
/**
* hash route
*/
function getRoute () {
var loc = window.location;
if (cacheHash === loc.hash && !isNil(cacheRoute$1)) { return cacheRoute$1 }
var route = loc.hash.match(/^#\/([^#]+)/);
if (route && route.length === 2) {
route = route[1];
} else {
route = /^#\//.test(loc.hash) ? '' : loc.pathname;
}
cacheRoute$1 = route;
cacheHash = loc.hash;
return route
}
function isMobile () {
return document.body.clientWidth <= 600
}
function slugify (string) {
var re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g;
var maintainCase = false;
var replacement = '-';
slugify.occurrences = slugify.occurrences || {};
if (typeof string !== 'string') { return '' }
if (!maintainCase) { string = string.toLowerCase(); }
var slug = string.trim()
.replace(re, '')
.replace(/\s/g, replacement);
var occurrences = slugify.occurrences[slug];
if (slugify.occurrences.hasOwnProperty(slug)) {
occurrences++;
} else {
occurrences = 0;
}
slugify.occurrences[slug] = occurrences;
if (occurrences) {
slug = slug + '-' + occurrences;
}
return slug
}
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
*/
function scrollActiveSidebar () {
if (isMobile()) { return }
var anchors = document.querySelectorAll('.anchor');
var nav = {};
var lis = document.querySelectorAll('.sidebar li');
var active = null;
for (var i = 0, len = lis.length; i < len; i += 1) {
var li = lis[i];
var href = li.querySelector('a').getAttribute('href');
if (href !== '/') {
var match = href.match('#([^#]+)$');
if (match && match.length) { href = match[0].slice(1); }
}
nav[decodeURIComponent(href)] = li;
}
function highlight () {
for (var i = 0, len = anchors.length; i < len; i += 1) {
var node = anchors[i];
var bcr = node.getBoundingClientRect();
if (bcr.top < 10 && bcr.bottom > 10) {
var li = nav[node.getAttribute('data-id')];
if (!li || li === active) { return }
if (active) { active.setAttribute('class', ''); }
li.setAttribute('class', 'active');
active = li;
return
}
}
}
window.removeEventListener('scroll', highlight);
window.addEventListener('scroll', highlight);
highlight();
}
function scrollIntoView () {
var id = window.location.hash.match(/#[^#\/]+$/g);
if (!id || !id.length) { return }
var section = document.querySelector(decodeURIComponent(id[0]));
if (section) { section.scrollIntoView(); }
}
/**
* Acitve link
*/
function activeLink (dom, activeParent) {
var host = window.location.href;
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
if (!dom) { return }
var target;[].slice.call(dom.querySelectorAll('a'))
.sort(function (a, b) { return b.href.length - a.href.length; })
.forEach(function (node) {
if (host.indexOf(node.href) === 0 && !target) {
activeParent
? node.parentNode.setAttribute('class', 'active')
: node.setAttribute('class', 'active');
target = node;
} else {
activeParent
? node.parentNode.removeAttribute('class')
: node.removeAttribute('class');
}
});
return target
}
/**
* sidebar toggle
*/
function bindToggle (dom) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
if (!dom) { return }
var body = document.body;
dom.addEventListener('click', function () { return body.classList.toggle('close'); });
if (!/mobile/i.test(navigator.userAgent)) { return }
document.querySelector('aside').addEventListener('click', function (event) {
body.classList.toggle('close');
});
}
var cacheContentDOM;
function scroll2Top () {
if (!cacheContentDOM) {
var dom = isMobile() ? 'body' : 'section.content';
cacheContentDOM = document.querySelector(dom);
}
cacheContentDOM.scrollTop = 0;
}
function sticky () {
var dom = document.querySelector('section.cover');
var coverHeight = dom.getBoundingClientRect().height;
return (function () {
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
document.body.classList.add('sticky');
} else {
document.body.classList.remove('sticky');
}
})()
}
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -2112,50 +2358,69 @@ Prism.languages.js = Prism.languages.javascript;
});
/**
* @link from https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
* Render github corner
* @param {Object} data
* @return {String}
*/
var tocToTree = function (toc) {
var headlines = [];
var last = {};
function corner (data) {
if (!data) { return '' }
if (!/\/\//.test(data)) { data = 'https://github.com/' + data; }
data = data.replace(/^git\+/, '');
toc.forEach(function (headline) {
var level = headline.level || 1;
var len = level - 1;
return ("\n <a href=\"" + data + "\" class=\"github-corner\" aria-label=\"View source on Github\">\n <svg viewBox=\"0 0 250 250\" aria-hidden=\"true\">\n <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n <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>\n <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>\n </svg>\n </a>")
}
if (last[len]) {
last[len].children = last[len].children || [];
last[len].children.push(headline);
} else {
headlines.push(headline);
}
last[level] = headline;
});
/**
* Render main content
*/
function main (tpl) {
return ("<main>\n " + tpl + "\n <aside class=\"sidebar\"></aside>\n <section class=\"content\">\n <article class=\"markdown-section\"></article>\n </section>\n </main>")
}
return headlines
};
/**
* Cover Page
*/
function cover () {
var SL = ', 100%, 85%';
var bgc = "linear-gradient(to left bottom, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 0%, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 100%)";
var buildHeadlinesTree = function (tree, tpl) {
return ("<section class=\"cover\" style=\"background: " + bgc + "\">\n <div class=\"cover-main\"></div>\n <div class=\"mask\"></div>\n </section>")
}
function toggle () {
return "<button class=\"sidebar-toggle\">\n <span></span><span></span><span></span>\n </button>"
}
/**
* Render tree
* @param {Array} tree
* @param {String} tpl
* @return {String}
*/
function tree (toc, tpl) {
if ( tpl === void 0 ) tpl = '';
if (!tree || !tree.length) { return '' }
if (!toc || !toc.length) { return '' }
tree.forEach(function (node) {
tpl += "<li><a class=\"section-link\" href=\"#" + (node.slug) + "\">" + (node.title) + "</a></li>";
toc.forEach(function (node) {
tpl += "<li><a class=\"section-link\" href=\"" + (node.slug) + "\">" + (node.title) + "</a></li>";
if (node.children) {
tpl += "<li><ul class=\"children\">" + (buildHeadlinesTree(node.children)) + "</li></ul>";
tpl += "<li><ul class=\"children\">" + (tree(node.children)) + "</li></ul>";
}
});
return tpl
};
}
var genToc = function (toc) {
var tree = tocToTree(toc);
var result = buildHeadlinesTree(tree, '<ul>');
return result
};
var OPTIONS$1 = {};
var CACHE = {};
var cornerTpl = "\n <a href=\"{{repo}}\" class=\"github-corner\" aria-label=\"View source on Github\">\n <svg viewBox=\"0 0 250 250\" aria-hidden=\"true\">\n <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n <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>\n <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>\n </svg>\n </a>\n";
var renderTo = function (dom, content) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
dom.innerHTML = content;
return dom
};
var toc = [];
var renderer = new marked.Renderer();
@@ -2164,152 +2429,294 @@ var renderer = new marked.Renderer();
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
renderer.heading = function (text, level) {
var slug = text.toLowerCase().replace(/[\s\n\t]+/g, '-');
var slug = slugify(text);
var route = '';
toc.push({ level: level, slug: slug, title: text });
if (OPTIONS$1.router) {
route = "#/" + (getRoute());
}
return ("<h" + level + " id=\"" + slug + "\"><a href=\"#" + slug + "\" class=\"anchor\"></a>" + text + "</h" + level + ">")
toc.push({ level: level, slug: (route + "#" + (encodeURIComponent(slug))), title: text });
return ("<a href=\"" + route + "#" + slug + "\" data-id=\"" + slug + "\" class=\"anchor\"><h" + level + " id=\"" + slug + "\">" + text + "</h" + level + "></a>")
};
// highlight code
renderer.code = function (code, lang) {
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
if ( lang === void 0 ) lang = '';
return ("<pre><code class=\"lang-" + lang + "\" data-lang=\"" + lang + "\">" + hl + "</code></pre>")
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup)
.replace(/{{/g, '<span>{{</span>');
return ("<pre data-lang=\"" + lang + "\"><code class=\"lang-" + lang + "\">" + hl + "</code></pre>")
};
renderer.link = function (href, title, text) {
if (OPTIONS$1.router && !/^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(href)) {
href = ("#/" + href).replace(/\/\//g, '/');
}
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
};
marked.setOptions({ renderer: renderer });
var render = function (content, opts) {
if ( opts === void 0 ) opts = {};
/**
* App
*/
function renderApp (dom, replace) {
var nav = document.querySelector('nav') || document.createElement('nav');
var corner = '';
if (!OPTIONS$1.repo) { nav.classList.add('no-badge'); }
if (opts.repo) {
var repo = /\/\//.test(opts.repo) ? opts.repo : ('https://github.com/' + opts.repo);
corner = cornerTpl.replace(/{{repo}}/g, repo);
dom[replace ? 'outerHTML' : 'innerHTML'] = corner(OPTIONS$1.repo) +
(OPTIONS$1.coverpage ? cover() : '') +
main(OPTIONS$1.sidebarToggle ? toggle() : '');
document.body.insertBefore(nav, document.body.children[0]);
// bind toggle
bindToggle('button.sidebar-toggle');
// bind sticky effect
if (OPTIONS$1.coverpage) {
!isMobile() && window.addEventListener('scroll', sticky);
} else {
document.body.classList.add('sticky');
}
var section = "<section class=\"content\">\n <article class=\"markdown-section\">" + (marked(content)) + "</article>\n </section>";
var sidebar = "<aside class=\"sidebar\">" + (genToc(toc)) + "</aside>";
return (corner + "<main>" + sidebar + section + "</main>")
};
function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) { return }
var anchors = document.querySelectorAll('.anchor');
var nav = {};
var lis = document.querySelectorAll('.sidebar li');
var active = null;
for (var i = 0, len = lis.length; i < len; i += 1) {
var li = lis[i];
var a = li.querySelector('a');
nav[a.getAttribute('href').slice(1)] = li;
}
function highlight () {
for (var i = 0, len = anchors.length; i < len; i += 1) {
var node = anchors[i].parentNode;
var bcr = node.getBoundingClientRect();
if (bcr.top < 10 && bcr.bottom > 10) {
var li = nav[node.id];
if (li === active) { return }
if (active) { active.setAttribute('class', ''); }
li.setAttribute('class', 'active');
active = li;
return
}
}
}
document.querySelector('main .content').addEventListener('scroll', highlight);
highlight();
function scrollIntoView () {
var id = window.location.hash.slice(1);
if (!id) { return }
var section = document.querySelector('#' + id);
if (section) { section.scrollIntoView(); }
}
window.addEventListener('hashchange', scrollIntoView);
scrollIntoView();
}
var bindEvent = function () {
/**
* article
*/
function renderArticle (content) {
renderTo('article', content ? marked(content) : 'not found');
if (!OPTIONS$1.sidebar && !OPTIONS$1.loadSidebar) { renderSidebar(); }
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
var vm = new Vue({ el: 'main' }); // eslint-disable-line
vm.$nextTick(function (_) { return scrollActiveSidebar(); });
}
if (OPTIONS$1.auto2top) { scroll2Top(); }
}
/**
* navbar
*/
function renderNavbar (content) {
if (CACHE.navbar && CACHE.navbar === content) { return }
CACHE.navbar = content;
if (content) { renderTo('nav', marked(content)); }
activeLink('nav');
}
/**
* sidebar
*/
function renderSidebar (content) {
var html;
if (content) {
html = marked(content);
} else if (OPTIONS$1.sidebar) {
html = tree(OPTIONS$1.sidebar, '<ul>');
} else {
html = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
}
renderTo('aside.sidebar', html);
var target = activeLink('aside.sidebar', true);
if (content) { renderSubSidebar(target); }
toc = [];
scrollActiveSidebar();
};
}
var DEFAULT_OPTS = {
function renderSubSidebar (target) {
if (!OPTIONS$1.subMaxLevel) { return }
target.parentNode.innerHTML += tree(genTree(toc, OPTIONS$1.subMaxLevel), '<ul>');
}
/**
* Cover Page
*/
function renderCover (content) {
renderCover.dom = renderCover.dom || document.querySelector('section.cover');
if (!content) {
renderCover.dom.classList.remove('show');
return
}
renderCover.dom.classList.add('show');
if (renderCover.rendered) { return }
// render cover
var html = marked(content);
var match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$');
// render background
if (match) {
var coverEl = document.querySelector('section.cover');
if (match[2] === 'color') {
coverEl.style.background = match[1];
} else {
coverEl.classList.add('has-mask');
coverEl.style.backgroundImage = "url(" + (match[1]) + ")";
}
html = html.replace(match[0], '');
}
renderTo('.cover-main', html);
renderCover.rendered = true;
sticky();
}
/**
* render loading bar
* @return {[type]} [description]
*/
function renderLoading (ref) {
var loaded = ref.loaded;
var total = ref.total;
var step = ref.step;
var num;
if (!CACHE.loading) {
var div = document.createElement('div');
div.classList.add('progress');
document.body.appendChild(div);
CACHE.loading = div;
}
if (step) {
num = parseInt(CACHE.loading.style.width, 10) + step;
num = num > 80 ? 80 : num;
} else {
num = Math.floor(loaded / total * 100);
}
CACHE.loading.style.opacity = 1;
CACHE.loading.style.width = num >= 95 ? '100%' : num + '%';
if (num >= 95) {
clearTimeout(renderLoading.cacheTimeout);
renderLoading.cacheTimeout = setTimeout(function (_) {
CACHE.loading.style.opacity = 0;
CACHE.loading.style.width = '0%';
}, 200);
}
}
/**
* Load Config
* @param {Object} options
*/
function config (options) {
OPTIONS$1 = options;
}
var OPTIONS = {
el: '#app',
repo: ''
repo: '',
maxLevel: 6,
subMaxLevel: 0,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false
};
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
// load configuration for script attribute
if (script) {
for (var prop in DEFAULT_OPTS) {
DEFAULT_OPTS[prop] = script.getAttribute('data-' + prop) || DEFAULT_OPTS[prop];
for (var prop in OPTIONS) {
var 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.coverpage === true) { OPTIONS.coverpage = '_coverpage.md'; }
if (OPTIONS.sidebar) { OPTIONS.sidebar = window[OPTIONS.sidebar]; }
}
var Docsify = function Docsify (opts) {
Docsify.installed = true;
// load options
config(OPTIONS);
this.opts = Object.assign({}, opts, DEFAULT_OPTS);
var cacheRoute = null;
var cacheXhr = null;
this.replace = true;
this.dom = document.querySelector(this.opts.el);
if (!this.dom) {
this.dom = document.body;
this.replace = false;
var mainRender = function (cb) {
var route = OPTIONS.basePath + getRoute();
if (cacheRoute === route) { return cb() }
var basePath = cacheRoute = route;
if (!/\//.test(basePath)) {
basePath = '';
} else if (basePath && !/\/$/.test(basePath)) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1];
}
this.loc = document.location.pathname;
if (/\/$/.test(this.loc)) { this.loc += 'README'; }
this.load();
var nav = document.querySelector('nav');
if (nav) { this.activeNav(nav); }
};
var page;
if (!route) {
page = OPTIONS.homepage || 'README.md';
} else if (/\/$/.test(route)) {
page = route + "README.md";
} else {
page = route + ".md";
}
Docsify.prototype.load = function load () {
var this$1 = this;
// Render Cover page
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
load(OPTIONS.coverpage).then(renderCover);
}
ajax(((this.loc) + ".md")).then(function (res) {
var target = res.target;
if (target.status >= 400) {
this$1.render('not found');
cacheXhr && cacheXhr.abort && cacheXhr.abort();
// Render markdown file
cacheXhr = load(page, 'GET', renderLoading);
cacheXhr.then(function (result) {
renderArticle(result);
// clear cover
if (OPTIONS.coverpage && page !== OPTIONS.homepage) { renderCover(); }
// render sidebar
if (OPTIONS.loadSidebar) {
load(basePath + OPTIONS.loadSidebar)
.then(function (result) {
renderSidebar(result);
cb();
});
} else {
this$1.render(res.target.response);
bindEvent();
cb();
}
});
}, function (_) { return renderArticle(null); });
// Render navbar
if (OPTIONS.loadNavbar) {
load(basePath + OPTIONS.loadNavbar).then(renderNavbar);
}
};
Docsify.prototype.render = function render$1 (content) {
this.dom[this.replace ? 'outerHTML' : 'innerHTML'] = render(content, this.opts);
var Docsify = function () {
var dom = document.querySelector(OPTIONS.el) || document.body;
var replace = dom !== document.body;
var main = function () {
mainRender(function (_) { return scrollIntoView(); });
};
// Render app
renderApp(dom, replace);
main();
if (OPTIONS.router) {
if (!/^#\//.test(window.location.hash)) { window.location.hash = '#/'; }
window.addEventListener('hashchange', main);
}
};
Docsify.prototype.activeNav = function activeNav (elm) {
var host = document.location.origin + document.location.pathname;[].slice.call(elm.querySelectorAll('a')).forEach(function (node) {
if (node.href === host) {
node.setAttribute('class', 'active');
}
});
};
var index = Docsify();
window.addEventListener('load', function () {
if (Docsify.installed) { return }
new Docsify();
});
return index;
return Docsify;
})));
}());
+2 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

+7 -4
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "0.2.0",
"version": "1.4.1",
"description": "A magical documentation generator.",
"main": "lib/docsify.js",
"files": [
@@ -9,8 +9,8 @@
"themes"
],
"scripts": {
"build": "node build/build.js",
"dev": "node app.js & nodemon --watch src themes --exec 'npm run build'",
"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 -e js,css --exec 'npm run build'",
"test": "eslint src test"
},
"repository": {
@@ -25,13 +25,16 @@
"generator"
],
"author": "qingwei-li <cinwell.li@gmail.com> (https://github.com/QingWei-Li)",
"homepage": "https://QingWei-Li.github.io/docsify",
"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",
-10
View File
@@ -1,10 +0,0 @@
export default function (url, options = {}) {
const xhr = new XMLHttpRequest()
xhr.open(options.method || 'get', url)
xhr.send()
return {
then: cb => xhr.addEventListener('load', cb)
}
}
-51
View File
@@ -1,51 +0,0 @@
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]
const a = li.querySelector('a')
nav[a.getAttribute('href').slice(1)] = 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 === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
}
}
}
document.querySelector('main .content').addEventListener('scroll', highlight)
highlight()
function scrollIntoView () {
const id = window.location.hash.slice(1)
if (!id) return
const section = document.querySelector('#' + id)
if (section) section.scrollIntoView()
}
window.addEventListener('hashchange', scrollIntoView)
scrollIntoView()
}
export default function () {
scrollActiveSidebar()
}
+123
View File
@@ -0,0 +1,123 @@
import { isMobile } from './util'
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
*/
export function scrollActiveSidebar () {
if (isMobile()) 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 !== '/') {
const match = href.match('#([^#]+)$')
if (match && match.length) href = match[0].slice(1)
}
nav[decodeURIComponent(href)] = li
}
function highlight () {
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i]
const bcr = node.getBoundingClientRect()
if (bcr.top < 10 && bcr.bottom > 10) {
const li = nav[node.getAttribute('data-id')]
if (!li || li === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
}
}
}
window.removeEventListener('scroll', highlight)
window.addEventListener('scroll', highlight)
highlight()
}
export function scrollIntoView () {
const id = window.location.hash.match(/#[^#\/]+$/g)
if (!id || !id.length) return
const section = document.querySelector(decodeURIComponent(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
let target
;[].slice.call(dom.querySelectorAll('a'))
.sort((a, b) => b.href.length - a.href.length)
.forEach(node => {
if (host.indexOf(node.href) === 0 && !target) {
activeParent
? node.parentNode.setAttribute('class', 'active')
: node.setAttribute('class', 'active')
target = node
} else {
activeParent
? node.parentNode.removeAttribute('class')
: node.removeAttribute('class')
}
})
return target
}
/**
* 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')
})
}
let cacheContentDOM
export function scroll2Top () {
if (!cacheContentDOM) {
const dom = isMobile() ? 'body' : 'section.content'
cacheContentDOM = document.querySelector(dom)
}
cacheContentDOM.scrollTop = 0
}
export function sticky () {
const dom = document.querySelector('section.cover')
const coverHeight = dom.getBoundingClientRect().height
return (function () {
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
document.body.classList.add('sticky')
} else {
document.body.classList.remove('sticky')
}
})()
}
-41
View File
@@ -1,41 +0,0 @@
/**
* @link from https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
*/
const tocToTree = function (toc) {
const headlines = []
const last = {}
toc.forEach(headline => {
const level = headline.level || 1
const len = level - 1
if (last[len]) {
last[len].children = last[len].children || []
last[len].children.push(headline)
} else {
headlines.push(headline)
}
last[level] = headline
})
return headlines
}
const buildHeadlinesTree = function (tree, tpl = '') {
if (!tree || !tree.length) return ''
tree.forEach((node) => {
tpl += `<li><a class="section-link" href="#${node.slug}">${node.title}</a></li>`
if (node.children) {
tpl += `<li><ul class="children">${buildHeadlinesTree(node.children)}</li></ul>`
}
})
return tpl
}
export default function (toc) {
var tree = tocToTree(toc)
var result = buildHeadlinesTree(tree, '<ul>')
return result
}
+90 -53
View File
@@ -1,70 +1,107 @@
import ajax from './ajax'
import render from './render'
import bindEvent from './bind-event'
import { load, camel2kebab, isNil, getRoute } from './util'
import { scrollIntoView } from './event'
import * as render from './render'
const DEFAULT_OPTS = {
const OPTIONS = {
el: '#app',
repo: ''
repo: '',
maxLevel: 6,
subMaxLevel: 0,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false
}
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
// load configuration for script attribute
if (script) {
for (const prop in DEFAULT_OPTS) {
DEFAULT_OPTS[prop] = script.getAttribute('data-' + prop) || DEFAULT_OPTS[prop]
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.coverpage === true) OPTIONS.coverpage = '_coverpage.md'
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
}
class Docsify {
constructor (opts) {
Docsify.installed = true
// load options
render.config(OPTIONS)
this.opts = Object.assign({}, opts, DEFAULT_OPTS)
let cacheRoute = null
let cacheXhr = null
this.replace = true
this.dom = document.querySelector(this.opts.el)
if (!this.dom) {
this.dom = document.body
this.replace = false
const mainRender = function (cb) {
const route = OPTIONS.basePath + getRoute()
if (cacheRoute === route) return cb()
let basePath = cacheRoute = route
if (!/\//.test(basePath)) {
basePath = ''
} else if (basePath && !/\/$/.test(basePath)) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1]
}
let page
if (!route) {
page = OPTIONS.homepage || 'README.md'
} else if (/\/$/.test(route)) {
page = `${route}README.md`
} else {
page = `${route}.md`
}
// Render Cover page
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
load(OPTIONS.coverpage).then(render.renderCover)
}
cacheXhr && cacheXhr.abort && cacheXhr.abort()
// Render markdown file
cacheXhr = load(page, 'GET', render.renderLoading)
cacheXhr.then(result => {
render.renderArticle(result)
// clear cover
if (OPTIONS.coverpage && page !== OPTIONS.homepage) render.renderCover()
// render sidebar
if (OPTIONS.loadSidebar) {
load(basePath + OPTIONS.loadSidebar)
.then(result => {
render.renderSidebar(result)
cb()
})
} else {
cb()
}
this.loc = document.location.pathname
if (/\/$/.test(this.loc)) this.loc += 'README'
this.load()
}, _ => render.renderArticle(null))
const nav = document.querySelector('nav')
if (nav) this.activeNav(nav)
}
load () {
ajax(`${this.loc}.md`).then(res => {
const target = res.target
if (target.status >= 400) {
this.render('not found')
} else {
this.render(res.target.response)
bindEvent()
}
})
}
render (content) {
this.dom[this.replace ? 'outerHTML' : 'innerHTML'] = render(content, this.opts)
}
activeNav (elm) {
const host = document.location.origin + document.location.pathname
;[].slice.call(elm.querySelectorAll('a')).forEach(node => {
if (node.href === host) {
node.setAttribute('class', 'active')
}
})
// Render navbar
if (OPTIONS.loadNavbar) {
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar)
}
}
window.addEventListener('load', () => {
if (Docsify.installed) return
new Docsify()
})
const Docsify = function () {
const dom = document.querySelector(OPTIONS.el) || document.body
const replace = dom !== document.body
const main = function () {
mainRender(_ => scrollIntoView())
}
export default Docsify
// 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()
+177 -27
View File
@@ -1,17 +1,19 @@
import marked from 'marked'
import Prism from 'prismjs'
import genToc from './gen-toc'
import * as tpl from './tpl'
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top, sticky } from './event'
import { genTree, getRoute, isMobile, slugify } from './util'
const cornerTpl = `
<a href="{{repo}}" 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>
`
const toc = []
let OPTIONS = {}
const CACHE = {}
const renderTo = function (dom, content) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
dom.innerHTML = content
return dom
}
let toc = []
const renderer = new marked.Renderer()
/**
@@ -19,33 +21,181 @@ const renderer = new marked.Renderer()
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
renderer.heading = function (text, level) {
const slug = text.toLowerCase().replace(/[\s\n\t]+/g, '-')
const slug = slugify(text)
let route = ''
toc.push({ level, slug, title: text })
if (OPTIONS.router) {
route = `#/${getRoute()}`
}
return `<h${level} id="${slug}"><a href="#${slug}" class="anchor"></a>${text}</h${level}>`
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
return `<a href="${route}#${slug}" data-id="${slug}" class="anchor"><h${level} id="${slug}">${text}</h${level}></a>`
}
// highlight code
renderer.code = function (code, lang) {
renderer.code = function (code, lang = '') {
const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup)
.replace(/{{/g, '<span>{{</span>')
return `<pre><code class="lang-${lang}" data-lang="${lang}">${hl}</code></pre>`
return `<pre data-lang="${lang}"><code class="lang-${lang}">${hl}</code></pre>`
}
renderer.link = function (href, title, text) {
if (OPTIONS.router && !/^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
}
return `<a href="${href}" title="${title || ''}">${text}</a>`
}
marked.setOptions({ renderer })
export default function (content, opts = {}) {
let corner = ''
/**
* App
*/
export function renderApp (dom, replace) {
const nav = document.querySelector('nav') || document.createElement('nav')
if (opts.repo) {
const repo = /\/\//.test(opts.repo) ? opts.repo : ('https://github.com/' + opts.repo)
corner = cornerTpl.replace(/{{repo}}/g, repo)
if (!OPTIONS.repo) nav.classList.add('no-badge')
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner(OPTIONS.repo) +
(OPTIONS.coverpage ? tpl.cover() : '') +
tpl.main(OPTIONS.sidebarToggle ? tpl.toggle() : '')
document.body.insertBefore(nav, document.body.children[0])
// bind toggle
bindToggle('button.sidebar-toggle')
// bind sticky effect
if (OPTIONS.coverpage) {
!isMobile() && window.addEventListener('scroll', sticky)
} else {
document.body.classList.add('sticky')
}
}
/**
* article
*/
export function renderArticle (content) {
renderTo('article', content ? marked(content) : 'not found')
if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
const vm = new Vue({ el: 'main' }) // eslint-disable-line
vm.$nextTick(_ => scrollActiveSidebar())
}
if (OPTIONS.auto2top) scroll2Top()
}
/**
* navbar
*/
export function renderNavbar (content) {
if (CACHE.navbar && CACHE.navbar === content) return
CACHE.navbar = content
if (content) renderTo('nav', marked(content))
activeLink('nav')
}
/**
* sidebar
*/
export function renderSidebar (content) {
let html
if (content) {
html = marked(content)
} else if (OPTIONS.sidebar) {
html = tpl.tree(OPTIONS.sidebar, '<ul>')
} else {
html = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
}
const section = `<section class="content">
<article class="markdown-section">${marked(content)}</article>
</section>`
const sidebar = `<aside class="sidebar">${genToc(toc)}</aside>`
renderTo('aside.sidebar', html)
const target = activeLink('aside.sidebar', true)
if (content) renderSubSidebar(target)
toc = []
return `${corner}<main>${sidebar}${section}</main>`
scrollActiveSidebar()
}
export function renderSubSidebar (target) {
if (!OPTIONS.subMaxLevel) return
target.parentNode.innerHTML += tpl.tree(genTree(toc, OPTIONS.subMaxLevel), '<ul>')
}
/**
* Cover Page
*/
export function renderCover (content) {
renderCover.dom = renderCover.dom || document.querySelector('section.cover')
if (!content) {
renderCover.dom.classList.remove('show')
return
}
renderCover.dom.classList.add('show')
if (renderCover.rendered) return
// render cover
let html = marked(content)
const match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$')
// render background
if (match) {
const coverEl = document.querySelector('section.cover')
if (match[2] === 'color') {
coverEl.style.background = match[1]
} else {
coverEl.classList.add('has-mask')
coverEl.style.backgroundImage = `url(${match[1]})`
}
html = html.replace(match[0], '')
}
renderTo('.cover-main', html)
renderCover.rendered = true
sticky()
}
/**
* render loading bar
* @return {[type]} [description]
*/
export function renderLoading ({ loaded, total, step }) {
let num
if (!CACHE.loading) {
const div = document.createElement('div')
div.classList.add('progress')
document.body.appendChild(div)
CACHE.loading = div
}
if (step) {
num = parseInt(CACHE.loading.style.width, 10) + step
num = num > 80 ? 80 : num
} else {
num = Math.floor(loaded / total * 100)
}
CACHE.loading.style.opacity = 1
CACHE.loading.style.width = num >= 95 ? '100%' : num + '%'
if (num >= 95) {
clearTimeout(renderLoading.cacheTimeout)
renderLoading.cacheTimeout = setTimeout(_ => {
CACHE.loading.style.opacity = 0
CACHE.loading.style.width = '0%'
}, 200)
}
}
/**
* Load Config
* @param {Object} options
*/
export function config (options) {
OPTIONS = options
}
+97
View File
@@ -0,0 +1,97 @@
section.cover {
align-items: center;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
display: none;
&.show {
display: flex;
}
&.has-mask .mask {
position: absolute;
size: 100%;
background-color: $color-bg;
opacity: .8;
}
.cover-main {
flex: 1;
text-align: center;
margin: 0 16px;
z-index: 1;
}
a {
color: inherit;
text-decoration: none;
&:hover {
text-decoration: none;
}
}
p {
margin: 1em 0;
line-height: 1.5rem;
}
h1 {
text-align: center;
font-size: 2.5rem;
position: relative;
margin: .625rem 0 2.5rem;
font-weight: 300;
color: inherit;
small {
position: absolute;
bottom: -.4375rem;
font-size: 1rem;
}
}
blockquote {
text-align: center;
font-size: 1.5rem;
}
ul {
max-width: 500px;
list-style-type: none;
margin: 1em auto;
padding: 0;
line-height: 1.8;
}
.cover-main p:last-child a {
border-radius: 2em;
border: 1px solid $color-primary;
box-sizing: border-box;
color: $color-primary;
font-size: 1.05em;
letter-spacing: 0.1em;
padding: 0.75em 2em;
text-decoration: none;
transition: all 0.15s ease;
margin-right: 1em;
display: inline-block;
&:last-child {
margin-right: 0;
background-color: $color-primary;
color: #fff;
&:hover {
opacity: .8;
color: inherit;
}
}
&:hover {
color: inherit;
}
}
}
+354
View File
@@ -0,0 +1,354 @@
* {
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
.progress {
background-color: $color-primary;
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
html, body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
kbd {
display: inline-block;
padding: 3px 5px;
margin-bottom : 3px;
font-size: 12px !important;
line-height: 12px;
vertical-align: middle;
border: solid 1px #ccc;
border-radius: 3px;
}
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
&.no-badge {
margin-right: 25px;
}
p {
margin: 0;
}
ul, li {
list-style: none;
display: inline-block;
margin: 0;
}
a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
&:hover {
color: $color-primary;
}
&.active {
color: $color-primary;
border-bottom: 2px solid $color-primary;
}
}
/* navbar dropdown */
li {
position: relative;
display: inline-block;
ul {
background-color: rgba($color-bg, .6);
border: 1px solid $color-primary;
opacity: 0;
overflow: hidden;
padding: 0;
position: absolute;
right: 1em;
top: 26px;
transform-origin: 100% 0%;
transform: scale(1, 0);
transition: opacity .4s ease-out, transform .2s ease;
transition-delay: .3s;
li {
display: block;
font-size: 14px;
margin: 0;
padding: 4px 10px;
white-space: nowrap;
}
a {
display: block;
margin: 0;
padding: 0;
&.active {
border-bottom: 0;
}
}
}
&:hover ul {
opacity: 1;
transform: scale(1, 1);
transition: opacity .4s ease, transform .2s ease-out;
transition-delay: 0;
}
}
}
/* github corner */
.github-corner {
position: fixed;
top: 0;
right: 0;
z-index: 1;
text-decoration: none;
border-bottom: 0;
&:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
svg {
color: $color-bg;
height: 80px;
width: 80px;
fill: $color-primary;
}
}
/* main */
main {
size: 100% 100%;
position: relative;
}
.anchor {
text-decoration: none;
transition: all .3s;
display: block;
&:hover {
text-decoration: underline;
}
}
/* sidebar */
.sidebar {
border-right: 1px solid rgba(0, 0, 0, .07);
overflow-y: auto;
padding-top: 40px;
position: absolute 0 * 0 0;
transition: transform 250ms ease-out;
width: $sidebar-width;
z-index: 20;
ul {
margin: 0;
padding: 0;
}
ul, ul li {
list-style: none;
}
ul li a {
display: block;
border-bottom: none;
}
ul li ul {
padding-left: 20px;
}
}
/* sidebar toggle */
.sidebar-toggle {
background-color: transparent;
border: 0;
bottom: 10px;
left: 10px;
outline: none;
position: absolute;
text-align: center;
transition: opacity .3s;
width: 30px;
z-index: 30;
outline: none;
&:hover {
opacity: .4;
}
span {
background-color: $color-primary;
display: block;
size: 16px 2px;
margin-bottom: 4px;
}
}
body.sticky {
.sidebar, .sidebar-toggle {
position: fixed;
}
}
/* main content */
.content {
position: absolute 0 0 0 $sidebar-width;
padding-top: 20px;
transition: left 250ms ease;
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 800px;
padding: 20px 15px 40px 15px;
> * {
box-sizing: border-box;
font-size: inherit;
}
>:first-child {
margin-top: 0!important;
}
}
.markdown-section table {
display: block;
width: 100%;
overflow: auto;
border-spacing: 0;
border-collapse: collapse;
margin-bottom: 1em;
}
.markdown-section th {
font-weight: bold;
padding: 6px 13px;
border: 1px solid #ddd;
}
.markdown-section td {
padding: 6px 13px;
border: 1px solid #ddd;
}
.markdown-section tr {
border-top: 1px solid #ccc;
&:nth-child(2n) {
background-color: #f8f8f8;
}
}
body.close {
.sidebar {
transform: translateX(-$sidebar-width);
}
.content {
left: 0;
}
}
@media (max-width: 600px) {
.github-corner, .sidebar-toggle, .sidebar {
position: fixed;
}
nav {
margin-top: 16px;
}
nav li ul {
top: 30px;
}
.sidebar {
left: -$sidebar-width;
transition: transform 250ms ease-out;
}
.content {
left: 0;
min-width: 100vw;
transition: transform 250ms ease;
}
nav, .github-corner {
transition: transform 250ms ease-out;
}
body.close {
.sidebar {
transform: translateX($sidebar-width);
}
.content {
transform: translateX($sidebar-width);
}
nav, .github-corner {
transform: translateX($sidebar-width);
}
}
.github-corner {
&:hover .octo-arm {
animation: none;
}
.octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
}
@keyframes octocat-wave {
0%,100% { transform: rotate(0); }
20%,60% { transform: rotate(-25deg); }
40%,80% { transform: rotate(10deg); }
}
+37 -187
View File
@@ -1,181 +1,42 @@
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
$color-primary: #0074D9;
$color-bg: #fff;
$sidebar-width: 16em;
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
}
nav a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
}
nav a:hover {
color: #0074D9;
}
nav a.active {
color: #0074D9;
border-bottom: 2px solid #0074D9;
}
/* github corner */
.github-corner {
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
.github-corner svg {
color: #fff;
fill: #0074D9;
height: 80px;
width: 80px;
}
.github-corner:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
@keyframes octocat-wave {
0%,100%{ transform: rotate(0); }
20%,60%{ transform: rotate(-25deg); }
40%,80%{ transform: rotate(10deg); }
}
@media (max-width: 500px) {
.github-corner:hover .octo-arm {
animation: none;
}
.github-corner .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
html, body {
height: 100%;
}
@import "basic/layout";
@import "basic/coverpage";
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-color: #fff;
color: #34495e;
font-family: 'Source Sans Pro', arial, sans-serif;
font-weight: 400px;
font-size: 15px;
letter-spacing: 0;
margin: 0;
}
/* main */
main {
height: 100%;
position: relative;
width: 100%;
}
/* sidebar */
.sidebar {
background-color: #fff;
border-right: 1px solid rgba(0,0,0,.07);
bottom: 0;
color: #364149;
overflow-y: auto;
position: absolute;
top: 0;
width: 14em;
z-index: 1;
padding-top: 40px;
}
background-color: $color-bg;
.sidebar ul {
margin: 0;
padding: 0;
}
.sidebar ul, .sidebar ul li {
list-style: none;
}
.sidebar a {
color: #666;
text-decoration: none;
}
.sidebar li {
list-style: none;
padding: 0.2em 0.2em 0.2em 1em;
margin: 0;
}
.sidebar .active {
background-color: #eee;
}
.sidebar .active a {
color: #333;
}
/* main content */
.content {
bottom: 0;
left: 14em;
overflow-y: auto;
position: absolute;
right: 0;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
@media screen and (max-width: 600px) {
.sidebar {
left: -14em;
a {
color: #666;
text-decoration: none;
}
.content {
left: 0;
li {
list-style: none;
padding: 0.2em 0 0.2em 1em;
margin: 0;
}
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 64em;
padding: 20px 15px 40px 15px;
}
ul li ul {
padding: 0;
}
.markdown-section * {
box-sizing: border-box;
-webkit-box-sizing: border-box;
font-size: inherit;
}
.active {
background-color: #eee;
.markdown-section>:first-child {
margin-top: 0!important;
a {
color: #333;
}
}
}
.markdown-section h1,
@@ -188,7 +49,7 @@ main {
}
.markdown-section a {
color: #0074D9;
color: $color-primary;
font-weight: 400;
}
@@ -196,6 +57,8 @@ main {
.markdown-section ul,
.markdown-section ol {
word-spacing: 0.05em;
line-height: 1.6em;
margin: 0 0 1em 0;
}
.markdown-section h1 {
@@ -237,13 +100,6 @@ main {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
margin: 0 0 1em 0;
line-height: 1.5;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5em;
@@ -256,7 +112,7 @@ main {
.markdown-section blockquote {
color: #858585;
border-left: 4px solid #0074D9;
border-left: 4px solid $color-primary;
margin: 2em 0;
padding-left: 20px;
}
@@ -288,8 +144,10 @@ main {
padding: 8px;
margin: 0 0 1em 0;
font-family: Inconsolata;
padding: 12px 10px 12px 12px;
padding: 0 10px 12px 0;
font-size: 16px;
overflow: auto;
word-wrap: normal;
}
/* code highlight */
@@ -362,9 +220,15 @@ main {
}
.markdown-section pre>code {
padding: 0;
display: block;
font-family: Inconsolata;
line-height: 1.2em;
overflow: inherit;
max-width: inherit;
position: relative;
background-color: #f8f8f8;
padding: 20px 0.8em 20px;
line-height: 1.1em;
border-radius: 2px;
}
.markdown-section code::after, .markdown-section code::before {
@@ -377,20 +241,6 @@ code .token {
-moz-osx-font-smoothing: initial;
}
pre code {
overflow-x: auto;
position: relative;
padding: 0;
background-color: #f8f8f8;
padding: 0.8em 0.8em 0.4em;
line-height: 1.1em;
border-radius: 2px;
}
.content img {
max-width: 100%;
}
.content span.light {
color: #7f8c8d;
}
+4
View File
@@ -0,0 +1,4 @@
$color-primary: #000;
$color-bg: #fff;
$sidebar-width: 300px;
@import "basic/layout";
+44 -199
View File
@@ -1,187 +1,49 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
$color-primary: #42b983;
$color-bg: #fff;
$sidebar-width: 300px;
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
}
nav a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
}
nav a:hover {
color: #42b983;
}
nav a.active {
color: #42b983;
border-bottom: 2px solid #42b983;
}
/* github corner */
.github-corner {
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
.github-corner svg {
color: #fff;
fill: #42b983;
height: 80px;
width: 80px;
}
.github-corner:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
@keyframes octocat-wave {
0%,100%{ transform: rotate(0); }
20%,60%{ transform: rotate(-25deg); }
40%,80%{ transform: rotate(10deg); }
}
@media (max-width: 500px) {
.github-corner:hover .octo-arm {
animation: none;
}
.github-corner .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
html, body {
height: 100%;
}
@import "basic/layout";
@import "basic/coverpage";
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-color: #fff;
background-color: $color-bg;
color: #34495e;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
}
/* main */
main {
height: 100%;
position: relative;
width: 100%;
}
/* sidebar */
.sidebar {
background-color: #fff;
border-right: 1px solid rgba(0,0,0,.07);
bottom: 0;
color: #364149;
overflow-y: auto;
position: absolute;
top: 0;
width: 300px;
z-index: 1;
padding-top: 40px;
}
background-color: $color-bg;
.sidebar ul {
margin: 0;
padding: 0;
}
.sidebar ul, .sidebar ul li {
list-style: none;
}
.sidebar ul li a {
color: #7f8c8d;
display: block;
padding: 6px 15px;
border-bottom: none;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-decoration: none;
}
.sidebar ul li a:hover {
text-decoration: underline;
}
.sidebar ul li.active>a {
color: #42b983;
font-weight: 500;
}
.sidebar ul li ul {
padding-left: 20px;
}
/* main content */
.content {
bottom: 0;
left: 300px;
overflow-y: auto;
position: absolute;
right: 0;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
@media screen and (max-width: 600px) {
.sidebar {
left: -300px;
li {
margin: 6px 15px;
}
.content {
left: 0;
ul li a {
color: #7f8c8d;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
ul li ul {
padding: 0;
}
ul li.active>a {
color: $color-primary;
font-weight: 600;
}
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 800px;
padding: 20px 15px 40px 15px;
}
.markdown-section * {
box-sizing: border-box;
-webkit-box-sizing: border-box;
font-size: inherit;
}
.markdown-section>:first-child {
margin-top: 0!important;
}
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
@@ -192,34 +54,25 @@ main {
}
.markdown-section a {
color: #42b983;
color: $color-primary;
font-weight: 600;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
word-spacing: 0.05em;
}
.markdown-section h1 {
margin: 0 0 1em;
font-size: 2em;
}
.markdown-section h2 {
border-bottom: 1px solid #ddd;
font-size: 1.75em;
margin: 45px 0 0.8em;
padding-bottom: 0.7em;
}
.markdown-section h3 {
margin: 52px 0 1.2em;
margin: 40px 0 .6em;
font-size: 1.5em;
}
.markdown-section h4 {
font-size: 1.25em;
}
@@ -244,6 +97,7 @@ main {
.markdown-section ul,
.markdown-section ol {
line-height: 1.6em;
word-spacing: 0.05em;
}
.markdown-section ul,
@@ -253,7 +107,7 @@ main {
.markdown-section blockquote {
color: #858585;
border-left: 4px solid #42b983;
border-left: 4px solid $color-primary;
margin: 2em 0;
padding-left: 20px;
}
@@ -283,13 +137,16 @@ main {
}
.markdown-section pre {
font-family: 'Roboto Mono', Monaco, courier, monospace;
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
font-family: 'Roboto Mono', Monaco, courier, monospace;
line-height: 1.5em;
margin: 1.2em 0;
padding: 1.2em 1.4em;
padding: 0 1.4em;
position: relative;
overflow: auto;
word-wrap: normal;
}
/* code highlight */
@@ -322,7 +179,7 @@ main {
}
.token.string {
color: #42b983;
color: $color-primary;
}
.token.selector {
@@ -344,7 +201,7 @@ main {
.token.control,
.token.directive,
.token.unit {
color: #42b983;
color: $color-primary;
}
.token.keyword {
@@ -399,8 +256,10 @@ main {
font-size: 0.8em;
line-height: inherit;
margin: 0 2px;
padding: 3px 5px;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit;
max-width: inherit;
}
.markdown-section code::after, .markdown-section code::before {
@@ -413,20 +272,10 @@ code .token {
-moz-osx-font-smoothing: initial;
}
pre code {
overflow-x: auto;
position: relative;
padding: 0;
background-color: #f8f8f8;
padding: 0.8em 0.8em 0.4em;
line-height: 1.1em;
border-radius: 2px;
}
pre code::after {
pre::after {
color: #ccc;
content: attr(data-lang);
font-size: 0.75em;
font-size: 0.6em;
font-weight: 600;
height: 15px;
line-height: 15px;
@@ -437,10 +286,6 @@ pre code::after {
top: 0;
}
.content img {
max-width: 100%;
}
.content span.light {
color: #7f8c8d;
}
+72
View File
@@ -0,0 +1,72 @@
/**
* 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 (tpl) {
return `<main>
${tpl}
<aside class="sidebar"></aside>
<section class="content">
<article class="markdown-section"></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" style="background: ${bgc}">
<div class="cover-main"></div>
<div class="mask"></div>
</section>`
}
export function toggle () {
return `<button class="sidebar-toggle">
<span></span><span></span><span></span>
</button>`
}
/**
* Render tree
* @param {Array} tree
* @param {String} tpl
* @return {String}
*/
export function tree (toc, tpl = '') {
if (!toc || !toc.length) return ''
toc.forEach(node => {
tpl += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
if (node.children) {
tpl += `<li><ul class="children">${tree(node.children)}</li></ul>`
}
})
return tpl
}
+136
View File
@@ -0,0 +1,136 @@
/**
* Simple ajax
* @param {String} url
* @param {String} [method=GET]
* @param {Function} [loading] handle loading
* @return {Promise}
*/
export function load (url, method = 'GET', loading) {
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.send()
return {
then: function (success, error = function () {}) {
if (loading) {
const id = setInterval(_ =>
loading({ step: Math.floor(Math.random() * 5 + 1) }),
500)
xhr.addEventListener('progress', loading)
xhr.addEventListener('loadend', evt => {
loading(evt)
clearInterval(id)
})
}
xhr.addEventListener('error', error)
xhr.addEventListener('load', ({ target }) => {
target.status >= 400 ? error(target) : success(target.response)
})
},
abort: () => xhr.readyState !== 4 && xhr.abort()
}
}
/**
* 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 || []
last[len].children.push(headline)
} else {
headlines.push(headline)
}
last[level] = headline
})
return headlines
}
/**
* camel to kebab
* @link https://github.com/bokuweb/kebab2camel/blob/master/index.js
* @param {String} str
* @return {String}
*/
export function camel2kebab (str) {
return str.replace(/([A-Z])/g, m => '-' + m.toLowerCase())
}
/**
* is nil
* @param {Object} object
* @return {Boolean}
*/
export function isNil (o) {
return o === null || o === undefined
}
let cacheRoute = null
let cacheHash = null
/**
* hash route
*/
export function getRoute () {
const loc = window.location
if (cacheHash === loc.hash && !isNil(cacheRoute)) return cacheRoute
let route = loc.hash.match(/^#\/([^#]+)/)
if (route && route.length === 2) {
route = route[1]
} else {
route = /^#\//.test(loc.hash) ? '' : loc.pathname
}
cacheRoute = route
cacheHash = loc.hash
return route
}
export function isMobile () {
return document.body.clientWidth <= 600
}
export function slugify (string) {
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g
const maintainCase = false
const replacement = '-'
slugify.occurrences = slugify.occurrences || {}
if (typeof string !== 'string') return ''
if (!maintainCase) string = string.toLowerCase()
let slug = string.trim()
.replace(re, '')
.replace(/\s/g, replacement)
let occurrences = slugify.occurrences[slug]
if (slugify.occurrences.hasOwnProperty(slug)) {
occurrences++
} else {
occurrences = 0
}
slugify.occurrences[slug] = occurrences
if (occurrences) {
slug = slug + '-' + occurrences
}
return slug
}