Skip to content

Commit 53aa142

Browse files
authored
Merge pull request #2395 from daiyam/chart-yaml
add YAML for chart
2 parents 3793378 + a63266b commit 53aa142

File tree

7 files changed

+190
-18
lines changed

7 files changed

+190
-18
lines changed

browser/components/MarkdownPreview.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import convertModeName from 'browser/lib/convertModeName'
1616
import copy from 'copy-to-clipboard'
1717
import mdurl from 'mdurl'
1818
import exportNote from 'browser/main/lib/dataApi/exportNote'
19+
import { escapeHtmlCharacters } from 'browser/lib/utils'
20+
import yaml from 'js-yaml'
1921
import context from 'browser/lib/context'
2022
import i18n from 'browser/lib/i18n'
2123
import fs from 'fs'
@@ -767,7 +769,8 @@ export default class MarkdownPreview extends React.Component {
767769
this.refs.root.contentWindow.document.querySelectorAll('.chart'),
768770
el => {
769771
try {
770-
const chartConfig = JSON.parse(el.innerHTML)
772+
const format = el.attributes.getNamedItem('data-format').value
773+
const chartConfig = format === 'yaml' ? yaml.load(el.innerHTML) : JSON.parse(el.innerHTML)
771774
el.innerHTML = ''
772775

773776
const canvas = document.createElement('canvas')

browser/lib/markdown-it-fence.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict'
22

33
module.exports = function (md, renderers, defaultRenderer) {
4+
const paramsRE = /^[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/
5+
46
function fence (state, startLine, endLine) {
57
let pos = state.bMarks[startLine] + state.tShift[startLine]
68
let max = state.eMarks[startLine]
@@ -66,7 +68,7 @@ module.exports = function (md, renderers, defaultRenderer) {
6668
let fileName = ''
6769
let firstLineNumber = 1
6870

69-
let match = /^(\w[-\w]*)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/.exec(params)
71+
let match = paramsRE.exec(params)
7072
if (match) {
7173
if (match[1]) {
7274
langType = match[1]

browser/lib/markdown.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,13 @@ class Markdown {
133133

134134
this.md.use(require('./markdown-it-fence'), {
135135
chart: token => {
136+
if (token.parameters.hasOwnProperty('yaml')) {
137+
token.parameters.format = 'yaml'
138+
}
139+
136140
return `<pre class="fence" data-line="${token.map[0]}">
137141
<span class="filename">${token.fileName}</span>
138-
<div class="chart" data-height="${token.parameters.height}">${token.content}</div>
142+
<div class="chart" data-height="${token.parameters.height}" data-format="${token.parameters.format || 'json'}">${token.content}</div>
139143
</pre>`
140144
},
141145
flowchart: token => {

extra_scripts/codemirror/mode/bfm/bfm.js

Lines changed: 171 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,170 @@
11
(function(mod) {
22
if (typeof exports == "object" && typeof module == "object") // CommonJS
3-
mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"))
3+
mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"), require("../codemirror/mode/yaml-frontmatter/yaml-frontmatter"))
44
else if (typeof define == "function" && define.amd) // AMD
5-
define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm"], mod)
5+
define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm", "../codemirror/mode/yaml-frontmatter/yaml-frontmatter"], mod)
66
else // Plain browser env
77
mod(CodeMirror)
88
})(function(CodeMirror) {
99
'use strict'
1010

11-
CodeMirror.defineMode('bfm', function(config, gfmConfig) {
12-
const bfmOverlay = {
13-
startState() {
11+
const fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/
12+
13+
function getMode(name, params, config, cm) {
14+
if (!name) {
15+
return null
16+
}
17+
18+
const parameters = {}
19+
if (params) {
20+
const regex = /(\w[-\w]*)(?:=(?:'(.*?[^\\])?'|"(.*?[^\\])?"|([^'"][^\s]*)))?/g
21+
22+
let match
23+
while ((match = regex.exec(params))) {
24+
parameters[match[1]] = match[2] || match[3] || match[4] || null
25+
}
26+
}
27+
28+
if (name === 'chart') {
29+
name = parameters.hasOwnProperty('yaml') ? 'yaml' : 'json'
30+
}
31+
32+
const found = CodeMirror.findModeByName(name)
33+
if (!found) {
34+
return null
35+
}
36+
37+
if (CodeMirror.modes.hasOwnProperty(found.mode)) {
38+
const mode = CodeMirror.getMode(config, found.mode)
39+
40+
return mode.name === 'null' ? null : mode
41+
} else {
42+
CodeMirror.requireMode(found.mode, () => {
43+
cm.setOption('mode', cm.getOption('mode'))
44+
})
45+
}
46+
}
47+
48+
CodeMirror.defineMode('bfm', function (config, baseConfig) {
49+
baseConfig.name = 'yaml-frontmatter'
50+
const baseMode = CodeMirror.getMode(config, baseConfig)
51+
52+
return {
53+
startState: function() {
1454
return {
55+
baseState: CodeMirror.startState(baseMode),
56+
57+
basePos: 0,
58+
baseCur: null,
59+
overlayPos: 0,
60+
overlayCur: null,
61+
streamSeen: null,
62+
63+
fencedEndRE: null,
64+
1565
inTable: false,
1666
rowIndex: 0
1767
}
1868
},
19-
copyState(s) {
69+
copyState: function(s) {
2070
return {
71+
baseState: CodeMirror.copyState(baseMode, s.baseState),
72+
73+
basePos: s.basePos,
74+
baseCur: null,
75+
overlayPos: s.overlayPos,
76+
overlayCur: null,
77+
78+
fencedMode: s.fencedMode,
79+
fencedState: s.fencedMode ? CodeMirror.copyState(s.fencedMode, s.fencedState) : null,
80+
81+
fencedEndRE: s.fencedEndRE,
82+
2183
inTable: s.inTable,
2284
rowIndex: s.rowIndex
2385
}
2486
},
25-
token(stream, state) {
87+
token: function(stream, state) {
88+
const initialPos = stream.pos
89+
90+
if (state.fencedEndRE && stream.match(state.fencedEndRE)) {
91+
state.fencedEndRE = null
92+
state.fencedMode = null
93+
state.fencedState = null
94+
95+
stream.pos = initialPos
96+
}
97+
else {
98+
if (state.fencedMode) {
99+
return state.fencedMode.token(stream, state.fencedState)
100+
}
101+
102+
const match = stream.match(fencedCodeRE, true)
103+
if (match) {
104+
state.fencedEndRE = new RegExp(match[1] + '+ *$')
105+
106+
state.fencedMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm)
107+
if (state.fencedMode) {
108+
state.fencedState = CodeMirror.startState(state.fencedMode)
109+
}
110+
111+
stream.pos = initialPos
112+
}
113+
}
114+
115+
if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) {
116+
state.streamSeen = stream
117+
state.basePos = state.overlayPos = stream.start
118+
}
119+
120+
if (stream.start == state.basePos) {
121+
state.baseCur = baseMode.token(stream, state.baseState)
122+
state.basePos = stream.pos
123+
}
124+
if (stream.start == state.overlayPos) {
125+
stream.pos = stream.start
126+
state.overlayCur = this.overlayToken(stream, state)
127+
state.overlayPos = stream.pos
128+
}
129+
stream.pos = Math.min(state.basePos, state.overlayPos)
130+
131+
if (state.overlayCur == null) {
132+
return state.baseCur
133+
}
134+
else if (state.baseCur != null && state.combineTokens) {
135+
return state.baseCur + ' ' + state.overlayCur
136+
}
137+
else {
138+
return state.overlayCur
139+
}
140+
},
141+
overlayToken: function(stream, state) {
142+
state.combineTokens = false
143+
144+
if (state.fencedEndRE && stream.match(state.fencedEndRE)) {
145+
state.fencedEndRE = null
146+
state.localMode = null
147+
state.localState = null
148+
149+
return null
150+
}
151+
152+
if (state.localMode) {
153+
return state.localMode.token(stream, state.localState) || ''
154+
}
155+
156+
const match = stream.match(fencedCodeRE, true)
157+
if (match) {
158+
state.fencedEndRE = new RegExp(match[1] + '+ *$')
159+
160+
state.localMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm)
161+
if (state.localMode) {
162+
state.localState = CodeMirror.startState(state.localMode)
163+
}
164+
165+
return null
166+
}
167+
26168
state.combineTokens = true
27169

28170
if (state.inTable) {
@@ -55,14 +197,31 @@
55197
stream.skipToEnd()
56198
return null
57199
},
58-
blankLine(state) {
200+
electricChars: baseMode.electricChars,
201+
innerMode: function(state) {
202+
if (state.fencedMode) {
203+
return {
204+
mode: state.fencedMode,
205+
state: state.fencedState
206+
}
207+
} else {
208+
return {
209+
mode: baseMode,
210+
state: state.baseState
211+
}
212+
}
213+
},
214+
blankLine: function(state) {
59215
state.inTable = false
216+
217+
if (state.fencedMode) {
218+
return state.fencedMode.blankLine && state.fencedMode.blankLine(state.fencedState)
219+
} else {
220+
return baseMode.blankLine(state.baseState)
221+
}
60222
}
61223
}
62-
63-
gfmConfig.name = 'gfm'
64-
return CodeMirror.overlayMode(CodeMirror.getMode(config, gfmConfig), bfmOverlay)
65-
})
224+
}, 'yaml-frontmatter')
66225

67226
CodeMirror.defineMIME('text/x-bfm', 'bfm')
68227

lib/main.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,11 @@
9898
<script src="../node_modules/codemirror/mode/xml/xml.js"></script>
9999
<script src="../node_modules/codemirror/mode/markdown/markdown.js"></script>
100100
<script src="../node_modules/codemirror/mode/gfm/gfm.js"></script>
101+
<script src="../node_modules/codemirror/mode/yaml/yaml.js"></script>
102+
<script src="../node_modules/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js"></script>
101103

102104
<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
105+
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
103106
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
104107
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
105108

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"iconv-lite": "^0.4.19",
6969
"immutable": "^3.8.1",
7070
"js-sequence-diagrams": "^1000000.0.6",
71+
"js-yaml": "^3.12.0",
7172
"katex": "^0.9.0",
7273
"lodash": "^4.11.1",
7374
"lodash-move": "^1.1.1",

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5326,7 +5326,7 @@ js-yaml@^3.10.0, js-yaml@^3.5.1, js-yaml@^3.7.0:
53265326
argparse "^1.0.7"
53275327
esprima "^4.0.0"
53285328

5329-
js-yaml@^3.8.1:
5329+
js-yaml@^3.12.0, js-yaml@^3.8.1:
53305330
version "3.12.0"
53315331
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
53325332
dependencies:
@@ -7349,8 +7349,8 @@ rcedit@^1.0.0:
73497349
resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-1.1.0.tgz#ae21c28d4efdd78e95fcab7309a5dd084920b16a"
73507350

73517351
react-autosuggest@^9.4.0:
7352-
version "9.4.0"
7353-
resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.0.tgz#3146bc9afa4f171bed067c542421edec5ca94294"
7352+
version "9.4.2"
7353+
resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.2.tgz#18cc0bebeebda3d24328e3da301f061a444ae223"
73547354
dependencies:
73557355
prop-types "^15.5.10"
73567356
react-autowhatever "^10.1.2"

0 commit comments

Comments
 (0)