@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
package/src/api/css.ts ADDED
@@ -0,0 +1,224 @@
1
+ import { domEach } from '../utils.js';
2
+ import { isTag, type Element, type AnyNode } from 'domhandler';
3
+ import type { Cheerio } from '../cheerio.js';
4
+
5
+ /**
6
+ * Get the value of a style property for the first element in the set of matched
7
+ * elements.
8
+ *
9
+ * @category CSS
10
+ * @param names - Optionally the names of the properties of interest.
11
+ * @returns A map of all of the style properties.
12
+ * @see {@link https://api.jquery.com/css/}
13
+ */
14
+ export function css<T extends AnyNode>(
15
+ this: Cheerio<T>,
16
+ names?: string[],
17
+ ): Record<string, string> | undefined;
18
+ /**
19
+ * Get the value of a style property for the first element in the set of matched
20
+ * elements.
21
+ *
22
+ * @category CSS
23
+ * @param name - The name of the property.
24
+ * @returns The property value for the given name.
25
+ * @see {@link https://api.jquery.com/css/}
26
+ */
27
+ export function css<T extends AnyNode>(
28
+ this: Cheerio<T>,
29
+ name: string,
30
+ ): string | undefined;
31
+ /**
32
+ * Set one CSS property for every matched element.
33
+ *
34
+ * @category CSS
35
+ * @param prop - The name of the property.
36
+ * @param val - The new value.
37
+ * @returns The instance itself.
38
+ * @see {@link https://api.jquery.com/css/}
39
+ */
40
+ export function css<T extends AnyNode>(
41
+ this: Cheerio<T>,
42
+ prop: string,
43
+ val:
44
+ | string
45
+ | ((this: Element, i: number, style: string) => string | undefined),
46
+ ): Cheerio<T>;
47
+ /**
48
+ * Set multiple CSS properties for every matched element.
49
+ *
50
+ * @category CSS
51
+ * @param map - A map of property names and values.
52
+ * @returns The instance itself.
53
+ * @see {@link https://api.jquery.com/css/}
54
+ */
55
+ export function css<T extends AnyNode>(
56
+ this: Cheerio<T>,
57
+ map: Record<string, string>,
58
+ ): Cheerio<T>;
59
+ /**
60
+ * Set multiple CSS properties for every matched element.
61
+ *
62
+ * @category CSS
63
+ * @param prop - The names of the properties.
64
+ * @param val - The new values.
65
+ * @returns The instance itself.
66
+ * @see {@link https://api.jquery.com/css/}
67
+ */
68
+ export function css<T extends AnyNode>(
69
+ this: Cheerio<T>,
70
+ prop?: string | string[] | Record<string, string>,
71
+ val?:
72
+ | string
73
+ | ((this: Element, i: number, style: string) => string | undefined),
74
+ ): Cheerio<T> | Record<string, string> | string | undefined {
75
+ if (
76
+ (prop != null && val != null) ||
77
+ // When `prop` is a "plain" object
78
+ (typeof prop === 'object' && !Array.isArray(prop))
79
+ ) {
80
+ return domEach(this, (el, i) => {
81
+ if (isTag(el)) {
82
+ // `prop` can't be an array here anymore.
83
+ setCss(el, prop as string, val, i);
84
+ }
85
+ });
86
+ }
87
+
88
+ if (this.length === 0) {
89
+ return undefined;
90
+ }
91
+
92
+ return getCss(this[0], prop as string);
93
+ }
94
+
95
+ /**
96
+ * Set styles of all elements.
97
+ *
98
+ * @private
99
+ * @param el - Element to set style of.
100
+ * @param prop - Name of property.
101
+ * @param value - Value to set property to.
102
+ * @param idx - Optional index within the selection.
103
+ */
104
+ function setCss(
105
+ el: Element,
106
+ prop: string | Record<string, string>,
107
+ value:
108
+ | string
109
+ | ((this: Element, i: number, style: string) => string | undefined)
110
+ | undefined,
111
+ idx: number,
112
+ ) {
113
+ if (typeof prop === 'string') {
114
+ const styles = getCss(el);
115
+
116
+ const val =
117
+ typeof value === 'function' ? value.call(el, idx, styles[prop]) : value;
118
+
119
+ if (val === '') {
120
+ delete styles[prop];
121
+ } else if (val != null) {
122
+ styles[prop] = val;
123
+ }
124
+
125
+ el.attribs['style'] = stringify(styles);
126
+ } else if (typeof prop === 'object') {
127
+ const keys = Object.keys(prop);
128
+ for (let i = 0; i < keys.length; i++) {
129
+ const k = keys[i];
130
+ setCss(el, k, prop[k], i);
131
+ }
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Get the parsed styles of the first element.
137
+ *
138
+ * @private
139
+ * @category CSS
140
+ * @param el - Element to get styles from.
141
+ * @param props - Optionally the names of the properties of interest.
142
+ * @returns The parsed styles.
143
+ */
144
+ function getCss(el: AnyNode, props?: string[]): Record<string, string>;
145
+ /**
146
+ * Get a property from the parsed styles of the first element.
147
+ *
148
+ * @private
149
+ * @category CSS
150
+ * @param el - Element to get styles from.
151
+ * @param prop - Name of the prop.
152
+ * @returns The value of the property.
153
+ */
154
+ function getCss(el: AnyNode, prop: string): string | undefined;
155
+ function getCss(
156
+ el: AnyNode,
157
+ prop?: string | string[],
158
+ ): Record<string, string> | string | undefined {
159
+ if (!el || !isTag(el)) return;
160
+
161
+ const styles = parse(el.attribs['style']);
162
+ if (typeof prop === 'string') {
163
+ return styles[prop];
164
+ }
165
+ if (Array.isArray(prop)) {
166
+ const newStyles: Record<string, string> = {};
167
+ for (const item of prop) {
168
+ if (styles[item] != null) {
169
+ newStyles[item] = styles[item];
170
+ }
171
+ }
172
+ return newStyles;
173
+ }
174
+ return styles;
175
+ }
176
+
177
+ /**
178
+ * Stringify `obj` to styles.
179
+ *
180
+ * @private
181
+ * @category CSS
182
+ * @param obj - Object to stringify.
183
+ * @returns The serialized styles.
184
+ */
185
+ function stringify(obj: Record<string, string>): string {
186
+ return Object.keys(obj).reduce(
187
+ (str, prop) => `${str}${str ? ' ' : ''}${prop}: ${obj[prop]};`,
188
+ '',
189
+ );
190
+ }
191
+
192
+ /**
193
+ * Parse `styles`.
194
+ *
195
+ * @private
196
+ * @category CSS
197
+ * @param styles - Styles to be parsed.
198
+ * @returns The parsed styles.
199
+ */
200
+ function parse(styles: string): Record<string, string> {
201
+ styles = (styles || '').trim();
202
+
203
+ if (!styles) return {};
204
+
205
+ const obj: Record<string, string> = {};
206
+
207
+ let key: string | undefined;
208
+
209
+ for (const str of styles.split(';')) {
210
+ const n = str.indexOf(':');
211
+ // If there is no :, or if it is the first/last character, add to the previous item's value
212
+ if (n < 1 || n === str.length - 1) {
213
+ const trimmed = str.trimEnd();
214
+ if (trimmed.length > 0 && key !== undefined) {
215
+ obj[key] += `;${trimmed}`;
216
+ }
217
+ } else {
218
+ key = str.slice(0, n).trim();
219
+ obj[key] = str.slice(n + 1).trim();
220
+ }
221
+ }
222
+
223
+ return obj;
224
+ }
@@ -0,0 +1,92 @@
1
+ import type { AnyNode, Element } from 'domhandler';
2
+ import type { Cheerio } from '../cheerio.js';
3
+ import type { prop } from './attributes.js';
4
+
5
+ type ExtractDescriptorFn = (
6
+ el: Element,
7
+ key: string,
8
+ // TODO: This could be typed with ExtractedMap
9
+ obj: Record<string, unknown>,
10
+ ) => unknown;
11
+
12
+ interface ExtractDescriptor {
13
+ selector: string;
14
+ value?: string | ExtractDescriptorFn | ExtractMap;
15
+ }
16
+
17
+ type ExtractValue = string | ExtractDescriptor | [string | ExtractDescriptor];
18
+
19
+ export type ExtractMap = Record<string, ExtractValue>;
20
+
21
+ type ExtractedValue<V extends ExtractValue> = V extends [
22
+ string | ExtractDescriptor,
23
+ ]
24
+ ? NonNullable<ExtractedValue<V[0]>>[]
25
+ : V extends string
26
+ ? string | undefined
27
+ : V extends ExtractDescriptor
28
+ ? V['value'] extends infer U
29
+ ? U extends ExtractMap
30
+ ? ExtractedMap<U> | undefined
31
+ : U extends ExtractDescriptorFn
32
+ ? ReturnType<U> | undefined
33
+ : ReturnType<typeof prop> | undefined
34
+ : never
35
+ : never;
36
+
37
+ export type ExtractedMap<M extends ExtractMap> = {
38
+ [key in keyof M]: ExtractedValue<M[key]>;
39
+ };
40
+
41
+ function getExtractDescr(
42
+ descr: string | ExtractDescriptor,
43
+ ): Required<ExtractDescriptor> {
44
+ if (typeof descr === 'string') {
45
+ return { selector: descr, value: 'textContent' };
46
+ }
47
+
48
+ return {
49
+ selector: descr.selector,
50
+ value: descr.value ?? 'textContent',
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Extract multiple values from a document, and store them in an object.
56
+ *
57
+ * @param map - An object containing key-value pairs. The keys are the names of
58
+ * the properties to be created on the object, and the values are the
59
+ * selectors to be used to extract the values.
60
+ * @returns An object containing the extracted values.
61
+ */
62
+ export function extract<M extends ExtractMap, T extends AnyNode>(
63
+ this: Cheerio<T>,
64
+ map: M,
65
+ ): ExtractedMap<M> {
66
+ const ret: Record<string, unknown> = {};
67
+
68
+ for (const key in map) {
69
+ const descr = map[key];
70
+ const isArray = Array.isArray(descr);
71
+
72
+ const { selector, value } = getExtractDescr(isArray ? descr[0] : descr);
73
+
74
+ const fn: ExtractDescriptorFn =
75
+ typeof value === 'function'
76
+ ? value
77
+ : typeof value === 'string'
78
+ ? (el: Element) => this._make(el).prop(value)
79
+ : (el: Element) => this._make(el).extract(value);
80
+
81
+ if (isArray) {
82
+ ret[key] = this._findBySelector(selector, Number.POSITIVE_INFINITY)
83
+ .map((_, el) => fn(el, key, ret))
84
+ .get();
85
+ } else {
86
+ const $ = this._findBySelector(selector, 1);
87
+ ret[key] = $.length > 0 ? fn($[0], key, ret) : undefined;
88
+ }
89
+ }
90
+
91
+ return ret as ExtractedMap<M>;
92
+ }
@@ -0,0 +1,103 @@
1
+ import { isTag, type AnyNode } from 'domhandler';
2
+ import type { Cheerio } from '../cheerio.js';
3
+
4
+ /*
5
+ * https://github.com/jquery/jquery/blob/2.1.3/src/manipulation/var/rcheckableType.js
6
+ * https://github.com/jquery/jquery/blob/2.1.3/src/serialize.js
7
+ */
8
+ const submittableSelector = 'input,select,textarea,keygen';
9
+ const r20 = /%20/g;
10
+ const rCRLF = /\r?\n/g;
11
+
12
+ /**
13
+ * Encode a set of form elements as a string for submission.
14
+ *
15
+ * @category Forms
16
+ * @example
17
+ *
18
+ * ```js
19
+ * $('<form><input name="foo" value="bar" /></form>').serialize();
20
+ * //=> 'foo=bar'
21
+ * ```
22
+ *
23
+ * @returns The serialized form.
24
+ * @see {@link https://api.jquery.com/serialize/}
25
+ */
26
+ export function serialize<T extends AnyNode>(this: Cheerio<T>): string {
27
+ // Convert form elements into name/value objects
28
+ const arr = this.serializeArray();
29
+
30
+ // Serialize each element into a key/value string
31
+ const retArr = arr.map(
32
+ (data) =>
33
+ `${encodeURIComponent(data.name)}=${encodeURIComponent(data.value)}`,
34
+ );
35
+
36
+ // Return the resulting serialization
37
+ return retArr.join('&').replace(r20, '+');
38
+ }
39
+
40
+ /**
41
+ * Encode a set of form elements as an array of names and values.
42
+ *
43
+ * @category Forms
44
+ * @example
45
+ *
46
+ * ```js
47
+ * $('<form><input name="foo" value="bar" /></form>').serializeArray();
48
+ * //=> [ { name: 'foo', value: 'bar' } ]
49
+ * ```
50
+ *
51
+ * @returns The serialized form.
52
+ * @see {@link https://api.jquery.com/serializeArray/}
53
+ */
54
+ export function serializeArray<T extends AnyNode>(
55
+ this: Cheerio<T>,
56
+ ): {
57
+ name: string;
58
+ value: string;
59
+ }[] {
60
+ // Resolve all form elements from either forms or collections of form elements
61
+ return this.map((_, elem) => {
62
+ const $elem = this._make(elem);
63
+ if (isTag(elem) && elem.name === 'form') {
64
+ return $elem.find(submittableSelector).toArray();
65
+ }
66
+ return $elem.filter(submittableSelector).toArray();
67
+ })
68
+ .filter(
69
+ // Verify elements have a name (`attr.name`) and are not disabled (`:enabled`)
70
+ '[name!=""]:enabled' +
71
+ // And cannot be clicked (`[type=submit]`) or are used in `x-www-form-urlencoded` (`[type=file]`)
72
+ ':not(:submit, :button, :image, :reset, :file)' +
73
+ // And are either checked/don't have a checkable state
74
+ ':matches([checked], :not(:checkbox, :radio))',
75
+ // Convert each of the elements to its value(s)
76
+ )
77
+ .map<
78
+ AnyNode,
79
+ {
80
+ name: string;
81
+ value: string;
82
+ }
83
+ >((_, elem) => {
84
+ const $elem = this._make(elem);
85
+ const name = $elem.attr('name')!; // We have filtered for elements with a name before.
86
+ // If there is no value set (e.g. `undefined`, `null`), then default value to empty
87
+ const value = $elem.val() ?? '';
88
+
89
+ // If we have an array of values (e.g. `<select multiple>`), return an array of key/value pairs
90
+ if (Array.isArray(value)) {
91
+ return value.map((val) =>
92
+ /*
93
+ * We trim replace any line endings (e.g. `\r` or `\r\n` with `\r\n`) to guarantee consistency across platforms
94
+ * These can occur inside of `<textarea>'s`
95
+ */
96
+ ({ name, value: val.replace(rCRLF, '\r\n') }),
97
+ );
98
+ }
99
+ // Otherwise (e.g. `<input type="text">`, return only one key/value pair
100
+ return { name, value: value.replace(rCRLF, '\r\n') };
101
+ })
102
+ .toArray();
103
+ }