This commit is contained in:
2025-05-12 05:38:44 +09:00
parent dced21c3f8
commit 6d78bfa46e
8120 changed files with 1161564 additions and 0 deletions

View File

@ -0,0 +1,385 @@
/**
* Methods for getting and modifying attributes.
*
* @module cheerio/attributes
*/
import { type AnyNode, type Element } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
/**
* Method for getting attributes. Gets the attribute value for only the first
* element in the matched set.
*
* @category Attributes
* @example
*
* ```js
* $('ul').attr('id');
* //=> fruits
* ```
*
* @param name - Name of the attribute.
* @returns The attribute's value.
* @see {@link https://api.jquery.com/attr/}
*/
export declare function attr<T extends AnyNode>(this: Cheerio<T>, name: string): string | undefined;
/**
* Method for getting all attributes and their values of the first element in
* the matched set.
*
* @category Attributes
* @example
*
* ```js
* $('ul').attr();
* //=> { id: 'fruits' }
* ```
*
* @returns The attribute's values.
* @see {@link https://api.jquery.com/attr/}
*/
export declare function attr<T extends AnyNode>(this: Cheerio<T>): Record<string, string> | undefined;
/**
* Method for setting attributes. Sets the attribute value for only the first
* element in the matched set. If you set an attribute's value to `null`, you
* remove that attribute. You may also pass a `map` and `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.apple').attr('id', 'favorite').html();
* //=> <li class="apple" id="favorite">Apple</li>
* ```
*
* @param name - Name of the attribute.
* @param value - The new value of the attribute.
* @returns The instance itself.
* @see {@link https://api.jquery.com/attr/}
*/
export declare function attr<T extends AnyNode>(this: Cheerio<T>, name: string, value?: string | null | ((this: Element, i: number, attrib: string) => string | null)): Cheerio<T>;
/**
* Method for setting multiple attributes at once. Sets the attribute value for
* only the first element in the matched set. If you set an attribute's value to
* `null`, you remove that attribute.
*
* @category Attributes
* @example
*
* ```js
* $('.apple').attr({ id: 'favorite' }).html();
* //=> <li class="apple" id="favorite">Apple</li>
* ```
*
* @param values - Map of attribute names and values.
* @returns The instance itself.
* @see {@link https://api.jquery.com/attr/}
*/
export declare function attr<T extends AnyNode>(this: Cheerio<T>, values: Record<string, string | null>): Cheerio<T>;
interface StyleProp {
length: number;
[key: string]: string | number;
[index: number]: string;
}
/**
* Method for getting and setting properties. Gets the property value for only
* the first element in the matched set.
*
* @category Attributes
* @example
*
* ```js
* $('input[type="checkbox"]').prop('checked');
* //=> false
*
* $('input[type="checkbox"]').prop('checked', true).val();
* //=> ok
* ```
*
* @param name - Name of the property.
* @returns If `value` is specified the instance itself, otherwise the prop's
* value.
* @see {@link https://api.jquery.com/prop/}
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: 'tagName' | 'nodeName'): string | undefined;
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: 'innerHTML' | 'outerHTML' | 'innerText' | 'textContent'): string | null;
/**
* Get a parsed CSS style object.
*
* @param name - Name of the property.
* @returns The style object, or `undefined` if the element has no `style`
* attribute.
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: 'style'): StyleProp | undefined;
/**
* Resolve `href` or `src` of supported elements. Requires the `baseURI` option
* to be set, and a global `URL` object to be part of the environment.
*
* @example With `baseURI` set to `'https://example.com'`:
*
* ```js
* $('<img src="image.png">').prop('src');
* //=> 'https://example.com/image.png'
* ```
*
* @param name - Name of the property.
* @returns The resolved URL, or `undefined` if the element is not supported.
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: 'href' | 'src'): string | undefined;
/**
* Get a property of an element.
*
* @param name - Name of the property.
* @returns The property's value.
*/
export declare function prop<T extends AnyNode, K extends keyof Element>(this: Cheerio<T>, name: K): Element[K];
/**
* Set a property of an element.
*
* @param name - Name of the property.
* @param value - Value to set the property to.
* @returns The instance itself.
*/
export declare function prop<T extends AnyNode, K extends keyof Element>(this: Cheerio<T>, name: K, value: Element[K] | ((this: Element, i: number, prop: K) => Element[keyof Element])): Cheerio<T>;
/**
* Set multiple properties of an element.
*
* @example
*
* ```js
* $('input[type="checkbox"]').prop({
* checked: true,
* disabled: false,
* });
* ```
*
* @param map - Object of properties to set.
* @returns The instance itself.
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, map: Record<string, string | Element[keyof Element] | boolean>): Cheerio<T>;
/**
* Set a property of an element.
*
* @param name - Name of the property.
* @param value - Value to set the property to.
* @returns The instance itself.
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: string, value: string | boolean | null | ((this: Element, i: number, prop: string) => string | boolean)): Cheerio<T>;
/**
* Get a property of an element.
*
* @param name - The property's name.
* @returns The property's value.
*/
export declare function prop<T extends AnyNode>(this: Cheerio<T>, name: string): string;
/**
* Method for getting data attributes, for only the first element in the matched
* set.
*
* @category Attributes
* @example
*
* ```js
* $('<div data-apple-color="red"></div>').data('apple-color');
* //=> 'red'
* ```
*
* @param name - Name of the data attribute.
* @returns The data attribute's value, or `undefined` if the attribute does not
* exist.
* @see {@link https://api.jquery.com/data/}
*/
export declare function data<T extends AnyNode>(this: Cheerio<T>, name: string): unknown | undefined;
/**
* Method for getting all of an element's data attributes, for only the first
* element in the matched set.
*
* @category Attributes
* @example
*
* ```js
* $('<div data-apple-color="red"></div>').data();
* //=> { appleColor: 'red' }
* ```
*
* @returns A map with all of the data attributes.
* @see {@link https://api.jquery.com/data/}
*/
export declare function data<T extends AnyNode>(this: Cheerio<T>): Record<string, unknown>;
/**
* Method for setting data attributes, for only the first element in the matched
* set.
*
* @category Attributes
* @example
*
* ```js
* const apple = $('.apple').data('kind', 'mac');
*
* apple.data('kind');
* //=> 'mac'
* ```
*
* @param name - Name of the data attribute.
* @param value - The new value.
* @returns The instance itself.
* @see {@link https://api.jquery.com/data/}
*/
export declare function data<T extends AnyNode>(this: Cheerio<T>, name: string, value: unknown): Cheerio<T>;
/**
* Method for setting multiple data attributes at once, for only the first
* element in the matched set.
*
* @category Attributes
* @example
*
* ```js
* const apple = $('.apple').data({ kind: 'mac' });
*
* apple.data('kind');
* //=> 'mac'
* ```
*
* @param values - Map of names to values.
* @returns The instance itself.
* @see {@link https://api.jquery.com/data/}
*/
export declare function data<T extends AnyNode>(this: Cheerio<T>, values: Record<string, unknown>): Cheerio<T>;
/**
* Method for getting the value of input, select, and textarea. Note: Support
* for `map`, and `function` has not been added yet.
*
* @category Attributes
* @example
*
* ```js
* $('input[type="text"]').val();
* //=> input_text
* ```
*
* @returns The value.
* @see {@link https://api.jquery.com/val/}
*/
export declare function val<T extends AnyNode>(this: Cheerio<T>): string | undefined | string[];
/**
* Method for setting the value of input, select, and textarea. Note: Support
* for `map`, and `function` has not been added yet.
*
* @category Attributes
* @example
*
* ```js
* $('input[type="text"]').val('test').html();
* //=> <input type="text" value="test"/>
* ```
*
* @param value - The new value.
* @returns The instance itself.
* @see {@link https://api.jquery.com/val/}
*/
export declare function val<T extends AnyNode>(this: Cheerio<T>, value: string | string[]): Cheerio<T>;
/**
* Method for removing attributes by `name`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').removeAttr('class').html();
* //=> <li>Pear</li>
*
* $('.apple').attr('id', 'favorite');
* $('.apple').removeAttr('id class').html();
* //=> <li>Apple</li>
* ```
*
* @param name - Name of the attribute.
* @returns The instance itself.
* @see {@link https://api.jquery.com/removeAttr/}
*/
export declare function removeAttr<T extends AnyNode>(this: Cheerio<T>, name: string): Cheerio<T>;
/**
* Check to see if _any_ of the matched elements have the given `className`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').hasClass('pear');
* //=> true
*
* $('apple').hasClass('fruit');
* //=> false
*
* $('li').hasClass('pear');
* //=> true
* ```
*
* @param className - Name of the class.
* @returns Indicates if an element has the given `className`.
* @see {@link https://api.jquery.com/hasClass/}
*/
export declare function hasClass<T extends AnyNode>(this: Cheerio<T>, className: string): boolean;
/**
* Adds class(es) to all of the matched elements. Also accepts a `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').addClass('fruit').html();
* //=> <li class="pear fruit">Pear</li>
*
* $('.apple').addClass('fruit red').html();
* //=> <li class="apple fruit red">Apple</li>
* ```
*
* @param value - Name of new class.
* @returns The instance itself.
* @see {@link https://api.jquery.com/addClass/}
*/
export declare function addClass<T extends AnyNode, R extends ArrayLike<T>>(this: R, value?: string | ((this: Element, i: number, className: string) => string | undefined)): R;
/**
* Removes one or more space-separated classes from the selected elements. If no
* `className` is defined, all classes will be removed. Also accepts a
* `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').removeClass('pear').html();
* //=> <li class="">Pear</li>
*
* $('.apple').addClass('red').removeClass().html();
* //=> <li class="">Apple</li>
* ```
*
* @param name - Name of the class. If not specified, removes all elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/removeClass/}
*/
export declare function removeClass<T extends AnyNode, R extends ArrayLike<T>>(this: R, name?: string | ((this: Element, i: number, className: string) => string | undefined)): R;
/**
* Add or remove class(es) from the matched elements, depending on either the
* class's presence or the value of the switch argument. Also accepts a
* `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.apple.green').toggleClass('fruit green red').html();
* //=> <li class="apple fruit red">Apple</li>
*
* $('.apple.green').toggleClass('fruit green red', true).html();
* //=> <li class="apple green fruit red">Apple</li>
* ```
*
* @param value - Name of the class. Can also be a function.
* @param stateVal - If specified the state of the class.
* @returns The instance itself.
* @see {@link https://api.jquery.com/toggleClass/}
*/
export declare function toggleClass<T extends AnyNode, R extends ArrayLike<T>>(this: R, value?: string | ((this: Element, i: number, className: string, stateVal?: boolean) => string), stateVal?: boolean): R;
export {};
//# sourceMappingURL=attributes.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/api/attributes.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,619 @@
/**
* Methods for getting and modifying attributes.
*
* @module cheerio/attributes
*/
import { text } from '../static.js';
import { domEach, camelCase, cssCase } from '../utils.js';
import { isTag } from 'domhandler';
import { innerText, textContent } from 'domutils';
const hasOwn = Object.prototype.hasOwnProperty;
const rspace = /\s+/;
const dataAttrPrefix = 'data-';
// Attributes that are booleans
const rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i;
// Matches strings that look like JSON objects or arrays
const rbrace = /^{[^]*}$|^\[[^]*]$/;
function getAttr(elem, name, xmlMode) {
var _a;
if (!elem || !isTag(elem))
return undefined;
(_a = elem.attribs) !== null && _a !== void 0 ? _a : (elem.attribs = {});
// Return the entire attribs object if no attribute specified
if (!name) {
return elem.attribs;
}
if (hasOwn.call(elem.attribs, name)) {
// Get the (decoded) attribute
return !xmlMode && rboolean.test(name) ? name : elem.attribs[name];
}
// Mimic the DOM and return text content as value for `option's`
if (elem.name === 'option' && name === 'value') {
return text(elem.children);
}
// Mimic DOM with default value for radios/checkboxes
if (elem.name === 'input' &&
(elem.attribs['type'] === 'radio' || elem.attribs['type'] === 'checkbox') &&
name === 'value') {
return 'on';
}
return undefined;
}
/**
* Sets the value of an attribute. The attribute will be deleted if the value is
* `null`.
*
* @private
* @param el - The element to set the attribute on.
* @param name - The attribute's name.
* @param value - The attribute's value.
*/
function setAttr(el, name, value) {
if (value === null) {
removeAttribute(el, name);
}
else {
el.attribs[name] = `${value}`;
}
}
export function attr(name, value) {
// Set the value (with attr map support)
if (typeof name === 'object' || value !== undefined) {
if (typeof value === 'function') {
if (typeof name !== 'string') {
{
throw new Error('Bad combination of arguments.');
}
}
return domEach(this, (el, i) => {
if (isTag(el))
setAttr(el, name, value.call(el, i, el.attribs[name]));
});
}
return domEach(this, (el) => {
if (!isTag(el))
return;
if (typeof name === 'object') {
for (const objName of Object.keys(name)) {
const objValue = name[objName];
setAttr(el, objName, objValue);
}
}
else {
setAttr(el, name, value);
}
});
}
return arguments.length > 1
? this
: getAttr(this[0], name, this.options.xmlMode);
}
/**
* Gets a node's prop.
*
* @private
* @category Attributes
* @param el - Element to get the prop of.
* @param name - Name of the prop.
* @param xmlMode - Disable handling of special HTML attributes.
* @returns The prop's value.
*/
function getProp(el, name, xmlMode) {
return name in el
? // @ts-expect-error TS doesn't like us accessing the value directly here.
el[name]
: !xmlMode && rboolean.test(name)
? getAttr(el, name, false) !== undefined
: getAttr(el, name, xmlMode);
}
/**
* Sets the value of a prop.
*
* @private
* @param el - The element to set the prop on.
* @param name - The prop's name.
* @param value - The prop's value.
* @param xmlMode - Disable handling of special HTML attributes.
*/
function setProp(el, name, value, xmlMode) {
if (name in el) {
// @ts-expect-error Overriding value
el[name] = value;
}
else {
setAttr(el, name, !xmlMode && rboolean.test(name) ? (value ? '' : null) : `${value}`);
}
}
export function prop(name, value) {
var _a;
if (typeof name === 'string' && value === undefined) {
const el = this[0];
if (!el || !isTag(el))
return undefined;
switch (name) {
case 'style': {
const property = this.css();
const keys = Object.keys(property);
for (let i = 0; i < keys.length; i++) {
property[i] = keys[i];
}
property.length = keys.length;
return property;
}
case 'tagName':
case 'nodeName': {
return el.name.toUpperCase();
}
case 'href':
case 'src': {
const prop = (_a = el.attribs) === null || _a === void 0 ? void 0 : _a[name];
if (typeof URL !== 'undefined' &&
((name === 'href' && (el.tagName === 'a' || el.tagName === 'link')) ||
(name === 'src' &&
(el.tagName === 'img' ||
el.tagName === 'iframe' ||
el.tagName === 'audio' ||
el.tagName === 'video' ||
el.tagName === 'source'))) &&
prop !== undefined &&
this.options.baseURI) {
return new URL(prop, this.options.baseURI).href;
}
return prop;
}
case 'innerText': {
return innerText(el);
}
case 'textContent': {
return textContent(el);
}
case 'outerHTML': {
return this.clone().wrap('<container />').parent().html();
}
case 'innerHTML': {
return this.html();
}
default: {
return getProp(el, name, this.options.xmlMode);
}
}
}
if (typeof name === 'object' || value !== undefined) {
if (typeof value === 'function') {
if (typeof name === 'object') {
throw new TypeError('Bad combination of arguments.');
}
return domEach(this, (el, i) => {
if (isTag(el)) {
setProp(el, name, value.call(el, i, getProp(el, name, this.options.xmlMode)), this.options.xmlMode);
}
});
}
return domEach(this, (el) => {
if (!isTag(el))
return;
if (typeof name === 'object') {
for (const key of Object.keys(name)) {
const val = name[key];
setProp(el, key, val, this.options.xmlMode);
}
}
else {
setProp(el, name, value, this.options.xmlMode);
}
});
}
return undefined;
}
/**
* Sets the value of a data attribute.
*
* @private
* @param elem - The element to set the data attribute on.
* @param name - The data attribute's name.
* @param value - The data attribute's value.
*/
function setData(elem, name, value) {
var _a;
(_a = elem.data) !== null && _a !== void 0 ? _a : (elem.data = {});
if (typeof name === 'object')
Object.assign(elem.data, name);
else if (typeof name === 'string' && value !== undefined) {
elem.data[name] = value;
}
}
/**
* Read _all_ HTML5 `data-*` attributes from the equivalent HTML5 `data-*`
* attribute, and cache the value in the node's internal data store.
*
* @private
* @category Attributes
* @param el - Element to get the data attribute of.
* @returns A map with all of the data attributes.
*/
function readAllData(el) {
for (const domName of Object.keys(el.attribs)) {
if (!domName.startsWith(dataAttrPrefix)) {
continue;
}
const jsName = camelCase(domName.slice(dataAttrPrefix.length));
if (!hasOwn.call(el.data, jsName)) {
el.data[jsName] = parseDataValue(el.attribs[domName]);
}
}
return el.data;
}
/**
* Read the specified attribute from the equivalent HTML5 `data-*` attribute,
* and (if present) cache the value in the node's internal data store.
*
* @private
* @category Attributes
* @param el - Element to get the data attribute of.
* @param name - Name of the data attribute.
* @returns The data attribute's value.
*/
function readData(el, name) {
const domName = dataAttrPrefix + cssCase(name);
const data = el.data;
if (hasOwn.call(data, name)) {
return data[name];
}
if (hasOwn.call(el.attribs, domName)) {
return (data[name] = parseDataValue(el.attribs[domName]));
}
return undefined;
}
/**
* Coerce string data-* attributes to their corresponding JavaScript primitives.
*
* @private
* @category Attributes
* @param value - The value to parse.
* @returns The parsed value.
*/
function parseDataValue(value) {
if (value === 'null')
return null;
if (value === 'true')
return true;
if (value === 'false')
return false;
const num = Number(value);
if (value === String(num))
return num;
if (rbrace.test(value)) {
try {
return JSON.parse(value);
}
catch {
/* Ignore */
}
}
return value;
}
export function data(name, value) {
var _a;
const elem = this[0];
if (!elem || !isTag(elem))
return;
const dataEl = elem;
(_a = dataEl.data) !== null && _a !== void 0 ? _a : (dataEl.data = {});
// Return the entire data object if no data specified
if (name == null) {
return readAllData(dataEl);
}
// Set the value (with attr map support)
if (typeof name === 'object' || value !== undefined) {
domEach(this, (el) => {
if (isTag(el)) {
if (typeof name === 'object')
setData(el, name);
else
setData(el, name, value);
}
});
return this;
}
return readData(dataEl, name);
}
export function val(value) {
const querying = arguments.length === 0;
const element = this[0];
if (!element || !isTag(element))
return querying ? undefined : this;
switch (element.name) {
case 'textarea': {
return this.text(value);
}
case 'select': {
const option = this.find('option:selected');
if (!querying) {
if (this.attr('multiple') == null && typeof value === 'object') {
return this;
}
this.find('option').removeAttr('selected');
const values = typeof value === 'object' ? value : [value];
for (const val of values) {
this.find(`option[value="${val}"]`).attr('selected', '');
}
return this;
}
return this.attr('multiple')
? option.toArray().map((el) => text(el.children))
: option.attr('value');
}
case 'input':
case 'option': {
return querying
? this.attr('value')
: this.attr('value', value);
}
}
return undefined;
}
/**
* Remove an attribute.
*
* @private
* @param elem - Node to remove attribute from.
* @param name - Name of the attribute to remove.
*/
function removeAttribute(elem, name) {
if (!elem.attribs || !hasOwn.call(elem.attribs, name))
return;
delete elem.attribs[name];
}
/**
* Splits a space-separated list of names to individual names.
*
* @category Attributes
* @param names - Names to split.
* @returns - Split names.
*/
function splitNames(names) {
return names ? names.trim().split(rspace) : [];
}
/**
* Method for removing attributes by `name`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').removeAttr('class').html();
* //=> <li>Pear</li>
*
* $('.apple').attr('id', 'favorite');
* $('.apple').removeAttr('id class').html();
* //=> <li>Apple</li>
* ```
*
* @param name - Name of the attribute.
* @returns The instance itself.
* @see {@link https://api.jquery.com/removeAttr/}
*/
export function removeAttr(name) {
const attrNames = splitNames(name);
for (const attrName of attrNames) {
domEach(this, (elem) => {
if (isTag(elem))
removeAttribute(elem, attrName);
});
}
return this;
}
/**
* Check to see if _any_ of the matched elements have the given `className`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').hasClass('pear');
* //=> true
*
* $('apple').hasClass('fruit');
* //=> false
*
* $('li').hasClass('pear');
* //=> true
* ```
*
* @param className - Name of the class.
* @returns Indicates if an element has the given `className`.
* @see {@link https://api.jquery.com/hasClass/}
*/
export function hasClass(className) {
return this.toArray().some((elem) => {
const clazz = isTag(elem) && elem.attribs['class'];
let idx = -1;
if (clazz && className.length > 0) {
while ((idx = clazz.indexOf(className, idx + 1)) > -1) {
const end = idx + className.length;
if ((idx === 0 || rspace.test(clazz[idx - 1])) &&
(end === clazz.length || rspace.test(clazz[end]))) {
return true;
}
}
}
return false;
});
}
/**
* Adds class(es) to all of the matched elements. Also accepts a `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').addClass('fruit').html();
* //=> <li class="pear fruit">Pear</li>
*
* $('.apple').addClass('fruit red').html();
* //=> <li class="apple fruit red">Apple</li>
* ```
*
* @param value - Name of new class.
* @returns The instance itself.
* @see {@link https://api.jquery.com/addClass/}
*/
export function addClass(value) {
// Support functions
if (typeof value === 'function') {
return domEach(this, (el, i) => {
if (isTag(el)) {
const className = el.attribs['class'] || '';
addClass.call([el], value.call(el, i, className));
}
});
}
// Return if no value or not a string or function
if (!value || typeof value !== 'string')
return this;
const classNames = value.split(rspace);
const numElements = this.length;
for (let i = 0; i < numElements; i++) {
const el = this[i];
// If selected element isn't a tag, move on
if (!isTag(el))
continue;
// If we don't already have classes — always set xmlMode to false here, as it doesn't matter for classes
const className = getAttr(el, 'class', false);
if (className) {
let setClass = ` ${className} `;
// Check if class already exists
for (const cn of classNames) {
const appendClass = `${cn} `;
if (!setClass.includes(` ${appendClass}`))
setClass += appendClass;
}
setAttr(el, 'class', setClass.trim());
}
else {
setAttr(el, 'class', classNames.join(' ').trim());
}
}
return this;
}
/**
* Removes one or more space-separated classes from the selected elements. If no
* `className` is defined, all classes will be removed. Also accepts a
* `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.pear').removeClass('pear').html();
* //=> <li class="">Pear</li>
*
* $('.apple').addClass('red').removeClass().html();
* //=> <li class="">Apple</li>
* ```
*
* @param name - Name of the class. If not specified, removes all elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/removeClass/}
*/
export function removeClass(name) {
// Handle if value is a function
if (typeof name === 'function') {
return domEach(this, (el, i) => {
if (isTag(el)) {
removeClass.call([el], name.call(el, i, el.attribs['class'] || ''));
}
});
}
const classes = splitNames(name);
const numClasses = classes.length;
const removeAll = arguments.length === 0;
return domEach(this, (el) => {
if (!isTag(el))
return;
if (removeAll) {
// Short circuit the remove all case as this is the nice one
el.attribs['class'] = '';
}
else {
const elClasses = splitNames(el.attribs['class']);
let changed = false;
for (let j = 0; j < numClasses; j++) {
const index = elClasses.indexOf(classes[j]);
if (index >= 0) {
elClasses.splice(index, 1);
changed = true;
/*
* We have to do another pass to ensure that there are not duplicate
* classes listed
*/
j--;
}
}
if (changed) {
el.attribs['class'] = elClasses.join(' ');
}
}
});
}
/**
* Add or remove class(es) from the matched elements, depending on either the
* class's presence or the value of the switch argument. Also accepts a
* `function`.
*
* @category Attributes
* @example
*
* ```js
* $('.apple.green').toggleClass('fruit green red').html();
* //=> <li class="apple fruit red">Apple</li>
*
* $('.apple.green').toggleClass('fruit green red', true).html();
* //=> <li class="apple green fruit red">Apple</li>
* ```
*
* @param value - Name of the class. Can also be a function.
* @param stateVal - If specified the state of the class.
* @returns The instance itself.
* @see {@link https://api.jquery.com/toggleClass/}
*/
export function toggleClass(value, stateVal) {
// Support functions
if (typeof value === 'function') {
return domEach(this, (el, i) => {
if (isTag(el)) {
toggleClass.call([el], value.call(el, i, el.attribs['class'] || '', stateVal), stateVal);
}
});
}
// Return if no value or not a string or function
if (!value || typeof value !== 'string')
return this;
const classNames = value.split(rspace);
const numClasses = classNames.length;
const state = typeof stateVal === 'boolean' ? (stateVal ? 1 : -1) : 0;
const numElements = this.length;
for (let i = 0; i < numElements; i++) {
const el = this[i];
// If selected element isn't a tag, move on
if (!isTag(el))
continue;
const elementClasses = splitNames(el.attribs['class']);
// Check if class already exists
for (let j = 0; j < numClasses; j++) {
// Check if the class name is currently defined
const index = elementClasses.indexOf(classNames[j]);
// Add if stateValue === true or we are toggling and there is no value
if (state >= 0 && index < 0) {
elementClasses.push(classNames[j]);
}
else if (state <= 0 && index >= 0) {
// Otherwise remove but only if the item exists
elementClasses.splice(index, 1);
}
}
el.attribs['class'] = elementClasses.join(' ');
}
return this;
}
//# sourceMappingURL=attributes.js.map

File diff suppressed because one or more lines are too long

42
book/node_modules/cheerio/dist/browser/api/css.d.ts generated vendored Normal file
View File

@ -0,0 +1,42 @@
import { type Element, type AnyNode } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
/**
* Get the value of a style property for the first element in the set of matched
* elements.
*
* @category CSS
* @param names - Optionally the names of the properties of interest.
* @returns A map of all of the style properties.
* @see {@link https://api.jquery.com/css/}
*/
export declare function css<T extends AnyNode>(this: Cheerio<T>, names?: string[]): Record<string, string> | undefined;
/**
* Get the value of a style property for the first element in the set of matched
* elements.
*
* @category CSS
* @param name - The name of the property.
* @returns The property value for the given name.
* @see {@link https://api.jquery.com/css/}
*/
export declare function css<T extends AnyNode>(this: Cheerio<T>, name: string): string | undefined;
/**
* Set one CSS property for every matched element.
*
* @category CSS
* @param prop - The name of the property.
* @param val - The new value.
* @returns The instance itself.
* @see {@link https://api.jquery.com/css/}
*/
export declare function css<T extends AnyNode>(this: Cheerio<T>, prop: string, val: string | ((this: Element, i: number, style: string) => string | undefined)): Cheerio<T>;
/**
* Set multiple CSS properties for every matched element.
*
* @category CSS
* @param map - A map of property names and values.
* @returns The instance itself.
* @see {@link https://api.jquery.com/css/}
*/
export declare function css<T extends AnyNode>(this: Cheerio<T>, map: Record<string, string>): Cheerio<T>;
//# sourceMappingURL=css.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../../src/api/css.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,EACnC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;AACtC;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,EACnC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAAC;AACtB;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,EACnC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,IAAI,EAAE,MAAM,EACZ,GAAG,EACC,MAAM,GACN,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GACpE,OAAO,CAAC,CAAC,CAAC,CAAC;AACd;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,CAAC,SAAS,OAAO,EACnC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAAC"}

116
book/node_modules/cheerio/dist/browser/api/css.js generated vendored Normal file
View File

@ -0,0 +1,116 @@
import { domEach } from '../utils.js';
import { isTag } from 'domhandler';
/**
* Set multiple CSS properties for every matched element.
*
* @category CSS
* @param prop - The names of the properties.
* @param val - The new values.
* @returns The instance itself.
* @see {@link https://api.jquery.com/css/}
*/
export function css(prop, val) {
if ((prop != null && val != null) ||
// When `prop` is a "plain" object
(typeof prop === 'object' && !Array.isArray(prop))) {
return domEach(this, (el, i) => {
if (isTag(el)) {
// `prop` can't be an array here anymore.
setCss(el, prop, val, i);
}
});
}
if (this.length === 0) {
return undefined;
}
return getCss(this[0], prop);
}
/**
* Set styles of all elements.
*
* @private
* @param el - Element to set style of.
* @param prop - Name of property.
* @param value - Value to set property to.
* @param idx - Optional index within the selection.
*/
function setCss(el, prop, value, idx) {
if (typeof prop === 'string') {
const styles = getCss(el);
const val = typeof value === 'function' ? value.call(el, idx, styles[prop]) : value;
if (val === '') {
delete styles[prop];
}
else if (val != null) {
styles[prop] = val;
}
el.attribs['style'] = stringify(styles);
}
else if (typeof prop === 'object') {
const keys = Object.keys(prop);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
setCss(el, k, prop[k], i);
}
}
}
function getCss(el, prop) {
if (!el || !isTag(el))
return;
const styles = parse(el.attribs['style']);
if (typeof prop === 'string') {
return styles[prop];
}
if (Array.isArray(prop)) {
const newStyles = {};
for (const item of prop) {
if (styles[item] != null) {
newStyles[item] = styles[item];
}
}
return newStyles;
}
return styles;
}
/**
* Stringify `obj` to styles.
*
* @private
* @category CSS
* @param obj - Object to stringify.
* @returns The serialized styles.
*/
function stringify(obj) {
return Object.keys(obj).reduce((str, prop) => `${str}${str ? ' ' : ''}${prop}: ${obj[prop]};`, '');
}
/**
* Parse `styles`.
*
* @private
* @category CSS
* @param styles - Styles to be parsed.
* @returns The parsed styles.
*/
function parse(styles) {
styles = (styles || '').trim();
if (!styles)
return {};
const obj = {};
let key;
for (const str of styles.split(';')) {
const n = str.indexOf(':');
// If there is no :, or if it is the first/last character, add to the previous item's value
if (n < 1 || n === str.length - 1) {
const trimmed = str.trimEnd();
if (trimmed.length > 0 && key !== undefined) {
obj[key] += `;${trimmed}`;
}
}
else {
key = str.slice(0, n).trim();
obj[key] = str.slice(n + 1).trim();
}
}
return obj;
}
//# sourceMappingURL=css.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"css.js","sourceRoot":"","sources":["../../../src/api/css.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,29 @@
import type { AnyNode, Element } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
import type { prop } from './attributes.js';
type ExtractDescriptorFn = (el: Element, key: string, obj: Record<string, unknown>) => unknown;
interface ExtractDescriptor {
selector: string;
value?: string | ExtractDescriptorFn | ExtractMap;
}
type ExtractValue = string | ExtractDescriptor | [string | ExtractDescriptor];
export interface ExtractMap {
[key: string]: ExtractValue;
}
type ExtractedValue<V extends ExtractValue, M extends ExtractMap> = V extends [
string | ExtractDescriptor
] ? NonNullable<ExtractedValue<V[0], M>>[] : V extends string ? string | undefined : V extends ExtractDescriptor ? V['value'] extends ExtractMap ? ExtractedMap<V['value']> | undefined : V['value'] extends ExtractDescriptorFn ? ReturnType<V['value']> | undefined : ReturnType<typeof prop> | undefined : never;
export type ExtractedMap<M extends ExtractMap> = {
[key in keyof M]: ExtractedValue<M[key], M>;
};
/**
* Extract multiple values from a document, and store them in an object.
*
* @param map - An object containing key-value pairs. The keys are the names of
* the properties to be created on the object, and the values are the
* selectors to be used to extract the values.
* @returns An object containing the extracted values.
*/
export declare function extract<M extends ExtractMap, T extends AnyNode>(this: Cheerio<T>, map: M): ExtractedMap<M>;
export {};
//# sourceMappingURL=extract.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../../src/api/extract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,KAAK,mBAAmB,GAAG,CACzB,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,MAAM,EAEX,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACzB,OAAO,CAAC;AAEb,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG,UAAU,CAAC;CACnD;AAED,KAAK,YAAY,GAAG,MAAM,GAAG,iBAAiB,GAAG,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAC;AAE9E,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;CAC7B;AAED,KAAK,cAAc,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS;IAC5E,MAAM,GAAG,iBAAiB;CAC3B,GACG,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GACtC,CAAC,SAAS,MAAM,GACd,MAAM,GAAG,SAAS,GAClB,CAAC,SAAS,iBAAiB,GACzB,CAAC,CAAC,OAAO,CAAC,SAAS,UAAU,GAC3B,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,GACpC,CAAC,CAAC,OAAO,CAAC,SAAS,mBAAmB,GACpC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,GAClC,UAAU,CAAC,OAAO,IAAI,CAAC,GAAG,SAAS,GACvC,KAAK,CAAC;AAEd,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,UAAU,IAAI;KAC9C,GAAG,IAAI,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;CAC5C,CAAC;AAeF;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,OAAO,EAC7D,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,GAAG,EAAE,CAAC,GACL,YAAY,CAAC,CAAC,CAAC,CA2BjB"}

42
book/node_modules/cheerio/dist/browser/api/extract.js generated vendored Normal file
View File

@ -0,0 +1,42 @@
function getExtractDescr(descr) {
var _a;
if (typeof descr === 'string') {
return { selector: descr, value: 'textContent' };
}
return {
selector: descr.selector,
value: (_a = descr.value) !== null && _a !== void 0 ? _a : 'textContent',
};
}
/**
* Extract multiple values from a document, and store them in an object.
*
* @param map - An object containing key-value pairs. The keys are the names of
* the properties to be created on the object, and the values are the
* selectors to be used to extract the values.
* @returns An object containing the extracted values.
*/
export function extract(map) {
const ret = {};
for (const key in map) {
const descr = map[key];
const isArray = Array.isArray(descr);
const { selector, value } = getExtractDescr(isArray ? descr[0] : descr);
const fn = typeof value === 'function'
? value
: typeof value === 'string'
? (el) => this._make(el).prop(value)
: (el) => this._make(el).extract(value);
if (isArray) {
ret[key] = this._findBySelector(selector, Number.POSITIVE_INFINITY)
.map((_, el) => fn(el, key, ret))
.get();
}
else {
const $ = this._findBySelector(selector, 1);
ret[key] = $.length > 0 ? fn($[0], key, ret) : undefined;
}
}
return ret;
}
//# sourceMappingURL=extract.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../src/api/extract.ts"],"names":[],"mappings":"AAwCA,SAAS,eAAe,CACtB,KAAiC;;IAEjC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;IACnD,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,MAAA,KAAK,CAAC,KAAK,mCAAI,aAAa;KACpC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAErB,GAAM;IAEN,MAAM,GAAG,GAA4B,EAAE,CAAC;IAExC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAExE,MAAM,EAAE,GACN,OAAO,KAAK,KAAK,UAAU;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;gBACzB,CAAC,CAAC,CAAC,EAAW,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC7C,CAAC,CAAC,CAAC,EAAW,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEvD,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,iBAAiB,CAAC;iBAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;iBAChC,GAAG,EAAE,CAAC;QACX,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAC5C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,GAAsB,CAAC;AAChC,CAAC"}

36
book/node_modules/cheerio/dist/browser/api/forms.d.ts generated vendored Normal file
View File

@ -0,0 +1,36 @@
import { type AnyNode } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
/**
* Encode a set of form elements as a string for submission.
*
* @category Forms
* @example
*
* ```js
* $('<form><input name="foo" value="bar" /></form>').serialize();
* //=> 'foo=bar'
* ```
*
* @returns The serialized form.
* @see {@link https://api.jquery.com/serialize/}
*/
export declare function serialize<T extends AnyNode>(this: Cheerio<T>): string;
/**
* Encode a set of form elements as an array of names and values.
*
* @category Forms
* @example
*
* ```js
* $('<form><input name="foo" value="bar" /></form>').serializeArray();
* //=> [ { name: 'foo', value: 'bar' } ]
* ```
*
* @returns The serialized form.
* @see {@link https://api.jquery.com/serializeArray/}
*/
export declare function serializeArray<T extends AnyNode>(this: Cheerio<T>): {
name: string;
value: string;
}[];
//# sourceMappingURL=forms.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../../src/api/forms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAU7C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAYrE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAC9C,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,EAAE,CA4CF"}

81
book/node_modules/cheerio/dist/browser/api/forms.js generated vendored Normal file
View File

@ -0,0 +1,81 @@
import { isTag } from 'domhandler';
/*
* https://github.com/jquery/jquery/blob/2.1.3/src/manipulation/var/rcheckableType.js
* https://github.com/jquery/jquery/blob/2.1.3/src/serialize.js
*/
const submittableSelector = 'input,select,textarea,keygen';
const r20 = /%20/g;
const rCRLF = /\r?\n/g;
/**
* Encode a set of form elements as a string for submission.
*
* @category Forms
* @example
*
* ```js
* $('<form><input name="foo" value="bar" /></form>').serialize();
* //=> 'foo=bar'
* ```
*
* @returns The serialized form.
* @see {@link https://api.jquery.com/serialize/}
*/
export function serialize() {
// Convert form elements into name/value objects
const arr = this.serializeArray();
// Serialize each element into a key/value string
const retArr = arr.map((data) => `${encodeURIComponent(data.name)}=${encodeURIComponent(data.value)}`);
// Return the resulting serialization
return retArr.join('&').replace(r20, '+');
}
/**
* Encode a set of form elements as an array of names and values.
*
* @category Forms
* @example
*
* ```js
* $('<form><input name="foo" value="bar" /></form>').serializeArray();
* //=> [ { name: 'foo', value: 'bar' } ]
* ```
*
* @returns The serialized form.
* @see {@link https://api.jquery.com/serializeArray/}
*/
export function serializeArray() {
// Resolve all form elements from either forms or collections of form elements
return this.map((_, elem) => {
const $elem = this._make(elem);
if (isTag(elem) && elem.name === 'form') {
return $elem.find(submittableSelector).toArray();
}
return $elem.filter(submittableSelector).toArray();
})
.filter(
// Verify elements have a name (`attr.name`) and are not disabled (`:enabled`)
'[name!=""]:enabled' +
// And cannot be clicked (`[type=submit]`) or are used in `x-www-form-urlencoded` (`[type=file]`)
':not(:submit, :button, :image, :reset, :file)' +
// And are either checked/don't have a checkable state
':matches([checked], :not(:checkbox, :radio))')
.map((_, elem) => {
var _a;
const $elem = this._make(elem);
const name = $elem.attr('name'); // We have filtered for elements with a name before.
// If there is no value set (e.g. `undefined`, `null`), then default value to empty
const value = (_a = $elem.val()) !== null && _a !== void 0 ? _a : '';
// If we have an array of values (e.g. `<select multiple>`), return an array of key/value pairs
if (Array.isArray(value)) {
return value.map((val) =>
/*
* We trim replace any line endings (e.g. `\r` or `\r\n` with `\r\n`) to guarantee consistency across platforms
* These can occur inside of `<textarea>'s`
*/
({ name, value: val.replace(rCRLF, '\r\n') }));
}
// Otherwise (e.g. `<input type="text">`, return only one key/value pair
return { name, value: value.replace(rCRLF, '\r\n') };
})
.toArray();
}
//# sourceMappingURL=forms.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"forms.js","sourceRoot":"","sources":["../../../src/api/forms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AAGjD;;;GAGG;AACH,MAAM,mBAAmB,GAAG,8BAA8B,CAAC;AAC3D,MAAM,GAAG,GAAG,MAAM,CAAC;AACnB,MAAM,KAAK,GAAG,QAAQ,CAAC;AAEvB;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS;IACvB,gDAAgD;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IAElC,iDAAiD;IACjD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CACpB,CAAC,IAAI,EAAE,EAAE,CACP,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACvE,CAAC;IAEF,qCAAqC;IACrC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc;IAM5B,8EAA8E;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,OAAO,EAAE,CAAC;QACnD,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,OAAO,EAAE,CAAC;IACrD,CAAC,CAAC;SACC,MAAM;IACL,8EAA8E;IAC9E,oBAAoB;QAClB,iGAAiG;QACjG,+CAA+C;QAC/C,sDAAsD;QACtD,8CAA8C,CAEjD;SACA,GAAG,CAMF,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAW,CAAC,CAAC,oDAAoD;QAC/F,mFAAmF;QACnF,MAAM,KAAK,GAAG,MAAA,KAAK,CAAC,GAAG,EAAE,mCAAI,EAAE,CAAC;QAEhC,+FAA+F;QAC/F,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACvB;;;eAGG;YACH,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAC9C,CAAC;QACJ,CAAC;QACD,wEAAwE;QACxE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;IACvD,CAAC,CAAC;SACD,OAAO,EAAE,CAAC;AACf,CAAC"}

View File

@ -0,0 +1,528 @@
/**
* Methods for modifying the DOM structure.
*
* @module cheerio/manipulation
*/
import { type AnyNode } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
import type { BasicAcceptedElems, AcceptedElems } from '../types.js';
/**
* Create an array of nodes, recursing into arrays and parsing strings if
* necessary.
*
* @private
* @category Manipulation
* @param elem - Elements to make an array of.
* @param clone - Optionally clone nodes.
* @returns The array of nodes.
*/
export declare function _makeDomArray<T extends AnyNode>(this: Cheerio<T>, elem?: BasicAcceptedElems<AnyNode> | BasicAcceptedElems<AnyNode>[], clone?: boolean): AnyNode[];
/**
* Insert every element in the set of matched elements to the end of the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').appendTo('#fruits');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @param target - Element to append elements to.
* @returns The instance itself.
* @see {@link https://api.jquery.com/appendTo/}
*/
export declare function appendTo<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
/**
* Insert every element in the set of matched elements to the beginning of the
* target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').prependTo('#fruits');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to prepend elements to.
* @returns The instance itself.
* @see {@link https://api.jquery.com/prependTo/}
*/
export declare function prependTo<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
/**
* Inserts content as the _last_ child of each of the selected elements.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').append('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @see {@link https://api.jquery.com/append/}
*/
export declare const append: <T extends AnyNode>(this: Cheerio<T>, ...elems: [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>] | BasicAcceptedElems<AnyNode>[]) => Cheerio<T>;
/**
* Inserts content as the _first_ child of each of the selected elements.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').prepend('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @see {@link https://api.jquery.com/prepend/}
*/
export declare const prepend: <T extends AnyNode>(this: Cheerio<T>, ...elems: [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>] | BasicAcceptedElems<AnyNode>[]) => Cheerio<T>;
/**
* The .wrap() function can take any string or object that could be passed to
* the $() factory function to specify a DOM structure. This structure may be
* nested several levels deep, but should contain only one inmost element. A
* copy of this structure will be wrapped around each of the elements in the set
* of matched elements. This method returns the original set of elements for
* chaining purposes.
*
* @category Manipulation
* @example
*
* ```js
* const redFruit = $('<div class="red-fruit"></div>');
* $('.apple').wrap(redFruit);
*
* //=> <ul id="fruits">
* // <div class="red-fruit">
* // <li class="apple">Apple</li>
* // </div>
* // <li class="orange">Orange</li>
* // <li class="plum">Plum</li>
* // </ul>
*
* const healthy = $('<div class="healthy"></div>');
* $('li').wrap(healthy);
*
* //=> <ul id="fruits">
* // <div class="healthy">
* // <li class="apple">Apple</li>
* // </div>
* // <div class="healthy">
* // <li class="orange">Orange</li>
* // </div>
* // <div class="healthy">
* // <li class="plum">Plum</li>
* // </div>
* // </ul>
* ```
*
* @param wrapper - The DOM structure to wrap around each element in the
* selection.
* @see {@link https://api.jquery.com/wrap/}
*/
export declare const wrap: <T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<AnyNode>) => Cheerio<T>;
/**
* The .wrapInner() function can take any string or object that could be passed
* to the $() factory function to specify a DOM structure. This structure may be
* nested several levels deep, but should contain only one inmost element. The
* structure will be wrapped around the content of each of the elements in the
* set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* const redFruit = $('<div class="red-fruit"></div>');
* $('.apple').wrapInner(redFruit);
*
* //=> <ul id="fruits">
* // <li class="apple">
* // <div class="red-fruit">Apple</div>
* // </li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
*
* const healthy = $('<div class="healthy"></div>');
* $('li').wrapInner(healthy);
*
* //=> <ul id="fruits">
* // <li class="apple">
* // <div class="healthy">Apple</div>
* // </li>
* // <li class="orange">
* // <div class="healthy">Orange</div>
* // </li>
* // <li class="pear">
* // <div class="healthy">Pear</div>
* // </li>
* // </ul>
* ```
*
* @param wrapper - The DOM structure to wrap around the content of each element
* in the selection.
* @returns The instance itself, for chaining.
* @see {@link https://api.jquery.com/wrapInner/}
*/
export declare const wrapInner: <T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<AnyNode>) => Cheerio<T>;
/**
* The .unwrap() function, removes the parents of the set of matched elements
* from the DOM, leaving the matched elements in their place.
*
* @category Manipulation
* @example <caption>without selector</caption>
*
* ```js
* const $ = cheerio.load(
* '<div id=test>\n <div><p>Hello</p></div>\n <div><p>World</p></div>\n</div>',
* );
* $('#test p').unwrap();
*
* //=> <div id=test>
* // <p>Hello</p>
* // <p>World</p>
* // </div>
* ```
*
* @example <caption>with selector</caption>
*
* ```js
* const $ = cheerio.load(
* '<div id=test>\n <p>Hello</p>\n <b><p>World</p></b>\n</div>',
* );
* $('#test p').unwrap('b');
*
* //=> <div id=test>
* // <p>Hello</p>
* // <p>World</p>
* // </div>
* ```
*
* @param selector - A selector to check the parent element against. If an
* element's parent does not match the selector, the element won't be
* unwrapped.
* @returns The instance itself, for chaining.
* @see {@link https://api.jquery.com/unwrap/}
*/
export declare function unwrap<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<T>;
/**
* The .wrapAll() function can take any string or object that could be passed to
* the $() function to specify a DOM structure. This structure may be nested
* several levels deep, but should contain only one inmost element. The
* structure will be wrapped around all of the elements in the set of matched
* elements, as a single group.
*
* @category Manipulation
* @example <caption>With markup passed to `wrapAll`</caption>
*
* ```js
* const $ = cheerio.load(
* '<div class="container"><div class="inner">First</div><div class="inner">Second</div></div>',
* );
* $('.inner').wrapAll("<div class='new'></div>");
*
* //=> <div class="container">
* // <div class='new'>
* // <div class="inner">First</div>
* // <div class="inner">Second</div>
* // </div>
* // </div>
* ```
*
* @example <caption>With an existing cheerio instance</caption>
*
* ```js
* const $ = cheerio.load(
* '<span>Span 1</span><strong>Strong</strong><span>Span 2</span>',
* );
* const wrap = $('<div><p><em><b></b></em></p></div>');
* $('span').wrapAll(wrap);
*
* //=> <div>
* // <p>
* // <em>
* // <b>
* // <span>Span 1</span>
* // <span>Span 2</span>
* // </b>
* // </em>
* // </p>
* // </div>
* // <strong>Strong</strong>
* ```
*
* @param wrapper - The DOM structure to wrap around all matched elements in the
* selection.
* @returns The instance itself.
* @see {@link https://api.jquery.com/wrapAll/}
*/
export declare function wrapAll<T extends AnyNode>(this: Cheerio<T>, wrapper: AcceptedElems<T>): Cheerio<T>;
/**
* Insert content next to each element in the set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* $('.apple').after('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="plum">Plum</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
* insert after each element in the set of matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/after/}
*/
export declare function after<T extends AnyNode>(this: Cheerio<T>, ...elems: [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
/**
* Insert every element in the set of matched elements after the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').insertAfter('.apple');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="plum">Plum</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to insert elements after.
* @returns The set of newly inserted elements.
* @see {@link https://api.jquery.com/insertAfter/}
*/
export declare function insertAfter<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
/**
* Insert content previous to each element in the set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* $('.apple').before('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
* insert before each element in the set of matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/before/}
*/
export declare function before<T extends AnyNode>(this: Cheerio<T>, ...elems: [(this: AnyNode, i: number, html: string) => BasicAcceptedElems<AnyNode>] | BasicAcceptedElems<AnyNode>[]): Cheerio<T>;
/**
* Insert every element in the set of matched elements before the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').insertBefore('.apple');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to insert elements before.
* @returns The set of newly inserted elements.
* @see {@link https://api.jquery.com/insertBefore/}
*/
export declare function insertBefore<T extends AnyNode>(this: Cheerio<T>, target: BasicAcceptedElems<AnyNode>): Cheerio<T>;
/**
* Removes the set of matched elements from the DOM and all their children.
* `selector` filters the set of matched elements to be removed.
*
* @category Manipulation
* @example
*
* ```js
* $('.pear').remove();
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // </ul>
* ```
*
* @param selector - Optional selector for elements to remove.
* @returns The instance itself.
* @see {@link https://api.jquery.com/remove/}
*/
export declare function remove<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<T>;
/**
* Replaces matched elements with `content`.
*
* @category Manipulation
* @example
*
* ```js
* const plum = $('<li class="plum">Plum</li>');
* $('.pear').replaceWith(plum);
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @param content - Replacement for matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/replaceWith/}
*/
export declare function replaceWith<T extends AnyNode>(this: Cheerio<T>, content: AcceptedElems<AnyNode>): Cheerio<T>;
/**
* Removes all children from each item in the selection. Text nodes and comment
* nodes are left as is.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').empty();
* $.html();
* //=> <ul id="fruits"></ul>
* ```
*
* @returns The instance itself.
* @see {@link https://api.jquery.com/empty/}
*/
export declare function empty<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
/**
* Gets an HTML content string from the first selected element.
*
* @category Manipulation
* @example
*
* ```js
* $('.orange').html();
* //=> Orange
*
* $('#fruits').html('<li class="mango">Mango</li>').html();
* //=> <li class="mango">Mango</li>
* ```
*
* @returns The HTML content string.
* @see {@link https://api.jquery.com/html/}
*/
export declare function html<T extends AnyNode>(this: Cheerio<T>): string | null;
/**
* Replaces each selected element's content with the specified content.
*
* @category Manipulation
* @example
*
* ```js
* $('.orange').html('<li class="mango">Mango</li>').html();
* //=> <li class="mango">Mango</li>
* ```
*
* @param str - The content to replace selection's contents with.
* @returns The instance itself.
* @see {@link https://api.jquery.com/html/}
*/
export declare function html<T extends AnyNode>(this: Cheerio<T>, str: string | Cheerio<T>): Cheerio<T>;
/**
* Turns the collection to a string. Alias for `.html()`.
*
* @category Manipulation
* @returns The rendered document.
*/
export declare function toString<T extends AnyNode>(this: Cheerio<T>): string;
/**
* Get the combined text contents of each element in the set of matched
* elements, including their descendants.
*
* @category Manipulation
* @example
*
* ```js
* $('.orange').text();
* //=> Orange
*
* $('ul').text();
* //=> Apple
* // Orange
* // Pear
* ```
*
* @returns The text contents of the collection.
* @see {@link https://api.jquery.com/text/}
*/
export declare function text<T extends AnyNode>(this: Cheerio<T>): string;
/**
* Set the content of each element in the set of matched elements to the
* specified text.
*
* @category Manipulation
* @example
*
* ```js
* $('.orange').text('Orange');
* //=> <div class="orange">Orange</div>
* ```
*
* @param str - The text to set as the content of each matched element.
* @returns The instance itself.
* @see {@link https://api.jquery.com/text/}
*/
export declare function text<T extends AnyNode>(this: Cheerio<T>, str: string | ((this: AnyNode, i: number, text: string) => string)): Cheerio<T>;
/**
* Clone the cheerio object.
*
* @category Manipulation
* @example
*
* ```js
* const moreFruit = $('#fruits').clone();
* ```
*
* @returns The cloned object.
* @see {@link https://api.jquery.com/clone/}
*/
export declare function clone<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
//# sourceMappingURL=manipulation.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"manipulation.d.ts","sourceRoot":"","sources":["../../../src/api/manipulation.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,829 @@
/**
* Methods for modifying the DOM structure.
*
* @module cheerio/manipulation
*/
import { isTag, Text, hasChildren, cloneNode, Document, } from 'domhandler';
import { update as updateDOM } from '../parse.js';
import { text as staticText } from '../static.js';
import { domEach, isHtml, isCheerio } from '../utils.js';
import { removeElement } from 'domutils';
/**
* Create an array of nodes, recursing into arrays and parsing strings if
* necessary.
*
* @private
* @category Manipulation
* @param elem - Elements to make an array of.
* @param clone - Optionally clone nodes.
* @returns The array of nodes.
*/
export function _makeDomArray(elem, clone) {
if (elem == null) {
return [];
}
if (typeof elem === 'string') {
return this._parse(elem, this.options, false, null).children.slice(0);
}
if ('length' in elem) {
if (elem.length === 1) {
return this._makeDomArray(elem[0], clone);
}
const result = [];
for (let i = 0; i < elem.length; i++) {
const el = elem[i];
if (typeof el === 'object') {
if (el == null) {
continue;
}
if (!('length' in el)) {
result.push(clone ? cloneNode(el, true) : el);
continue;
}
}
result.push(...this._makeDomArray(el, clone));
}
return result;
}
return [clone ? cloneNode(elem, true) : elem];
}
function _insert(concatenator) {
return function (...elems) {
const lastIdx = this.length - 1;
return domEach(this, (el, i) => {
if (!hasChildren(el))
return;
const domSrc = typeof elems[0] === 'function'
? elems[0].call(el, i, this._render(el.children))
: elems;
const dom = this._makeDomArray(domSrc, i < lastIdx);
concatenator(dom, el.children, el);
});
};
}
/**
* Modify an array in-place, removing some number of elements and adding new
* elements directly following them.
*
* @private
* @category Manipulation
* @param array - Target array to splice.
* @param spliceIdx - Index at which to begin changing the array.
* @param spliceCount - Number of elements to remove from the array.
* @param newElems - Elements to insert into the array.
* @param parent - The parent of the node.
* @returns The spliced array.
*/
function uniqueSplice(array, spliceIdx, spliceCount, newElems, parent) {
var _a, _b;
const spliceArgs = [
spliceIdx,
spliceCount,
...newElems,
];
const prev = spliceIdx === 0 ? null : array[spliceIdx - 1];
const next = spliceIdx + spliceCount >= array.length
? null
: array[spliceIdx + spliceCount];
/*
* Before splicing in new elements, ensure they do not already appear in the
* current array.
*/
for (let idx = 0; idx < newElems.length; ++idx) {
const node = newElems[idx];
const oldParent = node.parent;
if (oldParent) {
const oldSiblings = oldParent.children;
const prevIdx = oldSiblings.indexOf(node);
if (prevIdx > -1) {
oldParent.children.splice(prevIdx, 1);
if (parent === oldParent && spliceIdx > prevIdx) {
spliceArgs[0]--;
}
}
}
node.parent = parent;
if (node.prev) {
node.prev.next = (_a = node.next) !== null && _a !== void 0 ? _a : null;
}
if (node.next) {
node.next.prev = (_b = node.prev) !== null && _b !== void 0 ? _b : null;
}
node.prev = idx === 0 ? prev : newElems[idx - 1];
node.next = idx === newElems.length - 1 ? next : newElems[idx + 1];
}
if (prev) {
prev.next = newElems[0];
}
if (next) {
next.prev = newElems[newElems.length - 1];
}
return array.splice(...spliceArgs);
}
/**
* Insert every element in the set of matched elements to the end of the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').appendTo('#fruits');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @param target - Element to append elements to.
* @returns The instance itself.
* @see {@link https://api.jquery.com/appendTo/}
*/
export function appendTo(target) {
const appendTarget = isCheerio(target) ? target : this._make(target);
appendTarget.append(this);
return this;
}
/**
* Insert every element in the set of matched elements to the beginning of the
* target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').prependTo('#fruits');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to prepend elements to.
* @returns The instance itself.
* @see {@link https://api.jquery.com/prependTo/}
*/
export function prependTo(target) {
const prependTarget = isCheerio(target) ? target : this._make(target);
prependTarget.prepend(this);
return this;
}
/**
* Inserts content as the _last_ child of each of the selected elements.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').append('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @see {@link https://api.jquery.com/append/}
*/
export const append = _insert((dom, children, parent) => {
uniqueSplice(children, children.length, 0, dom, parent);
});
/**
* Inserts content as the _first_ child of each of the selected elements.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').prepend('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @see {@link https://api.jquery.com/prepend/}
*/
export const prepend = _insert((dom, children, parent) => {
uniqueSplice(children, 0, 0, dom, parent);
});
function _wrap(insert) {
return function (wrapper) {
const lastIdx = this.length - 1;
const lastParent = this.parents().last();
for (let i = 0; i < this.length; i++) {
const el = this[i];
const wrap = typeof wrapper === 'function'
? wrapper.call(el, i, el)
: typeof wrapper === 'string' && !isHtml(wrapper)
? lastParent.find(wrapper).clone()
: wrapper;
const [wrapperDom] = this._makeDomArray(wrap, i < lastIdx);
if (!wrapperDom || !hasChildren(wrapperDom))
continue;
let elInsertLocation = wrapperDom;
/*
* Find the deepest child. Only consider the first tag child of each node
* (ignore text); stop if no children are found.
*/
let j = 0;
while (j < elInsertLocation.children.length) {
const child = elInsertLocation.children[j];
if (isTag(child)) {
elInsertLocation = child;
j = 0;
}
else {
j++;
}
}
insert(el, elInsertLocation, [wrapperDom]);
}
return this;
};
}
/**
* The .wrap() function can take any string or object that could be passed to
* the $() factory function to specify a DOM structure. This structure may be
* nested several levels deep, but should contain only one inmost element. A
* copy of this structure will be wrapped around each of the elements in the set
* of matched elements. This method returns the original set of elements for
* chaining purposes.
*
* @category Manipulation
* @example
*
* ```js
* const redFruit = $('<div class="red-fruit"></div>');
* $('.apple').wrap(redFruit);
*
* //=> <ul id="fruits">
* // <div class="red-fruit">
* // <li class="apple">Apple</li>
* // </div>
* // <li class="orange">Orange</li>
* // <li class="plum">Plum</li>
* // </ul>
*
* const healthy = $('<div class="healthy"></div>');
* $('li').wrap(healthy);
*
* //=> <ul id="fruits">
* // <div class="healthy">
* // <li class="apple">Apple</li>
* // </div>
* // <div class="healthy">
* // <li class="orange">Orange</li>
* // </div>
* // <div class="healthy">
* // <li class="plum">Plum</li>
* // </div>
* // </ul>
* ```
*
* @param wrapper - The DOM structure to wrap around each element in the
* selection.
* @see {@link https://api.jquery.com/wrap/}
*/
export const wrap = _wrap((el, elInsertLocation, wrapperDom) => {
const { parent } = el;
if (!parent)
return;
const siblings = parent.children;
const index = siblings.indexOf(el);
updateDOM([el], elInsertLocation);
/*
* The previous operation removed the current element from the `siblings`
* array, so the `dom` array can be inserted without removing any
* additional elements.
*/
uniqueSplice(siblings, index, 0, wrapperDom, parent);
});
/**
* The .wrapInner() function can take any string or object that could be passed
* to the $() factory function to specify a DOM structure. This structure may be
* nested several levels deep, but should contain only one inmost element. The
* structure will be wrapped around the content of each of the elements in the
* set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* const redFruit = $('<div class="red-fruit"></div>');
* $('.apple').wrapInner(redFruit);
*
* //=> <ul id="fruits">
* // <li class="apple">
* // <div class="red-fruit">Apple</div>
* // </li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
*
* const healthy = $('<div class="healthy"></div>');
* $('li').wrapInner(healthy);
*
* //=> <ul id="fruits">
* // <li class="apple">
* // <div class="healthy">Apple</div>
* // </li>
* // <li class="orange">
* // <div class="healthy">Orange</div>
* // </li>
* // <li class="pear">
* // <div class="healthy">Pear</div>
* // </li>
* // </ul>
* ```
*
* @param wrapper - The DOM structure to wrap around the content of each element
* in the selection.
* @returns The instance itself, for chaining.
* @see {@link https://api.jquery.com/wrapInner/}
*/
export const wrapInner = _wrap((el, elInsertLocation, wrapperDom) => {
if (!hasChildren(el))
return;
updateDOM(el.children, elInsertLocation);
updateDOM(wrapperDom, el);
});
/**
* The .unwrap() function, removes the parents of the set of matched elements
* from the DOM, leaving the matched elements in their place.
*
* @category Manipulation
* @example <caption>without selector</caption>
*
* ```js
* const $ = cheerio.load(
* '<div id=test>\n <div><p>Hello</p></div>\n <div><p>World</p></div>\n</div>',
* );
* $('#test p').unwrap();
*
* //=> <div id=test>
* // <p>Hello</p>
* // <p>World</p>
* // </div>
* ```
*
* @example <caption>with selector</caption>
*
* ```js
* const $ = cheerio.load(
* '<div id=test>\n <p>Hello</p>\n <b><p>World</p></b>\n</div>',
* );
* $('#test p').unwrap('b');
*
* //=> <div id=test>
* // <p>Hello</p>
* // <p>World</p>
* // </div>
* ```
*
* @param selector - A selector to check the parent element against. If an
* element's parent does not match the selector, the element won't be
* unwrapped.
* @returns The instance itself, for chaining.
* @see {@link https://api.jquery.com/unwrap/}
*/
export function unwrap(selector) {
this.parent(selector)
.not('body')
.each((_, el) => {
this._make(el).replaceWith(el.children);
});
return this;
}
/**
* The .wrapAll() function can take any string or object that could be passed to
* the $() function to specify a DOM structure. This structure may be nested
* several levels deep, but should contain only one inmost element. The
* structure will be wrapped around all of the elements in the set of matched
* elements, as a single group.
*
* @category Manipulation
* @example <caption>With markup passed to `wrapAll`</caption>
*
* ```js
* const $ = cheerio.load(
* '<div class="container"><div class="inner">First</div><div class="inner">Second</div></div>',
* );
* $('.inner').wrapAll("<div class='new'></div>");
*
* //=> <div class="container">
* // <div class='new'>
* // <div class="inner">First</div>
* // <div class="inner">Second</div>
* // </div>
* // </div>
* ```
*
* @example <caption>With an existing cheerio instance</caption>
*
* ```js
* const $ = cheerio.load(
* '<span>Span 1</span><strong>Strong</strong><span>Span 2</span>',
* );
* const wrap = $('<div><p><em><b></b></em></p></div>');
* $('span').wrapAll(wrap);
*
* //=> <div>
* // <p>
* // <em>
* // <b>
* // <span>Span 1</span>
* // <span>Span 2</span>
* // </b>
* // </em>
* // </p>
* // </div>
* // <strong>Strong</strong>
* ```
*
* @param wrapper - The DOM structure to wrap around all matched elements in the
* selection.
* @returns The instance itself.
* @see {@link https://api.jquery.com/wrapAll/}
*/
export function wrapAll(wrapper) {
const el = this[0];
if (el) {
const wrap = this._make(typeof wrapper === 'function' ? wrapper.call(el, 0, el) : wrapper).insertBefore(el);
// If html is given as wrapper, wrap may contain text elements
let elInsertLocation;
for (let i = 0; i < wrap.length; i++) {
if (wrap[i].type === 'tag')
elInsertLocation = wrap[i];
}
let j = 0;
/*
* Find the deepest child. Only consider the first tag child of each node
* (ignore text); stop if no children are found.
*/
while (elInsertLocation && j < elInsertLocation.children.length) {
const child = elInsertLocation.children[j];
if (child.type === 'tag') {
elInsertLocation = child;
j = 0;
}
else {
j++;
}
}
if (elInsertLocation)
this._make(elInsertLocation).append(this);
}
return this;
}
/**
* Insert content next to each element in the set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* $('.apple').after('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="plum">Plum</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
* insert after each element in the set of matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/after/}
*/
export function after(...elems) {
const lastIdx = this.length - 1;
return domEach(this, (el, i) => {
if (!hasChildren(el) || !el.parent) {
return;
}
const siblings = el.parent.children;
const index = siblings.indexOf(el);
// If not found, move on
/* istanbul ignore next */
if (index < 0)
return;
const domSrc = typeof elems[0] === 'function'
? elems[0].call(el, i, this._render(el.children))
: elems;
const dom = this._makeDomArray(domSrc, i < lastIdx);
// Add element after `this` element
uniqueSplice(siblings, index + 1, 0, dom, el.parent);
});
}
/**
* Insert every element in the set of matched elements after the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').insertAfter('.apple');
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="plum">Plum</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to insert elements after.
* @returns The set of newly inserted elements.
* @see {@link https://api.jquery.com/insertAfter/}
*/
export function insertAfter(target) {
if (typeof target === 'string') {
target = this._make(target);
}
this.remove();
const clones = [];
for (const el of this._makeDomArray(target)) {
const clonedSelf = this.clone().toArray();
const { parent } = el;
if (!parent) {
continue;
}
const siblings = parent.children;
const index = siblings.indexOf(el);
// If not found, move on
/* istanbul ignore next */
if (index < 0)
continue;
// Add cloned `this` element(s) after target element
uniqueSplice(siblings, index + 1, 0, clonedSelf, parent);
clones.push(...clonedSelf);
}
return this._make(clones);
}
/**
* Insert content previous to each element in the set of matched elements.
*
* @category Manipulation
* @example
*
* ```js
* $('.apple').before('<li class="plum">Plum</li>');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param elems - HTML string, DOM element, array of DOM elements or Cheerio to
* insert before each element in the set of matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/before/}
*/
export function before(...elems) {
const lastIdx = this.length - 1;
return domEach(this, (el, i) => {
if (!hasChildren(el) || !el.parent) {
return;
}
const siblings = el.parent.children;
const index = siblings.indexOf(el);
// If not found, move on
/* istanbul ignore next */
if (index < 0)
return;
const domSrc = typeof elems[0] === 'function'
? elems[0].call(el, i, this._render(el.children))
: elems;
const dom = this._makeDomArray(domSrc, i < lastIdx);
// Add element before `el` element
uniqueSplice(siblings, index, 0, dom, el.parent);
});
}
/**
* Insert every element in the set of matched elements before the target.
*
* @category Manipulation
* @example
*
* ```js
* $('<li class="plum">Plum</li>').insertBefore('.apple');
* $.html();
* //=> <ul id="fruits">
* // <li class="plum">Plum</li>
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="pear">Pear</li>
* // </ul>
* ```
*
* @param target - Element to insert elements before.
* @returns The set of newly inserted elements.
* @see {@link https://api.jquery.com/insertBefore/}
*/
export function insertBefore(target) {
const targetArr = this._make(target);
this.remove();
const clones = [];
domEach(targetArr, (el) => {
const clonedSelf = this.clone().toArray();
const { parent } = el;
if (!parent) {
return;
}
const siblings = parent.children;
const index = siblings.indexOf(el);
// If not found, move on
/* istanbul ignore next */
if (index < 0)
return;
// Add cloned `this` element(s) after target element
uniqueSplice(siblings, index, 0, clonedSelf, parent);
clones.push(...clonedSelf);
});
return this._make(clones);
}
/**
* Removes the set of matched elements from the DOM and all their children.
* `selector` filters the set of matched elements to be removed.
*
* @category Manipulation
* @example
*
* ```js
* $('.pear').remove();
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // </ul>
* ```
*
* @param selector - Optional selector for elements to remove.
* @returns The instance itself.
* @see {@link https://api.jquery.com/remove/}
*/
export function remove(selector) {
// Filter if we have selector
const elems = selector ? this.filter(selector) : this;
domEach(elems, (el) => {
removeElement(el);
el.prev = el.next = el.parent = null;
});
return this;
}
/**
* Replaces matched elements with `content`.
*
* @category Manipulation
* @example
*
* ```js
* const plum = $('<li class="plum">Plum</li>');
* $('.pear').replaceWith(plum);
* $.html();
* //=> <ul id="fruits">
* // <li class="apple">Apple</li>
* // <li class="orange">Orange</li>
* // <li class="plum">Plum</li>
* // </ul>
* ```
*
* @param content - Replacement for matched elements.
* @returns The instance itself.
* @see {@link https://api.jquery.com/replaceWith/}
*/
export function replaceWith(content) {
return domEach(this, (el, i) => {
const { parent } = el;
if (!parent) {
return;
}
const siblings = parent.children;
const cont = typeof content === 'function' ? content.call(el, i, el) : content;
const dom = this._makeDomArray(cont);
/*
* In the case that `dom` contains nodes that already exist in other
* structures, ensure those nodes are properly removed.
*/
updateDOM(dom, null);
const index = siblings.indexOf(el);
// Completely remove old element
uniqueSplice(siblings, index, 1, dom, parent);
if (!dom.includes(el)) {
el.parent = el.prev = el.next = null;
}
});
}
/**
* Removes all children from each item in the selection. Text nodes and comment
* nodes are left as is.
*
* @category Manipulation
* @example
*
* ```js
* $('ul').empty();
* $.html();
* //=> <ul id="fruits"></ul>
* ```
*
* @returns The instance itself.
* @see {@link https://api.jquery.com/empty/}
*/
export function empty() {
return domEach(this, (el) => {
if (!hasChildren(el))
return;
for (const child of el.children) {
child.next = child.prev = child.parent = null;
}
el.children.length = 0;
});
}
export function html(str) {
if (str === undefined) {
const el = this[0];
if (!el || !hasChildren(el))
return null;
return this._render(el.children);
}
return domEach(this, (el) => {
if (!hasChildren(el))
return;
for (const child of el.children) {
child.next = child.prev = child.parent = null;
}
const content = isCheerio(str)
? str.toArray()
: this._parse(`${str}`, this.options, false, el).children;
updateDOM(content, el);
});
}
/**
* Turns the collection to a string. Alias for `.html()`.
*
* @category Manipulation
* @returns The rendered document.
*/
export function toString() {
return this._render(this);
}
export function text(str) {
// If `str` is undefined, act as a "getter"
if (str === undefined) {
return staticText(this);
}
if (typeof str === 'function') {
// Function support
return domEach(this, (el, i) => this._make(el).text(str.call(el, i, staticText([el]))));
}
// Append text node to each selected elements
return domEach(this, (el) => {
if (!hasChildren(el))
return;
for (const child of el.children) {
child.next = child.prev = child.parent = null;
}
const textNode = new Text(`${str}`);
updateDOM(textNode, el);
});
}
/**
* Clone the cheerio object.
*
* @category Manipulation
* @example
*
* ```js
* const moreFruit = $('#fruits').clone();
* ```
*
* @returns The cloned object.
* @see {@link https://api.jquery.com/clone/}
*/
export function clone() {
const clone = Array.prototype.map.call(this.get(), (el) => cloneNode(el, true));
// Add a root node around the cloned nodes
const root = new Document(clone);
for (const node of clone) {
node.parent = root;
}
return this._make(clone);
}
//# sourceMappingURL=manipulation.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,657 @@
/**
* Methods for traversing the DOM structure.
*
* @module cheerio/traversing
*/
import { type AnyNode, type Element, type Document } from 'domhandler';
import type { Cheerio } from '../cheerio.js';
import type { AcceptedFilters } from '../types.js';
/**
* Get the descendants of each element in the current set of matched elements,
* filtered by a selector, jQuery object, or element.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').find('li').length;
* //=> 3
* $('#fruits').find($('.apple')).length;
* //=> 1
* ```
*
* @param selectorOrHaystack - Element to look for.
* @returns The found elements.
* @see {@link https://api.jquery.com/find/}
*/
export declare function find<T extends AnyNode>(this: Cheerio<T>, selectorOrHaystack?: string | Cheerio<Element> | Element): Cheerio<Element>;
/**
* Find elements by a specific selector.
*
* @private
* @category Traversing
* @param selector - Selector to filter by.
* @param limit - Maximum number of elements to match.
* @returns The found elements.
*/
export declare function _findBySelector<T extends AnyNode>(this: Cheerio<T>, selector: string, limit: number): Cheerio<Element>;
/**
* Get the parent of each element in the current set of matched elements,
* optionally filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').parent().attr('id');
* //=> fruits
* ```
*
* @param selector - If specified filter for parent.
* @returns The parents.
* @see {@link https://api.jquery.com/parent/}
*/
export declare const parent: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Get a set of parents filtered by `selector` of each element in the current
* set of match elements.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').parents().length;
* //=> 2
* $('.orange').parents('#fruits').length;
* //=> 1
* ```
*
* @param selector - If specified filter for parents.
* @returns The parents.
* @see {@link https://api.jquery.com/parents/}
*/
export declare const parents: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Get the ancestors of each element in the current set of matched elements, up
* to but not including the element matched by the selector, DOM node, or
* cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').parentsUntil('#food').length;
* //=> 1
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - Optional filter for parents.
* @returns The parents.
* @see {@link https://api.jquery.com/parentsUntil/}
*/
export declare const parentsUntil: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* For each element in the set, get the first element that matches the selector
* by testing the element itself and traversing up through its ancestors in the
* DOM tree.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').closest();
* //=> []
*
* $('.orange').closest('.apple');
* // => []
*
* $('.orange').closest('li');
* //=> [<li class="orange">Orange</li>]
*
* $('.orange').closest('#fruits');
* //=> [<ul id="fruits"> ... </ul>]
* ```
*
* @param selector - Selector for the element to find.
* @returns The closest nodes.
* @see {@link https://api.jquery.com/closest/}
*/
export declare function closest<T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>): Cheerio<AnyNode>;
/**
* Gets the next sibling of each selected element, optionally filtered by a
* selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').next().hasClass('orange');
* //=> true
* ```
*
* @param selector - If specified filter for sibling.
* @returns The next nodes.
* @see {@link https://api.jquery.com/next/}
*/
export declare const next: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets all the following siblings of the each selected element, optionally
* filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').nextAll();
* //=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>]
* $('.apple').nextAll('.orange');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - If specified filter for siblings.
* @returns The next nodes.
* @see {@link https://api.jquery.com/nextAll/}
*/
export declare const nextAll: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets all the following siblings up to but not including the element matched
* by the selector, optionally filtered by another selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').nextUntil('.pear');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - If specified filter for siblings.
* @returns The next nodes.
* @see {@link https://api.jquery.com/nextUntil/}
*/
export declare const nextUntil: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets the previous sibling of each selected element optionally filtered by a
* selector.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').prev().hasClass('apple');
* //=> true
* ```
*
* @param selector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prev/}
*/
export declare const prev: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets all the preceding siblings of each selected element, optionally filtered
* by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').prevAll();
* //=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>]
*
* $('.pear').prevAll('.orange');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prevAll/}
*/
export declare const prevAll: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets all the preceding siblings up to but not including the element matched
* by the selector, optionally filtered by another selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').prevUntil('.apple');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prevUntil/}
*/
export declare const prevUntil: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element> | null, filterSelector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Get the siblings of each element (excluding the element) in the set of
* matched elements, optionally filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').siblings().length;
* //=> 2
*
* $('.pear').siblings('.orange').length;
* //=> 1
* ```
*
* @param selector - If specified filter for siblings.
* @returns The siblings.
* @see {@link https://api.jquery.com/siblings/}
*/
export declare const siblings: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets the element children of each element in the set of matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().length;
* //=> 3
*
* $('#fruits').children('.pear').text();
* //=> Pear
* ```
*
* @param selector - If specified filter for children.
* @returns The children.
* @see {@link https://api.jquery.com/children/}
*/
export declare const children: <T extends AnyNode>(this: Cheerio<T>, selector?: AcceptedFilters<Element>) => Cheerio<Element>;
/**
* Gets the children of each element in the set of matched elements, including
* text and comment nodes.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').contents().length;
* //=> 3
* ```
*
* @returns The children.
* @see {@link https://api.jquery.com/contents/}
*/
export declare function contents<T extends AnyNode>(this: Cheerio<T>): Cheerio<AnyNode>;
/**
* Iterates over a cheerio object, executing a function for each matched
* element. When the callback is fired, the function is fired in the context of
* the DOM element, so `this` refers to the current element, which is equivalent
* to the function parameter `element`. To break out of the `each` loop early,
* return with `false`.
*
* @category Traversing
* @example
*
* ```js
* const fruits = [];
*
* $('li').each(function (i, elem) {
* fruits[i] = $(this).text();
* });
*
* fruits.join(', ');
* //=> Apple, Orange, Pear
* ```
*
* @param fn - Function to execute.
* @returns The instance itself, useful for chaining.
* @see {@link https://api.jquery.com/each/}
*/
export declare function each<T>(this: Cheerio<T>, fn: (this: T, i: number, el: T) => void | boolean): Cheerio<T>;
/**
* Pass each element in the current matched set through a function, producing a
* new Cheerio object containing the return values. The function can return an
* individual data item or an array of data items to be inserted into the
* resulting set. If an array is returned, the elements inside the array are
* inserted into the set. If the function returns null or undefined, no element
* will be inserted.
*
* @category Traversing
* @example
*
* ```js
* $('li')
* .map(function (i, el) {
* // this === el
* return $(this).text();
* })
* .toArray()
* .join(' ');
* //=> "apple orange pear"
* ```
*
* @param fn - Function to execute.
* @returns The mapped elements, wrapped in a Cheerio collection.
* @see {@link https://api.jquery.com/map/}
*/
export declare function map<T, M>(this: Cheerio<T>, fn: (this: T, i: number, el: T) => M[] | M | null | undefined): Cheerio<M>;
/**
* Iterates over a cheerio object, reducing the set of selector elements to
* those that match the selector or pass the function's test.
*
* This is the definition for using type guards; have a look below for other
* ways to invoke this method. The function is executed in the context of the
* selected element, so `this` refers to the current element.
*
* @category Traversing
* @example <caption>Function</caption>
*
* ```js
* $('li')
* .filter(function (i, el) {
* // this === el
* return $(this).attr('class') === 'orange';
* })
* .attr('class'); //=> orange
* ```
*
* @param match - Value to look for, following the rules above.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/filter/}
*/
export declare function filter<T, S extends T>(this: Cheerio<T>, match: (this: T, index: number, value: T) => value is S): Cheerio<S>;
/**
* Iterates over a cheerio object, reducing the set of selector elements to
* those that match the selector or pass the function's test.
*
* - When a Cheerio selection is specified, return only the elements contained in
* that selection.
* - When an element is specified, return only that element (if it is contained in
* the original selection).
* - If using the function method, the function is executed in the context of the
* selected element, so `this` refers to the current element.
*
* @category Traversing
* @example <caption>Selector</caption>
*
* ```js
* $('li').filter('.orange').attr('class');
* //=> orange
* ```
*
* @example <caption>Function</caption>
*
* ```js
* $('li')
* .filter(function (i, el) {
* // this === el
* return $(this).attr('class') === 'orange';
* })
* .attr('class'); //=> orange
* ```
*
* @param match - Value to look for, following the rules above. See
* {@link AcceptedFilters}.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/filter/}
*/
export declare function filter<T, S extends AcceptedFilters<T>>(this: Cheerio<T>, match: S): Cheerio<S extends string ? Element : T>;
export declare function filterArray<T>(nodes: T[], match: AcceptedFilters<T>, xmlMode?: boolean, root?: Document): Element[] | T[];
/**
* Checks the current list of elements and returns `true` if _any_ of the
* elements match the selector. If using an element or Cheerio selection,
* returns `true` if _any_ of the elements match. If using a predicate function,
* the function is executed in the context of the selected element, so `this`
* refers to the current element.
*
* @category Traversing
* @param selector - Selector for the selection.
* @returns Whether or not the selector matches an element of the instance.
* @see {@link https://api.jquery.com/is/}
*/
export declare function is<T>(this: Cheerio<T>, selector?: AcceptedFilters<T>): boolean;
/**
* Remove elements from the set of matched elements. Given a Cheerio object that
* represents a set of DOM elements, the `.not()` method constructs a new
* Cheerio object from a subset of the matching elements. The supplied selector
* is tested against each element; the elements that don't match the selector
* will be included in the result.
*
* The `.not()` method can take a function as its argument in the same way that
* `.filter()` does. Elements for which the function returns `true` are excluded
* from the filtered set; all other elements are included.
*
* @category Traversing
* @example <caption>Selector</caption>
*
* ```js
* $('li').not('.apple').length;
* //=> 2
* ```
*
* @example <caption>Function</caption>
*
* ```js
* $('li').not(function (i, el) {
* // this === el
* return $(this).attr('class') === 'orange';
* }).length; //=> 2
* ```
*
* @param match - Value to look for, following the rules above.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/not/}
*/
export declare function not<T extends AnyNode>(this: Cheerio<T>, match: AcceptedFilters<T>): Cheerio<T>;
/**
* Filters the set of matched elements to only those which have the given DOM
* element as a descendant or which have a descendant that matches the given
* selector. Equivalent to `.filter(':has(selector)')`.
*
* @category Traversing
* @example <caption>Selector</caption>
*
* ```js
* $('ul').has('.pear').attr('id');
* //=> fruits
* ```
*
* @example <caption>Element</caption>
*
* ```js
* $('ul').has($('.pear')[0]).attr('id');
* //=> fruits
* ```
*
* @param selectorOrHaystack - Element to look for.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/has/}
*/
export declare function has(this: Cheerio<AnyNode | Element>, selectorOrHaystack: string | Cheerio<Element> | Element): Cheerio<AnyNode | Element>;
/**
* Will select the first element of a cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().first().text();
* //=> Apple
* ```
*
* @returns The first element.
* @see {@link https://api.jquery.com/first/}
*/
export declare function first<T extends AnyNode>(this: Cheerio<T>): Cheerio<T>;
/**
* Will select the last element of a cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().last().text();
* //=> Pear
* ```
*
* @returns The last element.
* @see {@link https://api.jquery.com/last/}
*/
export declare function last<T>(this: Cheerio<T>): Cheerio<T>;
/**
* Reduce the set of matched elements to the one at the specified index. Use
* `.eq(-i)` to count backwards from the last selected element.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).text();
* //=> Apple
*
* $('li').eq(-1).text();
* //=> Pear
* ```
*
* @param i - Index of the element to select.
* @returns The element at the `i`th position.
* @see {@link https://api.jquery.com/eq/}
*/
export declare function eq<T>(this: Cheerio<T>, i: number): Cheerio<T>;
/**
* Retrieve one of the elements matched by the Cheerio object, at the `i`th
* position.
*
* @category Traversing
* @example
*
* ```js
* $('li').get(0).tagName;
* //=> li
* ```
*
* @param i - Element to retrieve.
* @returns The element at the `i`th position.
* @see {@link https://api.jquery.com/get/}
*/
export declare function get<T>(this: Cheerio<T>, i: number): T | undefined;
/**
* Retrieve all elements matched by the Cheerio object, as an array.
*
* @category Traversing
* @example
*
* ```js
* $('li').get().length;
* //=> 3
* ```
*
* @returns All elements matched by the Cheerio object.
* @see {@link https://api.jquery.com/get/}
*/
export declare function get<T>(this: Cheerio<T>): T[];
/**
* Retrieve all the DOM elements contained in the jQuery set as an array.
*
* @example
*
* ```js
* $('li').toArray();
* //=> [ {...}, {...}, {...} ]
* ```
*
* @returns The contained items.
*/
export declare function toArray<T>(this: Cheerio<T>): T[];
/**
* Search for a given element from among the matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').index();
* //=> 2 $('.orange').index('li');
* //=> 1
* $('.apple').index($('#fruit, li'));
* //=> 1
* ```
*
* @param selectorOrNeedle - Element to look for.
* @returns The index of the element.
* @see {@link https://api.jquery.com/index/}
*/
export declare function index<T extends AnyNode>(this: Cheerio<T>, selectorOrNeedle?: string | Cheerio<AnyNode> | AnyNode): number;
/**
* Gets the elements matching the specified range (0-based position).
*
* @category Traversing
* @example
*
* ```js
* $('li').slice(1).eq(0).text();
* //=> 'Orange'
*
* $('li').slice(1, 2).length;
* //=> 1
* ```
*
* @param start - A position at which the elements begin to be selected. If
* negative, it indicates an offset from the end of the set.
* @param end - A position at which the elements stop being selected. If
* negative, it indicates an offset from the end of the set. If omitted, the
* range continues until the end of the set.
* @returns The elements matching the specified range.
* @see {@link https://api.jquery.com/slice/}
*/
export declare function slice<T>(this: Cheerio<T>, start?: number, end?: number): Cheerio<T>;
/**
* End the most recent filtering operation in the current chain and return the
* set of matched elements to its previous state.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).end().length;
* //=> 3
* ```
*
* @returns The previous state of the set of matched elements.
* @see {@link https://api.jquery.com/end/}
*/
export declare function end<T>(this: Cheerio<T>): Cheerio<AnyNode>;
/**
* Add elements to the set of matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').add('.orange').length;
* //=> 2
* ```
*
* @param other - Elements to add.
* @param context - Optionally the context of the new selection.
* @returns The combined set.
* @see {@link https://api.jquery.com/add/}
*/
export declare function add<S extends AnyNode, T extends AnyNode>(this: Cheerio<T>, other: string | Cheerio<S> | S | S[], context?: Cheerio<S> | string): Cheerio<S | T>;
/**
* Add the previous set of elements on the stack to the current set, optionally
* filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).addBack('.orange').length;
* //=> 2
* ```
*
* @param selector - Selector for the elements to add.
* @returns The combined set.
* @see {@link https://api.jquery.com/addBack/}
*/
export declare function addBack<T extends AnyNode>(this: Cheerio<T>, selector?: string): Cheerio<AnyNode>;
//# sourceMappingURL=traversing.d.ts.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,853 @@
/**
* Methods for traversing the DOM structure.
*
* @module cheerio/traversing
*/
import { isTag, hasChildren, isDocument, } from 'domhandler';
import * as select from 'cheerio-select';
import { domEach, isCheerio } from '../utils.js';
import { contains } from '../static.js';
import { getChildren, getSiblings, nextElementSibling, prevElementSibling, uniqueSort, } from 'domutils';
const reSiblingSelector = /^\s*[+~]/;
/**
* Get the descendants of each element in the current set of matched elements,
* filtered by a selector, jQuery object, or element.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').find('li').length;
* //=> 3
* $('#fruits').find($('.apple')).length;
* //=> 1
* ```
*
* @param selectorOrHaystack - Element to look for.
* @returns The found elements.
* @see {@link https://api.jquery.com/find/}
*/
export function find(selectorOrHaystack) {
if (!selectorOrHaystack) {
return this._make([]);
}
if (typeof selectorOrHaystack !== 'string') {
const haystack = isCheerio(selectorOrHaystack)
? selectorOrHaystack.toArray()
: [selectorOrHaystack];
const context = this.toArray();
return this._make(haystack.filter((elem) => context.some((node) => contains(node, elem))));
}
return this._findBySelector(selectorOrHaystack, Number.POSITIVE_INFINITY);
}
/**
* Find elements by a specific selector.
*
* @private
* @category Traversing
* @param selector - Selector to filter by.
* @param limit - Maximum number of elements to match.
* @returns The found elements.
*/
export function _findBySelector(selector, limit) {
var _a;
const context = this.toArray();
const elems = reSiblingSelector.test(selector)
? context
: this.children().toArray();
const options = {
context,
root: (_a = this._root) === null || _a === void 0 ? void 0 : _a[0],
// Pass options that are recognized by `cheerio-select`
xmlMode: this.options.xmlMode,
lowerCaseTags: this.options.lowerCaseTags,
lowerCaseAttributeNames: this.options.lowerCaseAttributeNames,
pseudos: this.options.pseudos,
quirksMode: this.options.quirksMode,
};
return this._make(select.select(selector, elems, options, limit));
}
/**
* Creates a matcher, using a particular mapping function. Matchers provide a
* function that finds elements using a generating function, supporting
* filtering.
*
* @private
* @param matchMap - Mapping function.
* @returns - Function for wrapping generating functions.
*/
function _getMatcher(matchMap) {
return function (fn, ...postFns) {
return function (selector) {
var _a;
let matched = matchMap(fn, this);
if (selector) {
matched = filterArray(matched, selector, this.options.xmlMode, (_a = this._root) === null || _a === void 0 ? void 0 : _a[0]);
}
return this._make(
// Post processing is only necessary if there is more than one element.
this.length > 1 && matched.length > 1
? postFns.reduce((elems, fn) => fn(elems), matched)
: matched);
};
};
}
/** Matcher that adds multiple elements for each entry in the input. */
const _matcher = _getMatcher((fn, elems) => {
let ret = [];
for (let i = 0; i < elems.length; i++) {
const value = fn(elems[i]);
if (value.length > 0)
ret = ret.concat(value);
}
return ret;
});
/** Matcher that adds at most one element for each entry in the input. */
const _singleMatcher = _getMatcher((fn, elems) => {
const ret = [];
for (let i = 0; i < elems.length; i++) {
const value = fn(elems[i]);
if (value !== null) {
ret.push(value);
}
}
return ret;
});
/**
* Matcher that supports traversing until a condition is met.
*
* @param nextElem - Function that returns the next element.
* @param postFns - Post processing functions.
* @returns A function usable for `*Until` methods.
*/
function _matchUntil(nextElem, ...postFns) {
// We use a variable here that is used from within the matcher.
let matches = null;
const innerMatcher = _getMatcher((nextElem, elems) => {
const matched = [];
domEach(elems, (elem) => {
for (let next; (next = nextElem(elem)); elem = next) {
// FIXME: `matched` might contain duplicates here and the index is too large.
if (matches === null || matches === void 0 ? void 0 : matches(next, matched.length))
break;
matched.push(next);
}
});
return matched;
})(nextElem, ...postFns);
return function (selector, filterSelector) {
// Override `matches` variable with the new target.
matches =
typeof selector === 'string'
? (elem) => select.is(elem, selector, this.options)
: selector
? getFilterFn(selector)
: null;
const ret = innerMatcher.call(this, filterSelector);
// Set `matches` to `null`, so we don't waste memory.
matches = null;
return ret;
};
}
function _removeDuplicates(elems) {
return elems.length > 1 ? Array.from(new Set(elems)) : elems;
}
/**
* Get the parent of each element in the current set of matched elements,
* optionally filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').parent().attr('id');
* //=> fruits
* ```
*
* @param selector - If specified filter for parent.
* @returns The parents.
* @see {@link https://api.jquery.com/parent/}
*/
export const parent = _singleMatcher(({ parent }) => (parent && !isDocument(parent) ? parent : null), _removeDuplicates);
/**
* Get a set of parents filtered by `selector` of each element in the current
* set of match elements.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').parents().length;
* //=> 2
* $('.orange').parents('#fruits').length;
* //=> 1
* ```
*
* @param selector - If specified filter for parents.
* @returns The parents.
* @see {@link https://api.jquery.com/parents/}
*/
export const parents = _matcher((elem) => {
const matched = [];
while (elem.parent && !isDocument(elem.parent)) {
matched.push(elem.parent);
elem = elem.parent;
}
return matched;
}, uniqueSort, (elems) => elems.reverse());
/**
* Get the ancestors of each element in the current set of matched elements, up
* to but not including the element matched by the selector, DOM node, or
* cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').parentsUntil('#food').length;
* //=> 1
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - Optional filter for parents.
* @returns The parents.
* @see {@link https://api.jquery.com/parentsUntil/}
*/
export const parentsUntil = _matchUntil(({ parent }) => (parent && !isDocument(parent) ? parent : null), uniqueSort, (elems) => elems.reverse());
/**
* For each element in the set, get the first element that matches the selector
* by testing the element itself and traversing up through its ancestors in the
* DOM tree.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').closest();
* //=> []
*
* $('.orange').closest('.apple');
* // => []
*
* $('.orange').closest('li');
* //=> [<li class="orange">Orange</li>]
*
* $('.orange').closest('#fruits');
* //=> [<ul id="fruits"> ... </ul>]
* ```
*
* @param selector - Selector for the element to find.
* @returns The closest nodes.
* @see {@link https://api.jquery.com/closest/}
*/
export function closest(selector) {
var _a;
const set = [];
if (!selector) {
return this._make(set);
}
const selectOpts = {
xmlMode: this.options.xmlMode,
root: (_a = this._root) === null || _a === void 0 ? void 0 : _a[0],
};
const selectFn = typeof selector === 'string'
? (elem) => select.is(elem, selector, selectOpts)
: getFilterFn(selector);
domEach(this, (elem) => {
if (elem && !isDocument(elem) && !isTag(elem)) {
elem = elem.parent;
}
while (elem && isTag(elem)) {
if (selectFn(elem, 0)) {
// Do not add duplicate elements to the set
if (!set.includes(elem)) {
set.push(elem);
}
break;
}
elem = elem.parent;
}
});
return this._make(set);
}
/**
* Gets the next sibling of each selected element, optionally filtered by a
* selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').next().hasClass('orange');
* //=> true
* ```
*
* @param selector - If specified filter for sibling.
* @returns The next nodes.
* @see {@link https://api.jquery.com/next/}
*/
export const next = _singleMatcher((elem) => nextElementSibling(elem));
/**
* Gets all the following siblings of the each selected element, optionally
* filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').nextAll();
* //=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>]
* $('.apple').nextAll('.orange');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - If specified filter for siblings.
* @returns The next nodes.
* @see {@link https://api.jquery.com/nextAll/}
*/
export const nextAll = _matcher((elem) => {
const matched = [];
while (elem.next) {
elem = elem.next;
if (isTag(elem))
matched.push(elem);
}
return matched;
}, _removeDuplicates);
/**
* Gets all the following siblings up to but not including the element matched
* by the selector, optionally filtered by another selector.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').nextUntil('.pear');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - If specified filter for siblings.
* @returns The next nodes.
* @see {@link https://api.jquery.com/nextUntil/}
*/
export const nextUntil = _matchUntil((el) => nextElementSibling(el), _removeDuplicates);
/**
* Gets the previous sibling of each selected element optionally filtered by a
* selector.
*
* @category Traversing
* @example
*
* ```js
* $('.orange').prev().hasClass('apple');
* //=> true
* ```
*
* @param selector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prev/}
*/
export const prev = _singleMatcher((elem) => prevElementSibling(elem));
/**
* Gets all the preceding siblings of each selected element, optionally filtered
* by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').prevAll();
* //=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>]
*
* $('.pear').prevAll('.orange');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prevAll/}
*/
export const prevAll = _matcher((elem) => {
const matched = [];
while (elem.prev) {
elem = elem.prev;
if (isTag(elem))
matched.push(elem);
}
return matched;
}, _removeDuplicates);
/**
* Gets all the preceding siblings up to but not including the element matched
* by the selector, optionally filtered by another selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').prevUntil('.apple');
* //=> [<li class="orange">Orange</li>]
* ```
*
* @param selector - Selector for element to stop at.
* @param filterSelector - If specified filter for siblings.
* @returns The previous nodes.
* @see {@link https://api.jquery.com/prevUntil/}
*/
export const prevUntil = _matchUntil((el) => prevElementSibling(el), _removeDuplicates);
/**
* Get the siblings of each element (excluding the element) in the set of
* matched elements, optionally filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').siblings().length;
* //=> 2
*
* $('.pear').siblings('.orange').length;
* //=> 1
* ```
*
* @param selector - If specified filter for siblings.
* @returns The siblings.
* @see {@link https://api.jquery.com/siblings/}
*/
export const siblings = _matcher((elem) => getSiblings(elem).filter((el) => isTag(el) && el !== elem), uniqueSort);
/**
* Gets the element children of each element in the set of matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().length;
* //=> 3
*
* $('#fruits').children('.pear').text();
* //=> Pear
* ```
*
* @param selector - If specified filter for children.
* @returns The children.
* @see {@link https://api.jquery.com/children/}
*/
export const children = _matcher((elem) => getChildren(elem).filter(isTag), _removeDuplicates);
/**
* Gets the children of each element in the set of matched elements, including
* text and comment nodes.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').contents().length;
* //=> 3
* ```
*
* @returns The children.
* @see {@link https://api.jquery.com/contents/}
*/
export function contents() {
const elems = this.toArray().reduce((newElems, elem) => hasChildren(elem) ? newElems.concat(elem.children) : newElems, []);
return this._make(elems);
}
/**
* Iterates over a cheerio object, executing a function for each matched
* element. When the callback is fired, the function is fired in the context of
* the DOM element, so `this` refers to the current element, which is equivalent
* to the function parameter `element`. To break out of the `each` loop early,
* return with `false`.
*
* @category Traversing
* @example
*
* ```js
* const fruits = [];
*
* $('li').each(function (i, elem) {
* fruits[i] = $(this).text();
* });
*
* fruits.join(', ');
* //=> Apple, Orange, Pear
* ```
*
* @param fn - Function to execute.
* @returns The instance itself, useful for chaining.
* @see {@link https://api.jquery.com/each/}
*/
export function each(fn) {
let i = 0;
const len = this.length;
while (i < len && fn.call(this[i], i, this[i]) !== false)
++i;
return this;
}
/**
* Pass each element in the current matched set through a function, producing a
* new Cheerio object containing the return values. The function can return an
* individual data item or an array of data items to be inserted into the
* resulting set. If an array is returned, the elements inside the array are
* inserted into the set. If the function returns null or undefined, no element
* will be inserted.
*
* @category Traversing
* @example
*
* ```js
* $('li')
* .map(function (i, el) {
* // this === el
* return $(this).text();
* })
* .toArray()
* .join(' ');
* //=> "apple orange pear"
* ```
*
* @param fn - Function to execute.
* @returns The mapped elements, wrapped in a Cheerio collection.
* @see {@link https://api.jquery.com/map/}
*/
export function map(fn) {
let elems = [];
for (let i = 0; i < this.length; i++) {
const el = this[i];
const val = fn.call(el, i, el);
if (val != null) {
elems = elems.concat(val);
}
}
return this._make(elems);
}
/**
* Creates a function to test if a filter is matched.
*
* @param match - A filter.
* @returns A function that determines if a filter has been matched.
*/
function getFilterFn(match) {
if (typeof match === 'function') {
return (el, i) => match.call(el, i, el);
}
if (isCheerio(match)) {
return (el) => Array.prototype.includes.call(match, el);
}
return function (el) {
return match === el;
};
}
export function filter(match) {
var _a;
return this._make(filterArray(this.toArray(), match, this.options.xmlMode, (_a = this._root) === null || _a === void 0 ? void 0 : _a[0]));
}
export function filterArray(nodes, match, xmlMode, root) {
return typeof match === 'string'
? select.filter(match, nodes, { xmlMode, root })
: nodes.filter(getFilterFn(match));
}
/**
* Checks the current list of elements and returns `true` if _any_ of the
* elements match the selector. If using an element or Cheerio selection,
* returns `true` if _any_ of the elements match. If using a predicate function,
* the function is executed in the context of the selected element, so `this`
* refers to the current element.
*
* @category Traversing
* @param selector - Selector for the selection.
* @returns Whether or not the selector matches an element of the instance.
* @see {@link https://api.jquery.com/is/}
*/
export function is(selector) {
const nodes = this.toArray();
return typeof selector === 'string'
? select.some(nodes.filter(isTag), selector, this.options)
: selector
? nodes.some(getFilterFn(selector))
: false;
}
/**
* Remove elements from the set of matched elements. Given a Cheerio object that
* represents a set of DOM elements, the `.not()` method constructs a new
* Cheerio object from a subset of the matching elements. The supplied selector
* is tested against each element; the elements that don't match the selector
* will be included in the result.
*
* The `.not()` method can take a function as its argument in the same way that
* `.filter()` does. Elements for which the function returns `true` are excluded
* from the filtered set; all other elements are included.
*
* @category Traversing
* @example <caption>Selector</caption>
*
* ```js
* $('li').not('.apple').length;
* //=> 2
* ```
*
* @example <caption>Function</caption>
*
* ```js
* $('li').not(function (i, el) {
* // this === el
* return $(this).attr('class') === 'orange';
* }).length; //=> 2
* ```
*
* @param match - Value to look for, following the rules above.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/not/}
*/
export function not(match) {
let nodes = this.toArray();
if (typeof match === 'string') {
const matches = new Set(select.filter(match, nodes, this.options));
nodes = nodes.filter((el) => !matches.has(el));
}
else {
const filterFn = getFilterFn(match);
nodes = nodes.filter((el, i) => !filterFn(el, i));
}
return this._make(nodes);
}
/**
* Filters the set of matched elements to only those which have the given DOM
* element as a descendant or which have a descendant that matches the given
* selector. Equivalent to `.filter(':has(selector)')`.
*
* @category Traversing
* @example <caption>Selector</caption>
*
* ```js
* $('ul').has('.pear').attr('id');
* //=> fruits
* ```
*
* @example <caption>Element</caption>
*
* ```js
* $('ul').has($('.pear')[0]).attr('id');
* //=> fruits
* ```
*
* @param selectorOrHaystack - Element to look for.
* @returns The filtered collection.
* @see {@link https://api.jquery.com/has/}
*/
export function has(selectorOrHaystack) {
return this.filter(typeof selectorOrHaystack === 'string'
? // Using the `:has` selector here short-circuits searches.
`:has(${selectorOrHaystack})`
: (_, el) => this._make(el).find(selectorOrHaystack).length > 0);
}
/**
* Will select the first element of a cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().first().text();
* //=> Apple
* ```
*
* @returns The first element.
* @see {@link https://api.jquery.com/first/}
*/
export function first() {
return this.length > 1 ? this._make(this[0]) : this;
}
/**
* Will select the last element of a cheerio object.
*
* @category Traversing
* @example
*
* ```js
* $('#fruits').children().last().text();
* //=> Pear
* ```
*
* @returns The last element.
* @see {@link https://api.jquery.com/last/}
*/
export function last() {
return this.length > 0 ? this._make(this[this.length - 1]) : this;
}
/**
* Reduce the set of matched elements to the one at the specified index. Use
* `.eq(-i)` to count backwards from the last selected element.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).text();
* //=> Apple
*
* $('li').eq(-1).text();
* //=> Pear
* ```
*
* @param i - Index of the element to select.
* @returns The element at the `i`th position.
* @see {@link https://api.jquery.com/eq/}
*/
export function eq(i) {
var _a;
i = +i;
// Use the first identity optimization if possible
if (i === 0 && this.length <= 1)
return this;
if (i < 0)
i = this.length + i;
return this._make((_a = this[i]) !== null && _a !== void 0 ? _a : []);
}
export function get(i) {
if (i == null) {
return this.toArray();
}
return this[i < 0 ? this.length + i : i];
}
/**
* Retrieve all the DOM elements contained in the jQuery set as an array.
*
* @example
*
* ```js
* $('li').toArray();
* //=> [ {...}, {...}, {...} ]
* ```
*
* @returns The contained items.
*/
export function toArray() {
return Array.prototype.slice.call(this);
}
/**
* Search for a given element from among the matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('.pear').index();
* //=> 2 $('.orange').index('li');
* //=> 1
* $('.apple').index($('#fruit, li'));
* //=> 1
* ```
*
* @param selectorOrNeedle - Element to look for.
* @returns The index of the element.
* @see {@link https://api.jquery.com/index/}
*/
export function index(selectorOrNeedle) {
let $haystack;
let needle;
if (selectorOrNeedle == null) {
$haystack = this.parent().children();
needle = this[0];
}
else if (typeof selectorOrNeedle === 'string') {
$haystack = this._make(selectorOrNeedle);
needle = this[0];
}
else {
// eslint-disable-next-line @typescript-eslint/no-this-alias, unicorn/no-this-assignment
$haystack = this;
needle = isCheerio(selectorOrNeedle)
? selectorOrNeedle[0]
: selectorOrNeedle;
}
return Array.prototype.indexOf.call($haystack, needle);
}
/**
* Gets the elements matching the specified range (0-based position).
*
* @category Traversing
* @example
*
* ```js
* $('li').slice(1).eq(0).text();
* //=> 'Orange'
*
* $('li').slice(1, 2).length;
* //=> 1
* ```
*
* @param start - A position at which the elements begin to be selected. If
* negative, it indicates an offset from the end of the set.
* @param end - A position at which the elements stop being selected. If
* negative, it indicates an offset from the end of the set. If omitted, the
* range continues until the end of the set.
* @returns The elements matching the specified range.
* @see {@link https://api.jquery.com/slice/}
*/
export function slice(start, end) {
return this._make(Array.prototype.slice.call(this, start, end));
}
/**
* End the most recent filtering operation in the current chain and return the
* set of matched elements to its previous state.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).end().length;
* //=> 3
* ```
*
* @returns The previous state of the set of matched elements.
* @see {@link https://api.jquery.com/end/}
*/
export function end() {
var _a;
return (_a = this.prevObject) !== null && _a !== void 0 ? _a : this._make([]);
}
/**
* Add elements to the set of matched elements.
*
* @category Traversing
* @example
*
* ```js
* $('.apple').add('.orange').length;
* //=> 2
* ```
*
* @param other - Elements to add.
* @param context - Optionally the context of the new selection.
* @returns The combined set.
* @see {@link https://api.jquery.com/add/}
*/
export function add(other, context) {
const selection = this._make(other, context);
const contents = uniqueSort([...this.get(), ...selection.get()]);
return this._make(contents);
}
/**
* Add the previous set of elements on the stack to the current set, optionally
* filtered by a selector.
*
* @category Traversing
* @example
*
* ```js
* $('li').eq(0).addBack('.orange').length;
* //=> 2
* ```
*
* @param selector - Selector for the elements to add.
* @returns The combined set.
* @see {@link https://api.jquery.com/addBack/}
*/
export function addBack(selector) {
return this.prevObject
? this.add(selector ? this.prevObject.filter(selector) : this.prevObject)
: this;
}
//# sourceMappingURL=traversing.js.map

File diff suppressed because one or more lines are too long