rusteerio 1.1.0 → 1.1.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/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +37 -37
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/{chunk-FPRP6UIX.mjs → chunk-HN63P3U7.mjs} +625 -401
- package/dist/chunk-HN63P3U7.mjs.map +1 -0
- package/dist/index.cjs +624 -400
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +1 -1
- package/dist/slim.cjs +555 -407
- package/dist/slim.cjs.map +1 -1
- package/dist/slim.d.mts +2 -2
- package/dist/slim.d.ts +2 -2
- package/dist/slim.mjs +1 -1
- package/dist/{types-Cs9UP1Vv.d.mts → types-CJsc0PH-.d.mts} +12 -0
- package/dist/{types-Cs9UP1Vv.d.ts → types-CJsc0PH-.d.ts} +12 -0
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/native/src/arena.rs +163 -7
- package/native/src/attributes.rs +18 -1
- package/native/src/codec.rs +79 -0
- package/native/src/lib.rs +117 -30
- package/native/src/snapshot.rs +144 -89
- package/native/src/tokenizer.rs +34 -20
- package/package.json +1 -1
- package/rusteerio.darwin-arm64.node +0 -0
- package/rusteerio.darwin-x64.node +0 -0
- package/rusteerio.linux-arm64-gnu.node +0 -0
- package/rusteerio.linux-arm64-musl.node +0 -0
- package/rusteerio.linux-x64-gnu.node +0 -0
- package/rusteerio.linux-x64-musl.node +0 -0
- package/rusteerio.win32-arm64-msvc.node +0 -0
- package/rusteerio.win32-x64-msvc.node +0 -0
- package/src/extract.ts +117 -24
- package/src/index.ts +27 -6
- package/src/match.ts +4 -4
- package/src/native.ts +4 -0
- package/src/nodes.ts +70 -10
- package/src/router.ts +80 -4
- package/src/selection.ts +18 -17
- package/src/snapshot.ts +37 -0
- package/src/transport.ts +1 -1
- package/dist/chunk-FPRP6UIX.mjs.map +0 -1
package/dist/slim.cjs
CHANGED
|
@@ -244,7 +244,7 @@ function wrapNativeBinding(binding) {
|
|
|
244
244
|
if (raw.NativeHookStream) wrapped.NativeHookStream = wrapConstructor(raw.NativeHookStream, ([isDocument2, options, bridge]) => [isDocument2, encodeOptions(options), wrapBridge(bridge)], wrapStream);
|
|
245
245
|
if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) => invoke(() => raw.parseWithTreeAdapter(encodeString(source), isDocument2, encodeOptions(options), wrapBridge(bridge)));
|
|
246
246
|
if (raw.parseAsync) wrapped.parseAsync = (source, isDocument2, options) => invoke(() => raw.parseAsync(encodeString(source), isDocument2, encodeOptions(options)));
|
|
247
|
-
if (raw.parseManyAsync) wrapped.parseManyAsync = (sources, isDocument2, threads, options) => invoke(() => raw.parseManyAsync(sources.map(encodeString), isDocument2, threads, encodeOptions(options)));
|
|
247
|
+
if (raw.parseManyAsync) wrapped.parseManyAsync = (sources, isDocument2, threads, options, plans) => invoke(() => raw.parseManyAsync(sources.map(encodeString), isDocument2, threads, encodeOptions(options), plans === void 0 ? void 0 : encodeJson(plans)));
|
|
248
248
|
if (raw.extractPlanManyAsync) wrapped.extractPlanManyAsync = async (sources, plan, threads, options) => decodeJson(await invoke(() => raw.extractPlanManyAsync(sources.map(encodeString), encodeJson(plan), threads, encodeOptions(options))));
|
|
249
249
|
if (raw.extractManyAsync) wrapped.extractManyAsync = async (sources, queries, threads, isDocument2, options) => decodeJson(await invoke(() => raw.extractManyAsync(sources.map(encodeString), queries.map((query) => ({ ...query, key: encodeString(query.key), selector: encodeString(query.selector), ...query.attr === void 0 ? {} : { attr: encodeString(query.attr) } })), threads, isDocument2, encodeOptions(options))));
|
|
250
250
|
return wrapped;
|
|
@@ -288,320 +288,6 @@ function requireNative() {
|
|
|
288
288
|
throw new Error('Rusteerio could not load its Rust native binding. Reinstall rusteerio for this platform or run "npm run build:native" from a source checkout.', { cause: bindingError });
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
// src/hooks.ts
|
|
292
|
-
var tokenCallbacks = ["onattribdata", "onattribentity", "onattribend", "onattribname", "oncdata", "onclosetag", "oncomment", "ondeclaration", "onend", "onopentagend", "onopentagname", "onprocessinginstruction", "onselfclosingtag", "ontext", "ontextentity"];
|
|
293
|
-
function createTokenizerSession(options) {
|
|
294
|
-
const events = [];
|
|
295
|
-
const callbacks = Object.fromEntries(tokenCallbacks.map((name) => [name, (...args) => {
|
|
296
|
-
if (name === "ontextentity" || name === "onattribentity") {
|
|
297
|
-
const codePoint = +args[0];
|
|
298
|
-
String.fromCodePoint(codePoint);
|
|
299
|
-
args[0] = codePoint;
|
|
300
|
-
}
|
|
301
|
-
events.push([name, ...args]);
|
|
302
|
-
}]));
|
|
303
|
-
const Constructor = options.Tokenizer;
|
|
304
|
-
const tokenizer = new Constructor(options, callbacks);
|
|
305
|
-
return {
|
|
306
|
-
write(chunk) {
|
|
307
|
-
if (tokenizer.running) tokenizer.write(chunk);
|
|
308
|
-
},
|
|
309
|
-
end() {
|
|
310
|
-
tokenizer.end();
|
|
311
|
-
const result = cleanParserOptions(options);
|
|
312
|
-
result.__tokenEvents = events;
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
function cleanParserOptions(options) {
|
|
318
|
-
const result = { ...options };
|
|
319
|
-
delete result.Tokenizer;
|
|
320
|
-
delete result.treeAdapter;
|
|
321
|
-
delete result.onParseError;
|
|
322
|
-
delete result.__tokenEvents;
|
|
323
|
-
if (!options._useHtmlParser2 && options.onParseError) {
|
|
324
|
-
result.__collectParseErrors = true;
|
|
325
|
-
result.sourceCodeLocationInfo = true;
|
|
326
|
-
}
|
|
327
|
-
return result;
|
|
328
|
-
}
|
|
329
|
-
function parserOptions(source, options) {
|
|
330
|
-
if (options._useHtmlParser2 && options.Tokenizer) {
|
|
331
|
-
const session = createTokenizerSession(options);
|
|
332
|
-
session.write(source);
|
|
333
|
-
return session.end();
|
|
334
|
-
}
|
|
335
|
-
return cleanParserOptions(options);
|
|
336
|
-
}
|
|
337
|
-
function deliverParseErrors(document, options) {
|
|
338
|
-
if (options._useHtmlParser2 || !options.onParseError) return;
|
|
339
|
-
const diagnostics = document.parserDiagnostics?.();
|
|
340
|
-
const errors = typeof diagnostics === "string" ? JSON.parse(diagnostics) : diagnostics ?? [];
|
|
341
|
-
for (const error of errors) options.onParseError(error);
|
|
342
|
-
}
|
|
343
|
-
function hasParserHooks(options) {
|
|
344
|
-
return !!(options._useHtmlParser2 ? options.Tokenizer : options.treeAdapter || options.onParseError);
|
|
345
|
-
}
|
|
346
|
-
function treeAdapterBridge(adapter, options) {
|
|
347
|
-
const deliveredErrors = /* @__PURE__ */ new Set();
|
|
348
|
-
const nodes = [];
|
|
349
|
-
const ids = /* @__PURE__ */ new WeakMap();
|
|
350
|
-
const identify = (node) => {
|
|
351
|
-
if (node == null) return null;
|
|
352
|
-
if (typeof node !== "object") throw new TypeError("treeAdapter methods must return DOM node objects");
|
|
353
|
-
let id = ids.get(node);
|
|
354
|
-
if (id === void 0) {
|
|
355
|
-
id = nodes.length;
|
|
356
|
-
ids.set(node, id);
|
|
357
|
-
nodes.push(node);
|
|
358
|
-
}
|
|
359
|
-
return id;
|
|
360
|
-
};
|
|
361
|
-
const nodeArgs = {
|
|
362
|
-
appendChild: [0, 1],
|
|
363
|
-
insertBefore: [0, 1, 2],
|
|
364
|
-
setTemplateContent: [0, 1],
|
|
365
|
-
getTemplateContent: [0],
|
|
366
|
-
setDocumentType: [0],
|
|
367
|
-
setDocumentMode: [0],
|
|
368
|
-
getDocumentMode: [0],
|
|
369
|
-
detachNode: [0],
|
|
370
|
-
insertText: [0],
|
|
371
|
-
insertTextBefore: [0, 2],
|
|
372
|
-
adoptAttributes: [0],
|
|
373
|
-
getFirstChild: [0],
|
|
374
|
-
getChildNodes: [0],
|
|
375
|
-
getParentNode: [0],
|
|
376
|
-
getAttrList: [0],
|
|
377
|
-
getTagName: [0],
|
|
378
|
-
getNamespaceURI: [0],
|
|
379
|
-
getTextNodeContent: [0],
|
|
380
|
-
getCommentNodeContent: [0],
|
|
381
|
-
getDocumentTypeNodeName: [0],
|
|
382
|
-
getDocumentTypeNodePublicId: [0],
|
|
383
|
-
getDocumentTypeNodeSystemId: [0],
|
|
384
|
-
isTextNode: [0],
|
|
385
|
-
isCommentNode: [0],
|
|
386
|
-
isElementNode: [0],
|
|
387
|
-
isDocumentTypeNode: [0],
|
|
388
|
-
setNodeSourceCodeLocation: [0],
|
|
389
|
-
getNodeSourceCodeLocation: [0],
|
|
390
|
-
updateNodeSourceCodeLocation: [0],
|
|
391
|
-
onItemPop: [0, 1],
|
|
392
|
-
onItemPush: [0]
|
|
393
|
-
};
|
|
394
|
-
const nodeReturns = /* @__PURE__ */ new Set(["createDocument", "createDocumentFragment", "createElement", "createCommentNode", "createTextNode", "getTemplateContent", "getFirstChild", "getParentNode"]);
|
|
395
|
-
const invoke = (method, args) => {
|
|
396
|
-
const fn = adapter[method];
|
|
397
|
-
if (typeof fn !== "function") {
|
|
398
|
-
if (method === "onItemPop" || method === "onItemPush") return void 0;
|
|
399
|
-
throw new TypeError(`treeAdapter.${method} must be a function`);
|
|
400
|
-
}
|
|
401
|
-
return Reflect.apply(fn, adapter, args);
|
|
402
|
-
};
|
|
403
|
-
const snapshot = () => {
|
|
404
|
-
const records = [];
|
|
405
|
-
for (let id = 0; id < nodes.length; id++) {
|
|
406
|
-
const node = nodes[id];
|
|
407
|
-
const element = invoke("isElementNode", [node]);
|
|
408
|
-
const text = invoke("isTextNode", [node]);
|
|
409
|
-
const comment = invoke("isCommentNode", [node]);
|
|
410
|
-
const doctype = invoke("isDocumentTypeNode", [node]);
|
|
411
|
-
const name = element ? invoke("getTagName", [node]) : doctype ? "!doctype" : node.name;
|
|
412
|
-
const type = element ? name === "script" || name === "style" ? name : "tag" : text ? "text" : comment ? "comment" : doctype ? "directive" : node.type ?? "root";
|
|
413
|
-
const children = element || type === "root" || type === "cdata" ? invoke("getChildNodes", [node]) ?? [] : [];
|
|
414
|
-
const record = { id, type, children: Array.from(children, identify), parent: identify(invoke("getParentNode", [node])) };
|
|
415
|
-
if (name !== void 0) record.name = name;
|
|
416
|
-
if (element) {
|
|
417
|
-
record.namespace = invoke("getNamespaceURI", [node]);
|
|
418
|
-
record.attribs = /* @__PURE__ */ Object.create(null);
|
|
419
|
-
record.attribsNamespace = /* @__PURE__ */ Object.create(null);
|
|
420
|
-
record.attribsPrefix = /* @__PURE__ */ Object.create(null);
|
|
421
|
-
for (const attr2 of invoke("getAttrList", [node])) {
|
|
422
|
-
Object.defineProperty(record.attribs, attr2.name, { value: attr2.value, enumerable: true, configurable: true, writable: true });
|
|
423
|
-
record.attribsNamespace[attr2.name] = attr2.namespace;
|
|
424
|
-
record.attribsPrefix[attr2.name] = attr2.prefix;
|
|
425
|
-
}
|
|
426
|
-
} else if (text || comment) record.data = invoke(text ? "getTextNodeContent" : "getCommentNodeContent", [node]);
|
|
427
|
-
else if (doctype) {
|
|
428
|
-
record.data = node.data;
|
|
429
|
-
for (const [field, method] of [["x-name", "getDocumentTypeNodeName"], ["x-publicId", "getDocumentTypeNodePublicId"], ["x-systemId", "getDocumentTypeNodeSystemId"]]) record[field] = invoke(method, [node]);
|
|
430
|
-
}
|
|
431
|
-
if (type === "root" && node["x-mode"] !== void 0) record["x-mode"] = invoke("getDocumentMode", [node]);
|
|
432
|
-
for (const field of ["startIndex", "endIndex", "sourceCodeLocation"]) if (node[field] !== void 0) record[field] = node[field];
|
|
433
|
-
records.push(record);
|
|
434
|
-
}
|
|
435
|
-
return records;
|
|
436
|
-
};
|
|
437
|
-
const bridge = (request) => {
|
|
438
|
-
const { method, args = [] } = JSON.parse(request);
|
|
439
|
-
if (method === "__parseError") {
|
|
440
|
-
deliveredErrors.add(JSON.stringify(args[0]));
|
|
441
|
-
options.onParseError?.(args[0]);
|
|
442
|
-
return "null";
|
|
443
|
-
}
|
|
444
|
-
if (method === "__snapshot") return JSON.stringify(snapshot());
|
|
445
|
-
if (method === "__locations") {
|
|
446
|
-
for (const entry of args[0]) invoke("setNodeSourceCodeLocation", [nodes[entry.id], hydrateLocation(entry.location)]);
|
|
447
|
-
return "null";
|
|
448
|
-
}
|
|
449
|
-
const values = args.slice();
|
|
450
|
-
if (method === "setNodeSourceCodeLocation" || method === "updateNodeSourceCodeLocation") hydrateLocation(values[1]);
|
|
451
|
-
for (const index of nodeArgs[method] ?? []) values[index] = values[index] == null ? null : nodes[values[index]];
|
|
452
|
-
const result = invoke(method, values);
|
|
453
|
-
return JSON.stringify(method === "getChildNodes" ? Array.from(result ?? [], identify) : nodeReturns.has(method) ? identify(result) : result ?? null);
|
|
454
|
-
};
|
|
455
|
-
return { bridge, nodes, deliveredErrors };
|
|
456
|
-
}
|
|
457
|
-
function bindAdapterDocument(document, options, adapter) {
|
|
458
|
-
if (options.onParseError) {
|
|
459
|
-
const errors = document.parserDiagnostics?.();
|
|
460
|
-
for (const error of errors ? JSON.parse(errors) : []) if (!adapter.deliveredErrors.has(JSON.stringify(error))) options.onParseError(error);
|
|
461
|
-
}
|
|
462
|
-
const routed = routeDocument(document, options);
|
|
463
|
-
const globalId = routed.localNodeId.bind(routed);
|
|
464
|
-
for (let id = 0; id < adapter.nodes.length; id++) getNode(routed, globalId(id), adapter.nodes[id]);
|
|
465
|
-
return routed;
|
|
466
|
-
}
|
|
467
|
-
function parseNativeDocument(source, options, isDocument2) {
|
|
468
|
-
const binding = requireNative();
|
|
469
|
-
const nativeOptions = parserOptions(source, options);
|
|
470
|
-
if (!options._useHtmlParser2 && options.treeAdapter && canReplay(options)) {
|
|
471
|
-
const document2 = routeDocument(new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions)), options);
|
|
472
|
-
const nodes = replayIntoAdapter(document2, options.treeAdapter, isDocument2);
|
|
473
|
-
if (nodes) {
|
|
474
|
-
attachParsedNodes(document2.state, nodes);
|
|
475
|
-
return document2;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
if (!options._useHtmlParser2 && options.treeAdapter) {
|
|
479
|
-
const parse3 = binding.parseWithTreeAdapter;
|
|
480
|
-
if (!parse3) throw new Error("This native addon does not support treeAdapter hooks; rebuild the Rust addon.");
|
|
481
|
-
const adapter = treeAdapterBridge(options.treeAdapter, options);
|
|
482
|
-
return bindAdapterDocument(parse3(source, isDocument2, JSON.stringify(nativeOptions), adapter.bridge), options, adapter);
|
|
483
|
-
}
|
|
484
|
-
const document = new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions));
|
|
485
|
-
deliverParseErrors(document, options);
|
|
486
|
-
return routeDocument(document, options);
|
|
487
|
-
}
|
|
488
|
-
function canReplay(options) {
|
|
489
|
-
const adapter = options.treeAdapter;
|
|
490
|
-
return !options.onParseError && !options.sourceCodeLocationInfo && adapter.onItemPush === void 0 && adapter.onItemPop === void 0;
|
|
491
|
-
}
|
|
492
|
-
function replayIntoAdapter(document, adapter, isDocument2) {
|
|
493
|
-
const state = document.state;
|
|
494
|
-
const root = document.rootId() - state.base;
|
|
495
|
-
const size = state.baseline;
|
|
496
|
-
const nodes = new Array(size);
|
|
497
|
-
for (let local = 0; local < Math.min(size, 65); local++) recordAt(state, local);
|
|
498
|
-
for (let local = 0; local < size; local++) {
|
|
499
|
-
const snapshot = plainSnapshot(state, local);
|
|
500
|
-
const record = snapshot ? void 0 : recordAt(state, local);
|
|
501
|
-
if (!snapshot && !record) continue;
|
|
502
|
-
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
503
|
-
if (local === root) {
|
|
504
|
-
nodes[local] = isDocument2 ? adapter.createDocument() : adapter.createDocumentFragment();
|
|
505
|
-
const mode = record?.["x-mode"];
|
|
506
|
-
if (isDocument2 && mode !== void 0) adapter.setDocumentMode(nodes[local], mode);
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
const parentLocal = snapshot ? snapshot.linkOf(local, 1) : record.parent;
|
|
510
|
-
const parent = parentLocal == null ? void 0 : nodes[parentLocal];
|
|
511
|
-
if (parent === void 0) return void 0;
|
|
512
|
-
switch (type) {
|
|
513
|
-
case "tag":
|
|
514
|
-
case "script":
|
|
515
|
-
case "style": {
|
|
516
|
-
const element = snapshot ? adapter.createElement(snapshot.nameOf(local), snapshot.namespaceOf(local), snapshot.attributeObjects(local)) : adapter.createElement(record.name, record.namespace, attributeList(record));
|
|
517
|
-
adapter.appendChild(parent, element);
|
|
518
|
-
nodes[local] = element;
|
|
519
|
-
break;
|
|
520
|
-
}
|
|
521
|
-
case "root": {
|
|
522
|
-
const content = adapter.createDocumentFragment();
|
|
523
|
-
adapter.setTemplateContent(parent, content);
|
|
524
|
-
nodes[local] = content;
|
|
525
|
-
break;
|
|
526
|
-
}
|
|
527
|
-
case "text": {
|
|
528
|
-
adapter.insertText(parent, (snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
529
|
-
const children = adapter.getChildNodes(parent);
|
|
530
|
-
nodes[local] = children[children.length - 1];
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
case "comment": {
|
|
534
|
-
const comment = adapter.createCommentNode((snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
535
|
-
adapter.appendChild(parent, comment);
|
|
536
|
-
nodes[local] = comment;
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
case "directive": {
|
|
540
|
-
if (!record || record.name !== "!doctype" || !isDocument2) return void 0;
|
|
541
|
-
adapter.setDocumentType(parent, record["x-name"] ?? "", record["x-publicId"] ?? "", record["x-systemId"] ?? "");
|
|
542
|
-
nodes[local] = Array.from(adapter.getChildNodes(parent) ?? []).find((child) => adapter.isDocumentTypeNode(child));
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
default:
|
|
546
|
-
return void 0;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
const changes = differencesFromParse(adapter, nodes, state, root);
|
|
550
|
-
if (!changes) return void 0;
|
|
551
|
-
for (const change of changes) operation(document, "setNode", { id: state.base + change.local, field: change.field, value: change.value });
|
|
552
|
-
return nodes;
|
|
553
|
-
}
|
|
554
|
-
function attributeList(record) {
|
|
555
|
-
const attributes = record.attribs ?? {};
|
|
556
|
-
return Object.keys(attributes).map((name) => {
|
|
557
|
-
const namespace = record.attribsNamespace?.[name];
|
|
558
|
-
const prefix = record.attribsPrefix?.[name];
|
|
559
|
-
return { name, value: attributes[name], ...namespace === void 0 ? {} : { namespace }, ...prefix === void 0 ? {} : { prefix } };
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
function differencesFromParse(adapter, nodes, state, root) {
|
|
563
|
-
const changes = [];
|
|
564
|
-
for (let local = 0; local < nodes.length; local++) {
|
|
565
|
-
const node = nodes[local];
|
|
566
|
-
const snapshot = plainSnapshot(state, local);
|
|
567
|
-
const record = snapshot ? void 0 : recordAt(state, local);
|
|
568
|
-
if (!snapshot && !record) continue;
|
|
569
|
-
if (!node) return void 0;
|
|
570
|
-
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
571
|
-
if (local !== root && adapter.getParentNode(node) !== nodes[snapshot ? snapshot.linkOf(local, 1) : record.parent]) return void 0;
|
|
572
|
-
if (type !== "text" && type !== "comment" && type !== "directive") {
|
|
573
|
-
const children = adapter.getChildNodes(node) ?? [];
|
|
574
|
-
const count = snapshot ? snapshot.childCount(local) : record.children.length;
|
|
575
|
-
if (children.length !== count) return void 0;
|
|
576
|
-
for (let index = 0; index < count; index++) if (children[index] !== nodes[snapshot ? snapshot.childAt(local, index) : record.children[index]]) return void 0;
|
|
577
|
-
}
|
|
578
|
-
if (type === "tag" || type === "script" || type === "style") {
|
|
579
|
-
const name = snapshot ? snapshot.nameOf(local) : record.name;
|
|
580
|
-
const namespace = snapshot ? snapshot.namespaceOf(local) : record.namespace;
|
|
581
|
-
if (!adapter.isElementNode(node) || adapter.getTagName(node) !== name || adapter.getNamespaceURI(node) !== namespace) return void 0;
|
|
582
|
-
const attributes = adapter.getAttrList(node) ?? [];
|
|
583
|
-
const expected = snapshot ? snapshot.attributeObjects(local) : attributeList(record);
|
|
584
|
-
const isSame = attributes.length === expected.length && attributes.every((attribute, index) => attribute.name === expected[index].name && attribute.value === expected[index].value);
|
|
585
|
-
if (!isSame) {
|
|
586
|
-
const values = /* @__PURE__ */ Object.create(null);
|
|
587
|
-
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
588
|
-
const prefixes = /* @__PURE__ */ Object.create(null);
|
|
589
|
-
for (const attribute of attributes) {
|
|
590
|
-
values[attribute.name] = attribute.value;
|
|
591
|
-
if (attribute.namespace !== void 0) namespaces[attribute.name] = attribute.namespace;
|
|
592
|
-
if (attribute.prefix !== void 0) prefixes[attribute.name] = attribute.prefix;
|
|
593
|
-
}
|
|
594
|
-
changes.push({ local, field: "attribs", value: values }, { local, field: "attribsNamespace", value: namespaces }, { local, field: "attribsPrefix", value: prefixes });
|
|
595
|
-
}
|
|
596
|
-
} else if (type === "text" || type === "comment") {
|
|
597
|
-
if (type === "text" ? !adapter.isTextNode(node) : !adapter.isCommentNode(node)) return void 0;
|
|
598
|
-
const data2 = type === "text" ? adapter.getTextNodeContent(node) : adapter.getCommentNodeContent(node);
|
|
599
|
-
if (data2 !== (snapshot ? snapshot.dataOf(local) : record.data)) changes.push({ local, field: "data", value: data2 });
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
return changes;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
291
|
// src/snapshot.ts
|
|
606
292
|
var HEADER = 5;
|
|
607
293
|
var STRIDE = 15;
|
|
@@ -702,8 +388,12 @@ var NodeSnapshot = class {
|
|
|
702
388
|
text;
|
|
703
389
|
isEncoded;
|
|
704
390
|
names = [];
|
|
391
|
+
/** Per interned type: 1 for element types, 2 for root, 3 for text, 0 otherwise. */
|
|
392
|
+
typeKinds = [];
|
|
705
393
|
/** Node object constructors by interned type, resolved once per snapshot. */
|
|
706
394
|
viewConstructors = void 0;
|
|
395
|
+
/** Text nodes too large for the arrays, read individually while this snapshot is current. */
|
|
396
|
+
largeTexts = /* @__PURE__ */ new Map();
|
|
707
397
|
constructor(raw) {
|
|
708
398
|
const { data: data2 } = raw;
|
|
709
399
|
const childrenStart = HEADER + data2[0];
|
|
@@ -792,6 +482,33 @@ var NodeSnapshot = class {
|
|
|
792
482
|
childStart(local) {
|
|
793
483
|
return this.nodes[local * STRIDE + 4];
|
|
794
484
|
}
|
|
485
|
+
/** Whether a node is an element: a tag, script or style. */
|
|
486
|
+
isElementAt(local) {
|
|
487
|
+
return this.typeKind(local) === 1;
|
|
488
|
+
}
|
|
489
|
+
isRootAt(local) {
|
|
490
|
+
return this.typeKind(local) === 2;
|
|
491
|
+
}
|
|
492
|
+
isTextAt(local) {
|
|
493
|
+
return this.typeKind(local) === 3;
|
|
494
|
+
}
|
|
495
|
+
/** Whether a node's record adds fields stored as JSON, such as source locations. */
|
|
496
|
+
hasExtraFields(local) {
|
|
497
|
+
return this.nodes[local * STRIDE + 14] !== 0;
|
|
498
|
+
}
|
|
499
|
+
/** Whether the slot holds a node, rather than one a collection released. */
|
|
500
|
+
isPresent(local) {
|
|
501
|
+
return local < this.size && (this.nodes[local * STRIDE + 10] & RELEASED) === 0;
|
|
502
|
+
}
|
|
503
|
+
typeKind(local) {
|
|
504
|
+
const reference = this.nodes[local * STRIDE];
|
|
505
|
+
let kind = this.typeKinds[reference];
|
|
506
|
+
if (kind === void 0) {
|
|
507
|
+
const type = this.name(reference);
|
|
508
|
+
kind = this.typeKinds[reference] = type === "tag" || type === "script" || type === "style" ? 1 : type === "root" ? 2 : type === "text" ? 3 : 0;
|
|
509
|
+
}
|
|
510
|
+
return kind;
|
|
511
|
+
}
|
|
795
512
|
/** The interned reference of a node's type, comparable across nodes of this snapshot. */
|
|
796
513
|
typeReference(local) {
|
|
797
514
|
return this.nodes[local * STRIDE];
|
|
@@ -800,54 +517,368 @@ var NodeSnapshot = class {
|
|
|
800
517
|
childCount(local) {
|
|
801
518
|
return this.nodes[local * STRIDE + 5];
|
|
802
519
|
}
|
|
803
|
-
childAt(local, index) {
|
|
804
|
-
return this.children[this.nodes[local * STRIDE + 4] + index];
|
|
520
|
+
childAt(local, index) {
|
|
521
|
+
return this.children[this.nodes[local * STRIDE + 4] + index];
|
|
522
|
+
}
|
|
523
|
+
childrenOf(local) {
|
|
524
|
+
const base = local * STRIDE;
|
|
525
|
+
const count = this.nodes[base + 5];
|
|
526
|
+
if (count === 0) return noChildren;
|
|
527
|
+
const first = this.nodes[base + 4];
|
|
528
|
+
return Array.from(this.children.subarray(first, first + count));
|
|
529
|
+
}
|
|
530
|
+
attributesOf(local) {
|
|
531
|
+
const base = local * STRIDE;
|
|
532
|
+
const count = this.nodes[base + 9];
|
|
533
|
+
if (count === 0) return noAttributes;
|
|
534
|
+
const first = this.nodes[base + 8];
|
|
535
|
+
const attributes = this.attributes;
|
|
536
|
+
const result = {};
|
|
537
|
+
for (let index = 0; index < count; index++) {
|
|
538
|
+
const pair = (first + index) * 2;
|
|
539
|
+
const name = this.name(attributes[pair]);
|
|
540
|
+
const value = this.string(attributes[pair + 1]);
|
|
541
|
+
if (name === "__proto__") Object.defineProperty(result, name, { value, writable: true, enumerable: true, configurable: true });
|
|
542
|
+
else result[name] = value;
|
|
543
|
+
}
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
546
|
+
/** One attribute's value, without decoding the rest. */
|
|
547
|
+
attributeValue(local, name) {
|
|
548
|
+
const base = local * STRIDE;
|
|
549
|
+
const count = this.nodes[base + 9];
|
|
550
|
+
const first = this.nodes[base + 8];
|
|
551
|
+
const attributes = this.attributes;
|
|
552
|
+
for (let index = count - 1; index >= 0; index--) {
|
|
553
|
+
const pair = (first + index) * 2;
|
|
554
|
+
if (this.name(attributes[pair]) === name) return this.string(attributes[pair + 1]);
|
|
555
|
+
}
|
|
556
|
+
return void 0;
|
|
557
|
+
}
|
|
558
|
+
string(reference) {
|
|
559
|
+
const strings = this.strings;
|
|
560
|
+
const value = this.text.slice(strings[reference * 2], strings[reference * 2 + 1]);
|
|
561
|
+
return this.isEncoded ? decodeString(value) : value;
|
|
562
|
+
}
|
|
563
|
+
/** Names repeat across nodes, so each decodes once. */
|
|
564
|
+
name(reference) {
|
|
565
|
+
return this.names[reference] ??= this.string(reference);
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
// src/hooks.ts
|
|
570
|
+
var tokenCallbacks = ["onattribdata", "onattribentity", "onattribend", "onattribname", "oncdata", "onclosetag", "oncomment", "ondeclaration", "onend", "onopentagend", "onopentagname", "onprocessinginstruction", "onselfclosingtag", "ontext", "ontextentity"];
|
|
571
|
+
function createTokenizerSession(options) {
|
|
572
|
+
const events = [];
|
|
573
|
+
const callbacks = Object.fromEntries(tokenCallbacks.map((name) => [name, (...args) => {
|
|
574
|
+
if (name === "ontextentity" || name === "onattribentity") {
|
|
575
|
+
const codePoint = +args[0];
|
|
576
|
+
String.fromCodePoint(codePoint);
|
|
577
|
+
args[0] = codePoint;
|
|
578
|
+
}
|
|
579
|
+
events.push([name, ...args]);
|
|
580
|
+
}]));
|
|
581
|
+
const Constructor = options.Tokenizer;
|
|
582
|
+
const tokenizer = new Constructor(options, callbacks);
|
|
583
|
+
return {
|
|
584
|
+
write(chunk) {
|
|
585
|
+
if (tokenizer.running) tokenizer.write(chunk);
|
|
586
|
+
},
|
|
587
|
+
end() {
|
|
588
|
+
tokenizer.end();
|
|
589
|
+
const result = cleanParserOptions(options);
|
|
590
|
+
result.__tokenEvents = events;
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
function cleanParserOptions(options) {
|
|
596
|
+
const result = { ...options };
|
|
597
|
+
delete result.Tokenizer;
|
|
598
|
+
delete result.treeAdapter;
|
|
599
|
+
delete result.onParseError;
|
|
600
|
+
delete result.__tokenEvents;
|
|
601
|
+
if (!options._useHtmlParser2 && options.onParseError) {
|
|
602
|
+
result.__collectParseErrors = true;
|
|
603
|
+
result.sourceCodeLocationInfo = true;
|
|
604
|
+
}
|
|
605
|
+
return result;
|
|
606
|
+
}
|
|
607
|
+
function parserOptions(source, options) {
|
|
608
|
+
if (options._useHtmlParser2 && options.Tokenizer) {
|
|
609
|
+
const session = createTokenizerSession(options);
|
|
610
|
+
session.write(source);
|
|
611
|
+
return session.end();
|
|
612
|
+
}
|
|
613
|
+
return cleanParserOptions(options);
|
|
614
|
+
}
|
|
615
|
+
function deliverParseErrors(document, options) {
|
|
616
|
+
if (options._useHtmlParser2 || !options.onParseError) return;
|
|
617
|
+
const diagnostics = document.parserDiagnostics?.();
|
|
618
|
+
const errors = typeof diagnostics === "string" ? JSON.parse(diagnostics) : diagnostics ?? [];
|
|
619
|
+
for (const error of errors) options.onParseError(error);
|
|
620
|
+
}
|
|
621
|
+
function hasParserHooks(options) {
|
|
622
|
+
return !!(options._useHtmlParser2 ? options.Tokenizer : options.treeAdapter || options.onParseError);
|
|
623
|
+
}
|
|
624
|
+
function treeAdapterBridge(adapter, options) {
|
|
625
|
+
const deliveredErrors = /* @__PURE__ */ new Set();
|
|
626
|
+
const nodes = [];
|
|
627
|
+
const ids = /* @__PURE__ */ new WeakMap();
|
|
628
|
+
const identify = (node) => {
|
|
629
|
+
if (node == null) return null;
|
|
630
|
+
if (typeof node !== "object") throw new TypeError("treeAdapter methods must return DOM node objects");
|
|
631
|
+
let id = ids.get(node);
|
|
632
|
+
if (id === void 0) {
|
|
633
|
+
id = nodes.length;
|
|
634
|
+
ids.set(node, id);
|
|
635
|
+
nodes.push(node);
|
|
636
|
+
}
|
|
637
|
+
return id;
|
|
638
|
+
};
|
|
639
|
+
const nodeArgs = {
|
|
640
|
+
appendChild: [0, 1],
|
|
641
|
+
insertBefore: [0, 1, 2],
|
|
642
|
+
setTemplateContent: [0, 1],
|
|
643
|
+
getTemplateContent: [0],
|
|
644
|
+
setDocumentType: [0],
|
|
645
|
+
setDocumentMode: [0],
|
|
646
|
+
getDocumentMode: [0],
|
|
647
|
+
detachNode: [0],
|
|
648
|
+
insertText: [0],
|
|
649
|
+
insertTextBefore: [0, 2],
|
|
650
|
+
adoptAttributes: [0],
|
|
651
|
+
getFirstChild: [0],
|
|
652
|
+
getChildNodes: [0],
|
|
653
|
+
getParentNode: [0],
|
|
654
|
+
getAttrList: [0],
|
|
655
|
+
getTagName: [0],
|
|
656
|
+
getNamespaceURI: [0],
|
|
657
|
+
getTextNodeContent: [0],
|
|
658
|
+
getCommentNodeContent: [0],
|
|
659
|
+
getDocumentTypeNodeName: [0],
|
|
660
|
+
getDocumentTypeNodePublicId: [0],
|
|
661
|
+
getDocumentTypeNodeSystemId: [0],
|
|
662
|
+
isTextNode: [0],
|
|
663
|
+
isCommentNode: [0],
|
|
664
|
+
isElementNode: [0],
|
|
665
|
+
isDocumentTypeNode: [0],
|
|
666
|
+
setNodeSourceCodeLocation: [0],
|
|
667
|
+
getNodeSourceCodeLocation: [0],
|
|
668
|
+
updateNodeSourceCodeLocation: [0],
|
|
669
|
+
onItemPop: [0, 1],
|
|
670
|
+
onItemPush: [0]
|
|
671
|
+
};
|
|
672
|
+
const nodeReturns = /* @__PURE__ */ new Set(["createDocument", "createDocumentFragment", "createElement", "createCommentNode", "createTextNode", "getTemplateContent", "getFirstChild", "getParentNode"]);
|
|
673
|
+
const invoke = (method, args) => {
|
|
674
|
+
const fn = adapter[method];
|
|
675
|
+
if (typeof fn !== "function") {
|
|
676
|
+
if (method === "onItemPop" || method === "onItemPush") return void 0;
|
|
677
|
+
throw new TypeError(`treeAdapter.${method} must be a function`);
|
|
678
|
+
}
|
|
679
|
+
return Reflect.apply(fn, adapter, args);
|
|
680
|
+
};
|
|
681
|
+
const snapshot = () => {
|
|
682
|
+
const records = [];
|
|
683
|
+
for (let id = 0; id < nodes.length; id++) {
|
|
684
|
+
const node = nodes[id];
|
|
685
|
+
const element = invoke("isElementNode", [node]);
|
|
686
|
+
const text = invoke("isTextNode", [node]);
|
|
687
|
+
const comment = invoke("isCommentNode", [node]);
|
|
688
|
+
const doctype = invoke("isDocumentTypeNode", [node]);
|
|
689
|
+
const name = element ? invoke("getTagName", [node]) : doctype ? "!doctype" : node.name;
|
|
690
|
+
const type = element ? name === "script" || name === "style" ? name : "tag" : text ? "text" : comment ? "comment" : doctype ? "directive" : node.type ?? "root";
|
|
691
|
+
const children = element || type === "root" || type === "cdata" ? invoke("getChildNodes", [node]) ?? [] : [];
|
|
692
|
+
const record = { id, type, children: Array.from(children, identify), parent: identify(invoke("getParentNode", [node])) };
|
|
693
|
+
if (name !== void 0) record.name = name;
|
|
694
|
+
if (element) {
|
|
695
|
+
record.namespace = invoke("getNamespaceURI", [node]);
|
|
696
|
+
record.attribs = /* @__PURE__ */ Object.create(null);
|
|
697
|
+
record.attribsNamespace = /* @__PURE__ */ Object.create(null);
|
|
698
|
+
record.attribsPrefix = /* @__PURE__ */ Object.create(null);
|
|
699
|
+
for (const attr2 of invoke("getAttrList", [node])) {
|
|
700
|
+
Object.defineProperty(record.attribs, attr2.name, { value: attr2.value, enumerable: true, configurable: true, writable: true });
|
|
701
|
+
record.attribsNamespace[attr2.name] = attr2.namespace;
|
|
702
|
+
record.attribsPrefix[attr2.name] = attr2.prefix;
|
|
703
|
+
}
|
|
704
|
+
} else if (text || comment) record.data = invoke(text ? "getTextNodeContent" : "getCommentNodeContent", [node]);
|
|
705
|
+
else if (doctype) {
|
|
706
|
+
record.data = node.data;
|
|
707
|
+
for (const [field, method] of [["x-name", "getDocumentTypeNodeName"], ["x-publicId", "getDocumentTypeNodePublicId"], ["x-systemId", "getDocumentTypeNodeSystemId"]]) record[field] = invoke(method, [node]);
|
|
708
|
+
}
|
|
709
|
+
if (type === "root" && node["x-mode"] !== void 0) record["x-mode"] = invoke("getDocumentMode", [node]);
|
|
710
|
+
for (const field of ["startIndex", "endIndex", "sourceCodeLocation"]) if (node[field] !== void 0) record[field] = node[field];
|
|
711
|
+
records.push(record);
|
|
712
|
+
}
|
|
713
|
+
return records;
|
|
714
|
+
};
|
|
715
|
+
const bridge = (request) => {
|
|
716
|
+
const { method, args = [] } = JSON.parse(request);
|
|
717
|
+
if (method === "__parseError") {
|
|
718
|
+
deliveredErrors.add(JSON.stringify(args[0]));
|
|
719
|
+
options.onParseError?.(args[0]);
|
|
720
|
+
return "null";
|
|
721
|
+
}
|
|
722
|
+
if (method === "__snapshot") return JSON.stringify(snapshot());
|
|
723
|
+
if (method === "__locations") {
|
|
724
|
+
for (const entry of args[0]) invoke("setNodeSourceCodeLocation", [nodes[entry.id], hydrateLocation(entry.location)]);
|
|
725
|
+
return "null";
|
|
726
|
+
}
|
|
727
|
+
const values = args.slice();
|
|
728
|
+
if (method === "setNodeSourceCodeLocation" || method === "updateNodeSourceCodeLocation") hydrateLocation(values[1]);
|
|
729
|
+
for (const index of nodeArgs[method] ?? []) values[index] = values[index] == null ? null : nodes[values[index]];
|
|
730
|
+
const result = invoke(method, values);
|
|
731
|
+
return JSON.stringify(method === "getChildNodes" ? Array.from(result ?? [], identify) : nodeReturns.has(method) ? identify(result) : result ?? null);
|
|
732
|
+
};
|
|
733
|
+
return { bridge, nodes, deliveredErrors };
|
|
734
|
+
}
|
|
735
|
+
function bindAdapterDocument(document, options, adapter) {
|
|
736
|
+
if (options.onParseError) {
|
|
737
|
+
const errors = document.parserDiagnostics?.();
|
|
738
|
+
for (const error of errors ? JSON.parse(errors) : []) if (!adapter.deliveredErrors.has(JSON.stringify(error))) options.onParseError(error);
|
|
739
|
+
}
|
|
740
|
+
const routed = routeDocument(document, options);
|
|
741
|
+
const globalId = routed.localNodeId.bind(routed);
|
|
742
|
+
for (let id = 0; id < adapter.nodes.length; id++) getNode(routed, globalId(id), adapter.nodes[id]);
|
|
743
|
+
return routed;
|
|
744
|
+
}
|
|
745
|
+
function parseNativeDocument(source, options, isDocument2) {
|
|
746
|
+
const binding = requireNative();
|
|
747
|
+
const nativeOptions = parserOptions(source, options);
|
|
748
|
+
if (!options._useHtmlParser2 && options.treeAdapter && canReplay(options)) {
|
|
749
|
+
const document2 = routeDocument(new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions)), options);
|
|
750
|
+
const nodes = replayIntoAdapter(document2, options.treeAdapter, isDocument2);
|
|
751
|
+
if (nodes) {
|
|
752
|
+
attachParsedNodes(document2.state, nodes);
|
|
753
|
+
return document2;
|
|
754
|
+
}
|
|
805
755
|
}
|
|
806
|
-
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
return Array.from(this.children.subarray(first, first + count));
|
|
756
|
+
if (!options._useHtmlParser2 && options.treeAdapter) {
|
|
757
|
+
const parse3 = binding.parseWithTreeAdapter;
|
|
758
|
+
if (!parse3) throw new Error("This native addon does not support treeAdapter hooks; rebuild the Rust addon.");
|
|
759
|
+
const adapter = treeAdapterBridge(options.treeAdapter, options);
|
|
760
|
+
return bindAdapterDocument(parse3(source, isDocument2, JSON.stringify(nativeOptions), adapter.bridge), options, adapter);
|
|
812
761
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
762
|
+
const document = new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions));
|
|
763
|
+
deliverParseErrors(document, options);
|
|
764
|
+
return routeDocument(document, options);
|
|
765
|
+
}
|
|
766
|
+
function canReplay(options) {
|
|
767
|
+
const adapter = options.treeAdapter;
|
|
768
|
+
return !options.onParseError && !options.sourceCodeLocationInfo && adapter.onItemPush === void 0 && adapter.onItemPop === void 0;
|
|
769
|
+
}
|
|
770
|
+
function replayIntoAdapter(document, adapter, isDocument2) {
|
|
771
|
+
const state = document.state;
|
|
772
|
+
const root = document.rootId() - state.base;
|
|
773
|
+
const size = state.baseline;
|
|
774
|
+
const nodes = new Array(size);
|
|
775
|
+
for (let local = 0; local < Math.min(size, 65); local++) recordAt(state, local);
|
|
776
|
+
for (let local = 0; local < size; local++) {
|
|
777
|
+
const snapshot = plainSnapshot(state, local);
|
|
778
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
779
|
+
if (!snapshot && !record) continue;
|
|
780
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
781
|
+
if (local === root) {
|
|
782
|
+
nodes[local] = isDocument2 ? adapter.createDocument() : adapter.createDocumentFragment();
|
|
783
|
+
const mode = record?.["x-mode"];
|
|
784
|
+
if (isDocument2 && mode !== void 0) adapter.setDocumentMode(nodes[local], mode);
|
|
785
|
+
continue;
|
|
826
786
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
787
|
+
const parentLocal = snapshot ? snapshot.linkOf(local, 1) : record.parent;
|
|
788
|
+
const parent = parentLocal == null ? void 0 : nodes[parentLocal];
|
|
789
|
+
if (parent === void 0) return void 0;
|
|
790
|
+
switch (type) {
|
|
791
|
+
case "tag":
|
|
792
|
+
case "script":
|
|
793
|
+
case "style": {
|
|
794
|
+
const element = snapshot ? adapter.createElement(snapshot.nameOf(local), snapshot.namespaceOf(local), snapshot.attributeObjects(local)) : adapter.createElement(record.name, record.namespace, attributeList(record));
|
|
795
|
+
adapter.appendChild(parent, element);
|
|
796
|
+
nodes[local] = element;
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
case "root": {
|
|
800
|
+
const content = adapter.createDocumentFragment();
|
|
801
|
+
adapter.setTemplateContent(parent, content);
|
|
802
|
+
nodes[local] = content;
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
805
|
+
case "text": {
|
|
806
|
+
adapter.insertText(parent, (snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
807
|
+
const children = adapter.getChildNodes(parent);
|
|
808
|
+
nodes[local] = children[children.length - 1];
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
case "comment": {
|
|
812
|
+
const comment = adapter.createCommentNode((snapshot ? snapshot.dataOf(local) : record.data) ?? "");
|
|
813
|
+
adapter.appendChild(parent, comment);
|
|
814
|
+
nodes[local] = comment;
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
case "directive": {
|
|
818
|
+
if (!record || record.name !== "!doctype" || !isDocument2) return void 0;
|
|
819
|
+
adapter.setDocumentType(parent, record["x-name"] ?? "", record["x-publicId"] ?? "", record["x-systemId"] ?? "");
|
|
820
|
+
nodes[local] = Array.from(adapter.getChildNodes(parent) ?? []).find((child) => adapter.isDocumentTypeNode(child));
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
default:
|
|
824
|
+
return void 0;
|
|
838
825
|
}
|
|
839
|
-
return void 0;
|
|
840
826
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
827
|
+
const changes = differencesFromParse(adapter, nodes, state, root);
|
|
828
|
+
if (!changes) return void 0;
|
|
829
|
+
for (const change of changes) operation(document, "setNode", { id: state.base + change.local, field: change.field, value: change.value });
|
|
830
|
+
return nodes;
|
|
831
|
+
}
|
|
832
|
+
function attributeList(record) {
|
|
833
|
+
const attributes = record.attribs ?? {};
|
|
834
|
+
return Object.keys(attributes).map((name) => {
|
|
835
|
+
const namespace = record.attribsNamespace?.[name];
|
|
836
|
+
const prefix = record.attribsPrefix?.[name];
|
|
837
|
+
return { name, value: attributes[name], ...namespace === void 0 ? {} : { namespace }, ...prefix === void 0 ? {} : { prefix } };
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
function differencesFromParse(adapter, nodes, state, root) {
|
|
841
|
+
const changes = [];
|
|
842
|
+
for (let local = 0; local < nodes.length; local++) {
|
|
843
|
+
const node = nodes[local];
|
|
844
|
+
const snapshot = plainSnapshot(state, local);
|
|
845
|
+
const record = snapshot ? void 0 : recordAt(state, local);
|
|
846
|
+
if (!snapshot && !record) continue;
|
|
847
|
+
if (!node) return void 0;
|
|
848
|
+
const type = snapshot ? snapshot.typeOf(local) : record.type;
|
|
849
|
+
if (local !== root && adapter.getParentNode(node) !== nodes[snapshot ? snapshot.linkOf(local, 1) : record.parent]) return void 0;
|
|
850
|
+
if (type !== "text" && type !== "comment" && type !== "directive") {
|
|
851
|
+
const children = adapter.getChildNodes(node) ?? [];
|
|
852
|
+
const count = snapshot ? snapshot.childCount(local) : record.children.length;
|
|
853
|
+
if (children.length !== count) return void 0;
|
|
854
|
+
for (let index = 0; index < count; index++) if (children[index] !== nodes[snapshot ? snapshot.childAt(local, index) : record.children[index]]) return void 0;
|
|
855
|
+
}
|
|
856
|
+
if (type === "tag" || type === "script" || type === "style") {
|
|
857
|
+
const name = snapshot ? snapshot.nameOf(local) : record.name;
|
|
858
|
+
const namespace = snapshot ? snapshot.namespaceOf(local) : record.namespace;
|
|
859
|
+
if (!adapter.isElementNode(node) || adapter.getTagName(node) !== name || adapter.getNamespaceURI(node) !== namespace) return void 0;
|
|
860
|
+
const attributes = adapter.getAttrList(node) ?? [];
|
|
861
|
+
const expected = snapshot ? snapshot.attributeObjects(local) : attributeList(record);
|
|
862
|
+
const isSame = attributes.length === expected.length && attributes.every((attribute, index) => attribute.name === expected[index].name && attribute.value === expected[index].value);
|
|
863
|
+
if (!isSame) {
|
|
864
|
+
const values = /* @__PURE__ */ Object.create(null);
|
|
865
|
+
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
866
|
+
const prefixes = /* @__PURE__ */ Object.create(null);
|
|
867
|
+
for (const attribute of attributes) {
|
|
868
|
+
values[attribute.name] = attribute.value;
|
|
869
|
+
if (attribute.namespace !== void 0) namespaces[attribute.name] = attribute.namespace;
|
|
870
|
+
if (attribute.prefix !== void 0) prefixes[attribute.name] = attribute.prefix;
|
|
871
|
+
}
|
|
872
|
+
changes.push({ local, field: "attribs", value: values }, { local, field: "attribsNamespace", value: namespaces }, { local, field: "attribsPrefix", value: prefixes });
|
|
873
|
+
}
|
|
874
|
+
} else if (type === "text" || type === "comment") {
|
|
875
|
+
if (type === "text" ? !adapter.isTextNode(node) : !adapter.isCommentNode(node)) return void 0;
|
|
876
|
+
const data2 = type === "text" ? adapter.getTextNodeContent(node) : adapter.getCommentNodeContent(node);
|
|
877
|
+
if (data2 !== (snapshot ? snapshot.dataOf(local) : record.data)) changes.push({ local, field: "data", value: data2 });
|
|
878
|
+
}
|
|
849
879
|
}
|
|
850
|
-
|
|
880
|
+
return changes;
|
|
881
|
+
}
|
|
851
882
|
|
|
852
883
|
// src/router.ts
|
|
853
884
|
var STRIDE2 = 2 ** 32;
|
|
@@ -946,7 +977,8 @@ function stateFor(raw, options = {}) {
|
|
|
946
977
|
isExposed: false,
|
|
947
978
|
hasChildLists: false,
|
|
948
979
|
collectionRetries: 0,
|
|
949
|
-
isCollectionEvicted: false
|
|
980
|
+
isCollectionEvicted: false,
|
|
981
|
+
hasPreparedSnapshot: false
|
|
950
982
|
};
|
|
951
983
|
holder[stateKey] = state;
|
|
952
984
|
return state;
|
|
@@ -1071,7 +1103,7 @@ function readRecord(state, local) {
|
|
|
1071
1103
|
const size = Math.max(state.snapshotSize, state.baseline);
|
|
1072
1104
|
const firstSnapshotRead = state.generation === 0 ? size / 100 : 1 + size / 100;
|
|
1073
1105
|
if (reads >= Math.min(minimumReadsBeforeSnapshot, firstSnapshotRead)) {
|
|
1074
|
-
const snapshot = new NodeSnapshot(state.raw.snapshot());
|
|
1106
|
+
const snapshot = new NodeSnapshot(takePreparedSnapshot(state, true) ?? state.raw.snapshot());
|
|
1075
1107
|
state.snapshotSize = snapshot.size;
|
|
1076
1108
|
state.bulk = snapshot;
|
|
1077
1109
|
const record = snapshot.record(local);
|
|
@@ -1080,10 +1112,40 @@ function readRecord(state, local) {
|
|
|
1080
1112
|
}
|
|
1081
1113
|
return rawOperation(state.raw, "node", { id: local });
|
|
1082
1114
|
}
|
|
1115
|
+
function takePreparedSnapshot(state, isWanted) {
|
|
1116
|
+
if (!state.hasPreparedSnapshot) return void 0;
|
|
1117
|
+
state.hasPreparedSnapshot = false;
|
|
1118
|
+
return state.raw.takePreparedSnapshot?.(isWanted) ?? void 0;
|
|
1119
|
+
}
|
|
1083
1120
|
function plainSnapshot(state, local) {
|
|
1084
1121
|
const bulk = state.bulk;
|
|
1085
1122
|
return bulk instanceof NodeSnapshot && !(state.stale.size && state.stale.has(local)) && bulk.isPlain(local) ? bulk : void 0;
|
|
1086
1123
|
}
|
|
1124
|
+
function structureSnapshot(state, local) {
|
|
1125
|
+
const bulk = state.bulk;
|
|
1126
|
+
return bulk instanceof NodeSnapshot && !(state.stale.size && state.stale.has(local)) && bulk.isPresent(local) ? bulk : void 0;
|
|
1127
|
+
}
|
|
1128
|
+
var snapshotTextBudget = 256;
|
|
1129
|
+
function textFromSnapshot(state, local) {
|
|
1130
|
+
let text = "";
|
|
1131
|
+
const stack = [local];
|
|
1132
|
+
for (let visited = 0; stack.length; visited++) {
|
|
1133
|
+
const node = stack.pop();
|
|
1134
|
+
const snapshot = structureSnapshot(state, node);
|
|
1135
|
+
if (!snapshot || visited === snapshotTextBudget) return void 0;
|
|
1136
|
+
if (snapshot.isTextAt(node)) {
|
|
1137
|
+
text += snapshot.dataOf(node) ?? largeText(state, snapshot, node);
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
for (let index = snapshot.childCount(node) - 1; index >= 0; index--) stack.push(snapshot.childAt(node, index));
|
|
1141
|
+
}
|
|
1142
|
+
return text;
|
|
1143
|
+
}
|
|
1144
|
+
function largeText(state, snapshot, local) {
|
|
1145
|
+
let text = snapshot.largeTexts.get(local);
|
|
1146
|
+
if (text === void 0) snapshot.largeTexts.set(local, text = state.raw.text([local]));
|
|
1147
|
+
return text;
|
|
1148
|
+
}
|
|
1087
1149
|
function attributeAt(state, local, name) {
|
|
1088
1150
|
const snapshot = plainSnapshot(state, local);
|
|
1089
1151
|
if (snapshot) return snapshot.attributeValue(local, name);
|
|
@@ -1092,15 +1154,18 @@ function attributeAt(state, local, name) {
|
|
|
1092
1154
|
return typeof value === "string" ? value : void 0;
|
|
1093
1155
|
}
|
|
1094
1156
|
function invalidate(state) {
|
|
1157
|
+
takePreparedSnapshot(state, false);
|
|
1095
1158
|
state.generation++;
|
|
1096
1159
|
state.records = [];
|
|
1097
1160
|
state.bulk = 0;
|
|
1098
1161
|
state.stale.clear();
|
|
1099
1162
|
}
|
|
1100
1163
|
function invalidateNodes(state, locals) {
|
|
1164
|
+
takePreparedSnapshot(state, false);
|
|
1101
1165
|
const isSnapshot = state.bulk instanceof NodeSnapshot;
|
|
1166
|
+
const { records } = state;
|
|
1102
1167
|
for (const local of locals) {
|
|
1103
|
-
|
|
1168
|
+
if (records[local] !== void 0) records[local] = void 0;
|
|
1104
1169
|
if (isSnapshot) state.stale.add(local);
|
|
1105
1170
|
}
|
|
1106
1171
|
}
|
|
@@ -1335,6 +1400,11 @@ var RoutedDocument = class {
|
|
|
1335
1400
|
return this.globals(group.state, found);
|
|
1336
1401
|
}
|
|
1337
1402
|
text(ids) {
|
|
1403
|
+
if (ids.length === 1) {
|
|
1404
|
+
const state = this.owner(ids[0]);
|
|
1405
|
+
const text = textFromSnapshot(state, ids[0] - state.base);
|
|
1406
|
+
if (text !== void 0) return text;
|
|
1407
|
+
}
|
|
1338
1408
|
return this.groups(ids).map((group) => group.state.raw.text(group.locals)).join("");
|
|
1339
1409
|
}
|
|
1340
1410
|
innerHtml(id) {
|
|
@@ -1419,9 +1489,12 @@ var RoutedDocument = class {
|
|
|
1419
1489
|
return this.globals(state, inserted);
|
|
1420
1490
|
}
|
|
1421
1491
|
const result2 = [];
|
|
1492
|
+
const isBesideTarget = args.position === "before" || args.position === "after";
|
|
1422
1493
|
for (let index = 0; index < targets.length; index++) {
|
|
1423
1494
|
const target = this.owner(targets[index]);
|
|
1424
1495
|
const targetLocal = targets[index] - target.base;
|
|
1496
|
+
const record = recordAt(target, targetLocal);
|
|
1497
|
+
if (!record || !parentTypes.has(record.type) || isBesideTarget && record.parent == null) continue;
|
|
1425
1498
|
const local = this.moveInto(target, nodes, index + 1 < targets.length);
|
|
1426
1499
|
const inserted = this.call(target, command, { ...args, targetIds: [targetLocal], nodeIds: local });
|
|
1427
1500
|
result2.push(...this.globals(target, inserted));
|
|
@@ -1644,6 +1717,8 @@ function traverseRecords(document, ids, kind) {
|
|
|
1644
1717
|
for (const id of ids) {
|
|
1645
1718
|
const state = stateIn(document, id);
|
|
1646
1719
|
const { base } = state;
|
|
1720
|
+
const snapshot = state.bulk instanceof NodeSnapshot ? state.bulk : void 0;
|
|
1721
|
+
if (snapshot?.isPresent(id - base) && traverseSnapshot(snapshot, base, id - base, kind, result)) continue;
|
|
1647
1722
|
const node = recordAt(state, id - base);
|
|
1648
1723
|
if (!node) continue;
|
|
1649
1724
|
const isElement2 = (local) => isElementType(recordAt(state, local)?.type);
|
|
@@ -1684,6 +1759,60 @@ function traverseRecords(document, ids, kind) {
|
|
|
1684
1759
|
}
|
|
1685
1760
|
return result;
|
|
1686
1761
|
}
|
|
1762
|
+
function traverseSnapshot(snapshot, base, local, kind, result) {
|
|
1763
|
+
const pushChildren2 = (parent, isElementsOnly, except) => {
|
|
1764
|
+
const count = snapshot.childCount(parent);
|
|
1765
|
+
for (let index = 0; index < count; index++) {
|
|
1766
|
+
const child = snapshot.childAt(parent, index);
|
|
1767
|
+
if (child !== except && (!isElementsOnly || snapshot.isElementAt(child))) result.push(base + child);
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1770
|
+
switch (kind) {
|
|
1771
|
+
case "children":
|
|
1772
|
+
pushChildren2(local, true, -1);
|
|
1773
|
+
return true;
|
|
1774
|
+
case "contents":
|
|
1775
|
+
pushChildren2(local, false, -1);
|
|
1776
|
+
return true;
|
|
1777
|
+
case "siblings": {
|
|
1778
|
+
const parent = snapshot.linkOf(local, 1);
|
|
1779
|
+
if (parent !== null && snapshot.isPresent(parent)) pushChildren2(parent, true, local);
|
|
1780
|
+
return true;
|
|
1781
|
+
}
|
|
1782
|
+
case "parent": {
|
|
1783
|
+
const parent = snapshot.linkOf(local, 1);
|
|
1784
|
+
if (parent !== null && snapshot.isPresent(parent) && snapshot.isElementAt(parent)) result.push(base + parent);
|
|
1785
|
+
return true;
|
|
1786
|
+
}
|
|
1787
|
+
case "parents":
|
|
1788
|
+
case "ancestors": {
|
|
1789
|
+
let parent = snapshot.linkOf(local, 1);
|
|
1790
|
+
for (let steps = 0; parent !== null && steps < snapshot.size && snapshot.isPresent(parent) && !snapshot.isRootAt(parent); steps++) {
|
|
1791
|
+
if (snapshot.isElementAt(parent)) result.push(base + parent);
|
|
1792
|
+
parent = snapshot.linkOf(parent, 1);
|
|
1793
|
+
}
|
|
1794
|
+
return true;
|
|
1795
|
+
}
|
|
1796
|
+
case "next":
|
|
1797
|
+
case "prev":
|
|
1798
|
+
case "nextAll":
|
|
1799
|
+
case "prevAll": {
|
|
1800
|
+
const offset = kind === "next" || kind === "nextAll" ? 3 : 2;
|
|
1801
|
+
const isSingle = kind === "next" || kind === "prev";
|
|
1802
|
+
let sibling = snapshot.linkOf(local, offset);
|
|
1803
|
+
for (let steps = 0; sibling !== null && steps < snapshot.size && snapshot.isPresent(sibling); steps++) {
|
|
1804
|
+
if (snapshot.isElementAt(sibling)) {
|
|
1805
|
+
result.push(base + sibling);
|
|
1806
|
+
if (isSingle) break;
|
|
1807
|
+
}
|
|
1808
|
+
sibling = snapshot.linkOf(sibling, offset);
|
|
1809
|
+
}
|
|
1810
|
+
return true;
|
|
1811
|
+
}
|
|
1812
|
+
default:
|
|
1813
|
+
return false;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1687
1816
|
function viewAt(state, local) {
|
|
1688
1817
|
const existing = state.views[local] ?? cachedView(state, local);
|
|
1689
1818
|
if (existing) return existing;
|
|
@@ -1692,9 +1821,9 @@ function viewAt(state, local) {
|
|
|
1692
1821
|
state.adapterNodes[local] = void 0;
|
|
1693
1822
|
return adoptObject(state, local, parsed);
|
|
1694
1823
|
}
|
|
1695
|
-
const snapshot =
|
|
1824
|
+
const snapshot = structureSnapshot(state, local);
|
|
1696
1825
|
let constructor;
|
|
1697
|
-
if (snapshot) constructor = viewConstructor(snapshot.typeOf(local), false);
|
|
1826
|
+
if (snapshot && !snapshot.hasExtraFields(local)) constructor = viewConstructor(snapshot.typeOf(local), false);
|
|
1698
1827
|
else {
|
|
1699
1828
|
const record = recordAt(state, local);
|
|
1700
1829
|
if (!record) return void 0;
|
|
@@ -1893,14 +2022,17 @@ function fillChildren(view) {
|
|
|
1893
2022
|
if (!target) return;
|
|
1894
2023
|
const state = view[VIEW_STATE];
|
|
1895
2024
|
const local = view[VIEW_LOCAL];
|
|
1896
|
-
const snapshot =
|
|
2025
|
+
const snapshot = structureSnapshot(state, local);
|
|
1897
2026
|
if (snapshot && state.stale.size === 0) {
|
|
1898
2027
|
fillFromSnapshot(state, snapshot, local, target);
|
|
1899
2028
|
return;
|
|
1900
2029
|
}
|
|
1901
2030
|
const locals = viewRecord(view).children ?? [];
|
|
1902
|
-
target.length = locals.length;
|
|
1903
2031
|
for (let index = 0; index < locals.length; index++) target[index] = viewAt(state, locals[index]);
|
|
2032
|
+
truncate(target, locals.length);
|
|
2033
|
+
}
|
|
2034
|
+
function truncate(target, length) {
|
|
2035
|
+
if (target.length !== length) target.length = length;
|
|
1904
2036
|
}
|
|
1905
2037
|
function fillFromSnapshot(state, snapshot, local, target) {
|
|
1906
2038
|
const count = snapshot.childCount(local);
|
|
@@ -1909,17 +2041,17 @@ function fillFromSnapshot(state, snapshot, local, target) {
|
|
|
1909
2041
|
const views = state.views;
|
|
1910
2042
|
const isStrong = !state.adapterNodes;
|
|
1911
2043
|
const constructors = snapshotConstructors(snapshot);
|
|
1912
|
-
target.length = count;
|
|
1913
2044
|
for (let index = 0; index < count; index++) {
|
|
1914
2045
|
const child = childIds2[first + index];
|
|
1915
2046
|
let node = views[child] ?? (state.weakViews.size ? cachedView(state, child) : void 0);
|
|
1916
2047
|
if (node === void 0) {
|
|
1917
|
-
const constructor = isStrong && child < state.baseline && snapshot.
|
|
2048
|
+
const constructor = isStrong && child < state.baseline && snapshot.isPresent(child) && !snapshot.hasExtraFields(child) ? constructors(snapshot.typeReference(child)) : void 0;
|
|
1918
2049
|
if (constructor) views[child] = node = new constructor(state, child);
|
|
1919
2050
|
else node = viewAt(state, child);
|
|
1920
2051
|
}
|
|
1921
2052
|
target[index] = node;
|
|
1922
2053
|
}
|
|
2054
|
+
truncate(target, count);
|
|
1923
2055
|
}
|
|
1924
2056
|
function snapshotConstructors(snapshot) {
|
|
1925
2057
|
let lookup = snapshot.viewConstructors;
|
|
@@ -1942,7 +2074,7 @@ var snapshotField = (field) => ({
|
|
|
1942
2074
|
get() {
|
|
1943
2075
|
const state = this[VIEW_STATE];
|
|
1944
2076
|
const local = this[VIEW_LOCAL];
|
|
1945
|
-
const snapshot = plainSnapshot(state, local);
|
|
2077
|
+
const snapshot = field === "data" ? plainSnapshot(state, local) : structureSnapshot(state, local);
|
|
1946
2078
|
if (snapshot) return field === "type" ? snapshot.typeOf(local) : field === "name" ? snapshot.nameOf(local) : snapshot.dataOf(local);
|
|
1947
2079
|
return viewRecord(this)[field];
|
|
1948
2080
|
},
|
|
@@ -1955,7 +2087,7 @@ var pointerField = (field) => ({
|
|
|
1955
2087
|
get() {
|
|
1956
2088
|
const state = this[VIEW_STATE];
|
|
1957
2089
|
const local = this[VIEW_LOCAL];
|
|
1958
|
-
const snapshot =
|
|
2090
|
+
const snapshot = structureSnapshot(state, local);
|
|
1959
2091
|
return linkedView(this, snapshot ? snapshot.linkOf(local, linkOffsets[field]) : viewRecord(this)[field]);
|
|
1960
2092
|
},
|
|
1961
2093
|
set(value) {
|
|
@@ -2808,11 +2940,11 @@ function selectSimpleWithin(document, contexts, selector, options) {
|
|
|
2808
2940
|
}
|
|
2809
2941
|
var isElementType2 = (type) => type === "tag" || type === "script" || type === "style";
|
|
2810
2942
|
function typeAt(state, local) {
|
|
2811
|
-
const snapshot =
|
|
2943
|
+
const snapshot = structureSnapshot(state, local);
|
|
2812
2944
|
return snapshot ? snapshot.typeOf(local) : recordAt(state, local)?.type;
|
|
2813
2945
|
}
|
|
2814
2946
|
function pushChildren(state, local, stack) {
|
|
2815
|
-
const snapshot =
|
|
2947
|
+
const snapshot = structureSnapshot(state, local);
|
|
2816
2948
|
if (snapshot) {
|
|
2817
2949
|
for (let index = snapshot.childCount(local) - 1; index >= 0; index--) stack.push(snapshot.childAt(local, index));
|
|
2818
2950
|
return;
|
|
@@ -2828,7 +2960,7 @@ function sameMatchOptions(documentOptions, isXml, isLowerCaseTags, isLowerCaseAt
|
|
|
2828
2960
|
return isDocumentXml === isXml && (documentOptions.lowerCaseTags ?? !isDocumentXml) === isLowerCaseTags && (documentOptions.lowerCaseAttributeNames ?? !isDocumentXml) === isLowerCaseAttributes;
|
|
2829
2961
|
}
|
|
2830
2962
|
function matchesCompound(state, local, compound, isLowerCaseTags, isLowerCaseAttributes) {
|
|
2831
|
-
const snapshot =
|
|
2963
|
+
const snapshot = structureSnapshot(state, local);
|
|
2832
2964
|
const record = snapshot ? void 0 : recordAt(state, local);
|
|
2833
2965
|
if (!snapshot && !record) return false;
|
|
2834
2966
|
if (!isElementType2(snapshot ? snapshot.typeOf(local) : record.type)) return false;
|
|
@@ -3408,26 +3540,25 @@ var Cheerio = class {
|
|
|
3408
3540
|
}
|
|
3409
3541
|
/** @internal */
|
|
3410
3542
|
_insert(position, content) {
|
|
3543
|
+
if (typeof content[0] !== "function") {
|
|
3544
|
+
const ids = this.ids;
|
|
3545
|
+
if (ids.length) this.op("insert", { targetIds: ids, nodeIds: this._domIds(content), position });
|
|
3546
|
+
return this;
|
|
3547
|
+
}
|
|
3411
3548
|
const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this[DOCUMENT], id).type));
|
|
3412
3549
|
if (!targets.length)
|
|
3413
3550
|
return this;
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
});
|
|
3426
|
-
let nodes = this._domIds(content);
|
|
3427
|
-
if (targets[targets.length - 1] !== this.ids[this.ids.length - 1])
|
|
3428
|
-
nodes = this.op("clone", { ids: nodes, deep: true });
|
|
3429
|
-
this.op("insert", { targetIds: targets, nodeIds: nodes, position });
|
|
3430
|
-
return this;
|
|
3551
|
+
return this.each((index, node) => {
|
|
3552
|
+
if (!targets.includes(this.ids[index]))
|
|
3553
|
+
return;
|
|
3554
|
+
if ((position === "before" || position === "after") && nodeRecord(this[DOCUMENT], this.ids[index]).parent == null)
|
|
3555
|
+
return;
|
|
3556
|
+
const value = content[0].call(node, index, this[DOCUMENT].innerHtml(this.ids[index]));
|
|
3557
|
+
let nodes = this._domIds(value);
|
|
3558
|
+
if (index < this.length - 1)
|
|
3559
|
+
nodes = this.op("clone", { ids: nodes, deep: true });
|
|
3560
|
+
this.op("insert", { targetIds: [this.ids[index]], nodeIds: nodes, position });
|
|
3561
|
+
});
|
|
3431
3562
|
}
|
|
3432
3563
|
append(...content) {
|
|
3433
3564
|
return this._insert("append", content);
|
|
@@ -3607,28 +3738,30 @@ function plainKeys(map) {
|
|
|
3607
3738
|
return !import_node_util2.types.isProxy(map) && (Object.getPrototypeOf(map) === Object.prototype || Object.getPrototypeOf(map) === null) ? Object.keys(map) : void 0;
|
|
3608
3739
|
}
|
|
3609
3740
|
function nativePrefix(scope, map, keys, key) {
|
|
3610
|
-
if (!keys || scope
|
|
3741
|
+
if (!keys || !hasNativeExtraction(scope)) return void 0;
|
|
3742
|
+
const prefix = prefixPlan(map, keys, key, scope.options);
|
|
3743
|
+
if (!prefix) return void 0;
|
|
3744
|
+
return { keys: prefix.names, values: runPlan(scope, prefix.plan) };
|
|
3745
|
+
}
|
|
3746
|
+
function prefixPlan(map, keys, key, options) {
|
|
3611
3747
|
const prefix = /* @__PURE__ */ Object.create(null);
|
|
3612
|
-
let count = 0;
|
|
3613
3748
|
let plan;
|
|
3614
|
-
|
|
3615
|
-
for (let position = index; position < keys.length; position++) {
|
|
3749
|
+
for (let position = keys.indexOf(key); position < keys.length; position++) {
|
|
3616
3750
|
const name = keys[position];
|
|
3617
3751
|
const slot = Object.getOwnPropertyDescriptor(map, name);
|
|
3618
3752
|
if (!slot || !slot.enumerable || !("value" in slot)) break;
|
|
3619
3753
|
Object.defineProperty(prefix, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3620
|
-
const compiled2 = compileExtractPlan(prefix,
|
|
3754
|
+
const compiled2 = compileExtractPlan(prefix, options);
|
|
3621
3755
|
if (!compiled2) {
|
|
3622
3756
|
delete prefix[name];
|
|
3623
3757
|
break;
|
|
3624
3758
|
}
|
|
3625
3759
|
plan = compiled2;
|
|
3626
|
-
count++;
|
|
3627
3760
|
}
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
return
|
|
3761
|
+
return plan ? { names: Object.keys(prefix), plan } : void 0;
|
|
3762
|
+
}
|
|
3763
|
+
function hasNativeExtraction(scope) {
|
|
3764
|
+
return scope._make === nativeExtractionMethods.make && scope._findBySelector === nativeExtractionMethods.find && scope.prop === nativeExtractionMethods.prop && scope.extract === nativeExtractionMethods.extract;
|
|
3632
3765
|
}
|
|
3633
3766
|
function extract(map) {
|
|
3634
3767
|
const result = {};
|
|
@@ -3673,8 +3806,17 @@ function extract(map) {
|
|
|
3673
3806
|
return result;
|
|
3674
3807
|
}
|
|
3675
3808
|
function nativeRows(scope, key, all, selector, map) {
|
|
3809
|
+
if (!hasNativeExtraction(scope)) return void 0;
|
|
3810
|
+
const planned = rowsPlan(key, all, selector, map, scope.options);
|
|
3811
|
+
if (!planned) return void 0;
|
|
3812
|
+
const writes = writeCount();
|
|
3813
|
+
const extracted = runPlan(scope, planned.plan)[key];
|
|
3814
|
+
const rows = all ? extracted : extracted === void 0 ? [] : [extracted];
|
|
3815
|
+
return Array.isArray(rows) ? { keys: planned.nativeKeys, rows, writes } : void 0;
|
|
3816
|
+
}
|
|
3817
|
+
function rowsPlan(key, all, selector, map, options) {
|
|
3676
3818
|
const keys = plainKeys(map);
|
|
3677
|
-
if (!keys
|
|
3819
|
+
if (!keys) return void 0;
|
|
3678
3820
|
const subset = /* @__PURE__ */ Object.create(null);
|
|
3679
3821
|
const nativeKeys = /* @__PURE__ */ new Set();
|
|
3680
3822
|
for (const name of keys) {
|
|
@@ -3682,21 +3824,25 @@ function nativeRows(scope, key, all, selector, map) {
|
|
|
3682
3824
|
if (!slot || !slot.enumerable || !("value" in slot)) continue;
|
|
3683
3825
|
const single = /* @__PURE__ */ Object.create(null);
|
|
3684
3826
|
Object.defineProperty(single, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3685
|
-
if (!compileExtractPlan(single,
|
|
3827
|
+
if (!compileExtractPlan(single, options)) continue;
|
|
3686
3828
|
Object.defineProperty(subset, name, { value: slot.value, enumerable: true, configurable: true });
|
|
3687
3829
|
nativeKeys.add(name);
|
|
3688
3830
|
}
|
|
3689
3831
|
if (!nativeKeys.size || nativeKeys.size === keys.length) return void 0;
|
|
3690
3832
|
const outer = /* @__PURE__ */ Object.create(null);
|
|
3691
3833
|
Object.defineProperty(outer, key, { value: all ? [{ selector, value: subset }] : { selector, value: subset }, enumerable: true, configurable: true });
|
|
3692
|
-
const plan = compileExtractPlan(outer,
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3834
|
+
const plan = compileExtractPlan(outer, options);
|
|
3835
|
+
return plan ? { nativeKeys, plan } : void 0;
|
|
3836
|
+
}
|
|
3837
|
+
var preparedPlans = /* @__PURE__ */ new WeakMap();
|
|
3838
|
+
function runPlan(scope, plan) {
|
|
3839
|
+
const document = scope[DOCUMENT];
|
|
3840
|
+
const prepared = preparedPlans.get(document);
|
|
3841
|
+
const isRoot = prepared !== void 0 && prepared.writes === writeCount() && scope.ids.length === 1 && scope.ids[0] === document.rootId();
|
|
3842
|
+
const result = isRoot ? prepared.results.get(JSON.stringify(plan)) : void 0;
|
|
3843
|
+
const values = result !== void 0 ? JSON.parse(result) : scope.op("extractPlan", { ids: scope.ids, plan });
|
|
3696
3844
|
hydrateExtractResult(values, plan.entries);
|
|
3697
|
-
|
|
3698
|
-
const rows = all ? extracted : extracted === void 0 ? [] : [extracted];
|
|
3699
|
-
return Array.isArray(rows) ? { keys: nativeKeys, rows, writes } : void 0;
|
|
3845
|
+
return values;
|
|
3700
3846
|
}
|
|
3701
3847
|
function completeRow(scope, map, rows, index) {
|
|
3702
3848
|
const row = {};
|
|
@@ -3774,7 +3920,9 @@ var dom = {
|
|
|
3774
3920
|
isCDATA,
|
|
3775
3921
|
hasChildren
|
|
3776
3922
|
};
|
|
3923
|
+
var defaultOptions = { _useHtmlParser2: false };
|
|
3777
3924
|
function flattenOptions(options, base) {
|
|
3925
|
+
if (!options) return base ?? defaultOptions;
|
|
3778
3926
|
const result = { _useHtmlParser2: false, ...base, ...options };
|
|
3779
3927
|
if (options?.xml) {
|
|
3780
3928
|
result._useHtmlParser2 = true;
|