Compare commits

..
Author SHA1 Message Date
up9cloudandAnton Wilhelm 6365a476e0 Add missing emoji
Generate GitHub emoji aliases from original source
2019-02-21 12:13:52 +01:00
liqingwei bc4d06bb16 chore: add changelog 4.9.1 2019-02-21 17:26:41 +08:00
liqingwei 29d9cda3de [build] 4.9.1 2019-02-21 17:26:40 +08:00
louisliviandcinwell.li 140bf10377 fix: github assets url (#774) 2019-02-21 17:25:33 +08:00
liqingwei dfd31b5de7 chore: add changelog 4.9.0 2019-02-19 11:26:54 +08:00
liqingwei d1c72686bb [build] 4.9.0 2019-02-19 11:26:53 +08:00
Anton WilhelmandGitHub 8cd786c9d5 Merge pull request #760 from docsifyjs/provide-tests
Setup test environment and provide the first test
2019-02-14 19:23:55 +01:00
Anton Wilhelm b53571810b Setup test environment and provide first tests 🌟 2019-02-14 18:33:33 +01:00
Anton WilhelmandGitHub cb53106fa7 Merge pull request #737 from jthegedus/ssr-now-fix
Fix typo in Now SSR example code snippet
2019-02-05 08:42:27 +01:00
Anton Wilhelm fd86c727af preperation to run the code in nodejs 2019-01-30 09:45:50 +01:00
John Hildenbiddleandcinwell.li 69ef489210 fix: task list rendering (Fix #749) (#757)
This PR restores the task list presentation removed in 4.8:

- Add “task-list-item” class to task list `<li>` elms
- Hide list bullets on unordered task lists `<li>` elms

It also provides several improvements on the pre-4.8 presentation:

- Add “task-list” class to task list `<ul>` elms 
- Display list numbers on ordered task lists `<li>` elms
- Render accessible task list items by wrapping checkbox and text in `<label>` elm
- Allow task lists to be nested within standard ordered/unordered lists 

Please makes sure these boxes are checked before submitting your PR, thank you!

* [x] Make sure you are merging your commits to `master` branch.
* [x] Add some descriptions and refer relative issues for you PR.
* [x] DO NOT include files inside `lib` directory.
2019-01-30 14:21:50 +08:00
Andy Chenandcinwell.li c3345ba20c feat: Add new theme "dolphin" (#735)
Dolphin is a blue theme based on the theme vue, using the font Thasadith -- https://fonts.google.com/specimen/Thasadith as default.
2019-01-23 10:57:07 +08:00
Anton Wilhelmandcinwell.li 1447c8a40a feat: Provide code fragments feature (#748) 2019-01-23 10:54:50 +08:00
jthegedus 3b952ac7c3 fix error in ssr config example 2019-01-06 10:26:21 +11:00
34 changed files with 1422 additions and 1017 deletions
+28
View File
@@ -1,3 +1,31 @@
<a name="4.9.1"></a>
## [4.9.1](https://github.com/docsifyjs/docsify/compare/v4.9.0...v4.9.1) (2019-02-21)
### Bug Fixes
* github assets url ([#774](https://github.com/docsifyjs/docsify/issues/774)) ([140bf10](https://github.com/docsifyjs/docsify/commit/140bf10))
<a name="4.9.0"></a>
# [4.9.0](https://github.com/docsifyjs/docsify/compare/v4.8.6...v4.9.0) (2019-02-19)
### Bug Fixes
* task list rendering (Fix [#749](https://github.com/docsifyjs/docsify/issues/749)) ([#757](https://github.com/docsifyjs/docsify/issues/757)) ([69ef489](https://github.com/docsifyjs/docsify/commit/69ef489))
* upgrade npm-run-all ([049726e](https://github.com/docsifyjs/docsify/commit/049726e))
### Features
* **search-plugin:** add namespace option ([#706](https://github.com/docsifyjs/docsify/issues/706)) ([28beff8](https://github.com/docsifyjs/docsify/commit/28beff8))
* Add new theme "dolphin" ([#735](https://github.com/docsifyjs/docsify/issues/735)) ([c3345ba](https://github.com/docsifyjs/docsify/commit/c3345ba))
* Provide code fragments feature ([#748](https://github.com/docsifyjs/docsify/issues/748)) ([1447c8a](https://github.com/docsifyjs/docsify/commit/1447c8a))
<a name="4.8.6"></a>
## [4.8.6](https://github.com/docsifyjs/docsify/compare/v4.8.5...v4.8.6) (2018-11-12)
+20
View File
@@ -0,0 +1,20 @@
const fs = require('fs')
const data = fs.readFileSync('/dev/stdin', 'utf-8')
const emoji = JSON.parse(data)
const AllGithubEmoji = []
for (let i = 0; i < emoji.length; i++) {
let o = emoji[i]
if (o.aliases) {
AllGithubEmoji.push(...o.aliases)
}
}
const str = `// DO NOT EDIT THIS FILE, IT'S GENERATED
// All from github official gemoji repo
// see https://github.com/github/gemoji/blob/master/db/emoji.json
export default ${JSON.stringify(AllGithubEmoji)}
`
fs.writeFileSync(__dirname + '/../src/plugins/emoji-aliases.js', str)
+1 -1
View File
@@ -1,6 +1,6 @@
![logo](_media/icon.svg)
# docsify <small>4.8.6</small>
# docsify <small>4.9.1</small>
> A magical documentation site generator.
+16
View File
@@ -0,0 +1,16 @@
import fetch from 'fetch'
const URL = 'https://example.com'
const PORT = 8080
/// [demo]
const result = fetch(`${URL}:${PORT}`)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});
/// [demo]
result.then(console.log).catch(console.error)
+15
View File
@@ -39,6 +39,21 @@ You will get it
[filename](_media/example.md ':include :type=code')
## Embedded code fragments
Sometimes you don't want to embed a whole file. Maybe because you need just a few lines but you want to compile and test the file in CI.
```markdown
[filename](_media/example.js ':include :type=code :fragment=demo')
```
In your code file you need to surround the fragment between `/// [demo]` lines (before and after the fragment).
Alternatively you can use `### [demo]`.
Example:
[filename](_media/example.js ':include :type=code :fragment=demo')
## Tag attribute
If you embed the file as `iframe`, `audio` and `video`, then you may need to set the attributes of these tags.
+1 -1
View File
@@ -111,7 +111,7 @@ var readFileSync = require('fs').readFileSync
// init
var renderer = new Renderer({
template: readFileSync('./docs/index.template.html', 'utf-8').,
template: readFileSync('./docs/index.template.html', 'utf-8'),
config: {
name: 'docsify',
repo: 'docsifyjs/docsify'
+40 -7
View File
@@ -3157,7 +3157,7 @@ slugify.clear = function () {
};
function replace(m, $1) {
return '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
return '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
}
function emojify(text) {
@@ -3335,7 +3335,7 @@ function getAndRemoveConfig(str) {
str = str
.replace(/^'/, '')
.replace(/'$/, '')
.replace(/:([\w-]+)=?([\w-]+)?/g, function (m, key, value) {
.replace(/(?:^|\s):([\w-]+)=?([\w-]+)?/g, function (m, key, value) {
config[key] = (value && value.replace(/&quot;/g, '')) || true;
return ''
})
@@ -3483,6 +3483,7 @@ Compiler.prototype.compileEmbed = function compileEmbed (href, title) {
embed = compileMedia[type].call(this, href, title);
embed.type = type;
}
embed.fragment = config.fragment;
return embed
}
@@ -3633,6 +3634,23 @@ Compiler.prototype._initRenderer = function _initRenderer () {
return ("<img src=\"" + url + "\"data-origin=\"" + href + "\" alt=\"" + text + "\"" + attrs + ">")
};
origin.list = renderer.list = function (body, ordered, start) {
var isTaskList = /<li class="task-list-item">/.test(body.split('class="task-list"')[0]);
var isStartReq = start && start > 1;
var tag = ordered ? 'ol' : 'ul';
var tagAttrs = [
(isTaskList ? 'class="task-list"' : ''),
(isStartReq ? ("start=\"" + start + "\"") : '')
].join(' ').trim();
return ("<" + tag + " " + tagAttrs + ">" + body + "</" + tag + ">")
};
origin.listitem = renderer.listitem = function (text) {
var isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text);
var html = isTaskItem ? ("<li class=\"task-list-item\"><label>" + text + "</label></li>") : ("<li>" + text + "</li>");
return html
};
renderer.origin = origin;
@@ -3708,6 +3726,9 @@ function btn(el) {
var toggle = function (_) { return body.classList.toggle('close'); };
el = getNode(el);
if (el == null) {
return
}
on(el, 'click', function (e) {
e.stopPropagation();
toggle();
@@ -3723,7 +3744,9 @@ function btn(el) {
function collapse(el) {
el = getNode(el);
if (el == null) {
return
}
on(el, 'click', function (ref) {
var target = ref.target;
@@ -3761,8 +3784,10 @@ function sticky() {
*/
function getAndActive(router, el, isParent, autoTitle) {
el = getNode(el);
var links = findAll(el, 'a');
var links = [];
if (el != null) {
links = findAll(el, 'a');
}
var hash = decodeURI(router.toURL(router.getCurrentPath()));
var target;
@@ -3965,7 +3990,10 @@ function scrollActiveSidebar(router) {
coverHeight = cover ? cover.offsetHeight : 0;
var sidebar = getNode('.sidebar');
var lis = findAll(sidebar, 'li');
var lis = [];
if (sidebar != null) {
lis = findAll(sidebar, 'li');
}
for (var i = 0, len = lis.length; i < len; i += 1) {
var li = lis[i];
@@ -4049,6 +4077,11 @@ function walkFetchEmbed(ref, cb) {
if (token.embed.type === 'markdown') {
embedToken = compile.lexer(text);
} else if (token.embed.type === 'code') {
if (token.embed.fragment) {
var fragment = token.embed.fragment;
var pattern = new RegExp(("(?:###|\\/\\/\\/)\\s*\\[" + fragment + "\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[" + fragment + "\\]"));
text = ((text.match(pattern) || [])[1] || '').trim();
}
embedToken = compile.lexer(
'```' +
token.embed.lang +
@@ -5013,7 +5046,7 @@ function initGlobalAPI () {
dom: dom,
get: get,
slugify: slugify,
version: '4.8.6'
version: '4.9.1'
};
window.DocsifyCompiler = Compiler;
window.marked = marked;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -893,7 +893,7 @@ var AllGithubEmoji = [
window.emojify = function (match, $1) {
return AllGithubEmoji.indexOf($1) === -1 ?
match :
'<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' +
'<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
$1 +
'.png" alt="' +
$1 +
+1 -1
View File
File diff suppressed because one or more lines are too long
+25 -7
View File
@@ -1,6 +1,18 @@
(function () {
var INDEXS = {};
var LOCAL_STORAGE = {
EXPIRE_KEY: 'docsify.search.expires',
INDEX_KEY: 'docsify.search.index'
};
function resolveExpireKey(namespace) {
return namespace ? ((LOCAL_STORAGE.EXPIRE_KEY) + "/" + namespace) : LOCAL_STORAGE.EXPIRE_KEY
}
function resolveIndexKey(namespace) {
return namespace ? ((LOCAL_STORAGE.INDEX_KEY) + "/" + namespace) : LOCAL_STORAGE.INDEX_KEY
}
function escapeHtml(string) {
var entityMap = {
'&': '&amp;',
@@ -34,9 +46,9 @@ function getAllPaths(router) {
return paths
}
function saveData(maxAge) {
localStorage.setItem('docsify.search.expires', Date.now() + maxAge);
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS));
function saveData(maxAge, expireKey, indexKey) {
localStorage.setItem(expireKey, Date.now() + maxAge);
localStorage.setItem(indexKey, JSON.stringify(INDEXS));
}
function genIndex(path, content, router, depth) {
@@ -154,9 +166,13 @@ function search(query) {
function init$1(config, vm) {
var isAuto = config.paths === 'auto';
var isExpired = localStorage.getItem('docsify.search.expires') < Date.now();
INDEXS = JSON.parse(localStorage.getItem('docsify.search.index'));
var expireKey = resolveExpireKey(config.namespace);
var indexKey = resolveIndexKey(config.namespace);
var isExpired = localStorage.getItem(expireKey) < Date.now();
INDEXS = JSON.parse(localStorage.getItem(indexKey));
if (isExpired) {
INDEXS = {};
@@ -177,7 +193,7 @@ function init$1(config, vm) {
.get(vm.router.getFile(path), false, vm.config.requestHeaders)
.then(function (result) {
INDEXS[path] = genIndex(path, result, vm.router, config.depth);
len === ++count && saveData(config.maxAge);
len === ++count && saveData(config.maxAge, expireKey, indexKey);
});
});
}
@@ -311,7 +327,8 @@ var CONFIG = {
paths: 'auto',
depth: 2,
maxAge: 86400000, // 1 day
hideOtherSidebarContent: false
hideOtherSidebarContent: false,
namespace: undefined
};
var install = function (hook, vm) {
@@ -327,6 +344,7 @@ var install = function (hook, vm) {
CONFIG.noData = opts.noData || CONFIG.noData;
CONFIG.depth = opts.depth || CONFIG.depth;
CONFIG.hideOtherSidebarContent = opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent;
CONFIG.namespace = opts.namespace || CONFIG.namespace;
}
var isAuto = CONFIG.paths === 'auto';
+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
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
+817 -1
View File
File diff suppressed because it is too large Load Diff
+10 -4
View File
@@ -1,6 +1,6 @@
{
"name": "docsify",
"version": "4.8.6",
"version": "4.9.1",
"description": "A magical documentation generator.",
"author": {
"name": "qingwei-li",
@@ -27,7 +27,7 @@
"dev": "run-p serve watch:*",
"dev:ssr": "run-p serve:ssr watch:*",
"lint": "eslint {src,packages} --fix",
"test": "run-p lint",
"test": "mocha",
"css": "stylus src/themes/*.styl -u autoprefixer-stylus",
"watch:css": "run-p 'css -- -o themes -w'",
"watch:js": "node build/build.js",
@@ -36,7 +36,8 @@
"build:js": "cross-env NODE_ENV=production node build/build.js",
"build:ssr": "node build/ssr.js",
"build:cover": "node build/cover.js",
"build": "rimraf lib themes && run-s build:js build:css build:css:min build:ssr build:cover",
"build:emoji-aliases": "wget https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json -O - | node build/emoji-aliases.js",
"build": "rimraf lib themes && run-s build:emoji-aliases build:js build:css build:css:min build:ssr build:cover",
"pub:next": "cross-env RELEASE_TAG=next sh build/release.sh",
"pub": "sh build/release.sh",
"postinstall": "opencollective postinstall"
@@ -51,14 +52,18 @@
},
"devDependencies": {
"autoprefixer-stylus": "^0.14.0",
"chai": "^4.2.0",
"chokidar": "^2.0.2",
"conventional-changelog-cli": "^1.3.5",
"cross-env": "^5.1.3",
"cssnano": "^3.10.0",
"eslint": "^4.14.0",
"eslint-config-xo-space": "^0.18.0",
"esm": "^3.1.4",
"jsdom": "^13.2.0",
"lerna": "^2.5.1",
"live-server": "^1.2.1",
"mocha": "^5.2.0",
"npm-run-all": "^4.1.5",
"rimraf": "^2.6.2",
"rollup": "^0.53.3",
@@ -68,7 +73,8 @@
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-uglify": "^2.0.1",
"stylus": "^0.54.5"
"stylus": "^0.54.5",
"xhr2": "^0.1.4"
},
"keywords": [
"doc",
+1 -1
View File
@@ -37,5 +37,5 @@
"integrity": "sha1-6DWIAbhrg7F1YNTjw4LXrvIQCUQ="
}
},
"version": "4.8.6"
"version": "4.9.1"
}
@@ -1,6 +1,6 @@
{
"name": "docsify-server-renderer",
"version": "4.8.6",
"version": "4.9.1",
"description": "docsify server renderer",
"author": {
"name": "qingwei-li",
+4 -25
View File
@@ -1,6 +1,5 @@
import {isMobile} from '../util/env'
import * as dom from '../util/dom'
import image from '../util/image'
import Tweezer from 'tweezer.js'
const nav = {}
@@ -88,7 +87,10 @@ export function scrollActiveSidebar(router) {
coverHeight = cover ? cover.offsetHeight : 0
const sidebar = dom.getNode('.sidebar')
const lis = dom.findAll(sidebar, 'li')
let lis = []
if (sidebar != null) {
lis = dom.findAll(sidebar, 'li')
}
for (let i = 0, len = lis.length; i < len; i += 1) {
const li = lis[i]
@@ -124,34 +126,11 @@ export function scrollActiveSidebar(router) {
})
}
export let pausedScrollToView
export function proceedScrollToView() {
if (pausedScrollToView) {
const copy = pausedScrollToView.slice()
pausedScrollToView = undefined
scrollIntoView(...copy)
}
image.unsubscribe(proceedScrollToView)
}
export function scrollIntoView(path, id) {
if (!id) {
return
}
if (pausedScrollToView) {
pausedScrollToView = [path, id]
return
}
if (!image.isAllImagesComplete()) {
pausedScrollToView = [path, id]
image.subscribe(proceedScrollToView)
return
}
const section = dom.find('#' + id)
section && scrollTo(section)
+10 -3
View File
@@ -9,6 +9,9 @@ export function btn(el) {
const toggle = _ => dom.body.classList.toggle('close')
el = dom.getNode(el)
if (el == null) {
return
}
dom.on(el, 'click', e => {
e.stopPropagation()
toggle()
@@ -24,7 +27,9 @@ export function btn(el) {
export function collapse(el) {
el = dom.getNode(el)
if (el == null) {
return
}
dom.on(el, 'click', ({target}) => {
if (
target.nodeName === 'A' &&
@@ -60,8 +65,10 @@ export function sticky() {
*/
export function getAndActive(router, el, isParent, autoTitle) {
el = dom.getNode(el)
const links = dom.findAll(el, 'a')
let links = []
if (el != null) {
links = dom.findAll(el, 'a')
}
const hash = decodeURI(router.toURL(router.getCurrentPath()))
let target
+18 -3
View File
@@ -6,7 +6,6 @@ import {slugify} from './slugify'
import {emojify} from './emojify'
import {isAbsolutePath, getPath, getParentPath} from '../router/util'
import {isFn, merge, cached, isPrimitive} from '../util/core'
import image from '../util/image'
// See https://github.com/PrismJS/prism/pull/1367
import 'prismjs/components/prism-markup-templating'
@@ -165,6 +164,7 @@ export class Compiler {
embed = compileMedia[type].call(this, href, title)
embed.type = type
}
embed.fragment = config.fragment
return embed
}
@@ -300,9 +300,24 @@ export class Compiler {
url = getPath(contentBase, getParentPath(router.getCurrentPath()), href)
}
image.increaseLoadingImageCount()
return `<img src="${url}"data-origin="${href}" alt="${text}"${attrs}>`
}
origin.list = renderer.list = function (body, ordered, start) {
const isTaskList = /<li class="task-list-item">/.test(body.split('class="task-list"')[0])
const isStartReq = start && start > 1
const tag = ordered ? 'ol' : 'ul'
const tagAttrs = [
(isTaskList ? 'class="task-list"' : ''),
(isStartReq ? `start="${start}"` : '')
].join(' ').trim()
return `<img src="${url}" data-origin="${href}" alt="${text}" onload="javascript:Docsify.util.image.onLoad(this)" onerror="javascript:Docsify.util.image.onError(this)"${attrs}>`
return `<${tag} ${tagAttrs}>${body}</${tag}>`
}
origin.listitem = renderer.listitem = function (text) {
const isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text)
const html = isTaskItem ? `<li class="task-list-item"><label>${text}</label></li>` : `<li>${text}</li>`
return html
}
renderer.origin = origin
+5
View File
@@ -20,6 +20,11 @@ function walkFetchEmbed({embedTokens, compile, fetch}, cb) {
if (token.embed.type === 'markdown') {
embedToken = compile.lexer(text)
} else if (token.embed.type === 'code') {
if (token.embed.fragment) {
const fragment = token.embed.fragment
const pattern = new RegExp(`(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[${fragment}\\]`)
text = ((text.match(pattern) || [])[1] || '').trim()
}
embedToken = compile.lexer(
'```' +
token.embed.lang +
+1 -1
View File
@@ -1,7 +1,7 @@
import {inBrowser} from '../util/env'
function replace(m, $1) {
return '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
return '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' + $1 + '.png" alt="' + $1 + '" />'
}
export function emojify(text) {
-62
View File
@@ -1,62 +0,0 @@
export default (function () {
let loadingImageCount = 0
const subscribers = []
function subscribe(cb) {
subscribers.push(cb)
}
function unsubscribe(cb) {
const index = subscribers.indexOf(cb)
if (index !== -1) {
subscribers.splice(index, 1)
}
}
function notifyAllImagesComplete() {
for (let i = 0; i < subscribers.length; i++) {
subscribers[i]()
}
}
function increaseLoadingImageCount() {
loadingImageCount += 1
}
function decreaseLoadingImageCount() {
loadingImageCount -= 1
if (loadingImageCount === 0) {
notifyAllImagesComplete()
}
}
function cleanElement(ele) {
ele.removeAttribute('onload')
ele.removeAttribute('onerror')
}
function onLoad(ele) {
cleanElement(ele)
decreaseLoadingImageCount()
}
function onError(ele) {
cleanElement(ele)
decreaseLoadingImageCount()
}
function isAllImagesComplete() {
return loadingImageCount === 0
}
return {
subscribe,
unsubscribe,
increaseLoadingImageCount,
onLoad,
onError,
isAllImagesComplete
}
})()
-1
View File
@@ -1,4 +1,3 @@
export * from './core'
export * from './env'
export * from '../router/util'
export {default as image} from './image'
File diff suppressed because one or more lines are too long
+2 -891
View File
@@ -1,898 +1,9 @@
const AllGithubEmoji = [
'+1',
'100',
'1234',
'8ball',
'a',
'ab',
'abc',
'abcd',
'accept',
'aerial_tramway',
'airplane',
'alarm_clock',
'alien',
'ambulance',
'anchor',
'angel',
'anger',
'angry',
'anguished',
'ant',
'apple',
'aquarius',
'aries',
'arrow_backward',
'arrow_double_down',
'arrow_double_up',
'arrow_down',
'arrow_down_small',
'arrow_forward',
'arrow_heading_down',
'arrow_heading_up',
'arrow_left',
'arrow_lower_left',
'arrow_lower_right',
'arrow_right',
'arrow_right_hook',
'arrow_up',
'arrow_up_down',
'arrow_up_small',
'arrow_upper_left',
'arrow_upper_right',
'arrows_clockwise',
'arrows_counterclockwise',
'art',
'articulated_lorry',
'astonished',
'athletic_shoe',
'atm',
'b',
'baby',
'baby_bottle',
'baby_chick',
'baby_symbol',
'back',
'baggage_claim',
'balloon',
'ballot_box_with_check',
'bamboo',
'banana',
'bangbang',
'bank',
'bar_chart',
'barber',
'baseball',
'basketball',
'bath',
'bathtub',
'battery',
'bear',
'bee',
'beer',
'beers',
'beetle',
'beginner',
'bell',
'bento',
'bicyclist',
'bike',
'bikini',
'bird',
'birthday',
'black_circle',
'black_joker',
'black_large_square',
'black_medium_small_square',
'black_medium_square',
'black_nib',
'black_small_square',
'black_square_button',
'blossom',
'blowfish',
'blue_book',
'blue_car',
'blue_heart',
'blush',
'boar',
'boat',
'bomb',
'book',
'bookmark',
'bookmark_tabs',
'books',
'boom',
'boot',
'bouquet',
'bow',
'bowling',
'bowtie',
'boy',
'bread',
'bride_with_veil',
'bridge_at_night',
'briefcase',
'broken_heart',
'bug',
'bulb',
'bullettrain_front',
'bullettrain_side',
'bus',
'busstop',
'bust_in_silhouette',
'busts_in_silhouette',
'cactus',
'cake',
'calendar',
'calling',
'camel',
'camera',
'cancer',
'candy',
'capital_abcd',
'capricorn',
'car',
'card_index',
'carousel_horse',
'cat',
'cat2',
'cd',
'chart',
'chart_with_downwards_trend',
'chart_with_upwards_trend',
'checkered_flag',
'cherries',
'cherry_blossom',
'chestnut',
'chicken',
'children_crossing',
'chocolate_bar',
'christmas_tree',
'church',
'cinema',
'circus_tent',
'city_sunrise',
'city_sunset',
'cl',
'clap',
'clapper',
'clipboard',
'clock1',
'clock10',
'clock1030',
'clock11',
'clock1130',
'clock12',
'clock1230',
'clock130',
'clock2',
'clock230',
'clock3',
'clock330',
'clock4',
'clock430',
'clock5',
'clock530',
'clock6',
'clock630',
'clock7',
'clock730',
'clock8',
'clock830',
'clock9',
'clock930',
'closed_book',
'closed_lock_with_key',
'closed_umbrella',
'cloud',
'clubs',
'cn',
'cocktail',
'coffee',
'cold_sweat',
'collision',
'computer',
'confetti_ball',
'confounded',
'confused',
'congratulations',
'construction',
'construction_worker',
'convenience_store',
'cookie',
'cool',
'cop',
'copyright',
'corn',
'couple',
'couple_with_heart',
'couplekiss',
'cow',
'cow2',
'credit_card',
'crescent_moon',
'crocodile',
'crossed_flags',
'crown',
'cry',
'crying_cat_face',
'crystal_ball',
'cupid',
'curly_loop',
'currency_exchange',
'curry',
'custard',
'customs',
'cyclone',
'dancer',
'dancers',
'dango',
'dart',
'dash',
'date',
'de',
'deciduous_tree',
'department_store',
'diamond_shape_with_a_dot_inside',
'diamonds',
'disappointed',
'disappointed_relieved',
'dizzy',
'dizzy_face',
'do_not_litter',
'dog',
'dog2',
'dollar',
'dolls',
'dolphin',
'door',
'doughnut',
'dragon',
'dragon_face',
'dress',
'dromedary_camel',
'droplet',
'dvd',
'e-mail',
'ear',
'ear_of_rice',
'earth_africa',
'earth_americas',
'earth_asia',
'egg',
'eggplant',
'eight',
'eight_pointed_black_star',
'eight_spoked_asterisk',
'electric_plug',
'elephant',
'email',
'end',
'envelope',
'envelope_with_arrow',
'es',
'euro',
'european_castle',
'european_post_office',
'evergreen_tree',
'exclamation',
'expressionless',
'eyeglasses',
'eyes',
'facepunch',
'factory',
'fallen_leaf',
'family',
'fast_forward',
'fax',
'fearful',
'feelsgood',
'feet',
'ferris_wheel',
'file_folder',
'finnadie',
'fire',
'fire_engine',
'fireworks',
'first_quarter_moon',
'first_quarter_moon_with_face',
'fish',
'fish_cake',
'fishing_pole_and_fish',
'fist',
'five',
'flags',
'flashlight',
'flipper',
'floppy_disk',
'flower_playing_cards',
'flushed',
'foggy',
'football',
'footprints',
'fork_and_knife',
'fountain',
'four',
'four_leaf_clover',
'fr',
'free',
'fried_shrimp',
'fries',
'frog',
'frowning',
'fu',
'fuelpump',
'full_moon',
'full_moon_with_face',
'game_die',
'gb',
'gem',
'gemini',
'ghost',
'gift',
'gift_heart',
'girl',
'globe_with_meridians',
'goat',
'goberserk',
'godmode',
'golf',
'grapes',
'green_apple',
'green_book',
'green_heart',
'grey_exclamation',
'grey_question',
'grimacing',
'grin',
'grinning',
'guardsman',
'guitar',
'gun',
'haircut',
'hamburger',
'hammer',
'hamster',
'hand',
'handbag',
'hankey',
'hash',
'hatched_chick',
'hatching_chick',
'headphones',
'hear_no_evil',
'heart',
'heart_decoration',
'heart_eyes',
'heart_eyes_cat',
'heartbeat',
'heartpulse',
'hearts',
'heavy_check_mark',
'heavy_division_sign',
'heavy_dollar_sign',
'heavy_exclamation_mark',
'heavy_minus_sign',
'heavy_multiplication_x',
'heavy_plus_sign',
'helicopter',
'herb',
'hibiscus',
'high_brightness',
'high_heel',
'hocho',
'honey_pot',
'honeybee',
'horse',
'horse_racing',
'hospital',
'hotel',
'hotsprings',
'hourglass',
'hourglass_flowing_sand',
'house',
'house_with_garden',
'hurtrealbad',
'hushed',
'ice_cream',
'icecream',
'id',
'ideograph_advantage',
'imp',
'inbox_tray',
'incoming_envelope',
'information_desk_person',
'information_source',
'innocent',
'interrobang',
'iphone',
'it',
'izakaya_lantern',
'jack_o_lantern',
'japan',
'japanese_castle',
'japanese_goblin',
'japanese_ogre',
'jeans',
'joy',
'joy_cat',
'jp',
'key',
'keycap_ten',
'kimono',
'kiss',
'kissing',
'kissing_cat',
'kissing_closed_eyes',
'kissing_heart',
'kissing_smiling_eyes',
'koala',
'koko',
'kr',
'lantern',
'large_blue_circle',
'large_blue_diamond',
'large_orange_diamond',
'last_quarter_moon',
'last_quarter_moon_with_face',
'laughing',
'leaves',
'ledger',
'left_luggage',
'left_right_arrow',
'leftwards_arrow_with_hook',
'lemon',
'leo',
'leopard',
'libra',
'light_rail',
'link',
'lips',
'lipstick',
'lock',
'lock_with_ink_pen',
'lollipop',
'loop',
'loud_sound',
'loudspeaker',
'love_hotel',
'love_letter',
'low_brightness',
'm',
'mag',
'mag_right',
'mahjong',
'mailbox',
'mailbox_closed',
'mailbox_with_mail',
'mailbox_with_no_mail',
'man',
'man_with_gua_pi_mao',
'man_with_turban',
'mans_shoe',
'maple_leaf',
'mask',
'massage',
'meat_on_bone',
'mega',
'melon',
'memo',
'mens',
'metal',
'metro',
'microphone',
'microscope',
'milky_way',
'minibus',
'minidisc',
'mobile_phone_off',
'money_with_wings',
'moneybag',
'monkey',
'monkey_face',
'monorail',
'moon',
'mortar_board',
'mount_fuji',
'mountain_bicyclist',
'mountain_cableway',
'mountain_railway',
'mouse',
'mouse2',
'movie_camera',
'moyai',
'muscle',
'mushroom',
'musical_keyboard',
'musical_note',
'musical_score',
'mute',
'nail_care',
'name_badge',
'neckbeard',
'necktie',
'negative_squared_cross_mark',
'neutral_face',
'new',
'new_moon',
'new_moon_with_face',
'newspaper',
'ng',
'night_with_stars',
'nine',
'no_bell',
'no_bicycles',
'no_entry',
'no_entry_sign',
'no_good',
'no_mobile_phones',
'no_mouth',
'no_pedestrians',
'no_smoking',
'non-potable_water',
'nose',
'notebook',
'notebook_with_decorative_cover',
'notes',
'nut_and_bolt',
'o',
'o2',
'ocean',
'octocat',
'octopus',
'oden',
'office',
'ok',
'ok_hand',
'ok_woman',
'older_man',
'older_woman',
'on',
'oncoming_automobile',
'oncoming_bus',
'oncoming_police_car',
'oncoming_taxi',
'one',
'open_book',
'open_file_folder',
'open_hands',
'open_mouth',
'ophiuchus',
'orange_book',
'outbox_tray',
'ox',
'package',
'page_facing_up',
'page_with_curl',
'pager',
'palm_tree',
'panda_face',
'paperclip',
'parking',
'part_alternation_mark',
'partly_sunny',
'passport_control',
'paw_prints',
'peach',
'pear',
'pencil',
'pencil2',
'penguin',
'pensive',
'performing_arts',
'persevere',
'person_frowning',
'person_with_blond_hair',
'person_with_pouting_face',
'phone',
'pig',
'pig2',
'pig_nose',
'pill',
'pineapple',
'pisces',
'pizza',
'point_down',
'point_left',
'point_right',
'point_up',
'point_up_2',
'police_car',
'poodle',
'poop',
'post_office',
'postal_horn',
'postbox',
'potable_water',
'pouch',
'poultry_leg',
'pound',
'pouting_cat',
'pray',
'princess',
'punch',
'purple_heart',
'purse',
'pushpin',
'put_litter_in_its_place',
'question',
'rabbit',
'rabbit2',
'racehorse',
'radio',
'radio_button',
'rage',
'rage1',
'rage2',
'rage3',
'rage4',
'railway_car',
'rainbow',
'raised_hand',
'raised_hands',
'raising_hand',
'ram',
'ramen',
'rat',
'recycle',
'red_car',
'red_circle',
'registered',
'relaxed',
'relieved',
'repeat',
'repeat_one',
'restroom',
'revolving_hearts',
'rewind',
'ribbon',
'rice',
'rice_ball',
'rice_cracker',
'rice_scene',
'ring',
'rocket',
'roller_coaster',
'rooster',
'rose',
'rotating_light',
'round_pushpin',
'rowboat',
'ru',
'rugby_football',
'runner',
'running',
'running_shirt_with_sash',
'sa',
'sagittarius',
'sailboat',
'sake',
'sandal',
'santa',
'satellite',
'satisfied',
'saxophone',
'school',
'school_satchel',
'scissors',
'scorpius',
'scream',
'scream_cat',
'scroll',
'seat',
'secret',
'see_no_evil',
'seedling',
'seven',
'shaved_ice',
'sheep',
'shell',
'ship',
'shipit',
'shirt',
'shit',
'shoe',
'shower',
'signal_strength',
'six',
'six_pointed_star',
'ski',
'skull',
'sleeping',
'sleepy',
'slot_machine',
'small_blue_diamond',
'small_orange_diamond',
'small_red_triangle',
'small_red_triangle_down',
'smile',
'smile_cat',
'smiley',
'smiley_cat',
'smiling_imp',
'smirk',
'smirk_cat',
'smoking',
'snail',
'snake',
'snowboarder',
'snowflake',
'snowman',
'sob',
'soccer',
'soon',
'sos',
'sound',
'space_invader',
'spades',
'spaghetti',
'sparkle',
'sparkler',
'sparkles',
'sparkling_heart',
'speak_no_evil',
'speaker',
'speech_balloon',
'speedboat',
'squirrel',
'star',
'star2',
'stars',
'station',
'statue_of_liberty',
'steam_locomotive',
'stew',
'straight_ruler',
'strawberry',
'stuck_out_tongue',
'stuck_out_tongue_closed_eyes',
'stuck_out_tongue_winking_eye',
'sun_with_face',
'sunflower',
'sunglasses',
'sunny',
'sunrise',
'sunrise_over_mountains',
'surfer',
'sushi',
'suspect',
'suspension_railway',
'sweat',
'sweat_drops',
'sweat_smile',
'sweet_potato',
'swimmer',
'symbols',
'syringe',
'tada',
'tanabata_tree',
'tangerine',
'taurus',
'taxi',
'tea',
'telephone',
'telephone_receiver',
'telescope',
'tennis',
'tent',
'thought_balloon',
'three',
'thumbsdown',
'thumbsup',
'ticket',
'tiger',
'tiger2',
'tired_face',
'tm',
'toilet',
'tokyo_tower',
'tomato',
'tongue',
'top',
'tophat',
'tractor',
'traffic_light',
'train',
'train2',
'tram',
'triangular_flag_on_post',
'triangular_ruler',
'trident',
'triumph',
'trolleybus',
'trollface',
'trophy',
'tropical_drink',
'tropical_fish',
'truck',
'trumpet',
'tshirt',
'tulip',
'turtle',
'tv',
'twisted_rightwards_arrows',
'two',
'two_hearts',
'two_men_holding_hands',
'two_women_holding_hands',
'u5272',
'u5408',
'u55b6',
'u6307',
'u6708',
'u6709',
'u6e80',
'u7121',
'u7533',
'u7981',
'u7a7a',
'uk',
'umbrella',
'unamused',
'underage',
'unlock',
'up',
'us',
'v',
'vertical_traffic_light',
'vhs',
'vibration_mode',
'video_camera',
'video_game',
'violin',
'virgo',
'volcano',
'vs',
'walking',
'waning_crescent_moon',
'waning_gibbous_moon',
'warning',
'watch',
'water_buffalo',
'watermelon',
'wave',
'wavy_dash',
'waxing_crescent_moon',
'waxing_gibbous_moon',
'wc',
'weary',
'wedding',
'whale',
'whale2',
'wheelchair',
'white_check_mark',
'white_circle',
'white_flower',
'white_large_square',
'white_medium_small_square',
'white_medium_square',
'white_small_square',
'white_square_button',
'wind_chime',
'wine_glass',
'wink',
'wolf',
'woman',
'womans_clothes',
'womans_hat',
'womens',
'worried',
'wrench',
'x',
'yellow_heart',
'yen',
'yum',
'zap',
'zero',
'zzz'
]
import AllGithubEmoji from './emoji-aliases.js'
// Emoji from All-Github-Emoji-Icons
// https://github.com/scotch-io/All-Github-Emoji-Icons
window.emojify = function (match, $1) {
return AllGithubEmoji.indexOf($1) === -1 ?
match :
'<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/' +
'<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
$1 +
'.png" alt="' +
$1 +
+3
View File
@@ -383,6 +383,9 @@ body.sticky
border-radius 2px
padding 1rem
.markdown-section ul.task-list > li
list-style-type none
body.close
.sidebar
transform translateX(- $sidebar-width)
+228
View File
@@ -0,0 +1,228 @@
@import url('https://fonts.googleapis.com/css?family=Thasadith:400,400i,700')
$color-primary = #00ffff
$color-bg = #f0ffff
$color-text = #34495e
$sidebar-width = 300px
@import 'basic/_layout'
@import 'basic/_coverpage'
body
background-color $color-bg
/* sidebar */
.sidebar
background-color $color-bg
color #364149
li
margin 6px 0 6px 0
ul li a
color #505d6b
font-size 14px
font-weight normal
overflow hidden
text-decoration none
text-overflow ellipsis
white-space nowrap
&:hover
text-decoration underline
ul li ul
padding 0
ul li.active > a
border-right 2px solid
color var(--theme-color, $color-primary)
font-weight 600
.app-sub-sidebar
li
&::before
content '-'
padding-right 4px
float left
/* markdown content found on pages */
.markdown-section h1, .markdown-section h2, .markdown-section h3, .markdown-section h4, .markdown-section strong
color #2c3e50
font-weight 600
.markdown-section a
color var(--theme-color, $color-primary)
font-weight 600
&:hover
text-decoration underline
.markdown-section h1
font-size 2rem
margin 0 0 1rem
.markdown-section h2
font-size 1.75rem
margin 45px 0 0.8rem
.markdown-section h3
font-size 1.5rem
margin 40px 0 0.6rem
.markdown-section h4
font-size 1.25rem
.markdown-section h5
font-size 1rem
.markdown-section h6
color #777
font-size 1rem
.markdown-section figure, .markdown-section p
margin 1.2em 0
.markdown-section p, .markdown-section ul, .markdown-section ol
line-height 1.6rem
word-spacing 0.05rem
.markdown-section ul, .markdown-section ol
padding-left 1.5rem
.markdown-section blockquote
border-left 4px solid var(--theme-color, $color-primary)
color #858585
margin 2em 0
padding-left 20px
.markdown-section blockquote p
font-weight 600
margin-left 0
.markdown-section iframe
margin 1em 0
.markdown-section em
color #7f8c8d
.markdown-section code
background-color #f8f8f8
border-radius 2px
color #e96900
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
margin 0 2px
padding 3px 5px
white-space pre-wrap
.markdown-section pre
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #f8f8f8
font-family 'Roboto Mono', Monaco, courier, monospace
line-height 1.5rem
margin 1.2em 0
overflow auto
padding 0 1.4rem
position relative
word-wrap normal
/* code highlight */
.token.comment, .token.prolog, .token.doctype, .token.cdata
color #8e908c
.token.namespace
opacity 0.7
.token.boolean, .token.number
color #c76b29
.token.punctuation
color #525252
.token.property
color #c08b30
.token.tag
color #2973b7
.token.string
color var(--theme-color, $color-primary)
.token.selector
color #6679cc
.token.attr-name
color #2973b7
.token.entity, .token.url, .language-css .token.string, .style .token.string
color #22a2c9
.token.attr-value, .token.control, .token.directive, .token.unit
color var(--theme-color, $color-primary)
.token.keyword, .token.function
color #e96900
.token.statement, .token.regex, .token.atrule
color #22a2c9
.token.placeholder, .token.variable
color #3d8fd1
.token.deleted
text-decoration line-through
.token.inserted
border-bottom 1px dotted #202746
text-decoration none
.token.italic
font-style italic
.token.important, .token.bold
font-weight bold
.token.important
color #c94922
.token.entity
cursor help
.markdown-section pre > code
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
background-color #f8f8f8
border-radius 2px
color #525252
display block
font-family 'Roboto Mono', Monaco, courier, monospace
font-size 0.8rem
line-height inherit
margin 0 2px
max-width inherit
overflow inherit
padding 2.2em 5px
white-space inherit
.markdown-section code::after, .markdown-section code::before
letter-spacing 0.05rem
code .token
-moz-osx-font-smoothing initial
-webkit-font-smoothing initial
min-height 1.5rem
pre::after
color #ccc
content attr(data-lang)
font-size 0.6rem
font-weight 600
height 15px
line-height 15px
padding 5px 10px 0
position absolute
right 0
text-align right
top 0
+74
View File
@@ -0,0 +1,74 @@
// load ES6 modules in Node.js on the fly
require = require('esm')(module/*, options*/)
const {expect} = require('chai')
const {JSDOM} = require('jsdom')
const XMLHttpRequest = require('xhr2') // JSDOM doesn't support XMLHttpRequest
// TODO: try to fix tests when using `<div id="app"></div>` in body
const markup = `<!DOCTYPE html>
<html>
<head></head>
<body></body>
</html>`
// TODO: this may not work if tests are mutate the DOM, instead a new instance needs to be created
// for every test case but that will slow down the tests
const dom = new JSDOM(markup)
global.window = dom.window
global.document = dom.window.document
global.navigator = dom.window.navigator
global.location = dom.window.location
global.XMLHttpRequest = XMLHttpRequest
const {initMixin} = require('../src/core/init')
const {routerMixin} = require('../src/core//router')
const {renderMixin} = require('../src/core//render')
const {fetchMixin} = require('../src/core/fetch')
const {eventMixin} = require('../src/core//event')
// mimic src/core/index.js but for Node.js
function Docsify() {
this._init()
}
const proto = Docsify.prototype
initMixin(proto)
routerMixin(proto)
renderMixin(proto)
fetchMixin(proto)
eventMixin(proto)
function ready(callback) {
const state = document.readyState
if (state === 'complete' || state === 'interactive') {
return setTimeout(callback, 0)
}
document.addEventListener('DOMContentLoaded', callback)
}
let docsify = null
module.exports.init = function(callback) {
return new Promise((resolve, reject) => {
// return cached version / TODO: see above: this might not scale, new instance of JSDOM is reqiured
if (docsify != null) {
return resolve(docsify)
}
ready(_ => {
docsify = new Docsify()
return resolve(docsify)
})
})
}
module.exports.expectSameDom = function(actual, expected) {
const WHITESPACES_BETWEEN_TAGS = />(\s\s+)</g
function replacer(match, group1) {
return match.replace(group1, '')
}
expect(actual.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
.equal(expected.replace(WHITESPACES_BETWEEN_TAGS, replacer).trim())
}
+89
View File
@@ -0,0 +1,89 @@
const path = require('path')
const {expect} = require('chai')
const {init, expectSameDom} = require('./_helper')
describe('render', function() {
it('important content (tips)', async function() {
docsify = await init()
const output = docsify.compiler.compile('!> **Time** is money, my friend!')
expect(output).equal('<p class="tip"><strong>Time</strong> is money, my friend!</p>')
})
describe('lists', function() {
it('as unordered task list', async function() {
docsify = await init()
const output = docsify.compiler.compile(`
- [x] Task 1
- [ ] Task 2
- [ ] Task 3`)
expect(output, `<ul class="task-list">
<li class="task-list-item"><label><input checked="" disabled="" type="checkbox"> Task 1</label></li>
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 2</label></li>
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 3</label></li>
</ul>`)
})
it('as ordered task list', async function() {
docsify = await init()
const output = docsify.compiler.compile(`
1. [ ] Task 1
2. [x] Task 2`)
expectSameDom(output, `<ol class="task-list">
<li class="task-list-item"><label><input disabled="" type="checkbox"> Task 1</label></li>
<li class="task-list-item"><label><input checked="" disabled="" type="checkbox"> Task 2</label></li>
</ol>`)
})
it('normal unordered', async function() {
docsify = await init()
const output = docsify.compiler.compile(`
- [linktext](link)
- just text`)
expectSameDom(output, `<ul >
<li><a href="#/link">linktext</a></li>
<li>just text</li>
</ul>`)
})
it('unordered with custom start', async function() {
docsify = await init()
const output = docsify.compiler.compile(`
1. first
2. second
text
3. third`)
expectSameDom(output, `<ol >
<li>first</li>
<li>second</li>
</ol>
<p>text</p>
<ol start="3">
<li>third</li>
</ol>`)
})
it('nested', async function() {
docsify = await init()
const output = docsify.compiler.compile(`
- 1
- 2
- 2 a
- 2 b
- 3`)
expectSameDom(output, `<ul >
<li>1</li>
<li>2<ul >
<li>2 a</li>
<li>2 b</li>
</ul>
</li>
<li>3</li>
</ul>`)
})
})
})