From 6775d80196c02e28e5dab2cbda0bf29ec3ab4778 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Fri, 7 Aug 2026 22:39:47 -0700 Subject: [PATCH 1/3] d2dagre: use native Go Dagro port --- .gitattributes | 1 - .prettierignore | 1 - README.md | 6 +- ci/release/README.md | 4 - ci/release/changelogs/next.md | 1 + d2layouts/d2dagrelayout/NOTICE.txt | 9 +- d2layouts/d2dagrelayout/dagre.js | 3809 ------------------ d2layouts/d2dagrelayout/dagre.js.br | Bin 54030 -> 0 bytes d2layouts/d2dagrelayout/layout.go | 154 +- d2layouts/d2dagrelayout/layout_embed.go | 10 - d2layouts/d2dagrelayout/layout_embed_wasm.go | 24 - d2layouts/d2dagrelayout/object_mapper.go | 30 - d2layouts/d2dagrelayout/setup.js | 7 - d2plugin/plugin_dagre.go | 4 +- go.mod | 1 + go.sum | 2 + 16 files changed, 76 insertions(+), 3987 deletions(-) delete mode 100644 d2layouts/d2dagrelayout/dagre.js delete mode 100644 d2layouts/d2dagrelayout/dagre.js.br delete mode 100644 d2layouts/d2dagrelayout/layout_embed.go delete mode 100644 d2layouts/d2dagrelayout/layout_embed_wasm.go delete mode 100644 d2layouts/d2dagrelayout/setup.js diff --git a/.gitattributes b/.gitattributes index 5b491df70d..65d508162a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,7 +2,6 @@ **/testdata/**/*.json linguist-generated go.mod linguist-generated go.sum linguist-generated -d2layouts/d2dagrelayout/dagre.js linguist-vendored d2layouts/d2elklayout/elk.js linguist-vendored d2renderers/d2svg/github-markdown.css linguist-vendored d2renderers/d2latex/mathjax.js linguist-vendored diff --git a/.prettierignore b/.prettierignore index 4cfcedd6ec..dfe5c5ee6e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,3 @@ -d2layouts/d2dagrelayout/dagre.js d2layouts/d2elklayout/setup.js d2renderers/d2latex/mathjax.js d2renderers/d2latex/polyfills.js diff --git a/README.md b/README.md index c4dbc21d69..b14137f365 100644 --- a/README.md +++ b/README.md @@ -193,9 +193,9 @@ bundled with the build or separately installed as a standalone binary. **Layout engines**: -- [dagre](https://github.com/dagrejs/dagre) (default, bundled): A fast, directed graph - layout engine that produces layered/hierarchical layouts. Based on Graphviz's DOT - algorithm. +- [Dagro](https://github.com/d2lang/dagro) (default, bundled): A native Go port of the + Dagre directed graph layout engine that produces layered/hierarchical layouts. Based + on Graphviz's DOT algorithm. - [ELK](https://github.com/kieler/elkjs) (bundled): A directed graph layout engine particularly suited for node-link diagrams with an inherent direction and ports. - [TALA](https://github.com/terrastruct/TALA) (binary): Novel layout engine designed diff --git a/ci/release/README.md b/ci/release/README.md index 05d2dadb96..2c5dc577f0 100644 --- a/ci/release/README.md +++ b/ci/release/README.md @@ -54,10 +54,6 @@ it depends on from ../sub/lib. - ./build.sh builds the release archives for each platform into ./build//*.tar.gz Run with --help for usage. -> note: Remember for production releases you need to set the $TSTRUCT_OS_ARCH_BUILDER -> variables as we must compile d2 directly on each release target to include dagre. -> See https://github.com/d2lang/d2/issues/31 - Use `--host-only` to build only the release for the host's `$OS-$ARCH` pair. ### Docker image helper diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 9f57e22b89..fcc6bdc41a 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -4,6 +4,7 @@ #### Improvements 🧹 +- d2dagre: replace the embedded JavaScript runtime with the native Go Dagro port without changing layout output - d2ascii: - sql_table and uml class shapes are supported [#2623](https://github.com/d2lang/d2/pull/2623) - newlines are handled [#2626](https://github.com/d2lang/d2/pull/2626) diff --git a/d2layouts/d2dagrelayout/NOTICE.txt b/d2layouts/d2dagrelayout/NOTICE.txt index cac5f33be9..64125d6883 100644 --- a/d2layouts/d2dagrelayout/NOTICE.txt +++ b/d2layouts/d2dagrelayout/NOTICE.txt @@ -1,6 +1,5 @@ -dagre.js comes from https://github.com/dagrejs/dagre +D2's Dagre layout uses Dagro, a native Go port of Dagre 0.8.5: +https://github.com/d2lang/dagro -Attribution: - -MIT License -https://github.com/dagrejs/dagre/blob/master/LICENSE +Dagro preserves the MIT attribution and license for Dagre and Graphlib in its +LICENSE and NOTICE files. diff --git a/d2layouts/d2dagrelayout/dagre.js b/d2layouts/d2dagrelayout/dagre.js deleted file mode 100644 index 741ec0b62c..0000000000 --- a/d2layouts/d2dagrelayout/dagre.js +++ /dev/null @@ -1,3809 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.dagre=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0;--i){entry=buckets[i].dequeue();if(entry){results=results.concat(removeNode(g,buckets,zeroIdx,entry,true));break}}}}return results}function removeNode(g,buckets,zeroIdx,entry,collectPredecessors){var results=collectPredecessors?[]:undefined;_.forEach(g.inEdges(entry.v),function(edge){var weight=g.edge(edge);var uEntry=g.node(edge.v);if(collectPredecessors){results.push({v:edge.v,w:edge.w})}uEntry.out-=weight;assignBucket(buckets,zeroIdx,uEntry)});_.forEach(g.outEdges(entry.v),function(edge){var weight=g.edge(edge);var w=edge.w;var wEntry=g.node(w);wEntry["in"]-=weight;assignBucket(buckets,zeroIdx,wEntry)});g.removeNode(entry.v);return results}function buildState(g,weightFn){var fasGraph=new Graph;var maxIn=0;var maxOut=0;_.forEach(g.nodes(),function(v){fasGraph.setNode(v,{v:v,in:0,out:0})}); -// Aggregate weights on nodes, but also sum the weights across multi-edges -// into a single edge for the fasGraph. -_.forEach(g.edges(),function(e){var prevWeight=fasGraph.edge(e.v,e.w)||0;var weight=weightFn(e);var edgeWeight=prevWeight+weight;fasGraph.setEdge(e.v,e.w,edgeWeight);maxOut=Math.max(maxOut,fasGraph.node(e.v).out+=weight);maxIn=Math.max(maxIn,fasGraph.node(e.w)["in"]+=weight)});var buckets=_.range(maxOut+maxIn+3).map(function(){return new List});var zeroIdx=maxIn+1;_.forEach(fasGraph.nodes(),function(v){assignBucket(buckets,zeroIdx,fasGraph.node(v))});return{graph:fasGraph,buckets:buckets,zeroIdx:zeroIdx}}function assignBucket(buckets,zeroIdx,entry){if(!entry.out){buckets[0].enqueue(entry)}else if(!entry["in"]){buckets[buckets.length-1].enqueue(entry)}else{buckets[entry.out-entry["in"]+zeroIdx].enqueue(entry)}}},{"./data/list":5,"./graphlib":7,"./lodash":10}],9:[function(require,module,exports){"use strict";var _=require("./lodash");var acyclic=require("./acyclic");var normalize=require("./normalize");var rank=require("./rank");var normalizeRanks=require("./util").normalizeRanks;var parentDummyChains=require("./parent-dummy-chains");var removeEmptyRanks=require("./util").removeEmptyRanks;var nestingGraph=require("./nesting-graph");var addBorderSegments=require("./add-border-segments");var coordinateSystem=require("./coordinate-system");var order=require("./order");var position=require("./position");var util=require("./util");var Graph=require("./graphlib").Graph;module.exports=layout;function layout(g,opts){var time=opts&&opts.debugTiming?util.time:util.notime;time("layout",function(){var layoutGraph=time(" buildLayoutGraph",function(){return buildLayoutGraph(g)});time(" runLayout",function(){runLayout(layoutGraph,time)});time(" updateInputGraph",function(){updateInputGraph(g,layoutGraph)})})}function runLayout(g,time){time(" makeSpaceForEdgeLabels",function(){makeSpaceForEdgeLabels(g)});time(" removeSelfEdges",function(){removeSelfEdges(g)});time(" acyclic",function(){acyclic.run(g)});time(" nestingGraph.run",function(){nestingGraph.run(g)});time(" rank",function(){rank(util.asNonCompoundGraph(g))});time(" injectEdgeLabelProxies",function(){injectEdgeLabelProxies(g)});time(" removeEmptyRanks",function(){removeEmptyRanks(g)});time(" nestingGraph.cleanup",function(){nestingGraph.cleanup(g)});time(" normalizeRanks",function(){normalizeRanks(g)});time(" assignRankMinMax",function(){assignRankMinMax(g)});time(" removeEdgeLabelProxies",function(){removeEdgeLabelProxies(g)});time(" normalize.run",function(){normalize.run(g)});time(" parentDummyChains",function(){parentDummyChains(g)});time(" addBorderSegments",function(){addBorderSegments(g)});time(" order",function(){order(g)});time(" insertSelfEdges",function(){insertSelfEdges(g)});time(" adjustCoordinateSystem",function(){coordinateSystem.adjust(g)});time(" position",function(){position(g)});time(" positionSelfEdges",function(){positionSelfEdges(g)});time(" removeBorderNodes",function(){removeBorderNodes(g)});time(" normalize.undo",function(){normalize.undo(g)});time(" fixupEdgeLabelCoords",function(){fixupEdgeLabelCoords(g)});time(" undoCoordinateSystem",function(){coordinateSystem.undo(g)});time(" translateGraph",function(){translateGraph(g)});time(" assignNodeIntersects",function(){assignNodeIntersects(g)});time(" reversePoints",function(){reversePointsForReversedEdges(g)});time(" acyclic.undo",function(){acyclic.undo(g)})} -/* - * Copies final layout information from the layout graph back to the input - * graph. This process only copies whitelisted attributes from the layout graph - * to the input graph, so it serves as a good place to determine what - * attributes can influence layout. - */function updateInputGraph(inputGraph,layoutGraph){_.forEach(inputGraph.nodes(),function(v){var inputLabel=inputGraph.node(v);var layoutLabel=layoutGraph.node(v);if(inputLabel){inputLabel.x=layoutLabel.x;inputLabel.y=layoutLabel.y;if(layoutGraph.children(v).length){inputLabel.width=layoutLabel.width;inputLabel.height=layoutLabel.height}}});_.forEach(inputGraph.edges(),function(e){var inputLabel=inputGraph.edge(e);var layoutLabel=layoutGraph.edge(e);inputLabel.points=layoutLabel.points;if(_.has(layoutLabel,"x")){inputLabel.x=layoutLabel.x;inputLabel.y=layoutLabel.y}});inputGraph.graph().width=layoutGraph.graph().width;inputGraph.graph().height=layoutGraph.graph().height}var graphNumAttrs=["nodesep","edgesep","ranksep","marginx","marginy"];var graphDefaults={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"};var graphAttrs=["acyclicer","ranker","rankdir","align"];var nodeNumAttrs=["width","height"];var nodeDefaults={width:0,height:0};var edgeNumAttrs=["minlen","weight","width","height","labeloffset"];var edgeDefaults={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"};var edgeAttrs=["labelpos"]; -/* - * Constructs a new graph from the input graph, which can be used for layout. - * This process copies only whitelisted attributes from the input graph to the - * layout graph. Thus this function serves as a good place to determine what - * attributes can influence layout. - */function buildLayoutGraph(inputGraph){var g=new Graph({multigraph:true,compound:true});var graph=canonicalize(inputGraph.graph());g.setGraph(_.merge({},graphDefaults,selectNumberAttrs(graph,graphNumAttrs),_.pick(graph,graphAttrs)));_.forEach(inputGraph.nodes(),function(v){var node=canonicalize(inputGraph.node(v));g.setNode(v,_.defaults(selectNumberAttrs(node,nodeNumAttrs),nodeDefaults));g.setParent(v,inputGraph.parent(v))});_.forEach(inputGraph.edges(),function(e){var edge=canonicalize(inputGraph.edge(e));g.setEdge(e,_.merge({},edgeDefaults,selectNumberAttrs(edge,edgeNumAttrs),_.pick(edge,edgeAttrs)))});return g} -/* - * This idea comes from the Gansner paper: to account for edge labels in our - * layout we split each rank in half by doubling minlen and halving ranksep. - * Then we can place labels at these mid-points between nodes. - * - * We also add some minimal padding to the width to push the label for the edge - * away from the edge itself a bit. - */function makeSpaceForEdgeLabels(g){var graph=g.graph();graph.ranksep/=2;_.forEach(g.edges(),function(e){var edge=g.edge(e);edge.minlen*=2;if(edge.labelpos.toLowerCase()!=="c"){if(graph.rankdir==="TB"||graph.rankdir==="BT"){edge.width+=edge.labeloffset}else{edge.height+=edge.labeloffset}}})} -/* - * Creates temporary dummy nodes that capture the rank in which each edge's - * label is going to, if it has one of non-zero width and height. We do this - * so that we can safely remove empty ranks while preserving balance for the - * label's position. - */function injectEdgeLabelProxies(g){_.forEach(g.edges(),function(e){var edge=g.edge(e);if(edge.width&&edge.height){var v=g.node(e.v);var w=g.node(e.w);var label={rank:(w.rank-v.rank)/2+v.rank,e:e};util.addDummyNode(g,"edge-proxy",label,"_ep")}})}function assignRankMinMax(g){var maxRank=0;_.forEach(g.nodes(),function(v){var node=g.node(v);if(node.borderTop){node.minRank=g.node(node.borderTop).rank;node.maxRank=g.node(node.borderBottom).rank;maxRank=_.max(maxRank,node.maxRank)}});g.graph().maxRank=maxRank}function removeEdgeLabelProxies(g){_.forEach(g.nodes(),function(v){var node=g.node(v);if(node.dummy==="edge-proxy"){g.edge(node.e).labelRank=node.rank;g.removeNode(v)}})}function translateGraph(g){var minX=Number.POSITIVE_INFINITY;var maxX=0;var minY=Number.POSITIVE_INFINITY;var maxY=0;var graphLabel=g.graph();var marginX=graphLabel.marginx||0;var marginY=graphLabel.marginy||0;function getExtremes(attrs){var x=attrs.x;var y=attrs.y;var w=attrs.width;var h=attrs.height;minX=Math.min(minX,x-w/2);maxX=Math.max(maxX,x+w/2);minY=Math.min(minY,y-h/2);maxY=Math.max(maxY,y+h/2)}_.forEach(g.nodes(),function(v){getExtremes(g.node(v))});_.forEach(g.edges(),function(e){var edge=g.edge(e);if(_.has(edge,"x")){getExtremes(edge)}});minX-=marginX;minY-=marginY;_.forEach(g.nodes(),function(v){var node=g.node(v);node.x-=minX;node.y-=minY});_.forEach(g.edges(),function(e){var edge=g.edge(e);_.forEach(edge.points,function(p){p.x-=minX;p.y-=minY});if(_.has(edge,"x")){edge.x-=minX}if(_.has(edge,"y")){edge.y-=minY}});graphLabel.width=maxX-minX+marginX;graphLabel.height=maxY-minY+marginY}function assignNodeIntersects(g){_.forEach(g.edges(),function(e){var edge=g.edge(e);var nodeV=g.node(e.v);var nodeW=g.node(e.w);var p1,p2;if(!edge.points){edge.points=[];p1=nodeW;p2=nodeV}else{p1=edge.points[0];p2=edge.points[edge.points.length-1]}edge.points.unshift(util.intersectRect(nodeV,p1));edge.points.push(util.intersectRect(nodeW,p2))})}function fixupEdgeLabelCoords(g){_.forEach(g.edges(),function(e){var edge=g.edge(e);if(_.has(edge,"x")){if(edge.labelpos==="l"||edge.labelpos==="r"){edge.width-=edge.labeloffset}switch(edge.labelpos){case"l":edge.x-=edge.width/2+edge.labeloffset;break;case"r":edge.x+=edge.width/2+edge.labeloffset;break}}})}function reversePointsForReversedEdges(g){_.forEach(g.edges(),function(e){var edge=g.edge(e);if(edge.reversed){edge.points.reverse()}})}function removeBorderNodes(g){_.forEach(g.nodes(),function(v){if(g.children(v).length){var node=g.node(v);var t=g.node(node.borderTop);var b=g.node(node.borderBottom);var l=g.node(_.last(node.borderLeft));var r=g.node(_.last(node.borderRight));node.width=Math.abs(r.x-l.x);node.height=Math.abs(b.y-t.y);node.x=l.x+node.width/2;node.y=t.y+node.height/2}});_.forEach(g.nodes(),function(v){if(g.node(v).dummy==="border"){g.removeNode(v)}})}function removeSelfEdges(g){_.forEach(g.edges(),function(e){if(e.v===e.w){var node=g.node(e.v);if(!node.selfEdges){node.selfEdges=[]}node.selfEdges.push({e:e,label:g.edge(e)});g.removeEdge(e)}})}function insertSelfEdges(g){var layers=util.buildLayerMatrix(g);_.forEach(layers,function(layer){var orderShift=0;_.forEach(layer,function(v,i){var node=g.node(v);node.order=i+orderShift;_.forEach(node.selfEdges,function(selfEdge){util.addDummyNode(g,"selfedge",{width:selfEdge.label.width,height:selfEdge.label.height,rank:node.rank,order:i+ ++orderShift,e:selfEdge.e,label:selfEdge.label},"_se")});delete node.selfEdges})})}function positionSelfEdges(g){_.forEach(g.nodes(),function(v){var node=g.node(v);if(node.dummy==="selfedge"){var selfNode=g.node(node.e.v);var x=selfNode.x+selfNode.width/2;var y=selfNode.y;var dx=node.x-x;var dy=selfNode.height/2;g.setEdge(node.e,node.label);g.removeNode(v);node.label.points=[{x:x+2*dx/3,y:y-dy},{x:x+5*dx/6,y:y-dy},{x:x+dx,y:y},{x:x+5*dx/6,y:y+dy},{x:x+2*dx/3,y:y+dy}];node.label.x=node.x;node.label.y=node.y}})}function selectNumberAttrs(obj,attrs){return _.mapValues(_.pick(obj,attrs),Number)}function canonicalize(attrs){var newAttrs={};_.forEach(attrs,function(v,k){newAttrs[k.toLowerCase()]=v});return newAttrs}},{"./acyclic":2,"./add-border-segments":3,"./coordinate-system":4,"./graphlib":7,"./lodash":10,"./nesting-graph":11,"./normalize":12,"./order":17,"./parent-dummy-chains":22,"./position":24,"./rank":26,"./util":29}],10:[function(require,module,exports){ -/* global window */ -var lodash;if(typeof require==="function"){try{lodash={cloneDeep:require("lodash/cloneDeep"),constant:require("lodash/constant"),defaults:require("lodash/defaults"),each:require("lodash/each"),filter:require("lodash/filter"),find:require("lodash/find"),flatten:require("lodash/flatten"),forEach:require("lodash/forEach"),forIn:require("lodash/forIn"),has:require("lodash/has"),isUndefined:require("lodash/isUndefined"),last:require("lodash/last"),map:require("lodash/map"),mapValues:require("lodash/mapValues"),max:require("lodash/max"),merge:require("lodash/merge"),min:require("lodash/min"),minBy:require("lodash/minBy"),now:require("lodash/now"),pick:require("lodash/pick"),range:require("lodash/range"),reduce:require("lodash/reduce"),sortBy:require("lodash/sortBy"),uniqueId:require("lodash/uniqueId"),values:require("lodash/values"),zipObject:require("lodash/zipObject")}}catch(e){ -// continue regardless of error -}}if(!lodash){lodash=window._}module.exports=lodash},{"lodash/cloneDeep":227,"lodash/constant":228,"lodash/defaults":229,"lodash/each":230,"lodash/filter":232,"lodash/find":233,"lodash/flatten":235,"lodash/forEach":236,"lodash/forIn":237,"lodash/has":239,"lodash/isUndefined":258,"lodash/last":261,"lodash/map":262,"lodash/mapValues":263,"lodash/max":264,"lodash/merge":266,"lodash/min":267,"lodash/minBy":268,"lodash/now":270,"lodash/pick":271,"lodash/range":273,"lodash/reduce":274,"lodash/sortBy":276,"lodash/uniqueId":286,"lodash/values":287,"lodash/zipObject":288}],11:[function(require,module,exports){var _=require("./lodash");var util=require("./util");module.exports={run:run,cleanup:cleanup}; -/* - * A nesting graph creates dummy nodes for the tops and bottoms of subgraphs, - * adds appropriate edges to ensure that all cluster nodes are placed between - * these boundaries, and ensures that the graph is connected. - * - * In addition we ensure, through the use of the minlen property, that nodes - * and subgraph border nodes to not end up on the same rank. - * - * Preconditions: - * - * 1. Input graph is a DAG - * 2. Nodes in the input graph has a minlen attribute - * - * Postconditions: - * - * 1. Input graph is connected. - * 2. Dummy nodes are added for the tops and bottoms of subgraphs. - * 3. The minlen attribute for nodes is adjusted to ensure nodes do not - * get placed on the same rank as subgraph border nodes. - * - * The nesting graph idea comes from Sander, "Layout of Compound Directed - * Graphs." - */function run(g){var root=util.addDummyNode(g,"root",{},"_root");var depths=treeDepths(g);var height=_.max(_.values(depths))-1;// Note: depths is an Object not an array -var nodeSep=2*height+1;g.graph().nestingRoot=root; -// Multiply minlen by nodeSep to align nodes on non-border ranks. -_.forEach(g.edges(),function(e){g.edge(e).minlen*=nodeSep}); -// Calculate a weight that is sufficient to keep subgraphs vertically compact -var weight=sumWeights(g)+1; -// Create border nodes and link them up -_.forEach(g.children(),function(child){dfs(g,root,nodeSep,weight,height,depths,child)}); -// Save the multiplier for node layers for later removal of empty border -// layers. -g.graph().nodeRankFactor=nodeSep}function dfs(g,root,nodeSep,weight,height,depths,v){var children=g.children(v);if(!children.length){if(v!==root){g.setEdge(root,v,{weight:0,minlen:nodeSep})}return}var top=util.addBorderNode(g,"_bt");var bottom=util.addBorderNode(g,"_bb");var label=g.node(v);g.setParent(top,v);label.borderTop=top;g.setParent(bottom,v);label.borderBottom=bottom;_.forEach(children,function(child){dfs(g,root,nodeSep,weight,height,depths,child);var childNode=g.node(child);var childTop=childNode.borderTop?childNode.borderTop:child;var childBottom=childNode.borderBottom?childNode.borderBottom:child;var thisWeight=childNode.borderTop?weight:2*weight;var minlen=childTop!==childBottom?1:height-depths[v]+1;g.setEdge(top,childTop,{weight:thisWeight,minlen:minlen,nestingEdge:true});g.setEdge(childBottom,bottom,{weight:thisWeight,minlen:minlen,nestingEdge:true})});if(!g.parent(v)){g.setEdge(root,top,{weight:0,minlen:height+depths[v]})}}function treeDepths(g){var depths={};function dfs(v,depth){var children=g.children(v);if(children&&children.length){_.forEach(children,function(child){dfs(child,depth+1)})}depths[v]=depth}_.forEach(g.children(),function(v){dfs(v,1)});return depths}function sumWeights(g){return _.reduce(g.edges(),function(acc,e){return acc+g.edge(e).weight},0)}function cleanup(g){var graphLabel=g.graph();g.removeNode(graphLabel.nestingRoot);delete graphLabel.nestingRoot;_.forEach(g.edges(),function(e){var edge=g.edge(e);if(edge.nestingEdge){g.removeEdge(e)}})}},{"./lodash":10,"./util":29}],12:[function(require,module,exports){"use strict";var _=require("./lodash");var util=require("./util");module.exports={run:run,undo:undo}; -/* - * Breaks any long edges in the graph into short segments that span 1 layer - * each. This operation is undoable with the denormalize function. - * - * Pre-conditions: - * - * 1. The input graph is a DAG. - * 2. Each node in the graph has a "rank" property. - * - * Post-condition: - * - * 1. All edges in the graph have a length of 1. - * 2. Dummy nodes are added where edges have been split into segments. - * 3. The graph is augmented with a "dummyChains" attribute which contains - * the first dummy in each chain of dummy nodes produced. - */function run(g){g.graph().dummyChains=[];_.forEach(g.edges(),function(edge){normalizeEdge(g,edge)})}function normalizeEdge(g,e){var v=e.v;var vRank=g.node(v).rank;var w=e.w;var wRank=g.node(w).rank;var name=e.name;var edgeLabel=g.edge(e);var labelRank=edgeLabel.labelRank;if(wRank===vRank+1)return;g.removeEdge(e);var dummy,attrs,i;for(i=0,++vRank;vRank0){if(index%2){weightSum+=tree[index+1]}index=index-1>>1;tree[index]+=entry.weight}cc+=entry.weight*weightSum}));return cc}},{"../lodash":10}],17:[function(require,module,exports){"use strict";var _=require("../lodash");var initOrder=require("./init-order");var crossCount=require("./cross-count");var sortSubgraph=require("./sort-subgraph");var buildLayerGraph=require("./build-layer-graph");var addSubgraphConstraints=require("./add-subgraph-constraints");var Graph=require("../graphlib").Graph;var util=require("../util");module.exports=order; -/* - * Applies heuristics to minimize edge crossings in the graph and sets the best - * order solution as an order attribute on each node. - * - * Pre-conditions: - * - * 1. Graph must be DAG - * 2. Graph nodes must be objects with a "rank" attribute - * 3. Graph edges must have the "weight" attribute - * - * Post-conditions: - * - * 1. Graph nodes will have an "order" attribute based on the results of the - * algorithm. - */function order(g){var maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,_.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,_.range(maxRank-1,-1,-1),"outEdges");var layering=initOrder(g);assignOrder(g,layering);var bestCC=Number.POSITIVE_INFINITY,best;for(var i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);var cc=crossCount(g,layering);if(cc=vEntry.barycenter){mergeEntries(vEntry,uEntry)}}}function handleOut(vEntry){return function(wEntry){wEntry["in"].push(vEntry);if(--wEntry.indegree===0){sourceSet.push(wEntry)}}}while(sourceSet.length){var entry=sourceSet.pop();entries.push(entry);_.forEach(entry["in"].reverse(),handleIn(entry));_.forEach(entry.out,handleOut(entry))}return _.map(_.filter(entries,function(entry){return!entry.merged}),function(entry){return _.pick(entry,["vs","i","barycenter","weight"])})}function mergeEntries(target,source){var sum=0;var weight=0;if(target.weight){sum+=target.barycenter*target.weight;weight+=target.weight}if(source.weight){sum+=source.barycenter*source.weight;weight+=source.weight}target.vs=source.vs.concat(target.vs);target.barycenter=sum/weight;target.weight=weight;target.i=Math.min(source.i,target.i);source.merged=true}},{"../lodash":10}],20:[function(require,module,exports){var _=require("../lodash");var barycenter=require("./barycenter");var resolveConflicts=require("./resolve-conflicts");var sort=require("./sort");module.exports=sortSubgraph;function sortSubgraph(g,v,cg,biasRight){var movable=g.children(v);var node=g.node(v);var bl=node?node.borderLeft:undefined;var br=node?node.borderRight:undefined;var subgraphs={};if(bl){movable=_.filter(movable,function(w){return w!==bl&&w!==br})}var barycenters=barycenter(g,movable);_.forEach(barycenters,function(entry){if(g.children(entry.v).length){var subgraphResult=sortSubgraph(g,entry.v,cg,biasRight);subgraphs[entry.v]=subgraphResult;if(_.has(subgraphResult,"barycenter")){mergeBarycenters(entry,subgraphResult)}}});var entries=resolveConflicts(barycenters,cg);expandSubgraphs(entries,subgraphs);var result=sort(entries,biasRight);if(bl){result.vs=_.flatten([bl,result.vs,br],true);if(g.predecessors(bl).length){var blPred=g.node(g.predecessors(bl)[0]),brPred=g.node(g.predecessors(br)[0]);if(!_.has(result,"barycenter")){result.barycenter=0;result.weight=0}result.barycenter=(result.barycenter*result.weight+blPred.order+brPred.order)/(result.weight+2);result.weight+=2}}return result}function expandSubgraphs(entries,subgraphs){_.forEach(entries,function(entry){entry.vs=_.flatten(entry.vs.map(function(v){if(subgraphs[v]){return subgraphs[v].vs}return v}),true)})}function mergeBarycenters(target,other){if(!_.isUndefined(target.barycenter)){target.barycenter=(target.barycenter*target.weight+other.barycenter*other.weight)/(target.weight+other.weight);target.weight+=other.weight}else{target.barycenter=other.barycenter;target.weight=other.weight}}},{"../lodash":10,"./barycenter":14,"./resolve-conflicts":19,"./sort":21}],21:[function(require,module,exports){var _=require("../lodash");var util=require("../util");module.exports=sort;function sort(entries,biasRight){var parts=util.partition(entries,function(entry){return _.has(entry,"barycenter")});var sortable=parts.lhs,unsortable=_.sortBy(parts.rhs,function(entry){return-entry.i}),vs=[],sum=0,weight=0,vsIndex=0;sortable.sort(compareWithBias(!!biasRight));vsIndex=consumeUnsortable(vs,unsortable,vsIndex);_.forEach(sortable,function(entry){vsIndex+=entry.vs.length;vs.push(entry.vs);sum+=entry.barycenter*entry.weight;weight+=entry.weight;vsIndex=consumeUnsortable(vs,unsortable,vsIndex)});var result={vs:_.flatten(vs,true)};if(weight){result.barycenter=sum/weight;result.weight=weight}return result}function consumeUnsortable(vs,unsortable,index){var last;while(unsortable.length&&(last=_.last(unsortable)).i<=index){unsortable.pop();vs.push(last.vs);index++}return index}function compareWithBias(bias){return function(entryV,entryW){if(entryV.barycenterentryW.barycenter){return 1}return!bias?entryV.i-entryW.i:entryW.i-entryV.i}}},{"../lodash":10,"../util":29}],22:[function(require,module,exports){var _=require("./lodash");module.exports=parentDummyChains;function parentDummyChains(g){var postorderNums=postorder(g);_.forEach(g.graph().dummyChains,function(v){var node=g.node(v);var edgeObj=node.edgeObj;var pathData=findPath(g,postorderNums,edgeObj.v,edgeObj.w);var path=pathData.path;var lca=pathData.lca;var pathIdx=0;var pathV=path[pathIdx];var ascending=true;while(v!==edgeObj.w){node=g.node(v);if(ascending){while((pathV=path[pathIdx])!==lca&&g.node(pathV).maxRanklow||lim>postorderNums[parent].lim));lca=parent; -// Traverse from w to LCA -parent=w;while((parent=g.parent(parent))!==lca){wPath.push(parent)}return{path:vPath.concat(wPath.reverse()),lca:lca}}function postorder(g){var result={};var lim=0;function dfs(v){var low=lim;_.forEach(g.children(v),dfs);result[v]={low:low,lim:lim++}}_.forEach(g.children(),dfs);return result}},{"./lodash":10}],23:[function(require,module,exports){"use strict";var _=require("../lodash");var Graph=require("../graphlib").Graph;var util=require("../util"); -/* - * This module provides coordinate assignment based on Brandes and Köpf, "Fast - * and Simple Horizontal Coordinate Assignment." - */module.exports={positionX:positionX,findType1Conflicts:findType1Conflicts,findType2Conflicts:findType2Conflicts,addConflict:addConflict,hasConflict:hasConflict,verticalAlignment:verticalAlignment,horizontalCompaction:horizontalCompaction,alignCoordinates:alignCoordinates,findSmallestWidthAlignment:findSmallestWidthAlignment,balance:balance}; -/* - * Marks all edges in the graph with a type-1 conflict with the "type1Conflict" - * property. A type-1 conflict is one where a non-inner segment crosses an - * inner segment. An inner segment is an edge with both incident nodes marked - * with the "dummy" property. - * - * This algorithm scans layer by layer, starting with the second, for type-1 - * conflicts between the current layer and the previous layer. For each layer - * it scans the nodes from left to right until it reaches one that is incident - * on an inner segment. It then scans predecessors to determine if they have - * edges that cross that inner segment. At the end a final scan is done for all - * nodes on the current rank to see if they cross the last visited inner - * segment. - * - * This algorithm (safely) assumes that a dummy node will only be incident on a - * single node in the layers being scanned. - */function findType1Conflicts(g,layering){var conflicts={};function visitLayer(prevLayer,layer){var -// last visited node in the previous layer that is incident on an inner -// segment. -k0=0, -// Tracks the last node in this layer scanned for crossings with a type-1 -// segment. -scanPos=0,prevLayerLength=prevLayer.length,lastNode=_.last(layer);_.forEach(layer,function(v,i){var w=findOtherInnerSegmentNode(g,v),k1=w?g.node(w).order:prevLayerLength;if(w||v===lastNode){_.forEach(layer.slice(scanPos,i+1),function(scanNode){_.forEach(g.predecessors(scanNode),function(u){var uLabel=g.node(u),uPos=uLabel.order;if((uPosnextNorthBorder)){addConflict(conflicts,u,v)}})}})}function visitLayer(north,south){var prevNorthPos=-1,nextNorthPos,southPos=0;_.forEach(south,function(v,southLookahead){if(g.node(v).dummy==="border"){var predecessors=g.predecessors(v);if(predecessors.length){nextNorthPos=g.node(predecessors[0]).order;scan(south,southPos,southLookahead,prevNorthPos,nextNorthPos);southPos=southLookahead;prevNorthPos=nextNorthPos}}scan(south,southPos,south.length,nextNorthPos,north.length)});return south}_.reduce(layering,visitLayer);return conflicts}function findOtherInnerSegmentNode(g,v){if(g.node(v).dummy){return _.find(g.predecessors(v),function(u){return g.node(u).dummy})}}function addConflict(conflicts,v,w){if(v>w){var tmp=v;v=w;w=tmp}var conflictsV=conflicts[v];if(!conflictsV){conflicts[v]=conflictsV={}}conflictsV[w]=true}function hasConflict(conflicts,v,w){if(v>w){var tmp=v;v=w;w=tmp}return _.has(conflicts[v],w)} -/* - * Try to align nodes into vertical "blocks" where possible. This algorithm - * attempts to align a node with one of its median neighbors. If the edge - * connecting a neighbor is a type-1 conflict then we ignore that possibility. - * If a previous node has already formed a block with a node after the node - * we're trying to form a block with, we also ignore that possibility - our - * blocks would be split in that scenario. - */function verticalAlignment(g,layering,conflicts,neighborFn){var root={},align={},pos={}; -// We cache the position here based on the layering because the graph and -// layering may be out of sync. The layering matrix is manipulated to -// generate different extreme alignments. -_.forEach(layering,function(layer){_.forEach(layer,function(v,order){root[v]=v;align[v]=v;pos[v]=order})});_.forEach(layering,function(layer){var prevIdx=-1;_.forEach(layer,function(v){var ws=neighborFn(v);if(ws.length){ws=_.sortBy(ws,function(w){return pos[w]});var mp=(ws.length-1)/2;for(var i=Math.floor(mp),il=Math.ceil(mp);i<=il;++i){var w=ws[i];if(align[v]===v&&prevIdxwLabel.lim){tailLabel=wLabel;flip=true}var candidates=_.filter(g.edges(),function(edge){return flip===isDescendant(t,t.node(edge.v),tailLabel)&&flip!==isDescendant(t,t.node(edge.w),tailLabel)});return _.minBy(candidates,function(edge){return slack(g,edge)})}function exchangeEdges(t,g,e,f){var v=e.v;var w=e.w;t.removeEdge(v,w);t.setEdge(f.v,f.w,{});initLowLimValues(t);initCutValues(t,g);updateRanks(t,g)}function updateRanks(t,g){var root=_.find(t.nodes(),function(v){return!g.node(v).parent});var vs=preorder(t,root);vs=vs.slice(1);_.forEach(vs,function(v){var parent=t.node(v).parent,edge=g.edge(v,parent),flipped=false;if(!edge){edge=g.edge(parent,v);flipped=true}g.node(v).rank=g.node(parent).rank+(flipped?edge.minlen:-edge.minlen)})} -/* - * Returns true if the edge is in the tree. - */function isTreeEdge(tree,u,v){return tree.hasEdge(u,v)} -/* - * Returns true if the specified node is descendant of the root node per the - * assigned low and lim attributes in the tree. - */function isDescendant(tree,vLabel,rootLabel){return rootLabel.low<=vLabel.lim&&vLabel.lim<=rootLabel.lim}},{"../graphlib":7,"../lodash":10,"../util":29,"./feasible-tree":25,"./util":28}],28:[function(require,module,exports){"use strict";var _=require("../lodash");module.exports={longestPath:longestPath,slack:slack}; -/* - * Initializes ranks for the input graph using the longest path algorithm. This - * algorithm scales well and is fast in practice, it yields rather poor - * solutions. Nodes are pushed to the lowest layer possible, leaving the bottom - * ranks wide and leaving edges longer than necessary. However, due to its - * speed, this algorithm is good for getting an initial ranking that can be fed - * into other algorithms. - * - * This algorithm does not normalize layers because it will be used by other - * algorithms in most cases. If using this algorithm directly, be sure to - * run normalize at the end. - * - * Pre-conditions: - * - * 1. Input graph is a DAG. - * 2. Input graph node labels can be assigned properties. - * - * Post-conditions: - * - * 1. Each node will be assign an (unnormalized) "rank" property. - */function longestPath(g){var visited={};function dfs(v){var label=g.node(v);if(_.has(visited,v)){return label.rank}visited[v]=true;var rank=_.min(_.map(g.outEdges(v),function(e){return dfs(e.w)-g.edge(e).minlen}));if(rank===Number.POSITIVE_INFINITY||// return value of _.map([]) for Lodash 3 -rank===undefined||// return value of _.map([]) for Lodash 4 -rank===null){// return value of _.map([null]) -rank=0}return label.rank=rank}_.forEach(g.sources(),dfs)} -/* - * Returns the amount of slack for the given edge. The slack is defined as the - * difference between the length of the edge and its minimum length. - */function slack(g,e){return g.node(e.w).rank-g.node(e.v).rank-g.edge(e).minlen}},{"../lodash":10}],29:[function(require,module,exports){ -/* eslint "no-console": off */ -"use strict";var _=require("./lodash");var Graph=require("./graphlib").Graph;module.exports={addDummyNode:addDummyNode,simplify:simplify,asNonCompoundGraph:asNonCompoundGraph,successorWeights:successorWeights,predecessorWeights:predecessorWeights,intersectRect:intersectRect,buildLayerMatrix:buildLayerMatrix,normalizeRanks:normalizeRanks,removeEmptyRanks:removeEmptyRanks,addBorderNode:addBorderNode,maxRank:maxRank,partition:partition,time:time,notime:notime}; -/* - * Adds a dummy node to the graph and return v. - */function addDummyNode(g,type,attrs,name){var v;do{v=_.uniqueId(name)}while(g.hasNode(v));attrs.dummy=type;g.setNode(v,attrs);return v} -/* - * Returns a new graph with only simple edges. Handles aggregation of data - * associated with multi-edges. - */function simplify(g){var simplified=(new Graph).setGraph(g.graph());_.forEach(g.nodes(),function(v){simplified.setNode(v,g.node(v))});_.forEach(g.edges(),function(e){var simpleLabel=simplified.edge(e.v,e.w)||{weight:0,minlen:1};var label=g.edge(e);simplified.setEdge(e.v,e.w,{weight:simpleLabel.weight+label.weight,minlen:Math.max(simpleLabel.minlen,label.minlen)})});return simplified}function asNonCompoundGraph(g){var simplified=new Graph({multigraph:g.isMultigraph()}).setGraph(g.graph());_.forEach(g.nodes(),function(v){if(!g.children(v).length){simplified.setNode(v,g.node(v))}});_.forEach(g.edges(),function(e){simplified.setEdge(e,g.edge(e))});return simplified}function successorWeights(g){var weightMap=_.map(g.nodes(),function(v){var sucs={};_.forEach(g.outEdges(v),function(e){sucs[e.w]=(sucs[e.w]||0)+g.edge(e).weight});return sucs});return _.zipObject(g.nodes(),weightMap)}function predecessorWeights(g){var weightMap=_.map(g.nodes(),function(v){var preds={};_.forEach(g.inEdges(v),function(e){preds[e.v]=(preds[e.v]||0)+g.edge(e).weight});return preds});return _.zipObject(g.nodes(),weightMap)} -/* - * Finds where a line starting at point ({x, y}) would intersect a rectangle - * ({x, y, width, height}) if it were pointing at the rectangle's center. - */function intersectRect(rect,point){var x=rect.x;var y=rect.y; -// Rectangle intersection algorithm from: -// https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes -var dx=point.x-x;var dy=point.y-y;var w=rect.width/2;var h=rect.height/2;if(!dx&&!dy){throw new Error("Not possible to find intersection inside of the rectangle")}var sx,sy;if(Math.abs(dy)*w>Math.abs(dx)*h){ -// Intersection is top or bottom of rect. -if(dy<0){h=-h}sx=h*dx/dy;sy=h}else{ -// Intersection is left or right of rect. -if(dx<0){w=-w}sx=w;sy=w*dy/dx}return{x:x+sx,y:y+sy}} -/* - * Given a DAG with each node assigned "rank" and "order" properties, this - * function will produce a matrix with the ids of each node. - */function buildLayerMatrix(g){var layering=_.map(_.range(maxRank(g)+1),function(){return[]});_.forEach(g.nodes(),function(v){var node=g.node(v);var rank=node.rank;if(!_.isUndefined(rank)){layering[rank][node.order]=v}});return layering} -/* - * Adjusts the ranks for all nodes in the graph such that all nodes v have - * rank(v) >= 0 and at least one node w has rank(w) = 0. - */function normalizeRanks(g){var min=_.min(_.map(g.nodes(),function(v){return g.node(v).rank}));_.forEach(g.nodes(),function(v){var node=g.node(v);if(_.has(node,"rank")){node.rank-=min}})}function removeEmptyRanks(g){ -// Ranks may not start at 0, so we need to offset them -var offset=_.min(_.map(g.nodes(),function(v){return g.node(v).rank}));var layers=[];_.forEach(g.nodes(),function(v){var rank=g.node(v).rank-offset;if(!layers[rank]){layers[rank]=[]}layers[rank].push(v)});var delta=0;var nodeRankFactor=g.graph().nodeRankFactor;_.forEach(layers,function(vs,i){if(_.isUndefined(vs)&&i%nodeRankFactor!==0){--delta}else if(delta){_.forEach(vs,function(v){g.node(v).rank+=delta})}})}function addBorderNode(g,prefix,rank,order){var node={width:0,height:0};if(arguments.length>=4){node.rank=rank;node.order=order}return addDummyNode(g,"border",node,prefix)}function maxRank(g){return _.max(_.map(g.nodes(),function(v){var rank=g.node(v).rank;if(!_.isUndefined(rank)){return rank}}))} -/* - * Partition a collection into two groups: `lhs` and `rhs`. If the supplied - * function returns true for an entry it goes into `lhs`. Otherwise it goes - * into `rhs. - */function partition(collection,fn){var result={lhs:[],rhs:[]};_.forEach(collection,function(value){if(fn(value)){result.lhs.push(value)}else{result.rhs.push(value)}});return result} -/* - * Returns a new function that wraps `fn` with a timer. The wrapper logs the - * time it takes to execute the function. - */function time(name,fn){var start=_.now();try{return fn()}finally{console.log(name+" time: "+(_.now()-start)+"ms")}}function notime(name,fn){return fn()}},{"./graphlib":7,"./lodash":10}],30:[function(require,module,exports){module.exports="0.8.5"},{}],31:[function(require,module,exports){ -/** - * Copyright (c) 2014, Chris Pettitt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -var lib=require("./lib");module.exports={Graph:lib.Graph,json:require("./lib/json"),alg:require("./lib/alg"),version:lib.version}},{"./lib":47,"./lib/alg":38,"./lib/json":48}],32:[function(require,module,exports){var _=require("../lodash");module.exports=components;function components(g){var visited={};var cmpts=[];var cmpt;function dfs(v){if(_.has(visited,v))return;visited[v]=true;cmpt.push(v);_.each(g.successors(v),dfs);_.each(g.predecessors(v),dfs)}_.each(g.nodes(),function(v){cmpt=[];dfs(v);if(cmpt.length){cmpts.push(cmpt)}});return cmpts}},{"../lodash":49}],33:[function(require,module,exports){var _=require("../lodash");module.exports=dfs; -/* - * A helper that performs a pre- or post-order traversal on the input graph - * and returns the nodes in the order they were visited. If the graph is - * undirected then this algorithm will navigate using neighbors. If the graph - * is directed then this algorithm will navigate using successors. - * - * Order must be one of "pre" or "post". - */function dfs(g,vs,order){if(!_.isArray(vs)){vs=[vs]}var navigation=(g.isDirected()?g.successors:g.neighbors).bind(g);var acc=[];var visited={};_.each(vs,function(v){if(!g.hasNode(v)){throw new Error("Graph does not have node: "+v)}doDfs(g,v,order==="post",visited,navigation,acc)});return acc}function doDfs(g,v,postorder,visited,navigation,acc){if(!_.has(visited,v)){visited[v]=true;if(!postorder){acc.push(v)}_.each(navigation(v),function(w){doDfs(g,w,postorder,visited,navigation,acc)});if(postorder){acc.push(v)}}}},{"../lodash":49}],34:[function(require,module,exports){var dijkstra=require("./dijkstra");var _=require("../lodash");module.exports=dijkstraAll;function dijkstraAll(g,weightFunc,edgeFunc){return _.transform(g.nodes(),function(acc,v){acc[v]=dijkstra(g,v,weightFunc,edgeFunc)},{})}},{"../lodash":49,"./dijkstra":35}],35:[function(require,module,exports){var _=require("../lodash");var PriorityQueue=require("../data/priority-queue");module.exports=dijkstra;var DEFAULT_WEIGHT_FUNC=_.constant(1);function dijkstra(g,source,weightFn,edgeFn){return runDijkstra(g,String(source),weightFn||DEFAULT_WEIGHT_FUNC,edgeFn||function(v){return g.outEdges(v)})}function runDijkstra(g,source,weightFn,edgeFn){var results={};var pq=new PriorityQueue;var v,vEntry;var updateNeighbors=function(edge){var w=edge.v!==v?edge.v:edge.w;var wEntry=results[w];var weight=weightFn(edge);var distance=vEntry.distance+weight;if(weight<0){throw new Error("dijkstra does not allow negative edge weights. "+"Bad edge: "+edge+" Weight: "+weight)}if(distance0){v=pq.removeMin();vEntry=results[v];if(vEntry.distance===Number.POSITIVE_INFINITY){break}edgeFn(v).forEach(updateNeighbors)}return results}},{"../data/priority-queue":45,"../lodash":49}],36:[function(require,module,exports){var _=require("../lodash");var tarjan=require("./tarjan");module.exports=findCycles;function findCycles(g){return _.filter(tarjan(g),function(cmpt){return cmpt.length>1||cmpt.length===1&&g.hasEdge(cmpt[0],cmpt[0])})}},{"../lodash":49,"./tarjan":43}],37:[function(require,module,exports){var _=require("../lodash");module.exports=floydWarshall;var DEFAULT_WEIGHT_FUNC=_.constant(1);function floydWarshall(g,weightFn,edgeFn){return runFloydWarshall(g,weightFn||DEFAULT_WEIGHT_FUNC,edgeFn||function(v){return g.outEdges(v)})}function runFloydWarshall(g,weightFn,edgeFn){var results={};var nodes=g.nodes();nodes.forEach(function(v){results[v]={};results[v][v]={distance:0};nodes.forEach(function(w){if(v!==w){results[v][w]={distance:Number.POSITIVE_INFINITY}}});edgeFn(v).forEach(function(edge){var w=edge.v===v?edge.w:edge.v;var d=weightFn(edge);results[v][w]={distance:d,predecessor:v}})});nodes.forEach(function(k){var rowK=results[k];nodes.forEach(function(i){var rowI=results[i];nodes.forEach(function(j){var ik=rowI[k];var kj=rowK[j];var ij=rowI[j];var altDistance=ik.distance+kj.distance;if(altDistance0){v=pq.removeMin();if(_.has(parents,v)){result.setEdge(v,parents[v])}else if(init){throw new Error("Input graph is not connected: "+g)}else{init=true}g.nodeEdges(v).forEach(updateNeighbors)}return result}},{"../data/priority-queue":45,"../graph":46,"../lodash":49}],43:[function(require,module,exports){var _=require("../lodash");module.exports=tarjan;function tarjan(g){var index=0;var stack=[];var visited={};// node id -> { onStack, lowlink, index } -var results=[];function dfs(v){var entry=visited[v]={onStack:true,lowlink:index,index:index++};stack.push(v);g.successors(v).forEach(function(w){if(!_.has(visited,w)){dfs(w);entry.lowlink=Math.min(entry.lowlink,visited[w].lowlink)}else if(visited[w].onStack){entry.lowlink=Math.min(entry.lowlink,visited[w].index)}});if(entry.lowlink===entry.index){var cmpt=[];var w;do{w=stack.pop();visited[w].onStack=false;cmpt.push(w)}while(v!==w);results.push(cmpt)}}g.nodes().forEach(function(v){if(!_.has(visited,v)){dfs(v)}});return results}},{"../lodash":49}],44:[function(require,module,exports){var _=require("../lodash");module.exports=topsort;topsort.CycleException=CycleException;function topsort(g){var visited={};var stack={};var results=[];function visit(node){if(_.has(stack,node)){throw new CycleException}if(!_.has(visited,node)){stack[node]=true;visited[node]=true;_.each(g.predecessors(node),visit);delete stack[node];results.push(node)}}_.each(g.sinks(),visit);if(_.size(visited)!==g.nodeCount()){throw new CycleException}return results}function CycleException(){}CycleException.prototype=new Error;// must be an instance of Error to pass testing -},{"../lodash":49}],45:[function(require,module,exports){var _=require("../lodash");module.exports=PriorityQueue; -/** - * A min-priority queue data structure. This algorithm is derived from Cormen, - * et al., "Introduction to Algorithms". The basic idea of a min-priority - * queue is that you can efficiently (in O(1) time) get the smallest key in - * the queue. Adding and removing elements takes O(log n) time. A key can - * have its priority decreased in O(log n) time. - */function PriorityQueue(){this._arr=[];this._keyIndices={}} -/** - * Returns the number of elements in the queue. Takes `O(1)` time. - */PriorityQueue.prototype.size=function(){return this._arr.length}; -/** - * Returns the keys that are in the queue. Takes `O(n)` time. - */PriorityQueue.prototype.keys=function(){return this._arr.map(function(x){return x.key})}; -/** - * Returns `true` if **key** is in the queue and `false` if not. - */PriorityQueue.prototype.has=function(key){return _.has(this._keyIndices,key)}; -/** - * Returns the priority for **key**. If **key** is not present in the queue - * then this function returns `undefined`. Takes `O(1)` time. - * - * @param {Object} key - */PriorityQueue.prototype.priority=function(key){var index=this._keyIndices[key];if(index!==undefined){return this._arr[index].priority}}; -/** - * Returns the key for the minimum element in this queue. If the queue is - * empty this function throws an Error. Takes `O(1)` time. - */PriorityQueue.prototype.min=function(){if(this.size()===0){throw new Error("Queue underflow")}return this._arr[0].key}; -/** - * Inserts a new key into the priority queue. If the key already exists in - * the queue this function returns `false`; otherwise it will return `true`. - * Takes `O(n)` time. - * - * @param {Object} key the key to add - * @param {Number} priority the initial priority for the key - */PriorityQueue.prototype.add=function(key,priority){var keyIndices=this._keyIndices;key=String(key);if(!_.has(keyIndices,key)){var arr=this._arr;var index=arr.length;keyIndices[key]=index;arr.push({key:key,priority:priority});this._decrease(index);return true}return false}; -/** - * Removes and returns the smallest key in the queue. Takes `O(log n)` time. - */PriorityQueue.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var min=this._arr.pop();delete this._keyIndices[min.key];this._heapify(0);return min.key}; -/** - * Decreases the priority for **key** to **priority**. If the new priority is - * greater than the previous priority, this function will throw an Error. - * - * @param {Object} key the key for which to raise priority - * @param {Number} priority the new priority for the key - */PriorityQueue.prototype.decrease=function(key,priority){var index=this._keyIndices[key];if(priority>this._arr[index].priority){throw new Error("New priority is greater than current priority. "+"Key: "+key+" Old: "+this._arr[index].priority+" New: "+priority)}this._arr[index].priority=priority;this._decrease(index)};PriorityQueue.prototype._heapify=function(i){var arr=this._arr;var l=2*i;var r=l+1;var largest=i;if(l>1;if(arr[parent].priority label -this._nodes={};if(this._isCompound){ -// v -> parent -this._parent={}; -// v -> children -this._children={};this._children[GRAPH_NODE]={}} -// v -> edgeObj -this._in={}; -// u -> v -> Number -this._preds={}; -// v -> edgeObj -this._out={}; -// v -> w -> Number -this._sucs={}; -// e -> edgeObj -this._edgeObjs={}; -// e -> label -this._edgeLabels={}} -/* Number of nodes in the graph. Should only be changed by the implementation. */Graph.prototype._nodeCount=0; -/* Number of edges in the graph. Should only be changed by the implementation. */Graph.prototype._edgeCount=0; -/* === Graph functions ========= */Graph.prototype.isDirected=function(){return this._isDirected};Graph.prototype.isMultigraph=function(){return this._isMultigraph};Graph.prototype.isCompound=function(){return this._isCompound};Graph.prototype.setGraph=function(label){this._label=label;return this};Graph.prototype.graph=function(){return this._label}; -/* === Node functions ========== */Graph.prototype.setDefaultNodeLabel=function(newDefault){if(!_.isFunction(newDefault)){newDefault=_.constant(newDefault)}this._defaultNodeLabelFn=newDefault;return this};Graph.prototype.nodeCount=function(){return this._nodeCount};Graph.prototype.nodes=function(){return _.keys(this._nodes)};Graph.prototype.sources=function(){var self=this;return _.filter(this.nodes(),function(v){return _.isEmpty(self._in[v])})};Graph.prototype.sinks=function(){var self=this;return _.filter(this.nodes(),function(v){return _.isEmpty(self._out[v])})};Graph.prototype.setNodes=function(vs,value){var args=arguments;var self=this;_.each(vs,function(v){if(args.length>1){self.setNode(v,value)}else{self.setNode(v)}});return this};Graph.prototype.setNode=function(v,value){if(_.has(this._nodes,v)){if(arguments.length>1){this._nodes[v]=value}return this}this._nodes[v]=arguments.length>1?value:this._defaultNodeLabelFn(v);if(this._isCompound){this._parent[v]=GRAPH_NODE;this._children[v]={};this._children[GRAPH_NODE][v]=true}this._in[v]={};this._preds[v]={};this._out[v]={};this._sucs[v]={};++this._nodeCount;return this};Graph.prototype.node=function(v){return this._nodes[v]};Graph.prototype.hasNode=function(v){return _.has(this._nodes,v)};Graph.prototype.removeNode=function(v){var self=this;if(_.has(this._nodes,v)){var removeEdge=function(e){self.removeEdge(self._edgeObjs[e])};delete this._nodes[v];if(this._isCompound){this._removeFromParentsChildList(v);delete this._parent[v];_.each(this.children(v),function(child){self.setParent(child)});delete this._children[v]}_.each(_.keys(this._in[v]),removeEdge);delete this._in[v];delete this._preds[v];_.each(_.keys(this._out[v]),removeEdge);delete this._out[v];delete this._sucs[v];--this._nodeCount}return this};Graph.prototype.setParent=function(v,parent){if(!this._isCompound){throw new Error("Cannot set parent in a non-compound graph")}if(_.isUndefined(parent)){parent=GRAPH_NODE}else{ -// Coerce parent to string -parent+="";for(var ancestor=parent;!_.isUndefined(ancestor);ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create a cycle")}}this.setNode(parent)}this.setNode(v);this._removeFromParentsChildList(v);this._parent[v]=parent;this._children[parent][v]=true;return this};Graph.prototype._removeFromParentsChildList=function(v){delete this._children[this._parent[v]][v]};Graph.prototype.parent=function(v){if(this._isCompound){var parent=this._parent[v];if(parent!==GRAPH_NODE){return parent}}};Graph.prototype.children=function(v){if(_.isUndefined(v)){v=GRAPH_NODE}if(this._isCompound){var children=this._children[v];if(children){return _.keys(children)}}else if(v===GRAPH_NODE){return this.nodes()}else if(this.hasNode(v)){return[]}};Graph.prototype.predecessors=function(v){var predsV=this._preds[v];if(predsV){return _.keys(predsV)}};Graph.prototype.successors=function(v){var sucsV=this._sucs[v];if(sucsV){return _.keys(sucsV)}};Graph.prototype.neighbors=function(v){var preds=this.predecessors(v);if(preds){return _.union(preds,this.successors(v))}};Graph.prototype.isLeaf=function(v){var neighbors;if(this.isDirected()){neighbors=this.successors(v)}else{neighbors=this.neighbors(v)}return neighbors.length===0};Graph.prototype.filterNodes=function(filter){var copy=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});copy.setGraph(this.graph());var self=this;_.each(this._nodes,function(value,v){if(filter(v)){copy.setNode(v,value)}});_.each(this._edgeObjs,function(e){if(copy.hasNode(e.v)&©.hasNode(e.w)){copy.setEdge(e,self.edge(e))}});var parents={};function findParent(v){var parent=self.parent(v);if(parent===undefined||copy.hasNode(parent)){parents[v]=parent;return parent}else if(parent in parents){return parents[parent]}else{return findParent(parent)}}if(this._isCompound){_.each(copy.nodes(),function(v){copy.setParent(v,findParent(v))})}return copy}; -/* === Edge functions ========== */Graph.prototype.setDefaultEdgeLabel=function(newDefault){if(!_.isFunction(newDefault)){newDefault=_.constant(newDefault)}this._defaultEdgeLabelFn=newDefault;return this};Graph.prototype.edgeCount=function(){return this._edgeCount};Graph.prototype.edges=function(){return _.values(this._edgeObjs)};Graph.prototype.setPath=function(vs,value){var self=this;var args=arguments;_.reduce(vs,function(v,w){if(args.length>1){self.setEdge(v,w,value)}else{self.setEdge(v,w)}return w});return this}; -/* - * setEdge(v, w, [value, [name]]) - * setEdge({ v, w, [name] }, [value]) - */Graph.prototype.setEdge=function(){var v,w,name,value;var valueSpecified=false;var arg0=arguments[0];if(typeof arg0==="object"&&arg0!==null&&"v"in arg0){v=arg0.v;w=arg0.w;name=arg0.name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arg0;w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(!_.isUndefined(name)){name=""+name}var e=edgeArgsToId(this._isDirected,v,w,name);if(_.has(this._edgeLabels,e)){if(valueSpecified){this._edgeLabels[e]=value}return this}if(!_.isUndefined(name)&&!this._isMultigraph){throw new Error("Cannot set a named edge when isMultigraph = false")} -// It didn't exist, so we need to create it. -// First ensure the nodes exist. -this.setNode(v);this.setNode(w);this._edgeLabels[e]=valueSpecified?value:this._defaultEdgeLabelFn(v,w,name);var edgeObj=edgeArgsToObj(this._isDirected,v,w,name); -// Ensure we add undirected edges in a consistent way. -v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this._edgeObjs[e]=edgeObj;incrementOrInitEntry(this._preds[w],v);incrementOrInitEntry(this._sucs[v],w);this._in[w][e]=edgeObj;this._out[v][e]=edgeObj;this._edgeCount++;return this};Graph.prototype.edge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels[e]};Graph.prototype.hasEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return _.has(this._edgeLabels,e)};Graph.prototype.removeEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);var edge=this._edgeObjs[e];if(edge){v=edge.v;w=edge.w;delete this._edgeLabels[e];delete this._edgeObjs[e];decrementOrRemoveEntry(this._preds[w],v);decrementOrRemoveEntry(this._sucs[v],w);delete this._in[w][e];delete this._out[v][e];this._edgeCount--}return this};Graph.prototype.inEdges=function(v,u){var inV=this._in[v];if(inV){var edges=_.values(inV);if(!u){return edges}return _.filter(edges,function(edge){return edge.v===u})}};Graph.prototype.outEdges=function(v,w){var outV=this._out[v];if(outV){var edges=_.values(outV);if(!w){return edges}return _.filter(edges,function(edge){return edge.w===w})}};Graph.prototype.nodeEdges=function(v,w){var inEdges=this.inEdges(v,w);if(inEdges){return inEdges.concat(this.outEdges(v,w))}};function incrementOrInitEntry(map,k){if(map[k]){map[k]++}else{map[k]=1}}function decrementOrRemoveEntry(map,k){if(!--map[k]){delete map[k]}}function edgeArgsToId(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}return v+EDGE_KEY_DELIM+w+EDGE_KEY_DELIM+(_.isUndefined(name)?DEFAULT_EDGE_NAME:name)}function edgeArgsToObj(isDirected,v_,w_,name){var v=""+v_;var w=""+w_;if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}var edgeObj={v:v,w:w};if(name){edgeObj.name=name}return edgeObj}function edgeObjToId(isDirected,edgeObj){return edgeArgsToId(isDirected,edgeObj.v,edgeObj.w,edgeObj.name)}},{"./lodash":49}],47:[function(require,module,exports){ -// Includes only the "core" of graphlib -module.exports={Graph:require("./graph"),version:require("./version")}},{"./graph":46,"./version":50}],48:[function(require,module,exports){var _=require("./lodash");var Graph=require("./graph");module.exports={write:write,read:read};function write(g){var json={options:{directed:g.isDirected(),multigraph:g.isMultigraph(),compound:g.isCompound()},nodes:writeNodes(g),edges:writeEdges(g)};if(!_.isUndefined(g.graph())){json.value=_.clone(g.graph())}return json}function writeNodes(g){return _.map(g.nodes(),function(v){var nodeValue=g.node(v);var parent=g.parent(v);var node={v:v};if(!_.isUndefined(nodeValue)){node.value=nodeValue}if(!_.isUndefined(parent)){node.parent=parent}return node})}function writeEdges(g){return _.map(g.edges(),function(e){var edgeValue=g.edge(e);var edge={v:e.v,w:e.w};if(!_.isUndefined(e.name)){edge.name=e.name}if(!_.isUndefined(edgeValue)){edge.value=edgeValue}return edge})}function read(json){var g=new Graph(json.options).setGraph(json.value);_.each(json.nodes,function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});_.each(json.edges,function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":46,"./lodash":49}],49:[function(require,module,exports){ -/* global window */ -var lodash;if(typeof require==="function"){try{lodash={clone:require("lodash/clone"),constant:require("lodash/constant"),each:require("lodash/each"),filter:require("lodash/filter"),has:require("lodash/has"),isArray:require("lodash/isArray"),isEmpty:require("lodash/isEmpty"),isFunction:require("lodash/isFunction"),isUndefined:require("lodash/isUndefined"),keys:require("lodash/keys"),map:require("lodash/map"),reduce:require("lodash/reduce"),size:require("lodash/size"),transform:require("lodash/transform"),union:require("lodash/union"),values:require("lodash/values")}}catch(e){ -// continue regardless of error -}}if(!lodash){lodash=window._}module.exports=lodash},{"lodash/clone":226,"lodash/constant":228,"lodash/each":230,"lodash/filter":232,"lodash/has":239,"lodash/isArray":243,"lodash/isEmpty":247,"lodash/isFunction":248,"lodash/isUndefined":258,"lodash/keys":259,"lodash/map":262,"lodash/reduce":274,"lodash/size":275,"lodash/transform":284,"lodash/union":285,"lodash/values":287}],50:[function(require,module,exports){module.exports="2.1.8"},{}],51:[function(require,module,exports){var getNative=require("./_getNative"),root=require("./_root"); -/* Built-in method references that are verified to be native. */var DataView=getNative(root,"DataView");module.exports=DataView},{"./_getNative":163,"./_root":208}],52:[function(require,module,exports){var hashClear=require("./_hashClear"),hashDelete=require("./_hashDelete"),hashGet=require("./_hashGet"),hashHas=require("./_hashHas"),hashSet=require("./_hashSet"); -/** - * Creates a hash object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */function Hash(entries){var index=-1,length=entries==null?0:entries.length;this.clear();while(++index-1}module.exports=arrayIncludes},{"./_baseIndexOf":95}],67:[function(require,module,exports){ -/** - * This function is like `arrayIncludes` except that it accepts a comparator. - * - * @private - * @param {Array} [array] The array to inspect. - * @param {*} target The value to search for. - * @param {Function} comparator The comparator invoked per element. - * @returns {boolean} Returns `true` if `target` is found, else `false`. - */ -function arrayIncludesWith(array,value,comparator){var index=-1,length=array==null?0:array.length;while(++index0&&predicate(value)){if(depth>1){ -// Recursively flatten arrays (susceptible to call stack limits). -baseFlatten(value,depth-1,predicate,isStrict,result)}else{arrayPush(result,value)}}else if(!isStrict){result[result.length]=value}}return result}module.exports=baseFlatten},{"./_arrayPush":70,"./_isFlattenable":180}],87:[function(require,module,exports){var createBaseFor=require("./_createBaseFor"); -/** - * The base implementation of `baseForOwn` which iterates over `object` - * properties returned by `keysFunc` and invokes `iteratee` for each property. - * Iteratee 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`. - */var baseFor=createBaseFor();module.exports=baseFor},{"./_createBaseFor":149}],88:[function(require,module,exports){var baseFor=require("./_baseFor"),keys=require("./keys"); -/** - * The base implementation of `_.forOwn` without support for iteratee shorthands. - * - * @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 object&&baseFor(object,iteratee,keys)}module.exports=baseForOwn},{"./_baseFor":87,"./keys":259}],89:[function(require,module,exports){var castPath=require("./_castPath"),toKey=require("./_toKey"); -/** - * The base implementation of `_.get` without support for default values. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @returns {*} Returns the resolved value. - */function baseGet(object,path){path=castPath(path,object);var index=0,length=path.length;while(object!=null&&indexother}module.exports=baseGt},{}],93:[function(require,module,exports){ -/** Used for built-in method references. */ -var objectProto=Object.prototype; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** - * The base implementation of `_.has` without support for deep paths. - * - * @private - * @param {Object} [object] The object to query. - * @param {Array|string} key The key to check. - * @returns {boolean} Returns `true` if `key` exists, else `false`. - */function baseHas(object,key){return object!=null&&hasOwnProperty.call(object,key)}module.exports=baseHas},{}],94:[function(require,module,exports){ -/** - * The base implementation of `_.hasIn` without support for deep paths. - * - * @private - * @param {Object} [object] The object to query. - * @param {Array|string} key The key to check. - * @returns {boolean} Returns `true` if `key` exists, else `false`. - */ -function baseHasIn(object,key){return object!=null&&key in Object(object)}module.exports=baseHasIn},{}],95:[function(require,module,exports){var baseFindIndex=require("./_baseFindIndex"),baseIsNaN=require("./_baseIsNaN"),strictIndexOf=require("./_strictIndexOf"); -/** - * The base implementation of `_.indexOf` without `fromIndex` bounds checks. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */function baseIndexOf(array,value,fromIndex){return value===value?strictIndexOf(array,value,fromIndex):baseFindIndex(array,baseIsNaN,fromIndex)}module.exports=baseIndexOf},{"./_baseFindIndex":85,"./_baseIsNaN":101,"./_strictIndexOf":220}],96:[function(require,module,exports){var baseGetTag=require("./_baseGetTag"),isObjectLike=require("./isObjectLike"); -/** `Object#toString` result references. */var argsTag="[object Arguments]"; -/** - * The base implementation of `_.isArguments`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - */function baseIsArguments(value){return isObjectLike(value)&&baseGetTag(value)==argsTag}module.exports=baseIsArguments},{"./_baseGetTag":91,"./isObjectLike":252}],97:[function(require,module,exports){var baseIsEqualDeep=require("./_baseIsEqualDeep"),isObjectLike=require("./isObjectLike"); -/** - * The base implementation of `_.isEqual` which supports partial comparisons - * and tracks traversed objects. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @param {boolean} bitmask The bitmask flags. - * 1 - Unordered comparison - * 2 - Partial comparison - * @param {Function} [customizer] The function to customize comparisons. - * @param {Object} [stack] Tracks traversed `value` and `other` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - */function baseIsEqual(value,other,bitmask,customizer,stack){if(value===other){return true}if(value==null||other==null||!isObjectLike(value)&&!isObjectLike(other)){return value!==value&&other!==other}return baseIsEqualDeep(value,other,bitmask,customizer,baseIsEqual,stack)}module.exports=baseIsEqual},{"./_baseIsEqualDeep":98,"./isObjectLike":252}],98:[function(require,module,exports){var Stack=require("./_Stack"),equalArrays=require("./_equalArrays"),equalByTag=require("./_equalByTag"),equalObjects=require("./_equalObjects"),getTag=require("./_getTag"),isArray=require("./isArray"),isBuffer=require("./isBuffer"),isTypedArray=require("./isTypedArray"); -/** Used to compose bitmasks for value comparisons. */var COMPARE_PARTIAL_FLAG=1; -/** `Object#toString` result references. */var argsTag="[object Arguments]",arrayTag="[object Array]",objectTag="[object Object]"; -/** Used for built-in method references. */var objectProto=Object.prototype; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** - * 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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} [stack] Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */function baseIsEqualDeep(object,other,bitmask,customizer,equalFunc,stack){var objIsArr=isArray(object),othIsArr=isArray(other),objTag=objIsArr?arrayTag:getTag(object),othTag=othIsArr?arrayTag:getTag(other);objTag=objTag==argsTag?objectTag:objTag;othTag=othTag==argsTag?objectTag:othTag;var objIsObj=objTag==objectTag,othIsObj=othTag==objectTag,isSameTag=objTag==othTag;if(isSameTag&&isBuffer(object)){if(!isBuffer(other)){return false}objIsArr=true;objIsObj=false}if(isSameTag&&!objIsObj){stack||(stack=new Stack);return objIsArr||isTypedArray(object)?equalArrays(object,other,bitmask,customizer,equalFunc,stack):equalByTag(object,other,objTag,bitmask,customizer,equalFunc,stack)}if(!(bitmask&COMPARE_PARTIAL_FLAG)){var objIsWrapped=objIsObj&&hasOwnProperty.call(object,"__wrapped__"),othIsWrapped=othIsObj&&hasOwnProperty.call(other,"__wrapped__");if(objIsWrapped||othIsWrapped){var objUnwrapped=objIsWrapped?object.value():object,othUnwrapped=othIsWrapped?other.value():other;stack||(stack=new Stack);return equalFunc(objUnwrapped,othUnwrapped,bitmask,customizer,stack)}}if(!isSameTag){return false}stack||(stack=new Stack);return equalObjects(object,other,bitmask,customizer,equalFunc,stack)}module.exports=baseIsEqualDeep},{"./_Stack":59,"./_equalArrays":154,"./_equalByTag":155,"./_equalObjects":156,"./_getTag":168,"./isArray":243,"./isBuffer":246,"./isTypedArray":257}],99:[function(require,module,exports){var getTag=require("./_getTag"),isObjectLike=require("./isObjectLike"); -/** `Object#toString` result references. */var mapTag="[object Map]"; -/** - * The base implementation of `_.isMap` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a map, else `false`. - */function baseIsMap(value){return isObjectLike(value)&&getTag(value)==mapTag}module.exports=baseIsMap},{"./_getTag":168,"./isObjectLike":252}],100:[function(require,module,exports){var Stack=require("./_Stack"),baseIsEqual=require("./_baseIsEqual"); -/** Used to compose bitmasks for value comparisons. */var COMPARE_PARTIAL_FLAG=1,COMPARE_UNORDERED_FLAG=2; -/** - * The base implementation of `_.isMatch` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @param {Array} matchData The property names, values, and compare flags to match. - * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - */function baseIsMatch(object,source,matchData,customizer){var index=matchData.length,length=index,noCustomizer=!customizer;if(object==null){return!length}object=Object(object);while(index--){var data=matchData[index];if(noCustomizer&&data[2]?data[1]!==object[data[0]]:!(data[0]in object)){return false}}while(++index=LARGE_ARRAY_SIZE){var set=iteratee?null:createSet(array);if(set){return setToArray(set)}isCommon=false;includes=cacheHas;seen=new SetCache}else{seen=iteratee?[]:result}outer:while(++indexother||valIsSymbol&&othIsDefined&&othIsReflexive&&!othIsNull&&!othIsSymbol||valIsNull&&othIsDefined&&othIsReflexive||!valIsDefined&&othIsReflexive||!valIsReflexive){return 1}if(!valIsNull&&!valIsSymbol&&!othIsSymbol&&value=ordersLength){return result}var order=orders[index];return result*(order=="desc"?-1:1)}} -// 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://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. -return object.index-other.index}module.exports=compareMultiple},{"./_compareAscending":140}],142:[function(require,module,exports){ -/** - * 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 copyArray(source,array){var index=-1,length=source.length;array||(array=Array(length));while(++index1?sources[length-1]:undefined,guard=length>2?sources[2]:undefined;customizer=assigner.length>3&&typeof customizer=="function"?(length--,customizer):undefined;if(guard&&isIterateeCall(sources[0],sources[1],guard)){customizer=length<3?undefined:customizer;length=1}object=Object(object);while(++index-1?iterable[iteratee?collection[index]:index]:undefined}}module.exports=createFind},{"./_baseIteratee":105,"./isArrayLike":244,"./keys":259}],151:[function(require,module,exports){var baseRange=require("./_baseRange"),isIterateeCall=require("./_isIterateeCall"),toFinite=require("./toFinite"); -/** - * Creates a `_.range` or `_.rangeRight` function. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new range function. - */function createRange(fromRight){return function(start,end,step){if(step&&typeof step!="number"&&isIterateeCall(start,end,step)){end=step=undefined} -// Ensure the sign of `-0` is preserved. -start=toFinite(start);if(end===undefined){end=start;start=0}else{end=toFinite(end)}step=step===undefined?startarrLength)){return false} -// Assume cyclic values are equal. -var stacked=stack.get(array);if(stacked&&stack.get(other)){return stacked==other}var index=-1,result=true,seen=bitmask&COMPARE_UNORDERED_FLAG?new SetCache:undefined;stack.set(array,other);stack.set(other,array); -// Ignore non-index properties. -while(++index-1&&value%1==0&&value-1}module.exports=listCacheHas},{"./_assocIndexOf":76}],192:[function(require,module,exports){var assocIndexOf=require("./_assocIndexOf"); -/** - * Sets the list cache `key` to `value`. - * - * @private - * @name set - * @memberOf ListCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. - */function listCacheSet(key,value){var data=this.__data__,index=assocIndexOf(data,key);if(index<0){++this.size;data.push([key,value])}else{data[index][1]=value}return this}module.exports=listCacheSet},{"./_assocIndexOf":76}],193:[function(require,module,exports){var Hash=require("./_Hash"),ListCache=require("./_ListCache"),Map=require("./_Map"); -/** - * Removes all key-value entries from the map. - * - * @private - * @name clear - * @memberOf MapCache - */function mapCacheClear(){this.size=0;this.__data__={hash:new Hash,map:new(Map||ListCache),string:new Hash}}module.exports=mapCacheClear},{"./_Hash":52,"./_ListCache":53,"./_Map":54}],194:[function(require,module,exports){var getMapData=require("./_getMapData"); -/** - * Removes `key` and its value from the map. - * - * @private - * @name delete - * @memberOf MapCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */function mapCacheDelete(key){var result=getMapData(this,key)["delete"](key);this.size-=result?1:0;return result}module.exports=mapCacheDelete},{"./_getMapData":161}],195:[function(require,module,exports){var getMapData=require("./_getMapData"); -/** - * Gets the map value for `key`. - * - * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */function mapCacheGet(key){return getMapData(this,key).get(key)}module.exports=mapCacheGet},{"./_getMapData":161}],196:[function(require,module,exports){var getMapData=require("./_getMapData"); -/** - * Checks if a map value for `key` exists. - * - * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */function mapCacheHas(key){return getMapData(this,key).has(key)}module.exports=mapCacheHas},{"./_getMapData":161}],197:[function(require,module,exports){var getMapData=require("./_getMapData"); -/** - * Sets the map `key` to `value`. - * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */function mapCacheSet(key,value){var data=getMapData(this,key),size=data.size;data.set(key,value);this.size+=data.size==size?0:1;return this}module.exports=mapCacheSet},{"./_getMapData":161}],198:[function(require,module,exports){ -/** - * Converts `map` to its key-value pairs. - * - * @private - * @param {Object} map The map to convert. - * @returns {Array} Returns the key-value pairs. - */ -function mapToArray(map){var index=-1,result=Array(map.size);map.forEach(function(value,key){result[++index]=[key,value]});return result}module.exports=mapToArray},{}],199:[function(require,module,exports){ -/** - * A specialized version of `matchesProperty` for source values suitable - * for strict equality comparisons, i.e. `===`. - * - * @private - * @param {string} key The key of the property to get. - * @param {*} srcValue The value to match. - * @returns {Function} Returns the new spec function. - */ -function matchesStrictComparable(key,srcValue){return function(object){if(object==null){return false}return object[key]===srcValue&&(srcValue!==undefined||key in Object(object))}}module.exports=matchesStrictComparable},{}],200:[function(require,module,exports){var memoize=require("./memoize"); -/** Used as the maximum memoize cache size. */var MAX_MEMOIZE_SIZE=500; -/** - * A specialized version of `_.memoize` which clears the memoized function's - * cache when it exceeds `MAX_MEMOIZE_SIZE`. - * - * @private - * @param {Function} func The function to have its output memoized. - * @returns {Function} Returns the new memoized function. - */function memoizeCapped(func){var result=memoize(func,function(key){if(cache.size===MAX_MEMOIZE_SIZE){cache.clear()}return key});var cache=result.cache;return result}module.exports=memoizeCapped},{"./memoize":265}],201:[function(require,module,exports){var getNative=require("./_getNative"); -/* Built-in method references that are verified to be native. */var nativeCreate=getNative(Object,"create");module.exports=nativeCreate},{"./_getNative":163}],202:[function(require,module,exports){var overArg=require("./_overArg"); -/* Built-in method references for those with the same name as other `lodash` methods. */var nativeKeys=overArg(Object.keys,Object);module.exports=nativeKeys},{"./_overArg":206}],203:[function(require,module,exports){ -/** - * This function is like - * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * except that it includes inherited enumerable properties. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ -function nativeKeysIn(object){var result=[];if(object!=null){for(var key in Object(object)){result.push(key)}}return result}module.exports=nativeKeysIn},{}],204:[function(require,module,exports){var freeGlobal=require("./_freeGlobal"); -/** Detect free variable `exports`. */var freeExports=typeof exports=="object"&&exports&&!exports.nodeType&&exports; -/** Detect free variable `module`. */var freeModule=freeExports&&typeof module=="object"&&module&&!module.nodeType&&module; -/** Detect the popular CommonJS extension `module.exports`. */var moduleExports=freeModule&&freeModule.exports===freeExports; -/** Detect free variable `process` from Node.js. */var freeProcess=moduleExports&&freeGlobal.process; -/** Used to access faster Node.js helpers. */var nodeUtil=function(){try{ -// Use `util.types` for Node.js 10+. -var types=freeModule&&freeModule.require&&freeModule.require("util").types;if(types){return types} -// Legacy `process.binding('util')` for Node.js < 10. -return freeProcess&&freeProcess.binding&&freeProcess.binding("util")}catch(e){}}();module.exports=nodeUtil},{"./_freeGlobal":158}],205:[function(require,module,exports){ -/** Used for built-in method references. */ -var objectProto=Object.prototype; -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */var nativeObjectToString=objectProto.toString; -/** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */function objectToString(value){return nativeObjectToString.call(value)}module.exports=objectToString},{}],206:[function(require,module,exports){ -/** - * Creates a unary function that invokes `func` with its argument transformed. - * - * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. - */ -function overArg(func,transform){return function(arg){return func(transform(arg))}}module.exports=overArg},{}],207:[function(require,module,exports){var apply=require("./_apply"); -/* Built-in method references for those with the same name as other `lodash` methods. */var nativeMax=Math.max; -/** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */function overRest(func,start,transform){start=nativeMax(start===undefined?func.length-1:start,0);return function(){var args=arguments,index=-1,length=nativeMax(args.length-start,0),array=Array(length);while(++index0){if(++count>=HOT_COUNT){return arguments[0]}}else{count=0}return func.apply(undefined,arguments)}}module.exports=shortOut},{}],215:[function(require,module,exports){var ListCache=require("./_ListCache"); -/** - * Removes all key-value entries from the stack. - * - * @private - * @name clear - * @memberOf Stack - */function stackClear(){this.__data__=new ListCache;this.size=0}module.exports=stackClear},{"./_ListCache":53}],216:[function(require,module,exports){ -/** - * Removes `key` and its value from the stack. - * - * @private - * @name delete - * @memberOf Stack - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ -function stackDelete(key){var data=this.__data__,result=data["delete"](key);this.size=data.size;return result}module.exports=stackDelete},{}],217:[function(require,module,exports){ -/** - * Gets the stack value for `key`. - * - * @private - * @name get - * @memberOf Stack - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ -function stackGet(key){return this.__data__.get(key)}module.exports=stackGet},{}],218:[function(require,module,exports){ -/** - * Checks if a stack value for `key` exists. - * - * @private - * @name has - * @memberOf Stack - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ -function stackHas(key){return this.__data__.has(key)}module.exports=stackHas},{}],219:[function(require,module,exports){var ListCache=require("./_ListCache"),Map=require("./_Map"),MapCache=require("./_MapCache"); -/** Used as the size to enable large array optimizations. */var LARGE_ARRAY_SIZE=200; -/** - * Sets the stack `key` to `value`. - * - * @private - * @name set - * @memberOf Stack - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the stack cache instance. - */function stackSet(key,value){var data=this.__data__;if(data instanceof ListCache){var pairs=data.__data__;if(!Map||pairs.length true - */function clone(value){return baseClone(value,CLONE_SYMBOLS_FLAG)}module.exports=clone},{"./_baseClone":80}],227:[function(require,module,exports){var baseClone=require("./_baseClone"); -/** Used to compose bitmasks for cloning. */var CLONE_DEEP_FLAG=1,CLONE_SYMBOLS_FLAG=4; -/** - * This method is like `_.clone` except that it recursively clones `value`. - * - * @static - * @memberOf _ - * @since 1.0.0 - * @category Lang - * @param {*} value The value to recursively clone. - * @returns {*} Returns the deep cloned value. - * @see _.clone - * @example - * - * var objects = [{ 'a': 1 }, { 'b': 2 }]; - * - * var deep = _.cloneDeep(objects); - * console.log(deep[0] === objects[0]); - * // => false - */function cloneDeep(value){return baseClone(value,CLONE_DEEP_FLAG|CLONE_SYMBOLS_FLAG)}module.exports=cloneDeep},{"./_baseClone":80}],228:[function(require,module,exports){ -/** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new constant function. - * @example - * - * var objects = _.times(2, _.constant({ 'a': 1 })); - * - * console.log(objects); - * // => [{ 'a': 1 }, { 'a': 1 }] - * - * console.log(objects[0] === objects[1]); - * // => true - */ -function constant(value){return function(){return value}}module.exports=constant},{}],229:[function(require,module,exports){var baseRest=require("./_baseRest"),eq=require("./eq"),isIterateeCall=require("./_isIterateeCall"),keysIn=require("./keysIn"); -/** Used for built-in method references. */var objectProto=Object.prototype; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** - * Assigns own and inherited enumerable string keyed properties of source - * objects to the destination object for all destination properties that - * resolve to `undefined`. Source objects are applied from left to right. - * Once a property is set, additional values of the same property are ignored. - * - * **Note:** This method mutates `object`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.defaultsDeep - * @example - * - * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); - * // => { 'a': 1, 'b': 2 } - */var defaults=baseRest(function(object,sources){object=Object(object);var index=-1;var length=sources.length;var guard=length>2?sources[2]:undefined;if(guard&&isIterateeCall(sources[0],sources[1],guard)){length=1}while(++index true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ -function eq(value,other){return value===other||value!==value&&other!==other}module.exports=eq},{}],232:[function(require,module,exports){var arrayFilter=require("./_arrayFilter"),baseFilter=require("./_baseFilter"),baseIteratee=require("./_baseIteratee"),isArray=require("./isArray"); -/** - * Iterates over elements of `collection`, returning an array of all elements - * `predicate` returns truthy for. The predicate is invoked with three - * arguments: (value, index|key, collection). - * - * **Note:** Unlike `_.remove`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - * @see _.reject - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * _.filter(users, function(o) { return !o.active; }); - * // => objects for ['fred'] - * - * // The `_.matches` iteratee shorthand. - * _.filter(users, { 'age': 36, 'active': true }); - * // => objects for ['barney'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.filter(users, ['active', false]); - * // => objects for ['fred'] - * - * // The `_.property` iteratee shorthand. - * _.filter(users, 'active'); - * // => objects for ['barney'] - */function filter(collection,predicate){var func=isArray(collection)?arrayFilter:baseFilter;return func(collection,baseIteratee(predicate,3))}module.exports=filter},{"./_arrayFilter":65,"./_baseFilter":84,"./_baseIteratee":105,"./isArray":243}],233:[function(require,module,exports){var createFind=require("./_createFind"),findIndex=require("./findIndex"); -/** - * Iterates over elements of `collection`, returning the first element - * `predicate` returns truthy for. The predicate is invoked with three - * arguments: (value, index|key, collection). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=0] The index to search from. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false }, - * { 'user': 'pebbles', 'age': 1, 'active': true } - * ]; - * - * _.find(users, function(o) { return o.age < 40; }); - * // => object for 'barney' - * - * // The `_.matches` iteratee shorthand. - * _.find(users, { 'age': 1, 'active': true }); - * // => object for 'pebbles' - * - * // The `_.matchesProperty` iteratee shorthand. - * _.find(users, ['active', false]); - * // => object for 'fred' - * - * // The `_.property` iteratee shorthand. - * _.find(users, 'active'); - * // => object for 'barney' - */var find=createFind(findIndex);module.exports=find},{"./_createFind":150,"./findIndex":234}],234:[function(require,module,exports){var baseFindIndex=require("./_baseFindIndex"),baseIteratee=require("./_baseIteratee"),toInteger=require("./toInteger"); -/* Built-in method references for those with the same name as other `lodash` methods. */var nativeMax=Math.max; -/** - * This method is like `_.find` except that it returns the index of the first - * element `predicate` returns truthy for instead of the element itself. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the found element, else `-1`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * _.findIndex(users, function(o) { return o.user == 'barney'; }); - * // => 0 - * - * // The `_.matches` iteratee shorthand. - * _.findIndex(users, { 'user': 'fred', 'active': false }); - * // => 1 - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findIndex(users, ['active', false]); - * // => 0 - * - * // The `_.property` iteratee shorthand. - * _.findIndex(users, 'active'); - * // => 2 - */function findIndex(array,predicate,fromIndex){var length=array==null?0:array.length;if(!length){return-1}var index=fromIndex==null?0:toInteger(fromIndex);if(index<0){index=nativeMax(length+index,0)}return baseFindIndex(array,baseIteratee(predicate,3),index)}module.exports=findIndex},{"./_baseFindIndex":85,"./_baseIteratee":105,"./toInteger":280}],235:[function(require,module,exports){var baseFlatten=require("./_baseFlatten"); -/** - * Flattens `array` a single level deep. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to flatten. - * @returns {Array} Returns the new flattened array. - * @example - * - * _.flatten([1, [2, [3, [4]], 5]]); - * // => [1, 2, [3, [4]], 5] - */function flatten(array){var length=array==null?0:array.length;return length?baseFlatten(array,1):[]}module.exports=flatten},{"./_baseFlatten":86}],236:[function(require,module,exports){var arrayEach=require("./_arrayEach"),baseEach=require("./_baseEach"),castFunction=require("./_castFunction"),isArray=require("./isArray"); -/** - * Iterates over elements of `collection` and invokes `iteratee` for each element. - * The iteratee is invoked with three arguments: (value, index|key, collection). - * Iteratee 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 use `_.forIn` - * or `_.forOwn` for object iteration. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @alias each - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array|Object} Returns `collection`. - * @see _.forEachRight - * @example - * - * _.forEach([1, 2], function(value) { - * console.log(value); - * }); - * // => Logs `1` then `2`. - * - * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { - * console.log(key); - * }); - * // => Logs 'a' then 'b' (iteration order is not guaranteed). - */function forEach(collection,iteratee){var func=isArray(collection)?arrayEach:baseEach;return func(collection,castFunction(iteratee))}module.exports=forEach},{"./_arrayEach":64,"./_baseEach":82,"./_castFunction":132,"./isArray":243}],237:[function(require,module,exports){var baseFor=require("./_baseFor"),castFunction=require("./_castFunction"),keysIn=require("./keysIn"); -/** - * Iterates over own and inherited enumerable string keyed properties of an - * object and invokes `iteratee` for each property. The iteratee is invoked - * with three arguments: (value, key, object). Iteratee functions may exit - * iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @since 0.3.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns `object`. - * @see _.forInRight - * @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', then 'c' (iteration order is not guaranteed). - */function forIn(object,iteratee){return object==null?object:baseFor(object,castFunction(iteratee),keysIn)}module.exports=forIn},{"./_baseFor":87,"./_castFunction":132,"./keysIn":260}],238:[function(require,module,exports){var baseGet=require("./_baseGet"); -/** - * Gets the value at `path` of `object`. If the resolved value is - * `undefined`, the `defaultValue` is returned in its place. - * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.get(object, 'a[0].b.c'); - * // => 3 - * - * _.get(object, ['a', '0', 'b', 'c']); - * // => 3 - * - * _.get(object, 'a.b.c', 'default'); - * // => 'default' - */function get(object,path,defaultValue){var result=object==null?undefined:baseGet(object,path);return result===undefined?defaultValue:result}module.exports=get},{"./_baseGet":89}],239:[function(require,module,exports){var baseHas=require("./_baseHas"),hasPath=require("./_hasPath"); -/** - * Checks if `path` is a direct property of `object`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - * @example - * - * var object = { 'a': { 'b': 2 } }; - * var other = _.create({ 'a': _.create({ 'b': 2 }) }); - * - * _.has(object, 'a'); - * // => true - * - * _.has(object, 'a.b'); - * // => true - * - * _.has(object, ['a', 'b']); - * // => true - * - * _.has(other, 'a'); - * // => false - */function has(object,path){return object!=null&&hasPath(object,path,baseHas)}module.exports=has},{"./_baseHas":93,"./_hasPath":170}],240:[function(require,module,exports){var baseHasIn=require("./_baseHasIn"),hasPath=require("./_hasPath"); -/** - * Checks if `path` is a direct or inherited property of `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - * @example - * - * var object = _.create({ 'a': _.create({ 'b': 2 }) }); - * - * _.hasIn(object, 'a'); - * // => true - * - * _.hasIn(object, 'a.b'); - * // => true - * - * _.hasIn(object, ['a', 'b']); - * // => true - * - * _.hasIn(object, 'b'); - * // => false - */function hasIn(object,path){return object!=null&&hasPath(object,path,baseHasIn)}module.exports=hasIn},{"./_baseHasIn":94,"./_hasPath":170}],241:[function(require,module,exports){ -/** - * This method returns the first argument it receives. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'a': 1 }; - * - * console.log(_.identity(object) === object); - * // => true - */ -function identity(value){return value}module.exports=identity},{}],242:[function(require,module,exports){var baseIsArguments=require("./_baseIsArguments"),isObjectLike=require("./isObjectLike"); -/** Used for built-in method references. */var objectProto=Object.prototype; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** Built-in value references. */var propertyIsEnumerable=objectProto.propertyIsEnumerable; -/** - * Checks if `value` is likely an `arguments` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - * else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */var isArguments=baseIsArguments(function(){return arguments}())?baseIsArguments:function(value){return isObjectLike(value)&&hasOwnProperty.call(value,"callee")&&!propertyIsEnumerable.call(value,"callee")};module.exports=isArguments},{"./_baseIsArguments":96,"./isObjectLike":252}],243:[function(require,module,exports){ -/** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ -var isArray=Array.isArray;module.exports=isArray},{}],244:[function(require,module,exports){var isFunction=require("./isFunction"),isLength=require("./isLength"); -/** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * - * _.isArrayLike([1, 2, 3]); - * // => true - * - * _.isArrayLike(document.body.children); - * // => true - * - * _.isArrayLike('abc'); - * // => true - * - * _.isArrayLike(_.noop); - * // => false - */function isArrayLike(value){return value!=null&&isLength(value.length)&&!isFunction(value)}module.exports=isArrayLike},{"./isFunction":248,"./isLength":249}],245:[function(require,module,exports){var isArrayLike=require("./isArrayLike"),isObjectLike=require("./isObjectLike"); -/** - * This method is like `_.isArrayLike` except that it also checks if `value` - * is an object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, - * else `false`. - * @example - * - * _.isArrayLikeObject([1, 2, 3]); - * // => true - * - * _.isArrayLikeObject(document.body.children); - * // => true - * - * _.isArrayLikeObject('abc'); - * // => false - * - * _.isArrayLikeObject(_.noop); - * // => false - */function isArrayLikeObject(value){return isObjectLike(value)&&isArrayLike(value)}module.exports=isArrayLikeObject},{"./isArrayLike":244,"./isObjectLike":252}],246:[function(require,module,exports){var root=require("./_root"),stubFalse=require("./stubFalse"); -/** Detect free variable `exports`. */var freeExports=typeof exports=="object"&&exports&&!exports.nodeType&&exports; -/** Detect free variable `module`. */var freeModule=freeExports&&typeof module=="object"&&module&&!module.nodeType&&module; -/** Detect the popular CommonJS extension `module.exports`. */var moduleExports=freeModule&&freeModule.exports===freeExports; -/** Built-in value references. */var Buffer=moduleExports?root.Buffer:undefined; -/* Built-in method references for those with the same name as other `lodash` methods. */var nativeIsBuffer=Buffer?Buffer.isBuffer:undefined; -/** - * Checks if `value` is a buffer. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. - * @example - * - * _.isBuffer(new Buffer(2)); - * // => true - * - * _.isBuffer(new Uint8Array(2)); - * // => false - */var isBuffer=nativeIsBuffer||stubFalse;module.exports=isBuffer},{"./_root":208,"./stubFalse":278}],247:[function(require,module,exports){var baseKeys=require("./_baseKeys"),getTag=require("./_getTag"),isArguments=require("./isArguments"),isArray=require("./isArray"),isArrayLike=require("./isArrayLike"),isBuffer=require("./isBuffer"),isPrototype=require("./_isPrototype"),isTypedArray=require("./isTypedArray"); -/** `Object#toString` result references. */var mapTag="[object Map]",setTag="[object Set]"; -/** Used for built-in method references. */var objectProto=Object.prototype; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** - * Checks if `value` is an empty object, collection, map, or set. - * - * Objects are considered empty if they have no own enumerable string keyed - * properties. - * - * Array-like values such as `arguments` objects, arrays, buffers, strings, or - * jQuery-like collections are considered empty if they have a `length` of `0`. - * Similarly, maps and sets are considered empty if they have a `size` of `0`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @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}if(isArrayLike(value)&&(isArray(value)||typeof value=="string"||typeof value.splice=="function"||isBuffer(value)||isTypedArray(value)||isArguments(value))){return!value.length}var tag=getTag(value);if(tag==mapTag||tag==setTag){return!value.size}if(isPrototype(value)){return!baseKeys(value).length}for(var key in value){if(hasOwnProperty.call(value,key)){return false}}return true}module.exports=isEmpty},{"./_baseKeys":106,"./_getTag":168,"./_isPrototype":186,"./isArguments":242,"./isArray":243,"./isArrayLike":244,"./isBuffer":246,"./isTypedArray":257}],248:[function(require,module,exports){var baseGetTag=require("./_baseGetTag"),isObject=require("./isObject"); -/** `Object#toString` result references. */var asyncTag="[object AsyncFunction]",funcTag="[object Function]",genTag="[object GeneratorFunction]",proxyTag="[object Proxy]"; -/** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */function isFunction(value){if(!isObject(value)){return false} -// The use of `Object#toString` avoids issues with the `typeof` operator -// in Safari 9 which returns 'object' for typed arrays and other constructors. -var tag=baseGetTag(value);return tag==funcTag||tag==genTag||tag==asyncTag||tag==proxyTag}module.exports=isFunction},{"./_baseGetTag":91,"./isObject":251}],249:[function(require,module,exports){ -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER=9007199254740991; -/** - * Checks if `value` is a valid array-like length. - * - * **Note:** This method is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. - * @example - * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false - * - * _.isLength(Infinity); - * // => false - * - * _.isLength('3'); - * // => false - */function isLength(value){return typeof value=="number"&&value>-1&&value%1==0&&value<=MAX_SAFE_INTEGER}module.exports=isLength},{}],250:[function(require,module,exports){var baseIsMap=require("./_baseIsMap"),baseUnary=require("./_baseUnary"),nodeUtil=require("./_nodeUtil"); -/* Node.js helper references. */var nodeIsMap=nodeUtil&&nodeUtil.isMap; -/** - * Checks if `value` is classified as a `Map` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a map, else `false`. - * @example - * - * _.isMap(new Map); - * // => true - * - * _.isMap(new WeakMap); - * // => false - */var isMap=nodeIsMap?baseUnary(nodeIsMap):baseIsMap;module.exports=isMap},{"./_baseIsMap":99,"./_baseUnary":127,"./_nodeUtil":204}],251:[function(require,module,exports){ -/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ -function isObject(value){var type=typeof value;return value!=null&&(type=="object"||type=="function")}module.exports=isObject},{}],252:[function(require,module,exports){ -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value){return value!=null&&typeof value=="object"}module.exports=isObjectLike},{}],253:[function(require,module,exports){var baseGetTag=require("./_baseGetTag"),getPrototype=require("./_getPrototype"),isObjectLike=require("./isObjectLike"); -/** `Object#toString` result references. */var objectTag="[object Object]"; -/** Used for built-in method references. */var funcProto=Function.prototype,objectProto=Object.prototype; -/** Used to resolve the decompiled source of functions. */var funcToString=funcProto.toString; -/** Used to check objects for own properties. */var hasOwnProperty=objectProto.hasOwnProperty; -/** Used to infer the `Object` constructor. */var objectCtorString=funcToString.call(Object); -/** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * @static - * @memberOf _ - * @since 0.8.0 - * @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 - */function isPlainObject(value){if(!isObjectLike(value)||baseGetTag(value)!=objectTag){return false}var proto=getPrototype(value);if(proto===null){return true}var Ctor=hasOwnProperty.call(proto,"constructor")&&proto.constructor;return typeof Ctor=="function"&&Ctor instanceof Ctor&&funcToString.call(Ctor)==objectCtorString}module.exports=isPlainObject},{"./_baseGetTag":91,"./_getPrototype":164,"./isObjectLike":252}],254:[function(require,module,exports){var baseIsSet=require("./_baseIsSet"),baseUnary=require("./_baseUnary"),nodeUtil=require("./_nodeUtil"); -/* Node.js helper references. */var nodeIsSet=nodeUtil&&nodeUtil.isSet; -/** - * Checks if `value` is classified as a `Set` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a set, else `false`. - * @example - * - * _.isSet(new Set); - * // => true - * - * _.isSet(new WeakSet); - * // => false - */var isSet=nodeIsSet?baseUnary(nodeIsSet):baseIsSet;module.exports=isSet},{"./_baseIsSet":103,"./_baseUnary":127,"./_nodeUtil":204}],255:[function(require,module,exports){var baseGetTag=require("./_baseGetTag"),isArray=require("./isArray"),isObjectLike=require("./isObjectLike"); -/** `Object#toString` result references. */var stringTag="[object String]"; -/** - * Checks if `value` is classified as a `String` primitive or object. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a string, else `false`. - * @example - * - * _.isString('abc'); - * // => true - * - * _.isString(1); - * // => false - */function isString(value){return typeof value=="string"||!isArray(value)&&isObjectLike(value)&&baseGetTag(value)==stringTag}module.exports=isString},{"./_baseGetTag":91,"./isArray":243,"./isObjectLike":252}],256:[function(require,module,exports){var baseGetTag=require("./_baseGetTag"),isObjectLike=require("./isObjectLike"); -/** `Object#toString` result references. */var symbolTag="[object Symbol]"; -/** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */function isSymbol(value){return typeof value=="symbol"||isObjectLike(value)&&baseGetTag(value)==symbolTag}module.exports=isSymbol},{"./_baseGetTag":91,"./isObjectLike":252}],257:[function(require,module,exports){var baseIsTypedArray=require("./_baseIsTypedArray"),baseUnary=require("./_baseUnary"),nodeUtil=require("./_nodeUtil"); -/* Node.js helper references. */var nodeIsTypedArray=nodeUtil&&nodeUtil.isTypedArray; -/** - * Checks if `value` is classified as a typed array. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - * @example - * - * _.isTypedArray(new Uint8Array); - * // => true - * - * _.isTypedArray([]); - * // => false - */var isTypedArray=nodeIsTypedArray?baseUnary(nodeIsTypedArray):baseIsTypedArray;module.exports=isTypedArray},{"./_baseIsTypedArray":104,"./_baseUnary":127,"./_nodeUtil":204}],258:[function(require,module,exports){ -/** - * Checks if `value` is `undefined`. - * - * @static - * @since 0.1.0 - * @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 value===undefined}module.exports=isUndefined},{}],259:[function(require,module,exports){var arrayLikeKeys=require("./_arrayLikeKeys"),baseKeys=require("./_baseKeys"),isArrayLike=require("./isArrayLike"); -/** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * for more details. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @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'] - */function keys(object){return isArrayLike(object)?arrayLikeKeys(object):baseKeys(object)}module.exports=keys},{"./_arrayLikeKeys":68,"./_baseKeys":106,"./isArrayLike":244}],260:[function(require,module,exports){var arrayLikeKeys=require("./_arrayLikeKeys"),baseKeysIn=require("./_baseKeysIn"),isArrayLike=require("./isArrayLike"); -/** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Object - * @param {Object} object The object to query. - * @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){return isArrayLike(object)?arrayLikeKeys(object,true):baseKeysIn(object)}module.exports=keysIn},{"./_arrayLikeKeys":68,"./_baseKeysIn":107,"./isArrayLike":244}],261:[function(require,module,exports){ -/** - * Gets the last element of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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==null?0:array.length;return length?array[length-1]:undefined}module.exports=last},{}],262:[function(require,module,exports){var arrayMap=require("./_arrayMap"),baseIteratee=require("./_baseIteratee"),baseMap=require("./_baseMap"),isArray=require("./isArray"); -/** - * Creates an array of values by running each element in `collection` thru - * `iteratee`. The iteratee is invoked with three arguments: - * (value, index|key, collection). - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. - * - * The guarded methods are: - * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, - * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, - * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, - * `template`, `trim`, `trimEnd`, `trimStart`, and `words` - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - * @example - * - * function square(n) { - * return n * n; - * } - * - * _.map([4, 8], square); - * // => [16, 64] - * - * _.map({ 'a': 4, 'b': 8 }, square); - * // => [16, 64] (iteration order is not guaranteed) - * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } - * ]; - * - * // The `_.property` iteratee shorthand. - * _.map(users, 'user'); - * // => ['barney', 'fred'] - */function map(collection,iteratee){var func=isArray(collection)?arrayMap:baseMap;return func(collection,baseIteratee(iteratee,3))}module.exports=map},{"./_arrayMap":69,"./_baseIteratee":105,"./_baseMap":109,"./isArray":243}],263:[function(require,module,exports){var baseAssignValue=require("./_baseAssignValue"),baseForOwn=require("./_baseForOwn"),baseIteratee=require("./_baseIteratee"); -/** - * Creates an object with the same keys as `object` and values generated - * by running each own enumerable string keyed property of `object` thru - * `iteratee`. The iteratee is invoked with three arguments: - * (value, key, object). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new mapped object. - * @see _.mapKeys - * @example - * - * var users = { - * 'fred': { 'user': 'fred', 'age': 40 }, - * 'pebbles': { 'user': 'pebbles', 'age': 1 } - * }; - * - * _.mapValues(users, function(o) { return o.age; }); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) - * - * // The `_.property` iteratee shorthand. - * _.mapValues(users, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) - */function mapValues(object,iteratee){var result={};iteratee=baseIteratee(iteratee,3);baseForOwn(object,function(value,key,object){baseAssignValue(result,key,iteratee(value,key,object))});return result}module.exports=mapValues},{"./_baseAssignValue":79,"./_baseForOwn":88,"./_baseIteratee":105}],264:[function(require,module,exports){var baseExtremum=require("./_baseExtremum"),baseGt=require("./_baseGt"),identity=require("./identity"); -/** - * Computes the maximum value of `array`. If `array` is empty or falsey, - * `undefined` is returned. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Math - * @param {Array} array The array to iterate over. - * @returns {*} Returns the maximum value. - * @example - * - * _.max([4, 2, 8, 6]); - * // => 8 - * - * _.max([]); - * // => undefined - */function max(array){return array&&array.length?baseExtremum(array,identity,baseGt):undefined}module.exports=max},{"./_baseExtremum":83,"./_baseGt":92,"./identity":241}],265:[function(require,module,exports){var MapCache=require("./_MapCache"); -/** Error message constants. */var FUNC_ERROR_TEXT="Expected a function"; -/** - * 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 used as the map 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 - * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) - * method interface of `clear`, `delete`, `get`, `has`, and `set`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @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 memoized function. - * @example - * - * var object = { 'a': 1, 'b': 2 }; - * var other = { 'c': 3, 'd': 4 }; - * - * var values = _.memoize(_.values); - * values(object); - * // => [1, 2] - * - * values(other); - * // => [3, 4] - * - * object.a = 2; - * values(object); - * // => [1, 2] - * - * // Modify the result cache. - * values.cache.set(object, ['a', 'b']); - * values(object); - * // => ['a', 'b'] - * - * // Replace `_.memoize.Cache`. - * _.memoize.Cache = WeakMap; - */function memoize(func,resolver){if(typeof func!="function"||resolver!=null&&typeof resolver!="function"){throw new TypeError(FUNC_ERROR_TEXT)}var memoized=function(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key)}var result=func.apply(this,args);memoized.cache=cache.set(key,result)||cache;return result};memoized.cache=new(memoize.Cache||MapCache);return memoized} -// Expose `MapCache`. -memoize.Cache=MapCache;module.exports=memoize},{"./_MapCache":55}],266:[function(require,module,exports){var baseMerge=require("./_baseMerge"),createAssigner=require("./_createAssigner"); -/** - * This method is like `_.assign` except that it recursively merges own and - * inherited enumerable string keyed properties of source objects into the - * destination object. Source properties that resolve to `undefined` are - * skipped if a destination value exists. Array and plain object properties - * are merged recursively. Other objects and value types are overridden by - * assignment. Source objects are applied from left to right. Subsequent - * sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @example - * - * var object = { - * 'a': [{ 'b': 2 }, { 'd': 4 }] - * }; - * - * var other = { - * 'a': [{ 'c': 3 }, { 'e': 5 }] - * }; - * - * _.merge(object, other); - * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } - */var merge=createAssigner(function(object,source,srcIndex){baseMerge(object,source,srcIndex)});module.exports=merge},{"./_baseMerge":112,"./_createAssigner":147}],267:[function(require,module,exports){var baseExtremum=require("./_baseExtremum"),baseLt=require("./_baseLt"),identity=require("./identity"); -/** - * Computes the minimum value of `array`. If `array` is empty or falsey, - * `undefined` is returned. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Math - * @param {Array} array The array to iterate over. - * @returns {*} Returns the minimum value. - * @example - * - * _.min([4, 2, 8, 6]); - * // => 2 - * - * _.min([]); - * // => undefined - */function min(array){return array&&array.length?baseExtremum(array,identity,baseLt):undefined}module.exports=min},{"./_baseExtremum":83,"./_baseLt":108,"./identity":241}],268:[function(require,module,exports){var baseExtremum=require("./_baseExtremum"),baseIteratee=require("./_baseIteratee"),baseLt=require("./_baseLt"); -/** - * This method is like `_.min` except that it accepts `iteratee` which is - * invoked for each element in `array` to generate the criterion by which - * the value is ranked. The iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Math - * @param {Array} array The array to iterate over. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {*} Returns the minimum value. - * @example - * - * var objects = [{ 'n': 1 }, { 'n': 2 }]; - * - * _.minBy(objects, function(o) { return o.n; }); - * // => { 'n': 1 } - * - * // The `_.property` iteratee shorthand. - * _.minBy(objects, 'n'); - * // => { 'n': 1 } - */function minBy(array,iteratee){return array&&array.length?baseExtremum(array,baseIteratee(iteratee,2),baseLt):undefined}module.exports=minBy},{"./_baseExtremum":83,"./_baseIteratee":105,"./_baseLt":108}],269:[function(require,module,exports){ -/** - * This method returns `undefined`. - * - * @static - * @memberOf _ - * @since 2.3.0 - * @category Util - * @example - * - * _.times(2, _.noop); - * // => [undefined, undefined] - */ -function noop(){ -// No operation performed. -}module.exports=noop},{}],270:[function(require,module,exports){var root=require("./_root"); -/** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */var now=function(){return root.Date.now()};module.exports=now},{"./_root":208}],271:[function(require,module,exports){var basePick=require("./_basePick"),flatRest=require("./_flatRest"); -/** - * Creates an object composed of the picked `object` properties. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The source object. - * @param {...(string|string[])} [paths] The property paths to pick. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.pick(object, ['a', 'c']); - * // => { 'a': 1, 'c': 3 } - */var pick=flatRest(function(object,paths){return object==null?{}:basePick(object,paths)});module.exports=pick},{"./_basePick":115,"./_flatRest":157}],272:[function(require,module,exports){var baseProperty=require("./_baseProperty"),basePropertyDeep=require("./_basePropertyDeep"),isKey=require("./_isKey"),toKey=require("./_toKey"); -/** - * Creates a function that returns the value at `path` of a given object. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new accessor function. - * @example - * - * var objects = [ - * { 'a': { 'b': 2 } }, - * { 'a': { 'b': 1 } } - * ]; - * - * _.map(objects, _.property('a.b')); - * // => [2, 1] - * - * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); - * // => [1, 2] - */function property(path){return isKey(path)?baseProperty(toKey(path)):basePropertyDeep(path)}module.exports=property},{"./_baseProperty":117,"./_basePropertyDeep":118,"./_isKey":183,"./_toKey":223}],273:[function(require,module,exports){var createRange=require("./_createRange"); -/** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to, but not including, `end`. A step of `-1` is used if a negative - * `start` is specified without an `end` or `step`. If `end` is not specified, - * it's set to `start` with `start` then set to `0`. - * - * **Note:** JavaScript follows the IEEE-754 standard for resolving - * floating-point values which can produce unexpected results. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns the range of numbers. - * @see _.inRange, _.rangeRight - * @example - * - * _.range(4); - * // => [0, 1, 2, 3] - * - * _.range(-4); - * // => [0, -1, -2, -3] - * - * _.range(1, 5); - * // => [1, 2, 3, 4] - * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] - * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] - * - * _.range(1, 4, 0); - * // => [1, 1, 1] - * - * _.range(0); - * // => [] - */var range=createRange();module.exports=range},{"./_createRange":151}],274:[function(require,module,exports){var arrayReduce=require("./_arrayReduce"),baseEach=require("./_baseEach"),baseIteratee=require("./_baseIteratee"),baseReduce=require("./_baseReduce"),isArray=require("./isArray"); -/** - * Reduces `collection` to a value which is the accumulated result of running - * each element in `collection` thru `iteratee`, where each successive - * invocation is supplied the return value of the previous. If `accumulator` - * is not given, the first element of `collection` is used as the initial - * value. The iteratee is invoked with four arguments: - * (accumulator, value, index|key, collection). - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.reduce`, `_.reduceRight`, and `_.transform`. - * - * The guarded methods are: - * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, - * and `sortBy` - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @returns {*} Returns the accumulated value. - * @see _.reduceRight - * @example - * - * _.reduce([1, 2], function(sum, n) { - * return sum + n; - * }, 0); - * // => 3 - * - * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { - * (result[value] || (result[value] = [])).push(key); - * return result; - * }, {}); - * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) - */function reduce(collection,iteratee,accumulator){var func=isArray(collection)?arrayReduce:baseReduce,initAccum=arguments.length<3;return func(collection,baseIteratee(iteratee,4),accumulator,initAccum,baseEach)}module.exports=reduce},{"./_arrayReduce":71,"./_baseEach":82,"./_baseIteratee":105,"./_baseReduce":120,"./isArray":243}],275:[function(require,module,exports){var baseKeys=require("./_baseKeys"),getTag=require("./_getTag"),isArrayLike=require("./isArrayLike"),isString=require("./isString"),stringSize=require("./_stringSize"); -/** `Object#toString` result references. */var mapTag="[object Map]",setTag="[object Set]"; -/** - * Gets the size of `collection` by returning its length for array-like - * values or the number of own enumerable string keyed properties for objects. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object|string} collection The collection to inspect. - * @returns {number} Returns the collection size. - * @example - * - * _.size([1, 2, 3]); - * // => 3 - * - * _.size({ 'a': 1, 'b': 2 }); - * // => 2 - * - * _.size('pebbles'); - * // => 7 - */function size(collection){if(collection==null){return 0}if(isArrayLike(collection)){return isString(collection)?stringSize(collection):collection.length}var tag=getTag(collection);if(tag==mapTag||tag==setTag){return collection.size}return baseKeys(collection).length}module.exports=size},{"./_baseKeys":106,"./_getTag":168,"./_stringSize":221,"./isArrayLike":244,"./isString":255}],276:[function(require,module,exports){var baseFlatten=require("./_baseFlatten"),baseOrderBy=require("./_baseOrderBy"),baseRest=require("./_baseRest"),isIterateeCall=require("./_isIterateeCall"); -/** - * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection thru each iteratee. This method - * performs a stable sort, that is, it preserves the original sort order of - * equal elements. The iteratees are invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {...(Function|Function[])} [iteratees=[_.identity]] - * The iteratees to sort by. - * @returns {Array} Returns the new sorted array. - * @example - * - * var users = [ - * { 'user': 'fred', 'age': 48 }, - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 }, - * { 'user': 'barney', 'age': 34 } - * ]; - * - * _.sortBy(users, [function(o) { return o.user; }]); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] - * - * _.sortBy(users, ['user', 'age']); - * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] - */var sortBy=baseRest(function(collection,iteratees){if(collection==null){return[]}var length=iteratees.length;if(length>1&&isIterateeCall(collection,iteratees[0],iteratees[1])){iteratees=[]}else if(length>2&&isIterateeCall(iteratees[0],iteratees[1],iteratees[2])){iteratees=[iteratees[0]]}return baseOrderBy(collection,baseFlatten(iteratees,1),[])});module.exports=sortBy},{"./_baseFlatten":86,"./_baseOrderBy":114,"./_baseRest":121,"./_isIterateeCall":182}],277:[function(require,module,exports){ -/** - * This method returns a new empty array. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {Array} Returns the new empty array. - * @example - * - * var arrays = _.times(2, _.stubArray); - * - * console.log(arrays); - * // => [[], []] - * - * console.log(arrays[0] === arrays[1]); - * // => false - */ -function stubArray(){return[]}module.exports=stubArray},{}],278:[function(require,module,exports){ -/** - * This method returns `false`. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {boolean} Returns `false`. - * @example - * - * _.times(2, _.stubFalse); - * // => [false, false] - */ -function stubFalse(){return false}module.exports=stubFalse},{}],279:[function(require,module,exports){var toNumber=require("./toNumber"); -/** Used as references for various `Number` constants. */var INFINITY=1/0,MAX_INTEGER=17976931348623157e292; -/** - * Converts `value` to a finite number. - * - * @static - * @memberOf _ - * @since 4.12.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted number. - * @example - * - * _.toFinite(3.2); - * // => 3.2 - * - * _.toFinite(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toFinite(Infinity); - * // => 1.7976931348623157e+308 - * - * _.toFinite('3.2'); - * // => 3.2 - */function toFinite(value){if(!value){return value===0?value:0}value=toNumber(value);if(value===INFINITY||value===-INFINITY){var sign=value<0?-1:1;return sign*MAX_INTEGER}return value===value?value:0}module.exports=toFinite},{"./toNumber":281}],280:[function(require,module,exports){var toFinite=require("./toFinite"); -/** - * Converts `value` to an integer. - * - * **Note:** This method is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. - * @example - * - * _.toInteger(3.2); - * // => 3 - * - * _.toInteger(Number.MIN_VALUE); - * // => 0 - * - * _.toInteger(Infinity); - * // => 1.7976931348623157e+308 - * - * _.toInteger('3.2'); - * // => 3 - */function toInteger(value){var result=toFinite(value),remainder=result%1;return result===result?remainder?result-remainder:result:0}module.exports=toInteger},{"./toFinite":279}],281:[function(require,module,exports){var isObject=require("./isObject"),isSymbol=require("./isSymbol"); -/** Used as references for various `Number` constants. */var NAN=0/0; -/** Used to match leading and trailing whitespace. */var reTrim=/^\s+|\s+$/g; -/** Used to detect bad signed hexadecimal string values. */var reIsBadHex=/^[-+]0x[0-9a-f]+$/i; -/** Used to detect binary string values. */var reIsBinary=/^0b[01]+$/i; -/** Used to detect octal string values. */var reIsOctal=/^0o[0-7]+$/i; -/** Built-in method references without a dependency on `root`. */var freeParseInt=parseInt; -/** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */function toNumber(value){if(typeof value=="number"){return value}if(isSymbol(value)){return NAN}if(isObject(value)){var other=typeof value.valueOf=="function"?value.valueOf():value;value=isObject(other)?other+"":other}if(typeof value!="string"){return value===0?value:+value}value=value.replace(reTrim,"");var isBinary=reIsBinary.test(value);return isBinary||reIsOctal.test(value)?freeParseInt(value.slice(2),isBinary?2:8):reIsBadHex.test(value)?NAN:+value}module.exports=toNumber},{"./isObject":251,"./isSymbol":256}],282:[function(require,module,exports){var copyObject=require("./_copyObject"),keysIn=require("./keysIn"); -/** - * Converts `value` to a plain object flattening inherited enumerable string - * keyed properties of `value` to own properties of the plain object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @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 copyObject(value,keysIn(value))}module.exports=toPlainObject},{"./_copyObject":143,"./keysIn":260}],283:[function(require,module,exports){var baseToString=require("./_baseToString"); -/** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.toString(null); - * // => '' - * - * _.toString(-0); - * // => '-0' - * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */function toString(value){return value==null?"":baseToString(value)}module.exports=toString},{"./_baseToString":126}],284:[function(require,module,exports){var arrayEach=require("./_arrayEach"),baseCreate=require("./_baseCreate"),baseForOwn=require("./_baseForOwn"),baseIteratee=require("./_baseIteratee"),getPrototype=require("./_getPrototype"),isArray=require("./isArray"),isBuffer=require("./isBuffer"),isFunction=require("./isFunction"),isObject=require("./isObject"),isTypedArray=require("./isTypedArray"); -/** - * An alternative to `_.reduce`; this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable string keyed properties thru `iteratee`, with each invocation - * potentially mutating the `accumulator` object. If `accumulator` is not - * provided, a new object with the same `[[Prototype]]` will be used. The - * iteratee is invoked with four arguments: (accumulator, value, key, object). - * Iteratee functions may exit iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @since 1.3.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @returns {*} Returns the accumulated value. - * @example - * - * _.transform([2, 3, 4], function(result, n) { - * result.push(n *= n); - * return n % 2 == 0; - * }, []); - * // => [4, 9] - * - * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { - * (result[value] || (result[value] = [])).push(key); - * }, {}); - * // => { '1': ['a', 'c'], '2': ['b'] } - */function transform(object,iteratee,accumulator){var isArr=isArray(object),isArrLike=isArr||isBuffer(object)||isTypedArray(object);iteratee=baseIteratee(iteratee,4);if(accumulator==null){var Ctor=object&&object.constructor;if(isArrLike){accumulator=isArr?new Ctor:[]}else if(isObject(object)){accumulator=isFunction(Ctor)?baseCreate(getPrototype(object)):{}}else{accumulator={}}}(isArrLike?arrayEach:baseForOwn)(object,function(value,index,object){return iteratee(accumulator,value,index,object)});return accumulator}module.exports=transform},{"./_arrayEach":64,"./_baseCreate":81,"./_baseForOwn":88,"./_baseIteratee":105,"./_getPrototype":164,"./isArray":243,"./isBuffer":246,"./isFunction":248,"./isObject":251,"./isTypedArray":257}],285:[function(require,module,exports){var baseFlatten=require("./_baseFlatten"),baseRest=require("./_baseRest"),baseUniq=require("./_baseUniq"),isArrayLikeObject=require("./isArrayLikeObject"); -/** - * Creates an array of unique values, in order, from all given arrays using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of combined values. - * @example - * - * _.union([2], [1, 2]); - * // => [2, 1] - */var union=baseRest(function(arrays){return baseUniq(baseFlatten(arrays,1,isArrayLikeObject,true))});module.exports=union},{"./_baseFlatten":86,"./_baseRest":121,"./_baseUniq":128,"./isArrayLikeObject":245}],286:[function(require,module,exports){var toString=require("./toString"); -/** Used to generate unique IDs. */var idCounter=0; -/** - * Generates a unique ID. If `prefix` is given, the ID is appended to it. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {string} [prefix=''] The value to prefix the ID with. - * @returns {string} Returns the unique ID. - * @example - * - * _.uniqueId('contact_'); - * // => 'contact_104' - * - * _.uniqueId(); - * // => '105' - */function uniqueId(prefix){var id=++idCounter;return toString(prefix)+id}module.exports=uniqueId},{"./toString":283}],287:[function(require,module,exports){var baseValues=require("./_baseValues"),keys=require("./keys"); -/** - * Creates an array of the own enumerable string keyed property values of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @since 0.1.0 - * @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 object==null?[]:baseValues(object,keys(object))}module.exports=values},{"./_baseValues":129,"./keys":259}],288:[function(require,module,exports){var assignValue=require("./_assignValue"),baseZipObject=require("./_baseZipObject"); -/** - * This method is like `_.fromPairs` except that it accepts two arrays, - * one of property identifiers and one of corresponding values. - * - * @static - * @memberOf _ - * @since 0.4.0 - * @category Array - * @param {Array} [props=[]] The property identifiers. - * @param {Array} [values=[]] The property values. - * @returns {Object} Returns the new object. - * @example - * - * _.zipObject(['a', 'b'], [1, 2]); - * // => { 'a': 1, 'b': 2 } - */function zipObject(props,values){return baseZipObject(props||[],values||[],assignValue)}module.exports=zipObject},{"./_assignValue":75,"./_baseZipObject":130}]},{},[1])(1)}); diff --git a/d2layouts/d2dagrelayout/dagre.js.br b/d2layouts/d2dagrelayout/dagre.js.br deleted file mode 100644 index df864b35ded5d8404b64410d279393e69751bfd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54030 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 diff --git a/d2layouts/d2dagrelayout/layout.go b/d2layouts/d2dagrelayout/layout.go index 870e0eb361..e07c4e357c 100644 --- a/d2layouts/d2dagrelayout/layout.go +++ b/d2layouts/d2dagrelayout/layout.go @@ -2,15 +2,11 @@ package d2dagrelayout import ( "context" - _ "embed" - "encoding/json" "fmt" "math" "sort" "strings" - "log/slog" - "github.com/d2lang/util-go/xdefer" "github.com/d2lang/util-go/go2" @@ -18,15 +14,11 @@ import ( "github.com/d2lang/d2/d2graph" "github.com/d2lang/d2/d2target" "github.com/d2lang/d2/lib/geo" - "github.com/d2lang/d2/lib/jsrunner" "github.com/d2lang/d2/lib/label" - "github.com/d2lang/d2/lib/log" "github.com/d2lang/d2/lib/shape" + "github.com/d2lang/dagro" ) -//go:embed setup.js -var setupJS string - const ( MIN_RANK_SEP = 60 EDGE_LABEL_GAP = 20 @@ -44,18 +36,6 @@ var DefaultOpts = ConfigurableOpts{ EdgeSep: 20, } -type DagreNode struct { - ID string `json:"id"` - X float64 `json:"x"` - Y float64 `json:"y"` - Width float64 `json:"width"` - Height float64 `json:"height"` -} - -type DagreEdge struct { - Points []*geo.Point `json:"points"` -} - type dagreOpts struct { // for a top to bottom graph: ranksep is y spacing, nodesep is x spacing, edgesep is x spacing ranksep int @@ -75,15 +55,6 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } defer xdefer.Errorf(&err, "failed to dagre layout") - debugJS := false - runner := jsrunner.NewJSRunner() - if _, err := runner.RunString(dagreJS); err != nil { - return err - } - if _, err := runner.RunString(setupJS); err != nil { - return err - } - rootAttrs := dagreOpts{ ConfigurableOpts: ConfigurableOpts{ EdgeSep: opts.EdgeSep, @@ -131,20 +102,28 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err // Note: non-containers have both of these as padding (rootAttrs.NodeSep + rootAttrs.EdgeSep) } - configJS := setGraphAttrs(rootAttrs) - if _, err := runner.RunString(configJS); err != nil { - return err - } - mapper := NewObjectMapper() for _, obj := range g.Objects { mapper.Register(obj) } - loadScript := "" + + dagreGraph := dagro.NewGraph(dagro.GraphOptions{Compound: true, Multigraph: true}).SetGraph(dagro.Attrs{ + "ranksep": float64(rootAttrs.ranksep), + "edgesep": float64(rootAttrs.EdgeSep), + "nodesep": float64(rootAttrs.NodeSep), + "rankdir": rootAttrs.rankdir, + }) for _, obj := range g.Objects { - loadScript += mapper.generateAddNodeLine(obj, int(obj.Width), int(obj.Height)) + id := mapper.ToID(obj) + dagreGraph.SetNode(id, dagro.Attrs{ + "id": id, + "width": float64(int(obj.Width)), + "height": float64(int(obj.Height)), + }) if obj.Parent != g.Root { - loadScript += mapper.generateAddParentLine(obj, obj.Parent) + if err := dagreGraph.SetParent(id, mapper.ToID(obj.Parent)); err != nil { + return err + } } } @@ -172,64 +151,70 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } } - loadScript += mapper.generateAddEdgeLine(src, dst, edge.AbsID(), width, height) + dagreGraph.SetEdge( + mapper.ToID(src), + mapper.ToID(dst), + dagro.Attrs{ + "width": float64(width), + "height": float64(height), + "labelpos": "c", + }, + edge.AbsID(), + ) } - if debugJS { - log.Debug(ctx, "script", slog.Any("all", setupJS+configJS+loadScript)) - } - - if _, err := runner.RunString(loadScript); err != nil { + if err := dagro.Layout(dagreGraph); err != nil { return err } - if _, err := runner.RunString(`dagre.layout(g)`); err != nil { - if debugJS { - log.Warn(ctx, "layout error", slog.Any("err", err)) + for _, id := range dagreGraph.Nodes() { + dn, ok := dagreGraph.Node(id).(dagro.Attrs) + if !ok { + return fmt.Errorf("dagro returned invalid node label for %q", id) } - return err - } - - for i := range g.Objects { - val, err := runner.RunString(fmt.Sprintf("JSON.stringify(g.node(g.nodes()[%d]))", i)) - if err != nil { - return err + dnID, ok := dn["id"].(string) + if !ok { + return fmt.Errorf("dagro returned node %q without an id", id) } - var dn DagreNode - if err := json.Unmarshal([]byte(val.String()), &dn); err != nil { - return err + obj := mapper.ToObj(dnID) + if obj == nil { + return fmt.Errorf("dagro returned unknown node id %q", dnID) } - if debugJS { - log.Debug(ctx, "graph", slog.Any("json", dn)) + x, xOK := dn["x"].(float64) + y, yOK := dn["y"].(float64) + width, widthOK := dn["width"].(float64) + height, heightOK := dn["height"].(float64) + if !xOK || !yOK || !widthOK || !heightOK { + return fmt.Errorf("dagro returned invalid geometry for node %q", id) } - obj := mapper.ToObj(dn.ID) - // dagre gives center of node - obj.TopLeft = geo.NewPoint(math.Round(dn.X-dn.Width/2), math.Round(dn.Y-dn.Height/2)) - obj.Width = math.Ceil(dn.Width) - obj.Height = math.Ceil(dn.Height) + obj.TopLeft = geo.NewPoint(math.Round(x-width/2), math.Round(y-height/2)) + obj.Width = math.Ceil(width) + obj.Height = math.Ceil(height) } + dagreEdges := dagreGraph.Edges() + if len(dagreEdges) != len(g.Edges) { + return fmt.Errorf("dagro returned %d edges, expected %d", len(dagreEdges), len(g.Edges)) + } for i, edge := range g.Edges { - val, err := runner.RunString(fmt.Sprintf("JSON.stringify(g.edge(g.edges()[%d]))", i)) - if err != nil { - return err + de, ok := dagreGraph.Edge(dagreEdges[i]).(dagro.Attrs) + if !ok { + return fmt.Errorf("dagro returned invalid edge label for %q", dagreEdges[i].Name) } - var de DagreEdge - if err := json.Unmarshal([]byte(val.String()), &de); err != nil { - return err - } - if debugJS { - log.Debug(ctx, "graph", slog.Any("json", de)) + dagrePoints, ok := de["points"].([]dagro.Point) + if !ok { + return fmt.Errorf("dagro returned edge %q without points", dagreEdges[i].Name) } - points := make([]*geo.Point, len(de.Points)) - for i := range de.Points { + points := make([]*geo.Point, len(dagrePoints)) + for i, point := range dagrePoints { + p := geo.NewPoint(point.X, point.Y) if edge.SrcArrow && !edge.DstArrow { - points[len(de.Points)-i-1] = de.Points[i].Copy() + points[len(dagrePoints)-i-1] = p } else { - points[i] = de.Points[i].Copy() + points[i] = p } } @@ -394,21 +379,6 @@ func getEdgeEndpoints(g *d2graph.Graph, edge *d2graph.Edge) (*d2graph.Object, *d return src, dst } -func setGraphAttrs(attrs dagreOpts) string { - return fmt.Sprintf(`g.setGraph({ - ranksep: %d, - edgesep: %d, - nodesep: %d, - rankdir: "%s", -}); -`, - attrs.ranksep, - attrs.ConfigurableOpts.EdgeSep, - attrs.ConfigurableOpts.NodeSep, - attrs.rankdir, - ) -} - // getLongestEdgeChainHead finds the longest chain in a container and gets its head // If there are multiple chains of the same length, get the head closest to the center func getLongestEdgeChainHead(g *d2graph.Graph, container *d2graph.Object) *d2graph.Object { diff --git a/d2layouts/d2dagrelayout/layout_embed.go b/d2layouts/d2dagrelayout/layout_embed.go deleted file mode 100644 index 9426817bef..0000000000 --- a/d2layouts/d2dagrelayout/layout_embed.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !js || !wasm - -package d2dagrelayout - -import ( - _ "embed" -) - -//go:embed dagre.js -var dagreJS string diff --git a/d2layouts/d2dagrelayout/layout_embed_wasm.go b/d2layouts/d2dagrelayout/layout_embed_wasm.go deleted file mode 100644 index 40db10a994..0000000000 --- a/d2layouts/d2dagrelayout/layout_embed_wasm.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build js && wasm - -package d2dagrelayout - -import ( - _ "embed" - "fmt" - - "github.com/d2lang/d2/lib/compression" -) - -//go:embed dagre.js.br -var dagreJSBr []byte - -var dagreJS string - -func init() { - // Decompress Dagre JS for WASM builds - var err error - dagreJS, err = compression.DecompressBrotli(dagreJSBr) - if err != nil { - panic(fmt.Sprintf("Failed to decompress Dagre JS: %v", err)) - } -} diff --git a/d2layouts/d2dagrelayout/object_mapper.go b/d2layouts/d2dagrelayout/object_mapper.go index eb5f17615e..ab00774f6e 100644 --- a/d2layouts/d2dagrelayout/object_mapper.go +++ b/d2layouts/d2dagrelayout/object_mapper.go @@ -1,10 +1,7 @@ package d2dagrelayout import ( - "fmt" - "regexp" "strconv" - "strings" "github.com/d2lang/d2/d2graph" ) @@ -34,30 +31,3 @@ func (c *objectMapper) ToID(obj *d2graph.Object) string { func (c *objectMapper) ToObj(id string) *d2graph.Object { return c.idToObj[id] } - -func (c objectMapper) generateAddNodeLine(obj *d2graph.Object, width, height int) string { - id := c.ToID(obj) - return fmt.Sprintf("g.setNode(`%s`, { id: `%s`, width: %d, height: %d });\n", id, id, width, height) -} - -func (c objectMapper) generateAddParentLine(child, parent *d2graph.Object) string { - return fmt.Sprintf("g.setParent(`%s`, `%s`);\n", c.ToID(child), c.ToID(parent)) -} - -func (c objectMapper) generateAddEdgeLine(from, to *d2graph.Object, edgeID string, width, height int) string { - return fmt.Sprintf( - "g.setEdge({v:`%s`, w:`%s`, name:`%s`}, { width:%d, height:%d, labelpos: `c` });\n", - c.ToID(from), c.ToID(to), escapeID(edgeID), width, height, - ) -} - -func escapeID(id string) string { - // fixes \\ - id = strings.ReplaceAll(id, "\\", `\\`) - // replaces \n with \\n whenever \n is not preceded by \ (does not replace \\n) - re := regexp.MustCompile(`[^\\]\n`) - id = re.ReplaceAllString(id, `\\n`) - // avoid an unescaped \r becoming a \n in the layout result - id = strings.ReplaceAll(id, "\r", `\r`) - return id -} diff --git a/d2layouts/d2dagrelayout/setup.js b/d2layouts/d2dagrelayout/setup.js deleted file mode 100644 index 300901e77b..0000000000 --- a/d2layouts/d2dagrelayout/setup.js +++ /dev/null @@ -1,7 +0,0 @@ -var g = new dagre.graphlib.Graph({ compound: true, multigraph: true }); -g.setDefaultNodeLabel(function () { - return {}; -}); -g.setDefaultEdgeLabel(function () { - return {}; -}); diff --git a/d2plugin/plugin_dagre.go b/d2plugin/plugin_dagre.go index af78b4e5cb..75a3369ee8 100644 --- a/d2plugin/plugin_dagre.go +++ b/d2plugin/plugin_dagre.go @@ -75,9 +75,11 @@ func (p *dagrePlugin) Info(ctx context.Context) (*PluginInfo, error) { Type: "bundled", Features: []PluginFeature{}, ShortHelp: "The directed graph layout library Dagre", - LongHelp: fmt.Sprintf(`dagre is a directed graph layout library for JavaScript. + LongHelp: fmt.Sprintf(`dagre is a directed graph layout algorithm implemented natively in Go by Dagro. See https://d2lang.com/tour/dagre for more. +Dagro is a behavior-compatible port of Dagre 0.8.5: https://github.com/d2lang/dagro. + Flags correspond to ones found at https://github.com/dagrejs/dagre/wiki. Flags: diff --git a/go.mod b/go.mod index a73a3b7ec2..e3326e0adc 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/alecthomas/chroma/v2 v2.14.0 github.com/andybalholm/brotli v1.2.0 github.com/coder/websocket v1.8.12 + github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205 github.com/d2lang/util-go v0.2.0 github.com/dop251/goja v0.0.0-20240927123429-241b342198c2 github.com/dsoprea/go-exif/v3 v3.0.1 diff --git a/go.sum b/go.sum index 2c1dee3aa8..d650a9d8cb 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3C github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205 h1:GBCPRoyoxtd5l0T42IZGcGbJJQR8VR8YmHwZAZ6FW4Y= +github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205/go.mod h1:GYboiXSkXU1tuj7jYRXD8+lvHJBBZk3SAbfVT6qJsLU= github.com/d2lang/util-go v0.2.0 h1:X9+F4j2S0453cG3EpA5bm9KBEV4ZAanxH+5ELA2yPDk= github.com/d2lang/util-go v0.2.0/go.mod h1:9t8cKlmsQw6UlChU4HQE9tZr8efjKIGDHkDdDYUeJy0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From e1faa6a5dfc8c3da8d14cb48c31952aaa6964c66 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sat, 8 Aug 2026 10:50:58 -0700 Subject: [PATCH 2/3] release: ship Dagro license notices --- LICENSE.txt | 2 +- THIRD_PARTY_NOTICES.txt | 38 +++ ci/release/_build.sh | 1 + ci/release/build.sh | 1 + ci/release/windows/.gitignore | 1 + ci/release/windows/d2.wxs | 4 + d2js/js/LICENSE.txt | 375 +++++++++++++++++++++++++++++ d2js/js/THIRD_PARTY_NOTICES.txt | 38 +++ d2js/js/ci/build.sh | 16 ++ d2js/js/package.json | 4 +- d2layouts/d2dagrelayout/NOTICE.txt | 5 +- go.mod | 2 +- go.sum | 4 +- 13 files changed, 484 insertions(+), 7 deletions(-) create mode 100644 THIRD_PARTY_NOTICES.txt create mode 100644 d2js/js/LICENSE.txt create mode 100644 d2js/js/THIRD_PARTY_NOTICES.txt diff --git a/LICENSE.txt b/LICENSE.txt index cfaf2c6df0..c72430ef7f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -372,4 +372,4 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. \ No newline at end of file + defined by the Mozilla Public License, v. 2.0. diff --git a/THIRD_PARTY_NOTICES.txt b/THIRD_PARTY_NOTICES.txt new file mode 100644 index 0000000000..99f4bb07af --- /dev/null +++ b/THIRD_PARTY_NOTICES.txt @@ -0,0 +1,38 @@ +D2 Third-Party Notices + +Dagro +https://github.com/d2lang/dagro + +Dagro is a Go port of Dagre 0.8.5 and the subset of Graphlib 2.1.8 required by +Dagre's layout implementation. The port is based on these upstream sources: + + Dagre 0.8.5 + https://github.com/dagrejs/dagre + commit f56edb1abbb8530e532158f7cbd403228f5b0018 + + Graphlib 2.1.8 + https://github.com/dagrejs/graphlib + commit 64375bb8d96bce0d906d238853c2b5afa2f2c231 + +MIT License + +Copyright (c) 2012-2014 Chris Pettitt +Copyright (c) 2026 Dagro contributors + +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. diff --git a/ci/release/_build.sh b/ci/release/_build.sh index 2fc1c5a76b..28fc3d5fe2 100755 --- a/ci/release/_build.sh +++ b/ci/release/_build.sh @@ -6,6 +6,7 @@ cd -- "$(dirname "$0")/../.." sh_c rm -Rf "$HW_BUILD_DIR" sh_c mkdir -p "$HW_BUILD_DIR" sh_c cp ./ci/release/template/LICENSE.txt "$HW_BUILD_DIR" +sh_c cp ./THIRD_PARTY_NOTICES.txt "$HW_BUILD_DIR" sh_c cp ./ci/release/template/Makefile "$HW_BUILD_DIR" sh_c cp -R ./ci/release/template/man "$HW_BUILD_DIR" sh_c cp -R ./ci/release/template/scripts "$HW_BUILD_DIR" diff --git a/ci/release/build.sh b/ci/release/build.sh index db21a186f6..be62fd6730 100755 --- a/ci/release/build.sh +++ b/ci/release/build.sh @@ -155,6 +155,7 @@ build_windows_msi() { REMOTE_HOST=$CI_D2_WINDOWS_AMD64 ln -sf "../build/$VERSION/windows-amd64/d2-$VERSION/bin/d2.exe" ./ci/release/windows/d2.exe + ln -sf "../build/$VERSION/windows-amd64/d2-$VERSION/THIRD_PARTY_NOTICES.txt" ./ci/release/windows/THIRD_PARTY_NOTICES.txt sh_c rsync --archive --human-readable --copy-links --delete ./ci/release/windows/ "'$REMOTE_HOST:windows/'" if ! echo "$VERSION" | grep '[0-9]\.[0-9]\.[0-9]'; then WIX_VERSION=0.0.0 diff --git a/ci/release/windows/.gitignore b/ci/release/windows/.gitignore index 55ae023fcb..717caf094c 100644 --- a/ci/release/windows/.gitignore +++ b/ci/release/windows/.gitignore @@ -1 +1,2 @@ d2.exe +THIRD_PARTY_NOTICES.txt diff --git a/ci/release/windows/d2.wxs b/ci/release/windows/d2.wxs index 1b7b466316..779f79c4fc 100644 --- a/ci/release/windows/d2.wxs +++ b/ci/release/windows/d2.wxs @@ -16,6 +16,7 @@ This file was pieced together from: + @@ -33,6 +34,9 @@ This file was pieced together from: System="yes" Value="[INSTALLDIR]" /> + + + diff --git a/d2js/js/LICENSE.txt b/d2js/js/LICENSE.txt new file mode 100644 index 0000000000..c72430ef7f --- /dev/null +++ b/d2js/js/LICENSE.txt @@ -0,0 +1,375 @@ +Copyright 2022 Terrastruct Inc. + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/d2js/js/THIRD_PARTY_NOTICES.txt b/d2js/js/THIRD_PARTY_NOTICES.txt new file mode 100644 index 0000000000..99f4bb07af --- /dev/null +++ b/d2js/js/THIRD_PARTY_NOTICES.txt @@ -0,0 +1,38 @@ +D2 Third-Party Notices + +Dagro +https://github.com/d2lang/dagro + +Dagro is a Go port of Dagre 0.8.5 and the subset of Graphlib 2.1.8 required by +Dagre's layout implementation. The port is based on these upstream sources: + + Dagre 0.8.5 + https://github.com/dagrejs/dagre + commit f56edb1abbb8530e532158f7cbd403228f5b0018 + + Graphlib 2.1.8 + https://github.com/dagrejs/graphlib + commit 64375bb8d96bce0d906d238853c2b5afa2f2c231 + +MIT License + +Copyright (c) 2012-2014 Chris Pettitt +Copyright (c) 2026 Dagro contributors + +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. diff --git a/d2js/js/ci/build.sh b/d2js/js/ci/build.sh index 98419ed009..aa0ae674c2 100755 --- a/d2js/js/ci/build.sh +++ b/d2js/js/ci/build.sh @@ -4,6 +4,14 @@ set -eu cd -- "$(dirname "$0")/.." cd ../.. +if ! cmp -s ./LICENSE.txt ./d2js/js/LICENSE.txt; then + echoerr "d2js/js/LICENSE.txt is out of sync with the repository license" + exit 1 +fi +if ! cmp -s ./THIRD_PARTY_NOTICES.txt ./d2js/js/THIRD_PARTY_NOTICES.txt; then + echoerr "d2js/js/THIRD_PARTY_NOTICES.txt is out of sync with the repository notice" + exit 1 +fi if [ -n "${NPM_VERSION:-}" ]; then JS_VERSION="$NPM_VERSION" else @@ -188,6 +196,14 @@ EOF echoerr "npm pack did not return complete metadata for ${package_name}" exit 1 fi + if ! tar -xOzf "$PACK_DIR/$pack_filename" package/LICENSE.txt | cmp - LICENSE.txt; then + echoerr "${package_name} package does not contain the repository license" + exit 1 + fi + if ! tar -xOzf "$PACK_DIR/$pack_filename" package/THIRD_PARTY_NOTICES.txt | cmp - THIRD_PARTY_NOTICES.txt; then + echoerr "${package_name} package does not contain the third-party notices" + exit 1 + fi case "$package_name" in @d2lang/d2) diff --git a/d2js/js/package.json b/d2js/js/package.json index d9c6a61cbf..ab39669a30 100644 --- a/d2js/js/package.json +++ b/d2js/js/package.json @@ -35,7 +35,9 @@ }, "files": [ "dist", - "index.d.ts" + "index.d.ts", + "LICENSE.txt", + "THIRD_PARTY_NOTICES.txt" ], "types": "./index.d.ts", "scripts": { diff --git a/d2layouts/d2dagrelayout/NOTICE.txt b/d2layouts/d2dagrelayout/NOTICE.txt index 64125d6883..b885c51d27 100644 --- a/d2layouts/d2dagrelayout/NOTICE.txt +++ b/d2layouts/d2dagrelayout/NOTICE.txt @@ -1,5 +1,6 @@ D2's Dagre layout uses Dagro, a native Go port of Dagre 0.8.5: https://github.com/d2lang/dagro -Dagro preserves the MIT attribution and license for Dagre and Graphlib in its -LICENSE and NOTICE files. +The complete Dagro, Dagre, and Graphlib attribution and MIT license text is in +../../THIRD_PARTY_NOTICES.txt. D2 includes that file in its native, MSI, and +npm/WASM release artifacts. diff --git a/go.mod b/go.mod index e3326e0adc..289f1e39ff 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/alecthomas/chroma/v2 v2.14.0 github.com/andybalholm/brotli v1.2.0 github.com/coder/websocket v1.8.12 - github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205 + github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c github.com/d2lang/util-go v0.2.0 github.com/dop251/goja v0.0.0-20240927123429-241b342198c2 github.com/dsoprea/go-exif/v3 v3.0.1 diff --git a/go.sum b/go.sum index d650a9d8cb..07fb3299ff 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3C github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205 h1:GBCPRoyoxtd5l0T42IZGcGbJJQR8VR8YmHwZAZ6FW4Y= -github.com/d2lang/dagro v0.0.0-20260808053601-40eebd4e6205/go.mod h1:GYboiXSkXU1tuj7jYRXD8+lvHJBBZk3SAbfVT6qJsLU= +github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c h1:yMMay3TY6L4rB63XotVb9qnBuHAYh6UCAS4S6zRv3GU= +github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c/go.mod h1:GYboiXSkXU1tuj7jYRXD8+lvHJBBZk3SAbfVT6qJsLU= github.com/d2lang/util-go v0.2.0 h1:X9+F4j2S0453cG3EpA5bm9KBEV4ZAanxH+5ELA2yPDk= github.com/d2lang/util-go v0.2.0/go.mod h1:9t8cKlmsQw6UlChU4HQE9tZr8efjKIGDHkDdDYUeJy0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From b83487e78379a062557844a5fbd1040cfb5b594c Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sat, 8 Aug 2026 11:05:56 -0700 Subject: [PATCH 3/3] go: pin dagro v0.1.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 289f1e39ff..65192cc4fb 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/alecthomas/chroma/v2 v2.14.0 github.com/andybalholm/brotli v1.2.0 github.com/coder/websocket v1.8.12 - github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c + github.com/d2lang/dagro v0.1.0 github.com/d2lang/util-go v0.2.0 github.com/dop251/goja v0.0.0-20240927123429-241b342198c2 github.com/dsoprea/go-exif/v3 v3.0.1 diff --git a/go.sum b/go.sum index 07fb3299ff..0985344506 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3C github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c h1:yMMay3TY6L4rB63XotVb9qnBuHAYh6UCAS4S6zRv3GU= -github.com/d2lang/dagro v0.0.0-20260808174325-2c6cb448da0c/go.mod h1:GYboiXSkXU1tuj7jYRXD8+lvHJBBZk3SAbfVT6qJsLU= +github.com/d2lang/dagro v0.1.0 h1:517f9fzr6p1eN5TdUXjUGy9DKZnHhPIScWOsmN0ot4w= +github.com/d2lang/dagro v0.1.0/go.mod h1:GYboiXSkXU1tuj7jYRXD8+lvHJBBZk3SAbfVT6qJsLU= github.com/d2lang/util-go v0.2.0 h1:X9+F4j2S0453cG3EpA5bm9KBEV4ZAanxH+5ELA2yPDk= github.com/d2lang/util-go v0.2.0/go.mod h1:9t8cKlmsQw6UlChU4HQE9tZr8efjKIGDHkDdDYUeJy0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=