mirror of https://github.com/gorhill/uBlock.git
Add auto-completion for procedural operators
Related commit:
- 3e72a47c1f
This commit is contained in:
parent
de8d217983
commit
aa000e282e
|
@ -127,3 +127,7 @@ div.CodeMirror span.CodeMirror-matchingbracket {
|
||||||
.CodeMirror-merge-gap {
|
.CodeMirror-merge-gap {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.CodeMirror-hints {
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
|
@ -262,8 +262,13 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
|
||||||
const parser = new StaticFilteringParser();
|
const parser = new StaticFilteringParser();
|
||||||
const redirectNames = new Map();
|
const redirectNames = new Map();
|
||||||
const scriptletNames = new Map();
|
const scriptletNames = new Map();
|
||||||
|
const proceduralOperatorNames = new Map(
|
||||||
|
Array.from(parser.proceduralOperatorTokens).filter(item => {
|
||||||
|
return (item[1] & 0b01) !== 0;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const getNetOptionHint = function(cursor, isNegated, seedLeft, seedRight) {
|
const getNetOptionHints = function(cursor, isNegated, seedLeft, seedRight) {
|
||||||
const assignPos = seedRight.indexOf('=');
|
const assignPos = seedRight.indexOf('=');
|
||||||
if ( assignPos !== -1 ) { seedRight = seedRight.slice(0, assignPos); }
|
if ( assignPos !== -1 ) { seedRight = seedRight.slice(0, assignPos); }
|
||||||
const seed = (seedLeft + seedRight).trim();
|
const seed = (seedLeft + seedRight).trim();
|
||||||
|
@ -289,7 +294,7 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getNetRedirectHint = function(cursor, seedLeft, seedRight) {
|
const getNetRedirectHints = function(cursor, seedLeft, seedRight) {
|
||||||
const seed = (seedLeft + seedRight).trim();
|
const seed = (seedLeft + seedRight).trim();
|
||||||
const out = [];
|
const out = [];
|
||||||
for ( let text of redirectNames.keys() ) {
|
for ( let text of redirectNames.keys() ) {
|
||||||
|
@ -303,7 +308,7 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getNetHint = function(cursor, line) {
|
const getNetHints = function(cursor, line) {
|
||||||
const beg = cursor.ch;
|
const beg = cursor.ch;
|
||||||
if ( beg < parser.optionsSpan ) { return; }
|
if ( beg < parser.optionsSpan ) { return; }
|
||||||
const lineBefore = line.slice(0, beg);
|
const lineBefore = line.slice(0, beg);
|
||||||
|
@ -313,21 +318,41 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
|
||||||
if ( matchLeft === null || matchRight === null ) { return; }
|
if ( matchLeft === null || matchRight === null ) { return; }
|
||||||
let pos = matchLeft[1].indexOf('=');
|
let pos = matchLeft[1].indexOf('=');
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) {
|
||||||
return getNetOptionHint(
|
return getNetOptionHints(
|
||||||
cursor,
|
cursor,
|
||||||
matchLeft[0].startsWith('~'),
|
matchLeft[0].startsWith('~'),
|
||||||
matchLeft[1],
|
matchLeft[1],
|
||||||
matchRight[1]
|
matchRight[1]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return getNetRedirectHint(
|
return getNetRedirectHints(
|
||||||
cursor,
|
cursor,
|
||||||
matchLeft[1].slice(pos + 1),
|
matchLeft[1].slice(pos + 1),
|
||||||
matchRight[1]
|
matchRight[1]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getExtScriptletHint = function(cursor, line) {
|
const getExtSelectorHints = function(cursor, line) {
|
||||||
|
const beg = cursor.ch;
|
||||||
|
const matchLeft = /#\^?.*:([^:]*)$/.exec(line.slice(0, beg));
|
||||||
|
const matchRight = /^([a-z-]*)\(?/.exec(line.slice(beg));
|
||||||
|
if ( matchLeft === null || matchRight === null ) { return; }
|
||||||
|
const isStaticDOM = matchLeft[0].indexOf('^') !== -1;
|
||||||
|
const seed = (matchLeft[1] + matchRight[1]).trim();
|
||||||
|
const out = [];
|
||||||
|
for ( let [ text, bits ] of proceduralOperatorNames ) {
|
||||||
|
if ( text.startsWith(seed) === false ) { continue; }
|
||||||
|
if ( isStaticDOM && (bits & 0b10) !== 0 ) { continue; }
|
||||||
|
out.push(text);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
from: { line: cursor.line, ch: cursor.ch - matchLeft[1].length },
|
||||||
|
to: { line: cursor.line, ch: cursor.ch + matchRight[1].length },
|
||||||
|
list: out,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getExtScriptletHints = function(cursor, line) {
|
||||||
const beg = cursor.ch;
|
const beg = cursor.ch;
|
||||||
const matchLeft = /#\+\js\(([^,]*)$/.exec(line.slice(0, beg));
|
const matchLeft = /#\+\js\(([^,]*)$/.exec(line.slice(0, beg));
|
||||||
const matchRight = /^([^,)]*)/.exec(line.slice(beg));
|
const matchRight = /^([^,)]*)/.exec(line.slice(beg));
|
||||||
|
@ -353,14 +378,14 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
|
||||||
const cursor = cm.getCursor();
|
const cursor = cm.getCursor();
|
||||||
const line = cm.getLine(cursor.line);
|
const line = cm.getLine(cursor.line);
|
||||||
parser.analyze(line);
|
parser.analyze(line);
|
||||||
if (
|
if ( parser.category === parser.CATStaticExtFilter ) {
|
||||||
parser.category === parser.CATStaticExtFilter &&
|
if ( parser.hasFlavor(parser.BITFlavorExtScriptlet) ) {
|
||||||
parser.hasFlavor(parser.BITFlavorExtScriptlet)
|
return getExtScriptletHints(cursor, line);
|
||||||
) {
|
}
|
||||||
return getExtScriptletHint(cursor, line);
|
return getExtSelectorHints(cursor, line);
|
||||||
}
|
}
|
||||||
if ( parser.category === parser.CATStaticNetFilter ) {
|
if ( parser.category === parser.CATStaticNetFilter ) {
|
||||||
return getNetHint(cursor, line);
|
return getNetHints(cursor, line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1101,27 +1101,7 @@ Parser.prototype.SelectorCompiler = class {
|
||||||
this.rePseudoClass = /:(?::?after|:?before|:[a-z][a-z-]*[a-z])$/;
|
this.rePseudoClass = /:(?::?after|:?before|:[a-z][a-z-]*[a-z])$/;
|
||||||
this.reProceduralOperator = new RegExp([
|
this.reProceduralOperator = new RegExp([
|
||||||
'^(?:',
|
'^(?:',
|
||||||
[
|
Array.from(parser.proceduralOperatorTokens.keys()).join('|'),
|
||||||
'-abp-contains',
|
|
||||||
'-abp-has',
|
|
||||||
'contains',
|
|
||||||
'has',
|
|
||||||
'has-text',
|
|
||||||
'if',
|
|
||||||
'if-not',
|
|
||||||
'matches-css',
|
|
||||||
'matches-css-after',
|
|
||||||
'matches-css-before',
|
|
||||||
'min-text-length',
|
|
||||||
'not',
|
|
||||||
'nth-ancestor',
|
|
||||||
'remove',
|
|
||||||
'style',
|
|
||||||
'upward',
|
|
||||||
'watch-attr',
|
|
||||||
'watch-attrs',
|
|
||||||
'xpath'
|
|
||||||
].join('|'),
|
|
||||||
')\\('
|
')\\('
|
||||||
].join(''));
|
].join(''));
|
||||||
this.reEatBackslashes = /\\([()])/g;
|
this.reEatBackslashes = /\\([()])/g;
|
||||||
|
@ -1627,6 +1607,28 @@ Parser.prototype.SelectorCompiler = class {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.prototype.proceduralOperatorTokens = new Map([
|
||||||
|
[ '-abp-contains', 0b00 ],
|
||||||
|
[ '-abp-has', 0b00, ],
|
||||||
|
[ 'contains', 0b00, ],
|
||||||
|
[ 'has', 0b01 ],
|
||||||
|
[ 'has-text', 0b01 ],
|
||||||
|
[ 'if', 0b00 ],
|
||||||
|
[ 'if-not', 0b00 ],
|
||||||
|
[ 'matches-css', 0b11 ],
|
||||||
|
[ 'matches-css-after', 0b11 ],
|
||||||
|
[ 'matches-css-before', 0b11 ],
|
||||||
|
[ 'min-text-length', 0b01 ],
|
||||||
|
[ 'not', 0b01 ],
|
||||||
|
[ 'nth-ancestor', 0b00 ],
|
||||||
|
[ 'remove', 0b11 ],
|
||||||
|
[ 'style', 0b11 ],
|
||||||
|
[ 'upward', 0b01 ],
|
||||||
|
[ 'watch-attr', 0b11 ],
|
||||||
|
[ 'watch-attrs', 0b00 ],
|
||||||
|
[ 'xpath', 0b01 ],
|
||||||
|
]);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const hasNoBits = (v, bits) => (v & bits) === 0;
|
const hasNoBits = (v, bits) => (v & bits) === 0;
|
||||||
|
|
Loading…
Reference in New Issue