mirror of
https://github.com/wahyd4/docsify.git
synced 2026-08-10 05:48:18 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b15b286c5c | ||
|
|
5ab86271c2 | ||
|
|
9638eee50d | ||
|
|
375a1dd3e1 | ||
|
|
3069ad3928 | ||
|
|
b287f57c86 | ||
|
|
e932ff66b9 | ||
|
|
7a10e4aecf | ||
|
|
41e7ef6863 | ||
|
|
7ce166501b | ||
|
|
b9aeb4a922 | ||
|
|
9ac8293c0a | ||
|
|
aa3121eca2 | ||
|
|
0e615abbdc | ||
|
|
cb2b191ba1 | ||
|
|
6adcfffba9 | ||
|
|
f165470265 | ||
|
|
bbb7b4a9d6 | ||
|
|
540095ee35 | ||
|
|
bd354094c0 | ||
|
|
6e81e66441 | ||
|
|
67f9083ff7 | ||
|
|
383b976ddd | ||
|
|
54ba970552 | ||
|
|
16623c9301 | ||
|
|
668c5ca714 | ||
|
|
d0861d7427 | ||
|
|
97669e0d28 | ||
|
|
a0408b7a38 | ||
|
|
f917da8214 | ||
|
|
64309beee9 |
@@ -1,3 +1,4 @@
|
||||
.DS_Store
|
||||
*.log
|
||||
node_modules
|
||||
yarn.lock
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
## 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
|
||||
|
||||
@@ -42,12 +42,6 @@ index.html
|
||||
</html>
|
||||
```
|
||||
|
||||
Or create a `404.html` and `README.md` into `/docs`. Just remove `data-router`
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
```
|
||||
|
||||
## CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
@@ -58,6 +52,10 @@ These open-source projects are using docsify to generate their sites. Pull reque
|
||||
- [docsify](https://docsify.js.org) - A magical documentation site generator.
|
||||
- [Snipaste](https://docs.snipaste.com/) - A new way to boost your productivity.
|
||||
|
||||
## Similar projects
|
||||
- [docute](https://github.com/egoist/docute) - 📜 Effortlessly documentation done right
|
||||
- [docpress](https://github.com/docpress/docpress) - Documentation website generator
|
||||
|
||||
## Contributing
|
||||
|
||||
- Fork it!
|
||||
|
||||
@@ -5,7 +5,7 @@ var fs = require('fs')
|
||||
http.createServer(function (req, res) {
|
||||
serveStatic('.')(req, res, function () {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' })
|
||||
res.end(fs.readFileSync('404.dev.html'))
|
||||
res.end(fs.readFileSync('dev.html'))
|
||||
})
|
||||
}).listen(3000, '0.0.0.0')
|
||||
|
||||
|
||||
@@ -8,5 +8,7 @@
|
||||
<body class="">
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src=//unpkg.com/vue></script>
|
||||
<script src=//unpkg.com/vuep></script>
|
||||
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-auto2top data-sidebar-toggle data-router></script>
|
||||
</html>
|
||||
+45
-17
@@ -8,7 +8,7 @@ mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### Create entry file
|
||||
Create a `404.html` file
|
||||
Create a `index.html` file
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
@@ -20,7 +20,7 @@ Create a `404.html` file
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="//unpkg.com/docsify"></script>
|
||||
<script src="//unpkg.com/docsify" data-router></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -29,7 +29,7 @@ Create `README.md` as the main page
|
||||
```
|
||||
# Title
|
||||
|
||||
## balabala
|
||||
## blabla
|
||||
```
|
||||
|
||||
### Deploy!
|
||||
@@ -38,7 +38,7 @@ Push and open the **GitHub Pages** feature
|
||||
|
||||
## CLI
|
||||
|
||||
Easy to setup and preivew a docs.
|
||||
Easy to setup and preview a docs.
|
||||
|
||||
### Install
|
||||
```shell
|
||||
@@ -77,19 +77,18 @@ Minified files
|
||||
## More
|
||||
|
||||
### Multiple pages
|
||||
If you need other pages, directly create the markdown file, such as `guide.md` is `/guide`.
|
||||
If you need other pages, directly create the markdown file, such as `guide.md` is `/#/guide`.
|
||||
|
||||
### Navbar
|
||||
Code in `404.html`
|
||||
Code in `index.html`
|
||||
|
||||
```html
|
||||
<nav>
|
||||
<a href="/docsify/">En</a>
|
||||
<a href="/docsify/zh-cn">中文</a>
|
||||
<a href="/#/docsify/">En</a>
|
||||
<a href="/#/docsify/zh-cn">中文</a>
|
||||
</nav>
|
||||
```
|
||||
|
||||
|
||||
### CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
@@ -97,7 +96,7 @@ Code in `404.html`
|
||||
|
||||
### Cover Page
|
||||
|
||||
Through the markdown can generate a cover page. create a `_coverpage.md` and set `data-coverpage` in script tag.
|
||||
Generate a cover page through with markdown. Create a `_coverpage.md` and set `data-coverpage` in script tag.
|
||||
|
||||
```markdown
|
||||

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

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

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

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

|
||||
|
||||
|
||||
#### load-navbar
|
||||
|
||||
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
|
||||
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-navbar></script>
|
||||
@@ -234,7 +262,7 @@ 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>
|
||||
@@ -251,7 +279,7 @@ Scroll to the top on changing hash.
|
||||
|
||||
#### homepage
|
||||
|
||||
`README.md` will be render as homepage for your website in docs folder, but sometimes we want to specify another file as a homepage, or even use the `README.md` in your repo. we can use (need `data-router`):
|
||||
`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>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
# docsify <small>1.3.1</small>
|
||||
# docsify <small>1.3.3</small>
|
||||
|
||||
> A magical documentation site generator.
|
||||
|
||||
|
||||
+40
-10
@@ -14,7 +14,7 @@ mkdir docs && cd docs
|
||||
```
|
||||
|
||||
### 创建入口文件
|
||||
创建一个 `404.html` 文件,内容为
|
||||
创建一个 `index.html` 文件,内容为
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -25,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>
|
||||
```
|
||||
|
||||
@@ -66,7 +66,7 @@ docsify serve docs
|
||||
更多选项参考 [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
|
||||
|
||||
## 主题
|
||||
目前提供 vue.css 和 buble.css,直接修改 `404.html` 里的 cdn 地址即可
|
||||
目前提供 vue.css 和 buble.css,直接修改 `index.html` 里的 cdn 地址即可
|
||||
```html
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
|
||||
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
|
||||
@@ -82,19 +82,20 @@ docsify serve docs
|
||||
## 更多功能
|
||||
|
||||
### 多页面
|
||||
`README.md` 作为主页面,如果需要其他页面,直接在文档目录下创建对应的 `*.md` 文件,例如创建一个 `guide.md` 那么对应的路由就是 `/guide`。
|
||||
`README.md` 作为主页面,如果需要其他页面,直接在文档目录下创建对应的 `*.md` 文件,例如创建一个 `guide.md` 那么对应的路由就是 `/#/guide`。
|
||||
|
||||
### 导航
|
||||
导航需要自己写在 `404.html` 文件里,效果参考本文档
|
||||
导航需要自己写在 `index.html` 文件里,效果参考本文档
|
||||
|
||||
```html
|
||||
<nav>
|
||||
<a href="/docsify/">En</a>
|
||||
<a href="/docsify/zh-cn">中文</a>
|
||||
<a href="/#/docsify/">En</a>
|
||||
<a href="/#/docsify/zh-cn">中文</a>
|
||||
</nav>
|
||||
```
|
||||
|
||||
|
||||
|
||||
### CDN
|
||||
- UNPKG [https://unpkg.com/docsify/](https://unpkg.com/docsify/)
|
||||
- jsDelivr [http://www.jsdelivr.com/projects/docsify](http://www.jsdelivr.com/projects/docsify)
|
||||
@@ -120,11 +121,28 @@ docsify serve docs
|
||||
```
|
||||
|
||||
|
||||
#### 自定义封面背景
|
||||
默认的背景是随机生成的,你可以自定义背景色或者背景图片。只需要在文档末尾用添加图片的 Markdown 语法
|
||||
|
||||
```markdown
|
||||
# docsify <small>1.2.0</small>
|
||||
|
||||
> xxx
|
||||
|
||||
[GitHub](https://github.com/QingWei-Li/docsify/)
|
||||
[Get Started](#quick-start)
|
||||
|
||||
<!-- 背景图片 -->
|
||||

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

|
||||
```
|
||||
|
||||
|
||||
### 配置参数
|
||||
|
||||
#### repo
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
|
||||
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `index.html` 里的 script 改成
|
||||
|
||||
```html
|
||||
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
|
||||
@@ -205,6 +223,18 @@ Sidebar 开关按钮
|
||||
- [HTML5 History Mode](/history-mode)
|
||||
```
|
||||
|
||||
#### sub-max-level
|
||||
|
||||
显示 TOC 在自定义的侧边栏里,默认最大显示 0 层。
|
||||
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
#### load-navbar
|
||||
|
||||
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
|
||||
@@ -237,7 +267,7 @@ Sidebar 开关按钮
|
||||
|
||||
#### router
|
||||
|
||||
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
|
||||
开启 hash router 功能,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-router></script>
|
||||
@@ -276,7 +306,7 @@ Sidebar 开关按钮
|
||||
|
||||
#### coverpage
|
||||
|
||||
生成封面,参考 [#封面](#封面).
|
||||
生成封面,参考 [#封面](/zh-cn#封面).
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-coverpage></script>
|
||||
|
||||
+111
-62
@@ -114,6 +114,35 @@ function isMobile () {
|
||||
return document.body.clientWidth <= 600
|
||||
}
|
||||
|
||||
function slugify (string) {
|
||||
var re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g;
|
||||
var maintainCase = false;
|
||||
var replacement = '-';
|
||||
slugify.occurrences = slugify.occurrences || {};
|
||||
|
||||
if (typeof string !== 'string') { return '' }
|
||||
if (!maintainCase) { string = string.toLowerCase(); }
|
||||
|
||||
var slug = string.trim()
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, replacement);
|
||||
var occurrences = slugify.occurrences[slug];
|
||||
|
||||
if (slugify.occurrences.hasOwnProperty(slug)) {
|
||||
occurrences++;
|
||||
} else {
|
||||
occurrences = 0;
|
||||
}
|
||||
|
||||
slugify.occurrences[slug] = occurrences;
|
||||
|
||||
if (occurrences) {
|
||||
slug = slug + '-' + occurrences;
|
||||
}
|
||||
|
||||
return slug
|
||||
}
|
||||
|
||||
/**
|
||||
* Active sidebar when scroll
|
||||
* @link https://buble.surge.sh/
|
||||
@@ -130,7 +159,10 @@ function scrollActiveSidebar () {
|
||||
var li = lis[i];
|
||||
var href = li.querySelector('a').getAttribute('href');
|
||||
|
||||
if (href !== '/') { href = href.match(/#([^#]+)$/g)[0].slice(1); }
|
||||
if (href !== '/') {
|
||||
var match = href.match('#([^#]+)$');
|
||||
if (match && match.length) { href = match[0].slice(1); }
|
||||
}
|
||||
|
||||
nav[decodeURIComponent(href)] = li;
|
||||
}
|
||||
@@ -174,19 +206,23 @@ function activeLink (dom, activeParent) {
|
||||
var host = window.location.href;
|
||||
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
|
||||
if (!dom) { return
|
||||
if (!dom) { return }
|
||||
var target;[].slice.call(dom.querySelectorAll('a'))
|
||||
.sort(function (a, b) { return b.href.length - a.href.length; })
|
||||
.forEach(function (node) {
|
||||
if (host.indexOf(node.href) === 0 && !target) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active');
|
||||
target = node;
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class');
|
||||
}
|
||||
});
|
||||
|
||||
; }[].slice.call(dom.querySelectorAll('a')).forEach(function (node) {
|
||||
if (node.href === host) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active');
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class');
|
||||
}
|
||||
});
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2348,7 +2384,7 @@ function cover () {
|
||||
var SL = ', 100%, 85%';
|
||||
var bgc = "linear-gradient(to left bottom, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 0%, hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 100%)";
|
||||
|
||||
return ("<section class=\"cover\" style=\"background: " + bgc + "\">\n <div class=\"cover-main\"></div>\n </section>")
|
||||
return ("<section class=\"cover\" style=\"background: " + bgc + "\">\n <div class=\"cover-main\"></div>\n <div class=\"mask\"></div>\n </section>")
|
||||
}
|
||||
|
||||
function toggle () {
|
||||
@@ -2393,9 +2429,7 @@ var renderer = new marked.Renderer();
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
var slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
|
||||
var slug = slugify(text);
|
||||
var route = '';
|
||||
|
||||
if (OPTIONS$1.router) {
|
||||
@@ -2410,13 +2444,14 @@ renderer.heading = function (text, level) {
|
||||
renderer.code = function (code, lang) {
|
||||
if ( lang === void 0 ) lang = '';
|
||||
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
|
||||
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup)
|
||||
.replace(/{{/g, '<span>{{</span>');
|
||||
|
||||
return ("<pre data-lang=\"" + lang + "\"><code class=\"lang-" + lang + "\">" + hl + "</code></pre>")
|
||||
};
|
||||
renderer.link = function (href, title, text) {
|
||||
if (OPTIONS$1.router && !/^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(href)) {
|
||||
href = !/^\/#/.test(href) ? ("#/" + (getRoute()) + href) : href;
|
||||
href = ("#/" + href).replace(/\/\//g, '/');
|
||||
}
|
||||
|
||||
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
|
||||
@@ -2451,11 +2486,12 @@ function renderApp (dom, replace) {
|
||||
*/
|
||||
function renderArticle (content) {
|
||||
renderTo('article', content ? marked(content) : 'not found');
|
||||
if (!renderSidebar.rendered) { renderSidebar(null, OPTIONS$1); }
|
||||
if (!renderNavbar.rendered) { renderNavbar(null, OPTIONS$1); }
|
||||
renderSidebar.rendered = false;
|
||||
renderNavbar.rendered = false;
|
||||
if (!OPTIONS$1.sidebar && !OPTIONS$1.loadSidebar) { renderSidebar(); }
|
||||
|
||||
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
|
||||
var vm = new Vue({ el: 'main' }); // eslint-disable-line
|
||||
vm.$nextTick(function (_) { return scrollActiveSidebar(); });
|
||||
}
|
||||
if (OPTIONS$1.auto2top) { scroll2Top(); }
|
||||
}
|
||||
|
||||
@@ -2465,7 +2501,6 @@ function renderArticle (content) {
|
||||
function renderNavbar (content) {
|
||||
if (CACHE.navbar && CACHE.navbar === content) { return }
|
||||
CACHE.navbar = content;
|
||||
renderNavbar.rendered = true;
|
||||
|
||||
if (content) { renderTo('nav', marked(content)); }
|
||||
activeLink('nav');
|
||||
@@ -2475,23 +2510,27 @@ function renderNavbar (content) {
|
||||
* sidebar
|
||||
*/
|
||||
function renderSidebar (content) {
|
||||
var isToc = false;
|
||||
var html;
|
||||
|
||||
if (content) {
|
||||
content = marked(content);
|
||||
html = marked(content);
|
||||
} else if (OPTIONS$1.sidebar) {
|
||||
content = tree(OPTIONS$1.sidebar, '<ul>');
|
||||
html = tree(OPTIONS$1.sidebar, '<ul>');
|
||||
} else {
|
||||
content = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
|
||||
isToc = true;
|
||||
html = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
|
||||
}
|
||||
|
||||
renderSidebar.rendered = true;
|
||||
if (CACHE.sidebar && CACHE.sidebar === content) { return }
|
||||
CACHE.sidebar = content;
|
||||
renderTo('aside.sidebar', content);
|
||||
if (isToc) { scrollActiveSidebar(); }
|
||||
renderTo('aside.sidebar', html);
|
||||
var target = activeLink('aside.sidebar', true);
|
||||
if (content) { renderSubSidebar(target); }
|
||||
toc = [];
|
||||
|
||||
scrollActiveSidebar();
|
||||
}
|
||||
|
||||
function renderSubSidebar (target) {
|
||||
if (!OPTIONS$1.subMaxLevel) { return }
|
||||
target.parentNode.innerHTML += tree(genTree(toc, OPTIONS$1.subMaxLevel), '<ul>');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2500,12 +2539,33 @@ function renderSidebar (content) {
|
||||
function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover');
|
||||
if (!content) {
|
||||
renderCover.dom.classList.add('hidden');
|
||||
} else {
|
||||
renderCover.dom.classList.remove('hidden');
|
||||
!renderCover.rendered && renderTo('.cover-main', marked(content));
|
||||
renderCover.rendered = true;
|
||||
renderCover.dom.classList.remove('show');
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show');
|
||||
if (renderCover.rendered) { return }
|
||||
|
||||
// render cover
|
||||
var html = marked(content);
|
||||
var match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$');
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
var coverEl = document.querySelector('section.cover');
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1];
|
||||
} else {
|
||||
coverEl.classList.add('has-mask');
|
||||
coverEl.style.backgroundImage = "url(" + (match[1]) + ")";
|
||||
}
|
||||
html = html.replace(match[0], '');
|
||||
}
|
||||
|
||||
renderTo('.cover-main', html);
|
||||
renderCover.rendered = true;
|
||||
|
||||
sticky();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2557,6 +2617,7 @@ var OPTIONS = {
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
subMaxLevel: 0,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
loadSidebar: null,
|
||||
@@ -2591,7 +2652,6 @@ var mainRender = function (cb) {
|
||||
var route = OPTIONS.basePath + getRoute();
|
||||
if (cacheRoute === route) { return cb() }
|
||||
|
||||
var wait;
|
||||
var basePath = cacheRoute = route;
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -2610,12 +2670,8 @@ var mainRender = function (cb) {
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage) {
|
||||
if (page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(renderCover);
|
||||
} else {
|
||||
renderCover();
|
||||
}
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(renderCover);
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort();
|
||||
@@ -2623,23 +2679,20 @@ var mainRender = function (cb) {
|
||||
cacheXhr = load(page, 'GET', renderLoading);
|
||||
cacheXhr.then(function (result) {
|
||||
renderArticle(result);
|
||||
// clear cover
|
||||
if (OPTIONS.coverpage && page !== OPTIONS.homepage) { renderCover(); }
|
||||
// render sidebar
|
||||
if (OPTIONS.loadSidebar) {
|
||||
if (wait === false) { cb(); }
|
||||
wait = false;
|
||||
load(basePath + OPTIONS.loadSidebar)
|
||||
.then(function (result) {
|
||||
renderSidebar(result);
|
||||
cb();
|
||||
});
|
||||
} 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);
|
||||
@@ -2650,11 +2703,7 @@ var Docsify = function () {
|
||||
var dom = document.querySelector(OPTIONS.el) || document.body;
|
||||
var replace = dom !== document.body;
|
||||
var main = function () {
|
||||
mainRender(function (_) {
|
||||
activeLink('aside.sidebar', true);
|
||||
scrollIntoView();
|
||||
OPTIONS.coverpage && sticky();
|
||||
});
|
||||
mainRender(function (_) { return scrollIntoView(); });
|
||||
};
|
||||
|
||||
// Render app
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docsify",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.1",
|
||||
"description": "A magical documentation generator.",
|
||||
"main": "lib/docsify.js",
|
||||
"files": [
|
||||
|
||||
+21
-12
@@ -16,7 +16,10 @@ export function scrollActiveSidebar () {
|
||||
const li = lis[i]
|
||||
let href = li.querySelector('a').getAttribute('href')
|
||||
|
||||
if (href !== '/') href = href.match(/#([^#]+)$/g)[0].slice(1)
|
||||
if (href !== '/') {
|
||||
const match = href.match('#([^#]+)$')
|
||||
if (match && match.length) href = match[0].slice(1)
|
||||
}
|
||||
|
||||
nav[decodeURIComponent(href)] = li
|
||||
}
|
||||
@@ -61,18 +64,24 @@ export function activeLink (dom, activeParent) {
|
||||
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
|
||||
if (!dom) return
|
||||
let target
|
||||
|
||||
;[].slice.call(dom.querySelectorAll('a')).forEach(node => {
|
||||
if (node.href === host) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active')
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class')
|
||||
}
|
||||
})
|
||||
;[].slice.call(dom.querySelectorAll('a'))
|
||||
.sort((a, b) => b.href.length - a.href.length)
|
||||
.forEach(node => {
|
||||
if (host.indexOf(node.href) === 0 && !target) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active')
|
||||
target = node
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class')
|
||||
}
|
||||
})
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-24
@@ -1,11 +1,12 @@
|
||||
import { load, camel2kebab, isNil, getRoute } from './util'
|
||||
import { activeLink, scrollIntoView, sticky } from './event'
|
||||
import { scrollIntoView } from './event'
|
||||
import * as render from './render'
|
||||
|
||||
const OPTIONS = {
|
||||
el: '#app',
|
||||
repo: '',
|
||||
maxLevel: 6,
|
||||
subMaxLevel: 0,
|
||||
sidebar: '',
|
||||
sidebarToggle: false,
|
||||
loadSidebar: null,
|
||||
@@ -40,7 +41,6 @@ const mainRender = function (cb) {
|
||||
const route = OPTIONS.basePath + getRoute()
|
||||
if (cacheRoute === route) return cb()
|
||||
|
||||
let wait
|
||||
let basePath = cacheRoute = route
|
||||
|
||||
if (!/\//.test(basePath)) {
|
||||
@@ -59,12 +59,8 @@ const mainRender = function (cb) {
|
||||
}
|
||||
|
||||
// Render Cover page
|
||||
if (OPTIONS.coverpage) {
|
||||
if (page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(render.renderCover)
|
||||
} else {
|
||||
render.renderCover()
|
||||
}
|
||||
if (OPTIONS.coverpage && page === OPTIONS.homepage) {
|
||||
load(OPTIONS.coverpage).then(render.renderCover)
|
||||
}
|
||||
|
||||
cacheXhr && cacheXhr.abort && cacheXhr.abort()
|
||||
@@ -72,23 +68,20 @@ const mainRender = function (cb) {
|
||||
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
|
||||
load(basePath + OPTIONS.loadSidebar)
|
||||
.then(result => {
|
||||
render.renderSidebar(result)
|
||||
cb()
|
||||
})
|
||||
} 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)
|
||||
@@ -99,11 +92,7 @@ const Docsify = function () {
|
||||
const dom = document.querySelector(OPTIONS.el) || document.body
|
||||
const replace = dom !== document.body
|
||||
const main = function () {
|
||||
mainRender(_ => {
|
||||
activeLink('aside.sidebar', true)
|
||||
scrollIntoView()
|
||||
OPTIONS.coverpage && sticky()
|
||||
})
|
||||
mainRender(_ => scrollIntoView())
|
||||
}
|
||||
|
||||
// Render app
|
||||
|
||||
+49
-25
@@ -2,7 +2,7 @@ import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import * as tpl from './tpl'
|
||||
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top, sticky } from './event'
|
||||
import { genTree, getRoute, isMobile } from './util'
|
||||
import { genTree, getRoute, isMobile, slugify } from './util'
|
||||
|
||||
let OPTIONS = {}
|
||||
const CACHE = {}
|
||||
@@ -21,9 +21,7 @@ const renderer = new marked.Renderer()
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = text.toLowerCase()
|
||||
.replace(/<(?:.|\n)*?>/gm, '')
|
||||
.replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
|
||||
const slug = slugify(text)
|
||||
let route = ''
|
||||
|
||||
if (OPTIONS.router) {
|
||||
@@ -37,12 +35,13 @@ renderer.heading = function (text, level) {
|
||||
// highlight code
|
||||
renderer.code = function (code, lang = '') {
|
||||
const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup)
|
||||
.replace(/{{/g, '<span>{{</span>')
|
||||
|
||||
return `<pre data-lang="${lang}"><code class="lang-${lang}">${hl}</code></pre>`
|
||||
}
|
||||
renderer.link = function (href, title, text) {
|
||||
if (OPTIONS.router && !/^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(href)) {
|
||||
href = !/^\/#/.test(href) ? `#/${getRoute()}${href}` : href
|
||||
href = `#/${href}`.replace(/\/\//g, '/')
|
||||
}
|
||||
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
@@ -77,11 +76,12 @@ export function renderApp (dom, replace) {
|
||||
*/
|
||||
export function renderArticle (content) {
|
||||
renderTo('article', content ? marked(content) : 'not found')
|
||||
if (!renderSidebar.rendered) renderSidebar(null, OPTIONS)
|
||||
if (!renderNavbar.rendered) renderNavbar(null, OPTIONS)
|
||||
renderSidebar.rendered = false
|
||||
renderNavbar.rendered = false
|
||||
if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
|
||||
|
||||
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
|
||||
const vm = new Vue({ el: 'main' }) // eslint-disable-line
|
||||
vm.$nextTick(_ => scrollActiveSidebar())
|
||||
}
|
||||
if (OPTIONS.auto2top) scroll2Top()
|
||||
}
|
||||
|
||||
@@ -91,7 +91,6 @@ export function renderArticle (content) {
|
||||
export function renderNavbar (content) {
|
||||
if (CACHE.navbar && CACHE.navbar === content) return
|
||||
CACHE.navbar = content
|
||||
renderNavbar.rendered = true
|
||||
|
||||
if (content) renderTo('nav', marked(content))
|
||||
activeLink('nav')
|
||||
@@ -101,23 +100,27 @@ export function renderNavbar (content) {
|
||||
* sidebar
|
||||
*/
|
||||
export function renderSidebar (content) {
|
||||
let isToc = false
|
||||
let html
|
||||
|
||||
if (content) {
|
||||
content = marked(content)
|
||||
html = marked(content)
|
||||
} else if (OPTIONS.sidebar) {
|
||||
content = tpl.tree(OPTIONS.sidebar, '<ul>')
|
||||
html = tpl.tree(OPTIONS.sidebar, '<ul>')
|
||||
} else {
|
||||
content = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
||||
isToc = true
|
||||
html = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
|
||||
}
|
||||
|
||||
renderSidebar.rendered = true
|
||||
if (CACHE.sidebar && CACHE.sidebar === content) return
|
||||
CACHE.sidebar = content
|
||||
renderTo('aside.sidebar', content)
|
||||
if (isToc) scrollActiveSidebar()
|
||||
renderTo('aside.sidebar', html)
|
||||
const target = activeLink('aside.sidebar', true)
|
||||
if (content) renderSubSidebar(target)
|
||||
toc = []
|
||||
|
||||
scrollActiveSidebar()
|
||||
}
|
||||
|
||||
export function renderSubSidebar (target) {
|
||||
if (!OPTIONS.subMaxLevel) return
|
||||
target.parentNode.innerHTML += tpl.tree(genTree(toc, OPTIONS.subMaxLevel), '<ul>')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,12 +129,33 @@ export function renderSidebar (content) {
|
||||
export function renderCover (content) {
|
||||
renderCover.dom = renderCover.dom || document.querySelector('section.cover')
|
||||
if (!content) {
|
||||
renderCover.dom.classList.add('hidden')
|
||||
} else {
|
||||
renderCover.dom.classList.remove('hidden')
|
||||
!renderCover.rendered && renderTo('.cover-main', marked(content))
|
||||
renderCover.rendered = true
|
||||
renderCover.dom.classList.remove('show')
|
||||
return
|
||||
}
|
||||
renderCover.dom.classList.add('show')
|
||||
if (renderCover.rendered) return
|
||||
|
||||
// render cover
|
||||
let html = marked(content)
|
||||
const match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$')
|
||||
|
||||
// render background
|
||||
if (match) {
|
||||
const coverEl = document.querySelector('section.cover')
|
||||
|
||||
if (match[2] === 'color') {
|
||||
coverEl.style.background = match[1]
|
||||
} else {
|
||||
coverEl.classList.add('has-mask')
|
||||
coverEl.style.backgroundImage = `url(${match[1]})`
|
||||
}
|
||||
html = html.replace(match[0], '')
|
||||
}
|
||||
|
||||
renderTo('.cover-main', html)
|
||||
renderCover.rendered = true
|
||||
|
||||
sticky()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
section.cover {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
display: none;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
&.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.has-mask .mask {
|
||||
position: absolute;
|
||||
size: 100%;
|
||||
background-color: $color-bg;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.cover-main {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
margin: 0 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
@@ -95,7 +95,7 @@ nav {
|
||||
display: inline-block;
|
||||
|
||||
ul {
|
||||
background-color: rgba(#fff, .6);
|
||||
background-color: rgba($color-bg, .6);
|
||||
border: 1px solid $color-primary;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
@@ -150,7 +150,7 @@ nav {
|
||||
}
|
||||
|
||||
svg {
|
||||
color: #fff;
|
||||
color: $color-bg;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
fill: $color-primary;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
|
||||
|
||||
$color-primary: #0074D9;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 16em;
|
||||
|
||||
@import "basic/layout";
|
||||
@@ -12,7 +13,7 @@ body {
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
$color-primary: #000;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 300px;
|
||||
@import "basic/layout";
|
||||
|
||||
+3
-2
@@ -1,20 +1,21 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
|
||||
|
||||
$color-primary: #42b983;
|
||||
$color-bg: #fff;
|
||||
$sidebar-width: 300px;
|
||||
|
||||
@import "basic/layout";
|
||||
@import "basic/coverpage";
|
||||
|
||||
body {
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
.sidebar {
|
||||
color: #364149;
|
||||
background-color: #fff;
|
||||
background-color: $color-bg;
|
||||
|
||||
li {
|
||||
margin: 6px 15px;
|
||||
|
||||
@@ -41,6 +41,7 @@ export function cover () {
|
||||
|
||||
return `<section class="cover" style="background: ${bgc}">
|
||||
<div class="cover-main"></div>
|
||||
<div class="mask"></div>
|
||||
</section>`
|
||||
}
|
||||
|
||||
|
||||
+28
@@ -106,3 +106,31 @@ export function isMobile () {
|
||||
return document.body.clientWidth <= 600
|
||||
}
|
||||
|
||||
export function slugify (string) {
|
||||
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g
|
||||
const maintainCase = false
|
||||
const replacement = '-'
|
||||
slugify.occurrences = slugify.occurrences || {}
|
||||
|
||||
if (typeof string !== 'string') return ''
|
||||
if (!maintainCase) string = string.toLowerCase()
|
||||
|
||||
let slug = string.trim()
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, replacement)
|
||||
let occurrences = slugify.occurrences[slug]
|
||||
|
||||
if (slugify.occurrences.hasOwnProperty(slug)) {
|
||||
occurrences++
|
||||
} else {
|
||||
occurrences = 0
|
||||
}
|
||||
|
||||
slugify.occurrences[slug] = occurrences
|
||||
|
||||
if (occurrences) {
|
||||
slug = slug + '-' + occurrences
|
||||
}
|
||||
|
||||
return slug
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user