Compare commits

...
159 Commits
Author SHA1 Message Date
qingwei.li 4a77b8a7f3 -> v1.10.2 2017-01-25 21:39:42 +08:00
qingwei.li 00b13c5e86 bump 1.10.2 2017-01-25 21:39:32 +08:00
qingwei.li 82b7b8226d Fix render emojis again 2017-01-25 21:39:12 +08:00
qingwei.li c9739e71af -> v1.10.1 2017-01-25 21:17:54 +08:00
qingwei.li bda1b76ba5 bump 1.10.1 2017-01-25 21:17:43 +08:00
qingwei.li 11f77cd434 Fix render emojis 2017-01-25 21:16:53 +08:00
qingwei.li 6d42c6b04a -> v1.10.0 2017-01-25 15:08:40 +08:00
qingwei.li 46967e73bf bump 1.10.0 2017-01-25 15:08:28 +08:00
qingwei.li ccdc3c855a Support emoji, closed #61 2017-01-25 15:07:36 +08:00
qingwei.li 7c4b0b7c74 -> v1.9.0 2017-01-24 22:31:44 +08:00
qingwei.li 98d1b19bea bump 1.9.0 2017-01-24 22:31:27 +08:00
cinwell.liandGitHub 0709239c77 1.9 (#62)
* Destroys the vue instance when the route is changed

* Add new doc helper

* Update docs
2017-01-24 22:29:50 +08:00
qingwei.li 73cc43c6bd -> v1.8.0 2017-01-24 11:28:15 +08:00
qingwei.li 9d096b03a4 bump 1.8.0 2017-01-24 11:28:04 +08:00
qingwei.li 2af035ff45 Fix fallback sidebar 2017-01-24 10:18:58 +08:00
qingwei.li 3979f5cd3f Update change log 2017-01-24 10:07:14 +08:00
qingwei.li 9abae495ac Execute script when vue exists. 2017-01-24 10:06:38 +08:00
qingwei.li d179ade7df Using v-pre 2017-01-18 16:35:19 +08:00
qingwei.li d79c7655cd Update license 2017-01-18 16:34:05 +08:00
citycideandcinwell.li af5d2934e4 add Trilogy to showcase list (#58) 2017-01-17 08:05:12 +08:00
Antony Jonesandcinwell.li 129bd4d3a0 Add vudash to list of projects using docsify (#57) 2017-01-15 18:45:32 +08:00
qingwei.li abaf5c0849 -> v1.7.4 2017-01-13 23:33:20 +08:00
qingwei.li 336efb30cb bump 1.7.4 2017-01-13 23:33:04 +08:00
qingwei.li fb8bf89d73 Fix bugs caused by the previous version, fixed #56 2017-01-13 23:32:38 +08:00
qingwei.li 8630591bd2 -> v1.7.3 2017-01-13 23:06:31 +08:00
qingwei.li c47ff83073 bump 1.7.3 2017-01-13 23:06:18 +08:00
cinwell.liandGitHub 69e500bd33 Fix repo (#55)
* Fix option is an empty string

* Fix test

* Add hr style #54

* Tweak hr style
2017-01-13 23:05:05 +08:00
qingwei.li 000a1fcdf0 -> v1.7.2 2017-01-12 21:31:40 +08:00
qingwei.li b84544960f bump 1.7.2 2017-01-12 21:31:22 +08:00
qingwei.li 28a004840d Fix sidebar click event in mobile browser 2017-01-12 21:30:33 +08:00
qingwei.li ff44152d12 -> v1.7.1 2017-01-12 20:46:24 +08:00
qingwei.li b6bfad8579 bump 1.7.1 2017-01-12 20:46:04 +08:00
qingwei.li e93f6b95ea Fix sidebar style in mobile browser 2017-01-12 20:45:35 +08:00
qingwei.li 5c58629e69 Fix index.html 2017-01-12 20:34:47 +08:00
qingwei.li 55826691eb -> v1.7.0 2017-01-12 20:30:13 +08:00
qingwei.li 64093c0567 bump 1.7.0 2017-01-12 20:29:45 +08:00
qingwei.li c998fad98e Add docs 2017-01-12 20:28:59 +08:00
qingwei.li 0a2e1ddf11 Tweak active item in sidebar 2017-01-12 20:23:55 +08:00
qingwei.li 4a7df99224 Add name link 2017-01-12 20:16:18 +08:00
qingwei.li 6c6f687925 Merge branch 'feat/data-name' 2017-01-12 19:48:21 +08:00
qingwei.li ddc13aa280 Add changelog 2017-01-12 19:46:59 +08:00
qingwei.li f997280ab1 Fix sticky sidebar 2017-01-12 19:46:28 +08:00
qingwei.li 458e262a26 Tweak style 2017-01-12 18:44:41 +08:00
qingwei.li d971948f10 Add yarn.lock 2017-01-12 18:44:41 +08:00
qingwei.li a309d3041e Update docs 2017-01-12 18:44:41 +08:00
qingwei.li 557a165349 fixed custom cover background, fixed #52 2017-01-12 18:44:41 +08:00
Chao Leeandcinwell.li d9eedf609e add showcase at README.md (#53) 2017-01-12 11:32:45 +08:00
qingwei.li aa939147c6 Add name option 2017-01-11 18:11:49 +08:00
qingwei.li 67c1d0cd7d Add yarn.lock 2017-01-11 16:53:08 +08:00
qingwei.li 06892e6de4 Update docs 2017-01-11 16:22:17 +08:00
qingwei.li 439a1e6841 fixed custom cover background, fixed #52 2017-01-11 16:18:43 +08:00
qingwei.li f540e3c4fc Add bash/markdown highlight 2017-01-10 23:55:58 +08:00
qingwei.li 2ffef062db Update version number 2017-01-10 23:52:32 +08:00
qingwei.li db7db5af8b -> v1.6.1 2017-01-10 23:49:06 +08:00
qingwei.li a418096a29 bump 1.6.1 2017-01-10 23:48:49 +08:00
qingwei.li 90b490c9c1 Fixed sidebar bug when the coverpage exist 2017-01-10 23:48:12 +08:00
qingwei.li 7915027418 -> v1.6.0 2017-01-10 23:34:20 +08:00
qingwei.li 87b373b841 bump 1.6.0 2017-01-10 23:33:41 +08:00
qingwei.li 510ae37a04 Add doc 2017-01-10 23:32:25 +08:00
qingwei.li ef53a07f49 Add new markdown grammar & improve sidebar performance. 2017-01-10 23:16:55 +08:00
qingwei.li 9defe1bf7d -> v1.5.2 2017-01-10 14:40:36 +08:00
qingwei.li b87f6ae5e8 bump 1.5.2 2017-01-10 14:40:21 +08:00
qingwei.li b8b9dbc872 Fixed number at the beginning of the slug, fixed #51 2017-01-10 14:39:40 +08:00
qingwei.li f7779b01d9 -> v1.5.1 2017-01-09 17:50:54 +08:00
qingwei.li 1c935b2fd7 bump 1.5.1 2017-01-09 17:50:43 +08:00
cinwell.liandGitHub 114955558e Remove HTML tag when handling slug, fixed #49 (#50)
* Remove HTML tag when handling slug, fixed #49

* Fix slugify
2017-01-09 17:47:38 +08:00
qingwei.li 847cf3b656 Update readme 2017-01-05 10:33:48 +08:00
Sina Nedadahandehandcinwell.li 356b937d44 Clean up readme (#48)
* Readme/homepage cleanup

* Readme cleanup
2017-01-05 10:31:41 +08:00
qingwei.li 8df57f0bc2 -> v1.5.0 2017-01-04 21:49:51 +08:00
qingwei.li 73dfbf5be3 Update package size 2017-01-04 21:49:16 +08:00
qingwei.li ecba3f1b05 bump 1.5.0 2017-01-04 21:42:40 +08:00
qingwei.li e5452243b1 Update docs 2017-01-04 21:41:35 +08:00
qingwei.li 8b1000a4a5 feat: Markdown parser is configurable, #42 2017-01-04 21:41:08 +08:00
qingwei.li 897283418a init config by window. 2017-01-04 20:47:55 +08:00
qingwei.li 7be6baae7a Fix nav highlight 2017-01-04 20:04:15 +08:00
qingwei.li 24ab3d4d10 Update change log 2017-01-03 15:50:31 +08:00
qingwei.li 424a243c5c Fix slugify 2017-01-03 15:48:57 +08:00
rozboandcinwell.li 9ce47c48af add showcase and edit Development Tips (#47) 2017-01-02 07:31:03 +08:00
qingwei.li 4e7485aa1f Update version 2017-01-01 12:02:06 +08:00
qingwei.li cb592e7bf0 -> v1.4.3 2017-01-01 12:01:36 +08:00
qingwei.li 3c01d1f82d bump 1.4.3 2017-01-01 12:01:23 +08:00
qingwei.li 00253d3148 Tweak style 2017-01-01 12:01:01 +08:00
qingwei.li d23881ba7c Update version 2016-12-31 22:23:47 +08:00
qingwei.li f0a99c0d1d Update change log 2016-12-31 22:06:43 +08:00
qingwei.li b952a3a08c -> v1.4.2 2016-12-31 22:05:10 +08:00
qingwei.li 2bb8641303 bump 1.4.3 2016-12-31 22:04:54 +08:00
qingwei.li 66d7919fa9 Fix href type, fixed #46 2016-12-31 22:04:14 +08:00
qingwei.li 580767bf78 Clear dev.html 2016-12-31 15:12:28 +08:00
qingwei.li d6b996f4c1 Add changelog 2016-12-31 15:07:02 +08:00
qingwei.li b4e0d54d7b Fix menu toggle style 2016-12-31 14:53:27 +08:00
qingwei.li b15b286c5c -> v1.4.1 2016-12-31 14:16:54 +08:00
qingwei.li 5ab86271c2 bump 1.4.1 2016-12-31 14:16:39 +08:00
qingwei.li 9638eee50d fix generate slug, fixed #45 2016-12-31 14:16:15 +08:00
qingwei.li 375a1dd3e1 -> v1.4.0 2016-12-31 13:47:28 +08:00
qingwei.li 3069ad3928 bump 1.4.0 2016-12-31 13:47:16 +08:00
qingwei.li b287f57c86 Add custom cover background 2016-12-31 13:40:29 +08:00
qingwei.li e932ff66b9 max-sub-level => sub-max-level 2016-12-31 11:50:30 +08:00
nsinaandcinwell.li 7a10e4aecf Readme/homepage cleanup 2016-12-31 10:22:31 +08:00
qingwei.li 41e7ef6863 Add docs 2016-12-30 18:09:13 +08:00
qingwei.li 7ce166501b Add render sub menu 2016-12-30 17:58:39 +08:00
qingwei.li b9aeb4a922 Fix scroll highlight when Vue exist 2016-12-27 23:58:26 +08:00
qingwei.li 9ac8293c0a Update docs 2016-12-26 23:47:26 +08:00
qingwei.li aa3121eca2 Bye 🎅 2016-12-25 20:59:08 +08:00
qingwei.li 0e615abbdc -> v1.3.5 2016-12-25 20:13:21 +08:00
qingwei.li cb2b191ba1 bump 1.3.5 2016-12-25 20:13:11 +08:00
qingwei.li 6adcfffba9 fix vue 2016-12-25 20:12:03 +08:00
qingwei.li f165470265 -> v1.3.4 2016-12-25 18:34:14 +08:00
qingwei.li bbb7b4a9d6 bump 1.3.4 2016-12-25 18:33:57 +08:00
qingwei.li 540095ee35 Support vuep 2016-12-25 18:33:12 +08:00
qingwei.li bd354094c0 🎄 Merry Christmas 2016-12-24 20:32:04 +08:00
qingwei.li 6e81e66441 404.dev => dev 2016-12-24 19:50:41 +08:00
qingwei.li 67f9083ff7 Remove 404.html 2016-12-24 19:50:04 +08:00
qingwei.li 383b976ddd Update docs 2016-12-24 11:33:48 +08:00
qingwei.li 54ba970552 -> v1.3.3 2016-12-23 21:47:42 +08:00
qingwei.li 16623c9301 bump 1.3.3 2016-12-23 21:47:31 +08:00
qingwei.li 668c5ca714 fix lint 2016-12-23 21:47:15 +08:00
qingwei.li d0861d7427 Fixed cover rendering timing 2016-12-23 21:46:12 +08:00
qingwei.li 97669e0d28 Add similar projects into readme 2016-12-23 09:25:30 +08:00
qingwei.li a0408b7a38 -> v1.3.2 2016-12-23 01:20:57 +08:00
qingwei.li f917da8214 bump 1.3.2 2016-12-23 01:20:47 +08:00
qingwei.li 64309beee9 Fixed render link 2016-12-23 01:20:28 +08:00
qingwei.li 4c8c0349e6 -> v1.3.1 2016-12-23 00:25:05 +08:00
qingwei.li 91b6720219 bump 1.3.1 2016-12-23 00:24:45 +08:00
qingwei.li c93ba1ea16 Fixed cover page style 2016-12-23 00:24:24 +08:00
qingwei.li 4f5a150c17 update cdn 2016-12-22 01:03:52 +08:00
qingwei.li 801df6ae3e Update changelog
Update changelog
2016-12-22 00:30:30 +08:00
qingwei.li 6c2e7dca99 -> v1.3.0 2016-12-22 00:26:23 +08:00
qingwei.li a39eddba74 bump 1.3.0 2016-12-22 00:26:06 +08:00
cinwell.liandGitHub 50addfdac6 1.3 (#38)
* Add cover page

* Update doc

* Add kbd style, resolve #37

* headling can cliked, resolve #36

* Update change log, close #35

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

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

* Add logo

* Update index.html

* Update doc
2016-12-18 15:30:50 +08:00
qingwei.li ab34cc97f9 -> v1.1.5 2016-12-18 10:50:37 +08:00
qingwei.li 3fbcd876ae bump 1.1.5 2016-12-18 10:50:02 +08:00
qingwei.li 3af5ca5cd4 Correct calculation of whether the mobile browser 2016-12-18 10:49:21 +08:00
qingwei.li 74ee0cf6bc Add table style 2016-12-18 10:37:34 +08:00
qingwei.li 46dd542b48 -> v1.1.4 2016-12-17 16:08:45 +08:00
qingwei.li cc7bdf5df2 bump 1.1.4 2016-12-17 15:56:55 +08:00
qingwei.li 9a1db6ed43 Fix chinese auchor link 2016-12-17 15:56:01 +08:00
qingwei.li 9d30ac7435 -> v1.1.3 2016-12-17 15:38:59 +08:00
qingwei.li f8a68b87c7 bump 1.1.3 2016-12-17 15:38:00 +08:00
qingwei.li 7dc47cc4d4 Optimize progress bar again 2016-12-17 15:37:32 +08:00
qingwei.li 7d995d8362 Update readme 2016-12-17 15:25:03 +08:00
31 changed files with 5444 additions and 537 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
.DS_Store
*.log
node_modules
yarn.lock
/themes
+177
View File
@@ -1,3 +1,180 @@
## 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
### 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
View File
@@ -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
+56 -32
View File
@@ -1,36 +1,31 @@
# docsify
[![Build Status](https://travis-ci.org/QingWei-Li/docsify.svg?branch=master)](https://travis-ci.org/QingWei-Li/docsify)
[![npm](https://img.shields.io/npm/v/docsify.svg)](https://www.npmjs.com/package/docsify)
<p align="center">
<a href="https://docsify.js.org">
<img alt="docsify" src="./media/docsify.png">
</a>
</p>
>🃏 A magical documentation site generator.
<p align="center">
A magical documentation site generator.
</p>
<p align="center">
<a href="https://travis-ci.org/QingWei-Li/docsify"><img alt="Travis Status" src="https://img.shields.io/travis/rust-lang/rust/master.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/docsify"><img alt="npm" src="https://img.shields.io/npm/v/docsify.svg?style=flat-square"></a>
<a href="https://github.com/vuejs/vue"><img alt="code style" src="https://img.shields.io/badge/code%20style-vue-orange.svg?style=flat-square"></a>
</p>
## Links
- [Documentation](https://docsify.js.org)
- [CLI](https://github.com/QingWei-Li/docsify-cli)
## Features
- Easy and lightweight
- Custom themes
- No build
- Simple and lightweight (~13kB gzipped)
- Multiple themes
- Not build static html files
- Support emoji :laughing:
## 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,27 +36,56 @@ 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.
- [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.
## 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
### prepare
```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
## Support on Beerpay
Hey dude! Help me out for a couple of :beers:!
[![Beerpay](https://beerpay.io/QingWei-Li/docsify/badge.svg?style=beer-square)](https://beerpay.io/QingWei-Li/docsify) [![Beerpay](https://beerpay.io/QingWei-Li/docsify/make-wish.svg?style=flat-square)](https://beerpay.io/QingWei-Li/docsify?focus=wish)
+1 -1
View File
@@ -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')
+1 -1
View File
@@ -8,5 +8,5 @@
<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>
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-name="docsify" data-auto2top data-sidebar-toggle data-router></script>
</html>
View File
+318 -44
View File
@@ -1,23 +1,14 @@
# docsify
> A magical documentation site generator.
## Features
- Easy and lightweight
- Custom themes
- No build
## Quick Start
### 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>
@@ -29,47 +20,51 @@ 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>
```
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
![image](https://cloud.githubusercontent.com/assets/7565692/20639058/e65e6d22-b3f3-11e6-9b8b-6309c89826f2.png)
## 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">
@@ -83,45 +78,189 @@ 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>
```
### Options
### CDN
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
#### repo
### Cover Page
Generate a cover page with markdown. Create a `_coverpage.md` and set `data-coverpage` in the script tag.
```markdown
![logo](_media/icon.svg)
# docsify <small>1.2.0</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
```
#### Custom background
Currently the background of the cover page is generated randomly. We can customize the background color, or add a background image.
```markdown
# docsify <small>1.2.0</small>
> xxx
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
<!-- background image -->
![](_media/bg.png)
<!-- background color -->
![color](#f0f0f0)
```
### 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" data-router></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
```js
window.$docsify = {
el: '#app'
}
```
### sidebar-toggle
Sidebar with toggle
@@ -129,9 +268,15 @@ Sidebar with toggle
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
```js
window.$docsify = {
sidebarToggle: true
}
```
Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on the `data-sidebar`.
### sidebar
Custom sidebar. If it's set, the TOC will be disabled. Bind global variables on the `data-sidebar`.
![image](https://cloud.githubusercontent.com/assets/7565692/20647425/de5ab1c2-b4ce-11e6-863a-135868f2f9b4.png)
@@ -153,9 +298,16 @@ Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on th
```
#### load-sidebar
```js
window.$docsify = {
sidebar: '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
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>
@@ -167,6 +319,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
@@ -176,16 +334,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>
@@ -197,6 +366,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
@@ -215,12 +390,19 @@ If you write a sub level list, it will generate a dropdown list.
### router
Hash router. You can replace `404.html` with `index.html`.
Hash router.
```html
<script src="/lib/docsify.js" data-router></script>
```
```js
window.$docsify = {
router: true
}
```
### auto2top
Scroll to the top on changing hash.
@@ -228,5 +410,97 @@ 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>
```
```js
window.$docsify = {
auto2top: true,
// auto2top: 50
}
```
### 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>
```
```js
window.$docsify = {
homepage: true
}
```
### 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>
```
```js
window.$docsify = {
basePath: '/base/'
}
```
### coverpage
Generate cover page.
```html
<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'
}
```
### nameLink
Name link. The default value is `window.location.pathname`.
```html
<script src="/lib/docsify.js" data-name-link="/"></script>
```
```js
window.$docsify = {
nameLink: '/'
}
```
+14
View File
@@ -0,0 +1,14 @@
![logo](_media/icon.svg)
# docsify <small>1.10.2</small>
> A magical documentation site generator.
- Simple and lightweight (~13kB gzipped)
- Not build static html files
- Support emoji :laughing:
- Multiple themes
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="122px" height="94px" viewBox="0 0 122 94" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>icon</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M144.453286,104 C177.038086,104 203.453286,77.5848002 203.453286,45 C203.453286,12.4151998 177.038086,-14 144.453286,-14 C111.868486,-14 114.603207,13.6754846 114.603207,46.2602848 C114.603207,78.845085 111.868486,104 144.453286,104 Z" id="path-1"></path>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="7" dy="-10" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
<feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
</filter>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-98.000000, 2.000000)">
<g id="body" transform="translate(159.000000, 45.000000) rotate(-90.000000) translate(-159.000000, -45.000000) ">
<use fill="#2ECE53" fill-rule="evenodd" xlink:href="#path-1"></use>
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use stroke="#0E1320" stroke-width="4" xlink:href="#path-1"></use>
</g>
<circle id="left-eye" fill="#000000" cx="139" cy="38" r="7"></circle>
<circle id="right-eye" fill="#000000" cx="183" cy="38" r="7"></circle>
<g id="light" transform="translate(112.000000, 10.000000)" fill="#FFFFFF">
<circle cx="2" cy="28" r="2"></circle>
<path d="M12.2551528,-1.65016666 C12.1154537,-2.17684986 12.4455583,-2.60381096 13.011574,-2.60381096 L14.9928363,-2.60381096 C15.5502953,-2.60381096 16.1214654,-2.16566487 16.2594657,-1.64268776 C16.2594657,-1.64268776 17.4280152,2.48668594 17.9030739,6.45786647 C18.3781327,10.429047 18.3171359,10.4652901 18.3171359,12.1782569 C18.3171359,16.9413523 16.2076398,26.4389164 16.2076398,26.4389164 C16.0941814,26.9676035 15.558852,27.396189 14.9928363,27.396189 L13.011574,27.396189 C12.454115,27.396189 12.1166642,26.9691757 12.2568366,26.4301177 C12.2568366,26.4301177 13.4260575,22.2288768 13.9640759,17.9859148 C14.5020943,13.7429529 14.309594,15.2982629 14.5626609,12.3723978 C14.9355337,8.06138047 12.2551528,-1.65016666 12.2551528,-1.65016666 Z" id="light-line" transform="translate(15.271433, 12.396189) scale(-1, 1) rotate(-48.000000) translate(-15.271433, -12.396189) "></path>
</g>
<path d="M159.5,78.3050108 C169.164983,78.3050108 177,70.4699939 177,60.8050108 C177,51.1400277 169.688728,56.4616841 160.023745,56.4616841 C150.358762,56.4616841 142,51.1400277 142,60.8050108 C142,70.4699939 149.835017,78.3050108 159.5,78.3050108 Z" id="mouth" fill="#000000"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

+6 -2
View File
@@ -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,11 @@
</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-name="docsify"
data-router></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
</html>
+314 -34
View File
@@ -1,23 +1,20 @@
# docsify
> 无需构建快速生成文档页
## 特性
- 无需构建,写完 markdown 直接发布
- 支持自定义主题
- 容易使用并且轻量
- 容易使用并且轻量 (~12kb gzipped)
## 快速上手
### 创建项目
新建一个空项目,接着创建一个 `docs` 目录并进入到 docs 目录下
```shell
```bash
mkdir my-project && cd my-project
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>
```
@@ -49,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">
@@ -82,48 +82,196 @@ 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)
目前可用的 CDN 有 [UNPKG](unpkg.com/docsify),如果觉得访问较慢可以将文件放到 Pages 的目录下。
### 封面
### 配置参数
只需要写几行简单的 markdown 就可以拥有一页精致的封面,通过添加 `data-coverpage` 属性,并创建 `_coverpage.md`,按照下面的格式书写即可。
#### repo
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
```markdown
![logo](_media/icon.svg)
# docsify <small>1.2.0</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Multiple themes
- Not build static html files
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
```
#### 自定义封面背景
默认的背景是随机生成的,你可以自定义背景色或者背景图片。只需要在文档末尾用添加图片的 Markdown 语法
```markdown
# docsify <small>1.2.0</small>
> xxx
[GitHub](https://github.com/QingWei-Li/docsify/)
[Get Started](#quick-start)
<!-- 背景图片 -->
![](_media/bg.png)
<!-- 背景色 -->
![color](#f0f0f0)
```
### 自定义 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" data-router></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
```js
window.$docsify = {
el: '#app'
}
```
### sidebar-toggle
Sidebar 开关按钮
@@ -131,7 +279,14 @@ Sidebar 开关按钮
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
```js
window.$docsify = {
sidebarToggle: true
}
```
### sidebar
设置后 TOC 功能将不可用,适合导航较多的文档,`data-sidebar` 传入全局变量名。
@@ -154,20 +309,35 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
```
#### load-sidebar
```js
window.$docsify = {
sidebar: 'sidebar'
}
```
### load-sidebar
读取侧边栏配置文件,如果配置,默认加载当前目录下的 `_sidebar.md`。如果文件不存在,会显示 TOC 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
**如果用 `_` 开头作为文件名,你应该在文档目录下添加 `.nojekyll`,阻止 GitHub Pages 忽略下划线开头的文件。**
```html
<script src="/lib/docsify.js" data-load-sidebar></script>
```
你可以指定侧边栏文件名
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
```js
window.$docsify = {
loadSidebar: '_sidebar.md'
}
```
`_sidebar.md` 的内容可以是这样的
```markdown
@@ -177,14 +347,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 里定义的导航栏。
@@ -198,6 +378,12 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
```js
window.$docsify = {
loadNavbar: '_navbar.md'
}
```
`_navbar.md` 的内容可以是这样
```markdown
@@ -216,12 +402,18 @@ Sidebar 开关按钮
### router
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
开启 hash router 功能,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
```html
<script src="/lib/docsify.js" data-router></script>
```
```js
window.$docsify = {
router: true
}
```
### auto2top
切换路由时自动跳转到页面顶部
@@ -231,3 +423,91 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-auto2top></script>
```
```js
window.$docsify = {
auto2top: true
}
```
### 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>
```
```js
window.$docsify = {
homepage: true
}
```
### 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>
```
```js
window.$docsify = {
basePath: '/base/'
}
```
### coverpage
生成封面,参考 [#封面](/zh-cn#封面).
```html
<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
项目名,将显示在侧边栏。
```html
<script src="/lib/docsify.js" data-name="docsify"></script>
```
```js
window.$docsify = {
name: 'docsify'
}
```
### nameLink
项目名链接,默认为 `window.location.pathname`
```html
<script src="/lib/docsify.js" data-name-link="/"></script>
```
```js
window.$docsify = {
nameLink: '/'
}
```
+416 -191
View File
@@ -21,8 +21,13 @@ function load (url, method, loading) {
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('loaded', loading);
xhr.addEventListener('loadend', function (evt) {
loading(evt);
clearInterval(id);
});
}
xhr.addEventListener('error', error);
xhr.addEventListener('load', function (ref) {
@@ -106,7 +111,67 @@ function getRoute () {
}
function isMobile () {
return /mobile/i.test(navigator.userAgent)
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(/:(\w*?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
.replace(/__colon__/g, ':')
}
/**
@@ -116,51 +181,64 @@ function isMobile () {
function scrollActiveSidebar () {
if (isMobile()) { return }
var hoveredOverSidebar = false;
var anchors = document.querySelectorAll('.anchor');
var sidebar = document.querySelector('aside.sidebar');
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[href] = li;
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].parentNode;
var bcr = node.getBoundingClientRect();
var node = anchors[i];
if (bcr.top < 10 && bcr.bottom > 10) {
var li = nav[node.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;
!hoveredOverSidebar && !sticky.noSticky && active.scrollIntoView(false);
}
var dom = document.querySelector('main .content');
dom.removeEventListener('scroll', highlight);
dom.addEventListener('scroll', highlight);
highlight();
window.removeEventListener('scroll', highlight);
window.addEventListener('scroll', highlight);
sidebar.addEventListener('mouseover', function () { hoveredOverSidebar = true; });
sidebar.addEventListener('mouseleave', function () { hoveredOverSidebar = false; });
}
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(); }
if (section) { setTimeout(function () { return section.scrollIntoView(); }, 0); }
return section
}
/**
@@ -170,19 +248,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
}
/**
@@ -195,19 +277,34 @@ 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('aside.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 () {
sticky.dom = sticky.dom || document.querySelector('section.cover');
var coverHeight = sticky.dom.getBoundingClientRect().height;
return (function () {
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;
}
})()
}
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -1508,12 +1605,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() {
@@ -1731,6 +1824,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;
}
@@ -1808,9 +1904,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++) { // Dont cache length as it changes during the loop
// Dont 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];
@@ -1830,40 +1933,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) {
@@ -1932,7 +2033,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;
};
@@ -1968,13 +2069,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, '&quot;') + '"';
}).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 + '>';
};
@@ -2007,7 +2106,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);
@@ -2019,7 +2122,7 @@ return _self.Prism;
})();
if (typeof module !== 'undefined' && module.exports) {
if ('object' !== 'undefined' && module.exports) {
module.exports = Prism;
}
@@ -2036,10 +2139,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,
@@ -2096,7 +2199,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,
@@ -2177,7 +2283,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', {
@@ -2319,15 +2426,26 @@ 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) {
var aside = tpl + "<aside class=\"sidebar\"></aside>";
return (isMobile() ? (aside + "<main>") : ("<main>" + aside)) +
"<section class=\"content\">\n <article class=\"markdown-section\"></article>\n </section>\n </main>"
}
function toggle (bool) {
if (!bool) { return '' }
return "<button class=\"sidebar-toggle\">\n <span></span><span></span><span></span>\n </button>"
/**
* 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 <div class=\"sidebar-toggle-button\">\n <span></span><span></span><span></span>\n </div>\n </button>"
}
/**
@@ -2351,50 +2469,82 @@ function tree (toc, tpl) {
return tpl
}
function helper (className, content) {
return ("<p class=\"" + className + "\">" + (content.slice(5).trim()) + "</p>")
}
var OPTIONS$1 = {};
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
* @param {Object} options
*/
renderer.heading = function (text, level) {
var slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
var route = '';
function init (options) {
OPTIONS$1 = options;
if (OPTIONS$1.router) {
route = "#/" + (getRoute());
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.replace(/:/g, '__colon__')) + "</code></pre>")
};
renderer.link = function (href, title, text) {
if (OPTIONS$1.router && !/:/.test(href)) {
href = ("#/" + href).replace(/\/\//g, '/');
}
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
};
renderer.paragraph = function (text) {
if (/^!&gt;/.test(text)) {
return helper('tip', text)
} else if (/^\?&gt;/.test(text)) {
return helper('warn', text)
}
return ("<p>" + text + "</p>")
};
if (typeof OPTIONS$1.markdown === 'function') {
markdown.setOptions({ renderer: renderer });
markdown = OPTIONS$1.markdown.call(this, markdown);
} else {
markdown.setOptions(merge({ renderer: renderer }, OPTIONS$1.markdown));
}
toc.push({ level: level, slug: (route + "#" + slug), title: text });
var md = markdown;
return ("<h" + level + " id=\"" + slug + "\"><a href=\"" + route + "#" + slug + "\" class=\"anchor\"></a>" + text + "</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 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 });
markdown = function (text) { return emojify(md(text)); };
}
/**
* App
@@ -2402,35 +2552,51 @@ 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');
}
}
/**
* 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 (!OPTIONS$1.sidebar && !OPTIONS$1.loadSidebar) { renderSidebar(); }
if (OPTIONS$1.auto2top) { scroll2Top(); }
if (content && typeof Vue !== 'undefined') {
var script = content.match('<script[^>]*?>([^<]+)</script>');
script && document.body.querySelector('article script').remove();
CACHE.vm && CACHE.vm.$destroy();
CACHE.vm = script
? new Function(("return " + (script[1].trim())))()
: new Vue({ el: 'main' }); // eslint-disable-line
CACHE.vm && CACHE.vm.$nextTick(function (_) { return scrollActiveSidebar(); });
}
if (OPTIONS$1.auto2top) { setTimeout(function () { return scroll2Top(OPTIONS$1.auto2top); }, 0); }
}
/**
* navbar
*/
function renderNavbar (content) {
if (CACHE['navbar'] && 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)); }
if (content) { renderTo('nav', markdown(content)); }
activeLink('nav');
}
@@ -2438,23 +2604,68 @@ function renderNavbar (content) {
* sidebar
*/
function renderSidebar (content) {
var isToc = false;
var html;
if (content) {
content = marked(content);
html = markdown(content);
// find url tag
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0];
} 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>');
}
renderSidebar.rendered = true;
if (CACHE['sidebar'] && CACHE['sidebar'] === content) { return }
CACHE['sidebar'] = content;
renderTo('aside.sidebar', content);
if (isToc) { scrollActiveSidebar(); }
html = (OPTIONS$1.name ? ("<h1><a href=\"" + (OPTIONS$1.nameLink) + "\">" + (OPTIONS$1.name) + "</a></h1>") : '') + html;
renderTo('aside.sidebar', html);
var target = activeLink('aside.sidebar', true);
if (target) { 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 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();
}
/**
@@ -2464,49 +2675,53 @@ function renderSidebar (content) {
function renderLoading (ref) {
var loaded = ref.loaded;
var total = ref.total;
var step = ref.step;
var num = Math.floor(loaded / total * 100);
var num;
if (!CACHE['loading']) {
if (!CACHE.loading) {
var div = document.createElement('div');
div.classList.add('progress');
document.body.appendChild(div);
CACHE['loading'] = 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);
CACHE['loading'].style.width = '100%';
renderLoading.cacheTImeout = setTimeout(function (_) {
CACHE['loading'].style.opacity = 0;
CACHE['loading'].style.width = '0%';
clearTimeout(renderLoading.cacheTimeout);
renderLoading.cacheTimeout = setTimeout(function (_) {
CACHE.loading.style.opacity = 0;
CACHE.loading.style.width = '0%';
}, 200);
} else {
CACHE['loading'].style.opacity = 1;
CACHE['loading'].style.width = num + '%';
}
}
/**
* Load Config
* @param {Object} options
*/
function config (options) {
OPTIONS$1 = options;
}
var OPTIONS = {
var OPTIONS = merge({
el: '#app',
repo: '',
maxLevel: 6,
subMaxLevel: 0,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
auto2top: false
};
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false,
name: '',
nameLink: window.location.pathname
}, window.$docsify);
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
// load configuration for script attribute
@@ -2517,19 +2732,22 @@ 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.repo === true) { OPTIONS.repo = ''; }
if (OPTIONS.name === true) { OPTIONS.name = ''; }
if (OPTIONS.sidebar) { OPTIONS.sidebar = window[OPTIONS.sidebar]; }
}
// load options
config(OPTIONS);
init(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)) {
@@ -2538,35 +2756,42 @@ var mainRender = function (cb) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1];
}
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(
(!route || /\/$/.test(route)) ? (route + "README.md") : (route + ".md"),
'GET',
renderLoading);
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); });
}
};
@@ -2575,8 +2800,8 @@ var Docsify = function () {
var replace = dom !== document.body;
var main = function () {
mainRender(function (_) {
activeLink('aside.sidebar', true);
scrollIntoView();
activeLink('nav');
});
};
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "1.1.2",
"version": "1.10.2",
"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": {
@@ -35,9 +35,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"
+76 -44
View File
@@ -7,51 +7,64 @@ import { isMobile } from './util'
export function scrollActiveSidebar () {
if (isMobile()) return
let hoveredOverSidebar = false
const anchors = document.querySelectorAll('.anchor')
const sidebar = document.querySelector('aside.sidebar')
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[href] = li
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].parentNode
const bcr = node.getBoundingClientRect()
const node = anchors[i]
if (bcr.top < 10 && bcr.bottom > 10) {
const li = nav[node.id]
if (!li || li === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
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
!hoveredOverSidebar && !sticky.noSticky && active.scrollIntoView(false)
}
const dom = document.querySelector('main .content')
dom.removeEventListener('scroll', highlight)
dom.addEventListener('scroll', highlight)
highlight()
window.removeEventListener('scroll', highlight)
window.addEventListener('scroll', highlight)
sidebar.addEventListener('mouseover', () => { hoveredOverSidebar = true })
sidebar.addEventListener('mouseleave', () => { hoveredOverSidebar = false })
}
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()
if (section) setTimeout(() => section.scrollIntoView(), 0)
return section
}
/**
@@ -62,18 +75,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
}
/**
@@ -86,17 +105,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('aside.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 () {
sticky.dom = sticky.dom || document.querySelector('section.cover')
const coverHeight = sticky.dom.getBoundingClientRect().height
return (function () {
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
}
})()
}
+42 -26
View File
@@ -1,18 +1,24 @@
import { load, camel2kebab, isNil, getRoute } from './util'
import { activeLink, scrollIntoView } from './event'
import { load, camel2kebab, isNil, getRoute, merge } from './util'
import { scrollIntoView, activeLink } from './event'
import * as render from './render'
const OPTIONS = {
const OPTIONS = merge({
el: '#app',
repo: '',
maxLevel: 6,
subMaxLevel: 0,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
auto2top: false
}
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false,
name: '',
nameLink: window.location.pathname
}, window.$docsify)
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
// load configuration for script attribute
@@ -23,19 +29,22 @@ 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.repo === true) OPTIONS.repo = ''
if (OPTIONS.name === true) OPTIONS.name = ''
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
}
// load options
render.config(OPTIONS)
render.init(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)) {
@@ -44,35 +53,42 @@ const mainRender = function (cb) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1]
}
let page
if (!route) {
page = OPTIONS.homepage || 'README.md'
} else if (/\/$/.test(route)) {
page = `${route}README.md`
} else {
page = `${route}.md`
}
// Render Cover page
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
load(OPTIONS.coverpage).then(render.renderCover)
}
cacheXhr && cacheXhr.abort && cacheXhr.abort()
// Render markdown file
cacheXhr = load(
(!route || /\/$/.test(route)) ? `${route}README.md` : `${route}.md`,
'GET',
render.renderLoading)
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) {
if (wait === false) cb()
wait = false
const renderSidebar = result => { render.renderSidebar(result); cb() }
load(basePath + OPTIONS.loadSidebar).then(renderSidebar,
_ => 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)
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar,
_ => load(OPTIONS.loadNavbar).then(render.renderNavbar))
}
}
@@ -81,8 +97,8 @@ const Docsify = function () {
const replace = dom !== document.body
const main = function () {
mainRender(_ => {
activeLink('aside.sidebar', true)
scrollIntoView()
activeLink('nav')
})
}
+155 -70
View File
@@ -1,51 +1,79 @@
import marked from 'marked'
import Prism from 'prismjs'
import * as tpl from './tpl'
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top } from './event'
import { genTree, getRoute } from './util'
import * as event from './event'
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
* @param {Object} options
*/
renderer.heading = function (text, level) {
const slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
let route = ''
export function init (options) {
OPTIONS = options
if (OPTIONS.router) {
route = `#/${getRoute()}`
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.replace(/:/g, '__colon__')}</code></pre>`
}
renderer.link = function (href, title, text) {
if (OPTIONS.router && !/:/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
}
return `<a href="${href}" title="${title || ''}">${text}</a>`
}
renderer.paragraph = function (text) {
if (/^!&gt;/.test(text)) {
return tpl.helper('tip', text)
} else if (/^\?&gt;/.test(text)) {
return tpl.helper('warn', text)
}
return `<p>${text}</p>`
}
toc.push({ level, slug: `${route}#${slug}`, title: text })
return `<h${level} id="${slug}"><a href="${route}#${slug}" class="anchor"></a>${text}</h${level}>`
}
// 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 OPTIONS.markdown === 'function') {
markdown.setOptions({ renderer })
markdown = OPTIONS.markdown.call(this, markdown)
} else {
markdown.setOptions(merge({ renderer }, OPTIONS.markdown))
}
return `<a href="${href}" title="${title || ''}">${text}</a>`
const md = markdown
markdown = text => emojify(md(text))
}
marked.setOptions({ renderer })
/**
* App
@@ -53,94 +81,151 @@ 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')
event.bindToggle('button.sidebar-toggle')
// bind sticky effect
if (OPTIONS.coverpage) {
!isMobile() && window.addEventListener('scroll', event.sticky)
} else {
document.body.classList.add('sticky')
}
}
/**
* 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 (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
if (OPTIONS.auto2top) scroll2Top()
if (content && typeof Vue !== 'undefined') {
const script = content.match('<script[^>]*?>([^<]+)</script>')
script && document.body.querySelector('article script').remove()
CACHE.vm && CACHE.vm.$destroy()
CACHE.vm = script
? new Function(`return ${script[1].trim()}`)()
: new Vue({ el: 'main' }) // eslint-disable-line
CACHE.vm && CACHE.vm.$nextTick(_ => event.scrollActiveSidebar())
}
if (OPTIONS.auto2top) setTimeout(() => event.scroll2Top(OPTIONS.auto2top), 0)
}
/**
* navbar
*/
export function renderNavbar (content) {
if (CACHE['navbar'] && 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')
if (content) renderTo('nav', markdown(content))
event.activeLink('nav')
}
/**
* sidebar
*/
export function renderSidebar (content) {
let isToc = false
let html
if (content) {
content = marked(content)
html = markdown(content)
// find url tag
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
} 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>')
}
renderSidebar.rendered = true
if (CACHE['sidebar'] && CACHE['sidebar'] === content) return
CACHE['sidebar'] = content
renderTo('aside.sidebar', content)
if (isToc) scrollActiveSidebar()
html = (OPTIONS.name ? `<h1><a href="${OPTIONS.nameLink}">${OPTIONS.name}</a></h1>` : '') + html
renderTo('aside.sidebar', html)
const target = event.activeLink('aside.sidebar', true)
if (target) renderSubSidebar(target)
toc = []
event.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 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()
}
/**
* render loading bar
* @return {[type]} [description]
*/
export function renderLoading ({ loaded, total }) {
const num = Math.floor(loaded / total * 100)
export function renderLoading ({ loaded, total, step }) {
let num
if (!CACHE['loading']) {
if (!CACHE.loading) {
const div = document.createElement('div')
div.classList.add('progress')
document.body.appendChild(div)
CACHE['loading'] = 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)
CACHE['loading'].style.width = '100%'
renderLoading.cacheTImeout = setTimeout(_ => {
CACHE['loading'].style.opacity = 0
CACHE['loading'].style.width = '0%'
clearTimeout(renderLoading.cacheTimeout)
renderLoading.cacheTimeout = setTimeout(_ => {
CACHE.loading.style.opacity = 0
CACHE.loading.style.width = '0%'
}, 200)
} else {
CACHE['loading'].style.opacity = 1
CACHE['loading'].style.width = num + '%'
}
}
/**
* Load Config
* @param {Object} options
*/
export function config (options) {
OPTIONS = options
}
+101
View File
@@ -0,0 +1,101 @@
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: -20px 16px 0;
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;
a {
display: block;
}
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;
}
}
}
+181 -23
View File
@@ -1,4 +1,3 @@
* {
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
@@ -8,6 +7,11 @@
-webkit-font-smoothing: antialiased;
}
.emoji {
height: 1.2em;
vertical-align: middle;
}
.progress {
background-color: $color-primary;
height: 2px;
@@ -32,12 +36,24 @@ body {
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
color: $color-text;
}
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;
@@ -47,6 +63,10 @@ nav {
margin: 25px 60px 0 0;
text-align: right;
&.no-badge {
margin-right: 25px;
}
p {
margin: 0;
}
@@ -81,7 +101,8 @@ nav {
display: inline-block;
ul {
background-color: rgba(#fff, .6);
border-radius: 2px;
background-color: rgba($color-bg, .6);
border: 1px solid $color-primary;
opacity: 0;
overflow: hidden;
@@ -124,24 +145,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;
@@ -150,19 +166,55 @@ nav {
/* main */
main {
size: 100% 100%;
display: block;
size: 100vw 100%;
position: relative;
}
.anchor {
text-decoration: none;
transition: all .3s;
display: inline-block;
span {
color: $color-text;
}
&:hover {
text-decoration: underline;
}
}
/* 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;
margin-bottom: 40px;
&::after {
content: '';
position: inherit;
left: calc($sidebar-width - 1px);
top: 0;
height: 100vh;
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;
@@ -187,17 +239,18 @@ main {
.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;
}
@@ -209,11 +262,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;
}
@@ -235,21 +292,107 @@ main {
}
}
.markdown-section hr {
border: none;
margin: 2em 0;
border-bottom: 1px solid #eee;
}
.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;
}
}
.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;
}
}
@media (max-width: 600px) {
nav, .github-corner, .sidebar-toggle, .sidebar {
.github-corner, .sidebar-toggle, .sidebar {
position: fixed;
}
.sidebar {
margin-bottom: 0;
border-right: 1px solid rgba(0, 0, 0, .07);
&::after {
content: none;
}
}
nav {
margin-top: 16px;
}
@@ -258,6 +401,11 @@ body.close {
top: 30px;
}
main {
height: auto;
overflow-x: hidden;
}
.sidebar {
left: -$sidebar-width;
transition: transform 250ms ease-out;
@@ -265,27 +413,37 @@ body.close {
.content {
left: 0;
min-width: 100vw;
transition: transform 250ms ease;
max-width: 100vw;
position: static;
overflow-y: auto;
transition: transform 250ms ease;
}
nav, .github-corner {
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;
}
}
+7 -23
View File
@@ -1,16 +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: $color-bg;
a {
color: #666;
@@ -27,7 +28,7 @@ body {
padding: 0;
}
.active {
li.active {
background-color: #eee;
a {
@@ -54,6 +55,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 +98,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;
@@ -242,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;
}
+2
View File
@@ -1,3 +1,5 @@
$color-primary: #000;
$color-bg: #fff;
$color-text: #000;
$sidebar-width: 300px;
@import "basic/layout";
+7 -21
View File
@@ -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;
$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: $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;
@@ -287,15 +285,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;
}
+28 -11
View File
@@ -1,4 +1,4 @@
import { isMobile } from './util'
/**
* Render github corner
* @param {Object} data
@@ -21,22 +21,36 @@ export function corner (data) {
/**
* Render main content
* @return {[type]} [description]
*/
export function main () {
return `<main>
<aside class="sidebar"></aside>
<section class="content">
export function main (tpl) {
const aside = `${tpl}<aside class="sidebar"></aside>`
return (isMobile() ? `${aside}<main>` : `<main>${aside}`) +
`<section class="content">
<article class="markdown-section"></article>
</section>
</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>`
<div class="sidebar-toggle-button">
<span></span><span></span><span></span>
</div>
</button>`
}
/**
@@ -58,3 +72,6 @@ export function tree (toc, tpl = '') {
return tpl
}
export function helper (className, content) {
return `<p class="${className}">${content.slice(5).trim()}</p>`
}
+66 -2
View File
@@ -14,8 +14,14 @@ export function load (url, method = 'GET', loading) {
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('loaded', loading)
xhr.addEventListener('loadend', evt => {
loading(evt)
clearInterval(id)
})
}
xhr.addEventListener('error', error)
xhr.addEventListener('load', ({ target }) => {
@@ -97,6 +103,64 @@ export function getRoute () {
}
export function isMobile () {
return /mobile/i.test(navigator.userAgent)
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(/:(\w*?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
.replace(/__colon__/g, ':')
}
+3434
View File
File diff suppressed because it is too large Load Diff