summaryrefslogtreecommitdiffstats
path: root/src/js/codemirror
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/codemirror')
-rw-r--r--src/js/codemirror/search.js86
-rw-r--r--src/js/codemirror/ubo-static-filtering.js447
2 files changed, 282 insertions, 251 deletions
diff --git a/src/js/codemirror/search.js b/src/js/codemirror/search.js
index 477e9cc..7ee5b33 100644
--- a/src/js/codemirror/search.js
+++ b/src/js/codemirror/search.js
@@ -25,18 +25,25 @@
// Ctrl-G.
// =====
-'use strict';
-
import { dom, qs$ } from '../dom.js';
import { i18n$ } from '../i18n.js';
{
const CodeMirror = self.CodeMirror;
+ CodeMirror.defineOption('maximizable', true, (cm, maximizable) => {
+ if ( typeof maximizable !== 'boolean' ) { return; }
+ const wrapper = cm.getWrapperElement();
+ if ( wrapper === null ) { return; }
+ const container = wrapper.closest('.codeMirrorContainer');
+ if ( container === null ) { return; }
+ container.dataset.maximizable = `${maximizable}`;
+ });
+
const searchOverlay = function(query, caseInsensitive) {
if ( typeof query === 'string' )
query = new RegExp(
- query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'),
+ query.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'),
caseInsensitive ? 'gi' : 'g'
);
else if ( !query.global )
@@ -89,8 +96,10 @@ import { i18n$ } from '../i18n.js';
state.queryTimer.offon(350);
};
- const searchWidgetClickHandler = function(cm, ev) {
- const tcl = ev.target.classList;
+ const searchWidgetClickHandler = (ev, cm) => {
+ if ( ev.button !== 0 ) { return; }
+ const target = ev.target;
+ const tcl = target.classList;
if ( tcl.contains('cm-search-widget-up') ) {
findNext(cm, -1);
} else if ( tcl.contains('cm-search-widget-down') ) {
@@ -99,11 +108,14 @@ import { i18n$ } from '../i18n.js';
findNextError(cm, -1);
} else if ( tcl.contains('cm-linter-widget-down') ) {
findNextError(cm, 1);
+ } else if ( tcl.contains('cm-maximize') ) {
+ const container = target.closest('.codeMirrorContainer');
+ if ( container !== null ) {
+ container.classList.toggle('cm-maximized');
+ }
}
- if ( ev.target.localName !== 'input' ) {
- ev.preventDefault();
- } else {
- ev.stopImmediatePropagation();
+ if ( target.localName !== 'input' ) {
+ cm.focus();
}
};
@@ -127,7 +139,9 @@ import { i18n$ } from '../i18n.js';
this.widget = widgetParent.children[0];
this.widget.addEventListener('keydown', searchWidgetKeydownHandler.bind(null, cm));
this.widget.addEventListener('input', searchWidgetInputHandler.bind(null, cm));
- this.widget.addEventListener('mousedown', searchWidgetClickHandler.bind(null, cm));
+ this.widget.addEventListener('click', ev => {
+ searchWidgetClickHandler(ev, cm);
+ });
if ( typeof cm.addPanel === 'function' ) {
this.panel = cm.addPanel(this.widget);
}
@@ -236,10 +250,7 @@ import { i18n$ } from '../i18n.js';
notation: 'compact',
maximumSignificantDigits: 3
});
- if (
- intl.resolvedOptions instanceof Function &&
- intl.resolvedOptions().hasOwnProperty('notation')
- ) {
+ if ( intl.resolvedOptions().notation ) {
intlNumberFormat = intl;
}
}
@@ -330,9 +341,6 @@ import { i18n$ } from '../i18n.js';
state.annotate.update(annotations);
});
state.widget.setAttribute('data-query', state.queryText);
- // Ensure the caret is visible
- const input = state.widget.querySelector('.cm-search-widget-input input');
- input.selectionStart = input.selectionStart;
};
const findNext = function(cm, dir, callback) {
@@ -458,26 +466,30 @@ import { i18n$ } from '../i18n.js';
};
{
- const searchWidgetTemplate =
- '<div class="cm-search-widget-template" style="display:none;">' +
- '<div class="cm-search-widget">' +
- '<span class="cm-search-widget-input">' +
- '<span class="fa-icon fa-icon-ro">search</span>&ensp;' +
- '<input type="search" spellcheck="false">&emsp;' +
- '<span class="cm-search-widget-up cm-search-widget-button fa-icon">angle-up</span>&nbsp;' +
- '<span class="cm-search-widget-down cm-search-widget-button fa-icon fa-icon-vflipped">angle-up</span>&emsp;' +
- '<span class="cm-search-widget-count"></span>' +
- '</span>' +
- '<span class="cm-linter-widget" data-lint="0">' +
- '<span class="cm-linter-widget-count"></span>&emsp;' +
- '<span class="cm-linter-widget-up cm-search-widget-button fa-icon">angle-up</span>&nbsp;' +
- '<span class="cm-linter-widget-down cm-search-widget-button fa-icon fa-icon-vflipped">angle-up</span>&emsp;' +
- '</span>' +
- '<span>' +
- '<a class="fa-icon sourceURL" href>external-link</a>' +
- '</span>' +
- '</div>' +
- '</div>';
+ const searchWidgetTemplate = [
+ '<div class="cm-search-widget-template" style="display:none;">',
+ '<div class="cm-search-widget">',
+ '<span class="cm-maximize"><svg viewBox="0 0 40 40"><path d="M4,16V4h12M24,4H36V16M4,24V36H16M36,24V36H24" /><path d="M14 2.5v12h-12M38 14h-12v-12M14 38v-12h-12M26 38v-12h12" /></svg></span>&ensp;',
+ '<span class="cm-search-widget-input">',
+ '<span class="searchfield">',
+ '<input type="search" spellcheck="false" placeholder="">',
+ '<span class="fa-icon">search</span>',
+ '</span>&ensp;',
+ '<span class="cm-search-widget-up cm-search-widget-button fa-icon">angle-up</span>&nbsp;',
+ '<span class="cm-search-widget-down cm-search-widget-button fa-icon fa-icon-vflipped">angle-up</span>&ensp;',
+ '<span class="cm-search-widget-count"></span>',
+ '</span>',
+ '<span class="cm-linter-widget" data-lint="0">',
+ '<span class="cm-linter-widget-count"></span>&ensp;',
+ '<span class="cm-linter-widget-up cm-search-widget-button fa-icon">angle-up</span>&nbsp;',
+ '<span class="cm-linter-widget-down cm-search-widget-button fa-icon fa-icon-vflipped">angle-up</span>&ensp;',
+ '</span>',
+ '<span>',
+ '<a class="fa-icon sourceURL" href>external-link</a>',
+ '</span>',
+ '</div>',
+ '</div>',
+ ].join('\n');
const domParser = new DOMParser();
const doc = domParser.parseFromString(searchWidgetTemplate, 'text/html');
const widgetTemplate = document.adoptNode(doc.body.firstElementChild);
diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js
index ac1b048..2aaf85b 100644
--- a/src/js/codemirror/ubo-static-filtering.js
+++ b/src/js/codemirror/ubo-static-filtering.js
@@ -21,8 +21,6 @@
/* global CodeMirror */
-'use strict';
-
/******************************************************************************/
import * as sfp from '../static-filtering-parser.js';
@@ -39,10 +37,10 @@ let hintHelperRegistered = false;
/******************************************************************************/
-CodeMirror.defineOption('trustedSource', false, (cm, state) => {
- if ( typeof state !== 'boolean' ) { return; }
+CodeMirror.defineOption('trustedSource', false, (cm, trusted) => {
+ if ( typeof trusted !== 'boolean' ) { return; }
self.dispatchEvent(new CustomEvent('trustedSource', {
- detail: state,
+ detail: { cm, trusted },
}));
});
@@ -56,219 +54,232 @@ CodeMirror.defineOption('trustedScriptletTokens', undefined, (cm, tokens) => {
/******************************************************************************/
-CodeMirror.defineMode('ubo-static-filtering', function() {
- const astParser = new sfp.AstFilterParser({
- interactive: true,
- nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'),
- });
- const astWalker = astParser.getWalker();
- let currentWalkerNode = 0;
- let lastNetOptionType = 0;
-
- const redirectTokenStyle = node => {
- const rawToken = astParser.getNodeString(node || currentWalkerNode);
+const uBOStaticFilteringMode = (( ) => {
+ const redirectTokenStyle = (mode, node) => {
+ const rawToken = mode.astParser.getNodeString(node || mode.currentWalkerNode);
const { token } = sfp.parseRedirectValue(rawToken);
return redirectNames.has(token) ? 'value' : 'value warning';
};
- const nodeHasError = node => {
- return astParser.getNodeFlags(
- node || currentWalkerNode, sfp.NODE_FLAG_ERROR
+ const nodeHasError = (mode, node) => {
+ return mode.astParser.getNodeFlags(
+ node || mode.currentWalkerNode, sfp.NODE_FLAG_ERROR
) !== 0;
};
- const colorFromAstNode = function() {
- if ( astParser.nodeIsEmptyString(currentWalkerNode) ) { return '+'; }
- if ( nodeHasError() ) { return 'error'; }
- const nodeType = astParser.getNodeType(currentWalkerNode);
+ const colorFromAstNode = mode => {
+ if ( mode.astParser.nodeIsEmptyString(mode.currentWalkerNode) ) { return '+'; }
+ if ( nodeHasError(mode) ) { return 'error'; }
+ const nodeType = mode.astParser.getNodeType(mode.currentWalkerNode);
switch ( nodeType ) {
- case sfp.NODE_TYPE_WHITESPACE:
- return '';
- case sfp.NODE_TYPE_COMMENT:
- if ( astWalker.canGoDown() ) { break; }
- return 'comment';
- case sfp.NODE_TYPE_COMMENT_URL:
- return 'comment link';
- case sfp.NODE_TYPE_IGNORE:
- return 'comment';
- case sfp.NODE_TYPE_PREPARSE_DIRECTIVE:
- case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_VALUE:
- return 'directive';
- case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE: {
- const raw = astParser.getNodeString(currentWalkerNode);
- const state = sfp.utils.preparser.evaluateExpr(raw, preparseDirectiveEnv);
- return state ? 'positive strong' : 'negative strong';
+ case sfp.NODE_TYPE_WHITESPACE:
+ return '';
+ case sfp.NODE_TYPE_COMMENT:
+ if ( mode.astWalker.canGoDown() ) { break; }
+ return 'comment';
+ case sfp.NODE_TYPE_COMMENT_URL:
+ return 'comment link';
+ case sfp.NODE_TYPE_IGNORE:
+ return 'comment';
+ case sfp.NODE_TYPE_PREPARSE_DIRECTIVE:
+ case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_VALUE:
+ return 'directive';
+ case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE: {
+ const raw = mode.astParser.getNodeString(mode.currentWalkerNode);
+ const state = sfp.utils.preparser.evaluateExpr(raw, preparseDirectiveEnv);
+ return state ? 'positive strong' : 'negative strong';
+ }
+ case sfp.NODE_TYPE_EXT_OPTIONS_ANCHOR:
+ return mode.astParser.getFlags(sfp.AST_FLAG_IS_EXCEPTION)
+ ? 'tag strong'
+ : 'def strong';
+ case sfp.NODE_TYPE_EXT_DECORATION:
+ return 'def';
+ case sfp.NODE_TYPE_EXT_PATTERN_RAW:
+ if ( mode.astWalker.canGoDown() ) { break; }
+ return 'variable';
+ case sfp.NODE_TYPE_EXT_PATTERN_COSMETIC:
+ case sfp.NODE_TYPE_EXT_PATTERN_HTML:
+ return 'variable';
+ case sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER:
+ case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET:
+ if ( mode.astWalker.canGoDown() ) { break; }
+ return 'variable';
+ case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: {
+ const token = mode.astParser.getNodeString(mode.currentWalkerNode);
+ if ( scriptletNames.has(token) === false ) {
+ return 'warning';
}
- case sfp.NODE_TYPE_EXT_OPTIONS_ANCHOR:
- return astParser.getFlags(sfp.AST_FLAG_IS_EXCEPTION)
- ? 'tag strong'
- : 'def strong';
- case sfp.NODE_TYPE_EXT_DECORATION:
- return 'def';
- case sfp.NODE_TYPE_EXT_PATTERN_RAW:
- if ( astWalker.canGoDown() ) { break; }
- return 'variable';
- case sfp.NODE_TYPE_EXT_PATTERN_COSMETIC:
- case sfp.NODE_TYPE_EXT_PATTERN_HTML:
- return 'variable';
- case sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER:
- case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET:
- if ( astWalker.canGoDown() ) { break; }
- return 'variable';
- case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: {
- const token = astParser.getNodeString(currentWalkerNode);
- if ( scriptletNames.has(token) === false ) {
- return 'warning';
+ return 'variable';
+ }
+ case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG:
+ return 'variable';
+ case sfp.NODE_TYPE_NET_EXCEPTION:
+ return 'tag strong';
+ case sfp.NODE_TYPE_NET_PATTERN:
+ if ( mode.astWalker.canGoDown() ) { break; }
+ if ( mode.astParser.isRegexPattern() ) {
+ if ( mode.astParser.getNodeFlags(mode.currentWalkerNode, sfp.NODE_FLAG_PATTERN_UNTOKENIZABLE) !== 0 ) {
+ return 'variable warning';
}
- return 'variable';
+ return 'variable notice';
}
- case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG:
- return 'variable';
- case sfp.NODE_TYPE_NET_EXCEPTION:
- return 'tag strong';
- case sfp.NODE_TYPE_NET_PATTERN:
- if ( astWalker.canGoDown() ) { break; }
- if ( astParser.isRegexPattern() ) {
- if ( astParser.getNodeFlags(currentWalkerNode, sfp.NODE_FLAG_PATTERN_UNTOKENIZABLE) !== 0 ) {
- return 'variable warning';
- }
- return 'variable notice';
- }
- return 'variable';
- case sfp.NODE_TYPE_NET_PATTERN_PART:
- return 'variable';
- case sfp.NODE_TYPE_NET_PATTERN_PART_SPECIAL:
- return 'keyword strong';
- case sfp.NODE_TYPE_NET_PATTERN_PART_UNICODE:
- return 'variable unicode';
- case sfp.NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR:
- case sfp.NODE_TYPE_NET_PATTERN_LEFT_ANCHOR:
- case sfp.NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR:
- case sfp.NODE_TYPE_NET_OPTION_NAME_NOT:
- return 'keyword strong';
- case sfp.NODE_TYPE_NET_OPTIONS_ANCHOR:
- case sfp.NODE_TYPE_NET_OPTION_SEPARATOR:
- lastNetOptionType = 0;
- return 'def strong';
- case sfp.NODE_TYPE_NET_OPTION_NAME_UNKNOWN:
- lastNetOptionType = 0;
- return 'error';
- case sfp.NODE_TYPE_NET_OPTION_NAME_1P:
- case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT1P:
- case sfp.NODE_TYPE_NET_OPTION_NAME_3P:
- case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT3P:
- case sfp.NODE_TYPE_NET_OPTION_NAME_ALL:
- case sfp.NODE_TYPE_NET_OPTION_NAME_BADFILTER:
- case sfp.NODE_TYPE_NET_OPTION_NAME_CNAME:
- case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
- case sfp.NODE_TYPE_NET_OPTION_NAME_CSS:
- case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
- case sfp.NODE_TYPE_NET_OPTION_NAME_DOC:
- case sfp.NODE_TYPE_NET_OPTION_NAME_EHIDE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_EMPTY:
- case sfp.NODE_TYPE_NET_OPTION_NAME_FONT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_FRAME:
- case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
- case sfp.NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK:
- case sfp.NODE_TYPE_NET_OPTION_NAME_GHIDE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
- case sfp.NODE_TYPE_NET_OPTION_NAME_IMAGE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_IMPORTANT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_MEDIA:
- case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
- case sfp.NODE_TYPE_NET_OPTION_NAME_MP4:
- case sfp.NODE_TYPE_NET_OPTION_NAME_NOOP:
- case sfp.NODE_TYPE_NET_OPTION_NAME_OBJECT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_OTHER:
- case sfp.NODE_TYPE_NET_OPTION_NAME_PING:
- case sfp.NODE_TYPE_NET_OPTION_NAME_POPUNDER:
- case sfp.NODE_TYPE_NET_OPTION_NAME_POPUP:
+ return 'variable';
+ case sfp.NODE_TYPE_NET_PATTERN_PART:
+ return 'variable';
+ case sfp.NODE_TYPE_NET_PATTERN_PART_SPECIAL:
+ return 'keyword strong';
+ case sfp.NODE_TYPE_NET_PATTERN_PART_UNICODE:
+ return 'variable unicode';
+ case sfp.NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR:
+ case sfp.NODE_TYPE_NET_PATTERN_LEFT_ANCHOR:
+ case sfp.NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_NOT:
+ return 'keyword strong';
+ case sfp.NODE_TYPE_NET_OPTIONS_ANCHOR:
+ case sfp.NODE_TYPE_NET_OPTION_SEPARATOR:
+ mode.lastNetOptionType = 0;
+ return 'def strong';
+ case sfp.NODE_TYPE_NET_OPTION_NAME_UNKNOWN:
+ mode.lastNetOptionType = 0;
+ return 'error';
+ case sfp.NODE_TYPE_NET_OPTION_NAME_1P:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT1P:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_3P:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_STRICT3P:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_ALL:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_BADFILTER:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_CNAME:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_CSP:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_CSS:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_DOC:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_EHIDE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_EMPTY:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_FONT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_FRAME:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_FROM:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_GHIDE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_HEADER:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_IMAGE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_IMPORTANT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_MEDIA:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_METHOD:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_MP4:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_NOOP:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_OBJECT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_OTHER:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_PING:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_POPUNDER:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_POPUP:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_SCRIPT:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_SHIDE:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_XHR:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_WEBRTC:
+ case sfp.NODE_TYPE_NET_OPTION_NAME_WEBSOCKET:
+ mode.lastNetOptionType = nodeType;
+ return 'def';
+ case sfp.NODE_TYPE_NET_OPTION_ASSIGN:
+ return 'def';
+ case sfp.NODE_TYPE_NET_OPTION_VALUE:
+ if ( mode.astWalker.canGoDown() ) { break; }
+ switch ( mode.lastNetOptionType ) {
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
- case sfp.NODE_TYPE_NET_OPTION_NAME_SCRIPT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_SHIDE:
- case sfp.NODE_TYPE_NET_OPTION_NAME_TO:
- case sfp.NODE_TYPE_NET_OPTION_NAME_XHR:
- case sfp.NODE_TYPE_NET_OPTION_NAME_WEBRTC:
- case sfp.NODE_TYPE_NET_OPTION_NAME_WEBSOCKET:
- lastNetOptionType = nodeType;
- return 'def';
- case sfp.NODE_TYPE_NET_OPTION_ASSIGN:
- return 'def';
- case sfp.NODE_TYPE_NET_OPTION_VALUE:
- if ( astWalker.canGoDown() ) { break; }
- switch ( lastNetOptionType ) {
- case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT:
- case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
- return redirectTokenStyle();
- default:
- break;
- }
- return 'value';
- case sfp.NODE_TYPE_OPTION_VALUE_NOT:
- return 'keyword strong';
- case sfp.NODE_TYPE_OPTION_VALUE_DOMAIN:
- return 'value';
- case sfp.NODE_TYPE_OPTION_VALUE_SEPARATOR:
- return 'def';
+ return redirectTokenStyle(mode);
default:
break;
+ }
+ return 'value';
+ case sfp.NODE_TYPE_OPTION_VALUE_NOT:
+ return 'keyword strong';
+ case sfp.NODE_TYPE_OPTION_VALUE_DOMAIN:
+ return 'value';
+ case sfp.NODE_TYPE_OPTION_VALUE_SEPARATOR:
+ return 'def';
+ default:
+ break;
}
return '+';
};
- self.addEventListener('trustedSource', ev => {
- astParser.options.trustedSource = ev.detail;
- });
-
- self.addEventListener('trustedScriptletTokens', ev => {
- astParser.options.trustedScriptletTokens = ev.detail;
- });
+ class ModeState {
+ constructor() {
+ this.astParser = new sfp.AstFilterParser({
+ interactive: true,
+ nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'),
+ });
+ this.astWalker = this.astParser.getWalker();
+ this.currentWalkerNode = 0;
+ this.lastNetOptionType = 0;
+ self.addEventListener('trustedSource', ev => {
+ const { trusted } = ev.detail;
+ this.astParser.options.trustedSource = trusted;
+ });
+ self.addEventListener('trustedScriptletTokens', ev => {
+ this.astParser.options.trustedScriptletTokens = ev.detail;
+ });
+ }
+ }
- return {
- lineComment: '!',
- token: function(stream) {
+ return {
+ state: null,
+ startState() {
+ if ( this.state === null ) {
+ this.state = new ModeState();
+ }
+ return this.state;
+ },
+ copyState(other) {
+ return other;
+ },
+ token(stream, state) {
if ( stream.sol() ) {
- astParser.parse(stream.string);
- if ( astParser.getFlags(sfp.AST_FLAG_UNSUPPORTED) !== 0 ) {
+ state.astParser.parse(stream.string);
+ if ( state.astParser.getFlags(sfp.AST_FLAG_UNSUPPORTED) !== 0 ) {
stream.skipToEnd();
return 'error';
}
- if ( astParser.getType() === sfp.AST_TYPE_NONE ) {
+ if ( state.astParser.getType() === sfp.AST_TYPE_NONE ) {
stream.skipToEnd();
return 'comment';
}
- currentWalkerNode = astWalker.reset();
- } else if ( nodeHasError() ) {
- currentWalkerNode = astWalker.right();
+ state.currentWalkerNode = state.astWalker.reset();
+ } else if ( nodeHasError(state) ) {
+ state.currentWalkerNode = state.astWalker.right();
} else {
- currentWalkerNode = astWalker.next();
+ state.currentWalkerNode = state.astWalker.next();
}
let style = '';
- while ( currentWalkerNode !== 0 ) {
- style = colorFromAstNode(stream);
+ while ( state.currentWalkerNode !== 0 ) {
+ style = colorFromAstNode(state, stream);
if ( style !== '+' ) { break; }
- currentWalkerNode = astWalker.next();
+ state.currentWalkerNode = state.astWalker.next();
}
if ( style === '+' ) {
stream.skipToEnd();
return null;
}
- stream.pos = astParser.getNodeStringEnd(currentWalkerNode);
- if ( astParser.isNetworkFilter() ) {
+ stream.pos = state.astParser.getNodeStringEnd(state.currentWalkerNode);
+ if ( state.astParser.isNetworkFilter() ) {
return style ? `line-cm-net ${style}` : 'line-cm-net';
}
- if ( astParser.isExtendedFilter() ) {
+ if ( state.astParser.isExtendedFilter() ) {
let flavor = '';
- if ( astParser.isCosmeticFilter() ) {
+ if ( state.astParser.isCosmeticFilter() ) {
flavor = 'line-cm-ext-dom';
- } else if ( astParser.isScriptletFilter() ) {
+ } else if ( state.astParser.isScriptletFilter() ) {
flavor = 'line-cm-ext-js';
- } else if ( astParser.isHtmlFilter() ) {
+ } else if ( state.astParser.isHtmlFilter() ) {
flavor = 'line-cm-ext-html';
}
if ( flavor !== '' ) {
@@ -278,9 +289,11 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
style = style.trim();
return style !== '' ? style : null;
},
- parser: astParser,
+ lineComment: '!',
};
-});
+})();
+
+CodeMirror.defineMode('ubo-static-filtering', ( ) => uBOStaticFilteringMode);
/******************************************************************************/
@@ -327,7 +340,7 @@ function initHints() {
});
const proceduralOperatorNames = new Map(
Array.from(sfp.proceduralOperatorTokens)
- .filter(item => (item[1] & 0b01) !== 0)
+ .filter(item => (item[1] & 0b01) !== 0)
);
const excludedHints = new Set([
'genericblock',
@@ -562,7 +575,7 @@ function initHints() {
const getExtScriptletHints = function(cursor, line) {
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));
if ( matchLeft === null || matchRight === null ) { return; }
const hints = [];
@@ -709,38 +722,38 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
if ( astParser.hasError() ) {
let msg = 'Invalid filter';
switch ( astParser.astError ) {
- case sfp.AST_ERROR_UNSUPPORTED:
- msg = `${msg}: Unsupported filter syntax`;
- break;
- case sfp.AST_ERROR_REGEX:
- msg = `${msg}: Bad regular expression`;
- break;
- case sfp.AST_ERROR_PATTERN:
- msg = `${msg}: Bad pattern`;
- break;
- case sfp.AST_ERROR_DOMAIN_NAME:
- msg = `${msg}: Bad domain name`;
- break;
- case sfp.AST_ERROR_OPTION_BADVALUE:
- msg = `${msg}: Bad value assigned to a valid option`;
- break;
- case sfp.AST_ERROR_OPTION_DUPLICATE:
- msg = `${msg}: Duplicate filter option`;
- break;
- case sfp.AST_ERROR_OPTION_UNKNOWN:
- msg = `${msg}: Unsupported filter option`;
- break;
- case sfp.AST_ERROR_IF_TOKEN_UNKNOWN:
- msg = `${msg}: Unknown preparsing token`;
- break;
- case sfp.AST_ERROR_UNTRUSTED_SOURCE:
- msg = `${msg}: Filter requires trusted source`;
- break;
- default:
- if ( astParser.isCosmeticFilter() && astParser.result.error ) {
- msg = `${msg}: ${astParser.result.error}`;
- }
- break;
+ case sfp.AST_ERROR_UNSUPPORTED:
+ msg = `${msg}: Unsupported filter syntax`;
+ break;
+ case sfp.AST_ERROR_REGEX:
+ msg = `${msg}: Bad regular expression`;
+ break;
+ case sfp.AST_ERROR_PATTERN:
+ msg = `${msg}: Bad pattern`;
+ break;
+ case sfp.AST_ERROR_DOMAIN_NAME:
+ msg = `${msg}: Bad domain name`;
+ break;
+ case sfp.AST_ERROR_OPTION_BADVALUE:
+ msg = `${msg}: Bad value assigned to a valid option`;
+ break;
+ case sfp.AST_ERROR_OPTION_DUPLICATE:
+ msg = `${msg}: Duplicate filter option`;
+ break;
+ case sfp.AST_ERROR_OPTION_UNKNOWN:
+ msg = `${msg}: Unsupported filter option`;
+ break;
+ case sfp.AST_ERROR_IF_TOKEN_UNKNOWN:
+ msg = `${msg}: Unknown preparsing token`;
+ break;
+ case sfp.AST_ERROR_UNTRUSTED_SOURCE:
+ msg = `${msg}: Filter requires trusted source`;
+ break;
+ default:
+ if ( astParser.isCosmeticFilter() && astParser.result.error ) {
+ msg = `${msg}: ${astParser.result.error}`;
+ }
+ break;
}
return { lint: 'error', msg };
}
@@ -877,6 +890,11 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
ifendifSet.add(lineHandle);
ifendifSetChanged = true;
}
+ } else if ( marker.dataset.lint === 'error' ) {
+ if ( marker.dataset.error !== 'y' ) {
+ marker.dataset.error = 'y';
+ errorCount += 1;
+ }
}
if ( typeof details.msg !== 'string' || details.msg === '' ) { return; }
const msgElem = qs$(marker, '.msg');
@@ -1083,7 +1101,8 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
};
self.addEventListener('trustedSource', ev => {
- astParser.options.trustedSource = ev.detail;
+ const { trusted } = ev.detail;
+ astParser.options.trustedSource = trusted;
});
self.addEventListener('trustedScriptletTokens', ev => {