Compare commits

..
45 Commits
Author SHA1 Message Date
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
22 changed files with 4273 additions and 315 deletions
-1
View File
@@ -1,5 +1,4 @@
.DS_Store
*.log
node_modules
yarn.lock
/themes
+36
View File
@@ -1,3 +1,39 @@
## 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.
+13 -2
View File
@@ -19,7 +19,7 @@
- [CLI](https://github.com/QingWei-Li/docsify-cli)
## Features
- Simple and lightweight (~12kb gzipped)
- Simple and lightweight (~13kB gzipped)
- Multiple themes
- Not build static html files
@@ -51,6 +51,8 @@ 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.
- [puck](https://puck.zz173.com/) - A small & magical php framework.
- [Samaritan](http://samaritan.stockdb.org) - An Algorithmic Trading Framework for Digital Currency.
## Similar projects
- [docute](https://github.com/egoist/docute) - 📜 Effortlessly documentation done right
@@ -67,11 +69,20 @@ These open-source projects are using docsify to generate their sites. Pull reque
## Development
```shell
### 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
+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>
+189 -33
View File
@@ -2,7 +2,7 @@
### Create a project
First create a project, then create a `docs` folder
```shell
```bash
mkdir my-project && cd my-project
mkdir docs && cd docs
```
@@ -26,14 +26,14 @@ Create a `index.html` file
Create `README.md` as the main page
```
```markdown
# Title
## 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
@@ -41,26 +41,30 @@ Push and open the **GitHub Pages** feature
Easy to setup and preview a docs.
### Install
```shell
```bash
npm i docsify-cli -g
```
### Setup
Setup a boilerplate docs
```shell
```bash
docsify init docs
```
### Preview
Preview and serve your docs using
```shell
```bash
docsify serve docs
```
Read more [docsify-cli](https://github.com/QingWei-Li/docsify-cli)
## Themes
## More
### Themes
Currently available `vue.css` and `buble.css`
```html
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
@@ -74,8 +78,6 @@ 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`.
@@ -96,7 +98,7 @@ Code in `index.html`
### Cover Page
Generate a cover page through with markdown. Create a `_coverpage.md` and set `data-coverpage` in script tag.
Generate a cover page with markdown. Create a `_coverpage.md` and set `data-coverpage` in the script tag.
```markdown
![logo](_media/icon.svg)
@@ -115,7 +117,7 @@ Generate a cover page through with markdown. Create a `_coverpage.md` and set `d
```
#### Custom background
Currently the background of cover page is generated randomly. We can customize the background, just using the syntax to add image.
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>
@@ -131,31 +133,95 @@ Currently the background of cover page is generated randomly. We can customize t
![color](#f0f0f0)
```
### Markdown parser
### Options
Docsify uses [marked](https://github.com/chjj/marked) to parse markdown. We can configure it
#### repo
```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**
## 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
```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
@@ -163,7 +229,13 @@ Sidebar with toggle
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
```js
window.$docsify = {
sidebarToggle: true
}
```
### sidebar
Custom sidebar. If it's set, the TOC will be disabled. Bind global variables on the `data-sidebar`.
@@ -187,9 +259,15 @@ Custom sidebar. If it's set, the TOC will be disabled. Bind global variables on
```
#### 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 as a 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
@@ -202,6 +280,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
@@ -211,14 +295,9 @@ 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)
```
#### sub-max-level
### sub-max-level
Display TOC in the custom sidebar. The default value is 0.
@@ -227,10 +306,14 @@ Display TOC in the custom sidebar. The default value is 0.
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
```
![image](https://cloud.githubusercontent.com/assets/7565692/21563209/a8894512-ceba-11e6-80eb-fef00b80625c.png)
```js
window.$docsify = {
maxSubLevel: 4
}
```
#### load-navbar
### load-navbar
Load navbar markdown file. If it is configured, load the current directory `_navbar.md` by default.
@@ -244,6 +327,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
@@ -260,7 +349,7 @@ If you write a sub level list, it will generate a dropdown list.
- [chinese](/zh-cn)
```
#### router
### router
Hash router.
@@ -268,16 +357,32 @@ Hash router.
<script src="/lib/docsify.js" data-router></script>
```
#### auto2top
```js
window.$docsify = {
router: true
}
```
### auto2top
Scroll to the top on changing hash.
```html
<script src="/lib/docsify.js" data-auto2top></script>
<!-- Set offset top -->
<script src="/lib/docsify.js" data-auto2top="50"></script>
```
#### homepage
```js
window.$docsify = {
auto2top: true,
// auto2top: 50
}
```
### 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`):
@@ -288,7 +393,14 @@ Scroll to the top on changing hash.
```
#### basePath
```js
window.$docsify = {
homepage: true
}
```
### basePath
If your HTML entry file and the markdown files are in different directories, we can use:
@@ -300,7 +412,14 @@ If your HTML entry file and the markdown files are in different directories, we
```
#### coverpage
```js
window.$docsify = {
basePath: '/base/'
}
```
### coverpage
Generate cover page.
@@ -308,4 +427,41 @@ Generate cover page.
<script src="/lib/docsify.js" data-coverpage></script>
<!-- or -->
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
```
```
```js
window.$docsify = {
coverpage: true
}
```
### name
Project name. It is displayed in the sidebar.
```html
<script src="/lib/docsify.js" data-name="docsify"></script>
```
```js
window.$docsify = {
name: 'docsify'
}
```
### nameLink
Name link. The default value is `window.location.pathname`.
```html
<script src="/lib/docsify.js" data-name-link="/"></script>
```
```js
window.$docsify = {
nameLink: '/'
}
```
+2 -2
View File
@@ -1,10 +1,10 @@
![logo](_media/icon.svg)
# docsify <small>1.4.2</small>
# docsify <small>1.7.0</small>
> A magical documentation site generator.
- Simple and lightweight (~12kb gzipped)
- Simple and lightweight (~13kB gzipped)
- Multiple themes
- Not build static html files
+5 -2
View File
@@ -6,7 +6,7 @@
<link rel="icon" href="favicon.ico">
<meta name="description" content="A magical documentation generator.">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="/lib/themes/vue.css">
</head>
<body>
<nav>
@@ -16,9 +16,12 @@
<div id="app"></div>
</body>
<script
src="//unpkg.com/docsify/lib/docsify.min.js"
src="/lib/docsify.min.js"
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>
+181 -28
View File
@@ -8,7 +8,7 @@
### 创建项目
新建一个空项目,接着创建一个 `docs` 目录并进入到 docs 目录下
```shell
```bash
mkdir my-project && cd my-project
mkdir docs && cd docs
```
@@ -46,26 +46,29 @@ 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,直接修改 `index.html` 里的 cdn 地址即可
```html
<link rel="stylesheet" href="//unpkg.com/docsify/themes/vue.css">
@@ -79,8 +82,6 @@ docsify serve docs
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
```
## 更多功能
### 多页面
`README.md` 作为主页面,如果需要其他页面,直接在文档目录下创建对应的 `*.md` 文件,例如创建一个 `guide.md` 那么对应的路由就是 `/#/guide`
@@ -138,30 +139,95 @@ docsify serve docs
![color](#f0f0f0)
```
### 自定义 Markdown parser
### 配置参数
默认使用 [marked](https://github.com/chjj/marked) 处理 markdown 部分,你可以修改默认配置
#### repo
```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>
```
效果
! 适合显示醒目的内容
## 配置参数
你可以通过在标签上添加属性的方式,或者给 `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 开关按钮
@@ -169,7 +235,14 @@ Sidebar 开关按钮
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
```js
window.$docsify = {
sidebarToggle: true
}
```
### sidebar
设置后 TOC 功能将不可用,适合导航较多的文档,`data-sidebar` 传入全局变量名。
@@ -192,7 +265,14 @@ 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 忽略下划线开头的文件。**
@@ -201,12 +281,19 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-load-sidebar></script>
```
你可以指定侧边栏文件名
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
```js
window.$docsify = {
loadSidebar: '_sidebar.md'
}
```
`_sidebar.md` 的内容可以是这样的
```markdown
@@ -216,14 +303,9 @@ 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)
```
#### sub-max-level
### sub-max-level
显示 TOC 在自定义的侧边栏里,默认最大显示 0 层。
@@ -232,10 +314,13 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-load-sidebar data-max-sub-level="4"></script>
```
![image](https://cloud.githubusercontent.com/assets/7565692/21563209/a8894512-ceba-11e6-80eb-fef00b80625c.png)
```js
window.$docsify = {
maxSubLevel: 4
}
```
#### load-navbar
### load-navbar
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
@@ -249,6 +334,12 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
```js
window.$docsify = {
loadNavbar: '_navbar.md'
}
```
`_navbar.md` 的内容可以是这样
```markdown
@@ -265,7 +356,7 @@ Sidebar 开关按钮
```
#### router
### router
开启 hash router 功能,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
@@ -273,7 +364,13 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-router></script>
```
#### auto2top
```js
window.$docsify = {
router: true
}
```
### auto2top
切换路由时自动跳转到页面顶部
@@ -282,7 +379,13 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-auto2top></script>
```
#### homepage
```js
window.$docsify = {
auto2top: true
}
```
### homepage
默认情况下网站会将根目录下 `README.md` 作为首页渲染,但是有些时候我们想指定其他文件,甚至想直接将 repo 下的 README 作为首页。你可以这样做(需要设置 `data-router`):
@@ -293,7 +396,13 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-homepage="Welcome.md"></script>
```
#### basePath
```js
window.$docsify = {
homepage: true
}
```
### basePath
指定加载文档的路径,如果你的 HTML 入口文件和文档是放在不同地方,你可以设置:
@@ -304,7 +413,14 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-base-path="https://docsify.js.org/"></script>
```
#### coverpage
```js
window.$docsify = {
basePath: '/base/'
}
```
### coverpage
生成封面,参考 [#封面](/zh-cn#封面).
@@ -314,3 +430,40 @@ Sidebar 开关按钮
<script src="/lib/docsify.js" data-coverpage="other.md"></script>
```
```js
window.$docsify = {
coverpage: true
}
```
### name
项目名,将显示在侧边栏。
```html
<script src="/lib/docsify.js" data-name="docsify"></script>
```
```js
window.$docsify = {
name: 'docsify'
}
```
### nameLink
项目名链接,默认为 `window.location.pathname`
```html
<script src="/lib/docsify.js" data-name-link="/"></script>
```
```js
window.$docsify = {
nameLink: '/'
}
```
+200 -126
View File
@@ -118,14 +118,18 @@ 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(/\s/g, replacement)
.replace(/-+/g, replacement)
.replace(/^(\d)/, '_$1');
var occurrences = slugify.occurrences[slug];
if (slugify.occurrences.hasOwnProperty(slug)) {
@@ -143,6 +147,27 @@ function slugify (string) {
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
};
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
@@ -150,10 +175,12 @@ function slugify (string) {
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];
@@ -168,27 +195,34 @@ function scrollActiveSidebar () {
}
function highlight () {
var top = document.body.scrollTop;
var last;
for (var i = 0, len = anchors.length; i < len; i += 1) {
var node = anchors[i];
var bcr = node.getBoundingClientRect();
if (bcr.top < 10 && bcr.bottom > 10) {
var li = nav[node.getAttribute('data-id')];
if (!li || li === active) { return }
if (active) { active.setAttribute('class', ''); }
li.setAttribute('class', 'active');
active = li;
return
if (node.offsetTop > top) {
if (!last) { last = node; }
break
} else {
last = node;
}
}
if (!last) { return }
var li = nav[last.getAttribute('data-id')];
if (!li || li === active) { return }
if (active) { active.classList.remove('active'); }
li.classList.add('active');
active = li;
!hoveredOverSidebar && !sticky.noSticky && active.scrollIntoView(false);
}
window.removeEventListener('scroll', highlight);
window.addEventListener('scroll', highlight);
highlight();
sidebar.addEventListener('mouseover', function () { hoveredOverSidebar = true; });
sidebar.addEventListener('mouseleave', function () { hoveredOverSidebar = false; });
}
function scrollIntoView () {
@@ -196,7 +230,9 @@ function scrollIntoView () {
if (!id || !id.length) { return }
var section = document.querySelector(decodeURIComponent(id[0]));
if (section) { section.scrollIntoView(); }
if (section) { setTimeout(function () { return section.scrollIntoView(); }, 0); }
return section
}
/**
@@ -212,13 +248,13 @@ function activeLink (dom, activeParent) {
.forEach(function (node) {
if (host.indexOf(node.href) === 0 && !target) {
activeParent
? node.parentNode.setAttribute('class', 'active')
: node.setAttribute('class', 'active');
? node.parentNode.classList.add('active')
: node.classList.add('active');
target = node;
} else {
activeParent
? node.parentNode.removeAttribute('class')
: node.removeAttribute('class');
? node.parentNode.classList.remove('active')
: node.classList.remove('active');
}
});
@@ -236,24 +272,31 @@ function bindToggle (dom) {
dom.addEventListener('click', function () { return body.classList.toggle('close'); });
if (isMobile()) {
document.querySelector('aside')
.addEventListener('click', function (_) { return body.classList.toggle('close'); });
var sidebar = document.querySelector('aside.sidebar');
document.body.addEventListener('click', function (e) {
if (e.target !== dom && !dom.contains(e.target)) { body.classList.toggle('close'); }
if (sidebar.contains(e.target)) { setTimeout(function () { return activeLink(sidebar, true); }, 0); }
});
}
}
function scroll2Top () {
document.body.scrollTop = 0;
function scroll2Top (offset) {
if ( offset === void 0 ) offset = 0;
document.body.scrollTop = offset === true ? 0 : Number(offset);
}
function sticky () {
var dom = document.querySelector('section.cover');
var coverHeight = dom.getBoundingClientRect().height;
sticky.dom = sticky.dom || document.querySelector('section.cover');
var coverHeight = sticky.dom.getBoundingClientRect().height;
return (function () {
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
if (window.pageYOffset >= coverHeight || sticky.dom.classList.contains('hidden')) {
document.body.classList.add('sticky');
sticky.noSticky = false;
} else {
document.body.classList.remove('sticky');
sticky.noSticky = true;
}
})()
}
@@ -1556,12 +1599,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() {
@@ -1779,6 +1818,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;
}
@@ -1856,9 +1898,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];
@@ -1878,40 +1927,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) {
@@ -1980,7 +2027,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;
};
@@ -2016,13 +2063,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 + '>';
};
@@ -2055,7 +2100,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);
@@ -2067,7 +2116,7 @@ return _self.Prism;
})();
if (typeof module !== 'undefined' && module.exports) {
if ('object' !== 'undefined' && module.exports) {
module.exports = Prism;
}
@@ -2084,10 +2133,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,
@@ -2144,7 +2193,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,
@@ -2225,7 +2277,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', {
@@ -2411,50 +2464,71 @@ function tree (toc, tpl) {
}
var OPTIONS$1 = {};
var markdown = marked;
var toc = [];
var CACHE = {};
var TIP_RE = /^!\s/;
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 = slugify(text);
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)
.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 && !/:/.test(href)) {
href = ("#/" + href).replace(/\/\//g, '/');
}
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
};
renderer.paragraph = function (text) {
var isTip = TIP_RE.test(text);
return isTip ? ("<p class=\"tip\">" + (text.replace(TIP_RE, '')) + "</p>") : ("<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 + "#" + (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)
.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 && !/:/.test(href)) {
href = ("#/" + href).replace(/\/\//g, '/');
}
return ("<a href=\"" + href + "\" title=\"" + (title || '') + "\">" + text + "</a>")
};
marked.setOptions({ renderer: renderer });
}
/**
* App
@@ -2483,14 +2557,14 @@ function renderApp (dom, replace) {
* article
*/
function renderArticle (content) {
renderTo('article', content ? marked(content) : 'not found');
renderTo('article', content ? markdown(content) : 'not found');
if (!OPTIONS$1.sidebar && !OPTIONS$1.loadSidebar) { renderSidebar(); }
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
var vm = new Vue({ el: 'main' }); // eslint-disable-line
vm.$nextTick(function (_) { return scrollActiveSidebar(); });
}
if (OPTIONS$1.auto2top) { scroll2Top(); }
if (OPTIONS$1.auto2top) { setTimeout(function () { return scroll2Top(OPTIONS$1.auto2top); }, 0); }
}
/**
@@ -2500,7 +2574,7 @@ function renderNavbar (content) {
if (CACHE.navbar && CACHE.navbar === content) { return }
CACHE.navbar = content;
if (content) { renderTo('nav', marked(content)); }
if (content) { renderTo('nav', markdown(content)); }
activeLink('nav');
}
@@ -2511,16 +2585,19 @@ function renderSidebar (content) {
var html;
if (content) {
html = marked(content);
html = markdown(content);
// find url tag
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0];
} else if (OPTIONS$1.sidebar) {
html = tree(OPTIONS$1.sidebar, '<ul>');
} else {
html = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
}
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 (content) { renderSubSidebar(target); }
if (target) { renderSubSidebar(target); }
toc = [];
scrollActiveSidebar();
@@ -2541,18 +2618,18 @@ function renderCover (content) {
return
}
renderCover.dom.classList.add('show');
if (renderCover.rendered) { return }
if (renderCover.rendered) { return sticky() }
// render cover
var html = marked(content);
var match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$');
var html = markdown(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];
coverEl.style.background = match[1] + (match[3] || '');
} else {
coverEl.classList.add('has-mask');
coverEl.style.backgroundImage = "url(" + (match[1]) + ")";
@@ -2603,15 +2680,7 @@ function renderLoading (ref) {
}
}
/**
* Load Config
* @param {Object} options
*/
function config (options) {
OPTIONS$1 = options;
}
var OPTIONS = {
var OPTIONS = merge({
el: '#app',
repo: '',
maxLevel: 6,
@@ -2624,8 +2693,10 @@ var OPTIONS = {
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false
};
auto2top: false,
name: '',
nameLink: window.location.pathname
}, window.$docsify);
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
// load configuration for script attribute
@@ -2641,7 +2712,7 @@ if (script) {
}
// load options
config(OPTIONS);
init(OPTIONS);
var cacheRoute = null;
var cacheXhr = null;
@@ -2701,7 +2772,10 @@ var Docsify = function () {
var dom = document.querySelector(OPTIONS.el) || document.body;
var replace = dom !== document.body;
var main = function () {
mainRender(function (_) { return scrollIntoView(); });
mainRender(function (_) {
scrollIntoView();
activeLink('nav');
});
};
// Render app
+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
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "1.4.3",
"version": "1.7.0",
"description": "A magical documentation generator.",
"main": "lib/docsify.js",
"files": [
@@ -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"
+42 -26
View File
@@ -7,10 +7,12 @@ 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]
@@ -25,27 +27,34 @@ export function scrollActiveSidebar () {
}
function highlight () {
const top = document.body.scrollTop
let last
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i]
const bcr = node.getBoundingClientRect()
if (bcr.top < 10 && bcr.bottom > 10) {
const li = nav[node.getAttribute('data-id')]
if (!li || li === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
if (node.offsetTop > top) {
if (!last) last = node
break
} else {
last = node
}
}
if (!last) return
const li = nav[last.getAttribute('data-id')]
if (!li || li === active) return
if (active) active.classList.remove('active')
li.classList.add('active')
active = li
!hoveredOverSidebar && !sticky.noSticky && active.scrollIntoView(false)
}
window.removeEventListener('scroll', highlight)
window.addEventListener('scroll', highlight)
highlight()
sidebar.addEventListener('mouseover', () => { hoveredOverSidebar = true })
sidebar.addEventListener('mouseleave', () => { hoveredOverSidebar = false })
}
export function scrollIntoView () {
@@ -53,7 +62,9 @@ export function scrollIntoView () {
if (!id || !id.length) return
const section = document.querySelector(decodeURIComponent(id[0]))
if (section) section.scrollIntoView()
if (section) setTimeout(() => section.scrollIntoView(), 0)
return section
}
/**
@@ -71,13 +82,13 @@ export function activeLink (dom, activeParent) {
.forEach(node => {
if (host.indexOf(node.href) === 0 && !target) {
activeParent
? node.parentNode.setAttribute('class', 'active')
: node.setAttribute('class', 'active')
? node.parentNode.classList.add('active')
: node.classList.add('active')
target = node
} else {
activeParent
? node.parentNode.removeAttribute('class')
: node.removeAttribute('class')
? node.parentNode.classList.remove('active')
: node.classList.remove('active')
}
})
@@ -95,24 +106,29 @@ export function bindToggle (dom) {
dom.addEventListener('click', () => body.classList.toggle('close'))
if (isMobile()) {
document.querySelector('aside')
.addEventListener('click', _ => body.classList.toggle('close'))
const sidebar = document.querySelector('aside.sidebar')
document.body.addEventListener('click', e => {
if (e.target !== dom && !dom.contains(e.target)) body.classList.toggle('close')
if (sidebar.contains(e.target)) setTimeout(() => activeLink(sidebar, true), 0)
})
}
}
export function scroll2Top () {
document.body.scrollTop = 0
export function scroll2Top (offset = 0) {
document.body.scrollTop = offset === true ? 0 : Number(offset)
}
export function sticky () {
const dom = document.querySelector('section.cover')
const coverHeight = dom.getBoundingClientRect().height
sticky.dom = sticky.dom || document.querySelector('section.cover')
const coverHeight = sticky.dom.getBoundingClientRect().height
return (function () {
if (window.pageYOffset >= coverHeight || dom.classList.contains('hidden')) {
if (window.pageYOffset >= coverHeight || sticky.dom.classList.contains('hidden')) {
document.body.classList.add('sticky')
sticky.noSticky = false
} else {
document.body.classList.remove('sticky')
sticky.noSticky = true
}
})()
}
+12 -7
View File
@@ -1,8 +1,8 @@
import { load, camel2kebab, isNil, getRoute } from './util'
import { 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,
@@ -15,8 +15,10 @@ const OPTIONS = {
homepage: 'README.md',
coverpage: '',
basePath: '',
auto2top: false
}
auto2top: false,
name: '',
nameLink: window.location.pathname
}, window.$docsify)
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
// load configuration for script attribute
@@ -32,7 +34,7 @@ if (script) {
}
// load options
render.config(OPTIONS)
render.init(OPTIONS)
let cacheRoute = null
let cacheXhr = null
@@ -92,7 +94,10 @@ const Docsify = function () {
const dom = document.querySelector(OPTIONS.el) || document.body
const replace = dom !== document.body
const main = function () {
mainRender(_ => scrollIntoView())
mainRender(_ => {
scrollIntoView()
activeLink('nav')
})
}
// Render app
+68 -53
View File
@@ -1,52 +1,73 @@
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, slugify } from './util'
import * as event from './event'
import { genTree, getRoute, isMobile, slugify, merge } from './util'
let OPTIONS = {}
let markdown = marked
let toc = []
const CACHE = {}
const TIP_RE = /^!\s/
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 = slugify(text)
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)
.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 && !/:/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
}
return `<a href="${href}" title="${title || ''}">${text}</a>`
}
renderer.paragraph = function (text) {
const isTip = TIP_RE.test(text)
return isTip ? `<p class="tip">${text.replace(TIP_RE, '')}</p>` : `<p>${text}</p>`
}
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)
.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 && !/:/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
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>`
}
marked.setOptions({ renderer })
/**
* App
@@ -62,10 +83,10 @@ export function renderApp (dom, replace) {
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', sticky)
!isMobile() && window.addEventListener('scroll', event.sticky)
} else {
document.body.classList.add('sticky')
}
@@ -75,14 +96,14 @@ export function renderApp (dom, replace) {
* article
*/
export function renderArticle (content) {
renderTo('article', content ? marked(content) : 'not found')
renderTo('article', content ? markdown(content) : 'not found')
if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar()
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
const vm = new Vue({ el: 'main' }) // eslint-disable-line
vm.$nextTick(_ => scrollActiveSidebar())
vm.$nextTick(_ => event.scrollActiveSidebar())
}
if (OPTIONS.auto2top) scroll2Top()
if (OPTIONS.auto2top) setTimeout(() => event.scroll2Top(OPTIONS.auto2top), 0)
}
/**
@@ -92,8 +113,8 @@ export function renderNavbar (content) {
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')
}
/**
@@ -103,19 +124,22 @@ export function renderSidebar (content) {
let html
if (content) {
html = marked(content)
html = markdown(content)
// find url tag
html = html.match(/<ul[^>]*>([\s\S]+)<\/ul>/g)[0]
} else if (OPTIONS.sidebar) {
html = tpl.tree(OPTIONS.sidebar, '<ul>')
} else {
html = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
}
html = (OPTIONS.name ? `<h1><a href="${OPTIONS.nameLink}">${OPTIONS.name}</a></h1>` : '') + html
renderTo('aside.sidebar', html)
const target = activeLink('aside.sidebar', true)
if (content) renderSubSidebar(target)
const target = event.activeLink('aside.sidebar', true)
if (target) renderSubSidebar(target)
toc = []
scrollActiveSidebar()
event.scrollActiveSidebar()
}
export function renderSubSidebar (target) {
@@ -133,18 +157,18 @@ export function renderCover (content) {
return
}
renderCover.dom.classList.add('show')
if (renderCover.rendered) return
if (renderCover.rendered) return event.sticky()
// render cover
let html = marked(content)
const match = html.trim().match('<p><img[^s]+src="(.*?)"[^a]+alt="(.*?)"></p>$')
let html = markdown(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]
coverEl.style.background = match[1] + (match[3] || '')
} else {
coverEl.classList.add('has-mask')
coverEl.style.backgroundImage = `url(${match[1]})`
@@ -155,7 +179,7 @@ export function renderCover (content) {
renderTo('.cover-main', html)
renderCover.rendered = true
sticky()
event.sticky()
}
/**
@@ -190,12 +214,3 @@ export function renderLoading ({ loaded, total, step }) {
}, 200)
}
}
/**
* Load Config
* @param {Object} options
*/
export function config (options) {
OPTIONS = options
}
+58 -1
View File
@@ -96,6 +96,7 @@ nav {
display: inline-block;
ul {
border-radius: 2px;
background-color: rgba($color-bg, .6);
border: 1px solid $color-primary;
opacity: 0;
@@ -160,6 +161,7 @@ nav {
/* main */
main {
display: block;
size: 100vw 100%;
position: relative;
}
@@ -180,13 +182,34 @@ main {
/* sidebar */
.sidebar {
border-right: 1px solid rgba(0, 0, 0, .07);
overflow-y: auto;
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: $sidebar-width;
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;
@@ -291,6 +314,40 @@ body.sticky {
}
}
.markdown-section p.tip {
padding: 12px 24px 12px 30px;
margin: 2em 0;
border-left: 4px solid #f66;
background-color: #f8f8f8;
position: relative;
border-bottom-right-radius: 2px;
border-top-right-radius: 2px;
&:before {
position: absolute;
top: 14px;
left: -12px;
background-color: #f66;
color: $color-bg;
content: "!";
size: 20px;
border-radius: 100%;
text-align: center;
line-height: 20px;
font-weight: bold;
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
}
code {
background-color: #efefef;
}
em {
color: $color-text;
}
}
body.close {
.sidebar {
transform: translateX(-$sidebar-width);
-12
View File
@@ -238,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;
}
-12
View File
@@ -285,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;
}
+23
View File
@@ -110,14 +110,18 @@ 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)) {
@@ -134,3 +138,22 @@ export function slugify (string) {
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
}
+3434
View File
File diff suppressed because it is too large Load Diff