diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..f3fc95057c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: cheerio +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with a single custom sponsorship URL diff --git a/.travis.yml b/.travis.yml index b7d7df23f8..e8b962b198 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ node_js: - "unstable" - "6" - "4" - - "0.12" script: make travis-test matrix: fast_finish: true diff --git a/CNAME b/CNAME new file mode 100644 index 0000000000..c9cd136f79 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +cheerio.js.org \ No newline at end of file diff --git a/Readme.md b/Readme.md index 57327b1108..752cb21241 100644 --- a/Readme.md +++ b/Readme.md @@ -12,6 +12,10 @@ $.html() //=>

Hello there!

``` +## Note + +We are currently working on the 1.0.0 release of cheerio on the `master` branch. The source code for the last published version, `0.22.0`, can be found [here](https://github.com/cheeriojs/cheerio/tree/aa90399c9c02f12432bfff97b8f1c7d8ece7c307). + ## Installation `npm install react-native-cheerio` @@ -44,6 +48,7 @@ $.html()
Forms + - [.serialize()](#serialize) - [.serializeArray()](#serializearray)
@@ -198,6 +203,13 @@ $('li[class=orange]').html() //=> Orange ``` +##### XML Namespaces +You can select with XML Namespaces but [due to the CSS specification](https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#attribute-selectors), the colon (`:`) needs to be escaped for the selector to be valid. + +```js +$('[xml\\:id="main"'); +``` + ### Attributes Methods for getting and modifying attributes. @@ -324,6 +336,15 @@ Checks the current list of elements and returns `true` if _any_ of the elements ### Forms +#### .serialize() + +Encodes a set of form elements as a URL query string. + +```js +$('
').serialize() +//=> foo=bar&foo=qux +``` + #### .serializeArray() Encode a set of form elements as an array of names and values. @@ -856,7 +877,7 @@ $('li').wrap(healthy) // ``` -#### .css( [propertName] )
.css( [ propertyNames] )
.css( [propertyName], [value] )
.css( [propertName], [function] )
.css( [properties] ) +#### .css( [propertyName] )
.css( [ propertyNames] )
.css( [propertyName], [value] )
.css( [propertyName], [function] )
.css( [properties] ) Get the value of a style property for the first element in the set of matched elements or set one or more CSS properties for every matched element. @@ -941,7 +962,7 @@ $.root().append('').html(); Checks to see if the `contained` DOM element is a descendant of the `container` DOM element. #### $.parseHTML( data [, context ] [, keepScripts ] ) -Parses a string into an array of DOM nodes. The `context` argument has no meaning for Cheerio, but it is maintained for API compatability. +Parses a string into an array of DOM nodes. The `context` argument has no meaning for Cheerio, but it is maintained for API compatibility. #### $.load( html[, options ] ) Load in the HTML. (See the previous section titled "Loading" for more information.) @@ -961,7 +982,7 @@ $('body').logHtml(); // logs "Hello, world!" to the console ### The "DOM Node" object -Cheerio collections are made up of objects that bear some resemblence to [browser-based DOM nodes](https://developer.mozilla.org/en-US/docs/Web/API/Node). You can expect them to define the following properties: +Cheerio collections are made up of objects that bear some resemblance to [browser-based DOM nodes](https://developer.mozilla.org/en-US/docs/Web/API/Node). You can expect them to define the following properties: - `tagName` - `parentNode` diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000000..c4192631f2 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/benchmark/suite.js b/benchmark/suite.js index da029ad7ec..d45ccf7eb8 100644 --- a/benchmark/suite.js +++ b/benchmark/suite.js @@ -62,20 +62,19 @@ Suites.prototype.add = function(name, fileName, options) { Suites.prototype._benchJsDom = function(suite, markup, options) { var testFn = options.test; - jsdom.env({ - html: markup, - scripts: jQuerySrc, - done: function(err, window) { - var setupData; - if (options.setup) { - setupData = options.setup.call(null, window.$); - } - suite.add('jsdom', function() { - testFn.call(null, window.$, setupData); - }); - suite.run(); - } + var { JSDOM } = jsdom; + var { window } = new JSDOM(markup); + window.$ = require(jQuerySrc)(window); + + var setupData; + if (options.setup) { + setupData = options.setup.call(null, window.$); + } + suite.add('jsdom', function() { + testFn.call(null, window.$, setupData); }); + suite.run(); + }; Suites.prototype._benchCheerio = function(suite, markup, options) { diff --git a/lib/api/attributes.js b/lib/api/attributes.js index 01a1dc9dfe..6abbb2f7dc 100644 --- a/lib/api/attributes.js +++ b/lib/api/attributes.js @@ -93,7 +93,7 @@ exports.attr = function(name, value) { var getProp = function (el, name) { if (!el || !isTag(el)) return; - return el.hasOwnProperty(name) + return name in el ? el[name] : rboolean.test(name) ? getAttr(el, name) !== undefined diff --git a/lib/api/css.js b/lib/api/css.js index d9ffae6cfa..d784b68d22 100644 --- a/lib/api/css.js +++ b/lib/api/css.js @@ -66,6 +66,10 @@ function setCss(el, prop, val, idx) { */ function getCss(el, prop) { + if(!el || !el.attribs) { + return undefined; + } + var styles = parse(el.attribs.style); if (typeof prop === 'string') { return styles[prop]; diff --git a/package.json b/package.json index ca6c2c9730..8b86a419e1 100644 --- a/package.json +++ b/package.json @@ -25,24 +25,24 @@ "node": ">= 0.6" }, "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2-without-node-native": "^3.9.0", - "lodash": "^4.15.0" + "htmlparser2-without-node-native": "^3.9.2", + "css-select": "~2.0.2", + "dom-serializer": "~0.1.1", + "entities": "~1.1.2", + "lodash": "^4.17.11" }, "devDependencies": { - "benchmark": "^2.1.0", - "coveralls": "^2.11.9", + "benchmark": "^2.1.4", + "coveralls": "^3.0.2", "expect.js": "~0.3.1", - "istanbul": "^0.4.3", - "jsdom": "^9.2.1", - "jquery": "^3.0.0", - "jshint": "^2.9.2", - "mocha": "^3.1.2", - "xyz": "~1.1.0" + "istanbul": "^0.4.5", + "jquery": "^3.3.1", + "jsdom": "^13.2.0", + "jshint": "^2.10.1", + "mocha": "^5.2.0", + "xyz": "~3.0.0" }, "scripts": { - "test": "make test" + "test": "jshint lib/ test/ && mocha --recursive --reporter dot" } } diff --git a/test/api/attributes.js b/test/api/attributes.js index 1f99e66a8d..61072dd9b9 100644 --- a/test/api/attributes.js +++ b/test/api/attributes.js @@ -130,10 +130,11 @@ describe('$(...)', function() { }); describe('.prop', function () { - var checkbox; + var checkbox, selectMenu; beforeEach(function () { $ = cheerio.load(inputs); + selectMenu = $('select'); checkbox = $('input[name=checkbox_on]'); }); @@ -186,6 +187,10 @@ describe('$(...)', function() { expect($(undefined).prop('prop')).to.be(undefined); expect($(null).prop('prop')).to.be(undefined); }); + + it('(inherited properties) : prop should support inherited properties', function() { + expect(selectMenu.prop('childNodes')).to.equal(selectMenu[0].childNodes); + }); }); describe('.data', function() { diff --git a/test/api/css.js b/test/api/css.js index 9e394c44f0..1f75abb4a4 100644 --- a/test/api/css.js +++ b/test/api/css.js @@ -42,6 +42,16 @@ describe('$(...)', function() { expect(el.css()).to.eql({position:'absolute'}); }); + it('(prop): should return undefined for unmatched elements', function() { + var $ = cheerio.load('
  • '); + expect($('ul').css('background-image')).to.eql(undefined); + }); + + it('(prop): should return undefined for unmatched styles', function() { + var el = cheerio('
  • '); + expect(el.css('margin')).to.eql(undefined); + }); + describe('(prop, function):', function() { beforeEach(function() { this.$el = cheerio('
    '); diff --git a/test/api/traversing.js b/test/api/traversing.js index 06a969ca42..939ffb36d1 100644 --- a/test/api/traversing.js +++ b/test/api/traversing.js @@ -63,9 +63,7 @@ describe('$(...)', function() { it('should throw a SyntaxError if given an invalid selector', function() { expect(function() { $('#fruits').find(':bah'); - }).to.throwException(function(err) { - expect(err).to.be.a(SyntaxError); - }); + }).to.throwException(/unmatched pseudo-class/); }); describe('(cheerio object) :', function() { @@ -456,9 +454,7 @@ describe('$(...)', function() { it('(selector) : should throw a SyntaxError if given an invalid selector', function() { expect(function() { $('.orange').siblings(':bah'); - }).to.throwException(function(err) { - expect(err).to.be.a(SyntaxError); - }); + }).to.throwException(/unmatched pseudo-class/); }); it('(selector) : does not consider the contents of siblings when filtering (GH-374)', function() { diff --git a/test/api/utils.js b/test/api/utils.js index d6983c8a1c..a750f28377 100644 --- a/test/api/utils.js +++ b/test/api/utils.js @@ -101,8 +101,12 @@ describe('cheerio', function() { // }); it('(buffer) : should accept a buffer', function() { - var $html = cheerio.load(new Buffer('
    foo
    ')); - expect($html.html()).to.be('
    foo
    '); + var html = '
    foo
    '; + var buf = Buffer.from && Buffer.from !== Uint8Array.from + ? Buffer.from(html) + : new Buffer(html); + var $html = cheerio.load(buf); + expect($html.html()).to.be(html); }); }); diff --git a/test/cheerio.js b/test/cheerio.js index 69562466c0..4501f9bdb6 100644 --- a/test/cheerio.js +++ b/test/cheerio.js @@ -162,12 +162,6 @@ describe('cheerio', function() { expect($fruits[0].attribs.id).to.equal('fruits'); }); - it('should select first element $(:first)'); - // var $elem = $(':first', fruits); - // var $h2 = $('

    fruits

    '); - // console.log($elem.before('hi')); - // console.log($elem.before($h2)); - it('should be able to select immediate children: $("#fruits > .pear")', function() { var $food = $(food); $('.pear', $food).append('
  • Another Pear!
  • '); @@ -368,7 +362,7 @@ describe('cheerio', function() { var str = '', // since parsing done without xmlMode flag, all tags converted to lowercase expectedXml = '', - expectedNoXml = '', + expectedNoXml = '', dom = $.load(str); expect(dom('MixedCaseTag').get(0).tagName).to.equal('mixedcasetag'); diff --git a/test/mocha.opts b/test/mocha.opts index 9431de4c17..b8a05a88fc 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1 @@ --reporter list ---growl \ No newline at end of file