mirror of https://github.com/gorhill/uBlock
145 lines
4.4 KiB
JavaScript
145 lines
4.4 KiB
JavaScript
/*******************************************************************************
|
|
|
|
uBlock Origin - a comprehensive, efficient content blocker
|
|
Copyright (C) 2014-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
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/******************************************************************************/
|
|
|
|
// https://www.reddit.com/r/uBlockOrigin/comments/oq6kt5/ubo_loads_generic_filter_instead_of_specific/
|
|
// Ensure blocks of content are sorted in ascending id order, such that the
|
|
// specific cosmetic filters will be found (and thus reported) before the
|
|
// generic ones.
|
|
|
|
const serialize = JSON.stringify;
|
|
const unserialize = JSON.parse;
|
|
|
|
const blockStartPrefix = '#block-start-'; // ensure no special regex characters
|
|
const blockEndPrefix = '#block-end-'; // ensure no special regex characters
|
|
|
|
class CompiledListWriter {
|
|
constructor() {
|
|
this.blockId = undefined;
|
|
this.block = undefined;
|
|
this.blocks = new Map();
|
|
this.properties = new Map();
|
|
}
|
|
push(args) {
|
|
this.block.push(serialize(args));
|
|
}
|
|
pushMany(many) {
|
|
for ( const args of many ) {
|
|
this.block.push(serialize(args));
|
|
}
|
|
}
|
|
last() {
|
|
if ( Array.isArray(this.block) && this.block.length !== 0 ) {
|
|
return this.block[this.block.length - 1];
|
|
}
|
|
}
|
|
select(blockId) {
|
|
if ( blockId === this.blockId ) { return; }
|
|
this.blockId = blockId;
|
|
this.block = this.blocks.get(blockId);
|
|
if ( this.block === undefined ) {
|
|
this.blocks.set(blockId, (this.block = []));
|
|
}
|
|
return this;
|
|
}
|
|
toString() {
|
|
const result = [];
|
|
const sortedBlocks =
|
|
Array.from(this.blocks).sort((a, b) => a[0] - b[0]);
|
|
for ( const [ id, lines ] of sortedBlocks ) {
|
|
if ( lines.length === 0 ) { continue; }
|
|
result.push(
|
|
blockStartPrefix + id,
|
|
lines.join('\n'),
|
|
blockEndPrefix + id
|
|
);
|
|
}
|
|
return result.join('\n');
|
|
}
|
|
static serialize(arg) {
|
|
return serialize(arg);
|
|
}
|
|
}
|
|
|
|
class CompiledListReader {
|
|
constructor(raw, blockId) {
|
|
this.block = '';
|
|
this.len = 0;
|
|
this.offset = 0;
|
|
this.line = '';
|
|
this.blocks = new Map();
|
|
this.properties = new Map();
|
|
const reBlockStart = new RegExp(`^${blockStartPrefix}([\\w:]+)\\n`, 'gm');
|
|
let match = reBlockStart.exec(raw);
|
|
while ( match !== null ) {
|
|
const sectionId = match[1];
|
|
const beg = match.index + match[0].length;
|
|
const end = raw.indexOf(blockEndPrefix + sectionId, beg);
|
|
this.blocks.set(sectionId, raw.slice(beg, end));
|
|
reBlockStart.lastIndex = end;
|
|
match = reBlockStart.exec(raw);
|
|
}
|
|
if ( blockId !== undefined ) {
|
|
this.select(blockId);
|
|
}
|
|
}
|
|
next() {
|
|
if ( this.offset === this.len ) {
|
|
this.line = '';
|
|
return false;
|
|
}
|
|
let pos = this.block.indexOf('\n', this.offset);
|
|
if ( pos !== -1 ) {
|
|
this.line = this.block.slice(this.offset, pos);
|
|
this.offset = pos + 1;
|
|
} else {
|
|
this.line = this.block.slice(this.offset);
|
|
this.offset = this.len;
|
|
}
|
|
return true;
|
|
}
|
|
select(blockId) {
|
|
this.block = this.blocks.get(blockId) || '';
|
|
this.len = this.block.length;
|
|
this.offset = 0;
|
|
return this;
|
|
}
|
|
fingerprint() {
|
|
return this.line;
|
|
}
|
|
args() {
|
|
return unserialize(this.line);
|
|
}
|
|
static unserialize(arg) {
|
|
return unserialize(arg);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
export {
|
|
CompiledListReader,
|
|
CompiledListWriter,
|
|
};
|