diff --git a/lib/api/traversing.js b/lib/api/traversing.js index 8547210d73..1b159d280b 100644 --- a/lib/api/traversing.js +++ b/lib/api/traversing.js @@ -9,6 +9,7 @@ var utils = require('../utils'); var domEach = utils.domEach; var uniqueSort = require('htmlparser2').DomUtils.uniqueSort; var isTag = utils.isTag; +var reSiblingSelector = /^\s*[~+]/; /** * Get the descendants of each element in the current set of matched elements, @@ -26,9 +27,6 @@ var isTag = utils.isTag; * @see {@link http://api.jquery.com/find/} */ exports.find = function (selectorOrHaystack) { - var elems = this.toArray().reduce(function (newElems, elem) { - return newElems.concat(elem.children.filter(isTag)); - }, []); var contains = this.constructor.contains; var haystack; @@ -52,9 +50,20 @@ exports.find = function (selectorOrHaystack) { ); } - var options = { __proto__: this.options, context: this.toArray() }; + if (!selectorOrHaystack) { + return this._make([]); + } + + var context = this.toArray(); + var elems = reSiblingSelector.test(selectorOrHaystack) + ? context + : context.reduce(function (newElems, elem) { + return newElems.concat(elem.children.filter(isTag)); + }, []); + + var options = Object.assign({ context: context }, this.options); - return this._make(select.select(selectorOrHaystack || '', elems, options)); + return this._make(select.select(selectorOrHaystack, elems, options)); }; /** diff --git a/test/api/traversing.js b/test/api/traversing.js index 0c2bf23e9b..daff61c4f9 100644 --- a/test/api/traversing.js +++ b/test/api/traversing.js @@ -61,6 +61,15 @@ describe('$(...)', function () { expect(q('foo').find('> bar')).to.have.length(1); }); + it('should find siblings', function () { + var q = cheerio.load('

'); + expect(q('.a').find('+.b')).to.have.length(1); + expect(q('.a').find('~.b')).to.have.length(1); + // Should not find itself + expect(q('.a').find('+.a')).to.have.length(0); + expect(q('.a').find('~.a')).to.have.length(0); + }); + it('should query case-sensitively when in xml mode', function () { var q = cheerio.load('', { xml: true }); expect(q('caseSenSitive')).to.have.length(1);