mirror of
https://github.com/wahyd4/docsify.git
synced 2026-08-09 13:26:34 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aedf16e433 | ||
|
|
41e4cb1b04 | ||
|
|
9d3cc89aa9 | ||
|
|
50f5fc2b22 | ||
|
|
3941304fda | ||
|
|
be6a97af92 | ||
|
|
55323a38b8 | ||
|
|
5b25e7daca | ||
|
|
a4bd5fd295 | ||
|
|
ac61bb0e75 | ||
|
|
9605c18fff | ||
|
|
dc35b051d3 | ||
|
|
0ca1ece188 | ||
|
|
fc140ef957 | ||
|
|
e1da2f8a84 | ||
|
|
eb5ff3e987 | ||
|
|
12e2479014 | ||
|
|
168d8475d5 | ||
|
|
7ba434e61d | ||
|
|
8cd386ae49 | ||
|
|
8c7e4d7866 | ||
|
|
cbaee21ded | ||
|
|
543cbbce81 | ||
|
|
72c34152d4 | ||
|
|
44708554f7 | ||
|
|
6e35f6481a | ||
|
|
115c80b2f2 | ||
|
|
addb34d38a | ||
|
|
1f12009a98 | ||
|
|
4abcb02824 | ||
|
|
d45e325d54 | ||
|
|
f2f37eec46 | ||
|
|
fef969f55d | ||
|
|
5cc9f0514c | ||
|
|
ae1ad735d5 | ||
|
|
a35a336d00 | ||
|
|
3ec7c89bbb | ||
|
|
89f0b1fcbd | ||
|
|
6f5bb1a527 | ||
|
|
98ec020c7a | ||
|
|
bb13ddd5df | ||
|
|
e69efb8954 | ||
|
|
0e5f28cf60 | ||
|
|
7db1f1034a | ||
|
|
b0320416a5 | ||
|
|
4a77b8a7f3 | ||
|
|
00b13c5e86 | ||
|
|
82b7b8226d | ||
|
|
c9739e71af | ||
|
|
bda1b76ba5 | ||
|
|
11f77cd434 | ||
|
|
6d42c6b04a | ||
|
|
46967e73bf | ||
|
|
ccdc3c855a | ||
|
|
7c4b0b7c74 | ||
|
|
98d1b19bea | ||
|
|
0709239c77 | ||
|
|
73cc43c6bd | ||
|
|
9d096b03a4 | ||
|
|
2af035ff45 | ||
|
|
3979f5cd3f | ||
|
|
9abae495ac | ||
|
|
d179ade7df | ||
|
|
d79c7655cd | ||
|
|
af5d2934e4 | ||
|
|
129bd4d3a0 | ||
|
|
abaf5c0849 | ||
|
|
336efb30cb | ||
|
|
fb8bf89d73 | ||
|
|
8630591bd2 | ||
|
|
c47ff83073 | ||
|
|
69e500bd33 | ||
|
|
000a1fcdf0 | ||
|
|
b84544960f | ||
|
|
28a004840d | ||
|
|
ff44152d12 | ||
|
|
b6bfad8579 | ||
|
|
e93f6b95ea | ||
|
|
5c58629e69 | ||
|
|
55826691eb | ||
|
|
64093c0567 | ||
|
|
c998fad98e | ||
|
|
0a2e1ddf11 | ||
|
|
4a7df99224 | ||
|
|
6c6f687925 | ||
|
|
ddc13aa280 | ||
|
|
f997280ab1 | ||
|
|
458e262a26 | ||
|
|
d971948f10 | ||
|
|
a309d3041e | ||
|
|
557a165349 | ||
|
|
d9eedf609e | ||
|
|
aa939147c6 | ||
|
|
67c1d0cd7d | ||
|
|
06892e6de4 | ||
|
|
439a1e6841 | ||
|
|
f540e3c4fc | ||
|
|
2ffef062db | ||
|
|
db7db5af8b | ||
|
|
a418096a29 | ||
|
|
90b490c9c1 | ||
|
|
7915027418 | ||
|
|
87b373b841 | ||
|
|
510ae37a04 | ||
|
|
ef53a07f49 | ||
|
|
9defe1bf7d | ||
|
|
b87f6ae5e8 | ||
|
|
b8b9dbc872 | ||
|
|
f7779b01d9 | ||
|
|
1c935b2fd7 | ||
|
|
114955558e | ||
|
|
847cf3b656 | ||
|
|
356b937d44 | ||
|
|
8df57f0bc2 | ||
|
|
73dfbf5be3 | ||
|
|
ecba3f1b05 | ||
|
|
e5452243b1 | ||
|
|
8b1000a4a5 | ||
|
|
897283418a | ||
|
|
7be6baae7a | ||
|
|
24ab3d4d10 | ||
|
|
424a243c5c | ||
|
|
9ce47c48af | ||
|
|
4e7485aa1f | ||
|
|
cb592e7bf0 | ||
|
|
3c01d1f82d | ||
|
|
00253d3148 | ||
|
|
d23881ba7c | ||
|
|
f0a99c0d1d | ||
|
|
b952a3a08c | ||
|
|
2bb8641303 | ||
|
|
66d7919fa9 | ||
|
|
580767bf78 | ||
|
|
d6b996f4c1 | ||
|
|
b4e0d54d7b | ||
|
|
b15b286c5c | ||
|
|
5ab86271c2 | ||
|
|
9638eee50d | ||
|
|
375a1dd3e1 | ||
|
|
3069ad3928 | ||
|
|
b287f57c86 | ||
|
|
e932ff66b9 | ||
|
|
7a10e4aecf | ||
|
|
41e7ef6863 | ||
|
|
7ce166501b | ||
|
|
b9aeb4a922 | ||
|
|
9ac8293c0a | ||
|
|
aa3121eca2 | ||
|
|
0e615abbdc | ||
|
|
cb2b191ba1 | ||
|
|
6adcfffba9 | ||
|
|
f165470265 | ||
|
|
bbb7b4a9d6 | ||
|
|
540095ee35 | ||
|
|
bd354094c0 | ||
|
|
6e81e66441 | ||
|
|
67f9083ff7 | ||
|
|
383b976ddd | ||
|
|
54ba970552 | ||
|
|
16623c9301 | ||
|
|
668c5ca714 | ||
|
|
d0861d7427 | ||
|
|
97669e0d28 | ||
|
|
a0408b7a38 | ||
|
|
f917da8214 | ||
|
|
64309beee9 | ||
|
|
4c8c0349e6 | ||
|
|
91b6720219 | ||
|
|
c93ba1ea16 | ||
|
|
4f5a150c17 | ||
|
|
801df6ae3e |
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"extends": ["vue"],
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"globals": {
|
||||
"XMLHttpRequest": true
|
||||
"$docsify": true
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
.DS_Store
|
||||
*.log
|
||||
node_modules
|
||||
yarn.lock
|
||||
/themes
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="/themes/vue.css">
|
||||
</head>
|
||||
<body class="">
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-auto2top data-sidebar-toggle data-router></script>
|
||||
</html>
|
||||
+199
-3
@@ -1,12 +1,208 @@
|
||||
## 2.2.1
|
||||
|
||||
> 2017-02-11
|
||||
|
||||
### Bug fixes
|
||||
- fix(search): crash when not content, fixed #68
|
||||
- fix(event): scroll active sidebar
|
||||
- fix(search): not work in mobile
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Features
|
||||
- Add `Google Analytics` plugin.
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-ga="UA-XXXXX-Y"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/ga.js"></script>
|
||||
```
|
||||
## 2.1.0
|
||||
### Features
|
||||
- Add search plugin
|
||||
```html
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
|
||||
```
|
||||
|
||||
### Bug fixes
|
||||
- fix sidebar style
|
||||
|
||||
## 2.0.3
|
||||
### Bug fixes
|
||||
- fix: rendering emojis
|
||||
- fix: css var polyfill
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Bug fixes
|
||||
- fix button style in cover page.
|
||||
|
||||
## 2.0.1
|
||||
### Bug fixes
|
||||
- border style.
|
||||
|
||||
## 2.0.0
|
||||
### Features
|
||||
- Customize the theme color
|
||||
|
||||
### Break change
|
||||
- Remove `data-router`, `data-sidebar`, `data-sidebar-toggle` APIs
|
||||
|
||||
## 1.10.5
|
||||
### Bug fixes
|
||||
- fix initialize the Vue instance
|
||||
|
||||
## 1.10.4
|
||||
### Bug fixes
|
||||
- fix execute script
|
||||
|
||||
## 1.10.3
|
||||
### Bug fixes
|
||||
- compatible vuep QingWei-Li/vuep/issues/2
|
||||
- fix sidebar scroll, fixed #63
|
||||
|
||||
## 1.10.2
|
||||
### Bug fixes
|
||||
- Fix render emojis again
|
||||
|
||||
## 1.10.1
|
||||
### Bug fixes
|
||||
- Fix render emojis
|
||||
|
||||
## 1.10.0
|
||||
### Features
|
||||
- Support emoji :laughing:
|
||||
|
||||
## 1.9.0
|
||||
|
||||
### Bug fixes
|
||||
- Destroys the vue instance when the route is changed
|
||||
|
||||
### Features
|
||||
- Add `!>` and `?>` doc helper.
|
||||
|
||||
### Break change
|
||||
- Remove `!` doc helper.
|
||||
|
||||
## 1.8.0
|
||||
### Bug fixes
|
||||
- Using `v-pre` skip compilation.
|
||||
|
||||
### Features
|
||||
- Execute script when vue exists.
|
||||
|
||||
## 1.7.4
|
||||
### Bug fixes
|
||||
- Fix bugs caused by the previous version
|
||||
|
||||
## 1.7.3
|
||||
### Bug fixes
|
||||
- Add `hr` style
|
||||
- Fixed option is an empty string
|
||||
|
||||
## 1.7.2
|
||||
### Bug fixes
|
||||
- Fix sidebar click event in mobile browser.
|
||||
|
||||
## 1.7.1
|
||||
### Bug fixes
|
||||
- Fix sidebar style in mobile browser.
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Bug fixes
|
||||
- Fixed custom cover background, fixed #52
|
||||
- Fixed sticky sidebar
|
||||
|
||||
## Features
|
||||
- Add `name` and `nameLink`
|
||||
|
||||
## 1.6.1
|
||||
### Bug fixes
|
||||
- Fixed sidebar bug when the coverpage exist
|
||||
|
||||
## 1.6.0
|
||||
### Features
|
||||
- Improve sidebar performance. The active item is automatically scrolled in the visible view.
|
||||
- New doc helper: `! `. e.g. `! content` will be rendered as `<p class="tip">content</p>`
|
||||
|
||||
## 1.5.2
|
||||
### Bug fixes
|
||||
- Fixed number at the beginning of the slug
|
||||
|
||||
## 1.5.1
|
||||
### Bug fixes
|
||||
- Remove HTML tag when handling slug
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Bug fixes
|
||||
- Fix slugify.
|
||||
- Fix nav highlight.
|
||||
|
||||
### Features
|
||||
- Initialize the configuration by `window.$docsify`.
|
||||
- Markdown parser is configurable.
|
||||
|
||||
## 1.4.3
|
||||
### Bug fixes
|
||||
- Tweak style.
|
||||
|
||||
## 1.4.2
|
||||
|
||||
### Bug fixes
|
||||
- Fix toggle button style.
|
||||
- Support `mailto`, `tel`, etc. href type
|
||||
- Fix scroll to top.
|
||||
|
||||
|
||||
## 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
|
||||
- headling can be cliked
|
||||
- add `<kbd>` style
|
||||
|
||||
|
||||
### break change
|
||||
- Navbar no longer fixed at the top
|
||||
|
||||
## 1.2.0
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 cinwell.li
|
||||
Copyright (c) 2016 - 2017 cinwell.li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
- [CLI](https://github.com/QingWei-Li/docsify-cli)
|
||||
|
||||
## Features
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Simple and lightweight (~13kB gzipped)
|
||||
- Multiple themes
|
||||
- Not build static html files
|
||||
- Support emoji :laughing:
|
||||
|
||||
## Quick start
|
||||
Create a `index.html` and using `hash router`.
|
||||
Create a `index.html`.
|
||||
|
||||
index.html
|
||||
|
||||
@@ -38,25 +39,32 @@ index.html
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="//unpkg.com/docsify" data-router></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
Or create a `404.html` and `README.md` into `/docs`. Just remove `data-router`
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
## CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
|
||||
## Browser Support
|
||||
|
||||
Modern browsers and Internet Explorer 9+.
|
||||
|
||||
## 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.
|
||||
- [puck](https://puck.zz173.com/) - A small & magical php framework.
|
||||
- [Samaritan](http://samaritan.stockdb.org) - An Algorithmic Trading Framework for Digital Currency.
|
||||
- [Vudash](http://vudash.github.io/vudash/) - Powerful, Flexible, Open Source dashboards for anything
|
||||
- [Trilogy](http://trilogy.js.org) - No-hassle SQLite with a Promise-based, document store style API.
|
||||
- [Mybatis-Plus](http://mp.baomidou.com/) - An enhanced toolkit of Mybatis to simplify development
|
||||
|
||||
## Similar projects
|
||||
- [docute](https://github.com/egoist/docute) - 📜 Effortlessly documentation done right
|
||||
- [docpress](https://github.com/docpress/docpress) - Documentation website generator
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -69,11 +77,19 @@ These open-source projects are using docsify to generate their sites. Pull reque
|
||||
|
||||
## Development
|
||||
|
||||
```shell
|
||||
```bash
|
||||
npm i && npm run dev
|
||||
open http://localhost:3000
|
||||
```
|
||||
|
||||
## More Language Highlight
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-bash.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-php.js"></script>
|
||||
```
|
||||
|
||||
## License
|
||||
MIT
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ var fs = require('fs')
|
||||
http.createServer(function (req, res) {
|
||||
serveStatic('.')(req, res, function () {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' })
|
||||
res.end(fs.readFileSync('404.dev.html'))
|
||||
res.end(fs.readFileSync('dev.html'))
|
||||
})
|
||||
}).listen(3000, '0.0.0.0')
|
||||
|
||||
|
||||
+11
-2
@@ -2,8 +2,17 @@ var fs = require('fs')
|
||||
var cssnano = require('cssnano').process
|
||||
var resolve = require('path').resolve
|
||||
var postcss = require('postcss')
|
||||
var isProd = process.argv[process.argv.length - 1] !== '--dev'
|
||||
|
||||
var processor = postcss([require('postcss-salad')])
|
||||
var processor = postcss([require('postcss-salad')({
|
||||
features: {
|
||||
precss: {
|
||||
properties: {
|
||||
preserve: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})])
|
||||
|
||||
var saveMin = function (file, content) {
|
||||
fs.writeFileSync(resolve(__dirname, '../lib/themes/', file), content)
|
||||
@@ -26,7 +35,7 @@ list.forEach(function (file) {
|
||||
.then(function (result) {
|
||||
save(file, result.css)
|
||||
console.log('salad - ' + file)
|
||||
cssnano(loadLib(file))
|
||||
isProd && cssnano(loadLib(file))
|
||||
.then(function (result) {
|
||||
saveMin(file, result.css)
|
||||
console.log('cssnao - ' + file)
|
||||
|
||||
+25
-2
@@ -3,6 +3,7 @@ var buble = require('rollup-plugin-buble')
|
||||
var commonjs = require('rollup-plugin-commonjs')
|
||||
var nodeResolve = require('rollup-plugin-node-resolve')
|
||||
var uglify = require('rollup-plugin-uglify')
|
||||
var isProd = process.argv[process.argv.length - 1] !== '--dev'
|
||||
|
||||
var build = function (opts) {
|
||||
rollup
|
||||
@@ -16,7 +17,7 @@ var build = function (opts) {
|
||||
console.log(dest)
|
||||
bundle.write({
|
||||
format: 'iife',
|
||||
moduleName: opts.moduleName || 'Docsify',
|
||||
moduleName: opts.moduleName || 'D',
|
||||
dest: dest
|
||||
})
|
||||
})
|
||||
@@ -30,8 +31,30 @@ build({
|
||||
output: 'docsify.js',
|
||||
plugins: [commonjs(), nodeResolve()]
|
||||
})
|
||||
build({
|
||||
isProd && build({
|
||||
entry: 'index.js',
|
||||
output: 'docsify.min.js',
|
||||
plugins: [commonjs(), nodeResolve(), uglify()]
|
||||
})
|
||||
build({
|
||||
entry: 'plugins/search.js',
|
||||
output: 'plugins/search.js',
|
||||
moduleName: 'D.Search'
|
||||
})
|
||||
isProd && build({
|
||||
entry: 'plugins/search.js',
|
||||
output: 'plugins/search.min.js',
|
||||
moduleName: 'D.Search',
|
||||
plugins: [uglify()]
|
||||
})
|
||||
build({
|
||||
entry: 'plugins/ga.js',
|
||||
output: 'plugins/ga.js',
|
||||
moduleName: 'D.GA'
|
||||
})
|
||||
isProd && build({
|
||||
entry: 'plugins/ga.js',
|
||||
output: 'plugins/ga.min.js',
|
||||
moduleName: 'D.GA',
|
||||
plugins: [uglify()]
|
||||
})
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="/themes/vue.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="#/">En</a>
|
||||
<a href="#/zh-cn">中文</a>
|
||||
</nav>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
search: {
|
||||
maxAge: 0
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="/lib/docsify.js"
|
||||
data-repo="qingwei-li/docsify"
|
||||
data-name="docsify"
|
||||
data-base-path="docs/"
|
||||
data-auto2top></script>
|
||||
<script src="/lib/plugins/search.js"></script>
|
||||
</html>
|
||||
+307
-76
@@ -2,13 +2,13 @@
|
||||
|
||||
### Create a project
|
||||
First create a project, then create a `docs` folder
|
||||
```shell
|
||||
```bash
|
||||
mkdir my-project && cd my-project
|
||||
mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### Create entry file
|
||||
Create a `404.html` file
|
||||
Create a `index.html` file
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
@@ -26,41 +26,45 @@ Create a `404.html` file
|
||||
|
||||
Create `README.md` as the main page
|
||||
|
||||
```
|
||||
```markdown
|
||||
# Title
|
||||
|
||||
## balabala
|
||||
## blabla
|
||||
```
|
||||
|
||||
### Deploy!
|
||||
Push and open the **GitHub Pages** feature
|
||||
Push code and activate **GitHub Pages** via your repo's settings
|
||||

|
||||
|
||||
## CLI
|
||||
|
||||
Easy to setup and preivew a docs.
|
||||
Easy to setup and preview a docs.
|
||||
|
||||
### Install
|
||||
```shell
|
||||
```bash
|
||||
npm i docsify-cli -g
|
||||
```
|
||||
|
||||
### Setup
|
||||
|
||||
Setup a boilerplate docs
|
||||
```shell
|
||||
```bash
|
||||
docsify init docs
|
||||
```
|
||||
|
||||
### Preview
|
||||
Preview and serve your docs using
|
||||
```shell
|
||||
```bash
|
||||
docsify serve docs
|
||||
```
|
||||
|
||||
Read more [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
|
||||
|
||||
## Themes
|
||||
|
||||
|
||||
## More
|
||||
|
||||
### Themes
|
||||
Currently available `vue.css` and `buble.css`
|
||||
```html
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
|
||||
@@ -74,22 +78,19 @@ Minified files
|
||||
<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>
|
||||
```
|
||||
|
||||
|
||||
### CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
@@ -97,7 +98,7 @@ Code in `404.html`
|
||||
|
||||
### Cover Page
|
||||
|
||||
Through the markdown can generate a cover page. create a `_coverpage.md` and set `data-coverpage` in script tag.
|
||||
Generate a cover page with markdown. Create a `_coverpage.md` and set `data-coverpage` in the script tag.
|
||||
|
||||
```markdown
|
||||

|
||||
@@ -115,66 +116,154 @@ Through the markdown can generate a cover page. create a `_coverpage.md` and set
|
||||
[Get Started](#quick-start)
|
||||
```
|
||||
|
||||
#### Custom background
|
||||
Currently the background of the cover page is generated randomly. We can customize the background color, or add a background image.
|
||||
|
||||
### Options
|
||||
```markdown
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
#### repo
|
||||
> xxx
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
|
||||
<!-- background image -->
|
||||

|
||||
<!-- background color -->
|
||||

|
||||
```
|
||||
|
||||
### Markdown parser
|
||||
|
||||
Docsify uses [marked](https://github.com/chjj/marked) to parse markdown. We can configure it
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
markdown: {
|
||||
smartypants: true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And it can even be customized
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
markdown: function(marked) {
|
||||
// ...
|
||||
|
||||
return marked
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Doc Helpers
|
||||
#### p.tip
|
||||
|
||||
`!> ` add your content will rendered as `<p class="tip">content</p>`
|
||||
|
||||
```markdown
|
||||
!> Important **information**
|
||||
```
|
||||
|
||||
It will be rendered
|
||||
|
||||
```html
|
||||
<p class="tip">Important <strong>information</strong></p>
|
||||
```
|
||||
|
||||
e.g.
|
||||
|
||||
!> Important **information**
|
||||
|
||||
|
||||
#### p.warn
|
||||
|
||||
```markdown
|
||||
?> todo info
|
||||
```
|
||||
|
||||
?> todo info
|
||||
|
||||
### Combining Vue
|
||||
We can write the Vue syntax directly in the markdown file, when the Vue library is loaded into `index.html`. Default will automatically initialize a Vue instance, of course, we can also manually.
|
||||
|
||||
index.html
|
||||
```html
|
||||
<script src="//unpkg.com/vue"></script>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
```
|
||||
|
||||
```markdown
|
||||
<ul>
|
||||
<li v-for="i in 10">{{ i }}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
Manual initialization
|
||||
|
||||
```markdown
|
||||
<div>
|
||||
<input type="text" v-model="msg">
|
||||
<p>Hello, {{ msg }}</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: 'main',
|
||||
data: { msg: 'Docsify' }
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
You can add configurations in the script tag attributes or with `window.$docsify`.
|
||||
|
||||
### 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.
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
repo: 'your/repo'
|
||||
}
|
||||
```
|
||||
|
||||
### max-level
|
||||
TOC level.
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-max-level="6"></script>
|
||||
```
|
||||
|
||||
#### el
|
||||
```js
|
||||
window.$docsify = {
|
||||
maxLevel: 6
|
||||
}
|
||||
```
|
||||
|
||||
### 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>
|
||||
```js
|
||||
window.$docsify = {
|
||||
el: '#app'
|
||||
}
|
||||
```
|
||||
|
||||
#### sidebar
|
||||
### load-sidebar
|
||||
|
||||
Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on the `data-sidebar`.
|
||||
|
||||

|
||||
|
||||
```html
|
||||
<script>
|
||||
window.sidebar = [
|
||||
{ slug: '/', title: 'Home' },
|
||||
{
|
||||
slug: '/pageA',
|
||||
title: 'page A',
|
||||
children: [
|
||||
{ slug: '/pageA/childrenB', title: 'children B' }
|
||||
]
|
||||
},
|
||||
{ slug: '/PageC', title: 'Page C' }
|
||||
]
|
||||
</script>
|
||||
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
|
||||
```
|
||||
|
||||
|
||||
#### load-sidebar
|
||||
|
||||
Load sidebar markdown file. If it is configured, load the current directory `_sidebar.md` by default. If the file isn't exist, sidebar will appear TOC.
|
||||
** you should add `.nojekyll` into docs folder, to prevent GitHub Pages from ignoring the `_sidebar.md`**
|
||||
Load sidebar markdown file. If it is configured, load the current directory `_sidebar.md` by default. If the file doesn't exist, the 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>
|
||||
@@ -186,6 +275,12 @@ You can specify a file:
|
||||
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
loadSidebar: '_sidebar.md'
|
||||
}
|
||||
```
|
||||
|
||||
The contents of the file can be:
|
||||
|
||||
```markdown
|
||||
@@ -195,16 +290,27 @@ The contents of the file can be:
|
||||
- [Getting Started](/getting-started)
|
||||
- [Dynamic Route Matching](/dynamic-matching)
|
||||
- [Nested Routes](/nested-routes)
|
||||
- [Programmatic Navigation](/navigation)
|
||||
- [Named Routes](/named-routes)
|
||||
- [Named Views](/named-views)
|
||||
- [Redirect and Alias](/redirect-and-alias)
|
||||
- [HTML5 History Mode](/history-mode)
|
||||
```
|
||||
|
||||
#### load-navbar
|
||||
### sub-max-level
|
||||
|
||||
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
|
||||
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>
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
maxSubLevel: 4
|
||||
}
|
||||
```
|
||||
|
||||
### 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>
|
||||
@@ -216,6 +322,12 @@ You can specify a file:
|
||||
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
loadNavbar: '_navbar.md'
|
||||
}
|
||||
```
|
||||
|
||||
The contents of the file can be:
|
||||
|
||||
```markdown
|
||||
@@ -232,26 +344,28 @@ If you write a sub level list, it will generate a dropdown list.
|
||||
- [chinese](/zh-cn)
|
||||
```
|
||||
|
||||
#### router
|
||||
|
||||
Hash router. You can replace `404.html` with `index.html`.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-router></script>
|
||||
```
|
||||
|
||||
#### auto2top
|
||||
### auto2top
|
||||
|
||||
Scroll to the top on changing hash.
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-auto2top></script>
|
||||
<!-- Set offset top -->
|
||||
<script src="/lib/docsify.js" data-auto2top="50"></script>
|
||||
```
|
||||
|
||||
#### homepage
|
||||
```js
|
||||
window.$docsify = {
|
||||
auto2top: true,
|
||||
// auto2top: 50
|
||||
}
|
||||
```
|
||||
|
||||
`README.md` will be render as homepage for your website in 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`):
|
||||
### 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.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-homepage="https://raw.githubusercontent.com/QingWei-Li/docsify/master/README.md"></script>
|
||||
@@ -260,7 +374,14 @@ Scroll to the top on changing hash.
|
||||
```
|
||||
|
||||
|
||||
#### basePath
|
||||
```js
|
||||
window.$docsify = {
|
||||
homepage: true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### base-path
|
||||
|
||||
If your HTML entry file and the markdown files are in different directories, we can use:
|
||||
|
||||
@@ -272,7 +393,14 @@ If your HTML entry file and the markdown files are in different directories, we
|
||||
```
|
||||
|
||||
|
||||
#### coverpage
|
||||
```js
|
||||
window.$docsify = {
|
||||
basePath: '/base/'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### coverpage
|
||||
|
||||
Generate cover page.
|
||||
|
||||
@@ -280,4 +408,107 @@ Generate cover page.
|
||||
<script src="/lib/docsify.js" data-coverpage></script>
|
||||
<!-- or -->
|
||||
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
|
||||
```
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
coverpage: true
|
||||
}
|
||||
```
|
||||
|
||||
### name
|
||||
|
||||
Project name. It is displayed in the sidebar.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-name="docsify"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
name: 'docsify'
|
||||
}
|
||||
```
|
||||
|
||||
### name-link
|
||||
|
||||
Name link. The default value is `window.location.pathname`.
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-name-link="/"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
nameLink: '/'
|
||||
}
|
||||
```
|
||||
|
||||
### theme-color
|
||||
|
||||
Customize the theme color.
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-theme-color="#3F51B5"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
themeColor: '#3F51B5'
|
||||
}
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
### Full Text Search
|
||||
|
||||
If a document can have a search, can enhance some user experience. Installing the search plugin is easy. Such as
|
||||
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
|
||||
```
|
||||
|
||||
By default, the hyperlink on the current page is recognized and the content is saved in `localStorage`. You can also specify the path to the files.
|
||||
|
||||
!> Configure the content before the plugin is installed.
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
search: 'auto', // default
|
||||
|
||||
search : [
|
||||
'/', // => /README.md
|
||||
'/guide', // => /guide.md
|
||||
'/get-started', // => /get-started.md
|
||||
'/zh-cn/', // => /zh-cn/README.md
|
||||
],
|
||||
|
||||
// Full configuration
|
||||
search: {
|
||||
maxAge: 86400000, // Expiration time, the default one day
|
||||
paths: [], // or 'auto'
|
||||
placeholder: 'Type to search'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Google Analytics
|
||||
|
||||
Install the plugin and configure the track id.
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-ga="UA-XXXXX-Y"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/ga.js"></script>
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
ga: 'UA-XXXXX-Y'
|
||||
}
|
||||
```
|
||||
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||

|
||||
|
||||
# docsify <small>1.3.0</small>
|
||||
# docsify <small>2.2.1</small>
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Multiple themes
|
||||
- Simple and lightweight (~13kB gzipped)
|
||||
- Not build static html files
|
||||
- Support emoji :laughing:
|
||||
- Multiple themes
|
||||
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
|
||||
+6
-4
@@ -6,7 +6,7 @@
|
||||
<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="//cdn.jsdelivr.net/docsify/latest/lib/themes/vue.css">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
@@ -16,9 +16,11 @@
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script
|
||||
src="//cdn.jsdelivr.net/docsify/latest/lib/docsify.min.js"
|
||||
src="//unpkg.com/docsify/lib/docsify.min.js"
|
||||
data-max-level="4"
|
||||
data-sidebar-toggle
|
||||
data-coverpage
|
||||
data-router></script>
|
||||
data-name="docsify"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
|
||||
</html>
|
||||
|
||||
+301
-67
@@ -8,13 +8,13 @@
|
||||
|
||||
### 创建项目
|
||||
新建一个空项目,接着创建一个 `docs` 目录并进入到 docs 目录下
|
||||
```shell
|
||||
```bash
|
||||
mkdir my-project && cd my-project
|
||||
mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### 创建入口文件
|
||||
创建一个 `404.html` 文件,内容为
|
||||
创建一个 `index.html` 文件,内容为
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -46,27 +46,30 @@ mkdir docs && cd docs
|
||||
方便快速创建文档目录,会读取项目的 `package.json` 里的选项作为 docsify 的配置,支持本地预览。
|
||||
|
||||
### 安装
|
||||
```shell
|
||||
```bash
|
||||
npm i docsify-cli -g
|
||||
```
|
||||
|
||||
### 初始化文档
|
||||
|
||||
默认初始化在当前目录,推荐将文档放在 `docs` 目录下
|
||||
```shell
|
||||
```bash
|
||||
docsify init docs
|
||||
```
|
||||
|
||||
### 启动本地服务
|
||||
启动一个 server 方便预览,打开 http://localhost:3000
|
||||
```shell
|
||||
```bash
|
||||
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">
|
||||
@@ -79,22 +82,21 @@ docsify serve docs
|
||||
<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>
|
||||
```
|
||||
|
||||
|
||||
|
||||
### CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
@@ -120,61 +122,156 @@ docsify serve docs
|
||||
```
|
||||
|
||||
|
||||
#### 自定义封面背景
|
||||
默认的背景是随机生成的,你可以自定义背景色或者背景图片。只需要在文档末尾用添加图片的 Markdown 语法
|
||||
|
||||
### 配置参数
|
||||
```markdown
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
#### repo
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
|
||||
> xxx
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
|
||||
<!-- 背景图片 -->
|
||||

|
||||
<!-- 背景色 -->
|
||||

|
||||
```
|
||||
|
||||
### 自定义 Markdown parser
|
||||
|
||||
默认使用 [marked](https://github.com/chjj/marked) 处理 markdown 部分,你可以修改默认配置
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
markdown: {
|
||||
smartypants: true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
甚至可以完全定制化
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
markdown: function(marked) {
|
||||
// ...
|
||||
|
||||
return marked
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 文档助手
|
||||
#### 内置「提示」语法
|
||||
|
||||
`!>`后面接内容,会渲染成带 tip 类名的段落。
|
||||
|
||||
```markdown
|
||||
!> 提示信息,**支持其他 markdown 语法**
|
||||
```
|
||||
|
||||
将被渲染成
|
||||
|
||||
```html
|
||||
<p class="tip">提示信息<strong>支持其他 markdown 语法</strong></p>
|
||||
```
|
||||
|
||||
效果
|
||||
|
||||
!> 适合显示醒目的内容
|
||||
|
||||
#### 内置「警示」语法
|
||||
|
||||
`?>`后面接内容,会渲染成带 warn 类名的段落。
|
||||
|
||||
```markdown
|
||||
?> 警示内容样式
|
||||
```
|
||||
|
||||
效果
|
||||
|
||||
?> 警示内容样式
|
||||
|
||||
### 结合 Vue
|
||||
|
||||
`index.html` 内引入 Vue 后,可以在文档里直接写 Vue 语法。默认会自己初始化一个 Vue 示例,当然我们也可以手动初始化一个实例。
|
||||
|
||||
index.html
|
||||
```html
|
||||
<script src="//unpkg.com/vue"></script>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
```
|
||||
|
||||
```markdown
|
||||
<ul>
|
||||
<li v-for="i in 10">{{ i }}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
手动初始化示例
|
||||
|
||||
```markdown
|
||||
<div>
|
||||
<input type="text" v-model="msg">
|
||||
<p>Hello, {{ msg }}</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: 'main',
|
||||
data: { msg: 'Docsify' }
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## 配置参数
|
||||
|
||||
你可以通过在标签上添加属性的方式,或者给 `window.$docsify` 传配置信息。
|
||||
|
||||
### repo
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `index.html` 里的 script 改成
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
|
||||
```
|
||||
|
||||
#### max-level
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
repo: 'your/repo'
|
||||
}
|
||||
```
|
||||
|
||||
### max-level
|
||||
目录最大展开层级,默认值为 6
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-max-level="6"></script>
|
||||
```
|
||||
|
||||
#### el
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
maxLevel: 6
|
||||
}
|
||||
```
|
||||
|
||||
### 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>
|
||||
```js
|
||||
window.$docsify = {
|
||||
el: '#app'
|
||||
}
|
||||
```
|
||||
|
||||
#### sidebar
|
||||
|
||||
设置后 TOC 功能将不可用,适合导航较多的文档,`data-sidebar` 传入全局变量名。
|
||||
|
||||

|
||||
|
||||
```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
|
||||
|
||||
读取侧边栏配置文件,如果配置,默认加载当前目录下的 `_sidebar.md`。如果文件不存在,会显示 TOC 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
|
||||
**如果用 `_` 开头作为文件名,你应该在文档目录下添加 `.nojekyll`,阻止 GitHub Pages 忽略下划线开头的文件。**
|
||||
@@ -183,12 +280,19 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-load-sidebar></script>
|
||||
```
|
||||
|
||||
|
||||
你可以指定侧边栏文件名
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
loadSidebar: '_sidebar.md'
|
||||
}
|
||||
```
|
||||
|
||||
`_sidebar.md` 的内容可以是这样的
|
||||
|
||||
```markdown
|
||||
@@ -198,14 +302,24 @@ Sidebar 开关按钮
|
||||
- [Getting Started](/getting-started)
|
||||
- [Dynamic Route Matching](/dynamic-matching)
|
||||
- [Nested Routes](/nested-routes)
|
||||
- [Programmatic Navigation](/navigation)
|
||||
- [Named Routes](/named-routes)
|
||||
- [Named Views](/named-views)
|
||||
- [Redirect and Alias](/redirect-and-alias)
|
||||
- [HTML5 History Mode](/history-mode)
|
||||
```
|
||||
|
||||
#### load-navbar
|
||||
### sub-max-level
|
||||
|
||||
显示 TOC 在自定义的侧边栏里,默认最大显示 0 层。
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
maxSubLevel: 4
|
||||
}
|
||||
```
|
||||
|
||||
### load-navbar
|
||||
|
||||
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
|
||||
|
||||
@@ -219,6 +333,12 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
loadNavbar: '_navbar.md'
|
||||
}
|
||||
```
|
||||
|
||||
`_navbar.md` 的内容可以是这样
|
||||
|
||||
```markdown
|
||||
@@ -235,15 +355,7 @@ Sidebar 开关按钮
|
||||
```
|
||||
|
||||
|
||||
#### router
|
||||
|
||||
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-router></script>
|
||||
```
|
||||
|
||||
#### auto2top
|
||||
### auto2top
|
||||
|
||||
切换路由时自动跳转到页面顶部
|
||||
|
||||
@@ -252,9 +364,15 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-auto2top></script>
|
||||
```
|
||||
|
||||
#### homepage
|
||||
```js
|
||||
window.$docsify = {
|
||||
auto2top: true
|
||||
}
|
||||
```
|
||||
|
||||
默认情况下网站会将根目录下 `README.md` 作为首页渲染,但是有些时候我们想指定其他文件,甚至想直接将 repo 下的 README 作为首页。你可以这样做(需要设置 `data-router`):
|
||||
### homepage
|
||||
|
||||
默认情况下网站会将根目录下 `README.md` 作为首页渲染,但是有些时候我们想指定其他文件,甚至想直接将 repo 下的 README 作为首页。
|
||||
|
||||
|
||||
```html
|
||||
@@ -263,7 +381,13 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
|
||||
```
|
||||
|
||||
#### basePath
|
||||
```js
|
||||
window.$docsify = {
|
||||
homepage: true
|
||||
}
|
||||
```
|
||||
|
||||
### base-path
|
||||
|
||||
指定加载文档的路径,如果你的 HTML 入口文件和文档是放在不同地方,你可以设置:
|
||||
|
||||
@@ -274,9 +398,16 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
|
||||
```
|
||||
|
||||
#### coverpage
|
||||
|
||||
生成封面,参考 [#封面](#封面).
|
||||
```js
|
||||
window.$docsify = {
|
||||
basePath: '/base/'
|
||||
}
|
||||
```
|
||||
|
||||
### coverpage
|
||||
|
||||
生成封面,参考 [#封面](/zh-cn#封面).
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-coverpage></script>
|
||||
@@ -284,3 +415,106 @@ Sidebar 开关按钮
|
||||
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
|
||||
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
coverpage: true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### name
|
||||
|
||||
项目名,将显示在侧边栏。
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-name="docsify"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
name: 'docsify'
|
||||
}
|
||||
```
|
||||
|
||||
### name-link
|
||||
|
||||
项目名链接,默认为 `window.location.pathname`。
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-name-link="/"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
nameLink: '/'
|
||||
}
|
||||
```
|
||||
|
||||
### theme-color
|
||||
|
||||
自定义主题色。
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-theme-color="#3F51B5"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
themeColor: '#3F51B5'
|
||||
}
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
### 全文检索 - search
|
||||
|
||||
一份文档如果能有搜索功能会提升一些用户体验,加载搜索插件也很简单,直接引入就自动安装并启用。默认情况下会自动分析当前页面上的超链接,获取内容后建立索引并存储在 `localStorage` 里,默认过期时间为一天,当然这是可配置的。
|
||||
|
||||
自动识别的方式不一定能识别完整或者如果你想指定某些文件可索引,你可以自己指定文件的路径。
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
|
||||
```
|
||||
|
||||
!> 配置要在 docsify 引入之前
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
search: 'auto', // default
|
||||
|
||||
search : [
|
||||
'/', // => /README.md
|
||||
'/guide', // => /guide.md
|
||||
'/get-started', // => /get-started.md
|
||||
'/zh-cn/', // => /zh-cn/README.md
|
||||
],
|
||||
|
||||
// Full configuration
|
||||
search: {
|
||||
maxAge: 86400000, // Expiration time, the default one day
|
||||
paths: [], // or 'auto'
|
||||
placeholder: 'Type to search'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Google Analytics
|
||||
|
||||
安装插件并且配置 track id。
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-ga="UA-XXXXX-Y"></script>
|
||||
<script src="//unpkg.com/docsify/lib/plugins/ga.js"></script>
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
ga: 'UA-XXXXX-Y'
|
||||
}
|
||||
```
|
||||
|
||||
+430
-195
@@ -1,4 +1,4 @@
|
||||
var Docsify = (function () {
|
||||
var D = (function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ function getRoute () {
|
||||
var loc = window.location;
|
||||
if (cacheHash === loc.hash && !isNil(cacheRoute$1)) { return cacheRoute$1 }
|
||||
|
||||
var route = loc.hash.match(/^#\/([^#]+)/);
|
||||
var route = loc.hash.replace(/%23/g, '#').match(/^#\/([^#]+)/);
|
||||
|
||||
if (route && route.length === 2) {
|
||||
route = route[1];
|
||||
@@ -114,6 +114,81 @@ 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(/<[^>\d]+>/g, '')
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, replacement)
|
||||
.replace(/-+/g, replacement)
|
||||
.replace(/^(\d)/, '_$1');
|
||||
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
|
||||
}
|
||||
|
||||
slugify.clear = function () {
|
||||
slugify.occurrences = {};
|
||||
};
|
||||
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var merge = Object.assign || function (to) {
|
||||
var arguments$1 = arguments;
|
||||
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var from = Object(arguments$1[i]);
|
||||
|
||||
for (var key in from) {
|
||||
if (hasOwnProperty.call(from, key)) {
|
||||
to[key] = from[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to
|
||||
};
|
||||
|
||||
function emojify (text) {
|
||||
return text
|
||||
.replace(/<(pre|template)[^>]*?>([\s\S]+)<\/(pre|template)>/g, function (match) { return match.replace(/:/g, '__colon__'); })
|
||||
.replace(/:(\w*?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
|
||||
.replace(/__colon__/g, ':')
|
||||
}
|
||||
|
||||
|
||||
|
||||
var utils = Object.freeze({
|
||||
load: load,
|
||||
genTree: genTree,
|
||||
camel2kebab: camel2kebab,
|
||||
isNil: isNil,
|
||||
getRoute: getRoute,
|
||||
isMobile: isMobile,
|
||||
slugify: slugify,
|
||||
merge: merge,
|
||||
emojify: emojify
|
||||
});
|
||||
|
||||
/**
|
||||
* Active sidebar when scroll
|
||||
* @link https://buble.surge.sh/
|
||||
@@ -121,42 +196,75 @@ function isMobile () {
|
||||
function scrollActiveSidebar () {
|
||||
if (isMobile()) { return }
|
||||
|
||||
var hoveredOverSidebar = false;
|
||||
var anchors = document.querySelectorAll('.anchor');
|
||||
var sidebar = document.querySelector('.sidebar');
|
||||
var sidebarContainer = sidebar.querySelector('.sidebar-nav');
|
||||
var sidebarHeight = sidebar.clientHeight;
|
||||
|
||||
var nav = {};
|
||||
var lis = document.querySelectorAll('.sidebar li');
|
||||
var active = null;
|
||||
var lis = sidebar.querySelectorAll('li');
|
||||
var active = sidebar.querySelector('li.active');
|
||||
|
||||
for (var i = 0, len = lis.length; i < len; i += 1) {
|
||||
var li = lis[i];
|
||||
var href = li.querySelector('a').getAttribute('href');
|
||||
|
||||
if (href !== '/') { href = href.match(/#([^#]+)$/g)[0].slice(1); }
|
||||
if (href !== '/') {
|
||||
var match = href.match('#([^#]+)$');
|
||||
if (match && match.length) { href = match[0].slice(1); }
|
||||
}
|
||||
|
||||
nav[decodeURIComponent(href)] = li;
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
var top = document.body.scrollTop;
|
||||
var last;
|
||||
|
||||
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
|
||||
if (node.offsetTop > top) {
|
||||
if (!last) { last = node; }
|
||||
break
|
||||
} else {
|
||||
last = node;
|
||||
}
|
||||
}
|
||||
if (!last) { return }
|
||||
var li = nav[last.getAttribute('data-id')];
|
||||
|
||||
if (!li || li === active) { return }
|
||||
if (active) { active.classList.remove('active'); }
|
||||
|
||||
li.classList.add('active');
|
||||
active = li;
|
||||
|
||||
// scroll into view
|
||||
// https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297
|
||||
if (!hoveredOverSidebar && !sticky.noSticky) {
|
||||
var currentPageOffset = 0;
|
||||
var currentActiveOffset = active.offsetTop + active.clientHeight + 40;
|
||||
var currentActiveIsInView = (
|
||||
active.offsetTop >= sidebarContainer.scrollTop &&
|
||||
currentActiveOffset <= sidebarContainer.scrollTop + sidebarHeight
|
||||
);
|
||||
var linkNotFurtherThanSidebarHeight = currentActiveOffset - currentPageOffset < sidebarHeight;
|
||||
var newScrollTop = currentActiveIsInView
|
||||
? sidebarContainer.scrollTop
|
||||
: linkNotFurtherThanSidebarHeight
|
||||
? currentPageOffset
|
||||
: currentActiveOffset - sidebarHeight;
|
||||
|
||||
sidebar.scrollTop = newScrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', highlight);
|
||||
window.addEventListener('scroll', highlight);
|
||||
highlight();
|
||||
sidebar.addEventListener('mouseover', function () { hoveredOverSidebar = true; });
|
||||
sidebar.addEventListener('mouseleave', function () { hoveredOverSidebar = false; });
|
||||
}
|
||||
|
||||
function scrollIntoView () {
|
||||
@@ -164,7 +272,9 @@ function scrollIntoView () {
|
||||
if (!id || !id.length) { return }
|
||||
var section = document.querySelector(decodeURIComponent(id[0]));
|
||||
|
||||
if (section) { section.scrollIntoView(); }
|
||||
if (section) { setTimeout(function () { return section.scrollIntoView(); }, 0); }
|
||||
|
||||
return section
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,19 +284,23 @@ function activeLink (dom, activeParent) {
|
||||
var host = window.location.href;
|
||||
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
|
||||
if (!dom) { return
|
||||
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.classList.add('active')
|
||||
: node.classList.add('active');
|
||||
target = node;
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.classList.remove('active')
|
||||
: node.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
; }[].slice.call(dom.querySelectorAll('a')).forEach(function (node) {
|
||||
if (node.href === host) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active');
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class');
|
||||
}
|
||||
});
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,30 +313,32 @@ function bindToggle (dom) {
|
||||
|
||||
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');
|
||||
});
|
||||
if (isMobile()) {
|
||||
var sidebar = document.querySelector('.sidebar');
|
||||
sidebar.addEventListener('click', function () {
|
||||
body.classList.toggle('close');
|
||||
setTimeout(function () { return activeLink(sidebar, true); }, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var cacheContentDOM;
|
||||
function scroll2Top () {
|
||||
if (!cacheContentDOM) {
|
||||
var dom = isMobile() ? 'body' : 'section.content';
|
||||
cacheContentDOM = document.querySelector(dom);
|
||||
}
|
||||
cacheContentDOM.scrollTop = 0;
|
||||
function scroll2Top (offset) {
|
||||
if ( offset === void 0 ) offset = 0;
|
||||
|
||||
document.body.scrollTop = offset === true ? 0 : Number(offset);
|
||||
}
|
||||
|
||||
function sticky () {
|
||||
var dom = document.querySelector('section.cover');
|
||||
var coverHeight = dom.getBoundingClientRect().height;
|
||||
sticky.dom = sticky.dom || document.querySelector('section.cover');
|
||||
var coverHeight = sticky.dom.getBoundingClientRect().height;
|
||||
|
||||
return (function () {
|
||||
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
|
||||
if (window.pageYOffset >= coverHeight || sticky.dom.classList.contains('hidden')) {
|
||||
document.body.classList.add('sticky');
|
||||
sticky.noSticky = false;
|
||||
} else {
|
||||
document.body.classList.remove('sticky');
|
||||
sticky.noSticky = true;
|
||||
}
|
||||
})()
|
||||
}
|
||||
@@ -1525,12 +1641,8 @@ marked.inlineLexer = InlineLexer.output;
|
||||
|
||||
marked.parse = marked;
|
||||
|
||||
if (typeof module !== 'undefined' && typeof exports === 'object') {
|
||||
{
|
||||
module.exports = marked;
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define(function() { return marked; });
|
||||
} else {
|
||||
this.marked = marked;
|
||||
}
|
||||
|
||||
}).call(function() {
|
||||
@@ -1748,6 +1860,9 @@ var _ = _self.Prism = {
|
||||
_.hooks.run('before-sanity-check', env);
|
||||
|
||||
if (!env.code || !env.grammar) {
|
||||
if (env.code) {
|
||||
env.element.textContent = env.code;
|
||||
}
|
||||
_.hooks.run('complete', env);
|
||||
return;
|
||||
}
|
||||
@@ -1825,9 +1940,16 @@ var _ = _self.Prism = {
|
||||
lookbehindLength = 0,
|
||||
alias = pattern.alias;
|
||||
|
||||
if (greedy && !pattern.pattern.global) {
|
||||
// Without the global flag, lastIndex won't work
|
||||
var flags = pattern.pattern.toString().match(/[imuy]*$/)[0];
|
||||
pattern.pattern = RegExp(pattern.pattern.source, flags + "g");
|
||||
}
|
||||
|
||||
pattern = pattern.pattern || pattern;
|
||||
|
||||
for (var i=0; i<strarr.length; i++) { // Don’t cache length as it changes during the loop
|
||||
// Don’t cache length as it changes during the loop
|
||||
for (var i=0, pos = 0; i<strarr.length; pos += strarr[i].length, ++i) {
|
||||
|
||||
var str = strarr[i];
|
||||
|
||||
@@ -1847,40 +1969,38 @@ var _ = _self.Prism = {
|
||||
|
||||
// Greedy patterns can override/remove up to two previously matched tokens
|
||||
if (!match && greedy && i != strarr.length - 1) {
|
||||
// Reconstruct the original text using the next two tokens
|
||||
var nextToken = strarr[i + 1].matchedStr || strarr[i + 1],
|
||||
combStr = str + nextToken;
|
||||
|
||||
if (i < strarr.length - 2) {
|
||||
combStr += strarr[i + 2].matchedStr || strarr[i + 2];
|
||||
}
|
||||
|
||||
// Try the pattern again on the reconstructed text
|
||||
pattern.lastIndex = 0;
|
||||
match = pattern.exec(combStr);
|
||||
pattern.lastIndex = pos;
|
||||
match = pattern.exec(text);
|
||||
if (!match) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
var from = match.index + (lookbehind ? match[1].length : 0);
|
||||
// To be a valid candidate, the new match has to start inside of str
|
||||
if (from >= str.length) {
|
||||
var from = match.index + (lookbehind ? match[1].length : 0),
|
||||
to = match.index + match[0].length,
|
||||
k = i,
|
||||
p = pos;
|
||||
|
||||
for (var len = strarr.length; k < len && p < to; ++k) {
|
||||
p += strarr[k].length;
|
||||
// Move the index i to the element in strarr that is closest to from
|
||||
if (from >= p) {
|
||||
++i;
|
||||
pos = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If strarr[i] is a Token, then the match starts inside another Token, which is invalid
|
||||
* If strarr[k - 1] is greedy we are in conflict with another greedy pattern
|
||||
*/
|
||||
if (strarr[i] instanceof Token || strarr[k - 1].greedy) {
|
||||
continue;
|
||||
}
|
||||
var to = match.index + match[0].length,
|
||||
len = str.length + nextToken.length;
|
||||
|
||||
// Number of tokens to delete and replace with the new match
|
||||
delNum = 3;
|
||||
|
||||
if (to <= len) {
|
||||
if (strarr[i + 1].greedy) {
|
||||
continue;
|
||||
}
|
||||
delNum = 2;
|
||||
combStr = combStr.slice(0, len);
|
||||
}
|
||||
str = combStr;
|
||||
delNum = k - i;
|
||||
str = text.slice(pos, p);
|
||||
match.index -= pos;
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
@@ -1949,7 +2069,7 @@ var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
|
||||
this.content = content;
|
||||
this.alias = alias;
|
||||
// Copy of the full string this token was created from
|
||||
this.matchedStr = matchedStr || null;
|
||||
this.length = (matchedStr || "").length|0;
|
||||
this.greedy = !!greedy;
|
||||
};
|
||||
|
||||
@@ -1985,13 +2105,11 @@ Token.stringify = function(o, language, parent) {
|
||||
|
||||
_.hooks.run('wrap', env);
|
||||
|
||||
var attributes = '';
|
||||
var attributes = Object.keys(env.attributes).map(function(name) {
|
||||
return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"';
|
||||
}).join(' ');
|
||||
|
||||
for (var name in env.attributes) {
|
||||
attributes += (attributes ? ' ' : '') + name + '="' + (env.attributes[name] || '') + '"';
|
||||
}
|
||||
|
||||
return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '</' + env.tag + '>';
|
||||
return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>';
|
||||
|
||||
};
|
||||
|
||||
@@ -2024,7 +2142,11 @@ if (script) {
|
||||
|
||||
if (document.addEventListener && !script.hasAttribute('data-manual')) {
|
||||
if(document.readyState !== "loading") {
|
||||
requestAnimationFrame(_.highlightAll, 0);
|
||||
if (window.requestAnimationFrame) {
|
||||
window.requestAnimationFrame(_.highlightAll);
|
||||
} else {
|
||||
window.setTimeout(_.highlightAll, 16);
|
||||
}
|
||||
}
|
||||
else {
|
||||
document.addEventListener('DOMContentLoaded', _.highlightAll);
|
||||
@@ -2036,7 +2158,7 @@ return _self.Prism;
|
||||
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if ('object' !== 'undefined' && module.exports) {
|
||||
module.exports = Prism;
|
||||
}
|
||||
|
||||
@@ -2053,10 +2175,10 @@ if (typeof commonjsGlobal !== 'undefined') {
|
||||
Prism.languages.markup = {
|
||||
'comment': /<!--[\w\W]*?-->/,
|
||||
'prolog': /<\?[\w\W]+?\?>/,
|
||||
'doctype': /<!DOCTYPE[\w\W]+?>/,
|
||||
'doctype': /<!DOCTYPE[\w\W]+?>/i,
|
||||
'cdata': /<!\[CDATA\[[\w\W]*?]]>/i,
|
||||
'tag': {
|
||||
pattern: /<\/?(?!\d)[^\s>\/=.$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
|
||||
pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
|
||||
inside: {
|
||||
'tag': {
|
||||
pattern: /^<\/?[^\s>\/]+/i,
|
||||
@@ -2113,7 +2235,10 @@ Prism.languages.css = {
|
||||
},
|
||||
'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
|
||||
'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
|
||||
'string': /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,
|
||||
'string': {
|
||||
pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,
|
||||
greedy: true
|
||||
},
|
||||
'property': /(\b|\B)[\w-]+(?=\s*:)/i,
|
||||
'important': /\B!important\b/i,
|
||||
'function': /[-a-z0-9]+(?=\()/i,
|
||||
@@ -2194,7 +2319,8 @@ Prism.languages.javascript = Prism.languages.extend('clike', {
|
||||
'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
|
||||
'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
|
||||
// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
|
||||
'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i
|
||||
'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,
|
||||
'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/
|
||||
});
|
||||
|
||||
Prism.languages.insertBefore('javascript', 'keyword', {
|
||||
@@ -2337,8 +2463,11 @@ function corner (data) {
|
||||
/**
|
||||
* 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>")
|
||||
function main () {
|
||||
var aside = (toggle()) + "<aside class=\"sidebar\"><div class=\"sidebar-nav\"></div></aside>";
|
||||
|
||||
return (isMobile() ? (aside + "<main>") : ("<main>" + aside)) +
|
||||
"<section class=\"content\">\n <article class=\"markdown-section\"></article>\n </section>\n </main>"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2348,11 +2477,11 @@ 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%)";
|
||||
|
||||
return ("<section class=\"cover\" style=\"background: " + bgc + "\">\n <div class=\"cover-main\"></div>\n </section>")
|
||||
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>"
|
||||
return "<button class=\"sidebar-toggle\">\n <div class=\"sidebar-toggle-button\">\n <span></span><span></span><span></span>\n </div>\n </button>"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2376,73 +2505,147 @@ function tree (toc, tpl) {
|
||||
return tpl
|
||||
}
|
||||
|
||||
var OPTIONS$1 = {};
|
||||
function helper (className, content) {
|
||||
return ("<p class=\"" + className + "\">" + (content.slice(5).trim()) + "</p>")
|
||||
}
|
||||
|
||||
function theme (color) {
|
||||
return ("<style>:root{--theme-color: " + color + ";}</style>")
|
||||
}
|
||||
|
||||
function replaceVar (block) {
|
||||
block.innerHTML = block.innerHTML.replace(/var\(\s*--theme-color.*?\)/g, $docsify.themeColor);
|
||||
}
|
||||
|
||||
function cssVars () {
|
||||
// variable support
|
||||
if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) { return }
|
||||
|
||||
var styleBlocks = document.querySelectorAll('style:not(.inserted),link');[].forEach.call(styleBlocks, function (block) {
|
||||
if (block.nodeName === 'STYLE') {
|
||||
replaceVar(block);
|
||||
} else if (block.nodeName === 'LINK') {
|
||||
var href = block.getAttribute('href');
|
||||
|
||||
if (!/\.css$/.test(href)) { return }
|
||||
|
||||
load(href).then(function (res) {
|
||||
var style = document.createElement('style');
|
||||
|
||||
style.innerHTML = res;
|
||||
document.head.appendChild(style);
|
||||
replaceVar(style);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var markdown = marked;
|
||||
var toc = [];
|
||||
var CACHE = {};
|
||||
|
||||
var renderTo = function (dom, content) {
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
|
||||
dom.innerHTML = content;
|
||||
slugify.clear();
|
||||
|
||||
return dom
|
||||
};
|
||||
var toc = [];
|
||||
var renderer = new marked.Renderer();
|
||||
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
* init render
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
var slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
|
||||
var route = '';
|
||||
function init () {
|
||||
var renderer = new marked.Renderer();
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
var slug = slugify(text);
|
||||
var route = '';
|
||||
|
||||
if (OPTIONS$1.router) {
|
||||
route = "#/" + (getRoute());
|
||||
toc.push({ level: level, slug: (route + "#" + (encodeURIComponent(slug))), title: text });
|
||||
|
||||
return ("<h" + level + " id=\"" + slug + "\"><a href=\"" + route + "#" + slug + "\" data-id=\"" + slug + "\" class=\"anchor\"><span>" + text + "</span></a></h" + level + ">")
|
||||
};
|
||||
// highlight code
|
||||
renderer.code = function (code, lang) {
|
||||
if ( lang === void 0 ) lang = '';
|
||||
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
|
||||
|
||||
return ("<pre v-pre data-lang=\"" + lang + "\"><code class=\"lang-" + lang + "\">" + hl + "</code></pre>")
|
||||
};
|
||||
renderer.link = function (href, title, text) {
|
||||
if (!/:/.test(href)) {
|
||||
href = ("#/" + href).replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
|
||||
};
|
||||
renderer.paragraph = function (text) {
|
||||
if (/^!>/.test(text)) {
|
||||
return helper('tip', text)
|
||||
} else if (/^\?>/.test(text)) {
|
||||
return helper('warn', text)
|
||||
}
|
||||
return ("<p>" + text + "</p>")
|
||||
};
|
||||
|
||||
if (typeof $docsify.markdown === 'function') {
|
||||
markdown.setOptions({ renderer: renderer });
|
||||
markdown = $docsify.markdown.call(this, markdown);
|
||||
} else {
|
||||
markdown.setOptions(merge({ renderer: renderer }, $docsify.markdown));
|
||||
}
|
||||
|
||||
toc.push({ level: level, slug: (route + "#" + (encodeURIComponent(slug))), title: text });
|
||||
var md = markdown;
|
||||
|
||||
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) {
|
||||
if ( lang === void 0 ) lang = '';
|
||||
markdown = function (text) { return emojify(md(text)); };
|
||||
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
|
||||
|
||||
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 = !/^\/#/.test(href) ? ("#" + href) : href;
|
||||
}
|
||||
|
||||
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
|
||||
};
|
||||
marked.setOptions({ renderer: renderer });
|
||||
window.Docsify.utils.marked = function (text) {
|
||||
var result = markdown(text);
|
||||
toc = [];
|
||||
return result
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* App
|
||||
*/
|
||||
function renderApp (dom, replace) {
|
||||
var nav = document.querySelector('nav') || document.createElement('nav');
|
||||
var body = document.body;
|
||||
var head = document.head;
|
||||
|
||||
if (!OPTIONS$1.repo) { nav.classList.add('no-badge'); }
|
||||
if (!$docsify.repo) { nav.classList.add('no-badge'); }
|
||||
|
||||
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]);
|
||||
dom[replace ? 'outerHTML' : 'innerHTML'] = corner($docsify.repo) +
|
||||
($docsify.coverpage ? cover() : '') +
|
||||
main();
|
||||
body.insertBefore(nav, body.children[0]);
|
||||
|
||||
// theme color
|
||||
if ($docsify.themeColor) {
|
||||
head.innerHTML += theme($docsify.themeColor);
|
||||
cssVars();
|
||||
}
|
||||
|
||||
// render name
|
||||
if ($docsify.name) {
|
||||
var aside = document.querySelector('.sidebar');
|
||||
aside.innerHTML = "<h1><a href=\"" + ($docsify.nameLink) + "\">" + ($docsify.name) + "</a></h1>" + aside.innerHTML;
|
||||
}
|
||||
|
||||
// bind toggle
|
||||
bindToggle('button.sidebar-toggle');
|
||||
// bind sticky effect
|
||||
if (OPTIONS$1.coverpage) {
|
||||
if ($docsify.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', sticky);
|
||||
} else {
|
||||
document.body.classList.add('sticky');
|
||||
body.classList.add('sticky');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2450,13 +2653,25 @@ function renderApp (dom, replace) {
|
||||
* article
|
||||
*/
|
||||
function renderArticle (content) {
|
||||
renderTo('article', content ? marked(content) : 'not found');
|
||||
if (!renderSidebar.rendered) { renderSidebar(null, OPTIONS$1); }
|
||||
if (!renderNavbar.rendered) { renderNavbar(null, OPTIONS$1); }
|
||||
renderSidebar.rendered = false;
|
||||
renderNavbar.rendered = false;
|
||||
renderTo('article', content ? markdown(content) : 'not found');
|
||||
if (!$docsify.loadSidebar) { renderSidebar(); }
|
||||
|
||||
if (OPTIONS$1.auto2top) { scroll2Top(); }
|
||||
if (content && typeof Vue !== 'undefined') {
|
||||
CACHE.vm && CACHE.vm.$destroy();
|
||||
|
||||
var script = [].slice.call(
|
||||
document.body.querySelectorAll('article>script'))
|
||||
.filter(function (script) { return !/template/.test(script.type); }
|
||||
)[0];
|
||||
var code = script ? script.innerText.trim() : null;
|
||||
|
||||
script && script.remove();
|
||||
CACHE.vm = code
|
||||
? new Function(("return " + code))()
|
||||
: new Vue({ el: 'main' }); // eslint-disable-line
|
||||
CACHE.vm && CACHE.vm.$nextTick(function (_) { return scrollActiveSidebar(); });
|
||||
}
|
||||
if ($docsify.auto2top) { setTimeout(function () { return scroll2Top($docsify.auto2top); }, 0); }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2465,9 +2680,8 @@ function renderArticle (content) {
|
||||
function renderNavbar (content) {
|
||||
if (CACHE.navbar && CACHE.navbar === content) { return }
|
||||
CACHE.navbar = content;
|
||||
renderNavbar.rendered = true;
|
||||
|
||||
if (content) { renderTo('nav', marked(content)); }
|
||||
if (content) { renderTo('nav', markdown(content)); }
|
||||
activeLink('nav');
|
||||
}
|
||||
|
||||
@@ -2475,23 +2689,27 @@ function renderNavbar (content) {
|
||||
* sidebar
|
||||
*/
|
||||
function renderSidebar (content) {
|
||||
var isToc = false;
|
||||
var html;
|
||||
|
||||
if (content) {
|
||||
content = marked(content);
|
||||
} else if (OPTIONS$1.sidebar) {
|
||||
content = tree(OPTIONS$1.sidebar, '<ul>');
|
||||
html = markdown(content);
|
||||
// find url tag
|
||||
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0];
|
||||
} else {
|
||||
content = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
|
||||
isToc = true;
|
||||
html = tree(genTree(toc, $docsify.maxLevel), '<ul>');
|
||||
}
|
||||
|
||||
renderSidebar.rendered = true;
|
||||
if (CACHE.sidebar && CACHE.sidebar === content) { return }
|
||||
CACHE.sidebar = content;
|
||||
renderTo('aside.sidebar', content);
|
||||
if (isToc) { scrollActiveSidebar(); }
|
||||
renderTo('.sidebar-nav', html);
|
||||
var target = activeLink('.sidebar-nav', true);
|
||||
if (target) { renderSubSidebar(target); }
|
||||
toc = [];
|
||||
|
||||
scrollActiveSidebar();
|
||||
}
|
||||
|
||||
function renderSubSidebar (target) {
|
||||
if (!$docsify.subMaxLevel) { return }
|
||||
target.parentNode.innerHTML += tree(genTree(toc, $docsify.subMaxLevel), '<ul>');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2500,12 +2718,36 @@ function renderSidebar (content) {
|
||||
function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover');
|
||||
if (!content) {
|
||||
renderCover.dom.classList.add('hidden');
|
||||
} else {
|
||||
renderCover.dom.classList.remove('hidden');
|
||||
!renderCover.rendered && renderTo('.cover-main', marked(content));
|
||||
renderCover.rendered = true;
|
||||
renderCover.dom.classList.remove('show');
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show');
|
||||
if (renderCover.rendered) { return sticky() }
|
||||
|
||||
// render cover
|
||||
var cacheToc = toc.slice();
|
||||
var html = markdown(content);
|
||||
var match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$');
|
||||
|
||||
toc = cacheToc.slice();
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
var coverEl = document.querySelector('section.cover');
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1] + (match[3] || '');
|
||||
} 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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2545,28 +2787,22 @@ function renderLoading (ref) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Config
|
||||
* @param {Object} options
|
||||
*/
|
||||
function config (options) {
|
||||
OPTIONS$1 = options;
|
||||
}
|
||||
|
||||
var OPTIONS = {
|
||||
var OPTIONS = merge({
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
subMaxLevel: 0,
|
||||
loadSidebar: null,
|
||||
loadNavbar: null,
|
||||
router: false,
|
||||
homepage: 'README.md',
|
||||
coverpage: '',
|
||||
basePath: '',
|
||||
auto2top: false
|
||||
};
|
||||
auto2top: false,
|
||||
name: '',
|
||||
themeColor: '',
|
||||
nameLink: window.location.pathname,
|
||||
ga: ''
|
||||
}, window.$docsify);
|
||||
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
|
||||
|
||||
// load configuration for script attribute
|
||||
@@ -2578,11 +2814,19 @@ if (script) {
|
||||
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]; }
|
||||
if (OPTIONS.repo === true) { OPTIONS.repo = ''; }
|
||||
if (OPTIONS.name === true) { OPTIONS.name = ''; }
|
||||
}
|
||||
|
||||
// utils
|
||||
window.$docsify = OPTIONS;
|
||||
window.Docsify = {
|
||||
installed: true,
|
||||
utils: merge({}, utils)
|
||||
};
|
||||
|
||||
// load options
|
||||
config(OPTIONS);
|
||||
init();
|
||||
|
||||
var cacheRoute = null;
|
||||
var cacheXhr = null;
|
||||
@@ -2591,7 +2835,6 @@ var mainRender = function (cb) {
|
||||
var route = OPTIONS.basePath + getRoute();
|
||||
if (cacheRoute === route) { return cb() }
|
||||
|
||||
var wait;
|
||||
var basePath = cacheRoute = route;
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -2601,6 +2844,7 @@ var mainRender = function (cb) {
|
||||
}
|
||||
|
||||
var page;
|
||||
|
||||
if (!route) {
|
||||
page = OPTIONS.homepage || 'README.md';
|
||||
} else if (/\/$/.test(route)) {
|
||||
@@ -2610,12 +2854,8 @@ var mainRender = function (cb) {
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage) {
|
||||
if (page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(renderCover);
|
||||
} else {
|
||||
renderCover();
|
||||
}
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(renderCover);
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort();
|
||||
@@ -2623,26 +2863,23 @@ var mainRender = function (cb) {
|
||||
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) {
|
||||
if (wait === false) { cb(); }
|
||||
wait = false;
|
||||
var renderSidebar$$1 = function (result) { renderSidebar(result); cb(); };
|
||||
|
||||
load(basePath + OPTIONS.loadSidebar).then(renderSidebar$$1,
|
||||
function (_) { return load(OPTIONS.loadSidebar).then(renderSidebar$$1); });
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}, function (_) { return renderArticle(null); });
|
||||
|
||||
// Render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
load(basePath + OPTIONS.loadSidebar).then(function (result) {
|
||||
renderSidebar(result);
|
||||
if (wait === false) { cb(); }
|
||||
wait = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Render navbar
|
||||
if (OPTIONS.loadNavbar) {
|
||||
load(basePath + OPTIONS.loadNavbar).then(renderNavbar);
|
||||
load(basePath + OPTIONS.loadNavbar).then(renderNavbar,
|
||||
function (_) { return load(OPTIONS.loadNavbar).then(renderNavbar); });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2651,19 +2888,17 @@ var Docsify = function () {
|
||||
var replace = dom !== document.body;
|
||||
var main = function () {
|
||||
mainRender(function (_) {
|
||||
activeLink('aside.sidebar', true);
|
||||
scrollIntoView();
|
||||
OPTIONS.coverpage && sticky();
|
||||
activeLink('nav')
|
||||
;[].concat(window.$docsify.plugins).forEach(function (fn) { return fn && fn(); });
|
||||
});
|
||||
};
|
||||
|
||||
// Render app
|
||||
renderApp(dom, replace);
|
||||
main();
|
||||
if (OPTIONS.router) {
|
||||
if (!/^#\//.test(window.location.hash)) { window.location.hash = '#/'; }
|
||||
window.addEventListener('hashchange', main);
|
||||
}
|
||||
if (!/^#\//.test(window.location.hash)) { window.location.hash = '#/'; }
|
||||
window.addEventListener('hashchange', main);
|
||||
};
|
||||
|
||||
var index = Docsify();
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
|
||||
this.D = this.D || {};
|
||||
this.D.GA = (function () {
|
||||
'use strict';
|
||||
|
||||
// From https://github.com/egoist/vue-ga/blob/master/src/index.js
|
||||
|
||||
function appendScript () {
|
||||
var script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = 'https://www.google-analytics.com/analytics.js';
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
function init (id) {
|
||||
if (!window.ga) {
|
||||
appendScript();
|
||||
window.ga = window.ga || function () {
|
||||
(window.ga.q = window.ga.q || []).push(arguments);
|
||||
};
|
||||
window.ga.l = Number(new Date());
|
||||
window.ga('create', id, 'auto');
|
||||
}
|
||||
}
|
||||
|
||||
function collect () {
|
||||
init(window.$docsify.ga);
|
||||
window.ga('set', 'page', location.href);
|
||||
window.ga('send', 'pageview');
|
||||
}
|
||||
|
||||
var install = function () {
|
||||
if (!window.Docsify || !window.Docsify.installed) {
|
||||
console.error('[Docsify] Please load docsify.js first.');
|
||||
return
|
||||
}
|
||||
|
||||
if (!window.$docsify.ga) {
|
||||
console.error('[Docsify] ga is required.');
|
||||
return
|
||||
}
|
||||
|
||||
collect();
|
||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, collect);
|
||||
};
|
||||
|
||||
var ga = install();
|
||||
|
||||
return ga;
|
||||
|
||||
}());
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
this.D=this.D||{},this.D.GA=function(){"use strict";function o(){var o=document.createElement("script");o.async=!0,o.src="https://www.google-analytics.com/analytics.js",document.body.appendChild(o)}function i(i){window.ga||(o(),window.ga=window.ga||function(){(window.ga.q=window.ga.q||[]).push(arguments)},window.ga.l=Number(new Date),window.ga("create",i,"auto"))}function n(){i(window.$docsify.ga),window.ga("set","page",location.href),window.ga("send","pageview")}var w=function(){return window.Docsify&&window.Docsify.installed?window.$docsify.ga?(n(),void(window.$docsify.plugins=[].concat(window.$docsify.plugins,n))):void console.error("[Docsify] ga is required."):void console.error("[Docsify] Please load docsify.js first.")},s=w();return s}();
|
||||
@@ -0,0 +1,287 @@
|
||||
this.D = this.D || {};
|
||||
this.D.Search = (function () {
|
||||
'use strict';
|
||||
|
||||
var INDEXS = {};
|
||||
var CONFIG = {
|
||||
placeholder: 'Type to search',
|
||||
paths: 'auto',
|
||||
maxAge: 86400000 // 1 day
|
||||
};
|
||||
|
||||
var isObj = function (obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
};
|
||||
|
||||
var escapeHtml = function (string) {
|
||||
var entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/'
|
||||
};
|
||||
|
||||
return String(string).replace(/[&<>"'\/]/g, function (s) { return entityMap[s]; })
|
||||
};
|
||||
|
||||
/**
|
||||
* find all filepath from A tag
|
||||
*/
|
||||
var getAllPaths = function () {
|
||||
var paths = [];[].slice.call(document.querySelectorAll('a'))
|
||||
.map(function (node) {
|
||||
var href = node.href;
|
||||
if (/#\/[^#]*?$/.test(href)) {
|
||||
var path = href.replace(/^[^#]+#/, '');
|
||||
|
||||
if (paths.indexOf(path) <= 0) { paths.push(path); }
|
||||
}
|
||||
});
|
||||
|
||||
return paths
|
||||
};
|
||||
|
||||
/**
|
||||
* return file path
|
||||
*/
|
||||
var genFilePath = function (path) {
|
||||
var basePath = window.$docsify.basePath;
|
||||
var filePath = /\/$/.test(path) ? (path + "README.md") : (path + ".md");
|
||||
|
||||
filePath = basePath + filePath;
|
||||
|
||||
return filePath.replace(/\/+/g, '/')
|
||||
};
|
||||
|
||||
/**
|
||||
* generate index
|
||||
*/
|
||||
var genIndex = function (path, content) {
|
||||
if ( content === void 0 ) content = '';
|
||||
|
||||
INDEXS[path] = { slug: '', title: '', body: '' };
|
||||
var slug;
|
||||
|
||||
content
|
||||
// remove PRE and TEMPLATE tag
|
||||
.replace(/<template[^>]*?>[\s\S]+?<\/template>/g, '')
|
||||
// find all html tag
|
||||
.replace(/<(\w+)([^>]*?)>([\s\S]+?)<\//g, function (match, tag, attr, html) {
|
||||
// remove all html tag
|
||||
var text = html.replace(/<[^>]+>/g, '');
|
||||
|
||||
// tag is headline
|
||||
if (/^h\d$/.test(tag)) {
|
||||
// <h1 id="xxx"></h1>
|
||||
var id = attr.match(/id="(\S+)"/)[1];
|
||||
|
||||
slug = ("#/" + path + "#" + id).replace(/\/+/, '/');
|
||||
INDEXS[slug] = { slug: slug, title: text, body: '' };
|
||||
} else {
|
||||
if (!slug) { return }
|
||||
// other html tag
|
||||
if (!INDEXS[slug]) {
|
||||
INDEXS[slug] = {};
|
||||
} else {
|
||||
if (INDEXS[slug].body && INDEXS[slug].body.length) {
|
||||
INDEXS[slug].body += '\n' + text;
|
||||
} else {
|
||||
INDEXS[slug].body = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* component
|
||||
*/
|
||||
var SearchComponent = function SearchComponent () {
|
||||
if (this.rendered) { return }
|
||||
|
||||
this.style();
|
||||
|
||||
var el = document.createElement('div');
|
||||
var aside = document.querySelector('aside');
|
||||
|
||||
el.classList.add('search');
|
||||
aside.insertBefore(el, aside.children[0]);
|
||||
this.render(el);
|
||||
this.rendered = true;
|
||||
this.bindEvent();
|
||||
};
|
||||
|
||||
SearchComponent.prototype.style = function style () {
|
||||
var code = "\n .sidebar {\n padding-top: 0;\n }\n\n .search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n }\n\n .search .results-panel {\n display: none;\n }\n\n .search .results-panel.show {\n display: block;\n }\n\n .search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 7px;\n line-height: 22px;\n font-size: 14px;\n }\n\n .search h2 {\n font-size: 17px;\n margin: 10px 0;\n }\n\n .search a {\n text-decoration: none;\n color: inherit;\n }\n\n .search .matching-post {\n border-bottom: 1px solid #eee;\n }\n\n .search .matching-post:last-child {\n border-bottom: 0;\n }\n\n .search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n\n .search p.empty {\n text-align: center;\n }\n ";
|
||||
var style = document.createElement('style');
|
||||
|
||||
style.innerHTML = code;
|
||||
document.head.appendChild(style);
|
||||
};
|
||||
|
||||
SearchComponent.prototype.render = function render (dom) {
|
||||
dom.innerHTML = "<input type=\"search\" placeholder=\"" + (CONFIG.placeholder) + "\" /><div class=\"results-panel\"></div>";
|
||||
};
|
||||
|
||||
SearchComponent.prototype.bindEvent = function bindEvent () {
|
||||
var this$1 = this;
|
||||
|
||||
var search = document.querySelector('.search');
|
||||
var input = search.querySelector('.search input');
|
||||
var panel = search.querySelector('.results-panel');
|
||||
|
||||
search.addEventListener('click', function (e) { return e.target.tagName !== 'A' && e.stopPropagation(); });
|
||||
input.addEventListener('input', function (e) {
|
||||
var target = e.target;
|
||||
|
||||
if (target.value.trim() !== '') {
|
||||
var matchingPosts = this$1.search(target.value);
|
||||
var html = '';
|
||||
|
||||
matchingPosts.forEach(function (post, index) {
|
||||
html += "\n <div class=\"matching-post\">\n <h2><a href=\"" + (post.url) + "\">" + (post.title) + "</a></h2>\n <p>" + (post.content) + "</p>\n </div>\n ";
|
||||
});
|
||||
if (panel.classList.contains('results-panel')) {
|
||||
panel.classList.add('show');
|
||||
panel.innerHTML = html || '<p class="empty">No Results!</p>';
|
||||
}
|
||||
} else {
|
||||
if (panel.classList.contains('results-panel')) {
|
||||
panel.classList.remove('show');
|
||||
panel.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// From [weex website] https://weex-project.io/js/common.js
|
||||
SearchComponent.prototype.search = function search (keywords) {
|
||||
var matchingResults = [];
|
||||
var data = Object.keys(INDEXS).map(function (key) { return INDEXS[key]; });
|
||||
|
||||
keywords = keywords.trim().split(/[\s\-\,\\/]+/);
|
||||
|
||||
var loop = function ( i ) {
|
||||
var post = data[i];
|
||||
var isMatch = false;
|
||||
var resultStr = '';
|
||||
var postTitle = post.title && post.title.trim();
|
||||
var postContent = post.body && post.body.trim();
|
||||
var postUrl = post.slug || '';
|
||||
|
||||
if (postTitle !== '' && postContent !== '') {
|
||||
keywords.forEach(function (keyword, i) {
|
||||
var regEx = new RegExp(keyword, 'gi');
|
||||
var indexTitle = -1;
|
||||
var indexContent = -1;
|
||||
|
||||
indexTitle = postTitle.search(regEx);
|
||||
indexContent = postContent.search(regEx);
|
||||
|
||||
if (indexTitle < 0 && indexContent < 0) {
|
||||
isMatch = false;
|
||||
} else {
|
||||
isMatch = true;
|
||||
if (indexContent < 0) { indexContent = 0; }
|
||||
|
||||
var start = 0;
|
||||
var end = 0;
|
||||
|
||||
start = indexContent < 11 ? 0 : indexContent - 10;
|
||||
end = start === 0 ? 70 : indexContent + keyword.length + 60;
|
||||
|
||||
if (end > postContent.length) { end = postContent.length; }
|
||||
|
||||
var matchContent = '...' +
|
||||
postContent
|
||||
.substring(start, end)
|
||||
.replace(regEx, ("<em class=\"search-keyword\">" + keyword + "</em>")) +
|
||||
'...';
|
||||
|
||||
resultStr += matchContent;
|
||||
}
|
||||
});
|
||||
|
||||
if (isMatch) {
|
||||
var matchingPost = {
|
||||
title: escapeHtml(postTitle),
|
||||
content: resultStr,
|
||||
url: postUrl
|
||||
};
|
||||
|
||||
matchingResults.push(matchingPost);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < data.length; i++) loop( i );
|
||||
|
||||
return matchingResults
|
||||
};
|
||||
|
||||
var searchPlugin = function () {
|
||||
var isAuto = CONFIG.paths === 'auto';
|
||||
var isExpired = localStorage.getItem('docsify.search.expires') < Date.now();
|
||||
|
||||
INDEXS = JSON.parse(localStorage.getItem('docsify.search.index'));
|
||||
|
||||
if (isExpired) {
|
||||
INDEXS = {};
|
||||
} else if (!isAuto) {
|
||||
return
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var paths = isAuto ? getAllPaths() : CONFIG.paths;
|
||||
var len = paths.length;
|
||||
var ref = window.Docsify.utils;
|
||||
var load = ref.load;
|
||||
var marked = ref.marked;
|
||||
var slugify = ref.slugify;
|
||||
var done = function () {
|
||||
localStorage.setItem('docsify.search.expires', Date.now() + CONFIG.maxAge);
|
||||
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS));
|
||||
};
|
||||
|
||||
paths.forEach(function (path) {
|
||||
if (INDEXS[path]) { return count++ }
|
||||
|
||||
load(genFilePath(path)).then(function (content) {
|
||||
genIndex(path, marked(content));
|
||||
slugify.clear();
|
||||
count++;
|
||||
|
||||
if (len === count) { done(); }
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var install = function () {
|
||||
if (!window.Docsify || !window.Docsify.installed) {
|
||||
console.error('[Docsify] Please load docsify.js first.');
|
||||
return
|
||||
}
|
||||
|
||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, searchPlugin);
|
||||
|
||||
var userConfig = window.$docsify.search;
|
||||
var isNil = window.Docsify.utils.isNil;
|
||||
|
||||
if (Array.isArray(userConfig)) {
|
||||
CONFIG.paths = userConfig;
|
||||
} else if (isObj(userConfig)) {
|
||||
CONFIG.paths = Array.isArray(userConfig.paths) ? userConfig.paths : 'auto';
|
||||
CONFIG.maxAge = isNil(userConfig.maxAge) ? CONFIG.maxAge : userConfig.maxAge;
|
||||
CONFIG.placeholder = userConfig.placeholder || CONFIG.placeholder;
|
||||
}
|
||||
|
||||
new SearchComponent();
|
||||
};
|
||||
|
||||
var search = install();
|
||||
|
||||
return search;
|
||||
|
||||
}());
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+6
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docsify",
|
||||
"version": "1.3.0",
|
||||
"version": "2.2.1",
|
||||
"description": "A magical documentation generator.",
|
||||
"main": "lib/docsify.js",
|
||||
"files": [
|
||||
@@ -10,7 +10,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"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'",
|
||||
"dev:build": "rm -rf lib themes && mkdir themes && node build/build.js --dev && node build/build-css.js --dev",
|
||||
"dev": "node app.js & nodemon -w src -e js,css --exec 'npm run dev:build'",
|
||||
"test": "eslint src test"
|
||||
},
|
||||
"repository": {
|
||||
@@ -35,9 +36,9 @@
|
||||
"nodemon": "^1.11.0",
|
||||
"postcss": "^5.2.6",
|
||||
"postcss-salad": "^1.0.5",
|
||||
"rollup": "^0.36.3",
|
||||
"rollup-plugin-buble": "^0.14.0",
|
||||
"rollup-plugin-commonjs": "^5.0.5",
|
||||
"rollup": "^0.41.1",
|
||||
"rollup-plugin-buble": "^0.15.0",
|
||||
"rollup-plugin-commonjs": "^7.0.0",
|
||||
"rollup-plugin-node-resolve": "^2.0.0",
|
||||
"rollup-plugin-uglify": "^1.0.1",
|
||||
"serve-static": "^1.11.1"
|
||||
|
||||
+82
-41
@@ -7,42 +7,75 @@ import { isMobile } from './util'
|
||||
export function scrollActiveSidebar () {
|
||||
if (isMobile()) return
|
||||
|
||||
let hoveredOverSidebar = false
|
||||
const anchors = document.querySelectorAll('.anchor')
|
||||
const sidebar = document.querySelector('.sidebar')
|
||||
const sidebarContainer = sidebar.querySelector('.sidebar-nav')
|
||||
const sidebarHeight = sidebar.clientHeight
|
||||
|
||||
const nav = {}
|
||||
const lis = document.querySelectorAll('.sidebar li')
|
||||
let active = null
|
||||
const lis = sidebar.querySelectorAll('li')
|
||||
let active = sidebar.querySelector('li.active')
|
||||
|
||||
for (let i = 0, len = lis.length; i < len; i += 1) {
|
||||
const li = lis[i]
|
||||
let href = li.querySelector('a').getAttribute('href')
|
||||
|
||||
if (href !== '/') href = href.match(/#([^#]+)$/g)[0].slice(1)
|
||||
if (href !== '/') {
|
||||
const match = href.match('#([^#]+)$')
|
||||
if (match && match.length) href = match[0].slice(1)
|
||||
}
|
||||
|
||||
nav[decodeURIComponent(href)] = li
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
const top = document.body.scrollTop
|
||||
let last
|
||||
|
||||
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
|
||||
if (node.offsetTop > top) {
|
||||
if (!last) last = node
|
||||
break
|
||||
} else {
|
||||
last = node
|
||||
}
|
||||
}
|
||||
if (!last) return
|
||||
const li = nav[last.getAttribute('data-id')]
|
||||
|
||||
if (!li || li === active) return
|
||||
if (active) active.classList.remove('active')
|
||||
|
||||
li.classList.add('active')
|
||||
active = li
|
||||
|
||||
// scroll into view
|
||||
// https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297
|
||||
if (!hoveredOverSidebar && !sticky.noSticky) {
|
||||
const currentPageOffset = 0
|
||||
const currentActiveOffset = active.offsetTop + active.clientHeight + 40
|
||||
const currentActiveIsInView = (
|
||||
active.offsetTop >= sidebarContainer.scrollTop &&
|
||||
currentActiveOffset <= sidebarContainer.scrollTop + sidebarHeight
|
||||
)
|
||||
const linkNotFurtherThanSidebarHeight = currentActiveOffset - currentPageOffset < sidebarHeight
|
||||
const newScrollTop = currentActiveIsInView
|
||||
? sidebarContainer.scrollTop
|
||||
: linkNotFurtherThanSidebarHeight
|
||||
? currentPageOffset
|
||||
: currentActiveOffset - sidebarHeight
|
||||
|
||||
sidebar.scrollTop = newScrollTop
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', highlight)
|
||||
window.addEventListener('scroll', highlight)
|
||||
highlight()
|
||||
sidebar.addEventListener('mouseover', () => { hoveredOverSidebar = true })
|
||||
sidebar.addEventListener('mouseleave', () => { hoveredOverSidebar = false })
|
||||
}
|
||||
|
||||
export function scrollIntoView () {
|
||||
@@ -50,7 +83,9 @@ export function scrollIntoView () {
|
||||
if (!id || !id.length) return
|
||||
const section = document.querySelector(decodeURIComponent(id[0]))
|
||||
|
||||
if (section) section.scrollIntoView()
|
||||
if (section) setTimeout(() => section.scrollIntoView(), 0)
|
||||
|
||||
return section
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,18 +96,24 @@ export function activeLink (dom, activeParent) {
|
||||
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
|
||||
if (!dom) return
|
||||
let target
|
||||
|
||||
;[].slice.call(dom.querySelectorAll('a')).forEach(node => {
|
||||
if (node.href === host) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active')
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class')
|
||||
}
|
||||
})
|
||||
;[].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.classList.add('active')
|
||||
: node.classList.add('active')
|
||||
target = node
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.classList.remove('active')
|
||||
: node.classList.remove('active')
|
||||
}
|
||||
})
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,30 +126,30 @@ export function bindToggle (dom) {
|
||||
|
||||
dom.addEventListener('click', () => body.classList.toggle('close'))
|
||||
|
||||
if (!/mobile/i.test(navigator.userAgent)) return
|
||||
document.querySelector('aside').addEventListener('click', event => {
|
||||
body.classList.toggle('close')
|
||||
})
|
||||
if (isMobile()) {
|
||||
const sidebar = document.querySelector('.sidebar')
|
||||
sidebar.addEventListener('click', () => {
|
||||
body.classList.toggle('close')
|
||||
setTimeout(() => activeLink(sidebar, true), 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let cacheContentDOM
|
||||
export function scroll2Top () {
|
||||
if (!cacheContentDOM) {
|
||||
const dom = isMobile() ? 'body' : 'section.content'
|
||||
cacheContentDOM = document.querySelector(dom)
|
||||
}
|
||||
cacheContentDOM.scrollTop = 0
|
||||
export function scroll2Top (offset = 0) {
|
||||
document.body.scrollTop = offset === true ? 0 : Number(offset)
|
||||
}
|
||||
|
||||
export function sticky () {
|
||||
const dom = document.querySelector('section.cover')
|
||||
const coverHeight = dom.getBoundingClientRect().height
|
||||
sticky.dom = sticky.dom || document.querySelector('section.cover')
|
||||
const coverHeight = sticky.dom.getBoundingClientRect().height
|
||||
|
||||
return (function () {
|
||||
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
|
||||
if (window.pageYOffset >= coverHeight || sticky.dom.classList.contains('hidden')) {
|
||||
document.body.classList.add('sticky')
|
||||
sticky.noSticky = false
|
||||
} else {
|
||||
document.body.classList.remove('sticky')
|
||||
sticky.noSticky = true
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
+40
-39
@@ -1,46 +1,55 @@
|
||||
import { load, camel2kebab, isNil, getRoute } from './util'
|
||||
import { activeLink, scrollIntoView, sticky } from './event'
|
||||
import * as utils from './util'
|
||||
import { scrollIntoView, activeLink } from './event'
|
||||
import * as render from './render'
|
||||
|
||||
const OPTIONS = {
|
||||
const OPTIONS = utils.merge({
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
subMaxLevel: 0,
|
||||
loadSidebar: null,
|
||||
loadNavbar: null,
|
||||
router: false,
|
||||
homepage: 'README.md',
|
||||
coverpage: '',
|
||||
basePath: '',
|
||||
auto2top: false
|
||||
}
|
||||
auto2top: false,
|
||||
name: '',
|
||||
themeColor: '',
|
||||
nameLink: window.location.pathname,
|
||||
ga: ''
|
||||
}, window.$docsify)
|
||||
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
|
||||
|
||||
// load configuration for script attribute
|
||||
if (script) {
|
||||
for (const prop in OPTIONS) {
|
||||
const val = script.getAttribute('data-' + camel2kebab(prop))
|
||||
OPTIONS[prop] = isNil(val) ? OPTIONS[prop] : (val || true)
|
||||
const val = script.getAttribute('data-' + utils.camel2kebab(prop))
|
||||
OPTIONS[prop] = utils.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]
|
||||
if (OPTIONS.repo === true) OPTIONS.repo = ''
|
||||
if (OPTIONS.name === true) OPTIONS.name = ''
|
||||
}
|
||||
|
||||
// utils
|
||||
window.$docsify = OPTIONS
|
||||
window.Docsify = {
|
||||
installed: true,
|
||||
utils: utils.merge({}, utils)
|
||||
}
|
||||
|
||||
// load options
|
||||
render.config(OPTIONS)
|
||||
render.init()
|
||||
|
||||
let cacheRoute = null
|
||||
let cacheXhr = null
|
||||
|
||||
const mainRender = function (cb) {
|
||||
const route = OPTIONS.basePath + getRoute()
|
||||
const route = OPTIONS.basePath + utils.getRoute()
|
||||
if (cacheRoute === route) return cb()
|
||||
|
||||
let wait
|
||||
let basePath = cacheRoute = route
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -50,6 +59,7 @@ const mainRender = function (cb) {
|
||||
}
|
||||
|
||||
let page
|
||||
|
||||
if (!route) {
|
||||
page = OPTIONS.homepage || 'README.md'
|
||||
} else if (/\/$/.test(route)) {
|
||||
@@ -59,39 +69,32 @@ const mainRender = function (cb) {
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage) {
|
||||
if (page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(render.renderCover)
|
||||
} else {
|
||||
render.renderCover()
|
||||
}
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
utils.load(OPTIONS.coverpage).then(render.renderCover)
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort()
|
||||
// Render markdown file
|
||||
cacheXhr = load(page, 'GET', render.renderLoading)
|
||||
cacheXhr = utils.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) {
|
||||
if (wait === false) cb()
|
||||
wait = false
|
||||
const renderSidebar = result => { render.renderSidebar(result); cb() }
|
||||
|
||||
utils.load(basePath + OPTIONS.loadSidebar).then(renderSidebar,
|
||||
_ => utils.load(OPTIONS.loadSidebar).then(renderSidebar))
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}, _ => render.renderArticle(null))
|
||||
|
||||
// Render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
load(basePath + OPTIONS.loadSidebar).then(result => {
|
||||
render.renderSidebar(result)
|
||||
if (wait === false) cb()
|
||||
wait = false
|
||||
})
|
||||
}
|
||||
|
||||
// Render navbar
|
||||
if (OPTIONS.loadNavbar) {
|
||||
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar)
|
||||
utils.load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar,
|
||||
_ => utils.load(OPTIONS.loadNavbar).then(render.renderNavbar))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,19 +103,17 @@ const Docsify = function () {
|
||||
const replace = dom !== document.body
|
||||
const main = function () {
|
||||
mainRender(_ => {
|
||||
activeLink('aside.sidebar', true)
|
||||
scrollIntoView()
|
||||
OPTIONS.coverpage && sticky()
|
||||
activeLink('nav')
|
||||
;[].concat(window.$docsify.plugins).forEach(fn => fn && fn())
|
||||
})
|
||||
}
|
||||
|
||||
// Render app
|
||||
render.renderApp(dom, replace)
|
||||
main()
|
||||
if (OPTIONS.router) {
|
||||
if (!/^#\//.test(window.location.hash)) window.location.hash = '#/'
|
||||
window.addEventListener('hashchange', main)
|
||||
}
|
||||
if (!/^#\//.test(window.location.hash)) window.location.hash = '#/'
|
||||
window.addEventListener('hashchange', main)
|
||||
}
|
||||
|
||||
export default Docsify()
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// From https://github.com/egoist/vue-ga/blob/master/src/index.js
|
||||
|
||||
function appendScript () {
|
||||
const script = document.createElement('script')
|
||||
script.async = true
|
||||
script.src = 'https://www.google-analytics.com/analytics.js'
|
||||
document.body.appendChild(script)
|
||||
}
|
||||
|
||||
function init (id) {
|
||||
if (!window.ga) {
|
||||
appendScript()
|
||||
window.ga = window.ga || function () {
|
||||
(window.ga.q = window.ga.q || []).push(arguments)
|
||||
}
|
||||
window.ga.l = Number(new Date())
|
||||
window.ga('create', id, 'auto')
|
||||
}
|
||||
}
|
||||
|
||||
function collect () {
|
||||
init(window.$docsify.ga)
|
||||
window.ga('set', 'page', location.href)
|
||||
window.ga('send', 'pageview')
|
||||
}
|
||||
|
||||
const install = function () {
|
||||
if (!window.Docsify || !window.Docsify.installed) {
|
||||
console.error('[Docsify] Please load docsify.js first.')
|
||||
return
|
||||
}
|
||||
|
||||
if (!window.$docsify.ga) {
|
||||
console.error('[Docsify] ga is required.')
|
||||
return
|
||||
}
|
||||
|
||||
collect()
|
||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, collect)
|
||||
}
|
||||
|
||||
export default install()
|
||||
@@ -0,0 +1,337 @@
|
||||
let INDEXS = {}
|
||||
const CONFIG = {
|
||||
placeholder: 'Type to search',
|
||||
paths: 'auto',
|
||||
maxAge: 86400000 // 1 day
|
||||
}
|
||||
|
||||
const isObj = function (obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
const escapeHtml = function (string) {
|
||||
const entityMap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/'
|
||||
}
|
||||
|
||||
return String(string).replace(/[&<>"'\/]/g, s => entityMap[s])
|
||||
}
|
||||
|
||||
/**
|
||||
* find all filepath from A tag
|
||||
*/
|
||||
const getAllPaths = function () {
|
||||
const paths = []
|
||||
|
||||
;[].slice.call(document.querySelectorAll('a'))
|
||||
.map(node => {
|
||||
const href = node.href
|
||||
if (/#\/[^#]*?$/.test(href)) {
|
||||
const path = href.replace(/^[^#]+#/, '')
|
||||
|
||||
if (paths.indexOf(path) <= 0) paths.push(path)
|
||||
}
|
||||
})
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
/**
|
||||
* return file path
|
||||
*/
|
||||
const genFilePath = function (path) {
|
||||
const basePath = window.$docsify.basePath
|
||||
let filePath = /\/$/.test(path) ? `${path}README.md` : `${path}.md`
|
||||
|
||||
filePath = basePath + filePath
|
||||
|
||||
return filePath.replace(/\/+/g, '/')
|
||||
}
|
||||
|
||||
/**
|
||||
* generate index
|
||||
*/
|
||||
const genIndex = function (path, content = '') {
|
||||
INDEXS[path] = { slug: '', title: '', body: '' }
|
||||
let slug
|
||||
|
||||
content
|
||||
// remove PRE and TEMPLATE tag
|
||||
.replace(/<template[^>]*?>[\s\S]+?<\/template>/g, '')
|
||||
// find all html tag
|
||||
.replace(/<(\w+)([^>]*?)>([\s\S]+?)<\//g, (match, tag, attr, html) => {
|
||||
// remove all html tag
|
||||
const text = html.replace(/<[^>]+>/g, '')
|
||||
|
||||
// tag is headline
|
||||
if (/^h\d$/.test(tag)) {
|
||||
// <h1 id="xxx"></h1>
|
||||
const id = attr.match(/id="(\S+)"/)[1]
|
||||
|
||||
slug = `#/${path}#${id}`.replace(/\/+/, '/')
|
||||
INDEXS[slug] = { slug, title: text, body: '' }
|
||||
} else {
|
||||
if (!slug) return
|
||||
// other html tag
|
||||
if (!INDEXS[slug]) {
|
||||
INDEXS[slug] = {}
|
||||
} else {
|
||||
if (INDEXS[slug].body && INDEXS[slug].body.length) {
|
||||
INDEXS[slug].body += '\n' + text
|
||||
} else {
|
||||
INDEXS[slug].body = text
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* component
|
||||
*/
|
||||
class SearchComponent {
|
||||
constructor () {
|
||||
if (this.rendered) return
|
||||
|
||||
this.style()
|
||||
|
||||
const el = document.createElement('div')
|
||||
const aside = document.querySelector('aside')
|
||||
|
||||
el.classList.add('search')
|
||||
aside.insertBefore(el, aside.children[0])
|
||||
this.render(el)
|
||||
this.rendered = true
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
style () {
|
||||
const code = `
|
||||
.sidebar {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin-bottom: 20px;
|
||||
padding: 6px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.search .results-panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search .results-panel.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.search input {
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
padding: 7px;
|
||||
line-height: 22px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.search h2 {
|
||||
font-size: 17px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.search a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.search .matching-post {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.search .matching-post:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.search p {
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.search p.empty {
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
const style = document.createElement('style')
|
||||
|
||||
style.innerHTML = code
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
|
||||
render (dom) {
|
||||
dom.innerHTML = `<input type="search" placeholder="${CONFIG.placeholder}" /><div class="results-panel"></div>`
|
||||
}
|
||||
|
||||
bindEvent () {
|
||||
const search = document.querySelector('.search')
|
||||
const input = search.querySelector('.search input')
|
||||
const panel = search.querySelector('.results-panel')
|
||||
|
||||
search.addEventListener('click', e => e.target.tagName !== 'A' && e.stopPropagation())
|
||||
input.addEventListener('input', e => {
|
||||
const target = e.target
|
||||
|
||||
if (target.value.trim() !== '') {
|
||||
const matchingPosts = this.search(target.value)
|
||||
let html = ''
|
||||
|
||||
matchingPosts.forEach(function (post, index) {
|
||||
html += `
|
||||
<div class="matching-post">
|
||||
<h2><a href="${post.url}">${post.title}</a></h2>
|
||||
<p>${post.content}</p>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
if (panel.classList.contains('results-panel')) {
|
||||
panel.classList.add('show')
|
||||
panel.innerHTML = html || '<p class="empty">No Results!</p>'
|
||||
}
|
||||
} else {
|
||||
if (panel.classList.contains('results-panel')) {
|
||||
panel.classList.remove('show')
|
||||
panel.innerHTML = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// From [weex website] https://weex-project.io/js/common.js
|
||||
search (keywords) {
|
||||
const matchingResults = []
|
||||
const data = Object.keys(INDEXS).map(key => INDEXS[key])
|
||||
|
||||
keywords = keywords.trim().split(/[\s\-\,\\/]+/)
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const post = data[i]
|
||||
let isMatch = false
|
||||
let resultStr = ''
|
||||
const postTitle = post.title && post.title.trim()
|
||||
const postContent = post.body && post.body.trim()
|
||||
const postUrl = post.slug || ''
|
||||
|
||||
if (postTitle !== '' && postContent !== '') {
|
||||
keywords.forEach((keyword, i) => {
|
||||
const regEx = new RegExp(keyword, 'gi')
|
||||
let indexTitle = -1
|
||||
let indexContent = -1
|
||||
|
||||
indexTitle = postTitle.search(regEx)
|
||||
indexContent = postContent.search(regEx)
|
||||
|
||||
if (indexTitle < 0 && indexContent < 0) {
|
||||
isMatch = false
|
||||
} else {
|
||||
isMatch = true
|
||||
if (indexContent < 0) indexContent = 0
|
||||
|
||||
let start = 0
|
||||
let end = 0
|
||||
|
||||
start = indexContent < 11 ? 0 : indexContent - 10
|
||||
end = start === 0 ? 70 : indexContent + keyword.length + 60
|
||||
|
||||
if (end > postContent.length) end = postContent.length
|
||||
|
||||
const matchContent = '...' +
|
||||
postContent
|
||||
.substring(start, end)
|
||||
.replace(regEx, `<em class="search-keyword">${keyword}</em>`) +
|
||||
'...'
|
||||
|
||||
resultStr += matchContent
|
||||
}
|
||||
})
|
||||
|
||||
if (isMatch) {
|
||||
const matchingPost = {
|
||||
title: escapeHtml(postTitle),
|
||||
content: resultStr,
|
||||
url: postUrl
|
||||
}
|
||||
|
||||
matchingResults.push(matchingPost)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingResults
|
||||
}
|
||||
}
|
||||
|
||||
const searchPlugin = function () {
|
||||
const isAuto = CONFIG.paths === 'auto'
|
||||
const isExpired = localStorage.getItem('docsify.search.expires') < Date.now()
|
||||
|
||||
INDEXS = JSON.parse(localStorage.getItem('docsify.search.index'))
|
||||
|
||||
if (isExpired) {
|
||||
INDEXS = {}
|
||||
} else if (!isAuto) {
|
||||
return
|
||||
}
|
||||
|
||||
let count = 0
|
||||
const paths = isAuto ? getAllPaths() : CONFIG.paths
|
||||
const len = paths.length
|
||||
const { load, marked, slugify } = window.Docsify.utils
|
||||
const done = () => {
|
||||
localStorage.setItem('docsify.search.expires', Date.now() + CONFIG.maxAge)
|
||||
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS))
|
||||
}
|
||||
|
||||
paths.forEach(path => {
|
||||
if (INDEXS[path]) return count++
|
||||
|
||||
load(genFilePath(path)).then(content => {
|
||||
genIndex(path, marked(content))
|
||||
slugify.clear()
|
||||
count++
|
||||
|
||||
if (len === count) done()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const install = function () {
|
||||
if (!window.Docsify || !window.Docsify.installed) {
|
||||
console.error('[Docsify] Please load docsify.js first.')
|
||||
return
|
||||
}
|
||||
|
||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, searchPlugin)
|
||||
|
||||
const userConfig = window.$docsify.search
|
||||
const isNil = window.Docsify.utils.isNil
|
||||
|
||||
if (Array.isArray(userConfig)) {
|
||||
CONFIG.paths = userConfig
|
||||
} else if (isObj(userConfig)) {
|
||||
CONFIG.paths = Array.isArray(userConfig.paths) ? userConfig.paths : 'auto'
|
||||
CONFIG.maxAge = isNil(userConfig.maxAge) ? CONFIG.maxAge : userConfig.maxAge
|
||||
CONFIG.placeholder = userConfig.placeholder || CONFIG.placeholder
|
||||
}
|
||||
|
||||
new SearchComponent()
|
||||
}
|
||||
|
||||
export default install()
|
||||
@@ -0,0 +1,30 @@
|
||||
import { load } from './util'
|
||||
|
||||
function replaceVar (block) {
|
||||
block.innerHTML = block.innerHTML.replace(/var\(\s*--theme-color.*?\)/g, $docsify.themeColor)
|
||||
}
|
||||
|
||||
export function cssVars () {
|
||||
// variable support
|
||||
if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) return
|
||||
|
||||
const styleBlocks = document.querySelectorAll('style:not(.inserted),link')
|
||||
|
||||
;[].forEach.call(styleBlocks, block => {
|
||||
if (block.nodeName === 'STYLE') {
|
||||
replaceVar(block)
|
||||
} else if (block.nodeName === 'LINK') {
|
||||
const href = block.getAttribute('href')
|
||||
|
||||
if (!/\.css$/.test(href)) return
|
||||
|
||||
load(href).then(res => {
|
||||
const style = document.createElement('style')
|
||||
|
||||
style.innerHTML = res
|
||||
document.head.appendChild(style)
|
||||
replaceVar(style)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
+141
-71
@@ -1,74 +1,114 @@
|
||||
import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import * as tpl from './tpl'
|
||||
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top, sticky } from './event'
|
||||
import { genTree, getRoute, isMobile } from './util'
|
||||
import * as event from './event'
|
||||
import * as polyfill from './polyfill'
|
||||
import { genTree, getRoute, isMobile, slugify, merge, emojify } from './util'
|
||||
|
||||
let OPTIONS = {}
|
||||
let markdown = marked
|
||||
let toc = []
|
||||
const CACHE = {}
|
||||
|
||||
const renderTo = function (dom, content) {
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
|
||||
dom.innerHTML = content
|
||||
slugify.clear()
|
||||
|
||||
return dom
|
||||
}
|
||||
let toc = []
|
||||
const renderer = new marked.Renderer()
|
||||
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
* init render
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
|
||||
let route = ''
|
||||
export function init () {
|
||||
const renderer = new marked.Renderer()
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = slugify(text)
|
||||
let route = ''
|
||||
|
||||
if (OPTIONS.router) {
|
||||
route = `#/${getRoute()}`
|
||||
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
|
||||
|
||||
return `<h${level} id="${slug}"><a href="${route}#${slug}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
|
||||
}
|
||||
// highlight code
|
||||
renderer.code = function (code, lang = '') {
|
||||
const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup)
|
||||
|
||||
return `<pre v-pre data-lang="${lang}"><code class="lang-${lang}">${hl}</code></pre>`
|
||||
}
|
||||
renderer.link = function (href, title, text) {
|
||||
if (!/:/.test(href)) {
|
||||
href = `#/${href}`.replace(/\/+/g, '/')
|
||||
}
|
||||
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
}
|
||||
renderer.paragraph = function (text) {
|
||||
if (/^!>/.test(text)) {
|
||||
return tpl.helper('tip', text)
|
||||
} else if (/^\?>/.test(text)) {
|
||||
return tpl.helper('warn', text)
|
||||
}
|
||||
return `<p>${text}</p>`
|
||||
}
|
||||
|
||||
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 = '') {
|
||||
const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup)
|
||||
|
||||
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 = !/^\/#/.test(href) ? `#${href}` : href
|
||||
if (typeof $docsify.markdown === 'function') {
|
||||
markdown.setOptions({ renderer })
|
||||
markdown = $docsify.markdown.call(this, markdown)
|
||||
} else {
|
||||
markdown.setOptions(merge({ renderer }, $docsify.markdown))
|
||||
}
|
||||
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
const md = markdown
|
||||
|
||||
markdown = text => emojify(md(text))
|
||||
|
||||
window.Docsify.utils.marked = text => {
|
||||
const result = markdown(text)
|
||||
toc = []
|
||||
return result
|
||||
}
|
||||
}
|
||||
marked.setOptions({ renderer })
|
||||
|
||||
/**
|
||||
* App
|
||||
*/
|
||||
export function renderApp (dom, replace) {
|
||||
const nav = document.querySelector('nav') || document.createElement('nav')
|
||||
const body = document.body
|
||||
const head = document.head
|
||||
|
||||
if (!OPTIONS.repo) nav.classList.add('no-badge')
|
||||
if (!$docsify.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])
|
||||
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner($docsify.repo) +
|
||||
($docsify.coverpage ? tpl.cover() : '') +
|
||||
tpl.main()
|
||||
body.insertBefore(nav, body.children[0])
|
||||
|
||||
// theme color
|
||||
if ($docsify.themeColor) {
|
||||
head.innerHTML += tpl.theme($docsify.themeColor)
|
||||
polyfill.cssVars()
|
||||
}
|
||||
|
||||
// render name
|
||||
if ($docsify.name) {
|
||||
const aside = document.querySelector('.sidebar')
|
||||
aside.innerHTML = `<h1><a href="${$docsify.nameLink}">${$docsify.name}</a></h1>` + aside.innerHTML
|
||||
}
|
||||
|
||||
// bind toggle
|
||||
bindToggle('button.sidebar-toggle')
|
||||
event.bindToggle('button.sidebar-toggle')
|
||||
// bind sticky effect
|
||||
if (OPTIONS.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', sticky)
|
||||
if ($docsify.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', event.sticky)
|
||||
} else {
|
||||
document.body.classList.add('sticky')
|
||||
body.classList.add('sticky')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +116,25 @@ export function renderApp (dom, replace) {
|
||||
* article
|
||||
*/
|
||||
export function renderArticle (content) {
|
||||
renderTo('article', content ? marked(content) : 'not found')
|
||||
if (!renderSidebar.rendered) renderSidebar(null, OPTIONS)
|
||||
if (!renderNavbar.rendered) renderNavbar(null, OPTIONS)
|
||||
renderSidebar.rendered = false
|
||||
renderNavbar.rendered = false
|
||||
renderTo('article', content ? markdown(content) : 'not found')
|
||||
if (!$docsify.loadSidebar) renderSidebar()
|
||||
|
||||
if (OPTIONS.auto2top) scroll2Top()
|
||||
if (content && typeof Vue !== 'undefined') {
|
||||
CACHE.vm && CACHE.vm.$destroy()
|
||||
|
||||
const script = [].slice.call(
|
||||
document.body.querySelectorAll('article>script'))
|
||||
.filter(script => !/template/.test(script.type)
|
||||
)[0]
|
||||
const code = script ? script.innerText.trim() : null
|
||||
|
||||
script && script.remove()
|
||||
CACHE.vm = code
|
||||
? new Function(`return ${code}`)()
|
||||
: new Vue({ el: 'main' }) // eslint-disable-line
|
||||
CACHE.vm && CACHE.vm.$nextTick(_ => event.scrollActiveSidebar())
|
||||
}
|
||||
if ($docsify.auto2top) setTimeout(() => event.scroll2Top($docsify.auto2top), 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,33 +143,36 @@ export function renderArticle (content) {
|
||||
export function renderNavbar (content) {
|
||||
if (CACHE.navbar && CACHE.navbar === content) return
|
||||
CACHE.navbar = content
|
||||
renderNavbar.rendered = true
|
||||
|
||||
if (content) renderTo('nav', marked(content))
|
||||
activeLink('nav')
|
||||
if (content) renderTo('nav', markdown(content))
|
||||
event.activeLink('nav')
|
||||
}
|
||||
|
||||
/**
|
||||
* sidebar
|
||||
*/
|
||||
export function renderSidebar (content) {
|
||||
let isToc = false
|
||||
let html
|
||||
|
||||
if (content) {
|
||||
content = marked(content)
|
||||
} else if (OPTIONS.sidebar) {
|
||||
content = tpl.tree(OPTIONS.sidebar, '<ul>')
|
||||
html = markdown(content)
|
||||
// find url tag
|
||||
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
|
||||
} else {
|
||||
content = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
||||
isToc = true
|
||||
html = tpl.tree(genTree(toc, $docsify.maxLevel), '<ul>')
|
||||
}
|
||||
|
||||
renderSidebar.rendered = true
|
||||
if (CACHE.sidebar && CACHE.sidebar === content) return
|
||||
CACHE.sidebar = content
|
||||
renderTo('aside.sidebar', content)
|
||||
if (isToc) scrollActiveSidebar()
|
||||
renderTo('.sidebar-nav', html)
|
||||
const target = event.activeLink('.sidebar-nav', true)
|
||||
if (target) renderSubSidebar(target)
|
||||
toc = []
|
||||
|
||||
event.scrollActiveSidebar()
|
||||
}
|
||||
|
||||
export function renderSubSidebar (target) {
|
||||
if (!$docsify.subMaxLevel) return
|
||||
target.parentNode.innerHTML += tpl.tree(genTree(toc, $docsify.subMaxLevel), '<ul>')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,12 +181,36 @@ export function renderSidebar (content) {
|
||||
export function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover')
|
||||
if (!content) {
|
||||
renderCover.dom.classList.add('hidden')
|
||||
} else {
|
||||
renderCover.dom.classList.remove('hidden')
|
||||
!renderCover.rendered && renderTo('.cover-main', marked(content))
|
||||
renderCover.rendered = true
|
||||
renderCover.dom.classList.remove('show')
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show')
|
||||
if (renderCover.rendered) return event.sticky()
|
||||
|
||||
// render cover
|
||||
const cacheToc = toc.slice()
|
||||
let html = markdown(content)
|
||||
const match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$')
|
||||
|
||||
toc = cacheToc.slice()
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
const coverEl = document.querySelector('section.cover')
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1] + (match[3] || '')
|
||||
} else {
|
||||
coverEl.classList.add('has-mask')
|
||||
coverEl.style.backgroundImage = `url(${match[1]})`
|
||||
}
|
||||
html = html.replace(match[0], '')
|
||||
}
|
||||
|
||||
renderTo('.cover-main', html)
|
||||
renderCover.rendered = true
|
||||
|
||||
event.sticky()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,12 +245,3 @@ export function renderLoading ({ loaded, total, step }) {
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Config
|
||||
* @param {Object} options
|
||||
*/
|
||||
export function config (options) {
|
||||
OPTIONS = options
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
section.cover {
|
||||
&.hidden {
|
||||
display: none;
|
||||
align-items: center;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
display: none;
|
||||
|
||||
&.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
&.has-mask .mask {
|
||||
position: absolute;
|
||||
size: 100%;
|
||||
background-color: $color-bg;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.cover-main {
|
||||
position: absolute 0 0 0 0;
|
||||
padding: 20vh 0;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
margin: 0 16px;
|
||||
margin: -20px 16px 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -22,6 +33,11 @@ section.cover {
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 2.5rem;
|
||||
@@ -30,6 +46,10 @@ section.cover {
|
||||
font-weight: 300;
|
||||
color: inherit;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
small {
|
||||
position: absolute;
|
||||
bottom: -.4375rem;
|
||||
@@ -50,12 +70,13 @@ section.cover {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
p a {
|
||||
margin-top: 1em;
|
||||
.cover-main p:last-child a {
|
||||
border-radius: 2em;
|
||||
border: 1px solid $color-primary;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--theme-color, $color-primary);
|
||||
box-sizing: border-box;
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
font-size: 1.05em;
|
||||
letter-spacing: 0.1em;
|
||||
padding: 0.75em 2em;
|
||||
@@ -66,7 +87,7 @@ section.cover {
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
background-color: $color-primary;
|
||||
background-color: var(--theme-color, $color-primary);
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
|
||||
+139
-19
@@ -7,8 +7,13 @@
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
height: 1.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-color: $color-primary;
|
||||
background-color: var(--theme-color, $color-primary);
|
||||
height: 2px;
|
||||
left: 0px;
|
||||
position: fixed;
|
||||
@@ -19,6 +24,15 @@
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.search a:hover {
|
||||
color: var(--theme-color, $color-primary);
|
||||
}
|
||||
|
||||
.search .search-keyword {
|
||||
color: var(--theme-color, $color-primary);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
@@ -31,6 +45,7 @@ body {
|
||||
letter-spacing: 0;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
color: $color-text;
|
||||
}
|
||||
|
||||
img {
|
||||
@@ -80,12 +95,12 @@ nav {
|
||||
transition: color .3s;
|
||||
|
||||
&:hover {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $color-primary;
|
||||
border-bottom: 2px solid $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
border-bottom: 2px solid var(--theme-color, $color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,8 +110,11 @@ nav {
|
||||
display: inline-block;
|
||||
|
||||
ul {
|
||||
background-color: rgba(#fff, .6);
|
||||
border: 1px solid $color-primary;
|
||||
border-radius: 2px;
|
||||
background-color: rgba($color-bg, .6);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--theme-color, $color-primary);
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
@@ -150,23 +168,28 @@ nav {
|
||||
}
|
||||
|
||||
svg {
|
||||
color: #fff;
|
||||
color: $color-bg;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
fill: $color-primary;
|
||||
fill: var(--theme-color, $color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* main */
|
||||
main {
|
||||
size: 100% 100%;
|
||||
display: block;
|
||||
size: 100vw 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.anchor {
|
||||
text-decoration: none;
|
||||
transition: all .3s;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
|
||||
span {
|
||||
color: $color-text;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
@@ -175,13 +198,25 @@ main {
|
||||
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
border-right: 1px solid rgba(0, 0, 0, .07);
|
||||
overflow-y: auto;
|
||||
padding-top: 40px;
|
||||
padding: 40px 0;
|
||||
position: absolute 0 * 0 0;
|
||||
transition: transform 250ms ease-out;
|
||||
width: $sidebar-width;
|
||||
z-index: 20;
|
||||
border-right: 1px solid rgba(0, 0, 0, .07);
|
||||
|
||||
> h1 {
|
||||
text-align: center;
|
||||
margin: 0 auto 1em;
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
@@ -200,28 +235,46 @@ main {
|
||||
ul li ul {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&:hover::-webkit-scrollbar-thumb {
|
||||
background: rgba(136, 136, 136, 0.4);
|
||||
}
|
||||
|
||||
&:hover::-webkit-scrollbar-track {
|
||||
background: rgba(136, 136, 136, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* sidebar toggle */
|
||||
.sidebar-toggle {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
position: absolute * * 0 0;
|
||||
text-align: center;
|
||||
transition: opacity .3s;
|
||||
width: 30px;
|
||||
z-index: 30;
|
||||
outline: none;
|
||||
width: calc($sidebar-width - 16px);
|
||||
padding: 10px;
|
||||
background-color: rgba($color-bg, .8);
|
||||
|
||||
&:hover {
|
||||
.sidebar-toggle-button:hover {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
span {
|
||||
background-color: $color-primary;
|
||||
background-color: var(--theme-color, $color-primary);
|
||||
display: block;
|
||||
size: 16px 2px;
|
||||
margin-bottom: 4px;
|
||||
@@ -258,6 +311,12 @@ body.sticky {
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section hr {
|
||||
border: none;
|
||||
margin: 2em 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.markdown-section table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
@@ -285,11 +344,55 @@ body.sticky {
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section p.tip {
|
||||
padding: 12px 24px 12px 30px;
|
||||
margin: 2em 0;
|
||||
border-left: 4px solid #f66;
|
||||
background-color: #f8f8f8;
|
||||
position: relative;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: -12px;
|
||||
background-color: #f66;
|
||||
color: $color-bg;
|
||||
content: "!";
|
||||
size: 20px;
|
||||
border-radius: 100%;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
font-weight: bold;
|
||||
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
em {
|
||||
color: $color-text;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section p.warn {
|
||||
padding: 1em;
|
||||
background: rgba($color-primary, 0.1);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
body.close {
|
||||
.sidebar {
|
||||
transform: translateX(-$sidebar-width);
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
left: 0;
|
||||
}
|
||||
@@ -308,6 +411,11 @@ body.close {
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
main {
|
||||
height: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
left: -$sidebar-width;
|
||||
transition: transform 250ms ease-out;
|
||||
@@ -315,7 +423,8 @@ body.close {
|
||||
|
||||
.content {
|
||||
left: 0;
|
||||
min-width: 100vw;
|
||||
max-width: 100vw;
|
||||
position: static;
|
||||
transition: transform 250ms ease;
|
||||
}
|
||||
|
||||
@@ -323,17 +432,28 @@ body.close {
|
||||
transition: transform 250ms ease-out;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
width: auto;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
body.close {
|
||||
.sidebar {
|
||||
transform: translateX($sidebar-width);
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
width: calc($sidebar-width - 16px);
|
||||
background-color: rgba($color-bg, .8);
|
||||
transition: 1s background-color;
|
||||
}
|
||||
|
||||
.content {
|
||||
transform: translateX($sidebar-width);
|
||||
}
|
||||
|
||||
nav, .github-corner {
|
||||
transform: translateX($sidebar-width);
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-19
@@ -1,18 +1,17 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
|
||||
|
||||
$color-primary: #0074D9;
|
||||
$color-bg: #fff;
|
||||
$color-text: #34495e;
|
||||
$sidebar-width: 16em;
|
||||
|
||||
@import "basic/layout";
|
||||
@import "basic/coverpage";
|
||||
|
||||
body {
|
||||
color: #34495e;
|
||||
}
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
@@ -29,7 +28,7 @@ body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
li.active {
|
||||
background-color: #eee;
|
||||
|
||||
a {
|
||||
@@ -48,7 +47,7 @@ body {
|
||||
}
|
||||
|
||||
.markdown-section a {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -111,7 +110,7 @@ body {
|
||||
|
||||
.markdown-section blockquote {
|
||||
color: #858585;
|
||||
border-left: 4px solid $color-primary;
|
||||
border-left: 4px solid var(--theme-color, $color-primary);
|
||||
margin: 2em 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
@@ -239,15 +238,3 @@ code .token {
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
}
|
||||
|
||||
.content span.light {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.content span.info {
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
margin-left: 20px;
|
||||
vertical-align: middle;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
$color-primary: #000;
|
||||
$color-bg: #fff;
|
||||
$color-text: #000;
|
||||
$sidebar-width: 300px;
|
||||
@import "basic/layout";
|
||||
|
||||
+11
-21
@@ -1,31 +1,33 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
|
||||
|
||||
$color-primary: #42b983;
|
||||
$color-bg: #fff;
|
||||
$color-text: #34495e;
|
||||
$sidebar-width: 300px;
|
||||
|
||||
@import "basic/layout";
|
||||
@import "basic/coverpage";
|
||||
|
||||
body {
|
||||
background-color: #fff;
|
||||
color: #34495e;
|
||||
background-color: $color-bg;
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
|
||||
li {
|
||||
margin: 6px 15px;
|
||||
}
|
||||
|
||||
ul li a {
|
||||
color: #7f8c8d;
|
||||
color: #505d6b;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
@@ -37,7 +39,7 @@ body {
|
||||
}
|
||||
|
||||
ul li.active>a {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +55,7 @@ body {
|
||||
}
|
||||
|
||||
.markdown-section a {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -106,7 +108,7 @@ body {
|
||||
|
||||
.markdown-section blockquote {
|
||||
color: #858585;
|
||||
border-left: 4px solid $color-primary;
|
||||
border-left: 4px solid var(--theme-color, $color-primary);
|
||||
margin: 2em 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
@@ -178,7 +180,7 @@ body {
|
||||
}
|
||||
|
||||
.token.string {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
@@ -200,7 +202,7 @@ body {
|
||||
.token.control,
|
||||
.token.directive,
|
||||
.token.unit {
|
||||
color: $color-primary;
|
||||
color: var(--theme-color, $color-primary);
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
@@ -284,15 +286,3 @@ pre::after {
|
||||
text-align: right;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.content span.light {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.content span.info {
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
margin-left: 20px;
|
||||
vertical-align: middle;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
+19
-9
@@ -1,4 +1,4 @@
|
||||
|
||||
import { isMobile } from './util'
|
||||
/**
|
||||
* Render github corner
|
||||
* @param {Object} data
|
||||
@@ -22,14 +22,14 @@ export function corner (data) {
|
||||
/**
|
||||
* Render main content
|
||||
*/
|
||||
export function main (tpl) {
|
||||
return `<main>
|
||||
${tpl}
|
||||
<aside class="sidebar"></aside>
|
||||
<section class="content">
|
||||
export function main () {
|
||||
const aside = `${toggle()}<aside class="sidebar"><div class="sidebar-nav"></div></aside>`
|
||||
|
||||
return (isMobile() ? `${aside}<main>` : `<main>${aside}`) +
|
||||
`<section class="content">
|
||||
<article class="markdown-section"></article>
|
||||
</section>
|
||||
</main>`
|
||||
</main>`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,13 +41,16 @@ export function cover () {
|
||||
|
||||
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>`
|
||||
<div class="sidebar-toggle-button">
|
||||
<span></span><span></span><span></span>
|
||||
</div>
|
||||
</button>`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,3 +72,10 @@ export function tree (toc, tpl = '') {
|
||||
return tpl
|
||||
}
|
||||
|
||||
export function helper (className, content) {
|
||||
return `<p class="${className}">${content.slice(5).trim()}</p>`
|
||||
}
|
||||
|
||||
export function theme (color) {
|
||||
return `<style>:root{--theme-color: ${color};}</style>`
|
||||
}
|
||||
|
||||
+60
-1
@@ -89,7 +89,7 @@ export function getRoute () {
|
||||
const loc = window.location
|
||||
if (cacheHash === loc.hash && !isNil(cacheRoute)) return cacheRoute
|
||||
|
||||
let route = loc.hash.match(/^#\/([^#]+)/)
|
||||
let route = loc.hash.replace(/%23/g, '#').match(/^#\/([^#]+)/)
|
||||
|
||||
if (route && route.length === 2) {
|
||||
route = route[1]
|
||||
@@ -106,3 +106,62 @@ 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(/<[^>\d]+>/g, '')
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, replacement)
|
||||
.replace(/-+/g, replacement)
|
||||
.replace(/^(\d)/, '_$1')
|
||||
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
|
||||
}
|
||||
|
||||
slugify.clear = function () {
|
||||
slugify.occurrences = {}
|
||||
}
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
export const merge = Object.assign || function (to) {
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
const from = Object(arguments[i])
|
||||
|
||||
for (const key in from) {
|
||||
if (hasOwnProperty.call(from, key)) {
|
||||
to[key] = from[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to
|
||||
}
|
||||
|
||||
export function emojify (text) {
|
||||
return text
|
||||
.replace(/<(pre|template)[^>]*?>([\s\S]+)<\/(pre|template)>/g, match => match.replace(/:/g, '__colon__'))
|
||||
.replace(/:(\w*?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
|
||||
.replace(/__colon__/g, ':')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user