Support brace wrapped param in fence lang

Signed-off-by: Yukai Huang <yukaihuangtw@gmail.com>
This commit is contained in:
Yukai Huang 2020-04-19 16:52:24 +08:00
parent e72bcfe0ea
commit 77f4b0590a
No known key found for this signature in database
GPG Key ID: D4D3B2F0E99D4914
3 changed files with 76 additions and 16 deletions

View File

@ -15,6 +15,7 @@ import { stripTags } from '../../utils/string'
import getUIElements from './lib/editor/ui-elements'
import { emojifyImageDir } from './lib/editor/constants'
import { parseFenceCodeParams, serializeParamToAttribute } from './lib/markdown/utils'
import markdownit from 'markdown-it'
import markdownitContainer from 'markdown-it-container'
@ -1028,24 +1029,30 @@ export function scrollToHash () {
location.hash = hash
}
const fenceCodeAlias = {
sequence: 'sequence-diagram',
flow: 'flow-chart',
graphviz: 'graphviz',
mermaid: 'mermaid',
abc: 'abc',
vega: 'vega',
geo: 'geo'
}
function highlightRender (code, lang) {
if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }
const params = parseFenceCodeParams(lang)
const attr = serializeParamToAttribute(params)
lang = lang.split(/\s+/g)[0]
code = escapeHTML(code)
if (lang === 'sequence') {
return `<div class="sequence-diagram raw">${code}</div>`
} else if (lang === 'flow') {
return `<div class="flow-chart raw">${code}</div>`
} else if (lang === 'graphviz') {
return `<div class="graphviz raw">${code}</div>`
} else if (lang === 'mermaid') {
return `<div class="mermaid raw">${code}</div>`
} else if (lang === 'abc') {
return `<div class="abc raw">${code}</div>`
} else if (lang === 'vega') {
return `<div class="vega raw">${code}</div>`
} else if (lang === 'geo') {
return `<div class="geo raw">${code}</div>`
const langAlias = fenceCodeAlias[lang]
if (langAlias) {
return `<div class="${langAlias} raw"${attr}>${code}</div>`
}
const result = {
value: code
}
@ -1167,7 +1174,7 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
}
if (options.highlight) {
highlighted = options.highlight(token.content, langName) || md.utils.escapeHtml(token.content)
highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)
} else {
highlighted = md.utils.escapeHtml(token.content)
}

View File

@ -0,0 +1,53 @@
export function parseFenceCodeParams (lang) {
const attrMatch = lang.match(/{(.*)}/)
const params = {}
if (attrMatch && attrMatch.length >= 2) {
const attrs = attrMatch[1]
const paraMatch = attrs.match(/([#.](\S+?)\s)|((\S+?)\s*=\s*("(.+?)"|'(.+?)'|\[[^\]]*\]|\{[}]*\}|(\S+)))/g)
paraMatch && paraMatch.forEach(param => {
param = param.trim()
if (param[0] === '#') {
params['id'] = param.slice(1)
} else if (param[0] === '.') {
if (params['class']) params['class'] = []
params['class'] = params['class'].concat(param.slice(1))
} else {
const offset = param.indexOf('=')
const id = param.substring(0, offset).trim().toLowerCase()
let val = param.substring(offset + 1).trim()
const valStart = val[0]
const valEnd = val[val.length - 1]
if (['"', "'"].indexOf(valStart) !== -1 && ['"', "'"].indexOf(valEnd) !== -1 && valStart === valEnd) {
val = val.substring(1, val.length - 1)
}
if (id === 'class') {
if (params['class']) params['class'] = []
params['class'] = params['class'].concat(val)
} else {
params[id] = val
}
}
})
}
return params
}
export function serializeParamToAttribute (params) {
if (Object.getOwnPropertyNames(params).length === 0) {
return ''
} else {
return ` data-params="${escape(JSON.stringify(params))}"`
}
}
/**
* @param {HTMLElement} elem
*/
export function deserializeParamAttributeFromElement (elem) {
const params = elem.getAttribute('data-params')
if (params) {
return JSON.parse(unescape(params))
} else {
return {}
}
}

View File

@ -73,7 +73,7 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
}
if (options.highlight) {
highlighted = options.highlight(token.content, langName) || md.utils.escapeHtml(token.content)
highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)
} else {
highlighted = md.utils.escapeHtml(token.content)
}