xml-event-parser 0.2.0 → 0.2.2
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 +86 -186
- package/dist/stream.cjs +1 -1
- package/dist/stream.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,18 +2,14 @@ xml-event-parser
|
|
|
2
2
|
================
|
|
3
3
|
|
|
4
4
|
**Stream XML without loading it.** A tiny parser that gives you a document tree
|
|
5
|
-
and path-based events in one pass
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- **
|
|
11
|
-
|
|
12
|
-
- **
|
|
13
|
-
no second traversal, no DOM.
|
|
14
|
-
- **Small and portable**: 6.4 KiB minified / 2.2 KiB gzipped, zero dependencies,
|
|
15
|
-
no `eval`, works in Node, browsers and edge runtimes (the Node adapter is a
|
|
16
|
-
separate `xml-event-parser/stream` entry).
|
|
5
|
+
and path-based events in one pass.
|
|
6
|
+
|
|
7
|
+
- **Bounded memory**: keep only the element you are reading. A 240 MB report
|
|
8
|
+
parses in 81 MiB of RSS.
|
|
9
|
+
- **Fast**: ~3.7x `sax` and ~4x `fast-xml-parser` on the same report.
|
|
10
|
+
- **Portable**: 6.4 KiB minified / 2.2 KiB gzipped, zero dependencies, no
|
|
11
|
+
`node:*` imports in the core entry, no `eval`.
|
|
12
|
+
- **One pass, two views**: a tree node and an `open`/`close` event per element.
|
|
17
13
|
|
|
18
14
|
## When to use this
|
|
19
15
|
|
|
@@ -21,15 +17,14 @@ gzipped, zero dependencies, and no `node:*` imports in the core entry.
|
|
|
21
17
|
| --- | --- |
|
|
22
18
|
| Read a file bigger than memory: CI/test reports (JUnit, SARIF, coverage), sitemaps, GPX/KML tracks, OSM extracts | **this**, `xml-event-parser/stream` |
|
|
23
19
|
| Pick elements while streaming without writing a SAX state machine | **this**, path events |
|
|
24
|
-
| Parse occasionally in a browser or Worker where a 20 KiB parser is too much | **this**, core entry
|
|
25
|
-
| Turn a small config XML into a plain object | `fast-xml-parser` or `xml2js`
|
|
20
|
+
| Parse occasionally in a browser or Worker where a 20 KiB parser is too much | **this**, core entry |
|
|
21
|
+
| Turn a small config XML into a plain object | `fast-xml-parser` or `xml2js` |
|
|
26
22
|
| DOM semantics: namespaces, XPath, mutation | `@xmldom/xmldom` |
|
|
27
|
-
|
|
|
23
|
+
| Hand-tuned callbacks with no tree at all | `sax` |
|
|
28
24
|
|
|
29
25
|
## 240 MB in one second
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
heap - a typical CI container ([reproduce it](#development)):
|
|
27
|
+
Generated JUnit reports, each parser in its own process capped at 512 MB of heap:
|
|
33
28
|
|
|
34
29
|
| parser | 60 MB report | 240 MB report |
|
|
35
30
|
| --- | --- | --- |
|
|
@@ -37,25 +32,18 @@ heap - a typical CI container ([reproduce it](#development)):
|
|
|
37
32
|
| sax | 0.96 s, 67 MiB | 3.80 s, 79 MiB |
|
|
38
33
|
| fast-xml-parser | 1.52 s, 637 MiB | **out of memory** |
|
|
39
34
|
|
|
40
|
-
The file grows 4x; the heap does not.
|
|
41
|
-
needs roughly 7-11x the file size and dies on the larger report.
|
|
35
|
+
The file grows 4x; the heap does not.
|
|
42
36
|
|
|
43
|
-
##
|
|
37
|
+
## Install
|
|
44
38
|
|
|
45
39
|
```sh
|
|
46
40
|
npm install xml-event-parser
|
|
47
41
|
```
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```js
|
|
52
|
-
import { XmlParser } from 'xml-event-parser';
|
|
53
|
-
|
|
54
|
-
const roots = new XmlParser().parse(xml);
|
|
55
|
-
// roots[0].tagName, roots[0].children, roots[0].text, attributes are flat
|
|
56
|
-
```
|
|
43
|
+
## Typical usage
|
|
57
44
|
|
|
58
|
-
Stream
|
|
45
|
+
Stream a report and act on each element. This is the case the library is built
|
|
46
|
+
for: the file can be any size, memory stays flat.
|
|
59
47
|
|
|
60
48
|
```js
|
|
61
49
|
import { createReadStream } from 'node:fs';
|
|
@@ -69,9 +57,9 @@ await pipeline(
|
|
|
69
57
|
new Writable({
|
|
70
58
|
objectMode: true,
|
|
71
59
|
write(testcase, _encoding, done) {
|
|
72
|
-
// complete
|
|
60
|
+
// testcase is complete: attributes plus <failure>/<system-out> children
|
|
73
61
|
if (testcase.children?.some((child) => child.tagName === 'failure')) {
|
|
74
|
-
console.log(testcase.name);
|
|
62
|
+
console.log(`${testcase.classname} › ${testcase.name}`);
|
|
75
63
|
}
|
|
76
64
|
done();
|
|
77
65
|
},
|
|
@@ -79,63 +67,62 @@ await pipeline(
|
|
|
79
67
|
);
|
|
80
68
|
```
|
|
81
69
|
|
|
82
|
-
|
|
70
|
+
> **The path is the full chain from the document root.** For
|
|
71
|
+
> `<testsuites><testsuite><testcase>` the event is
|
|
72
|
+
> `'</testsuites.testsuite.testcase>'`; `'</testcase>'` matches nothing.
|
|
73
|
+
> `event` also accepts the bare path (`'testsuites.testsuite.testcase'`).
|
|
74
|
+
|
|
75
|
+
Without Node streams - a Worker, Deno, Bun or a plain callback loop:
|
|
83
76
|
|
|
84
77
|
```js
|
|
85
|
-
const parser = new XmlParser({
|
|
78
|
+
const parser = new XmlParser({
|
|
79
|
+
progressive: true,
|
|
80
|
+
retain: 'none',
|
|
81
|
+
keep: ['testsuites.testsuite.testcase'],
|
|
82
|
+
});
|
|
83
|
+
|
|
86
84
|
parser.on('</testsuites.testsuite.testcase>', (testcase) => { /* ... */ });
|
|
87
|
-
|
|
85
|
+
|
|
86
|
+
for await (const chunk of stream) {
|
|
87
|
+
parser.write(chunk);
|
|
88
|
+
}
|
|
88
89
|
parser.end();
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
[`examples/sitemap.mjs`](examples/sitemap.mjs),
|
|
93
|
-
[`examples/gpx.mjs`](examples/gpx.mjs) - `node examples/junit.mjs`.
|
|
92
|
+
When the document fits in memory, skip streaming:
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
```js
|
|
95
|
+
import { XmlParser } from 'xml-event-parser';
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
tagName: string; // element name, e.g. 'way'
|
|
100
|
-
children?: XmlNode[]; // present only when the element has child elements
|
|
101
|
-
text?: string; // present only for text-only elements
|
|
102
|
-
[attribute: string]: any; // attributes, copied flat onto the node
|
|
103
|
-
}
|
|
97
|
+
const roots = new XmlParser().parse(xml);
|
|
98
|
+
console.log(roots[0].tagName, roots[0].children);
|
|
104
99
|
```
|
|
105
100
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
[`
|
|
109
|
-
`children` or `text` are shadowed by the element's own values; if that matters
|
|
110
|
-
for your vocabulary, read attributes off the source XML instead.
|
|
101
|
+
Runnable examples, one per common job: [`examples/junit.mjs`](examples/junit.mjs)
|
|
102
|
+
(test report), [`examples/sitemap.mjs`](examples/sitemap.mjs),
|
|
103
|
+
[`examples/gpx.mjs`](examples/gpx.mjs) (track length).
|
|
111
104
|
|
|
112
|
-
|
|
113
|
-
attached, so `node.children` is complete inside a close listener.
|
|
105
|
+
## API
|
|
114
106
|
|
|
115
|
-
|
|
107
|
+
### Node shape
|
|
116
108
|
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// one complete element; `way` is released after this returns
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
for await (const chunk of createReadStream('planet.osm.xml', 'utf8')) {
|
|
127
|
-
parser.write(chunk);
|
|
109
|
+
```ts
|
|
110
|
+
interface XmlNode {
|
|
111
|
+
tagName: string; // element name
|
|
112
|
+
children?: XmlNode[]; // present only when the element has child elements
|
|
113
|
+
text?: string; // present only for text-only elements
|
|
114
|
+
[attribute: string]: any; // attributes, flat on the node
|
|
128
115
|
}
|
|
129
|
-
parser.end();
|
|
130
116
|
```
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
document whole or in 1-byte chunks produces the same tree (the suite checks every
|
|
136
|
-
split point).
|
|
118
|
+
An element is emitted on close after its children are attached, so
|
|
119
|
+
`node.children` is complete inside a close listener. Attributes whose names
|
|
120
|
+
collide with `tagName`, `children` or `text` are shadowed by those fields.
|
|
137
121
|
|
|
138
|
-
|
|
122
|
+
### Streaming and retention
|
|
123
|
+
|
|
124
|
+
`write(chunk)` accepts a document in pieces; chunks may split anywhere, and
|
|
125
|
+
`end()` closes whatever is still open and returns the roots.
|
|
139
126
|
|
|
140
127
|
| `retain` | keeps | `end()` returns | memory |
|
|
141
128
|
| --- | --- | --- | --- |
|
|
@@ -143,159 +130,72 @@ split point).
|
|
|
143
130
|
| `'root'` | the root being built | `[]`; a finished root is emitted and dropped | largest root |
|
|
144
131
|
| `'none'` | nothing | `[]`; every element is emitted and dropped | nesting depth |
|
|
145
132
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
327k elements. Without listeners, `retain: 'none'` still parses - it just throws
|
|
149
|
-
the result away.
|
|
150
|
-
|
|
151
|
-
Under `retain: 'none'`, `keep` restores the subtree of the elements you actually
|
|
152
|
-
want, so a streamed element is complete rather than a bare tag:
|
|
133
|
+
With `retain: 'none'`, `keep` restores the subtree of the elements you want, so
|
|
134
|
+
a streamed element arrives complete rather than as a bare tag:
|
|
153
135
|
|
|
154
136
|
```js
|
|
155
137
|
new XmlParser({
|
|
156
138
|
progressive: true,
|
|
157
139
|
retain: 'none',
|
|
158
|
-
keep: ['testsuites.testsuite.testcase'],
|
|
140
|
+
keep: ['testsuites.testsuite.testcase'],
|
|
159
141
|
});
|
|
160
142
|
```
|
|
161
143
|
|
|
162
|
-
|
|
163
|
-
sets this up for you from its `event` path.
|
|
144
|
+
`createStream` applies `keep` for you from its `event` path.
|
|
164
145
|
|
|
165
|
-
|
|
146
|
+
### Events
|
|
166
147
|
|
|
167
148
|
| form | fires |
|
|
168
149
|
| --- | --- |
|
|
169
150
|
| `'<osm.way>'` | when a `<way>` inside `<osm>` opens |
|
|
170
151
|
| `'</osm.way>'` | when it closes, with `children` populated |
|
|
171
152
|
|
|
172
|
-
The path is the dotted chain
|
|
173
|
-
|
|
174
|
-
|
|
153
|
+
The path is the dotted chain from the document root, not just the element name:
|
|
154
|
+
`'</osm.way>'`, never `'</way>'`. The same applies to `keep`. Filter inside the
|
|
155
|
+
listener:
|
|
175
156
|
|
|
176
157
|
```js
|
|
177
158
|
parser.on('</osm.way>', (way) => {
|
|
178
|
-
if (!way.tags) return;
|
|
159
|
+
if (!way.tags) return;
|
|
179
160
|
});
|
|
180
161
|
```
|
|
181
162
|
|
|
182
|
-
|
|
163
|
+
### Options
|
|
183
164
|
|
|
184
165
|
| option | default | meaning |
|
|
185
166
|
| --- | --- | --- |
|
|
186
|
-
| `progressive` | `false` | emit events
|
|
187
|
-
| `queryParent` | `false` | track parents
|
|
188
|
-
| `retain` | `'all'` |
|
|
189
|
-
| `keep` | `[]` | under `retain: 'none'`,
|
|
167
|
+
| `progressive` | `false` | emit events; without it `parse()` only builds the tree |
|
|
168
|
+
| `queryParent` | `false` | track parents for `parser.getParent(node)` |
|
|
169
|
+
| `retain` | `'all'` | `'all'`, `'root'` or `'none'` (see [Streaming and retention](#streaming-and-retention)) |
|
|
170
|
+
| `keep` | `[]` | under `retain: 'none'`, paths whose elements keep their subtree |
|
|
190
171
|
|
|
191
|
-
`parse(xml, parent?, dir?)`
|
|
192
|
-
|
|
172
|
+
`parse(xml, parent?, dir?)` can attach the parsed roots to an existing node and
|
|
173
|
+
prefix event paths.
|
|
193
174
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
`text` is `'text'`).
|
|
199
|
-
|
|
200
|
-
CDATA sections are content, not markup: their text is kept verbatim and is not
|
|
201
|
-
entity-decoded, while text outside them is decoded (the five predefined
|
|
202
|
-
entities and numeric character references).
|
|
175
|
+
Malformed input never throws: comments, processing instructions and doctypes
|
|
176
|
+
are skipped, and elements still open at end of input are closed, so a truncated
|
|
177
|
+
download yields the document parsed so far. CDATA content is kept verbatim and
|
|
178
|
+
not entity-decoded; text outside CDATA is.
|
|
203
179
|
|
|
204
180
|
## Benchmarks
|
|
205
181
|
|
|
206
|
-
|
|
207
|
-
nesting)
|
|
208
|
-
[`bench/RESULTS.md`](bench/RESULTS.md); rerun with `npm run bench:data && npm run bench`.
|
|
209
|
-
|
|
210
|
-
Realistic Overpass-style document, 6.0 MiB, Apple M4 Pro / Node 26:
|
|
182
|
+
Speed on six generated shapes (Overpass-style documents, children-heavy, text,
|
|
183
|
+
nesting), against `txml`, `fast-xml-parser`, `sax` and `htmlparser2`:
|
|
211
184
|
|
|
212
185
|
| workload | xml-event-parser | txml | fast-xml-parser | sax | htmlparser2 |
|
|
213
186
|
| --- | --- | --- | --- | --- | --- |
|
|
214
187
|
| tree (parse + walk) | **26.0 ms, 230 MB/s** | 50.6 ms, 118 MB/s | 167.8 ms, 36 MB/s | — | — |
|
|
215
|
-
| tree, retained heap | **30.0 MiB** | 42.5 MiB | 35.2 MiB | — | — |
|
|
216
188
|
| element callbacks | **27.8 ms, 215 MB/s** | — | — | 100.0 ms, 60 MB/s | 44.9 ms, 133 MB/s |
|
|
217
189
|
| streamed, 64 KiB chunks | **27.3 ms, 219 MB/s** | 77.4 ms, 77 MB/s | — | 103.3 ms, 58 MB/s | 50.8 ms, 118 MB/s |
|
|
218
190
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
- The callback and streamed rows for `xml-event-parser` use `retain: 'none'`, so
|
|
222
|
-
they do not build a document either; the tree row is the only one that holds
|
|
223
|
-
memory. `txml`'s streaming API is a Node stream (`transformStream`), measured
|
|
224
|
-
separately and asynchronously.
|
|
225
|
-
- Text-heavy documents with many entities and CDATA used to be the weak shape;
|
|
226
|
-
replacing the regex decoder with a manual scan took it from 325 to 442 MB/s,
|
|
227
|
-
ahead of `txml` (382 MB/s).
|
|
228
|
-
|
|
229
|
-
## Status
|
|
230
|
-
|
|
231
|
-
Extracted from [osm2geojson-lite](https://github.com/tibetty/osm2geojson-lite),
|
|
232
|
-
where this parser served until 2.2.0 and was then replaced by a purpose-built
|
|
233
|
-
OSM scanner. The code and its original unit tests are unchanged apart from the
|
|
234
|
-
public naming (`children`/`tagName`/`text` instead of `$innerNodes`/`$tag`/
|
|
235
|
-
`$innerText`) and the removal of the `new Function`-based conditioned-path
|
|
236
|
-
events.
|
|
237
|
-
|
|
238
|
-
Published as `xml-event-parser` (current version on npm). Releases are cut by
|
|
239
|
-
changing `version` on `main`: `release.yml` publishes through npm trusted
|
|
240
|
-
publishing (OIDC, with provenance), tags `v<version>` and creates the GitHub
|
|
241
|
-
release. The job runs only when the repository variable
|
|
242
|
-
`NPM_TRUSTED_PUBLISHER` is `true`.
|
|
243
|
-
|
|
244
|
-
## Development
|
|
245
|
-
|
|
246
|
-
```sh
|
|
247
|
-
npm ci
|
|
248
|
-
npm test # unit tests
|
|
249
|
-
npm run typecheck
|
|
250
|
-
npm run build # dist/index.mjs, dist/index.cjs, dist/index.d.ts
|
|
251
|
-
npm run bench:data # generate ~27 MiB benchmark corpus (gitignored)
|
|
252
|
-
npm run bench:memory # JUnit memory/time table under a 512 MB heap cap
|
|
253
|
-
npm run bench # compare against txml / sax / htmlparser2 / fast-xml-parser
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Releasing
|
|
257
|
-
|
|
258
|
-
`release.yml` publishes with npm trusted publishing (OIDC) and is gated on the
|
|
259
|
-
repository variable `NPM_TRUSTED_PUBLISHER`, which stays unset until a trusted
|
|
260
|
-
publisher exists.
|
|
261
|
-
|
|
262
|
-
One-time bootstrap, because npm cannot attach a trusted publisher to a package
|
|
263
|
-
that does not exist yet:
|
|
264
|
-
|
|
265
|
-
1. Publish the first version locally:
|
|
266
|
-
|
|
267
|
-
```sh
|
|
268
|
-
npm login
|
|
269
|
-
npm publish --access public
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
2. npmjs.com -> Packages -> `xml-event-parser` -> Settings -> **Trusted
|
|
273
|
-
publishing** -> GitHub Actions:
|
|
274
|
-
|
|
275
|
-
| field | value |
|
|
276
|
-
| --- | --- |
|
|
277
|
-
| Organization or user | `tibetty` |
|
|
278
|
-
| Repository | `xml-event-parser` |
|
|
279
|
-
| Workflow filename | `release.yml` (filename only, case-sensitive) |
|
|
280
|
-
| Environment name | leave empty |
|
|
281
|
-
| Allowed actions | tick **npm publish** |
|
|
282
|
-
|
|
283
|
-
Configurations created after September 2026 default to `npm stage publish`
|
|
284
|
-
only, so `npm publish` has to be ticked explicitly. The first publish through
|
|
285
|
-
that workflow must complete within **two days**, or the configuration expires.
|
|
286
|
-
|
|
287
|
-
3. GitHub -> Settings -> Secrets and variables -> Actions -> Variables: add
|
|
288
|
-
`NPM_TRUSTED_PUBLISHER` = `true`.
|
|
191
|
+
Full tables, methodology and caveats: [`bench/RESULTS.md`](bench/RESULTS.md).
|
|
289
192
|
|
|
290
|
-
|
|
291
|
-
package Settings -> Publishing access -> *Require two-factor authentication
|
|
292
|
-
and disallow tokens*.
|
|
193
|
+
## Contributing
|
|
293
194
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
provenance automatically only for a public repository; from a private one the
|
|
297
|
-
package is published without an attestation.
|
|
195
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development commands, tests,
|
|
196
|
+
benchmarks and the release process.
|
|
298
197
|
|
|
299
198
|
## License
|
|
300
199
|
|
|
301
|
-
MIT. Includes work contributed to
|
|
200
|
+
MIT. Includes work contributed to
|
|
201
|
+
[osm2geojson-lite](https://github.com/tibetty/osm2geojson-lite) by Harel Mazor.
|
package/dist/stream.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:stream"),t=require("node:string_decoder");function n(e){switch(e){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`}if(e.charCodeAt(0)===35){let t=e.charCodeAt(1)===120||e.charCodeAt(1)===88?parseInt(e.slice(2),16):parseInt(e.slice(1),10);if(Number.isFinite(t)&&t>=0&&t<=1114111)return String.fromCodePoint(t)}return null}function r(e){let t=e.indexOf(`&`);if(t<0)return e;let r=e.slice(0,t);for(;t<e.length;){let i=e.indexOf(`;`,t+1);if(i<0){r+=e.slice(t);break}let a=n(e.slice(t+1,i));if(r+=a===null?e.slice(t,i+1):a,t=e.indexOf(`&`,i+1),t<0){r+=e.slice(i+1);break}r+=e.slice(i+1,t)}return r}function i(e){if(e.indexOf(`<![CDATA[`)<0)return e.indexOf(`&`)<0?e:r(e);let t=``,n=0;for(;n<e.length;){let i=e.indexOf(`<![CDATA[`,n);if(i<0){t+=r(e.slice(n));break}i>n&&(t+=r(e.slice(n,i)));let a=e.indexOf(`]]>`,i+9);if(a<0){t+=e.slice(i+9);break}t+=e.slice(i+9,a),n=a+3}return t}function a(e){let t=0,n=e.length;return e.charCodeAt(0)===60&&(t=e.charCodeAt(1)===47?2:1),e.charCodeAt(n-1)===62&&n--,e.slice(t,n)}function o(e){return e===32||e===9||e===10||e===13}var s=class{constructor(e){if(this.queryParent=!1,this.progressive=!1,this.retain=`all`,this.keepPaths=/* @__PURE__ */ new Set,this.parentMap=/* @__PURE__ */ new WeakMap,this.evtListeners={},this.openListenerCount=0,this.watchedPaths=/* @__PURE__ */ new Set,this.watchedChildren=/* @__PURE__ */ new Map,this.watchedTopLevel=/* @__PURE__ */ new Set,this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=``,this.active=!1,e&&(this.queryParent=e.queryParent===!0,this.progressive=e.progressive===!0,e.retain&&(this.retain=e.retain),e.keep))for(let t of e.keep)this.keepPaths.add(a(t))}write(e){return this.active||this.begin(void 0,void 0),e.length===0||(this.buffer.length===0?this.buffer=e:this.buffer+=e,this.consume(!1)),this}end(){if(!this.active)return[];this.consume(!0),this.finish();let e=this.roots;return this.reset(),e}parse(e,t,n){return this.begin(t,n),this.write(e),this.end()}begin(e,t){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=t||``,this.top=e?{node:e,fullTag:this.basePath,textStart:0}:void 0,this.rootOwner=this.top,this.parentMap=/* @__PURE__ */ new WeakMap,this.active=!0}reset(){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.top=void 0,this.rootOwner=void 0,this.basePath=``,this.active=!1}attach(e,t,n){if(this.retain===`none`&&!n)return;if(t===void 0){this.retain===`all`&&this.roots.push(e);return}let r=t.children;r?r.push(e):t.children=[e]}consume(e){let t=this.buffer,n=t.length,r=this.progressive,a=r&&this.openListenerCount>0,o=this.cursor,s=-1;for(;o<n;){let c=t.indexOf(`<`,o);if(c<0||(s=c,o=c+1,o>=n))break;let l=t.charCodeAt(o);if(l===47){let a=t.indexOf(`>`,o);if(a<0){if(!e)break;o=n;break}let l=this.stack.pop();if(o=a+1,s=-1,!l)continue;let u=l.node,d=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,f=d?d.node:void 0;!l.hasChild&&c>l.textStart&&(u.text=i(t.slice(l.textStart,c))),r&&this.watchedPaths.has(l.fullTag)&&this.emit(`</`+l.fullTag+`>`,u,f),this.attach(u,f,d?d.keep===!0:!1),d&&(d.hasChild=!0),this.top=d;continue}if(l===63){let r=t.indexOf(`>`,o);if(r<0){if(!e)break;o=n;break}o=r+1,s=-1;continue}if(l===33){let r;if(t.charCodeAt(o+1)===45&&t.charCodeAt(o+2)===45?(r=t.indexOf(`-->`,o+3),r=r<0?-1:r+3):t.startsWith(`![CDATA[`,o)?(r=t.indexOf(`]]>`,o+9),r=r<0?-1:r+3):(r=t.indexOf(`>`,o),r=r<0?-1:r+1),r<0){if(!e)break;o=n;break}o=r,s=-1;continue}let u=this.parseOpenTag(t,o,n,e);if(u===null)break;o=u.end,s=-1;let d=u.node,f=u.tag,p=this.top?this.top.node:void 0;if(this.queryParent&&p&&this.parentMap.set(d,p),u.selfClose){if(r){let e=this.top?this.top.fullTag:this.basePath,t=e?this.watchedChildren.get(e):this.watchedTopLevel;if(t&&t.has(f)){let t=e?e+`.`+f:f;a&&this.emit(`<`+t+`>`,d,p),this.emit(`</`+t+`>`,d,p)}}this.attach(d,p,this.top?this.top.keep===!0:!1),this.top&&(this.top.hasChild=!0);continue}let m=this.top?this.top.fullTag?this.top.fullTag+`.`+f:f:this.basePath?this.basePath+`.`+f:f;a&&this.watchedPaths.has(m)&&this.emit(`<`+m+`>`,d,p);let h=this.top!==void 0&&this.top.keep===!0||this.keepPaths.has(m),g={node:d,fullTag:m,textStart:o,keep:h};this.stack.push(g),this.top=g}this.cursor=e?n:s>=0?s:o,e||this.compact()}parseOpenTag(e,t,n,i){let a=t;for(;a<n;){let t=e.charCodeAt(a);if(o(t)||t===47||t===62)break;a++}if(a>=n&&!i)return null;let s=e.slice(t,a),c={tagName:s},l=!1;for(;a<n;){let t=e.charCodeAt(a);for(;a<n&&o(t);)t=e.charCodeAt(++a);if(a>=n)break;if(t===62)return a++,{node:c,tag:s,selfClose:l,end:a};if(t===47){l=!0,a++;continue}let u=a;for(;a<n&&(t=e.charCodeAt(a),!(t===61||o(t)||t===62||t===47));)a++;if(a>=n&&!i)return null;let d=e.slice(u,a);for(;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;if(e.charCodeAt(a)===61){for(a++;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;let t=e.charCodeAt(a);if(t===34||t===39){a++;let o=e.indexOf(t===34?`"`:`'`,a);if(o<0){if(!i)return null;o=n}let s=e.slice(a,o);c[d]=s.indexOf(`&`)<0?s:r(s),a=o+1}}else d&&(c[d]=``)}return i?{node:c,tag:s,selfClose:l,end:a}:null}finish(){let e=this.buffer,t=e.length;for(;this.stack.length>0;){let n=this.stack.pop(),r=n.node;!n.hasChild&&t>n.textStart&&(r.text=i(e.slice(n.textStart,t)),t=n.textStart);let a=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,o=a?a.node:void 0;this.attach(r,o,a?a.keep===!0:!1)}}compact(){let e=this.cursor;for(let t=this.stack.length-1;t>=0;t--){let n=this.stack[t];if(!n.hasChild){e=n.textStart;break}}if(!(e<=0)){this.buffer=this.buffer.slice(e),this.cursor-=e;for(let t=0;t<this.stack.length;t++){let n=this.stack[t];n.textStart=n.textStart>e?n.textStart-e:0}this.rootOwner&&(this.rootOwner.textStart=0)}}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){this.$addListener(e,t)}removeListener(e,t){this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){let n=this.evtListeners[e];if(n?n.push(t):this.evtListeners[e]=[t],e.charCodeAt(1)!==47&&this.openListenerCount++,e.charCodeAt(0)===60){let t=e.slice(e.charCodeAt(1)===47?2:1,e.length-1);this.watchedPaths.add(t);let n=t.lastIndexOf(`.`);if(n<0)this.watchedTopLevel.add(t);else{let e=t.slice(0,n),r=this.watchedChildren.get(e);r||(r=/* @__PURE__ */ new Set,this.watchedChildren.set(e,r)),r.add(t.slice(n+1))}}}$removeListener(e,t){let n=this.evtListeners[e],r=-1;n&&(r=n.indexOf(t)),r>=0&&(n.splice(r,1),e.charCodeAt(1)!==47&&this.openListenerCount--)}emit(e,t,n){let r=this.evtListeners[e];if(r)for(let e=0;e<r.length;e++)r[e](t,n)}};function c(e){if(typeof e!=`string`||e.length===0)throw TypeError(`createStream() requires { event }, e.g. { event: "</root.item>" }`);return e}function l(n){let r=c(n&&n.event),i=new s({...n,progressive:!0,retain:`none`,keep:[r]}),a=new t.StringDecoder(`utf8`),o=new e.Transform({readableObjectMode:!0,transform(e,t,n){try{i.write(typeof e==`string`?e:a.write(e)),n()}catch(e){n(e)}},flush(e){try{let t=a.end();t.length>0&&i.write(t),i.end(),e()}catch(t){e(t)}}});return i.on(r,e=>{o.push(e)}),o}exports.createStream=l;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("node:stream"),t=require("node:string_decoder");function n(e){switch(e){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`}if(e.charCodeAt(0)===35){let t=e.charCodeAt(1)===120||e.charCodeAt(1)===88?parseInt(e.slice(2),16):parseInt(e.slice(1),10);if(Number.isFinite(t)&&t>=0&&t<=1114111)return String.fromCodePoint(t)}return null}function r(e){let t=e.indexOf(`&`);if(t<0)return e;let r=e.slice(0,t);for(;t<e.length;){let i=e.indexOf(`;`,t+1);if(i<0){r+=e.slice(t);break}let a=n(e.slice(t+1,i));if(r+=a===null?e.slice(t,i+1):a,t=e.indexOf(`&`,i+1),t<0){r+=e.slice(i+1);break}r+=e.slice(i+1,t)}return r}function i(e){if(e.indexOf(`<![CDATA[`)<0)return e.indexOf(`&`)<0?e:r(e);let t=``,n=0;for(;n<e.length;){let i=e.indexOf(`<![CDATA[`,n);if(i<0){t+=r(e.slice(n));break}i>n&&(t+=r(e.slice(n,i)));let a=e.indexOf(`]]>`,i+9);if(a<0){t+=e.slice(i+9);break}t+=e.slice(i+9,a),n=a+3}return t}function a(e){let t=0,n=e.length;return e.charCodeAt(0)===60&&(t=e.charCodeAt(1)===47?2:1),e.charCodeAt(n-1)===62&&n--,e.slice(t,n)}function o(e){return e===32||e===9||e===10||e===13}var s=class{constructor(e){if(this.queryParent=!1,this.progressive=!1,this.retain=`all`,this.keepPaths=/* @__PURE__ */ new Set,this.parentMap=/* @__PURE__ */ new WeakMap,this.evtListeners={},this.openListenerCount=0,this.watchedPaths=/* @__PURE__ */ new Set,this.watchedChildren=/* @__PURE__ */ new Map,this.watchedTopLevel=/* @__PURE__ */ new Set,this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=``,this.active=!1,e&&(this.queryParent=e.queryParent===!0,this.progressive=e.progressive===!0,e.retain&&(this.retain=e.retain),e.keep))for(let t of e.keep)this.keepPaths.add(a(t))}write(e){return this.active||this.begin(void 0,void 0),e.length===0||(this.buffer.length===0?this.buffer=e:this.buffer+=e,this.consume(!1)),this}end(){if(!this.active)return[];this.consume(!0),this.finish();let e=this.roots;return this.reset(),e}parse(e,t,n){return this.begin(t,n),this.write(e),this.end()}begin(e,t){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=t||``,this.top=e?{node:e,fullTag:this.basePath,textStart:0}:void 0,this.rootOwner=this.top,this.parentMap=/* @__PURE__ */ new WeakMap,this.active=!0}reset(){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.top=void 0,this.rootOwner=void 0,this.basePath=``,this.active=!1}attach(e,t,n){if(this.retain===`none`&&!n)return;if(t===void 0){this.retain===`all`&&this.roots.push(e);return}let r=t.children;r?r.push(e):t.children=[e]}consume(e){let t=this.buffer,n=t.length,r=this.progressive,a=r&&this.openListenerCount>0,o=this.cursor,s=-1;for(;o<n;){let c=t.indexOf(`<`,o);if(c<0||(s=c,o=c+1,o>=n))break;let l=t.charCodeAt(o);if(l===47){let a=t.indexOf(`>`,o);if(a<0){if(!e)break;o=n;break}let l=this.stack.pop();if(o=a+1,s=-1,!l)continue;let u=l.node,d=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,f=d?d.node:void 0;!l.hasChild&&c>l.textStart&&(u.text=i(t.slice(l.textStart,c))),r&&this.watchedPaths.has(l.fullTag)&&this.emit(`</`+l.fullTag+`>`,u,f),this.attach(u,f,d?d.keep===!0:!1),d&&(d.hasChild=!0),this.top=d;continue}if(l===63){let r=t.indexOf(`>`,o);if(r<0){if(!e)break;o=n;break}o=r+1,s=-1;continue}if(l===33){let r;if(t.charCodeAt(o+1)===45&&t.charCodeAt(o+2)===45?(r=t.indexOf(`-->`,o+3),r=r<0?-1:r+3):t.startsWith(`![CDATA[`,o)?(r=t.indexOf(`]]>`,o+9),r=r<0?-1:r+3):(r=t.indexOf(`>`,o),r=r<0?-1:r+1),r<0){if(!e)break;o=n;break}o=r,s=-1;continue}let u=this.parseOpenTag(t,o,n,e);if(u===null)break;o=u.end,s=-1;let d=u.node,f=u.tag,p=this.top?this.top.node:void 0;if(this.queryParent&&p&&this.parentMap.set(d,p),u.selfClose){if(r){let e=this.top?this.top.fullTag:this.basePath,t=e?this.watchedChildren.get(e):this.watchedTopLevel;if(t&&t.has(f)){let t=e?e+`.`+f:f;a&&this.emit(`<`+t+`>`,d,p),this.emit(`</`+t+`>`,d,p)}}this.attach(d,p,this.top?this.top.keep===!0:!1),this.top&&(this.top.hasChild=!0);continue}let m=this.top?this.top.fullTag?this.top.fullTag+`.`+f:f:this.basePath?this.basePath+`.`+f:f;a&&this.watchedPaths.has(m)&&this.emit(`<`+m+`>`,d,p);let h=this.top!==void 0&&this.top.keep===!0||this.keepPaths.has(m),g={node:d,fullTag:m,textStart:o,keep:h};this.stack.push(g),this.top=g}this.cursor=e?n:s>=0?s:o,e||this.compact()}parseOpenTag(e,t,n,i){let a=t;for(;a<n;){let t=e.charCodeAt(a);if(o(t)||t===47||t===62)break;a++}if(a>=n&&!i)return null;let s=e.slice(t,a),c={tagName:s},l=!1;for(;a<n;){let t=e.charCodeAt(a);for(;a<n&&o(t);)t=e.charCodeAt(++a);if(a>=n)break;if(t===62)return a++,{node:c,tag:s,selfClose:l,end:a};if(t===47){l=!0,a++;continue}let u=a;for(;a<n&&(t=e.charCodeAt(a),!(t===61||o(t)||t===62||t===47));)a++;if(a>=n&&!i)return null;let d=e.slice(u,a);for(;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;if(e.charCodeAt(a)===61){for(a++;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;let t=e.charCodeAt(a);if(t===34||t===39){a++;let o=e.indexOf(t===34?`"`:`'`,a);if(o<0){if(!i)return null;o=n}let s=e.slice(a,o);c[d]=s.indexOf(`&`)<0?s:r(s),a=o+1}}else d&&(c[d]=``)}return i?{node:c,tag:s,selfClose:l,end:a}:null}finish(){let e=this.buffer,t=e.length;for(;this.stack.length>0;){let n=this.stack.pop(),r=n.node;!n.hasChild&&t>n.textStart&&(r.text=i(e.slice(n.textStart,t)),t=n.textStart);let a=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,o=a?a.node:void 0;this.attach(r,o,a?a.keep===!0:!1)}}compact(){let e=this.cursor;for(let t=this.stack.length-1;t>=0;t--){let n=this.stack[t];if(!n.hasChild){e=n.textStart;break}}if(!(e<=0)){this.buffer=this.buffer.slice(e),this.cursor-=e;for(let t=0;t<this.stack.length;t++){let n=this.stack[t];n.textStart=n.textStart>e?n.textStart-e:0}this.rootOwner&&(this.rootOwner.textStart=0)}}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){this.$addListener(e,t)}removeListener(e,t){this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){let n=this.evtListeners[e];if(n?n.push(t):this.evtListeners[e]=[t],e.charCodeAt(1)!==47&&this.openListenerCount++,e.charCodeAt(0)===60){let t=e.slice(e.charCodeAt(1)===47?2:1,e.length-1);this.watchedPaths.add(t);let n=t.lastIndexOf(`.`);if(n<0)this.watchedTopLevel.add(t);else{let e=t.slice(0,n),r=this.watchedChildren.get(e);r||(r=/* @__PURE__ */ new Set,this.watchedChildren.set(e,r)),r.add(t.slice(n+1))}}}$removeListener(e,t){let n=this.evtListeners[e],r=-1;n&&(r=n.indexOf(t)),r>=0&&(n.splice(r,1),e.charCodeAt(1)!==47&&this.openListenerCount--)}emit(e,t,n){let r=this.evtListeners[e];if(r)for(let e=0;e<r.length;e++)r[e](t,n)}};function c(e){if(typeof e!=`string`||e.length===0)throw TypeError(`createStream() requires { event }, e.g. { event: "</root.item>" }`);return e.charCodeAt(0)===60?e:`</`+e+`>`}function l(n){let r=c(n&&n.event),i=new s({...n,progressive:!0,retain:`none`,keep:[r]}),a=new t.StringDecoder(`utf8`),o=new e.Transform({readableObjectMode:!0,transform(e,t,n){try{i.write(typeof e==`string`?e:a.write(e)),n()}catch(e){n(e)}},flush(e){try{let t=a.end();t.length>0&&i.write(t),i.end(),e()}catch(t){e(t)}}});return i.on(r,e=>{o.push(e)}),o}exports.createStream=l;
|
package/dist/stream.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Transform as e}from"node:stream";import{StringDecoder as t}from"node:string_decoder";function n(e){switch(e){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`}if(e.charCodeAt(0)===35){let t=e.charCodeAt(1)===120||e.charCodeAt(1)===88?parseInt(e.slice(2),16):parseInt(e.slice(1),10);if(Number.isFinite(t)&&t>=0&&t<=1114111)return String.fromCodePoint(t)}return null}function r(e){let t=e.indexOf(`&`);if(t<0)return e;let r=e.slice(0,t);for(;t<e.length;){let i=e.indexOf(`;`,t+1);if(i<0){r+=e.slice(t);break}let a=n(e.slice(t+1,i));if(r+=a===null?e.slice(t,i+1):a,t=e.indexOf(`&`,i+1),t<0){r+=e.slice(i+1);break}r+=e.slice(i+1,t)}return r}function i(e){if(e.indexOf(`<![CDATA[`)<0)return e.indexOf(`&`)<0?e:r(e);let t=``,n=0;for(;n<e.length;){let i=e.indexOf(`<![CDATA[`,n);if(i<0){t+=r(e.slice(n));break}i>n&&(t+=r(e.slice(n,i)));let a=e.indexOf(`]]>`,i+9);if(a<0){t+=e.slice(i+9);break}t+=e.slice(i+9,a),n=a+3}return t}function a(e){let t=0,n=e.length;return e.charCodeAt(0)===60&&(t=e.charCodeAt(1)===47?2:1),e.charCodeAt(n-1)===62&&n--,e.slice(t,n)}function o(e){return e===32||e===9||e===10||e===13}var s=class{constructor(e){if(this.queryParent=!1,this.progressive=!1,this.retain=`all`,this.keepPaths=/* @__PURE__ */ new Set,this.parentMap=/* @__PURE__ */ new WeakMap,this.evtListeners={},this.openListenerCount=0,this.watchedPaths=/* @__PURE__ */ new Set,this.watchedChildren=/* @__PURE__ */ new Map,this.watchedTopLevel=/* @__PURE__ */ new Set,this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=``,this.active=!1,e&&(this.queryParent=e.queryParent===!0,this.progressive=e.progressive===!0,e.retain&&(this.retain=e.retain),e.keep))for(let t of e.keep)this.keepPaths.add(a(t))}write(e){return this.active||this.begin(void 0,void 0),e.length===0||(this.buffer.length===0?this.buffer=e:this.buffer+=e,this.consume(!1)),this}end(){if(!this.active)return[];this.consume(!0),this.finish();let e=this.roots;return this.reset(),e}parse(e,t,n){return this.begin(t,n),this.write(e),this.end()}begin(e,t){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=t||``,this.top=e?{node:e,fullTag:this.basePath,textStart:0}:void 0,this.rootOwner=this.top,this.parentMap=/* @__PURE__ */ new WeakMap,this.active=!0}reset(){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.top=void 0,this.rootOwner=void 0,this.basePath=``,this.active=!1}attach(e,t,n){if(this.retain===`none`&&!n)return;if(t===void 0){this.retain===`all`&&this.roots.push(e);return}let r=t.children;r?r.push(e):t.children=[e]}consume(e){let t=this.buffer,n=t.length,r=this.progressive,a=r&&this.openListenerCount>0,o=this.cursor,s=-1;for(;o<n;){let c=t.indexOf(`<`,o);if(c<0||(s=c,o=c+1,o>=n))break;let l=t.charCodeAt(o);if(l===47){let a=t.indexOf(`>`,o);if(a<0){if(!e)break;o=n;break}let l=this.stack.pop();if(o=a+1,s=-1,!l)continue;let u=l.node,d=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,f=d?d.node:void 0;!l.hasChild&&c>l.textStart&&(u.text=i(t.slice(l.textStart,c))),r&&this.watchedPaths.has(l.fullTag)&&this.emit(`</`+l.fullTag+`>`,u,f),this.attach(u,f,d?d.keep===!0:!1),d&&(d.hasChild=!0),this.top=d;continue}if(l===63){let r=t.indexOf(`>`,o);if(r<0){if(!e)break;o=n;break}o=r+1,s=-1;continue}if(l===33){let r;if(t.charCodeAt(o+1)===45&&t.charCodeAt(o+2)===45?(r=t.indexOf(`-->`,o+3),r=r<0?-1:r+3):t.startsWith(`![CDATA[`,o)?(r=t.indexOf(`]]>`,o+9),r=r<0?-1:r+3):(r=t.indexOf(`>`,o),r=r<0?-1:r+1),r<0){if(!e)break;o=n;break}o=r,s=-1;continue}let u=this.parseOpenTag(t,o,n,e);if(u===null)break;o=u.end,s=-1;let d=u.node,f=u.tag,p=this.top?this.top.node:void 0;if(this.queryParent&&p&&this.parentMap.set(d,p),u.selfClose){if(r){let e=this.top?this.top.fullTag:this.basePath,t=e?this.watchedChildren.get(e):this.watchedTopLevel;if(t&&t.has(f)){let t=e?e+`.`+f:f;a&&this.emit(`<`+t+`>`,d,p),this.emit(`</`+t+`>`,d,p)}}this.attach(d,p,this.top?this.top.keep===!0:!1),this.top&&(this.top.hasChild=!0);continue}let m=this.top?this.top.fullTag?this.top.fullTag+`.`+f:f:this.basePath?this.basePath+`.`+f:f;a&&this.watchedPaths.has(m)&&this.emit(`<`+m+`>`,d,p);let h=this.top!==void 0&&this.top.keep===!0||this.keepPaths.has(m),g={node:d,fullTag:m,textStart:o,keep:h};this.stack.push(g),this.top=g}this.cursor=e?n:s>=0?s:o,e||this.compact()}parseOpenTag(e,t,n,i){let a=t;for(;a<n;){let t=e.charCodeAt(a);if(o(t)||t===47||t===62)break;a++}if(a>=n&&!i)return null;let s=e.slice(t,a),c={tagName:s},l=!1;for(;a<n;){let t=e.charCodeAt(a);for(;a<n&&o(t);)t=e.charCodeAt(++a);if(a>=n)break;if(t===62)return a++,{node:c,tag:s,selfClose:l,end:a};if(t===47){l=!0,a++;continue}let u=a;for(;a<n&&(t=e.charCodeAt(a),!(t===61||o(t)||t===62||t===47));)a++;if(a>=n&&!i)return null;let d=e.slice(u,a);for(;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;if(e.charCodeAt(a)===61){for(a++;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;let t=e.charCodeAt(a);if(t===34||t===39){a++;let o=e.indexOf(t===34?`"`:`'`,a);if(o<0){if(!i)return null;o=n}let s=e.slice(a,o);c[d]=s.indexOf(`&`)<0?s:r(s),a=o+1}}else d&&(c[d]=``)}return i?{node:c,tag:s,selfClose:l,end:a}:null}finish(){let e=this.buffer,t=e.length;for(;this.stack.length>0;){let n=this.stack.pop(),r=n.node;!n.hasChild&&t>n.textStart&&(r.text=i(e.slice(n.textStart,t)),t=n.textStart);let a=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,o=a?a.node:void 0;this.attach(r,o,a?a.keep===!0:!1)}}compact(){let e=this.cursor;for(let t=this.stack.length-1;t>=0;t--){let n=this.stack[t];if(!n.hasChild){e=n.textStart;break}}if(!(e<=0)){this.buffer=this.buffer.slice(e),this.cursor-=e;for(let t=0;t<this.stack.length;t++){let n=this.stack[t];n.textStart=n.textStart>e?n.textStart-e:0}this.rootOwner&&(this.rootOwner.textStart=0)}}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){this.$addListener(e,t)}removeListener(e,t){this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){let n=this.evtListeners[e];if(n?n.push(t):this.evtListeners[e]=[t],e.charCodeAt(1)!==47&&this.openListenerCount++,e.charCodeAt(0)===60){let t=e.slice(e.charCodeAt(1)===47?2:1,e.length-1);this.watchedPaths.add(t);let n=t.lastIndexOf(`.`);if(n<0)this.watchedTopLevel.add(t);else{let e=t.slice(0,n),r=this.watchedChildren.get(e);r||(r=/* @__PURE__ */ new Set,this.watchedChildren.set(e,r)),r.add(t.slice(n+1))}}}$removeListener(e,t){let n=this.evtListeners[e],r=-1;n&&(r=n.indexOf(t)),r>=0&&(n.splice(r,1),e.charCodeAt(1)!==47&&this.openListenerCount--)}emit(e,t,n){let r=this.evtListeners[e];if(r)for(let e=0;e<r.length;e++)r[e](t,n)}};function c(e){if(typeof e!=`string`||e.length===0)throw TypeError(`createStream() requires { event }, e.g. { event: "</root.item>" }`);return e}function l(n){let r=c(n&&n.event),i=new s({...n,progressive:!0,retain:`none`,keep:[r]}),a=new t(`utf8`),o=new e({readableObjectMode:!0,transform(e,t,n){try{i.write(typeof e==`string`?e:a.write(e)),n()}catch(e){n(e)}},flush(e){try{let t=a.end();t.length>0&&i.write(t),i.end(),e()}catch(t){e(t)}}});return i.on(r,e=>{o.push(e)}),o}export{l as createStream};
|
|
1
|
+
import{Transform as e}from"node:stream";import{StringDecoder as t}from"node:string_decoder";function n(e){switch(e){case`amp`:return`&`;case`lt`:return`<`;case`gt`:return`>`;case`quot`:return`"`;case`apos`:return`'`}if(e.charCodeAt(0)===35){let t=e.charCodeAt(1)===120||e.charCodeAt(1)===88?parseInt(e.slice(2),16):parseInt(e.slice(1),10);if(Number.isFinite(t)&&t>=0&&t<=1114111)return String.fromCodePoint(t)}return null}function r(e){let t=e.indexOf(`&`);if(t<0)return e;let r=e.slice(0,t);for(;t<e.length;){let i=e.indexOf(`;`,t+1);if(i<0){r+=e.slice(t);break}let a=n(e.slice(t+1,i));if(r+=a===null?e.slice(t,i+1):a,t=e.indexOf(`&`,i+1),t<0){r+=e.slice(i+1);break}r+=e.slice(i+1,t)}return r}function i(e){if(e.indexOf(`<![CDATA[`)<0)return e.indexOf(`&`)<0?e:r(e);let t=``,n=0;for(;n<e.length;){let i=e.indexOf(`<![CDATA[`,n);if(i<0){t+=r(e.slice(n));break}i>n&&(t+=r(e.slice(n,i)));let a=e.indexOf(`]]>`,i+9);if(a<0){t+=e.slice(i+9);break}t+=e.slice(i+9,a),n=a+3}return t}function a(e){let t=0,n=e.length;return e.charCodeAt(0)===60&&(t=e.charCodeAt(1)===47?2:1),e.charCodeAt(n-1)===62&&n--,e.slice(t,n)}function o(e){return e===32||e===9||e===10||e===13}var s=class{constructor(e){if(this.queryParent=!1,this.progressive=!1,this.retain=`all`,this.keepPaths=/* @__PURE__ */ new Set,this.parentMap=/* @__PURE__ */ new WeakMap,this.evtListeners={},this.openListenerCount=0,this.watchedPaths=/* @__PURE__ */ new Set,this.watchedChildren=/* @__PURE__ */ new Map,this.watchedTopLevel=/* @__PURE__ */ new Set,this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=``,this.active=!1,e&&(this.queryParent=e.queryParent===!0,this.progressive=e.progressive===!0,e.retain&&(this.retain=e.retain),e.keep))for(let t of e.keep)this.keepPaths.add(a(t))}write(e){return this.active||this.begin(void 0,void 0),e.length===0||(this.buffer.length===0?this.buffer=e:this.buffer+=e,this.consume(!1)),this}end(){if(!this.active)return[];this.consume(!0),this.finish();let e=this.roots;return this.reset(),e}parse(e,t,n){return this.begin(t,n),this.write(e),this.end()}begin(e,t){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.basePath=t||``,this.top=e?{node:e,fullTag:this.basePath,textStart:0}:void 0,this.rootOwner=this.top,this.parentMap=/* @__PURE__ */ new WeakMap,this.active=!0}reset(){this.buffer=``,this.cursor=0,this.stack=[],this.roots=[],this.top=void 0,this.rootOwner=void 0,this.basePath=``,this.active=!1}attach(e,t,n){if(this.retain===`none`&&!n)return;if(t===void 0){this.retain===`all`&&this.roots.push(e);return}let r=t.children;r?r.push(e):t.children=[e]}consume(e){let t=this.buffer,n=t.length,r=this.progressive,a=r&&this.openListenerCount>0,o=this.cursor,s=-1;for(;o<n;){let c=t.indexOf(`<`,o);if(c<0||(s=c,o=c+1,o>=n))break;let l=t.charCodeAt(o);if(l===47){let a=t.indexOf(`>`,o);if(a<0){if(!e)break;o=n;break}let l=this.stack.pop();if(o=a+1,s=-1,!l)continue;let u=l.node,d=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,f=d?d.node:void 0;!l.hasChild&&c>l.textStart&&(u.text=i(t.slice(l.textStart,c))),r&&this.watchedPaths.has(l.fullTag)&&this.emit(`</`+l.fullTag+`>`,u,f),this.attach(u,f,d?d.keep===!0:!1),d&&(d.hasChild=!0),this.top=d;continue}if(l===63){let r=t.indexOf(`>`,o);if(r<0){if(!e)break;o=n;break}o=r+1,s=-1;continue}if(l===33){let r;if(t.charCodeAt(o+1)===45&&t.charCodeAt(o+2)===45?(r=t.indexOf(`-->`,o+3),r=r<0?-1:r+3):t.startsWith(`![CDATA[`,o)?(r=t.indexOf(`]]>`,o+9),r=r<0?-1:r+3):(r=t.indexOf(`>`,o),r=r<0?-1:r+1),r<0){if(!e)break;o=n;break}o=r,s=-1;continue}let u=this.parseOpenTag(t,o,n,e);if(u===null)break;o=u.end,s=-1;let d=u.node,f=u.tag,p=this.top?this.top.node:void 0;if(this.queryParent&&p&&this.parentMap.set(d,p),u.selfClose){if(r){let e=this.top?this.top.fullTag:this.basePath,t=e?this.watchedChildren.get(e):this.watchedTopLevel;if(t&&t.has(f)){let t=e?e+`.`+f:f;a&&this.emit(`<`+t+`>`,d,p),this.emit(`</`+t+`>`,d,p)}}this.attach(d,p,this.top?this.top.keep===!0:!1),this.top&&(this.top.hasChild=!0);continue}let m=this.top?this.top.fullTag?this.top.fullTag+`.`+f:f:this.basePath?this.basePath+`.`+f:f;a&&this.watchedPaths.has(m)&&this.emit(`<`+m+`>`,d,p);let h=this.top!==void 0&&this.top.keep===!0||this.keepPaths.has(m),g={node:d,fullTag:m,textStart:o,keep:h};this.stack.push(g),this.top=g}this.cursor=e?n:s>=0?s:o,e||this.compact()}parseOpenTag(e,t,n,i){let a=t;for(;a<n;){let t=e.charCodeAt(a);if(o(t)||t===47||t===62)break;a++}if(a>=n&&!i)return null;let s=e.slice(t,a),c={tagName:s},l=!1;for(;a<n;){let t=e.charCodeAt(a);for(;a<n&&o(t);)t=e.charCodeAt(++a);if(a>=n)break;if(t===62)return a++,{node:c,tag:s,selfClose:l,end:a};if(t===47){l=!0,a++;continue}let u=a;for(;a<n&&(t=e.charCodeAt(a),!(t===61||o(t)||t===62||t===47));)a++;if(a>=n&&!i)return null;let d=e.slice(u,a);for(;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;if(e.charCodeAt(a)===61){for(a++;a<n&&o(e.charCodeAt(a));)a++;if(a>=n&&!i)return null;let t=e.charCodeAt(a);if(t===34||t===39){a++;let o=e.indexOf(t===34?`"`:`'`,a);if(o<0){if(!i)return null;o=n}let s=e.slice(a,o);c[d]=s.indexOf(`&`)<0?s:r(s),a=o+1}}else d&&(c[d]=``)}return i?{node:c,tag:s,selfClose:l,end:a}:null}finish(){let e=this.buffer,t=e.length;for(;this.stack.length>0;){let n=this.stack.pop(),r=n.node;!n.hasChild&&t>n.textStart&&(r.text=i(e.slice(n.textStart,t)),t=n.textStart);let a=this.stack.length?this.stack[this.stack.length-1]:this.rootOwner,o=a?a.node:void 0;this.attach(r,o,a?a.keep===!0:!1)}}compact(){let e=this.cursor;for(let t=this.stack.length-1;t>=0;t--){let n=this.stack[t];if(!n.hasChild){e=n.textStart;break}}if(!(e<=0)){this.buffer=this.buffer.slice(e),this.cursor-=e;for(let t=0;t<this.stack.length;t++){let n=this.stack[t];n.textStart=n.textStart>e?n.textStart-e:0}this.rootOwner&&(this.rootOwner.textStart=0)}}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){this.$addListener(e,t)}removeListener(e,t){this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){let n=this.evtListeners[e];if(n?n.push(t):this.evtListeners[e]=[t],e.charCodeAt(1)!==47&&this.openListenerCount++,e.charCodeAt(0)===60){let t=e.slice(e.charCodeAt(1)===47?2:1,e.length-1);this.watchedPaths.add(t);let n=t.lastIndexOf(`.`);if(n<0)this.watchedTopLevel.add(t);else{let e=t.slice(0,n),r=this.watchedChildren.get(e);r||(r=/* @__PURE__ */ new Set,this.watchedChildren.set(e,r)),r.add(t.slice(n+1))}}}$removeListener(e,t){let n=this.evtListeners[e],r=-1;n&&(r=n.indexOf(t)),r>=0&&(n.splice(r,1),e.charCodeAt(1)!==47&&this.openListenerCount--)}emit(e,t,n){let r=this.evtListeners[e];if(r)for(let e=0;e<r.length;e++)r[e](t,n)}};function c(e){if(typeof e!=`string`||e.length===0)throw TypeError(`createStream() requires { event }, e.g. { event: "</root.item>" }`);return e.charCodeAt(0)===60?e:`</`+e+`>`}function l(n){let r=c(n&&n.event),i=new s({...n,progressive:!0,retain:`none`,keep:[r]}),a=new t(`utf8`),o=new e({readableObjectMode:!0,transform(e,t,n){try{i.write(typeof e==`string`?e:a.write(e)),n()}catch(e){n(e)}},flush(e){try{let t=a.end();t.length>0&&i.write(t),i.end(),e()}catch(t){e(t)}}});return i.on(r,e=>{o.push(e)}),o}export{l as createStream};
|