/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {module.exports = global["pdfMake"] = __webpack_require__(1); /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer) {/* jslint node: true */ /* jslint browser: true */ /* global BlobBuilder */ 'use strict'; var PdfPrinter = __webpack_require__(2); var saveAs = __webpack_require__(3); var defaultClientFonts = { Roboto: { normal: 'Roboto-Regular.ttf', bold: 'Roboto-Medium.ttf', italics: 'Roboto-Italic.ttf', bolditalics: 'Roboto-Italic.ttf' } }; function Document(docDefinition, fonts, vfs) { this.docDefinition = docDefinition; this.fonts = fonts || defaultClientFonts; this.vfs = vfs; } Document.prototype._createDoc = function(options, callback) { var printer = new PdfPrinter(this.fonts); printer.fs.bindFS(this.vfs); var doc = printer.createPdfKitDocument(this.docDefinition, options); var chunks = []; var result; doc.on('data', function(chunk) { chunks.push(chunk); }); doc.on('end', function() { result = Buffer.concat(chunks); callback(result, doc._pdfMakePages); }); doc.end(); }; Document.prototype._getPages = function(options, cb){ if (!cb) throw 'getBuffer is an async method and needs a callback argument'; this._createDoc(options, function(ignoreBuffer, pages){ cb(pages); }); }; Document.prototype.open = function(message) { // we have to open the window immediately and store the reference // otherwise popup blockers will stop us var win = window.open('', '_blank'); try { this.getDataUrl(function(result) { win.location.href = result; }); } catch(e) { win.close(); throw e; } }; Document.prototype.print = function() { this.getDataUrl(function(dataUrl) { var iFrame = document.createElement('iframe'); iFrame.style.position = 'absolute'; iFrame.style.left = '-99999px'; iFrame.src = dataUrl; iFrame.onload = function() { function removeIFrame(){ document.body.removeChild(iFrame); document.removeEventListener('click', removeIFrame); } document.addEventListener('click', removeIFrame, false); }; document.body.appendChild(iFrame); }, { autoPrint: true }); }; Document.prototype.download = function(defaultFileName, cb) { if(typeof defaultFileName === "function") { cb = defaultFileName; defaultFileName = null; } defaultFileName = defaultFileName || 'file.pdf'; this.getBuffer(function(result) { saveAs(new Blob([result], {type: 'application/pdf'}), defaultFileName); if (typeof cb === "function") { cb(); } }); }; Document.prototype.getBase64 = function(cb, options) { if (!cb) throw 'getBase64 is an async method and needs a callback argument'; this._createDoc(options, function(buffer) { cb(buffer.toString('base64')); }); }; Document.prototype.getDataUrl = function(cb, options) { if (!cb) throw 'getDataUrl is an async method and needs a callback argument'; this._createDoc(options, function(buffer) { cb('data:application/pdf;base64,' + buffer.toString('base64')); }); }; Document.prototype.getBuffer = function(cb, options) { if (!cb) throw 'getBuffer is an async method and needs a callback argument'; this._createDoc(options, function(buffer){ cb(buffer); }); }; module.exports = { createPdf: function(docDefinition) { return new Document(docDefinition, window.pdfMake.fonts, window.pdfMake.vfs); } }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4).Buffer)) /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { /* jslint node: true */ /* global window */ 'use strict'; var _ = __webpack_require__(11); var FontProvider = __webpack_require__(5); var LayoutBuilder = __webpack_require__(6); var PdfKit = __webpack_require__(28); var PDFReference = __webpack_require__(12); var sizes = __webpack_require__(7); var ImageMeasure = __webpack_require__(8); var textDecorator = __webpack_require__(9); var FontProvider = __webpack_require__(5); //////////////////////////////////////// // PdfPrinter /** * @class Creates an instance of a PdfPrinter which turns document definition into a pdf * * @param {Object} fontDescriptors font definition dictionary * * @example * var fontDescriptors = { * Roboto: { * normal: 'fonts/Roboto-Regular.ttf', * bold: 'fonts/Roboto-Medium.ttf', * italics: 'fonts/Roboto-Italic.ttf', * bolditalics: 'fonts/Roboto-Italic.ttf' * } * }; * * var printer = new PdfPrinter(fontDescriptors); */ function PdfPrinter(fontDescriptors) { this.fontDescriptors = fontDescriptors; } /** * Executes layout engine for the specified document and renders it into a pdfkit document * ready to be saved. * * @param {Object} docDefinition document definition * @param {Object} docDefinition.content an array describing the pdf structure (for more information take a look at the examples in the /examples folder) * @param {Object} [docDefinition.defaultStyle] default (implicit) style definition * @param {Object} [docDefinition.styles] dictionary defining all styles which can be used in the document * @param {Object} [docDefinition.pageSize] page size (pdfkit units, A4 dimensions by default) * @param {Number} docDefinition.pageSize.width width * @param {Number} docDefinition.pageSize.height height * @param {Object} [docDefinition.pageMargins] page margins (pdfkit units) * * @example * * var docDefinition = { * content: [ * 'First paragraph', * 'Second paragraph, this time a little bit longer', * { text: 'Third paragraph, slightly bigger font size', fontSize: 20 }, * { text: 'Another paragraph using a named style', style: 'header' }, * { text: ['playing with ', 'inlines' ] }, * { text: ['and ', { text: 'restyling ', bold: true }, 'them'] }, * ], * styles: { * header: { fontSize: 30, bold: true } * } * } * * var pdfDoc = printer.createPdfKitDocument(docDefinition); * * pdfDoc.pipe(fs.createWriteStream('sample.pdf')); * pdfDoc.end(); * * @return {Object} a pdfKit document object which can be saved or encode to data-url */ PdfPrinter.prototype.createPdfKitDocument = function(docDefinition, options) { options = options || {}; var pageSize = pageSize2widthAndHeight(docDefinition.pageSize || 'a4'); if(docDefinition.pageOrientation === 'landscape') { pageSize = { width: pageSize.height, height: pageSize.width}; } pageSize.orientation = docDefinition.pageOrientation === 'landscape' ? docDefinition.pageOrientation : 'portrait'; this.pdfKitDoc = new PdfKit({ size: [ pageSize.width, pageSize.height ], compress: false}); this.pdfKitDoc.info.Producer = 'pdfmake'; this.pdfKitDoc.info.Creator = 'pdfmake'; this.fontProvider = new FontProvider(this.fontDescriptors, this.pdfKitDoc); docDefinition.images = docDefinition.images || {}; var builder = new LayoutBuilder( pageSize, fixPageMargins(docDefinition.pageMargins || 40), new ImageMeasure(this.pdfKitDoc, docDefinition.images)); registerDefaultTableLayouts(builder); if (options.tableLayouts) { builder.registerTableLayouts(options.tableLayouts); } var pages = builder.layoutDocument(docDefinition.content, this.fontProvider, docDefinition.styles || {}, docDefinition.defaultStyle || { fontSize: 12, font: 'Roboto' }, docDefinition.background, docDefinition.header, docDefinition.footer, docDefinition.images, docDefinition.watermark, docDefinition.pageBreakBefore); renderPages(pages, this.fontProvider, this.pdfKitDoc); if(options.autoPrint){ var jsRef = this.pdfKitDoc.ref({ S: 'JavaScript', JS: new StringObject('this.print\\(true\\);') }); var namesRef = this.pdfKitDoc.ref({ Names: [new StringObject('EmbeddedJS'), new PDFReference(this.pdfKitDoc, jsRef.id)], }); jsRef.end(); namesRef.end(); this.pdfKitDoc._root.data.Names = { JavaScript: new PDFReference(this.pdfKitDoc, namesRef.id) }; } return this.pdfKitDoc; }; function fixPageMargins(margin) { if (!margin) return null; if (typeof margin === 'number' || margin instanceof Number) { margin = { left: margin, right: margin, top: margin, bottom: margin }; } else if (margin instanceof Array) { if (margin.length === 2) { margin = { left: margin[0], top: margin[1], right: margin[0], bottom: margin[1] }; } else if (margin.length === 4) { margin = { left: margin[0], top: margin[1], right: margin[2], bottom: margin[3] }; } else throw 'Invalid pageMargins definition'; } return margin; } function registerDefaultTableLayouts(layoutBuilder) { layoutBuilder.registerTableLayouts({ noBorders: { hLineWidth: function(i) { return 0; }, vLineWidth: function(i) { return 0; }, paddingLeft: function(i) { return i && 4 || 0; }, paddingRight: function(i, node) { return (i < node.table.widths.length - 1) ? 4 : 0; }, }, headerLineOnly: { hLineWidth: function(i, node) { if (i === 0 || i === node.table.body.length) return 0; return (i === node.table.headerRows) ? 2 : 0; }, vLineWidth: function(i) { return 0; }, paddingLeft: function(i) { return i === 0 ? 0 : 8; }, paddingRight: function(i, node) { return (i === node.table.widths.length - 1) ? 0 : 8; } }, lightHorizontalLines: { hLineWidth: function(i, node) { if (i === 0 || i === node.table.body.length) return 0; return (i === node.table.headerRows) ? 2 : 1; }, vLineWidth: function(i) { return 0; }, hLineColor: function(i) { return i === 1 ? 'black' : '#aaa'; }, paddingLeft: function(i) { return i === 0 ? 0 : 8; }, paddingRight: function(i, node) { return (i === node.table.widths.length - 1) ? 0 : 8; } } }); } var defaultLayout = { hLineWidth: function(i, node) { return 1; }, //return node.table.headerRows && i === node.table.headerRows && 3 || 0; }, vLineWidth: function(i, node) { return 1; }, hLineColor: function(i, node) { return 'black'; }, vLineColor: function(i, node) { return 'black'; }, paddingLeft: function(i, node) { return 4; }, //i && 4 || 0; }, paddingRight: function(i, node) { return 4; }, //(i < node.table.widths.length - 1) ? 4 : 0; }, paddingTop: function(i, node) { return 2; }, paddingBottom: function(i, node) { return 2; } }; function pageSize2widthAndHeight(pageSize) { if (typeof pageSize == 'string' || pageSize instanceof String) { var size = sizes[pageSize.toUpperCase()]; if (!size) throw ('Page size ' + pageSize + ' not recognized'); return { width: size[0], height: size[1] }; } return pageSize; } function StringObject(str){ this.isString = true; this.toString = function(){ return str; }; } function updatePageOrientationInOptions(currentPage, pdfKitDoc) { var previousPageOrientation = pdfKitDoc.options.size[0] > pdfKitDoc.options.size[1] ? 'landscape' : 'portrait'; if(currentPage.pageSize.orientation !== previousPageOrientation) { var width = pdfKitDoc.options.size[0]; var height = pdfKitDoc.options.size[1]; pdfKitDoc.options.size = [height, width]; } } function renderPages(pages, fontProvider, pdfKitDoc) { pdfKitDoc._pdfMakePages = pages; for (var i = 0; i < pages.length; i++) { if (i > 0) { updatePageOrientationInOptions(pages[i], pdfKitDoc); pdfKitDoc.addPage(pdfKitDoc.options); } var page = pages[i]; for(var ii = 0, il = page.items.length; ii < il; ii++) { var item = page.items[ii]; switch(item.type) { case 'vector': renderVector(item.item, pdfKitDoc); break; case 'line': renderLine(item.item, item.item.x, item.item.y, pdfKitDoc); break; case 'image': renderImage(item.item, item.item.x, item.item.y, pdfKitDoc); break; } } if(page.watermark){ renderWatermark(page, pdfKitDoc); } fontProvider.setFontRefsToPdfDoc(); } } function renderLine(line, x, y, pdfKitDoc) { x = x || 0; y = y || 0; var ascenderHeight = line.getAscenderHeight(); textDecorator.drawBackground(line, x, y, pdfKitDoc); //TODO: line.optimizeInlines(); for(var i = 0, l = line.inlines.length; i < l; i++) { var inline = line.inlines[i]; pdfKitDoc.fill(inline.color || 'black'); pdfKitDoc.save(); pdfKitDoc.transform(1, 0, 0, -1, 0, pdfKitDoc.page.height); var encoded = inline.font.encode(inline.text); pdfKitDoc.addContent('BT'); pdfKitDoc.addContent('' + (x + inline.x) + ' ' + (pdfKitDoc.page.height - y - ascenderHeight) + ' Td'); pdfKitDoc.addContent('/' + encoded.fontId + ' ' + inline.fontSize + ' Tf'); pdfKitDoc.addContent('<' + encoded.encodedText + '> Tj'); pdfKitDoc.addContent('ET'); pdfKitDoc.restore(); } textDecorator.drawDecorations(line, x, y, pdfKitDoc); } function renderWatermark(page, pdfKitDoc){ var watermark = page.watermark; pdfKitDoc.fill('black'); pdfKitDoc.opacity(0.1); pdfKitDoc.save(); pdfKitDoc.transform(1, 0, 0, -1, 0, pdfKitDoc.page.height); var angle = Math.atan2(pdfKitDoc.page.height, pdfKitDoc.page.width) * 180/Math.PI; pdfKitDoc.rotate(angle, {origin: [pdfKitDoc.page.width/2, pdfKitDoc.page.height/2]}); var encoded = watermark.font.encode(watermark.text); pdfKitDoc.addContent('BT'); pdfKitDoc.addContent('' + (pdfKitDoc.page.width/2 - watermark.size.size.width/2) + ' ' + (pdfKitDoc.page.height/2 - watermark.size.size.height/4) + ' Td'); // http://stackoverflow.com/a/32658671 //pdfKitDoc.addContent('/' + encoded.fontId + ' ' + watermark.size.fontSize + ' Tf'); //pdfKitDoc.addContent('<' + encoded.encodedText + '> Tj'); pdfKitDoc.addContent('/ ' + watermark.size.fontSize + ' Tf'); pdfKitDoc.addContent('(' + watermark.text + ') Tj'); pdfKitDoc.addContent('ET'); pdfKitDoc.restore(); } function renderVector(vector, pdfDoc) { //TODO: pdf optimization (there's no need to write all properties everytime) pdfDoc.lineWidth(vector.lineWidth || 1); if (vector.dash) { pdfDoc.dash(vector.dash.length, { space: vector.dash.space || vector.dash.length }); } else { pdfDoc.undash(); } pdfDoc.fillOpacity(vector.fillOpacity || 1); pdfDoc.strokeOpacity(vector.strokeOpacity || 1); pdfDoc.lineJoin(vector.lineJoin || 'miter'); //TODO: clipping switch(vector.type) { case 'ellipse': pdfDoc.ellipse(vector.x, vector.y, vector.r1, vector.r2); break; case 'rect': if (vector.r) { pdfDoc.roundedRect(vector.x, vector.y, vector.w, vector.h, vector.r); } else { pdfDoc.rect(vector.x, vector.y, vector.w, vector.h); } break; case 'line': pdfDoc.moveTo(vector.x1, vector.y1); pdfDoc.lineTo(vector.x2, vector.y2); break; case 'polyline': if (vector.points.length === 0) break; pdfDoc.moveTo(vector.points[0].x, vector.points[0].y); for(var i = 1, l = vector.points.length; i < l; i++) { pdfDoc.lineTo(vector.points[i].x, vector.points[i].y); } if (vector.points.length > 1) { var p1 = vector.points[0]; var pn = vector.points[vector.points.length - 1]; if (vector.closePath || p1.x === pn.x && p1.y === pn.y) { pdfDoc.closePath(); } } break; } if (vector.color && vector.lineColor) { pdfDoc.fillAndStroke(vector.color, vector.lineColor); } else if (vector.color) { pdfDoc.fill(vector.color); } else { pdfDoc.stroke(vector.lineColor || 'black'); } } function renderImage(image, x, y, pdfKitDoc) { pdfKitDoc.image(image.image, image.x, image.y, { width: image._width, height: image._height }); } module.exports = PdfPrinter; /* temporary browser extension */ PdfPrinter.prototype.fs = __webpack_require__(10); /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module) {/* FileSaver.js * A saveAs() FileSaver implementation. * 2014-08-29 * * By Eli Grey, http://eligrey.com * License: X11/MIT * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md */ /*global self */ /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ var saveAs = saveAs // IE 10+ (native saveAs) || (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator)) // Everyone else || (function(view) { "use strict"; // IE <10 is explicitly unsupported if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { return; } var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet , get_URL = function() { return view.URL || view.webkitURL || view; } , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") , can_use_save_link = "download" in save_link , click = function(node) { var event = doc.createEvent("MouseEvents"); event.initMouseEvent( "click", true, false, view, 0, 0, 0, 0, 0 , false, false, false, false, 0, null ); node.dispatchEvent(event); } , webkit_req_fs = view.webkitRequestFileSystem , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem , throw_outside = function(ex) { (view.setImmediate || view.setTimeout)(function() { throw ex; }, 0); } , force_saveable_type = "application/octet-stream" , fs_min_size = 0 // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 for // the reasoning behind the timeout and revocation flow , arbitrary_revoke_timeout = 10 , revoke = function(file) { var revoker = function() { if (typeof file === "string") { // file is an object URL get_URL().revokeObjectURL(file); } else { // file is a File file.remove(); } }; if (view.chrome) { revoker(); } else { setTimeout(revoker, arbitrary_revoke_timeout); } } , dispatch = function(filesaver, event_types, event) { event_types = [].concat(event_types); var i = event_types.length; while (i--) { var listener = filesaver["on" + event_types[i]]; if (typeof listener === "function") { try { listener.call(filesaver, event || filesaver); } catch (ex) { throw_outside(ex); } } } } , FileSaver = function(blob, name) { // First try a.download, then web filesystem, then object URLs var filesaver = this , type = blob.type , blob_changed = false , object_url , target_view , dispatch_all = function() { dispatch(filesaver, "writestart progress write writeend".split(" ")); } // on any filesys errors revert to saving with object URLs , fs_error = function() { // don't create more object URLs than needed if (blob_changed || !object_url) { object_url = get_URL().createObjectURL(blob); } if (target_view) { target_view.location.href = object_url; } else { var new_tab = view.open(object_url, "_blank"); if (new_tab == undefined && typeof safari !== "undefined") { //Apple do not allow window.open, see http://bit.ly/1kZffRI view.location.href = object_url } } filesaver.readyState = filesaver.DONE; dispatch_all(); revoke(object_url); } , abortable = function(func) { return function() { if (filesaver.readyState !== filesaver.DONE) { return func.apply(this, arguments); } }; } , create_if_not_found = {create: true, exclusive: false} , slice ; filesaver.readyState = filesaver.INIT; if (!name) { name = "download"; } if (can_use_save_link) { object_url = get_URL().createObjectURL(blob); save_link.href = object_url; save_link.download = name; click(save_link); filesaver.readyState = filesaver.DONE; dispatch_all(); revoke(object_url); return; } // Object and web filesystem URLs have a problem saving in Google Chrome when // viewed in a tab, so I force save with application/octet-stream // http://code.google.com/p/chromium/issues/detail?id=91158 // Update: Google errantly closed 91158, I submitted it again: // https://code.google.com/p/chromium/issues/detail?id=389642 if (view.chrome && type && type !== force_saveable_type) { slice = blob.slice || blob.webkitSlice; blob = slice.call(blob, 0, blob.size, force_saveable_type); blob_changed = true; } // Since I can't be sure that the guessed media type will trigger a download // in WebKit, I append .download to the filename. // https://bugs.webkit.org/show_bug.cgi?id=65440 if (webkit_req_fs && name !== "download") { name += ".download"; } if (type === force_saveable_type || webkit_req_fs) { target_view = view; } if (!req_fs) { fs_error(); return; } fs_min_size += blob.size; req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { var save = function() { dir.getFile(name, create_if_not_found, abortable(function(file) { file.createWriter(abortable(function(writer) { writer.onwriteend = function(event) { target_view.location.href = file.toURL(); filesaver.readyState = filesaver.DONE; dispatch(filesaver, "writeend", event); revoke(file); }; writer.onerror = function() { var error = writer.error; if (error.code !== error.ABORT_ERR) { fs_error(); } }; "writestart progress write abort".split(" ").forEach(function(event) { writer["on" + event] = filesaver["on" + event]; }); writer.write(blob); filesaver.abort = function() { writer.abort(); filesaver.readyState = filesaver.DONE; }; filesaver.readyState = filesaver.WRITING; }), fs_error); }), fs_error); }; dir.getFile(name, {create: false}, abortable(function(file) { // delete file if it already exists file.remove(); save(); }), abortable(function(ex) { if (ex.code === ex.NOT_FOUND_ERR) { save(); } else { fs_error(); } })); }), fs_error); }), fs_error); } , FS_proto = FileSaver.prototype , saveAs = function(blob, name) { return new FileSaver(blob, name); } ; FS_proto.abort = function() { var filesaver = this; filesaver.readyState = filesaver.DONE; dispatch(filesaver, "abort"); }; FS_proto.readyState = FS_proto.INIT = 0; FS_proto.WRITING = 1; FS_proto.DONE = 2; FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; return saveAs; }( typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content )); // `self` is undefined in Firefox for Android content script context // while `this` is nsIContentFrameMessageManager // with an attribute `content` that corresponds to the window if (typeof module !== "undefined" && module !== null) { module.exports = saveAs; } else if (("function" !== "undefined" && __webpack_require__(13) !== null) && (__webpack_require__(14) != null)) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() { return saveAs; }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15)(module))) /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer) {/*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ var base64 = __webpack_require__(31) var ieee754 = __webpack_require__(29) var isArray = __webpack_require__(30) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 // not used by this implementation var kMaxLength = 0x3fffffff var rootParent = {} /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Note: * * - Implementation must support adding new properties to `Uint8Array` instances. * Firefox 4-29 lacked support, fixed in Firefox 30+. * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will * get the Object implementation, which is slower but will work correctly. */ Buffer.TYPED_ARRAY_SUPPORT = (function () { try { var buf = new ArrayBuffer(0) var arr = new Uint8Array(buf) arr.foo = function () { return 42 } return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } })() /** * Class: Buffer * ============= * * The Buffer constructor returns instances of `Uint8Array` that are augmented * with function properties for all the node `Buffer` API functions. We use * `Uint8Array` so that square bracket notation works as expected -- it returns * a single octet. * * By augmenting the instances, we can avoid modifying the `Uint8Array` * prototype. */ function Buffer (arg) { if (!(this instanceof Buffer)) { // Avoid going through an ArgumentsAdaptorTrampoline in the common case. if (arguments.length > 1) return new Buffer(arg, arguments[1]) return new Buffer(arg) } this.length = 0 this.parent = undefined // Common case. if (typeof arg === 'number') { return fromNumber(this, arg) } // Slightly less common case. if (typeof arg === 'string') { return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') } // Unusual. return fromObject(this, arg) } function fromNumber (that, length) { that = allocate(that, length < 0 ? 0 : checked(length) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < length; i++) { that[i] = 0 } } return that } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' // Assumption: byteLength() return value is always < kMaxLength. var length = byteLength(string, encoding) | 0 that = allocate(that, length) that.write(string, encoding) return that } function fromObject (that, object) { if (Buffer.isBuffer(object)) return fromBuffer(that, object) if (isArray(object)) return fromArray(that, object) if (object == null) { throw new TypeError('must start with number, buffer, array or string') } if (typeof ArrayBuffer !== 'undefined' && object.buffer instanceof ArrayBuffer) { return fromTypedArray(that, object) } if (object.length) return fromArrayLike(that, object) return fromJsonObject(that, object) } function fromBuffer (that, buffer) { var length = checked(buffer.length) | 0 that = allocate(that, length) buffer.copy(that, 0, 0, length) return that } function fromArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Duplicate of fromArray() to keep fromArray() monomorphic. function fromTypedArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) // Truncating the elements is probably not what people expect from typed // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior // of the old Buffer constructor. for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayLike (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. // Returns a zero-length buffer for inputs that don't conform to the spec. function fromJsonObject (that, object) { var array var length = 0 if (object.type === 'Buffer' && isArray(object.data)) { array = object.data length = checked(array.length) | 0 } that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function allocate (that, length) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = Buffer._augment(new Uint8Array(length)) } else { // Fallback: Return an object instance of the Buffer class that.length = length that._isBuffer = true } var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 if (fromPool) that.parent = rootParent return that } function checked (length) { // Note: cannot use `length < kMaxLength` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength.toString(16) + ' bytes') } return length | 0 } function SlowBuffer (subject, encoding) { if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) var buf = new Buffer(subject, encoding) delete buf.parent return buf } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length var i = 0 var len = Math.min(x, y) while (i < len) { if (a[i] !== b[i]) break ++i } if (i !== len) { x = a[i] y = b[i] } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'raw': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } } Buffer.concat = function concat (list, length) { if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') if (list.length === 0) { return new Buffer(0) } else if (list.length === 1) { return list[0] } var i if (length === undefined) { length = 0 for (i = 0; i < list.length; i++) { length += list[i].length } } var buf = new Buffer(length) var pos = 0 for (i = 0; i < list.length; i++) { var item = list[i] item.copy(buf, pos) pos += item.length } return buf } function byteLength (string, encoding) { if (typeof string !== 'string') string = String(string) if (string.length === 0) return 0 switch (encoding || 'utf8') { case 'ascii': case 'binary': case 'raw': return string.length case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return string.length * 2 case 'hex': return string.length >>> 1 case 'utf8': case 'utf-8': return utf8ToBytes(string).length case 'base64': return base64ToBytes(string).length default: return string.length } } Buffer.byteLength = byteLength // pre-set for values that may exist in the future Buffer.prototype.length = undefined Buffer.prototype.parent = undefined // toString(encoding, start=0, end=buffer.length) Buffer.prototype.toString = function toString (encoding, start, end) { var loweredCase = false start = start | 0 end = end === undefined || end === Infinity ? this.length : end | 0 if (!encoding) encoding = 'utf8' if (start < 0) start = 0 if (end > this.length) end = this.length if (end <= start) return '' while (true) { switch (encoding) { case 'hex': return hexSlice(this, start, end) case 'utf8': case 'utf-8': return utf8Slice(this, start, end) case 'ascii': return asciiSlice(this, start, end) case 'binary': return binarySlice(this, start, end) case 'base64': return base64Slice(this, start, end) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return utf16leSlice(this, start, end) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase() loweredCase = true } } } Buffer.prototype.equals = function equals (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return true return Buffer.compare(this, b) === 0 } Buffer.prototype.inspect = function inspect () { var str = '' var max = exports.INSPECT_MAX_BYTES if (this.length > 0) { str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') if (this.length > max) str += ' ... ' } return '' } Buffer.prototype.compare = function compare (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return 0 return Buffer.compare(this, b) } Buffer.prototype.indexOf = function indexOf (val, byteOffset) { if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff else if (byteOffset < -0x80000000) byteOffset = -0x80000000 byteOffset >>= 0 if (this.length === 0) return -1 if (byteOffset >= this.length) return -1 // Negative offsets start from the end of the buffer if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) if (typeof val === 'string') { if (val.length === 0) return -1 // special case: looking for empty string always fails return String.prototype.indexOf.call(this, val, byteOffset) } if (Buffer.isBuffer(val)) { return arrayIndexOf(this, val, byteOffset) } if (typeof val === 'number') { if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { return Uint8Array.prototype.indexOf.call(this, val, byteOffset) } return arrayIndexOf(this, [ val ], byteOffset) } function arrayIndexOf (arr, val, byteOffset) { var foundIndex = -1 for (var i = 0; byteOffset + i < arr.length; i++) { if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { if (foundIndex === -1) foundIndex = i if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex } else { foundIndex = -1 } } return -1 } throw new TypeError('val must be string, number or Buffer') } // `get` will be removed in Node 0.13+ Buffer.prototype.get = function get (offset) { console.log('.get() is deprecated. Access using array indexes instead.') return this.readUInt8(offset) } // `set` will be removed in Node 0.13+ Buffer.prototype.set = function set (v, offset) { console.log('.set() is deprecated. Access using array indexes instead.') return this.writeUInt8(v, offset) } function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 var remaining = buf.length - offset if (!length) { length = remaining } else { length = Number(length) if (length > remaining) { length = remaining } } // must be an even number of digits var strLen = string.length if (strLen % 2 !== 0) throw new Error('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var parsed = parseInt(string.substr(i * 2, 2), 16) if (isNaN(parsed)) throw new Error('Invalid hex string') buf[offset + i] = parsed } return i } function utf8Write (buf, string, offset, length) { return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) } function asciiWrite (buf, string, offset, length) { return blitBuffer(asciiToBytes(string), buf, offset, length) } function binaryWrite (buf, string, offset, length) { return asciiWrite(buf, string, offset, length) } function base64Write (buf, string, offset, length) { return blitBuffer(base64ToBytes(string), buf, offset, length) } function ucs2Write (buf, string, offset, length) { return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { encoding = 'utf8' length = this.length offset = 0 // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { encoding = offset length = this.length offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { offset = offset | 0 if (isFinite(length)) { length = length | 0 if (encoding === undefined) encoding = 'utf8' } else { encoding = length length = undefined } // legacy write(string, encoding, offset, length) - remove in v0.13 } else { var swap = encoding encoding = offset offset = length | 0 length = swap } var remaining = this.length - offset if (length === undefined || length > remaining) length = remaining if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('attempt to write outside buffer bounds') } if (!encoding) encoding = 'utf8' var loweredCase = false for (;;) { switch (encoding) { case 'hex': return hexWrite(this, string, offset, length) case 'utf8': case 'utf-8': return utf8Write(this, string, offset, length) case 'ascii': return asciiWrite(this, string, offset, length) case 'binary': return binaryWrite(this, string, offset, length) case 'base64': // Warning: maxLength not taken into account in base64Write return base64Write(this, string, offset, length) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return ucs2Write(this, string, offset, length) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } } function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) } else { return base64.fromByteArray(buf.slice(start, end)) } } function utf8Slice (buf, start, end) { var res = '' var tmp = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { if (buf[i] <= 0x7F) { res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) tmp = '' } else { tmp += '%' + buf[i].toString(16) } } return res + decodeUtf8Char(tmp) } function asciiSlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { ret += String.fromCharCode(buf[i] & 0x7F) } return ret } function binarySlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { ret += String.fromCharCode(buf[i]) } return ret } function hexSlice (buf, start, end) { var len = buf.length if (!start || start < 0) start = 0 if (!end || end < 0 || end > len) end = len var out = '' for (var i = start; i < end; i++) { out += toHex(buf[i]) } return out } function utf16leSlice (buf, start, end) { var bytes = buf.slice(start, end) var res = '' for (var i = 0; i < bytes.length; i += 2) { res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) } return res } Buffer.prototype.slice = function slice (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { start += len if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len if (end < 0) end = 0 } else if (end > len) { end = len } if (end < start) end = start var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { newBuf = Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) for (var i = 0; i < sliceLen; i++) { newBuf[i] = this[i + start] } } if (newBuf.length) newBuf.parent = this.parent || this return newBuf } /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } return val } Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { checkOffset(offset, byteLength, this.length) } var val = this[offset + --byteLength] var mul = 1 while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul } return val } Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) } Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) } Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var i = byteLength var mul = 1 var val = this[offset + --i] while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset] | (this[offset + 1] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset + 1] | (this[offset] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) } Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) } Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } function checkInt (buf, value, offset, ext, max, min) { if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') if (value > max || value < min) throw new RangeError('value is out of bounds') if (offset + ext > buf.length) throw new RangeError('index out of range') } Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) var mul = 1 var i = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) var i = byteLength - 1 var mul = 1 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = value return offset + 1 } function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } } Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = value this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = value } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset + 3] = (value >>> 24) this[offset + 2] = (value >>> 16) this[offset + 1] = (value >>> 8) this[offset] = value } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = value } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = 0 var mul = 1 var sub = value < 0 ? 1 : 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = byteLength - 1 var mul = 1 var sub = value < 0 ? 1 : 0 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) if (value < 0) value = 0xff + value + 1 this[offset] = value return offset + 1 } Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = value this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = value } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = value this[offset + 1] = (value >>> 8) this[offset + 2] = (value >>> 16) this[offset + 3] = (value >>> 24) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (value < 0) value = 0xffffffff + value + 1 if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = value } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } function checkIEEE754 (buf, value, offset, ext, max, min) { if (value > max || value < min) throw new RangeError('value is out of bounds') if (offset + ext > buf.length) throw new RangeError('index out of range') if (offset < 0) throw new RangeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (!start) start = 0 if (!end && end !== 0) end = this.length if (targetStart >= target.length) targetStart = target.length if (!targetStart) targetStart = 0 if (end > 0 && end < start) end = start // Copy 0 bytes; we're done if (end === start) return 0 if (target.length === 0 || this.length === 0) return 0 // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length if (target.length - targetStart < end - start) { end = target.length - targetStart + start } var len = end - start if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < len; i++) { target[i + targetStart] = this[i + start] } } else { target._set(this.subarray(start, start + len), targetStart) } return len } // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length if (end < start) throw new RangeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') if (end < 0 || end > this.length) throw new RangeError('end out of bounds') var i if (typeof value === 'number') { for (i = start; i < end; i++) { this[i] = value } } else { var bytes = utf8ToBytes(value.toString()) var len = bytes.length for (i = start; i < end; i++) { this[i] = bytes[i % len] } } return this } /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. */ Buffer.prototype.toArrayBuffer = function toArrayBuffer () { if (typeof Uint8Array !== 'undefined') { if (Buffer.TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer } else { var buf = new Uint8Array(this.length) for (var i = 0, len = buf.length; i < len; i += 1) { buf[i] = this[i] } return buf.buffer } } else { throw new TypeError('Buffer.toArrayBuffer not supported in this browser') } } // HELPER FUNCTIONS // ================ var BP = Buffer.prototype /** * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ Buffer._augment = function _augment (arr) { arr.constructor = Buffer arr._isBuffer = true // save reference to original Uint8Array set method before overwriting arr._set = arr.set // deprecated, will be removed in node 0.13+ arr.get = BP.get arr.set = BP.set arr.write = BP.write arr.toString = BP.toString arr.toLocaleString = BP.toString arr.toJSON = BP.toJSON arr.equals = BP.equals arr.compare = BP.compare arr.indexOf = BP.indexOf arr.copy = BP.copy arr.slice = BP.slice arr.readUIntLE = BP.readUIntLE arr.readUIntBE = BP.readUIntBE arr.readUInt8 = BP.readUInt8 arr.readUInt16LE = BP.readUInt16LE arr.readUInt16BE = BP.readUInt16BE arr.readUInt32LE = BP.readUInt32LE arr.readUInt32BE = BP.readUInt32BE arr.readIntLE = BP.readIntLE arr.readIntBE = BP.readIntBE arr.readInt8 = BP.readInt8 arr.readInt16LE = BP.readInt16LE arr.readInt16BE = BP.readInt16BE arr.readInt32LE = BP.readInt32LE arr.readInt32BE = BP.readInt32BE arr.readFloatLE = BP.readFloatLE arr.readFloatBE = BP.readFloatBE arr.readDoubleLE = BP.readDoubleLE arr.readDoubleBE = BP.readDoubleBE arr.writeUInt8 = BP.writeUInt8 arr.writeUIntLE = BP.writeUIntLE arr.writeUIntBE = BP.writeUIntBE arr.writeUInt16LE = BP.writeUInt16LE arr.writeUInt16BE = BP.writeUInt16BE arr.writeUInt32LE = BP.writeUInt32LE arr.writeUInt32BE = BP.writeUInt32BE arr.writeIntLE = BP.writeIntLE arr.writeIntBE = BP.writeIntBE arr.writeInt8 = BP.writeInt8 arr.writeInt16LE = BP.writeInt16LE arr.writeInt16BE = BP.writeInt16BE arr.writeInt32LE = BP.writeInt32LE arr.writeInt32BE = BP.writeInt32BE arr.writeFloatLE = BP.writeFloatLE arr.writeFloatBE = BP.writeFloatBE arr.writeDoubleLE = BP.writeDoubleLE arr.writeDoubleBE = BP.writeDoubleBE arr.fill = BP.fill arr.inspect = BP.inspect arr.toArrayBuffer = BP.toArrayBuffer return arr } var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') // Node converts strings with length < 2 to '' if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' } return str } function stringtrim (str) { if (str.trim) return str.trim() return str.replace(/^\s+|\s+$/g, '') } function toHex (n) { if (n < 16) return '0' + n.toString(16) return n.toString(16) } function utf8ToBytes (string, units) { units = units || Infinity var codePoint var length = string.length var leadSurrogate = null var bytes = [] var i = 0 for (; i < length; i++) { codePoint = string.charCodeAt(i) // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (leadSurrogate) { // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) leadSurrogate = codePoint continue } else { // valid surrogate pair codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 leadSurrogate = null } } else { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } else { // valid lead leadSurrogate = codePoint continue } } } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) leadSurrogate = null } // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break bytes.push(codePoint) } else if (codePoint < 0x800) { if ((units -= 2) < 0) break bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x200000) { if ((units -= 4) < 0) break bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else { throw new Error('Invalid code point') } } return bytes } function asciiToBytes (str) { var byteArray = [] for (var i = 0; i < str.length; i++) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) } return byteArray } function utf16leToBytes (str, units) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; i++) { if ((units -= 2) < 0) break c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 byteArray.push(lo) byteArray.push(hi) } return byteArray } function base64ToBytes (str) { return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; i++) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i } function decodeUtf8Char (str) { try { return decodeURIComponent(str) } catch (err) { return String.fromCharCode(0xFFFD) // UTF 8 invalid char } } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4).Buffer)) /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { /* jslint node: true */ 'use strict'; var _ = __webpack_require__(11); var FontWrapper = __webpack_require__(16); function typeName(bold, italics){ var type = 'normal'; if (bold && italics) type = 'bolditalics'; else if (bold) type = 'bold'; else if (italics) type = 'italics'; return type; } function FontProvider(fontDescriptors, pdfDoc) { this.fonts = {}; this.pdfDoc = pdfDoc; this.fontWrappers = {}; for(var font in fontDescriptors) { if (fontDescriptors.hasOwnProperty(font)) { var fontDef = fontDescriptors[font]; this.fonts[font] = { normal: fontDef.normal, bold: fontDef.bold, italics: fontDef.italics, bolditalics: fontDef.bolditalics }; } } } FontProvider.prototype.provideFont = function(familyName, bold, italics) { if (!this.fonts[familyName]) return this.pdfDoc._font; var type = typeName(bold, italics); this.fontWrappers[familyName] = this.fontWrappers[familyName] || {}; if (!this.fontWrappers[familyName][type]) { this.fontWrappers[familyName][type] = new FontWrapper(this.pdfDoc, this.fonts[familyName][type], familyName + '(' + type + ')'); } return this.fontWrappers[familyName][type]; }; FontProvider.prototype.setFontRefsToPdfDoc = function(){ var self = this; _.each(self.fontWrappers, function(fontFamily) { _.each(fontFamily, function(fontWrapper){ _.each(fontWrapper.pdfFonts, function(font){ if (!self.pdfDoc.page.fonts[font.id]) { self.pdfDoc.page.fonts[font.id] = font.ref(); } }); }); }); }; module.exports = FontProvider; /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { /* jslint node: true */ 'use strict'; var _ = __webpack_require__(11); var TraversalTracker = __webpack_require__(18); var DocMeasure = __webpack_require__(19); var DocumentContext = __webpack_require__(20); var PageElementWriter = __webpack_require__(21); var ColumnCalculator = __webpack_require__(22); var TableProcessor = __webpack_require__(23); var Line = __webpack_require__(24); var pack = __webpack_require__(25).pack; var offsetVector = __webpack_require__(25).offsetVector; var fontStringify = __webpack_require__(25).fontStringify; var isFunction = __webpack_require__(25).isFunction; var TextTools = __webpack_require__(26); var StyleContextStack = __webpack_require__(27); function addAll(target, otherArray){ _.each(otherArray, function(item){ target.push(item); }); } /** * Creates an instance of LayoutBuilder - layout engine which turns document-definition-object * into a set of pages, lines, inlines and vectors ready to be rendered into a PDF * * @param {Object} pageSize - an object defining page width and height * @param {Object} pageMargins - an object defining top, left, right and bottom margins */ function LayoutBuilder(pageSize, pageMargins, imageMeasure) { this.pageSize = pageSize; this.pageMargins = pageMargins; this.tracker = new TraversalTracker(); this.imageMeasure = imageMeasure; this.tableLayouts = {}; } LayoutBuilder.prototype.registerTableLayouts = function (tableLayouts) { this.tableLayouts = pack(this.tableLayouts, tableLayouts); }; /** * Executes layout engine on document-definition-object and creates an array of pages * containing positioned Blocks, Lines and inlines * * @param {Object} docStructure document-definition-object * @param {Object} fontProvider font provider * @param {Object} styleDictionary dictionary with style definitions * @param {Object} defaultStyle default style definition * @return {Array} an array of pages */ LayoutBuilder.prototype.layoutDocument = function (docStructure, fontProvider, styleDictionary, defaultStyle, background, header, footer, images, watermark, pageBreakBeforeFct) { function addPageBreaksIfNecessary(linearNodeList, pages) { linearNodeList = _.reject(linearNodeList, function(node){ return _.isEmpty(node.positions); }); _.each(linearNodeList, function(node) { var nodeInfo = _.pick(node, [ 'id', 'text', 'ul', 'ol', 'table', 'image', 'qr', 'canvas', 'columns', 'headlineLevel', 'style', 'pageBreak', 'pageOrientation', 'width', 'height' ]); nodeInfo.startPosition = _.first(node.positions); nodeInfo.pageNumbers = _.chain(node.positions).map('pageNumber').uniq().value(); nodeInfo.pages = pages.length; nodeInfo.stack = _.isArray(node.stack); node.nodeInfo = nodeInfo; }); return _.any(linearNodeList, function (node, index, followingNodeList) { if (node.pageBreak !== 'before' && !node.pageBreakCalculated) { node.pageBreakCalculated = true; var pageNumber = _.first(node.nodeInfo.pageNumbers); var followingNodesOnPage = _.chain(followingNodeList).drop(index + 1).filter(function (node0) { return _.contains(node0.nodeInfo.pageNumbers, pageNumber); }).value(); var nodesOnNextPage = _.chain(followingNodeList).drop(index + 1).filter(function (node0) { return _.contains(node0.nodeInfo.pageNumbers, pageNumber + 1); }).value(); var previousNodesOnPage = _.chain(followingNodeList).take(index).filter(function (node0) { return _.contains(node0.nodeInfo.pageNumbers, pageNumber); }).value(); if (pageBreakBeforeFct(node.nodeInfo, _.map(followingNodesOnPage, 'nodeInfo'), _.map(nodesOnNextPage, 'nodeInfo'), _.map(previousNodesOnPage, 'nodeInfo'))) { node.pageBreak = 'before'; return true; } } }); } if(!isFunction(pageBreakBeforeFct)){ pageBreakBeforeFct = function(){ return false; }; } this.docMeasure = new DocMeasure(fontProvider, styleDictionary, defaultStyle, this.imageMeasure, this.tableLayouts, images); function resetXYs(result) { _.each(result.linearNodeList, function (node) { node.resetXY(); }); } var result = this.tryLayoutDocument(docStructure, fontProvider, styleDictionary, defaultStyle, background, header, footer, images, watermark); while(addPageBreaksIfNecessary(result.linearNodeList, result.pages)){ resetXYs(result); result = this.tryLayoutDocument(docStructure, fontProvider, styleDictionary, defaultStyle, background, header, footer, images, watermark); } return result.pages; }; LayoutBuilder.prototype.tryLayoutDocument = function (docStructure, fontProvider, styleDictionary, defaultStyle, background, header, footer, images, watermark, pageBreakBeforeFct) { this.linearNodeList = []; docStructure = this.docMeasure.measureDocument(docStructure); this.writer = new PageElementWriter( new DocumentContext(this.pageSize, this.pageMargins), this.tracker); var _this = this; this.writer.context().tracker.startTracking('pageAdded', function() { _this.addBackground(background); }); this.addBackground(background); this.processNode(docStructure); this.addHeadersAndFooters(header, footer); /* jshint eqnull:true */ if(watermark != null) this.addWatermark(watermark, fontProvider); return {pages: this.writer.context().pages, linearNodeList: this.linearNodeList}; }; LayoutBuilder.prototype.addBackground = function(background) { var backgroundGetter = isFunction(background) ? background : function() { return background; }; var pageBackground = backgroundGetter(this.writer.context().page + 1); if (pageBackground) { var pageSize = this.writer.context().getCurrentPage().pageSize; this.writer.beginUnbreakableBlock(pageSize.width, pageSize.height); this.processNode(this.docMeasure.measureDocument(pageBackground)); this.writer.commitUnbreakableBlock(0, 0); } }; LayoutBuilder.prototype.addStaticRepeatable = function(headerOrFooter, sizeFunction) { this.addDynamicRepeatable(function() { return headerOrFooter; }, sizeFunction); }; LayoutBuilder.prototype.addDynamicRepeatable = function(nodeGetter, sizeFunction) { var pages = this.writer.context().pages; for(var pageIndex = 0, l = pages.length; pageIndex < l; pageIndex++) { this.writer.context().page = pageIndex; var node = nodeGetter(pageIndex + 1, l); if (node) { var sizes = sizeFunction(this.writer.context().getCurrentPage().pageSize, this.pageMargins); this.writer.beginUnbreakableBlock(sizes.width, sizes.height); this.processNode(this.docMeasure.measureDocument(node)); this.writer.commitUnbreakableBlock(sizes.x, sizes.y); } } }; LayoutBuilder.prototype.addHeadersAndFooters = function(header, footer) { var headerSizeFct = function(pageSize, pageMargins){ return { x: 0, y: 0, width: pageSize.width, height: pageMargins.top }; }; var footerSizeFct = function (pageSize, pageMargins) { return { x: 0, y: pageSize.height - pageMargins.bottom, width: pageSize.width, height: pageMargins.bottom }; }; if(isFunction(header)) { this.addDynamicRepeatable(header, headerSizeFct); } else if(header) { this.addStaticRepeatable(header, headerSizeFct); } if(isFunction(footer)) { this.addDynamicRepeatable(footer, footerSizeFct); } else if(footer) { this.addStaticRepeatable(footer, footerSizeFct); } }; LayoutBuilder.prototype.addWatermark = function(watermark, fontProvider){ var defaultFont = Object.getOwnPropertyNames(fontProvider.fonts)[0]; // TODO allow selection of other font var watermarkObject = { text: watermark, font: fontProvider.provideFont(fontProvider[defaultFont], false, false), size: getSize(this.pageSize, watermark, fontProvider) }; var pages = this.writer.context().pages; for(var i = 0, l = pages.length; i < l; i++) { pages[i].watermark = watermarkObject; } function getSize(pageSize, watermark, fontProvider){ var width = pageSize.width; var height = pageSize.height; var targetWidth = Math.sqrt(width*width + height*height)*0.8; /* page diagnoal * sample factor */ var textTools = new TextTools(fontProvider); var styleContextStack = new StyleContextStack(); var size; /** * Binary search the best font size. * Initial bounds [0, 1000] * Break when range < 1 */ var a = 0; var b = 1000; var c = (a+b)/2; while(Math.abs(a - b) > 1){ styleContextStack.push({ fontSize: c }); size = textTools.sizeOfString(watermark, styleContextStack); if(size.width > targetWidth){ b = c; c = (a+b)/2; } else if(size.width < targetWidth){ a = c; c = (a+b)/2; } styleContextStack.pop(); } /* End binary search */ return {size: size, fontSize: c}; } }; function decorateNode(node){ var x = node.x, y = node.y; node.positions = []; _.each(node.canvas, function(vector){ var x = vector.x, y = vector.y; vector.resetXY = function(){ vector.x = x; vector.y = y; }; }); node.resetXY = function(){ node.x = x; node.y = y; _.each(node.canvas, function(vector){ vector.resetXY(); }); }; } LayoutBuilder.prototype.processNode = function(node) { var self = this; this.linearNodeList.push(node); decorateNode(node); applyMargins(function() { var absPosition = node.absolutePosition; if(absPosition){ self.writer.context().beginDetachedBlock(); self.writer.context().moveTo(absPosition.x || 0, absPosition.y || 0); } if (node.stack) { self.processVerticalContainer(node); } else if (node.columns) { self.processColumns(node); } else if (node.ul) { self.processList(false, node); } else if (node.ol) { self.processList(true, node); } else if (node.table) { self.processTable(node); } else if (node.text !== undefined) { self.processLeaf(node); } else if (node.image) { self.processImage(node); } else if (node.canvas) { self.processCanvas(node); } else if (node.qr) { self.processQr(node); }else if (!node._span) { throw 'Unrecognized document structure: ' + JSON.stringify(node, fontStringify); } if(absPosition){ self.writer.context().endDetachedBlock(); } }); function applyMargins(callback) { var margin = node._margin; if (node.pageBreak === 'before') { self.writer.moveToNextPage(node.pageOrientation); } if (margin) { self.writer.context().moveDown(margin[1]); self.writer.context().addMargin(margin[0], margin[2]); } callback(); if(margin) { self.writer.context().addMargin(-margin[0], -margin[2]); self.writer.context().moveDown(margin[3]); } if (node.pageBreak === 'after') { self.writer.moveToNextPage(node.pageOrientation); } } }; // vertical container LayoutBuilder.prototype.processVerticalContainer = function(node) { var self = this; node.stack.forEach(function(item) { self.processNode(item); addAll(node.positions, item.positions); //TODO: paragraph gap }); }; // columns LayoutBuilder.prototype.processColumns = function(columnNode) { var columns = columnNode.columns; var availableWidth = this.writer.context().availableWidth; var gaps = gapArray(columnNode._gap); if (gaps) availableWidth -= (gaps.length - 1) * columnNode._gap; ColumnCalculator.buildColumnWidths(columns, availableWidth); var result = this.processRow(columns, columns, gaps); addAll(columnNode.positions, result.positions); function gapArray(gap) { if (!gap) return null; var gaps = []; gaps.push(0); for(var i = columns.length - 1; i > 0; i--) { gaps.push(gap); } return gaps; } }; LayoutBuilder.prototype.processRow = function(columns, widths, gaps, tableBody, tableRow) { var self = this; var pageBreaks = [], positions = []; this.tracker.auto('pageChanged', storePageBreakData, function() { widths = widths || columns; self.writer.context().beginColumnGroup(); for(var i = 0, l = columns.length; i < l; i++) { var column = columns[i]; var width = widths[i]._calcWidth; var leftOffset = colLeftOffset(i); if (column.colSpan && column.colSpan > 1) { for(var j = 1; j < column.colSpan; j++) { width += widths[++i]._calcWidth + gaps[i]; } } self.writer.context().beginColumn(width, leftOffset, getEndingCell(column, i)); if (!column._span) { self.processNode(column); addAll(positions, column.positions); } else if (column._columnEndingContext) { // row-span ending self.writer.context().markEnding(column); } } self.writer.context().completeColumnGroup(); }); return {pageBreaks: pageBreaks, positions: positions}; function storePageBreakData(data) { var pageDesc; for(var i = 0, l = pageBreaks.length; i < l; i++) { var desc = pageBreaks[i]; if (desc.prevPage === data.prevPage) { pageDesc = desc; break; } } if (!pageDesc) { pageDesc = data; pageBreaks.push(pageDesc); } pageDesc.prevY = Math.max(pageDesc.prevY, data.prevY); pageDesc.y = Math.min(pageDesc.y, data.y); } function colLeftOffset(i) { if (gaps && gaps.length > i) return gaps[i]; return 0; } function getEndingCell(column, columnIndex) { if (column.rowSpan && column.rowSpan > 1) { var endingRow = tableRow + column.rowSpan - 1; if (endingRow >= tableBody.length) throw 'Row span for column ' + columnIndex + ' (with indexes starting from 0) exceeded row count'; return tableBody[endingRow][columnIndex]; } return null; } }; // lists LayoutBuilder.prototype.processList = function(orderedList, node) { var self = this, items = orderedList ? node.ol : node.ul, gapSize = node._gapSize; this.writer.context().addMargin(gapSize.width); var nextMarker; this.tracker.auto('lineAdded', addMarkerToFirstLeaf, function() { items.forEach(function(item) { nextMarker = item.listMarker; self.processNode(item); addAll(node.positions, item.positions); }); }); this.writer.context().addMargin(-gapSize.width); function addMarkerToFirstLeaf(line) { // I'm not very happy with the way list processing is implemented // (both code and algorithm should be rethinked) if (nextMarker) { var marker = nextMarker; nextMarker = null; if (marker.canvas) { var vector = marker.canvas[0]; offsetVector(vector, -marker._minWidth, 0); self.writer.addVector(vector); } else { var markerLine = new Line(self.pageSize.width); markerLine.addInline(marker._inlines[0]); markerLine.x = -marker._minWidth; markerLine.y = line.getAscenderHeight() - markerLine.getAscenderHeight(); self.writer.addLine(markerLine, true); } } } }; // tables LayoutBuilder.prototype.processTable = function(tableNode) { var processor = new TableProcessor(tableNode); processor.beginTable(this.writer); for(var i = 0, l = tableNode.table.body.length; i < l; i++) { processor.beginRow(i, this.writer); var result = this.processRow(tableNode.table.body[i], tableNode.table.widths, tableNode._offsets.offsets, tableNode.table.body, i); addAll(tableNode.positions, result.positions); processor.endRow(i, this.writer, result.pageBreaks); } processor.endTable(this.writer); }; // leafs (texts) LayoutBuilder.prototype.processLeaf = function(node) { var line = this.buildNextLine(node); while (line) { var positions = this.writer.addLine(line); node.positions.push(positions); line = this.buildNextLine(node); } }; LayoutBuilder.prototype.buildNextLine = function(textNode) { if (!textNode._inlines || textNode._inlines.length === 0) return null; var line = new Line(this.writer.context().availableWidth); while(textNode._inlines && textNode._inlines.length > 0 && line.hasEnoughSpaceForInline(textNode._inlines[0])) { line.addInline(textNode._inlines.shift()); } line.lastLineInParagraph = textNode._inlines.length === 0; return line; }; // images LayoutBuilder.prototype.processImage = function(node) { var position = this.writer.addImage(node); node.positions.push(position); }; LayoutBuilder.prototype.processCanvas = function(node) { var height = node._minHeight; if (this.writer.context().availableHeight < height) { // TODO: support for canvas larger than a page // TODO: support for other overflow methods this.writer.moveToNextPage(); } node.canvas.forEach(function(vector) { var position = this.writer.addVector(vector); node.positions.push(position); }, this); this.writer.context().moveDown(height); }; LayoutBuilder.prototype.processQr = function(node) { var position = this.writer.addQr(node); node.positions.push(position); }; module.exports = LayoutBuilder; /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { module.exports = { '4A0': [4767.87, 6740.79], '2A0': [3370.39, 4767.87], A0: [2383.94, 3370.39], A1: [1683.78, 2383.94], A2: [1190.55, 1683.78], A3: [841.89, 1190.55], A4: [595.28, 841.89], A5: [419.53, 595.28], A6: [297.64, 419.53], A7: [209.76, 297.64], A8: [147.40, 209.76], A9: [104.88, 147.40], A10: [73.70, 104.88], B0: [2834.65, 4008.19], B1: [2004.09, 2834.65], B2: [1417.32, 2004.09], B3: [1000.63, 1417.32], B4: [708.66, 1000.63], B5: [498.90, 708.66], B6: [354.33, 498.90], B7: [249.45, 354.33], B8: [175.75, 249.45], B9: [124.72, 175.75], B10: [87.87, 124.72], C0: [2599.37, 3676.54], C1: [1836.85, 2599.37], C2: [1298.27, 1836.85], C3: [918.43, 1298.27], C4: [649.13, 918.43], C5: [459.21, 649.13], C6: [323.15, 459.21], C7: [229.61, 323.15], C8: [161.57, 229.61], C9: [113.39, 161.57], C10: [79.37, 113.39], RA0: [2437.80, 3458.27], RA1: [1729.13, 2437.80], RA2: [1218.90, 1729.13], RA3: [864.57, 1218.90], RA4: [609.45, 864.57], SRA0: [2551.18, 3628.35], SRA1: [1814.17, 2551.18], SRA2: [1275.59, 1814.17], SRA3: [907.09, 1275.59], SRA4: [637.80, 907.09], EXECUTIVE: [521.86, 756.00], FOLIO: [612.00, 936.00], LEGAL: [612.00, 1008.00], LETTER: [612.00, 792.00], TABLOID: [792.00, 1224.00] }; /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer) {/* jslint node: true */ 'use strict'; var pdfKit = __webpack_require__(28); var PDFImage = __webpack_require__(17); function ImageMeasure(pdfDoc, imageDictionary) { this.pdfDoc = pdfDoc; this.imageDictionary = imageDictionary || {}; } ImageMeasure.prototype.measureImage = function(src) { var image, label; var that = this; if (!this.pdfDoc._imageRegistry[src]) { label = 'I' + (++this.pdfDoc._imageCount); image = PDFImage.open(realImageSrc(src), label); image.embed(this.pdfDoc); this.pdfDoc._imageRegistry[src] = image; } else { image = this.pdfDoc._imageRegistry[src]; } return { width: image.width, height: image.height }; function realImageSrc(src) { var img = that.imageDictionary[src]; if (!img) return src; var index = img.indexOf('base64,'); if (index < 0) { throw 'invalid image format, images dictionary should contain dataURL entries'; } return new Buffer(img.substring(index + 7), 'base64'); } }; module.exports = ImageMeasure; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4).Buffer)) /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { /* jslint node: true */ 'use strict'; function groupDecorations(line) { var groups = [], curGroup = null; for(var i = 0, l = line.inlines.length; i < l; i++) { var inline = line.inlines[i]; var decoration = inline.decoration; if(!decoration) { curGroup = null; continue; } var color = inline.decorationColor || inline.color || 'black'; var style = inline.decorationStyle || 'solid'; decoration = Array.isArray(decoration) ? decoration : [ decoration ]; for(var ii = 0, ll = decoration.length; ii < ll; ii++) { var deco = decoration[ii]; if(!curGroup || deco !== curGroup.decoration || style !== curGroup.decorationStyle || color !== curGroup.decorationColor || deco === 'lineThrough') { curGroup = { line: line, decoration: deco, decorationColor: color, decorationStyle: style, inlines: [ inline ] }; groups.push(curGroup); } else { curGroup.inlines.push(inline); } } } return groups; } function drawDecoration(group, x, y, pdfKitDoc) { function maxInline() { var max = 0; for (var i = 0, l = group.inlines.length; i < l; i++) { var inl = group.inlines[i]; max = inl.fontSize > max ? i : max; } return group.inlines[max]; } function width() { var sum = 0; for (var i = 0, l = group.inlines.length; i < l; i++) { sum += group.inlines[i].width; } return sum; } var firstInline = group.inlines[0], biggerInline = maxInline(), totalWidth = width(), lineAscent = group.line.getAscenderHeight(), ascent = biggerInline.font.ascender / 1000 * biggerInline.fontSize, height = biggerInline.height, descent = height - ascent; var lw = 0.5 + Math.floor(Math.max(biggerInline.fontSize - 8, 0) / 2) * 0.12; switch (group.decoration) { case 'underline': y += lineAscent + descent * 0.45; break; case 'overline': y += lineAscent - (ascent * 0.85); break; case 'lineThrough': y += lineAscent - (ascent * 0.25); break; default: throw 'Unkown decoration : ' + group.decoration; } pdfKitDoc.save(); if(group.decorationStyle === 'double') { var gap = Math.max(0.5, lw*2); pdfKitDoc .fillColor(group.decorationColor) .rect(x + firstInline.x, y-lw/2, totalWidth, lw/2).fill() .rect(x + firstInline.x, y+gap-lw/2, totalWidth, lw/2).fill(); } else if(group.decorationStyle === 'dashed') { var nbDashes = Math.ceil(totalWidth / (3.96+2.84)); var rdx = x + firstInline.x; pdfKitDoc.rect(rdx, y, totalWidth, lw).clip(); pdfKitDoc.fillColor(group.decorationColor); for (var i = 0; i < nbDashes; i++) { pdfKitDoc.rect(rdx, y-lw/2, 3.96, lw).fill(); rdx += 3.96 + 2.84; } } else if(group.decorationStyle === 'dotted') { var nbDots = Math.ceil(totalWidth / (lw*3)); var rx = x + firstInline.x; pdfKitDoc.rect(rx, y, totalWidth, lw).clip(); pdfKitDoc.fillColor(group.decorationColor); for (var ii = 0; ii < nbDots; ii++) { pdfKitDoc.rect(rx, y-lw/2, lw, lw).fill(); rx += (lw*3); } } else if(group.decorationStyle === 'wavy') { var sh = 0.7, sv = 1; var nbWaves = Math.ceil(totalWidth / (sh*2))+1; var rwx = x + firstInline.x - 1; pdfKitDoc.rect(x + firstInline.x, y-sv, totalWidth, y+sv).clip(); pdfKitDoc.lineWidth(0.24); pdfKitDoc.moveTo(rwx, y); for(var iii = 0; iii < nbWaves; iii++) { pdfKitDoc .bezierCurveTo(rwx+sh, y-sv, rwx+sh*2, y-sv, rwx+sh*3, y) .bezierCurveTo(rwx+sh*4, y+sv, rwx+sh*5, y+sv, rwx+sh*6, y); rwx += sh*6; } pdfKitDoc.stroke(group.decorationColor); } else { pdfKitDoc .fillColor(group.decorationColor) .rect(x + firstInline.x, y-lw/2, totalWidth, lw) .fill(); } pdfKitDoc.restore(); } function drawDecorations(line, x, y, pdfKitDoc) { var groups = groupDecorations(line); for (var i = 0, l = groups.length; i < l; i++) { drawDecoration(groups[i], x, y, pdfKitDoc); } } function drawBackground(line, x, y, pdfKitDoc) { var height = line.getHeight(); for(var i = 0, l = line.inlines.length; i < l; i++) { var inline = line.inlines[i]; if(inline.background) { pdfKitDoc .fillColor(inline.background) .rect(x + inline.x, y, inline.width, height) .fill(); } } } module.exports = { drawBackground: drawBackground, drawDecorations: drawDecorations }; /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer, __dirname) {/* jslint node: true */ 'use strict'; // var b64 = require('./base64.js').base64DecToArr; function VirtualFileSystem() { this.fileSystem = {}; this.baseSystem = {}; } VirtualFileSystem.prototype.readFileSync = function(filename) { filename = fixFilename(filename); var base64content = this.baseSystem[filename]; if (base64content) { return new Buffer(base64content, 'base64'); } return this.fileSystem[filename]; }; VirtualFileSystem.prototype.writeFileSync = function(filename, content) { this.fileSystem[fixFilename(filename)] = content; }; VirtualFileSystem.prototype.bindFS = function(data) { this.baseSystem = data; }; function fixFilename(filename) { if (filename.indexOf(__dirname) === 0) { filename = filename.substring(__dirname.length); } if (filename.indexOf('/') === 0) { filename = filename.substring(1); } return filename; } module.exports = new VirtualFileSystem(); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4).Buffer, "/")) /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/** * @license * lodash 3.1.0 (Custom Build) * Build: `lodash modern -d -o ./index.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.7.0 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license */ ;(function() { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; /** Used as the semantic version number. */ var VERSION = '3.1.0'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, REARG_FLAG = 128, ARY_FLAG = 256; /** Used as default options for `_.trunc`. */ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = '...'; /** Used to detect when a function becomes hot. */ var HOT_COUNT = 150, HOT_SPAN = 16; /** Used to indicate the type of lazy iteratees. */ var LAZY_FILTER_FLAG = 0, LAZY_MAP_FLAG = 1, LAZY_WHILE_FLAG = 2; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', weakMapTag = '[object WeakMap]'; var arrayBufferTag = '[object ArrayBuffer]', float32Tag = '[object Float32Array]', float64Tag = '[object Float64Array]', int8Tag = '[object Int8Array]', int16Tag = '[object Int16Array]', int32Tag = '[object Int32Array]', uint8Tag = '[object Uint8Array]', uint8ClampedTag = '[object Uint8ClampedArray]', uint16Tag = '[object Uint16Array]', uint32Tag = '[object Uint32Array]'; /** Used to match empty string literals in compiled template source. */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; /** Used to match HTML entities and HTML characters. */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); /** Used to match template delimiters. */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; /** * Used to match ES template delimiters. * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) * for more details. */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; /** Used to detect named functions. */ var reFuncName = /^\s*function[ \n\r\t]+\w/; /** Used to detect hexadecimal string values. */ var reHexPrefix = /^0[xX]/; /** Used to detect host constructors (Safari > 5). */ var reHostCtor = /^\[object .+?Constructor\]$/; /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; /** * Used to match `RegExp` special characters. * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) * for more details. */ var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, reHasRegExpChars = RegExp(reRegExpChars.source); /** Used to detect functions containing a `this` reference. */ var reThis = /\bthis\b/; /** Used to match unescaped characters in compiled string literals. */ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; /** Used to match words to create compound words. */ var reWords = (function() { var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]', lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+'; return RegExp(upper + '{2,}(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); }()); /** Used to detect and test for whitespace. */ var whitespace = ( // Basic whitespace characters. ' \t\x0b\f\xa0\ufeff' + // Line terminators. '\n\r\u2028\u2029' + // Unicode category "Zs" space separators. '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' ); /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'window', 'WinRTError' ]; /** Used to make template sourceURLs easier to identify. */ var templateCounter = -1; /** Used to identify `toStringTag` values of typed arrays. */ var typedArrayTags = {}; typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; /** Used as an internal `_.debounce` options object by `_.throttle`. */ var debounceOptions = { 'leading': false, 'maxWait': 0, 'trailing': false }; /** Used to map latin-1 supplementary letters to basic latin letters. */ var deburredLetters = { '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', '\xc7': 'C', '\xe7': 'c', '\xd0': 'D', '\xf0': 'd', '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', '\xd1': 'N', '\xf1': 'n', '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', '\xc6': 'Ae', '\xe6': 'ae', '\xde': 'Th', '\xfe': 'th', '\xdf': 'ss' }; /** Used to map characters to HTML entities. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '`': '`' }; /** Used to map HTML entities to characters. */ var htmlUnescapes = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'", '`': '`' }; /** Used to determine if values are of the language type `Object`. */ var objectTypes = { 'function': true, 'object': true }; /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', '\u2028': 'u2028', '\u2029': 'u2029' }; /** * Used as a reference to the global object. * * The `this` value is used if it is the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ var root = (objectTypes[typeof window] && window !== (this && this.window)) ? window : this; /** Detect free variable `exports`. */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; /** Detect free variable `module`. */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; /*--------------------------------------------------------------------------*/ /** * The base implementation of `compareAscending` which compares values and * sorts them in ascending order without guaranteeing a stable sort. * * @private * @param {*} value The value to compare to `other`. * @param {*} other The value to compare to `value`. * @returns {number} Returns the sort order indicator for `value`. */ function baseCompareAscending(value, other) { if (value !== other) { var valIsReflexive = value === value, othIsReflexive = other === other; if (value > other || !valIsReflexive || (typeof value == 'undefined' && othIsReflexive)) { return 1; } if (value < other || !othIsReflexive || (typeof other == 'undefined' && valIsReflexive)) { return -1; } } return 0; } /** * The base implementation of `_.indexOf` without support for binary searches. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { if (value !== value) { return indexOfNaN(array, fromIndex); } var index = (fromIndex || 0) - 1, length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * The base implementation of `_.sortBy` and `_.sortByAll` which uses `comparer` * to define the sort order of `array` and replaces criteria objects with their * corresponding values. * * @private * @param {Array} array The array to sort. * @param {Function} comparer The function to define sort order. * @returns {Array} Returns `array`. */ function baseSortBy(array, comparer) { var length = array.length; array.sort(comparer); while (length--) { array[length] = array[length].value; } return array; } /** * Converts `value` to a string if it is not one. An empty string is returned * for `null` or `undefined` values. * * @private * @param {*} value The value to process. * @returns {string} Returns the string. */ function baseToString(value) { if (typeof value == 'string') { return value; } return value == null ? '' : (value + ''); } /** * Used by `_.max` and `_.min` as the default callback for string values. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the code unit of the first character of the string. */ function charAtCallback(string) { return string.charCodeAt(0); } /** * Used by `_.trim` and `_.trimLeft` to get the index of the first character * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @param {string} chars The characters to find. * @returns {number} Returns the index of the first character not found in `chars`. */ function charsLeftIndex(string, chars) { var index = -1, length = string.length; while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} return index; } /** * Used by `_.trim` and `_.trimRight` to get the index of the last character * of `string` that is not found in `chars`. * * @private * @param {string} string The string to inspect. * @param {string} chars The characters to find. * @returns {number} Returns the index of the last character not found in `chars`. */ function charsRightIndex(string, chars) { var index = string.length; while (index-- && chars.indexOf(string.charAt(index)) > -1) {} return index; } /** * Used by `_.sortBy` to compare transformed elements of a collection and stable * sort them in ascending order. * * @private * @param {Object} object The object to compare to `other`. * @param {Object} other The object to compare to `object`. * @returns {number} Returns the sort order indicator for `object`. */ function compareAscending(object, other) { return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index); } /** * Used by `_.sortByAll` to compare multiple properties of each element * in a collection and stable sort them in ascending order. * * @private * @param {Object} object The object to compare to `other`. * @param {Object} other The object to compare to `object`. * @returns {number} Returns the sort order indicator for `object`. */ function compareMultipleAscending(object, other) { var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length; while (++index < length) { var result = baseCompareAscending(objCriteria[index], othCriteria[index]); if (result) { return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications // that causes it, under certain circumstances, to provide the same value for // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 // for more details. // // This also ensures a stable sort in V8 and other engines. // See https://code.google.com/p/v8/issues/detail?id=90 for more details. return object.index - other.index; } /** * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. * * @private * @param {string} letter The matched letter to deburr. * @returns {string} Returns the deburred letter. */ function deburrLetter(letter) { return deburredLetters[letter]; } /** * Used by `_.escape` to convert characters to HTML entities. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeHtmlChar(chr) { return htmlEscapes[chr]; } /** * Used by `_.template` to escape characters for inclusion in compiled * string literals. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { return '\\' + stringEscapes[chr]; } /** * Gets the index at which the first occurrence of `NaN` is found in `array`. * If `fromRight` is provided elements of `array` are iterated from right to left. * * @private * @param {Array} array The array to search. * @param {number} [fromIndex] The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched `NaN`, else `-1`. */ function indexOfNaN(array, fromIndex, fromRight) { var length = array.length, index = fromRight ? (fromIndex || length) : ((fromIndex || 0) - 1); while ((fromRight ? index-- : ++index < length)) { var other = array[index]; if (other !== other) { return index; } } return -1; } /** * Checks if `value` is object-like. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. */ function isObjectLike(value) { return (value && typeof value == 'object') || false; } /** * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a * character code is whitespace. * * @private * @param {number} charCode The character code to inspect. * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`. */ function isSpace(charCode) { return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279))); } /** * Replaces all `placeholder` elements in `array` with an internal placeholder * and returns an array of their indexes. * * @private * @param {Array} array The array to modify. * @param {*} placeholder The placeholder to replace. * @returns {Array} Returns the new array of placeholder indexes. */ function replaceHolders(array, placeholder) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { if (array[index] === placeholder) { array[index] = PLACEHOLDER; result[++resIndex] = index; } } return result; } /** * An implementation of `_.uniq` optimized for sorted arrays without support * for callback shorthands and `this` binding. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function sortedUniq(array, iteratee) { var seen, index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; if (!index || seen !== computed) { seen = computed; result[++resIndex] = value; } } return result; } /** * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace * character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the first non-whitespace character. */ function trimmedLeftIndex(string) { var index = -1, length = string.length; while (++index < length && isSpace(string.charCodeAt(index))) {} return index; } /** * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace * character of `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the index of the last non-whitespace character. */ function trimmedRightIndex(string) { var index = string.length; while (index-- && isSpace(string.charCodeAt(index))) {} return index; } /** * Used by `_.unescape` to convert HTML entities to characters. * * @private * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ function unescapeHtmlChar(chr) { return htmlUnescapes[chr]; } /*--------------------------------------------------------------------------*/ /** * Create a new pristine `lodash` function using the given `context` object. * * @static * @memberOf _ * @category Utility * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `lodash` function. * @example * * _.mixin({ 'add': function(a, b) { return a + b; } }); * * var lodash = _.runInContext(); * lodash.mixin({ 'sub': function(a, b) { return a - b; } }); * * _.isFunction(_.add); * // => true * _.isFunction(_.sub); * // => false * * lodash.isFunction(lodash.add); * // => false * lodash.isFunction(lodash.sub); * // => true * * // using `context` to mock `Date#getTime` use in `_.now` * var mock = _.runInContext({ * 'Date': function() { * return { 'getTime': getTimeMock }; * } * }); * * // or creating a suped-up `defer` in Node.js * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. // See https://es5.github.io/#x11.1.5 for more details. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; /** Native constructor references. */ var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; /** Used for native method references. */ var arrayProto = Array.prototype, objectProto = Object.prototype; /** Used to detect DOM support. */ var document = (document = context.window) && document.document; /** Used to resolve the decompiled source of functions. */ var fnToString = Function.prototype.toString; /** Used to the length of n-tuples for `_.unzip`. */ var getLength = baseProperty('length'); /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to generate unique IDs. */ var idCounter = 0; /** * Used to resolve the `toStringTag` of values. * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) * for more details. */ var objToString = objectProto.toString; /** Used to restore the original `_` reference in `_.noConflict`. */ var oldDash = context._; /** Used to detect if a method is native. */ var reNative = RegExp('^' + escapeRegExp(objToString) .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Native method references. */ var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, push = arrayProto.push, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, unshift = arrayProto.unshift, WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; /** Used to clone array buffers. */ var Float64Array = (function() { // Safari 5 errors when using an array buffer to initialize a typed array // where the array buffer's `byteLength` is not a multiple of the typed // array's `BYTES_PER_ELEMENT`. try { var func = isNative(func = context.Float64Array) && func, result = new func(new ArrayBuffer(10), 0, 1) && func; } catch(e) {} return result; }()); /* Native method references for those with the same name as other `lodash` methods. */ var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsFinite = context.isFinite, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, nativeNow = isNative(nativeNow = Date.now) && nativeNow, nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite, nativeParseInt = context.parseInt, nativeRandom = Math.random; /** Used as references for `-Infinity` and `Infinity`. */ var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** Used as the size, in bytes, of each `Float64Array` element. */ var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; /** * Used as the maximum length of an array-like value. * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) * for more details. */ var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps `value` to enable intuitive chaining. * Methods that operate on and return arrays, collections, and functions can * be chained together. Methods that return a boolean or single value will * automatically end the chain returning the unwrapped value. Explicit chaining * may be enabled using `_.chain`. The execution of chained methods is lazy, * that is, execution is deferred until `_#value` is implicitly or explicitly * called. * * Lazy evaluation allows several methods to support shortcut fusion. Shortcut * fusion is an optimization that merges iteratees to avoid creating intermediate * arrays and reduce the number of iteratee executions. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. * * In addition to lodash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * * The wrapper functions that support shortcut fusion are: * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `first`, * `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, `slice`, * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `where` * * The chainable wrapper functions are: * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, * `callback`, `chain`, `chunk`, `compact`, `concat`, `constant`, `countBy`, * `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, `difference`, * `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, `flatten`, * `flattenDeep`, `flow`, `flowRight`, `forEach`, `forEachRight`, `forIn`, * `forInRight`, `forOwn`, `forOwnRight`, `functions`, `groupBy`, `indexBy`, * `initial`, `intersection`, `invert`, `invoke`, `keys`, `keysIn`, `map`, * `mapValues`, `matches`, `memoize`, `merge`, `mixin`, `negate`, `noop`, * `omit`, `once`, `pairs`, `partial`, `partialRight`, `partition`, `pick`, * `pluck`, `property`, `propertyOf`, `pull`, `pullAt`, `push`, `range`, * `rearg`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, * `sortBy`, `sortByAll`, `splice`, `take`, `takeRight`, `takeRightWhile`, * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, * `transform`, `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, * `where`, `without`, `wrap`, `xor`, `zip`, and `zipObject` * * The wrapper functions that are **not** chainable by default are: * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, * `identity`, `includes`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, * `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, * `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, * `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, * `startCase`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, * `trunc`, `unescape`, `uniqueId`, `value`, and `words` * * The wrapper function `sample` will return a wrapped value when `n` is provided, * otherwise an unwrapped value is returned. * * @name _ * @constructor * @category Chain * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns a `lodash` instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value * wrapped.reduce(function(sum, n) { return sum + n; }); * // => 6 * * // returns a wrapped value * var squares = wrapped.map(function(n) { return n * n; }); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { if (isObjectLike(value) && !isArray(value)) { if (value instanceof LodashWrapper) { return value; } if (hasOwnProperty.call(value, '__wrapped__')) { return new LodashWrapper(value.__wrapped__, value.__chain__, arrayCopy(value.__actions__)); } } return new LodashWrapper(value); } /** * The base constructor for creating `lodash` wrapper objects. * * @private * @param {*} value The value to wrap. * @param {boolean} [chainAll] Enable chaining for all wrapper methods. * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. */ function LodashWrapper(value, chainAll, actions) { this.__actions__ = actions || []; this.__chain__ = !!chainAll; this.__wrapped__ = value; } /** * An object environment feature flags. * * @static * @memberOf _ * @type Object */ var support = lodash.support = {}; (function(x) { /** * Detect if functions can be decompiled by `Function#toString` * (all but Firefox OS certified apps, older Opera mobile browsers, and * the PlayStation 3; forced `false` for Windows 8 apps). * * @memberOf _.support * @type boolean */ support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); /** * Detect if `Function#name` is supported (all but IE). * * @memberOf _.support * @type boolean */ support.funcNames = typeof Function.name == 'string'; /** * Detect if the DOM is supported. * * @memberOf _.support * @type boolean */ try { support.dom = document.createDocumentFragment().nodeType === 11; } catch(e) { support.dom = false; } /** * Detect if `arguments` object indexes are non-enumerable. * * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` * checks for indexes that exceed their function's formal parameters with * associated values of `0`. * * @memberOf _.support * @type boolean */ try { support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); } catch(e) { support.nonEnumArgs = true; } }(0, 0)); /** * By default, the template delimiters used by lodash are like those in * embedded Ruby (ERB). Change the following template settings to use * alternative delimiters. * * @static * @memberOf _ * @type Object */ lodash.templateSettings = { /** * Used to detect `data` property values to be HTML-escaped. * * @memberOf _.templateSettings * @type RegExp */ 'escape': reEscape, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type RegExp */ 'evaluate': reEvaluate, /** * Used to detect `data` property values to inject. * * @memberOf _.templateSettings * @type RegExp */ 'interpolate': reInterpolate, /** * Used to reference the data object in the template text. * * @memberOf _.templateSettings * @type string */ 'variable': '', /** * Used to import variables into the compiled template. * * @memberOf _.templateSettings * @type Object */ 'imports': { /** * A reference to the `lodash` function. * * @memberOf _.templateSettings.imports * @type Function */ '_': lodash } }; /*------------------------------------------------------------------------*/ /** * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. * * @private * @param {*} value The value to wrap. */ function LazyWrapper(value) { this.actions = null; this.dir = 1; this.dropCount = 0; this.filtered = false; this.iteratees = null; this.takeCount = POSITIVE_INFINITY; this.views = null; this.wrapped = value; } /** * Creates a clone of the lazy wrapper object. * * @private * @name clone * @memberOf LazyWrapper * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { var actions = this.actions, iteratees = this.iteratees, views = this.views, result = new LazyWrapper(this.wrapped); result.actions = actions ? arrayCopy(actions) : null; result.dir = this.dir; result.dropCount = this.dropCount; result.filtered = this.filtered; result.iteratees = iteratees ? arrayCopy(iteratees) : null; result.takeCount = this.takeCount; result.views = views ? arrayCopy(views) : null; return result; } /** * Reverses the direction of lazy iteration. * * @private * @name reverse * @memberOf LazyWrapper * @returns {Object} Returns the new reversed `LazyWrapper` object. */ function lazyReverse() { if (this.filtered) { var result = new LazyWrapper(this); result.dir = -1; result.filtered = true; } else { result = this.clone(); result.dir *= -1; } return result; } /** * Extracts the unwrapped value from its lazy wrapper. * * @private * @name value * @memberOf LazyWrapper * @returns {*} Returns the unwrapped value. */ function lazyValue() { var array = this.wrapped.value(); if (!isArray(array)) { return baseWrapperValue(array, this.actions); } var dir = this.dir, isRight = dir < 0, view = getView(0, array.length, this.views), start = view.start, end = view.end, length = end - start, dropCount = this.dropCount, takeCount = nativeMin(length, this.takeCount - dropCount), index = isRight ? end : start - 1, iteratees = this.iteratees, iterLength = iteratees ? iteratees.length : 0, resIndex = 0, result = []; outer: while (length-- && resIndex < takeCount) { index += dir; var iterIndex = -1, value = array[index]; while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, computed = iteratee(value, index, array), type = data.type; if (type == LAZY_MAP_FLAG) { value = computed; } else if (!computed) { if (type == LAZY_FILTER_FLAG) { continue outer; } else { break outer; } } } if (dropCount) { dropCount--; } else { result[resIndex++] = value; } } return result; } /*------------------------------------------------------------------------*/ /** * Creates a cache object to store key/value pairs. * * @private * @static * @name Cache * @memberOf _.memoize */ function MapCache() { this.__data__ = {}; } /** * Removes `key` and its value from the cache. * * @private * @name delete * @memberOf _.memoize.Cache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`. */ function mapDelete(key) { return this.has(key) && delete this.__data__[key]; } /** * Gets the cached value for `key`. * * @private * @name get * @memberOf _.memoize.Cache * @param {string} key The key of the value to get. * @returns {*} Returns the cached value. */ function mapGet(key) { return key == '__proto__' ? undefined : this.__data__[key]; } /** * Checks if a cached value for `key` exists. * * @private * @name has * @memberOf _.memoize.Cache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapHas(key) { return key != '__proto__' && hasOwnProperty.call(this.__data__, key); } /** * Adds `value` to `key` of the cache. * * @private * @name set * @memberOf _.memoize.Cache * @param {string} key The key of the value to cache. * @param {*} value The value to cache. * @returns {Object} Returns the cache object. */ function mapSet(key, value) { if (key != '__proto__') { this.__data__[key] = value; } return this; } /*------------------------------------------------------------------------*/ /** * * Creates a cache object to store unique values. * * @private * @param {Array} [values] The values to cache. */ function SetCache(values) { var length = values ? values.length : 0; this.data = { 'hash': nativeCreate(null), 'set': new Set }; while (length--) { this.push(values[length]); } } /** * Checks if `value` is in `cache` mimicking the return signature of * `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private * @param {Object} cache The cache to search. * @param {*} value The value to search for. * @returns {number} Returns `0` if `value` is found, else `-1`. */ function cacheIndexOf(cache, value) { var data = cache.data, result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value]; return result ? 0 : -1; } /** * Adds `value` to the cache. * * @private * @name push * @memberOf SetCache * @param {*} value The value to cache. */ function cachePush(value) { var data = this.data; if (typeof value == 'string' || isObject(value)) { data.set.add(value); } else { data.hash[value] = true; } } /*------------------------------------------------------------------------*/ /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function arrayCopy(source, array) { var index = -1, length = source.length; array || (array = Array(length)); while (++index < length) { array[index] = source[index]; } return array; } /** * A specialized version of `_.forEach` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { break; } } return array; } /** * A specialized version of `_.forEachRight` for arrays without support for * callback shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { if (iteratee(array[length], length, array) === false) { break; } } return array; } /** * A specialized version of `_.every` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. */ function arrayEvery(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (!predicate(array[index], index, array)) { return false; } } return true; } /** * A specialized version of `_.filter` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { var index = -1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result[++resIndex] = value; } } return result; } /** * A specialized version of `_.map` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { result[index] = iteratee(array[index], index, array); } return result; } /** * A specialized version of `_.max` for arrays without support for iteratees. * * @private * @param {Array} array The array to iterate over. * @returns {*} Returns the maximum value. */ function arrayMax(array) { var index = -1, length = array.length, result = NEGATIVE_INFINITY; while (++index < length) { var value = array[index]; if (value > result) { result = value; } } return result; } /** * A specialized version of `_.min` for arrays without support for iteratees. * * @private * @param {Array} array The array to iterate over. * @returns {*} Returns the minimum value. */ function arrayMin(array) { var index = -1, length = array.length, result = POSITIVE_INFINITY; while (++index < length) { var value = array[index]; if (value < result) { result = value; } } return result; } /** * A specialized version of `_.reduce` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray] Specify using the first element of `array` * as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, length = array.length; if (initFromArray && length) { accumulator = array[++index]; } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } /** * A specialized version of `_.reduceRight` for arrays without support for * callback shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initFromArray] Specify using the last element of `array` * as the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduceRight(array, iteratee, accumulator, initFromArray) { var length = array.length; if (initFromArray && length) { accumulator = array[--length]; } while (length--) { accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } /** * A specialized version of `_.some` for arrays without support for callback * shorthands or `this` binding. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function arraySome(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (predicate(array[index], index, array)) { return true; } } return false; } /** * Used by `_.defaults` to customize its `_.assign` use. * * @private * @param {*} objectValue The destination object property value. * @param {*} sourceValue The source object property value. * @returns {*} Returns the value to assign to the destination object. */ function assignDefaults(objectValue, sourceValue) { return typeof objectValue == 'undefined' ? sourceValue : objectValue; } /** * Used by `_.template` to customize its `_.assign` use. * * **Note:** This method is like `assignDefaults` except that it ignores * inherited property values when checking if a property is `undefined`. * * @private * @param {*} objectValue The destination object property value. * @param {*} sourceValue The source object property value. * @param {string} key The key associated with the object and source values. * @param {Object} object The destination object. * @returns {*} Returns the value to assign to the destination object. */ function assignOwnDefaults(objectValue, sourceValue, key, object) { return (typeof objectValue == 'undefined' || !hasOwnProperty.call(object, key)) ? sourceValue : objectValue; } /** * The base implementation of `_.assign` without support for argument juggling, * multiple sources, and `this` binding `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize assigning values. * @returns {Object} Returns the destination object. */ function baseAssign(object, source, customizer) { var props = keys(source); if (!customizer) { return baseCopy(source, object, props); } var index = -1, length = props.length while (++index < length) { var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); if ((result === result ? result !== value : value === value) || (typeof value == 'undefined' && !(key in object))) { object[key] = result; } } return object; } /** * The base implementation of `_.at` without support for strings and individual * key arguments. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {number[]|string[]} [props] The property names or indexes of elements to pick. * @returns {Array} Returns the new array of picked elements. */ function baseAt(collection, props) { var index = -1, length = collection.length, isArr = isLength(length), propsLength = props.length, result = Array(propsLength); while(++index < propsLength) { var key = props[index]; if (isArr) { key = parseFloat(key); result[index] = isIndex(key, length) ? collection[key] : undefined; } else { result[index] = collection[key]; } } return result; } /** * Copies the properties of `source` to `object`. * * @private * @param {Object} source The object to copy properties from. * @param {Object} [object={}] The object to copy properties to. * @param {Array} props The property names to copy. * @returns {Object} Returns `object`. */ function baseCopy(source, object, props) { if (!props) { props = object; object = {}; } var index = -1, length = props.length; while (++index < length) { var key = props[index]; object[key] = source[key]; } return object; } /** * The base implementation of `_.bindAll` without support for individual * method name arguments. * * @private * @param {Object} object The object to bind and assign the bound methods to. * @param {string[]} methodNames The object method names to bind. * @returns {Object} Returns `object`. */ function baseBindAll(object, methodNames) { var index = -1, length = methodNames.length; while (++index < length) { var key = methodNames[index]; object[key] = createWrapper(object[key], BIND_FLAG, object); } return object; } /** * The base implementation of `_.callback` which supports specifying the * number of arguments to provide to `func`. * * @private * @param {*} [func=_.identity] The value to convert to a callback. * @param {*} [thisArg] The `this` binding of `func`. * @param {number} [argCount] The number of arguments to provide to `func`. * @returns {Function} Returns the callback. */ function baseCallback(func, thisArg, argCount) { var type = typeof func; if (type == 'function') { return (typeof thisArg != 'undefined' && isBindable(func)) ? bindCallback(func, thisArg, argCount) : func; } if (func == null) { return identity; } // Handle "_.property" and "_.matches" style callback shorthands. return type == 'object' ? baseMatches(func) : baseProperty(func + ''); } /** * The base implementation of `_.clone` without support for argument juggling * and `this` binding `customizer` functions. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {string} [key] The key of `value`. * @param {Object} [object] The object `value` belongs to. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates clones with source counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { var result; if (customizer) { result = object ? customizer(value, key, object) : customizer(value); } if (typeof result != 'undefined') { return result; } if (!isObject(value)) { return value; } var isArr = isArray(value); if (isArr) { result = initCloneArray(value); if (!isDeep) { return arrayCopy(value, result); } } else { var tag = objToString.call(value), isFunc = tag == funcTag; if (tag == objectTag || tag == argsTag || (isFunc && !object)) { result = initCloneObject(isFunc ? {} : value); if (!isDeep) { return baseCopy(value, result, keys(value)); } } else { return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : (object ? value : {}); } } // Check for circular references and return corresponding clone. stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == value) { return stackB[length]; } } // Add the source value to the stack of traversed objects and associate it with its clone. stackA.push(value); stackB.push(result); // Recursively populate clone (susceptible to call stack limits). (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); }); return result; } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} prototype The object to inherit from. * @returns {Object} Returns the new object. */ var baseCreate = (function() { function Object() {} return function(prototype) { if (isObject(prototype)) { Object.prototype = prototype; var result = new Object; Object.prototype = null; } return result || context.Object(); }; }()); /** * The base implementation of `_.delay` and `_.defer` which accepts an index * of where to slice the arguments to provide to `func`. * * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Object} args The `arguments` object to slice and provide to `func`. * @returns {number} Returns the timer id. */ function baseDelay(func, wait, args, fromIndex) { if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); } /** * The base implementation of `_.difference` which accepts a single array * of values to exclude. * * @private * @param {Array} array The array to inspect. * @param {Array} values The values to exclude. * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values) { var length = array ? array.length : 0, result = []; if (!length) { return result; } var index = -1, indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf, cache = isCommon && values.length >= 200 && createCache(values), valuesLength = values.length; if (cache) { indexOf = cacheIndexOf; isCommon = false; values = cache; } outer: while (++index < length) { var value = array[index]; if (isCommon && value === value) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === value) { continue outer; } } result.push(value); } else if (indexOf(values, value) < 0) { result.push(value); } } return result; } /** * The base implementation of `_.forEach` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEach(collection, iteratee) { var length = collection ? collection.length : 0; if (!isLength(length)) { return baseForOwn(collection, iteratee); } var index = -1, iterable = toObject(collection); while (++index < length) { if (iteratee(iterable[index], index, iterable) === false) { break; } } return collection; } /** * The base implementation of `_.forEachRight` without support for callback * shorthands and `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object|string} Returns `collection`. */ function baseEachRight(collection, iteratee) { var length = collection ? collection.length : 0; if (!isLength(length)) { return baseForOwnRight(collection, iteratee); } var iterable = toObject(collection); while (length--) { if (iteratee(iterable[length], length, iterable) === false) { break; } } return collection; } /** * The base implementation of `_.every` without support for callback * shorthands or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false` */ function baseEvery(collection, predicate) { var result = true; baseEach(collection, function(value, index, collection) { result = !!predicate(value, index, collection); return result; }); return result; } /** * The base implementation of `_.filter` without support for callback * shorthands or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { var result = []; baseEach(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result.push(value); } }); return result; } /** * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, * without support for callback shorthands and `this` binding, which iterates * over `collection` using the provided `eachFunc`. * * @private * @param {Array|Object|string} collection The collection to search. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey] Specify returning the key of the found element * instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { var result; eachFunc(collection, function(value, key, collection) { if (predicate(value, key, collection)) { result = retKey ? key : value; return false; } }); return result; } /** * The base implementation of `_.flatten` with added support for restricting * flattening and specifying the start index. * * @private * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param {boolean} [isStrict] Restrict flattening to arrays and `arguments` objects. * @param {number} [fromIndex=0] The index to start from. * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, isDeep, isStrict, fromIndex) { var index = (fromIndex || 0) - 1, length = array.length, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) { if (isDeep) { // Recursively flatten arrays (susceptible to call stack limits). value = baseFlatten(value, isDeep, isStrict); } var valIndex = -1, valLength = value.length; result.length += valLength; while (++valIndex < valLength) { result[++resIndex] = value[valIndex]; } } else if (!isStrict) { result[++resIndex] = value; } } return result; } /** * The base implementation of `baseForIn` and `baseForOwn` which iterates * over `object` properties returned by `keysFunc` invoking `iteratee` for * each property. Iterator functions may exit iteration early by explicitly * returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ function baseFor(object, iteratee, keysFunc) { var index = -1, iterable = toObject(object), props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; if (iteratee(iterable[key], key, iterable) === false) { break; } } return object; } /** * This function is like `baseFor` except that it iterates over properties * in the opposite order. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ function baseForRight(object, iteratee, keysFunc) { var iterable = toObject(object), props = keysFunc(object), length = props.length; while (length--) { var key = props[length]; if (iteratee(iterable[key], key, iterable) === false) { break; } } return object; } /** * The base implementation of `_.forIn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForIn(object, iteratee) { return baseFor(object, iteratee, keysIn); } /** * The base implementation of `_.forOwn` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return baseFor(object, iteratee, keys); } /** * The base implementation of `_.forOwnRight` without support for callback * shorthands and `this` binding. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { return baseForRight(object, iteratee, keys); } /** * The base implementation of `_.functions` which creates an array of * `object` function property names filtered from those provided. * * @private * @param {Object} object The object to inspect. * @param {Array} props The property names to filter. * @returns {Array} Returns the new array of filtered property names. */ function baseFunctions(object, props) { var index = -1, length = props.length, resIndex = -1, result = []; while (++index < length) { var key = props[index]; if (isFunction(object[key])) { result[++resIndex] = key; } } return result; } /** * The base implementation of `_.invoke` which requires additional arguments * to be provided as an array of arguments rather than individually. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {Array} [args] The arguments to invoke the method with. * @returns {Array} Returns the array of results. */ function baseInvoke(collection, methodName, args) { var index = -1, isFunc = typeof methodName == 'function', length = collection ? collection.length : 0, result = isLength(length) ? Array(length) : []; baseEach(collection, function(value) { var func = isFunc ? methodName : (value != null && value[methodName]); result[++index] = func ? func.apply(value, args) : undefined; }); return result; } /** * The base implementation of `_.isEqual` without support for `this` binding * `customizer` functions. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparing values. * @param {boolean} [isWhere] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { // Exit early for identical values. if (value === other) { // Treat `+0` vs. `-0` as not equal. return value !== 0 || (1 / value == 1 / other); } var valType = typeof value, othType = typeof other; // Exit early for unlike primitive values. if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') || value == null || other == null) { // Return `false` unless both values are `NaN`. return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB); } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing objects. * @param {boolean} [isWhere] Specify performing partial comparisons. * @param {Array} [stackA=[]] Tracks traversed `value` objects. * @param {Array} [stackB=[]] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; if (!objIsArr) { objTag = objToString.call(object); if (objTag == argsTag) { objTag = objectTag; } else if (objTag != objectTag) { objIsArr = isTypedArray(object); } } if (!othIsArr) { othTag = objToString.call(other); if (othTag == argsTag) { othTag = objectTag; } else if (othTag != objectTag) { othIsArr = isTypedArray(other); } } var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; if (isSameTag && !(objIsArr || objIsObj)) { return equalByTag(object, other, objTag); } var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (valWrapped || othWrapped) { return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); } if (!isSameTag) { return false; } // Assume cyclic values are equal. // For more information on detecting circular references see https://es5.github.io/#JO. stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == object) { return stackB[length] == other; } } // Add `object` and `other` to the stack of traversed objects. stackA.push(object); stackB.push(other); var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB); stackA.pop(); stackB.pop(); return result; } /** * The base implementation of `_.isMatch` without support for callback * shorthands or `this` binding. * * @private * @param {Object} source The object to inspect. * @param {Array} props The source property names to match. * @param {Array} values The source values to match. * @param {Array} strictCompareFlags Strict comparison flags for source values. * @param {Function} [customizer] The function to customize comparing objects. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, props, values, strictCompareFlags, customizer) { var length = props.length; if (object == null) { return !length; } var index = -1, noCustomizer = !customizer; while (++index < length) { if ((noCustomizer && strictCompareFlags[index]) ? values[index] !== object[props[index]] : !hasOwnProperty.call(object, props[index]) ) { return false; } } index = -1; while (++index < length) { var key = props[index]; if (noCustomizer && strictCompareFlags[index]) { var result = hasOwnProperty.call(object, key); } else { var objValue = object[key], srcValue = values[index]; result = customizer ? customizer(objValue, srcValue, key) : undefined; if (typeof result == 'undefined') { result = baseIsEqual(srcValue, objValue, customizer, true); } } if (!result) { return false; } } return true; } /** * The base implementation of `_.map` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { var result = []; baseEach(collection, function(value, key, collection) { result.push(iteratee(value, key, collection)); }); return result; } /** * The base implementation of `_.matches` which supports specifying whether * `source` should be cloned. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new function. */ function baseMatches(source) { var props = keys(source), length = props.length; if (length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { return function(object) { return object != null && value === object[key] && hasOwnProperty.call(object, key); }; } } var values = Array(length), strictCompareFlags = Array(length); while (length--) { value = source[props[length]]; values[length] = value; strictCompareFlags[length] = isStrictComparable(value); } return function(object) { return baseIsMatch(object, props, values, strictCompareFlags); }; } /** * The base implementation of `_.merge` without support for argument juggling, * multiple sources, and `this` binding `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {Object} Returns the destination object. */ function baseMerge(object, source, customizer, stackA, stackB) { var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source)); (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { if (isObjectLike(srcValue)) { stackA || (stackA = []); stackB || (stackB = []); return baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); } var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = typeof result == 'undefined'; if (isCommon) { result = srcValue; } if ((isSrcArr || typeof result != 'undefined') && (isCommon || (result === result ? result !== value : value === value))) { object[key] = result; } }); return object; } /** * A specialized version of `baseMerge` for arrays and objects which performs * deep merges and tracks traversed objects enabling objects with circular * references to be merged. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {Function} mergeFunc The function to merge values. * @param {Function} [customizer] The function to customize merging properties. * @param {Array} [stackA=[]] Tracks traversed source objects. * @param {Array} [stackB=[]] Associates values with source counterparts. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { var length = stackA.length, srcValue = source[key]; while (length--) { if (stackA[length] == srcValue) { object[key] = stackB[length]; return; } } var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = typeof result == 'undefined'; if (isCommon) { result = srcValue; if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { result = isArray(value) ? value : (value ? arrayCopy(value) : []); } else if (isPlainObject(srcValue) || isArguments(srcValue)) { result = isArguments(value) ? toPlainObject(value) : (isPlainObject(value) ? value : {}); } else { isCommon = false; } } // Add the source value to the stack of traversed objects and associate // it with its merged value. stackA.push(srcValue); stackB.push(result); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); } else if (result === result ? result !== value : value === value) { object[key] = result; } } /** * The base implementation of `_.property` which does not coerce `key` to a string. * * @private * @param {string} key The key of the property to get. * @returns {Function} Returns the new function. */ function baseProperty(key) { return function(object) { return object == null ? undefined : object[key]; }; } /** * The base implementation of `_.pullAt` without support for individual * index arguments. * * @private * @param {Array} array The array to modify. * @param {number[]} indexes The indexes of elements to remove. * @returns {Array} Returns the new array of removed elements. */ function basePullAt(array, indexes) { var length = indexes.length, result = baseAt(array, indexes); indexes.sort(baseCompareAscending); while (length--) { var index = parseFloat(indexes[length]); if (index != previous && isIndex(index)) { var previous = index; splice.call(array, index, 1); } } return result; } /** * The base implementation of `_.random` without support for argument juggling * and returning floating-point numbers. * * @private * @param {number} min The minimum possible value. * @param {number} max The maximum possible value. * @returns {number} Returns the random number. */ function baseRandom(min, max) { return min + floor(nativeRandom() * (max - min + 1)); } /** * The base implementation of `_.reduce` and `_.reduceRight` without support * for callback shorthands or `this` binding, which iterates over `collection` * using the provided `eachFunc`. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initFromCollection Specify using the first or last element * of `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection) }); return accumulator; } /** * The base implementation of `setData` without support for hot loop detection. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var baseSetData = !metaMap ? identity : function(func, data) { metaMap.set(func, data); return func; }; /** * The base implementation of `_.slice` without an iteratee call guard. * * @private * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function baseSlice(array, start, end) { var index = -1, length = array.length; start = start == null ? 0 : (+start || 0); if (start < 0) { start = -start > length ? 0 : (length + start); } end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); if (end < 0) { end += length; } length = start > end ? 0 : (end - start) >>> 0; start >>>= 0; var result = Array(length); while (++index < length) { result[index] = array[index + start]; } return result; } /** * The base implementation of `_.some` without support for callback shorthands * or `this` binding. * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function baseSome(collection, predicate) { var result; baseEach(collection, function(value, index, collection) { result = predicate(value, index, collection); return !result; }); return !!result; } /** * The base implementation of `_.uniq` without support for callback shorthands * and `this` binding. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The function invoked per iteration. * @returns {Array} Returns the new duplicate-value-free array. */ function baseUniq(array, iteratee) { var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf == baseIndexOf, isLarge = isCommon && length >= 200, seen = isLarge && createCache(), result = []; if (seen) { indexOf = cacheIndexOf; isCommon = false; } else { isLarge = false; seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; if (isCommon && value === value) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } if (iteratee) { seen.push(computed); } result.push(value); } else if (indexOf(seen, computed) < 0) { if (iteratee || isLarge) { seen.push(computed); } result.push(value); } } return result; } /** * The base implementation of `_.values` and `_.valuesIn` which creates an * array of `object` property values corresponding to the property names * returned by `keysFunc`. * * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. * @returns {Object} Returns the array of property values. */ function baseValues(object, props) { var index = -1, length = props.length, result = Array(length); while (++index < length) { result[index] = object[props[index]]; } return result; } /** * The base implementation of `wrapperValue` which returns the result of * performing a sequence of actions on the unwrapped `value`, where each * successive action is supplied the return value of the previous. * * @private * @param {*} value The unwrapped value. * @param {Array} actions Actions to peform to resolve the unwrapped value. * @returns {*} Returns the resolved unwrapped value. */ function baseWrapperValue(value, actions) { var result = value; if (result instanceof LazyWrapper) { result = result.value(); } var index = -1, length = actions.length; while (++index < length) { var args = [result], action = actions[index]; push.apply(args, action.args); result = action.func.apply(action.thisArg, args); } return result; } /** * Performs a binary search of `array` to determine the index at which `value` * should be inserted into `array` in order to maintain its sort order. * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {boolean} [retHighest] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function binaryIndex(array, value, retHighest) { var low = 0, high = array ? array.length : low; if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { while (low < high) { var mid = (low + high) >>> 1, computed = array[mid]; if (retHighest ? (computed <= value) : (computed < value)) { low = mid + 1; } else { high = mid; } } return high; } return binaryIndexBy(array, value, identity, retHighest); } /** * This function is like `binaryIndex` except that it invokes `iteratee` for * `value` and each element of `array` to compute their sort ranking. The * iteratee is invoked with one argument; (value). * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [retHighest] Specify returning the highest, instead * of the lowest, index at which a value should be inserted into `array`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function binaryIndexBy(array, value, iteratee, retHighest) { value = iteratee(value); var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsUndef = typeof value == 'undefined'; while (low < high) { var mid = floor((low + high) / 2), computed = iteratee(array[mid]), isReflexive = computed === computed; if (valIsNaN) { var setLow = isReflexive || retHighest; } else if (valIsUndef) { setLow = isReflexive && (retHighest || typeof computed != 'undefined'); } else { setLow = retHighest ? (computed <= value) : (computed < value); } if (setLow) { low = mid + 1; } else { high = mid; } } return nativeMin(high, MAX_ARRAY_INDEX); } /** * A specialized version of `baseCallback` which only supports `this` binding * and specifying the number of arguments to provide to `func`. * * @private * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. * @param {number} [argCount] The number of arguments to provide to `func`. * @returns {Function} Returns the callback. */ function bindCallback(func, thisArg, argCount) { if (typeof func != 'function') { return identity; } if (typeof thisArg == 'undefined') { return func; } switch (argCount) { case 1: return function(value) { return func.call(thisArg, value); }; case 3: return function(value, index, collection) { return func.call(thisArg, value, index, collection); }; case 4: return function(accumulator, value, index, collection) { return func.call(thisArg, accumulator, value, index, collection); }; case 5: return function(value, other, key, object, source) { return func.call(thisArg, value, other, key, object, source); }; } return function() { return func.apply(thisArg, arguments); }; } /** * Creates a clone of the given array buffer. * * @private * @param {ArrayBuffer} buffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function bufferClone(buffer) { return bufferSlice.call(buffer, 0); } if (!bufferSlice) { // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { var byteLength = buffer.byteLength, floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, result = new ArrayBuffer(byteLength); if (floatLength) { var view = new Float64Array(result, 0, floatLength); view.set(new Float64Array(buffer, 0, floatLength)); } if (byteLength != offset) { view = new Uint8Array(result, offset); view.set(new Uint8Array(buffer, offset)); } return result; }; } /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private * @param {Array|Object} args The provided arguments. * @param {Array} partials The arguments to prepend to those provided. * @param {Array} holders The `partials` placeholder indexes. * @returns {Array} Returns the new array of composed arguments. */ function composeArgs(args, partials, holders) { var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(argsLength + leftLength); while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; } while (++argsIndex < holdersLength) { result[holders[argsIndex]] = args[argsIndex]; } while (argsLength--) { result[leftIndex++] = args[argsIndex++]; } return result; } /** * This function is like `composeArgs` except that the arguments composition * is tailored for `_.partialRight`. * * @private * @param {Array|Object} args The provided arguments. * @param {Array} partials The arguments to append to those provided. * @param {Array} holders The `partials` placeholder indexes. * @returns {Array} Returns the new array of composed arguments. */ function composeArgsRight(args, partials, holders) { var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); while (++argsIndex < argsLength) { result[argsIndex] = args[argsIndex]; } var pad = argsIndex; while (++rightIndex < rightLength) { result[pad + rightIndex] = partials[rightIndex]; } while (++holdersIndex < holdersLength) { result[pad + holders[holdersIndex]] = args[argsIndex++]; } return result; } /** * Creates a function that aggregates a collection, creating an accumulator * object composed from the results of running each element in the collection * through an iteratee. The `setter` sets the keys and values of the accumulator * object. If `initializer` is provided initializes the accumulator object. * * @private * @param {Function} setter The function to set keys and values of the accumulator object. * @param {Function} [initializer] The function to initialize the accumulator object. * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { return function(collection, iteratee, thisArg) { var result = initializer ? initializer() : {}; iteratee = getCallback(iteratee, thisArg, 3); if (isArray(collection)) { var index = -1, length = collection.length; while (++index < length) { var value = collection[index]; setter(result, value, iteratee(value, index, collection), collection); } } else { baseEach(collection, function(value, key, collection) { setter(result, value, iteratee(value, key, collection), collection); }); } return result; }; } /** * Creates a function that assigns properties of source object(s) to a given * destination object. * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { return function() { var length = arguments.length, object = arguments[0]; if (length < 2 || object == null) { return object; } if (length > 3 && isIterateeCall(arguments[1], arguments[2], arguments[3])) { length = 2; } // Juggle arguments. if (length > 3 && typeof arguments[length - 2] == 'function') { var customizer = bindCallback(arguments[--length - 1], arguments[length--], 5); } else if (length > 2 && typeof arguments[length - 1] == 'function') { customizer = arguments[--length]; } var index = 0; while (++index < length) { var source = arguments[index]; if (source) { assigner(object, source, customizer); } } return object; }; } /** * Creates a function that wraps `func` and invokes it with the `this` * binding of `thisArg`. * * @private * @param {Function} func The function to bind. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new bound function. */ function createBindWrapper(func, thisArg) { var Ctor = createCtorWrapper(func); function wrapper() { return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); } return wrapper; } /** * Creates a `Set` cache object to optimize linear searches of large arrays. * * @private * @param {Array} [values] The values to cache. * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. */ var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { return new SetCache(values); }; /** * Creates a function that produces compound words out of the words in a * given string. * * @private * @param {Function} callback The function to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { return function(string) { var index = -1, array = words(deburr(string)), length = array.length, result = ''; while (++index < length) { result = callback(result, array[index], index); } return result; }; } /** * Creates a function that produces an instance of `Ctor` regardless of * whether it was invoked as part of a `new` expression or by `call` or `apply`. * * @private * @param {Function} Ctor The constructor to wrap. * @returns {Function} Returns the new wrapped function. */ function createCtorWrapper(Ctor) { return function() { var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, arguments); // Mimic the constructor's `return` behavior. // See https://es5.github.io/#x13.2.2 for more details. return isObject(result) ? result : thisBinding; }; } /** * Creates a function that gets the extremum value of a collection. * * @private * @param {Function} arrayFunc The function to get the extremum value from an array. * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum, * extremum value. * @returns {Function} Returns the new extremum function. */ function createExtremum(arrayFunc, isMin) { return function(collection, iteratee, thisArg) { if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = null; } var func = getCallback(), noIteratee = iteratee == null; if (!(func === baseCallback && noIteratee)) { noIteratee = false; iteratee = func(iteratee, thisArg, 3); } if (noIteratee) { var isArr = isArray(collection); if (!isArr && isString(collection)) { iteratee = charAtCallback; } else { return arrayFunc(isArr ? collection : toIterable(collection)); } } return extremumBy(collection, iteratee, isMin); }; } /** * Creates a function that wraps `func` and invokes it with optional `this` * binding of, partial application, and currying. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [partialsRight] The arguments to append to those provided to the new function. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG; var Ctor = !isBindKey && createCtorWrapper(func), key = func; function wrapper() { // Avoid `arguments` object use disqualifying optimizations by // converting it to an array before providing it to other functions. var length = arguments.length, index = length, args = Array(length); while (index--) { args[index] = arguments[index]; } if (partials) { args = composeArgs(args, partials, holders); } if (partialsRight) { args = composeArgsRight(args, partialsRight, holdersRight); } if (isCurry || isCurryRight) { var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); length -= argsHolders.length; if (length < arity) { var newArgPos = argPos ? arrayCopy(argPos) : null, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : null, newHoldersRight = isCurry ? null : argsHolders, newPartials = isCurry ? args : null, newPartialsRight = isCurry ? null : args; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); if (!isCurryBound) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity); result.placeholder = placeholder; return result; } } var thisBinding = isBind ? thisArg : this; if (isBindKey) { func = thisBinding[key]; } if (argPos) { args = reorder(args, argPos); } if (isAry && ary < args.length) { args.length = ary; } return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); } return wrapper; } /** * Creates the pad required for `string` based on the given padding length. * The `chars` string may be truncated if the number of padding characters * exceeds the padding length. * * @private * @param {string} string The string to create padding for. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the pad for `string`. */ function createPad(string, length, chars) { var strLength = string.length; length = +length; if (strLength >= length || !nativeIsFinite(length)) { return ''; } var padLength = length - strLength; chars = chars == null ? ' ' : (chars + ''); return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); } /** * Creates a function that wraps `func` and invokes it with the optional `this` * binding of `thisArg` and the `partials` prepended to those provided to * the wrapper. * * @private * @param {Function} func The function to partially apply arguments to. * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. * @param {*} thisArg The `this` binding of `func`. * @param {Array} partials The arguments to prepend to those provided to the new function. * @returns {Function} Returns the new bound function. */ function createPartialWrapper(func, bitmask, thisArg, partials) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { // Avoid `arguments` object use disqualifying optimizations by // converting it to an array before providing it `func`. var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(argsLength + leftLength); while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; } while (argsLength--) { args[leftIndex++] = arguments[++argsIndex]; } return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); } return wrapper; } /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` * 4 - `_.curry` or `_.curryRight` of a bound function * 8 - `_.curry` * 16 - `_.curryRight` * 32 - `_.partial` * 64 - `_.partialRight` * 128 - `_.rearg` * 256 - `_.ary` * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to be partially applied. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && !isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); partials = holders = null; } length -= (holders ? holders.length : 0); if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; partials = holders = null; } var data = !isBindKey && getData(func), newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; if (data && data !== true) { mergeData(newData, data); bitmask = newData[1]; arity = newData[9]; } newData[9] = arity == null ? (isBindKey ? 0 : func.length) : (nativeMax(arity - length, 0) || 0); if (bitmask == BIND_FLAG) { var result = createBindWrapper(newData[0], newData[2]); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { result = createPartialWrapper.apply(null, newData); } else { result = createHybridWrapper.apply(null, newData); } var setter = data ? baseSetData : setData; return setter(result, newData); } /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing arrays. * @param {boolean} [isWhere] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) { var index = -1, arrLength = array.length, othLength = other.length, result = true; if (arrLength != othLength && !(isWhere && othLength > arrLength)) { return false; } // Deep compare the contents, ignoring non-numeric properties. while (result && ++index < arrLength) { var arrValue = array[index], othValue = other[index]; result = undefined; if (customizer) { result = isWhere ? customizer(othValue, arrValue, index) : customizer(arrValue, othValue, index); } if (typeof result == 'undefined') { // Recursively compare arrays (susceptible to call stack limits). if (isWhere) { var othIndex = othLength; while (othIndex--) { othValue = other[othIndex]; result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); if (result) { break; } } } else { result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); } } } return !!result; } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} value The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag(object, other, tag) { switch (tag) { case boolTag: case dateTag: // Coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. return +object == +other; case errorTag: return object.name == other.name && object.message == other.message; case numberTag: // Treat `NaN` vs. `NaN` as equal. return (object != +object) ? other != +other // But, treat `-0` vs. `+0` as not equal. : (object == 0 ? ((1 / object) == (1 / other)) : object == +other); case regexpTag: case stringTag: // Coerce regexes to strings and treat strings primitives and string // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. return object == (other + ''); } return false; } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparing values. * @param {boolean} [isWhere] Specify performing partial comparisons. * @param {Array} [stackA] Tracks traversed `value` objects. * @param {Array} [stackB] Tracks traversed `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) { var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; if (objLength != othLength && !isWhere) { return false; } var hasCtor, index = -1; while (++index < objLength) { var key = objProps[index], result = hasOwnProperty.call(other, key); if (result) { var objValue = object[key], othValue = other[key]; result = undefined; if (customizer) { result = isWhere ? customizer(othValue, objValue, key) : customizer(objValue, othValue, key); } if (typeof result == 'undefined') { // Recursively compare objects (susceptible to call stack limits). result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB); } } if (!result) { return false; } hasCtor || (hasCtor = key == 'constructor'); } if (!hasCtor) { var objCtor = object.constructor, othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal. if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { return false; } } return true; } /** * Gets the extremum value of `collection` invoking `iteratee` for each value * in `collection` to generate the criterion by which the value is ranked. * The `iteratee` is invoked with three arguments; (value, index, collection). * * @private * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {boolean} [isMin] Specify returning the minimum, instead of the * maximum, extremum value. * @returns {*} Returns the extremum value. */ function extremumBy(collection, iteratee, isMin) { var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY, computed = exValue, result = computed; baseEach(collection, function(value, index, collection) { var current = iteratee(value, index, collection); if ((isMin ? current < computed : current > computed) || (current === exValue && current === result)) { computed = current; result = value; } }); return result; } /** * Gets the appropriate "callback" function. If the `_.callback` method is * customized this function returns the custom method, otherwise it returns * the `baseCallback` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function} Returns the chosen function or its result. */ function getCallback(func, thisArg, argCount) { var result = lodash.callback || callback; result = result === callback ? baseCallback : result; return argCount ? result(func, thisArg, argCount) : result; } /** * Gets metadata for `func`. * * @private * @param {Function} func The function to query. * @returns {*} Returns the metadata for `func`. */ var getData = !metaMap ? noop : function(func) { return metaMap.get(func); }; /** * Gets the appropriate "indexOf" function. If the `_.indexOf` method is * customized this function returns the custom method, otherwise it returns * the `baseIndexOf` function. If arguments are provided the chosen function * is invoked with them and its result is returned. * * @private * @returns {Function|number} Returns the chosen function or its result. */ function getIndexOf(collection, target, fromIndex) { var result = lodash.indexOf || indexOf; result = result === indexOf ? baseIndexOf : result; return collection ? result(collection, target, fromIndex) : result; } /** * Gets the view, applying any `transforms` to the `start` and `end` positions. * * @private * @param {number} start The start of the view. * @param {number} end The end of the view. * @param {Array} [transforms] The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, length = transforms ? transforms.length : 0; while (++index < length) { var data = transforms[index], size = data.size; switch (data.type) { case 'drop': start += size; break; case 'dropRight': end -= size; break; case 'take': end = nativeMin(end, start + size); break; case 'takeRight': start = nativeMax(start, end - size); break; } } return { 'start': start, 'end': end }; } /** * Initializes an array clone. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the initialized clone. */ function initCloneArray(array) { var length = array.length, result = new array.constructor(length); // Add array properties assigned by `RegExp#exec`. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {Object} object The object to clone. * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { var Ctor = object.constructor; if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { Ctor = Object; } return new Ctor; } /** * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * * @private * @param {Object} object The object to clone. * @param {string} tag The `toStringTag` of the object to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the initialized clone. */ function initCloneByTag(object, tag, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: return bufferClone(object); case boolTag: case dateTag: return new Ctor(+object); case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: var buffer = object.buffer; return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); case numberTag: case stringTag: return new Ctor(object); case regexpTag: var result = new Ctor(object.source, reFlags.exec(object)); result.lastIndex = object.lastIndex; } return result; } /** * Checks if `func` is eligible for `this` binding. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` is eligible, else `false`. */ function isBindable(func) { var support = lodash.support, result = !(support.funcNames ? func.name : support.funcDecomp); if (!result) { var source = fnToString.call(func); if (!support.funcNames) { result = !reFuncName.test(source); } if (!result) { // Check if `func` references the `this` keyword and store the result. result = reThis.test(source) || isNative(func); baseSetData(func, result); } } return result; } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { value = +value; length = length == null ? MAX_SAFE_INTEGER : length; return value > -1 && value % 1 == 0 && value < length; } /** * Checks if the provided arguments are from an iteratee call. * * @private * @param {*} value The potential iteratee value argument. * @param {*} index The potential iteratee index or key argument. * @param {*} object The potential iteratee object argument. * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. */ function isIterateeCall(value, index, object) { if (!isObject(object)) { return false; } var type = typeof index; if (type == 'number') { var length = object.length, prereq = isLength(length) && isIndex(index, length); } else { prereq = type == 'string' && index in object; } return prereq && object[index] === value; } /** * Checks if `value` is a valid array-like length. * * **Note:** This function is based on ES `ToLength`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) * for more details. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. */ function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); } /** * Merges the function metadata of `source` into `data`. * * Merging metadata reduces the number of wrappers required to invoke a function. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` * augment function arguments, making the order in which they are executed important, * preventing the merging of metadata. However, we make an exception for a safe * common case where curried functions have `_.ary` and or `_.rearg` applied. * * @private * @param {Array} data The destination metadata. * @param {Array} source The source metadata. * @returns {Array} Returns `data`. */ function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask; var arityFlags = ARY_FLAG | REARG_FLAG, bindFlags = BIND_FLAG | BIND_KEY_FLAG, comboFlags = arityFlags | bindFlags | CURRY_BOUND_FLAG | CURRY_RIGHT_FLAG; var isAry = bitmask & ARY_FLAG && !(srcBitmask & ARY_FLAG), isRearg = bitmask & REARG_FLAG && !(srcBitmask & REARG_FLAG), argPos = (isRearg ? data : source)[7], ary = (isAry ? data : source)[8]; var isCommon = !(bitmask >= REARG_FLAG && srcBitmask > bindFlags) && !(bitmask > bindFlags && srcBitmask >= REARG_FLAG); var isCombo = (newBitmask >= arityFlags && newBitmask <= comboFlags) && (bitmask < REARG_FLAG || ((isRearg || isAry) && argPos.length <= ary)); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { return data; } // Use source `thisArg` if available. if (srcBitmask & BIND_FLAG) { data[2] = source[2]; // Set when currying a bound function. newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG; } // Compose partial arguments. var value = source[3]; if (value) { var partials = data[3]; data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); } // Compose partial right arguments. value = source[5]; if (value) { partials = data[5]; data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); } // Use source `argPos` if available. value = source[7]; if (value) { data[7] = arrayCopy(value); } // Use source `ary` if it's smaller. if (srcBitmask & ARY_FLAG) { data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); } // Use source `arity` if one is not provided. if (data[9] == null) { data[9] = source[9]; } // Use source `func` and merge bitmasks. data[0] = source[0]; data[1] = newBitmask; return data; } /** * A specialized version of `_.pick` that picks `object` properties specified * by the `props` array. * * @private * @param {Object} object The source object. * @param {string[]} props The property names to pick. * @returns {Object} Returns the new object. */ function pickByArray(object, props) { object = toObject(object); var index = -1, length = props.length, result = {}; while (++index < length) { var key = props[index]; if (key in object) { result[key] = object[key]; } } return result; } /** * A specialized version of `_.pick` that picks `object` properties `predicate` * returns truthy for. * * @private * @param {Object} object The source object. * @param {Function} predicate The function invoked per iteration. * @returns {Object} Returns the new object. */ function pickByCallback(object, predicate) { var result = {}; baseForIn(object, function(value, key, object) { if (predicate(value, key, object)) { result[key] = value; } }); return result; } /** * Reorder `array` according to the specified indexes where the element at * the first index is assigned as the first element, the element at * the second index is assigned as the second element, and so on. * * @private * @param {Array} array The array to reorder. * @param {Array} indexes The arranged array indexes. * @returns {Array} Returns `array`. */ function reorder(array, indexes) { var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); while (length--) { var index = indexes[length]; array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; } return array; } /** * Sets metadata for `func`. * * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity function * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) * for more details. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var setData = (function() { var count = 0, lastCalled = 0; return function(key, value) { var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { return key; } } else { count = 0; } return baseSetData(key, value); }; }()); /** * A fallback implementation of `_.isPlainObject` which checks if `value` * is an object created by the `Object` constructor or has a `[[Prototype]]` * of `null`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. */ function shimIsPlainObject(value) { var Ctor, support = lodash.support; // Exit early for non `Object` objects. if (!(isObjectLike(value) && objToString.call(value) == objectTag) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { return false; } // IE < 9 iterates inherited properties before own properties. If the first // iterated property is an object's own property then there are no inherited // enumerable properties. var result; // In most environments an object's own properties are iterated before // its inherited properties. If the last iterated property is an object's // own property then there are no inherited enumerable properties. baseForIn(value, function(subValue, key) { result = key; }); return typeof result == 'undefined' || hasOwnProperty.call(value, result); } /** * A fallback implementation of `Object.keys` which creates an array of the * own enumerable property names of `object`. * * @private * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. */ function shimKeys(object) { var props = keysIn(object), propsLength = props.length, length = propsLength && object.length, support = lodash.support; var allowIndexes = length && isLength(length) && (isArray(object) || (support.nonEnumArgs && isArguments(object))); var index = -1, result = []; while (++index < propsLength) { var key = props[index]; if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { result.push(key); } } return result; } /** * Converts `value` to an array-like object if it is not one. * * @private * @param {*} value The value to process. * @returns {Array|Object} Returns the array-like object. */ function toIterable(value) { if (value == null) { return []; } if (!isLength(value.length)) { return values(value); } return isObject(value) ? value : Object(value); } /** * Converts `value` to an object if it is not one. * * @private * @param {*} value The value to process. * @returns {Object} Returns the object. */ function toObject(value) { return isObject(value) ? value : Object(value); } /*------------------------------------------------------------------------*/ /** * Creates an array of elements split into groups the length of `size`. * If `collection` can't be split evenly, the final chunk will be the remaining * elements. * * @static * @memberOf _ * @category Array * @param {Array} array The array to process. * @param {numer} [size=1] The length of each chunk. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new array containing chunks. * @example * * _.chunk(['a', 'b', 'c', 'd'], 2); * // => [['a', 'b'], ['c', 'd']] * * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ function chunk(array, size, guard) { if (guard ? isIterateeCall(array, size, guard) : size == null) { size = 1; } else { size = nativeMax(+size || 1, 1); } var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(ceil(length / size)); while (index < length) { result[++resIndex] = baseSlice(array, index, (index += size)); } return result; } /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are falsey. * * @static * @memberOf _ * @category Array * @param {Array} array The array to compact. * @returns {Array} Returns the new array of filtered values. * @example * * _.compact([0, 1, false, 2, '', 3]); * // => [1, 2, 3] */ function compact(array) { var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; while (++index < length) { var value = array[index]; if (value) { result[++resIndex] = value; } } return result; } /** * Creates an array excluding all values of the provided arrays using * `SameValueZero` for equality comparisons. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The arrays of values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * * _.difference([1, 2, 3], [5, 2, 10]); * // => [1, 3] */ function difference() { var index = -1, length = arguments.length; while (++index < length) { var value = arguments[index]; if (isArray(value) || isArguments(value)) { break; } } return baseDifference(value, baseFlatten(arguments, false, true, ++index)); } /** * Creates a slice of `array` with `n` elements dropped from the beginning. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.drop([1, 2, 3]); * // => [2, 3] * * _.drop([1, 2, 3], 2); * // => [3] * * _.drop([1, 2, 3], 5); * // => [] * * _.drop([1, 2, 3], 0); * // => [1, 2, 3] */ function drop(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } if (guard ? isIterateeCall(array, n, guard) : n == null) { n = 1; } return baseSlice(array, n < 0 ? 0 : n); } /** * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRight([1, 2, 3]); * // => [1, 2] * * _.dropRight([1, 2, 3], 2); * // => [1] * * _.dropRight([1, 2, 3], 5); * // => [] * * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ function dropRight(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } if (guard ? isIterateeCall(array, n, guard) : n == null) { n = 1; } n = length - (+n || 0); return baseSlice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` excluding elements dropped from the end. * Elements are dropped until `predicate` returns falsey. The predicate is * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [1] * * var users = [ * { 'user': 'barney', 'status': 'busy', 'active': false }, * { 'user': 'fred', 'status': 'busy', 'active': true }, * { 'user': 'pebbles', 'status': 'away', 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.dropRightWhile(users, 'active'), 'user'); * // => ['barney'] * * // using the "_.matches" callback shorthand * _.pluck(_.dropRightWhile(users, { 'status': 'away' }), 'user'); * // => ['barney', 'fred'] */ function dropRightWhile(array, predicate, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } predicate = getCallback(predicate, thisArg, 3); while (length-- && predicate(array[length], length, array)) {} return baseSlice(array, 0, length + 1); } /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements are dropped until `predicate` returns falsey. The predicate is * bound to `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropWhile([1, 2, 3], function(n) { return n < 3; }); * // => [3] * * var users = [ * { 'user': 'barney', 'status': 'busy', 'active': true }, * { 'user': 'fred', 'status': 'busy', 'active': false }, * { 'user': 'pebbles', 'status': 'away', 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.dropWhile(users, 'active'), 'user'); * // => ['fred', 'pebbles'] * * // using the "_.matches" callback shorthand * _.pluck(_.dropWhile(users, { 'status': 'busy' }), 'user'); * // => ['pebbles'] */ function dropWhile(array, predicate, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } var index = -1; predicate = getCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) {} return baseSlice(array, index); } /** * This method is like `_.find` except that it returns the index of the first * element `predicate` returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * _.findIndex(users, function(chr) { return chr.age < 40; }); * // => 0 * * // using the "_.matches" callback shorthand * _.findIndex(users, { 'age': 1 }); * // => 2 * * // using the "_.property" callback shorthand * _.findIndex(users, 'active'); * // => 1 */ function findIndex(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (++index < length) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * This method is like `_.findIndex` except that it iterates over elements * of `collection` from right to left. * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * _.findLastIndex(users, function(chr) { return chr.age < 40; }); * // => 2 * * // using the "_.matches" callback shorthand * _.findLastIndex(users, { 'age': 40 }); * // => 1 * * // using the "_.property" callback shorthand * _.findLastIndex(users, 'active'); * // => 0 */ function findLastIndex(array, predicate, thisArg) { var length = array ? array.length : 0; predicate = getCallback(predicate, thisArg, 3); while (length--) { if (predicate(array[length], length, array)) { return length; } } return -1; } /** * Gets the first element of `array`. * * @static * @memberOf _ * @alias head * @category Array * @param {Array} array The array to query. * @returns {*} Returns the first element of `array`. * @example * * _.first([1, 2, 3]); * // => 1 * * _.first([]); * // => undefined */ function first(array) { return array ? array[0] : undefined; } /** * Flattens a nested array. If `isDeep` is `true` the array is recursively * flattened, otherwise it is only flattened a single level. * * @static * @memberOf _ * @category Array * @param {Array} array The array to flatten. * @param {boolean} [isDeep] Specify a deep flatten. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the new flattened array. * @example * * _.flatten([1, [2], [3, [[4]]]]); * // => [1, 2, 3, [[4]]]; * * // using `isDeep` * _.flatten([1, [2], [3, [[4]]]], true); * // => [1, 2, 3, 4]; */ function flatten(array, isDeep, guard) { var length = array ? array.length : 0; if (guard && isIterateeCall(array, isDeep, guard)) { isDeep = false; } return length ? baseFlatten(array, isDeep) : []; } /** * Recursively flattens a nested array. * * @static * @memberOf _ * @category Array * @param {Array} array The array to recursively flatten. * @returns {Array} Returns the new flattened array. * @example * * _.flattenDeep([1, [2], [3, [[4]]]]); * // => [1, 2, 3, 4]; */ function flattenDeep(array) { var length = array ? array.length : 0; return length ? baseFlatten(array, true) : []; } /** * Gets the index at which the first occurrence of `value` is found in `array` * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, * it is used as the offset from the end of `array`. If `array` is sorted * providing `true` for `fromIndex` performs a faster binary search. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=0] The index to search from or `true` * to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.indexOf([1, 2, 3, 1, 2, 3], 2); * // => 1 * * // using `fromIndex` * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 4 * * // performing a binary search * _.indexOf([4, 4, 5, 5, 6, 6], 5, true); * // => 2 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else if (fromIndex) { var index = binaryIndex(array, value), other = array[index]; return (value === value ? value === other : other !== other) ? index : -1; } return baseIndexOf(array, value, fromIndex); } /** * Gets all but the last element of `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] */ function initial(array) { return dropRight(array, 1); } /** * Creates an array of unique values in all provided arrays using `SameValueZero` * for equality comparisons. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of shared values. * @example * * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2] */ function intersection() { var args = [], argsIndex = -1, argsLength = arguments.length, caches = [], indexOf = getIndexOf(), isCommon = indexOf == baseIndexOf; while (++argsIndex < argsLength) { var value = arguments[argsIndex]; if (isArray(value) || isArguments(value)) { args.push(value); caches.push(isCommon && value.length >= 120 && createCache(argsIndex && value)); } } argsLength = args.length; var array = args[0], index = -1, length = array ? array.length : 0, result = [], seen = caches[0]; outer: while (++index < length) { value = array[index]; if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { argsIndex = argsLength; while (--argsIndex) { var cache = caches[argsIndex]; if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { continue outer; } } if (seen) { seen.push(value); } result.push(value); } } return result; } /** * Gets the last element of `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 */ function last(array) { var length = array ? array.length : 0; return length ? array[length - 1] : undefined; } /** * This method is like `_.indexOf` except that it iterates over elements of * `array` from right to left. * * @static * @memberOf _ * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {boolean|number} [fromIndex=array.length-1] The index to search from * or `true` to perform a binary search on a sorted array. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); * // => 4 * * // using `fromIndex` * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); * // => 1 * * // performing a binary search * _.lastIndexOf([4, 4, 5, 5, 6, 6], 5, true); * // => 3 */ function lastIndexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } var index = length; if (typeof fromIndex == 'number') { index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; } else if (fromIndex) { index = binaryIndex(array, value, true) - 1; var other = array[index]; return (value === value ? value === other : other !== other) ? index : -1; } if (value !== value) { return indexOfNaN(array, index, true); } while (index--) { if (array[index] === value) { return index; } } return -1; } /** * Removes all provided values from `array` using `SameValueZero` for equality * comparisons. * * **Notes:** * - Unlike `_.without`, this method mutates `array`. * - `SameValueZero` comparisons are like strict equality comparisons, e.g. `===`, * except that `NaN` matches `NaN`. See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {...*} [values] The values to remove. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3, 1, 2, 3]; * _.pull(array, 2, 3); * console.log(array); * // => [1, 1] */ function pull() { var array = arguments[0]; if (!(array && array.length)) { return array; } var index = 0, indexOf = getIndexOf(), length = arguments.length; while (++index < length) { var fromIndex = 0, value = arguments[index]; while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { splice.call(array, fromIndex, 1); } } return array; } /** * Removes elements from `array` corresponding to the given indexes and returns * an array of the removed elements. Indexes may be specified as an array of * indexes or as individual arguments. * * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {...(number|number[])} [indexes] The indexes of elements to remove, * specified as individual indexes or arrays of indexes. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [5, 10, 15, 20]; * var evens = _.pullAt(array, [1, 3]); * * console.log(array); * // => [5, 15] * * console.log(evens); * // => [10, 20] */ function pullAt(array) { return basePullAt(array || [], baseFlatten(arguments, false, false, 1)); } /** * Removes all elements from `array` that `predicate` returns truthy for * and returns an array of the removed elements. The predicate is bound to * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * **Note:** Unlike `_.filter`, this method mutates `array`. * * @static * @memberOf _ * @category Array * @param {Array} array The array to modify. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(n) { return n % 2 == 0; }); * * console.log(array); * // => [1, 3] * * console.log(evens); * // => [2, 4] */ function remove(array, predicate, thisArg) { var index = -1, length = array ? array.length : 0, result = []; predicate = getCallback(predicate, thisArg, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result.push(value); splice.call(array, index--, 1); length--; } } return result; } /** * Gets all but the first element of `array`. * * @static * @memberOf _ * @alias tail * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.rest([1, 2, 3]); * // => [2, 3] */ function rest(array) { return drop(array, 1); } /** * Creates a slice of `array` from `start` up to, but not including, `end`. * * **Note:** This function is used instead of `Array#slice` to support node * lists in IE < 9 and to ensure dense arrays are returned. * * @static * @memberOf _ * @category Array * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { var length = array ? array.length : 0; if (!length) { return []; } if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { start = 0; end = length; } return baseSlice(array, start, end); } /** * Uses a binary search to determine the lowest index at which `value` should * be inserted into `array` in order to maintain its sort order. If an iteratee * function is provided it is invoked for `value` and each element of `array` * to compute their sort ranking. The iteratee is bound to `thisArg` and * invoked with one argument; (value). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedIndex([30, 50], 40); * // => 1 * * _.sortedIndex([4, 4, 5, 5, 6, 6], 5); * // => 2 * * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; * * // using an iteratee function * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { * return this.data[word]; * }, dict); * // => 1 * * // using the "_.property" callback shorthand * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); * // => 1 */ function sortedIndex(array, value, iteratee, thisArg) { var func = getCallback(iteratee); return (func === baseCallback && iteratee == null) ? binaryIndex(array, value) : binaryIndexBy(array, value, func(iteratee, thisArg, 1)); } /** * This method is like `_.sortedIndex` except that it returns the highest * index at which `value` should be inserted into `array` in order to * maintain its sort order. * * @static * @memberOf _ * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedLastIndex([4, 4, 5, 5, 6, 6], 5); * // => 4 */ function sortedLastIndex(array, value, iteratee, thisArg) { var func = getCallback(iteratee); return (func === baseCallback && iteratee == null) ? binaryIndex(array, value, true) : binaryIndexBy(array, value, func(iteratee, thisArg, 1), true); } /** * Creates a slice of `array` with `n` elements taken from the beginning. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.take([1, 2, 3]); * // => [1] * * _.take([1, 2, 3], 2); * // => [1, 2] * * _.take([1, 2, 3], 5); * // => [1, 2, 3] * * _.take([1, 2, 3], 0); * // => [] */ function take(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } if (guard ? isIterateeCall(array, n, guard) : n == null) { n = 1; } return baseSlice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` with `n` elements taken from the end. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRight([1, 2, 3]); * // => [3] * * _.takeRight([1, 2, 3], 2); * // => [2, 3] * * _.takeRight([1, 2, 3], 5); * // => [1, 2, 3] * * _.takeRight([1, 2, 3], 0); * // => [] */ function takeRight(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } if (guard ? isIterateeCall(array, n, guard) : n == null) { n = 1; } n = length - (+n || 0); return baseSlice(array, n < 0 ? 0 : n); } /** * Creates a slice of `array` with elements taken from the end. Elements are * taken until `predicate` returns falsey. The predicate is bound to `thisArg` * and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRightWhile([1, 2, 3], function(n) { return n > 1; }); * // => [2, 3] * * var users = [ * { 'user': 'barney', 'status': 'busy', 'active': false }, * { 'user': 'fred', 'status': 'busy', 'active': true }, * { 'user': 'pebbles', 'status': 'away', 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.takeRightWhile(users, 'active'), 'user'); * // => ['fred', 'pebbles'] * * // using the "_.matches" callback shorthand * _.pluck(_.takeRightWhile(users, { 'status': 'away' }), 'user'); * // => ['pebbles'] */ function takeRightWhile(array, predicate, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } predicate = getCallback(predicate, thisArg, 3); while (length-- && predicate(array[length], length, array)) {} return baseSlice(array, length + 1); } /** * Creates a slice of `array` with elements taken from the beginning. Elements * are taken until `predicate` returns falsey. The predicate is bound to * `thisArg` and invoked with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @type Function * @category Array * @param {Array} array The array to query. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per element. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeWhile([1, 2, 3], function(n) { return n < 3; }); * // => [1, 2] * * var users = [ * { 'user': 'barney', 'status': 'busy', 'active': true }, * { 'user': 'fred', 'status': 'busy', 'active': false }, * { 'user': 'pebbles', 'status': 'away', 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.takeWhile(users, 'active'), 'user'); * // => ['barney'] * * // using the "_.matches" callback shorthand * _.pluck(_.takeWhile(users, { 'status': 'busy' }), 'user'); * // => ['barney', 'fred'] */ function takeWhile(array, predicate, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } var index = -1; predicate = getCallback(predicate, thisArg, 3); while (++index < length && predicate(array[index], index, array)) {} return baseSlice(array, 0, index); } /** * Creates an array of unique values, in order, of the provided arrays using * `SameValueZero` for equality comparisons. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of combined values. * @example * * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); * // => [1, 2, 3, 5, 4] */ function union() { return baseUniq(baseFlatten(arguments, false, true)); } /** * Creates a duplicate-value-free version of an array using `SameValueZero` * for equality comparisons. Providing `true` for `isSorted` performs a faster * search algorithm for sorted arrays. If an iteratee function is provided it * is invoked for each value in the array to generate the criterion by which * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, index, array). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @alias unique * @category Array * @param {Array} array The array to inspect. * @param {boolean} [isSorted] Specify the array is sorted. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.property" * or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new duplicate-value-free array. * @example * * _.uniq([1, 2, 1]); * // => [1, 2] * * // using `isSorted` * _.uniq([1, 1, 2], true); * // => [1, 2] * * // using an iteratee function * _.uniq([1, 2.5, 1.5, 2], function(n) { return this.floor(n); }, Math); * // => [1, 2.5] * * // using the "_.property" callback shorthand * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ function uniq(array, isSorted, iteratee, thisArg) { var length = array ? array.length : 0; if (!length) { return []; } // Juggle arguments. if (typeof isSorted != 'boolean' && isSorted != null) { thisArg = iteratee; iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; isSorted = false; } var func = getCallback(); if (!(func === baseCallback && iteratee == null)) { iteratee = func(iteratee, thisArg, 3); } return (isSorted && getIndexOf() == baseIndexOf) ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); } /** * This method is like `_.zip` except that it accepts an array of grouped * elements and creates an array regrouping the elements to their pre-`_.zip` * configuration. * * @static * @memberOf _ * @category Array * @param {Array} array The array of grouped elements to process. * @returns {Array} Returns the new array of regrouped elements. * @example * * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] * * _.unzip(zipped); * // => [['fred', 'barney'], [30, 40], [true, false]] */ function unzip(array) { var index = -1, length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0, result = Array(length); while (++index < length) { result[index] = arrayMap(array, baseProperty(index)); } return result; } /** * Creates an array excluding all provided values using `SameValueZero` for * equality comparisons. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @category Array * @param {Array} array The array to filter. * @param {...*} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. * @example * * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); * // => [2, 3, 4] */ function without(array) { return baseDifference(array, baseSlice(arguments, 1)); } /** * Creates an array that is the symmetric difference of the provided arrays. * See [Wikipedia](https://en.wikipedia.org/wiki/Symmetric_difference) for * more details. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of values. * @example * * _.xor([1, 2, 3], [5, 2, 1, 4]); * // => [3, 5, 4] * * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); * // => [1, 4, 5] */ function xor() { var index = -1, length = arguments.length; while (++index < length) { var array = arguments[index]; if (isArray(array) || isArguments(array)) { var result = result ? baseDifference(result, array).concat(baseDifference(array, result)) : array; } } return result ? baseUniq(result) : []; } /** * Creates an array of grouped elements, the first of which contains the first * elements of the given arrays, the second of which contains the second elements * of the given arrays, and so on. * * @static * @memberOf _ * @category Array * @param {...Array} [arrays] The arrays to process. * @returns {Array} Returns the new array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ function zip() { var length = arguments.length, array = Array(length); while (length--) { array[length] = arguments[length]; } return unzip(array); } /** * Creates an object composed from arrays of property names and values. Provide * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` * or two arrays, one of property names and one of corresponding values. * * @static * @memberOf _ * @alias object * @category Array * @param {Array} props The property names. * @param {Array} [values=[]] The property values. * @returns {Object} Returns the new object. * @example * * _.zipObject(['fred', 'barney'], [30, 40]); * // => { 'fred': 30, 'barney': 40 } */ function zipObject(props, values) { var index = -1, length = props ? props.length : 0, result = {}; if (length && !values && !isArray(props[0])) { values = []; } while (++index < length) { var key = props[index]; if (values) { result[key] = values[index]; } else if (key) { result[key[0]] = key[1]; } } return result; } /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object that wraps `value` with explicit method * chaining enabled. * * @static * @memberOf _ * @category Chain * @param {*} value The value to wrap. * @returns {Object} Returns the new `lodash` object. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'pebbles', 'age': 1 } * ]; * * var youngest = _.chain(users) * .sortBy('age') * .map(function(chr) { return chr.user + ' is ' + chr.age; }) * .first() * .value(); * // => 'pebbles is 1' */ function chain(value) { var result = lodash(value); result.__chain__ = true; return result; } /** * This method invokes `interceptor` and returns `value`. The interceptor is * bound to `thisArg` and invoked with one argument; (value). The purpose of * this method is to "tap into" a method chain in order to perform operations * on intermediate results within the chain. * * @static * @memberOf _ * @category Chain * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns `value`. * @example * * _([1, 2, 3]) * .tap(function(array) { array.pop(); }) * .reverse() * .value(); * // => [2, 1] */ function tap(value, interceptor, thisArg) { interceptor.call(thisArg, value); return value; } /** * This method is like `_.tap` except that it returns the result of `interceptor`. * * @static * @memberOf _ * @category Chain * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @param {*} [thisArg] The `this` binding of `interceptor`. * @returns {*} Returns the result of `interceptor`. * @example * * _([1, 2, 3]) * .last() * .thru(function(value) { return [value]; }) * .value(); * // => [3] */ function thru(value, interceptor, thisArg) { return interceptor.call(thisArg, value); } /** * Enables explicit method chaining on the wrapper object. * * @name chain * @memberOf _ * @category Chain * @returns {*} Returns the `lodash` object. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // without explicit chaining * _(users).first(); * // => { 'user': 'barney', 'age': 36 } * * // with explicit chaining * _(users).chain() * .first() * .pick('user') * .value(); * // => { 'user': 'barney' } */ function wrapperChain() { return chain(this); } /** * Reverses the wrapped array so the first element becomes the last, the * second element becomes the second to last, and so on. * * **Note:** This method mutates the wrapped array. * * @name reverse * @memberOf _ * @category Chain * @returns {Object} Returns the new reversed `lodash` object. * @example * * var array = [1, 2, 3]; * * _(array).reverse().value() * // => [3, 2, 1] * * console.log(array); * // => [3, 2, 1] */ function wrapperReverse() { var value = this.__wrapped__; if (value instanceof LazyWrapper) { if (this.__actions__.length) { value = new LazyWrapper(this); } return new LodashWrapper(value.reverse()); } return this.thru(function(value) { return value.reverse(); }); } /** * Produces the result of coercing the unwrapped value to a string. * * @name toString * @memberOf _ * @category Chain * @returns {string} Returns the coerced string value. * @example * * _([1, 2, 3]).toString(); * // => '1,2,3' */ function wrapperToString() { return (this.value() + ''); } /** * Executes the chained sequence to extract the unwrapped value. * * @name value * @memberOf _ * @alias toJSON, valueOf * @category Chain * @returns {*} Returns the resolved unwrapped value. * @example * * _([1, 2, 3]).value(); * // => [1, 2, 3] */ function wrapperValue() { return baseWrapperValue(this.__wrapped__, this.__actions__); } /*------------------------------------------------------------------------*/ /** * Creates an array of elements corresponding to the given keys, or indexes, * of `collection`. Keys may be specified as individual arguments or as arrays * of keys. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {...(number|number[]|string|string[])} [props] The property names * or indexes of elements to pick, specified individually or in arrays. * @returns {Array} Returns the new array of picked elements. * @example * * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); * // => ['a', 'c', 'e'] * * _.at(['fred', 'barney', 'pebbles'], 0, 2); * // => ['fred', 'pebbles'] */ function at(collection) { var length = collection ? collection.length : 0; if (isLength(length)) { collection = toIterable(collection); } return baseAt(collection, baseFlatten(arguments, false, false, 1)); } /** * Checks if `value` is in `collection` using `SameValueZero` for equality * comparisons. If `fromIndex` is negative, it is used as the offset from * the end of `collection`. * * **Note:** `SameValueZero` comparisons are like strict equality comparisons, * e.g. `===`, except that `NaN` matches `NaN`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) * for more details. * * @static * @memberOf _ * @alias contains, include * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {*} target The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {boolean} Returns `true` if a matching element is found, else `false`. * @example * * _.includes([1, 2, 3], 1); * // => true * * _.includes([1, 2, 3], 1, 2); * // => false * * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); * // => true * * _.includes('pebbles', 'eb'); * // => true */ function includes(collection, target, fromIndex) { var length = collection ? collection.length : 0; if (!isLength(length)) { collection = values(collection); length = collection.length; } if (!length) { return false; } if (typeof fromIndex == 'number') { fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); } else { fromIndex = 0; } return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) : (getIndexOf(collection, target, fromIndex) > -1); } /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the number of times the key was returned by `iteratee`. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * _.countBy([4.3, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': 1, '6': 2 } * * _.countBy([4.3, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); }); /** * Checks if `predicate` returns truthy for **all** elements of `collection`. * The predicate is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias all * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes']); * // => false * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // using the "_.property" callback shorthand * _.every(users, 'age'); * // => true * * // using the "_.matches" callback shorthand * _.every(users, { 'age': 36 }); * // => false */ function every(collection, predicate, thisArg) { var func = isArray(collection) ? arrayEvery : baseEvery; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } return func(collection, predicate); } /** * Iterates over elements of `collection`, returning an array of all elements * `predicate` returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias select * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * * var evens = _.filter([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [2, 4] * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.filter(users, 'active'), 'user'); * // => ['fred'] * * // using the "_.matches" callback shorthand * _.pluck(_.filter(users, { 'age': 36 }), 'user'); * // => ['barney'] */ function filter(collection, predicate, thisArg) { var func = isArray(collection) ? arrayFilter : baseFilter; predicate = getCallback(predicate, thisArg, 3); return func(collection, predicate); } /** * Iterates over elements of `collection`, returning the first element * `predicate` returns truthy for. The predicate is bound to `thisArg` and * invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias detect * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * _.result(_.find(users, function(chr) { return chr.age < 40; }), 'user'); * // => 'barney' * * // using the "_.matches" callback shorthand * _.result(_.find(users, { 'age': 1 }), 'user'); * // => 'pebbles' * * // using the "_.property" callback shorthand * _.result(_.find(users, 'active'), 'user'); * // => 'fred' */ function find(collection, predicate, thisArg) { if (isArray(collection)) { var index = findIndex(collection, predicate, thisArg); return index > -1 ? collection[index] : undefined; } predicate = getCallback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEach); } /** * This method is like `_.find` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {*} Returns the matched element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(n) { return n % 2 == 1; }); * // => 3 */ function findLast(collection, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(collection, predicate, baseEachRight); } /** * Performs a deep comparison between each element in `collection` and the * source object, returning the first element that has equivalent property * values. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Object} source The object of property values to match. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'status': 'busy' }, * { 'user': 'fred', 'age': 40, 'status': 'busy' } * ]; * * _.result(_.findWhere(users, { 'status': 'busy' }), 'user'); * // => 'barney' * * _.result(_.findWhere(users, { 'age': 40 }), 'user'); * // => 'fred' */ function findWhere(collection, source) { return find(collection, baseMatches(source)); } /** * Iterates over elements of `collection` invoking `iteratee` for each element. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). Iterator functions may exit iteration early * by explicitly returning `false`. * * **Note:** As with other "Collections" methods, objects with a `length` property * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` * may be used for object iteration. * * @static * @memberOf _ * @alias each * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEach(function(n) { console.log(n); }).value(); * // => logs each value from left to right and returns the array * * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(n, key) { console.log(n, key); }); * // => logs each value-key pair and returns the object (iteration order is not guaranteed) */ function forEach(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEach(collection, iteratee) : baseEach(collection, bindCallback(iteratee, thisArg, 3)); } /** * This method is like `_.forEach` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @alias eachRight * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array|Object|string} Returns `collection`. * @example * * _([1, 2, 3]).forEachRight(function(n) { console.log(n); }).join(','); * // => logs each value from right to left and returns the array */ function forEachRight(collection, iteratee, thisArg) { return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) ? arrayEachRight(collection, iteratee) : baseEachRight(collection, bindCallback(iteratee, thisArg, 3)); } /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is an array of the elements responsible for generating the key. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * _.groupBy([4.2, 6.1, 6.4], function(n) { return Math.floor(n); }); * // => { '4': [4.2], '6': [6.1, 6.4] } * * _.groupBy([4.2, 6.1, 6.4], function(n) { return this.floor(n); }, Math); * // => { '4': [4.2], '6': [6.1, 6.4] } * * // using the "_.property" callback shorthand * _.groupBy(['one', 'two', 'three'], 'length'); * // => { '3': ['one', 'two'], '5': ['three'] } */ var groupBy = createAggregator(function(result, value, key) { if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { result[key] = [value]; } }); /** * Creates an object composed of keys generated from the results of running * each element of `collection` through `iteratee`. The corresponding value * of each key is the last element responsible for generating the key. The * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the composed aggregate object. * @example * * var keyData = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * * _.indexBy(keyData, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keyData, function(object) { return String.fromCharCode(object.code); }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * * _.indexBy(keyData, function(object) { return this.fromCharCode(object.code); }, String); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } */ var indexBy = createAggregator(function(result, value, key) { result[key] = value; }); /** * Invokes the method named by `methodName` on each element in `collection`, * returning an array of the results of each invoked method. Any additional * arguments are provided to each invoked method. If `methodName` is a function * it is invoked for, and `this` bound to, each element in `collection`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|string} methodName The name of the method to invoke or * the function invoked per iteration. * @param {...*} [args] The arguments to invoke the method with. * @returns {Array} Returns the array of results. * @example * * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invoke([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ function invoke(collection, methodName) { return baseInvoke(collection, methodName, baseSlice(arguments, 2)); } /** * Creates an array of values by running each element in `collection` through * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias collect * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new mapped array. * @example * * _.map([1, 2, 3], function(n) { return n * 3; }); * // => [3, 6, 9] * * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(n) { return n * 3; }); * // => [3, 6, 9] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * // using the "_.property" callback shorthand * _.map(users, 'user'); * // => ['barney', 'fred'] */ function map(collection, iteratee, thisArg) { var func = isArray(collection) ? arrayMap : baseMap; iteratee = getCallback(iteratee, thisArg, 3); return func(collection, iteratee); } /** * Gets the maximum value of `collection`. If `collection` is empty or falsey * `-Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.property" * or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the maximum value. * @example * * _.max([4, 2, 8, 6]); * // => 8 * * _.max([]); * // => -Infinity * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.max(users, function(chr) { return chr.age; }); * // => { 'user': 'fred', 'age': 40 }; * * // using the "_.property" callback shorthand * _.max(users, 'age'); * // => { 'user': 'fred', 'age': 40 }; */ var max = createExtremum(arrayMax); /** * Gets the minimum value of `collection`. If `collection` is empty or falsey * `Infinity` is returned. If an iteratee function is provided it is invoked * for each value in `collection` to generate the criterion by which the value * is ranked. The `iteratee` is bound to `thisArg` and invoked with three * arguments; (value, index, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [iteratee] The function invoked per iteration. * If a property name or object is provided it is used to create a "_.property" * or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the minimum value. * @example * * _.min([4, 2, 8, 6]); * // => 2 * * _.min([]); * // => Infinity * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.min(users, function(chr) { return chr.age; }); * // => { 'user': 'barney', 'age': 36 }; * * // using the "_.property" callback shorthand * _.min(users, 'age'); * // => { 'user': 'barney', 'age': 36 }; */ var min = createExtremum(arrayMin, true); /** * Creates an array of elements split into two groups, the first of which * contains elements `predicate` returns truthy for, while the second of which * contains elements `predicate` returns falsey for. The predicate is bound * to `thisArg` and invoked with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the array of grouped elements. * @example * * _.partition([1, 2, 3], function(n) { return n % 2; }); * // => [[1, 3], [2]] * * _.partition([1.2, 2.3, 3.4], function(n) { return this.floor(n) % 2; }, Math); * // => [[1, 3], [2]] * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * // using the "_.matches" callback shorthand * _.map(_.partition(users, { 'age': 1 }), function(array) { return _.pluck(array, 'user'); }); * // => [['pebbles'], ['barney', 'fred']] * * // using the "_.property" callback shorthand * _.map(_.partition(users, 'active'), function(array) { return _.pluck(array, 'user'); }); * // => [['fred'], ['barney', 'pebbles']] */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); }, function() { return [[], []]; }); /** * Gets the value of `key` from all elements in `collection`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {string} key The key of the property to pluck. * @returns {Array} Returns the property values. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * _.pluck(users, 'user'); * // => ['barney', 'fred'] * * var userIndex = _.indexBy(users, 'user'); * _.pluck(userIndex, 'age'); * // => [36, 40] (iteration order is not guaranteed) */ function pluck(collection, key) { return map(collection, baseProperty(key + '')); } /** * Reduces `collection` to a value which is the accumulated result of running * each element in `collection` through `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not provided the first element of `collection` is used as the initial * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; * (accumulator, value, index|key, collection). * * @static * @memberOf _ * @alias foldl, inject * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var sum = _.reduce([1, 2, 3], function(sum, n) { return sum + n; }); * // => 6 * * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { * result[key] = n * 3; * return result; * }, {}); * // => { 'a': 3, 'b': 6, 'c': 9 } (iteration order is not guaranteed) */ function reduce(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduce : baseReduce; return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** * This method is like `_.reduce` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @alias foldr * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var array = [[0, 1], [2, 3], [4, 5]]; * _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, iteratee, accumulator, thisArg) { var func = isArray(collection) ? arrayReduceRight : baseReduce; return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); } /** * The opposite of `_.filter`; this method returns the elements of `collection` * that `predicate` does **not** return truthy for. * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Array} Returns the new filtered array. * @example * * var odds = _.reject([1, 2, 3, 4], function(n) { return n % 2 == 0; }); * // => [1, 3] * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.reject(users, 'active'), 'user'); * // => ['barney'] * * // using the "_.matches" callback shorthand * _.pluck(_.reject(users, { 'age': 36 }), 'user'); * // => ['fred'] */ function reject(collection, predicate, thisArg) { var func = isArray(collection) ? arrayFilter : baseFilter; predicate = getCallback(predicate, thisArg, 3); return func(collection, function(value, index, collection) { return !predicate(value, index, collection); }); } /** * Gets a random element or `n` random elements from a collection. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to sample. * @param {number} [n] The number of elements to sample. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {*} Returns the random sample(s). * @example * * _.sample([1, 2, 3, 4]); * // => 2 * * _.sample([1, 2, 3, 4], 2); * // => [3, 1] */ function sample(collection, n, guard) { if (guard ? isIterateeCall(collection, n, guard) : n == null) { collection = toIterable(collection); var length = collection.length; return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; } var result = shuffle(collection); result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); return result; } /** * Creates an array of shuffled values, using a version of the Fisher-Yates * shuffle. See [Wikipedia](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) * for more details. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to shuffle. * @returns {Array} Returns the new shuffled array. * @example * * _.shuffle([1, 2, 3, 4]); * // => [4, 1, 3, 2] */ function shuffle(collection) { collection = toIterable(collection); var index = -1, length = collection.length, result = Array(length); while (++index < length) { var rand = baseRandom(0, index); if (index != rand) { result[index] = result[rand]; } result[rand] = collection[index]; } return result; } /** * Gets the size of `collection` by returning `collection.length` for * array-like values or the number of own enumerable properties for objects. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns the size of `collection`. * @example * * _.size([1, 2]); * // => 2 * * _.size({ 'one': 1, 'two': 2, 'three': 3 }); * // => 3 * * _.size('pebbles'); * // => 7 */ function size(collection) { var length = collection ? collection.length : 0; return isLength(length) ? length : keys(collection).length; } /** * Checks if `predicate` returns truthy for **any** element of `collection`. * The function returns as soon as it finds a passing value and does not iterate * over the entire collection. The predicate is bound to `thisArg` and invoked * with three arguments; (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @alias any * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); * // => true * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true } * ]; * * // using the "_.property" callback shorthand * _.some(users, 'active'); * // => true * * // using the "_.matches" callback shorthand * _.some(users, { 'age': 1 }); * // => false */ function some(collection, predicate, thisArg) { var func = isArray(collection) ? arraySome : baseSome; if (typeof predicate != 'function' || typeof thisArg != 'undefined') { predicate = getCallback(predicate, thisArg, 3); } return func(collection, predicate); } /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection through `iteratee`. This method performs * a stable sort, that is, it preserves the original sort order of equal elements. * The `iteratee` is bound to `thisArg` and invoked with three arguments; * (value, index|key, collection). * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] The function * invoked per iteration. If a property name or an object is provided it is * used to create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Array} Returns the new sorted array. * @example * * _.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); * // => [3, 1, 2] * * _.sortBy([1, 2, 3], function(n) { return this.sin(n); }, Math); * // => [3, 1, 2] * * var users = [ * { 'user': 'fred' }, * { 'user': 'pebbles' }, * { 'user': 'barney' } * ]; * * // using the "_.property" callback shorthand * _.pluck(_.sortBy(users, 'user'), 'user'); * // => ['barney', 'fred', 'pebbles'] */ function sortBy(collection, iteratee, thisArg) { var index = -1, length = collection ? collection.length : 0, result = isLength(length) ? Array(length) : []; if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { iteratee = null; } iteratee = getCallback(iteratee, thisArg, 3); baseEach(collection, function(value, key, collection) { result[++index] = { 'criteria': iteratee(value, key, collection), 'index': index, 'value': value }; }); return baseSortBy(result, compareAscending); } /** * This method is like `_.sortBy` except that it sorts by property names * instead of an iteratee function. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to iterate over. * @param {...(string|string[])} props The property names to sort by, * specified as individual property names or arrays of property names. * @returns {Array} Returns the new sorted array. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 26 }, * { 'user': 'fred', 'age': 30 } * ]; * * _.map(_.sortByAll(users, ['user', 'age']), _.values); * // => [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] */ function sortByAll(collection) { var args = arguments; if (args.length > 3 && isIterateeCall(args[1], args[2], args[3])) { args = [collection, args[1]]; } var index = -1, length = collection ? collection.length : 0, props = baseFlatten(args, false, false, 1), result = isLength(length) ? Array(length) : []; baseEach(collection, function(value, key, collection) { var length = props.length, criteria = Array(length); while (length--) { criteria[length] = value == null ? undefined : value[props[length]]; } result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; }); return baseSortBy(result, compareMultipleAscending); } /** * Performs a deep comparison between each element in `collection` and the * source object, returning an array of all elements that have equivalent * property values. * * @static * @memberOf _ * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {Object} source The object of property values to match. * @returns {Array} Returns the new filtered array. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'status': 'busy', 'pets': ['hoppy'] }, * { 'user': 'fred', 'age': 40, 'status': 'busy', 'pets': ['baby puss', 'dino'] } * ]; * * _.pluck(_.where(users, { 'age': 36 }), 'user'); * // => ['barney'] * * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); * // => ['fred'] * * _.pluck(_.where(users, { 'status': 'busy' }), 'user'); * // => ['barney', 'fred'] */ function where(collection, source) { return filter(collection, baseMatches(source)); } /*------------------------------------------------------------------------*/ /** * Gets the number of milliseconds that have elapsed since the Unix epoch * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @category Date * @example * * _.defer(function(stamp) { console.log(_.now() - stamp); }, _.now()); * // => logs the number of milliseconds it took for the deferred function to be invoked */ var now = nativeNow || function() { return new Date().getTime(); }; /*------------------------------------------------------------------------*/ /** * The opposite of `_.before`; this method creates a function that invokes * `func` once it is called `n` or more times. * * @static * @memberOf _ * @category Function * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var saves = ['profile', 'settings']; * * var done = _.after(saves.length, function() { * console.log('done saving!'); * }); * * _.forEach(saves, function(type) { * asyncSave({ 'type': type, 'complete': done }); * }); * // => logs 'done saving!' after the two async saves have completed */ function after(n, func) { if (!isFunction(func)) { if (isFunction(n)) { var temp = n; n = func; func = temp; } else { throw new TypeError(FUNC_ERROR_TEXT); } } n = nativeIsFinite(n = +n) ? n : 0; return function() { if (--n < 1) { return func.apply(this, arguments); } }; } /** * Creates a function that accepts up to `n` arguments ignoring any * additional arguments. * * @static * @memberOf _ * @category Function * @param {Function} func The function to cap arguments for. * @param {number} [n=func.length] The arity cap. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Function} Returns the new function. * @example * * _.map(['6', '8', '10'], _.ary(parseInt, 1)); * // => [6, 8, 10] */ function ary(func, n, guard) { if (guard && isIterateeCall(func, n, guard)) { n = null; } n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); return createWrapper(func, ARY_FLAG, null, null, null, null, n); } /** * Creates a function that invokes `func`, with the `this` binding and arguments * of the created function, while it is called less than `n` times. Subsequent * calls to the created function return the result of the last `func` invocation. * * @static * @memberOf _ * @category Function * @param {number} n The number of calls at which `func` is no longer invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * jQuery('#add').on('click', _.before(5, addContactToList)); * // => allows adding up to 4 contacts to the list */ function before(n, func) { var result; if (!isFunction(func)) { if (isFunction(n)) { var temp = n; n = func; func = temp; } else { throw new TypeError(FUNC_ERROR_TEXT); } } return function() { if (--n > 0) { result = func.apply(this, arguments); } else { func = null; } return result; }; } /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and prepends any additional `_.bind` arguments to those provided to the * bound function. * * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for partially applied arguments. * * **Note:** Unlike native `Function#bind` this method does not set the `length` * property of bound functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var greet = function(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; * }; * * var object = { 'user': 'fred' }; * * var bound = _.bind(greet, object, 'hi'); * bound('!'); * // => 'hi fred!' * * // using placeholders * var bound = _.bind(greet, object, _, '!'); * bound('hi'); * // => 'hi fred!' */ function bind(func, thisArg) { var bitmask = BIND_FLAG; if (arguments.length > 2) { var partials = baseSlice(arguments, 2), holders = replaceHolders(partials, bind.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(func, bitmask, thisArg, partials, holders); } /** * Binds methods of an object to the object itself, overwriting the existing * method. Method names may be specified as individual arguments or as arrays * of method names. If no method names are provided all enumerable function * properties, own and inherited, of `object` are bound. * * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ * @category Function * @param {Object} object The object to bind and assign the bound methods to. * @param {...(string|string[])} [methodNames] The object method names to bind, * specified as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * * var view = { * 'label': 'docs', * 'onClick': function() { console.log('clicked ' + this.label); } * }; * * _.bindAll(view); * jQuery('#docs').on('click', view.onClick); * // => logs 'clicked docs' when the element is clicked */ function bindAll(object) { return baseBindAll(object, arguments.length > 1 ? baseFlatten(arguments, false, false, 1) : functions(object) ); } /** * Creates a function that invokes the method at `object[key]` and prepends * any additional `_.bindKey` arguments to those provided to the bound function. * * This method differs from `_.bind` by allowing bound functions to reference * methods that may be redefined or don't yet exist. * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) * for more details. * * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * @static * @memberOf _ * @category Function * @param {Object} object The object the method belongs to. * @param {string} key The key of the method. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var object = { * 'user': 'fred', * 'greet': function(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; * } * }; * * var bound = _.bindKey(object, 'greet', 'hi'); * bound('!'); * // => 'hi fred!' * * object.greet = function(greeting, punctuation) { * return greeting + 'ya ' + this.user + punctuation; * }; * * bound('!'); * // => 'hiya fred!' * * // using placeholders * var bound = _.bindKey(object, 'greet', _, '!'); * bound('hi'); * // => 'hiya fred!' */ function bindKey(object, key) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (arguments.length > 2) { var partials = baseSlice(arguments, 2), holders = replaceHolders(partials, bindKey.placeholder); bitmask |= PARTIAL_FLAG; } return createWrapper(key, bitmask, object, partials, holders); } /** * Creates a function that accepts one or more arguments of `func` that when * called either invokes `func` returning its result, if all `func` arguments * have been provided, or returns a function that accepts one or more of the * remaining `func` arguments, and so on. The arity of `func` may be specified * if `func.length` is not sufficient. * * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for provided arguments. * * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Function} Returns the new curried function. * @example * * var abc = function(a, b, c) { * return [a, b, c]; * }; * * var curried = _.curry(abc); * * curried(1)(2)(3); * // => [1, 2, 3] * * curried(1, 2)(3); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] * * // using placeholders * curried(1)(_, 3)(2); * // => [1, 2, 3] */ function curry(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { arity = null; } var result = createWrapper(func, CURRY_FLAG, null, null, null, null, null, arity); result.placeholder = curry.placeholder; return result; } /** * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for provided arguments. * * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Function} Returns the new curried function. * @example * * var abc = function(a, b, c) { * return [a, b, c]; * }; * * var curried = _.curryRight(abc); * * curried(3)(2)(1); * // => [1, 2, 3] * * curried(2, 3)(1); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] * * // using placeholders * curried(3)(1, _)(2); * // => [1, 2, 3] */ function curryRight(func, arity, guard) { if (guard && isIterateeCall(func, arity, guard)) { arity = null; } var result = createWrapper(func, CURRY_RIGHT_FLAG, null, null, null, null, null, arity); result.placeholder = curryRight.placeholder; return result; } /** * Creates a function that delays invoking `func` until after `wait` milliseconds * have elapsed since the last time it was invoked. The created function comes * with a `cancel` method to cancel delayed invocations. Provide an options * object to indicate that `func` should be invoked on the leading and/or * trailing edge of the `wait` timeout. Subsequent calls to the debounced * function return the result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the debounced function is * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ * @category Function * @param {Function} func The function to debounce. * @param {number} wait The number of milliseconds to delay. * @param {Object} [options] The options object. * @param {boolean} [options.leading=false] Specify invoking on the leading * edge of the timeout. * @param {number} [options.maxWait] The maximum time `func` is allowed to be * delayed before it is invoked. * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // avoid costly calculations while the window size is in flux * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // invoke `sendMail` when the click event is fired, debouncing subsequent calls * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })); * * // ensure `batchLog` is invoked once after 1 second of debounced calls * var source = new EventSource('/stream'); * jQuery(source).on('message', _.debounce(batchLog, 250, { * 'maxWait': 1000 * })); * * // cancel a debounced call * var todoChanges = _.debounce(batchLog, 1000); * Object.observe(models.todo, todoChanges); * * Object.observe(models, function(changes) { * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { * todoChanges.cancel(); * } * }, ['delete']); * * // ...at some point `models.todo` is changed * models.todo.completed = true; * * // ...before 1 second has passed `models.todo` is deleted * // which cancels the debounced `todoChanges` call * delete models.todo; */ function debounce(func, wait, options) { var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } wait = wait < 0 ? 0 : wait; if (options === true) { var leading = true; trailing = false; } else if (isObject(options)) { leading = options.leading; maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); trailing = 'trailing' in options ? options.trailing : trailing; } function cancel() { if (timeoutId) { clearTimeout(timeoutId); } if (maxTimeoutId) { clearTimeout(maxTimeoutId); } maxTimeoutId = timeoutId = trailingCall = undefined; } function delayed() { var remaining = wait - (now() - stamp); if (remaining <= 0 || remaining > wait) { if (maxTimeoutId) { clearTimeout(maxTimeoutId); } var isCalled = trailingCall; maxTimeoutId = timeoutId = trailingCall = undefined; if (isCalled) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } } else { timeoutId = setTimeout(delayed, remaining); } } function maxDelayed() { if (timeoutId) { clearTimeout(timeoutId); } maxTimeoutId = timeoutId = trailingCall = undefined; if (trailing || (maxWait !== wait)) { lastCalled = now(); result = func.apply(thisArg, args); if (!timeoutId && !maxTimeoutId) { args = thisArg = null; } } } function debounced() { args = arguments; stamp = now(); thisArg = this; trailingCall = trailing && (timeoutId || !leading); if (maxWait === false) { var leadingCall = leading && !timeoutId; } else { if (!maxTimeoutId && !leading) { lastCalled = stamp; } var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; if (isCalled) { if (maxTimeoutId) { maxTimeoutId = clearTimeout(maxTimeoutId); } lastCalled = stamp; result = func.apply(thisArg, args); } else if (!maxTimeoutId) { maxTimeoutId = setTimeout(maxDelayed, remaining); } } if (isCalled && timeoutId) { timeoutId = clearTimeout(timeoutId); } else if (!timeoutId && wait !== maxWait) { timeoutId = setTimeout(delayed, wait); } if (leadingCall) { isCalled = true; result = func.apply(thisArg, args); } if (isCalled && !timeoutId && !maxTimeoutId) { args = thisArg = null; } return result; } debounced.cancel = cancel; return debounced; } /** * Defers invoking the `func` until the current call stack has cleared. Any * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to defer. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.defer(function(text) { console.log(text); }, 'deferred'); * // logs 'deferred' after one or more milliseconds */ function defer(func) { return baseDelay(func, 1, arguments, 1); } /** * Invokes `func` after `wait` milliseconds. Any additional arguments are * provided to `func` when it is invoked. * * @static * @memberOf _ * @category Function * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke the function with. * @returns {number} Returns the timer id. * @example * * _.delay(function(text) { console.log(text); }, 1000, 'later'); * // => logs 'later' after one second */ function delay(func, wait) { return baseDelay(func, wait, arguments, 2); } /** * Creates a function that returns the result of invoking the provided * functions with the `this` binding of the created function, where each * successive invocation is supplied the return value of the previous. * * @static * @memberOf _ * @category Function * @param {...Function} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * * function add(x, y) { * return x + y; * } * * function square(n) { * return n * n; * } * * var addSquare = _.flow(add, square); * addSquare(1, 2); * // => 9 */ function flow() { var funcs = arguments, length = funcs.length; if (!length) { return function() {}; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { var index = 0, result = funcs[index].apply(this, arguments); while (++index < length) { result = funcs[index].call(this, result); } return result; }; } /** * This method is like `_.flow` except that it creates a function that * invokes the provided functions from right to left. * * @static * @memberOf _ * @alias backflow, compose * @category Function * @param {...Function} [funcs] Functions to invoke. * @returns {Function} Returns the new function. * @example * * function add(x, y) { * return x + y; * } * * function square(n) { * return n * n; * } * * var addSquare = _.flowRight(square, add); * addSquare(1, 2); * // => 9 */ function flowRight() { var funcs = arguments, fromIndex = funcs.length - 1; if (fromIndex < 0) { return function() {}; } if (!arrayEvery(funcs, isFunction)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { var index = fromIndex, result = funcs[index].apply(this, arguments); while (index--) { result = funcs[index].call(this, result); } return result; }; } /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is coerced to a string and used as the * cache key. The `func` is invoked with the `this` binding of the memoized * function. * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the ES `Map` method interface * of `get`, `has`, and `set`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) * for more details. * * @static * @memberOf _ * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoizing function. * @example * * var upperCase = _.memoize(function(string) { * return string.toUpperCase(); * }); * * upperCase('fred'); * // => 'FRED' * * // modifying the result cache * upperCase.cache.set('fred', 'BARNEY'); * upperCase('fred'); * // => 'BARNEY' * * // replacing `_.memoize.Cache` * var object = { 'user': 'fred' }; * var other = { 'user': 'barney' }; * var identity = _.memoize(_.identity); * * identity(object); * // => { 'user': 'fred' } * identity(other); * // => { 'user': 'fred' } * * _.memoize.Cache = WeakMap; * var identity = _.memoize(_.identity); * * identity(object); * // => { 'user': 'fred' } * identity(other); * // => { 'user': 'barney' } */ function memoize(func, resolver) { if (!isFunction(func) || (resolver && !isFunction(resolver))) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { var cache = memoized.cache, key = resolver ? resolver.apply(this, arguments) : arguments[0]; if (cache.has(key)) { return cache.get(key); } var result = func.apply(this, arguments); cache.set(key, result); return result; }; memoized.cache = new memoize.Cache; return memoized; } /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static * @memberOf _ * @category Function * @param {Function} predicate The predicate to negate. * @returns {Function} Returns the new function. * @example * * function isEven(n) { * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); * // => [1, 3, 5] */ function negate(predicate) { if (!isFunction(predicate)) { throw new TypeError(FUNC_ERROR_TEXT); } return function() { return !predicate.apply(this, arguments); }; } /** * Creates a function that is restricted to invoking `func` once. Repeat calls * to the function return the value of the first call. The `func` is invoked * with the `this` binding of the created function. * * @static * @memberOf _ * @type Function * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var initialize = _.once(createApplication); * initialize(); * initialize(); * // `initialize` invokes `createApplication` once */ function once(func) { return before(func, 2); } /** * Creates a function that invokes `func` with `partial` arguments prepended * to those provided to the new function. This method is like `_.bind` except * it does **not** alter the `this` binding. * * The `_.partial.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * **Note:** This method does not set the `length` property of partially * applied functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { * return greeting + ' ' + name; * }; * * var sayHelloTo = _.partial(greet, 'hello'); * sayHelloTo('fred'); * // => 'hello fred' * * // using placeholders * var greetFred = _.partial(greet, _, 'fred'); * greetFred('hi'); * // => 'hi fred' */ function partial(func) { var partials = baseSlice(arguments, 1), holders = replaceHolders(partials, partial.placeholder); return createWrapper(func, PARTIAL_FLAG, null, partials, holders); } /** * This method is like `_.partial` except that partially applied arguments * are appended to those provided to the new function. * * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * **Note:** This method does not set the `length` property of partially * applied functions. * * @static * @memberOf _ * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [args] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { * return greeting + ' ' + name; * }; * * var greetFred = _.partialRight(greet, 'fred'); * greetFred('hi'); * // => 'hi fred' * * // using placeholders * var sayHelloTo = _.partialRight(greet, 'hello', _); * sayHelloTo('fred'); * // => 'hello fred' */ function partialRight(func) { var partials = baseSlice(arguments, 1), holders = replaceHolders(partials, partialRight.placeholder); return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders); } /** * Creates a function that invokes `func` with arguments arranged according * to the specified indexes where the argument value at the first index is * provided as the first argument, the argument value at the second index is * provided as the second argument, and so on. * * @static * @memberOf _ * @category Function * @param {Function} func The function to rearrange arguments for. * @param {...(number|number[])} indexes The arranged argument indexes, * specified as individual indexes or arrays of indexes. * @returns {Function} Returns the new function. * @example * * var rearged = _.rearg(function(a, b, c) { * return [a, b, c]; * }, 2, 0, 1); * * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] * * var map = _.rearg(_.map, [1, 0]); * map(function(n) { return n * 3; }, [1, 2, 3]); * // => [3, 6, 9] */ function rearg(func) { var indexes = baseFlatten(arguments, false, false, 1); return createWrapper(func, REARG_FLAG, null, null, null, indexes); } /** * Creates a function that only invokes `func` at most once per every `wait` * milliseconds. The created function comes with a `cancel` method to cancel * delayed invocations. Provide an options object to indicate that `func` * should be invoked on the leading and/or trailing edge of the `wait` timeout. * Subsequent calls to the throttled function return the result of the last * `func` call. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the the throttled function is * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) * for details over the differences between `_.throttle` and `_.debounce`. * * @static * @memberOf _ * @category Function * @param {Function} func The function to throttle. * @param {number} wait The number of milliseconds to throttle invocations to. * @param {Object} [options] The options object. * @param {boolean} [options.leading=true] Specify invoking on the leading * edge of the timeout. * @param {boolean} [options.trailing=true] Specify invoking on the trailing * edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * * // avoid excessively updating the position while scrolling * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }) * jQuery('.interactive').on('click', throttled); * * // cancel a trailing throttled call * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, trailing = true; if (!isFunction(func)) { throw new TypeError(FUNC_ERROR_TEXT); } if (options === false) { leading = false; } else if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } debounceOptions.leading = leading; debounceOptions.maxWait = +wait; debounceOptions.trailing = trailing; return debounce(func, wait, debounceOptions); } /** * Creates a function that provides `value` to the wrapper function as its * first argument. Any additional arguments provided to the function are * appended to those provided to the wrapper function. The wrapper is invoked * with the `this` binding of the created function. * * @static * @memberOf _ * @category Function * @param {*} value The value to wrap. * @param {Function} wrapper The wrapper function. * @returns {Function} Returns the new function. * @example * * var p = _.wrap(_.escape, function(func, text) { * return '

' + func(text) + '

'; * }); * * p('fred, barney, & pebbles'); * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); } /*------------------------------------------------------------------------*/ /** * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, * otherwise they are assigned by reference. If `customizer` is provided it is * invoked to produce the cloned values. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is bound to * `thisArg` and invoked with two argument; (value [, index|key, object]). * * **Note:** This method is loosely based on the structured clone algorithm. * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {*} Returns the cloned value. * @example * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * var shallow = _.clone(users); * shallow[0] === users[0]; * // => true * * var deep = _.clone(users, true); * deep[0] === users[0]; * // => false * * // using a customizer callback * var body = _.clone(document.body, function(value) { * return _.isElement(value) ? value.cloneNode(false) : undefined; * }); * * body === document.body * // => false * body.nodeName * // => BODY * body.childNodes.length; * // => 0 */ function clone(value, isDeep, customizer, thisArg) { // Juggle arguments. if (typeof isDeep != 'boolean' && isDeep != null) { thisArg = customizer; customizer = isIterateeCall(value, isDeep, thisArg) ? null : isDeep; isDeep = false; } customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); return baseClone(value, isDeep, customizer); } /** * Creates a deep clone of `value`. If `customizer` is provided it is invoked * to produce the cloned values. If `customizer` returns `undefined` cloning * is handled by the method instead. The `customizer` is bound to `thisArg` * and invoked with two argument; (value [, index|key, object]). * * **Note:** This method is loosely based on the structured clone algorithm. * The enumerable properties of `arguments` objects and objects created by * constructors other than `Object` are cloned to plain `Object` objects. An * empty object is returned for uncloneable values such as functions, DOM nodes, * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to deep clone. * @param {Function} [customizer] The function to customize cloning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {*} Returns the deep cloned value. * @example * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * var deep = _.cloneDeep(users); * deep[0] === users[0]; * // => false * * // using a customizer callback * var el = _.cloneDeep(document.body, function(value) { * return _.isElement(value) ? value.cloneNode(true) : undefined; * }); * * body === document.body * // => false * body.nodeName * // => BODY * body.childNodes.length; * // => 20 */ function cloneDeep(value, customizer, thisArg) { customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); return baseClone(value, true, customizer); } /** * Checks if `value` is classified as an `arguments` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * (function() { return _.isArguments(arguments); })(); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { var length = isObjectLike(value) ? value.length : undefined; return (isLength(length) && objToString.call(value) == argsTag) || false; } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * (function() { return _.isArray(arguments); })(); * // => false */ var isArray = nativeIsArray || function(value) { return (isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag) || false; }; /** * Checks if `value` is classified as a boolean primitive or object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isBoolean(false); * // => true * * _.isBoolean(null); * // => false */ function isBoolean(value) { return (value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag) || false; } /** * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isDate(new Date); * // => true * * _.isDate('Mon April 23 2012'); * // => false */ function isDate(value) { return (isObjectLike(value) && objToString.call(value) == dateTag) || false; } /** * Checks if `value` is a DOM element. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); * // => true * * _.isElement(''); * // => false */ function isElement(value) { return (value && value.nodeType === 1 && isObjectLike(value) && objToString.call(value).indexOf('Element') > -1) || false; } // Fallback for environments without DOM support. if (!support.dom) { isElement = function(value) { return (value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value)) || false; }; } /** * Checks if a value is empty. A value is considered empty unless it is an * `arguments` object, array, string, or jQuery-like collection with a length * greater than `0` or an object with own enumerable properties. * * @static * @memberOf _ * @category Lang * @param {Array|Object|string} value The value to inspect. * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * * _.isEmpty(null); * // => true * * _.isEmpty(true); * // => true * * _.isEmpty(1); * // => true * * _.isEmpty([1, 2, 3]); * // => false * * _.isEmpty({ 'a': 1 }); * // => false */ function isEmpty(value) { if (value == null) { return true; } var length = value.length; if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) || (isObjectLike(value) && isFunction(value.splice)))) { return !length; } return !keys(value).length; } /** * Performs a deep comparison between two values to determine if they are * equivalent. If `customizer` is provided it is invoked to compare values. * If `customizer` returns `undefined` comparisons are handled by the method * instead. The `customizer` is bound to `thisArg` and invoked with three * arguments; (value, other [, index|key]). * * **Note:** This method supports comparing arrays, booleans, `Date` objects, * numbers, `Object` objects, regexes, and strings. Functions and DOM nodes * are **not** supported. Provide a customizer function to extend support * for comparing other values. * * @static * @memberOf _ * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'user': 'fred' }; * var other = { 'user': 'fred' }; * * object == other; * // => false * * _.isEqual(object, other); * // => true * * // using a customizer callback * var array = ['hello', 'goodbye']; * var other = ['hi', 'goodbye']; * * _.isEqual(array, other, function(value, other) { * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; * }); * // => true */ function isEqual(value, other, customizer, thisArg) { customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); if (!customizer && isStrictComparable(value) && isStrictComparable(other)) { return value === other; } var result = customizer ? customizer(value, other) : undefined; return typeof result == 'undefined' ? baseIsEqual(value, other, customizer) : !!result; } /** * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, * `SyntaxError`, `TypeError`, or `URIError` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * * _.isError(new Error); * // => true * * _.isError(Error); * // => false */ function isError(value) { return (isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag) || false; } /** * Checks if `value` is a finite primitive number. * * **Note:** This method is based on ES `Number.isFinite`. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * * _.isFinite(10); * // => true * * _.isFinite('10'); * // => false * * _.isFinite(true); * // => false * * _.isFinite(Object(10)); * // => false * * _.isFinite(Infinity); * // => false */ var isFinite = nativeNumIsFinite || function(value) { return typeof value == 'number' && nativeIsFinite(value); }; /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { // Avoid a Chakra JIT bug in compatibility modes of IE 11. // See https://github.com/jashkenas/underscore/issues/1621 for more details. return typeof value == 'function' || false; } // Fallback for environments that return incorrect `typeof` operator results. if (isFunction(/x/) || (Uint8Array && !isFunction(Uint8Array))) { isFunction = function(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in older versions of Chrome and Safari which return 'function' for regexes // and Safari 8 equivalents which return 'object' for typed array constructors. return objToString.call(value) == funcTag; }; } /** * Checks if `value` is the language type of `Object`. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(1); * // => false */ function isObject(value) { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. var type = typeof value; return type == 'function' || (value && type == 'object') || false; } /** * Performs a deep comparison between `object` and `source` to determine if * `object` contains equivalent property values. If `customizer` is provided * it is invoked to compare values. If `customizer` returns `undefined` * comparisons are handled by the method instead. The `customizer` is bound * to `thisArg` and invoked with three arguments; (value, other, index|key). * * **Note:** This method supports comparing properties of arrays, booleans, * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions * and DOM nodes are **not** supported. Provide a customizer function to extend * support for comparing other values. * * @static * @memberOf _ * @category Lang * @param {Object} source The object to inspect. * @param {Object} source The object of property values to match. * @param {Function} [customizer] The function to customize comparing values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * * var object = { 'user': 'fred', 'age': 40 }; * * _.isMatch(object, { 'age': 40 }); * // => true * * _.isMatch(object, { 'age': 36 }); * // => false * * // using a customizer callback * var object = { 'greeting': 'hello' }; * var source = { 'greeting': 'hi' }; * * _.isMatch(object, source, function(value, other) { * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; * }); * // => true */ function isMatch(object, source, customizer, thisArg) { var props = keys(source), length = props.length; customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); if (!customizer && length == 1) { var key = props[0], value = source[key]; if (isStrictComparable(value)) { return object != null && value === object[key] && hasOwnProperty.call(object, key); } } var values = Array(length), strictCompareFlags = Array(length); while (length--) { value = values[length] = source[props[length]]; strictCompareFlags[length] = isStrictComparable(value); } return baseIsMatch(object, props, values, strictCompareFlags, customizer); } /** * Checks if `value` is `NaN`. * * **Note:** This method is not the same as native `isNaN` which returns `true` * for `undefined` and other non-numeric values. See the [ES5 spec](https://es5.github.io/#x15.1.2.4) * for more details. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); * // => true * * _.isNaN(new Number(NaN)); * // => true * * isNaN(undefined); * // => true * * _.isNaN(undefined); * // => false */ function isNaN(value) { // An `NaN` primitive is the only value that is not equal to itself. // Perform the `toStringTag` check first to avoid errors with some host objects in IE. return isNumber(value) && value != +value; } /** * Checks if `value` is a native function. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, else `false`. * @example * * _.isNative(Array.prototype.push); * // => true * * _.isNative(_); * // => false */ function isNative(value) { if (value == null) { return false; } if (objToString.call(value) == funcTag) { return reNative.test(fnToString.call(value)); } return (isObjectLike(value) && reHostCtor.test(value)) || false; } /** * Checks if `value` is `null`. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * * _.isNull(void 0); * // => false */ function isNull(value) { return value === null; } /** * Checks if `value` is classified as a `Number` primitive or object. * * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified * as numbers, use the `_.isFinite` method. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isNumber(8.4); * // => true * * _.isNumber(NaN); * // => true * * _.isNumber('8.4'); * // => false */ function isNumber(value) { return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag) || false; } /** * Checks if `value` is a plain object, that is, an object created by the * `Object` constructor or one with a `[[Prototype]]` of `null`. * * **Note:** This method assumes objects created by the `Object` constructor * have no inherited enumerable properties. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Foo() { * this.a = 1; * } * * _.isPlainObject(new Foo); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true * * _.isPlainObject(Object.create(null)); * // => true */ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { if (!(value && objToString.call(value) == objectTag)) { return false; } var valueOf = value.valueOf, objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); return objProto ? (value == objProto || getPrototypeOf(value) == objProto) : shimIsPlainObject(value); }; /** * Checks if `value` is classified as a `RegExp` object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isRegExp(/abc/); * // => true * * _.isRegExp('/abc/'); * // => false */ function isRegExp(value) { return (isObjectLike(value) && objToString.call(value) == regexpTag) || false; } /** * Checks if `value` is classified as a `String` primitive or object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isString('abc'); * // => true * * _.isString(1); * // => false */ function isString(value) { return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag) || false; } /** * Checks if `value` is classified as a typed array. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * * _.isTypedArray(new Uint8Array); * // => true * * _.isTypedArray([]); * // => false */ function isTypedArray(value) { return (isObjectLike(value) && isLength(value.length) && typedArrayTags[objToString.call(value)]) || false; } /** * Checks if `value` is `undefined`. * * @static * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true * * _.isUndefined(null); * // => false */ function isUndefined(value) { return typeof value == 'undefined'; } /** * Converts `value` to an array. * * @static * @memberOf _ * @category Lang * @param {*} value The value to convert. * @returns {Array} Returns the converted array. * @example * * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3); * // => [2, 3] */ function toArray(value) { var length = value ? value.length : 0; if (!isLength(length)) { return values(value); } if (!length) { return []; } return arrayCopy(value); } /** * Converts `value` to a plain object flattening inherited enumerable * properties of `value` to own properties of the plain object. * * @static * @memberOf _ * @category Lang * @param {*} value The value to convert. * @returns {Object} Returns the converted plain object. * @example * * function Foo() { * this.b = 2; * } * * Foo.prototype.c = 3; * * _.assign({ 'a': 1 }, new Foo); * // => { 'a': 1, 'b': 2 } * * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); * // => { 'a': 1, 'b': 2, 'c': 3 } */ function toPlainObject(value) { return baseCopy(value, keysIn(value)); } /*------------------------------------------------------------------------*/ /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous sources. * If `customizer` is provided it is invoked to produce the assigned values. * The `customizer` is bound to `thisArg` and invoked with five arguments; * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ * @alias extend * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize assigning values. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns `object`. * @example * * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); * // => { 'user': 'fred', 'age': 40 } * * // using a customizer callback * var defaults = _.partialRight(_.assign, function(value, other) { * return typeof value == 'undefined' ? other : value; * }); * * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ var assign = createAssigner(baseAssign); /** * Creates an object that inherits from the given `prototype` object. If a * `properties` object is provided its own enumerable properties are assigned * to the created object. * * @static * @memberOf _ * @category Object * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Object} Returns the new object. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * function Circle() { * Shape.call(this); * } * * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); * * var circle = new Circle; * circle instanceof Circle; * // => true * * circle instanceof Shape; * // => true */ function create(prototype, properties, guard) { var result = baseCreate(prototype); if (guard && isIterateeCall(prototype, properties, guard)) { properties = null; } return properties ? baseCopy(properties, result, keys(properties)) : result; } /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to `undefined`. Once a * property is set, additional defaults of the same property are ignored. * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @example * * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ function defaults(object) { if (object == null) { return object; } var args = arrayCopy(arguments); args.push(assignDefaults); return assign.apply(undefined, args); } /** * This method is like `_.findIndex` except that it returns the key of the * first element `predicate` returns truthy for, instead of the element itself. * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var users = { * 'barney': { 'age': 36, 'active': true }, * 'fred': { 'age': 40, 'active': false }, * 'pebbles': { 'age': 1, 'active': true } * }; * * _.findKey(users, function(chr) { return chr.age < 40; }); * // => 'barney' (iteration order is not guaranteed) * * // using the "_.matches" callback shorthand * _.findKey(users, { 'age': 1 }); * // => 'pebbles' * * // using the "_.property" callback shorthand * _.findKey(users, 'active'); * // => 'barney' */ function findKey(object, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwn, true); } /** * This method is like `_.findKey` except that it iterates over elements of * a collection in the opposite order. * * If a property name is provided for `predicate` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `predicate` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to search. * @param {Function|Object|string} [predicate=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * * var users = { * 'barney': { 'age': 36, 'active': true }, * 'fred': { 'age': 40, 'active': false }, * 'pebbles': { 'age': 1, 'active': true } * }; * * _.findLastKey(users, function(chr) { return chr.age < 40; }); * // => returns `pebbles` assuming `_.findKey` returns `barney` * * // using the "_.matches" callback shorthand * _.findLastKey(users, { 'age': 36 }); * // => 'barney' * * // using the "_.property" callback shorthand * _.findLastKey(users, 'active'); * // => 'pebbles' */ function findLastKey(object, predicate, thisArg) { predicate = getCallback(predicate, thisArg, 3); return baseFind(object, predicate, baseForOwnRight, true); } /** * Iterates over own and inherited enumerable properties of an object invoking * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked * with three arguments; (value, key, object). Iterator functions may exit * iteration early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forIn(new Foo, function(value, key) { * console.log(key); * }); * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) */ function forIn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { iteratee = bindCallback(iteratee, thisArg, 3); } return baseFor(object, iteratee, keysIn); } /** * This method is like `_.forIn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forInRight(new Foo, function(value, key) { * console.log(key); * }); * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' */ function forInRight(object, iteratee, thisArg) { iteratee = bindCallback(iteratee, thisArg, 3); return baseForRight(object, iteratee, keysIn); } /** * Iterates over own enumerable properties of an object invoking `iteratee` * for each property. The `iteratee` is bound to `thisArg` and invoked with * three arguments; (value, key, object). Iterator functions may exit iteration * early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs '0', '1', and 'length' (iteration order is not guaranteed) */ function forOwn(object, iteratee, thisArg) { if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { iteratee = bindCallback(iteratee, thisArg, 3); } return baseForOwn(object, iteratee); } /** * This method is like `_.forOwn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns `object`. * @example * * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(n, key) { * console.log(key); * }); * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' */ function forOwnRight(object, iteratee, thisArg) { iteratee = bindCallback(iteratee, thisArg, 3); return baseForRight(object, iteratee, keys); } /** * Creates an array of function property names from all enumerable properties, * own and inherited, of `object`. * * @static * @memberOf _ * @alias methods * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the new array of property names. * @example * * _.functions(_); * // => ['all', 'any', 'bind', ...] */ function functions(object) { return baseFunctions(object, keysIn(object)); } /** * Checks if `key` exists as a direct property of `object` instead of an * inherited property. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @param {string} key The key to check. * @returns {boolean} Returns `true` if `key` is a direct property, else `false`. * @example * * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); * // => true */ function has(object, key) { return object ? hasOwnProperty.call(object, key) : false; } /** * Creates an object composed of the inverted keys and values of `object`. * If `object` contains duplicate values, subsequent values overwrite property * assignments of previous values unless `multiValue` is `true`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to invert. * @param {boolean} [multiValue] Allow multiple values per key. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {Object} Returns the new inverted object. * @example * * _.invert({ 'first': 'fred', 'second': 'barney' }); * // => { 'fred': 'first', 'barney': 'second' } * * // without `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }); * // => { 'fred': 'third', 'barney': 'second' } * * // with `multiValue` * _.invert({ 'first': 'fred', 'second': 'barney', 'third': 'fred' }, true); * // => { 'fred': ['first', 'third'], 'barney': ['second'] } */ function invert(object, multiValue, guard) { if (guard && isIterateeCall(object, multiValue, guard)) { multiValue = null; } var index = -1, props = keys(object), length = props.length, result = {}; while (++index < length) { var key = props[index], value = object[key]; if (multiValue) { if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { result[value] = [key]; } } else { result[value] = key; } } return result; } /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) * for more details. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keys(new Foo); * // => ['a', 'b'] (iteration order is not guaranteed) * * _.keys('hi'); * // => ['0', '1'] */ var keys = !nativeKeys ? shimKeys : function(object) { if (object) { var Ctor = object.constructor, length = object.length; } if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && (length && isLength(length)))) { return shimKeys(object); } return isObject(object) ? nativeKeys(object) : []; }; /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { if (object == null) { return []; } if (!isObject(object)) { object = Object(object); } var length = object.length; length = (length && isLength(length) && (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0; var Ctor = object.constructor, index = -1, isProto = typeof Ctor == 'function' && Ctor.prototype == object, result = Array(length), skipIndexes = length > 0; while (++index < length) { result[index] = (index + ''); } for (var key in object) { if (!(skipIndexes && isIndex(key, length)) && !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { result.push(key); } } return result; } /** * Creates an object with the same keys as `object` and values generated by * running each own enumerable property of `object` through `iteratee`. The * iteratee function is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * If a property name is provided for `iteratee` the created "_.property" * style callback returns the property value of the given element. * * If an object is provided for `iteratee` the created "_.matches" style * callback returns `true` for elements that have the properties of the given * object, else `false`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to iterate over. * @param {Function|Object|string} [iteratee=_.identity] The function invoked * per iteration. If a property name or object is provided it is used to * create a "_.property" or "_.matches" style callback respectively. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {Object} Returns the new mapped object. * @example * * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(n) { return n * 3; }); * // => { 'a': 3, 'b': 6, 'c': 9 } * * var users = { * 'fred': { 'user': 'fred', 'age': 40 }, * 'pebbles': { 'user': 'pebbles', 'age': 1 } * }; * * // using the "_.property" callback shorthand * _.mapValues(users, 'age'); * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) */ function mapValues(object, iteratee, thisArg) { var result = {}; iteratee = getCallback(iteratee, thisArg, 3); baseForOwn(object, function(value, key, object) { result[key] = iteratee(value, key, object); }); return result; } /** * Recursively merges own enumerable properties of the source object(s), that * don't resolve to `undefined` into the destination object. Subsequent sources * overwrite property assignments of previous sources. If `customizer` is * provided it is invoked to produce the merged values of the destination and * source properties. If `customizer` returns `undefined` merging is handled * by the method instead. The `customizer` is bound to `thisArg` and invoked * with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @param {Function} [customizer] The function to customize merging properties. * @param {*} [thisArg] The `this` binding of `customizer`. * @returns {Object} Returns `object`. * @example * * var users = { * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] * }; * * var ages = { * 'data': [{ 'age': 36 }, { 'age': 40 }] * }; * * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } * * // using a customizer callback * var object = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var other = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * _.merge(object, other, function(a, b) { * return _.isArray(a) ? a.concat(b) : undefined; * }); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ var merge = createAssigner(baseMerge); /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable properties of `object` that are not omitted. * Property names may be specified as individual arguments or as arrays of * property names. If `predicate` is provided it is invoked for each property * of `object` omitting the properties `predicate` returns truthy for. The * predicate is bound to `thisArg` and invoked with three arguments; * (value, key, object). * * @static * @memberOf _ * @category Object * @param {Object} object The source object. * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to omit, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns the new object. * @example * * var object = { 'user': 'fred', 'age': 40 }; * * _.omit(object, 'age'); * // => { 'user': 'fred' } * * _.omit(object, _.isNumber); * // => { 'user': 'fred' } */ function omit(object, predicate, thisArg) { if (object == null) { return {}; } if (typeof predicate != 'function') { var props = arrayMap(baseFlatten(arguments, false, false, 1), String); return pickByArray(object, baseDifference(keysIn(object), props)); } predicate = bindCallback(predicate, thisArg, 3); return pickByCallback(object, function(value, key, object) { return !predicate(value, key, object); }); } /** * Creates a two dimensional array of the key-value pairs for `object`, * e.g. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the new array of key-value pairs. * @example * * _.pairs({ 'barney': 36, 'fred': 40 }); * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ function pairs(object) { var index = -1, props = keys(object), length = props.length, result = Array(length); while (++index < length) { var key = props[index]; result[index] = [key, object[key]]; } return result; } /** * Creates an object composed of the picked `object` properties. Property * names may be specified as individual arguments or as arrays of property * names. If `predicate` is provided it is invoked for each property of `object` * picking the properties `predicate` returns truthy for. The predicate is * bound to `thisArg` and invoked with three arguments; (value, key, object). * * @static * @memberOf _ * @category Object * @param {Object} object The source object. * @param {Function|...(string|string[])} [predicate] The function invoked per * iteration or property names to pick, specified as individual property * names or arrays of property names. * @param {*} [thisArg] The `this` binding of `predicate`. * @returns {Object} Returns the new object. * @example * * var object = { 'user': 'fred', 'age': 40 }; * * _.pick(object, 'user'); * // => { 'user': 'fred' } * * _.pick(object, _.isString); * // => { 'user': 'fred' } */ function pick(object, predicate, thisArg) { if (object == null) { return {}; } return typeof predicate == 'function' ? pickByCallback(object, bindCallback(predicate, thisArg, 3)) : pickByArray(object, baseFlatten(arguments, false, false, 1)); } /** * Resolves the value of property `key` on `object`. If the value of `key` is * a function it is invoked with the `this` binding of `object` and its result * is returned, else the property value is returned. If the property value is * `undefined` the `defaultValue` is used in its place. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {string} key The key of the property to resolve. * @param {*} [defaultValue] The value returned if the property value * resolves to `undefined`. * @returns {*} Returns the resolved value. * @example * * var object = { 'user': 'fred', 'age': _.constant(40) }; * * _.result(object, 'user'); * // => 'fred' * * _.result(object, 'age'); * // => 40 * * _.result(object, 'status', 'busy'); * // => 'busy' * * _.result(object, 'status', _.constant('busy')); * // => 'busy' */ function result(object, key, defaultValue) { var value = object == null ? undefined : object[key]; if (typeof value == 'undefined') { value = defaultValue; } return isFunction(value) ? value.call(object) : value; } /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own enumerable * properties through `iteratee`, with each invocation potentially mutating * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked * with four arguments; (accumulator, value, key, object). Iterator functions * may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ * @category Object * @param {Array|Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @param {*} [thisArg] The `this` binding of `iteratee`. * @returns {*} Returns the accumulated value. * @example * * var squares = _.transform([1, 2, 3, 4, 5, 6], function(result, n) { * n *= n; * if (n % 2) { * return result.push(n) < 3; * } * }); * // => [1, 9, 25] * * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, n, key) { * result[key] = n * 3; * }); * // => { 'a': 3, 'b': 6, 'c': 9 } */ function transform(object, iteratee, accumulator, thisArg) { var isArr = isArray(object) || isTypedArray(object); iteratee = getCallback(iteratee, thisArg, 4); if (accumulator == null) { if (isArr || isObject(object)) { var Ctor = object.constructor; if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { accumulator = baseCreate(typeof Ctor == 'function' && Ctor.prototype); } } else { accumulator = {}; } } (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { return iteratee(accumulator, value, index, object); }); return accumulator; } /** * Creates an array of the own enumerable property values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.values(new Foo); * // => [1, 2] (iteration order is not guaranteed) * * _.values('hi'); * // => ['h', 'i'] */ function values(object) { return baseValues(object, keys(object)); } /** * Creates an array of the own and inherited enumerable property values * of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.valuesIn(new Foo); * // => [1, 2, 3] (iteration order is not guaranteed) */ function valuesIn(object) { return baseValues(object, keysIn(object)); } /*------------------------------------------------------------------------*/ /** * Produces a random number between `min` and `max` (inclusive). If only one * argument is provided a number between `0` and the given number is returned. * If `floating` is `true`, or either `min` or `max` are floats, a floating-point * number is returned instead of an integer. * * @static * @memberOf _ * @category Number * @param {number} [min=0] The minimum possible value. * @param {number} [max=1] The maximum possible value. * @param {boolean} [floating] Specify returning a floating-point number. * @returns {number} Returns the random number. * @example * * _.random(0, 5); * // => an integer between 0 and 5 * * _.random(5); * // => also an integer between 0 and 5 * * _.random(5, true); * // => a floating-point number between 0 and 5 * * _.random(1.2, 5.2); * // => a floating-point number between 1.2 and 5.2 */ function random(min, max, floating) { if (floating && isIterateeCall(min, max, floating)) { max = floating = null; } var noMin = min == null, noMax = max == null; if (floating == null) { if (noMax && typeof min == 'boolean') { floating = min; min = 1; } else if (typeof max == 'boolean') { floating = max; noMax = true; } } if (noMin && noMax) { max = 1; noMax = false; } min = +min || 0; if (noMax) { max = min; min = 0; } else { max = +max || 0; } if (floating || min % 1 || max % 1) { var rand = nativeRandom(); return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max); } return baseRandom(min, max); } /*------------------------------------------------------------------------*/ /** * Converts `string` to camel case. * See [Wikipedia](https://en.wikipedia.org/wiki/CamelCase) for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the camel cased string. * @example * * _.camelCase('Foo Bar'); * // => 'fooBar' * * _.camelCase('--foo-bar'); * // => 'fooBar' * * _.camelCase('__foo_bar__'); * // => 'fooBar' */ var camelCase = createCompounder(function(result, word, index) { word = word.toLowerCase(); return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word); }); /** * Capitalizes the first character of `string`. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to capitalize. * @returns {string} Returns the capitalized string. * @example * * _.capitalize('fred'); * // => 'Fred' */ function capitalize(string) { string = baseToString(string); return string && (string.charAt(0).toUpperCase() + string.slice(1)); } /** * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. * See [Wikipedia](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) * for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to deburr. * @returns {string} Returns the deburred string. * @example * * _.deburr('déjà vu'); * // => 'deja vu' */ function deburr(string) { string = baseToString(string); return string && string.replace(reLatin1, deburrLetter); } /** * Checks if `string` ends with the given target string. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search from. * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`. * @example * * _.endsWith('abc', 'c'); * // => true * * _.endsWith('abc', 'b'); * // => false * * _.endsWith('abc', 'b', 2); * // => true */ function endsWith(string, target, position) { string = baseToString(string); target = (target + ''); var length = string.length; position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; return position >= 0 && string.indexOf(target, position) == position; } /** * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional characters * use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't require escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in Internet Explorer < 9, they can break out * of attribute values or HTML comments. See [#102](https://html5sec.org/#102), * [#108](https://html5sec.org/#108), and [#133](https://html5sec.org/#133) of * the [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. * * When working with HTML you should always quote attribute values to reduce * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) * for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escape('fred, barney, & pebbles'); * // => 'fred, barney, & pebbles' */ function escape(string) { // Reset `lastIndex` because in IE < 9 `String#replace` does not. string = baseToString(string); return (string && reHasUnescapedHtml.test(string)) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; } /** * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", * "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escapeRegExp('[lodash](https://lodash.com/)'); * // => '\[lodash\]\(https://lodash\.com/\)' */ function escapeRegExp(string) { string = baseToString(string); return (string && reHasRegExpChars.test(string)) ? string.replace(reRegExpChars, '\\$&') : string; } /** * Converts `string` to kebab case (a.k.a. spinal case). * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) for * more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the kebab cased string. * @example * * _.kebabCase('Foo Bar'); * // => 'foo-bar' * * _.kebabCase('fooBar'); * // => 'foo-bar' * * _.kebabCase('__foo_bar__'); * // => 'foo-bar' */ var kebabCase = createCompounder(function(result, word, index) { return result + (index ? '-' : '') + word.toLowerCase(); }); /** * Pads `string` on the left and right sides if it is shorter then the given * padding length. The `chars` string may be truncated if the number of padding * characters can't be evenly divided by the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.pad('abc', 8); * // => ' abc ' * * _.pad('abc', 8, '_-'); * // => '_-abc_-_' * * _.pad('abc', 3); * // => 'abc' */ function pad(string, length, chars) { string = baseToString(string); length = +length; var strLength = string.length; if (strLength >= length || !nativeIsFinite(length)) { return string; } var mid = (length - strLength) / 2, leftLength = floor(mid), rightLength = ceil(mid); chars = createPad('', rightLength, chars); return chars.slice(0, leftLength) + string + chars; } /** * Pads `string` on the left side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padLeft('abc', 6); * // => ' abc' * * _.padLeft('abc', 6, '_-'); * // => '_-_abc' * * _.padLeft('abc', 3); * // => 'abc' */ function padLeft(string, length, chars) { string = baseToString(string); return string && (createPad(string, length, chars) + string); } /** * Pads `string` on the right side if it is shorter then the given padding * length. The `chars` string may be truncated if the number of padding * characters exceeds the padding length. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padRight('abc', 6); * // => 'abc ' * * _.padRight('abc', 6, '_-'); * // => 'abc_-_' * * _.padRight('abc', 3); * // => 'abc' */ function padRight(string, length, chars) { string = baseToString(string); return string && (string + createPad(string, length, chars)); } /** * Converts `string` to an integer of the specified radix. If `radix` is * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, * in which case a `radix` of `16` is used. * * **Note:** This method aligns with the ES5 implementation of `parseInt`. * See the [ES5 spec](https://es5.github.io/#E) for more details. * * @static * @memberOf _ * @category String * @param {string} string The string to convert. * @param {number} [radix] The radix to interpret `value` by. * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. * @returns {number} Returns the converted integer. * @example * * _.parseInt('08'); * // => 8 * * _.map(['6', '08', '10'], _.parseInt); * // => [6, 8, 10] */ function parseInt(string, radix, guard) { if (guard && isIterateeCall(string, radix, guard)) { radix = 0; } return nativeParseInt(string, radix); } // Fallback for environments with pre-ES5 implementations. if (nativeParseInt(whitespace + '08') != 8) { parseInt = function(string, radix, guard) { // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. // Chrome fails to trim leading whitespace characters. // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. if (guard ? isIterateeCall(string, radix, guard) : radix == null) { radix = 0; } else if (radix) { radix = +radix; } string = trim(string); return nativeParseInt(string, radix || (reHexPrefix.test(string) ? 16 : 10)); }; } /** * Repeats the given string `n` times. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to repeat. * @param {number} [n=0] The number of times to repeat the string. * @returns {string} Returns the repeated string. * @example * * _.repeat('*', 3); * // => '***' * * _.repeat('abc', 2); * // => 'abcabc' * * _.repeat('abc', 0); * // => '' */ function repeat(string, n) { var result = ''; string = baseToString(string); n = +n; if (n < 1 || !string || !nativeIsFinite(n)) { return result; } // Leverage the exponentiation by squaring algorithm for a faster repeat. // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. do { if (n % 2) { result += string; } n = floor(n / 2); string += string; } while (n); return result; } /** * Converts `string` to snake case. * See [Wikipedia](https://en.wikipedia.org/wiki/Snake_case) for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the snake cased string. * @example * * _.snakeCase('Foo Bar'); * // => 'foo_bar' * * _.snakeCase('fooBar'); * // => 'foo_bar' * * _.snakeCase('--foo-bar'); * // => 'foo_bar' */ var snakeCase = createCompounder(function(result, word, index) { return result + (index ? '_' : '') + word.toLowerCase(); }); /** * Converts `string` to start case. * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage) * for more details. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the start cased string. * @example * * _.startCase('--foo-bar'); * // => 'Foo Bar' * * _.startCase('fooBar'); * // => 'Foo Bar' * * _.startCase('__foo_bar__'); * // => 'Foo Bar' */ var startCase = createCompounder(function(result, word, index) { return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1)); }); /** * Checks if `string` starts with the given target string. * * @static * @memberOf _ * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`. * @example * * _.startsWith('abc', 'a'); * // => true * * _.startsWith('abc', 'b'); * // => false * * _.startsWith('abc', 'b', 1); * // => true */ function startsWith(string, target, position) { string = baseToString(string); position = position == null ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); return string.lastIndexOf(target, position) == position; } /** * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escape interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data * properties may be accessed as free variables in the template. If a setting * object is provided it takes precedence over `_.templateSettings` values. * * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for more details. * * For more information on precompiling templates see * [lodash's custom builds documentation](https://lodash.com/custom-builds). * * For more information on Chrome extension sandboxes see * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). * * @static * @memberOf _ * @category String * @param {string} [string=''] The template string. * @param {Object} [options] The options object. * @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {Object} [options.imports] An object to import into the template as free variables. * @param {RegExp} [options.interpolate] The "interpolate" delimiter. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. * @param {string} [options.variable] The data object variable name. * @param- {Object} [otherOptions] Enables the legacy `options` param signature. * @returns {Function} Returns the compiled template function. * @example * * // using the "interpolate" delimiter to create a compiled template * var compiled = _.template('hello <%= user %>!'); * compiled({ 'user': 'fred' }); * // => 'hello fred!' * * // using the HTML "escape" delimiter to escape data property values * var compiled = _.template('<%- value %>'); * compiled({ 'value': '