diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index faa04e9ad..59fabaeb4 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -321,10 +321,18 @@ export default class CodeEditor extends React.Component { 'CodeMirror-lint-markers' ], autoCloseBrackets: { - pairs: this.props.matchingPairs, - triples: this.props.matchingTriples, - explode: this.props.explodingPairs, - override: true + codeBlock: { + pairs: this.props.codeBlockMatchingPairs, + closeBefore: this.props.codeBlockMatchingCloseBefore, + triples: this.props.codeBlockMatchingTriples, + explode: this.props.codeBlockExplodingPairs + }, + markdown: { + pairs: this.props.matchingPairs, + closeBefore: this.props.matchingCloseBefore, + triples: this.props.matchingTriples, + explode: this.props.explodingPairs + } }, extraKeys: this.defaultKeyMap, prettierConfig: this.props.prettierConfig @@ -629,16 +637,32 @@ export default class CodeEditor extends React.Component { if ( prevProps.matchingPairs !== this.props.matchingPairs || + prevProps.matchingCloseBefore !== this.props.matchingCloseBefore || prevProps.matchingTriples !== this.props.matchingTriples || - prevProps.explodingPairs !== this.props.explodingPairs + prevProps.explodingPairs !== this.props.explodingPairs || + prevProps.codeBlockMatchingPairs !== this.props.codeBlockMatchingPairs || + prevProps.codeBlockMatchingCloseBefore !== + this.props.codeBlockMatchingCloseBefore || + prevProps.codeBlockMatchingTriples !== + this.props.codeBlockMatchingTriples || + prevProps.codeBlockExplodingPairs !== this.props.codeBlockExplodingPairs ) { - const bracketObject = { - pairs: this.props.matchingPairs, - triples: this.props.matchingTriples, - explode: this.props.explodingPairs, - override: true + const autoCloseBrackets = { + codeBlock: { + pairs: this.props.codeBlockMatchingPairs, + closeBefore: this.props.codeBlockMatchingCloseBefore, + triples: this.props.codeBlockMatchingTriples, + explode: this.props.codeBlockExplodingPairs + }, + markdown: { + pairs: this.props.matchingPairs, + closeBefore: this.props.matchingCloseBefore, + triples: this.props.matchingTriples, + explode: this.props.explodingPairs + } } - this.editor.setOption('autoCloseBrackets', bracketObject) + + this.editor.setOption('autoCloseBrackets', autoCloseBrackets) } if (prevProps.enableTableEditor !== this.props.enableTableEditor) { diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index d07ffb0e0..5108ddc66 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -365,8 +365,15 @@ class MarkdownEditor extends React.Component { displayLineNumbers={config.editor.displayLineNumbers} lineWrapping matchingPairs={config.editor.matchingPairs} + matchingCloseBefore={config.editor.matchingCloseBefore} matchingTriples={config.editor.matchingTriples} explodingPairs={config.editor.explodingPairs} + codeBlockMatchingPairs={config.editor.codeBlockMatchingPairs} + codeBlockMatchingCloseBefore={ + config.editor.codeBlockMatchingCloseBefore + } + codeBlockMatchingTriples={config.editor.codeBlockMatchingTriples} + codeBlockExplodingPairs={config.editor.codeBlockExplodingPairs} scrollPastEnd={config.editor.scrollPastEnd} storageKey={storageKey} noteKey={noteKey} diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index a26a819b5..4f8965178 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -260,8 +260,15 @@ class MarkdownSplitEditor extends React.Component { displayLineNumbers={config.editor.displayLineNumbers} lineWrapping matchingPairs={config.editor.matchingPairs} + matchingCloseBefore={config.editor.matchingCloseBefore} matchingTriples={config.editor.matchingTriples} explodingPairs={config.editor.explodingPairs} + codeBlockMatchingPairs={config.editor.codeBlockMatchingPairs} + codeBlockMatchingCloseBefore={ + config.editor.codeBlockMatchingCloseBefore + } + codeBlockMatchingTriples={config.editor.codeBlockMatchingTriples} + codeBlockExplodingPairs={config.editor.codeBlockExplodingPairs} indentType={config.editor.indentType} indentSize={editorStyle.indentSize} enableRulers={config.editor.enableRulers} diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 827230925..09ec9b335 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -859,8 +859,15 @@ class SnippetNoteDetail extends React.Component { indentSize={editorIndentSize} displayLineNumbers={config.editor.displayLineNumbers} matchingPairs={config.editor.matchingPairs} + matchingCloseBefore={config.editor.matchingCloseBefore} matchingTriples={config.editor.matchingTriples} explodingPairs={config.editor.explodingPairs} + codeBlockMatchingPairs={config.editor.codeBlockMatchingPairs} + codeBlockMatchingCloseBefore={ + config.editor.codeBlockMatchingCloseBefore + } + codeBlockMatchingTriples={config.editor.codeBlockMatchingTriples} + codeBlockExplodingPairs={config.editor.codeBlockExplodingPairs} keyMap={config.editor.keyMap} scrollPastEnd={config.editor.scrollPastEnd} fetchUrlTitle={config.editor.fetchUrlTitle} diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index a0b23fc20..76ef620cf 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -86,8 +86,13 @@ export const DEFAULT_CONFIG = { rulers: [80, 120], displayLineNumbers: true, matchingPairs: '()[]{}\'\'""$$**``~~__', + matchingCloseBefore: ')]}\'":;>', matchingTriples: '```"""\'\'\'', explodingPairs: '[]{}``$$', + codeBlockMatchingPairs: '()[]{}\'\'""``', + codeBlockMatchingCloseBefore: ')]}\'":;>', + codeBlockMatchingTriples: '', + codeBlockExplodingPairs: '[]{}``', switchPreview: 'BLUR', // 'BLUR', 'DBL_CLICK', 'RIGHTCLICK' delfaultStatus: 'PREVIEW', // 'PREVIEW', 'CODE' scrollPastEnd: false, diff --git a/browser/main/modals/PreferencesModal/ConfigTab.styl b/browser/main/modals/PreferencesModal/ConfigTab.styl index c27bd3ac3..a2d4901f9 100644 --- a/browser/main/modals/PreferencesModal/ConfigTab.styl +++ b/browser/main/modals/PreferencesModal/ConfigTab.styl @@ -139,6 +139,13 @@ div[id^="firstRow"] margin-right 10px font-size 14px +.group-section-label-right + width 200px + text-align right + margin-right 10px + font-size 14px + padding-right 1.5rem + .group-section-control flex 1 margin-left 5px diff --git a/browser/main/modals/PreferencesModal/SnippetEditor.js b/browser/main/modals/PreferencesModal/SnippetEditor.js index f748924ca..3a5eb8376 100644 --- a/browser/main/modals/PreferencesModal/SnippetEditor.js +++ b/browser/main/modals/PreferencesModal/SnippetEditor.js @@ -35,10 +35,18 @@ class SnippetEditor extends React.Component { foldGutter: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], autoCloseBrackets: { - pairs: this.props.matchingPairs, - triples: this.props.matchingTriples, - explode: this.props.explodingPairs, - override: true + codeBlock: { + pairs: this.props.codeBlockMatchingPairs, + closeBefore: this.props.codeBlockMatchingCloseBefore, + triples: this.props.codeBlockMatchingTriples, + explode: this.props.codeBlockExplodingPairs + }, + markdown: { + pairs: this.props.matchingPairs, + closeBefore: this.props.matchingCloseBefore, + triples: this.props.matchingTriples, + explode: this.props.explodingPairs + } }, mode: 'null' }) diff --git a/browser/main/modals/PreferencesModal/SnippetTab.js b/browser/main/modals/PreferencesModal/SnippetTab.js index 0476c5c2e..156b4424b 100644 --- a/browser/main/modals/PreferencesModal/SnippetTab.js +++ b/browser/main/modals/PreferencesModal/SnippetTab.js @@ -152,8 +152,15 @@ class SnippetTab extends React.Component { rulers={config.editor.rulers} displayLineNumbers={config.editor.displayLineNumbers} matchingPairs={config.editor.matchingPairs} + matchingCloseBefore={config.editor.matchingCloseBefore} matchingTriples={config.editor.matchingTriples} explodingPairs={config.editor.explodingPairs} + codeBlockMatchingPairs={config.editor.codeBlockMatchingPairs} + codeBlockMatchingCloseBefore={ + config.editor.codeBlockMatchingCloseBefore + } + codeBlockMatchingTriples={config.editor.codeBlockMatchingTriples} + codeBlockExplodingPairs={config.editor.codeBlockExplodingPairs} scrollPastEnd={config.editor.scrollPastEnd} onRef={ref => { this.snippetEditor = ref diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 17eb5558f..2ddb9e3a8 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -124,8 +124,14 @@ class UiTab extends React.Component { enableFrontMatterTitle: this.refs.enableFrontMatterTitle.checked, frontMatterTitleField: this.refs.frontMatterTitleField.value, matchingPairs: this.refs.matchingPairs.value, + matchingCloseBefore: this.refs.matchingCloseBefore.value, matchingTriples: this.refs.matchingTriples.value, explodingPairs: this.refs.explodingPairs.value, + codeBlockMatchingPairs: this.refs.codeBlockMatchingPairs.value, + codeBlockMatchingCloseBefore: this.refs.codeBlockMatchingCloseBefore + .value, + codeBlockMatchingTriples: this.refs.codeBlockMatchingTriples.value, + codeBlockExplodingPairs: this.refs.codeBlockExplodingPairs.value, spellcheck: this.refs.spellcheck.checked, enableSmartPaste: this.refs.enableSmartPaste.checked, enableMarkdownLint: this.refs.enableMarkdownLint.checked, @@ -745,6 +751,126 @@ class UiTab extends React.Component { +
+
+ {i18n.__('Matching character pairs')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('in code blocks')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('Close pairs before')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('in code blocks')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('Matching character triples')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('in code blocks')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('Exploding character pairs')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+ +
+
+ {i18n.__('in code blocks')} +
+
+ this.handleUIChange(e)} + type='text' + /> +
+
+
-
-
- {i18n.__('Matching character pairs')} -
-
- this.handleUIChange(e)} - type='text' - /> -
-
- -
-
- {i18n.__('Matching character triples')} -
-
- this.handleUIChange(e)} - type='text' - /> -
-
- -
-
- {i18n.__('Exploding character pairs')} -
-
- this.handleUIChange(e)} - type='text' - /> -
-
{i18n.__('Custom MarkdownLint Rules')} diff --git a/extra_scripts/codemirror/addon/edit/closebrackets.js b/extra_scripts/codemirror/addon/edit/closebrackets.js new file mode 100644 index 000000000..357185cac --- /dev/null +++ b/extra_scripts/codemirror/addon/edit/closebrackets.js @@ -0,0 +1,196 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + var defaults = { + pairs: "()[]{}''\"\"", + closeBefore: ")]}'\":;>", + triples: "", + explode: "[]{}" + }; + + var Pos = CodeMirror.Pos; + + CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { + if (old && old != CodeMirror.Init) { + cm.removeKeyMap(keyMap); + cm.state.closeBrackets = null; + } + if (val) { + ensureBound(getOption(val.markdown, "pairs")) + cm.state.closeBrackets = val; + cm.addKeyMap(keyMap); + } + }); + + function getOption(conf, name) { + if (name == "pairs" && typeof conf == "string") return conf; + if (typeof conf == "object" && conf[name] != null) return conf[name]; + return defaults[name]; + } + + var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; + function ensureBound(chars) { + for (var i = 0; i < chars.length; i++) { + var ch = chars.charAt(i), key = "'" + ch + "'" + if (!keyMap[key]) keyMap[key] = handler(ch) + } + } + ensureBound(defaults.pairs + "`") + + function handler(ch) { + return function(cm) { return handleChar(cm, ch); }; + } + + function getConfig(cm) { + var cursor = cm.getCursor(); + var token = cm.getTokenAt(cursor); + var inCodeBlock = !!token.state.fencedEndRE; + + if (inCodeBlock) { + return cm.state.closeBrackets.codeBlock + } else { + return cm.state.closeBrackets.markdown + } + } + + function handleBackspace(cm) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + for (var i = ranges.length - 1; i >= 0; i--) { + var cur = ranges[i].head; + cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete"); + } + } + + function handleEnter(cm) { + var conf = getConfig(cm); + var explode = conf && getOption(conf, "explode"); + if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass; + + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + cm.operation(function() { + var linesep = cm.lineSeparator() || "\n"; + cm.replaceSelection(linesep + linesep, null); + cm.execCommand("goCharLeft"); + ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var line = ranges[i].head.line; + cm.indentLine(line, null, true); + cm.indentLine(line + 1, null, true); + } + }); + } + + function contractSelection(sel) { + var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0; + return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)), + head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))}; + } + + function handleChar(cm, ch) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var pos = pairs.indexOf(ch); + if (pos == -1) return CodeMirror.Pass; + + var closeBefore = getOption(conf,"closeBefore"); + + var triples = getOption(conf, "triples"); + + var identical = pairs.charAt(pos + 1) == ch; + var ranges = cm.listSelections(); + var opening = pos % 2 == 0; + + var type; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], cur = range.head, curType; + var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); + if (opening && !range.empty()) { + curType = "surround"; + } else if ((identical || !opening) && next == ch) { + if (identical && stringStartsAfter(cm, cur)) + curType = "both"; + else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch) + curType = "skipThree"; + else + curType = "skip"; + } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 && + cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) { + if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass; + curType = "addFour"; + } else if (identical) { + var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur) + if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both"; + else return CodeMirror.Pass; + } else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) { + curType = "both"; + } else { + return CodeMirror.Pass; + } + if (!type) type = curType; + else if (type != curType) return CodeMirror.Pass; + } + + var left = pos % 2 ? pairs.charAt(pos - 1) : ch; + var right = pos % 2 ? ch : pairs.charAt(pos + 1); + cm.operation(function() { + if (type == "skip") { + cm.execCommand("goCharRight"); + } else if (type == "skipThree") { + for (var i = 0; i < 3; i++) + cm.execCommand("goCharRight"); + } else if (type == "surround") { + var sels = cm.getSelections(); + for (var i = 0; i < sels.length; i++) + sels[i] = left + sels[i] + right; + cm.replaceSelections(sels, "around"); + sels = cm.listSelections().slice(); + for (var i = 0; i < sels.length; i++) + sels[i] = contractSelection(sels[i]); + cm.setSelections(sels); + } else if (type == "both") { + cm.replaceSelection(left + right, null); + cm.triggerElectric(left + right); + cm.execCommand("goCharLeft"); + } else if (type == "addFour") { + cm.replaceSelection(left + left + left + left, "before"); + cm.execCommand("goCharRight"); + } + }); + } + + function charsAround(cm, pos) { + var str = cm.getRange(Pos(pos.line, pos.ch - 1), + Pos(pos.line, pos.ch + 1)); + return str.length == 2 ? str : null; + } + + function stringStartsAfter(cm, pos) { + var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1)) + return /\bstring/.test(token.type) && token.start == pos.ch && + (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos))) + } +}); \ No newline at end of file diff --git a/extra_scripts/codemirror/mode/bfm/bfm.js b/extra_scripts/codemirror/mode/bfm/bfm.js index d08183cdc..76d06336c 100644 --- a/extra_scripts/codemirror/mode/bfm/bfm.js +++ b/extra_scripts/codemirror/mode/bfm/bfm.js @@ -55,202 +55,168 @@ } } - CodeMirror.defineMode( - 'bfm', - function(config, baseConfig) { - baseConfig.name = 'yaml-frontmatter' - const baseMode = CodeMirror.getMode(config, baseConfig) - - return { - startState: function() { - return { - baseState: CodeMirror.startState(baseMode), + CodeMirror.defineMode('bfm', function (config, baseConfig) { + baseConfig.name = 'yaml-frontmatter' + const baseMode = CodeMirror.getMode(config, baseConfig) - basePos: 0, - baseCur: null, - overlayPos: 0, - overlayCur: null, - streamSeen: null, + return { + startState: function() { + return { + baseState: CodeMirror.startState(baseMode), - fencedEndRE: null, + basePos: 0, + baseCur: null, + overlayPos: 0, + overlayCur: null, + streamSeen: null, - inTable: false, - rowIndex: 0 - } - }, - copyState: function(s) { - return { - baseState: CodeMirror.copyState(baseMode, s.baseState), + fencedEndRE: null, - basePos: s.basePos, - baseCur: null, - overlayPos: s.overlayPos, - overlayCur: null, + inTable: false, + rowIndex: 0 + } + }, + copyState: function(s) { + return { + baseState: CodeMirror.copyState(baseMode, s.baseState), - fencedMode: s.fencedMode, - fencedState: s.fencedMode - ? CodeMirror.copyState(s.fencedMode, s.fencedState) - : null, + basePos: s.basePos, + baseCur: null, + overlayPos: s.overlayPos, + overlayCur: null, - fencedEndRE: s.fencedEndRE, + fencedMode: s.fencedMode, + fencedState: s.fencedMode ? CodeMirror.copyState(s.fencedMode, s.fencedState) : null, - inTable: s.inTable, - rowIndex: s.rowIndex - } - }, - token: function(stream, state) { - const initialPos = stream.pos + fencedEndRE: s.fencedEndRE, + + inTable: s.inTable, + rowIndex: s.rowIndex + } + }, + token: function(stream, state) { + const initialPos = stream.pos - if (state.fencedEndRE && stream.match(state.fencedEndRE)) { + if (state.fencedEndRE) { + if (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) } 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) || '' - } - + } + else { 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) + state.fencedMode = getMode(match[2], match[3], config, stream.lineOracle.doc.cm) + if (state.fencedMode) { + state.fencedState = CodeMirror.startState(state.fencedMode) } - return null + 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) - state.combineTokens = true + 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.inTable) { - if (stream.match(/^\|/)) { - ++state.rowIndex + if (state.localMode) { + return state.localMode.token(stream, state.localState) || '' + } - stream.skipToEnd() + state.combineTokens = true - if (state.rowIndex === 1) { - return 'table table-separator' - } else if (state.rowIndex % 2 === 0) { - return 'table table-row table-row-even' - } else { - return 'table table-row table-row-odd' - } - } else { - state.inTable = false + if (state.inTable) { + if (stream.match(/^\|/)) { + ++state.rowIndex + + stream.skipToEnd() - stream.skipToEnd() - return null + if (state.rowIndex === 1) { + return 'table table-separator' + } else if (state.rowIndex % 2 === 0) { + return 'table table-row table-row-even' + } else { + return 'table table-row table-row-odd' } - } else if (stream.match(/^\|/)) { - state.inTable = true - state.rowIndex = 0 + } else { + state.inTable = false stream.skipToEnd() - return 'table table-header' + return null } + } else if (stream.match(/^\|/)) { + state.inTable = true + state.rowIndex = 0 stream.skipToEnd() - return null - }, - electricChars: baseMode.electricChars, - innerMode: function(state) { - if (state.fencedMode) { - return { - mode: state.fencedMode, - state: state.fencedState - } - } else { - return { - mode: baseMode, - state: state.baseState - } + return 'table table-header' + } + + stream.skipToEnd() + return null + }, + electricChars: baseMode.electricChars, + innerMode: function(state) { + if (state.fencedMode) { + return { + mode: state.fencedMode, + state: state.fencedState } - }, - blankLine: function(state) { - state.inTable = false - - if (state.fencedMode) { - return ( - state.fencedMode.blankLine && - state.fencedMode.blankLine(state.fencedState) - ) - } else { - return baseMode.blankLine(state.baseState) + } 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) + } } - }, - 'yaml-frontmatter' - ) + } + }, 'yaml-frontmatter') CodeMirror.defineMIME('text/x-bfm', 'bfm') @@ -259,4 +225,4 @@ mime: 'text/x-bfm', mode: 'bfm' }) -}) +}) \ No newline at end of file diff --git a/lib/main.development.html b/lib/main.development.html index 900c66c75..d6216b7e5 100644 --- a/lib/main.development.html +++ b/lib/main.development.html @@ -72,7 +72,7 @@ border-left-color: rgba(142, 142, 142, 0.5); mix-blend-mode: difference; } - + .CodeMirror-scroll { margin-bottom: 0; padding-bottom: 0; @@ -116,7 +116,7 @@ - + diff --git a/lib/main.production.html b/lib/main.production.html index 05d803450..289fe1b39 100644 --- a/lib/main.production.html +++ b/lib/main.production.html @@ -112,7 +112,7 @@ - +