1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-22 18:32:45 +01:00
This commit is contained in:
gorhill 2016-12-26 11:35:37 -05:00
parent 251bbe0f43
commit 6e458dca5c
5 changed files with 125 additions and 37 deletions

View File

@ -5,12 +5,36 @@ div > p:last-child {
margin-bottom: 0;
}
#whitelist {
box-sizing: border-box;
border: 1px solid gray;
height: 60vh;
text-align: left;
margin: 0;
padding: 1px;
position: relative;
resize: vertical;
}
#whitelist.invalid {
border-color: red;
}
#whitelist textarea {
border: none;
box-sizing: border-box;
height: 100%;
padding: 0.4em;
resize: none;
text-align: left;
white-space: pre;
width: 100%;
}
#whitelist.bad {
background-color: #fee;
}
#whitelist textarea + div {
background-color: red;
bottom: 0;
color: white;
display: none;
padding: 2px 4px;
pointer-events: none;
position: absolute;
right: 0;
}
#whitelist.invalid textarea + div {
display: block;
}

View File

@ -1011,6 +1011,10 @@ var onMessage = function(request, sender, callback) {
response = getRules();
break;
case 'validateWhitelistString':
response = µb.validateWhitelistString(request.raw);
break;
case 'writeHiddenSettings':
µb.hiddenSettingsFromString(request.content);
break;

View File

@ -194,9 +194,7 @@ var matchBucket = function(url, hostname, bucket, start) {
µBlock.whitelistFromString = function(s) {
var whitelist = Object.create(null),
reInvalidHostname = /[^a-z0-9.\-\[\]:]/,
reHostnameExtractor = /([a-z0-9\[][a-z0-9.\-]*[a-z0-9\]])(?::[\d*]+)?\/(?:[^\x00-\x20\/]|$)[^\x00-\x20]*$/,
lines = s.split(/[\n\r]+/),
lineIter = new this.LineIterator(s),
line, matches, key, directive, re;
// Comment bucket must always be ready to be used.
@ -205,8 +203,9 @@ var matchBucket = function(url, hostname, bucket, start) {
// New set of directives, scrap cached data.
directiveToRegexpMap.clear();
for ( var i = 0; i < lines.length; i++ ) {
line = lines[i].trim();
while ( !lineIter.eot() ) {
line = lineIter.next().trim();
// https://github.com/gorhill/uBlock/issues/171
// Skip empty lines
if ( line === '' ) {
@ -228,7 +227,7 @@ var matchBucket = function(url, hostname, bucket, start) {
}
}
// Regex-based (ensure it is valid)
else if ( line.startsWith('/') && line.endsWith('/') ) {
else if ( line.length > 2 && line.startsWith('/') && line.endsWith('/') ) {
key = '//';
directive = line;
try {
@ -267,6 +266,28 @@ var matchBucket = function(url, hostname, bucket, start) {
return whitelist;
};
µBlock.validateWhitelistString = function(s) {
var lineIter = new this.LineIterator(s), line;
while ( !lineIter.eot() ) {
line = lineIter.next().trim();
if ( line === '' ) { continue; }
if ( line.startsWith('#') ) { continue; } // Comment
if ( line.indexOf('/') === -1 ) { // Plain hostname
if ( reInvalidHostname.test(line) ) { return false; }
continue;
}
if ( line.length > 2 && line.startsWith('/') && line.endsWith('/') ) { // Regex-based
try { new RegExp(line.slice(1, -1)); } catch(ex) { return false; }
continue;
}
if ( reHostnameExtractor.test(line) === false ) { return false; } // URL
}
return true;
};
var reInvalidHostname = /[^a-z0-9.\-\[\]:]/,
reHostnameExtractor = /([a-z0-9\[][a-z0-9.\-]*[a-z0-9\]])(?::[\d*]+)?\/(?:[^\x00-\x20\/]|$)[^\x00-\x20]*$/;
/******************************************************************************/
})();

View File

@ -29,30 +29,68 @@
/******************************************************************************/
var messaging = vAPI.messaging;
var cachedWhitelist = '';
// Could make it more fancy if needed. But speed... It's a compromise.
var reUnwantedChars = /[\x00-\x09\x0b\x0c\x0e-\x1f!"'()<>{}|`~]/;
var messaging = vAPI.messaging,
cachedWhitelist = '';
/******************************************************************************/
var whitelistChanged = function() {
var textarea = uDom.nodeFromId('whitelist');
var s = textarea.value.trim();
var changed = s === cachedWhitelist;
var bad = reUnwantedChars.test(s);
uDom.nodeFromId('whitelistApply').disabled = changed || bad;
uDom.nodeFromId('whitelistRevert').disabled = changed;
textarea.classList.toggle('bad', bad);
var getTextareaNode = function() {
var me = getTextareaNode,
node = me.theNode;
if ( node === undefined ) {
node = me.theNode = uDom.nodeFromSelector('#whitelist textarea');
}
return node;
};
var setErrorNodeHorizontalOffset = function(px) {
var me = setErrorNodeHorizontalOffset,
offset = me.theOffset || 0;
if ( px === offset ) { return; }
var node = me.theNode;
if ( node === undefined ) {
node = me.theNode = uDom.nodeFromSelector('#whitelist textarea + div');
}
node.style.right = px + 'px';
me.theOffset = px;
};
/******************************************************************************/
var whitelistChanged = (function() {
var changedWhitelist, changed, timer;
var updateUI = function(good) {
uDom.nodeFromId('whitelistApply').disabled = changed || !good;
uDom.nodeFromId('whitelistRevert').disabled = changed;
uDom.nodeFromId('whitelist').classList.toggle('invalid', !good);
};
var validate = function() {
timer = undefined;
messaging.send(
'dashboard',
{ what: 'validateWhitelistString', raw: changedWhitelist },
updateUI
);
};
return function() {
changedWhitelist = getTextareaNode().value.trim();
changed = changedWhitelist === cachedWhitelist;
if ( timer !== undefined ) { clearTimeout(timer); }
timer = vAPI.setTimeout(validate, 251);
var textarea = getTextareaNode();
setErrorNodeHorizontalOffset(textarea.offsetWidth - textarea.clientWidth);
};
})();
/******************************************************************************/
var renderWhitelist = function() {
var onRead = function(whitelist) {
cachedWhitelist = whitelist.trim();
uDom.nodeFromId('whitelist').value = cachedWhitelist + '\n';
getTextareaNode().value = cachedWhitelist + '\n';
whitelistChanged();
};
messaging.send('dashboard', { what: 'getWhitelist' }, onRead);
@ -62,8 +100,8 @@ var renderWhitelist = function() {
var handleImportFilePicker = function() {
var fileReaderOnLoadHandler = function() {
var textarea = uDom('#whitelist');
textarea.val([textarea.val(), this.result].join('\n').trim());
var textarea = getTextareaNode();
textarea.value = [textarea.value.trim(), this.result.trim()].join('\n').trim();
whitelistChanged();
};
var file = this.files[0];
@ -92,10 +130,8 @@ var startImportFilePicker = function() {
/******************************************************************************/
var exportWhitelistToFile = function() {
var val = uDom('#whitelist').val().trim();
if ( val === '' ) {
return;
}
var val = getTextareaNode().value.trim();
if ( val === '' ) { return; }
var filename = vAPI.i18n('whitelistExportFilename')
.replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString())
.replace(/ +/g, '_');
@ -108,7 +144,7 @@ var exportWhitelistToFile = function() {
/******************************************************************************/
var applyChanges = function() {
cachedWhitelist = uDom.nodeFromId('whitelist').value.trim();
cachedWhitelist = getTextareaNode().value.trim();
var request = {
what: 'setWhitelist',
whitelist: cachedWhitelist
@ -117,21 +153,21 @@ var applyChanges = function() {
};
var revertChanges = function() {
uDom.nodeFromId('whitelist').value = cachedWhitelist + '\n';
getTextareaNode().value = cachedWhitelist + '\n';
whitelistChanged();
};
/******************************************************************************/
var getCloudData = function() {
return uDom.nodeFromId('whitelist').value;
return getTextareaNode().value;
};
var setCloudData = function(data, append) {
if ( typeof data !== 'string' ) {
return;
}
var textarea = uDom.nodeFromId('whitelist');
var textarea = getTextareaNode();
if ( append ) {
data = uBlockDashboard.mergeNewLines(textarea.value.trim(), data);
}
@ -147,7 +183,7 @@ self.cloud.onPull = setCloudData;
uDom('#importWhitelistFromFile').on('click', startImportFilePicker);
uDom('#importFilePicker').on('change', handleImportFilePicker);
uDom('#exportWhitelistToFile').on('click', exportWhitelistToFile);
uDom('#whitelist').on('input', whitelistChanged);
uDom('#whitelist textarea').on('input', whitelistChanged);
uDom('#whitelistApply').on('click', applyChanges);
uDom('#whitelistRevert').on('click', revertChanges);

View File

@ -17,7 +17,10 @@
<p>
<button id="whitelistApply" class="custom important" type="button" disabled="true" data-i18n="whitelistApply"></button>&ensp;
<button id="whitelistRevert" class="custom" type="button" disabled="true" data-i18n="genericRevert"></button>
<p><textarea id="whitelist" dir="auto" spellcheck="false"></textarea>
<p><section id="whitelist">
<textarea dir="auto" spellcheck="false"></textarea>
<div>E</div>
</section>
<p>
<button id="importWhitelistFromFile" class="custom" data-i18n="whitelistImport"></button>&ensp;
<button id="exportWhitelistToFile" class="custom" data-i18n="whitelistExport"></button>