/** * Module dependencies */ var select = require('CSSselect'), parse = require('./parse'), render = require('dom-serializer'), _ = require('lodash'); /** * $.load(str) */ var load = exports.load = function(content, options) { var Cheerio = require('./cheerio'); options = _.defaults(options || {}, Cheerio.prototype.options); var root = parse(content, options); var initialize = function(selector, context, r, opts) { opts = _.defaults(opts || {}, options); return new Cheerio(selector, context, r || root, opts); }; // Add in the static methods initialize.__proto__ = exports; // Add in the root initialize._root = root; // store options initialize._options = options; return initialize; }; /** * $.html([selector | dom]) */ var html = exports.html = function(dom, options) { var Cheerio = require('./cheerio'); // be flexible about parameters, sometimes we call html(), // with options as only parameter // check dom argument for dom element specific properties // assume there is no 'length' or 'type' properties in the options object if (Object.prototype.toString.call(dom) === '[object Object]' && !options && !('length' in dom) && !('type' in dom)) { options = dom; dom = undefined; } // sometimes $.html() used without preloading html // so fallback non existing options to the default ones options = _.defaults(options || {}, this._options, Cheerio.prototype.options); if (dom) { dom = (typeof dom === 'string') ? select(dom, this._root, options) : dom; return render(dom, options); } else if (this._root && this._root.children) { return render(this._root.children, options); } else { return ''; } }; /** * $.xml([selector | dom]) */ var xml = exports.xml = function(dom) { if (dom) { dom = (typeof dom === 'string') ? select(dom, this._root, this.options) : dom; return render(dom, { xmlMode: true }); } else if (this._root && this._root.children) { return render(this._root.children, { xmlMode: true }); } else { return ''; } }; /** * $.text(dom) */ var text = exports.text = function(elems) { if (!elems) return ''; var ret = '', len = elems.length, elem; for (var i = 0; i < len; i ++) { elem = elems[i]; if (elem.type === 'text') ret += elem.data; else if (elem.children && elem.type !== 'comment') { ret += text(elem.children); } } return ret; }; /** * $.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 compatibility with jQuery. */ var parseHTML = exports.parseHTML = function(data, context, keepScripts) { var parsed; if (!data || typeof data !== 'string') { return null; } if (typeof context === 'boolean') { keepScripts = context; } parsed = this.load(data); if (!keepScripts) { parsed('script').remove(); } return parsed.root()[0].children; }; /** * $.root() */ var root = exports.root = function() { return this(this._root); }; /** * $.contains() */ var contains = exports.contains = function(container, contained) { // According to the jQuery API, an element does not "contain" itself if (contained === container) { return false; } // Step up the descendants, stopping when the root element is reached // (signaled by `.parent` returning a reference to the same object) while (contained && contained !== contained.parent) { contained = contained.parent; if (contained === container) { return true; } } return false; };