Skip to content

Commit 662bb87

Browse files
authored
Merge pull request #1488 from hackmdio/feature/fence-params
2 parents d7cc951 + 77f4b05 commit 662bb87

File tree

3 files changed

+76
-16
lines changed

3 files changed

+76
-16
lines changed

public/js/extra.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { stripTags } from '../../utils/string'
1515

1616
import getUIElements from './lib/editor/ui-elements'
1717
import { emojifyImageDir } from './lib/editor/constants'
18+
import { parseFenceCodeParams, serializeParamToAttribute } from './lib/markdown/utils'
1819

1920
import markdownit from 'markdown-it'
2021
import markdownitContainer from 'markdown-it-container'
@@ -1028,24 +1029,30 @@ export function scrollToHash () {
10281029
location.hash = hash
10291030
}
10301031

1032+
const fenceCodeAlias = {
1033+
sequence: 'sequence-diagram',
1034+
flow: 'flow-chart',
1035+
graphviz: 'graphviz',
1036+
mermaid: 'mermaid',
1037+
abc: 'abc',
1038+
vega: 'vega',
1039+
geo: 'geo'
1040+
}
1041+
10311042
function highlightRender (code, lang) {
10321043
if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }
1044+
1045+
const params = parseFenceCodeParams(lang)
1046+
const attr = serializeParamToAttribute(params)
1047+
lang = lang.split(/\s+/g)[0]
1048+
10331049
code = escapeHTML(code)
1034-
if (lang === 'sequence') {
1035-
return `<div class="sequence-diagram raw">${code}</div>`
1036-
} else if (lang === 'flow') {
1037-
return `<div class="flow-chart raw">${code}</div>`
1038-
} else if (lang === 'graphviz') {
1039-
return `<div class="graphviz raw">${code}</div>`
1040-
} else if (lang === 'mermaid') {
1041-
return `<div class="mermaid raw">${code}</div>`
1042-
} else if (lang === 'abc') {
1043-
return `<div class="abc raw">${code}</div>`
1044-
} else if (lang === 'vega') {
1045-
return `<div class="vega raw">${code}</div>`
1046-
} else if (lang === 'geo') {
1047-
return `<div class="geo raw">${code}</div>`
1050+
1051+
const langAlias = fenceCodeAlias[lang]
1052+
if (langAlias) {
1053+
return `<div class="${langAlias} raw"${attr}>${code}</div>`
10481054
}
1055+
10491056
const result = {
10501057
value: code
10511058
}
@@ -1167,7 +1174,7 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
11671174
}
11681175

11691176
if (options.highlight) {
1170-
highlighted = options.highlight(token.content, langName) || md.utils.escapeHtml(token.content)
1177+
highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)
11711178
} else {
11721179
highlighted = md.utils.escapeHtml(token.content)
11731180
}

public/js/lib/markdown/utils.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
export function parseFenceCodeParams (lang) {
2+
const attrMatch = lang.match(/{(.*)}/)
3+
const params = {}
4+
if (attrMatch && attrMatch.length >= 2) {
5+
const attrs = attrMatch[1]
6+
const paraMatch = attrs.match(/([#.](\S+?)\s)|((\S+?)\s*=\s*("(.+?)"|'(.+?)'|\[[^\]]*\]|\{[}]*\}|(\S+)))/g)
7+
paraMatch && paraMatch.forEach(param => {
8+
param = param.trim()
9+
if (param[0] === '#') {
10+
params['id'] = param.slice(1)
11+
} else if (param[0] === '.') {
12+
if (params['class']) params['class'] = []
13+
params['class'] = params['class'].concat(param.slice(1))
14+
} else {
15+
const offset = param.indexOf('=')
16+
const id = param.substring(0, offset).trim().toLowerCase()
17+
let val = param.substring(offset + 1).trim()
18+
const valStart = val[0]
19+
const valEnd = val[val.length - 1]
20+
if (['"', "'"].indexOf(valStart) !== -1 && ['"', "'"].indexOf(valEnd) !== -1 && valStart === valEnd) {
21+
val = val.substring(1, val.length - 1)
22+
}
23+
if (id === 'class') {
24+
if (params['class']) params['class'] = []
25+
params['class'] = params['class'].concat(val)
26+
} else {
27+
params[id] = val
28+
}
29+
}
30+
})
31+
}
32+
return params
33+
}
34+
35+
export function serializeParamToAttribute (params) {
36+
if (Object.getOwnPropertyNames(params).length === 0) {
37+
return ''
38+
} else {
39+
return ` data-params="${escape(JSON.stringify(params))}"`
40+
}
41+
}
42+
43+
/**
44+
* @param {HTMLElement} elem
45+
*/
46+
export function deserializeParamAttributeFromElement (elem) {
47+
const params = elem.getAttribute('data-params')
48+
if (params) {
49+
return JSON.parse(unescape(params))
50+
} else {
51+
return {}
52+
}
53+
}

public/js/lib/syncscroll.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
7373
}
7474

7575
if (options.highlight) {
76-
highlighted = options.highlight(token.content, langName) || md.utils.escapeHtml(token.content)
76+
highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)
7777
} else {
7878
highlighted = md.utils.escapeHtml(token.content)
7979
}

0 commit comments

Comments
 (0)