@depup/cheerio 1.2.0-depup.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.
Files changed (230) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/Readme.md +229 -0
  4. package/changes.json +30 -0
  5. package/dist/browser/api/attributes.d.ts +385 -0
  6. package/dist/browser/api/attributes.d.ts.map +1 -0
  7. package/dist/browser/api/attributes.js +636 -0
  8. package/dist/browser/api/attributes.js.map +1 -0
  9. package/dist/browser/api/css.d.ts +42 -0
  10. package/dist/browser/api/css.d.ts.map +1 -0
  11. package/dist/browser/api/css.js +116 -0
  12. package/dist/browser/api/css.js.map +1 -0
  13. package/dist/browser/api/extract.d.ts +27 -0
  14. package/dist/browser/api/extract.d.ts.map +1 -0
  15. package/dist/browser/api/extract.js +42 -0
  16. package/dist/browser/api/extract.js.map +1 -0
  17. package/dist/browser/api/forms.d.ts +36 -0
  18. package/dist/browser/api/forms.d.ts.map +1 -0
  19. package/dist/browser/api/forms.js +81 -0
  20. package/dist/browser/api/forms.js.map +1 -0
  21. package/dist/browser/api/manipulation.d.ts +528 -0
  22. package/dist/browser/api/manipulation.d.ts.map +1 -0
  23. package/dist/browser/api/manipulation.js +831 -0
  24. package/dist/browser/api/manipulation.js.map +1 -0
  25. package/dist/browser/api/traversing.d.ts +657 -0
  26. package/dist/browser/api/traversing.d.ts.map +1 -0
  27. package/dist/browser/api/traversing.js +857 -0
  28. package/dist/browser/api/traversing.js.map +1 -0
  29. package/dist/browser/cheerio.d.ts +85 -0
  30. package/dist/browser/cheerio.d.ts.map +1 -0
  31. package/dist/browser/cheerio.js +58 -0
  32. package/dist/browser/cheerio.js.map +1 -0
  33. package/dist/browser/index-browser.d.mts.map +1 -0
  34. package/dist/browser/index-browser.mjs.map +1 -0
  35. package/dist/browser/index.d.ts +5 -0
  36. package/dist/browser/index.js +3 -0
  37. package/dist/browser/load-parse.d.ts +20 -0
  38. package/dist/browser/load-parse.d.ts.map +1 -0
  39. package/dist/browser/load-parse.js +28 -0
  40. package/dist/browser/load-parse.js.map +1 -0
  41. package/dist/browser/load.d.ts +91 -0
  42. package/dist/browser/load.d.ts.map +1 -0
  43. package/dist/browser/load.js +129 -0
  44. package/dist/browser/load.js.map +1 -0
  45. package/dist/browser/options.d.ts +98 -0
  46. package/dist/browser/options.d.ts.map +1 -0
  47. package/dist/browser/options.js +34 -0
  48. package/dist/browser/options.js.map +1 -0
  49. package/dist/browser/package.json +3 -0
  50. package/dist/browser/parse.d.ts +18 -0
  51. package/dist/browser/parse.d.ts.map +1 -0
  52. package/dist/browser/parse.js +73 -0
  53. package/dist/browser/parse.js.map +1 -0
  54. package/dist/browser/parsers/parse5-adapter.d.ts +20 -0
  55. package/dist/browser/parsers/parse5-adapter.d.ts.map +1 -0
  56. package/dist/browser/parsers/parse5-adapter.js +50 -0
  57. package/dist/browser/parsers/parse5-adapter.js.map +1 -0
  58. package/dist/browser/slim.d.ts +25 -0
  59. package/dist/browser/slim.d.ts.map +1 -0
  60. package/dist/browser/slim.js +22 -0
  61. package/dist/browser/slim.js.map +1 -0
  62. package/dist/browser/static.d.ts +112 -0
  63. package/dist/browser/static.d.ts.map +1 -0
  64. package/dist/browser/static.js +204 -0
  65. package/dist/browser/static.js.map +1 -0
  66. package/dist/browser/types.d.ts +21 -0
  67. package/dist/browser/types.d.ts.map +1 -0
  68. package/dist/browser/types.js +3 -0
  69. package/dist/browser/types.js.map +1 -0
  70. package/dist/browser/utils.d.ts +55 -0
  71. package/dist/browser/utils.d.ts.map +1 -0
  72. package/dist/browser/utils.js +84 -0
  73. package/dist/browser/utils.js.map +1 -0
  74. package/dist/commonjs/api/attributes.d.ts +385 -0
  75. package/dist/commonjs/api/attributes.d.ts.map +1 -0
  76. package/dist/commonjs/api/attributes.js +647 -0
  77. package/dist/commonjs/api/attributes.js.map +1 -0
  78. package/dist/commonjs/api/css.d.ts +42 -0
  79. package/dist/commonjs/api/css.d.ts.map +1 -0
  80. package/dist/commonjs/api/css.js +119 -0
  81. package/dist/commonjs/api/css.js.map +1 -0
  82. package/dist/commonjs/api/extract.d.ts +27 -0
  83. package/dist/commonjs/api/extract.d.ts.map +1 -0
  84. package/dist/commonjs/api/extract.js +45 -0
  85. package/dist/commonjs/api/extract.js.map +1 -0
  86. package/dist/commonjs/api/forms.d.ts +36 -0
  87. package/dist/commonjs/api/forms.d.ts.map +1 -0
  88. package/dist/commonjs/api/forms.js +85 -0
  89. package/dist/commonjs/api/forms.js.map +1 -0
  90. package/dist/commonjs/api/manipulation.d.ts +528 -0
  91. package/dist/commonjs/api/manipulation.d.ts.map +1 -0
  92. package/dist/commonjs/api/manipulation.js +850 -0
  93. package/dist/commonjs/api/manipulation.js.map +1 -0
  94. package/dist/commonjs/api/traversing.d.ts +657 -0
  95. package/dist/commonjs/api/traversing.d.ts.map +1 -0
  96. package/dist/commonjs/api/traversing.js +914 -0
  97. package/dist/commonjs/api/traversing.js.map +1 -0
  98. package/dist/commonjs/cheerio.d.ts +85 -0
  99. package/dist/commonjs/cheerio.d.ts.map +1 -0
  100. package/dist/commonjs/cheerio.js +95 -0
  101. package/dist/commonjs/cheerio.js.map +1 -0
  102. package/dist/commonjs/index.d.ts +104 -0
  103. package/dist/commonjs/index.d.ts.map +1 -0
  104. package/dist/commonjs/index.js +250 -0
  105. package/dist/commonjs/index.js.map +1 -0
  106. package/dist/commonjs/load-parse.d.ts +20 -0
  107. package/dist/commonjs/load-parse.d.ts.map +1 -0
  108. package/dist/commonjs/load-parse.js +34 -0
  109. package/dist/commonjs/load-parse.js.map +1 -0
  110. package/dist/commonjs/load.d.ts +91 -0
  111. package/dist/commonjs/load.d.ts.map +1 -0
  112. package/dist/commonjs/load.js +165 -0
  113. package/dist/commonjs/load.js.map +1 -0
  114. package/dist/commonjs/options.d.ts +98 -0
  115. package/dist/commonjs/options.d.ts.map +1 -0
  116. package/dist/commonjs/options.js +37 -0
  117. package/dist/commonjs/options.js.map +1 -0
  118. package/dist/commonjs/package.json +3 -0
  119. package/dist/commonjs/parse.d.ts +18 -0
  120. package/dist/commonjs/parse.d.ts.map +1 -0
  121. package/dist/commonjs/parse.js +77 -0
  122. package/dist/commonjs/parse.js.map +1 -0
  123. package/dist/commonjs/parsers/parse5-adapter.d.ts +20 -0
  124. package/dist/commonjs/parsers/parse5-adapter.d.ts.map +1 -0
  125. package/dist/commonjs/parsers/parse5-adapter.js +54 -0
  126. package/dist/commonjs/parsers/parse5-adapter.js.map +1 -0
  127. package/dist/commonjs/slim.d.ts +25 -0
  128. package/dist/commonjs/slim.d.ts.map +1 -0
  129. package/dist/commonjs/slim.js +30 -0
  130. package/dist/commonjs/slim.js.map +1 -0
  131. package/dist/commonjs/static.d.ts +112 -0
  132. package/dist/commonjs/static.d.ts.map +1 -0
  133. package/dist/commonjs/static.js +214 -0
  134. package/dist/commonjs/static.js.map +1 -0
  135. package/dist/commonjs/types.d.ts +21 -0
  136. package/dist/commonjs/types.d.ts.map +1 -0
  137. package/dist/commonjs/types.js +4 -0
  138. package/dist/commonjs/types.js.map +1 -0
  139. package/dist/commonjs/utils.d.ts +55 -0
  140. package/dist/commonjs/utils.d.ts.map +1 -0
  141. package/dist/commonjs/utils.js +91 -0
  142. package/dist/commonjs/utils.js.map +1 -0
  143. package/dist/esm/api/attributes.d.ts +385 -0
  144. package/dist/esm/api/attributes.d.ts.map +1 -0
  145. package/dist/esm/api/attributes.js +636 -0
  146. package/dist/esm/api/attributes.js.map +1 -0
  147. package/dist/esm/api/css.d.ts +42 -0
  148. package/dist/esm/api/css.d.ts.map +1 -0
  149. package/dist/esm/api/css.js +116 -0
  150. package/dist/esm/api/css.js.map +1 -0
  151. package/dist/esm/api/extract.d.ts +27 -0
  152. package/dist/esm/api/extract.d.ts.map +1 -0
  153. package/dist/esm/api/extract.js +42 -0
  154. package/dist/esm/api/extract.js.map +1 -0
  155. package/dist/esm/api/forms.d.ts +36 -0
  156. package/dist/esm/api/forms.d.ts.map +1 -0
  157. package/dist/esm/api/forms.js +81 -0
  158. package/dist/esm/api/forms.js.map +1 -0
  159. package/dist/esm/api/manipulation.d.ts +528 -0
  160. package/dist/esm/api/manipulation.d.ts.map +1 -0
  161. package/dist/esm/api/manipulation.js +831 -0
  162. package/dist/esm/api/manipulation.js.map +1 -0
  163. package/dist/esm/api/traversing.d.ts +657 -0
  164. package/dist/esm/api/traversing.d.ts.map +1 -0
  165. package/dist/esm/api/traversing.js +857 -0
  166. package/dist/esm/api/traversing.js.map +1 -0
  167. package/dist/esm/cheerio.d.ts +85 -0
  168. package/dist/esm/cheerio.d.ts.map +1 -0
  169. package/dist/esm/cheerio.js +58 -0
  170. package/dist/esm/cheerio.js.map +1 -0
  171. package/dist/esm/index.d.ts +104 -0
  172. package/dist/esm/index.d.ts.map +1 -0
  173. package/dist/esm/index.js +202 -0
  174. package/dist/esm/index.js.map +1 -0
  175. package/dist/esm/load-parse.d.ts +20 -0
  176. package/dist/esm/load-parse.d.ts.map +1 -0
  177. package/dist/esm/load-parse.js +28 -0
  178. package/dist/esm/load-parse.js.map +1 -0
  179. package/dist/esm/load.d.ts +91 -0
  180. package/dist/esm/load.d.ts.map +1 -0
  181. package/dist/esm/load.js +129 -0
  182. package/dist/esm/load.js.map +1 -0
  183. package/dist/esm/options.d.ts +98 -0
  184. package/dist/esm/options.d.ts.map +1 -0
  185. package/dist/esm/options.js +34 -0
  186. package/dist/esm/options.js.map +1 -0
  187. package/dist/esm/package.json +3 -0
  188. package/dist/esm/parse.d.ts +18 -0
  189. package/dist/esm/parse.d.ts.map +1 -0
  190. package/dist/esm/parse.js +73 -0
  191. package/dist/esm/parse.js.map +1 -0
  192. package/dist/esm/parsers/parse5-adapter.d.ts +20 -0
  193. package/dist/esm/parsers/parse5-adapter.d.ts.map +1 -0
  194. package/dist/esm/parsers/parse5-adapter.js +50 -0
  195. package/dist/esm/parsers/parse5-adapter.js.map +1 -0
  196. package/dist/esm/slim.d.ts +25 -0
  197. package/dist/esm/slim.d.ts.map +1 -0
  198. package/dist/esm/slim.js +22 -0
  199. package/dist/esm/slim.js.map +1 -0
  200. package/dist/esm/static.d.ts +112 -0
  201. package/dist/esm/static.d.ts.map +1 -0
  202. package/dist/esm/static.js +204 -0
  203. package/dist/esm/static.js.map +1 -0
  204. package/dist/esm/types.d.ts +21 -0
  205. package/dist/esm/types.d.ts.map +1 -0
  206. package/dist/esm/types.js +3 -0
  207. package/dist/esm/types.js.map +1 -0
  208. package/dist/esm/utils.d.ts +55 -0
  209. package/dist/esm/utils.d.ts.map +1 -0
  210. package/dist/esm/utils.js +84 -0
  211. package/dist/esm/utils.js.map +1 -0
  212. package/package.json +219 -0
  213. package/src/api/attributes.ts +1145 -0
  214. package/src/api/css.ts +224 -0
  215. package/src/api/extract.ts +92 -0
  216. package/src/api/forms.ts +103 -0
  217. package/src/api/manipulation.ts +1115 -0
  218. package/src/api/traversing.ts +1175 -0
  219. package/src/cheerio.ts +143 -0
  220. package/src/index-browser.mts +10 -0
  221. package/src/index.ts +294 -0
  222. package/src/load-parse.ts +39 -0
  223. package/src/load.ts +282 -0
  224. package/src/options.ts +136 -0
  225. package/src/parse.ts +105 -0
  226. package/src/parsers/parse5-adapter.ts +66 -0
  227. package/src/slim.ts +33 -0
  228. package/src/static.ts +312 -0
  229. package/src/types.ts +58 -0
  230. package/src/utils.ts +99 -0
@@ -0,0 +1,1115 @@
1
+ /**
2
+ * Methods for modifying the DOM structure.
3
+ *
4
+ * @module cheerio/manipulation
5
+ */
6
+
7
+ import {
8
+ isTag,
9
+ Text,
10
+ hasChildren,
11
+ cloneNode,
12
+ Document,
13
+ type ParentNode,
14
+ type AnyNode,
15
+ type Element,
16
+ } from 'domhandler';
17
+ import { update as updateDOM } from '../parse.js';
18
+ import { text as staticText } from '../static.js';
19
+ import { domEach, isHtml, isCheerio } from '../utils.js';
20
+ import { removeElement } from 'domutils';
21
+ import type { Cheerio } from '../cheerio.js';
22
+ import type { BasicAcceptedElems, AcceptedElems } from '../types.js';
23
+ import { ElementType } from 'htmlparser2';
24
+
25
+ /**
26
+ * Create an array of nodes, recursing into arrays and parsing strings if
27
+ * necessary.
28
+ *
29
+ * @private
30
+ * @category Manipulation
31
+ * @param elem - Elements to make an array of.
32
+ * @param clone - Optionally clone nodes.
33
+ * @returns The array of nodes.
34
+ */
35
+ export function _makeDomArray<T extends AnyNode>(
36
+ this: Cheerio<T>,
37
+ elem?: BasicAcceptedElems<AnyNode> | BasicAcceptedElems<AnyNode>[],
38
+ clone?: boolean,
39
+ ): AnyNode[] {
40
+ if (elem == null) {
41
+ return [];
42
+ }
43
+
44
+ if (typeof elem === 'string') {
45
+ return this._parse(elem, this.options, false, null).children.slice(0);
46
+ }
47
+
48
+ if ('length' in elem) {
49
+ if (elem.length === 1) {
50
+ return this._makeDomArray(elem[0], clone);
51
+ }
52
+
53
+ const result: AnyNode[] = [];
54
+
55
+ for (let i = 0; i < elem.length; i++) {
56
+ const el = elem[i];
57
+
58
+ if (typeof el === 'object') {
59
+ if (el == null) {
60
+ continue;
61
+ }
62
+
63
+ if (!('length' in el)) {
64
+ result.push(clone ? cloneNode(el, true) : el);
65
+ continue;
66
+ }
67
+ }
68
+
69
+ result.push(...this._makeDomArray(el, clone));
70
+ }
71
+
72
+ return result;
73
+ }
74
+
75
+ return [clone ? cloneNode(elem, true) : elem];
76
+ }
77
+
78
+ function _insert(
79
+ concatenator: (
80
+ dom: AnyNode[],
81
+ children: AnyNode[],
82
+ parent: ParentNode,
83
+ ) => void,
84
+ ) {
85
+ return function <T extends AnyNode>(
86
+ this: Cheerio<T>,
87
+ ...elems:
88
+ | [
89
+ (
90
+ this: AnyNode,
91
+ i: number,
92
+ html: string,
93
+ ) => BasicAcceptedElems<AnyNode>,
94
+ ]
95
+ | BasicAcceptedElems<AnyNode>[]
96
+ ) {
97
+ const lastIdx = this.length - 1;
98
+
99
+ return domEach(this, (el, i) => {
100
+ if (!hasChildren(el)) return;
101
+
102
+ const domSrc =
103
+ typeof elems[0] === 'function'
104
+ ? elems[0].call(el, i, this._render(el.children))
105
+ : (elems as BasicAcceptedElems<AnyNode>[]);
106
+
107
+ const dom = this._makeDomArray(domSrc, i < lastIdx);
108
+ concatenator(dom, el.children, el);
109
+ });
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Modify an array in-place, removing some number of elements and adding new
115
+ * elements directly following them.
116
+ *
117
+ * @private
118
+ * @category Manipulation
119
+ * @param array - Target array to splice.
120
+ * @param spliceIdx - Index at which to begin changing the array.
121
+ * @param spliceCount - Number of elements to remove from the array.
122
+ * @param newElems - Elements to insert into the array.
123
+ * @param parent - The parent of the node.
124
+ * @returns The spliced array.
125
+ */
126
+ function uniqueSplice(
127
+ array: AnyNode[],
128
+ spliceIdx: number,
129
+ spliceCount: number,
130
+ newElems: AnyNode[],
131
+ parent: ParentNode,
132
+ ): AnyNode[] {
133
+ const spliceArgs: Parameters<AnyNode[]['splice']> = [
134
+ spliceIdx,
135
+ spliceCount,
136
+ ...newElems,
137
+ ];
138
+ const prev = spliceIdx === 0 ? null : array[spliceIdx - 1];
139
+ const next =
140
+ spliceIdx + spliceCount >= array.length
141
+ ? null
142
+ : array[spliceIdx + spliceCount];
143
+
144
+ /*
145
+ * Before splicing in new elements, ensure they do not already appear in the
146
+ * current array.
147
+ */
148
+ for (let idx = 0; idx < newElems.length; ++idx) {
149
+ const node = newElems[idx];
150
+ const oldParent = node.parent;
151
+
152
+ if (oldParent) {
153
+ const oldSiblings: AnyNode[] = oldParent.children;
154
+ const prevIdx = oldSiblings.indexOf(node);
155
+
156
+ if (prevIdx !== -1) {
157
+ oldParent.children.splice(prevIdx, 1);
158
+ if (parent === oldParent && spliceIdx > prevIdx) {
159
+ spliceArgs[0]--;
160
+ }
161
+ }
162
+ }
163
+
164
+ node.parent = parent;
165
+
166
+ if (node.prev) {
167
+ node.prev.next = node.next ?? null;
168
+ }
169
+
170
+ if (node.next) {
171
+ node.next.prev = node.prev ?? null;
172
+ }
173
+
174
+ node.prev = idx === 0 ? prev : newElems[idx - 1];
175
+ node.next = idx === newElems.length - 1 ? next : newElems[idx + 1];
176
+ }
177
+
178
+ if (prev) {
179
+ prev.next = newElems[0];
180
+ }
181
+ if (next) {
182
+ next.prev = newElems[newElems.length - 1];
183
+ }
184
+ return array.splice(...spliceArgs);
185
+ }
186
+
187
+ /**
188
+ * Insert every element in the set of matched elements to the end of the target.
189
+ *
190
+ * @category Manipulation
191
+ * @example
192
+ *
193
+ * ```js
194
+ * $('<li class="plum">Plum</li>').appendTo('#fruits');
195
+ * $.html();
196
+ * //=> <ul id="fruits">
197
+ * // <li class="apple">Apple</li>
198
+ * // <li class="orange">Orange</li>
199
+ * // <li class="pear">Pear</li>
200
+ * // <li class="plum">Plum</li>
201
+ * // </ul>
202
+ * ```
203
+ *
204
+ * @param target - Element to append elements to.
205
+ * @returns The instance itself.
206
+ * @see {@link https://api.jquery.com/appendTo/}
207
+ */
208
+ export function appendTo<T extends AnyNode>(
209
+ this: Cheerio<T>,
210
+ target: BasicAcceptedElems<AnyNode>,
211
+ ): Cheerio<T> {
212
+ const appendTarget = isCheerio<T>(target) ? target : this._make(target);
213
+
214
+ appendTarget.append(this);
215
+
216
+ return this;
217
+ }
218
+
219
+ /**
220
+ * Insert every element in the set of matched elements to the beginning of the
221
+ * target.
222
+ *
223
+ * @category Manipulation
224
+ * @example
225
+ *
226
+ * ```js
227
+ * $('<li class="plum">Plum</li>').prependTo('#fruits');
228
+ * $.html();
229
+ * //=> <ul id="fruits">
230
+ * // <li class="plum">Plum</li>
231
+ * // <li class="apple">Apple</li>
232
+ * // <li class="orange">Orange</li>
233
+ * // <li class="pear">Pear</li>
234
+ * // </ul>
235
+ * ```
236
+ *
237
+ * @param target - Element to prepend elements to.
238
+ * @returns The instance itself.
239
+ * @see {@link https://api.jquery.com/prependTo/}
240
+ */
241
+ export function prependTo<T extends AnyNode>(
242
+ this: Cheerio<T>,
243
+ target: BasicAcceptedElems<AnyNode>,
244
+ ): Cheerio<T> {
245
+ const prependTarget = isCheerio<T>(target) ? target : this._make(target);
246
+
247
+ prependTarget.prepend(this);
248
+
249
+ return this;
250
+ }
251
+
252
+ /**
253
+ * Inserts content as the _last_ child of each of the selected elements.
254
+ *
255
+ * @category Manipulation
256
+ * @example
257
+ *
258
+ * ```js
259
+ * $('ul').append('<li class="plum">Plum</li>');
260
+ * $.html();
261
+ * //=> <ul id="fruits">
262
+ * // <li class="apple">Apple</li>
263
+ * // <li class="orange">Orange</li>
264
+ * // <li class="pear">Pear</li>
265
+ * // <li class="plum">Plum</li>
266
+ * // </ul>
267
+ * ```
268
+ *
269
+ * @see {@link https://api.jquery.com/append/}
270
+ */
271
+ export const append: <T extends AnyNode>(
272
+ this: Cheerio<T>,
273
+ ...elems:
274
+ | [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>]
275
+ | BasicAcceptedElems<AnyNode>[]
276
+ ) => Cheerio<T> = _insert((dom, children, parent) => {
277
+ uniqueSplice(children, children.length, 0, dom, parent);
278
+ });
279
+
280
+ /**
281
+ * Inserts content as the _first_ child of each of the selected elements.
282
+ *
283
+ * @category Manipulation
284
+ * @example
285
+ *
286
+ * ```js
287
+ * $('ul').prepend('<li class="plum">Plum</li>');
288
+ * $.html();
289
+ * //=> <ul id="fruits">
290
+ * // <li class="plum">Plum</li>
291
+ * // <li class="apple">Apple</li>
292
+ * // <li class="orange">Orange</li>
293
+ * // <li class="pear">Pear</li>
294
+ * // </ul>
295
+ * ```
296
+ *
297
+ * @see {@link https://api.jquery.com/prepend/}
298
+ */
299
+ export const prepend: <T extends AnyNode>(
300
+ this: Cheerio<T>,
301
+ ...elems:
302
+ | [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>]
303
+ | BasicAcceptedElems<AnyNode>[]
304
+ ) => Cheerio<T> = _insert((dom, children, parent) => {
305
+ uniqueSplice(children, 0, 0, dom, parent);
306
+ });
307
+
308
+ function _wrap(
309
+ insert: (
310
+ el: AnyNode,
311
+ elInsertLocation: ParentNode,
312
+ wrapperDom: ParentNode[],
313
+ ) => void,
314
+ ) {
315
+ return function <T extends AnyNode>(
316
+ this: Cheerio<T>,
317
+ wrapper: AcceptedElems<AnyNode>,
318
+ ) {
319
+ const lastIdx = this.length - 1;
320
+ const lastParent = this.parents().last();
321
+
322
+ for (let i = 0; i < this.length; i++) {
323
+ const el = this[i];
324
+
325
+ const wrap =
326
+ typeof wrapper === 'function'
327
+ ? wrapper.call(el, i, el)
328
+ : typeof wrapper === 'string' && !isHtml(wrapper)
329
+ ? lastParent.find(wrapper).clone()
330
+ : wrapper;
331
+
332
+ const [wrapperDom] = this._makeDomArray(wrap, i < lastIdx);
333
+
334
+ if (!wrapperDom || !hasChildren(wrapperDom)) continue;
335
+
336
+ let elInsertLocation = wrapperDom;
337
+
338
+ /*
339
+ * Find the deepest child. Only consider the first tag child of each node
340
+ * (ignore text); stop if no children are found.
341
+ */
342
+ let j = 0;
343
+
344
+ while (j < elInsertLocation.children.length) {
345
+ const child = elInsertLocation.children[j];
346
+ if (isTag(child)) {
347
+ elInsertLocation = child;
348
+ j = 0;
349
+ } else {
350
+ j++;
351
+ }
352
+ }
353
+
354
+ insert(el, elInsertLocation, [wrapperDom]);
355
+ }
356
+
357
+ return this;
358
+ };
359
+ }
360
+
361
+ /**
362
+ * The .wrap() function can take any string or object that could be passed to
363
+ * the $() factory function to specify a DOM structure. This structure may be
364
+ * nested several levels deep, but should contain only one inmost element. A
365
+ * copy of this structure will be wrapped around each of the elements in the set
366
+ * of matched elements. This method returns the original set of elements for
367
+ * chaining purposes.
368
+ *
369
+ * @category Manipulation
370
+ * @example
371
+ *
372
+ * ```js
373
+ * const redFruit = $('<div class="red-fruit"></div>');
374
+ * $('.apple').wrap(redFruit);
375
+ *
376
+ * //=> <ul id="fruits">
377
+ * // <div class="red-fruit">
378
+ * // <li class="apple">Apple</li>
379
+ * // </div>
380
+ * // <li class="orange">Orange</li>
381
+ * // <li class="plum">Plum</li>
382
+ * // </ul>
383
+ *
384
+ * const healthy = $('<div class="healthy"></div>');
385
+ * $('li').wrap(healthy);
386
+ *
387
+ * //=> <ul id="fruits">
388
+ * // <div class="healthy">
389
+ * // <li class="apple">Apple</li>
390
+ * // </div>
391
+ * // <div class="healthy">
392
+ * // <li class="orange">Orange</li>
393
+ * // </div>
394
+ * // <div class="healthy">
395
+ * // <li class="plum">Plum</li>
396
+ * // </div>
397
+ * // </ul>
398
+ * ```
399
+ *
400
+ * @param wrapper - The DOM structure to wrap around each element in the
401
+ * selection.
402
+ * @see {@link https://api.jquery.com/wrap/}
403
+ */
404
+ export const wrap: <T extends AnyNode>(
405
+ this: Cheerio<T>,
406
+ wrapper: AcceptedElems<AnyNode>,
407
+ ) => Cheerio<T> = _wrap((el, elInsertLocation, wrapperDom) => {
408
+ const { parent } = el;
409
+
410
+ if (!parent) return;
411
+
412
+ const siblings: AnyNode[] = parent.children;
413
+ const index = siblings.indexOf(el);
414
+
415
+ updateDOM([el], elInsertLocation);
416
+ /*
417
+ * The previous operation removed the current element from the `siblings`
418
+ * array, so the `dom` array can be inserted without removing any
419
+ * additional elements.
420
+ */
421
+ uniqueSplice(siblings, index, 0, wrapperDom, parent);
422
+ });
423
+
424
+ /**
425
+ * The .wrapInner() function can take any string or object that could be passed
426
+ * to the $() factory function to specify a DOM structure. This structure may be
427
+ * nested several levels deep, but should contain only one inmost element. The
428
+ * structure will be wrapped around the content of each of the elements in the
429
+ * set of matched elements.
430
+ *
431
+ * @category Manipulation
432
+ * @example
433
+ *
434
+ * ```js
435
+ * const redFruit = $('<div class="red-fruit"></div>');
436
+ * $('.apple').wrapInner(redFruit);
437
+ *
438
+ * //=> <ul id="fruits">
439
+ * // <li class="apple">
440
+ * // <div class="red-fruit">Apple</div>
441
+ * // </li>
442
+ * // <li class="orange">Orange</li>
443
+ * // <li class="pear">Pear</li>
444
+ * // </ul>
445
+ *
446
+ * const healthy = $('<div class="healthy"></div>');
447
+ * $('li').wrapInner(healthy);
448
+ *
449
+ * //=> <ul id="fruits">
450
+ * // <li class="apple">
451
+ * // <div class="healthy">Apple</div>
452
+ * // </li>
453
+ * // <li class="orange">
454
+ * // <div class="healthy">Orange</div>
455
+ * // </li>
456
+ * // <li class="pear">
457
+ * // <div class="healthy">Pear</div>
458
+ * // </li>
459
+ * // </ul>
460
+ * ```
461
+ *
462
+ * @param wrapper - The DOM structure to wrap around the content of each element
463
+ * in the selection.
464
+ * @returns The instance itself, for chaining.
465
+ * @see {@link https://api.jquery.com/wrapInner/}
466
+ */
467
+ export const wrapInner: <T extends AnyNode>(
468
+ this: Cheerio<T>,
469
+ wrapper: AcceptedElems<AnyNode>,
470
+ ) => Cheerio<T> = _wrap((el, elInsertLocation, wrapperDom) => {
471
+ if (!hasChildren(el)) return;
472
+ updateDOM(el.children, elInsertLocation);
473
+ updateDOM(wrapperDom, el);
474
+ });
475
+
476
+ /**
477
+ * The .unwrap() function, removes the parents of the set of matched elements
478
+ * from the DOM, leaving the matched elements in their place.
479
+ *
480
+ * @category Manipulation
481
+ * @example <caption>without selector</caption>
482
+ *
483
+ * ```js
484
+ * const $ = cheerio.load(
485
+ * '<div id=test>\n <div><p>Hello</p></div>\n <div><p>World</p></div>\n</div>',
486
+ * );
487
+ * $('#test p').unwrap();
488
+ *
489
+ * //=> <div id=test>
490
+ * // <p>Hello</p>
491
+ * // <p>World</p>
492
+ * // </div>
493
+ * ```
494
+ *
495
+ * @example <caption>with selector</caption>
496
+ *
497
+ * ```js
498
+ * const $ = cheerio.load(
499
+ * '<div id=test>\n <p>Hello</p>\n <b><p>World</p></b>\n</div>',
500
+ * );
501
+ * $('#test p').unwrap('b');
502
+ *
503
+ * //=> <div id=test>
504
+ * // <p>Hello</p>
505
+ * // <p>World</p>
506
+ * // </div>
507
+ * ```
508
+ *
509
+ * @param selector - A selector to check the parent element against. If an
510
+ * element's parent does not match the selector, the element won't be
511
+ * unwrapped.
512
+ * @returns The instance itself, for chaining.
513
+ * @see {@link https://api.jquery.com/unwrap/}
514
+ */
515
+ export function unwrap<T extends AnyNode>(
516
+ this: Cheerio<T>,
517
+ selector?: string,
518
+ ): Cheerio<T> {
519
+ this.parent(selector)
520
+ .not('body')
521
+ .each((_, el) => {
522
+ this._make(el).replaceWith(el.children);
523
+ });
524
+ return this;
525
+ }
526
+
527
+ /**
528
+ * The .wrapAll() function can take any string or object that could be passed to
529
+ * the $() function to specify a DOM structure. This structure may be nested
530
+ * several levels deep, but should contain only one inmost element. The
531
+ * structure will be wrapped around all of the elements in the set of matched
532
+ * elements, as a single group.
533
+ *
534
+ * @category Manipulation
535
+ * @example <caption>With markup passed to `wrapAll`</caption>
536
+ *
537
+ * ```js
538
+ * const $ = cheerio.load(
539
+ * '<div class="container"><div class="inner">First</div><div class="inner">Second</div></div>',
540
+ * );
541
+ * $('.inner').wrapAll("<div class='new'></div>");
542
+ *
543
+ * //=> <div class="container">
544
+ * // <div class='new'>
545
+ * // <div class="inner">First</div>
546
+ * // <div class="inner">Second</div>
547
+ * // </div>
548
+ * // </div>
549
+ * ```
550
+ *
551
+ * @example <caption>With an existing cheerio instance</caption>
552
+ *
553
+ * ```js
554
+ * const $ = cheerio.load(
555
+ * '<span>Span 1</span><strong>Strong</strong><span>Span 2</span>',
556
+ * );
557
+ * const wrap = $('<div><p><em><b></b></em></p></div>');
558
+ * $('span').wrapAll(wrap);
559
+ *
560
+ * //=> <div>
561
+ * // <p>
562
+ * // <em>
563
+ * // <b>
564
+ * // <span>Span 1</span>
565
+ * // <span>Span 2</span>
566
+ * // </b>
567
+ * // </em>
568
+ * // </p>
569
+ * // </div>
570
+ * // <strong>Strong</strong>
571
+ * ```
572
+ *
573
+ * @param wrapper - The DOM structure to wrap around all matched elements in the
574
+ * selection.
575
+ * @returns The instance itself.
576
+ * @see {@link https://api.jquery.com/wrapAll/}
577
+ */
578
+ export function wrapAll<T extends AnyNode>(
579
+ this: Cheerio<T>,
580
+ wrapper: AcceptedElems<T>,
581
+ ): Cheerio<T> {
582
+ const el = this[0];
583
+ if (el) {
584
+ const wrap: Cheerio<AnyNode> = this._make(
585
+ typeof wrapper === 'function' ? wrapper.call(el, 0, el) : wrapper,
586
+ ).insertBefore(el);
587
+
588
+ // If html is given as wrapper, wrap may contain text elements
589
+ let elInsertLocation: Element | undefined;
590
+
591
+ for (let i = 0; i < wrap.length; i++) {
592
+ if (wrap[i].type === ElementType.Tag) {
593
+ elInsertLocation = wrap[i] as Element;
594
+ }
595
+ }
596
+
597
+ let j = 0;
598
+
599
+ /*
600
+ * Find the deepest child. Only consider the first tag child of each node
601
+ * (ignore text); stop if no children are found.
602
+ */
603
+ while (elInsertLocation && j < elInsertLocation.children.length) {
604
+ const child = elInsertLocation.children[j];
605
+ if (child.type === ElementType.Tag) {
606
+ elInsertLocation = child;
607
+ j = 0;
608
+ } else {
609
+ j++;
610
+ }
611
+ }
612
+
613
+ if (elInsertLocation) this._make(elInsertLocation).append(this);
614
+ }
615
+ return this;
616
+ }
617
+
618
+ /**
619
+ * Insert content next to each element in the set of matched elements.
620
+ *
621
+ * @category Manipulation
622
+ * @example
623
+ *
624
+ * ```js
625
+ * $('.apple').after('<li class="plum">Plum</li>');
626
+ * $.html();
627
+ * //=> <ul id="fruits">
628
+ * // <li class="apple">Apple</li>
629
+ * // <li class="plum">Plum</li>
630
+ * // <li class="orange">Orange</li>
631
+ * // <li class="pear">Pear</li>
632
+ * // </ul>
633
+ * ```
634
+ *
635
+ * @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
636
+ * insert after each element in the set of matched elements.
637
+ * @returns The instance itself.
638
+ * @see {@link https://api.jquery.com/after/}
639
+ */
640
+ export function after<T extends AnyNode>(
641
+ this: Cheerio<T>,
642
+ ...elems:
643
+ | [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>]
644
+ | BasicAcceptedElems<AnyNode>[]
645
+ ): Cheerio<T> {
646
+ const lastIdx = this.length - 1;
647
+
648
+ return domEach(this, (el, i) => {
649
+ if (!hasChildren(el) || !el.parent) {
650
+ return;
651
+ }
652
+
653
+ const siblings: AnyNode[] = el.parent.children;
654
+ const index = siblings.indexOf(el);
655
+
656
+ // If not found, move on
657
+ /* istanbul ignore next */
658
+ if (index === -1) return;
659
+
660
+ const domSrc =
661
+ typeof elems[0] === 'function'
662
+ ? elems[0].call(el, i, this._render(el.children))
663
+ : (elems as BasicAcceptedElems<AnyNode>[]);
664
+
665
+ const dom = this._makeDomArray(domSrc, i < lastIdx);
666
+
667
+ // Add element after `this` element
668
+ uniqueSplice(siblings, index + 1, 0, dom, el.parent);
669
+ });
670
+ }
671
+
672
+ /**
673
+ * Insert every element in the set of matched elements after the target.
674
+ *
675
+ * @category Manipulation
676
+ * @example
677
+ *
678
+ * ```js
679
+ * $('<li class="plum">Plum</li>').insertAfter('.apple');
680
+ * $.html();
681
+ * //=> <ul id="fruits">
682
+ * // <li class="apple">Apple</li>
683
+ * // <li class="plum">Plum</li>
684
+ * // <li class="orange">Orange</li>
685
+ * // <li class="pear">Pear</li>
686
+ * // </ul>
687
+ * ```
688
+ *
689
+ * @param target - Element to insert elements after.
690
+ * @returns The set of newly inserted elements.
691
+ * @see {@link https://api.jquery.com/insertAfter/}
692
+ */
693
+ export function insertAfter<T extends AnyNode>(
694
+ this: Cheerio<T>,
695
+ target: BasicAcceptedElems<AnyNode>,
696
+ ): Cheerio<T> {
697
+ if (typeof target === 'string') {
698
+ target = this._make<AnyNode>(target);
699
+ }
700
+
701
+ this.remove();
702
+
703
+ const clones: T[] = [];
704
+
705
+ for (const el of this._makeDomArray(target)) {
706
+ const clonedSelf = this.clone().toArray();
707
+ const { parent } = el;
708
+ if (!parent) {
709
+ continue;
710
+ }
711
+
712
+ const siblings: AnyNode[] = parent.children;
713
+ const index = siblings.indexOf(el);
714
+
715
+ // If not found, move on
716
+ /* istanbul ignore next */
717
+ if (index === -1) continue;
718
+
719
+ // Add cloned `this` element(s) after target element
720
+ uniqueSplice(siblings, index + 1, 0, clonedSelf, parent);
721
+ clones.push(...clonedSelf);
722
+ }
723
+
724
+ return this._make(clones);
725
+ }
726
+
727
+ /**
728
+ * Insert content previous to each element in the set of matched elements.
729
+ *
730
+ * @category Manipulation
731
+ * @example
732
+ *
733
+ * ```js
734
+ * $('.apple').before('<li class="plum">Plum</li>');
735
+ * $.html();
736
+ * //=> <ul id="fruits">
737
+ * // <li class="plum">Plum</li>
738
+ * // <li class="apple">Apple</li>
739
+ * // <li class="orange">Orange</li>
740
+ * // <li class="pear">Pear</li>
741
+ * // </ul>
742
+ * ```
743
+ *
744
+ * @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
745
+ * insert before each element in the set of matched elements.
746
+ * @returns The instance itself.
747
+ * @see {@link https://api.jquery.com/before/}
748
+ */
749
+ export function before<T extends AnyNode>(
750
+ this: Cheerio<T>,
751
+ ...elems:
752
+ | [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>]
753
+ | BasicAcceptedElems<AnyNode>[]
754
+ ): Cheerio<T> {
755
+ const lastIdx = this.length - 1;
756
+
757
+ return domEach(this, (el, i) => {
758
+ if (!hasChildren(el) || !el.parent) {
759
+ return;
760
+ }
761
+
762
+ const siblings: AnyNode[] = el.parent.children;
763
+ const index = siblings.indexOf(el);
764
+
765
+ // If not found, move on
766
+ /* istanbul ignore next */
767
+ if (index === -1) return;
768
+
769
+ const domSrc =
770
+ typeof elems[0] === 'function'
771
+ ? elems[0].call(el, i, this._render(el.children))
772
+ : (elems as BasicAcceptedElems<AnyNode>[]);
773
+
774
+ const dom = this._makeDomArray(domSrc, i < lastIdx);
775
+
776
+ // Add element before `el` element
777
+ uniqueSplice(siblings, index, 0, dom, el.parent);
778
+ });
779
+ }
780
+
781
+ /**
782
+ * Insert every element in the set of matched elements before the target.
783
+ *
784
+ * @category Manipulation
785
+ * @example
786
+ *
787
+ * ```js
788
+ * $('<li class="plum">Plum</li>').insertBefore('.apple');
789
+ * $.html();
790
+ * //=> <ul id="fruits">
791
+ * // <li class="plum">Plum</li>
792
+ * // <li class="apple">Apple</li>
793
+ * // <li class="orange">Orange</li>
794
+ * // <li class="pear">Pear</li>
795
+ * // </ul>
796
+ * ```
797
+ *
798
+ * @param target - Element to insert elements before.
799
+ * @returns The set of newly inserted elements.
800
+ * @see {@link https://api.jquery.com/insertBefore/}
801
+ */
802
+ export function insertBefore<T extends AnyNode>(
803
+ this: Cheerio<T>,
804
+ target: BasicAcceptedElems<AnyNode>,
805
+ ): Cheerio<T> {
806
+ const targetArr = this._make<AnyNode>(target);
807
+
808
+ this.remove();
809
+
810
+ const clones: T[] = [];
811
+
812
+ domEach(targetArr, (el) => {
813
+ const clonedSelf = this.clone().toArray();
814
+ const { parent } = el;
815
+ if (!parent) {
816
+ return;
817
+ }
818
+
819
+ const siblings: AnyNode[] = parent.children;
820
+ const index = siblings.indexOf(el);
821
+
822
+ // If not found, move on
823
+ /* istanbul ignore next */
824
+ if (index === -1) return;
825
+
826
+ // Add cloned `this` element(s) after target element
827
+ uniqueSplice(siblings, index, 0, clonedSelf, parent);
828
+ clones.push(...clonedSelf);
829
+ });
830
+
831
+ return this._make(clones);
832
+ }
833
+
834
+ /**
835
+ * Removes the set of matched elements from the DOM and all their children.
836
+ * `selector` filters the set of matched elements to be removed.
837
+ *
838
+ * @category Manipulation
839
+ * @example
840
+ *
841
+ * ```js
842
+ * $('.pear').remove();
843
+ * $.html();
844
+ * //=> <ul id="fruits">
845
+ * // <li class="apple">Apple</li>
846
+ * // <li class="orange">Orange</li>
847
+ * // </ul>
848
+ * ```
849
+ *
850
+ * @param selector - Optional selector for elements to remove.
851
+ * @returns The instance itself.
852
+ * @see {@link https://api.jquery.com/remove/}
853
+ */
854
+ export function remove<T extends AnyNode>(
855
+ this: Cheerio<T>,
856
+ selector?: string,
857
+ ): Cheerio<T> {
858
+ // Filter if we have selector
859
+ const elems = selector ? this.filter(selector) : this;
860
+
861
+ domEach(elems, (el) => {
862
+ removeElement(el);
863
+ el.prev = el.next = el.parent = null;
864
+ });
865
+
866
+ return this;
867
+ }
868
+
869
+ /**
870
+ * Replaces matched elements with `content`.
871
+ *
872
+ * @category Manipulation
873
+ * @example
874
+ *
875
+ * ```js
876
+ * const plum = $('<li class="plum">Plum</li>');
877
+ * $('.pear').replaceWith(plum);
878
+ * $.html();
879
+ * //=> <ul id="fruits">
880
+ * // <li class="apple">Apple</li>
881
+ * // <li class="orange">Orange</li>
882
+ * // <li class="plum">Plum</li>
883
+ * // </ul>
884
+ * ```
885
+ *
886
+ * @param content - Replacement for matched elements.
887
+ * @returns The instance itself.
888
+ * @see {@link https://api.jquery.com/replaceWith/}
889
+ */
890
+ export function replaceWith<T extends AnyNode>(
891
+ this: Cheerio<T>,
892
+ content: AcceptedElems<AnyNode>,
893
+ ): Cheerio<T> {
894
+ return domEach(this, (el, i) => {
895
+ const { parent } = el;
896
+ if (!parent) {
897
+ return;
898
+ }
899
+
900
+ const siblings: AnyNode[] = parent.children;
901
+ const cont =
902
+ typeof content === 'function' ? content.call(el, i, el) : content;
903
+ const dom = this._makeDomArray(cont);
904
+
905
+ /*
906
+ * In the case that `dom` contains nodes that already exist in other
907
+ * structures, ensure those nodes are properly removed.
908
+ */
909
+ updateDOM(dom, null);
910
+
911
+ const index = siblings.indexOf(el);
912
+
913
+ // Completely remove old element
914
+ uniqueSplice(siblings, index, 1, dom, parent);
915
+
916
+ if (!dom.includes(el)) {
917
+ el.parent = el.prev = el.next = null;
918
+ }
919
+ });
920
+ }
921
+
922
+ /**
923
+ * Removes all children from each item in the selection. Text nodes and comment
924
+ * nodes are left as is.
925
+ *
926
+ * @category Manipulation
927
+ * @example
928
+ *
929
+ * ```js
930
+ * $('ul').empty();
931
+ * $.html();
932
+ * //=> <ul id="fruits"></ul>
933
+ * ```
934
+ *
935
+ * @returns The instance itself.
936
+ * @see {@link https://api.jquery.com/empty/}
937
+ */
938
+ export function empty<T extends AnyNode>(this: Cheerio<T>): Cheerio<T> {
939
+ return domEach(this, (el) => {
940
+ if (!hasChildren(el)) return;
941
+ for (const child of el.children) {
942
+ child.next = child.prev = child.parent = null;
943
+ }
944
+
945
+ el.children.length = 0;
946
+ });
947
+ }
948
+
949
+ /**
950
+ * Gets an HTML content string from the first selected element.
951
+ *
952
+ * @category Manipulation
953
+ * @example
954
+ *
955
+ * ```js
956
+ * $('.orange').html();
957
+ * //=> Orange
958
+ *
959
+ * $('#fruits').html('<li class="mango">Mango</li>').html();
960
+ * //=> <li class="mango">Mango</li>
961
+ * ```
962
+ *
963
+ * @returns The HTML content string.
964
+ * @see {@link https://api.jquery.com/html/}
965
+ */
966
+ export function html<T extends AnyNode>(this: Cheerio<T>): string | null;
967
+ /**
968
+ * Replaces each selected element's content with the specified content.
969
+ *
970
+ * @category Manipulation
971
+ * @example
972
+ *
973
+ * ```js
974
+ * $('.orange').html('<li class="mango">Mango</li>').html();
975
+ * //=> <li class="mango">Mango</li>
976
+ * ```
977
+ *
978
+ * @param str - The content to replace selection's contents with.
979
+ * @returns The instance itself.
980
+ * @see {@link https://api.jquery.com/html/}
981
+ */
982
+ export function html<T extends AnyNode>(
983
+ this: Cheerio<T>,
984
+ str: string | Cheerio<T>,
985
+ ): Cheerio<T>;
986
+ export function html<T extends AnyNode>(
987
+ this: Cheerio<T>,
988
+ str?: string | Cheerio<AnyNode>,
989
+ ): Cheerio<T> | string | null {
990
+ if (str === undefined) {
991
+ const el = this[0];
992
+ if (!el || !hasChildren(el)) return null;
993
+ return this._render(el.children);
994
+ }
995
+
996
+ return domEach(this, (el) => {
997
+ if (!hasChildren(el)) return;
998
+ for (const child of el.children) {
999
+ child.next = child.prev = child.parent = null;
1000
+ }
1001
+
1002
+ const content = isCheerio(str)
1003
+ ? str.toArray()
1004
+ : this._parse(`${str}`, this.options, false, el).children;
1005
+
1006
+ updateDOM(content, el);
1007
+ });
1008
+ }
1009
+
1010
+ /**
1011
+ * Turns the collection to a string. Alias for `.html()`.
1012
+ *
1013
+ * @category Manipulation
1014
+ * @returns The rendered document.
1015
+ */
1016
+ export function toString<T extends AnyNode>(this: Cheerio<T>): string {
1017
+ return this._render(this);
1018
+ }
1019
+
1020
+ /**
1021
+ * Get the combined text contents of each element in the set of matched
1022
+ * elements, including their descendants.
1023
+ *
1024
+ * @category Manipulation
1025
+ * @example
1026
+ *
1027
+ * ```js
1028
+ * $('.orange').text();
1029
+ * //=> Orange
1030
+ *
1031
+ * $('ul').text();
1032
+ * //=> Apple
1033
+ * // Orange
1034
+ * // Pear
1035
+ * ```
1036
+ *
1037
+ * @returns The text contents of the collection.
1038
+ * @see {@link https://api.jquery.com/text/}
1039
+ */
1040
+ export function text<T extends AnyNode>(this: Cheerio<T>): string;
1041
+ /**
1042
+ * Set the content of each element in the set of matched elements to the
1043
+ * specified text.
1044
+ *
1045
+ * @category Manipulation
1046
+ * @example
1047
+ *
1048
+ * ```js
1049
+ * $('.orange').text('Orange');
1050
+ * //=> <div class="orange">Orange</div>
1051
+ * ```
1052
+ *
1053
+ * @param str - The text to set as the content of each matched element.
1054
+ * @returns The instance itself.
1055
+ * @see {@link https://api.jquery.com/text/}
1056
+ */
1057
+ export function text<T extends AnyNode>(
1058
+ this: Cheerio<T>,
1059
+ str: string | ((this: AnyNode, i: number, text: string) => string),
1060
+ ): Cheerio<T>;
1061
+ export function text<T extends AnyNode>(
1062
+ this: Cheerio<T>,
1063
+ str?: string | ((this: AnyNode, i: number, text: string) => string),
1064
+ ): Cheerio<T> | string {
1065
+ // If `str` is undefined, act as a "getter"
1066
+ if (str === undefined) {
1067
+ return staticText(this);
1068
+ }
1069
+ if (typeof str === 'function') {
1070
+ // Function support
1071
+ return domEach(this, (el, i) =>
1072
+ this._make(el).text(str.call(el, i, staticText([el]))),
1073
+ );
1074
+ }
1075
+
1076
+ // Append text node to each selected elements
1077
+ return domEach(this, (el) => {
1078
+ if (!hasChildren(el)) return;
1079
+ for (const child of el.children) {
1080
+ child.next = child.prev = child.parent = null;
1081
+ }
1082
+
1083
+ const textNode = new Text(`${str}`);
1084
+
1085
+ updateDOM(textNode, el);
1086
+ });
1087
+ }
1088
+
1089
+ /**
1090
+ * Clone the cheerio object.
1091
+ *
1092
+ * @category Manipulation
1093
+ * @example
1094
+ *
1095
+ * ```js
1096
+ * const moreFruit = $('#fruits').clone();
1097
+ * ```
1098
+ *
1099
+ * @returns The cloned object.
1100
+ * @see {@link https://api.jquery.com/clone/}
1101
+ */
1102
+ export function clone<T extends AnyNode>(this: Cheerio<T>): Cheerio<T> {
1103
+ const clone = Array.prototype.map.call(
1104
+ this.get(),
1105
+ (el) => cloneNode(el, true) as T,
1106
+ ) as T[];
1107
+
1108
+ // Add a root node around the cloned nodes
1109
+ const root = new Document(clone);
1110
+ for (const node of clone) {
1111
+ node.parent = root;
1112
+ }
1113
+
1114
+ return this._make(clone);
1115
+ }