diff --git a/404.dev.html b/404.dev.html index a2b9beef8..18257df03 100644 --- a/404.dev.html +++ b/404.dev.html @@ -3,10 +3,10 @@ - + - +
- + diff --git a/CHANGELOG.md b/CHANGELOG.md index 860aabe1b..38cd6586a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 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. diff --git a/README.md b/README.md index fdc4adcf9..12c85e5f7 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,33 @@ Create a `404.html` and `README.md` into `/docs`. ``` +Or Create a `index.html` and using `hash router`. + +index.html + +```html + + + + + + + + + +``` + ## Showcase -These open-source projects are using docsify to generate their sites. +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 and clone! +- Fork it! - Run `npm i && npm run dev` +- open `localhost:3000` ## License MIT diff --git a/app.js b/app.js index c3b48bcf9..e960cf44d 100644 --- a/app.js +++ b/app.js @@ -7,6 +7,6 @@ http.createServer(function (req, res) { res.writeHead(404, { 'Content-Type': 'text/html' }) res.end(fs.readFileSync('404.dev.html')) }) -}).listen(3000) +}).listen(3000, '0.0.0.0') -console.log(`\nListening at http://localhost:3000\n`) +console.log(`\nListening at http://0.0.0.0:3000\n`) diff --git a/docs/README.md b/docs/README.md index 678b1c431..7aea75c19 100644 --- a/docs/README.md +++ b/docs/README.md @@ -213,8 +213,10 @@ If you write a sub level list, it will generate a dropdown list. - [chinese](/zh-cn) ``` -## FAQ +### router -### Why use `404.html` instead of `index.html` +Hash router. You can replace `404.html` with `index.html`. -[issues/7](https://github.com/QingWei-Li/docsify/issues/7) +```html + +``` diff --git a/docs/404.html b/docs/index.html similarity index 93% rename from docs/404.html rename to docs/index.html index 485fcec29..fdc506fc6 100644 --- a/docs/404.html +++ b/docs/index.html @@ -18,5 +18,6 @@ src="//unpkg.com/docsify/lib/docsify.min.js" data-repo="qingwei-li/docsify" data-max-level="3" - data-sidebar-toggle> + data-sidebar-toggle + data-router> diff --git a/docs/zh-cn.md b/docs/zh-cn.md index 150194440..726588f17 100644 --- a/docs/zh-cn.md +++ b/docs/zh-cn.md @@ -97,6 +97,10 @@ docsify serve docs ``` +### CDN + +目前可用的 CDN 有 [UNPKG](unpkg.com/docsify),如果觉得访问较慢可以将文件放到 Pages 的目录下。 + ### 配置参数 #### repo @@ -210,6 +214,14 @@ Sidebar 开关按钮 ``` +### router + +开启 hash router 功能,此时可以创建 `index.html` 作为入口文件,同时多页面切换不会重新加载资源。资源路径会被替换成 `/#/` 的形式。 + +```html + +``` + ## FAQ ### 为什么是 `404.html` 而不用 `index.html` diff --git a/lib/docsify.js b/lib/docsify.js index 216bed947..33fd3a73e 100644 --- a/lib/docsify.js +++ b/lib/docsify.js @@ -76,6 +76,29 @@ 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 +} + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; @@ -2231,9 +2254,11 @@ function scrollActiveSidebar () { for (var i = 0, len = lis.length; i < len; i += 1) { var li = lis[i]; - var a = li.querySelector('a'); + var href = li.querySelector('a').getAttribute('href'); - nav[a.getAttribute('href').slice(1)] = li; + if (href !== '/') { href = href.match(/#([^#]+)$/g)[0].slice(1); } + + nav[href] = li; } function highlight () { @@ -2244,8 +2269,7 @@ function scrollActiveSidebar () { if (bcr.top < 10 && bcr.bottom > 10) { var li = nav[node.id]; - if (!li) { return } - if (li === active) { return } + if (!li || li === active) { return } if (active) { active.setAttribute('class', ''); } li.setAttribute('class', 'active'); @@ -2260,9 +2284,9 @@ function scrollActiveSidebar () { highlight(); function scrollIntoView () { - var id = window.location.hash.slice(1); - if (!id) { return } - var section = document.querySelector('#' + id); + var id = window.location.hash.match(/#[^#\/]+$/g); + if (!id || !id.length) { return } + var section = document.querySelector(id[0]); if (section) { section.scrollIntoView(); } } @@ -2275,7 +2299,7 @@ function scrollActiveSidebar () { * Acitve link */ function activeLink (dom, activeParent) { - var host = document.location.origin + document.location.pathname; + var host = window.location.href; dom = typeof dom === 'object' ? dom : document.querySelector(dom); if (!dom) { return @@ -2285,6 +2309,10 @@ function activeLink (dom, activeParent) { activeParent ? node.parentNode.setAttribute('class', 'active') : node.setAttribute('class', 'active'); + } else { + activeParent + ? node.parentNode.removeAttribute('class') + : node.removeAttribute('class'); } }); } @@ -2305,6 +2333,8 @@ function bindToggle (dom) { }); } +var OPTIONS$1 = {}; + var renderTo = function (dom, content) { dom = typeof dom === 'object' ? dom : document.querySelector(dom); dom.innerHTML = content; @@ -2319,11 +2349,16 @@ var renderer = new marked.Renderer(); * @link https://github.com/chjj/marked#overriding-renderer-methods */ renderer.heading = function (text, level) { - var slug = text.toLowerCase().replace(/<(?:.|\n)*?>/gm, '').replace(/[\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 ("" + text + "") + toc.push({ level: level, slug: (route + "#" + slug), title: text }); + + return ("" + text + "") }; // highlight code renderer.code = function (code, lang) { @@ -2333,15 +2368,22 @@ renderer.code = function (code, lang) { return ("
" + hl + "
") }; +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 ("" + text + "") +}; marked.setOptions({ renderer: renderer }); /** * App */ -function renderApp (dom, replace, opts) { +function renderApp (dom, replace) { var nav = document.querySelector('nav') || document.createElement('nav'); - dom[replace ? 'outerHTML' : 'innerHTML'] = toggle(opts.sidebarToggle) + corner(opts.repo) + main(); + dom[replace ? 'outerHTML' : 'innerHTML'] = toggle(OPTIONS$1.sidebarToggle) + corner(OPTIONS$1.repo) + main(); document.body.insertBefore(nav, document.body.children[0]); // bind toggle @@ -2351,18 +2393,18 @@ function renderApp (dom, replace, opts) { /** * article */ -function renderArticle (content, OPTIONS) { +function renderArticle (content) { renderTo('article', content ? marked(content) : 'not found'); - if (!renderSidebar.rendered) { renderSidebar(null, OPTIONS); } - if (!renderNavbar.rendered) { renderNavbar(null, OPTIONS); } + if (!renderSidebar.rendered) { renderSidebar(null, OPTIONS$1); } + if (!renderNavbar.rendered) { renderNavbar(null, OPTIONS$1); } + renderSidebar.rendered = false; + renderNavbar.rendered = false; } /** * navbar */ -function renderNavbar (content, OPTIONS) { - if ( OPTIONS === void 0 ) OPTIONS = {}; - +function renderNavbar (content) { renderNavbar.rendered = true; if (content) { renderTo('nav', marked(content)); } @@ -2372,24 +2414,27 @@ function renderNavbar (content, OPTIONS) { /** * sidebar */ -function renderSidebar (content, OPTIONS) { - if ( OPTIONS === void 0 ) OPTIONS = {}; - +function renderSidebar (content) { renderSidebar.rendered = true; var isToc = false; if (content) { content = marked(content); - } else if (OPTIONS.sidebar) { - content = tree(OPTIONS.sidebar, '