find @-moz-doc sections faster in the editor
This commit is contained in:
parent
d8c2cd449e
commit
d8e2dcb2e8
|
@ -5,6 +5,7 @@
|
|||
|
||||
function createAppliesToLineWidget(cm) {
|
||||
const THROTTLE_DELAY = 400;
|
||||
const RX_SPACE = /(?:\s+|\s*\/\*)+/y;
|
||||
let TPL, EVENTS, CLICK_ROUTE;
|
||||
let widgets = [];
|
||||
let fromLine, toLine, actualStyle;
|
||||
|
@ -294,21 +295,15 @@ function createAppliesToLineWidget(cm) {
|
|||
const toPos = {line: widgets[j] ? widgets[j].line.lineNo() : toLine + 1, ch: 0};
|
||||
|
||||
// calc index->pos lookup table
|
||||
let line = 0;
|
||||
let index = 0;
|
||||
let fromIndex, toIndex;
|
||||
const lineIndexes = [index];
|
||||
cm.doc.iter(({text}) => {
|
||||
fromIndex = line === fromPos.line ? index : fromIndex;
|
||||
const lineIndexes = [0];
|
||||
cm.doc.iter(0, toPos.line + 1, ({text}) => {
|
||||
lineIndexes.push((index += text.length + 1));
|
||||
line++;
|
||||
toIndex = line >= toPos.line ? index : toIndex;
|
||||
return toIndex;
|
||||
});
|
||||
|
||||
// splice
|
||||
i = Math.max(0, i);
|
||||
widgets.splice(i, 0, ...createWidgets(fromIndex, toIndex, widgets.splice(i, j - i), lineIndexes));
|
||||
widgets.splice(i, 0, ...createWidgets(fromPos, toPos, widgets.splice(i, j - i), lineIndexes));
|
||||
|
||||
fromLine = null;
|
||||
toLine = null;
|
||||
|
@ -317,7 +312,7 @@ function createAppliesToLineWidget(cm) {
|
|||
function *createWidgets(start, end, removed, lineIndexes) {
|
||||
let i = 0;
|
||||
let itemHeight;
|
||||
for (const section of findAppliesTo(start, end)) {
|
||||
for (const section of findAppliesTo(start, end, lineIndexes)) {
|
||||
let removedWidget = removed[i];
|
||||
while (removedWidget && removedWidget.line.lineNo() < section.pos.line) {
|
||||
clearWidget(removed[i]);
|
||||
|
@ -488,40 +483,77 @@ function createAppliesToLineWidget(cm) {
|
|||
};
|
||||
}
|
||||
|
||||
function *findAppliesTo(posStart, posEnd) {
|
||||
const text = cm.getValue();
|
||||
const re = /^[\t ]*@-moz-document[\s\n]+/gm;
|
||||
const applyRe = new RegExp([
|
||||
/(?:\/\*[\s\S]*?(?:\*\/\s*|$))*/,
|
||||
/(url|url-prefix|domain|regexp)/,
|
||||
/\(((['"])(?:\\\\|\\\n|\\\3|[^\n])*?\3|[^)\n]*)\)\s*(,\s*)?/,
|
||||
].map(rx => rx.source).join(''), 'giy');
|
||||
let match;
|
||||
re.lastIndex = posStart;
|
||||
while ((match = re.exec(text))) {
|
||||
if (match.index >= posEnd) {
|
||||
return;
|
||||
}
|
||||
function *findAppliesTo(posStart, posEnd, lineIndexes) {
|
||||
const funcRe = /^(url|url-prefix|domain|regexp)$/i;
|
||||
let pos;
|
||||
const eatToken = sticky => {
|
||||
if (!sticky) skipSpace(pos, posEnd);
|
||||
pos.ch++;
|
||||
const token = cm.getTokenAt(pos);
|
||||
pos.ch = token.end;
|
||||
return CodeMirror.cmpPos(pos, posEnd) <= 0 ? token : {};
|
||||
};
|
||||
const docCur = cm.getSearchCursor('@-moz-document', posStart);
|
||||
while (docCur.findNext() &&
|
||||
CodeMirror.cmpPos(docCur.pos.to, posEnd) <= 0) {
|
||||
if (!/\bdef\b/.test(cm.getTokenTypeAt(docCur.pos.from))) continue;
|
||||
const applies = [];
|
||||
let m;
|
||||
applyRe.lastIndex = re.lastIndex;
|
||||
while ((m = applyRe.exec(text))) {
|
||||
pos = docCur.pos.to;
|
||||
do {
|
||||
skipSpace(pos, posEnd);
|
||||
const funcIndex = lineIndexes[pos.line] + pos.ch;
|
||||
const func = eatToken().string;
|
||||
// no space allowed before the opening parenthesis
|
||||
if (!funcRe.test(func) || eatToken(true).string !== '(') break;
|
||||
const url = eatToken();
|
||||
if (url.type !== 'string' || eatToken().string !== ')') break;
|
||||
const unquotedUrl = unquote(url.string);
|
||||
const apply = createApply(
|
||||
m.index,
|
||||
m[1],
|
||||
unquote(m[2]),
|
||||
unquote(m[2]) !== m[2]
|
||||
funcIndex,
|
||||
func,
|
||||
unquotedUrl,
|
||||
unquotedUrl !== url.string
|
||||
);
|
||||
applies.push(apply);
|
||||
re.lastIndex = applyRe.lastIndex;
|
||||
}
|
||||
} while (eatToken().string === ',');
|
||||
yield {
|
||||
pos: cm.posFromIndex(match.index),
|
||||
pos: docCur.pos.from,
|
||||
applies
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function skipSpace(pos, posEnd) {
|
||||
let {ch, line} = pos;
|
||||
let lookForEnd;
|
||||
line--;
|
||||
cm.doc.iter(pos.line, posEnd.line + 1, ({text}) => {
|
||||
line++;
|
||||
while (true) {
|
||||
if (lookForEnd) {
|
||||
ch = text.indexOf('*/', ch) + 1;
|
||||
if (!ch) {
|
||||
return;
|
||||
}
|
||||
ch++;
|
||||
lookForEnd = false;
|
||||
}
|
||||
RX_SPACE.lastIndex = ch;
|
||||
const m = RX_SPACE.exec(text);
|
||||
if (!m) {
|
||||
return true;
|
||||
}
|
||||
ch += m[0].length;
|
||||
lookForEnd = m[0].includes('/*');
|
||||
if (ch < text.length && !lookForEnd) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
pos.line = line;
|
||||
pos.ch = ch;
|
||||
}
|
||||
|
||||
function unquote(s) {
|
||||
const first = s.charAt(0);
|
||||
return (first === '"' || first === "'") && s.endsWith(first) ? s.slice(1, -1) : s;
|
||||
|
|
Loading…
Reference in New Issue
Block a user