mirror of
https://github.com/wahyd4/docsify.git
synced 2026-08-09 13:26:34 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
6c2e7dca99 | ||
|
|
a39eddba74 | ||
|
|
50addfdac6 | ||
|
|
b14fcf7d1c | ||
|
|
3b02b8fc39 | ||
|
|
039c7a7a6f | ||
|
|
0101492dd4 | ||
|
|
60fc73c691 | ||
|
|
476d49bc1f | ||
|
|
73456e6fac | ||
|
|
f9d75ab931 | ||
|
|
f93f9ceb09 | ||
|
|
b57712dd5a | ||
|
|
f2d894932b | ||
|
|
48912a0b79 | ||
|
|
73a193d602 | ||
|
|
30b6644f21 | ||
|
|
d343ff5b21 | ||
|
|
3bf932a81c | ||
|
|
c8bb66955d | ||
|
|
e5e1e07e1a | ||
|
|
9ba989c86c | ||
|
|
ab34cc97f9 | ||
|
|
3fbcd876ae | ||
|
|
3af5ca5cd4 | ||
|
|
74ee0cf6bc | ||
|
|
46dd542b48 | ||
|
|
cc7bdf5df2 | ||
|
|
9a1db6ed43 | ||
|
|
9d30ac7435 | ||
|
|
f8a68b87c7 | ||
|
|
7dc47cc4d4 | ||
|
|
7d995d8362 | ||
|
|
1fdfaf0b6b | ||
|
|
fe33e2d506 | ||
|
|
6463dd3bae | ||
|
|
299c31dff9 | ||
|
|
aa1d84b513 | ||
|
|
14a4c2f77d | ||
|
|
e58c17fdc6 | ||
|
|
8b719238e6 | ||
|
|
7f0b1089c0 | ||
|
|
2610e25040 | ||
|
|
ec53f1e307 | ||
|
|
670cc68a28 | ||
|
|
844ba3e022 | ||
|
|
9092b22246 |
@@ -1,3 +1,4 @@
|
||||
.DS_Store
|
||||
*.log
|
||||
node_modules
|
||||
yarn.lock
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.yarn-cache
|
||||
language: node_js
|
||||
node_js: stable
|
||||
|
||||
@@ -1,3 +1,99 @@
|
||||
## 1.4.0 Happly new year 🎉
|
||||
### Features
|
||||
- Display TOC in the custom sidebar, `data-sub-max-level`.
|
||||
- Custom background in coverpage.
|
||||
|
||||
### Bug fixes
|
||||
- Fix scroll highlight when Vue exist.
|
||||
|
||||
## 1.3.5
|
||||
### Bug fixes
|
||||
- Fix vue
|
||||
|
||||
## 1.3.4
|
||||
### Bug fixes
|
||||
|
||||
- Supports [vuep](https://github.com/QingWei-Li/vuep)
|
||||
|
||||
## 1.3.3
|
||||
### Bug fixes
|
||||
- Fixed cover rendering timing
|
||||
|
||||
## 1.3.2
|
||||
|
||||
### Bug fixes
|
||||
- Fixed render link
|
||||
|
||||
## 1.3.1
|
||||
|
||||
### Bug fixes
|
||||
- Fixed cover page style
|
||||
- Generate the correct link when rendering the article
|
||||
|
||||
## 1.3.0
|
||||
### Features
|
||||
- Add cover page
|
||||
- add `<kbd>` style
|
||||
- headling can be cliked
|
||||
|
||||
### Bug fixes
|
||||
- sidebar highlight
|
||||
|
||||
|
||||
### break change
|
||||
- Navbar no longer fixed at the top
|
||||
|
||||
## 1.2.0
|
||||
### Features
|
||||
- custom basePath
|
||||
- custom homepage
|
||||
|
||||
## 1.1.7
|
||||
### Bug fixes
|
||||
- Optimize progress bar
|
||||
|
||||
## 1.1.6
|
||||
### Features
|
||||
- Add logo 😂
|
||||
|
||||
### Bug fixes
|
||||
- Remove table background color
|
||||
- Fixed highlight sidebar using chinese ids
|
||||
|
||||
## 1.1.5
|
||||
### Features
|
||||
- Add table style
|
||||
|
||||
### Bug fixes
|
||||
- Not fixed position of hte navbar in the mobile browser
|
||||
- Correct calculation of whether the mobile browser
|
||||
|
||||
## 1.1.4
|
||||
### Bug fixes
|
||||
- Fixed chinese auchor link
|
||||
|
||||
## 1.1.3
|
||||
### Bug fixes
|
||||
- Optimize progress bar again
|
||||
|
||||
## 1.1.2
|
||||
### Bug fixes
|
||||
- fix failed `auto2top` in mobile
|
||||
|
||||
|
||||
## 1.1.1
|
||||
### Bug fixes
|
||||
- Optimize progress bar
|
||||
|
||||
## 1.1.0
|
||||
## Features
|
||||
- Add progress bar
|
||||
- Add `auto2top` option for hash router
|
||||
|
||||
## 1.0.3
|
||||
### Bug fixes
|
||||
- Fix cache
|
||||
|
||||
## 1.0.2
|
||||
### Bug fixes
|
||||
- Fix binding events bug, fixed #24
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
# docsify
|
||||
[](https://travis-ci.org/QingWei-Li/docsify)
|
||||
[](https://www.npmjs.com/package/docsify)
|
||||
<p align="center">
|
||||
<a href="https://docsify.js.org">
|
||||
<img alt="docsify" src="./media/docsify.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
>🃏 A magical documentation site generator.
|
||||
<p align="center">
|
||||
A magical documentation site generator.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/QingWei-Li/docsify"><img alt="Travis Status" src="https://img.shields.io/travis/rust-lang/rust/master.svg?style=flat-square"></a>
|
||||
<a href="https://www.npmjs.com/package/docsify"><img alt="npm" src="https://img.shields.io/npm/v/docsify.svg?style=flat-square"></a>
|
||||
<a href="https://github.com/vuejs/vue"><img alt="code style" src="https://img.shields.io/badge/code%20style-vue-orange.svg?style=flat-square"></a>
|
||||
</p>
|
||||
|
||||
## Links
|
||||
- [Documentation](https://docsify.js.org)
|
||||
- [CLI](https://github.com/QingWei-Li/docsify-cli)
|
||||
|
||||
## Features
|
||||
- Easy and lightweight
|
||||
- Custom themes
|
||||
- No build
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Multiple themes
|
||||
- Not build static html files
|
||||
|
||||
## Quick start
|
||||
Create a `404.html` and `README.md` into `/docs`.
|
||||
|
||||
404.html
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
|
||||
</head>
|
||||
<body></body>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
Or Create a `index.html` and using `hash router`.
|
||||
Create a `index.html` and using `hash router`.
|
||||
|
||||
index.html
|
||||
|
||||
@@ -41,22 +35,43 @@ index.html
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
|
||||
</head>
|
||||
<body></body>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="//unpkg.com/docsify" data-router></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)
|
||||
|
||||
## 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.
|
||||
|
||||
## How to contribute
|
||||
## Similar projects
|
||||
- [docute](https://github.com/egoist/docute) - 📜 Effortlessly documentation done right
|
||||
- [docpress](https://github.com/docpress/docpress) - Documentation website generator
|
||||
|
||||
## Contributing
|
||||
|
||||
- Fork it!
|
||||
- Run `npm i && npm run dev`
|
||||
- open `localhost:3000`
|
||||
- Create your feature branch: `git checkout -b my-new-feature`
|
||||
- Commit your changes: `git commit -am 'Add some feature'`
|
||||
- Push to the branch: `git push origin my-new-feature`
|
||||
- Submit a pull request :D
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
```shell
|
||||
npm i && npm run dev
|
||||
open http://localhost:3000
|
||||
```
|
||||
|
||||
## License
|
||||
MIT
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -8,5 +8,7 @@
|
||||
<body class="">
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-sidebar-toggle data-router data-load-sidebar></script>
|
||||
<script src=//unpkg.com/vue></script>
|
||||
<script src=//unpkg.com/vuep></script>
|
||||
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-auto2top data-sidebar-toggle data-router></script>
|
||||
</html>
|
||||
+112
-23
@@ -1,12 +1,3 @@
|
||||
# docsify
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
## Features
|
||||
- Easy and lightweight
|
||||
- Custom themes
|
||||
- No build
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Create a project
|
||||
@@ -17,7 +8,7 @@ mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### Create entry file
|
||||
Create a `404.html` file
|
||||
Create a `index.html` file
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
@@ -29,7 +20,7 @@ Create a `404.html` file
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/docsify" data-router></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -38,7 +29,7 @@ Create `README.md` as the main page
|
||||
```
|
||||
# Title
|
||||
|
||||
## balabala
|
||||
## blabla
|
||||
```
|
||||
|
||||
### Deploy!
|
||||
@@ -47,7 +38,7 @@ Push and open the **GitHub Pages** feature
|
||||
|
||||
## CLI
|
||||
|
||||
Easy to setup and preivew a docs.
|
||||
Easy to setup and preview a docs.
|
||||
|
||||
### Install
|
||||
```shell
|
||||
@@ -86,18 +77,61 @@ Minified files
|
||||
## 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)
|
||||
|
||||
|
||||
### Cover Page
|
||||
|
||||
Generate a cover page through with markdown. Create a `_coverpage.md` and set `data-coverpage` in script tag.
|
||||
|
||||
```markdown
|
||||

|
||||
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Multiple themes
|
||||
- Not build static html files
|
||||
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
```
|
||||
|
||||
#### Custom background
|
||||
Currently the background of cover page is generated randomly. We can customize the background, just using the syntax to add image.
|
||||
|
||||
```markdown
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
> xxx
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
|
||||
<!-- background image -->
|
||||

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

|
||||
```
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
#### repo
|
||||
@@ -108,7 +142,7 @@ Display the [GitHub Corner](http://tholman.com/github-corners/) widget.
|
||||
```
|
||||
|
||||
#### max-level
|
||||
Toc level.
|
||||
TOC level.
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-max-level="6"></script>
|
||||
@@ -131,7 +165,7 @@ Sidebar with toggle
|
||||
|
||||
#### sidebar
|
||||
|
||||
Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on the `data-sidebar`.
|
||||
Custom sidebar. If it's set, the TOC will be disabled. Bind global variables on the `data-sidebar`.
|
||||
|
||||

|
||||
|
||||
@@ -155,7 +189,8 @@ Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on th
|
||||
|
||||
#### 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.
|
||||
Load sidebar markdown file. If it is configured, load the current directory `_sidebar.md` by default. If the file isn't exist, sidebar will appear as a TOC.
|
||||
** you should add `.nojekyll` into docs folder to prevent GitHub Pages from ignoring the `_sidebar.md`**
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar></script>
|
||||
@@ -183,9 +218,21 @@ The contents of the file can be:
|
||||
- [HTML5 History Mode](/history-mode)
|
||||
```
|
||||
|
||||
#### sub-max-level
|
||||
|
||||
Display TOC in the custom sidebar. The default value is 0.
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
#### load-navbar
|
||||
|
||||
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
|
||||
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>
|
||||
@@ -213,10 +260,52 @@ If you write a sub level list, it will generate a dropdown list.
|
||||
- [chinese](/zh-cn)
|
||||
```
|
||||
|
||||
### router
|
||||
#### router
|
||||
|
||||
Hash router. You can replace `404.html` with `index.html`.
|
||||
Hash router.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-router></script>
|
||||
```
|
||||
|
||||
#### auto2top
|
||||
|
||||
Scroll to the top on changing hash.
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-auto2top></script>
|
||||
```
|
||||
|
||||
#### homepage
|
||||
|
||||
`README.md` will be rendered as a homepage for your website in the docs folder, but sometimes we want to specify another file as a homepage, or even use the `README.md` in your repo. We can use (need `data-router`):
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-homepage="https://raw.githubusercontent.com/QingWei-Li/docsify/master/README.md"></script>
|
||||
<!-- Or using `Welcome.md` as homepge -->
|
||||
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
|
||||
```
|
||||
|
||||
|
||||
#### basePath
|
||||
|
||||
If your HTML entry file and the markdown files are in different directories, we can use:
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-base-path="/base/"></script>
|
||||
|
||||
<!-- Even if the docs is on another site 😄 -->
|
||||
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
|
||||
```
|
||||
|
||||
|
||||
#### coverpage
|
||||
|
||||
Generate cover page.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-coverpage></script>
|
||||
<!-- or -->
|
||||
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||

|
||||
|
||||
# docsify <small>1.3.3</small>
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Multiple themes
|
||||
- Not build static html files
|
||||
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="122px" height="94px" viewBox="0 0 122 94" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>icon</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<path d="M144.453286,104 C177.038086,104 203.453286,77.5848002 203.453286,45 C203.453286,12.4151998 177.038086,-14 144.453286,-14 C111.868486,-14 114.603207,13.6754846 114.603207,46.2602848 C114.603207,78.845085 111.868486,104 144.453286,104 Z" id="path-1"></path>
|
||||
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2">
|
||||
<feOffset dx="7" dy="-10" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
|
||||
<feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="icon" transform="translate(-98.000000, 2.000000)">
|
||||
<g id="body" transform="translate(159.000000, 45.000000) rotate(-90.000000) translate(-159.000000, -45.000000) ">
|
||||
<use fill="#2ECE53" fill-rule="evenodd" xlink:href="#path-1"></use>
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
|
||||
<use stroke="#0E1320" stroke-width="4" xlink:href="#path-1"></use>
|
||||
</g>
|
||||
<circle id="left-eye" fill="#000000" cx="139" cy="38" r="7"></circle>
|
||||
<circle id="right-eye" fill="#000000" cx="183" cy="38" r="7"></circle>
|
||||
<g id="light" transform="translate(112.000000, 10.000000)" fill="#FFFFFF">
|
||||
<circle cx="2" cy="28" r="2"></circle>
|
||||
<path d="M12.2551528,-1.65016666 C12.1154537,-2.17684986 12.4455583,-2.60381096 13.011574,-2.60381096 L14.9928363,-2.60381096 C15.5502953,-2.60381096 16.1214654,-2.16566487 16.2594657,-1.64268776 C16.2594657,-1.64268776 17.4280152,2.48668594 17.9030739,6.45786647 C18.3781327,10.429047 18.3171359,10.4652901 18.3171359,12.1782569 C18.3171359,16.9413523 16.2076398,26.4389164 16.2076398,26.4389164 C16.0941814,26.9676035 15.558852,27.396189 14.9928363,27.396189 L13.011574,27.396189 C12.454115,27.396189 12.1166642,26.9691757 12.2568366,26.4301177 C12.2568366,26.4301177 13.4260575,22.2288768 13.9640759,17.9859148 C14.5020943,13.7429529 14.309594,15.2982629 14.5626609,12.3723978 C14.9355337,8.06138047 12.2551528,-1.65016666 12.2551528,-1.65016666 Z" id="light-line" transform="translate(15.271433, 12.396189) scale(-1, 1) rotate(-48.000000) translate(-15.271433, -12.396189) "></path>
|
||||
</g>
|
||||
<path d="M159.5,78.3050108 C169.164983,78.3050108 177,70.4699939 177,60.8050108 C177,51.1400277 169.688728,56.4616841 160.023745,56.4616841 C150.358762,56.4616841 142,51.1400277 142,60.8050108 C142,70.4699939 149.835017,78.3050108 159.5,78.3050108 Z" id="mouth" fill="#000000"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
+3
-2
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>docsify - A magical documentation site generator.</title>
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<meta name="description" content="A magical documentation generator.">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
|
||||
@@ -16,8 +17,8 @@
|
||||
</body>
|
||||
<script
|
||||
src="//unpkg.com/docsify/lib/docsify.min.js"
|
||||
data-repo="qingwei-li/docsify"
|
||||
data-max-level="3"
|
||||
data-max-level="4"
|
||||
data-sidebar-toggle
|
||||
data-coverpage
|
||||
data-router></script>
|
||||
</html>
|
||||
|
||||
+109
-16
@@ -1,11 +1,8 @@
|
||||
# docsify
|
||||
|
||||
> 无需构建快速生成文档页
|
||||
|
||||
## 特性
|
||||
- 无需构建,写完 markdown 直接发布
|
||||
- 支持自定义主题
|
||||
- 容易使用并且轻量
|
||||
- 容易使用并且轻量 (~12kb gzipped)
|
||||
|
||||
## 快速上手
|
||||
|
||||
@@ -17,7 +14,7 @@ mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### 创建入口文件
|
||||
创建一个 `404.html` 文件,内容为
|
||||
创建一个 `index.html` 文件,内容为
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -28,7 +25,7 @@ mkdir docs && cd docs
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/docsify" data-router></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -69,7 +66,7 @@ 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">
|
||||
@@ -85,26 +82,67 @@ docsify serve docs
|
||||
## 更多功能
|
||||
|
||||
### 多页面
|
||||
`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
|
||||
|
||||
目前可用的 CDN 有 [UNPKG](unpkg.com/docsify),如果觉得访问较慢可以将文件放到 Pages 的目录下。
|
||||
|
||||
### CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
|
||||
### 封面
|
||||
|
||||
只需要写几行简单的 markdown 就可以拥有一页精致的封面,通过添加 `data-coverpage` 属性,并创建 `_coverpage.md`,按照下面的格式书写即可。
|
||||
|
||||
```markdown
|
||||

|
||||
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
- Simple and lightweight (~12kb gzipped)
|
||||
- Multiple themes
|
||||
- Not build static html files
|
||||
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
```
|
||||
|
||||
|
||||
#### 自定义封面背景
|
||||
默认的背景是随机生成的,你可以自定义背景色或者背景图片。只需要在文档末尾用添加图片的 Markdown 语法
|
||||
|
||||
```markdown
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
> xxx
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
|
||||
<!-- 背景图片 -->
|
||||

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

|
||||
```
|
||||
|
||||
|
||||
### 配置参数
|
||||
|
||||
#### repo
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `index.html` 里的 script 改成
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
|
||||
@@ -157,6 +195,7 @@ Sidebar 开关按钮
|
||||
#### load-sidebar
|
||||
|
||||
读取侧边栏配置文件,如果配置,默认加载当前目录下的 `_sidebar.md`。如果文件不存在,会显示 TOC 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
|
||||
**如果用 `_` 开头作为文件名,你应该在文档目录下添加 `.nojekyll`,阻止 GitHub Pages 忽略下划线开头的文件。**
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar></script>
|
||||
@@ -184,6 +223,18 @@ Sidebar 开关按钮
|
||||
- [HTML5 History Mode](/history-mode)
|
||||
```
|
||||
|
||||
#### sub-max-level
|
||||
|
||||
显示 TOC 在自定义的侧边栏里,默认最大显示 0 层。
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
#### load-navbar
|
||||
|
||||
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
|
||||
@@ -214,10 +265,52 @@ Sidebar 开关按钮
|
||||
```
|
||||
|
||||
|
||||
### router
|
||||
#### router
|
||||
|
||||
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
|
||||
开启 hash router 功能,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-router></script>
|
||||
```
|
||||
|
||||
#### auto2top
|
||||
|
||||
切换路由时自动跳转到页面顶部
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-auto2top></script>
|
||||
```
|
||||
|
||||
#### homepage
|
||||
|
||||
默认情况下网站会将根目录下 `README.md` 作为首页渲染,但是有些时候我们想指定其他文件,甚至想直接将 repo 下的 README 作为首页。你可以这样做(需要设置 `data-router`):
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-homepage="https://raw.githubusercontent.com/QingWei-Li/docsify/master/README.md"></script>
|
||||
<!-- 或者将 Welcome.md 作为首页 -->
|
||||
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
|
||||
```
|
||||
|
||||
#### basePath
|
||||
|
||||
指定加载文档的路径,如果你的 HTML 入口文件和文档是放在不同地方,你可以设置:
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-base-path="/base/"></script>
|
||||
|
||||
<!-- 甚至文档是在其他站点下 😄 -->
|
||||
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
|
||||
```
|
||||
|
||||
#### coverpage
|
||||
|
||||
生成封面,参考 [#封面](/zh-cn#封面).
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-coverpage></script>
|
||||
<!-- or -->
|
||||
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
|
||||
|
||||
```
|
||||
|
||||
+241
-80
@@ -4,11 +4,12 @@ var Docsify = (function () {
|
||||
/**
|
||||
* Simple ajax
|
||||
* @param {String} url
|
||||
* @param {String} [method=get]
|
||||
* @param {String} [method=GET]
|
||||
* @param {Function} [loading] handle loading
|
||||
* @return {Promise}
|
||||
*/
|
||||
function load (url, method) {
|
||||
if ( method === void 0 ) method = 'get';
|
||||
function load (url, method, loading) {
|
||||
if ( method === void 0 ) method = 'GET';
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
@@ -19,13 +20,23 @@ function load (url, method) {
|
||||
then: function (success, error) {
|
||||
if ( error === void 0 ) error = function () {};
|
||||
|
||||
if (loading) {
|
||||
var id = setInterval(function (_) { return loading({ step: Math.floor(Math.random() * 5 + 1) }); },
|
||||
500);
|
||||
xhr.addEventListener('progress', loading);
|
||||
xhr.addEventListener('loadend', function (evt) {
|
||||
loading(evt);
|
||||
clearInterval(id);
|
||||
});
|
||||
}
|
||||
xhr.addEventListener('error', error);
|
||||
xhr.addEventListener('load', function (ref) {
|
||||
var target = ref.target;
|
||||
|
||||
target.status >= 400 ? error(target) : success(target.response);
|
||||
});
|
||||
}
|
||||
},
|
||||
abort: function () { return xhr.readyState !== 4 && xhr.abort(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,12 +110,16 @@ function getRoute () {
|
||||
return route
|
||||
}
|
||||
|
||||
function isMobile () {
|
||||
return document.body.clientWidth <= 600
|
||||
}
|
||||
|
||||
/**
|
||||
* Active sidebar when scroll
|
||||
* @link https://buble.surge.sh/
|
||||
*/
|
||||
function scrollActiveSidebar () {
|
||||
if (/mobile/i.test(navigator.userAgent)) { return }
|
||||
if (isMobile()) { return }
|
||||
|
||||
var anchors = document.querySelectorAll('.anchor');
|
||||
var nav = {};
|
||||
@@ -115,18 +130,21 @@ function scrollActiveSidebar () {
|
||||
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[href] = li;
|
||||
nav[decodeURIComponent(href)] = li;
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
for (var i = 0, len = anchors.length; i < len; i += 1) {
|
||||
var node = anchors[i].parentNode;
|
||||
var node = anchors[i];
|
||||
var bcr = node.getBoundingClientRect();
|
||||
|
||||
if (bcr.top < 10 && bcr.bottom > 10) {
|
||||
var li = nav[node.id];
|
||||
var li = nav[node.getAttribute('data-id')];
|
||||
|
||||
if (!li || li === active) { return }
|
||||
if (active) { active.setAttribute('class', ''); }
|
||||
@@ -139,16 +157,15 @@ function scrollActiveSidebar () {
|
||||
}
|
||||
}
|
||||
|
||||
var dom = document.querySelector('main .content');
|
||||
dom.removeEventListener('scroll', highlight);
|
||||
dom.addEventListener('scroll', highlight);
|
||||
window.removeEventListener('scroll', highlight);
|
||||
window.addEventListener('scroll', highlight);
|
||||
highlight();
|
||||
}
|
||||
|
||||
function scrollIntoView () {
|
||||
var id = window.location.hash.match(/#[^#\/]+$/g);
|
||||
if (!id || !id.length) { return }
|
||||
var section = document.querySelector(id[0]);
|
||||
var section = document.querySelector(decodeURIComponent(id[0]));
|
||||
|
||||
if (section) { section.scrollIntoView(); }
|
||||
}
|
||||
@@ -160,19 +177,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.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active');
|
||||
target = node;
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class');
|
||||
}
|
||||
});
|
||||
|
||||
; }[].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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,6 +212,28 @@ function bindToggle (dom) {
|
||||
});
|
||||
}
|
||||
|
||||
var cacheContentDOM;
|
||||
function scroll2Top () {
|
||||
if (!cacheContentDOM) {
|
||||
var dom = isMobile() ? 'body' : 'section.content';
|
||||
cacheContentDOM = document.querySelector(dom);
|
||||
}
|
||||
cacheContentDOM.scrollTop = 0;
|
||||
}
|
||||
|
||||
function sticky () {
|
||||
var dom = document.querySelector('section.cover');
|
||||
var coverHeight = dom.getBoundingClientRect().height;
|
||||
|
||||
return (function () {
|
||||
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
|
||||
document.body.classList.add('sticky');
|
||||
} else {
|
||||
document.body.classList.remove('sticky');
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||
|
||||
|
||||
@@ -2300,14 +2343,22 @@ function corner (data) {
|
||||
|
||||
/**
|
||||
* Render main content
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
function main () {
|
||||
return "<main>\n <aside class=\"sidebar\"></aside>\n <section class=\"content\">\n <article class=\"markdown-section\"></article>\n </section>\n </main>"
|
||||
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 toggle (bool) {
|
||||
if (!bool) { return '' }
|
||||
/**
|
||||
* Cover Page
|
||||
*/
|
||||
function cover () {
|
||||
var SL = ', 100%, 85%';
|
||||
var bgc = "linear-gradient(to left bottom, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 0%, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 100%)";
|
||||
|
||||
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>"
|
||||
}
|
||||
|
||||
@@ -2349,28 +2400,31 @@ var renderer = new marked.Renderer();
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
var slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
|
||||
var slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
|
||||
var route = '';
|
||||
|
||||
if (OPTIONS$1.router) {
|
||||
route = "#/" + (getRoute());
|
||||
}
|
||||
|
||||
toc.push({ level: level, slug: (route + "#" + slug), title: text });
|
||||
toc.push({ level: level, slug: (route + "#" + (encodeURIComponent(slug))), title: text });
|
||||
|
||||
return ("<h" + level + " id=\"" + slug + "\"><a href=\"" + route + "#" + slug + "\" class=\"anchor\"></a>" + text + "</h" + level + ">")
|
||||
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 = '';
|
||||
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup)
|
||||
.replace(/{{/g, '<span>{{</span>');
|
||||
|
||||
return ("<pre data-lang=\"" + lang + "\"><code class=\"lang-" + lang + "\">" + hl + "</code></pre>")
|
||||
};
|
||||
renderer.link = function (href, title, text) {
|
||||
if (OPTIONS$1.router && !/^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(href)) {
|
||||
href = !/^\/#/.test(href) ? ("#" + href) : href;
|
||||
href = ("#/" + href).replace(/\/\//g, '/');
|
||||
}
|
||||
|
||||
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
|
||||
@@ -2383,11 +2437,21 @@ marked.setOptions({ renderer: renderer });
|
||||
function renderApp (dom, replace) {
|
||||
var nav = document.querySelector('nav') || document.createElement('nav');
|
||||
|
||||
dom[replace ? 'outerHTML' : 'innerHTML'] = toggle(OPTIONS$1.sidebarToggle) + corner(OPTIONS$1.repo) + main();
|
||||
if (!OPTIONS$1.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]);
|
||||
|
||||
// bind toggle
|
||||
bindToggle('button.sidebar-toggle');
|
||||
// bind sticky effect
|
||||
if (OPTIONS$1.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', sticky);
|
||||
} else {
|
||||
document.body.classList.add('sticky');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2395,19 +2459,21 @@ function renderApp (dom, replace) {
|
||||
*/
|
||||
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;
|
||||
if (!OPTIONS$1.sidebar && !OPTIONS$1.loadSidebar) { renderSidebar(); }
|
||||
|
||||
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
|
||||
var vm = new Vue({ el: 'main' }); // eslint-disable-line
|
||||
vm.$nextTick(function (_) { return scrollActiveSidebar(); });
|
||||
}
|
||||
if (OPTIONS$1.auto2top) { scroll2Top(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* navbar
|
||||
*/
|
||||
function renderNavbar (content) {
|
||||
if (CACHE['navbar'] === content) { return }
|
||||
CACHE['navbar'] = content;
|
||||
renderNavbar.rendered = true;
|
||||
if (CACHE.navbar && CACHE.navbar === content) { return }
|
||||
CACHE.navbar = content;
|
||||
|
||||
if (content) { renderTo('nav', marked(content)); }
|
||||
activeLink('nav');
|
||||
@@ -2417,26 +2483,105 @@ function renderNavbar (content) {
|
||||
* sidebar
|
||||
*/
|
||||
function renderSidebar (content) {
|
||||
if (CACHE['sidebar'] === content) { return }
|
||||
CACHE['sidebar'] = content;
|
||||
renderSidebar.rendered = true;
|
||||
|
||||
var isToc = false;
|
||||
var html;
|
||||
|
||||
if (content) {
|
||||
content = marked(content);
|
||||
html = marked(content);
|
||||
} else if (OPTIONS$1.sidebar) {
|
||||
content = tree(OPTIONS$1.sidebar, '<ul>');
|
||||
html = tree(OPTIONS$1.sidebar, '<ul>');
|
||||
} else {
|
||||
content = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
|
||||
isToc = true;
|
||||
html = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
|
||||
}
|
||||
|
||||
renderTo('aside.sidebar', content);
|
||||
if (isToc) { scrollActiveSidebar(); }
|
||||
renderTo('aside.sidebar', html);
|
||||
var target = activeLink('aside.sidebar', true);
|
||||
if (content) { renderSubSidebar(target); }
|
||||
toc = [];
|
||||
|
||||
scrollActiveSidebar();
|
||||
}
|
||||
|
||||
function renderSubSidebar (target) {
|
||||
if (!OPTIONS$1.subMaxLevel) { return }
|
||||
target.parentNode.innerHTML += tree(genTree(toc, OPTIONS$1.subMaxLevel), '<ul>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Cover Page
|
||||
*/
|
||||
function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover');
|
||||
if (!content) {
|
||||
renderCover.dom.classList.remove('show');
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show');
|
||||
if (renderCover.rendered) { return }
|
||||
|
||||
// render cover
|
||||
var html = marked(content);
|
||||
var match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$');
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
var coverEl = document.querySelector('section.cover');
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1];
|
||||
} else {
|
||||
coverEl.classList.add('has-mask');
|
||||
coverEl.style.backgroundImage = "url(" + (match[1]) + ")";
|
||||
}
|
||||
html = html.replace(match[0], '');
|
||||
}
|
||||
|
||||
renderTo('.cover-main', html);
|
||||
renderCover.rendered = true;
|
||||
|
||||
sticky();
|
||||
}
|
||||
|
||||
/**
|
||||
* render loading bar
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
function renderLoading (ref) {
|
||||
var loaded = ref.loaded;
|
||||
var total = ref.total;
|
||||
var step = ref.step;
|
||||
|
||||
var num;
|
||||
|
||||
if (!CACHE.loading) {
|
||||
var div = document.createElement('div');
|
||||
|
||||
div.classList.add('progress');
|
||||
document.body.appendChild(div);
|
||||
CACHE.loading = div;
|
||||
}
|
||||
if (step) {
|
||||
num = parseInt(CACHE.loading.style.width, 10) + step;
|
||||
num = num > 80 ? 80 : num;
|
||||
} else {
|
||||
num = Math.floor(loaded / total * 100);
|
||||
}
|
||||
|
||||
CACHE.loading.style.opacity = 1;
|
||||
CACHE.loading.style.width = num >= 95 ? '100%' : num + '%';
|
||||
|
||||
if (num >= 95) {
|
||||
clearTimeout(renderLoading.cacheTimeout);
|
||||
renderLoading.cacheTimeout = setTimeout(function (_) {
|
||||
CACHE.loading.style.opacity = 0;
|
||||
CACHE.loading.style.width = '0%';
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Config
|
||||
* @param {Object} options
|
||||
*/
|
||||
function config (options) {
|
||||
OPTIONS$1 = options;
|
||||
}
|
||||
@@ -2445,11 +2590,16 @@ var OPTIONS = {
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
subMaxLevel: 0,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
loadSidebar: null,
|
||||
loadNavbar: null,
|
||||
router: false
|
||||
router: false,
|
||||
homepage: 'README.md',
|
||||
coverpage: '',
|
||||
basePath: '',
|
||||
auto2top: false
|
||||
};
|
||||
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
|
||||
|
||||
@@ -2461,6 +2611,7 @@ 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]; }
|
||||
}
|
||||
|
||||
@@ -2468,11 +2619,12 @@ if (script) {
|
||||
config(OPTIONS);
|
||||
|
||||
var cacheRoute = null;
|
||||
var cacheXhr = null;
|
||||
|
||||
var mainRender = function (cb) {
|
||||
var route = getRoute();
|
||||
var route = OPTIONS.basePath + getRoute();
|
||||
if (cacheRoute === route) { return cb() }
|
||||
var wait;
|
||||
|
||||
var basePath = cacheRoute = route;
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -2481,27 +2633,39 @@ var mainRender = function (cb) {
|
||||
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1];
|
||||
}
|
||||
|
||||
// Render markdown file
|
||||
load((!route || /\/$/.test(route)) ? (route + "README.md") : (route + ".md"))
|
||||
.then(function (result) {
|
||||
renderArticle(result);
|
||||
if (OPTIONS.loadSidebar) {
|
||||
if (wait === false) { cb(); }
|
||||
wait = false;
|
||||
} 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;
|
||||
});
|
||||
var page;
|
||||
if (!route) {
|
||||
page = OPTIONS.homepage || 'README.md';
|
||||
} else if (/\/$/.test(route)) {
|
||||
page = route + "README.md";
|
||||
} else {
|
||||
page = route + ".md";
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(renderCover);
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort();
|
||||
// Render markdown file
|
||||
cacheXhr = load(page, 'GET', renderLoading);
|
||||
cacheXhr.then(function (result) {
|
||||
renderArticle(result);
|
||||
// clear cover
|
||||
if (OPTIONS.coverpage && page !== OPTIONS.homepage) { renderCover(); }
|
||||
// render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
load(basePath + OPTIONS.loadSidebar)
|
||||
.then(function (result) {
|
||||
renderSidebar(result);
|
||||
cb();
|
||||
});
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}, function (_) { return renderArticle(null); });
|
||||
|
||||
// Render navbar
|
||||
if (OPTIONS.loadNavbar) {
|
||||
load(basePath + OPTIONS.loadNavbar).then(renderNavbar);
|
||||
@@ -2512,10 +2676,7 @@ var Docsify = function () {
|
||||
var dom = document.querySelector(OPTIONS.el) || document.body;
|
||||
var replace = dom !== document.body;
|
||||
var main = function () {
|
||||
mainRender(function (_) {
|
||||
activeLink('aside.sidebar', true);
|
||||
scrollIntoView();
|
||||
});
|
||||
mainRender(function (_) { return scrollIntoView(); });
|
||||
};
|
||||
|
||||
// Render app
|
||||
|
||||
Vendored
+2
-2
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
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docsify",
|
||||
"version": "1.0.2",
|
||||
"version": "1.4.0",
|
||||
"description": "A magical documentation generator.",
|
||||
"main": "lib/docsify.js",
|
||||
"files": [
|
||||
@@ -10,7 +10,7 @@
|
||||
],
|
||||
"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 --exec 'npm run build'",
|
||||
"dev": "node app.js & nodemon -w src -e js,css --exec 'npm run build'",
|
||||
"test": "eslint src test"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
+51
-20
@@ -1,10 +1,11 @@
|
||||
import { isMobile } from './util'
|
||||
|
||||
/**
|
||||
* Active sidebar when scroll
|
||||
* @link https://buble.surge.sh/
|
||||
*/
|
||||
export function scrollActiveSidebar () {
|
||||
if (/mobile/i.test(navigator.userAgent)) return
|
||||
if (isMobile()) return
|
||||
|
||||
const anchors = document.querySelectorAll('.anchor')
|
||||
const nav = {}
|
||||
@@ -15,18 +16,21 @@ export function scrollActiveSidebar () {
|
||||
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[href] = li
|
||||
nav[decodeURIComponent(href)] = li
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
for (let i = 0, len = anchors.length; i < len; i += 1) {
|
||||
const node = anchors[i].parentNode
|
||||
const node = anchors[i]
|
||||
const bcr = node.getBoundingClientRect()
|
||||
|
||||
if (bcr.top < 10 && bcr.bottom > 10) {
|
||||
const li = nav[node.id]
|
||||
const li = nav[node.getAttribute('data-id')]
|
||||
|
||||
if (!li || li === active) return
|
||||
if (active) active.setAttribute('class', '')
|
||||
@@ -39,16 +43,15 @@ export function scrollActiveSidebar () {
|
||||
}
|
||||
}
|
||||
|
||||
const dom = document.querySelector('main .content')
|
||||
dom.removeEventListener('scroll', highlight)
|
||||
dom.addEventListener('scroll', highlight)
|
||||
window.removeEventListener('scroll', highlight)
|
||||
window.addEventListener('scroll', highlight)
|
||||
highlight()
|
||||
}
|
||||
|
||||
export function scrollIntoView () {
|
||||
const id = window.location.hash.match(/#[^#\/]+$/g)
|
||||
if (!id || !id.length) return
|
||||
const section = document.querySelector(id[0])
|
||||
const section = document.querySelector(decodeURIComponent(id[0]))
|
||||
|
||||
if (section) section.scrollIntoView()
|
||||
}
|
||||
@@ -61,18 +64,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.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active')
|
||||
target = node
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class')
|
||||
}
|
||||
})
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,3 +99,25 @@ export function bindToggle (dom) {
|
||||
body.classList.toggle('close')
|
||||
})
|
||||
}
|
||||
|
||||
let cacheContentDOM
|
||||
export function scroll2Top () {
|
||||
if (!cacheContentDOM) {
|
||||
const dom = isMobile() ? 'body' : 'section.content'
|
||||
cacheContentDOM = document.querySelector(dom)
|
||||
}
|
||||
cacheContentDOM.scrollTop = 0
|
||||
}
|
||||
|
||||
export function sticky () {
|
||||
const dom = document.querySelector('section.cover')
|
||||
const coverHeight = dom.getBoundingClientRect().height
|
||||
|
||||
return (function () {
|
||||
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
|
||||
document.body.classList.add('sticky')
|
||||
} else {
|
||||
document.body.classList.remove('sticky')
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
+43
-27
@@ -1,16 +1,21 @@
|
||||
import { load, camel2kebab, isNil, getRoute } from './util'
|
||||
import { activeLink, scrollIntoView } from './event'
|
||||
import { scrollIntoView } from './event'
|
||||
import * as render from './render'
|
||||
|
||||
const OPTIONS = {
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
subMaxLevel: 0,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
loadSidebar: null,
|
||||
loadNavbar: null,
|
||||
router: false
|
||||
router: false,
|
||||
homepage: 'README.md',
|
||||
coverpage: '',
|
||||
basePath: '',
|
||||
auto2top: false
|
||||
}
|
||||
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
|
||||
|
||||
@@ -22,6 +27,7 @@ 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]
|
||||
}
|
||||
|
||||
@@ -29,11 +35,12 @@ if (script) {
|
||||
render.config(OPTIONS)
|
||||
|
||||
let cacheRoute = null
|
||||
let cacheXhr = null
|
||||
|
||||
const mainRender = function (cb) {
|
||||
const route = getRoute()
|
||||
const route = OPTIONS.basePath + getRoute()
|
||||
if (cacheRoute === route) return cb()
|
||||
let wait
|
||||
|
||||
let basePath = cacheRoute = route
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -42,27 +49,39 @@ const mainRender = function (cb) {
|
||||
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1]
|
||||
}
|
||||
|
||||
// Render markdown file
|
||||
load((!route || /\/$/.test(route)) ? `${route}README.md` : `${route}.md`)
|
||||
.then(result => {
|
||||
render.renderArticle(result)
|
||||
if (OPTIONS.loadSidebar) {
|
||||
if (wait === false) cb()
|
||||
wait = false
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}, _ => render.renderArticle(null))
|
||||
|
||||
// Render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
load(basePath + OPTIONS.loadSidebar).then(result => {
|
||||
render.renderSidebar(result)
|
||||
if (wait === false) cb()
|
||||
wait = false
|
||||
})
|
||||
let page
|
||||
if (!route) {
|
||||
page = OPTIONS.homepage || 'README.md'
|
||||
} else if (/\/$/.test(route)) {
|
||||
page = `${route}README.md`
|
||||
} else {
|
||||
page = `${route}.md`
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(render.renderCover)
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort()
|
||||
// Render markdown file
|
||||
cacheXhr = load(page, 'GET', render.renderLoading)
|
||||
cacheXhr.then(result => {
|
||||
render.renderArticle(result)
|
||||
// clear cover
|
||||
if (OPTIONS.coverpage && page !== OPTIONS.homepage) render.renderCover()
|
||||
// render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
load(basePath + OPTIONS.loadSidebar)
|
||||
.then(result => {
|
||||
render.renderSidebar(result)
|
||||
cb()
|
||||
})
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}, _ => render.renderArticle(null))
|
||||
|
||||
// Render navbar
|
||||
if (OPTIONS.loadNavbar) {
|
||||
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar)
|
||||
@@ -73,10 +92,7 @@ const Docsify = function () {
|
||||
const dom = document.querySelector(OPTIONS.el) || document.body
|
||||
const replace = dom !== document.body
|
||||
const main = function () {
|
||||
mainRender(_ => {
|
||||
activeLink('aside.sidebar', true)
|
||||
scrollIntoView()
|
||||
})
|
||||
mainRender(_ => scrollIntoView())
|
||||
}
|
||||
|
||||
// Render app
|
||||
|
||||
+116
-25
@@ -1,8 +1,8 @@
|
||||
import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import * as tpl from './tpl'
|
||||
import { activeLink, scrollActiveSidebar, bindToggle } from './event'
|
||||
import { genTree, getRoute } from './util'
|
||||
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top, sticky } from './event'
|
||||
import { genTree, getRoute, isMobile } from './util'
|
||||
|
||||
let OPTIONS = {}
|
||||
const CACHE = {}
|
||||
@@ -21,26 +21,29 @@ const renderer = new marked.Renderer()
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
|
||||
const slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
|
||||
let route = ''
|
||||
|
||||
if (OPTIONS.router) {
|
||||
route = `#/${getRoute()}`
|
||||
}
|
||||
|
||||
toc.push({ level, slug: `${route}#${slug}`, title: text })
|
||||
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
|
||||
|
||||
return `<h${level} id="${slug}"><a href="${route}#${slug}" class="anchor"></a>${text}</h${level}>`
|
||||
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)
|
||||
.replace(/{{/g, '<span>{{</span>')
|
||||
|
||||
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
|
||||
href = `#/${href}`.replace(/\/\//g, '/')
|
||||
}
|
||||
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
@@ -53,11 +56,21 @@ marked.setOptions({ renderer })
|
||||
export function renderApp (dom, replace) {
|
||||
const nav = document.querySelector('nav') || document.createElement('nav')
|
||||
|
||||
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.toggle(OPTIONS.sidebarToggle) + tpl.corner(OPTIONS.repo) + tpl.main()
|
||||
if (!OPTIONS.repo) nav.classList.add('no-badge')
|
||||
|
||||
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner(OPTIONS.repo) +
|
||||
(OPTIONS.coverpage ? tpl.cover() : '') +
|
||||
tpl.main(OPTIONS.sidebarToggle ? tpl.toggle() : '')
|
||||
document.body.insertBefore(nav, document.body.children[0])
|
||||
|
||||
// bind toggle
|
||||
bindToggle('button.sidebar-toggle')
|
||||
// bind sticky effect
|
||||
if (OPTIONS.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', sticky)
|
||||
} else {
|
||||
document.body.classList.add('sticky')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,19 +78,21 @@ export function renderApp (dom, replace) {
|
||||
*/
|
||||
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
|
||||
if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
|
||||
|
||||
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
|
||||
const vm = new Vue({ el: 'main' }) // eslint-disable-line
|
||||
vm.$nextTick(_ => scrollActiveSidebar())
|
||||
}
|
||||
if (OPTIONS.auto2top) scroll2Top()
|
||||
}
|
||||
|
||||
/**
|
||||
* navbar
|
||||
*/
|
||||
export function renderNavbar (content) {
|
||||
if (CACHE['navbar'] === content) return
|
||||
CACHE['navbar'] = content
|
||||
renderNavbar.rendered = true
|
||||
if (CACHE.navbar && CACHE.navbar === content) return
|
||||
CACHE.navbar = content
|
||||
|
||||
if (content) renderTo('nav', marked(content))
|
||||
activeLink('nav')
|
||||
@@ -87,26 +102,102 @@ export function renderNavbar (content) {
|
||||
* sidebar
|
||||
*/
|
||||
export function renderSidebar (content) {
|
||||
if (CACHE['sidebar'] === content) return
|
||||
CACHE['sidebar'] = content
|
||||
renderSidebar.rendered = true
|
||||
|
||||
let isToc = false
|
||||
let html
|
||||
|
||||
if (content) {
|
||||
content = marked(content)
|
||||
html = marked(content)
|
||||
} else if (OPTIONS.sidebar) {
|
||||
content = tpl.tree(OPTIONS.sidebar, '<ul>')
|
||||
html = tpl.tree(OPTIONS.sidebar, '<ul>')
|
||||
} else {
|
||||
content = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
||||
isToc = true
|
||||
html = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
||||
}
|
||||
|
||||
renderTo('aside.sidebar', content)
|
||||
if (isToc) scrollActiveSidebar()
|
||||
renderTo('aside.sidebar', html)
|
||||
const target = activeLink('aside.sidebar', true)
|
||||
if (content) renderSubSidebar(target)
|
||||
toc = []
|
||||
|
||||
scrollActiveSidebar()
|
||||
}
|
||||
|
||||
export function renderSubSidebar (target) {
|
||||
if (!OPTIONS.subMaxLevel) return
|
||||
target.parentNode.innerHTML += tpl.tree(genTree(toc, OPTIONS.subMaxLevel), '<ul>')
|
||||
}
|
||||
|
||||
/**
|
||||
* Cover Page
|
||||
*/
|
||||
export function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover')
|
||||
if (!content) {
|
||||
renderCover.dom.classList.remove('show')
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show')
|
||||
if (renderCover.rendered) return
|
||||
|
||||
// render cover
|
||||
let html = marked(content)
|
||||
const match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$')
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
const coverEl = document.querySelector('section.cover')
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1]
|
||||
} else {
|
||||
coverEl.classList.add('has-mask')
|
||||
coverEl.style.backgroundImage = `url(${match[1]})`
|
||||
}
|
||||
html = html.replace(match[0], '')
|
||||
}
|
||||
|
||||
renderTo('.cover-main', html)
|
||||
renderCover.rendered = true
|
||||
|
||||
sticky()
|
||||
}
|
||||
|
||||
/**
|
||||
* render loading bar
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
export function renderLoading ({ loaded, total, step }) {
|
||||
let num
|
||||
|
||||
if (!CACHE.loading) {
|
||||
const div = document.createElement('div')
|
||||
|
||||
div.classList.add('progress')
|
||||
document.body.appendChild(div)
|
||||
CACHE.loading = div
|
||||
}
|
||||
if (step) {
|
||||
num = parseInt(CACHE.loading.style.width, 10) + step
|
||||
num = num > 80 ? 80 : num
|
||||
} else {
|
||||
num = Math.floor(loaded / total * 100)
|
||||
}
|
||||
|
||||
CACHE.loading.style.opacity = 1
|
||||
CACHE.loading.style.width = num >= 95 ? '100%' : num + '%'
|
||||
|
||||
if (num >= 95) {
|
||||
clearTimeout(renderLoading.cacheTimeout)
|
||||
renderLoading.cacheTimeout = setTimeout(_ => {
|
||||
CACHE.loading.style.opacity = 0
|
||||
CACHE.loading.style.width = '0%'
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Config
|
||||
* @param {Object} options
|
||||
*/
|
||||
export function config (options) {
|
||||
OPTIONS = options
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
section.cover {
|
||||
align-items: center;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
display: none;
|
||||
|
||||
&.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.has-mask .mask {
|
||||
position: absolute;
|
||||
size: 100%;
|
||||
background-color: $color-bg;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.cover-main {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
margin: 0 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 2.5rem;
|
||||
position: relative;
|
||||
margin: .625rem 0 2.5rem;
|
||||
font-weight: 300;
|
||||
color: inherit;
|
||||
|
||||
small {
|
||||
position: absolute;
|
||||
bottom: -.4375rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
max-width: 500px;
|
||||
list-style-type: none;
|
||||
margin: 1em auto;
|
||||
padding: 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.cover-main p:last-child a {
|
||||
border-radius: 2em;
|
||||
border: 1px solid $color-primary;
|
||||
box-sizing: border-box;
|
||||
color: $color-primary;
|
||||
font-size: 1.05em;
|
||||
letter-spacing: 0.1em;
|
||||
padding: 0.75em 2em;
|
||||
text-decoration: none;
|
||||
transition: all 0.15s ease;
|
||||
margin-right: 1em;
|
||||
display: inline-block;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
background-color: $color-primary;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
@@ -8,6 +7,18 @@
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-color: $color-primary;
|
||||
height: 2px;
|
||||
left: 0px;
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
transition: width 0.2s, opacity 0.4s;
|
||||
width: 0%;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
@@ -26,6 +37,17 @@ img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
margin-bottom : 3px;
|
||||
font-size: 12px !important;
|
||||
line-height: 12px;
|
||||
vertical-align: middle;
|
||||
border: solid 1px #ccc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* navbar */
|
||||
nav {
|
||||
position: absolute;
|
||||
@@ -35,6 +57,10 @@ nav {
|
||||
margin: 25px 60px 0 0;
|
||||
text-align: right;
|
||||
|
||||
&.no-badge {
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -69,7 +95,7 @@ nav {
|
||||
display: inline-block;
|
||||
|
||||
ul {
|
||||
background-color: rgba(#fff, .6);
|
||||
background-color: rgba($color-bg, .6);
|
||||
border: 1px solid $color-primary;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
@@ -112,24 +138,19 @@ nav {
|
||||
|
||||
/* github corner */
|
||||
.github-corner {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
text-decoration: none;
|
||||
border-bottom: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
&:hover .octo-arm {
|
||||
animation:octocat-wave 560ms ease-in-out;
|
||||
}
|
||||
|
||||
svg {
|
||||
color: #fff;
|
||||
color: $color-bg;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
fill: $color-primary;
|
||||
@@ -142,6 +163,16 @@ main {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.anchor {
|
||||
text-decoration: none;
|
||||
transition: all .3s;
|
||||
display: block;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
border-right: 1px solid rgba(0, 0, 0, .07);
|
||||
@@ -197,11 +228,15 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
body.sticky {
|
||||
.sidebar, .sidebar-toggle {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
/* main content */
|
||||
.content {
|
||||
overflow-y: auto;
|
||||
position: absolute 0 0 0 $sidebar-width;
|
||||
overflow-x: hidden;
|
||||
padding-top: 20px;
|
||||
transition: left 250ms ease;
|
||||
}
|
||||
@@ -223,6 +258,33 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.markdown-section th {
|
||||
font-weight: bold;
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.markdown-section td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.markdown-section tr {
|
||||
border-top: 1px solid #ccc;
|
||||
&:nth-child(2n) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
body.close {
|
||||
.sidebar {
|
||||
transform: translateX(-$sidebar-width);
|
||||
@@ -234,7 +296,7 @@ body.close {
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
nav, .github-corner, .sidebar-toggle, .sidebar {
|
||||
.github-corner, .sidebar-toggle, .sidebar {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
@@ -255,8 +317,6 @@ body.close {
|
||||
left: 0;
|
||||
min-width: 100vw;
|
||||
transition: transform 250ms ease;
|
||||
position: static;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
nav, .github-corner {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
|
||||
|
||||
$color-primary: #0074D9;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 16em;
|
||||
|
||||
@import "basic/layout";
|
||||
@import "basic/coverpage";
|
||||
|
||||
body {
|
||||
color: #34495e;
|
||||
@@ -11,6 +13,7 @@ body {
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: $color-bg;
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
@@ -54,6 +57,8 @@ body {
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
word-spacing: 0.05em;
|
||||
line-height: 1.6em;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
.markdown-section h1 {
|
||||
@@ -95,13 +100,6 @@ body {
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
|
||||
.markdown-section p,
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
margin: 0 0 1em 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
padding-left: 1.5em;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
$color-primary: #000;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 300px;
|
||||
@import "basic/layout";
|
||||
|
||||
+6
-8
@@ -1,18 +1,21 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
|
||||
|
||||
$color-primary: #42b983;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 300px;
|
||||
|
||||
@import "basic/layout";
|
||||
@import "basic/coverpage";
|
||||
|
||||
body {
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: $color-bg;
|
||||
|
||||
li {
|
||||
margin: 6px 15px;
|
||||
@@ -55,12 +58,6 @@ body {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-section p,
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
word-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.markdown-section h1 {
|
||||
margin: 0 0 1em;
|
||||
font-size: 2em;
|
||||
@@ -100,6 +97,7 @@ body {
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
line-height: 1.6em;
|
||||
word-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.markdown-section ul,
|
||||
@@ -277,7 +275,7 @@ code .token {
|
||||
pre::after {
|
||||
color: #ccc;
|
||||
content: attr(data-lang);
|
||||
font-size: 0.75em;
|
||||
font-size: 0.6em;
|
||||
font-weight: 600;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
|
||||
+17
-4
@@ -21,10 +21,10 @@ export function corner (data) {
|
||||
|
||||
/**
|
||||
* Render main content
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
export function main () {
|
||||
export function main (tpl) {
|
||||
return `<main>
|
||||
${tpl}
|
||||
<aside class="sidebar"></aside>
|
||||
<section class="content">
|
||||
<article class="markdown-section"></article>
|
||||
@@ -32,8 +32,20 @@ export function main () {
|
||||
</main>`
|
||||
}
|
||||
|
||||
export function toggle (bool) {
|
||||
if (!bool) return ''
|
||||
/**
|
||||
* Cover Page
|
||||
*/
|
||||
export function cover () {
|
||||
const SL = ', 100%, 85%'
|
||||
const bgc = `linear-gradient(to left bottom, hsl(${Math.floor(Math.random() * 255) + SL}) 0%, hsl(${Math.floor(Math.random() * 255) + SL}) 100%)`
|
||||
|
||||
return `<section class="cover" style="background: ${bgc}">
|
||||
<div class="cover-main"></div>
|
||||
<div class="mask"></div>
|
||||
</section>`
|
||||
}
|
||||
|
||||
export function toggle () {
|
||||
return `<button class="sidebar-toggle">
|
||||
<span></span><span></span><span></span>
|
||||
</button>`
|
||||
@@ -57,3 +69,4 @@ export function tree (toc, tpl = '') {
|
||||
|
||||
return tpl
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -1,10 +1,11 @@
|
||||
/**
|
||||
* Simple ajax
|
||||
* @param {String} url
|
||||
* @param {String} [method=get]
|
||||
* @param {String} [method=GET]
|
||||
* @param {Function} [loading] handle loading
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function load (url, method = 'get') {
|
||||
export function load (url, method = 'GET', loading) {
|
||||
const xhr = new XMLHttpRequest()
|
||||
|
||||
xhr.open(method, url)
|
||||
@@ -12,11 +13,22 @@ export function load (url, method = 'get') {
|
||||
|
||||
return {
|
||||
then: function (success, error = function () {}) {
|
||||
if (loading) {
|
||||
const id = setInterval(_ =>
|
||||
loading({ step: Math.floor(Math.random() * 5 + 1) }),
|
||||
500)
|
||||
xhr.addEventListener('progress', loading)
|
||||
xhr.addEventListener('loadend', evt => {
|
||||
loading(evt)
|
||||
clearInterval(id)
|
||||
})
|
||||
}
|
||||
xhr.addEventListener('error', error)
|
||||
xhr.addEventListener('load', ({ target }) => {
|
||||
target.status >= 400 ? error(target) : success(target.response)
|
||||
})
|
||||
}
|
||||
},
|
||||
abort: () => xhr.readyState !== 4 && xhr.abort()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,3 +101,7 @@ export function getRoute () {
|
||||
|
||||
return route
|
||||
}
|
||||
|
||||
export function isMobile () {
|
||||
return document.body.clientWidth <= 600
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user