mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-30 17:32:38 +00:00
Replace copied code with require methods to import the CodeMirror helpers
Put back the correct require notation for importing the foldcode and foldgutter helpers #629
This commit is contained in:
@@ -14,8 +14,11 @@ if(typeof navigator !== 'undefined'){
|
|||||||
require('codemirror/mode/css/css.js');
|
require('codemirror/mode/css/css.js');
|
||||||
require('codemirror/mode/javascript/javascript.js');
|
require('codemirror/mode/javascript/javascript.js');
|
||||||
|
|
||||||
|
// this should add the foldcode helpers and such to the CodeMirror object, but seemingly is adding them to a new instance of CodeMirror
|
||||||
|
require('codemirror/addon/fold/foldcode.js');
|
||||||
|
require('codemirror/addon/fold/foldgutter.js');
|
||||||
|
|
||||||
const foldCode = require('./fold-code');
|
const foldCode = require('./fold-code');
|
||||||
foldCode.enableCodeFolding(CodeMirror);
|
|
||||||
foldCode.registerHomebreweryHelper(CodeMirror);
|
foldCode.registerHomebreweryHelper(CodeMirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +43,10 @@ const CodeEditor = createClass({
|
|||||||
const newDoc = CodeMirror.Doc(this.props.value, this.props.language);
|
const newDoc = CodeMirror.Doc(this.props.value, this.props.language);
|
||||||
this.codeMirror.swapDoc(newDoc);
|
this.codeMirror.swapDoc(newDoc);
|
||||||
},
|
},
|
||||||
|
getSnapshotBeforeUpdate : function() {
|
||||||
componentDidUpdate : function(prevProps) {
|
return _.uniq(this.codeMirror.getAllMarks().filter((mark)=>mark.__isFold).map((mark)=>mark.find().from));
|
||||||
|
},
|
||||||
|
componentDidUpdate : function(prevProps, prevState, snapshot) {
|
||||||
if(prevProps.view !== this.props.view){ //view changed; swap documents
|
if(prevProps.view !== this.props.view){ //view changed; swap documents
|
||||||
let newDoc;
|
let newDoc;
|
||||||
|
|
||||||
@@ -61,6 +66,12 @@ const CodeEditor = createClass({
|
|||||||
} else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
|
} else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
|
||||||
this.codeMirror.setValue(this.props.value);
|
this.codeMirror.setValue(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTimeout(()=>{
|
||||||
|
snapshot.forEach((fold)=>{
|
||||||
|
this.codeMirror.foldCode(fold, { scanUp: false }, 'fold');
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
buildEditor : function() {
|
buildEditor : function() {
|
||||||
@@ -79,12 +90,30 @@ const CodeEditor = createClass({
|
|||||||
'Cmd-M' : this.makeSpan,
|
'Cmd-M' : this.makeSpan,
|
||||||
'Ctrl-/' : this.makeComment,
|
'Ctrl-/' : this.makeComment,
|
||||||
'Cmd-/' : this.makeComment,
|
'Cmd-/' : this.makeComment,
|
||||||
'Ctrl-,' : this.toggleCodeFolded,
|
'Ctrl-\\' : this.toggleCodeFolded,
|
||||||
'Cmd-,' : this.toggleCodeFolded
|
'Cmd-\\' : this.toggleCodeFolded,
|
||||||
|
'Ctrl-[' : this.foldAllCode,
|
||||||
|
'Cmd-[' : this.foldAllCode,
|
||||||
|
'Ctrl-]' : this.unfoldAllCode,
|
||||||
|
'Cmd-]' : this.unfoldAllCode
|
||||||
},
|
},
|
||||||
foldGutter : true,
|
foldGutter : true,
|
||||||
foldOptions : {
|
foldOptions : {
|
||||||
rangeFinder : CodeMirror.fold.homebrewery,
|
rangeFinder : CodeMirror.fold.homebrewery,
|
||||||
|
widget : (from, to)=>{
|
||||||
|
let text = '';
|
||||||
|
let currentLine = from.line;
|
||||||
|
const maxLength = 50;
|
||||||
|
while (currentLine <= to.line && text.length <= maxLength) {
|
||||||
|
text += this.codeMirror.getLine(currentLine);
|
||||||
|
if(currentLine < to.line) {
|
||||||
|
text += ' ';
|
||||||
|
}
|
||||||
|
currentLine += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `\u21A4${text.substr(0, maxLength)}\u21A6`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
gutters : ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
|
gutters : ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
|
||||||
});
|
});
|
||||||
@@ -134,6 +163,14 @@ const CodeEditor = createClass({
|
|||||||
this.codeMirror.foldCode(this.codeMirror.getCursor());
|
this.codeMirror.foldCode(this.codeMirror.getCursor());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
foldAllCode : function() {
|
||||||
|
this.codeMirror.execCommand('foldAll');
|
||||||
|
},
|
||||||
|
|
||||||
|
unfoldAllCode : function() {
|
||||||
|
this.codeMirror.execCommand('unfoldAll');
|
||||||
|
},
|
||||||
|
|
||||||
//=-- Externally used -==//
|
//=-- Externally used -==//
|
||||||
setCursorPosition : function(line, char){
|
setCursorPosition : function(line, char){
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
@import (less) 'codemirror/addon/fold/foldgutter.css';
|
@import (less) 'codemirror/addon/fold/foldgutter.css';
|
||||||
|
|
||||||
.codeEditor{
|
.codeEditor{
|
||||||
|
.CodeMirror-foldmarker {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,313 +1,4 @@
|
|||||||
/* eslint-disable max-lines */
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
enableCodeFolding : function (CodeMirror) {
|
|
||||||
// foldcode.js
|
|
||||||
const makeWidget = function(cm, options, range) {
|
|
||||||
let widget = getOption(cm, options, 'widget');
|
|
||||||
|
|
||||||
if(typeof widget == 'function') {
|
|
||||||
widget = widget(range.from, range.to);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof widget == 'string') {
|
|
||||||
const text = document.createTextNode(widget);
|
|
||||||
widget = document.createElement('span');
|
|
||||||
widget.appendChild(text);
|
|
||||||
widget.className = 'CodeMirror-foldmarker';
|
|
||||||
} else if(widget) {
|
|
||||||
widget = widget.cloneNode(true);
|
|
||||||
}
|
|
||||||
return widget;
|
|
||||||
};
|
|
||||||
|
|
||||||
const doFold = function(cm, pos, options, force) {
|
|
||||||
let finder;
|
|
||||||
if(options && options.call) {
|
|
||||||
finder = options;
|
|
||||||
options = null;
|
|
||||||
} else {
|
|
||||||
finder = getOption(cm, options, 'rangeFinder');
|
|
||||||
}
|
|
||||||
if(typeof pos == 'number') pos = CodeMirror.Pos(pos, 0);
|
|
||||||
const minSize = getOption(cm, options, 'minFoldSize');
|
|
||||||
|
|
||||||
const getRange = function(allowFolded) {
|
|
||||||
const range = finder(cm, pos);
|
|
||||||
if(!range || range.to.line - range.from.line < minSize) return null;
|
|
||||||
if(force === 'fold') return range;
|
|
||||||
|
|
||||||
const marks = cm.findMarksAt(range.from);
|
|
||||||
for (let i = 0; i < marks.length; ++i) {
|
|
||||||
if(marks[i].__isFold) {
|
|
||||||
if(!allowFolded) return null;
|
|
||||||
range.cleared = true;
|
|
||||||
marks[i].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return range;
|
|
||||||
};
|
|
||||||
|
|
||||||
let range = getRange(true);
|
|
||||||
if(getOption(cm, options, 'scanUp')) while (!range && pos.line > cm.firstLine()) {
|
|
||||||
pos = CodeMirror.Pos(pos.line - 1, 0);
|
|
||||||
range = getRange(false);
|
|
||||||
}
|
|
||||||
if(!range || range.cleared || force === 'unfold') return;
|
|
||||||
|
|
||||||
const myWidget = makeWidget(cm, options, range);
|
|
||||||
CodeMirror.on(myWidget, 'mousedown', function (e) {
|
|
||||||
myRange.clear();
|
|
||||||
CodeMirror.e_preventDefault(e);
|
|
||||||
});
|
|
||||||
const myRange = cm.markText(range.from, range.to, {
|
|
||||||
replacedWith : myWidget,
|
|
||||||
clearOnEnter : getOption(cm, options, 'clearOnEnter'),
|
|
||||||
__isFold : true
|
|
||||||
});
|
|
||||||
myRange.on('clear', function (from, to) {
|
|
||||||
CodeMirror.signal(cm, 'unfold', cm, from, to);
|
|
||||||
});
|
|
||||||
CodeMirror.signal(cm, 'fold', cm, range.from, range.to);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clumsy backwards-compatible interface
|
|
||||||
CodeMirror.newFoldFunction = function (rangeFinder, widget) {
|
|
||||||
return function (cm, pos) {
|
|
||||||
doFold(cm, pos, { rangeFinder: rangeFinder, widget: widget });
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// New-style interface
|
|
||||||
CodeMirror.defineExtension('foldCode', function (pos, options, force) {
|
|
||||||
doFold(this, pos, options, force);
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.defineExtension('isFolded', function (pos) {
|
|
||||||
const marks = this.findMarksAt(pos);
|
|
||||||
for (let i = 0; i < marks.length; ++i)
|
|
||||||
if(marks[i].__isFold) return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.commands.toggleFold = function (cm) {
|
|
||||||
cm.foldCode(cm.getCursor());
|
|
||||||
};
|
|
||||||
CodeMirror.commands.fold = function (cm) {
|
|
||||||
cm.foldCode(cm.getCursor(), null, 'fold');
|
|
||||||
};
|
|
||||||
CodeMirror.commands.unfold = function (cm) {
|
|
||||||
cm.foldCode(cm.getCursor(), { scanUp: false }, 'unfold');
|
|
||||||
};
|
|
||||||
CodeMirror.commands.foldAll = function (cm) {
|
|
||||||
cm.operation(function () {
|
|
||||||
for (let i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
|
|
||||||
cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, 'fold');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
CodeMirror.commands.unfoldAll = function (cm) {
|
|
||||||
cm.operation(function () {
|
|
||||||
for (let i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
|
|
||||||
cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, 'unfold');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.registerHelper('fold', 'combine', function () {
|
|
||||||
const funcs = Array.prototype.slice.call(arguments, 0);
|
|
||||||
return function (cm, start) {
|
|
||||||
for (let i = 0; i < funcs.length; ++i) {
|
|
||||||
const found = funcs[i](cm, start);
|
|
||||||
if(found) return found;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.registerHelper('fold', 'auto', function (cm, start) {
|
|
||||||
const helpers = cm.getHelpers(start, 'fold');
|
|
||||||
for (let i = 0; i < helpers.length; i++) {
|
|
||||||
const cur = helpers[i](cm, start);
|
|
||||||
if(cur) return cur;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
rangeFinder : CodeMirror.fold.auto,
|
|
||||||
widget : '\u2194',
|
|
||||||
minFoldSize : 0,
|
|
||||||
scanUp : false,
|
|
||||||
clearOnEnter : true
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.defineOption('foldOptions', null);
|
|
||||||
|
|
||||||
const getOption = function(cm, options, name) {
|
|
||||||
if(options && options[name] !== undefined)
|
|
||||||
return options[name];
|
|
||||||
const editorOptions = cm.options.foldOptions;
|
|
||||||
if(editorOptions && editorOptions[name] !== undefined)
|
|
||||||
return editorOptions[name];
|
|
||||||
return defaultOptions[name];
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.defineExtension('foldOption', function (options, name) {
|
|
||||||
return getOption(this, options, name);
|
|
||||||
});
|
|
||||||
|
|
||||||
// foldgutter.js
|
|
||||||
const State = function(options) {
|
|
||||||
this.options = options;
|
|
||||||
this.from = this.to = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseOptions = function(opts) {
|
|
||||||
if(opts === true) opts = {};
|
|
||||||
if(opts.gutter == null) opts.gutter = 'CodeMirror-foldgutter';
|
|
||||||
if(opts.indicatorOpen == null) opts.indicatorOpen = 'CodeMirror-foldgutter-open';
|
|
||||||
if(opts.indicatorFolded == null) opts.indicatorFolded = 'CodeMirror-foldgutter-folded';
|
|
||||||
return opts;
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.defineOption('foldGutter', false, function (cm, val, old) {
|
|
||||||
if(old && old != CodeMirror.Init) {
|
|
||||||
cm.clearGutter(cm.state.foldGutter.options.gutter);
|
|
||||||
cm.state.foldGutter = null;
|
|
||||||
cm.off('gutterClick', onGutterClick);
|
|
||||||
cm.off('changes', onChange);
|
|
||||||
cm.off('viewportChange', onViewportChange);
|
|
||||||
cm.off('fold', onFold);
|
|
||||||
cm.off('unfold', onFold);
|
|
||||||
cm.off('swapDoc', onChange);
|
|
||||||
}
|
|
||||||
if(val) {
|
|
||||||
cm.state.foldGutter = new State(parseOptions(val));
|
|
||||||
updateInViewport(cm);
|
|
||||||
cm.on('gutterClick', onGutterClick);
|
|
||||||
cm.on('changes', onChange);
|
|
||||||
cm.on('viewportChange', onViewportChange);
|
|
||||||
cm.on('fold', onFold);
|
|
||||||
cm.on('unfold', onFold);
|
|
||||||
cm.on('swapDoc', onChange);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Pos = CodeMirror.Pos;
|
|
||||||
|
|
||||||
const isFolded = function(cm, line) {
|
|
||||||
const marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
|
|
||||||
for (let i = 0; i < marks.length; ++i) {
|
|
||||||
if(marks[i].__isFold) {
|
|
||||||
const fromPos = marks[i].find(-1);
|
|
||||||
if(fromPos && fromPos.line === line)
|
|
||||||
return marks[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const marker = function(spec) {
|
|
||||||
if(typeof spec == 'string') {
|
|
||||||
const elt = document.createElement('div');
|
|
||||||
elt.className = `${spec} CodeMirror-guttermarker-subtle`;
|
|
||||||
return elt;
|
|
||||||
} else {
|
|
||||||
return spec.cloneNode(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateFoldInfo = function(cm, from, to) {
|
|
||||||
const opts = cm.state.foldGutter.options;
|
|
||||||
let cur = from - 1;
|
|
||||||
const minSize = cm.foldOption(opts, 'minFoldSize');
|
|
||||||
const func = cm.foldOption(opts, 'rangeFinder');
|
|
||||||
// we can reuse the built-in indicator element if its className matches the new state
|
|
||||||
const clsFolded = typeof opts.indicatorFolded == 'string' && classTest(opts.indicatorFolded);
|
|
||||||
const clsOpen = typeof opts.indicatorOpen == 'string' && classTest(opts.indicatorOpen);
|
|
||||||
cm.eachLine(from, to, function (line) {
|
|
||||||
++cur;
|
|
||||||
let mark = null;
|
|
||||||
let old = line.gutterMarkers;
|
|
||||||
if(old) old = old[opts.gutter];
|
|
||||||
if(isFolded(cm, cur)) {
|
|
||||||
if(clsFolded && old && clsFolded.test(old.className)) return;
|
|
||||||
mark = marker(opts.indicatorFolded);
|
|
||||||
} else {
|
|
||||||
const pos = Pos(cur, 0);
|
|
||||||
const range = func && func(cm, pos);
|
|
||||||
if(range && range.to.line - range.from.line >= minSize) {
|
|
||||||
if(clsOpen && old && clsOpen.test(old.className)) return;
|
|
||||||
mark = marker(opts.indicatorOpen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!mark && !old) return;
|
|
||||||
cm.setGutterMarker(line, opts.gutter, mark);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// copied from CodeMirror/src/util/dom.js
|
|
||||||
const classTest = function(cls) {
|
|
||||||
return new RegExp(`(^|\\s)${cls}(?:$|\\s)\\s*`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateInViewport = function(cm) {
|
|
||||||
const vp = cm.getViewport(), state = cm.state.foldGutter;
|
|
||||||
if(!state) return;
|
|
||||||
cm.operation(function () {
|
|
||||||
updateFoldInfo(cm, vp.from, vp.to);
|
|
||||||
});
|
|
||||||
state.from = vp.from;
|
|
||||||
state.to = vp.to;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onGutterClick = function(cm, line, gutter) {
|
|
||||||
const state = cm.state.foldGutter;
|
|
||||||
if(!state) return;
|
|
||||||
const opts = state.options;
|
|
||||||
if(gutter != opts.gutter) return;
|
|
||||||
const folded = isFolded(cm, line);
|
|
||||||
if(folded) folded.clear();
|
|
||||||
else cm.foldCode(Pos(line, 0), opts);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onChange = function(cm) {
|
|
||||||
const state = cm.state.foldGutter;
|
|
||||||
if(!state) return;
|
|
||||||
const opts = state.options;
|
|
||||||
state.from = state.to = 0;
|
|
||||||
clearTimeout(state.changeUpdate);
|
|
||||||
state.changeUpdate = setTimeout(function () {
|
|
||||||
updateInViewport(cm);
|
|
||||||
}, opts.foldOnChangeTimeSpan || 600);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onViewportChange = function(cm) {
|
|
||||||
const state = cm.state.foldGutter;
|
|
||||||
if(!state) return;
|
|
||||||
const opts = state.options;
|
|
||||||
clearTimeout(state.changeUpdate);
|
|
||||||
state.changeUpdate = setTimeout(function () {
|
|
||||||
const vp = cm.getViewport();
|
|
||||||
if(state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
|
|
||||||
updateInViewport(cm);
|
|
||||||
} else {
|
|
||||||
cm.operation(function () {
|
|
||||||
if(vp.from < state.from) {
|
|
||||||
updateFoldInfo(cm, vp.from, state.from);
|
|
||||||
state.from = vp.from;
|
|
||||||
}
|
|
||||||
if(vp.to > state.to) {
|
|
||||||
updateFoldInfo(cm, state.to, vp.to);
|
|
||||||
state.to = vp.to;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, opts.updateViewportTimeSpan || 400);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onFold = function(cm, from) {
|
|
||||||
const state = cm.state.foldGutter;
|
|
||||||
if(!state) return;
|
|
||||||
const line = from.line;
|
|
||||||
if(line >= state.from && line < state.to)
|
|
||||||
updateFoldInfo(cm, line, line + 1);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
registerHomebreweryHelper : function(CodeMirror) {
|
registerHomebreweryHelper : function(CodeMirror) {
|
||||||
CodeMirror.registerHelper('fold', 'homebrewery', function(cm, start) {
|
CodeMirror.registerHelper('fold', 'homebrewery', function(cm, start) {
|
||||||
const matcher = /^\\page.*/;
|
const matcher = /^\\page.*/;
|
||||||
@@ -321,7 +12,7 @@ module.exports = {
|
|||||||
while (end < lastLineNo) {
|
while (end < lastLineNo) {
|
||||||
if(nextLine.match(matcher)) {
|
if(nextLine.match(matcher)) {
|
||||||
return {
|
return {
|
||||||
from : CodeMirror.Pos(start.line, firstLine.length),
|
from : CodeMirror.Pos(start.line, 0),
|
||||||
to : CodeMirror.Pos(end, cm.getLine(end).length)
|
to : CodeMirror.Pos(end, cm.getLine(end).length)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user