chowdown
Version:
A JavaScript library that allows for the quick transformation of DOM documents into useful formats.
211 lines (171 loc) • 7.5 kB
JavaScript
;
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var _require = require('lodash'),
capitalize = _require.capitalize,
identity = _require.identity,
castArray = _require.castArray,
assignIn = _require.assignIn;
/**
* An abstract class representing a document.
* Can be queried to retrieve values, links and child documents.
*
* @class Document
* @abstract
*/
var Document =
/*#__PURE__*/
function () {
/**
* Builds a document instance given the type of document (i.e dom), the
* body of the whole doocument and a root allowing queries to be relative.
*
* @param {string} type The type of the document e.g 'dom' or 'json'.
* @param {any} document The raw document object.
* @param {any} [root] The root of the document.
*/
function Document(type, document, root) {
_classCallCheck(this, Document);
this.options = {};
this.options.type = type;
this.options.document = this.loadDocument(document);
this.options.root = this.loadRoot(root);
}
/**
* Creates a child document of the same type given a new root.
*
* @param {any} root The root of the new child document.
* @return {Document} The new child document.
*/
_createClass(Document, [{
key: "create",
value: function create(root) {
return Document.factory[this.options.type](this.options.document, root);
}
/**
* Given a function, this method attempts to call it
* with relevant parameters determined by the concrete type
* and returns the result.
*
* @param {function} fn The raw document function to call.
* @return {any} The result of the raw document function.
*/
}, {
key: "raw",
value: function raw(fn) {
return this.queryRaw(fn);
}
/**
* Given a selector, it attempts to resolve an array of child documents.
*
* @param {string} selector The selector for to the children.
* @return {Document[]} An array of child documents.
*/
}, {
key: "children",
value: function children(selector) {
var _this = this;
var children = this.queryChildren(this.formatSelector(selector));
if (children === undefined) return undefined;
return children.map(function (child) {
return _this.create(child);
});
}
/**
* Given a selector, this method attempts to find a leaf value in the document.
*
* @param {string} selector The selector for the value.
* @return {any} The value of the resolved selector.
*/
}, {
key: "value",
value: function value(selector) {
return this.queryValue(this.formatSelector(selector));
}
/**
* Given a selector, this method attempts to resolve a URI to another document.
*
* @param {string} selector The selector for the URI.
* @return {any} The resolved URI.
*/
}, {
key: "uri",
value: function uri(selector) {
return this.queryUri(this.formatSelector(selector));
}
/**
* An abstract method that handles the querying of values within the document.
*
* @param {string} selector The selector for the value.
* @return {any} The value rettrieved.
* @abstract
*/
}, {
key: "query",
value: function query(selector) {
throw new Error('the query method must be implemented by the subclass');
}
}]);
return Document;
}();
module.exports = Document;
/**
* Set the child load methods to the identity function by default.
*/
for (var _i = 0, _arr = ['root', 'document']; _i < _arr.length; _i++) {
var suffix = _arr[_i];
Document.prototype['load' + capitalize(suffix)] = identity;
}
/**
* Set the child format methods to the identity function by default.
*/
for (var _i2 = 0, _arr2 = ['selector']; _i2 < _arr2.length; _i2++) {
var _suffix = _arr2[_i2];
Document.prototype['format' + capitalize(_suffix)] = identity;
}
/**
* Set the child query methods to call the general query method by default.
*/
for (var _i3 = 0, _arr3 = ['uri', 'value', 'children']; _i3 < _arr3.length; _i3++) {
var _suffix2 = _arr3[_i3];
Document.prototype['query' + capitalize(_suffix2)] = function (selector) {
return this.query(selector);
};
}
/**
* Holds a list of factory methods to create different document types.
*
* @type {object}
*/
Document.factory = {};
/**
* Creates and adds a a factory method for a new subtype of document.
*
* @param {string} name The name of the subtype.
* @param {object} methods The methods the class will have.
*/
function add(name, methods) {
// Create a container class that extends Document for our methods.
var ConcreteDocument =
/*#__PURE__*/
function (_Document) {
_inherits(ConcreteDocument, _Document);
function ConcreteDocument(document, root) {
_classCallCheck(this, ConcreteDocument);
return _possibleConstructorReturn(this, _getPrototypeOf(ConcreteDocument).call(this, name, document, root));
}
return ConcreteDocument;
}(Document); // Assign the methods to the new classes prototype.
assignIn(ConcreteDocument.prototype, methods); // Add a factory method for the new type.
Document.factory[name] = function (document, root) {
return new ConcreteDocument(document, root);
};
} // Add the DOM document type;
add('dom', require('./dom'));