diff --git a/index.html b/index.html index e48ecaa..fc58e29 100755 --- a/index.html +++ b/index.html @@ -17,6 +17,13 @@ ",returnEnd:!0,subLanguage:""}},n,{className:"pi",begin:/<\?\w+/,end:/\?>/,relevance:10},{className:"tag",begin:"",contains:[{className:"title",begin:/[^ \/><\n\t]+/,relevance:0},a]}]}}},{}],122:[function(e,t,n){(function(e){(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||u.defaults,this.rules=p.normal,this.options.gfm&&(this.rules=this.options.tables?p.tables:p.gfm)}function a(e,t){if(this.options=t||u.defaults,this.links=e,this.rules=m.normal,this.renderer=this.options.renderer||new r,this.renderer.options=this.options,!this.links)throw new Error("Tokens array requires a `links` property.");this.options.gfm?this.rules=this.options.breaks?m.breaks:m.gfm:this.options.pedantic&&(this.rules=m.pedantic)}function r(e){this.options=e||{}}function i(e){this.tokens=[],this.token=null,this.options=e||u.defaults,this.options.renderer=this.options.renderer||new r,this.renderer=this.options.renderer,this.renderer.options=this.options}function s(e,t){return e.replace(t?/&/g:/&(?!#?\w+;)/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function o(e){return e.replace(/&([#\w]+);/g,function(e,t){return t=t.toLowerCase(),"colon"===t?":":"#"===t.charAt(0)?String.fromCharCode("x"===t.charAt(1)?parseInt(t.substring(2),16):+t.substring(1)):""})}function l(e,t){return e=e.source,t=t||"",function n(a,r){return a?(r=r.source||r,r=r.replace(/(^|[^\[])\^/g,"$1"),e=e.replace(a,r),n):new RegExp(e,t)}}function c(){}function d(e){for(var t,n,a=1;aAn error occured:

"+s(p.message+"",!0)+"
";throw p}}var p={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:c,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:c,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:c,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};p.bullet=/(?:[*+-]|\d+\.)/,p.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,p.item=l(p.item,"gm")(/bull/g,p.bullet)(),p.list=l(p.list)(/bull/g,p.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+p.def.source+")")(),p.blockquote=l(p.blockquote)("def",p.def)(),p._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",p.html=l(p.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,p._tag)(),p.paragraph=l(p.paragraph)("hr",p.hr)("heading",p.heading)("lheading",p.lheading)("blockquote",p.blockquote)("tag","<"+p._tag)("def",p.def)(),p.normal=d({},p),p.gfm=d({},p.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/}),p.gfm.paragraph=l(p.paragraph)("(?!","(?!"+p.gfm.fences.source.replace("\\1","\\2")+"|"+p.list.source.replace("\\1","\\3")+"|")(),p.tables=d({},p.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),e.rules=p,e.lex=function(t,n){var a=new e(n);return a.lex(t)},e.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var a,r,i,s,o,l,c,d,u,e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?i:i.replace(/\n+$/,"")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2],text:i[3]});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if(t&&(i=this.rules.nptable.exec(e))){for(e=e.substring(i[0].length),l={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/\n$/,"").split("\n")},d=0;d ?/gm,""),this.token(i,t,!0),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),s=i[2],this.tokens.push({type:"list_start",ordered:s.length>1}),i=i[0].match(this.rules.item),a=!1,u=i.length,d=0;u>d;d++)l=i[d],c=l.length,l=l.replace(/^ *([*+-]|\d+\.) +/,""),~l.indexOf("\n ")&&(c-=l.length,l=this.options.pedantic?l.replace(/^ {1,4}/gm,""):l.replace(new RegExp("^ {1,"+c+"}","gm"),"")),this.options.smartLists&&d!==u-1&&(o=p.bullet.exec(i[d+1])[0],s===o||s.length>1&&o.length>1||(e=i.slice(d+1).join("\n")+e,d=u-1)),r=a||/\n\n(?!\s*$)/.test(l),d!==u-1&&(a="\n"===l.charAt(l.length-1),r||(r=a)),this.tokens.push({type:r?"loose_item_start":"list_item_start"}),this.token(l,!1,n),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:"pre"===i[1]||"script"===i[1]||"style"===i[1],text:i[0]});else if(!n&&t&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),this.tokens.links[i[1].toLowerCase()]={href:i[2],title:i[3]};else if(t&&(i=this.rules.table.exec(e))){for(e=e.substring(i[0].length),l={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/(?: *\| *)?\n$/,"").split("\n")},d=0;d])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:c,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:c,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/,m.link=l(m.link)("inside",m._inside)("href",m._href)(),m.reflink=l(m.reflink)("inside",m._inside)(),m.normal=d({},m),m.pedantic=d({},m.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),m.gfm=d({},m.normal,{escape:l(m.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:l(m.text)("]|","~]|")("|","|https?://|")()}),m.breaks=d({},m.gfm,{br:l(m.br)("{2,}","*")(),text:l(m.gfm.text)("{2,}","*")()}),a.rules=m,a.output=function(e,t,n){var r=new a(t,n);return r.output(e)},a.prototype.output=function(e){for(var t,n,a,r,i="";e;)if(r=this.rules.escape.exec(e))e=e.substring(r[0].length),i+=r[1];else if(r=this.rules.autolink.exec(e))e=e.substring(r[0].length),"@"===r[2]?(n=this.mangle(":"===r[1].charAt(6)?r[1].substring(7):r[1]),a=this.mangle("mailto:")+n):(n=s(r[1]),a=n),i+=this.renderer.link(a,null,n);else if(this.inLink||!(r=this.rules.url.exec(e))){if(r=this.rules.tag.exec(e))!this.inLink&&/^/i.test(r[0])&&(this.inLink=!1),e=e.substring(r[0].length),i+=this.options.sanitize?s(r[0]):r[0];else if(r=this.rules.link.exec(e))e=e.substring(r[0].length),this.inLink=!0,i+=this.outputLink(r,{href:r[2],title:r[3]}),this.inLink=!1;else if((r=this.rules.reflink.exec(e))||(r=this.rules.nolink.exec(e))){if(e=e.substring(r[0].length),t=(r[2]||r[1]).replace(/\s+/g," "),t=this.links[t.toLowerCase()],!t||!t.href){i+=r[0].charAt(0),e=r[0].substring(1)+e;continue}this.inLink=!0,i+=this.outputLink(r,t),this.inLink=!1}else if(r=this.rules.strong.exec(e))e=e.substring(r[0].length),i+=this.renderer.strong(this.output(r[2]||r[1]));else if(r=this.rules.em.exec(e))e=e.substring(r[0].length),i+=this.renderer.em(this.output(r[2]||r[1]));else if(r=this.rules.code.exec(e))e=e.substring(r[0].length),i+=this.renderer.codespan(s(r[2],!0));else if(r=this.rules.br.exec(e))e=e.substring(r[0].length),i+=this.renderer.br();else if(r=this.rules.del.exec(e))e=e.substring(r[0].length),i+=this.renderer.del(this.output(r[1]));else if(r=this.rules.text.exec(e))e=e.substring(r[0].length),i+=s(this.smartypants(r[0]));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else e=e.substring(r[0].length),n=s(r[1]),a=n,i+=this.renderer.link(a,null,n);return i},a.prototype.outputLink=function(e,t){var n=s(t.href),a=t.title?s(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,a,this.output(e[1])):this.renderer.image(n,a,s(e[1]))},a.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},a.prototype.mangle=function(e){for(var t,n="",a=e.length,r=0;a>r;r++)t=e.charCodeAt(r),Math.random()>.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},r.prototype.code=function(e,t,n){if(this.options.highlight){var a=this.options.highlight(e,t);null!=a&&a!==e&&(n=!0,e=a)}return t?'
'+(n?e:s(e,!0))+"\n
\n":"
"+(n?e:s(e,!0))+"\n
"},r.prototype.blockquote=function(e){return"
\n"+e+"
\n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n){return"'+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},r.prototype.list=function(e,t){var n=t?"ol":"ul";return"<"+n+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return"\n\n"+e+"\n\n"+t+"\n
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td",a=t.align?"<"+n+' style="text-align:'+t.align+'">':"<"+n+">";return a+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(this.options.sanitize){try{var a=decodeURIComponent(o(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(r){return""}if(0===a.indexOf("javascript:")||0===a.indexOf("vbscript:"))return""}var i='
    "},r.prototype.image=function(e,t,n){var a=''+n+'":">"},i.parse=function(e,t,n){var a=new i(t,n);return a.parse(e)},i.prototype.parse=function(e){this.inline=new a(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},i.prototype.next=function(){return this.token=this.tokens.pop()},i.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},i.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},i.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,a,r,i="",s="";for(n="",e=0;e and the stuff below it (but before the second + //

    ) into the left pane. + do { + left.appendChild(content.firstChild); + } while (content.firstChild.tagName !== 'H1') + + var right = document.createElement('DIV'); + right.className = 'right'; + + // Insert everything else into the right pane. + do { + right.appendChild(content.firstChild); + } while (content.firstChild); + + content.appendChild(left); + content.appendChild(right); + } + } + }; + + Slidedown.prototype = { + // default object, can be set by setOptions() + // must be put here as static variable as all + // exported functions are staticized + options: { + "marked": { + "breaks": true + } + }, + + to: function to(target, cb) { + this.target = target; + + whenReady(function() { + if (typeof cb === "function") { + cb(); + } + }); + }, + + destination: function destination() { + var destination = typeof this.target === 'string' ? + document.querySelector(this.target) : this.target; + return destination; + }, + + append: function append(element) { + this.destination().appendChild(element); + }, + + fromElements: function fromElements(elements) { + var slidedown = this; + + whenReady(function() { + eachSlide(elements, function(slide, number) { + var element = document.createElement('DIV'); + element.id = 'slide-' + number; + element.className = 'slide'; + + var content = document.createElement('DIV'); + content.className = 'content'; + content.setAttribute('data-layout', slide.layout); + content.innerHTML = slide.html; + element.appendChild(content); + + var layout = slideLayouts[slide.layout]; + if (layout && typeof layout.postprocess === 'function') { + layout.postprocess(content); + } + + if (number === 1) { + addNavigationInstructions(element); + } + + slidedown.append(element); + }); + + // Attach left/right keyboard shortcuts + handleKey(39, nextSlide); + handleKey(37, prevSlide); + handleClick('x > 90%', nextSlide); + handleClick('x < 10%', prevSlide); + + var numSlides = document.getElementsByClassName('slide').length; + + // more key feature: + // using `home` key to go to first page + handleKey(36, goToSlide(1)); + + // using `end` key to go to last page + handleKey(35, goToSlide(numSlides)); + + // using `t` to go to toc page; + var tocElement = document.getElementById('toc'); + if (tocElement) { + handleKey(84, goToSlide(getElementSlideNo(tocElement))); + } + + // using `r` key to go to root page + // useful when the default md shows a listing of md's + handleKey(82, function() { + location.assign(location.pathname); + }); + + // Hammer integration with feature detection + if (typeof Hammer !== 'undefined') { + (function(Hammer) { + var hammer = Hammer(document, { + drag_block_horizontal: true + }); + hammer.on('swipeleft', nextSlide); + hammer.on('swiperight', prevSlide); + }(Hammer)); + } + + // Change title to the first h1 of md + changeTitle(); + + // Generate TOC if #toc is found + generateTOC(); + + // Focus on the target slide (or first, by default) + focusTargetSlide(); + window.addEventListener('hashchange', focusTargetSlide); + }); + + return slidedown; + }, + + fromHTML: function fromHTML(html) { + var elements = parseHTML(html); + return this.fromElements(elements); + }, + + fromMarkdown: function fromMarkdown(markdown) { + var markedOptions = deepDefaults({ + renderer: new CustomRenderer() + }, Slidedown.prototype.options.marked); + + marked.setOptions(markedOptions); + + var html = marked(markdown); + return this.fromHTML(html); + }, + + fromXHR: function fromXHR(title) { + var slidedown = this, + format = inferFormat(title); + + var request = new XMLHttpRequest(); + request.open('GET', title); + + request.addEventListener('load', function() { + slidedown['from' + format](request.responseText); + }); + + request.send(); + + return this; + }, + + // setOptions() should be run before any other function of Slidedown + setOptions: function setOptions(options) { + + // set the default value to some properties, + // otherwise if passing an empty object to setOption() + // will result to erase the default this.options. + zschema.registerFormat('defaultOptions', function(obj){ + obj = deepDefaults(obj, Slidedown.prototype.options); + return true; + }); + + var customOptionsSchema = { + type: "object", + properties:{ + marked: { + type: "object", + properties: { + gfm: { type: "boolean"}, + tables: { type: "boolean"}, + breaks: { type: "boolean"}, + pedantic: { type: "boolean"}, + sanitize: { type: "boolean"}, + smartLists: { type: "boolean"}, + smartypants: { type: "boolean"} + } + } + }, + format: "defaultOptions" + }; + + var validator = new zschema(); + var valid = validator.validate(options, customOptionsSchema); + if(!valid){ + console.log(validator.getLastError()); + return; + } + Slidedown.prototype.options = deepDefaults(options, Slidedown.prototype.options); + } + }; + + function whenReady(callback) { + if (document.readyState === "complete") { + setTimeout(callback, 0); + return; + } + + window.addEventListener('load', callback); + } + + function inferFormat(title) { + var extension = title.split('.').pop(); + + switch (extension) { + case 'htm': + case 'html': + return 'HTML'; + + case 'md': + case 'markdown': + default: + return 'Markdown'; + } + } + + function parseHTML(html) { + var wrapper = document.createElement('DIV'); + wrapper.innerHTML = html; + return wrapper.children; + } + + function eachSlide(doc, callback) { + var parts = [], + counter = 1; + + forEach(doc, function(element) { + if (element.tagName === 'HR') { + callback(createSlide(parts), counter++); + parts = []; + return; + } + + parts.push(element); + }); + + if (parts.length > 0) { + callback(createSlide(parts), counter++); + } + } + + function forEach(collection, callback) { + return Array.prototype.forEach.call(collection, callback); + } + + function createSlide(parts) { + return { + layout: getSlideLayout(parts), + html: parts.map(function(part) { return part.outerHTML; }).join('') + }; + } + + function getSlideLayout(parts) { + var key = parts.map(function(part) { return part.tagName; }).join(','); + + for (var layout in slideLayouts) { + if (slideLayouts[layout].pattern.test(key)) { + return layout; + } + } + + return 'default'; + } + + function addNavigationInstructions(element) { + var footer = document.createElement('FOOTER'); + element.appendChild(footer); + + var instructions = document.createElement('DIV'); + instructions.className = 'navigation-instructions'; + footer.appendChild(instructions); + + var label = document.createElement('P'); + label.textContent = 'Navigation options:'; + instructions.appendChild(label); + + var list = document.createElement('UL'); + instructions.appendChild(list); + + var options = [ + 'Use left + right arrow keys', + 'Click on the left + right sides of the screen', + 'Use home/ end key to go to first/ last page', + 'Use r key to go to root page', + 'Use t key to go to Table of Content' + ]; + + forEach(options, function(option) { + var listItem = document.createElement('LI'); + listItem.textContent = option; + list.appendChild(listItem); + }); + } + + function removeClass(element, className) { + if (!element) { return; } + element.classList.remove(className); + } + + function addClass(element, className) { + if (!element) { return; } + element.classList.add(className); + } + + function handleKey(keyCode, callback) { + document.addEventListener('keydown', function(e) { + if (e.keyCode === keyCode) { + callback(); + } + }); + } + + function handleClick(conditions, callback) { + conditions = parseConditions(conditions); + + document.addEventListener('click', function(e) { + if (conditions(e)) { + callback(); + } + }); + } + + function parseConditions(conditions) { + conditions = conditions.split(/\s+/); + + var property = conditions[0], + operator = conditions[1], + threshold = conditions[2]; + + if (threshold.charAt(threshold.length - 1) === '%') { + threshold = Number(threshold.substring(0, threshold.length - 1)); + threshold /= 100; + } else { + threshold = Number(threshold); + } + + var comparisonProperty; + switch (property) { + case 'x': + property = 'clientX'; + comparisonProperty = 'innerWidth'; + break; + + case 'y': + property = 'clientY'; + comparisonProperty = 'innerHeight'; + break; + + default: + throw "Unrecognized property: '" + property + '"'; + } + + switch (operator) { + case '<': + return function(e) { + return e[property] < (window[comparisonProperty] * threshold); + }; + + case '>': + return function(e) { + return e[property] > (window[comparisonProperty] * threshold); + }; + + default: + throw "Unrecognized operator: '" + operator + '"'; + } + } + + function nextSlide() { + var current = document.querySelector('.slide.current'), + prev = current.previousElementSibling, + next = current.nextElementSibling, + following = next && next.nextElementSibling; + + if (next) { + removeClass(prev, 'previous'); + removeClass(current, 'current'); + removeClass(next, 'next'); + + addClass(current, 'previous'); + addClass(next, 'current'); + addClass(following, 'next'); + + setSlideId(next.id); + } + } + + function prevSlide() { + var current = document.querySelector('.slide.current'), + prev = current.previousElementSibling, + next = current.nextElementSibling, + preceding = prev && prev.previousElementSibling; + + if (prev) { + removeClass(next, 'next'); + removeClass(current, 'current'); + removeClass(prev, 'previous'); + + addClass(current, 'next'); + addClass(prev, 'current'); + addClass(preceding, 'previous'); + + setSlideId(prev.id); + } + } + + function setSlideId(id) { + window.history.pushState({}, '', '#' + id); + } + + function focusTargetSlide() { + var current = document.querySelector('.slide.current'), + previous = document.querySelector('.slide.previous'), + next = document.querySelector('.slide.next'); + + removeClass(current, 'current'); + removeClass(previous, 'previous'); + removeClass(next, 'next'); + + var targetSlide = document.querySelector(window.location.hash || '.slide:first-child'); + addClass(targetSlide, 'current'); + addClass(targetSlide.previousElementSibling, 'previous'); + addClass(targetSlide.nextElementSibling, 'next'); + + // Correct for any rogue dragging that occurred. + setTimeout(function() { + window.scrollTo(0, window.scrollY); + }, 0); + } + + function changeTitle() { + var firstH1 = document.getElementsByTagName("h1")[0]; + var title = firstH1 ? firstH1.textContent : 'slidedown'; + document.title = title; + return title; + } + + function getElementSlideNo (element) { + while (!(/slide/.test(element.className) || element === null)) { + element = element.parentNode; + } + return parseInt(element.id.substr(6)); + } + + function generateTOC(){ + var tocElement = document.getElementById('toc'); + if (!tocElement) return ; + var headings = document.querySelectorAll("h1, h2"); + var tocMarkdownString = ""; + + forEach(headings, function (heading){ + switch (heading.tagName) { + case 'H1': + tocMarkdownString += '- [' + heading.textContent + '](#slide-' + getElementSlideNo(heading) +')\n'; + break; + case 'H2': + tocMarkdownString += '\t+ [' + heading.textContent + '](#slide-' + getElementSlideNo(heading) +')\n'; + break; + default: + } + }); + + tocElement.innerHTML = marked(tocMarkdownString); + } + + function goToSlide(slideNo) { + return function() { + setSlideId('slide-' + slideNo); + focusTargetSlide(); + }; + } + + function CustomRenderer() {} + + CustomRenderer.prototype = new marked.Renderer(); + + CustomRenderer.prototype.code = function code(code, lang) { + if (!lang) { + return marked.Renderer.prototype.code.call(this, code, lang); + } + + var html = hljs.highlight(lang, code).value; + return '
    ' + html + '
    '; + }; + + function staticize(constructor, properties) { + var staticized = {}; + + forEach(properties, function(property) { + staticized[property] = function() { + var instance = new constructor(); + return instance[property].apply(instance, arguments); + }; + }); + + return staticized; + } + + window.Slidedown = staticize(Slidedown, [ + 'fromElements', + 'fromHTML', + 'fromMarkdown', + 'fromXHR', + 'setOptions' + ]); + +})(); + +},{"deep-defaults":2,"highlight.js":6,"marked":125,"z-schema":136}],2:[function(require,module,exports){ +'use strict'; + +var _ = require('lodash'); + +/** + * Recursively assigns own enumerable properties of the source object to the destination object for all destination properties that resolve to undefined. + * @param {Object} dest destination object; this object is modified. + * @param {Object} src source object that has the defaults + * @returns {Object} destination object + */ +function _deepDefaults(dest, src) { + if(_.isUndefined(dest) || _.isNull(dest) || !_.isPlainObject(dest)) { return dest; } + + _.each(src, function(v, k) { + if(_.isUndefined(dest[k])) { + dest[k] = v; + } else if(_.isPlainObject(v)) { + _deepDefaults(dest[k], v); + } + }); + + return dest; +} + +exports = module.exports = _deepDefaults; +},{"lodash":3}],3:[function(require,module,exports){ +(function (global){ +/** + * @license + * lodash 3.0.1 (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.0.1'; + + /** 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-tolength) + * 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`, + * `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, !argCount) + : 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. + * @param {boolean} [isCloned] Specify cloning the source object. + * @returns {Function} Returns the new function. + */ + function baseMatches(source, isCloned) { + 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); + }; + } + } + if (isCloned) { + source = baseClone(source, true); + } + 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 value; + } + return prereq && object[index] === value; + } + + /** + * Checks if `value` is a valid array-like length. + * + * @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, matches(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, property(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, matches(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 index ? (result + 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('--foo-bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * 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': '', returnEnd: true, + subLanguage: '' + } + }, + PHP, + { + className: 'pi', + begin: /<\?\w+/, end: /\?>/, + relevance: 10 + }, + { + className: 'tag', + begin: '', + contains: [ + { + className: 'title', begin: /[^ \/><\n\t]+/, relevance: 0 + }, + TAG_INTERNALS + ] + } + ] + }; +}; +},{}],125:[function(require,module,exports){ +(function (global){ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +;(function() { + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ +}; + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + +block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + +block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + +block.html = replace(block.html) + ('comment', //) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /])*?>/) + (/tag/g, block._tag) + (); + +block.paragraph = replace(block.paragraph) + ('hr', block.hr) + ('heading', block.heading) + ('lheading', block.lheading) + ('blockquote', block.blockquote) + ('tag', '<' + block._tag) + ('def', block.def) + (); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, + paragraph: /^/ +}); + +block.gfm.paragraph = replace(block.paragraph) + ('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + (); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top, bq) { + var src = src.replace(/^ +$/gm, '') + , next + , loose + , cap + , bull + , b + , item + , space + , i + , l; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top, true); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + + this.tokens.push({ + type: 'list_start', + ordered: bull.length > 1 + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false, bq); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0] + }); + continue; + } + + // def + if ((!bq && top) && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.links[cap[1].toLowerCase()] = { + href: cap[2], + title: cap[3] + }; + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, + url: noop, + tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; + +inline.link = replace(inline.link) + ('inside', inline._inside) + ('href', inline._href) + (); + +inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + (); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: replace(inline.escape)('])', '~|])')(), + url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: replace(inline.text) + (']|', '~]|') + ('|', '|https?://|') + () +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: replace(inline.br)('{2,}', '*')(), + text: replace(inline.gfm.text)('{2,}', '*')() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer; + this.renderer.options = this.options; + + if (!this.links) { + throw new + Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '' + , link + , text + , href + , cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = cap[1].charAt(6) === ':' + ? this.mangle(cap[1].substring(7)) + : this.mangle(cap[1]); + href = this.mangle('mailto:') + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + src = src.substring(cap[0].length); + text = escape(cap[1]); + href = text; + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^
    /i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? escape(cap[0]) + : cap[0]; + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2], true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += escape(this.smartypants(cap[0])); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href) + , title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/--/g, '\u2014') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || {}; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
    '
    +      + (escaped ? code : escape(code, true))
    +      + '\n
    '; + } + + return '
    '
    +    + (escaped ? code : escape(code, true))
    +    + '\n
    \n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '
    \n' + quote + '
    \n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '' + + text + + '\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '
    \n' : '
    \n'; +}; + +Renderer.prototype.list = function(body, ordered) { + var type = ordered ? 'ol' : 'ul'; + return '<' + type + '>\n' + body + '\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; +}; + +Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; +}; + +Renderer.prototype.table = function(header, body) { + return '\n' + + '\n' + + header + + '\n' + + '\n' + + body + + '\n' + + '
    \n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.em = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.codespan = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; +}; + +Renderer.prototype.del = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return ''; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { + return ''; + } + } + var out = '
    '; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + var out = '' + text + '' : '>'; + return out; +}; + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer; + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options, renderer) { + var parser = new Parser(options, renderer); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + this.token.text); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '' + , body = '' + , i + , row + , cell + , flags + , j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + flags = { header: true, align: this.token.align[i] }; + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + var body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + var body = '' + , ordered = this.token.ordered; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered); + } + case 'list_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + return html.replace(/&([#\w]+);/g, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; +} + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1 + , target + , key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + + +/** + * Marked + */ + +function marked(src, opt, callback) { + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight + , tokens + , pending + , i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/chjj/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occured:

    '
    +        + escape(e.message + '', true)
    +        + '
    '; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}()); + +}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],126:[function(require,module,exports){ +/*! + * Copyright (c) 2014 Chris O'Hara + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +(function (name, definition) { + if (typeof exports !== 'undefined' && typeof module !== 'undefined') { + module.exports = definition(); + } else if (typeof define === 'function' && typeof define.amd === 'object') { + define(definition); + } else { + this[name] = definition(); + } +})('validator', function (validator) { + + 'use strict'; + + validator = { version: '3.39.0' }; + + var emailUser = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e])|(\\[\x01-\x09\x0b\x0c\x0d-\x7f])))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))$/i; + + var emailUserUtf8 = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))$/i; + + var displayName = /^(?:[a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~\.]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(?:[a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~\.]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\s)*<(.+)>$/i; + + var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/; + + var isin = /^[A-Z]{2}[0-9A-Z]{9}[0-9]$/; + + var isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/ + , isbn13Maybe = /^(?:[0-9]{13})$/; + + var ipv4Maybe = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + , ipv6Block = /^[0-9A-F]{1,4}$/i; + + var uuid = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i + , '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i + , '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i + , all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }; + + var alpha = /^[A-Z]+$/i + , alphanumeric = /^[0-9A-Z]+$/i + , numeric = /^[-+]?[0-9]+$/ + , int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/ + , float = /^(?:[-+]?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/ + , hexadecimal = /^[0-9A-F]+$/i + , hexcolor = /^#?([0-9A-F]{3}|[0-9A-F]{6})$/i; + + var ascii = /^[\x00-\x7F]+$/ + , multibyte = /[^\x00-\x7F]/ + , fullWidth = /[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/ + , halfWidth = /[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/; + + var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; + + var base64 = /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i; + + var phones = { + 'zh-CN': /^(\+?0?86\-?)?1[345789]\d{9}$/, + 'en-ZA': /^(\+?27|0)\d{9}$/, + 'en-AU': /^(\+?61|0)4\d{8}$/, + 'en-HK': /^(\+?852\-?)?[569]\d{3}\-?\d{4}$/, + 'fr-FR': /^(\+?33|0)[67]\d{8}$/, + 'pt-PT': /^(\+351)?9[1236]\d{7}$/, + 'el-GR': /^(\+30)?((2\d{9})|(69\d{8}))$/, + 'en-GB': /^(\+?44|0)7\d{9}$/, + 'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/, + 'en-ZM': /^(\+26)?09[567]\d{7}$/ + }; + + validator.extend = function (name, fn) { + validator[name] = function () { + var args = Array.prototype.slice.call(arguments); + args[0] = validator.toString(args[0]); + return fn.apply(validator, args); + }; + }; + + //Right before exporting the validator object, pass each of the builtins + //through extend() so that their first argument is coerced to a string + validator.init = function () { + for (var name in validator) { + if (typeof validator[name] !== 'function' || name === 'toString' || + name === 'toDate' || name === 'extend' || name === 'init') { + continue; + } + validator.extend(name, validator[name]); + } + }; + + validator.toString = function (input) { + if (typeof input === 'object' && input !== null && input.toString) { + input = input.toString(); + } else if (input === null || typeof input === 'undefined' || (isNaN(input) && !input.length)) { + input = ''; + } else if (typeof input !== 'string') { + input += ''; + } + return input; + }; + + validator.toDate = function (date) { + if (Object.prototype.toString.call(date) === '[object Date]') { + return date; + } + date = Date.parse(date); + return !isNaN(date) ? new Date(date) : null; + }; + + validator.toFloat = function (str) { + return parseFloat(str); + }; + + validator.toInt = function (str, radix) { + return parseInt(str, radix || 10); + }; + + validator.toBoolean = function (str, strict) { + if (strict) { + return str === '1' || str === 'true'; + } + return str !== '0' && str !== 'false' && str !== ''; + }; + + validator.equals = function (str, comparison) { + return str === validator.toString(comparison); + }; + + validator.contains = function (str, elem) { + return str.indexOf(validator.toString(elem)) >= 0; + }; + + validator.matches = function (str, pattern, modifiers) { + if (Object.prototype.toString.call(pattern) !== '[object RegExp]') { + pattern = new RegExp(pattern, modifiers); + } + return pattern.test(str); + }; + + var default_email_options = { + allow_display_name: false, + allow_utf8_local_part: true, + require_tld: true + }; + + validator.isEmail = function (str, options) { + options = merge(options, default_email_options); + + if (options.allow_display_name) { + var display_email = str.match(displayName); + if (display_email) { + str = display_email[1]; + } + } else if (/\s/.test(str)) { + return false; + } + + var parts = str.split('@') + , domain = parts.pop() + , user = parts.join('@'); + + if (!validator.isFQDN(domain, {require_tld: options.require_tld})) { + return false; + } + + return options.allow_utf8_local_part ? + emailUserUtf8.test(user) : + emailUser.test(user); + }; + + var default_url_options = { + protocols: [ 'http', 'https', 'ftp' ] + , require_tld: true + , require_protocol: false + , allow_underscores: false + , allow_trailing_dot: false + , allow_protocol_relative_urls: false + }; + + validator.isURL = function (url, options) { + if (!url || url.length >= 2083 || /\s/.test(url)) { + return false; + } + if (url.indexOf('mailto:') === 0) { + return false; + } + options = merge(options, default_url_options); + var protocol, auth, host, hostname, port, + port_str, split; + split = url.split('://'); + if (split.length > 1) { + protocol = split.shift(); + if (options.protocols.indexOf(protocol) === -1) { + return false; + } + } else if (options.require_protocol) { + return false; + } else if (options.allow_protocol_relative_urls && url.substr(0, 2) === '//') { + split[0] = url.substr(2); + } + url = split.join('://'); + split = url.split('#'); + url = split.shift(); + + split = url.split('?'); + url = split.shift(); + + split = url.split('/'); + url = split.shift(); + split = url.split('@'); + if (split.length > 1) { + auth = split.shift(); + if (auth.indexOf(':') >= 0 && auth.split(':').length > 2) { + return false; + } + } + hostname = split.join('@'); + split = hostname.split(':'); + host = split.shift(); + if (split.length) { + port_str = split.join(':'); + port = parseInt(port_str, 10); + if (!/^[0-9]+$/.test(port_str) || port <= 0 || port > 65535) { + return false; + } + } + if (!validator.isIP(host) && !validator.isFQDN(host, options) && + host !== 'localhost') { + return false; + } + if (options.host_whitelist && + options.host_whitelist.indexOf(host) === -1) { + return false; + } + if (options.host_blacklist && + options.host_blacklist.indexOf(host) !== -1) { + return false; + } + return true; + }; + + validator.isIP = function (str, version) { + version = validator.toString(version); + if (!version) { + return validator.isIP(str, 4) || validator.isIP(str, 6); + } else if (version === '4') { + if (!ipv4Maybe.test(str)) { + return false; + } + var parts = str.split('.').sort(function (a, b) { + return a - b; + }); + return parts[3] <= 255; + } else if (version === '6') { + var blocks = str.split(':'); + var foundOmissionBlock = false; // marker to indicate :: + + if (blocks.length > 8) + return false; + + // initial or final :: + if (str === '::') { + return true; + } else if (str.substr(0, 2) === '::') { + blocks.shift(); + blocks.shift(); + foundOmissionBlock = true; + } else if (str.substr(str.length - 2) === '::') { + blocks.pop(); + blocks.pop(); + foundOmissionBlock = true; + } + + for (var i = 0; i < blocks.length; ++i) { + // test for a :: which can not be at the string start/end + // since those cases have been handled above + if (blocks[i] === '' && i > 0 && i < blocks.length -1) { + if (foundOmissionBlock) + return false; // multiple :: in address + foundOmissionBlock = true; + } else if (!ipv6Block.test(blocks[i])) { + return false; + } + } + + if (foundOmissionBlock) { + return blocks.length >= 1; + } else { + return blocks.length === 8; + } + } + return false; + }; + + var default_fqdn_options = { + require_tld: true + , allow_underscores: false + , allow_trailing_dot: false + }; + + validator.isFQDN = function (str, options) { + options = merge(options, default_fqdn_options); + + /* Remove the optional trailing dot before checking validity */ + if (options.allow_trailing_dot && str[str.length - 1] === '.') { + str = str.substring(0, str.length - 1); + } + var parts = str.split('.'); + if (options.require_tld) { + var tld = parts.pop(); + if (!parts.length || !/^([a-z\u00a1-\uffff]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) { + return false; + } + } + for (var part, i = 0; i < parts.length; i++) { + part = parts[i]; + if (options.allow_underscores) { + if (part.indexOf('__') >= 0) { + return false; + } + part = part.replace(/_/g, ''); + } + if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) { + return false; + } + if (part[0] === '-' || part[part.length - 1] === '-' || + part.indexOf('---') >= 0) { + return false; + } + } + return true; + }; + + validator.isAlpha = function (str) { + return alpha.test(str); + }; + + validator.isAlphanumeric = function (str) { + return alphanumeric.test(str); + }; + + validator.isNumeric = function (str) { + return numeric.test(str); + }; + + validator.isHexadecimal = function (str) { + return hexadecimal.test(str); + }; + + validator.isHexColor = function (str) { + return hexcolor.test(str); + }; + + validator.isLowercase = function (str) { + return str === str.toLowerCase(); + }; + + validator.isUppercase = function (str) { + return str === str.toUpperCase(); + }; + + validator.isInt = function (str, options) { + options = options || {}; + return int.test(str) && (!options.hasOwnProperty('min') || str >= options.min) && (!options.hasOwnProperty('max') || str <= options.max); + }; + + validator.isFloat = function (str, options) { + options = options || {}; + return str !== '' && float.test(str) && (!options.hasOwnProperty('min') || str >= options.min) && (!options.hasOwnProperty('max') || str <= options.max); + }; + + validator.isDivisibleBy = function (str, num) { + return validator.toFloat(str) % validator.toInt(num) === 0; + }; + + validator.isNull = function (str) { + return str.length === 0; + }; + + validator.isLength = function (str, min, max) { + var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || []; + var len = str.length - surrogatePairs.length; + return len >= min && (typeof max === 'undefined' || len <= max); + }; + + validator.isByteLength = function (str, min, max) { + return str.length >= min && (typeof max === 'undefined' || str.length <= max); + }; + + validator.isUUID = function (str, version) { + var pattern = uuid[version ? version : 'all']; + return pattern && pattern.test(str); + }; + + validator.isDate = function (str) { + return !isNaN(Date.parse(str)); + }; + + validator.isAfter = function (str, date) { + var comparison = validator.toDate(date || new Date()) + , original = validator.toDate(str); + return !!(original && comparison && original > comparison); + }; + + validator.isBefore = function (str, date) { + var comparison = validator.toDate(date || new Date()) + , original = validator.toDate(str); + return original && comparison && original < comparison; + }; + + validator.isIn = function (str, options) { + var i; + if (Object.prototype.toString.call(options) === '[object Array]') { + var array = []; + for (i in options) { + array[i] = validator.toString(options[i]); + } + return array.indexOf(str) >= 0; + } else if (typeof options === 'object') { + return options.hasOwnProperty(str); + } else if (options && typeof options.indexOf === 'function') { + return options.indexOf(str) >= 0; + } + return false; + }; + + validator.isCreditCard = function (str) { + var sanitized = str.replace(/[^0-9]+/g, ''); + if (!creditCard.test(sanitized)) { + return false; + } + var sum = 0, digit, tmpNum, shouldDouble; + for (var i = sanitized.length - 1; i >= 0; i--) { + digit = sanitized.substring(i, (i + 1)); + tmpNum = parseInt(digit, 10); + if (shouldDouble) { + tmpNum *= 2; + if (tmpNum >= 10) { + sum += ((tmpNum % 10) + 1); + } else { + sum += tmpNum; + } + } else { + sum += tmpNum; + } + shouldDouble = !shouldDouble; + } + return !!((sum % 10) === 0 ? sanitized : false); + }; + + validator.isISIN = function (str) { + if (!isin.test(str)) { + return false; + } + + var checksumStr = str.replace(/[A-Z]/g, function(character) { + return parseInt(character, 36); + }); + + var sum = 0, digit, tmpNum, shouldDouble = true; + for (var i = checksumStr.length - 2; i >= 0; i--) { + digit = checksumStr.substring(i, (i + 1)); + tmpNum = parseInt(digit, 10); + if (shouldDouble) { + tmpNum *= 2; + if (tmpNum >= 10) { + sum += tmpNum + 1; + } else { + sum += tmpNum; + } + } else { + sum += tmpNum; + } + shouldDouble = !shouldDouble; + } + + return parseInt(str.substr(str.length - 1), 10) === (10000 - sum) % 10; + }; + + validator.isISBN = function (str, version) { + version = validator.toString(version); + if (!version) { + return validator.isISBN(str, 10) || validator.isISBN(str, 13); + } + var sanitized = str.replace(/[\s-]+/g, '') + , checksum = 0, i; + if (version === '10') { + if (!isbn10Maybe.test(sanitized)) { + return false; + } + for (i = 0; i < 9; i++) { + checksum += (i + 1) * sanitized.charAt(i); + } + if (sanitized.charAt(9) === 'X') { + checksum += 10 * 10; + } else { + checksum += 10 * sanitized.charAt(9); + } + if ((checksum % 11) === 0) { + return !!sanitized; + } + } else if (version === '13') { + if (!isbn13Maybe.test(sanitized)) { + return false; + } + var factor = [ 1, 3 ]; + for (i = 0; i < 12; i++) { + checksum += factor[i % 2] * sanitized.charAt(i); + } + if (sanitized.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) { + return !!sanitized; + } + } + return false; + }; + + validator.isMobilePhone = function(str, locale) { + if (locale in phones) { + return phones[locale].test(str); + } + return false; + }; + + var default_currency_options = { + symbol: '$' + , require_symbol: false + , allow_space_after_symbol: false + , symbol_after_digits: false + , allow_negatives: true + , parens_for_negatives: false + , negative_sign_before_digits: false + , negative_sign_after_digits: false + , allow_negative_sign_placeholder: false + , thousands_separator: ',' + , decimal_separator: '.' + , allow_space_after_digits: false + }; + + validator.isCurrency = function (str, options) { + options = merge(options, default_currency_options); + + return currencyRegex(options).test(str); + }; + + validator.isJSON = function (str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + }; + + validator.isMultibyte = function (str) { + return multibyte.test(str); + }; + + validator.isAscii = function (str) { + return ascii.test(str); + }; + + validator.isFullWidth = function (str) { + return fullWidth.test(str); + }; + + validator.isHalfWidth = function (str) { + return halfWidth.test(str); + }; + + validator.isVariableWidth = function (str) { + return fullWidth.test(str) && halfWidth.test(str); + }; + + validator.isSurrogatePair = function (str) { + return surrogatePair.test(str); + }; + + validator.isBase64 = function (str) { + return base64.test(str); + }; + + validator.isMongoId = function (str) { + return validator.isHexadecimal(str) && str.length === 24; + }; + + validator.ltrim = function (str, chars) { + var pattern = chars ? new RegExp('^[' + chars + ']+', 'g') : /^\s+/g; + return str.replace(pattern, ''); + }; + + validator.rtrim = function (str, chars) { + var pattern = chars ? new RegExp('[' + chars + ']+$', 'g') : /\s+$/g; + return str.replace(pattern, ''); + }; + + validator.trim = function (str, chars) { + var pattern = chars ? new RegExp('^[' + chars + ']+|[' + chars + ']+$', 'g') : /^\s+|\s+$/g; + return str.replace(pattern, ''); + }; + + validator.escape = function (str) { + return (str.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + .replace(/\//g, '/') + .replace(/\`/g, '`')); + }; + + validator.stripLow = function (str, keep_new_lines) { + var chars = keep_new_lines ? '\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F' : '\\x00-\\x1F\\x7F'; + return validator.blacklist(str, chars); + }; + + validator.whitelist = function (str, chars) { + return str.replace(new RegExp('[^' + chars + ']+', 'g'), ''); + }; + + validator.blacklist = function (str, chars) { + return str.replace(new RegExp('[' + chars + ']+', 'g'), ''); + }; + + var default_normalize_email_options = { + lowercase: true + }; + + validator.normalizeEmail = function (email, options) { + options = merge(options, default_normalize_email_options); + if (!validator.isEmail(email)) { + return false; + } + var parts = email.split('@', 2); + parts[1] = parts[1].toLowerCase(); + if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') { + parts[0] = parts[0].toLowerCase().replace(/\./g, ''); + if (parts[0][0] === '+') { + return false; + } + parts[0] = parts[0].split('+')[0]; + parts[1] = 'gmail.com'; + } else if (options.lowercase) { + parts[0] = parts[0].toLowerCase(); + } + return parts.join('@'); + }; + + function merge(obj, defaults) { + obj = obj || {}; + for (var key in defaults) { + if (typeof obj[key] === 'undefined') { + obj[key] = defaults[key]; + } + } + return obj; + } + + function currencyRegex(options) { + var symbol = '(\\' + options.symbol.replace(/\./g, '\\.') + ')' + (options.require_symbol ? '' : '?') + , negative = '-?' + , whole_dollar_amount_without_sep = '[1-9]\\d*' + , whole_dollar_amount_with_sep = '[1-9]\\d{0,2}(\\' + options.thousands_separator + '\\d{3})*' + , valid_whole_dollar_amounts = ['0', whole_dollar_amount_without_sep, whole_dollar_amount_with_sep] + , whole_dollar_amount = '(' + valid_whole_dollar_amounts.join('|') + ')?' + , decimal_amount = '(\\' + options.decimal_separator + '\\d{2})?'; + var pattern = whole_dollar_amount + decimal_amount; + // default is negative sign before symbol, but there are two other options (besides parens) + if (options.allow_negatives && !options.parens_for_negatives) { + if (options.negative_sign_after_digits) { + pattern += negative; + } + else if (options.negative_sign_before_digits) { + pattern = negative + pattern; + } + } + // South African Rand, for example, uses R 123 (space) and R-123 (no space) + if (options.allow_negative_sign_placeholder) { + pattern = '( (?!\\-))?' + pattern; + } + else if (options.allow_space_after_symbol) { + pattern = ' ?' + pattern; + } + else if (options.allow_space_after_digits) { + pattern += '( (?!$))?'; + } + if (options.symbol_after_digits) { + pattern += symbol; + } else { + pattern = symbol + pattern; + } + if (options.allow_negatives) { + if (options.parens_for_negatives) { + pattern = '(\\(' + pattern + '\\)|' + pattern + ')'; + } + else if (!(options.negative_sign_before_digits || options.negative_sign_after_digits)) { + pattern = negative + pattern; + } + } + return new RegExp( + '^' + + // ensure there's a dollar and/or decimal amount, and that it doesn't start with a space or a negative sign followed by a space + '(?!-? )(?=.*\\d)' + + pattern + + '$' + ); + } + + validator.init(); + + return validator; + +}); + +},{}],127:[function(require,module,exports){ +"use strict"; + +module.exports = { + + INVALID_TYPE: "Expected type {0} but found type {1}", + INVALID_FORMAT: "Object didn't pass validation for format {0}: {1}", + ENUM_MISMATCH: "No enum match for: {0}", + ANY_OF_MISSING: "Data does not match any schemas from 'anyOf'", + ONE_OF_MISSING: "Data does not match any schemas from 'oneOf'", + ONE_OF_MULTIPLE: "Data is valid against more than one schema from 'oneOf'", + NOT_PASSED: "Data matches schema from 'not'", + + // Array errors + ARRAY_LENGTH_SHORT: "Array is too short ({0}), minimum {1}", + ARRAY_LENGTH_LONG: "Array is too long ({0}), maximum {1}", + ARRAY_UNIQUE: "Array items are not unique (indexes {0} and {1})", + ARRAY_ADDITIONAL_ITEMS: "Additional items not allowed", + + // Numeric errors + MULTIPLE_OF: "Value {0} is not a multiple of {1}", + MINIMUM: "Value {0} is less than minimum {1}", + MINIMUM_EXCLUSIVE: "Value {0} is equal or less than exclusive minimum {1}", + MAXIMUM: "Value {0} is greater than maximum {1}", + MAXIMUM_EXCLUSIVE: "Value {0} is equal or greater than exclusive maximum {1}", + + // Object errors + OBJECT_PROPERTIES_MINIMUM: "Too few properties defined ({0}), minimum {1}", + OBJECT_PROPERTIES_MAXIMUM: "Too many properties defined ({0}), maximum {1}", + OBJECT_MISSING_REQUIRED_PROPERTY: "Missing required property: {0}", + OBJECT_ADDITIONAL_PROPERTIES: "Additional properties not allowed: {0}", + OBJECT_DEPENDENCY_KEY: "Dependency failed - key must exist: {0} (due to key: {1})", + + // String errors + MIN_LENGTH: "String is too short ({0} chars), minimum {1}", + MAX_LENGTH: "String is too long ({0} chars), maximum {1}", + PATTERN: "String does not match pattern {0}: {1}", + + // Schema validation errors + KEYWORD_TYPE_EXPECTED: "Keyword '{0}' is expected to be of type '{1}'", + KEYWORD_UNDEFINED_STRICT: "Keyword '{0}' must be defined in strict mode", + KEYWORD_UNEXPECTED: "Keyword '{0}' is not expected to appear in the schema", + KEYWORD_MUST_BE: "Keyword '{0}' must be {1}", + KEYWORD_DEPENDENCY: "Keyword '{0}' requires keyword '{1}'", + KEYWORD_PATTERN: "Keyword '{0}' is not a valid RegExp pattern: {1}", + KEYWORD_VALUE_TYPE: "Each element of keyword '{0}' array must be a '{1}'", + UNKNOWN_FORMAT: "There is no validation function for format '{0}'", + CUSTOM_MODE_FORCE_PROPERTIES: "{0} must define at least one property if present", + + // Remote errors + REF_UNRESOLVED: "Reference has not been resolved during compilation: {0}", + UNRESOLVABLE_REFERENCE: "Reference could not be resolved: {0}", + SCHEMA_NOT_REACHABLE: "Validator was not able to read schema with uri: {0}", + SCHEMA_TYPE_EXPECTED: "Schema is expected to be of type 'object'", + SCHEMA_NOT_AN_OBJECT: "Schema is not an object: {0}", + ASYNC_TIMEOUT: "{0} asynchronous task(s) have timed out after {1} ms", + PARENT_SCHEMA_VALIDATION_FAILED: "Schema failed to validate against its parent schema, see inner errors for details.", + REMOTE_NOT_VALID: "Remote reference didn't compile successfully: {0}" + +}; + +},{}],128:[function(require,module,exports){ +/*jshint maxlen: false*/ + +var validator = require("validator"); + +var FormatValidators = { + "date": function (date) { + if (typeof date !== "string") { + return true; + } + // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 + var matches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(date); + if (matches === null) { + return false; + } + // var year = matches[1]; + // var month = matches[2]; + // var day = matches[3]; + if (matches[2] < "01" || matches[2] > "12" || matches[3] < "01" || matches[3] > "31") { + return false; + } + return true; + }, + "date-time": function (dateTime) { + if (typeof dateTime !== "string") { + return true; + } + // date-time from http://tools.ietf.org/html/rfc3339#section-5.6 + var s = dateTime.toLowerCase().split("t"); + if (!FormatValidators.date(s[0])) { + return false; + } + var matches = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/.exec(s[1]); + if (matches === null) { + return false; + } + // var hour = matches[1]; + // var minute = matches[2]; + // var second = matches[3]; + // var fraction = matches[4]; + // var timezone = matches[5]; + if (matches[1] > "23" || matches[2] > "59" || matches[3] > "59") { + return false; + } + return true; + }, + "email": function (email) { + if (typeof email !== "string") { + return true; + } + return validator.isEmail(email, { "require_tld": true }); + }, + "hostname": function (hostname) { + if (typeof hostname !== "string") { + return true; + } + /* + http://json-schema.org/latest/json-schema-validation.html#anchor114 + A string instance is valid against this attribute if it is a valid + representation for an Internet host name, as defined by RFC 1034, section 3.1 [RFC1034]. + + http://tools.ietf.org/html/rfc1034#section-3.5 + + ::= any one of the ten digits 0 through 9 + var digit = /[0-9]/; + + ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case + var letter = /[a-zA-Z]/; + + ::= | + var letDig = /[0-9a-zA-Z]/; + + ::= | "-" + var letDigHyp = /[-0-9a-zA-Z]/; + + ::= | + var ldhStr = /[-0-9a-zA-Z]+/; + +