restore the original match-highlighter and monkeypatch it
This commit is contained in:
parent
c1c61ed590
commit
a30ef3ed14
|
@ -37,7 +37,7 @@
|
|||
<link rel="stylesheet" href="vendor/codemirror/addon/search/matchesonscrollbar.css">
|
||||
<script src="vendor/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
||||
<script src="vendor/codemirror/addon/search/matchesonscrollbar.js"></script>
|
||||
<script src="vendor-overwrites/codemirror/addon/search/match-highlighter.js"></script>
|
||||
<script src="vendor/codemirror/addon/search/match-highlighter.js"></script>
|
||||
<script src="vendor/codemirror/addon/dialog/dialog.js"></script>
|
||||
<script src="vendor/codemirror/addon/search/searchcursor.js"></script>
|
||||
<script src="vendor/codemirror/addon/search/search.js"></script>
|
||||
|
@ -61,6 +61,7 @@
|
|||
<script src="vendor/codemirror/keymap/emacs.js"></script>
|
||||
<script src="vendor/codemirror/keymap/vim.js"></script>
|
||||
|
||||
<script src="/edit/match-highlighter-helper.js"></script>
|
||||
<script src="/edit/codemirror-default.js"></script>
|
||||
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
||||
<link id="cm-theme" rel="stylesheet">
|
||||
|
|
99
edit/match-highlighter-helper.js
Normal file
99
edit/match-highlighter-helper.js
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* global CodeMirror */
|
||||
'use strict';
|
||||
|
||||
(() => {
|
||||
const HL_APPROVED = 'cm-matchhighlight-approved';
|
||||
const originalAddOverlay = CodeMirror.prototype.addOverlay;
|
||||
const originalRemoveOverlay = CodeMirror.prototype.removeOverlay;
|
||||
CodeMirror.prototype.addOverlay = addOverlay;
|
||||
CodeMirror.prototype.removeOverlay = removeOverlay;
|
||||
return;
|
||||
|
||||
function shouldIntercept(overlay) {
|
||||
const hlState = this.state.matchHighlighter || {};
|
||||
return overlay === hlState.overlay && (hlState.options || {}).showToken;
|
||||
}
|
||||
|
||||
function addOverlay() {
|
||||
return shouldIntercept.apply(this, arguments) &&
|
||||
addOverlayForHighlighter.apply(this, arguments) ||
|
||||
originalAddOverlay.apply(this, arguments);
|
||||
}
|
||||
|
||||
function removeOverlay() {
|
||||
return shouldIntercept.apply(this, arguments) &&
|
||||
removeOverlayForHighlighter.apply(this, arguments) ||
|
||||
originalRemoveOverlay.apply(this, arguments);
|
||||
}
|
||||
|
||||
function addOverlayForHighlighter(overlay) {
|
||||
const state = this.state.matchHighlighter || {};
|
||||
const helper = state.stylusMHLHelper || {};
|
||||
if (helper.matchesonscroll) {
|
||||
// restore the original addon's unwanted removeOverlay effects
|
||||
// (in case the token under cursor hasn't changed)
|
||||
state.matchesonscroll = helper.matchesonscroll;
|
||||
state.overlay = helper.overlay;
|
||||
helper.matchesonscroll = null;
|
||||
helper.overlay = null;
|
||||
return true;
|
||||
}
|
||||
if (overlay.token !== tokenHook) {
|
||||
overlay.stylusMHLHelper = {
|
||||
token: overlay.token,
|
||||
occurrences: 0,
|
||||
};
|
||||
overlay.token = tokenHook;
|
||||
}
|
||||
clearTimeout(helper.hookTimer);
|
||||
}
|
||||
|
||||
function tokenHook(stream) {
|
||||
const style = this.stylusMHLHelper.token.call(this, stream);
|
||||
if (style !== 'matchhighlight') {
|
||||
return style;
|
||||
}
|
||||
const num = ++this.stylusMHLHelper.occurrences;
|
||||
if (num === 1) {
|
||||
stream.lineOracle.doc.cm.display.wrapper.classList.remove(HL_APPROVED);
|
||||
} else if (num === 2) {
|
||||
stream.lineOracle.doc.cm.display.wrapper.classList.add(HL_APPROVED);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function removeOverlayForHighlighter() {
|
||||
const state = this.state.matchHighlighter || {};
|
||||
const {query} = state.matchesonscroll || {};
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
const {line, ch} = this.getCursor();
|
||||
const rx = query instanceof RegExp ? query : new RegExp(`\\b${query}\\b`);
|
||||
const start = Math.max(0, ch - rx.source.length + 4 + 1);
|
||||
const end = ch + rx.source.length - 4;
|
||||
const area = this.getLine(line).substring(start, end);
|
||||
const startInArea = (area.match(rx) || {}).index;
|
||||
if (start + startInArea <= ch) {
|
||||
// same token on cursor => prevent the highlighter from rerunning
|
||||
state.stylusMHLHelper = {
|
||||
overlay: state.overlay,
|
||||
matchesonscroll: state.matchesonscroll,
|
||||
hookTimer: setTimeout(removeOverlayIfExpired, 0, this, state),
|
||||
};
|
||||
state.matchesonscroll = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function removeOverlayIfExpired(self, state) {
|
||||
const {overlay, matchesonscroll} = state.stylusMHLHelper || {};
|
||||
if (overlay) {
|
||||
originalRemoveOverlay.call(self, overlay);
|
||||
}
|
||||
if (matchesonscroll) {
|
||||
matchesonscroll.clear();
|
||||
}
|
||||
state.stylusMHLHelper = null;
|
||||
}
|
||||
})();
|
|
@ -23,6 +23,7 @@
|
|||
<script src="/vendor/codemirror/keymap/emacs.js"></script>
|
||||
<script src="/vendor/codemirror/keymap/vim.js"></script>
|
||||
|
||||
<script src="/edit/match-highlighter-helper.js"></script>
|
||||
<script src="/edit/codemirror-default.js"></script>
|
||||
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
||||
|
||||
|
@ -32,7 +33,7 @@
|
|||
<link rel="stylesheet" href="/vendor/codemirror/addon/search/matchesonscrollbar.css">
|
||||
<script src="/vendor/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
||||
<script src="/vendor/codemirror/addon/search/matchesonscrollbar.js"></script>
|
||||
<script src="/vendor-overwrites/codemirror/addon/search/match-highlighter.js"></script>
|
||||
<script src="/vendor/codemirror/addon/search/match-highlighter.js"></script>
|
||||
<script src="/vendor/codemirror/addon/dialog/dialog.js"></script>
|
||||
<script src="/vendor/codemirror/addon/search/searchcursor.js"></script>
|
||||
<script src="/vendor/codemirror/addon/search/search.js"></script>
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
// highlighting the matches. If annotateScrollbar is enabled, the occurences
|
||||
// will be highlighted on the scrollbar via the matchesonscrollbar addon.
|
||||
|
||||
/* STYLUS: hack start (part 1) */
|
||||
/* eslint curly: 1, brace-style:1, strict: 0, quotes: 0, semi: 1, indent: 1 */
|
||||
/* eslint no-var: 0, block-scoped-var: 0, no-redeclare: 0, no-unused-expressions: 1 */
|
||||
/* global CodeMirror, require, define */
|
||||
/* STYLUS: hack end (part 1) */
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("./matchesonscrollbar"));
|
||||
|
@ -94,9 +88,7 @@
|
|||
|
||||
function addOverlay(cm, query, hasBoundary, style) {
|
||||
var state = cm.state.matchHighlighter;
|
||||
/* STYLUS: hack start (part 2) */
|
||||
cm.addOverlay(state.overlay = makeOverlay(cm, query, hasBoundary, style));
|
||||
/* STYLUS: hack end (part 2) */
|
||||
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
|
||||
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
|
||||
var searchFor = hasBoundary ? new RegExp("\\b" + query + "\\b") : query;
|
||||
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
|
||||
|
@ -119,24 +111,16 @@
|
|||
function highlightMatches(cm) {
|
||||
cm.operation(function() {
|
||||
var state = cm.state.matchHighlighter;
|
||||
removeOverlay(cm);
|
||||
if (!cm.somethingSelected() && state.options.showToken) {
|
||||
var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
|
||||
var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
|
||||
while (start && re.test(line.charAt(start - 1))) --start;
|
||||
while (end < line.length && re.test(line.charAt(end))) ++end;
|
||||
/* STYLUS: hack start */
|
||||
const token = line.slice(start, end);
|
||||
if (token !== state.lastToken) {
|
||||
state.lastToken = token;
|
||||
removeOverlay(cm);
|
||||
if (token) {
|
||||
addOverlay(cm, token, re, state.options.style);
|
||||
}
|
||||
}
|
||||
if (start < end)
|
||||
addOverlay(cm, line.slice(start, end), re, state.options.style);
|
||||
return;
|
||||
}
|
||||
removeOverlay(cm);
|
||||
/* STYLUS: hack end */
|
||||
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
||||
if (from.line != to.line) return;
|
||||
if (state.options.wordsOnly && !isWord(cm, from, to)) return;
|
||||
|
@ -169,28 +153,11 @@
|
|||
(stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
|
||||
}
|
||||
|
||||
function makeOverlay(cm, query, hasBoundary, style) {
|
||||
/* STYLUS: hack start (part 3) */
|
||||
const approvedClassName = `cm-${style}-approved`;
|
||||
let timer;
|
||||
let occurrences = 0;
|
||||
function makeOverlay(query, hasBoundary, style) {
|
||||
return {token: function(stream) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
occurrences = 0;
|
||||
timer = null;
|
||||
});
|
||||
if (stream.match(query) &&
|
||||
(!hasBoundary || boundariesAround(stream, hasBoundary))) {
|
||||
occurrences++;
|
||||
if (occurrences == 1) {
|
||||
cm.display.wrapper.classList.remove(approvedClassName);
|
||||
} else if (occurrences == 2) {
|
||||
cm.display.wrapper.classList.add(approvedClassName);
|
||||
}
|
||||
(!hasBoundary || boundariesAround(stream, hasBoundary)))
|
||||
return style;
|
||||
}
|
||||
/* STYLUS: hack end (part 3) */
|
||||
stream.next();
|
||||
stream.skipTo(query.charAt(0)) || stream.skipToEnd();
|
||||
}};
|
Loading…
Reference in New Issue
Block a user