diff --git a/src/advanced-settings.html b/src/advanced-settings.html
index 564ae99dc..5afb9a0d9 100644
--- a/src/advanced-settings.html
+++ b/src/advanced-settings.html
@@ -27,8 +27,6 @@
-
-
diff --git a/src/js/advanced-settings.js b/src/js/advanced-settings.js
index 6d993e1ed..2b41f80b6 100644
--- a/src/js/advanced-settings.js
+++ b/src/js/advanced-settings.js
@@ -25,15 +25,49 @@
/******************************************************************************/
-(( ) => {
+{
// >>>> Start of private namespace
/******************************************************************************/
-const noopFunc = function(){};
-
+let defaultSettings = new Map();
let beforeHash = '';
+/******************************************************************************/
+
+CodeMirror.defineMode('raw-settings', function() {
+ let lastSetting = '';
+
+ return {
+ token: function(stream) {
+ if ( stream.sol() ) {
+ const match = stream.match(/\s*\S+/);
+ if ( match !== null ) {
+ lastSetting = match[0].trim();
+ if ( defaultSettings.has(lastSetting) ) {
+ return 'keyword';
+ }
+ }
+ lastSetting = '';
+ stream.skipToEnd();
+ return 'error';
+ }
+ if ( lastSetting !== '' ) {
+ stream.eatSpace();
+ const match = stream.match(/\S+.*$/);
+ if ( match !== null ) {
+ if ( match[0] !== defaultSettings.get(lastSetting) ) {
+ return 'strong';
+ }
+ }
+ lastSetting = '';
+ }
+ stream.skipToEnd();
+ return null;
+ }
+ };
+});
+
const cmEditor = new CodeMirror(
document.getElementById('advancedSettings'),
{
@@ -49,7 +83,41 @@ uBlockDashboard.patchCodeMirrorEditor(cmEditor);
/******************************************************************************/
const hashFromAdvancedSettings = function(raw) {
- return raw.trim().replace(/\s*[\n\r]+\s*/g, '\n').replace(/[ \t]+/g, ' ');
+ const aa = typeof raw === 'string'
+ ? arrayFromString(raw)
+ : arrayFromObject(raw);
+ aa.sort((a, b) => a[0].localeCompare(b[0]));
+ return JSON.stringify(aa);
+};
+
+/******************************************************************************/
+
+const arrayFromObject = function(o) {
+ const out = [];
+ for ( const k in o ) {
+ if ( o.hasOwnProperty(k) === false ) { continue; }
+ out.push([ k, `${o[k]}` ]);
+ }
+ return out;
+};
+
+const arrayFromString = function(s) {
+ const out = [];
+ for ( let line of s.split(/[\n\r]+/) ) {
+ line = line.trim();
+ if ( line === '' ) { continue; }
+ const pos = line.indexOf(' ');
+ let k, v;
+ if ( pos !== -1 ) {
+ k = line.slice(0, pos);
+ v = line.slice(pos + 1);
+ } else {
+ k = line;
+ v = '';
+ }
+ out.push([ k.trim(), v.trim() ]);
+ }
+ return out;
};
/******************************************************************************/
@@ -64,7 +132,7 @@ const advancedSettingsChanged = (( ) => {
const changed =
hashFromAdvancedSettings(cmEditor.getValue()) !== beforeHash;
uDom.nodeFromId('advancedSettingsApply').disabled = !changed;
- CodeMirror.commands.save = changed ? applyChanges : noopFunc;
+ CodeMirror.commands.save = changed ? applyChanges : function(){};
};
return function() {
@@ -78,21 +146,19 @@ cmEditor.on('changes', advancedSettingsChanged);
/******************************************************************************/
const renderAdvancedSettings = async function(first) {
- const raw = await vAPI.messaging.send('dashboard', {
+ const details = await vAPI.messaging.send('dashboard', {
what: 'readHiddenSettings',
});
-
- beforeHash = hashFromAdvancedSettings(raw);
+ defaultSettings = new Map(arrayFromObject(details.default));
+ beforeHash = hashFromAdvancedSettings(details.current);
const pretty = [];
- const lines = raw.split('\n');
+ const entries = arrayFromObject(details.current);
let max = 0;
- for ( const line of lines ) {
- const pos = line.indexOf(' ');
- if ( pos > max ) { max = pos; }
+ for ( const [ k ] of entries ) {
+ if ( k.length > max ) { max = k.length; }
}
- for ( const line of lines ) {
- const pos = line.indexOf(' ');
- pretty.push(' '.repeat(max - pos) + line);
+ for ( const [ k, v ] of entries ) {
+ pretty.push(' '.repeat(max - k.length) + `${k} ${v}`);
}
pretty.push('');
cmEditor.setValue(pretty.join('\n'));
@@ -128,4 +194,4 @@ renderAdvancedSettings(true);
/******************************************************************************/
// <<<< End of private namespace
-})();
+}
diff --git a/src/js/codemirror/mode/raw-settings.js b/src/js/codemirror/mode/raw-settings.js
deleted file mode 100644
index 34585d99c..000000000
--- a/src/js/codemirror/mode/raw-settings.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
-
- uBlock Origin - a browser extension to block requests.
- Copyright (C) 2019-present Raymond Hill
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see {http://www.gnu.org/licenses/}.
-
- Home: https://github.com/gorhill/uBlock
-*/
-
-/* global CodeMirror */
-
-'use strict';
-
-CodeMirror.defineMode("raw-settings", function() {
- return {
- token: function(stream) {
- if ( stream.sol() ) {
- stream.match(/\s*\S+/);
- return 'keyword';
- }
- stream.skipToEnd();
- return null;
- }
- };
-});
diff --git a/src/js/messaging.js b/src/js/messaging.js
index 92c897917..1561346bd 100644
--- a/src/js/messaging.js
+++ b/src/js/messaging.js
@@ -1163,7 +1163,10 @@ const onMessage = function(request, sender, callback) {
break;
case 'readHiddenSettings':
- response = µb.stringFromHiddenSettings();
+ response = {
+ current: µb.hiddenSettings,
+ default: µb.hiddenSettingsDefault,
+ };
break;
case 'restoreUserData':