Socket
Socket
Sign inDemoInstall

cheerio

Package Overview
Dependencies
4
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.12.2 to 0.12.3

CONTRIBUTING.md

11

History.md
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
* Correct the implementation `filter` and `is` (@jugglinmike)
* add .data() function (@andi-neck)
* add .css() (@yields)
* Implements contents() (@jlep)
0.12.2 / 2013-09-04

@@ -3,0 +14,0 @@ ==================

@@ -59,2 +59,51 @@ var _ = require('underscore'),

var setData = function(el, name, value) {
if (typeof name === 'object') return _.extend(el.data, name);
if (typeof name === 'string' && value !== undefined) {
el.data[name] = encode(value);
} else if (typeof name === 'object') {
// If its an object, loop through it
_.each(name, function(value, key) {
el.data[key] = encode(value);
});
}
return el.data;
};
var data = exports.data = function(name, value) {
var elem = this[0];
if (!elem || !isTag(elem)) return;
if (!elem.data) {
elem.data = {};
}
// Return the entire data object if no data specified
if (!name) {
_.each(elem.data, function(value, key) {
elem.data[key] = decode(value);
});
return elem.data;
}
// Set the value (with attr map support)
if (typeof name === 'object' || value !== undefined) {
this.each(function(i, el) {
el.data = setData(el, name, value);
});
return this;
} else if (Object.hasOwnProperty.call(elem.data, name)) {
// Get the (decoded) data
return decode(elem.data[name]);
} else if (typeof name === 'string' && value === undefined) {
return undefined;
}
return this;
};
/**

@@ -232,2 +281,36 @@ * Get the value of an element

var toggleClass = exports.toggleClass = function(value, stateVal) {
// Support functions
if (_.isFunction(value)) {
return this.each(function(i, el) {
this.toggleClass(value.call(this, i, el.attribs['class'] || '', stateVal), stateVal);
});
}
// Return if no value or not a string or function
if (!value || !_.isString(value)) return this;
var classNames = value.split(rspace),
numClasses = classNames.length,
isBool = typeof stateVal === 'boolean',
numElements = this.length,
$elem,
state;
for (var i = 0; i < numElements; i++) {
$elem = this.make(this[i]);
// If selected element isnt a tag, move on
if (!isTag(this[i])) continue;
// Check if class already exists
for (var j = 0; j < numClasses; j++) {
// check each className given, space separated list
state = isBool ? stateVal : !$elem.hasClass(classNames[j]);
$elem[state ? 'addClass' : 'removeClass'](classNames[j]);
}
}
return this;
};
var is = exports.is = function (selector) {

@@ -234,0 +317,0 @@ if (selector) {

32

lib/api/traversing.js

@@ -92,3 +92,3 @@ var _ = require('underscore'),

this.parent() ? this.parent().children() : this.siblingsAndMe(),
function(elem) { return isTag(elem) && elem !== this[0]; },
function(elem) { return isTag(elem) && !this.is(elem); },
this

@@ -114,2 +114,9 @@ );

var contents = exports.contents = function() {
return this.make(_.reduce(this, function(all, elem) {
all.push.apply(all, elem.children);
return all;
}, []));
}
var each = exports.each = function(fn) {

@@ -129,6 +136,21 @@ var i = 0, len = this.length;

var make = _.bind(this.make, this);
return make(_.filter(this, _.isString(match) ?
function(el) { return select(match, el)[0] === el; }
: function(el, i) { return match.call(make(el), i, el); }
));
var filterFn;
if (_.isString(match)) {
filterFn = function(el) {
return select(match, el)[0] === el;
};
} else if (_.isFunction(match)) {
filterFn = function(el, i) {
return match.call(make(el), i, el);
};
} else if (match.cheerio) {
filterFn = match.is.bind(match);
} else {
filterFn = function(el) {
return match === el;
};
}
return make(_.filter(this, filterFn));
};

@@ -135,0 +157,0 @@

2

lib/cheerio.js

@@ -16,3 +16,3 @@ /*

var api = ['attributes', 'traversing', 'manipulation'];
var api = ['attributes', 'traversing', 'manipulation', 'css'];

@@ -19,0 +19,0 @@ /*

@@ -7,2 +7,3 @@ /*

isTag = require('./utils').isTag;
camelCase = require('./utils').camelCase;

@@ -49,6 +50,13 @@ /*

_.each(dom, function(elem) {
// If tag and no attributes, add empty object
if (isTag(elem.type) && elem.attribs === undefined)
elem.attribs = {};
if (isTag(elem.type)) {
// If tag and no attributes, add empty object
if (elem.attribs === undefined) {
elem.attribs = {};
} else {
// If there are already attributes, add them to the data list.
elem.data = parseData(elem);
}
}
// Set parent

@@ -99,2 +107,21 @@ elem.parent = parent;

/**
* Extract data by using element attributes.
* @param {Object} elem Element
* @return {Object} `element.data` object
*/
var parseData = exports.parseData = function(elem) {
if (elem.data === undefined) elem.data = {};
var value;
for (var key in elem.attribs) {
if (key.substr(0, 5) === 'data-') {
value = elem.attribs[key];
key = key.slice(5);
key = camelCase(key);
elem.data[key] = value;
}
}
return elem.data;
};
// module.exports = $.extend(exports);

@@ -26,2 +26,4 @@ /*

for (var key in attributes) {
// Make sure it doesn't format data attributes.
if (key.substr(0, 5) === 'data-') continue;
value = attributes[key];

@@ -39,2 +41,13 @@ if (!value && (rboolean.test(key) || key === '/')) {

/*
Format data entries
*/
var formatData = function(data) {
if (!data) return '';
return Object.keys(data).map(function(key) {
return 'data-' + key + '="' + data[key] + '"';
}).join(' ');
};
/*
Self-enclosing tags (stolen from node-htmlparser)

@@ -116,2 +129,3 @@ */

if (elem.attribs && _.size(elem.attribs)) {
if (_.size(elem.data)) tag += ' ' + formatData(elem.data);
tag += ' ' + formatAttrs(elem.attribs);

@@ -118,0 +132,0 @@ }

@@ -24,2 +24,14 @@ /**

/**
* Convert a string to camel case notation.
* @param {String} str String to be converted.
* @return {String} String in camel case notation.
*/
exports.camelCase = function(str) {
return str.replace(/[_.-](\w|$)/g, function(_, x) {
return x.toUpperCase();
});
};
/**
* Expose encode and decode methods from FB55's node-entities library

@@ -26,0 +38,0 @@ *

@@ -6,3 +6,3 @@ {

"keywords": ["htmlparser", "jquery", "selector", "scraper"],
"version": "0.12.2",
"version": "0.12.3",
"repository": {

@@ -9,0 +9,0 @@ "type": "git",

@@ -146,2 +146,19 @@ # cheerio [![Build Status](https://secure.travis-ci.org/MatthewMueller/cheerio.png?branch=master)](http://travis-ci.org/MatthewMueller/cheerio)

#### .data( name, value )
Method for getting and setting data attributes. Gets or sets the data attribute value for only the first element in the matched set.
```js
$('<div data-apple-color="red"></div>').data()
//=> { appleColor: 'red' }
$('<div data-apple-color="red"></div>').data('data-apple-color')
//=> 'red'
var apple = $('.apple').data('kind', 'mac')
apple.data('kind')
//=> 'mac'
```
> See http://api.jquery.com/data/ for more information
#### .val( [value] )

@@ -205,5 +222,20 @@ Method for getting and setting the value of input, select, and textarea. Note: Support for `map`, and `function` has not been added yet.

#### .toggleClass( className, [switch] )
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` like jQuery.
```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>
```
> See http://api.jquery.com/toggleClass/ for more information.
#### .is( selector )
#### .is( element )
#### .is( selection )
#### .is( function(index) )
Checks the current list of elements and returns `true` if _any_ of the elements match the selector. If using a predicate function, the function is executed in the context of the selected element, so `this` refers to the current element.
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.

@@ -318,2 +350,10 @@

#### .contents()
Gets the children of each element in the set of matched elements, including text and comment nodes.
```js
$('#fruits').contents().length
//=> 3
```
#### .each( function(index, element) )

@@ -344,5 +384,5 @@ 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`.

#### .filter( selector ) <br /> .filter( function(index) )
#### .filter( selector ) <br /> .filter( selection ) <br /> .filter( element ) <br /> .filter( function(index) )
Iterates over a cheerio object, reducing the set of selector elements to those that match the selector or pass the function's test. If using the function method, the function is executed in the context of the selected element, so `this` refers to the current element.
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.

@@ -349,0 +389,0 @@ Selector:

@@ -6,2 +6,4 @@ var expect = require('expect.js');

var vegetables = require('./fixtures').vegetables;
var food = require('./fixtures').food;
var chocolates = require('./fixtures').chocolates;
var inputs = require('./fixtures').inputs;

@@ -83,2 +85,67 @@

describe('.data', function() {
it('() : should get all data attributes', function() {
var data = $('.linth', chocolates).data();
expect(data).to.eql({
highlight: 'Lindor',
origin: 'swiss'
});
});
it('() : no data attribute should return an empty object', function() {
var data = $('.cailler', chocolates).data();
expect(data).to.be.empty();
});
it('(invalid key) : invalid data attribute should return `undefined` ', function() {
var data = $('.frey', chocolates).data('lol');
expect(data).to.be(undefined);
});
it('(valid key) : valid data attribute should get value', function() {
var highlight = $('.linth', chocolates).data('highlight');
var origin = $('.linth', chocolates).data('origin');
expect(highlight).to.equal('Lindor');
expect(origin).to.equal('swiss');
});
it('(hyphen key) : data addribute with hyphen should be camelized ;-)', function() {
var data = $('.frey', chocolates).data();
expect(data).to.eql({
taste: 'sweet',
bestCollection: 'Mahony'
});
});
it('(key, value) : should set data attribute', function() {
// Adding as object.
var a = $('.frey', chocolates).data({
balls: 'giandor'
});
// Adding as string.
var b = $('.linth', chocolates).data('snack', 'chocoletti');
expect(a.data('balls')).to.eql('giandor');
expect(b.data('snack')).to.eql('chocoletti');
});
it('(map) : object map should set multiple data attributes', function() {
var data = $('.linth', chocolates).data({
id: 'Cailler',
flop: 'Pippilotti Rist',
top: 'Frigor',
url: 'http://www.cailler.ch/'
})['0'].data;
expect(data.id).to.equal('Cailler');
expect(data.flop).to.equal('Pippilotti Rist');
expect(data.top).to.equal('Frigor');
expect(data.url).to.equal('http://www.cailler.ch/');
});
});
describe('.val', function() {

@@ -287,26 +354,125 @@ it('.val(): on select should get value', function() {

describe('.toggleClass', function() {
it('(class class) : should toggle multiple classes from the element', function() {
var $fruits = $(fruits);
$('.apple', $fruits).addClass('fruit');
expect($('.apple', $fruits).hasClass('apple')).to.be.ok();
expect($('.apple', $fruits).hasClass('fruit')).to.be.ok();
expect($('.apple', $fruits).hasClass('red')).to.not.be.ok();
$('.apple', $fruits).toggleClass('apple red');
expect($('.fruit', $fruits).hasClass('apple')).to.not.be.ok();
expect($('.fruit', $fruits).hasClass('red')).to.be.ok();
expect($('.fruit', $fruits).hasClass('fruit')).to.be.ok();
});
it('(class class, true) : should add multiple classes to the element', function() {
var $fruits = $(fruits);
$('.apple', $fruits).addClass('fruit');
expect($('.apple', $fruits).hasClass('apple')).to.be.ok();
expect($('.apple', $fruits).hasClass('fruit')).to.be.ok();
expect($('.apple', $fruits).hasClass('red')).to.not.be.ok();
$('.apple', $fruits).toggleClass('apple red', true);
expect($('.fruit', $fruits).hasClass('apple')).to.be.ok();
expect($('.fruit', $fruits).hasClass('red')).to.be.ok();
expect($('.fruit', $fruits).hasClass('fruit')).to.be.ok();
});
it('(class class, false) : should remove multiple classes from the element', function() {
var $fruits = $(fruits);
$('.apple', $fruits).addClass('fruit');
expect($('.apple', $fruits).hasClass('apple')).to.be.ok();
expect($('.apple', $fruits).hasClass('fruit')).to.be.ok();
expect($('.apple', $fruits).hasClass('red')).to.not.be.ok();
$('.apple', $fruits).toggleClass('apple red', false);
expect($('.fruit', $fruits).hasClass('apple')).to.not.be.ok();
expect($('.fruit', $fruits).hasClass('red')).to.not.be.ok();
expect($('.fruit', $fruits).hasClass('fruit')).to.be.ok();
});
it('(fn) : should toggle classes returned from the function', function() {
var $food = $(food);
$('.apple', $food).addClass('fruit');
$('.carrot', $food).addClass('vegetable');
expect($('.apple', $food).hasClass('fruit')).to.be.ok();
expect($('.apple', $food).hasClass('vegetable')).to.not.be.ok();
expect($('.orange', $food).hasClass('fruit')).to.not.be.ok();
expect($('.orange', $food).hasClass('vegetable')).to.not.be.ok();
expect($('.carrot', $food).hasClass('fruit')).to.not.be.ok();
expect($('.carrot', $food).hasClass('vegetable')).to.be.ok();
expect($('.sweetcorn', $food).hasClass('fruit')).to.not.be.ok();
expect($('.sweetcorn', $food).hasClass('vegetable')).to.not.be.ok();
$('li', $food).toggleClass(function(index, className, switchVal) {
return $(this).parent().is('#fruits') ? 'fruit' : 'vegetable';
});
expect($('.apple', $food).hasClass('fruit')).to.not.be.ok();
expect($('.apple', $food).hasClass('vegetable')).to.not.be.ok();
expect($('.orange', $food).hasClass('fruit')).to.be.ok();
expect($('.orange', $food).hasClass('vegetable')).to.not.be.ok();
expect($('.carrot', $food).hasClass('fruit')).to.not.be.ok();
expect($('.carrot', $food).hasClass('vegetable')).to.not.be.ok();
expect($('.sweetcorn', $food).hasClass('fruit')).to.not.be.ok();
expect($('.sweetcorn', $food).hasClass('vegetable')).to.be.ok();
});
});
describe('.is', function () {
it('() should return false', function () {
expect($('li.apple', fruits).is()).to.be(false)
})
it('(true selector) should return true', function () {
expect($('#vegetables', vegetables).is('ul')).to.be(true)
})
it('(false selector) should return false', function () {
expect($('#vegetables', vegetables).is('div')).to.be(false)
})
it('(true predicate) should return true', function () {
it('() : should return false', function() {
expect($('li.apple', fruits).is()).to.be(false);
});
it('(true selector) : should return true', function() {
expect($('#vegetables', vegetables).is('ul')).to.be(true);
});
it('(false selector) : should return false', function() {
expect($('#vegetables', vegetables).is('div')).to.be(false);
});
it('(true selection) : should return true', function() {
var $vegetables = $('li', vegetables);
expect($vegetables.is($vegetables.eq(1))).to.be(true);
});
it('(false selection) : should return false', function() {
var $vegetableList = $(vegetables);
var $vegetables = $vegetableList.find('li');
expect($vegetables.is($vegetableList)).to.be(false);
});
it('(true element) : should return true', function() {
var $vegetables = $('li', vegetables);
expect($vegetables.is($vegetables[0])).to.be(true);
});
it('(false element) : should return false', function() {
var $vegetableList = $(vegetables);
var $vegetables = $vegetableList.find('li');
expect($vegetables.is($vegetableList[0])).to.be(false);
});
it('(true predicate) : should return true', function() {
var result = $('li', fruits).is(function() {
return this.hasClass('pear')
})
expect(result).to.be(true)
})
it('(false predicate) should return false', function () {
return this.hasClass('pear');
});
expect(result).to.be(true);
});
it('(false predicate) : should return false', function () {
var result = $('li', fruits).last().is(function() {
return this.name === 'ul'
})
expect(result).to.be(false)
})
})
return this.name === 'ul';
});
expect(result).to.be(false);
});
});
});

@@ -5,2 +5,3 @@ var expect = require('expect.js'),

fruits = require('./fixtures').fruits;
text = require('./fixtures').text;

@@ -70,2 +71,18 @@ describe('$(...)', function() {

describe('.contents', function() {
it('() : should get all contents', function() {
expect($('p', text).contents()).to.have.length(5);
});
it('() : should include text nodes', function() {
expect($('p', text).contents().first()[0].type).to.equal('text');
});
it('() : should include comment nodes', function() {
expect($('p', text).contents().last()[0].type).to.equal('comment');
});
});
describe('.next', function() {

@@ -148,2 +165,3 @@

expect($('#fruits', fruits).siblings()).to.have.length(0);
expect($('.apple, .carrot', food).siblings()).to.have.length(3);
});

@@ -309,2 +327,14 @@

it('(selection) : should reduce the set of matched elements to those that are contained in the provided selection', function() {
var $fruits = $('li', fruits);
var $pear = $fruits.filter('.pear, .apple');
expect($fruits.filter($pear)).to.have.length(2);
});
it('(element) : should reduce the set of matched elements to those that specified directly', function() {
var $fruits = $('li', fruits);
var pear = $fruits.filter('.pear')[0];
expect($fruits.filter(pear)).to.have.length(1);
});
it('(fn) : should reduce the set of matched elements to those that pass the function\'s test', function() {

@@ -311,0 +341,0 @@ var orange = $('li', fruits).filter(function(i, el) {

@@ -11,7 +11,15 @@ exports.fruits = [

'<ul id="vegetables">',
'<li>Carrot</li>',
'<li>Sweetcorn</li>',
'<li class="carrot">Carrot</li>',
'<li class="sweetcorn">Sweetcorn</li>',
'</ul>'
].join('');
exports.chocolates = [
'<ul id="chocolates">',
'<li class="linth" data-highlight="Lindor" data-origin="swiss">Linth</li>',
'<li class="frey" data-taste="sweet" data-best-collection="Mahony">Frey</li>',
'<li class="cailler">Cailler</li>',
'</ul>'
].join('');
exports.food = [

@@ -31,1 +39,6 @@ '<ul id="food">',

].join('');
exports.text = [
'<p>Apples, <b>oranges</b> and pears.</p>',
'<p>Carrots and <!-- sweetcorn --></p>'
].join('');
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc