diff --git a/.eslintrc.json b/.eslintrc.json index c81781a6a4..9d26bbfcad 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -33,6 +33,8 @@ }, "preferredTypes": { "node": "Node", + "nodewithchildren": "NodeWithChildren", + "element": "Element", "cheerio": "Cheerio" } } diff --git a/lib/api/attributes.js b/lib/api/attributes.js index e6dbdf3a22..de06a4de47 100644 --- a/lib/api/attributes.js +++ b/lib/api/attributes.js @@ -32,9 +32,9 @@ var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/; * Also supports getting the `value` of several form elements. * * @private - * @param {Node} elem - Elenent to get the attribute of. + * @param {Element} elem - Elenent to get the attribute of. * @param {string} name - Name of the attribute. - * @returns {string | undefined} The attribute's value. + * @returns {object | string | undefined} The attribute's value. */ function getAttr(elem, name) { if (!elem || !isTag(elem)) return; @@ -72,7 +72,7 @@ function getAttr(elem, name) { * Sets the value of an attribute. The attribute will be deleted if the value is `null`. * * @private - * @param {Node} el - The element to set the attribute on. + * @param {Element} el - The element to set the attribute on. * @param {string} name - The attribute's name. * @param {string | null} value - The attribute's value. */ @@ -98,7 +98,7 @@ function setAttr(el, name, value) { * //=>
  • Apple
  • * * @param {string} name - Name of the attribute. - * @param {string} [value] - If specified sets the value of the attribute. + * @param {string | Function} [value] - If specified sets the value of the attribute. * @see {@link https://api.jquery.com/attr/} * * @returns {string | Cheerio} If `value` is specified the instance itself, @@ -151,7 +151,7 @@ function getProp(el, name) { * Sets the value of a prop. * * @private - * @param {Node} el - The element to set the prop on. + * @param {Element} el - The element to set the prop on. * @param {string} name - The prop's name. * @param {string | null} value - The prop's value. */ @@ -193,23 +193,21 @@ exports.prop = function (name, value) { property.length = keys.length; - break; + return property; } case 'tagName': case 'nodeName': - property = this[0].name.toUpperCase(); - break; + return this[0].name.toUpperCase(); + case 'outerHTML': - property = this.clone().wrap('').parent().html(); - break; + return this.clone().wrap('').parent().html(); + case 'innerHTML': - property = this.html(); - break; + return this.html(); + default: - property = getProp(this[0], name); + return getProp(this[0], name); } - - return property; } if (typeof name === 'object' || value !== undefined) { @@ -238,8 +236,8 @@ exports.prop = function (name, value) { * Sets the value of a data attribute. * * @private - * @param {Node} el - The element to set the data attribute on. - * @param {string|object} name - The data attribute's name. + * @param {Element} el - The element to set the data attribute on. + * @param {string | object} name - The data attribute's name. * @param {string | null} value - The data attribute's value. */ function setData(el, name, value) { @@ -259,7 +257,7 @@ function setData(el, name, value) { * attribute name is specified, read *all* HTML5 `data-*` attributes in this manner. * * @private - * @param {Node} el - Elenent to get the data attribute of. + * @param {Element} el - Elenent to get the data attribute of. * @param {string} [name] - Name of the data attribute. * @returns {any} The data attribute's value, or a map with all of the data attribute. */ @@ -325,7 +323,7 @@ function readData(el, name) { * @param {any} [value] - If specified new value. * @see {@link https://api.jquery.com/data/} * - * @returns {string | Cheerio} If `value` is specified the instance itself, + * @returns {string | Cheerio | undefined} If `value` is specified the instance itself, * otherwise the data attribute's value. */ exports.data = function (name, value) { @@ -366,10 +364,9 @@ exports.data = function (name, value) { * $('input[type="text"]').val('test').html(); * //=> * - * @param {string} [value] - If specified new value. + * @param {string | string[]} [value] - If specified new value. * @see {@link https://api.jquery.com/val/} - * - * @returns {string | Cheerio} If a new `value` is specified the instance + * @returns {string | Cheerio | undefined} If a new `value` is specified the instance * itself, otherwise the value. */ exports.val = function (value) { @@ -383,7 +380,7 @@ exports.val = function (value) { return this.text(value); case 'select': { var option = this.find('option:selected'); - if (!option) return undefined; + if (!option) return; if (!querying) { if (this.attr('multiple') == null && typeof value == 'object') { return this; @@ -414,7 +411,7 @@ exports.val = function (value) { * Remove an attribute. * * @private - * @param {Node} elem - Node to remove attribute from. + * @param {Element} elem - Node to remove attribute from. * @param {string} name - Name of the attribute to remove. */ function removeAttribute(elem, name) { @@ -453,7 +450,7 @@ exports.removeAttr = function (name) { var attrNames = splitNames(name); for (var i = 0; i < attrNames.length; i++) { - domEach(this, function (j, elem) { + domEach(this, function (_, elem) { removeAttribute(elem, attrNames[i]); }); } @@ -496,6 +493,8 @@ exports.hasClass = function (className) { } } } + + return false; }); }; @@ -509,9 +508,8 @@ exports.hasClass = function (className) { * $('.apple').addClass('fruit red').html(); * //=>
  • Apple
  • * - * @param {string} value - Name of new class. + * @param {string | Function} value - Name of new class. * @see {@link https://api.jquery.com/addClass/} - * * @returns {Cheerio} The instance itself. */ exports.addClass = function (value) { @@ -566,9 +564,8 @@ exports.addClass = function (value) { * $('.apple').addClass('red').removeClass().html(); * //=>
  • Apple
  • * - * @param {string} value - Name of the class. + * @param {string | Function} value - Name of the class. * @see {@link https://api.jquery.com/removeClass/} - * * @returns {Cheerio} The instance itself. */ exports.removeClass = function (value) { @@ -586,7 +583,7 @@ exports.removeClass = function (value) { var numClasses = classes.length; var removeAll = arguments.length === 0; - return domEach(this, function (i, el) { + return domEach(this, function (_, el) { if (!isTag(el)) return; if (removeAll) { @@ -689,7 +686,7 @@ exports.toggleClass = function (value, stateVal) { * @param {string | Function | Cheerio | Node} selector - Selector for the selection. * @see {@link https://api.jquery.com/is/} * - * @returns {Cheerio} The instance itself. + * @returns {boolean} Whether or not the selector matches an element of the instance. */ exports.is = function (selector) { if (selector) { diff --git a/lib/api/css.js b/lib/api/css.js index fc29f34b2c..096026abec 100644 --- a/lib/api/css.js +++ b/lib/api/css.js @@ -32,9 +32,9 @@ exports.css = function (prop, val) { * * @private * - * @param {object} el - Element to set style of. + * @param {Element} el - Element to set style of. * @param {string | object} prop - Name of property. - * @param {string} val - Value to set property to. + * @param {string | Function} val - Value to set property to. * @param {number} [idx] - Optional index within the selection. */ function setCss(el, prop, val, idx) { @@ -63,14 +63,12 @@ function setCss(el, prop, val, idx) { * * @private * - * @param {Node} el - Element to get styles from. - * @param {string} prop - Name of the prop. - * @returns {object} The parsed styles. + * @param {Element} el - Element to get styles from. + * @param {string | string[]} [prop] - Name of the prop. + * @returns {object | undefined} The parsed styles. */ function getCss(el, prop) { - if (!el || !el.attribs) { - return undefined; - } + if (!el || !el.attribs) return; var styles = parse(el.attribs.style); if (typeof prop === 'string') { diff --git a/lib/api/forms.js b/lib/api/forms.js index 3ba47e3b9c..8d627ed0ca 100644 --- a/lib/api/forms.js +++ b/lib/api/forms.js @@ -35,12 +35,13 @@ exports.serialize = function () { * * @see {@link https://api.jquery.com/serializeArray/} * + * @this {Cheerio} * @returns {object[]} The serialized form. */ exports.serializeArray = function () { // Resolve all form elements from either forms or collections of form elements var Cheerio = this.constructor; - return this.map(function (i, elem) { + return this.map(function (_, elem) { var $elem = Cheerio(elem); if (elem.name === 'form') { return $elem.find(submittableSelector).toArray(); @@ -56,7 +57,7 @@ exports.serializeArray = function () { ':matches([checked], :not(:checkbox, :radio))' // Convert each of the elements to its value(s) ) - .map(function (i, elem) { + .map(function (_, elem) { var $elem = Cheerio(elem); var name = $elem.attr('name'); var value = $elem.val(); diff --git a/lib/api/manipulation.js b/lib/api/manipulation.js index 2e4aee7f65..10c512dd2e 100644 --- a/lib/api/manipulation.js +++ b/lib/api/manipulation.js @@ -29,7 +29,7 @@ exports._makeDomArray = function makeDomArray(elem, clone) { if (elem == null) { return []; } else if (elem.cheerio) { - return clone ? cloneDom(elem.get(), elem.options) : elem.get(); + return clone ? cloneDom(elem.get()) : elem.get(); } else if (Array.isArray(elem)) { return elem.reduce( function (newElems, el) { @@ -70,7 +70,7 @@ function _insert(concatenator) { * @param {number} spliceIdx - Index at which to begin changing the array. * @param {number} spliceCount - Number of elements to remove from the array. * @param {Node[]} newElems - Elements to insert into the array. - * @param {Node} parent - The parent of the node. + * @param {NodeWithChildren} parent - The parent of the node. * @returns {Node[]} The spliced array. */ function uniqueSplice(array, spliceIdx, spliceCount, newElems, parent) { @@ -612,7 +612,7 @@ exports.insertBefore = function (target) { } target = this._makeDomArray(target); self.remove(); - domEach(target, function (i, el) { + domEach(target, function (_, el) { var clonedSelf = self._makeDomArray(self.clone()); var parent = el.parent; if (!parent) { @@ -653,7 +653,7 @@ exports.remove = function (selector) { // Filter if we have selector var elems = selector ? this.filter(selector) : this; - domEach(elems, function (i, el) { + domEach(elems, function (_, el) { DomUtils.removeElement(el); el.prev = el.next = el.parent = null; }); @@ -719,7 +719,7 @@ exports.replaceWith = function (content) { * @returns {Cheerio} The instance itself. */ exports.empty = function () { - return domEach(this, function (i, el) { + return domEach(this, function (_, el) { el.children.forEach(function (child) { child.next = child.prev = child.parent = null; }); @@ -739,7 +739,7 @@ exports.empty = function () { * $('#fruits').html('
  • Mango
  • ').html(); * //=>
  • Mango
  • * - * @param {string} str - If specified used to replace selection's contents. + * @param {string | Cheerio} str - If specified used to replace selection's contents. * @see {@link https://api.jquery.com/html/} * * @returns {Cheerio} The instance itself. @@ -752,7 +752,7 @@ exports.html = function (str) { var opts = this.options; - return domEach(this, function (i, el) { + return domEach(this, function (_, el) { el.children.forEach(function (child) { child.next = child.prev = child.parent = null; }); @@ -788,9 +788,9 @@ exports.toString = function () { * // Orange * // Pear * - * @param {string} [str] - If specified replacement for the selected element's contents. + * @param {string | Function} [str] - If specified replacement for the selected + * element's contents. * @see {@link https://api.jquery.com/text/} - * * @returns {Cheerio | string} The instance itself when setting text, otherwise * the rendered document. */ @@ -806,7 +806,7 @@ exports.text = function (str) { } // Append text node to each selected elements - return domEach(this, function (i, el) { + return domEach(this, function (_, el) { el.children.forEach(function (child) { child.next = child.prev = child.parent = null; }); @@ -828,5 +828,5 @@ exports.text = function (str) { * @returns {Cheerio} The cloned object. */ exports.clone = function () { - return this._make(cloneDom(this.get(), this.options)); + return this._make(cloneDom(this.get())); }; diff --git a/lib/api/traversing.js b/lib/api/traversing.js index 0bc41925c1..b7fe46bda6 100644 --- a/lib/api/traversing.js +++ b/lib/api/traversing.js @@ -75,7 +75,7 @@ exports.find = function (selectorOrHaystack) { exports.parent = function (selector) { var set = []; - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { var parentElem = elem.parent; if ( parentElem && @@ -213,7 +213,7 @@ exports.closest = function (selector) { return this._make(set); } - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { var closestElem = traverseParents(this, elem, selector, 1)[0]; // Do not add duplicate elements to the set @@ -243,7 +243,7 @@ exports.next = function (selector) { } var elems = []; - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.next)) { if (isTag(elem)) { elems.push(elem); @@ -278,7 +278,7 @@ exports.nextAll = function (selector) { } var elems = []; - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.next)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); @@ -321,7 +321,7 @@ exports.nextUntil = function (selector, filterSelector) { untilNode = selector; } - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.next)) { if ( (untilNode && elem !== untilNode) || @@ -361,7 +361,7 @@ exports.prev = function (selector) { } var elems = []; - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.prev)) { if (isTag(elem)) { elems.push(elem); @@ -396,7 +396,7 @@ exports.prevAll = function (selector) { } var elems = []; - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.prev)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); @@ -439,7 +439,7 @@ exports.prevUntil = function (selector, filterSelector) { untilNode = selector; } - domEach(this, function (idx, elem) { + domEach(this, function (_, elem) { while ((elem = elem.prev)) { if ( (untilNode && elem !== untilNode) || @@ -635,7 +635,7 @@ function getFilterFn(match) { * * @function * @param {string | Function} match - Value to look for, following the rules above. - * @param {Node[]} container - Optional node to filter instead. + * @param {Cheerio} [container] - Optional node to filter instead. * @see {@link https://api.jquery.com/filter/} * * @returns {Cheerio} The filtered collection. @@ -675,10 +675,10 @@ exports.filter = function (match, container) { * //=> 2 * * @function - * @param {string | Function} match - Value to look for, following the rules above. - * @param {Node[]} container - Optional node to filter instead. + * @param {string | Function} match - Value to look for, following the rules + * above. + * @param {Node[] | Cheerio} [container] - Optional node to filter instead. * @see {@link https://api.jquery.com/not/} - * * @returns {Cheerio} The filtered collection. */ exports.not = function (match, container) { @@ -720,7 +720,7 @@ exports.not = function (match, container) { */ exports.has = function (selectorOrHaystack) { var that = this; - return exports.filter.call(this, function (i, el) { + return exports.filter.call(this, function (_, el) { return that._make(el).find(selectorOrHaystack).length > 0; }); }; diff --git a/lib/parse.js b/lib/parse.js index 1c62a7e00e..09abc5d89d 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -42,7 +42,7 @@ exports = module.exports = function parse(content, options, isDocument) { * Update the dom structure, for one changed layer. * * @param {Node[] | Node} arr - The new children. - * @param {Node} parent - The new parent. + * @param {NodeWithChildren} parent - The new parent. * @returns {Node} The parent node. */ exports.update = function (arr, parent) { diff --git a/lib/static.js b/lib/static.js index d8f87a1ac4..7f90ade49a 100644 --- a/lib/static.js +++ b/lib/static.js @@ -139,7 +139,7 @@ exports.xml = function (dom) { /** * Render the document as text. * - * @param {Cheerio | Node} [elems] - Elements to render. + * @param {Cheerio | Node[]} [elems] - Elements to render. * @returns {string} The rendered document. */ exports.text = function (elems) { diff --git a/lib/utils.js b/lib/utils.js index a2a1b174de..95a01c476f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -48,7 +48,7 @@ exports.cssCase = function (str) { * * @param {Cheerio} cheerio - Cheerio object. * @param {Function} fn - Function to call. - * @returns {void} + * @returns {Cheerio} The original instance. */ exports.domEach = function (cheerio, fn) { var i = 0; diff --git a/types/index.d.ts b/types/index.d.ts index 499c1d57b7..e5c8957f79 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -66,7 +66,7 @@ declare namespace cheerio { // Traversing find(selector: string): Cheerio; - find(element: Cheerio): Cheerio; + find(element: Cheerio | Element): Cheerio; parent(selector?: string): Cheerio; parents(selector?: string): Cheerio; diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 31e4824656..bfed0143c2 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -85,6 +85,7 @@ $el.attr('id', (el, i, attr) => el.tagName + i * 2 + attr).html(); $el.attr('id', (el) => el.tagName).html(); $el.attr({ id: 'uniq', class: 'big' }).html(); +$multiEl.prop('foo') === undefined; $emptyEl.attr('id') === undefined; // props @@ -183,13 +184,13 @@ $el.children('.class').text(); $el.contents().length; // .each( function(index, element) ) -$el.each((i, el) => { +$el.each((_, el) => { $(el).html(); }); // .map( function(index, element) ) $el - .map((i, el) => { + .map((_, el) => { return $(el).text(); }) .get() @@ -202,7 +203,7 @@ $el.filter($('.class')).attr('class'); $el.filter($('.class')[0]).attr('class'); $el - .filter((i, el) => { + .filter((_, el) => { return $(el).attr('class') === 'class'; }) .attr('class'); @@ -212,7 +213,7 @@ $el.not('.class').length; $el.not($('.class')).length; $el.not($('.class')[0]).length; -$el.not((i, el) => { +$el.not((_, el) => { return $(el).attr('class') === 'class'; }).length;