mirror of
https://github.com/docsifyjs/docsify.git
synced 2025-12-08 19:55:52 +00:00
Add new markdown grammar & improve sidebar performance.
This commit is contained in:
parent
9defe1bf7d
commit
ef53a07f49
@ -1,3 +1,8 @@
|
||||
## 1.6.0
|
||||
### Features
|
||||
- Improve sidebar performance. The active item is automatically scrolled in the visible view.
|
||||
- New markdown grammar: `! `. e.g. `! content` will be rendered as `<p class="tip">content</p>`
|
||||
|
||||
## 1.5.2
|
||||
### Bug fixes
|
||||
- Fixed number at the beginning of the slug
|
||||
|
||||
@ -351,11 +351,14 @@ Scroll to the top on changing hash.
|
||||
|
||||
```html
|
||||
<script src="/lib/docsify.js" data-auto2top></script>
|
||||
<!-- Set offset top -->
|
||||
<script src="/lib/docsify.js" data-auto2top="50"></script>
|
||||
```
|
||||
|
||||
```js
|
||||
window.$docsify = {
|
||||
auto2top: true
|
||||
auto2top: true,
|
||||
// auto2top: 50
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
60
src/event.js
60
src/event.js
@ -7,10 +7,12 @@ import { isMobile } from './util'
|
||||
export function scrollActiveSidebar () {
|
||||
if (isMobile()) return
|
||||
|
||||
let hoveredOverSidebar = false
|
||||
const anchors = document.querySelectorAll('.anchor')
|
||||
const sidebar = document.querySelector('aside.sidebar')
|
||||
const nav = {}
|
||||
const lis = document.querySelectorAll('.sidebar li')
|
||||
let active = null
|
||||
const lis = sidebar.querySelectorAll('li')
|
||||
let active = sidebar.querySelector('li.active')
|
||||
|
||||
for (let i = 0, len = lis.length; i < len; i += 1) {
|
||||
const li = lis[i]
|
||||
@ -25,27 +27,34 @@ export function scrollActiveSidebar () {
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
const top = document.body.scrollTop
|
||||
let last
|
||||
|
||||
for (let i = 0, len = anchors.length; i < len; i += 1) {
|
||||
const node = anchors[i]
|
||||
const bcr = node.getBoundingClientRect()
|
||||
|
||||
if (bcr.top < 10 && bcr.bottom > 10) {
|
||||
const li = nav[node.getAttribute('data-id')]
|
||||
|
||||
if (!li || li === active) return
|
||||
if (active) active.setAttribute('class', '')
|
||||
|
||||
li.setAttribute('class', 'active')
|
||||
active = li
|
||||
|
||||
return
|
||||
if (node.offsetTop > top) {
|
||||
if (!last) last = node
|
||||
break
|
||||
} else {
|
||||
last = node
|
||||
}
|
||||
}
|
||||
if (!last) return
|
||||
const li = nav[last.getAttribute('data-id')]
|
||||
|
||||
if (!li || li === active) return
|
||||
if (active) active.classList.remove('active')
|
||||
|
||||
li.classList.add('active')
|
||||
active = li
|
||||
!hoveredOverSidebar && active.scrollIntoView()
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', highlight)
|
||||
window.addEventListener('scroll', highlight)
|
||||
highlight()
|
||||
sidebar.addEventListener('mouseover', () => { hoveredOverSidebar = true })
|
||||
sidebar.addEventListener('mouseleave', () => { hoveredOverSidebar = false })
|
||||
}
|
||||
|
||||
export function scrollIntoView () {
|
||||
@ -53,7 +62,9 @@ export function scrollIntoView () {
|
||||
if (!id || !id.length) return
|
||||
const section = document.querySelector(decodeURIComponent(id[0]))
|
||||
|
||||
if (section) section.scrollIntoView()
|
||||
if (section) setTimeout(() => section.scrollIntoView(), 0)
|
||||
|
||||
return section
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,13 +82,13 @@ export function activeLink (dom, activeParent) {
|
||||
.forEach(node => {
|
||||
if (host.indexOf(node.href) === 0 && !target) {
|
||||
activeParent
|
||||
? node.parentNode.setAttribute('class', 'active')
|
||||
: node.setAttribute('class', 'active')
|
||||
? node.parentNode.classList.add('active')
|
||||
: node.classList.add('active')
|
||||
target = node
|
||||
} else {
|
||||
activeParent
|
||||
? node.parentNode.removeAttribute('class')
|
||||
: node.removeAttribute('class')
|
||||
? node.parentNode.classList.remove('active')
|
||||
: node.classList.remove('active')
|
||||
}
|
||||
})
|
||||
|
||||
@ -95,13 +106,16 @@ export function bindToggle (dom) {
|
||||
dom.addEventListener('click', () => body.classList.toggle('close'))
|
||||
|
||||
if (isMobile()) {
|
||||
document.querySelector('aside')
|
||||
.addEventListener('click', _ => body.classList.toggle('close'))
|
||||
const sidebar = document.querySelector('aside.sidebar')
|
||||
document.body.addEventListener('click', e => {
|
||||
if (e.target !== dom && !dom.contains(e.target)) body.classList.toggle('close')
|
||||
if (sidebar.contains(e.target)) setTimeout(() => activeLink(sidebar, true), 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function scroll2Top () {
|
||||
document.body.scrollTop = 0
|
||||
export function scroll2Top (offset = 0) {
|
||||
document.body.scrollTop = offset === true ? 0 : Number(offset)
|
||||
}
|
||||
|
||||
export function sticky () {
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import * as tpl from './tpl'
|
||||
import { activeLink, scrollActiveSidebar, bindToggle, scroll2Top, sticky } from './event'
|
||||
import * as event from './event'
|
||||
import { genTree, getRoute, isMobile, slugify, merge } from './util'
|
||||
|
||||
let OPTIONS = {}
|
||||
let markdown = marked
|
||||
let toc = []
|
||||
const CACHE = {}
|
||||
const TIP_RE = /^!\s/
|
||||
|
||||
const renderTo = function (dom, content) {
|
||||
dom = typeof dom === 'object' ? dom : document.querySelector(dom)
|
||||
@ -55,6 +56,10 @@ export function init (options) {
|
||||
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
}
|
||||
renderer.paragraph = function (text) {
|
||||
const isTip = TIP_RE.test(text)
|
||||
return isTip ? `<p class="tip">${text.replace(TIP_RE, '')}</p>` : `<p>${text}</p>`
|
||||
}
|
||||
|
||||
if (typeof OPTIONS.markdown === 'function') {
|
||||
markdown.setOptions({ renderer })
|
||||
@ -78,10 +83,10 @@ export function renderApp (dom, replace) {
|
||||
document.body.insertBefore(nav, document.body.children[0])
|
||||
|
||||
// bind toggle
|
||||
bindToggle('button.sidebar-toggle')
|
||||
event.bindToggle('button.sidebar-toggle')
|
||||
// bind sticky effect
|
||||
if (OPTIONS.coverpage) {
|
||||
!isMobile() && window.addEventListener('scroll', sticky)
|
||||
!isMobile() && window.addEventListener('scroll', event.sticky)
|
||||
} else {
|
||||
document.body.classList.add('sticky')
|
||||
}
|
||||
@ -96,9 +101,9 @@ export function renderArticle (content) {
|
||||
|
||||
if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') {
|
||||
const vm = new Vue({ el: 'main' }) // eslint-disable-line
|
||||
vm.$nextTick(_ => scrollActiveSidebar())
|
||||
vm.$nextTick(_ => event.scrollActiveSidebar())
|
||||
}
|
||||
if (OPTIONS.auto2top) scroll2Top()
|
||||
if (OPTIONS.auto2top) setTimeout(() => event.scroll2Top(OPTIONS.auto2top), 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +114,7 @@ export function renderNavbar (content) {
|
||||
CACHE.navbar = content
|
||||
|
||||
if (content) renderTo('nav', markdown(content))
|
||||
activeLink('nav')
|
||||
event.activeLink('nav')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,11 +132,11 @@ export function renderSidebar (content) {
|
||||
}
|
||||
|
||||
renderTo('aside.sidebar', html)
|
||||
const target = activeLink('aside.sidebar', true)
|
||||
if (content) renderSubSidebar(target)
|
||||
const target = event.activeLink('aside.sidebar', true)
|
||||
if (target) renderSubSidebar(target)
|
||||
toc = []
|
||||
|
||||
scrollActiveSidebar()
|
||||
event.scrollActiveSidebar()
|
||||
}
|
||||
|
||||
export function renderSubSidebar (target) {
|
||||
@ -171,7 +176,7 @@ export function renderCover (content) {
|
||||
renderTo('.cover-main', html)
|
||||
renderCover.rendered = true
|
||||
|
||||
sticky()
|
||||
event.sticky()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -291,6 +291,40 @@ body.sticky {
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-section p.tip {
|
||||
padding: 12px 24px 12px 30px;
|
||||
margin: 2em 0;
|
||||
border-left: 4px solid #f66;
|
||||
background-color: #f8f8f8;
|
||||
position: relative;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: -12px;
|
||||
background-color: #f66;
|
||||
color: $color-bg;
|
||||
content: "!";
|
||||
size: 20px;
|
||||
border-radius: 100%;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
font-weight: bold;
|
||||
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
em {
|
||||
color: $color-text;
|
||||
}
|
||||
}
|
||||
|
||||
body.close {
|
||||
.sidebar {
|
||||
transform: translateX(-$sidebar-width);
|
||||
|
||||
@ -238,15 +238,3 @@ code .token {
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
}
|
||||
|
||||
.content span.light {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.content span.info {
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
margin-left: 20px;
|
||||
vertical-align: middle;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
@ -285,15 +285,3 @@ pre::after {
|
||||
text-align: right;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.content span.light {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.content span.info {
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
margin-left: 20px;
|
||||
vertical-align: middle;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user