Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion browser/components/MarkdownPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import convertModeName from 'browser/lib/convertModeName'
import copy from 'copy-to-clipboard'
import mdurl from 'mdurl'
import exportNote from 'browser/main/lib/dataApi/exportNote'
import { escapeHtmlCharacters } from 'browser/lib/utils'
import yaml from 'js-yaml'
import context from 'browser/lib/context'
import i18n from 'browser/lib/i18n'
import fs from 'fs'
Expand Down Expand Up @@ -767,7 +769,8 @@ export default class MarkdownPreview extends React.Component {
this.refs.root.contentWindow.document.querySelectorAll('.chart'),
el => {
try {
const chartConfig = JSON.parse(el.innerHTML)
const format = el.attributes.getNamedItem('data-format').value
const chartConfig = format === 'yaml' ? yaml.load(el.innerHTML) : JSON.parse(el.innerHTML)
el.innerHTML = ''

const canvas = document.createElement('canvas')
Expand Down
4 changes: 3 additions & 1 deletion browser/lib/markdown-it-fence.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict'

module.exports = function (md, renderers, defaultRenderer) {
const paramsRE = /^[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/

function fence (state, startLine, endLine) {
let pos = state.bMarks[startLine] + state.tShift[startLine]
let max = state.eMarks[startLine]
Expand Down Expand Up @@ -66,7 +68,7 @@ module.exports = function (md, renderers, defaultRenderer) {
let fileName = ''
let firstLineNumber = 1

let match = /^(\w[-\w]*)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/.exec(params)
let match = paramsRE.exec(params)
if (match) {
if (match[1]) {
langType = match[1]
Expand Down
6 changes: 5 additions & 1 deletion browser/lib/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,13 @@ class Markdown {

this.md.use(require('./markdown-it-fence'), {
chart: token => {
if (token.parameters.hasOwnProperty('yaml')) {
token.parameters.format = 'yaml'
}

return `<pre class="fence" data-line="${token.map[0]}">
<span class="filename">${token.fileName}</span>
<div class="chart" data-height="${token.parameters.height}">${token.content}</div>
<div class="chart" data-height="${token.parameters.height}" data-format="${token.parameters.format || 'json'}">${token.content}</div>
</pre>`
},
flowchart: token => {
Expand Down
183 changes: 171 additions & 12 deletions extra_scripts/codemirror/mode/bfm/bfm.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,170 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"))
mod(require("../codemirror/lib/codemirror"), require("../codemirror/mode/gfm/gfm"), require("../codemirror/mode/yaml-frontmatter/yaml-frontmatter"))
else if (typeof define == "function" && define.amd) // AMD
define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm"], mod)
define(["../codemirror/lib/codemirror", "../codemirror/mode/gfm/gfm", "../codemirror/mode/yaml-frontmatter/yaml-frontmatter"], mod)
else // Plain browser env
mod(CodeMirror)
})(function(CodeMirror) {
'use strict'

CodeMirror.defineMode('bfm', function(config, gfmConfig) {
const bfmOverlay = {
startState() {
const fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/

function getMode(name, params, config, cm) {
if (!name) {
return null
}

const parameters = {}
if (params) {
const regex = /(\w[-\w]*)(?:=(?:'(.*?[^\\])?'|"(.*?[^\\])?"|([^'"][^\s]*)))?/g

let match
while ((match = regex.exec(params))) {
parameters[match[1]] = match[2] || match[3] || match[4] || null
}
}

if (name === 'chart') {
name = parameters.hasOwnProperty('yaml') ? 'yaml' : 'json'
}

const found = CodeMirror.findModeByName(name)
if (!found) {
return null
}

if (CodeMirror.modes.hasOwnProperty(found.mode)) {
const mode = CodeMirror.getMode(config, found.mode)

return mode.name === 'null' ? null : mode
} else {
CodeMirror.requireMode(found.mode, () => {
cm.setOption('mode', cm.getOption('mode'))
})
}
}

CodeMirror.defineMode('bfm', function (config, baseConfig) {
baseConfig.name = 'yaml-frontmatter'
const baseMode = CodeMirror.getMode(config, baseConfig)

return {
startState: function() {
return {
baseState: CodeMirror.startState(baseMode),

basePos: 0,
baseCur: null,
overlayPos: 0,
overlayCur: null,
streamSeen: null,

fencedEndRE: null,

inTable: false,
rowIndex: 0
}
},
copyState(s) {
copyState: function(s) {
return {
baseState: CodeMirror.copyState(baseMode, s.baseState),

basePos: s.basePos,
baseCur: null,
overlayPos: s.overlayPos,
overlayCur: null,

fencedMode: s.fencedMode,
fencedState: s.fencedMode ? CodeMirror.copyState(s.fencedMode, s.fencedState) : null,

fencedEndRE: s.fencedEndRE,

inTable: s.inTable,
rowIndex: s.rowIndex
}
},
token(stream, state) {
token: function(stream, state) {
const initialPos = stream.pos

if (state.fencedEndRE && stream.match(state.fencedEndRE)) {
state.fencedEndRE = null
state.fencedMode = null
state.fencedState = null

stream.pos = initialPos
}
else {
if (state.fencedMode) {
return state.fencedMode.token(stream, state.fencedState)
}

const match = stream.match(fencedCodeRE, true)
if (match) {
state.fencedEndRE = new RegExp(match[1] + '+ *$')

state.fencedMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm)
if (state.fencedMode) {
state.fencedState = CodeMirror.startState(state.fencedMode)
}

stream.pos = initialPos
}
}

if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream
state.basePos = state.overlayPos = stream.start
}

if (stream.start == state.basePos) {
state.baseCur = baseMode.token(stream, state.baseState)
state.basePos = stream.pos
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start
state.overlayCur = this.overlayToken(stream, state)
state.overlayPos = stream.pos
}
stream.pos = Math.min(state.basePos, state.overlayPos)

if (state.overlayCur == null) {
return state.baseCur
}
else if (state.baseCur != null && state.combineTokens) {
return state.baseCur + ' ' + state.overlayCur
}
else {
return state.overlayCur
}
},
overlayToken: function(stream, state) {
state.combineTokens = false

if (state.fencedEndRE && stream.match(state.fencedEndRE)) {
state.fencedEndRE = null
state.localMode = null
state.localState = null

return null
}

if (state.localMode) {
return state.localMode.token(stream, state.localState) || ''
}

const match = stream.match(fencedCodeRE, true)
if (match) {
state.fencedEndRE = new RegExp(match[1] + '+ *$')

state.localMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm)
if (state.localMode) {
state.localState = CodeMirror.startState(state.localMode)
}

return null
}

state.combineTokens = true

if (state.inTable) {
Expand Down Expand Up @@ -55,14 +197,31 @@
stream.skipToEnd()
return null
},
blankLine(state) {
electricChars: baseMode.electricChars,
innerMode: function(state) {
if (state.fencedMode) {
return {
mode: state.fencedMode,
state: state.fencedState
}
} else {
return {
mode: baseMode,
state: state.baseState
}
}
},
blankLine: function(state) {
state.inTable = false

if (state.fencedMode) {
return state.fencedMode.blankLine && state.fencedMode.blankLine(state.fencedState)
} else {
return baseMode.blankLine(state.baseState)
}
}
}

gfmConfig.name = 'gfm'
return CodeMirror.overlayMode(CodeMirror.getMode(config, gfmConfig), bfmOverlay)
})
}, 'yaml-frontmatter')

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

Expand Down
3 changes: 3 additions & 0 deletions lib/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@
<script src="../node_modules/codemirror/mode/xml/xml.js"></script>
<script src="../node_modules/codemirror/mode/markdown/markdown.js"></script>
<script src="../node_modules/codemirror/mode/gfm/gfm.js"></script>
<script src="../node_modules/codemirror/mode/yaml/yaml.js"></script>
<script src="../node_modules/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js"></script>

<script src="../extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js"></script>
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
<script src="../extra_scripts/codemirror/mode/bfm/bfm.js"></script>

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"iconv-lite": "^0.4.19",
"immutable": "^3.8.1",
"js-sequence-diagrams": "^1000000.0.6",
"js-yaml": "^3.12.0",
"katex": "^0.9.0",
"lodash": "^4.11.1",
"lodash-move": "^1.1.1",
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5326,7 +5326,7 @@ js-yaml@^3.10.0, js-yaml@^3.5.1, js-yaml@^3.7.0:
argparse "^1.0.7"
esprima "^4.0.0"

js-yaml@^3.8.1:
js-yaml@^3.12.0, js-yaml@^3.8.1:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
dependencies:
Expand Down Expand Up @@ -7349,8 +7349,8 @@ rcedit@^1.0.0:
resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-1.1.0.tgz#ae21c28d4efdd78e95fcab7309a5dd084920b16a"

react-autosuggest@^9.4.0:
version "9.4.0"
resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.0.tgz#3146bc9afa4f171bed067c542421edec5ca94294"
version "9.4.2"
resolved "https://registry.yarnpkg.com/react-autosuggest/-/react-autosuggest-9.4.2.tgz#18cc0bebeebda3d24328e3da301f061a444ae223"
dependencies:
prop-types "^15.5.10"
react-autowhatever "^10.1.2"
Expand Down