mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-12 17:26:17 +00:00
Merge pull request #2594 from daiyam/fix-autocomplete-codeblock
improve autocomplete within code blocks
This commit is contained in:
@@ -341,10 +341,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
|
||||
@@ -649,16 +657,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) {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
@@ -746,6 +752,126 @@ class UiTab extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Matching character pairs')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.matchingPairs}
|
||||
ref='matchingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label-right'>
|
||||
{i18n.__('in code blocks')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.codeBlockMatchingPairs}
|
||||
ref='codeBlockMatchingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Close pairs before')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.matchingCloseBefore}
|
||||
ref='matchingCloseBefore'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label-right'>
|
||||
{i18n.__('in code blocks')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.codeBlockMatchingCloseBefore}
|
||||
ref='codeBlockMatchingCloseBefore'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Matching character triples')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.matchingTriples}
|
||||
ref='matchingTriples'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label-right'>
|
||||
{i18n.__('in code blocks')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.codeBlockMatchingTriples}
|
||||
ref='codeBlockMatchingTriples'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Exploding character pairs')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.explodingPairs}
|
||||
ref='explodingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label-right'>
|
||||
{i18n.__('in code blocks')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.codeBlockExplodingPairs}
|
||||
ref='codeBlockExplodingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-checkBoxSection'>
|
||||
<label>
|
||||
<input
|
||||
@@ -889,50 +1015,6 @@ class UiTab extends React.Component {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Matching character pairs')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.matchingPairs}
|
||||
ref='matchingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Matching character triples')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.matchingTriples}
|
||||
ref='matchingTriples'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Exploding character pairs')}
|
||||
</div>
|
||||
<div styleName='group-section-control'>
|
||||
<input
|
||||
styleName='group-section-control-input'
|
||||
value={this.state.config.editor.explodingPairs}
|
||||
ref='explodingPairs'
|
||||
onChange={e => this.handleUIChange(e)}
|
||||
type='text'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div styleName='group-section'>
|
||||
<div styleName='group-section-label'>
|
||||
{i18n.__('Custom MarkdownLint Rules')}
|
||||
|
||||
196
extra_scripts/codemirror/addon/edit/closebrackets.js
vendored
Normal file
196
extra_scripts/codemirror/addon/edit/closebrackets.js
vendored
Normal file
@@ -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)))
|
||||
}
|
||||
});
|
||||
302
extra_scripts/codemirror/mode/bfm/bfm.js
vendored
302
extra_scripts/codemirror/mode/bfm/bfm.js
vendored
@@ -55,202 +55,168 @@
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineMode(
|
||||
'bfm',
|
||||
function(config, baseConfig) {
|
||||
baseConfig.name = 'yaml-frontmatter'
|
||||
const baseMode = CodeMirror.getMode(config, baseConfig)
|
||||
CodeMirror.defineMode('bfm', function (config, baseConfig) {
|
||||
baseConfig.name = 'yaml-frontmatter'
|
||||
const baseMode = CodeMirror.getMode(config, baseConfig)
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
baseState: CodeMirror.startState(baseMode),
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
baseState: CodeMirror.startState(baseMode),
|
||||
|
||||
basePos: 0,
|
||||
baseCur: null,
|
||||
overlayPos: 0,
|
||||
overlayCur: null,
|
||||
streamSeen: null,
|
||||
basePos: 0,
|
||||
baseCur: null,
|
||||
overlayPos: 0,
|
||||
overlayCur: null,
|
||||
streamSeen: null,
|
||||
|
||||
fencedEndRE: null,
|
||||
fencedEndRE: null,
|
||||
|
||||
inTable: false,
|
||||
rowIndex: 0
|
||||
}
|
||||
},
|
||||
copyState: function(s) {
|
||||
return {
|
||||
baseState: CodeMirror.copyState(baseMode, s.baseState),
|
||||
inTable: false,
|
||||
rowIndex: 0
|
||||
}
|
||||
},
|
||||
copyState: function(s) {
|
||||
return {
|
||||
baseState: CodeMirror.copyState(baseMode, s.baseState),
|
||||
|
||||
basePos: s.basePos,
|
||||
baseCur: null,
|
||||
overlayPos: s.overlayPos,
|
||||
overlayCur: null,
|
||||
basePos: s.basePos,
|
||||
baseCur: null,
|
||||
overlayPos: s.overlayPos,
|
||||
overlayCur: null,
|
||||
|
||||
fencedMode: s.fencedMode,
|
||||
fencedState: s.fencedMode
|
||||
? CodeMirror.copyState(s.fencedMode, s.fencedState)
|
||||
: null,
|
||||
fencedMode: s.fencedMode,
|
||||
fencedState: s.fencedMode ? CodeMirror.copyState(s.fencedMode, s.fencedState) : null,
|
||||
|
||||
fencedEndRE: s.fencedEndRE,
|
||||
fencedEndRE: s.fencedEndRE,
|
||||
|
||||
inTable: s.inTable,
|
||||
rowIndex: s.rowIndex
|
||||
}
|
||||
},
|
||||
token: function(stream, state) {
|
||||
const initialPos = stream.pos
|
||||
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
|
||||
}
|
||||
|
||||
state.combineTokens = true
|
||||
|
||||
if (state.inTable) {
|
||||
if (stream.match(/^\|/)) {
|
||||
++state.rowIndex
|
||||
|
||||
stream.skipToEnd()
|
||||
|
||||
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
|
||||
|
||||
stream.skipToEnd()
|
||||
return null
|
||||
}
|
||||
} else if (stream.match(/^\|/)) {
|
||||
state.inTable = true
|
||||
state.rowIndex = 0
|
||||
|
||||
stream.skipToEnd()
|
||||
return 'table table-header'
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
},
|
||||
blankLine: function(state) {
|
||||
state.inTable = false
|
||||
|
||||
if (state.fencedMode) {
|
||||
return (
|
||||
state.fencedMode.blankLine &&
|
||||
state.fencedMode.blankLine(state.fencedState)
|
||||
)
|
||||
} else {
|
||||
return baseMode.blankLine(state.baseState)
|
||||
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.localMode) {
|
||||
return state.localMode.token(stream, state.localState) || ''
|
||||
}
|
||||
|
||||
state.combineTokens = true
|
||||
|
||||
if (state.inTable) {
|
||||
if (stream.match(/^\|/)) {
|
||||
++state.rowIndex
|
||||
|
||||
stream.skipToEnd()
|
||||
|
||||
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
|
||||
|
||||
stream.skipToEnd()
|
||||
return null
|
||||
}
|
||||
} else if (stream.match(/^\|/)) {
|
||||
state.inTable = true
|
||||
state.rowIndex = 0
|
||||
|
||||
stream.skipToEnd()
|
||||
return 'table table-header'
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
},
|
||||
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'
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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 @@
|
||||
<script src="../extra_scripts/codemirror/mode/gfm/gfm.js"></script>
|
||||
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
|
||||
|
||||
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||
<script src="../extra_scripts/codemirror/addon/edit/closebrackets.js"></script>
|
||||
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>
|
||||
|
||||
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<script src="../extra_scripts/codemirror/mode/gfm/gfm.js"></script>
|
||||
<script src="../extra_scripts/codemirror/addon/hyperlink/hyperlink.js"></script>
|
||||
|
||||
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||
<script src="../extra_scripts/codemirror/addon/edit/closebrackets.js"></script>
|
||||
<script src="../node_modules/codemirror/addon/edit/matchbrackets.js"></script>
|
||||
|
||||
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user