prevent inline overlays from breaking color swatches
This commit is contained in:
parent
7e4683d417
commit
7c0d8f0841
|
@ -1,7 +1,8 @@
|
||||||
/* global CodeMirror loadScript editors showHelp */
|
/* global CodeMirror loadScript editors showHelp */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
window.initColorpicker = () => {
|
// eslint-disable-next-line no-var
|
||||||
|
var initColorpicker = () => {
|
||||||
initOverlayHooks();
|
initOverlayHooks();
|
||||||
onDOMready().then(() => {
|
onDOMready().then(() => {
|
||||||
$('#colorpicker-settings').onclick = configureColorpicker;
|
$('#colorpicker-settings').onclick = configureColorpicker;
|
||||||
|
@ -109,41 +110,37 @@ window.initColorpicker = () => {
|
||||||
|
|
||||||
function initOverlayHooks() {
|
function initOverlayHooks() {
|
||||||
const COLORVIEW_DISABLED_SUFFIX = ' colorview-disabled';
|
const COLORVIEW_DISABLED_SUFFIX = ' colorview-disabled';
|
||||||
|
const COLORVIEW_NEXT_DISABLED_SUFFIX = ' colorview-next-disabled';
|
||||||
const originalAddOverlay = CodeMirror.prototype.addOverlay;
|
const originalAddOverlay = CodeMirror.prototype.addOverlay;
|
||||||
CodeMirror.prototype.addOverlay = addOverlayHook;
|
CodeMirror.prototype.addOverlay = addOverlayHook;
|
||||||
|
|
||||||
function addOverlayHook(overlay) {
|
function addOverlayHook(overlay) {
|
||||||
if (overlay === (this.state.matchHighlighter || {}).overlay) {
|
if (overlay.token !== tokenHook && (
|
||||||
if (overlay.token !== tokenHook) {
|
overlay === (this.state.matchHighlighter || {}).overlay ||
|
||||||
overlay.stylusColorpickerHelper = {
|
overlay === (this.state.search || {}).overlay)) {
|
||||||
token: overlay.token,
|
overlay.colopickerHelper = {token: overlay.token};
|
||||||
};
|
overlay.token = tokenHook;
|
||||||
overlay.token = tokenHook;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
originalAddOverlay.apply(this, arguments);
|
originalAddOverlay.apply(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tokenHook(stream) {
|
function tokenHook(stream) {
|
||||||
const style = this.stylusColorpickerHelper.token.call(this, stream);
|
const style = this.colopickerHelper.token.apply(this, arguments);
|
||||||
if (style === 'matchhighlight') {
|
if (!style) {
|
||||||
return tokenHookForHighlighter.call(this, stream, style);
|
|
||||||
} else {
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function tokenHookForHighlighter(stream, style) {
|
|
||||||
const {start, pos, lineOracle: {baseTokens}} = stream;
|
const {start, pos, lineOracle: {baseTokens}} = stream;
|
||||||
if (!baseTokens) {
|
if (!baseTokens) {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
for (let prev = 0, i = 1; i < baseTokens.length; i += 2) {
|
for (let prev = 0, i = 1; i < baseTokens.length; i += 2) {
|
||||||
const end = baseTokens[i];
|
const end = baseTokens[i];
|
||||||
if (prev < start && start < end) {
|
if (prev <= start && start <= end) {
|
||||||
const base = baseTokens[i + 1];
|
const base = baseTokens[i + 1];
|
||||||
if (base && base.includes('colorview')) {
|
if (base && base.includes('colorview')) {
|
||||||
return style + COLORVIEW_DISABLED_SUFFIX;
|
return style +
|
||||||
|
(start > prev ? COLORVIEW_DISABLED_SUFFIX : '') +
|
||||||
|
(pos < end ? COLORVIEW_NEXT_DISABLED_SUFFIX : '');
|
||||||
}
|
}
|
||||||
} else if (end > pos) {
|
} else if (end > pos) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -28,7 +28,10 @@
|
||||||
|
|
||||||
function addOverlayForHighlighter(overlay) {
|
function addOverlayForHighlighter(overlay) {
|
||||||
const state = this.state.matchHighlighter || {};
|
const state = this.state.matchHighlighter || {};
|
||||||
const helper = state.stylusMHLHelper || {};
|
const helper = state.highlightHelper = state.highlightHelper || {};
|
||||||
|
|
||||||
|
clearTimeout(helper.hookTimer);
|
||||||
|
|
||||||
if (helper.matchesonscroll) {
|
if (helper.matchesonscroll) {
|
||||||
// restore the original addon's unwanted removeOverlay effects
|
// restore the original addon's unwanted removeOverlay effects
|
||||||
// (in case the token under cursor hasn't changed)
|
// (in case the token under cursor hasn't changed)
|
||||||
|
@ -38,22 +41,22 @@
|
||||||
helper.overlay = null;
|
helper.overlay = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overlay.token !== tokenHook) {
|
if (overlay.token !== tokenHook) {
|
||||||
overlay.stylusMHLHelper = {
|
overlay.highlightHelper = {
|
||||||
token: overlay.token,
|
token: overlay.token,
|
||||||
occurrences: 0,
|
occurrences: 0,
|
||||||
};
|
};
|
||||||
overlay.token = tokenHook;
|
overlay.token = tokenHook;
|
||||||
}
|
}
|
||||||
clearTimeout(helper.hookTimer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function tokenHook(stream) {
|
function tokenHook(stream) {
|
||||||
const style = this.stylusMHLHelper.token.call(this, stream);
|
const style = this.highlightHelper.token.call(this, stream);
|
||||||
if (style !== 'matchhighlight') {
|
if (style !== 'matchhighlight') {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
const num = ++this.stylusMHLHelper.occurrences;
|
const num = ++this.highlightHelper.occurrences;
|
||||||
if (num === 1) {
|
if (num === 1) {
|
||||||
stream.lineOracle.doc.cm.display.wrapper.classList.remove(HL_APPROVED);
|
stream.lineOracle.doc.cm.display.wrapper.classList.remove(HL_APPROVED);
|
||||||
} else if (num === 2) {
|
} else if (num === 2) {
|
||||||
|
@ -64,38 +67,54 @@
|
||||||
|
|
||||||
function removeOverlayForHighlighter() {
|
function removeOverlayForHighlighter() {
|
||||||
const state = this.state.matchHighlighter || {};
|
const state = this.state.matchHighlighter || {};
|
||||||
const {query} = state.matchesonscroll || {};
|
const {query} = state.highlightHelper || state.matchesonscroll || {};
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const {line, ch} = this.getCursor();
|
|
||||||
const rx = query instanceof RegExp && query;
|
const rx = query instanceof RegExp && query;
|
||||||
const queryLen = rx ? rx.source.length - 4 : query.length;
|
const sel = this.getSelection();
|
||||||
const start = Math.max(0, ch - queryLen + 1);
|
if (sel && (rx && !rx.test(sel) || sel.toLowerCase() !== query)) {
|
||||||
const end = ch + queryLen;
|
return;
|
||||||
const area = this.getLine(line).substring(start, end);
|
|
||||||
const startInArea = rx ? (area.match(rx) || {}).index :
|
|
||||||
(area.indexOf(query) + 1 || NaN) - 1;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
if (!sel) {
|
||||||
|
const {line, ch} = this.getCursor();
|
||||||
|
const queryLen = rx ? rx.source.length - 4 : query.length;
|
||||||
|
const start = Math.max(0, ch - queryLen + 1);
|
||||||
|
const end = ch + queryLen;
|
||||||
|
const area = this.getLine(line).substring(start, end);
|
||||||
|
const startInArea = rx ? (area.match(rx) || {}).index :
|
||||||
|
(area.indexOf(query) + 1 || NaN) - 1;
|
||||||
|
if (start + startInArea > ch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// same token on cursor => prevent the highlighter from rerunning
|
||||||
|
state.highlightHelper = {
|
||||||
|
overlay: state.overlay,
|
||||||
|
matchesonscroll: state.matchesonscroll,
|
||||||
|
showMatchesOnScrollbar: this.showMatchesOnScrollbar,
|
||||||
|
hookTimer: setTimeout(removeOverlayIfExpired, 0, this, state),
|
||||||
|
};
|
||||||
|
state.matchesonscroll = null;
|
||||||
|
this.showMatchesOnScrollbar = scrollbarForHighlighter;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeOverlayIfExpired(self, state) {
|
function removeOverlayIfExpired(self, state) {
|
||||||
const {overlay, matchesonscroll} = state.stylusMHLHelper || {};
|
const {overlay, matchesonscroll} = state.highlightHelper || {};
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
originalRemoveOverlay.call(self, overlay);
|
originalRemoveOverlay.call(self, overlay);
|
||||||
}
|
}
|
||||||
if (matchesonscroll) {
|
if (matchesonscroll) {
|
||||||
matchesonscroll.clear();
|
matchesonscroll.clear();
|
||||||
}
|
}
|
||||||
state.stylusMHLHelper = null;
|
self.showMatchesOnScrollbar = state.showMatchesOnScrollbar;
|
||||||
|
state.highlightHelper = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollbarForHighlighter(query) {
|
||||||
|
const helper = this.state.matchHighlighter.highlightHelper;
|
||||||
|
this.showMatchesOnScrollbar = helper.showMatchesOnScrollbar;
|
||||||
|
helper.query = query;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");
|
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
}
|
}
|
||||||
|
.cm-colorview-next-disabled + .cm-colorview::before {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
.codemirror-colorview-background {
|
.codemirror-colorview-background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -177,7 +177,6 @@
|
||||||
if (el.colorpickerData && el.colorpickerData.color === data.color) {
|
if (el.colorpickerData && el.colorpickerData.color === data.color) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
el.dataset.colorpicker = '';
|
|
||||||
el.colorpickerData = Object.assign({line, ch: start}, data);
|
el.colorpickerData = Object.assign({line, ch: start}, data);
|
||||||
let bg = el.firstElementChild;
|
let bg = el.firstElementChild;
|
||||||
if (!bg) {
|
if (!bg) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user