rusteerio 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +73 -0
- package/Cargo.lock +1051 -0
- package/Cargo.toml +36 -0
- package/LICENSE +21 -0
- package/README.md +252 -2
- package/RELEASING.md +138 -0
- package/THIRD_PARTY_NOTICES.md +7443 -0
- package/build.rs +3 -0
- package/dist/chunk-DKULX6VO.mjs +3185 -0
- package/dist/chunk-DKULX6VO.mjs.map +1 -0
- package/dist/chunk-OHPGEY3E.mjs +32 -0
- package/dist/chunk-OHPGEY3E.mjs.map +1 -0
- package/dist/index.cjs +3230 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +113 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.mjs +38 -0
- package/dist/index.mjs.map +1 -0
- package/dist/slim.cjs +2441 -0
- package/dist/slim.cjs.map +1 -0
- package/dist/slim.d.mts +11 -0
- package/dist/slim.d.ts +11 -0
- package/dist/slim.mjs +19 -0
- package/dist/slim.mjs.map +1 -0
- package/dist/types-BP6TpxE5.d.mts +532 -0
- package/dist/types-BP6TpxE5.d.ts +532 -0
- package/dist/utils.cjs +61 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.mts +13 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.mjs +17 -0
- package/dist/utils.mjs.map +1 -0
- package/native/src/arena.rs +1781 -0
- package/native/src/attributes.rs +923 -0
- package/native/src/codec.rs +172 -0
- package/native/src/diagnostics.rs +1249 -0
- package/native/src/extraction.rs +226 -0
- package/native/src/gc.rs +166 -0
- package/native/src/hook_sink.rs +727 -0
- package/native/src/hook_stream.rs +513 -0
- package/native/src/lib.rs +2095 -0
- package/native/src/location.rs +392 -0
- package/native/src/runtime.rs +189 -0
- package/native/src/selector.rs +1287 -0
- package/native/src/sink.rs +261 -0
- package/native/src/stream.rs +334 -0
- package/native/src/tokenizer.rs +355 -0
- package/native/src/tracker.rs +232 -0
- package/native/vendor/README.md +25 -0
- package/native/vendor/html5ever-0.35.0/.cargo_vcs_info.json +6 -0
- package/native/vendor/html5ever-0.35.0/Cargo.lock +828 -0
- package/native/vendor/html5ever-0.35.0/Cargo.toml +85 -0
- package/native/vendor/html5ever-0.35.0/LICENSE-APACHE +201 -0
- package/native/vendor/html5ever-0.35.0/LICENSE-MIT +25 -0
- package/native/vendor/html5ever-0.35.0/README.md +60 -0
- package/native/vendor/html5ever-0.35.0/benches/html5ever.rs +86 -0
- package/native/vendor/html5ever-0.35.0/data/bench/lipsum-zh.html +19 -0
- package/native/vendor/html5ever-0.35.0/data/bench/lipsum.html +40 -0
- package/native/vendor/html5ever-0.35.0/data/bench/medium-fragment.html +24 -0
- package/native/vendor/html5ever-0.35.0/data/bench/small-fragment.html +7 -0
- package/native/vendor/html5ever-0.35.0/data/bench/strong.html +1 -0
- package/native/vendor/html5ever-0.35.0/data/bench/tiny-fragment.html +1 -0
- package/native/vendor/html5ever-0.35.0/examples/arena.rs +356 -0
- package/native/vendor/html5ever-0.35.0/examples/capi/tokenize.c +74 -0
- package/native/vendor/html5ever-0.35.0/examples/noop-tokenize.rs +47 -0
- package/native/vendor/html5ever-0.35.0/examples/noop-tree-builder.rs +132 -0
- package/native/vendor/html5ever-0.35.0/examples/print-tree-actions.rs +185 -0
- package/native/vendor/html5ever-0.35.0/examples/tokenize.rs +111 -0
- package/native/vendor/html5ever-0.35.0/src/driver.rs +148 -0
- package/native/vendor/html5ever-0.35.0/src/lib.rs +30 -0
- package/native/vendor/html5ever-0.35.0/src/macros.rs +34 -0
- package/native/vendor/html5ever-0.35.0/src/serialize/mod.rs +255 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/char_ref/mod.rs +451 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/interface.rs +99 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/mod.rs +2305 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/states.rs +97 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/data.rs +170 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/mod.rs +1848 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/rules.rs +1494 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/tag_sets.rs +114 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/types.rs +91 -0
- package/native/vendor/html5ever-0.35.0/src/util/str.rs +52 -0
- package/native/vendor/html5gum-0.8.4/Cargo.lock +1006 -0
- package/native/vendor/html5gum-0.8.4/Cargo.toml +109 -0
- package/native/vendor/html5gum-0.8.4/LICENSE +19 -0
- package/native/vendor/html5gum-0.8.4/README.md +110 -0
- package/native/vendor/html5gum-0.8.4/benches/files/0050.html +2131 -0
- package/native/vendor/html5gum-0.8.4/benches/files/6D30.html +1004 -0
- package/native/vendor/html5gum-0.8.4/benches/files.rs +32 -0
- package/native/vendor/html5gum-0.8.4/benches/patterns.rs +31 -0
- package/native/vendor/html5gum-0.8.4/src/arrayvec.rs +29 -0
- package/native/vendor/html5gum-0.8.4/src/char_validator.rs +134 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/callback.rs +676 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/default.rs +207 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/emitter.rs +344 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/html5ever.rs +306 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/mod.rs +25 -0
- package/native/vendor/html5gum-0.8.4/src/entities.rs +3342 -0
- package/native/vendor/html5gum-0.8.4/src/error.rs +96 -0
- package/native/vendor/html5gum-0.8.4/src/htmlstring.rs +130 -0
- package/native/vendor/html5gum-0.8.4/src/lib.rs +66 -0
- package/native/vendor/html5gum-0.8.4/src/machine.rs +2136 -0
- package/native/vendor/html5gum-0.8.4/src/machine_helper.rs +277 -0
- package/native/vendor/html5gum-0.8.4/src/read_helper.rs +244 -0
- package/native/vendor/html5gum-0.8.4/src/reader.rs +440 -0
- package/native/vendor/html5gum-0.8.4/src/span.rs +98 -0
- package/native/vendor/html5gum-0.8.4/src/state.rs +16 -0
- package/native/vendor/html5gum-0.8.4/src/testutils.rs +71 -0
- package/native/vendor/html5gum-0.8.4/src/tokenizer.rs +189 -0
- package/native/vendor/html5gum-0.8.4/src/utils.rs +88 -0
- package/native/vendor/markup5ever-0.35.0/.cargo_vcs_info.json +6 -0
- package/native/vendor/markup5ever-0.35.0/Cargo.toml +45 -0
- package/native/vendor/markup5ever-0.35.0/LICENSE-APACHE +201 -0
- package/native/vendor/markup5ever-0.35.0/LICENSE-MIT +25 -0
- package/native/vendor/markup5ever-0.35.0/interface/mod.rs +422 -0
- package/native/vendor/markup5ever-0.35.0/interface/tree_builder.rs +280 -0
- package/native/vendor/markup5ever-0.35.0/lib.rs +59 -0
- package/native/vendor/markup5ever-0.35.0/serialize.rs +77 -0
- package/native/vendor/markup5ever-0.35.0/util/buffer_queue.rs +333 -0
- package/native/vendor/markup5ever-0.35.0/util/smallcharset.rs +88 -0
- package/package.json +137 -4
- 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/scripts/check-native.mjs +15 -0
- package/scripts/check-release.mjs +235 -0
- package/scripts/fix-declarations.mjs +27 -0
- package/scripts/generate-notices.mjs +176 -0
- package/scripts/notices/README.md +13 -0
- package/scripts/notices/cheerio-MIT.txt +21 -0
- package/scripts/notices/html5ever-AUTHORS.txt +20 -0
- package/scripts/notices/html5ever-COPYRIGHT.txt +8 -0
- package/scripts/notices/html5ever-LICENSE-APACHE.txt +201 -0
- package/scripts/notices/html5ever-LICENSE-MIT.txt +25 -0
- package/scripts/notices/napi-rs-MIT.txt +43 -0
- package/scripts/notices/neon-MIT.txt +19 -0
- package/scripts/notices/runtime-01c266bced4a434da005.txt +3 -0
- package/scripts/notices/runtime-0a54e647fe54104658b5.txt +14 -0
- package/scripts/notices/runtime-0b74dfa0bcee5c420c6b.txt +25 -0
- package/scripts/notices/runtime-0d542e0c8804e39aa7f3.txt +177 -0
- package/scripts/notices/runtime-0f96a83840e146e43c0e.txt +21 -0
- package/scripts/notices/runtime-123a331b5dbf04c30097.txt +25 -0
- package/scripts/notices/runtime-172020dbfd5b53a226df.txt +34 -0
- package/scripts/notices/runtime-209fbbe0ad52d9235e37.txt +26 -0
- package/scripts/notices/runtime-23f18e03dc49df91622f.txt +23 -0
- package/scripts/notices/runtime-268872b9816f90fd8e85.txt +220 -0
- package/scripts/notices/runtime-35242e7a83f69875e6ed.txt +176 -0
- package/scripts/notices/runtime-378f5840b258e2779c39.txt +25 -0
- package/scripts/notices/runtime-4108245a1f2df9d4e94d.txt +25 -0
- package/scripts/notices/runtime-4455bf75a91154108304.txt +21 -0
- package/scripts/notices/runtime-553fffcd9b1cb158bc3e.txt +13 -0
- package/scripts/notices/runtime-62c7a1e35f56406896d7.txt +176 -0
- package/scripts/notices/runtime-6485b8ed310d3f0340bf.txt +25 -0
- package/scripts/notices/runtime-69fef7b0f322a6555415.txt +201 -0
- package/scripts/notices/runtime-6df43f6f4b5d4587f3d8.txt +187 -0
- package/scripts/notices/runtime-799e9ca9d179295ef372.txt +24 -0
- package/scripts/notices/runtime-7b63ecd5f1902af1b637.txt +25 -0
- package/scripts/notices/runtime-7bc7d5de2a0b793d4e1a.txt +21 -0
- package/scripts/notices/runtime-7e12e5df4bae12cb2158.txt +24 -0
- package/scripts/notices/runtime-861399f8c21c042b1105.txt +12 -0
- package/scripts/notices/runtime-8ada45cd9f843acf64e4.txt +201 -0
- package/scripts/notices/runtime-90eb64f0279b0d9432ac.txt +12 -0
- package/scripts/notices/runtime-a60eea817514531668d7.txt +201 -0
- package/scripts/notices/runtime-a7c936ff1ed8fa340172.txt +25 -0
- package/scripts/notices/runtime-ab6eec6caf0fa5775e41.txt +275 -0
- package/scripts/notices/runtime-b1181a40b2a7b25cf66f.txt +19 -0
- package/scripts/notices/runtime-b71bd43a069ca0641a9e.txt +25 -0
- package/scripts/notices/runtime-c16f8dcf1a368b83be78.txt +201 -0
- package/scripts/notices/runtime-c2cfccb812fe482101a8.txt +21 -0
- package/scripts/notices/runtime-e99d88d232bf57d70f0f.txt +25 -0
- package/scripts/notices/runtime-f32fb3b417a194167cfa.txt +9 -0
- package/scripts/notices/runtime-f5062c9a188d81dfe66b.txt +39 -0
- package/scripts/notices/runtime-f9070a832833fa7488fd.txt +4 -0
- package/scripts/notices/runtime-fab3dd6bdab226f1c086.txt +373 -0
- package/scripts/notices/runtime-fba3318d0c600380177e.txt +62 -0
- package/scripts/notices/runtime-ff8f68cb076caf8cefe7.txt +25 -0
- package/scripts/notices/runtime-ff92bed461f50338dd70.txt +74 -0
- package/scripts/notices/runtime.json +1632 -0
- package/scripts/notices/sources.json +555 -0
- package/scripts/notices/xray-MIT.txt +21 -0
- package/src/attributes.ts +271 -0
- package/src/codec.ts +74 -0
- package/src/dom.ts +87 -0
- package/src/extract-plan.ts +97 -0
- package/src/extract.ts +130 -0
- package/src/hooks.ts +220 -0
- package/src/index.ts +223 -0
- package/src/io.ts +491 -0
- package/src/native.ts +135 -0
- package/src/nodes.ts +290 -0
- package/src/parse.ts +53 -0
- package/src/parser-types.ts +157 -0
- package/src/router.ts +327 -0
- package/src/selection.ts +566 -0
- package/src/slim.ts +12 -0
- package/src/transport.ts +104 -0
- package/src/types.ts +186 -0
- package/src/utils.ts +29 -0
- package/src/workers.ts +21 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +16 -0
package/src/selection.ts
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import type { AnyNode, Document, Element, ParentNode, CheerioAPI, CheerioOptions, AcceptedFilters, BasicAcceptedElems, AcceptedElems, ExtractMap, ExtractedMap } from './types.js';
|
|
2
|
+
import { requireNative, type NativeDocument } from './native.js';
|
|
3
|
+
import { getNode, importNodes, nodeBinding, nodeId, nodeRecord, operation, isTag } from './nodes.js';
|
|
4
|
+
import { installAttributes, type AttributeMethods } from './attributes.js';
|
|
5
|
+
import { extract } from './extract.js';
|
|
6
|
+
import { sameNodeSpace, retainNodes } from './router.js';
|
|
7
|
+
import { parse } from './parse.js';
|
|
8
|
+
const numeric = /^(?:0|[1-9]\d*)$/;
|
|
9
|
+
const isMarkup = (value: string) => /<[a-zA-Z!/?]/.test(value);
|
|
10
|
+
function* customPseudoArguments(selector: string, name: string): Generator<string | undefined> {
|
|
11
|
+
let attributeDepth = 0;
|
|
12
|
+
let quote = '';
|
|
13
|
+
for (let index = 0; index < selector.length; index++) {
|
|
14
|
+
const character = selector[index];
|
|
15
|
+
if (character === '\\') {
|
|
16
|
+
index++;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (quote) {
|
|
20
|
+
if (character === quote)
|
|
21
|
+
quote = '';
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (character === '"' || character === "'") {
|
|
25
|
+
quote = character;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (character === '[') {
|
|
29
|
+
attributeDepth++;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (character === ']') {
|
|
33
|
+
attributeDepth--;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (attributeDepth || character !== ':' || selector[index - 1] === ':')
|
|
37
|
+
continue;
|
|
38
|
+
const start = index + 1;
|
|
39
|
+
let end = start;
|
|
40
|
+
while (/[\w-]/.test(selector[end] ?? '') && end < selector.length)
|
|
41
|
+
end++;
|
|
42
|
+
if (selector.slice(start, end).toLowerCase() !== name.toLowerCase())
|
|
43
|
+
continue;
|
|
44
|
+
index = end - 1;
|
|
45
|
+
if (selector[end] !== '(') {
|
|
46
|
+
yield undefined;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const argumentStart = end + 1;
|
|
50
|
+
let depth = 1;
|
|
51
|
+
let argumentQuote = '';
|
|
52
|
+
for (end++; end < selector.length; end++) {
|
|
53
|
+
const next = selector[end];
|
|
54
|
+
if (next === '\\') {
|
|
55
|
+
end++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (argumentQuote) {
|
|
59
|
+
if (next === argumentQuote)
|
|
60
|
+
argumentQuote = '';
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (next === '"' || next === "'") {
|
|
64
|
+
argumentQuote = next;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (next === '(')
|
|
68
|
+
depth++;
|
|
69
|
+
else if (next === ')' && --depth === 0)
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (depth)
|
|
73
|
+
continue; // The native selector parser reports malformed syntax.
|
|
74
|
+
yield selector.slice(argumentStart, end);
|
|
75
|
+
index = end;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** An array-like selection of stable handles into the Rust document arena. */
|
|
79
|
+
export class Cheerio<T = AnyNode> implements ArrayLike<T>, Iterable<T> {
|
|
80
|
+
[index: number]: T;
|
|
81
|
+
/** @internal */ declare _document: NativeDocument;
|
|
82
|
+
/** @internal */ declare _api: CheerioAPI;
|
|
83
|
+
/** @internal */ declare _ids: number[];
|
|
84
|
+
/** @internal */ declare _values: T[] | undefined;
|
|
85
|
+
/** @internal */ declare _lease: object;
|
|
86
|
+
declare options: CheerioOptions;
|
|
87
|
+
declare _root: Cheerio<Document> | null;
|
|
88
|
+
declare prevObject: Cheerio<any> | undefined;
|
|
89
|
+
declare length: number;
|
|
90
|
+
cheerio = '[cheerio object]' as const;
|
|
91
|
+
constructor(api: CheerioAPI, document: NativeDocument, ids: number[] = [], root: Cheerio<Document> | null = null, options: CheerioOptions = {}, values?: T[]) {
|
|
92
|
+
Object.defineProperties(this, {
|
|
93
|
+
_document: { value: document, writable: true, configurable: true },
|
|
94
|
+
_api: { value: api, writable: true, configurable: true },
|
|
95
|
+
_ids: { value: ids, writable: true, configurable: true },
|
|
96
|
+
_values: { value: values, writable: true, configurable: true },
|
|
97
|
+
_lease: { value: retainNodes(document, ids), writable: true, configurable: true },
|
|
98
|
+
options: { value: options, writable: true, configurable: true, enumerable: true },
|
|
99
|
+
_root: { value: root, writable: true, configurable: true, enumerable: true },
|
|
100
|
+
length: { configurable: true, enumerable: true, get: () => this._values?.length ?? this._ids.length, set: (value: number) => { if (this._values)
|
|
101
|
+
this._values.length = value;
|
|
102
|
+
else
|
|
103
|
+
this._ids.length = value; this._lease = retainNodes(document, this._values ? [] : this._ids); } },
|
|
104
|
+
});
|
|
105
|
+
delete (this as any).cheerio;
|
|
106
|
+
return new Proxy(this, {
|
|
107
|
+
get: (target, property, receiver) => typeof property === 'string' && numeric.test(property)
|
|
108
|
+
? (target._values ? target._values[Number(property)] : target._ids[Number(property)] === undefined ? undefined : getNode(document, target._ids[Number(property)]))
|
|
109
|
+
: Reflect.get(target, property, receiver),
|
|
110
|
+
set: (target, property, value, receiver) => {
|
|
111
|
+
if (typeof property === 'string' && numeric.test(property)) {
|
|
112
|
+
if (target._values)
|
|
113
|
+
target._values[Number(property)] = value;
|
|
114
|
+
else {
|
|
115
|
+
const id = importNodes(document, [value])[0];
|
|
116
|
+
if (id === undefined) {
|
|
117
|
+
target._values = target._ids.map((existing) => getNode(document, existing)) as T[];
|
|
118
|
+
target._values[Number(property)] = value;
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
target._ids[Number(property)] = id;
|
|
122
|
+
}
|
|
123
|
+
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
return Reflect.set(target, property, value, receiver);
|
|
127
|
+
},
|
|
128
|
+
has: (target, property) => typeof property === 'string' && numeric.test(property) ? Number(property) < target.length : Reflect.has(target, property),
|
|
129
|
+
ownKeys: (target) => [...Array.from({ length: target.length }, (_, i) => String(i)), ...Reflect.ownKeys(target)],
|
|
130
|
+
getOwnPropertyDescriptor: (target, property) => typeof property === 'string' && numeric.test(property) && Number(property) < target.length
|
|
131
|
+
? { value: target._values ? target._values[Number(property)] : getNode(document, target._ids[Number(property)]), writable: true, configurable: true, enumerable: true }
|
|
132
|
+
: Reflect.getOwnPropertyDescriptor(target, property),
|
|
133
|
+
deleteProperty: (target, property) => {
|
|
134
|
+
if (typeof property === 'string' && numeric.test(property)) {
|
|
135
|
+
if (target._values)
|
|
136
|
+
delete target._values[Number(property)];
|
|
137
|
+
else
|
|
138
|
+
delete target._ids[Number(property)];
|
|
139
|
+
target._lease = retainNodes(document, target._values ? [] : target._ids);
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return Reflect.deleteProperty(target, property);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** @internal */ get ids(): number[] { return this._values ? importNodes(this._document, this._values) : this._ids; }
|
|
147
|
+
/** @internal */ op<R = any>(command: string, args: unknown = {}): R { const values = args as Record<string, unknown>; return operation<R>(this._document, command, { ...values, options: values.options ?? this.options }); }
|
|
148
|
+
/** @internal */ _query(command: 'select' | 'matches', args: {
|
|
149
|
+
selector: string;
|
|
150
|
+
ids?: number[];
|
|
151
|
+
contexts?: number[];
|
|
152
|
+
options?: CheerioOptions;
|
|
153
|
+
}): number[] {
|
|
154
|
+
const callbacks = Object.entries(this.options.pseudos ?? {}).filter((entry): entry is [
|
|
155
|
+
string,
|
|
156
|
+
(element: Element, argument?: string | null) => boolean
|
|
157
|
+
] => typeof entry[1] === 'function');
|
|
158
|
+
if (!callbacks.length)
|
|
159
|
+
return command === 'select' && !args.options ? this._document.select(args.selector, args.contexts) : this.op(command, args);
|
|
160
|
+
const pseudoMatches: Record<string, number[]> = {};
|
|
161
|
+
const candidates = [...new Set([...this._document.select('*'), ...(args.ids ?? []), ...(args.contexts ? this._document.select('*', args.contexts) : [])])];
|
|
162
|
+
for (const [name, callback] of callbacks) {
|
|
163
|
+
for (const argument of customPseudoArguments(args.selector, name)) {
|
|
164
|
+
if (argument !== undefined && callback.length < 2)
|
|
165
|
+
throw new Error(`Pseudo-class :${name} doesn't have any arguments`);
|
|
166
|
+
if (argument === undefined && callback.length >= 2)
|
|
167
|
+
throw new Error(`Pseudo-class :${name} requires an argument`);
|
|
168
|
+
pseudoMatches[`${name}(${argument ?? ''})`] = candidates.filter((id) => callback(getNode(this._document, id) as Element, argument ?? null));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return this.op(command, { ...args, pseudoMatches });
|
|
172
|
+
}
|
|
173
|
+
/** @internal */ _fromIds<R = AnyNode>(ids: number[]): Cheerio<R> {
|
|
174
|
+
const result = new (this._api.fn.constructor as typeof Cheerio)<R>(this._api, this._document, ids, this._root, this.options);
|
|
175
|
+
result.prevObject = this;
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
/** @internal */ _fromValues<R>(values: R[]): Cheerio<R> {
|
|
179
|
+
const allNodes = values.every((value: any) => value && typeof value === 'object' && typeof value.type === 'string');
|
|
180
|
+
const result = new (this._api.fn.constructor as typeof Cheerio)<R>(this._api, this._document, allNodes ? importNodes(this._document, values) : [], this._root, this.options, allNodes ? undefined : values);
|
|
181
|
+
result.prevObject = this;
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
_make<R>(value: ArrayLike<R> | R | string, context?: BasicAcceptedElems<AnyNode>): Cheerio<R>;
|
|
185
|
+
_make<R>(value: any, context?: any): Cheerio<R> {
|
|
186
|
+
const result = typeof value === 'string' || value?.cheerio ? this._api(value, context) : this._fromValues<R>(value == null ? [] : typeof value === 'object' && 'length' in value && !value.type ? Array.from(value) : [value]);
|
|
187
|
+
result.prevObject = this;
|
|
188
|
+
return result as Cheerio<R>;
|
|
189
|
+
}
|
|
190
|
+
_parse(content: any, options: CheerioOptions, isDocument: boolean, context: ParentNode | null): Document {
|
|
191
|
+
return parse(content, options, isDocument, context);
|
|
192
|
+
}
|
|
193
|
+
_render(content: any): string { return this._document.outerHtml(importNodes(this._document, content)); }
|
|
194
|
+
/** @internal */ _domIds(content: any, contextId?: number): number[] {
|
|
195
|
+
if (content == null || content === false)
|
|
196
|
+
return [];
|
|
197
|
+
if (typeof content === 'string')
|
|
198
|
+
return this.op('create', { html: content, contextId, options: this.options });
|
|
199
|
+
if (content?.cheerio)
|
|
200
|
+
return content._document && sameNodeSpace(this._document, content._document) ? content.ids : importNodes(this._document, content.toArray());
|
|
201
|
+
if (typeof content === 'object' && 'length' in content && !content.type)
|
|
202
|
+
return Array.from(content as ArrayLike<any>).flatMap((item) => this._domIds(item, contextId));
|
|
203
|
+
return importNodes(this._document, [content]);
|
|
204
|
+
}
|
|
205
|
+
_makeDomArray<T extends AnyNode>(this: Cheerio<T>, elem?: BasicAcceptedElems<AnyNode> | BasicAcceptedElems<AnyNode>[], clone?: boolean): AnyNode[];
|
|
206
|
+
_makeDomArray(this: Cheerio<any>, content: any, clone: any = false): any {
|
|
207
|
+
const ids = this._domIds(content);
|
|
208
|
+
return (clone ? this.op<number[]>('clone', { ids, deep: true }) : ids).map((id) => getNode(this._document, id));
|
|
209
|
+
}
|
|
210
|
+
find<T extends AnyNode>(this: Cheerio<T>, selectorOrHaystack?: string | Cheerio<Element> | Element): Cheerio<Element>;
|
|
211
|
+
find(this: Cheerio<any>, selector?: any): any {
|
|
212
|
+
if (!selector)
|
|
213
|
+
return this._fromIds([]);
|
|
214
|
+
if (typeof selector === 'string')
|
|
215
|
+
return this._findBySelector(selector, Infinity);
|
|
216
|
+
const ids = importNodes(this._document, selector);
|
|
217
|
+
return this._fromIds(ids.filter((id) => this.ids.some((container) => this.op<boolean>('contains', { container, contained: id }))));
|
|
218
|
+
}
|
|
219
|
+
_findBySelector<T extends AnyNode>(this: Cheerio<T>, selector: string, limit: number): Cheerio<Element>;
|
|
220
|
+
_findBySelector(this: Cheerio<any>, selector: any, limit: any): any {
|
|
221
|
+
const ids = this._query('select', { selector, contexts: this.ids });
|
|
222
|
+
return this._fromIds(Number.isFinite(limit) ? ids.slice(0, limit) : ids);
|
|
223
|
+
}
|
|
224
|
+
/** @internal */ _filterIds(ids: number[], selector?: any): number[] {
|
|
225
|
+
if (!selector)
|
|
226
|
+
return ids;
|
|
227
|
+
if (typeof selector === 'string')
|
|
228
|
+
return this._query('matches', { ids, selector, options: this.options });
|
|
229
|
+
return ids.filter((id, index) => this._predicate(selector, getNode(this._document, id), index));
|
|
230
|
+
}
|
|
231
|
+
/** @internal */ _predicate(selector: any, node: any, index: number): boolean {
|
|
232
|
+
if (typeof selector === 'function')
|
|
233
|
+
return !!selector.call(node, index, node);
|
|
234
|
+
if (typeof selector === 'string')
|
|
235
|
+
return this._query('matches', { ids: importNodes(this._document, [node]), selector, options: this.options }).length > 0;
|
|
236
|
+
if (selector?.cheerio)
|
|
237
|
+
return selector.toArray().includes(node);
|
|
238
|
+
return node === selector;
|
|
239
|
+
}
|
|
240
|
+
/** @internal */ _traverse(kind: string, selector?: any): Cheerio<Element> {
|
|
241
|
+
let ids = this.op<number[]>('traverse', { ids: this.ids, kind });
|
|
242
|
+
ids = this._filterIds(ids, selector);
|
|
243
|
+
if (this.length > 1 && ids.length > 1) {
|
|
244
|
+
if (kind === 'parents' || kind === 'siblings')
|
|
245
|
+
ids = this.op('uniqueSort', { ids });
|
|
246
|
+
else if (!['next', 'prev', 'contents'].includes(kind))
|
|
247
|
+
ids = [...new Set(ids)];
|
|
248
|
+
if (kind === 'parents')
|
|
249
|
+
ids.reverse();
|
|
250
|
+
}
|
|
251
|
+
return this._fromIds(ids);
|
|
252
|
+
}
|
|
253
|
+
parent<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
254
|
+
parent(this: Cheerio<any>, selector?: any): any { return this._traverse('parent', selector); }
|
|
255
|
+
parents<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
256
|
+
parents(this: Cheerio<any>, selector?: any): any { return this._traverse('parents', selector); }
|
|
257
|
+
next<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
258
|
+
next(this: Cheerio<any>, selector?: any): any { return this._traverse('next', selector); }
|
|
259
|
+
prev<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
260
|
+
prev(this: Cheerio<any>, selector?: any): any { return this._traverse('prev', selector); }
|
|
261
|
+
nextAll<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
262
|
+
nextAll(this: Cheerio<any>, selector?: any): any { return this._traverse('nextAll', selector); }
|
|
263
|
+
prevAll<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
264
|
+
prevAll(this: Cheerio<any>, selector?: any): any { return this._traverse('prevAll', selector); }
|
|
265
|
+
siblings<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
266
|
+
siblings(this: Cheerio<any>, selector?: any): any { return this._traverse('siblings', selector); }
|
|
267
|
+
children<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
268
|
+
children(this: Cheerio<any>, selector?: any): any { return this._traverse('children', selector); }
|
|
269
|
+
contents<T extends AnyNode>(this: Cheerio<T>): Cheerio<AnyNode>;
|
|
270
|
+
contents(this: Cheerio<any>): any { return this._traverse('contents') as any; }
|
|
271
|
+
/** @internal */ _until(kind: string, until?: any, filter?: any): Cheerio<Element> {
|
|
272
|
+
let ids: number[] = [];
|
|
273
|
+
for (const id of this.ids)
|
|
274
|
+
for (const candidate of this.op<number[]>('traverse', { ids: [id], kind })) {
|
|
275
|
+
if (until && this._predicate(until, getNode(this._document, candidate), ids.length))
|
|
276
|
+
break;
|
|
277
|
+
ids.push(candidate);
|
|
278
|
+
}
|
|
279
|
+
ids = this._filterIds(ids, filter);
|
|
280
|
+
if (this.length > 1 && ids.length > 1)
|
|
281
|
+
ids = kind === 'parents' ? this.op<number[]>('uniqueSort', { ids }).reverse() : [...new Set(ids)];
|
|
282
|
+
return this._fromIds(ids);
|
|
283
|
+
}
|
|
284
|
+
parentsUntil<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
285
|
+
parentsUntil(this: Cheerio<any>, until?: any, filter?: any): any { return this._until('parents', until, filter); }
|
|
286
|
+
nextUntil<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
287
|
+
nextUntil(this: Cheerio<any>, until?: any, filter?: any): any { return this._until('nextAll', until, filter); }
|
|
288
|
+
prevUntil<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>): Cheerio<Element>;
|
|
289
|
+
prevUntil(this: Cheerio<any>, until?: any, filter?: any): any { return this._until('prevAll', until, filter); }
|
|
290
|
+
closest<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<AnyNode>;
|
|
291
|
+
closest(this: Cheerio<any>, selector?: any): any {
|
|
292
|
+
if (!selector)
|
|
293
|
+
return this._fromIds([]);
|
|
294
|
+
const result: number[] = [];
|
|
295
|
+
for (const id of this.ids) {
|
|
296
|
+
const record = nodeRecord(this._document, id);
|
|
297
|
+
const candidates = [...(['tag', 'script', 'style'].includes(record.type) ? [id] : []), ...this.op<number[]>('traverse', { ids: [id], kind: 'parents' })];
|
|
298
|
+
const match = candidates.find((candidate) => this._predicate(selector, getNode(this._document, candidate), 0));
|
|
299
|
+
if (match !== undefined && !result.includes(match))
|
|
300
|
+
result.push(match);
|
|
301
|
+
}
|
|
302
|
+
return this._fromIds(result);
|
|
303
|
+
}
|
|
304
|
+
each<T>(this: Cheerio<T>, fn: (this: T, i: number, el: T) => void | boolean): Cheerio<T>;
|
|
305
|
+
each(this: Cheerio<any>, callback: any): any {
|
|
306
|
+
const length = this.length;
|
|
307
|
+
for (let i = 0; i < length; i++)
|
|
308
|
+
if (callback.call(this[i], i, this[i]) === false)
|
|
309
|
+
break;
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
map<T, M>(this: Cheerio<T>, fn: (this: T, i: number, el: T) => M[] | M | null | undefined): Cheerio<M>;
|
|
313
|
+
map<R>(this: Cheerio<any>, callback: any): any {
|
|
314
|
+
const result: R[] = [];
|
|
315
|
+
for (let i = 0; i < this.length; i++) {
|
|
316
|
+
const value = callback.call(this[i], i, this[i]);
|
|
317
|
+
if (value != null)
|
|
318
|
+
result.push(...(Array.isArray(value) ? value : [value]));
|
|
319
|
+
}
|
|
320
|
+
return this._fromValues(result);
|
|
321
|
+
}
|
|
322
|
+
filter<T, S extends T>(this: Cheerio<T>, match: (this: T, index: number, value: T) => value is S): Cheerio<S>;
|
|
323
|
+
filter<T, S extends AcceptedFilters<T>>(this: Cheerio<T>, match: S): Cheerio<S extends string ? Element : T>;
|
|
324
|
+
filter<S extends AcceptedFilters<T>>(this: Cheerio<any>, selector: any): any {
|
|
325
|
+
return (typeof selector === 'string' ? this._fromIds(this._query('matches', { ids: this.ids, selector, options: this.options })) : this._fromValues(this.toArray().filter((node, i) => this._predicate(selector, node, i)))) as any;
|
|
326
|
+
}
|
|
327
|
+
filterArray<T>(nodes: T[], match: AcceptedFilters<T>, xmlMode?: boolean, root?: Document): Element[] | T[];
|
|
328
|
+
filterArray<R>(this: Cheerio<any>, nodes: any, match: any, xmlMode?: any, root?: any): any {
|
|
329
|
+
const matcher: any = match;
|
|
330
|
+
if (typeof match !== 'string')
|
|
331
|
+
return nodes.filter((node: any, index: number) => typeof matcher === 'function' ? matcher.call(node, index, node) : matcher?.cheerio ? matcher.toArray().includes(node) : matcher === node);
|
|
332
|
+
const document = this?._document ?? nodeBinding(root)?.document ?? nodeBinding(nodes[0])?.document ?? new (requireNative().NativeDocument)('', false);
|
|
333
|
+
const ids = importNodes(document, nodes);
|
|
334
|
+
const selected = new Set(operation<number[]>(document, 'matches', { ids, selector: match, options: { xmlMode } }));
|
|
335
|
+
return nodes.filter((node: any) => { const id = nodeId(node, document); return id !== undefined && selected.has(id); });
|
|
336
|
+
}
|
|
337
|
+
not<T extends AnyNode>(this: Cheerio<T>, match: AcceptedFilters<T>): Cheerio<T>;
|
|
338
|
+
not(this: Cheerio<any>, selector: any): any {
|
|
339
|
+
if (typeof selector === 'string') {
|
|
340
|
+
const matched = new Set(this._query('matches', { ids: this.ids, selector, options: this.options }));
|
|
341
|
+
return this._fromIds(this.ids.filter((id) => !matched.has(id)));
|
|
342
|
+
}
|
|
343
|
+
return this._fromValues(this.toArray().filter((node, i) => !this._predicate(selector, node, i)));
|
|
344
|
+
}
|
|
345
|
+
is<T>(this: Cheerio<T>, selector?: AcceptedFilters<T>): boolean;
|
|
346
|
+
is(this: Cheerio<any>, selector?: any): any {
|
|
347
|
+
return typeof selector === 'string' ? this._query('matches', { ids: this.ids, selector, options: this.options }).length > 0 : !!selector && this.toArray().some((node, i) => this._predicate(selector, node, i));
|
|
348
|
+
}
|
|
349
|
+
has(this: Cheerio<AnyNode | Element>, selectorOrHaystack: string | Cheerio<Element> | Element): Cheerio<AnyNode | Element>;
|
|
350
|
+
has(this: Cheerio<any>, selector: any): any { return this.filter(((_i: number, node: any) => this._make(node).find(selector).length > 0) as any) as Cheerio<T>; }
|
|
351
|
+
first<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
|
|
352
|
+
first(this: Cheerio<any>): any { return this.length > 1 ? this.slice(0, 1) : this; }
|
|
353
|
+
last<T>(this: Cheerio<T>): Cheerio<T>;
|
|
354
|
+
last(this: Cheerio<any>): any { return this.length > 0 ? this.slice(-1) : this; }
|
|
355
|
+
eq<T>(this: Cheerio<T>, i: number): Cheerio<T>;
|
|
356
|
+
eq(this: Cheerio<any>, index: any): any {
|
|
357
|
+
index = +index;
|
|
358
|
+
if (index === 0 && this.length <= 1)
|
|
359
|
+
return this;
|
|
360
|
+
if (index < 0)
|
|
361
|
+
index += this.length;
|
|
362
|
+
return this._fromValues(this[index] === undefined ? [] : [this[index]]);
|
|
363
|
+
}
|
|
364
|
+
get<T>(this: Cheerio<T>, i: number): T | undefined;
|
|
365
|
+
get<T>(this: Cheerio<T>): T[];
|
|
366
|
+
get(this: Cheerio<any>, index?: any): any { return index == null ? this.toArray() : this[index < 0 ? this.length + index : index]; }
|
|
367
|
+
toArray<T>(this: Cheerio<T>): T[];
|
|
368
|
+
toArray(this: Cheerio<any>): any { return Array.from({ length: this.length }, (_unused, i) => this[i]); }
|
|
369
|
+
slice<T>(this: Cheerio<T>, start?: number, end?: number): Cheerio<T>;
|
|
370
|
+
slice(this: Cheerio<any>, start?: any, end?: any): any { return this._values ? this._fromValues(this._values.slice(start, end)) : this._fromIds(this._ids.slice(start, end)); }
|
|
371
|
+
end<T>(this: Cheerio<T>): Cheerio<AnyNode>;
|
|
372
|
+
end(this: Cheerio<any>): any { return this.prevObject ?? this._make([]); }
|
|
373
|
+
add<S extends AnyNode, T extends AnyNode>(this: Cheerio<T>, other: string | Cheerio<S> | S | S[], context?: Cheerio<S> | string): Cheerio<S | T>;
|
|
374
|
+
add<R extends AnyNode>(this: Cheerio<any>, other: any, context?: any): any { return this._fromIds(this.op('uniqueSort', { ids: [...this.ids, ...this._api(other, context).ids] })); }
|
|
375
|
+
addBack<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<AnyNode>;
|
|
376
|
+
addBack(this: Cheerio<any>, selector?: any): any { return this.prevObject ? this.add(selector ? this.prevObject.filter(selector) : this.prevObject) as any : this as any; }
|
|
377
|
+
index<T extends AnyNode>(this: Cheerio<T>, selectorOrNeedle?: string | Cheerio<AnyNode> | AnyNode): number;
|
|
378
|
+
index(this: Cheerio<any>, selector?: any): any { const haystack = selector == null ? this.parent().children() : typeof selector === 'string' ? this._api(selector) : this; const needle = selector == null || typeof selector === 'string' ? this[0] : selector?.cheerio ? selector[0] : selector; return haystack.toArray().indexOf(needle); }
|
|
379
|
+
splice(start: number, deleteCount?: number): any[];
|
|
380
|
+
splice(start: number, deleteCount: number, ...items: any[]): any[];
|
|
381
|
+
splice(...args: any[]): any[] { return Reflect.apply(Array.prototype.splice, this, args); }
|
|
382
|
+
[Symbol.iterator](): Iterator<T>;
|
|
383
|
+
*[Symbol.iterator](): IterableIterator<T> { for (let i = 0; i < this.length; i++)
|
|
384
|
+
yield this[i]; }
|
|
385
|
+
/** @internal */ _insert(position: string, content: any[]): this {
|
|
386
|
+
const targets = this.ids.filter((id) => ['root', 'tag', 'script', 'style', 'cdata'].includes(nodeRecord(this._document, id).type));
|
|
387
|
+
if (!targets.length)
|
|
388
|
+
return this;
|
|
389
|
+
if (typeof content[0] === 'function')
|
|
390
|
+
return (this as Cheerio<any>).each((index, node: any) => {
|
|
391
|
+
if (!targets.includes(this.ids[index]))
|
|
392
|
+
return;
|
|
393
|
+
if ((position === 'before' || position === 'after') && nodeRecord(this._document, this.ids[index]).parent == null)
|
|
394
|
+
return;
|
|
395
|
+
const value = content[0].call(node, index, this._document.innerHtml(this.ids[index]));
|
|
396
|
+
let nodes = this._domIds(value);
|
|
397
|
+
if (index < this.length - 1)
|
|
398
|
+
nodes = this.op('clone', { ids: nodes, deep: true });
|
|
399
|
+
this.op('insert', { targetIds: [this.ids[index]], nodeIds: nodes, position });
|
|
400
|
+
}) as this;
|
|
401
|
+
let nodes = this._domIds(content);
|
|
402
|
+
if (targets[targets.length - 1] !== this.ids[this.ids.length - 1])
|
|
403
|
+
nodes = this.op('clone', { ids: nodes, deep: true });
|
|
404
|
+
this.op('insert', { targetIds: targets, nodeIds: nodes, position });
|
|
405
|
+
return this;
|
|
406
|
+
}
|
|
407
|
+
append<T extends AnyNode>(this: Cheerio<T>, ...elems: [
|
|
408
|
+
(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>
|
|
409
|
+
] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
|
|
410
|
+
append(this: Cheerio<any>, ...content: any[]): any { return this._insert('append', content); }
|
|
411
|
+
prepend<T extends AnyNode>(this: Cheerio<T>, ...elems: [
|
|
412
|
+
(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>
|
|
413
|
+
] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
|
|
414
|
+
prepend(this: Cheerio<any>, ...content: any[]): any { return this._insert('prepend', content); }
|
|
415
|
+
before<T extends AnyNode>(this: Cheerio<T>, ...elems: [
|
|
416
|
+
(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>
|
|
417
|
+
] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
|
|
418
|
+
before(this: Cheerio<any>, ...content: any[]): any { return this._insert('before', content); }
|
|
419
|
+
after<T extends AnyNode>(this: Cheerio<T>, ...elems: [
|
|
420
|
+
(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>
|
|
421
|
+
] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
|
|
422
|
+
after(this: Cheerio<any>, ...content: any[]): any { return this._insert('after', content); }
|
|
423
|
+
appendTo<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
|
|
424
|
+
appendTo(this: Cheerio<any>, target: any): any { this._api(target).append(this); return this; }
|
|
425
|
+
prependTo<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
|
|
426
|
+
prependTo(this: Cheerio<any>, target: any): any { this._api(target).prepend(this); return this; }
|
|
427
|
+
/** @internal */ _insertRelative(target: any, position: string): Cheerio<T> {
|
|
428
|
+
const targets = this._api(target).ids;
|
|
429
|
+
(this as Cheerio<any>).remove();
|
|
430
|
+
const inserted: number[] = [];
|
|
431
|
+
for (const id of targets) {
|
|
432
|
+
if (nodeRecord(this._document, id).parent == null)
|
|
433
|
+
continue;
|
|
434
|
+
const clones = this.op<number[]>('clone', { ids: this.ids, deep: true });
|
|
435
|
+
this.op('insert', { targetIds: [id], nodeIds: clones, position });
|
|
436
|
+
inserted.push(...clones);
|
|
437
|
+
}
|
|
438
|
+
return this._fromIds(inserted);
|
|
439
|
+
}
|
|
440
|
+
insertBefore<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
|
|
441
|
+
insertBefore(this: Cheerio<any>, target: any): any { return this._insertRelative(target, 'before'); }
|
|
442
|
+
insertAfter<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
|
|
443
|
+
insertAfter(this: Cheerio<any>, target: any): any { return this._insertRelative(target, 'after'); }
|
|
444
|
+
remove<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<T>;
|
|
445
|
+
remove(this: Cheerio<any>, selector?: any): any { this.op('remove', { ids: selector ? this.filter(selector).ids : this.ids }); return this; }
|
|
446
|
+
replaceWith<T extends AnyNode>(this: Cheerio<T>, content: AcceptedElems<AnyNode>): Cheerio<T>;
|
|
447
|
+
replaceWith(this: Cheerio<any>, content: any): any {
|
|
448
|
+
return this.each((index, node: any) => {
|
|
449
|
+
if (nodeRecord(this._document, this.ids[index]).parent == null)
|
|
450
|
+
return;
|
|
451
|
+
const value = typeof content === 'function' ? content.call(node, index, node) : content;
|
|
452
|
+
this.op('insert', { targetIds: [this.ids[index]], nodeIds: this._domIds(value), position: 'replace' });
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
empty<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
|
|
456
|
+
empty(this: Cheerio<any>): any {
|
|
457
|
+
for (const id of this.ids)
|
|
458
|
+
this.op('setNode', { id, field: 'children', value: [] });
|
|
459
|
+
return this;
|
|
460
|
+
}
|
|
461
|
+
html<T extends AnyNode>(this: Cheerio<T>): string | null;
|
|
462
|
+
html<T extends AnyNode>(this: Cheerio<T>, str: string | Cheerio<T>): Cheerio<T>;
|
|
463
|
+
html(this: Cheerio<any>, content?: any): any {
|
|
464
|
+
if (content === undefined)
|
|
465
|
+
return this.length && ['root', 'tag', 'script', 'style', 'cdata'].includes(nodeRecord(this._document, this.ids[0]).type) ? this._document.innerHtml(this.ids[0]) : null;
|
|
466
|
+
if (!content?.cheerio) {
|
|
467
|
+
this.op('html', { ids: this.ids, value: String(content) });
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
for (const id of this.ids) {
|
|
471
|
+
const nodes = content?.cheerio ? importNodes(this._document, content.toArray()) : this._domIds(String(content), id);
|
|
472
|
+
this.op('setNode', { id, field: 'children', value: nodes });
|
|
473
|
+
}
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
text<T extends AnyNode>(this: Cheerio<T>): string;
|
|
477
|
+
text<T extends AnyNode>(this: Cheerio<T>, str: string | ((this: AnyNode, i: number, text: string) => string)): Cheerio<T>;
|
|
478
|
+
text(this: Cheerio<any>, content?: any): any {
|
|
479
|
+
if (content === undefined)
|
|
480
|
+
return this._document.text(this.ids);
|
|
481
|
+
if (typeof content !== 'function') {
|
|
482
|
+
this.op('text', { ids: this.ids, value: String(content) });
|
|
483
|
+
return this;
|
|
484
|
+
}
|
|
485
|
+
for (let i = 0; i < this.ids.length; i++) {
|
|
486
|
+
const id = this.ids[i];
|
|
487
|
+
const value = typeof content === 'function' ? content.call(getNode(this._document, id), i, this._document.text([id])) : content;
|
|
488
|
+
this.op('text', { ids: [id], value: String(value) });
|
|
489
|
+
}
|
|
490
|
+
return this;
|
|
491
|
+
}
|
|
492
|
+
toString<T extends AnyNode>(this: Cheerio<T>): string;
|
|
493
|
+
toString(this: Cheerio<any>): any { return this._document.outerHtml(this.ids); }
|
|
494
|
+
clone<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
|
|
495
|
+
clone(this: Cheerio<any>): any { return this._fromIds(this.op('clone', { ids: this.ids, deep: true })); }
|
|
496
|
+
/** @internal */ _deepest(id: number, tagsOnly = false): number {
|
|
497
|
+
for (;;) {
|
|
498
|
+
const children = this.op<number[]>('traverse', { ids: [id], kind: 'children' });
|
|
499
|
+
const child = tagsOnly ? children.find((candidate) => nodeRecord(this._document, candidate).type === 'tag') : children[0];
|
|
500
|
+
if (child === undefined)
|
|
501
|
+
return id;
|
|
502
|
+
id = child;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/** @internal */ _wrap(content: any, inner: boolean): this {
|
|
506
|
+
const lastParent = (this as Cheerio<any>).parents().last();
|
|
507
|
+
for (let i = 0; i < this.length; i++) {
|
|
508
|
+
const id = this.ids[i];
|
|
509
|
+
const node = getNode(this._document, id);
|
|
510
|
+
const value = typeof content === 'function' ? content.call(node, i, node) : typeof content === 'string' && !isMarkup(content) ? lastParent.find(content).clone() : content;
|
|
511
|
+
let wrappers = this._domIds(value);
|
|
512
|
+
if (i < this.length - 1)
|
|
513
|
+
wrappers = this.op('clone', { ids: wrappers, deep: true });
|
|
514
|
+
const wrapper = wrappers[0];
|
|
515
|
+
if (wrapper === undefined || !['root', 'tag', 'script', 'style'].includes(nodeRecord(this._document, wrapper).type))
|
|
516
|
+
continue;
|
|
517
|
+
const deepest = this._deepest(wrapper);
|
|
518
|
+
if (inner) {
|
|
519
|
+
if (!['root', 'tag', 'script', 'style', 'cdata'].includes(nodeRecord(this._document, id).type))
|
|
520
|
+
continue;
|
|
521
|
+
const contents = this.op<number[]>('traverse', { ids: [id], kind: 'contents' });
|
|
522
|
+
this.op('setNode', { id: deepest, field: 'children', value: contents });
|
|
523
|
+
this.op('setNode', { id, field: 'children', value: [wrapper] });
|
|
524
|
+
}
|
|
525
|
+
else if (nodeRecord(this._document, id).parent != null) {
|
|
526
|
+
this.op('insert', { targetIds: [id], nodeIds: [wrapper], position: 'before' });
|
|
527
|
+
this.op('setNode', { id: deepest, field: 'children', value: [id] });
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return this;
|
|
531
|
+
}
|
|
532
|
+
wrap<T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<AnyNode>): Cheerio<T>;
|
|
533
|
+
wrap(this: Cheerio<any>, content: any): any { return this._wrap(content, false); }
|
|
534
|
+
wrapInner<T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<AnyNode>): Cheerio<T>;
|
|
535
|
+
wrapInner(this: Cheerio<any>, content: any): any { return this._wrap(content, true); }
|
|
536
|
+
unwrap<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<T>;
|
|
537
|
+
unwrap(this: Cheerio<any>, selector?: any): any { this.op('remove', { ids: this.parent(selector).not('body').ids, keepChildren: true }); return this; }
|
|
538
|
+
wrapAll<T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<T>): Cheerio<T>;
|
|
539
|
+
wrapAll(this: Cheerio<any>, content: any): any {
|
|
540
|
+
if (!this.length)
|
|
541
|
+
return this;
|
|
542
|
+
const first = this[0];
|
|
543
|
+
const wrappers = this._make(typeof content === 'function' ? content.call(first, 0, first) : content).insertBefore(first);
|
|
544
|
+
const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this._document, id).type === 'tag');
|
|
545
|
+
if (root !== undefined)
|
|
546
|
+
this.op('insert', { targetIds: [this._deepest(root, true)], nodeIds: this.ids, position: 'append' });
|
|
547
|
+
return this;
|
|
548
|
+
}
|
|
549
|
+
extract<M extends ExtractMap, T extends AnyNode>(this: Cheerio<T>, map: M): ExtractedMap<M>;
|
|
550
|
+
// A structurally shared object signature breaks recursive enum comparisons
|
|
551
|
+
// across independent DOM declarations; calls retain the precise overload.
|
|
552
|
+
extract<M extends ExtractMap, T extends AnyNode>(this: Cheerio<T>, map: M): Record<string, unknown>;
|
|
553
|
+
extract<M extends ExtractMap>(this: Cheerio<any>, map: any): any { return extract.call(this as any, map) as ExtractedMap<M>; }
|
|
554
|
+
}
|
|
555
|
+
Object.defineProperty(Cheerio.prototype, 'cheerio', { value: '[cheerio object]', writable: true, configurable: true });
|
|
556
|
+
export interface Cheerio<T = AnyNode> extends AttributeMethods<T> {
|
|
557
|
+
}
|
|
558
|
+
installAttributes(Cheerio);
|
|
559
|
+
|
|
560
|
+
/** @internal */
|
|
561
|
+
export const nativeExtractionMethods = Object.freeze({
|
|
562
|
+
make: Cheerio.prototype._make,
|
|
563
|
+
find: Cheerio.prototype._findBySelector,
|
|
564
|
+
prop: Cheerio.prototype.prop,
|
|
565
|
+
extract: Cheerio.prototype.extract,
|
|
566
|
+
});
|
package/src/slim.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { load as loadNative, contains, merge } from './index.js';
|
|
2
|
+
import type { CheerioAPI, CheerioOptions, LoadContent } from './types.js';
|
|
3
|
+
|
|
4
|
+
export { contains, merge };
|
|
5
|
+
export { dom } from './index.js';
|
|
6
|
+
export type * from './types.js';
|
|
7
|
+
export type { Cheerio } from './selection.js';
|
|
8
|
+
|
|
9
|
+
/** Parser-compatible slim entry point, backed by the native fragment parser. */
|
|
10
|
+
export function load(content: LoadContent, options?: CheerioOptions | null, _isDocument?: boolean): CheerioAPI {
|
|
11
|
+
return loadNative(content, { ...options, _useHtmlParser2: true }, false);
|
|
12
|
+
}
|