Compare commits

...
68 Commits
Author SHA1 Message Date
qingwei.li aa1d84b513 1.1.1 2016-12-17 09:07:15 +08:00
qingwei.li 14a4c2f77d bump 1.1.1 2016-12-17 09:01:41 +08:00
qingwei.li e58c17fdc6 Optimize progress bar 2016-12-17 09:01:21 +08:00
qingwei.li 8b719238e6 -> v1.1.0 2016-12-16 22:38:53 +08:00
qingwei.li 7f0b1089c0 bump 1.1.0 2016-12-16 22:38:44 +08:00
cinwell.liandGitHub 2610e25040 Add progress bar and auto2top (#27)
* Add progress bar

* Add abort ajax

* Remove console

* Add cache folder

* Add auto2top
2016-12-16 22:37:21 +08:00
cinwell.li ec53f1e307 Add Beerpay's badge 2016-12-15 19:11:15 +08:00
qingwei.li 670cc68a28 -> v1.0.3 2016-12-13 22:27:36 +08:00
qingwei.li 844ba3e022 bump 1.0.3 2016-12-13 22:27:26 +08:00
qingwei.li 9092b22246 Fix cache sidebar content 2016-12-13 22:26:56 +08:00
qingwei.li d175ba6913 -> v1.0.2 2016-12-13 22:12:18 +08:00
qingwei.li 2574778605 bump 1.0.2 2016-12-13 22:11:50 +08:00
cinwell.liandGitHub 44a255103c Fix/1.0.2 (#25)
* Fix regular expression, fixed #23

* Fix repeat binding events

* Add content cache

* Add changelog
2016-12-13 22:10:58 +08:00
qingwei.li 440635aeeb -> v1.0.1 2016-12-08 21:24:05 +08:00
qingwei.li a8cc8e46cd bump 1.0.1 2016-12-08 21:23:38 +08:00
qingwei.li 626227be4d Update changelog 2016-12-08 21:22:33 +08:00
qingwei.li c4f02027a8 Fix img style 2016-12-08 21:20:37 +08:00
qingwei.li 8f3eb17dbf Update doc 2016-12-08 21:18:01 +08:00
qingwei.li 61d2474202 -> v1.0.0 2016-12-08 21:13:04 +08:00
qingwei.li 41be8176a6 bump 1.0.0 2016-12-08 21:12:33 +08:00
cinwell.liandGitHub 864935bfc1 1.0 features (#21)
* feat: hash routing, close #2

* Fix router bug

* Remove console

* Add hash router docs

* Improved scrolling on mobile

* Add change log

* Use hash router
2016-12-08 21:11:18 +08:00
qingwei.li b977715d42 Add Snipaste into showcase 2016-12-01 10:18:00 +08:00
qingwei.li 84871ca09e -> v0.7.0 2016-11-30 21:55:46 +08:00
qingwei.li 200dcf61ce bump 0.7.0 2016-11-30 21:53:16 +08:00
qingwei.li 816b6e2035 fix vue.css headling 2016-11-30 21:42:06 +08:00
qingwei.li e4a35d9dcf Add changelog 2016-11-30 21:35:14 +08:00
cinwell.liandGitHub 02a0adb872 0.7.0 (#16)
* add ignore

* Use postcss

* delete themes/

* fix build script

* fix css, fixed #15, fixed #13

* Add changelog

* Fix horizontal scroll for code block, fixed #11

* Fix sidebar animation
2016-11-30 21:33:44 +08:00
qingwei.li e48518b42a -> v0.6.1 2016-11-29 23:11:24 +08:00
qingwei.li 4d56be2f10 bump 0.6.1 2016-11-29 23:11:12 +08:00
cinwell.liandGitHub 19bf043cf8 Fix sidebar animation (#14) 2016-11-29 23:09:59 +08:00
qingwei.li a74cf6ceaf -> v0.6.0 2016-11-29 21:43:39 +08:00
qingwei.li 0f966e2eb1 bump 0.6.0 2016-11-29 21:43:29 +08:00
cinwell.liandGitHub d07ddaa85d 0.6.0 (#12)
* Fix ineffective option, fixed #10

* Feat: dropdown list, #6

* Fix repo url

* Feat: sidebar with toggle

* Update doc
2016-11-29 21:42:48 +08:00
qingwei.li dd361b34b9 -> v0.5.0 2016-11-29 01:11:12 +08:00
qingwei.li 1a7c6c094c bump 0.5.0 2016-11-29 01:11:02 +08:00
cinwell.liandGitHub 35d3bd1647 customize sidebar and navbar via markdown file, #6 (#8)
* Refactor: use iife

* Feat: customize sidebar and navbar via markdown file, #6

* Add changelog
2016-11-29 01:07:47 +08:00
qingwei.li e09b6f218f fix url 2016-11-28 15:39:35 +08:00
qingwei.li 4d7772035f add showcase 2016-11-28 14:03:54 +08:00
qingwei.li 6540e7370d -> v0.4.2 2016-11-28 12:34:05 +08:00
qingwei.li f3853d8e7f bump 0.4.2 2016-11-28 12:33:54 +08:00
qingwei.li 93ddf08615 fix code error 2016-11-28 12:33:25 +08:00
qingwei.li 7c05d729b4 -> v0.4.1 2016-11-28 12:24:14 +08:00
qingwei.li 5953ef7739 bump 0.4.1 2016-11-28 12:23:43 +08:00
qingwei.li d556282471 add docsify.js.org
fix cdn
2016-11-28 12:22:47 +08:00
qingwei.li ec58149aad add catch ajax error 2016-11-28 12:17:57 +08:00
qingwei.li e15c53a6b8 fix site
remove cname

remove cdn

remove cdn
2016-11-28 12:14:24 +08:00
qingwei.li f450b118ee use docsify.js.org 2016-11-28 11:27:28 +08:00
qingwei.li 6ac7d4f66f Add changelog 2016-11-27 19:06:14 +08:00
qingwei.li 17806def5a -> v0.4.0 2016-11-27 18:57:06 +08:00
qingwei.li ea03583d3d bump 0.4.0 2016-11-27 18:56:25 +08:00
cinwell.liandGitHub 37e7984e7e feat: custom sidebar, #4 (#5)
* feat: custom sidebar, #4

* fix dev html

* fix doc

* fix doc
2016-11-27 18:53:31 +08:00
qingwei.li fc2e5b6fb9 fix undefined language 2016-11-27 15:24:07 +08:00
qingwei.li 94f00053d7 -> v0.3.1 2016-11-27 14:02:07 +08:00
qingwei.li 029f92e341 bump 0.3.1 2016-11-27 14:01:47 +08:00
qingwei.li 8041c82e6d Strip HTML tag when rendering the headling 2016-11-27 14:01:05 +08:00
qingwei.li 5e38b702cd -> v0.3.0 2016-11-27 13:36:18 +08:00
qingwei.li 136ef2881e bump 0.3.0 2016-11-27 13:35:31 +08:00
qingwei.li 50006d2ceb fix cdn path 2016-11-27 13:35:10 +08:00
qingwei.li 657ad7d59c Add minified css files 2016-11-27 13:30:40 +08:00
qingwei.li eba21726d7 Add max level option 2016-11-27 13:09:18 +08:00
qingwei.li e789fb2b18 -> v0.2.1 2016-11-26 21:08:34 +08:00
qingwei.li 6e4b9d4cad bump 0.2.1 2016-11-26 21:08:21 +08:00
qingwei.li 824e64ae48 Fix style 2016-11-26 21:07:47 +08:00
qingwei.li 4b961a9b69 -> v0.2.0 2016-11-26 18:52:48 +08:00
qingwei.li 2cf91da2f0 bump 2016-11-26 18:52:35 +08:00
qingwei.li 4f27fff283 Remove dynamic title 2016-11-26 18:51:44 +08:00
qingwei.li ff9e31f0c4 Add dev script 2016-11-26 18:37:17 +08:00
qingwei.li e8617a8af2 fix route 2016-11-26 18:13:39 +08:00
32 changed files with 1787 additions and 768 deletions
+1
View File
@@ -1,3 +1,4 @@
*.log
node_modules
yarn.lock
/themes
+3
View File
@@ -1,3 +1,6 @@
sudo: false
cache:
directories:
- $HOME/.yarn-cache
language: node_js
node_js: stable
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="/themes/vue.css">
</head>
<body class="">
<div id="app"></div>
</body>
<script src="/lib/docsify.js" data-repo="qingwei-li/docsify" data-auto2top data-sidebar-toggle data-router></script>
</html>
+92
View File
@@ -0,0 +1,92 @@
## 1.1.1
### Bug fixes
- Optimize progress bar
## 1.1.0
## Features
- Add progress bar
- Add `auto2top` option for hash router
## 1.0.3
### Bug fixes
- Fix cache
## 1.0.2
### Bug fixes
- Fix binding events bug, fixed #24
- Fix regular expression, fixed #23
## 1.0.1
### Bug fixes
- `img` style
## 1.0.0
## Features
- Support hash router
### Bug fixes
- Improved scrolling on mobile
## 0.7.0
### Breaking change
- `themes/` was removed, only exists in the npm package.
### Bug fixes
- Fix style.
- Fix sidebar animation again.
## 0.6.1
### Bug fixes
- In the mobile, it should collapse the sidebar when toggle is clicked.
- Fix the dropdown list style.
- Fix sidebar animation.
## 0.6.0
### Features
- Navbar support dropdown list, #6
- Sidebar with toggle
### Bug fixes
- Fix ineffective option, fixed #10
## 0.5.0
### Features
- Custom sidebars and navbars by markdown file
## 0.4.2
### Bug fixes
- Correct catch ajax error
## 0.4.1
### Bug fixes
- catch ajax error
## 0.4.0
### Features
- Custom sidebar
### Bug fixes
- Fix undefined language
## 0.3.1
### Bug fixes
- Strip HTML tag when rendering the headings
## 0.3.0
### Features
- Add minified css files
- Add max level option
- Add pure.css
## 0.2.1
### Bug fixes
- Fix vue.css
## 0.2.0
### Bug fixes
- Fix route
- Remove dynamic title
## 0.1.0
### Features
- Add buble.css
+35 -2
View File
@@ -5,7 +5,7 @@
>🃏 A magical documentation site generator.
## Links
- [Documentation](https://qingwei-li.github.io/docsify)
- [Documentation](https://docsify.js.org)
- [CLI](https://github.com/QingWei-Li/docsify-cli)
## Features
@@ -14,7 +14,7 @@
- No build
## Quick start
Create `404.html` and `README.md` into `/docs`.
Create a `404.html` and `README.md` into `/docs`.
404.html
@@ -30,5 +30,38 @@ Create `404.html` and `README.md` into `/docs`.
</html>
```
Or Create a `index.html` and using `hash router`.
index.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" data-router></script>
</html>
```
## Showcase
These open-source projects are using docsify to generate their sites. Pull requests welcome : )
- [docsify](https://docsify.js.org) - A magical documentation site generator.
- [Snipaste](https://docs.snipaste.com/) - A new way to boost your productivity.
## How to contribute
- Fork it!
- Run `npm i && npm run dev`
- open `localhost:3000`
## 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)
+12
View File
@@ -0,0 +1,12 @@
var serveStatic = require('serve-static')
var http = require('http')
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'))
})
}).listen(3000, '0.0.0.0')
console.log(`\nListening at http://0.0.0.0:3000\n`)
+38
View File
@@ -0,0 +1,38 @@
var fs = require('fs')
var cssnano = require('cssnano').process
var resolve = require('path').resolve
var postcss = require('postcss')
var processor = postcss([require('postcss-salad')])
var saveMin = function (file, content) {
fs.writeFileSync(resolve(__dirname, '../lib/themes/', file), content)
}
var save = function (file, content) {
fs.writeFileSync(resolve(__dirname, '../themes/', file), content)
}
var load = function (file) {
return fs.readFileSync(resolve(__dirname, '../src/themes/', file)).toString()
}
var loadLib = function (file) {
return fs.readFileSync(resolve(__dirname, '../themes/', file)).toString()
}
var list = fs.readdirSync(resolve(__dirname, '../src/themes'))
list.forEach(function (file) {
if (!/\.css$/.test(file)) return
processor.process(load(file), { from: resolve(__dirname, '../src/themes/', file) })
.then(function (result) {
save(file, result.css)
console.log('salad - ' + file)
cssnano(loadLib(file))
.then(function (result) {
saveMin(file, result.css)
console.log('cssnao - ' + file)
})
}).catch(function (err) {
console.log(err)
})
})
+6 -3
View File
@@ -15,20 +15,23 @@ var build = function (opts) {
console.log(dest)
bundle.write({
format: 'umd',
format: 'iife',
moduleName: opts.moduleName || 'Docsify',
dest: dest
})
})
.catch(function (err) {
console.error(err)
})
}
build({
entry: 'docsify.js',
entry: 'index.js',
output: 'docsify.js',
plugins: [commonjs(), nodeResolve()]
})
build({
entry: 'docsify.js',
entry: 'index.js',
output: 'docsify.min.js',
plugins: [commonjs(), nodeResolve(), uglify()]
})
-18
View File
@@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Docsify</title>
<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/themes/vue.css">
</head>
<body>
<nav>
<a href="/">En</a>
<a href="/zh-cn">中文</a>
</nav>
<div id="app"></div>
</body>
<script src="//unpkg.com/docsify" data-repo="qingwei-li/docsify"></script>
</html>
+1
View File
@@ -0,0 +1 @@
docsify.js.org
+138 -4
View File
@@ -76,6 +76,13 @@ Currently available `vue.css` and `buble.css`
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
```
Minified files
```html
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
```
## More
### Multiple pages
@@ -86,13 +93,140 @@ Code in `404.html`
```html
<nav>
<a href="/">En</a>
<a href="/zh-cn">中文</a>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
</nav>
```
### GitHub Corner
Modify your `404.html`
### Options
#### 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.
```html
<script src="//unpkg.com/docsify" data-max-level="6"></script>
```
#### el
Root element.
```html
<script src="//unpkg.com/docsify" data-el="#app"></script>
```
#### sidebar-toggle
Sidebar with toggle
```html
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
Custom sidebar. if it'set, the TOC will be disabeld. Bind global variables on the `data-sidebar`.
![image](https://cloud.githubusercontent.com/assets/7565692/20647425/de5ab1c2-b4ce-11e6-863a-135868f2f9b4.png)
```html
<script>
window.sidebar = [
{ slug: '/', title: 'Home' },
{
slug: '/pageA',
title: 'page A',
children: [
{ slug: '/pageA/childrenB', title: 'children B' }
]
},
{ slug: '/PageC', title: 'Page C' }
]
</script>
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
```
#### load-sidebar
Load sidebar markdown file. If it is configured, load the current directory `_sidebar.md` by default. If the file isn't exist, sidebar will appear TOC.
```html
<script src="/lib/docsify.js" data-load-sidebar></script>
```
You can specify a file:
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
The contents of the file can be:
```markdown
- [Home](/)
- [Installation](/installation)
- Essentials
- [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
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>
```
You can specify a file:
```html
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
The contents of the file can be:
```markdown
- [en](/)
- [chinese](/zh-cn)
```
If you write a sub level list, it will generate a dropdown list.
```markdown
- [download](/download)
- language
- [en](/)
- [chinese](/zh-cn)
```
### router
Hash router. You can replace `404.html` with `index.html`.
```html
<script src="/lib/docsify.js" data-router></script>
```
### auto2top
Scroll to the top on changing hash.
```html
<script src="/lib/docsify.js" data-auto2top></script>
```
+23
View File
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>docsify - A magical documentation site generator.</title>
<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">
</head>
<body>
<nav>
<a href="#/">En</a>
<a href="#/zh-cn">中文</a>
</nav>
<div id="app"></div>
</body>
<script
src="//unpkg.com/docsify/lib/docsify.min.js"
data-repo="qingwei-li/docsify"
data-max-level="3"
data-sidebar-toggle
data-router></script>
</html>
+136 -3
View File
@@ -75,6 +75,13 @@ docsify serve docs
<link rel="stylesheet" href="//unpkg.com/docsify/themes/buble.css">
```
压缩版
```html
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/buble.css">
```
## 更多功能
### 多页面
@@ -85,16 +92,142 @@ docsify serve docs
```html
<nav>
<a href="/">En</a>
<a href="/zh-cn">中文</a>
<a href="/docsify/">En</a>
<a href="/docsify/zh-cn">中文</a>
</nav>
```
### GitHub Corner
### CDN
目前可用的 CDN 有 [UNPKG](unpkg.com/docsify),如果觉得访问较慢可以将文件放到 Pages 的目录下。
### 配置参数
#### repo
参考本文档的右上角的 GitHub 图标,如果要开启的话,将 `404.html` 里的 script 改成
```html
<script src="//unpkg.com/docsify" data-repo="your/repo"></script>
```
#### max-level
目录最大展开层级,默认值为 6
```html
<script src="//unpkg.com/docsify" data-max-level="6"></script>
```
#### el
替换节点元素,默认为 `#app`
```html
<script src="//unpkg.com/docsify" data-el="#app"></script>
```
#### sidebar-toggle
Sidebar 开关按钮
```html
<script src="//unpkg.com/docsify" data-sidebar-toggle></script>
```
#### sidebar
设置后 TOC 功能将不可用,适合导航较多的文档,`data-sidebar` 传入全局变量名。
![image](https://cloud.githubusercontent.com/assets/7565692/20647425/de5ab1c2-b4ce-11e6-863a-135868f2f9b4.png)
```html
<script>
window.sidebar = [
{ slug: '/', title: 'Home' },
{
slug: '/pageA',
title: 'page A',
children: [
{ slug: '/pageA/childrenB', title: 'children B' }
]
},
{ slug: '/PageC', title: 'Page C' }
]
</script>
<script src="/lib/docsify.js" data-sidebar="sidebar"></script>
```
#### load-sidebar
读取侧边栏配置文件,如果配置,默认加载当前目录下的 `_sidebar.md`。如果文件不存在,会显示 TOC 作为侧边栏内容。如果你有二级目录,也应该放置一份配置文件。
```html
<script src="/lib/docsify.js" data-load-sidebar></script>
```
你可以指定侧边栏文件名
```html
<script src="/lib/docsify.js" data-load-sidebar="_sidebar.md"></script>
```
`_sidebar.md` 的内容可以是这样的
```markdown
- [Home](/)
- [Installation](/installation)
- Essentials
- [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
读取导航配置文件,如果配置,默认加载当前目录下的 `_navbar.md`。如果文件不存在,会显示 html 里定义的导航栏。
```html
<script src="/lib/docsify.js" data-load-navbar></script>
```
你可以指定导航栏文件名
```html
<script src="/lib/docsify.js" data-load-navbar="_navbar.md"></script>
```
`_navbar.md` 的内容可以是这样
```markdown
- [en](/)
- [中文](/zh-cn)
```
当然也支持二级列表,将生成一个下拉列表
```markdown
- [download](/download)
- language
- [en](/)
- [中文](/zh-cn)
```
### router
开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。
```html
<script src="/lib/docsify.js" data-router></script>
```
### auto2top
切换路由时自动跳转到页面顶部
```html
<script src="/lib/docsify.js" data-auto2top></script>
```
+422 -156
View File
@@ -1,21 +1,207 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Docsify = factory());
}(this, (function () { 'use strict';
var Docsify = (function () {
'use strict';
var ajax = function (url, options) {
if ( options === void 0 ) options = {};
/**
* Simple ajax
* @param {String} url
* @param {String} [method=GET]
* @param {Function} [loading] handle loading
* @return {Promise}
*/
function load (url, method, loading) {
if ( method === void 0 ) method = 'GET';
var xhr = new XMLHttpRequest();
xhr.open(options.method || 'get', url);
xhr.open(method, url);
xhr.send();
return {
then: function (cb) { return xhr.addEventListener('load', cb); }
then: function (success, error) {
if ( error === void 0 ) error = function () {};
if (loading) {
xhr.addEventListener('progress', loading);
xhr.addEventListener('loaded', loading);
}
xhr.addEventListener('error', error);
xhr.addEventListener('load', function (ref) {
var target = ref.target;
target.status >= 400 ? error(target) : success(target.response);
});
},
abort: function () { return xhr.readyState !== 4 && xhr.abort(); }
}
};
}
/**
* gen toc tree
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
* @param {Array} toc
* @param {Number} maxLevel
* @return {Array}
*/
function genTree (toc, maxLevel) {
var headlines = [];
var last = {};
toc.forEach(function (headline) {
var level = headline.level || 1;
var len = level - 1;
if (level > maxLevel) { return }
if (last[len]) {
last[len].children = last[len].children || [];
last[len].children.push(headline);
} else {
headlines.push(headline);
}
last[level] = headline;
});
return headlines
}
/**
* camel to kebab
* @link https://github.com/bokuweb/kebab2camel/blob/master/index.js
* @param {String} str
* @return {String}
*/
function camel2kebab (str) {
return str.replace(/([A-Z])/g, function (m) { return '-' + m.toLowerCase(); })
}
/**
* is nil
* @param {Object} object
* @return {Boolean}
*/
function isNil (o) {
return o === null || o === undefined
}
var cacheRoute$1 = null;
var cacheHash = null;
/**
* hash route
*/
function getRoute () {
var loc = window.location;
if (cacheHash === loc.hash && !isNil(cacheRoute$1)) { return cacheRoute$1 }
var route = loc.hash.match(/^#\/([^#]+)/);
if (route && route.length === 2) {
route = route[1];
} else {
route = /^#\//.test(loc.hash) ? '' : loc.pathname;
}
cacheRoute$1 = route;
cacheHash = loc.hash;
return route
}
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
*/
function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) { return }
var anchors = document.querySelectorAll('.anchor');
var nav = {};
var lis = document.querySelectorAll('.sidebar li');
var active = null;
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); }
nav[href] = li;
}
function highlight () {
for (var i = 0, len = anchors.length; i < len; i += 1) {
var node = anchors[i].parentNode;
var bcr = node.getBoundingClientRect();
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
}
}
}
var dom = document.querySelector('main .content');
dom.removeEventListener('scroll', highlight);
dom.addEventListener('scroll', highlight);
highlight();
}
function scrollIntoView () {
var id = window.location.hash.match(/#[^#\/]+$/g);
if (!id || !id.length) { return }
var section = document.querySelector(id[0]);
if (section) { section.scrollIntoView(); }
}
/**
* Acitve link
*/
function activeLink (dom, activeParent) {
var host = window.location.href;
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
if (!dom) { return
; }[].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');
}
});
}
/**
* sidebar toggle
*/
function bindToggle (dom) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
if (!dom) { return }
var body = document.body;
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');
});
}
var cacheContentDOM;
function scroll2Top (dom) {
cacheContentDOM = cacheContentDOM || document.querySelector(dom);
cacheContentDOM.scrollTop = 0;
}
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -2112,50 +2298,61 @@ Prism.languages.js = Prism.languages.javascript;
});
/**
* @link from https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
* Render github corner
* @param {Object} data
* @return {String}
*/
var tocToTree = function (toc) {
var headlines = [];
var last = {};
function corner (data) {
if (!data) { return '' }
if (!/\/\//.test(data)) { data = 'https://github.com/' + data; }
data = data.replace(/^git\+/, '');
toc.forEach(function (headline) {
var level = headline.level || 1;
var len = level - 1;
return ("\n <a href=\"" + data + "\" class=\"github-corner\" aria-label=\"View source on Github\">\n <svg viewBox=\"0 0 250 250\" aria-hidden=\"true\">\n <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n <path d=\"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2\" fill=\"currentColor\" style=\"transform-origin: 130px 106px;\" class=\"octo-arm\"></path>\n <path d=\"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z\" fill=\"currentColor\" class=\"octo-body\"></path>\n </svg>\n </a>")
}
if (last[len]) {
last[len].children = last[len].children || [];
last[len].children.push(headline);
} else {
headlines.push(headline);
}
last[level] = headline;
});
/**
* 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>"
}
return headlines
};
function toggle (bool) {
if (!bool) { return '' }
return "<button class=\"sidebar-toggle\">\n <span></span><span></span><span></span>\n </button>"
}
var buildHeadlinesTree = function (tree, tpl) {
/**
* Render tree
* @param {Array} tree
* @param {String} tpl
* @return {String}
*/
function tree (toc, tpl) {
if ( tpl === void 0 ) tpl = '';
if (!tree || !tree.length) { return '' }
if (!toc || !toc.length) { return '' }
tree.forEach(function (node) {
tpl += "<li><a class=\"section-link\" href=\"#" + (node.slug) + "\">" + (node.title) + "</a></li>";
toc.forEach(function (node) {
tpl += "<li><a class=\"section-link\" href=\"" + (node.slug) + "\">" + (node.title) + "</a></li>";
if (node.children) {
tpl += "<li><ul class=\"children\">" + (buildHeadlinesTree(node.children)) + "</li></ul>";
tpl += "<li><ul class=\"children\">" + (tree(node.children)) + "</li></ul>";
}
});
return tpl
};
}
var genToc = function (toc) {
var tree = tocToTree(toc);
var result = buildHeadlinesTree(tree, '<ul>');
return result
};
var OPTIONS$1 = {};
var CACHE = {};
var cornerTpl = "\n <a href=\"{{repo}}\" class=\"github-corner\" aria-label=\"View source on Github\">\n <svg viewBox=\"0 0 250 250\" aria-hidden=\"true\">\n <path d=\"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z\"></path>\n <path d=\"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2\" fill=\"currentColor\" style=\"transform-origin: 130px 106px;\" class=\"octo-arm\"></path>\n <path d=\"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z\" fill=\"currentColor\" class=\"octo-body\"></path>\n </svg>\n </a>\n";
var renderTo = function (dom, content) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom);
dom.innerHTML = content;
return dom
};
var toc = [];
var renderer = new marked.Renderer();
@@ -2164,158 +2361,227 @@ var renderer = new marked.Renderer();
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
renderer.heading = function (text, level) {
var slug = text.toLowerCase().replace(/[\s\n\t]+/g, '-');
var slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-');
var route = '';
toc.push({ level: level, slug: slug, title: text });
if (OPTIONS$1.router) {
route = "#/" + (getRoute());
}
return ("<h" + level + " id=\"" + slug + "\"><a href=\"#" + slug + "\" class=\"anchor\"></a>" + text + "</h" + level + ">")
toc.push({ level: 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) {
if ( lang === void 0 ) lang = '';
var hl = prism.highlight(code, prism.languages[lang] || prism.languages.markup);
return ("<pre><code class=\"lang-" + lang + "\" data-lang=\"" + lang + "\">" + hl + "</code></pre>")
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 });
var render = function (content, opts) {
if ( opts === void 0 ) opts = {};
/**
* App
*/
function renderApp (dom, replace) {
var nav = document.querySelector('nav') || document.createElement('nav');
var corner = '';
dom[replace ? 'outerHTML' : 'innerHTML'] = toggle(OPTIONS$1.sidebarToggle) + corner(OPTIONS$1.repo) + main();
document.body.insertBefore(nav, document.body.children[0]);
if (opts.repo) {
var repo = /\/\//.test(opts.repo) ? opts.repo : ('https://github.com/' + opts.repo);
corner = cornerTpl.replace(/{{repo}}/g, repo);
}
var section = "<section class=\"content\">\n <article class=\"markdown-section\">" + (marked(content)) + "</article>\n </section>";
var sidebar = "<aside class=\"sidebar\">" + (genToc(toc)) + "</aside>";
return (corner + "<main>" + sidebar + section + "</main>")
};
function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) { return }
var anchors = document.querySelectorAll('.anchor');
var nav = {};
var lis = document.querySelectorAll('.sidebar li');
var active = null;
for (var i = 0, len = lis.length; i < len; i += 1) {
var li = lis[i];
var a = li.querySelector('a');
nav[a.getAttribute('href').slice(1)] = li;
}
function highlight () {
for (var i = 0, len = anchors.length; i < len; i += 1) {
var node = anchors[i].parentNode;
var bcr = node.getBoundingClientRect();
if (bcr.top < 10 && bcr.bottom > 10) {
var li = nav[node.id];
if (li === active) { return }
if (active) { active.setAttribute('class', ''); }
li.setAttribute('class', 'active');
active = li;
return
}
}
}
document.querySelector('main .content').addEventListener('scroll', highlight);
highlight();
function scrollIntoView () {
var id = window.location.hash.slice(1);
if (!id) { return }
var section = document.querySelector('#' + id);
if (section) { section.scrollIntoView(); }
}
window.addEventListener('hashchange', scrollIntoView);
scrollIntoView();
// bind toggle
bindToggle('button.sidebar-toggle');
}
var bindEvent = function () {
scrollActiveSidebar();
};
/**
* 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;
var DEFAULT_OPTS = {
if (OPTIONS$1.auto2top) { scroll2Top('section.content'); }
}
/**
* navbar
*/
function renderNavbar (content) {
if (CACHE['navbar'] && CACHE['navbar'] === content) { return }
CACHE['navbar'] = content;
renderNavbar.rendered = true;
if (content) { renderTo('nav', marked(content)); }
activeLink('nav');
}
/**
* sidebar
*/
function renderSidebar (content) {
var isToc = false;
if (content) {
content = marked(content);
} else if (OPTIONS$1.sidebar) {
content = tree(OPTIONS$1.sidebar, '<ul>');
} else {
content = tree(genTree(toc, OPTIONS$1.maxLevel), '<ul>');
isToc = true;
}
renderSidebar.rendered = true;
if (CACHE['sidebar'] && CACHE['sidebar'] === content) { return }
CACHE['sidebar'] = content;
renderTo('aside.sidebar', content);
if (isToc) { scrollActiveSidebar(); }
toc = [];
}
/**
* render loading bar
* @return {[type]} [description]
*/
function renderLoading (ref) {
var loaded = ref.loaded;
var total = ref.total;
var num = Math.floor(loaded / total * 100);
if (!CACHE['loading']) {
var div = document.createElement('div');
div.classList.add('progress');
document.body.appendChild(div);
CACHE['loading'] = div;
}
CACHE['loading'].style.opacity = 1;
CACHE['loading'].style.width = num + '%';
if (num >= 95) {
clearTimeout(renderLoading.cacheTImeout);
renderLoading.cacheTImeout = setTimeout(function (_) {
CACHE['loading'].style.opacity = 0;
CACHE['loading'].style.width = '0%';
}, 200);
}
}
/**
* Load Config
* @param {Object} options
*/
function config (options) {
OPTIONS$1 = options;
}
var OPTIONS = {
el: '#app',
title: document.title,
sep: ' - ',
repo: ''
repo: '',
maxLevel: 6,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
auto2top: false
};
var script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop();
// load configuration for script attribute
if (script) {
for (var prop in DEFAULT_OPTS) {
DEFAULT_OPTS[prop] = script.getAttribute('data-' + prop) || DEFAULT_OPTS[prop];
for (var prop in OPTIONS) {
var val = script.getAttribute('data-' + camel2kebab(prop));
OPTIONS[prop] = isNil(val) ? OPTIONS[prop] : (val || true);
}
if (OPTIONS.loadSidebar === true) { OPTIONS.loadSidebar = '_sidebar.md'; }
if (OPTIONS.loadNavbar === true) { OPTIONS.loadNavbar = '_navbar.md'; }
if (OPTIONS.sidebar) { OPTIONS.sidebar = window[OPTIONS.sidebar]; }
}
var Docsify = function Docsify (opts) {
Docsify.installed = true;
// load options
config(OPTIONS);
this.opts = Object.assign({}, opts, DEFAULT_OPTS);
this.opts.title = (this.opts.title ? this.opts.sep : '') + this.opts.title;
var cacheRoute = null;
var cacheXhr = null;
this.replace = true;
this.dom = document.querySelector(this.opts.el);
if (!this.dom) {
this.dom = document.body;
this.replace = false;
var mainRender = function (cb) {
var route = getRoute();
if (cacheRoute === route) { return cb() }
var wait;
var basePath = cacheRoute = route;
if (!/\//.test(basePath)) {
basePath = '';
} else if (basePath && !/\/$/.test(basePath)) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1];
}
this.loc = document.location.pathname;
if (/\/$/.test(this.loc)) { this.loc += 'README'; }
this.load();
var nav = document.querySelector('nav');
if (nav) { this.activeNav(nav); }
};
cacheXhr && cacheXhr.abort && cacheXhr.abort();
// Render markdown file
cacheXhr = load(
(!route || /\/$/.test(route)) ? (route + "README.md") : (route + ".md"),
'GET',
renderLoading);
Docsify.prototype.load = function load () {
var this$1 = this;
ajax(((this.loc) + ".md")).then(function (res) {
var target = res.target;
if (target.status >= 400) {
this$1.render('not found');
cacheXhr.then(function (result) {
renderArticle(result);
if (OPTIONS.loadSidebar) {
if (wait === false) { cb(); }
wait = false;
} else {
this$1.render(res.target.response);
bindEvent();
cb();
}
});
};
}, function (_) { return renderArticle(null); });
Docsify.prototype.render = function render$1 (content) {
if (this.loc.slice(1) !== 'README') {
document.title = this.loc.slice(1) + this.opts.title;
// 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);
}
this.dom[this.replace ? 'outerHTML' : 'innerHTML'] = render(content, this.opts);
};
Docsify.prototype.activeNav = function activeNav (elm) {
var host = document.location.origin + document.location.pathname;[].slice.call(elm.querySelectorAll('a')).forEach(function (node) {
if (node.href === host) {
node.setAttribute('class', 'active');
}
});
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();
});
};
// Render app
renderApp(dom, replace);
main();
if (OPTIONS.router) {
if (!/^#\//.test(window.location.hash)) { window.location.hash = '#/'; }
window.addEventListener('hashchange', main);
}
};
window.addEventListener('load', function () {
if (Docsify.installed) { return }
new Docsify();
});
var index = Docsify();
return Docsify;
return index;
})));
}());
+2 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10 -4
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "0.1.0",
"version": "1.1.1",
"description": "A magical documentation generator.",
"main": "lib/docsify.js",
"files": [
@@ -9,7 +9,8 @@
"themes"
],
"scripts": {
"build": "node build/build.js",
"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'",
"test": "eslint src test"
},
"repository": {
@@ -24,17 +25,22 @@
"generator"
],
"author": "qingwei-li <cinwell.li@gmail.com> (https://github.com/QingWei-Li)",
"homepage": "https://QingWei-Li.github.io/docsify",
"homepage": "https://docsify.js.org",
"license": "MIT",
"devDependencies": {
"cssnano": "^3.8.1",
"eslint": "^3.10.2",
"eslint-config-vue": "^2.0.1",
"eslint-plugin-vue": "^1.0.0",
"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-plugin-node-resolve": "^2.0.0",
"rollup-plugin-uglify": "^1.0.1"
"rollup-plugin-uglify": "^1.0.1",
"serve-static": "^1.11.1"
},
"dependencies": {
"marked": "^0.3.6",
-10
View File
@@ -1,10 +0,0 @@
export default function (url, options = {}) {
const xhr = new XMLHttpRequest()
xhr.open(options.method || 'get', url)
xhr.send()
return {
then: cb => xhr.addEventListener('load', cb)
}
}
-51
View File
@@ -1,51 +0,0 @@
function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) return
const anchors = document.querySelectorAll('.anchor')
const nav = {}
const lis = document.querySelectorAll('.sidebar li')
let active = null
for (let i = 0, len = lis.length; i < len; i += 1) {
const li = lis[i]
const a = li.querySelector('a')
nav[a.getAttribute('href').slice(1)] = li
}
function highlight () {
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i].parentNode
const bcr = node.getBoundingClientRect()
if (bcr.top < 10 && bcr.bottom > 10) {
const li = nav[node.id]
if (li === active) return
if (active) active.setAttribute('class', '')
li.setAttribute('class', 'active')
active = li
return
}
}
}
document.querySelector('main .content').addEventListener('scroll', highlight)
highlight()
function scrollIntoView () {
const id = window.location.hash.slice(1)
if (!id) return
const section = document.querySelector('#' + id)
if (section) section.scrollIntoView()
}
window.addEventListener('hashchange', scrollIntoView)
scrollIntoView()
}
export default function () {
scrollActiveSidebar()
}
-76
View File
@@ -1,76 +0,0 @@
import ajax from './ajax'
import render from './render'
import bindEvent from './bind-event'
const DEFAULT_OPTS = {
el: '#app',
title: document.title,
sep: ' - ',
repo: ''
}
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
if (script) {
for (const prop in DEFAULT_OPTS) {
DEFAULT_OPTS[prop] = script.getAttribute('data-' + prop) || DEFAULT_OPTS[prop]
}
}
class Docsify {
constructor (opts) {
Docsify.installed = true
this.opts = Object.assign({}, opts, DEFAULT_OPTS)
this.opts.title = (this.opts.title ? this.opts.sep : '') + this.opts.title
this.replace = true
this.dom = document.querySelector(this.opts.el)
if (!this.dom) {
this.dom = document.body
this.replace = false
}
this.loc = document.location.pathname
if (/\/$/.test(this.loc)) this.loc += 'README'
this.load()
const nav = document.querySelector('nav')
if (nav) this.activeNav(nav)
}
load () {
ajax(`${this.loc}.md`).then(res => {
const target = res.target
if (target.status >= 400) {
this.render('not found')
} else {
this.render(res.target.response)
bindEvent()
}
})
}
render (content) {
if (this.loc.slice(1) !== 'README') {
document.title = this.loc.slice(1) + this.opts.title
}
this.dom[this.replace ? 'outerHTML' : 'innerHTML'] = render(content, this.opts)
}
activeNav (elm) {
const host = document.location.origin + document.location.pathname
;[].slice.call(elm.querySelectorAll('a')).forEach(node => {
if (node.href === host) {
node.setAttribute('class', 'active')
}
})
}
}
window.addEventListener('load', () => {
if (Docsify.installed) return
new Docsify()
})
export default Docsify
+98
View File
@@ -0,0 +1,98 @@
/**
* Active sidebar when scroll
* @link https://buble.surge.sh/
*/
export function scrollActiveSidebar () {
if (/mobile/i.test(navigator.userAgent)) return
const anchors = document.querySelectorAll('.anchor')
const nav = {}
const lis = document.querySelectorAll('.sidebar li')
let active = null
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)
nav[href] = li
}
function highlight () {
for (let i = 0, len = anchors.length; i < len; i += 1) {
const node = anchors[i].parentNode
const bcr = node.getBoundingClientRect()
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
}
}
}
const dom = document.querySelector('main .content')
dom.removeEventListener('scroll', highlight)
dom.addEventListener('scroll', highlight)
highlight()
}
export function scrollIntoView () {
const id = window.location.hash.match(/#[^#\/]+$/g)
if (!id || !id.length) return
const section = document.querySelector(id[0])
if (section) section.scrollIntoView()
}
/**
* Acitve link
*/
export function activeLink (dom, activeParent) {
const host = window.location.href
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
if (!dom) return
;[].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')
}
})
}
/**
* sidebar toggle
*/
export function bindToggle (dom) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
if (!dom) return
const body = document.body
dom.addEventListener('click', () => body.classList.toggle('close'))
if (!/mobile/i.test(navigator.userAgent)) return
document.querySelector('aside').addEventListener('click', event => {
body.classList.toggle('close')
})
}
let cacheContentDOM
export function scroll2Top (dom) {
cacheContentDOM = cacheContentDOM || document.querySelector(dom)
cacheContentDOM.scrollTop = 0
}
-41
View File
@@ -1,41 +0,0 @@
/**
* @link from https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
*/
const tocToTree = function (toc) {
const headlines = []
const last = {}
toc.forEach(headline => {
const level = headline.level || 1
const len = level - 1
if (last[len]) {
last[len].children = last[len].children || []
last[len].children.push(headline)
} else {
headlines.push(headline)
}
last[level] = headline
})
return headlines
}
const buildHeadlinesTree = function (tree, tpl = '') {
if (!tree || !tree.length) return ''
tree.forEach((node) => {
tpl += `<li><a class="section-link" href="#${node.slug}">${node.title}</a></li>`
if (node.children) {
tpl += `<li><ul class="children">${buildHeadlinesTree(node.children)}</li></ul>`
}
})
return tpl
}
export default function (toc) {
var tree = tocToTree(toc)
var result = buildHeadlinesTree(tree, '<ul>')
return result
}
+98
View File
@@ -0,0 +1,98 @@
import { load, camel2kebab, isNil, getRoute } from './util'
import { activeLink, scrollIntoView } from './event'
import * as render from './render'
const OPTIONS = {
el: '#app',
repo: '',
maxLevel: 6,
sidebar: '',
sidebarToggle: false,
loadSidebar: null,
loadNavbar: null,
router: false,
auto2top: false
}
const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop()
// load configuration for script attribute
if (script) {
for (const prop in OPTIONS) {
const val = script.getAttribute('data-' + camel2kebab(prop))
OPTIONS[prop] = isNil(val) ? OPTIONS[prop] : (val || true)
}
if (OPTIONS.loadSidebar === true) OPTIONS.loadSidebar = '_sidebar.md'
if (OPTIONS.loadNavbar === true) OPTIONS.loadNavbar = '_navbar.md'
if (OPTIONS.sidebar) OPTIONS.sidebar = window[OPTIONS.sidebar]
}
// load options
render.config(OPTIONS)
let cacheRoute = null
let cacheXhr = null
const mainRender = function (cb) {
const route = getRoute()
if (cacheRoute === route) return cb()
let wait
let basePath = cacheRoute = route
if (!/\//.test(basePath)) {
basePath = ''
} else if (basePath && !/\/$/.test(basePath)) {
basePath = basePath.match(/(\S*\/)[^\/]+$/)[1]
}
cacheXhr && cacheXhr.abort && cacheXhr.abort()
// Render markdown file
cacheXhr = load(
(!route || /\/$/.test(route)) ? `${route}README.md` : `${route}.md`,
'GET',
render.renderLoading)
cacheXhr.then(result => {
render.renderArticle(result)
if (OPTIONS.loadSidebar) {
if (wait === false) cb()
wait = false
} else {
cb()
}
}, _ => render.renderArticle(null))
// Render sidebar
if (OPTIONS.loadSidebar) {
load(basePath + OPTIONS.loadSidebar).then(result => {
render.renderSidebar(result)
if (wait === false) cb()
wait = false
})
}
// Render navbar
if (OPTIONS.loadNavbar) {
load(basePath + OPTIONS.loadNavbar).then(render.renderNavbar)
}
}
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()
})
}
// Render app
render.renderApp(dom, replace)
main()
if (OPTIONS.router) {
if (!/^#\//.test(window.location.hash)) window.location.hash = '#/'
window.addEventListener('hashchange', main)
}
}
export default Docsify()
+121 -28
View File
@@ -1,17 +1,19 @@
import marked from 'marked'
import Prism from 'prismjs'
import genToc from './gen-toc'
import * as tpl from './tpl'
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top } from './event'
import { genTree, getRoute } from './util'
const cornerTpl = `
<a href="{{repo}}" class="github-corner" aria-label="View source on Github">
<svg viewBox="0 0 250 250" aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
</svg>
</a>
`
const toc = []
let OPTIONS = {}
const CACHE = {}
const renderTo = function (dom, content) {
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
dom.innerHTML = content
return dom
}
let toc = []
const renderer = new marked.Renderer()
/**
@@ -19,33 +21,124 @@ const renderer = new marked.Renderer()
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
renderer.heading = function (text, level) {
const slug = text.toLowerCase().replace(/[\s\n\t]+/g, '-')
const slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[^\w|\u4e00-\u9fa5]+/g, '-')
let route = ''
toc.push({ level, slug, title: text })
if (OPTIONS.router) {
route = `#/${getRoute()}`
}
return `<h${level} id="${slug}"><a href="#${slug}" class="anchor"></a>${text}</h${level}>`
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) {
renderer.code = function (code, lang = '') {
const hl = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup)
return `<pre><code class="lang-${lang}" data-lang="${lang}">${hl}</code></pre>`
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
}
return `<a href="${href}" title="${title || ''}">${text}</a>`
}
marked.setOptions({ renderer })
export default function (content, opts = {}) {
let corner = ''
/**
* App
*/
export function renderApp (dom, replace) {
const nav = document.querySelector('nav') || document.createElement('nav')
if (opts.repo) {
const repo = /\/\//.test(opts.repo) ? opts.repo : ('https://github.com/' + opts.repo)
corner = cornerTpl.replace(/{{repo}}/g, repo)
dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.toggle(OPTIONS.sidebarToggle) + tpl.corner(OPTIONS.repo) + tpl.main()
document.body.insertBefore(nav, document.body.children[0])
// bind toggle
bindToggle('button.sidebar-toggle')
}
/**
* 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
if (OPTIONS.auto2top) scroll2Top('section.content')
}
/**
* navbar
*/
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')
}
/**
* sidebar
*/
export function renderSidebar (content) {
let isToc = false
if (content) {
content = marked(content)
} else if (OPTIONS.sidebar) {
content = tpl.tree(OPTIONS.sidebar, '<ul>')
} else {
content = tpl.tree(genTree(toc, OPTIONS.maxLevel), '<ul>')
isToc = true
}
const section = `<section class="content">
<article class="markdown-section">${marked(content)}</article>
</section>`
const sidebar = `<aside class="sidebar">${genToc(toc)}</aside>`
return `${corner}<main>${sidebar}${section}</main>`
renderSidebar.rendered = true
if (CACHE['sidebar'] && CACHE['sidebar'] === content) return
CACHE['sidebar'] = content
renderTo('aside.sidebar', content)
if (isToc) scrollActiveSidebar()
toc = []
}
/**
* render loading bar
* @return {[type]} [description]
*/
export function renderLoading ({ loaded, total }) {
const num = Math.floor(loaded / total * 100)
if (!CACHE['loading']) {
const div = document.createElement('div')
div.classList.add('progress')
document.body.appendChild(div)
CACHE['loading'] = div
}
CACHE['loading'].style.opacity = 1
CACHE['loading'].style.width = num + '%'
if (num >= 95) {
clearTimeout(renderLoading.cacheTImeout)
renderLoading.cacheTImeout = setTimeout(_ => {
CACHE['loading'].style.opacity = 0
CACHE['loading'].style.width = '0%'
}, 200)
}
}
/**
* Load Config
* @param {Object} options
*/
export function config (options) {
OPTIONS = options
}
+306
View File
@@ -0,0 +1,306 @@
* {
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
.progress {
background-color: $color-primary;
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
html, body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
p {
margin: 0;
}
ul, li {
list-style: none;
display: inline-block;
margin: 0;
}
a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
&:hover {
color: $color-primary;
}
&.active {
color: $color-primary;
border-bottom: 2px solid $color-primary;
}
}
/* navbar dropdown */
li {
position: relative;
display: inline-block;
ul {
background-color: rgba(#fff, .6);
border: 1px solid $color-primary;
opacity: 0;
overflow: hidden;
padding: 0;
position: absolute;
right: 1em;
top: 26px;
transform-origin: 100% 0%;
transform: scale(1, 0);
transition: opacity .4s ease-out, transform .2s ease;
transition-delay: .3s;
li {
display: block;
font-size: 14px;
margin: 0;
padding: 4px 10px;
white-space: nowrap;
}
a {
display: block;
margin: 0;
padding: 0;
&.active {
border-bottom: 0;
}
}
}
&:hover ul {
opacity: 1;
transform: scale(1, 1);
transition: opacity .4s ease, transform .2s ease-out;
transition-delay: 0;
}
}
}
/* github corner */
.github-corner {
position: absolute;
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;
height: 80px;
width: 80px;
fill: $color-primary;
}
}
/* main */
main {
size: 100% 100%;
position: relative;
}
/* sidebar */
.sidebar {
border-right: 1px solid rgba(0, 0, 0, .07);
overflow-y: auto;
padding-top: 40px;
position: absolute 0 * 0 0;
transition: transform 250ms ease-out;
width: $sidebar-width;
z-index: 20;
ul {
margin: 0;
padding: 0;
}
ul, ul li {
list-style: none;
}
ul li a {
display: block;
border-bottom: none;
}
ul li ul {
padding-left: 20px;
}
}
/* sidebar toggle */
.sidebar-toggle {
background-color: transparent;
border: 0;
bottom: 10px;
left: 10px;
outline: none;
position: absolute;
text-align: center;
transition: opacity .3s;
width: 30px;
z-index: 30;
outline: none;
&:hover {
opacity: .4;
}
span {
background-color: $color-primary;
display: block;
size: 16px 2px;
margin-bottom: 4px;
}
}
/* main content */
.content {
overflow-y: auto;
position: absolute 0 0 0 $sidebar-width;
overflow-x: hidden;
padding-top: 20px;
transition: left 250ms ease;
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 800px;
padding: 20px 15px 40px 15px;
> * {
box-sizing: border-box;
font-size: inherit;
}
>:first-child {
margin-top: 0!important;
}
}
body.close {
.sidebar {
transform: translateX(-$sidebar-width);
}
.content {
left: 0;
}
}
@media (max-width: 600px) {
nav, .github-corner, .sidebar-toggle, .sidebar {
position: fixed;
}
nav {
margin-top: 16px;
}
nav li ul {
top: 30px;
}
.sidebar {
left: -$sidebar-width;
transition: transform 250ms ease-out;
}
.content {
left: 0;
min-width: 100vw;
transition: transform 250ms ease;
position: static;
overflow-y: auto;
}
nav, .github-corner {
transition: transform 250ms ease-out;
}
body.close {
.sidebar {
transform: translateX($sidebar-width);
}
.content {
transform: translateX($sidebar-width);
}
nav, .github-corner {
transform: translateX($sidebar-width);
}
}
.github-corner {
&:hover .octo-arm {
animation: none;
}
.octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
}
@keyframes octocat-wave {
0%,100% { transform: rotate(0); }
20%,60% { transform: rotate(-25deg); }
40%,80% { transform: rotate(10deg); }
}
+32 -180
View File
@@ -1,181 +1,39 @@
@import url('https://fonts.googleapis.com/css?family=Inconsolata|Inconsolata-Bold');
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
$color-primary: #0074D9;
$sidebar-width: 16em;
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
}
nav a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
}
nav a:hover {
color: #0074D9;
}
nav a.active {
color: #0074D9;
border-bottom: 2px solid #0074D9;
}
/* github corner */
.github-corner {
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
.github-corner svg {
color: #fff;
fill: #0074D9;
height: 80px;
width: 80px;
}
.github-corner:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
@keyframes octocat-wave {
0%,100%{ transform: rotate(0); }
20%,60%{ transform: rotate(-25deg); }
40%,80%{ transform: rotate(10deg); }
}
@media (max-width: 500px) {
.github-corner:hover .octo-arm {
animation: none;
}
.github-corner .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
html, body {
height: 100%;
}
@import "basic/layout";
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-color: #fff;
color: #34495e;
font-family: 'Source Sans Pro', arial, sans-serif;
font-weight: 400px;
font-size: 15px;
letter-spacing: 0;
margin: 0;
}
/* main */
main {
height: 100%;
position: relative;
width: 100%;
}
/* sidebar */
.sidebar {
background-color: #fff;
border-right: 1px solid rgba(0,0,0,.07);
bottom: 0;
color: #364149;
overflow-y: auto;
position: absolute;
top: 0;
width: 14em;
z-index: 1;
padding-top: 40px;
}
.sidebar ul {
margin: 0;
padding: 0;
}
.sidebar ul, .sidebar ul li {
list-style: none;
}
.sidebar a {
color: #666;
text-decoration: none;
}
.sidebar li {
list-style: none;
padding: 0.2em 0.2em 0.2em 1em;
margin: 0;
}
.sidebar .active {
background-color: #eee;
}
.sidebar .active a {
color: #333;
}
/* main content */
.content {
bottom: 0;
left: 14em;
overflow-y: auto;
position: absolute;
right: 0;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
@media screen and (max-width: 600px) {
.sidebar {
left: -14em;
a {
color: #666;
text-decoration: none;
}
.content {
left: 0;
li {
list-style: none;
padding: 0.2em 0 0.2em 1em;
margin: 0;
}
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 64em;
padding: 20px 15px 40px 15px;
}
ul li ul {
padding: 0;
}
.markdown-section * {
box-sizing: border-box;
-webkit-box-sizing: border-box;
font-size: inherit;
}
.active {
background-color: #eee;
.markdown-section>:first-child {
margin-top: 0!important;
a {
color: #333;
}
}
}
.markdown-section h1,
@@ -188,7 +46,7 @@ main {
}
.markdown-section a {
color: #0074D9;
color: $color-primary;
font-weight: 400;
}
@@ -256,7 +114,7 @@ main {
.markdown-section blockquote {
color: #858585;
border-left: 4px solid #0074D9;
border-left: 4px solid $color-primary;
margin: 2em 0;
padding-left: 20px;
}
@@ -288,8 +146,10 @@ main {
padding: 8px;
margin: 0 0 1em 0;
font-family: Inconsolata;
padding: 12px 10px 12px 12px;
padding: 0 10px 12px 0;
font-size: 16px;
overflow: auto;
word-wrap: normal;
}
/* code highlight */
@@ -362,9 +222,15 @@ main {
}
.markdown-section pre>code {
padding: 0;
display: block;
font-family: Inconsolata;
line-height: 1.2em;
overflow: inherit;
max-width: inherit;
position: relative;
background-color: #f8f8f8;
padding: 20px 0.8em 20px;
line-height: 1.1em;
border-radius: 2px;
}
.markdown-section code::after, .markdown-section code::before {
@@ -377,20 +243,6 @@ code .token {
-moz-osx-font-smoothing: initial;
}
pre code {
overflow-x: auto;
position: relative;
padding: 0;
background-color: #f8f8f8;
padding: 0.8em 0.8em 0.4em;
line-height: 1.1em;
border-radius: 2px;
}
.content img {
max-width: 100%;
}
.content span.light {
color: #7f8c8d;
}
+3
View File
@@ -0,0 +1,3 @@
$color-primary: #000;
$sidebar-width: 300px;
@import "basic/layout";
+38 -191
View File
@@ -1,187 +1,46 @@
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
-webkit-font-smoothing: antialiased;
}
$color-primary: #42b983;
$sidebar-width: 300px;
/* navbar */
nav {
position: absolute;
right: 0;
left: 0;
z-index: 10;
margin: 25px 60px 0 0;
text-align: right;
}
nav a {
margin: 0 1em;
padding: 5px 0;
font-size: 16px;
text-decoration: none;
color: inherit;
transition: color .3s;
}
nav a:hover {
color: #42b983;
}
nav a.active {
color: #42b983;
border-bottom: 2px solid #42b983;
}
/* github corner */
.github-corner {
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
.github-corner svg {
color: #fff;
fill: #42b983;
height: 80px;
width: 80px;
}
.github-corner:hover .octo-arm {
animation:octocat-wave 560ms ease-in-out;
}
@keyframes octocat-wave {
0%,100%{ transform: rotate(0); }
20%,60%{ transform: rotate(-25deg); }
40%,80%{ transform: rotate(10deg); }
}
@media (max-width: 500px) {
.github-corner:hover .octo-arm {
animation: none;
}
.github-corner .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
}
html, body {
height: 100%;
}
@import "basic/layout";
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
background-color: #fff;
color: #34495e;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
}
/* main */
main {
height: 100%;
position: relative;
width: 100%;
}
/* sidebar */
.sidebar {
background-color: #fff;
border-right: 1px solid rgba(0,0,0,.07);
bottom: 0;
color: #364149;
overflow-y: auto;
position: absolute;
top: 0;
width: 300px;
z-index: 1;
padding-top: 40px;
}
.sidebar ul {
margin: 0;
padding: 0;
}
.sidebar ul, .sidebar ul li {
list-style: none;
}
.sidebar ul li a {
color: #7f8c8d;
display: block;
padding: 6px 15px;
border-bottom: none;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-decoration: none;
}
.sidebar ul li a:hover {
text-decoration: underline;
}
.sidebar ul li.active>a {
color: #42b983;
font-weight: 500;
}
.sidebar ul li ul {
padding-left: 20px;
}
/* main content */
.content {
bottom: 0;
left: 300px;
overflow-y: auto;
position: absolute;
right: 0;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}
@media screen and (max-width: 600px) {
.sidebar {
left: -300px;
li {
margin: 6px 15px;
}
.content {
left: 0;
ul li a {
color: #7f8c8d;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
ul li ul {
padding: 0;
}
ul li.active>a {
color: $color-primary;
font-weight: 600;
}
}
/* markdown content found on pages */
.markdown-section {
position: relative;
margin: 0 auto;
max-width: 800px;
padding: 20px 15px 40px 15px;
}
.markdown-section * {
box-sizing: border-box;
-webkit-box-sizing: border-box;
font-size: inherit;
}
.markdown-section>:first-child {
margin-top: 0!important;
}
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
@@ -192,7 +51,7 @@ main {
}
.markdown-section a {
color: #42b983;
color: $color-primary;
font-weight: 600;
}
@@ -208,18 +67,15 @@ main {
}
.markdown-section h2 {
border-bottom: 1px solid #ddd;
font-size: 1.75em;
margin: 45px 0 0.8em;
padding-bottom: 0.7em;
}
.markdown-section h3 {
margin: 52px 0 1.2em;
margin: 40px 0 .6em;
font-size: 1.5em;
}
.markdown-section h4 {
font-size: 1.25em;
}
@@ -253,7 +109,7 @@ main {
.markdown-section blockquote {
color: #858585;
border-left: 4px solid #42b983;
border-left: 4px solid $color-primary;
margin: 2em 0;
padding-left: 20px;
}
@@ -283,13 +139,16 @@ main {
}
.markdown-section pre {
font-family: 'Roboto Mono', Monaco, courier, monospace;
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
background-color: #f8f8f8;
font-family: 'Roboto Mono', Monaco, courier, monospace;
line-height: 1.5em;
margin: 1.2em 0;
padding: 1.2em 1.4em;
padding: 0 1.4em;
position: relative;
overflow: auto;
word-wrap: normal;
}
/* code highlight */
@@ -322,7 +181,7 @@ main {
}
.token.string {
color: #42b983;
color: $color-primary;
}
.token.selector {
@@ -344,7 +203,7 @@ main {
.token.control,
.token.directive,
.token.unit {
color: #42b983;
color: $color-primary;
}
.token.keyword {
@@ -399,8 +258,10 @@ main {
font-size: 0.8em;
line-height: inherit;
margin: 0 2px;
padding: 3px 5px;
overflow: inherit;
padding: 2.2em 5px;
white-space: inherit;
max-width: inherit;
}
.markdown-section code::after, .markdown-section code::before {
@@ -413,17 +274,7 @@ code .token {
-moz-osx-font-smoothing: initial;
}
pre code {
overflow-x: auto;
position: relative;
padding: 0;
background-color: #f8f8f8;
padding: 0.8em 0.8em 0.4em;
line-height: 1.1em;
border-radius: 2px;
}
pre code::after {
pre::after {
color: #ccc;
content: attr(data-lang);
font-size: 0.75em;
@@ -437,10 +288,6 @@ pre code::after {
top: 0;
}
.content img {
max-width: 100%;
}
.content span.light {
color: #7f8c8d;
}
+60
View File
@@ -0,0 +1,60 @@
/**
* Render github corner
* @param {Object} data
* @return {String}
*/
export function corner (data) {
if (!data) return ''
if (!/\/\//.test(data)) data = 'https://github.com/' + data
data = data.replace(/^git\+/, '')
return `
<a href="${data}" class="github-corner" aria-label="View source on Github">
<svg viewBox="0 0 250 250" aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
</svg>
</a>`
}
/**
* Render main content
* @return {[type]} [description]
*/
export function main () {
return `<main>
<aside class="sidebar"></aside>
<section class="content">
<article class="markdown-section"></article>
</section>
</main>`
}
export function toggle (bool) {
if (!bool) return ''
return `<button class="sidebar-toggle">
<span></span><span></span><span></span>
</button>`
}
/**
* Render tree
* @param {Array} tree
* @param {String} tpl
* @return {String}
*/
export function tree (toc, tpl = '') {
if (!toc || !toc.length) return ''
toc.forEach(node => {
tpl += `<li><a class="section-link" href="${node.slug}">${node.title}</a></li>`
if (node.children) {
tpl += `<li><ul class="children">${tree(node.children)}</li></ul>`
}
})
return tpl
}
+97
View File
@@ -0,0 +1,97 @@
/**
* Simple ajax
* @param {String} url
* @param {String} [method=GET]
* @param {Function} [loading] handle loading
* @return {Promise}
*/
export function load (url, method = 'GET', loading) {
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.send()
return {
then: function (success, error = function () {}) {
if (loading) {
xhr.addEventListener('progress', loading)
xhr.addEventListener('loaded', loading)
}
xhr.addEventListener('error', error)
xhr.addEventListener('load', ({ target }) => {
target.status >= 400 ? error(target) : success(target.response)
})
},
abort: () => xhr.readyState !== 4 && xhr.abort()
}
}
/**
* gen toc tree
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
* @param {Array} toc
* @param {Number} maxLevel
* @return {Array}
*/
export function genTree (toc, maxLevel) {
const headlines = []
const last = {}
toc.forEach(headline => {
const level = headline.level || 1
const len = level - 1
if (level > maxLevel) return
if (last[len]) {
last[len].children = last[len].children || []
last[len].children.push(headline)
} else {
headlines.push(headline)
}
last[level] = headline
})
return headlines
}
/**
* camel to kebab
* @link https://github.com/bokuweb/kebab2camel/blob/master/index.js
* @param {String} str
* @return {String}
*/
export function camel2kebab (str) {
return str.replace(/([A-Z])/g, m => '-' + m.toLowerCase())
}
/**
* is nil
* @param {Object} object
* @return {Boolean}
*/
export function isNil (o) {
return o === null || o === undefined
}
let cacheRoute = null
let cacheHash = null
/**
* hash route
*/
export function getRoute () {
const loc = window.location
if (cacheHash === loc.hash && !isNil(cacheRoute)) return cacheRoute
let route = loc.hash.match(/^#\/([^#]+)/)
if (route && route.length === 2) {
route = route[1]
} else {
route = /^#\//.test(loc.hash) ? '' : loc.pathname
}
cacheRoute = route
cacheHash = loc.hash
return route
}