diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 05:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 05:47:55 +0000 |
commit | 31d6ff6f931696850c348007241195ab3b2eddc7 (patch) | |
tree | 615cb1c57ce9f6611bad93326b9105098f379609 /src/js/advanced-settings.js | |
parent | Initial commit. (diff) | |
download | ublock-origin-31d6ff6f931696850c348007241195ab3b2eddc7.tar.xz ublock-origin-31d6ff6f931696850c348007241195ab3b2eddc7.zip |
Adding upstream version 1.55.0+dfsg.upstream/1.55.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/js/advanced-settings.js | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/js/advanced-settings.js b/src/js/advanced-settings.js new file mode 100644 index 0000000..c21346f --- /dev/null +++ b/src/js/advanced-settings.js @@ -0,0 +1,194 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2016-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, uBlockDashboard */ + +'use strict'; + +import { dom, qs$ } from './dom.js'; + +/******************************************************************************/ + +let defaultSettings = new Map(); +let adminSettings = new Map(); +let beforeHash = ''; + +/******************************************************************************/ + +CodeMirror.defineMode('raw-settings', function() { + let lastSetting = ''; + + return { + token: function(stream) { + if ( stream.sol() ) { + stream.eatSpace(); + const match = stream.match(/\S+/); + if ( match !== null && defaultSettings.has(match[0]) ) { + lastSetting = match[0]; + return adminSettings.has(match[0]) + ? 'readonly keyword' + : 'keyword'; + } + stream.skipToEnd(); + return 'line-cm-error'; + } + stream.eatSpace(); + const match = stream.match(/.*$/); + if ( match !== null ) { + if ( match[0].trim() !== defaultSettings.get(lastSetting) ) { + return 'line-cm-strong'; + } + if ( adminSettings.has(lastSetting) ) { + return 'readonly'; + } + } + stream.skipToEnd(); + return null; + } + }; +}); + +const cmEditor = new CodeMirror(qs$('#advancedSettings'), { + autofocus: true, + lineNumbers: true, + lineWrapping: false, + styleActiveLine: true +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +/******************************************************************************/ + +const hashFromAdvancedSettings = function(raw) { + 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; +}; + +/******************************************************************************/ + +const advancedSettingsChanged = (( ) => { + const handler = ( ) => { + const changed = hashFromAdvancedSettings(cmEditor.getValue()) !== beforeHash; + qs$('#advancedSettingsApply').disabled = !changed; + CodeMirror.commands.save = changed ? applyChanges : function(){}; + }; + + const timer = vAPI.defer.create(handler); + + return function() { + timer.offon(200); + }; +})(); + +cmEditor.on('changes', advancedSettingsChanged); + +/******************************************************************************/ + +const renderAdvancedSettings = async function(first) { + const details = await vAPI.messaging.send('dashboard', { + what: 'readHiddenSettings', + }); + defaultSettings = new Map(arrayFromObject(details.default)); + adminSettings = new Map(arrayFromObject(details.admin)); + beforeHash = hashFromAdvancedSettings(details.current); + const pretty = []; + const roLines = []; + const entries = arrayFromObject(details.current); + let max = 0; + for ( const [ k ] of entries ) { + if ( k.length > max ) { max = k.length; } + } + for ( let i = 0; i < entries.length; i++ ) { + const [ k, v ] = entries[i]; + pretty.push(' '.repeat(max - k.length) + `${k} ${v}`); + if ( adminSettings.has(k) ) { + roLines.push(i); + } + } + pretty.push(''); + cmEditor.setValue(pretty.join('\n')); + if ( first ) { + cmEditor.clearHistory(); + } + for ( const line of roLines ) { + cmEditor.markText( + { line, ch: 0 }, + { line: line + 1, ch: 0 }, + { readOnly: true } + ); + } + advancedSettingsChanged(); + cmEditor.focus(); +}; + +/******************************************************************************/ + +const applyChanges = async function() { + await vAPI.messaging.send('dashboard', { + what: 'writeHiddenSettings', + content: cmEditor.getValue(), + }); + renderAdvancedSettings(); +}; + +/******************************************************************************/ + +dom.on('#advancedSettings', 'input', advancedSettingsChanged); +dom.on('#advancedSettingsApply', 'click', ( ) => { + applyChanges(); +}); + +renderAdvancedSettings(true); + +/******************************************************************************/ |