import marked from 'marked'
import Prism from 'prismjs'
import * as tpl from './tpl'
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)
dom.innerHTML = content
slugify.clear()
return dom
}
/**
* init render
* @param {Object} options
*/
export function init (options) {
OPTIONS = options
const renderer = new marked.Renderer()
/**
* render anchor tag
* @link https://github.com/chjj/marked#overriding-renderer-methods
*/
renderer.heading = function (text, level) {
const slug = slugify(text)
let route = ''
if (OPTIONS.router) {
route = `#/${getRoute()}`
}
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
return `
${hl}
`
}
renderer.link = function (href, title, text) {
if (OPTIONS.router && !/:/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
}
return `${text}`
}
renderer.paragraph = function (text) {
const isTip = TIP_RE.test(text)
return isTip ? `${text.replace(TIP_RE, '')}
` : `${text}
` } if (typeof OPTIONS.markdown === 'function') { markdown.setOptions({ renderer }) markdown = OPTIONS.markdown.call(this, markdown) } else { markdown.setOptions(merge({ renderer }, OPTIONS.markdown)) } } /** * App */ export function renderApp (dom, replace) { const nav = document.querySelector('nav') || document.createElement('nav') if (!OPTIONS.repo) nav.classList.add('no-badge') dom[replace ? 'outerHTML' : 'innerHTML'] = tpl.corner(OPTIONS.repo) + (OPTIONS.coverpage ? tpl.cover() : '') + tpl.main(OPTIONS.sidebarToggle ? tpl.toggle() : '') document.body.insertBefore(nav, document.body.children[0]) // bind toggle event.bindToggle('button.sidebar-toggle') // bind sticky effect if (OPTIONS.coverpage) { !isMobile() && window.addEventListener('scroll', event.sticky) } else { document.body.classList.add('sticky') } } /** * article */ export function renderArticle (content) { renderTo('article', content ? markdown(content) : 'not found') if (!OPTIONS.sidebar && !OPTIONS.loadSidebar) renderSidebar() if (content && typeof Vue !== 'undefined' && typeof Vuep !== 'undefined') { const vm = new Vue({ el: 'main' }) // eslint-disable-line vm.$nextTick(_ => event.scrollActiveSidebar()) } if (OPTIONS.auto2top) setTimeout(() => event.scroll2Top(OPTIONS.auto2top), 0) } /** * navbar */ export function renderNavbar (content) { if (CACHE.navbar && CACHE.navbar === content) return CACHE.navbar = content if (content) renderTo('nav', markdown(content)) event.activeLink('nav') } /** * sidebar */ export function renderSidebar (content) { let html if (content) { html = markdown(content) // find url tag html = html.match(/([^<]*?)