2023-10-03 11:14:36 +08:00
|
|
|
/*
|
|
|
|
Module dependencies
|
|
|
|
*/
|
|
|
|
|
|
|
|
var parse = require('./parse'),
|
|
|
|
isHtml = require('./utils').isHtml,
|
|
|
|
_ = {
|
|
|
|
extend: require('lodash.assignin'),
|
|
|
|
bind: require('lodash.bind'),
|
|
|
|
forEach: require('lodash.foreach'),
|
|
|
|
defaults: require('lodash.defaults')
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The API
|
|
|
|
*/
|
|
|
|
|
|
|
|
var api = [
|
|
|
|
require('./api/attributes'),
|
|
|
|
require('./api/traversing'),
|
|
|
|
require('./api/manipulation'),
|
|
|
|
require('./api/css'),
|
|
|
|
require('./api/forms')
|
|
|
|
];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Instance of cheerio
|
|
|
|
*/
|
|
|
|
|
|
|
|
var Cheerio = module.exports = function(selector, context, root, options) {
|
|
|
|
if (!(this instanceof Cheerio)) return new Cheerio(selector, context, root, options);
|
|
|
|
|
|
|
|
this.options = _.defaults(options || {}, this.options);
|
|
|
|
|
|
|
|
// $(), $(null), $(undefined), $(false)
|
|
|
|
if (!selector) return this;
|
|
|
|
|
|
|
|
if (root) {
|
|
|
|
if (typeof root === 'string') root = parse(root, this.options);
|
|
|
|
this._root = Cheerio.call(this, root);
|
|
|
|
}
|
|
|
|
|
|
|
|
// $($)
|
|
|
|
if (selector.cheerio) return selector;
|
|
|
|
|
|
|
|
// $(dom)
|
|
|
|
if (isNode(selector))
|
|
|
|
selector = [selector];
|
|
|
|
|
|
|
|
// $([dom])
|
|
|
|
if (Array.isArray(selector)) {
|
|
|
|
_.forEach(selector, _.bind(function(elem, idx) {
|
|
|
|
this[idx] = elem;
|
|
|
|
}, this));
|
|
|
|
this.length = selector.length;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// $(<html>)
|
|
|
|
if (typeof selector === 'string' && isHtml(selector)) {
|
|
|
|
return Cheerio.call(this, parse(selector, this.options).children);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have a context, maybe we have a root, from loading
|
|
|
|
if (!context) {
|
|
|
|
context = this._root;
|
|
|
|
} else if (typeof context === 'string') {
|
|
|
|
if (isHtml(context)) {
|
|
|
|
// $('li', '<ul>...</ul>')
|
|
|
|
context = parse(context, this.options);
|
|
|
|
context = Cheerio.call(this, context);
|
|
|
|
} else {
|
|
|
|
// $('li', 'ul')
|
|
|
|
selector = [context, selector].join(' ');
|
|
|
|
context = this._root;
|
|
|
|
}
|
|
|
|
// $('li', node), $('li', [nodes])
|
|
|
|
} else if (!context.cheerio) {
|
|
|
|
context = Cheerio.call(this, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we still don't have a context, return
|
|
|
|
if (!context) return this;
|
|
|
|
|
|
|
|
// #id, .class, tag
|
|
|
|
return context.find(selector);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mix in `static`
|
|
|
|
*/
|
|
|
|
|
|
|
|
_.extend(Cheerio, require('./static'));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set a signature of the object
|
|
|
|
*/
|
|
|
|
|
|
|
|
Cheerio.prototype.cheerio = '[cheerio object]';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cheerio default options
|
|
|
|
*/
|
|
|
|
|
|
|
|
Cheerio.prototype.options = {
|
|
|
|
withDomLvl1: true,
|
|
|
|
normalizeWhitespace: false,
|
|
|
|
xmlMode: false,
|
|
|
|
decodeEntities: true
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make cheerio an array-like object
|
|
|
|
*/
|
|
|
|
|
|
|
|
Cheerio.prototype.length = 0;
|
|
|
|
Cheerio.prototype.splice = Array.prototype.splice;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make a cheerio object
|
|
|
|
*
|
|
|
|
* @api private
|
|
|
|
*/
|
|
|
|
|
|
|
|
Cheerio.prototype._make = function(dom, context) {
|
|
|
|
var cheerio = new this.constructor(dom, context, this._root, this.options);
|
|
|
|
cheerio.prevObject = this;
|
|
|
|
return cheerio;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Turn a cheerio object into an array
|
|
|
|
*/
|
|
|
|
|
|
|
|
Cheerio.prototype.toArray = function() {
|
|
|
|
return this.get();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Plug in the API
|
|
|
|
*/
|
|
|
|
api.forEach(function(mod) {
|
|
|
|
_.extend(Cheerio.prototype, mod);
|
|
|
|
});
|
|
|
|
|
|
|
|
var isNode = function(obj) {
|
|
|
|
return obj.name || obj.type === 'text' || obj.type === 'comment';
|
|
|
|
};
|