UNPKG

chowdown

Version:

A JavaScript library that allows for the quick transformation of DOM documents into useful formats.

222 lines (195 loc) 8.58 kB
"use strict"; function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } 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 Promise = require('bluebird'); var _require = require('lodash'), assignIn = _require.assignIn, castArray = _require.castArray, identity = _require.identity, flow = _require.flow, extendWith = _require.extendWith, first = _require.first, isPlainObject = _require.isPlainObject, isFunction = _require.isFunction; /** * The ultimate class representing a query. * * When executed, this query will find attempt to find a value inside a given * document and return a promise resolving to it. * * @class Query */ var Query = /*#__PURE__*/ function () { /** * Constructs an query given a document selector and an object * containing additional configuration options. * * @param {string} selector A selector for this query's value in a document. * @param {object} [options] An object containing additional configuration options. * @param {any} [options.default] The default valuye to return if no value is found. * @param {boolean} [options.throwOnMissing=false] Whether or not to throw an error if no value is found. * @param {function[]} [options.format=[]] The functions used to format the value. */ function Query(selector) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, Query); options.selector = selector; this.configure(options); } /** * Configures this query given an object of configuration options. * * By default, throwOnMissing will be set to false and no format functions will * be set. * * @param {options} options The object of configuration options. * @param {string} options.selector A selector for this query's value in a document. * @param {any} [options.default] The default valuye to return if no value is found. * @param {boolean} [options.throwOnMissing=false] Whether or not to throw an error if no value is found. * @param {function[]} [options.format=[]] The functions used to format the value. */ _createClass(Query, [{ key: "configure", value: function configure(options) { this.options = assignIn(this.options, options); this.options.format = castArray(this.options.format || []); if (this.options.throwOnMissing === undefined) this.options.throwOnMissing = false; } /** * Retrieves a raw value from the document using the query's selector. * * @param {Document} document The document to retrieve the value from. * @return {any} The retrieved value. */ }, { key: "find", value: function find(document) { return document.value(this.options.selector); } /** * Determines if the query's default value should be used instead * of the value that was retrieved from the document. * * If no value was retrieved and the throwOnMissing * options is set to true, an error will be thrown. * * @param {any} value The value retreived from the document. * @param {Document} document The document the value was retrieved from. * @return {any} The query's default value or the value retrieved from the document. */ }, { key: "default", value: function _default(value, document) { if (value !== undefined) return value; if (this.options.throwOnMissing) throw new Error(); return this.options["default"]; } /** * "Builds" the retrieved value such that it is ready for formatting. * * @param {any} value The query's value retrieved from the document. * @param {Document} document The document the value was retrieved from. * @return {any} The built value. */ }, { key: "build", value: function build(value, document) { return value; } /** * Formats the built value by feeding it through the query's format functions. * * @param {any} value The query's value. * @param {Document} document The document the value was retrieved from. * @return {any} The formatted value. */ }, { key: "format", value: function format(value, document) { return flow(this.options.format)(value); } /** * Executes this query on the given document. * * @param {Document} The document to execute this query on. * @return {any} A promise that resolves to the value of this query. */ }, { key: "on", value: function on(document) { var _this = this; return Promise.resolve(document).then(function (document) { return _this.find(document); }).then(function (value) { return _this["default"](value, document); }).then(function (value) { return _this.build(value, document); }).then(function (value) { return _this.format(value, document); }); } }]); return Query; }(); module.exports = Query; /** * An object that maps query subclass names to their respective classes. * * @type {object} */ var children = { raw: require('./raw'), string: require('./string'), number: require('./number'), object: require('./object'), collection: require('./collection'), context: require('./context'), callback: require('./callback'), follow: require('./follow'), uri: require('./uri'), regex: require('./regex'), paginate: require('./paginate') }; /** * A function that when passed a "selector", will determine what * type of query to create and create it. * * If an existing Query is passed, then it will be returned. * * Accepts a default factory function (create) that will be called * if no matching type is found. * * @param {any} selector The selector for create a query for. * @param {function} create A default factory function. * @return {Query} The constructed query. */ Query.factory = function (selector) { var create = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Query.factory.string; if (isPlainObject(selector)) create = Query.factory.object; if (isFunction(selector)) create = Query.factory.callback; return create(selector); }; /** * Creates a method on the factory function for each query subclass. * * Each method takes an arbitrary number of arguments that are * passed through to the respective query constructor. * * If the first argument is already an Query, then it's * is returned and the consructor is not exectuted. */ extendWith(Query.factory, children, function (_, type) { return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (first(args) instanceof Query) return first(args); return _construct(type, args); }; });