diff --git a/README.md b/README.md index dd7de59..3e7554c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - Smart full-text search plugin - Multiple themes - Useful plugin API -- Compatible with IE9+ +- Compatible with IE10+ ## Quick start Create a `index.html`. diff --git a/build/build.js b/build/build.js index cbeefc9..96adf07 100644 --- a/build/build.js +++ b/build/build.js @@ -27,34 +27,39 @@ var build = function (opts) { } build({ - entry: 'index.js', + entry: 'core/index.js', output: 'docsify.js', plugins: [commonjs(), nodeResolve()] }) -isProd && build({ - entry: 'index.js', - output: 'docsify.min.js', - plugins: [commonjs(), nodeResolve(), uglify()] -}) -build({ - entry: 'plugins/search.js', - output: 'plugins/search.js', - moduleName: 'D.Search' -}) -isProd && build({ - entry: 'plugins/search.js', - output: 'plugins/search.min.js', - moduleName: 'D.Search', - plugins: [uglify()] -}) -build({ - entry: 'plugins/ga.js', - output: 'plugins/ga.js', - moduleName: 'D.GA' -}) -isProd && build({ - entry: 'plugins/ga.js', - output: 'plugins/ga.min.js', - moduleName: 'D.GA', - plugins: [uglify()] -}) + +// build({ +// entry: 'plugins/search.js', +// output: 'plugins/search.js', +// moduleName: 'D.Search' +// }) + +// build({ +// entry: 'plugins/ga.js', +// output: 'plugins/ga.js', +// moduleName: 'D.GA' +// }) + +if (isProd) { + build({ + entry: 'index.js', + output: 'docsify.min.js', + plugins: [commonjs(), nodeResolve(), uglify()] + }) + build({ + entry: 'plugins/search.js', + output: 'plugins/search.min.js', + moduleName: 'D.Search', + plugins: [uglify()] + }) + build({ + entry: 'plugins/ga.js', + output: 'plugins/ga.min.js', + moduleName: 'D.GA', + plugins: [uglify()] + }) +} diff --git a/docs/README.md b/docs/README.md index 529c54b..51f2506 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,7 +15,7 @@ See the [Quick start](/quickstart) for more details. - Smart full-text search plugin - Multiple themes - Useful plugin API -- Compatible with IE9+ +- Compatible with IE10+ ## Examples diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md index e5051b1..5f6e9fa 100644 --- a/docs/zh-cn/README.md +++ b/docs/zh-cn/README.md @@ -16,7 +16,7 @@ docsify 是一个动态生成文档网站的工具。不同于 GitBook、Hexo - 智能的全文搜索 - 提供多套主题 - 丰富的 API -- 兼容 IE9+ +- 兼容 IE10+ ## 例子 diff --git a/src/core/config.js b/src/core/config.js index d344aae..d11c3d1 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -17,7 +17,9 @@ const config = merge({ ga: '' }, window.$docsify) -const script = document.currentScript || [].slice.call(document.getElementsByTagName('script')).pop() +const script = document.currentScript || + [].slice.call(document.getElementsByTagName('script')) + .filter(n => /docsify\./.test(n.src))[0] if (script) { for (const prop in config) { diff --git a/src/core/event/index.js b/src/core/event/index.js index 46d9d28..a31188b 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -1,11 +1,19 @@ -export function eventMixin (Docsify) { - Docsify.prototype.$bindEvents = function () { - } +import { isMobile } from '../util/env' +import { dom, on } from '../util/dom' +import * as sidebar from './sidebar' +export function eventMixin (Docsify) { Docsify.prototype.$resetEvents = function () { } } export function initEvent (vm) { - vm.$bindEvents() + // Bind toggle button + sidebar.btn('button.sidebar-toggle') + // Bind sticky effect + if (vm.config.coverpage) { + !isMobile && on('scroll', sidebar.sticky) + } else { + dom.body.classList.add('sticky') + } } diff --git a/src/core/event/scroll.js b/src/core/event/scroll.js new file mode 100644 index 0000000..b79589b --- /dev/null +++ b/src/core/event/scroll.js @@ -0,0 +1,10 @@ +export function activeSidebar () { + +} + +export function scrollIntoView () { + +} + +export function scroll2Top () { +} diff --git a/src/core/event/sidebar.js b/src/core/event/sidebar.js new file mode 100644 index 0000000..aeaeeed --- /dev/null +++ b/src/core/event/sidebar.js @@ -0,0 +1,28 @@ +import { isMobile } from '../util/env' +import { getNode, on, dom } from '../util/dom' +/** + * Toggle button + */ +export function btn (el) { + const toggle = () => dom.body.classList.toggle('close') + + el = getNode(el) + on(el, 'click', toggle) + + if (isMobile) { + const sidebar = getNode('.sidebar') + + on(sidebar, 'click', () => { + toggle() + setTimeout(() => activeLink(sidebar, true), 0) + }) + } +} + +export function sticky () { + +} + +export function activeLink () { + +} diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index 7771e89..61acc81 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -1,7 +1,8 @@ import { callHook } from '../init/lifecycle' export function fetchMixin (Docsify) { - Docsify.prototype.$fetch = function () { + Docsify.prototype.$fetch = function (path) { + // 加载侧边栏、导航、内容 } } diff --git a/src/core/init/index.js b/src/core/init/index.js index 8a6c2a3..826e6ef 100644 --- a/src/core/init/index.js +++ b/src/core/init/index.js @@ -9,7 +9,7 @@ import { isFn } from '../util/core' export function initMixin (Docsify) { Docsify.prototype._init = function () { const vm = this - vm._config = config || {} + vm.config = config || {} initLifecycle(vm) // Init hooks initPlugin(vm) // Install plugins @@ -23,5 +23,5 @@ export function initMixin (Docsify) { } function initPlugin (vm) { - [].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm.bindHook)) + [].concat(vm.config.plugins).forEach(fn => isFn(fn) && fn(vm._lifecycle, vm)) } diff --git a/src/core/init/lifecycle.js b/src/core/init/lifecycle.js index e4a48a8..380bac1 100644 --- a/src/core/init/lifecycle.js +++ b/src/core/init/lifecycle.js @@ -4,10 +4,10 @@ export function initLifecycle (vm) { const hooks = ['init', 'beforeEach', 'afterEach', 'doneEach', 'ready'] vm._hooks = {} - vm.bindHook = {} + vm._lifecycle = {} hooks.forEach(hook => { const arr = vm._hooks[hook] = [] - vm._bindHook[hook] = fn => arr.push(fn) + vm._lifecycle[hook] = fn => arr.push(fn) }) } diff --git a/src/core/render/dom.js b/src/core/render/dom.js deleted file mode 100644 index 8277095..0000000 --- a/src/core/render/dom.js +++ /dev/null @@ -1,12 +0,0 @@ -const cacheNode = {} - -export function getCacheNode (el) { - if (typeof el === 'string') { - const selector = el - - el = cacheNode[el] || document.querySelector(el) - if (!el) console.error('Cannot find element:', selector) - } - - return el -} diff --git a/src/core/render/index.js b/src/core/render/index.js index 03ef3f0..12f50c5 100644 --- a/src/core/render/index.js +++ b/src/core/render/index.js @@ -1,9 +1,47 @@ -export function renderMixin (Docsify) { - Docsify.prototype._renderTo = function (dom, content) { +import { getNode, dom } from '../util/dom' +import cssVars from '../util/polyfill/css-vars' +import * as tpl from './tpl' +export function renderMixin (Docsify) { + Docsify.prototype._renderTo = function (el, content, replace) { + const node = getNode(el) + if (node) node[replace ? 'outerHTML' : 'innerHTML'] = content } } export function initRender (vm) { - // init + const config = vm.config + const id = config.el || '#app' + const navEl = dom.find('nav') || dom.create('nav') + + let el = dom.find(id) + let html = '' + + navEl.classList.add('app-nav') + + if (!config.repo) { + navEl.classList.add('no-badge') + } + if (!el) { + el = dom.create(id) + dom.appendTo(dom.body, el) + } + if (config.repo) { + html += tpl.corner(config.repo) + } + if (config.coverpage) { + html += tpl.cover() + } + + html += tpl.main(config) + // Render main app + vm._renderTo(el, html, true) + // Add nav + dom.body.insertBefore(navEl, dom.body.children[0]) + + if (config.themeColor) { + dom.head += tpl.theme(config.themeColor) + // Polyfll + cssVars(config.themeColor) + } } diff --git a/src/core/render/progressbar.js b/src/core/render/progressbar.js index 1da5b22..8eff66b 100644 --- a/src/core/render/progressbar.js +++ b/src/core/render/progressbar.js @@ -1,3 +1,4 @@ +import { dom } from '../util/dom' import { isPrimitive } from '../util/core' let loadingEl @@ -8,10 +9,10 @@ let timeId */ function init () { if (loadingEl) return - const div = document.createElement('div') + const div = dom.create('div') div.classList.add('progress') - document.body.appendChild(div) + dom.appendTo(div, dom.body) loadingEl = div } /** diff --git a/src/core/render/tpl.js b/src/core/render/tpl.js index df58979..cdf870d 100644 --- a/src/core/render/tpl.js +++ b/src/core/render/tpl.js @@ -1,4 +1,4 @@ -import { isMobile } from '../util/core' +import { isMobile } from '../util/env' /** * Render github corner * @param {Object} data @@ -9,27 +9,38 @@ export function corner (data) { if (!/\/\//.test(data)) data = 'https://github.com/' + data data = data.replace(/^git\+/, '') - return ` - - - ` + return ( + '' + + '' + + '`') } /** * Render main content */ -export function main () { - const aside = `${toggle()}` +export function main (config) { + const aside = ( + '' + + '') - return (isMobile() ? `${aside}
` : `
${aside}`) + - `
-
-
-
` + return (isMobile ? `${aside}
` : `
${aside}`) + + '
' + + '
' + + '
' + + '
' } /** @@ -37,20 +48,14 @@ export function main () { */ export function cover () { const SL = ', 100%, 85%' - const bgc = `linear-gradient(to left bottom, hsl(${Math.floor(Math.random() * 255) + SL}) 0%, hsl(${Math.floor(Math.random() * 255) + SL}) 100%)` + const bgc = 'linear-gradient(to left bottom, ' + + `hsl(${Math.floor(Math.random() * 255) + SL}) 0%,` + + `hsl(${Math.floor(Math.random() * 255) + SL}) 100%)` - return `
-
-
-
` -} - -export function toggle () { - return `` + return `
` + + '
' + + '
' + + '
' } /** diff --git a/src/core/route/hash.js b/src/core/route/hash.js index 90d180c..1f544d4 100644 --- a/src/core/route/hash.js +++ b/src/core/route/hash.js @@ -1,5 +1,4 @@ -import { cleanPath, getLocation } from './util' - +// import { cleanPath, getLocation } from './util' export function ensureSlash () { const path = getHash() if (path.charAt(0) === '/') return diff --git a/src/core/util/dom.js b/src/core/util/dom.js new file mode 100644 index 0000000..2232219 --- /dev/null +++ b/src/core/util/dom.js @@ -0,0 +1,41 @@ +import { isFn } from '../util/core' + +const cacheNode = {} + +/** + * Get Node + * @param {String|Element} el + * @param {Boolean} noCache + * @return {Element} + */ +export function getNode (el, noCache = false) { + if (typeof el === 'string') { + el = noCache ? dom.find(el) : (cacheNode[el] || dom.find(el)) + } + + return el +} + +export const dom = { + body: document.body, + head: document.head, + find: node => document.querySelector(node), + findAll: node => document.querySelectorAll(node), + create: (node, tpl) => { + node = document.createElement(node) + if (tpl) node.innerHTML = tpl + }, + appendTo: (target, el) => target.appendChild(el) +} + +export function on (el, type, handler) { + isFn(type) + ? window.addEventListener(el, type) + : el.addEventListener(type, handler) +} + +export const off = function on (el, type, handler) { + isFn(type) + ? window.removeEventListener(el, type) + : el.removeEventListener(type, handler) +} diff --git a/src/core/util/index.js b/src/core/util/index.js index bfcc8b2..38687ba 100644 --- a/src/core/util/index.js +++ b/src/core/util/index.js @@ -1,2 +1,3 @@ export * from './core' export * from './env' +export * from './dom' diff --git a/src/core/util/polyfill/css-vars.js b/src/core/util/polyfill/css-vars.js index f0200e6..686ad72 100644 --- a/src/core/util/polyfill/css-vars.js +++ b/src/core/util/polyfill/css-vars.js @@ -1,29 +1,32 @@ -import { get } from '../fetch/ajax' +import { dom } from '../dom' +import { get } from '../../fetch/ajax' -function replaceVar (block) { - block.innerHTML = block.innerHTML.replace(/var\(\s*--theme-color.*?\)/g, $docsify.themeColor) +function replaceVar (block, themeColor) { + block.innerHTML = block.innerHTML + .replace(/var\(\s*--theme-color.*?\)/g, themeColor) } -export function cssVars () { - // variable support - if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) return +export default function (themeColor) { + // Variable support + if (window.CSS + && window.CSS.supports + && window.CSS.supports('(--foo: red)')) return - const styleBlocks = document.querySelectorAll('style:not(.inserted),link') + const styleBlocks = dom.findAll('style:not(.inserted),link') ;[].forEach.call(styleBlocks, block => { if (block.nodeName === 'STYLE') { - replaceVar(block) + replaceVar(block, themeColor) } else if (block.nodeName === 'LINK') { const href = block.getAttribute('href') if (!/\.css$/.test(href)) return get(href).then(res => { - const style = document.createElement('style') + const style = dom.create('style', res) - style.innerHTML = res - document.head.appendChild(style) - replaceVar(style) + dom.head.appendChild(style) + replaceVar(style, themeColor) }) } }) diff --git a/src/themes/basic/_layout.css b/src/themes/basic/_layout.css index e194aff..d413c10 100644 --- a/src/themes/basic/_layout.css +++ b/src/themes/basic/_layout.css @@ -64,7 +64,7 @@ kbd { } /* navbar */ -nav { +nav.app-nav { position: absolute; right: 0; left: 0;