cheerio
Advanced tools
Comparing version 0.8.3 to 0.9.0
@@ -0,1 +1,11 @@ | ||
0.9.0 / 2012-07-24 | ||
================== | ||
* Added node 8.x support | ||
* Removed node 4.x support | ||
* Add html(dom) support (@wvl) | ||
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55) | ||
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers) | ||
* Tons of cleanup (@davidchambers) | ||
0.8.3 / 2012-06-12 | ||
@@ -6,3 +16,3 @@ ================== | ||
0.8.2 / 2012-06-11 | ||
0.8.2 / 2012-06-11 | ||
================== | ||
@@ -25,3 +35,3 @@ | ||
* ignoreWhitespace now on by default again. See #55 for context. | ||
* Changed $(":root") to $.root(), cleaned up $.clone() | ||
* Changed $(':root') to $.root(), cleaned up $.clone() | ||
* Support for .eq(i) thanks to @alexbardas | ||
@@ -63,3 +73,3 @@ * Removed support for node 0.4.x | ||
* `$.html()` returns the full HTML string. `$.html([cheerioObject])` will return the outer(selected element's tag) and inner HTML of that object | ||
* Fixed bug that prevented HTML strings with depth (eg. `append("<ul><li><li></ul>")`) from getting `parent`, `next`, `prev` attributes. | ||
* Fixed bug that prevented HTML strings with depth (eg. `append('<ul><li><li></ul>')`) from getting `parent`, `next`, `prev` attributes. | ||
* Halted [htmlparser2](https://github.com/FB55/node-htmlparser) at v2.2.2 until single attributes bug gets fixed. | ||
@@ -124,3 +134,3 @@ | ||
* Added benchmark directory for future speed tests | ||
* $("...").dom() was funky, so it was removed in favor of $("...").get(). $.dom() still works the same. | ||
* $('...').dom() was funky, so it was removed in favor of $('...').get(). $.dom() still works the same. | ||
* $.root now correctly static across all instances of $ | ||
@@ -127,0 +137,0 @@ * Added a screencast |
@@ -8,5 +8,2 @@ var fs = require('fs'); | ||
*/ | ||
exports.version = (function() { | ||
var pkg = fs.readFileSync(__dirname + '/package.json', 'utf8'); | ||
return JSON.parse(pkg).version; | ||
})(); | ||
exports.version = require('./package').version; |
@@ -1,3 +0,3 @@ | ||
var _ = require("underscore"), | ||
$ = require("../cheerio"), | ||
var _ = require('underscore'), | ||
$ = require('../cheerio'), | ||
rclass = /[\n\t\r]/g, | ||
@@ -14,20 +14,11 @@ rspace = /\s+/; | ||
}); | ||
return this; | ||
}; | ||
var hasClass = exports.hasClass = function(selector) { | ||
var className = " " + selector + " ", | ||
classes, | ||
elem; | ||
for(var i = 0; i < this.length; i++) { | ||
elem = this[i]; | ||
// Add spaces to support multiple classes | ||
classes = (" " + elem.attribs["class"] + " ").replace(rclass, " "); | ||
if ($.isTag(elem) && elem.attribs && classes.indexOf(className) > -1) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
var hasClass = exports.hasClass = function(className) { | ||
return _.any(this, function(elem) { | ||
var attrs = elem.attribs; | ||
return attrs && _.contains((attrs['class'] || '').split(/\s+/), className); | ||
}); | ||
}; | ||
@@ -40,3 +31,3 @@ | ||
var $this = $(this), | ||
className = $this.attr('class') || ""; | ||
className = $this.attr('class') || ''; | ||
@@ -57,3 +48,3 @@ $this.addClass(value.call(this, i, className)); | ||
for(var i = 0; i < numElements; i++) { | ||
for (var i = 0; i < numElements; i++) { | ||
$elem = $(this[i]); | ||
@@ -64,6 +55,6 @@ // If selected element isnt a tag, move on | ||
// If we don't already have classes | ||
if (!$elem.attr("class")) { | ||
if (!$elem.attr('class')) { | ||
$elem.attr('class', classNames.join(' ').trim()); | ||
} else { | ||
setClass = " " + $elem.attr("class") + " "; | ||
setClass = ' ' + $elem.attr('class') + ' '; | ||
numClasses = classNames.length; | ||
@@ -73,4 +64,4 @@ | ||
for (var j = 0; j < numClasses; j++) { | ||
if (!~setClass.indexOf(" " + classNames[j] + " ")) | ||
setClass += classNames[j] + " "; | ||
if (!~setClass.indexOf(' ' + classNames[j] + ' ')) | ||
setClass += classNames[j] + ' '; | ||
} | ||
@@ -91,3 +82,3 @@ | ||
var $this = $(this), | ||
className = $this.attr('class') || ""; | ||
className = $this.attr('class') || ''; | ||
$this.removeClass(value.call(this, j, className)); | ||
@@ -98,5 +89,5 @@ }); | ||
// If value isnt undefined and also not a string | ||
if(value !== undefined && !_.isString(value)) return this; | ||
if (value !== undefined && !_.isString(value)) return this; | ||
var classNames = (value || "").split(rspace), | ||
var classNames = (value || '').split(rspace), | ||
numClasses = classNames.length, | ||
@@ -111,4 +102,4 @@ className, | ||
if(!$.isTag(this[i]) || !className) continue; | ||
else if(!value) { | ||
if (!$.isTag(this[i]) || !className) continue; | ||
else if (!value) { | ||
this[i].attribs['class'] = ''; | ||
@@ -119,7 +110,7 @@ continue; | ||
// Separate out the classes | ||
ret = (" " + className + " ").replace(rclass, " "); | ||
ret = (' ' + className + ' ').replace(rclass, ' '); | ||
for (var j = 0; j < numClasses; j++) { | ||
className = classNames[j]; | ||
ret = ret.replace(" " + className + " ", " "); | ||
ret = ret.replace(' ' + className + ' ', ' '); | ||
} | ||
@@ -133,2 +124,2 @@ | ||
module.exports = $.fn.extend(exports); | ||
module.exports = $.fn.extend(exports); |
var underscore = require('underscore'), | ||
$ = require('../cheerio'), | ||
isArray = Array.isArray; | ||
var size = exports.size = function() { | ||
@@ -16,3 +16,3 @@ return this.length; | ||
if(~num) { | ||
if (~num) { | ||
return this[num]; | ||
@@ -27,3 +27,3 @@ } else { | ||
var ret = this.constructor(); | ||
if (isArray(elems)) { | ||
@@ -34,10 +34,10 @@ push.apply(ret, elems); | ||
} | ||
ret.prevObject = this; | ||
ret.context = this.context; | ||
if (name === "find") { | ||
ret.selector = this.selector + (this.selector ? " " : "") + selector; | ||
} else if(name) { | ||
ret.selector = this.selector + "." + name + "(" + selector + ")"; | ||
if (name === 'find') { | ||
ret.selector = this.selector + (this.selector ? ' ' : '') + selector; | ||
} else if (name) { | ||
ret.selector = this.selector + '.' + name + '(' + selector + ')'; | ||
} | ||
@@ -51,9 +51,9 @@ return ret; | ||
element = raw; | ||
while (element.prev) { | ||
element = element.prev; | ||
} | ||
siblings.push(element); | ||
while (element.next) { | ||
@@ -63,6 +63,6 @@ element = element.next; | ||
} | ||
return siblings; | ||
}; | ||
module.exports = $.fn.extend(exports); | ||
module.exports = $.fn.extend(exports); |
@@ -22,6 +22,6 @@ var _ = require('underscore'), | ||
for(var i = 0; i < len; i++) { | ||
for (var i = 0; i < len; i++) { | ||
elem = elems[i]; | ||
// If a cheerio object | ||
if(elem.cheerio) { | ||
if (elem.cheerio) { | ||
dom = dom.concat(elem.toArray()); | ||
@@ -41,7 +41,7 @@ } else { | ||
this.each(function() { | ||
if(_.isFunction(elems[0])) { | ||
if (_.isFunction(elems[0])) { | ||
// No yet supported | ||
return this; | ||
} else { | ||
if(!this.children) this.children = []; | ||
if (!this.children) this.children = []; | ||
this.children = this.children.concat(dom); | ||
@@ -65,7 +65,7 @@ updateDOM(this.children, this); | ||
this.each(function() { | ||
if(_.isFunction(elems[0])) { | ||
if (_.isFunction(elems[0])) { | ||
// No yet supported | ||
return this; | ||
} else { | ||
if(!this.children) this.children = []; | ||
if (!this.children) this.children = []; | ||
this.children = dom.concat(this.children); | ||
@@ -88,3 +88,3 @@ updateDOM(this.children, this); | ||
// If not found, move on | ||
if(!~index) return; | ||
if (!~index) return; | ||
@@ -112,3 +112,3 @@ // Add element after `this` element | ||
// If not found, move on | ||
if(!~index) return; | ||
if (!~index) return; | ||
@@ -134,3 +134,3 @@ // Add element before `this` element | ||
// Filter if we have selector | ||
if(selector) | ||
if (selector) | ||
elems = elems.find(selector); | ||
@@ -142,3 +142,3 @@ | ||
if(!~index) return; | ||
if (!~index) return; | ||
@@ -156,10 +156,10 @@ siblings.splice(index, 1); | ||
var replaceWith = exports.replaceWith = function(content) { | ||
var content = (content.cheerio) ? content.toArray() : $.parse.eval(content); | ||
content = content.cheerio ? content.toArray() : $.parse.eval(content); | ||
this.each(function() { | ||
var siblings = this.parent.children, | ||
index = siblings.indexOf(this); | ||
if(!~index) return; | ||
if (!~index) return; | ||
siblings.splice.apply(siblings, [index, 1].concat(content)); | ||
@@ -170,3 +170,3 @@ | ||
}); | ||
return this; | ||
@@ -182,12 +182,13 @@ }; | ||
var html = exports.html = function(str) { | ||
if(str === undefined || typeof(str) === 'object') { | ||
if(!this[0] || !this[0].children) return null; | ||
var html = exports.html = function(content) { | ||
if (content === undefined) { | ||
if (!this[0] || !this[0].children) return null; | ||
return $.html(this[0].children); | ||
} | ||
str = $.parse.eval(str); | ||
content = content.cheerio ? content.toArray() : $.parse.eval(content); | ||
this.each(function() { | ||
this.children = str; | ||
this.children = content; | ||
updateDOM(this.children, this); | ||
}); | ||
@@ -204,3 +205,3 @@ | ||
// If `str` blank or an object | ||
if(!str || typeof(str) === 'object') { | ||
if (!str || typeof str === 'object') { | ||
return $.text(this); | ||
@@ -216,3 +217,3 @@ } else if (_.isFunction(str)) { | ||
var elem = { | ||
data : str, | ||
data : $.encode(str), | ||
type : 'text', | ||
@@ -219,0 +220,0 @@ parent : null, |
@@ -5,2 +5,3 @@ /* | ||
var htmlparser = require('htmlparser2'), | ||
_ = require('underscore'), | ||
$ = require('../cheerio'), | ||
@@ -29,3 +30,3 @@ isArray = Array.isArray; | ||
update(dom, root); | ||
return root; | ||
@@ -48,33 +49,30 @@ }; | ||
parent = parent || null; | ||
var prevIndex = -1, | ||
lastElem = null, | ||
len = dom.length; | ||
for(var i = 0; i < len; i++) { | ||
var prevElem = null; | ||
_.each(dom, function(elem) { | ||
// If tag and no attributes, add empty object | ||
if($.isTag(dom[i].type) && dom[i].attribs === undefined) | ||
dom[i].attribs = {}; | ||
if ($.isTag(elem.type) && elem.attribs === undefined) | ||
elem.attribs = {}; | ||
// Set parent | ||
dom[i].parent = parent; | ||
elem.parent = parent; | ||
// Previous Sibling | ||
dom[i].prev = dom[prevIndex] || null; | ||
elem.prev = prevElem; | ||
// Next sibling | ||
dom[i].next = null; | ||
if(lastElem) lastElem.next = dom[i]; | ||
elem.next = null; | ||
if (prevElem) prevElem.next = elem; | ||
// Run through the children | ||
if(dom[i].children) | ||
connect(dom[i].children, dom[i]); | ||
else if($.isTag(dom[i].type)) | ||
dom[i].children = []; | ||
if (elem.children) | ||
connect(elem.children, elem); | ||
else if ($.isTag(elem.type)) | ||
elem.children = []; | ||
// Get ready for next element | ||
prevIndex = i; | ||
lastElem = dom[i]; | ||
} | ||
prevElem = elem; | ||
}); | ||
return dom; | ||
@@ -85,3 +83,3 @@ }; | ||
Update the dom structure, for one changed layer | ||
* Much faster than reconnecting | ||
@@ -92,5 +90,5 @@ */ | ||
arr = isArray(arr) ? arr : [arr]; | ||
// Update neighbors | ||
for(var i = 0; i < arr.length; i++) { | ||
for (var i = 0; i < arr.length; i++) { | ||
arr[i].prev = arr[i-1] || null; | ||
@@ -100,6 +98,6 @@ arr[i].next = arr[i+1] || null; | ||
} | ||
// Update parent | ||
parent.children = arr; | ||
return parent; | ||
@@ -106,0 +104,0 @@ }; |
@@ -21,7 +21,7 @@ /* | ||
var formatAttrs = function(attributes) { | ||
if(!attributes) return ''; | ||
if (!attributes) return ''; | ||
var output = [], | ||
value; | ||
// Loop through the attributes | ||
@@ -36,3 +36,3 @@ for (var key in attributes) { | ||
} | ||
return output.join(' '); | ||
@@ -60,3 +60,3 @@ }; | ||
include: 1, | ||
yield: 1 | ||
'yield': 1 | ||
}; | ||
@@ -82,29 +82,24 @@ | ||
var len = dom.length, | ||
output = [], | ||
tidy = (opts.tidy ? true : false), | ||
ending = (tidy ? "\n" : ""), | ||
elem; | ||
var output = [], | ||
tidy = !!opts.tidy; | ||
xmlMode = $.fn.options.xmlMode; | ||
ignoreWhitespace = $.fn.options.ignoreWhitespace; | ||
for(var i = 0; i < len; i++) { | ||
elem = dom[i]; | ||
var pushVal = ""; | ||
_.each(dom, function(elem) { | ||
var pushVal; | ||
if(tagType[elem.type]) | ||
if (tagType[elem.type]) | ||
pushVal = renderTag(elem); | ||
else if(elem.type === 'directive') | ||
else if (elem.type === 'directive') | ||
pushVal = renderDirective(elem); | ||
else if(elem.type === 'comment') | ||
else if (elem.type === 'comment') | ||
pushVal = renderComment(elem); | ||
else | ||
pushVal = renderText(elem); | ||
var spacing = ''; | ||
if (tidy) { | ||
for(var k = 0; k < depth; k++){ spacing += ' ' }; | ||
output.push(spacing + pushVal + "\n"); | ||
spacing = Array(depth + 1).join(' '); | ||
output.push(spacing + pushVal + '\n'); | ||
} else { | ||
@@ -115,11 +110,11 @@ output.push(pushVal); | ||
depth++; | ||
if(elem.children) | ||
if (elem.children) | ||
output.push(render(elem.children, { tidy: tidy })); | ||
depth--; | ||
if((!singleTag[elem.name] || xmlMode) && tagType[elem.type]) | ||
output.push(spacing + "</" + elem.name + ">" + ending); | ||
} | ||
if ((!singleTag[elem.name] || xmlMode) && tagType[elem.type]) | ||
output.push(spacing + '</' + elem.name + '>'); | ||
}); | ||
return output.join(''); | ||
return output.join(tidy ? '\n' : ''); | ||
}; | ||
@@ -129,19 +124,11 @@ | ||
var tag = '<' + elem.name; | ||
if(elem.attribs && _.size(elem.attribs)) { | ||
if (elem.attribs && _.size(elem.attribs)) { | ||
tag += ' ' + formatAttrs(elem.attribs); | ||
} | ||
if(xmlMode || !singleTag[elem.name]) { | ||
tag += '>'; | ||
} else { | ||
tag = tag.trim().replace(/\/$/, ''); | ||
tag += '/>'; | ||
} | ||
return tag; | ||
return tag + (!xmlMode && singleTag[elem.name] ? '/>' : '>'); | ||
}; | ||
var renderDirective = exports.render.renderDirective = function(elem) { | ||
return "<" + elem.data + ">"; | ||
return '<' + elem.data + '>'; | ||
}; | ||
@@ -148,0 +135,0 @@ |
@@ -1,7 +0,7 @@ | ||
var _ = require("underscore"), | ||
var _ = require('underscore'), | ||
select = require('cheerio-select'), | ||
$ = require("../cheerio"); | ||
$ = require('../cheerio'); | ||
var find = exports.find = function(selector) { | ||
if(!selector) return this; | ||
if (!selector) return this; | ||
try { | ||
@@ -16,3 +16,3 @@ var elem = select(selector, this.toArray()); | ||
var parent = exports.parent = function(elem) { | ||
if(this[0] && this[0].parent) | ||
if (this[0] && this[0].parent) | ||
return $(this[0].parent); | ||
@@ -24,7 +24,7 @@ else | ||
var next = exports.next = function(elem) { | ||
if(!this[0]) return $(); | ||
if (!this[0]) return $(); | ||
var nextSibling = this[0].next; | ||
while(nextSibling) { | ||
if($.isTag(nextSibling)) return $(nextSibling); | ||
while (nextSibling) { | ||
if ($.isTag(nextSibling)) return $(nextSibling); | ||
nextSibling = nextSibling.next; | ||
@@ -36,7 +36,7 @@ } | ||
var prev = exports.prev = function(elem) { | ||
if(!this[0]) return $(); | ||
if (!this[0]) return $(); | ||
var prevSibling = this[0].prev; | ||
while(prevSibling) { | ||
if($.isTag(prevSibling)) return $(prevSibling); | ||
while (prevSibling) { | ||
if ($.isTag(prevSibling)) return $(prevSibling); | ||
prevSibling = prevSibling.prev; | ||
@@ -48,3 +48,3 @@ } | ||
var siblings = exports.siblings = function(elem) { | ||
if(!this[0]) return $(); | ||
if (!this[0]) return $(); | ||
@@ -63,3 +63,3 @@ var self = this, | ||
var children = exports.children = function(selector) { | ||
if(!this[0] || !this[0].children) return $(); | ||
if (!this[0] || !this[0].children) return $(); | ||
@@ -70,4 +70,4 @@ var children = _.filter(this[0].children, function(elem) { | ||
if(selector === undefined) return $(children); | ||
else if(_.isNumber(selector)) return $(children[selector]); | ||
if (selector === undefined) return $(children); | ||
else if (_.isNumber(selector)) return $(children[selector]); | ||
@@ -74,0 +74,0 @@ return $(children).find(selector); |
/* | ||
Module Dependencies | ||
*/ | ||
var _ = require("underscore"), | ||
$ = require("../cheerio"), | ||
var _ = require('underscore'), | ||
$ = require('../cheerio'), | ||
entities = require('entities'); | ||
@@ -37,2 +37,7 @@ | ||
// Expose encode and decode methods from FB55's node-entities library | ||
// 0 = XML, 1 = HTML4 and 2 = HTML5 | ||
var encode = exports.encode = function(str) { return entities.encode(str, 0); }; | ||
var decode = exports.decode = function(str) { return entities.decode(str, 2); }; | ||
/* | ||
@@ -42,3 +47,3 @@ isTag(type) includes <script> and <style> tags | ||
var isTag = exports.isTag = function(type) { | ||
if(type.type) type = type.type; | ||
if (type.type) type = type.type; | ||
return tags[type] || false; | ||
@@ -49,3 +54,3 @@ }; | ||
var type = exports.type = function(obj) { | ||
if(obj === null) | ||
if (obj === null) | ||
return String(obj); | ||
@@ -56,98 +61,98 @@ else | ||
var merge = exports.merge = function( first, second ) { | ||
var i = first.length, | ||
j = 0; | ||
var merge = exports.merge = function(first, second) { | ||
var i = first.length, | ||
j = 0; | ||
if ( typeof second.length === "number" ) { | ||
for ( var l = second.length; j < l; j++ ) { | ||
first[ i++ ] = second[ j ]; | ||
} | ||
if (typeof second.length === 'number') { | ||
for (var l = second.length; j < l; j++) { | ||
first[i++] = second[j]; | ||
} | ||
} else { | ||
while ( second[j] !== undefined ) { | ||
first[ i++ ] = second[ j++ ]; | ||
} | ||
} | ||
} else { | ||
while (second[j] !== undefined) { | ||
first[i++] = second[j++]; | ||
} | ||
} | ||
first.length = i; | ||
first.length = i; | ||
return first; | ||
return first; | ||
}; | ||
var makeArray = exports.makeArray = function( array, results ) { | ||
var makeArray = exports.makeArray = function(array, results) { | ||
var ret = results || [], | ||
type = $.type(array); | ||
if(!array) return ret; | ||
if ( array.length == null || type === "string" || type === "function" || type === "regexp") { | ||
push.call( ret, array ); | ||
} else { | ||
merge( ret, array ); | ||
} | ||
if (!array) return ret; | ||
if (array.length == null || type === 'string' || type === 'function' || type === 'regexp') { | ||
push.call(ret, array); | ||
} else { | ||
merge(ret, array); | ||
} | ||
return ret; | ||
}; | ||
var inArray = exports.inArray = function( elem, array, i ) { | ||
var len; | ||
var inArray = exports.inArray = function(elem, array, i) { | ||
var len; | ||
if ( array ) { | ||
if ( indexOf ) { | ||
return indexOf.call( array, elem, i ); | ||
} | ||
if (array) { | ||
if (indexOf) { | ||
return indexOf.call(array, elem, i); | ||
} | ||
len = array.length; | ||
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; | ||
len = array.length; | ||
i = i ? i < 0 ? Math.max(0, len + i) : i : 0; | ||
for ( ; i < len; i++ ) { | ||
// Skip accessing in sparse arrays | ||
if ( i in array && array[ i ] === elem ) { | ||
return i; | ||
} | ||
} | ||
} | ||
for (; i < len; i++) { | ||
// Skip accessing in sparse arrays | ||
if (i in array && array[i] === elem) { | ||
return i; | ||
} | ||
} | ||
} | ||
return -1; | ||
return -1; | ||
}; | ||
// args is for internal usage only | ||
var each = exports.each = function( object, callback, args ) { | ||
var name, i = 0, | ||
length = object.length, | ||
isObj = length === undefined || _.isFunction( object ); | ||
var each = exports.each = function(object, callback, args) { | ||
var name, i = 0, | ||
length = object.length, | ||
isObj = length === undefined || _.isFunction(object); | ||
if ( args ) { | ||
if ( isObj ) { | ||
for ( name in object ) { | ||
if ( callback.apply( object[ name ], args ) === false ) { | ||
break; | ||
} | ||
} | ||
} else { | ||
for ( ; i < length; ) { | ||
if ( callback.apply( object[ i++ ], args ) === false ) { | ||
break; | ||
} | ||
} | ||
} | ||
if (args) { | ||
if (isObj) { | ||
for (name in object) { | ||
if (callback.apply(object[name], args) === false) { | ||
break; | ||
} | ||
} | ||
} else { | ||
for (; i < length;) { | ||
if (callback.apply(object[i++], args) === false) { | ||
break; | ||
} | ||
} | ||
} | ||
// A special, fast, case for the most common use of each | ||
} else { | ||
if ( isObj ) { | ||
for ( name in object ) { | ||
if ( callback.call( object[ name ], name, object[ name ] ) === false ) { | ||
break; | ||
} | ||
} | ||
} else { | ||
for ( ; i < length; ) { | ||
if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
// A special, fast, case for the most common use of each | ||
} else { | ||
if (isObj) { | ||
for (name in object) { | ||
if (callback.call(object[name], name, object[name]) === false) { | ||
break; | ||
} | ||
} | ||
} else { | ||
for (; i < length;) { | ||
if (callback.call(object[i], i, object[i++]) === false) { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
return object; | ||
return object; | ||
}; | ||
@@ -157,31 +162,31 @@ | ||
// The value/s can optionally be executed if it's a function | ||
var access = exports.access = function( elems, key, value, exec, fn, pass ) { | ||
var length = elems.length; | ||
var access = exports.access = function(elems, key, value, exec, fn, pass) { | ||
var length = elems.length; | ||
// Setting many attributes | ||
if ( typeof key === "object" ) { | ||
for ( var k in key ) { | ||
access( elems, k, key[k], exec, fn, value ); | ||
} | ||
return elems; | ||
} | ||
// Setting many attributes | ||
if (typeof key === 'object') { | ||
for (var k in key) { | ||
access(elems, k, key[k], exec, fn, value); | ||
} | ||
return elems; | ||
} | ||
// Setting one attribute | ||
if ( value !== undefined ) { | ||
// Optionally, function values get executed if exec is true | ||
exec = !pass && exec && _.isFunction(value); | ||
// Setting one attribute | ||
if (value !== undefined) { | ||
// Optionally, function values get executed if exec is true | ||
exec = !pass && exec && _.isFunction(value); | ||
for ( var i = 0; i < length; i++ ) { | ||
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); | ||
} | ||
for (var i = 0; i < length; i++) { | ||
fn(elems[i], key, exec ? value.call(elems[i], i, fn(elems[i], key)) : value, pass); | ||
} | ||
return elems; | ||
} | ||
return elems; | ||
} | ||
// Getting an attribute | ||
return length ? fn( elems[0], key ) : undefined; | ||
// Getting an attribute | ||
return length ? fn(elems[0], key) : undefined; | ||
}; | ||
var attr = exports.attr = function( elem, name, value, pass ) { | ||
var type = elem.type; | ||
var attr = exports.attr = function(elem, name, value, pass) { | ||
var type = elem.type; | ||
@@ -194,5 +199,8 @@ if (!elem || !isTag(elem)) | ||
} | ||
// Return the entire attribs object if no attribute specified | ||
if (!name) { | ||
for(var a in elem.attribs) { | ||
elem.attribs[a] = decode(elem.attribs[a]); | ||
} | ||
return elem.attribs; | ||
@@ -207,7 +215,7 @@ } | ||
// Set the attribute | ||
elem.attribs[name] = "" + value; | ||
elem.attribs[name] = '' + encode(value); | ||
} | ||
} else { | ||
// Get the attributes | ||
return elem.attribs[name]; | ||
} else if(elem.attribs[name]) { | ||
// Get the (decoded) attribute | ||
return decode(elem.attribs[name]); | ||
} | ||
@@ -217,6 +225,6 @@ }; | ||
var removeAttr = exports.removeAttr = function(elem, name) { | ||
if(!isTag(elem.type) || !elem.attribs || !elem.attribs[name]) | ||
if (!isTag(elem.type) || !elem.attribs || !elem.attribs[name]) | ||
return; | ||
if(rboolean.test(elem.attribs[name])) | ||
if (rboolean.test(elem.attribs[name])) | ||
elem.attribs[name] = false; | ||
@@ -230,14 +238,14 @@ else | ||
var ret = "", | ||
var ret = '', | ||
len = elems.length, | ||
elem; | ||
for(var i = 0; i < len; i ++) { | ||
for (var i = 0; i < len; i ++) { | ||
elem = elems[i]; | ||
if(elem.type === 'text') ret += entities.decode(elem.data, 2); | ||
else if(elem.children && elem.type !== 'comment') { | ||
if (elem.type === 'text') ret += decode(elem.data); | ||
else if (elem.children && elem.type !== 'comment') { | ||
ret += text(elem.children); | ||
} | ||
} | ||
return ret; | ||
@@ -252,3 +260,3 @@ }; | ||
var root = $.parse(html); | ||
function fn(selector, context, r) { | ||
@@ -259,6 +267,6 @@ // Overwrite our original root if we explicitly pass in a root | ||
} | ||
// Add the root to cheerio | ||
$.extend({ '_root': root }); | ||
return _(fn).extend($); | ||
@@ -273,3 +281,3 @@ }; | ||
} else { | ||
return ""; | ||
return ''; | ||
} | ||
@@ -285,3 +293,3 @@ }; | ||
} else { | ||
return ""; | ||
return ''; | ||
} | ||
@@ -296,3 +304,3 @@ }; | ||
} else { | ||
return ""; | ||
return ''; | ||
} | ||
@@ -305,2 +313,3 @@ }; | ||
module.exports = $.extend(exports); |
@@ -8,3 +8,3 @@ /* | ||
_ = require('underscore'); | ||
var cheerio = (function() { | ||
@@ -14,7 +14,7 @@ var cheerio = function(selector, context, root) { | ||
}; | ||
// A simple way to check for HTML strings or ID strings | ||
// Prioritize #id over <tag> | ||
var quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/; | ||
cheerio.fn = cheerio.prototype = { | ||
@@ -25,18 +25,18 @@ cheerio : '[cheerio object]', | ||
// Handle $(''), $(null), and $(undefined) | ||
if(!selector) return this; | ||
if (!selector) return this; | ||
// Handle the root | ||
if(root) { | ||
if (root) { | ||
cheerio.extend({ '_root' : root }); | ||
if(typeof context === 'string') | ||
if (typeof context === 'string') | ||
selector = context + ' ' + selector; | ||
context = root; | ||
} | ||
// Handle strings | ||
if(typeof selector === 'string') { | ||
if (typeof selector === 'string') { | ||
var match = null; | ||
// Handle HTML strings | ||
if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) { | ||
if (/^<.+>$/.test(selector)) { | ||
match = [null, selector, null]; | ||
@@ -63,4 +63,4 @@ } else { | ||
} | ||
if(!context || context.cheerio) { | ||
if (!context || context.cheerio) { | ||
// HANDLE : $(expr, $(...)) | ||
@@ -71,3 +71,3 @@ return this.constructor(context || root).find(selector); | ||
// HANDLE : $(expr, context) | ||
if(typeof context === 'string') { | ||
if (typeof context === 'string') { | ||
context = cheerio.parse(context); | ||
@@ -79,9 +79,9 @@ } | ||
} | ||
return cheerio.makeArray(selector, this); | ||
}, | ||
options : { | ||
ignoreWhitespace: false, | ||
xmlMode: false, | ||
lowerCaseTags: false | ||
ignoreWhitespace : false, | ||
xmlMode : false, | ||
lowerCaseTags : false | ||
}, | ||
@@ -92,5 +92,5 @@ selector : '', | ||
}; | ||
cheerio.fn.init.prototype = cheerio.fn; | ||
// Use underscores extend | ||
@@ -102,3 +102,3 @@ cheerio.extend = cheerio.fn.extend = function (obj) { | ||
return cheerio; | ||
})(); | ||
@@ -111,5 +111,4 @@ | ||
*/ | ||
var api = ['core', 'utils', 'parse', 'render', 'attributes', 'traversing', 'manipulation']; | ||
for (var t = 0; t < api.length; t++) { | ||
require('./api/' + api[t] + '.js'); | ||
} | ||
_.each(['core', 'utils', 'parse', 'render', 'attributes', 'traversing', 'manipulation'], function(name) { | ||
require('./api/' + name + '.js'); | ||
}); |
@@ -6,3 +6,3 @@ { | ||
"keywords": ["htmlparser", "jquery", "selector", "scraper"], | ||
"version": "0.8.3", | ||
"version": "0.9.0", | ||
"repository": { | ||
@@ -24,4 +24,3 @@ "type": "git", | ||
"mocha" : "*", | ||
"expect.js" : "*", | ||
"coffee-script": "*" | ||
"expect.js" : "*" | ||
}, | ||
@@ -28,0 +27,0 @@ "scripts": { |
@@ -10,4 +10,4 @@ # cheerio [![Build Status](https://secure.travis-ci.org/MatthewMueller/cheerio.png?branch=master)](http://travis-ci.org/MatthewMueller/cheerio) | ||
var cheerio = require("cheerio"), | ||
$ = cheerio.load("<h2 class = 'title'>Hello world</h2>"); | ||
var cheerio = require('cheerio'), | ||
$ = cheerio.load('<h2 class = "title">Hello world</h2>'); | ||
@@ -35,3 +35,3 @@ $('h2.title').text('Hello there!'); | ||
__❁ Insanely flexible:__ | ||
Cheerio wraps around @tautologistics forgiving htmlparser. Cheerio can parse nearly any HTML or XML document. | ||
Cheerio wraps around @FB55's forgiving htmlparser. Cheerio can parse nearly any HTML or XML document. | ||
@@ -104,5 +104,5 @@ ## What about JSDOM? | ||
This selector method is the starting point for traversing and manipulating the document. Like jQuery, it's the primary method for selecting elements in the document, but unlike jQuery it's built on top of the soup-select library, not the Sizzle engine. | ||
This selector method is the starting point for traversing and manipulating the document. Like jQuery, it's the primary method for selecting elements in the document, but unlike jQuery it's built on top of the CSSSelect library, which implements most of the Sizzle selectors. | ||
$(".apple", '#fruits').text() | ||
$('.apple', '#fruits').text() | ||
=> Apple | ||
@@ -116,5 +116,2 @@ | ||
See [cheerio-soupselect](https://github.com/MatthewMueller/cheerio-soupselect) for a list of all available selectors, | ||
as well as more detailed documentation regarding what is supported and what isn't. | ||
### Attributes | ||
@@ -190,3 +187,3 @@ Methods for getting and modifying attributes. | ||
#### .next() | ||
Gets the next sibling thats an element of the first selected element. | ||
Gets the next sibling of the first selected element. | ||
@@ -197,3 +194,3 @@ $('.apple').next().hasClass('orange') | ||
#### .prev() | ||
Gets the previous sibling thats an element of the first selected element. | ||
Gets the previous sibling of the first selected element. | ||
@@ -243,3 +240,3 @@ $('.orange').prev().hasClass('apple') | ||
#### .eq( i ) | ||
Reduce the set of matched elements to the one at the specified index. Use `.eq(-i)` to count backwards from the last selected element. | ||
Reduce the set of matched elements to the one at the specified index. Use `.eq(-i)` to count backwards from the last selected element. | ||
@@ -410,3 +407,3 @@ $('li').eq(0).text() | ||
$.dom() | ||
=> [{ | ||
=> [{ | ||
type: 'tag', | ||
@@ -425,3 +422,3 @@ name: 'ul', | ||
prev: null, | ||
next: null | ||
next: null | ||
}] | ||
@@ -461,2 +458,22 @@ | ||
This will download the development packages and run the test suite. | ||
## Contributors | ||
These are some of the contributors that have made cheerio possible: | ||
project: cheerio | ||
commits: 292 | ||
active : 78 days | ||
files : 26 | ||
authors: | ||
223 Matt Mueller 76.4% | ||
33 Matthew Mueller 11.3% | ||
15 Siddharth Mahendraker 5.1% | ||
10 David Chambers 3.4% | ||
4 ironchefpython 1.4% | ||
3 Jos Shepherd 1.0% | ||
2 alexbardas 0.7% | ||
1 mattym 0.3% | ||
1 Chris O'Hara 0.3% | ||
## Special Thanks | ||
@@ -466,9 +483,6 @@ | ||
__• @tautologistics' node-htmlparser:__ | ||
This HTML parser can parse anything and produces really consistent results, even when the HTML string has errors. This man is a genius. | ||
__• @FB55 for node-htmlparser2 & CSSSelect:__ | ||
Felix has a knack for writing speedy parsing engines. He completely re-wrote both @tautologistic's `node-htmlparser` and @harry's `node-soupselect` from the ground up, making both of them much faster and more flexible. Cheerio would not be possible without his foundational work | ||
__• @harryf's node-soupselect:__ | ||
What an incredibly fast and precise CSS selector engine. I never really liked the feature-rich selector engines — I think this engine strikes a great balance. | ||
__• @jQuery team:__ | ||
__• @jQuery team for jQuery:__ | ||
The core API is the best of it's class and despite dealing with all the browser inconsistencies the code base is extremely clean and easy to follow. Much of cheerio's implementation and documentation is from jQuery. Thanks guys. | ||
@@ -478,2 +492,3 @@ | ||
The style, the structure, the open-source"-ness" of this library comes from studying TJ's style and using many of his libraries. This dude consistently pumps out high-quality libraries and has always been more than willing to help or answer questions. You rock TJ. | ||
## License | ||
@@ -480,0 +495,0 @@ |
@@ -1,17 +0,12 @@ | ||
var $ = require('../'), | ||
expect = require('expect.js'); | ||
var expect = require('expect.js'), | ||
$ = require('../'); | ||
/* | ||
Examples | ||
*/ | ||
describe('$', function() { | ||
describe('.html', function() { | ||
it('() : should return innerHTML; $.html(obj) should return outerHTML', function() { | ||
var div = $('div', '<div><span>foo</span><span>bar</span></div>'), | ||
span = div.children().get(1); | ||
var $div = $('div', '<div><span>foo</span><span>bar</span></div>'); | ||
var span = $div.children().get(1); | ||
expect($(span).html()).to.equal('bar'); | ||
@@ -22,36 +17,32 @@ expect($.html(span)).to.equal('<span>bar</span>'); | ||
it('(<obj>) : should accept an object, an array, or a cheerio object', function() { | ||
var span = $("<span>foo</span>"); | ||
expect($.html(span.get(0))).to.equal('<span>foo</span>'); | ||
expect($.html(span.get())).to.equal('<span>foo</span>'); | ||
expect($.html(span)).to.equal('<span>foo</span>'); | ||
var $span = $('<span>foo</span>'); | ||
expect($.html($span.get(0))).to.equal('<span>foo</span>'); | ||
expect($.html($span.get())).to.equal('<span>foo</span>'); | ||
expect($.html($span)).to.equal('<span>foo</span>'); | ||
}); | ||
it('(<value>) : should be able to set to an empty string', function() { | ||
var elem = $("<span>foo</span>"); | ||
elem.html(''); | ||
expect($.html(elem)).to.equal('<span></span>'); | ||
var $elem = $('<span>foo</span>').html(''); | ||
expect($.html($elem)).to.equal('<span></span>'); | ||
}); | ||
it('() : of empty cheerio object should return null', function() { | ||
expect($().html()).to.be(null); | ||
}); | ||
}); | ||
describe('.clone', function() { | ||
it('() : should return a copy', function() { | ||
var src = $("<div><span>foo</span><span>bar</span><span>baz</span></div>").children(), | ||
elem = src.clone(); | ||
var $src = $('<div><span>foo</span><span>bar</span><span>baz</span></div>').children(); | ||
var $elem = $src.clone(); | ||
expect($elem.length).to.equal(3); | ||
expect($elem.parent().length).to.equal(1); | ||
expect($elem.parent()[0].type).to.equal('root'); | ||
expect($elem.text()).to.equal($src.text()); | ||
$src.text('rofl'); | ||
expect($elem.text()).to.not.equal($src.text()); | ||
}); | ||
expect(elem.length).to.equal(3); | ||
expect(elem.parent().length).to.equal(1); | ||
expect(elem.parent()[0].type).to.equal('root'); | ||
expect(elem.text()).to.equal(src.text()); | ||
src.text('rofl'); | ||
expect(elem.text()).to.not.equal(src.text()); | ||
}); | ||
}); | ||
@@ -62,4 +53,4 @@ | ||
it('() : should return a cheerio-wrapped root object', function() { | ||
var $html = $.load("<div><span>foo</span><span>bar</span></div>"); | ||
$html.root().append("<div id = 'test'></div>"); | ||
var $html = $.load('<div><span>foo</span><span>bar</span></div>'); | ||
$html.root().append('<div id="test"></div>'); | ||
expect($html.html()).to.equal('<div><span>foo</span><span>bar</span></div><div id="test"></div>'); | ||
@@ -71,9 +62,12 @@ }); | ||
describe('.load', function() { | ||
it('(html) : should retain original root after creating a new node', function() { | ||
var $html = $.load('<body><ul id = "fruits"></ul></body>'); | ||
var $html = $.load('<body><ul id="fruits"></ul></body>'); | ||
expect($html('body')).to.have.length(1); | ||
var script = $html('<script>'); | ||
$html('<script>'); | ||
expect($html('body')).to.have.length(1); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
90324
2
25
1939
506