refactor(core): and markdown compiler
This commit is contained in:
parent
30da0d5d46
commit
fe88c154b0
12 changed files with 194 additions and 232 deletions
|
|
@ -1,26 +1,56 @@
|
|||
import marked from 'marked'
|
||||
import Prism from 'prismjs'
|
||||
import { helper as helperTpl } from './tpl'
|
||||
import { slugify, clearSlugCache } from './slugify'
|
||||
import { emojify } from './emojify'
|
||||
import { toURL } from '../route/hash'
|
||||
import { isFn, merge, cached } from '../util/core'
|
||||
|
||||
export const renderer = new marked.Renderer()
|
||||
|
||||
export function markdown () {
|
||||
|
||||
}
|
||||
let markdownCompiler = marked
|
||||
let contentBase = ''
|
||||
let renderer = new marked.Renderer()
|
||||
|
||||
const toc = []
|
||||
|
||||
/**
|
||||
* Compile markdown content
|
||||
*/
|
||||
export const markdown = cached(text => {
|
||||
let html = ''
|
||||
|
||||
if (!text) return text
|
||||
|
||||
html = markdownCompiler(text)
|
||||
html = emojify(html)
|
||||
clearSlugCache()
|
||||
|
||||
return html
|
||||
})
|
||||
|
||||
markdown.renderer = renderer
|
||||
|
||||
markdown.init = function (config = {}, context = window.location.pathname) {
|
||||
contentBase = context
|
||||
|
||||
if (isFn(config)) {
|
||||
markdownCompiler = config(marked, renderer)
|
||||
} else {
|
||||
renderer = merge(renderer, config.renderer)
|
||||
marked.setOptions(merge(config, { renderer }))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* render anchor tag
|
||||
* @link https://github.com/chjj/marked#overriding-renderer-methods
|
||||
*/
|
||||
renderer.heading = function (text, level) {
|
||||
const slug = slugify(text)
|
||||
let route = ''
|
||||
const url = toURL(contentBase, { id: slug })
|
||||
|
||||
route = `#/${getRoute()}`
|
||||
toc.push({ level, slug: `${route}#${encodeURIComponent(slug)}`, title: text })
|
||||
toc.push({ level, slug: url, title: text })
|
||||
|
||||
return `<h${level} id="${slug}"><a href="${route}#${slug}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
|
||||
return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
|
||||
}
|
||||
// highlight code
|
||||
renderer.code = function (code, lang = '') {
|
||||
|
|
@ -30,21 +60,31 @@ renderer.code = function (code, lang = '') {
|
|||
}
|
||||
renderer.link = function (href, title, text) {
|
||||
if (!/:|(\/{2})/.test(href)) {
|
||||
// TODO
|
||||
href = `#/${href}`.replace(/\/+/g, '/')
|
||||
}
|
||||
return `<a href="${href}" title="${title || ''}">${text}</a>`
|
||||
}
|
||||
renderer.paragraph = function (text) {
|
||||
if (/^!>/.test(text)) {
|
||||
return tpl.helper('tip', text)
|
||||
return helperTpl('tip', text)
|
||||
} else if (/^\?>/.test(text)) {
|
||||
return tpl.helper('warn', text)
|
||||
return helperTpl('warn', text)
|
||||
}
|
||||
return `<p>${text}</p>`
|
||||
}
|
||||
renderer.image = function (href, title, text) {
|
||||
const url = /:|(\/{2})/.test(href) ? href : ($docsify.basePath + href).replace(/\/+/g, '/')
|
||||
const titleHTML = title ? ` title="${title}"` : ''
|
||||
// TODO
|
||||
// get base path
|
||||
// const url = /:|(\/{2})/.test(href) ? href : ($docsify.basePath + href).replace(/\/+/g, '/')
|
||||
// const titleHTML = title ? ` title="${title}"` : ''
|
||||
|
||||
// return `<img src="${url}" alt="${text}"${titleHTML} />`
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile sidebar
|
||||
*/
|
||||
export function sidebar (text) {
|
||||
|
||||
return `<img src="${url}" alt="${text}"${titleHTML} />`
|
||||
}
|
||||
|
|
|
|||
6
src/core/render/emojify.js
Normal file
6
src/core/render/emojify.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export function emojify (text) {
|
||||
return text
|
||||
.replace(/<(pre|template)[^>]*?>([\s\S]+)<\/(pre|template)>/g, m => m.replace(/:/g, '__colon__'))
|
||||
.replace(/:(\w+?):/ig, '<img class="emoji" src="https://assets-cdn.github.com/images/icons/emoji/$1.png" alt="$1" />')
|
||||
.replace(/__colon__/g, ':')
|
||||
}
|
||||
27
src/core/render/gen-tree.js
Normal file
27
src/core/render/gen-tree.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* gen toc tree
|
||||
* @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
|
||||
* @param {Array} toc
|
||||
* @param {Number} maxLevel
|
||||
* @return {Array}
|
||||
*/
|
||||
export function genTree (toc, maxLevel) {
|
||||
const headlines = []
|
||||
const last = {}
|
||||
|
||||
toc.forEach(headline => {
|
||||
const level = headline.level || 1
|
||||
const len = level - 1
|
||||
|
||||
if (level > maxLevel) return
|
||||
if (last[len]) {
|
||||
last[len].children = last[len].children || []
|
||||
last[len].children.push(headline)
|
||||
} else {
|
||||
headlines.push(headline)
|
||||
}
|
||||
last[level] = headline
|
||||
})
|
||||
|
||||
return headlines
|
||||
}
|
||||
|
|
@ -1,30 +1,47 @@
|
|||
import * as dom from '../util/dom'
|
||||
import cssVars from '../util/polyfill/css-vars'
|
||||
import * as tpl from './tpl'
|
||||
import { markdown, sidebar } from './compiler'
|
||||
import { callHook } from '../init/lifecycle'
|
||||
|
||||
function renderMain () {
|
||||
|
||||
}
|
||||
|
||||
function renderNav () {
|
||||
}
|
||||
|
||||
function renderSidebar () {
|
||||
function renderMain (html) {
|
||||
if (!html) {
|
||||
// TODO: Custom 404 page
|
||||
}
|
||||
this._renderTo('.markdown-section', html)
|
||||
}
|
||||
|
||||
export function renderMixin (Docsify) {
|
||||
Docsify.prototype._renderTo = function (el, content, replace) {
|
||||
const proto = Docsify.prototype
|
||||
|
||||
proto._renderTo = function (el, content, replace) {
|
||||
const node = dom.getNode(el)
|
||||
if (node) node[replace ? 'outerHTML' : 'innerHTML'] = content
|
||||
}
|
||||
|
||||
Docsify.prototype._renderSidebar = renderSidebar
|
||||
Docsify.prototype._renderNav = renderNav
|
||||
Docsify.prototype._renderMain = renderMain
|
||||
proto._renderSidebar = function (text) {
|
||||
this._renderTo('.sidebar-nav', sidebar(text))
|
||||
// bind event
|
||||
}
|
||||
|
||||
proto._renderNav = function (text) {
|
||||
this._renderTo('nav', markdown(text))
|
||||
}
|
||||
|
||||
proto._renderMain = function (text) {
|
||||
callHook(this, 'beforeEach', text, result => {
|
||||
const html = markdown(result)
|
||||
callHook(this, 'afterEach', html, text => renderMain.call(this, text))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function initRender (vm) {
|
||||
const config = vm.config
|
||||
|
||||
// Init markdown compiler
|
||||
markdown.init(vm.config.markdown)
|
||||
|
||||
const id = config.el || '#app'
|
||||
const navEl = dom.find('nav') || dom.create('nav')
|
||||
|
||||
|
|
|
|||
27
src/core/render/slugify.js
Normal file
27
src/core/render/slugify.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
let cache = {}
|
||||
const re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g
|
||||
|
||||
export function slugify (str) {
|
||||
if (typeof str !== 'string') return ''
|
||||
|
||||
let slug = str.toLowerCase().trim()
|
||||
.replace(/<[^>\d]+>/g, '')
|
||||
.replace(re, '')
|
||||
.replace(/\s/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.replace(/^(\d)/, '_$1')
|
||||
let count = cache[slug]
|
||||
|
||||
count = cache.hasOwnProperty(slug) ? (count + 1) : 0
|
||||
cache[slug] = count
|
||||
|
||||
if (count) {
|
||||
slug = slug + '-' + count
|
||||
}
|
||||
|
||||
return slug
|
||||
}
|
||||
|
||||
export function clearSlugCache () {
|
||||
cache = {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue