@adguard/filters-compiler 3.2.8 → 3.2.10-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +357 -186
- package/dist/index.cjs +28 -38
- package/dist/index.d.ts +84 -0
- package/dist/index.js +28 -38
- package/dist/types/src/main/utils/version.d.ts +20 -0
- package/dist/types/test/ts-imports-js.test.d.ts +1 -0
- package/dist/types/test/version.test.d.ts +1 -0
- package/package.json +39 -27
- package/dist/build.txt +0 -1
package/README.md
CHANGED
|
@@ -1,119 +1,255 @@
|
|
|
1
1
|
# AdGuard Filters Compiler
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
> A Node.js library that compiles, converts, validates, and optimizes
|
|
4
|
+
> ad-blocking filter lists into platform-specific formats for AdGuard
|
|
5
|
+
> products across all supported platforms.
|
|
6
|
+
|
|
7
|
+
> **Note:** This package is developed in [AdGuardSoftwareLimited/ext-compiler].
|
|
8
|
+
> The [AdguardTeam/FiltersCompiler] repository is a public mirror.
|
|
9
|
+
|
|
10
|
+
## Description
|
|
11
|
+
|
|
12
|
+
**AdGuard Filters Compiler** is a library for developers who maintain
|
|
13
|
+
ad-blocking filter lists and the build pipelines that ship them. It
|
|
14
|
+
transforms source filter lists — written in the AdGuard filter rules
|
|
15
|
+
syntax — into compiled output tailored to each target platform (browser
|
|
16
|
+
extensions, desktop and mobile apps, and the AdGuard CLI).
|
|
17
|
+
|
|
18
|
+
AdGuard's filter rules are authored once but must run on many engines
|
|
19
|
+
with different capabilities: not every platform supports scriptlets,
|
|
20
|
+
HTML filtering, `$redirect` modifiers, extended CSS, or regex-based
|
|
21
|
+
`$domain` selectors. The compiler closes that gap. It resolves
|
|
22
|
+
`@include` and `!#include` preprocessor directives, converts rules
|
|
23
|
+
between AdGuard and uBlock Origin formats, validates each rule against
|
|
24
|
+
the `@adguard/tsurlfilter` engine, optimizes blocking rules using
|
|
25
|
+
hit-count statistics, and strips rules that a given platform cannot
|
|
26
|
+
apply.
|
|
27
|
+
|
|
28
|
+
The library is consumed by [FiltersRegistry] to produce production
|
|
29
|
+
filter builds, but it can be used directly by anyone who needs to
|
|
30
|
+
compile filter lists for AdGuard platforms. The expected source
|
|
31
|
+
directory structure and the filters metadata format are documented in
|
|
32
|
+
the [FiltersRegistry README][filters-metadata].
|
|
33
|
+
|
|
34
|
+
## Table of Contents
|
|
35
|
+
|
|
36
|
+
- [Installation](#installation)
|
|
37
|
+
- [Quick Start](#quick-start)
|
|
38
|
+
- [API Overview](#api-overview)
|
|
39
|
+
- [Usage Examples](#usage-examples)
|
|
40
|
+
- [Compiling filter lists](#compiling-filter-lists)
|
|
41
|
+
- [Validating built filters](#validating-built-filters)
|
|
42
|
+
- [Validating locale translations](#validating-locale-translations)
|
|
11
43
|
- [`@include` directive and its options](#include-directive)
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
44
|
+
- [Configuration](#configuration)
|
|
45
|
+
- [Custom platforms](#custom-platforms)
|
|
46
|
+
- [Logging](#logging)
|
|
47
|
+
- [Environment variables](#environment-variables)
|
|
48
|
+
- [Supported platforms](#supported-platforms)
|
|
49
|
+
- [Documentation](#documentation)
|
|
14
50
|
|
|
15
|
-
|
|
51
|
+
---
|
|
16
52
|
|
|
17
|
-
|
|
53
|
+
## Installation
|
|
18
54
|
|
|
19
|
-
|
|
55
|
+
```bash
|
|
56
|
+
npm install @adguard/filters-compiler
|
|
57
|
+
```
|
|
20
58
|
|
|
21
|
-
|
|
22
|
-
const whitelist = [1, 3];
|
|
23
|
-
const blacklist = [2];
|
|
59
|
+
Also available via pnpm or yarn:
|
|
24
60
|
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
```bash
|
|
62
|
+
pnpm add @adguard/filters-compiler
|
|
63
|
+
# or
|
|
64
|
+
yarn add @adguard/filters-compiler
|
|
65
|
+
```
|
|
27
66
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const reportPath = path.join(__dirname, './report.txt');
|
|
67
|
+
The package ships as dual ESM + CJS, so both `import` and `require`
|
|
68
|
+
work out of the box.
|
|
31
69
|
|
|
32
|
-
|
|
70
|
+
## Quick Start
|
|
33
71
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"ignoreRuleHints": false,
|
|
42
|
-
"removeRulePatterns": [
|
|
43
|
-
"^\\/.*" // remove regex rules for some reason.
|
|
44
|
-
],
|
|
45
|
-
"replacements": [
|
|
46
|
-
{
|
|
47
|
-
"from": "regex",
|
|
48
|
-
"to": "repl"
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
},
|
|
52
|
-
"defines": {
|
|
53
|
-
"adguard": true,
|
|
54
|
-
"adguard_app_mac": true
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
};
|
|
72
|
+
```js
|
|
73
|
+
import { compile } from '@adguard/filters-compiler';
|
|
74
|
+
|
|
75
|
+
const filtersDir = './filters';
|
|
76
|
+
const logPath = './log.txt';
|
|
77
|
+
const reportPath = './report.txt';
|
|
78
|
+
const platformsPath = './platforms';
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
// Compile every filter for every platform, keeping only filters
|
|
81
|
+
// with IDs 1 and 3, and excluding filter ID 2.
|
|
82
|
+
await compile(filtersDir, logPath, reportPath, platformsPath, [1, 3], [2]);
|
|
60
83
|
```
|
|
61
84
|
|
|
62
|
-
The
|
|
63
|
-
|
|
85
|
+
The compiler reads the source filter lists from `filtersDir` and writes
|
|
86
|
+
platform-specific output to subdirectories under `platformsPath`. A
|
|
87
|
+
human-readable compilation report is written to `reportPath`, and a
|
|
88
|
+
timestamped log to `logPath`.
|
|
89
|
+
|
|
90
|
+
## API Overview
|
|
91
|
+
|
|
92
|
+
The library exports three functions:
|
|
93
|
+
|
|
94
|
+
| Function | Purpose |
|
|
95
|
+
| ------------------------- | ---------------------------------------------------- |
|
|
96
|
+
| `compile(...)` | Compiles filter lists into platform-specific output |
|
|
97
|
+
| `validateJSONSchema(...)` | Validates built platform output against JSON schemas |
|
|
98
|
+
| `validateLocales(...)` | Validates locale translation files for completeness |
|
|
99
|
+
|
|
100
|
+
### `compile(...)`
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
function compile(
|
|
104
|
+
path: string,
|
|
105
|
+
logPath: string | undefined,
|
|
106
|
+
reportFile: string | undefined,
|
|
107
|
+
platformsPath: string,
|
|
108
|
+
whitelist: number[],
|
|
109
|
+
blacklist: number[],
|
|
110
|
+
customPlatformsConfig?: CustomPlatformsConfig,
|
|
111
|
+
): Promise<void>;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Compiles the filter lists in `path` for all configured platforms and
|
|
115
|
+
writes the results to `platformsPath`.
|
|
116
|
+
|
|
117
|
+
- `whitelist` — compile only the filter IDs listed here (empty array
|
|
118
|
+
compiles all filters).
|
|
119
|
+
- `blacklist` — exclude the filter IDs listed here.
|
|
120
|
+
- `customPlatformsConfig` — overrides or extends the built-in platform
|
|
121
|
+
definitions (see [Custom platforms](#custom-platforms)).
|
|
64
122
|
|
|
65
|
-
|
|
66
|
-
const compiler = require("adguard-filters-compiler");
|
|
123
|
+
### `validateJSONSchema(...)`
|
|
67
124
|
|
|
68
|
-
|
|
125
|
+
```ts
|
|
126
|
+
function validateJSONSchema(
|
|
127
|
+
platformsPath: string,
|
|
128
|
+
requiredFiltersAmount: number,
|
|
129
|
+
): boolean;
|
|
69
130
|
```
|
|
70
131
|
|
|
71
|
-
|
|
72
|
-
|
|
132
|
+
Recursively validates the built JSON files in `platformsPath` against
|
|
133
|
+
the schemas bundled with the library (`filters.schema.json` and
|
|
134
|
+
`filters_i18n.schema.json`). `requiredFiltersAmount` is the minimum
|
|
135
|
+
number of filters expected in each platform's `filters.json`.
|
|
73
136
|
|
|
74
|
-
|
|
137
|
+
Returns `true` when all files are valid. On validation failure it logs
|
|
138
|
+
the errors and returns `false` instead of throwing, so callers must
|
|
139
|
+
check the return value.
|
|
75
140
|
|
|
76
|
-
|
|
77
|
-
|
|
141
|
+
### `validateLocales(...)`
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
function validateLocales(
|
|
145
|
+
localesDirPath: string,
|
|
146
|
+
requiredLocales: string[],
|
|
147
|
+
): ValidateLocalesResult;
|
|
148
|
+
|
|
149
|
+
interface ValidateLocalesResult {
|
|
150
|
+
ok: boolean;
|
|
151
|
+
data?: unknown[]; // per-locale warning details, present when warnings exist
|
|
152
|
+
log?: string; // formatted warnings log, present when warnings exist
|
|
153
|
+
}
|
|
78
154
|
```
|
|
79
155
|
|
|
80
|
-
|
|
156
|
+
Validates that the locale files in `localesDirPath` are complete — that
|
|
157
|
+
every filter, group, and tag has a translated name and description for
|
|
158
|
+
all locales listed in `requiredLocales`.
|
|
81
159
|
|
|
82
|
-
|
|
83
|
-
|
|
160
|
+
Returns `{ ok: true }` when no problems are found. When warnings are
|
|
161
|
+
found, `data` and `log` contain the per-locale details and `ok` is
|
|
162
|
+
`false` only if at least one warning is critical. Throws when the
|
|
163
|
+
locales directory is missing or empty.
|
|
84
164
|
|
|
85
|
-
|
|
86
|
-
you should update `@adguard/tsurlfilter` with updated scriptlets.
|
|
165
|
+
## Usage Examples
|
|
87
166
|
|
|
88
|
-
|
|
167
|
+
### Compiling filter lists
|
|
89
168
|
|
|
90
|
-
|
|
169
|
+
Compile all filters with the default platform configuration:
|
|
91
170
|
|
|
92
|
-
|
|
171
|
+
```js
|
|
172
|
+
import { compile } from '@adguard/filters-compiler';
|
|
93
173
|
|
|
94
|
-
|
|
95
|
-
|
|
174
|
+
await compile(
|
|
175
|
+
'./filters', // source filter lists
|
|
176
|
+
'./log.txt', // log file (omit to disable logging)
|
|
177
|
+
'./report.txt', // compilation report
|
|
178
|
+
'./platforms', // platform output directory
|
|
179
|
+
[], // whitelist (empty = compile all)
|
|
180
|
+
[], // blacklist (empty = exclude none)
|
|
181
|
+
);
|
|
182
|
+
```
|
|
96
183
|
|
|
97
|
-
|
|
98
|
-
> The same is true for `schemas/mac_v2/` directory.
|
|
184
|
+
Compile a single filter into a custom platform:
|
|
99
185
|
|
|
100
|
-
|
|
101
|
-
|
|
186
|
+
```js
|
|
187
|
+
import { compile } from '@adguard/filters-compiler';
|
|
102
188
|
|
|
103
|
-
|
|
104
|
-
|
|
189
|
+
const customPlatformsConfig = {
|
|
190
|
+
// Here you can redefine some of the platforms from platforms.json
|
|
191
|
+
// or add new platforms if you need it.
|
|
192
|
+
MAC_V3: {
|
|
193
|
+
platform: 'mac',
|
|
194
|
+
path: 'mac_v3',
|
|
195
|
+
configuration: {
|
|
196
|
+
ignoreRuleHints: false,
|
|
197
|
+
removeRulePatterns: [
|
|
198
|
+
'^\\/.*', // drop regex rules
|
|
199
|
+
],
|
|
200
|
+
replacements: [
|
|
201
|
+
{ from: 'regex', to: 'repl' },
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
defines: {
|
|
205
|
+
adguard: true,
|
|
206
|
+
adguard_app_mac: true,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
};
|
|
105
210
|
|
|
106
|
-
|
|
107
|
-
|
|
211
|
+
await compile(
|
|
212
|
+
'./filters',
|
|
213
|
+
undefined, // no log file
|
|
214
|
+
'./report.txt',
|
|
215
|
+
'./platforms',
|
|
216
|
+
[1], // only filter ID 1
|
|
217
|
+
[],
|
|
218
|
+
customPlatformsConfig,
|
|
219
|
+
);
|
|
108
220
|
```
|
|
109
221
|
|
|
110
|
-
|
|
222
|
+
### Validating built filters
|
|
223
|
+
|
|
224
|
+
After compiling, validate the built output against the bundled schemas:
|
|
111
225
|
|
|
112
|
-
|
|
226
|
+
```js
|
|
227
|
+
import { validateJSONSchema } from '@adguard/filters-compiler';
|
|
228
|
+
|
|
229
|
+
// Each platform build must contain at least 50 filters
|
|
230
|
+
const valid = validateJSONSchema('./platforms', 50);
|
|
231
|
+
if (!valid) {
|
|
232
|
+
throw new Error('Schema validation failed, see log for details');
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Validating locale translations
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
import { validateLocales } from '@adguard/filters-compiler';
|
|
240
|
+
|
|
241
|
+
const result = validateLocales('./locales', ['en', 'fr', 'ko']);
|
|
242
|
+
if (!result.ok) {
|
|
243
|
+
console.error(result.log);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
113
246
|
|
|
114
247
|
## <a name="include-directive"></a> `@include` directive and its options
|
|
115
248
|
|
|
116
|
-
The `@include` directive provides the ability to include content from
|
|
249
|
+
The `@include` directive provides the ability to include content from
|
|
250
|
+
the specified address. Filter source files use it to pull in content
|
|
251
|
+
from other files or remote URLs during compilation, letting you compose
|
|
252
|
+
filter lists from shared fragments.
|
|
117
253
|
|
|
118
254
|
### Syntax
|
|
119
255
|
|
|
@@ -121,152 +257,187 @@ The `@include` directive provides the ability to include content from the specif
|
|
|
121
257
|
@include <filepath> [<options>]
|
|
122
258
|
```
|
|
123
259
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
- `<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- `/
|
|
131
|
-
- `/
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- `/ignoreTrustLevel`
|
|
138
|
-
|
|
139
|
-
- `/optimizeDomainBlockingRules`
|
|
140
|
-
|
|
141
|
-
|
|
260
|
+
- `<filepath>` — required, URL or same-origin relative file path to
|
|
261
|
+
include.
|
|
262
|
+
- `<options>` — optional, space-separated flags:
|
|
263
|
+
|
|
264
|
+
- `/stripComments` — removes AdBlock-style comment lines (starting
|
|
265
|
+
with `!`) from the included file.
|
|
266
|
+
- `/notOptimized` — adds a `!+ NOT_OPTIMIZED` hint to the rules.
|
|
267
|
+
- `/exclude="<filepath>"` — excludes rules listed in the exception
|
|
268
|
+
file at `filepath`.
|
|
269
|
+
- `/addModifiers="<modifiers>"` — appends the given modifiers (as
|
|
270
|
+
is) to every rule in the included file. Works with host-rule
|
|
271
|
+
files too, converting `#` host-file comments to `!` AdBlock-style
|
|
272
|
+
comments.
|
|
273
|
+
- `/ignoreTrustLevel` — skips the trust-level check for the
|
|
274
|
+
included file. Only allowed for same-origin files.
|
|
275
|
+
- `/optimizeDomainBlockingRules` — removes redundant
|
|
276
|
+
domain-blocking rules. Rules with modifiers and rules of other
|
|
277
|
+
formats are ignored.
|
|
142
278
|
|
|
143
279
|
> [!IMPORTANT]
|
|
144
|
-
>
|
|
145
|
-
>
|
|
280
|
+
> Options are applied in the order they appear in the directive, except
|
|
281
|
+
> `/ignoreTrustLevel`.
|
|
146
282
|
|
|
147
283
|
### Examples
|
|
148
284
|
|
|
149
|
-
|
|
150
|
-
add a hint to the rules, and remove comments from the prepared rules:
|
|
151
|
-
|
|
152
|
-
```adblock
|
|
153
|
-
@include ../input.txt /addModifiers="script" /exclude="../exclusions.txt" /notOptimized /stripComments /optimizeDomainBlockingRules
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
The order of execution of the options is as follows:
|
|
285
|
+
Apply all options to an included file:
|
|
157
286
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
example.org
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
1. `/addModifiers="script"`: Adds the `$script` modifier to all rules in the included file.
|
|
167
|
-
|
|
168
|
-
Result of adding modifiers:
|
|
287
|
+
<!-- markdownlint-disable line-length -->
|
|
288
|
+
```adblock
|
|
289
|
+
@include ../input.txt /addModifiers="script" /exclude="../exclusions.txt" /notOptimized /stripComments /optimizeDomainBlockingRules
|
|
290
|
+
```
|
|
291
|
+
<!-- markdownlint-enable line-length -->
|
|
169
292
|
|
|
170
|
-
|
|
171
|
-
! comment
|
|
172
|
-
example.com$script
|
|
173
|
-
example.org$script
|
|
174
|
-
```
|
|
293
|
+
Given `../input.txt`:
|
|
175
294
|
|
|
176
|
-
|
|
177
|
-
|
|
295
|
+
```adblock
|
|
296
|
+
# comment
|
|
297
|
+
example.com
|
|
298
|
+
example.org
|
|
299
|
+
```
|
|
178
300
|
|
|
179
|
-
|
|
301
|
+
**1. `/addModifiers="script"`** appends `$script` to every rule and
|
|
302
|
+
converts host-file `#` comments to AdBlock-style `!`:
|
|
180
303
|
|
|
181
|
-
|
|
304
|
+
```adblock
|
|
305
|
+
! comment
|
|
306
|
+
example.com$script
|
|
307
|
+
example.org$script
|
|
308
|
+
```
|
|
182
309
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
example2.com$script
|
|
186
|
-
```
|
|
310
|
+
**2. `/exclude="../exclusions.txt"`** removes rules listed in
|
|
311
|
+
`exclusions.txt` (for example, `example.com$script`):
|
|
187
312
|
|
|
188
|
-
|
|
313
|
+
```adblock
|
|
314
|
+
! comment
|
|
315
|
+
example.org$script
|
|
316
|
+
```
|
|
189
317
|
|
|
190
|
-
|
|
191
|
-
! comment
|
|
192
|
-
example.org$script
|
|
193
|
-
```
|
|
318
|
+
**3. `/notOptimized`** adds the hint:
|
|
194
319
|
|
|
195
|
-
|
|
320
|
+
```adblock
|
|
321
|
+
! comment
|
|
322
|
+
!+ NOT_OPTIMIZED
|
|
323
|
+
example.org$script
|
|
324
|
+
```
|
|
196
325
|
|
|
197
|
-
|
|
326
|
+
**4. `/stripComments`** removes comment lines:
|
|
198
327
|
|
|
199
|
-
|
|
328
|
+
```adblock
|
|
329
|
+
!+ NOT_OPTIMIZED
|
|
330
|
+
example.org$script
|
|
331
|
+
```
|
|
200
332
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
```
|
|
333
|
+
**5. `/optimizeDomainBlockingRules`** removes redundant domain-blocking
|
|
334
|
+
rules. For example, when `||sub.example.com^` is already covered by
|
|
335
|
+
`||example.com^`, it is dropped, while rules with modifiers such as
|
|
336
|
+
`||test.com^$script` are kept:
|
|
206
337
|
|
|
207
|
-
|
|
208
|
-
|
|
338
|
+
```adblock
|
|
339
|
+
||example.com^
|
|
340
|
+
||domain.com^
|
|
341
|
+
||test.com^$script
|
|
342
|
+
```
|
|
209
343
|
|
|
210
|
-
|
|
344
|
+
Include a remote file with comment stripping:
|
|
211
345
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```
|
|
346
|
+
```adblock
|
|
347
|
+
@include "https://easylist.github.io/easylist/easylist.txt" /stripComments
|
|
348
|
+
```
|
|
216
349
|
|
|
217
|
-
|
|
350
|
+
Skip the trust-level check for a same-origin included file:
|
|
218
351
|
|
|
219
|
-
|
|
352
|
+
```adblock
|
|
353
|
+
@include ./input.txt /ignoreTrustLevel
|
|
354
|
+
```
|
|
220
355
|
|
|
221
|
-
|
|
222
|
-
||example.com^
|
|
223
|
-
||sub.example.com^
|
|
224
|
-
||domain.com^
|
|
225
|
-
||test.com^$script
|
|
226
|
-
```
|
|
356
|
+
## Configuration
|
|
227
357
|
|
|
228
|
-
|
|
358
|
+
### Custom platforms
|
|
229
359
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
||test.com^$script
|
|
234
|
-
```
|
|
360
|
+
Pass `customPlatformsConfig` to `compile()` to redefine existing
|
|
361
|
+
platforms or add new ones. Each entry mirrors the structure in
|
|
362
|
+
`src/main/platforms-config.js`:
|
|
235
363
|
|
|
236
|
-
|
|
237
|
-
|
|
364
|
+
```js
|
|
365
|
+
const customPlatformsConfig = {
|
|
366
|
+
MAC_V3: {
|
|
367
|
+
platform: 'mac', // platform family
|
|
368
|
+
path: 'mac_v3', // output subdirectory under platformsPath
|
|
369
|
+
expires: '12 hours', // optional cache TTL written to metadata
|
|
370
|
+
configuration: {
|
|
371
|
+
ignoreRuleHints: false, // honour `!+ HINT` hints when false
|
|
372
|
+
removeRulePatterns: [ // regexes of rules to drop
|
|
373
|
+
'^\\/.*',
|
|
374
|
+
],
|
|
375
|
+
replacements: [ // regex replacements applied to rules
|
|
376
|
+
{ from: 'regex', to: 'repl' },
|
|
377
|
+
],
|
|
378
|
+
},
|
|
379
|
+
defines: { // !#if preprocessor flags for this platform
|
|
380
|
+
adguard: true,
|
|
381
|
+
adguard_app_mac: true,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
```
|
|
238
386
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
387
|
+
`replacements[].from` is treated as a regular-expression pattern (it is
|
|
388
|
+
passed to `new RegExp(from, 'g')`), not as literal text. Escape regex
|
|
389
|
+
metacharacters in `from` when a literal match is intended.
|
|
242
390
|
|
|
243
|
-
|
|
391
|
+
### Logging
|
|
244
392
|
|
|
245
|
-
|
|
393
|
+
The compiler writes a timestamped log file when `logPath` is passed to
|
|
394
|
+
`compile()`. If `logPath` is omitted, no log file is written. The parent
|
|
395
|
+
directory is created automatically when it does not exist.
|
|
246
396
|
|
|
247
|
-
|
|
248
|
-
compile = (path, logPath, reportFile, platformsPath, whitelist, blacklist, customPlatformsConfig)
|
|
249
|
-
```
|
|
397
|
+
Log levels:
|
|
250
398
|
|
|
251
|
-
|
|
399
|
+
- `INFO` — general information about the process
|
|
400
|
+
- `WARN` — warnings that do not stop the process
|
|
401
|
+
- `ERROR` — errors indicating failures
|
|
252
402
|
|
|
253
|
-
###
|
|
403
|
+
### Environment variables
|
|
254
404
|
|
|
255
|
-
|
|
405
|
+
| Variable | Default | Purpose |
|
|
406
|
+
| -------- | ----------------- | ------------------------------------------------------------------------------------------------- |
|
|
407
|
+
| `TLS` | (system defaults) | Set to `insecure` to bypass TLS certificate verification when downloading external filter sources |
|
|
256
408
|
|
|
257
|
-
|
|
258
|
-
- `WARN`: Warning messages that don't stop the process
|
|
259
|
-
- `ERROR`: Error messages indicating failures
|
|
409
|
+
## Supported platforms
|
|
260
410
|
|
|
261
|
-
|
|
411
|
+
The compiler ships built-in configurations for the following platforms.
|
|
412
|
+
Each writes its output to a subdirectory under `platformsPath`.
|
|
262
413
|
|
|
263
|
-
|
|
414
|
+
| Platform ID | Output directory | Target |
|
|
415
|
+
| ----------------------------------- | ----------------------------------- | ----------------------------------------- |
|
|
416
|
+
| `WINDOWS` | `windows` | AdGuard for Windows |
|
|
417
|
+
| `MAC` | `mac` | AdGuard for macOS (legacy v1) |
|
|
418
|
+
| `MAC_V2` | `mac_v2` | AdGuard for macOS v2 |
|
|
419
|
+
| `MAC_V3` | `mac_v3` | AdGuard for macOS v3 |
|
|
420
|
+
| `ANDROID` | `android` | AdGuard for Android |
|
|
421
|
+
| `IOS` | `ios` | AdGuard for iOS |
|
|
422
|
+
| `CLI` | `cli` | AdGuard CLI / CoreLibs |
|
|
423
|
+
| `EXTENSION_CHROMIUM` | `extension/chromium` | AdGuard Browser Extension (Chromium, MV2) |
|
|
424
|
+
| `EXTENSION_CHROMIUM_MV3` | `extension/chromium-mv3` | AdGuard Browser Extension (Chromium, MV3) |
|
|
425
|
+
| `EXTENSION_EDGE` | `extension/edge` | AdGuard Browser Extension (Edge, MV2) |
|
|
426
|
+
| `EXTENSION_OPERA` | `extension/opera` | AdGuard Browser Extension (Opera, MV2) |
|
|
427
|
+
| `EXTENSION_OPERA_MV3` | `extension/opera-mv3` | AdGuard Browser Extension (Opera, MV3) |
|
|
428
|
+
| `EXTENSION_FIREFOX` | `extension/firefox` | AdGuard Browser Extension (Firefox) |
|
|
429
|
+
| `EXTENSION_SAFARI` | `extension/safari` | AdGuard Browser Extension (Safari) |
|
|
430
|
+
| `EXTENSION_ANDROID_CONTENT_BLOCKER` | `extension/android-content-blocker` | AdGuard content blocker (Android) |
|
|
431
|
+
| `EXTENSION_UBLOCK` | `extension/ublock` | uBlock Origin-compatible output |
|
|
264
432
|
|
|
265
|
-
##
|
|
433
|
+
## Documentation
|
|
266
434
|
|
|
267
|
-
- [
|
|
268
|
-
- [
|
|
269
|
-
- [
|
|
435
|
+
- [Development](DEVELOPMENT.md) — setup, build, and contributing workflow
|
|
436
|
+
- [Deployment and configuration](DEPLOYMENT.md) — release pipeline and runtime environment
|
|
437
|
+
- [Changelog](CHANGELOG.md) — version history
|
|
438
|
+
- [LLM agent rules](AGENTS.md) — AI-assisted development guidelines
|
|
270
439
|
|
|
271
440
|
[FiltersRegistry]: https://github.com/AdguardTeam/FiltersRegistry/
|
|
272
441
|
[filters-metadata]: https://github.com/AdguardTeam/FiltersRegistry/blob/master/README.md#filters-metadata
|
|
442
|
+
[AdGuardSoftwareLimited/ext-compiler]: https://github.com/AdGuardSoftwareLimited/ext-compiler
|
|
443
|
+
[AdguardTeam/FiltersCompiler]: https://github.com/AdguardTeam/FiltersCompiler
|
package/dist/index.cjs
CHANGED
|
@@ -23,57 +23,47 @@ var Ajv = require('ajv');
|
|
|
23
23
|
|
|
24
24
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
25
25
|
/**
|
|
26
|
-
* Version utility
|
|
26
|
+
* Version utility class.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
class Version {
|
|
29
29
|
/**
|
|
30
|
-
* Parses version from string
|
|
30
|
+
* Parses version from string.
|
|
31
31
|
*
|
|
32
|
-
* @param v
|
|
33
|
-
* @returns
|
|
32
|
+
* @param v Version string.
|
|
33
|
+
* @returns Array of numeric version parts.
|
|
34
34
|
*/
|
|
35
|
-
parse(v) {
|
|
36
|
-
const
|
|
37
|
-
const parts = String(v || '').split('.');
|
|
38
|
-
|
|
35
|
+
static parse(v) {
|
|
36
|
+
const parts = String(v ?? '').split('.');
|
|
39
37
|
const parseVersionPart = (part) => {
|
|
40
|
-
|
|
38
|
+
const n = Number(part);
|
|
39
|
+
if (Number.isNaN(n)) {
|
|
41
40
|
return 0;
|
|
42
41
|
}
|
|
43
|
-
return Math.max(
|
|
42
|
+
return Math.max(n, 0);
|
|
44
43
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
for (const part of parts) {
|
|
48
|
-
version.push(parseVersionPart(part));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return version;
|
|
52
|
-
},
|
|
53
|
-
|
|
44
|
+
return parts.map(parseVersionPart);
|
|
45
|
+
}
|
|
54
46
|
/**
|
|
55
|
-
* Increments build part of version '0.0.0.0'
|
|
47
|
+
* Increments the build (last) part of a version string `'0.0.0.0'`.
|
|
48
|
+
* Carries over when a part reaches 100.
|
|
56
49
|
*
|
|
57
|
-
* @param v
|
|
58
|
-
* @returns
|
|
50
|
+
* @param v Version string.
|
|
51
|
+
* @returns Incremented version string.
|
|
59
52
|
*/
|
|
60
|
-
increment(v) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
version[version.length - 1] = version[version.length - 1] + 1;
|
|
53
|
+
static increment(v) {
|
|
54
|
+
const parts = Version.parse(v);
|
|
55
|
+
if (parts.length > 0) {
|
|
56
|
+
parts[parts.length - 1] += 1;
|
|
65
57
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
version[i - 1] += 1;
|
|
58
|
+
for (let i = parts.length; i > 0; i -= 1) {
|
|
59
|
+
if (parts[i] === 100) {
|
|
60
|
+
parts[i] = 0;
|
|
61
|
+
parts[i - 1] += 1;
|
|
71
62
|
}
|
|
72
63
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
64
|
+
return parts.join('.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
77
67
|
|
|
78
68
|
/**
|
|
79
69
|
* Extend logger implementation
|
|
@@ -3413,7 +3403,7 @@ const makeRevision = function (path, hash) {
|
|
|
3413
3403
|
}
|
|
3414
3404
|
|
|
3415
3405
|
if (!currentRevision.hash || currentRevision.hash !== result.hash) {
|
|
3416
|
-
result.version =
|
|
3406
|
+
result.version = Version.increment(currentRevision.version);
|
|
3417
3407
|
result.timeUpdated = new Date().getTime();
|
|
3418
3408
|
}
|
|
3419
3409
|
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for the public API of @adguard/filters-compiler.
|
|
3
|
+
*
|
|
4
|
+
* These declarations provide TypeScript consumers with typed signatures for
|
|
5
|
+
* the three exported functions. They are hand-written because the entry point
|
|
6
|
+
* (src/index.js) is JavaScript and is not processed by the TypeScript compiler.
|
|
7
|
+
*
|
|
8
|
+
* When src/index.js is eventually migrated to TypeScript, this file should be
|
|
9
|
+
* removed — the compiler will generate declarations automatically.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Platform configuration for a single platform.
|
|
14
|
+
*/
|
|
15
|
+
export interface PlatformConfig {
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Custom platform configurations keyed by platform name.
|
|
21
|
+
*/
|
|
22
|
+
export type CustomPlatformsConfig = Record<string, PlatformConfig>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Compiles filter lists for all platforms.
|
|
26
|
+
*
|
|
27
|
+
* @param path Path to the filter lists directory.
|
|
28
|
+
* @param logPath Path for the compilation log file (logging disabled if omitted).
|
|
29
|
+
* @param reportFile Path for the compilation report file.
|
|
30
|
+
* @param platformsPath Path for platform-specific output.
|
|
31
|
+
* @param whitelist Whitelisted filter IDs.
|
|
32
|
+
* @param blacklist Blacklisted filter IDs.
|
|
33
|
+
* @param customPlatformsConfig Optional custom platform configurations.
|
|
34
|
+
*/
|
|
35
|
+
export function compile(
|
|
36
|
+
path: string,
|
|
37
|
+
logPath: string | undefined,
|
|
38
|
+
reportFile: string | undefined,
|
|
39
|
+
platformsPath: string,
|
|
40
|
+
whitelist: number[],
|
|
41
|
+
blacklist: number[],
|
|
42
|
+
customPlatformsConfig?: CustomPlatformsConfig,
|
|
43
|
+
): Promise<void>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Validates built filter files against JSON schemas.
|
|
47
|
+
*
|
|
48
|
+
* Validation failures are logged, not thrown — check the return value.
|
|
49
|
+
*
|
|
50
|
+
* @param platformsPath Path to the built platform output.
|
|
51
|
+
* @param requiredFiltersAmount Minimum number of filters expected.
|
|
52
|
+
* @returns `true` when all files are valid, `false` on validation failure.
|
|
53
|
+
*/
|
|
54
|
+
export function validateJSONSchema(
|
|
55
|
+
platformsPath: string,
|
|
56
|
+
requiredFiltersAmount: number,
|
|
57
|
+
): boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Result of locale validation.
|
|
61
|
+
*/
|
|
62
|
+
export interface ValidateLocalesResult {
|
|
63
|
+
/** `false` when at least one critical warning was found. */
|
|
64
|
+
ok: boolean;
|
|
65
|
+
/** Per-locale warning details. Present when warnings exist. */
|
|
66
|
+
data?: unknown[];
|
|
67
|
+
/** Formatted warnings log. Present when warnings exist. */
|
|
68
|
+
log?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Validates locale translation files.
|
|
73
|
+
*
|
|
74
|
+
* @param localesDirPath Path to the locales directory.
|
|
75
|
+
* @param requiredLocales List of required locale codes.
|
|
76
|
+
* @returns `{ ok: true }` when no problems are found; when warnings exist,
|
|
77
|
+
* the result includes `data` and `log`, and `ok` is `false` only for
|
|
78
|
+
* critical warnings.
|
|
79
|
+
* @throws Error when the locales directory is missing or empty.
|
|
80
|
+
*/
|
|
81
|
+
export function validateLocales(
|
|
82
|
+
localesDirPath: string,
|
|
83
|
+
requiredLocales: string[],
|
|
84
|
+
): ValidateLocalesResult;
|
package/dist/index.js
CHANGED
|
@@ -20,57 +20,47 @@ import { parse as parse$1 } from 'tldts';
|
|
|
20
20
|
import Ajv from 'ajv';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Version utility
|
|
23
|
+
* Version utility class.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
class Version {
|
|
26
26
|
/**
|
|
27
|
-
* Parses version from string
|
|
27
|
+
* Parses version from string.
|
|
28
28
|
*
|
|
29
|
-
* @param v
|
|
30
|
-
* @returns
|
|
29
|
+
* @param v Version string.
|
|
30
|
+
* @returns Array of numeric version parts.
|
|
31
31
|
*/
|
|
32
|
-
parse(v) {
|
|
33
|
-
const
|
|
34
|
-
const parts = String(v || '').split('.');
|
|
35
|
-
|
|
32
|
+
static parse(v) {
|
|
33
|
+
const parts = String(v ?? '').split('.');
|
|
36
34
|
const parseVersionPart = (part) => {
|
|
37
|
-
|
|
35
|
+
const n = Number(part);
|
|
36
|
+
if (Number.isNaN(n)) {
|
|
38
37
|
return 0;
|
|
39
38
|
}
|
|
40
|
-
return Math.max(
|
|
39
|
+
return Math.max(n, 0);
|
|
41
40
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
for (const part of parts) {
|
|
45
|
-
version.push(parseVersionPart(part));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return version;
|
|
49
|
-
},
|
|
50
|
-
|
|
41
|
+
return parts.map(parseVersionPart);
|
|
42
|
+
}
|
|
51
43
|
/**
|
|
52
|
-
* Increments build part of version '0.0.0.0'
|
|
44
|
+
* Increments the build (last) part of a version string `'0.0.0.0'`.
|
|
45
|
+
* Carries over when a part reaches 100.
|
|
53
46
|
*
|
|
54
|
-
* @param v
|
|
55
|
-
* @returns
|
|
47
|
+
* @param v Version string.
|
|
48
|
+
* @returns Incremented version string.
|
|
56
49
|
*/
|
|
57
|
-
increment(v) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
version[version.length - 1] = version[version.length - 1] + 1;
|
|
50
|
+
static increment(v) {
|
|
51
|
+
const parts = Version.parse(v);
|
|
52
|
+
if (parts.length > 0) {
|
|
53
|
+
parts[parts.length - 1] += 1;
|
|
62
54
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
version[i - 1] += 1;
|
|
55
|
+
for (let i = parts.length; i > 0; i -= 1) {
|
|
56
|
+
if (parts[i] === 100) {
|
|
57
|
+
parts[i] = 0;
|
|
58
|
+
parts[i - 1] += 1;
|
|
68
59
|
}
|
|
69
60
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
61
|
+
return parts.join('.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
74
64
|
|
|
75
65
|
/**
|
|
76
66
|
* Extend logger implementation
|
|
@@ -3410,7 +3400,7 @@ const makeRevision = function (path, hash) {
|
|
|
3410
3400
|
}
|
|
3411
3401
|
|
|
3412
3402
|
if (!currentRevision.hash || currentRevision.hash !== result.hash) {
|
|
3413
|
-
result.version =
|
|
3403
|
+
result.version = Version.increment(currentRevision.version);
|
|
3414
3404
|
result.timeUpdated = new Date().getTime();
|
|
3415
3405
|
}
|
|
3416
3406
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version utility class.
|
|
3
|
+
*/
|
|
4
|
+
export declare class Version {
|
|
5
|
+
/**
|
|
6
|
+
* Parses version from string.
|
|
7
|
+
*
|
|
8
|
+
* @param v Version string.
|
|
9
|
+
* @returns Array of numeric version parts.
|
|
10
|
+
*/
|
|
11
|
+
static parse(v: string | null | undefined): number[];
|
|
12
|
+
/**
|
|
13
|
+
* Increments the build (last) part of a version string `'0.0.0.0'`.
|
|
14
|
+
* Carries over when a part reaches 100.
|
|
15
|
+
*
|
|
16
|
+
* @param v Version string.
|
|
17
|
+
* @returns Incremented version string.
|
|
18
|
+
*/
|
|
19
|
+
static increment(v: string | null | undefined): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adguard/filters-compiler",
|
|
3
|
-
"version": "3.2.8",
|
|
4
3
|
"description": "AdGuard filters compiler",
|
|
5
4
|
"homepage": "http://adguard.com",
|
|
6
5
|
"type": "module",
|
|
@@ -10,48 +9,61 @@
|
|
|
10
9
|
],
|
|
11
10
|
"exports": {
|
|
12
11
|
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
13
|
"import": "./dist/index.js",
|
|
14
14
|
"require": "./dist/index.cjs"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"engines": {
|
|
18
|
-
"node": ">=22"
|
|
18
|
+
"node": ">=22",
|
|
19
|
+
"pnpm": ">=10.33.4 <11"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@adguard/agtree": "
|
|
22
|
-
"@adguard/css-tokenizer": "
|
|
23
|
-
"@adguard/ecss-tree": "
|
|
22
|
+
"@adguard/agtree": "4.1.0-beta.0",
|
|
23
|
+
"@adguard/css-tokenizer": "1.2.0",
|
|
24
|
+
"@adguard/ecss-tree": "2.0.1",
|
|
25
|
+
"@adguard/extended-css": "2.1.1",
|
|
26
|
+
"@adguard/filters-downloader": "2.4.4",
|
|
27
|
+
"@adguard/logger": "2.0.0",
|
|
28
|
+
"@adguard/scriptlets": "2.3.1",
|
|
29
|
+
"@adguard/tsurlfilter": "4.0.5",
|
|
24
30
|
"@eslint/css-tree": "3.6.6",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"@adguard/scriptlets": "^2.3.1",
|
|
29
|
-
"@adguard/tsurlfilter": "^4.0.5",
|
|
30
|
-
"ajv": "^8.17.1",
|
|
31
|
-
"child_process": ">=1.0.2",
|
|
32
|
-
"jsdom": "^21.1.1",
|
|
31
|
+
"ajv": "8.17.1",
|
|
32
|
+
"child_process": "1.0.2",
|
|
33
|
+
"jsdom": "21.1.2",
|
|
33
34
|
"md5": "2.3.0",
|
|
34
|
-
"moment": "
|
|
35
|
-
"tldts": "
|
|
36
|
-
"utf8": "
|
|
35
|
+
"moment": "2.30.1",
|
|
36
|
+
"tldts": "5.7.112",
|
|
37
|
+
"utf8": "3.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@
|
|
40
|
+
"@rollup/plugin-typescript": "12.3.0",
|
|
41
|
+
"@types/jsdom": "21.1.7",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "8.59.0",
|
|
43
|
+
"@typescript-eslint/parser": "8.59.0",
|
|
40
44
|
"eslint": "8.57.1",
|
|
41
|
-
"eslint-config-airbnb-base": "
|
|
42
|
-
"eslint-import-resolver-exports": "
|
|
43
|
-
"eslint-plugin-import": "
|
|
44
|
-
"husky": "
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
45
|
+
"eslint-config-airbnb-base": "15.0.0",
|
|
46
|
+
"eslint-import-resolver-exports": "1.0.0-beta.5",
|
|
47
|
+
"eslint-plugin-import": "2.31.0",
|
|
48
|
+
"husky": "8.0.2",
|
|
49
|
+
"markdownlint": "0.40.0",
|
|
50
|
+
"markdownlint-cli": "0.48.0",
|
|
51
|
+
"rimraf": "6.1.3",
|
|
52
|
+
"rollup": "4.39.0",
|
|
53
|
+
"rollup-plugin-copy": "3.5.0",
|
|
54
|
+
"tslib": "2.8.1",
|
|
55
|
+
"typescript": "6.0.3",
|
|
56
|
+
"vitest": "3.0.5"
|
|
48
57
|
},
|
|
58
|
+
"version": "3.2.10-beta.0",
|
|
49
59
|
"scripts": {
|
|
60
|
+
"prebuild": "rimraf dist",
|
|
50
61
|
"build": "rollup --config rollup.config.js --silent",
|
|
51
62
|
"test": "vitest",
|
|
52
|
-
"lint": "
|
|
53
|
-
"
|
|
54
|
-
"
|
|
63
|
+
"lint": "pnpm lint:code && pnpm lint:types && pnpm lint:md",
|
|
64
|
+
"lint:code": "eslint --cache .",
|
|
65
|
+
"lint:types": "tsc --noEmit",
|
|
66
|
+
"lint:md": "markdownlint .",
|
|
55
67
|
"build-schemas": "node --experimental-specifier-resolution=node tasks/build-schemas/index.js",
|
|
56
68
|
"tgz": "pnpm pack --out filters-compiler.tgz"
|
|
57
69
|
}
|
package/dist/build.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version=3.2.8
|