@adguard/agtree
Version:
Tool set for working with adblock filter lists
121 lines (118 loc) • 5.98 kB
JavaScript
/*
* AGTree v3.2.1 (build date: Wed, 28 May 2025 13:36:39 GMT)
* (c) 2025 Adguard Software Ltd.
* Released under the MIT license
* https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
*/
import { AdblockSyntax } from '../../utils/adblockers.js';
import { DomainListSerializer } from '../misc/domain-list-serializer.js';
import { NULL } from '../../utils/constants.js';
import { CosmeticRuleType } from '../../nodes/index.js';
import { AbpSnippetInjectionBodySerializer } from './body/abp-snippet-injection-body-serializer.js';
import { UboScriptletInjectionBodySerializer } from './body/ubo-scriptlet-injection-body-serializer.js';
import { AdgScriptletInjectionBodySerializer } from './body/adg-scriptlet-injection-body-serializer.js';
import { ValueSerializer } from '../misc/value-serializer.js';
import { isUndefined } from '../../utils/type-guards.js';
import { BaseSerializer } from '../base-serializer.js';
import { ElementHidingBodySerializer } from './element-hiding-body-serializer.js';
import { CssInjectionBodySerializer } from './css-injection-body-serializer.js';
import { ModifierListSerializer } from '../misc/modifier-list-serializer.js';
import { CosmeticRuleMarshallingMap, COSMETIC_RULE_SEPARATOR_SERIALIZATION_MAP } from '../../marshalling-utils/cosmetic/cosmetic-rule-common.js';
import { BinaryTypeMarshallingMap } from '../../marshalling-utils/misc/binary-type-common.js';
import { getSyntaxSerializationMap } from '../../marshalling-utils/syntax-serialization-map.js';
/**
* `CosmeticRuleSerializer` is responsible for serializing cosmetic rules into a binary format.
*
* This class takes a cosmetic rule Abstract Syntax Tree (AST) and converts it into a compact binary representation.
* It handles the serialization of different types of cosmetic rules, including element hiding, CSS injection,
* JavaScript injection, HTML filtering, and scriptlet injection rules.
*/
class CosmeticRuleSerializer extends BaseSerializer {
/**
* Serializes a cosmetic rule node to binary format.
*
* @param node Node to serialize.
* @param buffer ByteBuffer for writing binary data.
*/
// TODO: add support for raws, if ever needed
static serialize(node, buffer) {
// specific properties
switch (node.type) {
case CosmeticRuleType.ElementHidingRule:
// rule type
buffer.writeUint8(BinaryTypeMarshallingMap.ElementHidingRule);
// syntax
buffer.writeUint8(getSyntaxSerializationMap().get(node.syntax) ?? 0);
// rule body
ElementHidingBodySerializer.serialize(node.body, buffer);
break;
case CosmeticRuleType.CssInjectionRule:
// rule type
buffer.writeUint8(BinaryTypeMarshallingMap.CssInjectionRule);
// syntax
buffer.writeUint8(getSyntaxSerializationMap().get(node.syntax) ?? 0);
// rule body
CssInjectionBodySerializer.serialize(node.body, buffer);
break;
case CosmeticRuleType.JsInjectionRule:
// rule type
buffer.writeUint8(BinaryTypeMarshallingMap.JsInjectionRule);
// syntax
buffer.writeUint8(getSyntaxSerializationMap().get(node.syntax) ?? 0);
// rule body
ValueSerializer.serialize(node.body, buffer);
break;
case CosmeticRuleType.HtmlFilteringRule:
// rule type
buffer.writeUint8(BinaryTypeMarshallingMap.HtmlFilteringRule);
// syntax
buffer.writeUint8(getSyntaxSerializationMap().get(node.syntax) ?? 0);
// rule body
ValueSerializer.serialize(node.body, buffer);
break;
case CosmeticRuleType.ScriptletInjectionRule:
// rule type
buffer.writeUint8(BinaryTypeMarshallingMap.ScriptletInjectionRule);
// syntax
buffer.writeUint8(getSyntaxSerializationMap().get(node.syntax) ?? 0);
// rule body
switch (node.syntax) {
case AdblockSyntax.Adg:
AdgScriptletInjectionBodySerializer.serialize(node.body, buffer);
break;
case AdblockSyntax.Abp:
AbpSnippetInjectionBodySerializer.serialize(node.body, buffer);
break;
case AdblockSyntax.Ubo:
UboScriptletInjectionBodySerializer.serialize(node.body, buffer);
break;
default:
throw new Error('Scriptlet rule should have an explicit syntax');
}
break;
default:
throw new Error('Unknown cosmetic rule type');
}
// common properties
buffer.writeUint8(CosmeticRuleMarshallingMap.Exception);
buffer.writeUint8(node.exception ? 1 : 0);
buffer.writeUint8(CosmeticRuleMarshallingMap.Separator);
ValueSerializer.serialize(node.separator, buffer, COSMETIC_RULE_SEPARATOR_SERIALIZATION_MAP);
if (node.modifiers) {
buffer.writeUint8(CosmeticRuleMarshallingMap.Modifiers);
ModifierListSerializer.serialize(node.modifiers, buffer);
}
buffer.writeUint8(CosmeticRuleMarshallingMap.Domains);
DomainListSerializer.serialize(node.domains, buffer);
if (!isUndefined(node.start)) {
buffer.writeUint8(CosmeticRuleMarshallingMap.Start);
buffer.writeUint32(node.start);
}
if (!isUndefined(node.end)) {
buffer.writeUint8(CosmeticRuleMarshallingMap.End);
buffer.writeUint32(node.end);
}
buffer.writeUint8(NULL);
}
}
export { CosmeticRuleSerializer };