08-27-周三_17-09-29
This commit is contained in:
19
node_modules/dagre-layout/LICENSE
generated
vendored
Normal file
19
node_modules/dagre-layout/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2018 Tyler Long
|
||||
|
||||
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.
|
53
node_modules/dagre-layout/README.md
generated
vendored
Normal file
53
node_modules/dagre-layout/README.md
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# dagre-layout - Graph layout for JavaScript
|
||||
|
||||
[](http://travis-ci.org/tylingsoft/dagre-layout)
|
||||
[](https://coveralls.io/github/tylingsoft/dagre-layout?branch=master)
|
||||
|
||||
This project is an out-of-box replacement for [dagre](https://github.com/dagrejs/dagre).
|
||||
|
||||
This project isn't built from scratch. It's based on the original [dagre](https://github.com/dagrejs/dagre) project.
|
||||
|
||||
Dagre is a JavaScript library that makes it easy to lay out directed graphs on the client-side.
|
||||
|
||||
For more details, including examples and configuration options, please see our [wiki](https://github.com/dagrejs/dagre/wiki).
|
||||
|
||||
|
||||
## Changes compared to dagrejs/dagre
|
||||
|
||||
- Upgrade all the dependencies (loadash 3 => 4)
|
||||
- Yarn instead of NPM
|
||||
- Get rid of PhantomJS
|
||||
- ES6 instead of ES5
|
||||
- Use webpack instead of browserify
|
||||
- Use JavaScript Standard Style instead of JSHint
|
||||
- Use Jest for testing
|
||||
- Add test coverage report
|
||||
- Remove Bower support
|
||||
- Use 0 instead of `Number.NEGATIVE_INFINITY`
|
||||
- Git ignore auto-generated code
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
|
||||
## Test
|
||||
|
||||
```
|
||||
yarn test
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
dagre-layout is licensed under the terms of the MIT License. See the LICENSE file for details.
|
2
node_modules/dagre-layout/dist/dagre-layout.core.js
generated
vendored
Normal file
2
node_modules/dagre-layout/dist/dagre-layout.core.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/dagre-layout/dist/dagre-layout.core.js.map
generated
vendored
Normal file
1
node_modules/dagre-layout/dist/dagre-layout.core.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
10
node_modules/dagre-layout/dist/dagre-layout.js
generated
vendored
Normal file
10
node_modules/dagre-layout/dist/dagre-layout.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/dagre-layout/dist/dagre-layout.js.map
generated
vendored
Normal file
1
node_modules/dagre-layout/dist/dagre-layout.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
5
node_modules/dagre-layout/index.js
generated
vendored
Normal file
5
node_modules/dagre-layout/index.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import layout from './lib/layout'
|
||||
|
||||
export default {
|
||||
layout
|
||||
}
|
66
node_modules/dagre-layout/lib/acyclic.js
generated
vendored
Normal file
66
node_modules/dagre-layout/lib/acyclic.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import greedyFAS from './greedy-fas'
|
||||
|
||||
function run (g) {
|
||||
const fas = (g.graph().acyclicer === 'greedy'
|
||||
? greedyFAS(g, weightFn(g))
|
||||
: dfsFAS(g))
|
||||
_.forEach(fas, function (e) {
|
||||
const label = g.edge(e)
|
||||
g.removeEdge(e)
|
||||
label.forwardName = e.name
|
||||
label.reversed = true
|
||||
g.setEdge(e.w, e.v, label, _.uniqueId('rev'))
|
||||
})
|
||||
|
||||
function weightFn (g) {
|
||||
return function (e) {
|
||||
return g.edge(e).weight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dfsFAS (g) {
|
||||
const fas = []
|
||||
const stack = {}
|
||||
const visited = {}
|
||||
|
||||
function dfs (v) {
|
||||
if (_.has(visited, v)) {
|
||||
return
|
||||
}
|
||||
visited[v] = true
|
||||
stack[v] = true
|
||||
_.forEach(g.outEdges(v), function (e) {
|
||||
if (_.has(stack, e.w)) {
|
||||
fas.push(e)
|
||||
} else {
|
||||
dfs(e.w)
|
||||
}
|
||||
})
|
||||
delete stack[v]
|
||||
}
|
||||
|
||||
_.forEach(g.nodes(), dfs)
|
||||
return fas
|
||||
}
|
||||
|
||||
function undo (g) {
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const label = g.edge(e)
|
||||
if (label.reversed) {
|
||||
g.removeEdge(e)
|
||||
|
||||
const forwardName = label.forwardName
|
||||
delete label.reversed
|
||||
delete label.forwardName
|
||||
g.setEdge(e.w, e.v, label, forwardName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
run,
|
||||
undo
|
||||
}
|
39
node_modules/dagre-layout/lib/add-border-segments.js
generated
vendored
Normal file
39
node_modules/dagre-layout/lib/add-border-segments.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from './util'
|
||||
|
||||
function addBorderSegments (g) {
|
||||
function dfs (v) {
|
||||
const children = g.children(v)
|
||||
const node = g.node(v)
|
||||
if (children.length) {
|
||||
_.forEach(children, dfs)
|
||||
}
|
||||
|
||||
if (_.has(node, 'minRank')) {
|
||||
node.borderLeft = []
|
||||
node.borderRight = []
|
||||
for (let rank = node.minRank, maxRank = node.maxRank + 1;
|
||||
rank < maxRank;
|
||||
++rank) {
|
||||
addBorderNode(g, 'borderLeft', '_bl', v, node, rank)
|
||||
addBorderNode(g, 'borderRight', '_br', v, node, rank)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_.forEach(g.children(), dfs)
|
||||
}
|
||||
|
||||
function addBorderNode (g, prop, prefix, sg, sgNode, rank) {
|
||||
const label = { width: 0, height: 0, rank: rank, borderType: prop }
|
||||
const prev = sgNode[prop][rank - 1]
|
||||
const curr = util.addDummyNode(g, 'border', label, prefix)
|
||||
sgNode[prop][rank] = curr
|
||||
g.setParent(curr, sg)
|
||||
if (prev) {
|
||||
g.setEdge(prev, curr, { weight: 1 })
|
||||
}
|
||||
}
|
||||
|
||||
export default addBorderSegments
|
70
node_modules/dagre-layout/lib/coordinate-system.js
generated
vendored
Normal file
70
node_modules/dagre-layout/lib/coordinate-system.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
function adjust (g) {
|
||||
const rankDir = g.graph().rankdir.toLowerCase()
|
||||
if (rankDir === 'lr' || rankDir === 'rl') {
|
||||
swapWidthHeight(g)
|
||||
}
|
||||
}
|
||||
|
||||
function undo (g) {
|
||||
const rankDir = g.graph().rankdir.toLowerCase()
|
||||
if (rankDir === 'bt' || rankDir === 'rl') {
|
||||
reverseY(g)
|
||||
}
|
||||
|
||||
if (rankDir === 'lr' || rankDir === 'rl') {
|
||||
swapXY(g)
|
||||
swapWidthHeight(g)
|
||||
}
|
||||
}
|
||||
|
||||
function swapWidthHeight (g) {
|
||||
_.forEach(g.nodes(), function (v) { swapWidthHeightOne(g.node(v)) })
|
||||
_.forEach(g.edges(), function (e) { swapWidthHeightOne(g.edge(e)) })
|
||||
}
|
||||
|
||||
function swapWidthHeightOne (attrs) {
|
||||
const w = attrs.width
|
||||
attrs.width = attrs.height
|
||||
attrs.height = w
|
||||
}
|
||||
|
||||
function reverseY (g) {
|
||||
_.forEach(g.nodes(), function (v) { reverseYOne(g.node(v)) })
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const edge = g.edge(e)
|
||||
_.forEach(edge.points, reverseYOne)
|
||||
if (_.has(edge, 'y')) {
|
||||
reverseYOne(edge)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function reverseYOne (attrs) {
|
||||
attrs.y = -attrs.y
|
||||
}
|
||||
|
||||
function swapXY (g) {
|
||||
_.forEach(g.nodes(), function (v) { swapXYOne(g.node(v)) })
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const edge = g.edge(e)
|
||||
_.forEach(edge.points, swapXYOne)
|
||||
if (_.has(edge, 'x')) {
|
||||
swapXYOne(edge)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function swapXYOne (attrs) {
|
||||
const x = attrs.x
|
||||
attrs.x = attrs.y
|
||||
attrs.y = x
|
||||
}
|
||||
|
||||
export default {
|
||||
adjust,
|
||||
undo
|
||||
}
|
56
node_modules/dagre-layout/lib/data/list.js
generated
vendored
Normal file
56
node_modules/dagre-layout/lib/data/list.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Simple doubly linked list implementation derived from Cormen, et al.,
|
||||
* "Introduction to Algorithms".
|
||||
*/
|
||||
|
||||
function List () {
|
||||
const sentinel = {}
|
||||
sentinel._next = sentinel._prev = sentinel
|
||||
this._sentinel = sentinel
|
||||
}
|
||||
|
||||
List.prototype.dequeue = function () {
|
||||
const sentinel = this._sentinel
|
||||
const entry = sentinel._prev
|
||||
if (entry !== sentinel) {
|
||||
unlink(entry)
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
List.prototype.enqueue = function (entry) {
|
||||
const sentinel = this._sentinel
|
||||
if (entry._prev && entry._next) {
|
||||
unlink(entry)
|
||||
}
|
||||
entry._next = sentinel._next
|
||||
sentinel._next._prev = entry
|
||||
sentinel._next = entry
|
||||
entry._prev = sentinel
|
||||
}
|
||||
|
||||
List.prototype.toString = function () {
|
||||
const strs = []
|
||||
const sentinel = this._sentinel
|
||||
let curr = sentinel._prev
|
||||
while (curr !== sentinel) {
|
||||
strs.push(JSON.stringify(curr, filterOutLinks))
|
||||
curr = curr._prev
|
||||
}
|
||||
return '[' + strs.join(', ') + ']'
|
||||
}
|
||||
|
||||
function unlink (entry) {
|
||||
entry._prev._next = entry._next
|
||||
entry._next._prev = entry._prev
|
||||
delete entry._next
|
||||
delete entry._prev
|
||||
}
|
||||
|
||||
function filterOutLinks (k, v) {
|
||||
if (k !== '_next' && k !== '_prev') {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
export default List
|
35
node_modules/dagre-layout/lib/debug.js
generated
vendored
Normal file
35
node_modules/dagre-layout/lib/debug.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import util from './util'
|
||||
|
||||
/* istanbul ignore next */
|
||||
function debugOrdering (g) {
|
||||
const layerMatrix = util.buildLayerMatrix(g)
|
||||
|
||||
const h = new Graph({ compound: true, multigraph: true }).setGraph({})
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
h.setNode(v, { label: v })
|
||||
h.setParent(v, 'layer' + g.node(v).rank)
|
||||
})
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
h.setEdge(e.v, e.w, {}, e.name)
|
||||
})
|
||||
|
||||
_.forEach(layerMatrix, function (layer, i) {
|
||||
const layerV = 'layer' + i
|
||||
h.setNode(layerV, { rank: 'same' })
|
||||
_.reduce(layer, function (u, v) {
|
||||
h.setEdge(u, v, { style: 'invis' })
|
||||
return v
|
||||
})
|
||||
})
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
export default {
|
||||
debugOrdering
|
||||
}
|
120
node_modules/dagre-layout/lib/greedy-fas.js
generated
vendored
Normal file
120
node_modules/dagre-layout/lib/greedy-fas.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import List from './data/list'
|
||||
|
||||
/*
|
||||
* A greedy heuristic for finding a feedback arc set for a graph. A feedback
|
||||
* arc set is a set of edges that can be removed to make a graph acyclic.
|
||||
* The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
|
||||
* effective heuristic for the feedback arc set problem." This implementation
|
||||
* adjusts that from the paper to allow for weighted edges.
|
||||
*/
|
||||
|
||||
const DEFAULT_WEIGHT_FN = _.constant(1)
|
||||
|
||||
function greedyFAS (g, weightFn) {
|
||||
if (g.nodeCount() <= 1) {
|
||||
return []
|
||||
}
|
||||
const state = buildState(g, weightFn || DEFAULT_WEIGHT_FN)
|
||||
const results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx)
|
||||
|
||||
// Expand multi-edges
|
||||
return _.flatten(_.map(results, function (e) {
|
||||
return g.outEdges(e.v, e.w)
|
||||
}), true)
|
||||
}
|
||||
|
||||
function doGreedyFAS (g, buckets, zeroIdx) {
|
||||
let results = []
|
||||
const sources = buckets[buckets.length - 1]
|
||||
const sinks = buckets[0]
|
||||
|
||||
let entry
|
||||
while (g.nodeCount()) {
|
||||
while ((entry = sinks.dequeue())) { removeNode(g, buckets, zeroIdx, entry) }
|
||||
while ((entry = sources.dequeue())) { removeNode(g, buckets, zeroIdx, entry) }
|
||||
if (g.nodeCount()) {
|
||||
for (let i = buckets.length - 2; i > 0; --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) {
|
||||
const results = collectPredecessors ? [] : undefined
|
||||
|
||||
_.forEach(g.inEdges(entry.v), function (edge) {
|
||||
const weight = g.edge(edge)
|
||||
const 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) {
|
||||
const weight = g.edge(edge)
|
||||
const w = edge.w
|
||||
const wEntry = g.node(w)
|
||||
wEntry['in'] -= weight
|
||||
assignBucket(buckets, zeroIdx, wEntry)
|
||||
})
|
||||
|
||||
g.removeNode(entry.v)
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
function buildState (g, weightFn) {
|
||||
const fasGraph = new Graph()
|
||||
let maxIn = 0
|
||||
let 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) {
|
||||
const prevWeight = fasGraph.edge(e.v, e.w) || 0
|
||||
const weight = weightFn(e)
|
||||
const 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)
|
||||
})
|
||||
|
||||
const buckets = _.range(maxOut + maxIn + 3).map(function () { return new List() })
|
||||
const 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)
|
||||
}
|
||||
}
|
||||
|
||||
export default greedyFAS
|
394
node_modules/dagre-layout/lib/layout.js
generated
vendored
Normal file
394
node_modules/dagre-layout/lib/layout.js
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import acyclic from './acyclic'
|
||||
import normalize from './normalize'
|
||||
import rank from './rank'
|
||||
import util, { normalizeRanks, removeEmptyRanks } from './util'
|
||||
import parentDummyChains from './parent-dummy-chains'
|
||||
import nestingGraph from './nesting-graph'
|
||||
import addBorderSegments from './add-border-segments'
|
||||
import coordinateSystem from './coordinate-system'
|
||||
import order from './order'
|
||||
import position from './position'
|
||||
|
||||
function layout (g, opts) {
|
||||
const time = opts && opts.debugTiming ? util.time : util.notime
|
||||
time('layout', function () {
|
||||
const 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) {
|
||||
const inputLabel = inputGraph.node(v)
|
||||
const 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) {
|
||||
const inputLabel = inputGraph.edge(e)
|
||||
const 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
|
||||
}
|
||||
|
||||
const graphNumAttrs = ['nodesep', 'edgesep', 'ranksep', 'marginx', 'marginy']
|
||||
const graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: 'tb' }
|
||||
const graphAttrs = ['acyclicer', 'ranker', 'rankdir', 'align']
|
||||
const nodeNumAttrs = ['width', 'height']
|
||||
const nodeDefaults = { width: 0, height: 0 }
|
||||
const edgeNumAttrs = ['minlen', 'weight', 'width', 'height', 'labeloffset']
|
||||
const edgeDefaults = {
|
||||
minlen: 1,
|
||||
weight: 1,
|
||||
width: 0,
|
||||
height: 0,
|
||||
labeloffset: 10,
|
||||
labelpos: 'r'
|
||||
}
|
||||
const 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) {
|
||||
const g = new Graph({ multigraph: true, compound: true })
|
||||
const graph = canonicalize(inputGraph.graph())
|
||||
|
||||
g.setGraph(_.merge({},
|
||||
graphDefaults,
|
||||
selectNumberAttrs(graph, graphNumAttrs),
|
||||
_.pick(graph, graphAttrs)))
|
||||
|
||||
_.forEach(inputGraph.nodes(), function (v) {
|
||||
const node = canonicalize(inputGraph.node(v))
|
||||
g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults))
|
||||
g.setParent(v, inputGraph.parent(v))
|
||||
})
|
||||
|
||||
_.forEach(inputGraph.edges(), function (e) {
|
||||
const 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) {
|
||||
const graph = g.graph()
|
||||
graph.ranksep /= 2
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const 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) {
|
||||
const edge = g.edge(e)
|
||||
if (edge.width && edge.height) {
|
||||
const v = g.node(e.v)
|
||||
const w = g.node(e.w)
|
||||
const label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e }
|
||||
util.addDummyNode(g, 'edge-proxy', label, '_ep')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function assignRankMinMax (g) {
|
||||
let maxRank = 0
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
if (node.borderTop) {
|
||||
node.minRank = g.node(node.borderTop).rank
|
||||
node.maxRank = g.node(node.borderBottom).rank
|
||||
maxRank = Math.max(maxRank, node.maxRank)
|
||||
}
|
||||
})
|
||||
g.graph().maxRank = maxRank
|
||||
}
|
||||
|
||||
function removeEdgeLabelProxies (g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
if (node.dummy === 'edge-proxy') {
|
||||
g.edge(node.e).labelRank = node.rank
|
||||
g.removeNode(v)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function translateGraph (g) {
|
||||
let minX = Number.POSITIVE_INFINITY
|
||||
let maxX = 0
|
||||
let minY = Number.POSITIVE_INFINITY
|
||||
let maxY = 0
|
||||
const graphLabel = g.graph()
|
||||
const marginX = graphLabel.marginx || 0
|
||||
const marginY = graphLabel.marginy || 0
|
||||
|
||||
function getExtremes (attrs) {
|
||||
const x = attrs.x
|
||||
const y = attrs.y
|
||||
const w = attrs.width
|
||||
const 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) {
|
||||
const edge = g.edge(e)
|
||||
if (_.has(edge, 'x')) {
|
||||
getExtremes(edge)
|
||||
}
|
||||
})
|
||||
|
||||
minX -= marginX
|
||||
minY -= marginY
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
node.x -= minX
|
||||
node.y -= minY
|
||||
})
|
||||
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const 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) {
|
||||
const edge = g.edge(e)
|
||||
const nodeV = g.node(e.v)
|
||||
const nodeW = g.node(e.w)
|
||||
let p1 = null
|
||||
let p2 = null
|
||||
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) {
|
||||
const 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) {
|
||||
const edge = g.edge(e)
|
||||
if (edge.reversed) {
|
||||
edge.points.reverse()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function removeBorderNodes (g) {
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
if (g.children(v).length) {
|
||||
const node = g.node(v)
|
||||
const t = g.node(node.borderTop)
|
||||
const b = g.node(node.borderBottom)
|
||||
const l = g.node(_.last(node.borderLeft))
|
||||
const 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) {
|
||||
const 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) {
|
||||
const layers = util.buildLayerMatrix(g)
|
||||
_.forEach(layers, function (layer) {
|
||||
let orderShift = 0
|
||||
_.forEach(layer, function (v, i) {
|
||||
const 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) {
|
||||
const node = g.node(v)
|
||||
if (node.dummy === 'selfedge') {
|
||||
const selfNode = g.node(node.e.v)
|
||||
const x = selfNode.x + selfNode.width / 2
|
||||
const y = selfNode.y
|
||||
const dx = node.x - x
|
||||
const 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) {
|
||||
const newAttrs = {}
|
||||
_.forEach(attrs, function (v, k) {
|
||||
newAttrs[k.toLowerCase()] = v
|
||||
})
|
||||
return newAttrs
|
||||
}
|
||||
|
||||
export default layout
|
133
node_modules/dagre-layout/lib/nesting-graph.js
generated
vendored
Normal file
133
node_modules/dagre-layout/lib/nesting-graph.js
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from './util'
|
||||
|
||||
/*
|
||||
* 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 boundries, 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) {
|
||||
const root = util.addDummyNode(g, 'root', {}, '_root')
|
||||
const depths = treeDepths(g)
|
||||
const height = _.max(_.values(depths)) - 1
|
||||
const 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
|
||||
const 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) {
|
||||
const children = g.children(v)
|
||||
if (!children.length) {
|
||||
if (v !== root) {
|
||||
g.setEdge(root, v, { weight: 0, minlen: nodeSep })
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const top = util.addBorderNode(g, '_bt')
|
||||
const bottom = util.addBorderNode(g, '_bb')
|
||||
const 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)
|
||||
|
||||
const childNode = g.node(child)
|
||||
const childTop = childNode.borderTop ? childNode.borderTop : child
|
||||
const childBottom = childNode.borderBottom ? childNode.borderBottom : child
|
||||
const thisWeight = childNode.borderTop ? weight : 2 * weight
|
||||
const 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) {
|
||||
const depths = {}
|
||||
function dfs (v, depth) {
|
||||
const 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) {
|
||||
const graphLabel = g.graph()
|
||||
g.removeNode(graphLabel.nestingRoot)
|
||||
delete graphLabel.nestingRoot
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const edge = g.edge(e)
|
||||
if (edge.nestingEdge) {
|
||||
g.removeEdge(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
run,
|
||||
cleanup
|
||||
}
|
93
node_modules/dagre-layout/lib/normalize.js
generated
vendored
Normal file
93
node_modules/dagre-layout/lib/normalize.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from './util'
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
let v = e.v
|
||||
let vRank = g.node(v).rank
|
||||
const w = e.w
|
||||
const wRank = g.node(w).rank
|
||||
const name = e.name
|
||||
const edgeLabel = g.edge(e)
|
||||
const labelRank = edgeLabel.labelRank
|
||||
|
||||
if (wRank === vRank + 1) return
|
||||
|
||||
g.removeEdge(e)
|
||||
|
||||
let dummy
|
||||
let attrs
|
||||
let i
|
||||
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
|
||||
edgeLabel.points = []
|
||||
attrs = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
edgeLabel: edgeLabel,
|
||||
edgeObj: e,
|
||||
rank: vRank
|
||||
}
|
||||
dummy = util.addDummyNode(g, 'edge', attrs, '_d')
|
||||
if (vRank === labelRank) {
|
||||
attrs.width = edgeLabel.width
|
||||
attrs.height = edgeLabel.height
|
||||
attrs.dummy = 'edge-label'
|
||||
attrs.labelpos = edgeLabel.labelpos
|
||||
}
|
||||
g.setEdge(v, dummy, { weight: edgeLabel.weight }, name)
|
||||
if (i === 0) {
|
||||
g.graph().dummyChains.push(dummy)
|
||||
}
|
||||
v = dummy
|
||||
}
|
||||
|
||||
g.setEdge(v, w, { weight: edgeLabel.weight }, name)
|
||||
}
|
||||
|
||||
function undo (g) {
|
||||
_.forEach(g.graph().dummyChains, function (v) {
|
||||
let node = g.node(v)
|
||||
const origLabel = node.edgeLabel
|
||||
let w = null
|
||||
g.setEdge(node.edgeObj, origLabel)
|
||||
while (node.dummy) {
|
||||
w = g.successors(v)[0]
|
||||
g.removeNode(v)
|
||||
origLabel.points.push({ x: node.x, y: node.y })
|
||||
if (node.dummy === 'edge-label') {
|
||||
origLabel.x = node.x
|
||||
origLabel.y = node.y
|
||||
origLabel.width = node.width
|
||||
origLabel.height = node.height
|
||||
}
|
||||
v = w
|
||||
node = g.node(v)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
run,
|
||||
undo
|
||||
}
|
53
node_modules/dagre-layout/lib/order/add-subgraph-constraints.js
generated
vendored
Normal file
53
node_modules/dagre-layout/lib/order/add-subgraph-constraints.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
function addSubgraphConstraints (g, cg, vs) {
|
||||
const prev = {}
|
||||
let rootPrev
|
||||
|
||||
_.forEach(vs, function (v) {
|
||||
let child = g.parent(v)
|
||||
let parent
|
||||
let prevChild
|
||||
while (child) {
|
||||
parent = g.parent(child)
|
||||
if (parent) {
|
||||
prevChild = prev[parent]
|
||||
prev[parent] = child
|
||||
} else {
|
||||
prevChild = rootPrev
|
||||
rootPrev = child
|
||||
}
|
||||
if (prevChild && prevChild !== child) {
|
||||
cg.setEdge(prevChild, child)
|
||||
return
|
||||
}
|
||||
child = parent
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
function dfs(v) {
|
||||
const children = v ? g.children(v) : g.children();
|
||||
if (children.length) {
|
||||
const min = Number.POSITIVE_INFINITY,
|
||||
subgraphs = [];
|
||||
_.forEach(children, function(child) {
|
||||
const childMin = dfs(child);
|
||||
if (g.children(child).length) {
|
||||
subgraphs.push({ v: child, order: childMin });
|
||||
}
|
||||
min = Math.min(min, childMin);
|
||||
});
|
||||
_.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
|
||||
cg.setEdge(prev.v, curr.v);
|
||||
return curr;
|
||||
});
|
||||
return min;
|
||||
}
|
||||
return g.node(v).order;
|
||||
}
|
||||
dfs(undefined);
|
||||
*/
|
||||
}
|
||||
|
||||
export default addSubgraphConstraints
|
27
node_modules/dagre-layout/lib/order/barycenter.js
generated
vendored
Normal file
27
node_modules/dagre-layout/lib/order/barycenter.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
function barycenter (g, movable) {
|
||||
return _.map(movable, function (v) {
|
||||
const inV = g.inEdges(v)
|
||||
if (!inV.length) {
|
||||
return { v: v }
|
||||
} else {
|
||||
const result = _.reduce(inV, function (acc, e) {
|
||||
const edge = g.edge(e)
|
||||
const nodeU = g.node(e.v)
|
||||
return {
|
||||
sum: acc.sum + (edge.weight * nodeU.order),
|
||||
weight: acc.weight + edge.weight
|
||||
}
|
||||
}, { sum: 0, weight: 0 })
|
||||
|
||||
return {
|
||||
v: v,
|
||||
barycenter: result.sum / result.weight,
|
||||
weight: result.weight
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default barycenter
|
73
node_modules/dagre-layout/lib/order/build-layer-graph.js
generated
vendored
Normal file
73
node_modules/dagre-layout/lib/order/build-layer-graph.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
/*
|
||||
* Constructs a graph that can be used to sort a layer of nodes. The graph will
|
||||
* contain all base and subgraph nodes from the request layer in their original
|
||||
* hierarchy and any edges that are incident on these nodes and are of the type
|
||||
* requested by the "relationship" parameter.
|
||||
*
|
||||
* Nodes from the requested rank that do not have parents are assigned a root
|
||||
* node in the output graph, which is set in the root graph attribute. This
|
||||
* makes it easy to walk the hierarchy of movable nodes during ordering.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph is a DAG
|
||||
* 2. Base nodes in the input graph have a rank attribute
|
||||
* 3. Subgraph nodes in the input graph has minRank and maxRank attributes
|
||||
* 4. Edges have an assigned weight
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Output graph has all nodes in the movable rank with preserved
|
||||
* hierarchy.
|
||||
* 2. Root nodes in the movable layer are made children of the node
|
||||
* indicated by the root attribute of the graph.
|
||||
* 3. Non-movable nodes incident on movable nodes, selected by the
|
||||
* relationship parameter, are included in the graph (without hierarchy).
|
||||
* 4. Edges incident on movable nodes, selected by the relationship
|
||||
* parameter, are added to the output graph.
|
||||
* 5. The weights for copied edges are aggregated as need, since the output
|
||||
* graph is not a multi-graph.
|
||||
*/
|
||||
function buildLayerGraph (g, rank, relationship) {
|
||||
const root = createRootNode(g)
|
||||
const result = new Graph({ compound: true }).setGraph({ root: root })
|
||||
.setDefaultNodeLabel(function (v) { return g.node(v) })
|
||||
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
const parent = g.parent(v)
|
||||
|
||||
if (node.rank === rank || (node.minRank <= rank && rank <= node.maxRank)) {
|
||||
result.setNode(v)
|
||||
result.setParent(v, parent || root)
|
||||
|
||||
// This assumes we have only short edges!
|
||||
_.forEach(g[relationship](v), function (e) {
|
||||
const u = e.v === v ? e.w : e.v
|
||||
const edge = result.edge(u, v)
|
||||
const weight = !_.isUndefined(edge) ? edge.weight : 0
|
||||
result.setEdge(u, v, { weight: g.edge(e).weight + weight })
|
||||
})
|
||||
|
||||
if (_.has(node, 'minRank')) {
|
||||
result.setNode(v, {
|
||||
borderLeft: node.borderLeft[rank],
|
||||
borderRight: node.borderRight[rank]
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function createRootNode (g) {
|
||||
let v
|
||||
while (g.hasNode((v = _.uniqueId('_root'))));
|
||||
return v
|
||||
}
|
||||
|
||||
export default buildLayerGraph
|
70
node_modules/dagre-layout/lib/order/cross-count.js
generated
vendored
Normal file
70
node_modules/dagre-layout/lib/order/cross-count.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
/*
|
||||
* A function that takes a layering (an array of layers, each with an array of
|
||||
* ordererd nodes) and a graph and returns a weighted crossing count.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Input graph must be simple (not a multigraph), directed, and include
|
||||
* only simple edges.
|
||||
* 2. Edges in the input graph must have assigned weights.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. The graph and layering matrix are left unchanged.
|
||||
*
|
||||
* This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
|
||||
*/
|
||||
function crossCount (g, layering) {
|
||||
let cc = 0
|
||||
for (let i = 1; i < layering.length; ++i) {
|
||||
cc += twoLayerCrossCount(g, layering[i - 1], layering[i])
|
||||
}
|
||||
return cc
|
||||
}
|
||||
|
||||
function twoLayerCrossCount (g, northLayer, southLayer) {
|
||||
// Sort all of the edges between the north and south layers by their position
|
||||
// in the north layer and then the south. Map these edges to the position of
|
||||
// their head in the south layer.
|
||||
const southPos = _.zipObject(southLayer,
|
||||
_.map(southLayer, function (v, i) { return i }))
|
||||
const southEntries = _.flatten(_.map(northLayer, function (v) {
|
||||
return _.chain(g.outEdges(v))
|
||||
.map(function (e) {
|
||||
return { pos: southPos[e.w], weight: g.edge(e).weight }
|
||||
})
|
||||
.sortBy('pos')
|
||||
.value()
|
||||
}), true)
|
||||
|
||||
// Build the accumulator tree
|
||||
let firstIndex = 1
|
||||
while (firstIndex < southLayer.length) {
|
||||
firstIndex <<= 1
|
||||
}
|
||||
const treeSize = 2 * firstIndex - 1
|
||||
firstIndex -= 1
|
||||
const tree = _.map(new Array(treeSize), function () { return 0 })
|
||||
|
||||
// Calculate the weighted crossings
|
||||
let cc = 0
|
||||
_.forEach(southEntries.forEach(function (entry) {
|
||||
let index = entry.pos + firstIndex
|
||||
tree[index] += entry.weight
|
||||
let weightSum = 0
|
||||
while (index > 0) {
|
||||
if (index % 2) {
|
||||
weightSum += tree[index + 1]
|
||||
}
|
||||
index = (index - 1) >> 1
|
||||
tree[index] += entry.weight
|
||||
}
|
||||
cc += entry.weight * weightSum
|
||||
}))
|
||||
|
||||
return cc
|
||||
}
|
||||
|
||||
export default crossCount
|
78
node_modules/dagre-layout/lib/order/index.js
generated
vendored
Normal file
78
node_modules/dagre-layout/lib/order/index.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import initOrder from './init-order'
|
||||
import crossCount from './cross-count'
|
||||
import sortSubgraph from './sort-subgraph'
|
||||
import buildLayerGraph from './build-layer-graph'
|
||||
import addSubgraphConstraints from './add-subgraph-constraints'
|
||||
import util from '../util'
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
const maxRank = util.maxRank(g)
|
||||
const downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), 'inEdges')
|
||||
const upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), 'outEdges')
|
||||
|
||||
let layering = initOrder(g)
|
||||
assignOrder(g, layering)
|
||||
|
||||
let bestCC = Number.POSITIVE_INFINITY
|
||||
let best
|
||||
|
||||
for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
|
||||
sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2)
|
||||
|
||||
layering = util.buildLayerMatrix(g)
|
||||
const cc = crossCount(g, layering)
|
||||
if (cc < bestCC) {
|
||||
lastBest = 0
|
||||
best = _.cloneDeep(layering)
|
||||
bestCC = cc
|
||||
}
|
||||
}
|
||||
|
||||
assignOrder(g, best)
|
||||
}
|
||||
|
||||
function buildLayerGraphs (g, ranks, relationship) {
|
||||
return _.map(ranks, function (rank) {
|
||||
return buildLayerGraph(g, rank, relationship)
|
||||
})
|
||||
}
|
||||
|
||||
function sweepLayerGraphs (layerGraphs, biasRight) {
|
||||
const cg = new Graph()
|
||||
_.forEach(layerGraphs, function (lg) {
|
||||
const root = lg.graph().root
|
||||
const sorted = sortSubgraph(lg, root, cg, biasRight)
|
||||
_.forEach(sorted.vs, function (v, i) {
|
||||
lg.node(v).order = i
|
||||
})
|
||||
addSubgraphConstraints(lg, cg, sorted.vs)
|
||||
})
|
||||
}
|
||||
|
||||
function assignOrder (g, layering) {
|
||||
_.forEach(layering, function (layer) {
|
||||
_.forEach(layer, function (v, i) {
|
||||
g.node(v).order = i
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default order
|
36
node_modules/dagre-layout/lib/order/init-order.js
generated
vendored
Normal file
36
node_modules/dagre-layout/lib/order/init-order.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
/*
|
||||
* Assigns an initial order value for each node by performing a DFS search
|
||||
* starting from nodes in the first rank. Nodes are assigned an order in their
|
||||
* rank as they are first visited.
|
||||
*
|
||||
* This approach comes from Gansner, et al., "A Technique for Drawing Directed
|
||||
* Graphs."
|
||||
*
|
||||
* Returns a layering matrix with an array per layer and each layer sorted by
|
||||
* the order of its nodes.
|
||||
*/
|
||||
function initOrder (g) {
|
||||
const visited = {}
|
||||
const simpleNodes = _.filter(g.nodes(), function (v) {
|
||||
return !g.children(v).length
|
||||
})
|
||||
const maxRank = _.max(_.map(simpleNodes, function (v) { return g.node(v).rank }))
|
||||
const layers = _.map(_.range(maxRank + 1), function () { return [] })
|
||||
|
||||
function dfs (v) {
|
||||
if (_.has(visited, v)) return
|
||||
visited[v] = true
|
||||
const node = g.node(v)
|
||||
layers[node.rank].push(v)
|
||||
_.forEach(g.successors(v), dfs)
|
||||
}
|
||||
|
||||
const orderedVs = _.sortBy(simpleNodes, function (v) { return g.node(v).rank })
|
||||
_.forEach(orderedVs, dfs)
|
||||
|
||||
return layers
|
||||
}
|
||||
|
||||
export default initOrder
|
121
node_modules/dagre-layout/lib/order/resolve-conflicts.js
generated
vendored
Normal file
121
node_modules/dagre-layout/lib/order/resolve-conflicts.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
/*
|
||||
* Given a list of entries of the form {v, barycenter, weight} and a
|
||||
* constraint graph this function will resolve any conflicts between the
|
||||
* constraint graph and the barycenters for the entries. If the barycenters for
|
||||
* an entry would violate a constraint in the constraint graph then we coalesce
|
||||
* the nodes in the conflict into a new node that respects the contraint and
|
||||
* aggregates barycenter and weight information.
|
||||
*
|
||||
* This implementation is based on the description in Forster, "A Fast and
|
||||
* Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
|
||||
* differs in some specific details.
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Each entry has the form {v, barycenter, weight}, or if the node has
|
||||
* no barycenter, then {v}.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* A new list of entries of the form {vs, i, barycenter, weight}. The list
|
||||
* `vs` may either be a singleton or it may be an aggregation of nodes
|
||||
* ordered such that they do not violate constraints from the constraint
|
||||
* graph. The property `i` is the lowest original index of any of the
|
||||
* elements in `vs`.
|
||||
*/
|
||||
function resolveConflicts (entries, cg) {
|
||||
const mappedEntries = {}
|
||||
_.forEach(entries, function (entry, i) {
|
||||
const tmp = mappedEntries[entry.v] = {
|
||||
indegree: 0,
|
||||
'in': [],
|
||||
out: [],
|
||||
vs: [entry.v],
|
||||
i: i
|
||||
}
|
||||
if (!_.isUndefined(entry.barycenter)) {
|
||||
tmp.barycenter = entry.barycenter
|
||||
tmp.weight = entry.weight
|
||||
}
|
||||
})
|
||||
|
||||
_.forEach(cg.edges(), function (e) {
|
||||
const entryV = mappedEntries[e.v]
|
||||
const entryW = mappedEntries[e.w]
|
||||
if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
|
||||
entryW.indegree++
|
||||
entryV.out.push(mappedEntries[e.w])
|
||||
}
|
||||
})
|
||||
|
||||
const sourceSet = _.filter(mappedEntries, function (entry) {
|
||||
return !entry.indegree
|
||||
})
|
||||
|
||||
return doResolveConflicts(sourceSet)
|
||||
}
|
||||
|
||||
function doResolveConflicts (sourceSet) {
|
||||
const entries = []
|
||||
|
||||
function handleIn (vEntry) {
|
||||
return function (uEntry) {
|
||||
if (uEntry.merged) {
|
||||
return
|
||||
}
|
||||
if (_.isUndefined(uEntry.barycenter) ||
|
||||
_.isUndefined(vEntry.barycenter) ||
|
||||
uEntry.barycenter >= 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) {
|
||||
const entry = sourceSet.pop()
|
||||
entries.push(entry)
|
||||
_.forEach(entry['in'].reverse(), handleIn(entry))
|
||||
_.forEach(entry.out, handleOut(entry))
|
||||
}
|
||||
|
||||
return _.chain(entries)
|
||||
.filter(function (entry) { return !entry.merged })
|
||||
.map(function (entry) {
|
||||
return _.pick(entry, ['vs', 'i', 'barycenter', 'weight'])
|
||||
})
|
||||
.value()
|
||||
}
|
||||
|
||||
function mergeEntries (target, source) {
|
||||
let sum = 0
|
||||
let 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
|
||||
}
|
||||
|
||||
export default resolveConflicts
|
77
node_modules/dagre-layout/lib/order/sort-subgraph.js
generated
vendored
Normal file
77
node_modules/dagre-layout/lib/order/sort-subgraph.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import barycenter from './barycenter'
|
||||
import resolveConflicts from './resolve-conflicts'
|
||||
import sort from './sort'
|
||||
|
||||
function sortSubgraph (g, v, cg, biasRight) {
|
||||
let movable = g.children(v)
|
||||
const node = g.node(v)
|
||||
const bl = node ? node.borderLeft : undefined
|
||||
const br = node ? node.borderRight : undefined
|
||||
const subgraphs = {}
|
||||
|
||||
if (bl) {
|
||||
movable = _.filter(movable, function (w) {
|
||||
return w !== bl && w !== br
|
||||
})
|
||||
}
|
||||
|
||||
const barycenters = barycenter(g, movable)
|
||||
_.forEach(barycenters, function (entry) {
|
||||
if (g.children(entry.v).length) {
|
||||
const subgraphResult = sortSubgraph(g, entry.v, cg, biasRight)
|
||||
subgraphs[entry.v] = subgraphResult
|
||||
if (_.has(subgraphResult, 'barycenter')) {
|
||||
mergeBarycenters(entry, subgraphResult)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const entries = resolveConflicts(barycenters, cg)
|
||||
expandSubgraphs(entries, subgraphs)
|
||||
|
||||
const result = sort(entries, biasRight)
|
||||
|
||||
if (bl) {
|
||||
result.vs = _.flatten([bl, result.vs, br], true)
|
||||
if (g.predecessors(bl).length) {
|
||||
const blPred = g.node(g.predecessors(bl)[0])
|
||||
const 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
|
||||
}
|
||||
}
|
||||
|
||||
export default sortSubgraph
|
58
node_modules/dagre-layout/lib/order/sort.js
generated
vendored
Normal file
58
node_modules/dagre-layout/lib/order/sort.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from '../util'
|
||||
|
||||
function sort (entries, biasRight) {
|
||||
const parts = util.partition(entries, function (entry) {
|
||||
return _.has(entry, 'barycenter')
|
||||
})
|
||||
const sortable = parts.lhs
|
||||
const unsortable = _.sortBy(parts.rhs, function (entry) { return -entry.i })
|
||||
const vs = []
|
||||
let sum = 0
|
||||
let weight = 0
|
||||
let 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)
|
||||
})
|
||||
|
||||
const result = { vs: _.flatten(vs, true) }
|
||||
if (weight) {
|
||||
result.barycenter = sum / weight
|
||||
result.weight = weight
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function consumeUnsortable (vs, unsortable, index) {
|
||||
let 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.barycenter < entryW.barycenter) {
|
||||
return -1
|
||||
} else if (entryV.barycenter > entryW.barycenter) {
|
||||
return 1
|
||||
}
|
||||
|
||||
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i
|
||||
}
|
||||
}
|
||||
|
||||
export default sort
|
86
node_modules/dagre-layout/lib/parent-dummy-chains.js
generated
vendored
Normal file
86
node_modules/dagre-layout/lib/parent-dummy-chains.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
function parentDummyChains (g) {
|
||||
const postorderNums = postorder(g)
|
||||
|
||||
_.forEach(g.graph().dummyChains, function (v) {
|
||||
let node = g.node(v)
|
||||
const edgeObj = node.edgeObj
|
||||
const pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w)
|
||||
const path = pathData.path
|
||||
const lca = pathData.lca
|
||||
let pathIdx = 0
|
||||
let pathV = path[pathIdx]
|
||||
let ascending = true
|
||||
|
||||
while (v !== edgeObj.w) {
|
||||
node = g.node(v)
|
||||
|
||||
if (ascending) {
|
||||
while ((pathV = path[pathIdx]) !== lca &&
|
||||
g.node(pathV).maxRank < node.rank) {
|
||||
pathIdx++
|
||||
}
|
||||
|
||||
if (pathV === lca) {
|
||||
ascending = false
|
||||
}
|
||||
}
|
||||
|
||||
if (!ascending) {
|
||||
while (pathIdx < path.length - 1 &&
|
||||
g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
|
||||
pathIdx++
|
||||
}
|
||||
pathV = path[pathIdx]
|
||||
}
|
||||
|
||||
g.setParent(v, pathV)
|
||||
v = g.successors(v)[0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Find a path from v to w through the lowest common ancestor (LCA). Return the
|
||||
// full path and the LCA.
|
||||
function findPath (g, postorderNums, v, w) {
|
||||
const vPath = []
|
||||
const wPath = []
|
||||
const low = Math.min(postorderNums[v].low, postorderNums[w].low)
|
||||
const lim = Math.max(postorderNums[v].lim, postorderNums[w].lim)
|
||||
let parent
|
||||
let lca
|
||||
|
||||
// Traverse up from v to find the LCA
|
||||
parent = v
|
||||
do {
|
||||
parent = g.parent(parent)
|
||||
vPath.push(parent)
|
||||
} while (parent &&
|
||||
(postorderNums[parent].low > low || 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) {
|
||||
const result = {}
|
||||
let lim = 0
|
||||
|
||||
function dfs (v) {
|
||||
const low = lim
|
||||
_.forEach(g.children(v), dfs)
|
||||
result[v] = { low: low, lim: lim++ }
|
||||
}
|
||||
_.forEach(g.children(), dfs)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export default parentDummyChains
|
392
node_modules/dagre-layout/lib/position/bk.js
generated
vendored
Normal file
392
node_modules/dagre-layout/lib/position/bk.js
generated
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import util from '../util'
|
||||
|
||||
/*
|
||||
* This module provides coordinate assignment based on Brandes and Köpf, "Fast
|
||||
* and Simple Horizontal Coordinate Assignment."
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
const conflicts = {}
|
||||
|
||||
function visitLayer (prevLayer, layer) {
|
||||
// last visited node in the previous layer that is incident on an inner
|
||||
// segment.
|
||||
let k0 = 0
|
||||
// Tracks the last node in this layer scanned for crossings with a type-1
|
||||
// segment.
|
||||
let scanPos = 0
|
||||
const prevLayerLength = prevLayer.length
|
||||
const lastNode = _.last(layer)
|
||||
|
||||
_.forEach(layer, function (v, i) {
|
||||
const w = findOtherInnerSegmentNode(g, v)
|
||||
const 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) {
|
||||
const uLabel = g.node(u)
|
||||
const uPos = uLabel.order
|
||||
if ((uPos < k0 || k1 < uPos) &&
|
||||
!(uLabel.dummy && g.node(scanNode).dummy)) {
|
||||
addConflict(conflicts, u, scanNode)
|
||||
}
|
||||
})
|
||||
})
|
||||
scanPos = i + 1
|
||||
k0 = k1
|
||||
}
|
||||
})
|
||||
|
||||
return layer
|
||||
}
|
||||
|
||||
_.reduce(layering, visitLayer)
|
||||
return conflicts
|
||||
}
|
||||
|
||||
function findType2Conflicts (g, layering) {
|
||||
const conflicts = {}
|
||||
|
||||
function scan (south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
||||
let v
|
||||
_.forEach(_.range(southPos, southEnd), function (i) {
|
||||
v = south[i]
|
||||
if (g.node(v).dummy) {
|
||||
_.forEach(g.predecessors(v), function (u) {
|
||||
const uNode = g.node(u)
|
||||
if (uNode.dummy &&
|
||||
(uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
||||
addConflict(conflicts, u, v)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function visitLayer (north, south) {
|
||||
let prevNorthPos = -1
|
||||
let nextNorthPos
|
||||
let southPos = 0
|
||||
|
||||
_.forEach(south, function (v, southLookahead) {
|
||||
if (g.node(v).dummy === 'border') {
|
||||
const 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) {
|
||||
const tmp = v
|
||||
v = w
|
||||
w = tmp
|
||||
}
|
||||
|
||||
let conflictsV = conflicts[v]
|
||||
if (!conflictsV) {
|
||||
conflicts[v] = conflictsV = {}
|
||||
}
|
||||
conflictsV[w] = true
|
||||
}
|
||||
|
||||
function hasConflict (conflicts, v, w) {
|
||||
if (v > w) {
|
||||
const 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) {
|
||||
const root = {}
|
||||
const align = {}
|
||||
const 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) {
|
||||
let prevIdx = -1
|
||||
_.forEach(layer, function (v) {
|
||||
let ws = neighborFn(v)
|
||||
if (ws.length) {
|
||||
ws = _.sortBy(ws, function (w) { return pos[w] })
|
||||
const mp = (ws.length - 1) / 2
|
||||
for (let i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
||||
const w = ws[i]
|
||||
if (align[v] === v && prevIdx < pos[w] && !hasConflict(conflicts, v, w)) {
|
||||
align[w] = v
|
||||
align[v] = root[v] = root[w]
|
||||
prevIdx = pos[w]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return { root: root, align: align }
|
||||
}
|
||||
|
||||
function horizontalCompaction (g, layering, root, align, reverseSep) {
|
||||
// This portion of the algorithm differs from BK due to a number of problems.
|
||||
// Instead of their algorithm we construct a new block graph and do two
|
||||
// sweeps. The first sweep places blocks with the smallest possible
|
||||
// coordinates. The second sweep removes unused space by moving blocks to the
|
||||
// greatest coordinates without violating separation.
|
||||
const xs = {}
|
||||
const blockG = buildBlockGraph(g, layering, root, reverseSep)
|
||||
|
||||
// First pass, assign smallest coordinates via DFS
|
||||
const visited = {}
|
||||
function pass1 (v) {
|
||||
if (!_.has(visited, v)) {
|
||||
visited[v] = true
|
||||
xs[v] = _.reduce(blockG.inEdges(v), function (max, e) {
|
||||
pass1(e.v)
|
||||
return Math.max(max, xs[e.v] + blockG.edge(e))
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
_.forEach(blockG.nodes(), pass1)
|
||||
|
||||
const borderType = reverseSep ? 'borderLeft' : 'borderRight'
|
||||
function pass2 (v) {
|
||||
if (visited[v] !== 2) {
|
||||
visited[v]++
|
||||
const node = g.node(v)
|
||||
const min = _.reduce(blockG.outEdges(v), function (min, e) {
|
||||
pass2(e.w)
|
||||
return Math.min(min, xs[e.w] - blockG.edge(e))
|
||||
}, Number.POSITIVE_INFINITY)
|
||||
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
||||
xs[v] = Math.max(xs[v], min)
|
||||
}
|
||||
}
|
||||
}
|
||||
_.forEach(blockG.nodes(), pass2)
|
||||
|
||||
// Assign x coordinates to all nodes
|
||||
_.forEach(align, function (v) {
|
||||
xs[v] = xs[root[v]]
|
||||
})
|
||||
|
||||
return xs
|
||||
}
|
||||
|
||||
function buildBlockGraph (g, layering, root, reverseSep) {
|
||||
const blockGraph = new Graph()
|
||||
const graphLabel = g.graph()
|
||||
const sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep)
|
||||
|
||||
_.forEach(layering, function (layer) {
|
||||
let u
|
||||
_.forEach(layer, function (v) {
|
||||
const vRoot = root[v]
|
||||
blockGraph.setNode(vRoot)
|
||||
if (u) {
|
||||
const uRoot = root[u]
|
||||
const prevMax = blockGraph.edge(uRoot, vRoot)
|
||||
blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0))
|
||||
}
|
||||
u = v
|
||||
})
|
||||
})
|
||||
|
||||
return blockGraph
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the alignment that has the smallest width of the given alignments.
|
||||
*/
|
||||
function findSmallestWidthAlignment (g, xss) {
|
||||
return _.minBy(_.values(xss), function (xs) {
|
||||
const min = (_.minBy(_.toPairs(xs), (pair) => pair[1] - width(g, pair[0]) / 2) || ['k', 0])[1]
|
||||
const max = (_.maxBy(_.toPairs(xs), (pair) => pair[1] + width(g, pair[0]) / 2) || ['k', 0])[1]
|
||||
return max - min
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Align the coordinates of each of the layout alignments such that
|
||||
* left-biased alignments have their minimum coordinate at the same point as
|
||||
* the minimum coordinate of the smallest width alignment and right-biased
|
||||
* alignments have their maximum coordinate at the same point as the maximum
|
||||
* coordinate of the smallest width alignment.
|
||||
*/
|
||||
function alignCoordinates (xss, alignTo) {
|
||||
const alignToVals = _.values(alignTo)
|
||||
const alignToMin = _.min(alignToVals)
|
||||
const alignToMax = _.max(alignToVals)
|
||||
|
||||
_.forEach(['u', 'd'], function (vert) {
|
||||
_.forEach(['l', 'r'], function (horiz) {
|
||||
const alignment = vert + horiz
|
||||
const xs = xss[alignment]
|
||||
if (xs === alignTo) {
|
||||
return
|
||||
}
|
||||
const xsVals = _.values(xs)
|
||||
const delta = horiz === 'l' ? alignToMin - _.min(xsVals) : alignToMax - _.max(xsVals)
|
||||
if (delta) {
|
||||
xss[alignment] = _.mapValues(xs, function (x) { return x + delta })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function balance (xss, align) {
|
||||
return _.mapValues(xss.ul, function (ignore, v) {
|
||||
if (align) {
|
||||
return xss[align.toLowerCase()][v]
|
||||
} else {
|
||||
const xs = _.sortBy(_.map(xss, v))
|
||||
return (xs[1] + xs[2]) / 2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function positionX (g) {
|
||||
const layering = util.buildLayerMatrix(g)
|
||||
const conflicts = _.merge(findType1Conflicts(g, layering), findType2Conflicts(g, layering))
|
||||
|
||||
const xss = {}
|
||||
let adjustedLayering
|
||||
_.forEach(['u', 'd'], function (vert) {
|
||||
adjustedLayering = vert === 'u' ? layering : _.values(layering).reverse()
|
||||
_.forEach(['l', 'r'], function (horiz) {
|
||||
if (horiz === 'r') {
|
||||
adjustedLayering = _.map(adjustedLayering, function (inner) {
|
||||
return _.values(inner).reverse()
|
||||
})
|
||||
}
|
||||
|
||||
const neighborFn = _.bind(vert === 'u' ? g.predecessors : g.successors, g)
|
||||
const align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn)
|
||||
let xs = horizontalCompaction(g, adjustedLayering,
|
||||
align.root, align.align,
|
||||
horiz === 'r')
|
||||
if (horiz === 'r') {
|
||||
xs = _.mapValues(xs, function (x) { return -x })
|
||||
}
|
||||
xss[vert + horiz] = xs
|
||||
})
|
||||
})
|
||||
|
||||
const smallestWidth = findSmallestWidthAlignment(g, xss)
|
||||
alignCoordinates(xss, smallestWidth)
|
||||
return balance(xss, g.graph().align)
|
||||
}
|
||||
|
||||
function sep (nodeSep, edgeSep, reverseSep) {
|
||||
return function (g, v, w) {
|
||||
const vLabel = g.node(v)
|
||||
const wLabel = g.node(w)
|
||||
let sum = 0
|
||||
let delta
|
||||
|
||||
sum += vLabel.width / 2
|
||||
if (_.has(vLabel, 'labelpos')) {
|
||||
switch (vLabel.labelpos.toLowerCase()) {
|
||||
case 'l': delta = -vLabel.width / 2; break
|
||||
case 'r': delta = vLabel.width / 2; break
|
||||
}
|
||||
}
|
||||
if (delta) {
|
||||
sum += reverseSep ? delta : -delta
|
||||
}
|
||||
delta = 0
|
||||
|
||||
sum += (vLabel.dummy ? edgeSep : nodeSep) / 2
|
||||
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2
|
||||
|
||||
sum += wLabel.width / 2
|
||||
if (_.has(wLabel, 'labelpos')) {
|
||||
switch (wLabel.labelpos.toLowerCase()) {
|
||||
case 'l': delta = wLabel.width / 2; break
|
||||
case 'r': delta = -wLabel.width / 2; break
|
||||
}
|
||||
}
|
||||
if (delta) {
|
||||
sum += reverseSep ? delta : -delta
|
||||
}
|
||||
delta = 0
|
||||
|
||||
return sum
|
||||
}
|
||||
}
|
||||
|
||||
function width (g, v) {
|
||||
return g.node(v).width
|
||||
}
|
||||
|
||||
export default {
|
||||
positionX: positionX,
|
||||
findType1Conflicts: findType1Conflicts,
|
||||
findType2Conflicts: findType2Conflicts,
|
||||
addConflict: addConflict,
|
||||
hasConflict: hasConflict,
|
||||
verticalAlignment: verticalAlignment,
|
||||
horizontalCompaction: horizontalCompaction,
|
||||
alignCoordinates: alignCoordinates,
|
||||
findSmallestWidthAlignment: findSmallestWidthAlignment,
|
||||
balance: balance
|
||||
}
|
28
node_modules/dagre-layout/lib/position/index.js
generated
vendored
Normal file
28
node_modules/dagre-layout/lib/position/index.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from '../util'
|
||||
import { positionX } from './bk'
|
||||
|
||||
function position (g) {
|
||||
g = util.asNonCompoundGraph(g)
|
||||
|
||||
positionY(g)
|
||||
_.forEach(positionX(g), function (x, v) {
|
||||
g.node(v).x = x
|
||||
})
|
||||
}
|
||||
|
||||
function positionY (g) {
|
||||
const layering = util.buildLayerMatrix(g)
|
||||
const rankSep = g.graph().ranksep
|
||||
let prevY = 0
|
||||
_.forEach(layering, function (layer) {
|
||||
const maxHeight = _.max(_.map(layer, function (v) { return g.node(v).height }))
|
||||
_.forEach(layer, function (v) {
|
||||
g.node(v).y = prevY + maxHeight / 2
|
||||
})
|
||||
prevY += maxHeight + rankSep
|
||||
})
|
||||
}
|
||||
|
||||
export default position
|
89
node_modules/dagre-layout/lib/rank/feasible-tree.js
generated
vendored
Normal file
89
node_modules/dagre-layout/lib/rank/feasible-tree.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import { slack } from './util'
|
||||
|
||||
/*
|
||||
* Constructs a spanning tree with tight edges and adjusted the input node's
|
||||
* ranks to achieve this. A tight edge is one that is has a length that matches
|
||||
* its "minlen" attribute.
|
||||
*
|
||||
* The basic structure for this function is derived from Gansner, et al., "A
|
||||
* Technique for Drawing Directed Graphs."
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be a DAG.
|
||||
* 2. Graph must be connected.
|
||||
* 3. Graph must have at least one node.
|
||||
* 5. Graph nodes must have been previously assigned a "rank" property that
|
||||
* respects the "minlen" property of incident edges.
|
||||
* 6. Graph edges must have a "minlen" property.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* - Graph nodes will have their rank adjusted to ensure that all edges are
|
||||
* tight.
|
||||
*
|
||||
* Returns a tree (undirected graph) that is constructed using only "tight"
|
||||
* edges.
|
||||
*/
|
||||
function feasibleTree (g) {
|
||||
const t = new Graph({ directed: false })
|
||||
|
||||
// Choose arbitrary node from which to start our tree
|
||||
const start = g.nodes()[0]
|
||||
const size = g.nodeCount()
|
||||
t.setNode(start, {})
|
||||
|
||||
let edge
|
||||
let delta
|
||||
while (tightTree(t, g) < size) {
|
||||
edge = findMinSlackEdge(t, g)
|
||||
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge)
|
||||
shiftRanks(t, g, delta)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds a maximal tree of tight edges and returns the number of nodes in the
|
||||
* tree.
|
||||
*/
|
||||
function tightTree (t, g) {
|
||||
function dfs (v) {
|
||||
_.forEach(g.nodeEdges(v), function (e) {
|
||||
const edgeV = e.v
|
||||
const w = (v === edgeV) ? e.w : edgeV
|
||||
if (!t.hasNode(w) && !slack(g, e)) {
|
||||
t.setNode(w, {})
|
||||
t.setEdge(v, w, {})
|
||||
dfs(w)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_.forEach(t.nodes(), dfs)
|
||||
return t.nodeCount()
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the edge with the smallest slack that is incident on tree and returns
|
||||
* it.
|
||||
*/
|
||||
function findMinSlackEdge (t, g) {
|
||||
return _.minBy(g.edges(), function (e) {
|
||||
if (t.hasNode(e.v) !== t.hasNode(e.w)) {
|
||||
return slack(g, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function shiftRanks (t, g, delta) {
|
||||
_.forEach(t.nodes(), function (v) {
|
||||
g.node(v).rank += delta
|
||||
})
|
||||
}
|
||||
|
||||
export default feasibleTree
|
45
node_modules/dagre-layout/lib/rank/index.js
generated
vendored
Normal file
45
node_modules/dagre-layout/lib/rank/index.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import { longestPath } from './util'
|
||||
import feasibleTree from './feasible-tree'
|
||||
import networkSimplex from './network-simplex'
|
||||
|
||||
/*
|
||||
* Assigns a rank to each node in the input graph that respects the "minlen"
|
||||
* constraint specified on edges between nodes.
|
||||
*
|
||||
* This basic structure is derived from Gansner, et al., "A Technique for
|
||||
* Drawing Directed Graphs."
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be a connected DAG
|
||||
* 2. Graph nodes must be objects
|
||||
* 3. Graph edges must have "weight" and "minlen" attributes
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* 1. Graph nodes will have a "rank" attribute based on the results of the
|
||||
* algorithm. Ranks can start at any index (including negative), we'll
|
||||
* fix them up later.
|
||||
*/
|
||||
function rank (g) {
|
||||
switch (g.graph().ranker) {
|
||||
case 'network-simplex': networkSimplexRanker(g); break
|
||||
case 'tight-tree': tightTreeRanker(g); break
|
||||
case 'longest-path': longestPathRanker(g); break
|
||||
default: networkSimplexRanker(g)
|
||||
}
|
||||
}
|
||||
|
||||
// A fast and simple ranker, but results are far from optimal.
|
||||
const longestPathRanker = longestPath
|
||||
|
||||
function tightTreeRanker (g) {
|
||||
longestPath(g)
|
||||
feasibleTree(g)
|
||||
}
|
||||
|
||||
function networkSimplexRanker (g) {
|
||||
networkSimplex(g)
|
||||
}
|
||||
|
||||
export default rank
|
234
node_modules/dagre-layout/lib/rank/network-simplex.js
generated
vendored
Normal file
234
node_modules/dagre-layout/lib/rank/network-simplex.js
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
import _ from 'lodash'
|
||||
import { alg } from 'graphlibrary'
|
||||
|
||||
import feasibleTree from './feasible-tree'
|
||||
import { slack, longestPath as initRank } from './util'
|
||||
import { simplify } from '../util'
|
||||
|
||||
const { preorder, postorder } = alg
|
||||
|
||||
// Expose some internals for testing purposes
|
||||
networkSimplex.initLowLimValues = initLowLimValues
|
||||
networkSimplex.initCutValues = initCutValues
|
||||
networkSimplex.calcCutValue = calcCutValue
|
||||
networkSimplex.leaveEdge = leaveEdge
|
||||
networkSimplex.enterEdge = enterEdge
|
||||
networkSimplex.exchangeEdges = exchangeEdges
|
||||
|
||||
/*
|
||||
* The network simplex algorithm assigns ranks to each node in the input graph
|
||||
* and iteratively improves the ranking to reduce the length of edges.
|
||||
*
|
||||
* Preconditions:
|
||||
*
|
||||
* 1. The input graph must be a DAG.
|
||||
* 2. All nodes in the graph must have an object value.
|
||||
* 3. All edges in the graph must have "minlen" and "weight" attributes.
|
||||
*
|
||||
* Postconditions:
|
||||
*
|
||||
* 1. All nodes in the graph will have an assigned "rank" attribute that has
|
||||
* been optimized by the network simplex algorithm. Ranks start at 0.
|
||||
*
|
||||
*
|
||||
* A rough sketch of the algorithm is as follows:
|
||||
*
|
||||
* 1. Assign initial ranks to each node. We use the longest path algorithm,
|
||||
* which assigns ranks to the lowest position possible. In general this
|
||||
* leads to very wide bottom ranks and unnecessarily long edges.
|
||||
* 2. Construct a feasible tight tree. A tight tree is one such that all
|
||||
* edges in the tree have no slack (difference between length of edge
|
||||
* and minlen for the edge). This by itself greatly improves the assigned
|
||||
* rankings by shorting edges.
|
||||
* 3. Iteratively find edges that have negative cut values. Generally a
|
||||
* negative cut value indicates that the edge could be removed and a new
|
||||
* tree edge could be added to produce a more compact graph.
|
||||
*
|
||||
* Much of the algorithms here are derived from Gansner, et al., "A Technique
|
||||
* for Drawing Directed Graphs." The structure of the file roughly follows the
|
||||
* structure of the overall algorithm.
|
||||
*/
|
||||
function networkSimplex (g) {
|
||||
g = simplify(g)
|
||||
initRank(g)
|
||||
const t = feasibleTree(g)
|
||||
initLowLimValues(t)
|
||||
initCutValues(t, g)
|
||||
|
||||
let e
|
||||
let f
|
||||
while ((e = leaveEdge(t))) {
|
||||
f = enterEdge(t, g, e)
|
||||
exchangeEdges(t, g, e, f)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes cut values for all edges in the tree.
|
||||
*/
|
||||
function initCutValues (t, g) {
|
||||
let vs = postorder(t, t.nodes())
|
||||
vs = vs.slice(0, vs.length - 1)
|
||||
_.forEach(vs, function (v) {
|
||||
assignCutValue(t, g, v)
|
||||
})
|
||||
}
|
||||
|
||||
function assignCutValue (t, g, child) {
|
||||
const childLab = t.node(child)
|
||||
const parent = childLab.parent
|
||||
t.edge(child, parent).cutvalue = calcCutValue(t, g, child)
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the tight tree, its graph, and a child in the graph calculate and
|
||||
* return the cut value for the edge between the child and its parent.
|
||||
*/
|
||||
function calcCutValue (t, g, child) {
|
||||
const childLab = t.node(child)
|
||||
const parent = childLab.parent
|
||||
// True if the child is on the tail end of the edge in the directed graph
|
||||
let childIsTail = true
|
||||
// The graph's view of the tree edge we're inspecting
|
||||
let graphEdge = g.edge(child, parent)
|
||||
// The accumulated cut value for the edge between this node and its parent
|
||||
let cutValue = 0
|
||||
|
||||
if (!graphEdge) {
|
||||
childIsTail = false
|
||||
graphEdge = g.edge(parent, child)
|
||||
}
|
||||
|
||||
cutValue = graphEdge.weight
|
||||
|
||||
_.forEach(g.nodeEdges(child), function (e) {
|
||||
const isOutEdge = e.v === child
|
||||
const other = isOutEdge ? e.w : e.v
|
||||
|
||||
if (other !== parent) {
|
||||
const pointsToHead = isOutEdge === childIsTail
|
||||
const otherWeight = g.edge(e).weight
|
||||
|
||||
cutValue += pointsToHead ? otherWeight : -otherWeight
|
||||
if (isTreeEdge(t, child, other)) {
|
||||
const otherCutValue = t.edge(child, other).cutvalue
|
||||
cutValue += pointsToHead ? -otherCutValue : otherCutValue
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return cutValue
|
||||
}
|
||||
|
||||
function initLowLimValues (tree, root) {
|
||||
if (arguments.length < 2) {
|
||||
root = tree.nodes()[0]
|
||||
}
|
||||
dfsAssignLowLim(tree, {}, 1, root)
|
||||
}
|
||||
|
||||
function dfsAssignLowLim (tree, visited, nextLim, v, parent) {
|
||||
const low = nextLim
|
||||
const label = tree.node(v)
|
||||
|
||||
visited[v] = true
|
||||
_.forEach(tree.neighbors(v), function (w) {
|
||||
if (!_.has(visited, w)) {
|
||||
nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v)
|
||||
}
|
||||
})
|
||||
|
||||
label.low = low
|
||||
label.lim = nextLim++
|
||||
if (parent) {
|
||||
label.parent = parent
|
||||
} else {
|
||||
// TODO should be able to remove this when we incrementally update low lim
|
||||
delete label.parent
|
||||
}
|
||||
|
||||
return nextLim
|
||||
}
|
||||
|
||||
function leaveEdge (tree) {
|
||||
return _.find(tree.edges(), function (e) {
|
||||
return tree.edge(e).cutvalue < 0
|
||||
})
|
||||
}
|
||||
|
||||
function enterEdge (t, g, edge) {
|
||||
let v = edge.v
|
||||
let w = edge.w
|
||||
|
||||
// For the rest of this function we assume that v is the tail and w is the
|
||||
// head, so if we don't have this edge in the graph we should flip it to
|
||||
// match the correct orientation.
|
||||
if (!g.hasEdge(v, w)) {
|
||||
v = edge.w
|
||||
w = edge.v
|
||||
}
|
||||
|
||||
const vLabel = t.node(v)
|
||||
const wLabel = t.node(w)
|
||||
let tailLabel = vLabel
|
||||
let flip = false
|
||||
|
||||
// If the root is in the tail of the edge then we need to flip the logic that
|
||||
// checks for the head and tail nodes in the candidates function below.
|
||||
if (vLabel.lim > wLabel.lim) {
|
||||
tailLabel = wLabel
|
||||
flip = true
|
||||
}
|
||||
|
||||
const 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) {
|
||||
const v = e.v
|
||||
const 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) {
|
||||
const root = _.find(t.nodes(), function (v) { return !g.node(v).parent })
|
||||
let vs = preorder(t, root)
|
||||
vs = vs.slice(1)
|
||||
_.forEach(vs, function (v) {
|
||||
const parent = t.node(v).parent
|
||||
let edge = g.edge(v, parent)
|
||||
let 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
|
||||
}
|
||||
|
||||
export default networkSimplex
|
55
node_modules/dagre-layout/lib/rank/util.js
generated
vendored
Normal file
55
node_modules/dagre-layout/lib/rank/util.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export function longestPath (g) {
|
||||
const visited = {}
|
||||
|
||||
function dfs (v) {
|
||||
const label = g.node(v)
|
||||
if (_.has(visited, v)) {
|
||||
return label.rank
|
||||
}
|
||||
visited[v] = true
|
||||
|
||||
const rank = _.min(_.map(g.outEdges(v), function (e) {
|
||||
return dfs(e.w) - g.edge(e).minlen
|
||||
})) || 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.
|
||||
*/
|
||||
export function slack (g, e) {
|
||||
return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen
|
||||
}
|
||||
|
||||
export default {
|
||||
longestPath: longestPath,
|
||||
slack: slack
|
||||
}
|
235
node_modules/dagre-layout/lib/util.js
generated
vendored
Normal file
235
node_modules/dagre-layout/lib/util.js
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
/*
|
||||
* Adds a dummy node to the graph and return v.
|
||||
*/
|
||||
export function addDummyNode (g, type, attrs, name) {
|
||||
let 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.
|
||||
*/
|
||||
export function simplify (g) {
|
||||
const simplified = new Graph().setGraph(g.graph())
|
||||
_.forEach(g.nodes(), function (v) { simplified.setNode(v, g.node(v)) })
|
||||
_.forEach(g.edges(), function (e) {
|
||||
const simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 }
|
||||
const label = g.edge(e)
|
||||
simplified.setEdge(e.v, e.w, {
|
||||
weight: simpleLabel.weight + label.weight,
|
||||
minlen: Math.max(simpleLabel.minlen, label.minlen)
|
||||
})
|
||||
})
|
||||
return simplified
|
||||
}
|
||||
|
||||
export function asNonCompoundGraph (g) {
|
||||
const 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
|
||||
}
|
||||
|
||||
export function successorWeights (g) {
|
||||
const weightMap = _.map(g.nodes(), function (v) {
|
||||
const 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)
|
||||
}
|
||||
|
||||
export function predecessorWeights (g) {
|
||||
const weightMap = _.map(g.nodes(), function (v) {
|
||||
const 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.
|
||||
*/
|
||||
export function intersectRect (rect, point) {
|
||||
const x = rect.x
|
||||
const y = rect.y
|
||||
|
||||
// Rectangle intersection algorithm from:
|
||||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||||
const dx = point.x - x
|
||||
const dy = point.y - y
|
||||
let w = rect.width / 2
|
||||
let h = rect.height / 2
|
||||
|
||||
if (!dx && !dy) {
|
||||
throw new Error('Not possible to find intersection inside of the rectangle')
|
||||
}
|
||||
|
||||
let sx
|
||||
let 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.
|
||||
*/
|
||||
export function buildLayerMatrix (g) {
|
||||
const layering = _.map(_.range(maxRank(g) + 1), function () { return [] })
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
const 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.
|
||||
*/
|
||||
export function normalizeRanks (g) {
|
||||
const min = _.min(_.map(g.nodes(), function (v) { return g.node(v).rank }))
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
if (_.has(node, 'rank')) {
|
||||
node.rank -= min
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function removeEmptyRanks (g) {
|
||||
// Ranks may not start at 0, so we need to offset them
|
||||
const offset = _.min(_.map(g.nodes(), function (v) { return g.node(v).rank }))
|
||||
|
||||
const layers = []
|
||||
_.forEach(g.nodes(), function (v) {
|
||||
const rank = g.node(v).rank - offset
|
||||
if (!layers[rank]) {
|
||||
layers[rank] = []
|
||||
}
|
||||
layers[rank].push(v)
|
||||
})
|
||||
|
||||
let delta = 0
|
||||
const 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 })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function addBorderNode (g, prefix, rank, order) {
|
||||
const node = {
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
if (arguments.length >= 4) {
|
||||
node.rank = rank
|
||||
node.order = order
|
||||
}
|
||||
return addDummyNode(g, 'border', node, prefix)
|
||||
}
|
||||
|
||||
export function maxRank (g) {
|
||||
return _.max(_.map(g.nodes(), function (v) {
|
||||
const 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.
|
||||
*/
|
||||
export function partition (collection, fn) {
|
||||
const 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.
|
||||
*/
|
||||
export function time (name, fn) {
|
||||
const start = _.now()
|
||||
try {
|
||||
return fn()
|
||||
} finally {
|
||||
console.log(name + ' time: ' + (_.now() - start) + 'ms')
|
||||
}
|
||||
}
|
||||
|
||||
export function notime (name, fn) {
|
||||
return fn()
|
||||
}
|
||||
|
||||
export default {
|
||||
addDummyNode,
|
||||
simplify,
|
||||
asNonCompoundGraph,
|
||||
successorWeights,
|
||||
predecessorWeights,
|
||||
intersectRect,
|
||||
buildLayerMatrix,
|
||||
normalizeRanks,
|
||||
removeEmptyRanks,
|
||||
addBorderNode,
|
||||
maxRank,
|
||||
partition,
|
||||
time,
|
||||
notime
|
||||
}
|
47
node_modules/dagre-layout/node_modules/lodash/LICENSE
generated
vendored
Normal file
47
node_modules/dagre-layout/node_modules/lodash/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
|
||||
Based on Underscore.js, copyright Jeremy Ashkenas,
|
||||
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/lodash/lodash
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
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.
|
||||
|
||||
====
|
||||
|
||||
Copyright and related rights for sample code are waived via CC0. Sample
|
||||
code is defined as all source code displayed within the prose of the
|
||||
documentation.
|
||||
|
||||
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
====
|
||||
|
||||
Files located in the node_modules and vendor directories are externally
|
||||
maintained libraries used by this software which have their own
|
||||
licenses; we recommend you read them, as their terms may differ from the
|
||||
terms above.
|
39
node_modules/dagre-layout/node_modules/lodash/README.md
generated
vendored
Normal file
39
node_modules/dagre-layout/node_modules/lodash/README.md
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
# lodash v4.17.21
|
||||
|
||||
The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules.
|
||||
|
||||
## Installation
|
||||
|
||||
Using npm:
|
||||
```shell
|
||||
$ npm i -g npm
|
||||
$ npm i --save lodash
|
||||
```
|
||||
|
||||
In Node.js:
|
||||
```js
|
||||
// Load the full build.
|
||||
var _ = require('lodash');
|
||||
// Load the core build.
|
||||
var _ = require('lodash/core');
|
||||
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
|
||||
var fp = require('lodash/fp');
|
||||
|
||||
// Load method categories.
|
||||
var array = require('lodash/array');
|
||||
var object = require('lodash/fp/object');
|
||||
|
||||
// Cherry-pick methods for smaller browserify/rollup/webpack bundles.
|
||||
var at = require('lodash/at');
|
||||
var curryN = require('lodash/fp/curryN');
|
||||
```
|
||||
|
||||
See the [package source](https://github.com/lodash/lodash/tree/4.17.21-npm) for more details.
|
||||
|
||||
**Note:**<br>
|
||||
Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL.
|
||||
|
||||
## Support
|
||||
|
||||
Tested in Chrome 74-75, Firefox 66-67, IE 11, Edge 18, Safari 11-12, & Node.js 8-12.<br>
|
||||
Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available.
|
7
node_modules/dagre-layout/node_modules/lodash/_DataView.js
generated
vendored
Normal file
7
node_modules/dagre-layout/node_modules/lodash/_DataView.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
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;
|
32
node_modules/dagre-layout/node_modules/lodash/_Hash.js
generated
vendored
Normal file
32
node_modules/dagre-layout/node_modules/lodash/_Hash.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
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 < length) {
|
||||
var entry = entries[index];
|
||||
this.set(entry[0], entry[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add methods to `Hash`.
|
||||
Hash.prototype.clear = hashClear;
|
||||
Hash.prototype['delete'] = hashDelete;
|
||||
Hash.prototype.get = hashGet;
|
||||
Hash.prototype.has = hashHas;
|
||||
Hash.prototype.set = hashSet;
|
||||
|
||||
module.exports = Hash;
|
28
node_modules/dagre-layout/node_modules/lodash/_LazyWrapper.js
generated
vendored
Normal file
28
node_modules/dagre-layout/node_modules/lodash/_LazyWrapper.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
var baseCreate = require('./_baseCreate'),
|
||||
baseLodash = require('./_baseLodash');
|
||||
|
||||
/** Used as references for the maximum length and index of an array. */
|
||||
var MAX_ARRAY_LENGTH = 4294967295;
|
||||
|
||||
/**
|
||||
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {*} value The value to wrap.
|
||||
*/
|
||||
function LazyWrapper(value) {
|
||||
this.__wrapped__ = value;
|
||||
this.__actions__ = [];
|
||||
this.__dir__ = 1;
|
||||
this.__filtered__ = false;
|
||||
this.__iteratees__ = [];
|
||||
this.__takeCount__ = MAX_ARRAY_LENGTH;
|
||||
this.__views__ = [];
|
||||
}
|
||||
|
||||
// Ensure `LazyWrapper` is an instance of `baseLodash`.
|
||||
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
|
||||
LazyWrapper.prototype.constructor = LazyWrapper;
|
||||
|
||||
module.exports = LazyWrapper;
|
32
node_modules/dagre-layout/node_modules/lodash/_ListCache.js
generated
vendored
Normal file
32
node_modules/dagre-layout/node_modules/lodash/_ListCache.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var listCacheClear = require('./_listCacheClear'),
|
||||
listCacheDelete = require('./_listCacheDelete'),
|
||||
listCacheGet = require('./_listCacheGet'),
|
||||
listCacheHas = require('./_listCacheHas'),
|
||||
listCacheSet = require('./_listCacheSet');
|
||||
|
||||
/**
|
||||
* Creates an list cache object.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Array} [entries] The key-value pairs to cache.
|
||||
*/
|
||||
function ListCache(entries) {
|
||||
var index = -1,
|
||||
length = entries == null ? 0 : entries.length;
|
||||
|
||||
this.clear();
|
||||
while (++index < length) {
|
||||
var entry = entries[index];
|
||||
this.set(entry[0], entry[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add methods to `ListCache`.
|
||||
ListCache.prototype.clear = listCacheClear;
|
||||
ListCache.prototype['delete'] = listCacheDelete;
|
||||
ListCache.prototype.get = listCacheGet;
|
||||
ListCache.prototype.has = listCacheHas;
|
||||
ListCache.prototype.set = listCacheSet;
|
||||
|
||||
module.exports = ListCache;
|
22
node_modules/dagre-layout/node_modules/lodash/_LodashWrapper.js
generated
vendored
Normal file
22
node_modules/dagre-layout/node_modules/lodash/_LodashWrapper.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
var baseCreate = require('./_baseCreate'),
|
||||
baseLodash = require('./_baseLodash');
|
||||
|
||||
/**
|
||||
* The base constructor for creating `lodash` wrapper objects.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to wrap.
|
||||
* @param {boolean} [chainAll] Enable explicit method chain sequences.
|
||||
*/
|
||||
function LodashWrapper(value, chainAll) {
|
||||
this.__wrapped__ = value;
|
||||
this.__actions__ = [];
|
||||
this.__chain__ = !!chainAll;
|
||||
this.__index__ = 0;
|
||||
this.__values__ = undefined;
|
||||
}
|
||||
|
||||
LodashWrapper.prototype = baseCreate(baseLodash.prototype);
|
||||
LodashWrapper.prototype.constructor = LodashWrapper;
|
||||
|
||||
module.exports = LodashWrapper;
|
7
node_modules/dagre-layout/node_modules/lodash/_Map.js
generated
vendored
Normal file
7
node_modules/dagre-layout/node_modules/lodash/_Map.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var getNative = require('./_getNative'),
|
||||
root = require('./_root');
|
||||
|
||||
/* Built-in method references that are verified to be native. */
|
||||
var Map = getNative(root, 'Map');
|
||||
|
||||
module.exports = Map;
|
32
node_modules/dagre-layout/node_modules/lodash/_MapCache.js
generated
vendored
Normal file
32
node_modules/dagre-layout/node_modules/lodash/_MapCache.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var mapCacheClear = require('./_mapCacheClear'),
|
||||
mapCacheDelete = require('./_mapCacheDelete'),
|
||||
mapCacheGet = require('./_mapCacheGet'),
|
||||
mapCacheHas = require('./_mapCacheHas'),
|
||||
mapCacheSet = require('./_mapCacheSet');
|
||||
|
||||
/**
|
||||
* Creates a map cache object to store key-value pairs.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Array} [entries] The key-value pairs to cache.
|
||||
*/
|
||||
function MapCache(entries) {
|
||||
var index = -1,
|
||||
length = entries == null ? 0 : entries.length;
|
||||
|
||||
this.clear();
|
||||
while (++index < length) {
|
||||
var entry = entries[index];
|
||||
this.set(entry[0], entry[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add methods to `MapCache`.
|
||||
MapCache.prototype.clear = mapCacheClear;
|
||||
MapCache.prototype['delete'] = mapCacheDelete;
|
||||
MapCache.prototype.get = mapCacheGet;
|
||||
MapCache.prototype.has = mapCacheHas;
|
||||
MapCache.prototype.set = mapCacheSet;
|
||||
|
||||
module.exports = MapCache;
|
7
node_modules/dagre-layout/node_modules/lodash/_Promise.js
generated
vendored
Normal file
7
node_modules/dagre-layout/node_modules/lodash/_Promise.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var getNative = require('./_getNative'),
|
||||
root = require('./_root');
|
||||
|
||||
/* Built-in method references that are verified to be native. */
|
||||
var Promise = getNative(root, 'Promise');
|
||||
|
||||
module.exports = Promise;
|
7
node_modules/dagre-layout/node_modules/lodash/_Set.js
generated
vendored
Normal file
7
node_modules/dagre-layout/node_modules/lodash/_Set.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var getNative = require('./_getNative'),
|
||||
root = require('./_root');
|
||||
|
||||
/* Built-in method references that are verified to be native. */
|
||||
var Set = getNative(root, 'Set');
|
||||
|
||||
module.exports = Set;
|
27
node_modules/dagre-layout/node_modules/lodash/_SetCache.js
generated
vendored
Normal file
27
node_modules/dagre-layout/node_modules/lodash/_SetCache.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
var MapCache = require('./_MapCache'),
|
||||
setCacheAdd = require('./_setCacheAdd'),
|
||||
setCacheHas = require('./_setCacheHas');
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates an array cache object to store unique values.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Array} [values] The values to cache.
|
||||
*/
|
||||
function SetCache(values) {
|
||||
var index = -1,
|
||||
length = values == null ? 0 : values.length;
|
||||
|
||||
this.__data__ = new MapCache;
|
||||
while (++index < length) {
|
||||
this.add(values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add methods to `SetCache`.
|
||||
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
|
||||
SetCache.prototype.has = setCacheHas;
|
||||
|
||||
module.exports = SetCache;
|
27
node_modules/dagre-layout/node_modules/lodash/_Stack.js
generated
vendored
Normal file
27
node_modules/dagre-layout/node_modules/lodash/_Stack.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
var ListCache = require('./_ListCache'),
|
||||
stackClear = require('./_stackClear'),
|
||||
stackDelete = require('./_stackDelete'),
|
||||
stackGet = require('./_stackGet'),
|
||||
stackHas = require('./_stackHas'),
|
||||
stackSet = require('./_stackSet');
|
||||
|
||||
/**
|
||||
* Creates a stack cache object to store key-value pairs.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Array} [entries] The key-value pairs to cache.
|
||||
*/
|
||||
function Stack(entries) {
|
||||
var data = this.__data__ = new ListCache(entries);
|
||||
this.size = data.size;
|
||||
}
|
||||
|
||||
// Add methods to `Stack`.
|
||||
Stack.prototype.clear = stackClear;
|
||||
Stack.prototype['delete'] = stackDelete;
|
||||
Stack.prototype.get = stackGet;
|
||||
Stack.prototype.has = stackHas;
|
||||
Stack.prototype.set = stackSet;
|
||||
|
||||
module.exports = Stack;
|
6
node_modules/dagre-layout/node_modules/lodash/_Symbol.js
generated
vendored
Normal file
6
node_modules/dagre-layout/node_modules/lodash/_Symbol.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
var root = require('./_root');
|
||||
|
||||
/** Built-in value references. */
|
||||
var Symbol = root.Symbol;
|
||||
|
||||
module.exports = Symbol;
|
6
node_modules/dagre-layout/node_modules/lodash/_Uint8Array.js
generated
vendored
Normal file
6
node_modules/dagre-layout/node_modules/lodash/_Uint8Array.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
var root = require('./_root');
|
||||
|
||||
/** Built-in value references. */
|
||||
var Uint8Array = root.Uint8Array;
|
||||
|
||||
module.exports = Uint8Array;
|
7
node_modules/dagre-layout/node_modules/lodash/_WeakMap.js
generated
vendored
Normal file
7
node_modules/dagre-layout/node_modules/lodash/_WeakMap.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
var getNative = require('./_getNative'),
|
||||
root = require('./_root');
|
||||
|
||||
/* Built-in method references that are verified to be native. */
|
||||
var WeakMap = getNative(root, 'WeakMap');
|
||||
|
||||
module.exports = WeakMap;
|
21
node_modules/dagre-layout/node_modules/lodash/_apply.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_apply.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* A faster alternative to `Function#apply`, this function invokes `func`
|
||||
* with the `this` binding of `thisArg` and the arguments of `args`.
|
||||
*
|
||||
* @private
|
||||
* @param {Function} func The function to invoke.
|
||||
* @param {*} thisArg The `this` binding of `func`.
|
||||
* @param {Array} args The arguments to invoke `func` with.
|
||||
* @returns {*} Returns the result of `func`.
|
||||
*/
|
||||
function apply(func, thisArg, args) {
|
||||
switch (args.length) {
|
||||
case 0: return func.call(thisArg);
|
||||
case 1: return func.call(thisArg, args[0]);
|
||||
case 2: return func.call(thisArg, args[0], args[1]);
|
||||
case 3: return func.call(thisArg, args[0], args[1], args[2]);
|
||||
}
|
||||
return func.apply(thisArg, args);
|
||||
}
|
||||
|
||||
module.exports = apply;
|
22
node_modules/dagre-layout/node_modules/lodash/_arrayAggregator.js
generated
vendored
Normal file
22
node_modules/dagre-layout/node_modules/lodash/_arrayAggregator.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* A specialized version of `baseAggregator` for arrays.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} setter The function to set `accumulator` values.
|
||||
* @param {Function} iteratee The iteratee to transform keys.
|
||||
* @param {Object} accumulator The initial aggregated object.
|
||||
* @returns {Function} Returns `accumulator`.
|
||||
*/
|
||||
function arrayAggregator(array, setter, iteratee, accumulator) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length;
|
||||
|
||||
while (++index < length) {
|
||||
var value = array[index];
|
||||
setter(accumulator, value, iteratee(value), array);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
module.exports = arrayAggregator;
|
22
node_modules/dagre-layout/node_modules/lodash/_arrayEach.js
generated
vendored
Normal file
22
node_modules/dagre-layout/node_modules/lodash/_arrayEach.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* A specialized version of `_.forEach` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array} Returns `array`.
|
||||
*/
|
||||
function arrayEach(array, iteratee) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length;
|
||||
|
||||
while (++index < length) {
|
||||
if (iteratee(array[index], index, array) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
module.exports = arrayEach;
|
21
node_modules/dagre-layout/node_modules/lodash/_arrayEachRight.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_arrayEachRight.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* A specialized version of `_.forEachRight` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array} Returns `array`.
|
||||
*/
|
||||
function arrayEachRight(array, iteratee) {
|
||||
var length = array == null ? 0 : array.length;
|
||||
|
||||
while (length--) {
|
||||
if (iteratee(array[length], length, array) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
module.exports = arrayEachRight;
|
23
node_modules/dagre-layout/node_modules/lodash/_arrayEvery.js
generated
vendored
Normal file
23
node_modules/dagre-layout/node_modules/lodash/_arrayEvery.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* A specialized version of `_.every` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
||||
* else `false`.
|
||||
*/
|
||||
function arrayEvery(array, predicate) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length;
|
||||
|
||||
while (++index < length) {
|
||||
if (!predicate(array[index], index, array)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = arrayEvery;
|
25
node_modules/dagre-layout/node_modules/lodash/_arrayFilter.js
generated
vendored
Normal file
25
node_modules/dagre-layout/node_modules/lodash/_arrayFilter.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* A specialized version of `_.filter` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @returns {Array} Returns the new filtered array.
|
||||
*/
|
||||
function arrayFilter(array, predicate) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length,
|
||||
resIndex = 0,
|
||||
result = [];
|
||||
|
||||
while (++index < length) {
|
||||
var value = array[index];
|
||||
if (predicate(value, index, array)) {
|
||||
result[resIndex++] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = arrayFilter;
|
17
node_modules/dagre-layout/node_modules/lodash/_arrayIncludes.js
generated
vendored
Normal file
17
node_modules/dagre-layout/node_modules/lodash/_arrayIncludes.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var baseIndexOf = require('./_baseIndexOf');
|
||||
|
||||
/**
|
||||
* A specialized version of `_.includes` for arrays without support for
|
||||
* specifying an index to search from.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to inspect.
|
||||
* @param {*} target The value to search for.
|
||||
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
||||
*/
|
||||
function arrayIncludes(array, value) {
|
||||
var length = array == null ? 0 : array.length;
|
||||
return !!length && baseIndexOf(array, value, 0) > -1;
|
||||
}
|
||||
|
||||
module.exports = arrayIncludes;
|
22
node_modules/dagre-layout/node_modules/lodash/_arrayIncludesWith.js
generated
vendored
Normal file
22
node_modules/dagre-layout/node_modules/lodash/_arrayIncludesWith.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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 (++index < length) {
|
||||
if (comparator(value, array[index])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = arrayIncludesWith;
|
49
node_modules/dagre-layout/node_modules/lodash/_arrayLikeKeys.js
generated
vendored
Normal file
49
node_modules/dagre-layout/node_modules/lodash/_arrayLikeKeys.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
var baseTimes = require('./_baseTimes'),
|
||||
isArguments = require('./isArguments'),
|
||||
isArray = require('./isArray'),
|
||||
isBuffer = require('./isBuffer'),
|
||||
isIndex = require('./_isIndex'),
|
||||
isTypedArray = require('./isTypedArray');
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto = Object.prototype;
|
||||
|
||||
/** Used to check objects for own properties. */
|
||||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Creates an array of the enumerable property names of the array-like `value`.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to query.
|
||||
* @param {boolean} inherited Specify returning inherited property names.
|
||||
* @returns {Array} Returns the array of property names.
|
||||
*/
|
||||
function arrayLikeKeys(value, inherited) {
|
||||
var isArr = isArray(value),
|
||||
isArg = !isArr && isArguments(value),
|
||||
isBuff = !isArr && !isArg && isBuffer(value),
|
||||
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
|
||||
skipIndexes = isArr || isArg || isBuff || isType,
|
||||
result = skipIndexes ? baseTimes(value.length, String) : [],
|
||||
length = result.length;
|
||||
|
||||
for (var key in value) {
|
||||
if ((inherited || hasOwnProperty.call(value, key)) &&
|
||||
!(skipIndexes && (
|
||||
// Safari 9 has enumerable `arguments.length` in strict mode.
|
||||
key == 'length' ||
|
||||
// Node.js 0.10 has enumerable non-index properties on buffers.
|
||||
(isBuff && (key == 'offset' || key == 'parent')) ||
|
||||
// PhantomJS 2 has enumerable non-index properties on typed arrays.
|
||||
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
|
||||
// Skip index properties.
|
||||
isIndex(key, length)
|
||||
))) {
|
||||
result.push(key);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = arrayLikeKeys;
|
21
node_modules/dagre-layout/node_modules/lodash/_arrayMap.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_arrayMap.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* A specialized version of `_.map` for arrays without support for iteratee
|
||||
* shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array} Returns the new mapped array.
|
||||
*/
|
||||
function arrayMap(array, iteratee) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length,
|
||||
result = Array(length);
|
||||
|
||||
while (++index < length) {
|
||||
result[index] = iteratee(array[index], index, array);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = arrayMap;
|
20
node_modules/dagre-layout/node_modules/lodash/_arrayPush.js
generated
vendored
Normal file
20
node_modules/dagre-layout/node_modules/lodash/_arrayPush.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Appends the elements of `values` to `array`.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to modify.
|
||||
* @param {Array} values The values to append.
|
||||
* @returns {Array} Returns `array`.
|
||||
*/
|
||||
function arrayPush(array, values) {
|
||||
var index = -1,
|
||||
length = values.length,
|
||||
offset = array.length;
|
||||
|
||||
while (++index < length) {
|
||||
array[offset + index] = values[index];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
module.exports = arrayPush;
|
26
node_modules/dagre-layout/node_modules/lodash/_arrayReduce.js
generated
vendored
Normal file
26
node_modules/dagre-layout/node_modules/lodash/_arrayReduce.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* A specialized version of `_.reduce` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @param {*} [accumulator] The initial value.
|
||||
* @param {boolean} [initAccum] Specify using the first element of `array` as
|
||||
* the initial value.
|
||||
* @returns {*} Returns the accumulated value.
|
||||
*/
|
||||
function arrayReduce(array, iteratee, accumulator, initAccum) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length;
|
||||
|
||||
if (initAccum && length) {
|
||||
accumulator = array[++index];
|
||||
}
|
||||
while (++index < length) {
|
||||
accumulator = iteratee(accumulator, array[index], index, array);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
module.exports = arrayReduce;
|
24
node_modules/dagre-layout/node_modules/lodash/_arrayReduceRight.js
generated
vendored
Normal file
24
node_modules/dagre-layout/node_modules/lodash/_arrayReduceRight.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* A specialized version of `_.reduceRight` for arrays without support for
|
||||
* iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @param {*} [accumulator] The initial value.
|
||||
* @param {boolean} [initAccum] Specify using the last element of `array` as
|
||||
* the initial value.
|
||||
* @returns {*} Returns the accumulated value.
|
||||
*/
|
||||
function arrayReduceRight(array, iteratee, accumulator, initAccum) {
|
||||
var length = array == null ? 0 : array.length;
|
||||
if (initAccum && length) {
|
||||
accumulator = array[--length];
|
||||
}
|
||||
while (length--) {
|
||||
accumulator = iteratee(accumulator, array[length], length, array);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
module.exports = arrayReduceRight;
|
15
node_modules/dagre-layout/node_modules/lodash/_arraySample.js
generated
vendored
Normal file
15
node_modules/dagre-layout/node_modules/lodash/_arraySample.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var baseRandom = require('./_baseRandom');
|
||||
|
||||
/**
|
||||
* A specialized version of `_.sample` for arrays.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to sample.
|
||||
* @returns {*} Returns the random element.
|
||||
*/
|
||||
function arraySample(array) {
|
||||
var length = array.length;
|
||||
return length ? array[baseRandom(0, length - 1)] : undefined;
|
||||
}
|
||||
|
||||
module.exports = arraySample;
|
17
node_modules/dagre-layout/node_modules/lodash/_arraySampleSize.js
generated
vendored
Normal file
17
node_modules/dagre-layout/node_modules/lodash/_arraySampleSize.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var baseClamp = require('./_baseClamp'),
|
||||
copyArray = require('./_copyArray'),
|
||||
shuffleSelf = require('./_shuffleSelf');
|
||||
|
||||
/**
|
||||
* A specialized version of `_.sampleSize` for arrays.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to sample.
|
||||
* @param {number} n The number of elements to sample.
|
||||
* @returns {Array} Returns the random elements.
|
||||
*/
|
||||
function arraySampleSize(array, n) {
|
||||
return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
|
||||
}
|
||||
|
||||
module.exports = arraySampleSize;
|
15
node_modules/dagre-layout/node_modules/lodash/_arrayShuffle.js
generated
vendored
Normal file
15
node_modules/dagre-layout/node_modules/lodash/_arrayShuffle.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var copyArray = require('./_copyArray'),
|
||||
shuffleSelf = require('./_shuffleSelf');
|
||||
|
||||
/**
|
||||
* A specialized version of `_.shuffle` for arrays.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to shuffle.
|
||||
* @returns {Array} Returns the new shuffled array.
|
||||
*/
|
||||
function arrayShuffle(array) {
|
||||
return shuffleSelf(copyArray(array));
|
||||
}
|
||||
|
||||
module.exports = arrayShuffle;
|
23
node_modules/dagre-layout/node_modules/lodash/_arraySome.js
generated
vendored
Normal file
23
node_modules/dagre-layout/node_modules/lodash/_arraySome.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* A specialized version of `_.some` for arrays without support for iteratee
|
||||
* shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
||||
* else `false`.
|
||||
*/
|
||||
function arraySome(array, predicate) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length;
|
||||
|
||||
while (++index < length) {
|
||||
if (predicate(array[index], index, array)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = arraySome;
|
12
node_modules/dagre-layout/node_modules/lodash/_asciiSize.js
generated
vendored
Normal file
12
node_modules/dagre-layout/node_modules/lodash/_asciiSize.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
var baseProperty = require('./_baseProperty');
|
||||
|
||||
/**
|
||||
* Gets the size of an ASCII `string`.
|
||||
*
|
||||
* @private
|
||||
* @param {string} string The string inspect.
|
||||
* @returns {number} Returns the string size.
|
||||
*/
|
||||
var asciiSize = baseProperty('length');
|
||||
|
||||
module.exports = asciiSize;
|
12
node_modules/dagre-layout/node_modules/lodash/_asciiToArray.js
generated
vendored
Normal file
12
node_modules/dagre-layout/node_modules/lodash/_asciiToArray.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Converts an ASCII `string` to an array.
|
||||
*
|
||||
* @private
|
||||
* @param {string} string The string to convert.
|
||||
* @returns {Array} Returns the converted array.
|
||||
*/
|
||||
function asciiToArray(string) {
|
||||
return string.split('');
|
||||
}
|
||||
|
||||
module.exports = asciiToArray;
|
15
node_modules/dagre-layout/node_modules/lodash/_asciiWords.js
generated
vendored
Normal file
15
node_modules/dagre-layout/node_modules/lodash/_asciiWords.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/** Used to match words composed of alphanumeric characters. */
|
||||
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
||||
|
||||
/**
|
||||
* Splits an ASCII `string` into an array of its words.
|
||||
*
|
||||
* @private
|
||||
* @param {string} The string to inspect.
|
||||
* @returns {Array} Returns the words of `string`.
|
||||
*/
|
||||
function asciiWords(string) {
|
||||
return string.match(reAsciiWord) || [];
|
||||
}
|
||||
|
||||
module.exports = asciiWords;
|
20
node_modules/dagre-layout/node_modules/lodash/_assignMergeValue.js
generated
vendored
Normal file
20
node_modules/dagre-layout/node_modules/lodash/_assignMergeValue.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var baseAssignValue = require('./_baseAssignValue'),
|
||||
eq = require('./eq');
|
||||
|
||||
/**
|
||||
* This function is like `assignValue` except that it doesn't assign
|
||||
* `undefined` values.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to modify.
|
||||
* @param {string} key The key of the property to assign.
|
||||
* @param {*} value The value to assign.
|
||||
*/
|
||||
function assignMergeValue(object, key, value) {
|
||||
if ((value !== undefined && !eq(object[key], value)) ||
|
||||
(value === undefined && !(key in object))) {
|
||||
baseAssignValue(object, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = assignMergeValue;
|
28
node_modules/dagre-layout/node_modules/lodash/_assignValue.js
generated
vendored
Normal file
28
node_modules/dagre-layout/node_modules/lodash/_assignValue.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
var baseAssignValue = require('./_baseAssignValue'),
|
||||
eq = require('./eq');
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto = Object.prototype;
|
||||
|
||||
/** Used to check objects for own properties. */
|
||||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Assigns `value` to `key` of `object` if the existing value is not equivalent
|
||||
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
||||
* for equality comparisons.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to modify.
|
||||
* @param {string} key The key of the property to assign.
|
||||
* @param {*} value The value to assign.
|
||||
*/
|
||||
function assignValue(object, key, value) {
|
||||
var objValue = object[key];
|
||||
if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
|
||||
(value === undefined && !(key in object))) {
|
||||
baseAssignValue(object, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = assignValue;
|
21
node_modules/dagre-layout/node_modules/lodash/_assocIndexOf.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_assocIndexOf.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var eq = require('./eq');
|
||||
|
||||
/**
|
||||
* Gets the index at which the `key` is found in `array` of key-value pairs.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to inspect.
|
||||
* @param {*} key The key to search for.
|
||||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||||
*/
|
||||
function assocIndexOf(array, key) {
|
||||
var length = array.length;
|
||||
while (length--) {
|
||||
if (eq(array[length][0], key)) {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
module.exports = assocIndexOf;
|
21
node_modules/dagre-layout/node_modules/lodash/_baseAggregator.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_baseAggregator.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var baseEach = require('./_baseEach');
|
||||
|
||||
/**
|
||||
* Aggregates elements of `collection` on `accumulator` with keys transformed
|
||||
* by `iteratee` and values set by `setter`.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to iterate over.
|
||||
* @param {Function} setter The function to set `accumulator` values.
|
||||
* @param {Function} iteratee The iteratee to transform keys.
|
||||
* @param {Object} accumulator The initial aggregated object.
|
||||
* @returns {Function} Returns `accumulator`.
|
||||
*/
|
||||
function baseAggregator(collection, setter, iteratee, accumulator) {
|
||||
baseEach(collection, function(value, key, collection) {
|
||||
setter(accumulator, value, iteratee(value), collection);
|
||||
});
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
module.exports = baseAggregator;
|
17
node_modules/dagre-layout/node_modules/lodash/_baseAssign.js
generated
vendored
Normal file
17
node_modules/dagre-layout/node_modules/lodash/_baseAssign.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var copyObject = require('./_copyObject'),
|
||||
keys = require('./keys');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.assign` without support for multiple sources
|
||||
* or `customizer` functions.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The destination object.
|
||||
* @param {Object} source The source object.
|
||||
* @returns {Object} Returns `object`.
|
||||
*/
|
||||
function baseAssign(object, source) {
|
||||
return object && copyObject(source, keys(source), object);
|
||||
}
|
||||
|
||||
module.exports = baseAssign;
|
17
node_modules/dagre-layout/node_modules/lodash/_baseAssignIn.js
generated
vendored
Normal file
17
node_modules/dagre-layout/node_modules/lodash/_baseAssignIn.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var copyObject = require('./_copyObject'),
|
||||
keysIn = require('./keysIn');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.assignIn` without support for multiple sources
|
||||
* or `customizer` functions.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The destination object.
|
||||
* @param {Object} source The source object.
|
||||
* @returns {Object} Returns `object`.
|
||||
*/
|
||||
function baseAssignIn(object, source) {
|
||||
return object && copyObject(source, keysIn(source), object);
|
||||
}
|
||||
|
||||
module.exports = baseAssignIn;
|
25
node_modules/dagre-layout/node_modules/lodash/_baseAssignValue.js
generated
vendored
Normal file
25
node_modules/dagre-layout/node_modules/lodash/_baseAssignValue.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
var defineProperty = require('./_defineProperty');
|
||||
|
||||
/**
|
||||
* The base implementation of `assignValue` and `assignMergeValue` without
|
||||
* value checks.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to modify.
|
||||
* @param {string} key The key of the property to assign.
|
||||
* @param {*} value The value to assign.
|
||||
*/
|
||||
function baseAssignValue(object, key, value) {
|
||||
if (key == '__proto__' && defineProperty) {
|
||||
defineProperty(object, key, {
|
||||
'configurable': true,
|
||||
'enumerable': true,
|
||||
'value': value,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
object[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = baseAssignValue;
|
23
node_modules/dagre-layout/node_modules/lodash/_baseAt.js
generated
vendored
Normal file
23
node_modules/dagre-layout/node_modules/lodash/_baseAt.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
var get = require('./get');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.at` without support for individual paths.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to iterate over.
|
||||
* @param {string[]} paths The property paths to pick.
|
||||
* @returns {Array} Returns the picked elements.
|
||||
*/
|
||||
function baseAt(object, paths) {
|
||||
var index = -1,
|
||||
length = paths.length,
|
||||
result = Array(length),
|
||||
skip = object == null;
|
||||
|
||||
while (++index < length) {
|
||||
result[index] = skip ? undefined : get(object, paths[index]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseAt;
|
22
node_modules/dagre-layout/node_modules/lodash/_baseClamp.js
generated
vendored
Normal file
22
node_modules/dagre-layout/node_modules/lodash/_baseClamp.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* The base implementation of `_.clamp` which doesn't coerce arguments.
|
||||
*
|
||||
* @private
|
||||
* @param {number} number The number to clamp.
|
||||
* @param {number} [lower] The lower bound.
|
||||
* @param {number} upper The upper bound.
|
||||
* @returns {number} Returns the clamped number.
|
||||
*/
|
||||
function baseClamp(number, lower, upper) {
|
||||
if (number === number) {
|
||||
if (upper !== undefined) {
|
||||
number = number <= upper ? number : upper;
|
||||
}
|
||||
if (lower !== undefined) {
|
||||
number = number >= lower ? number : lower;
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
module.exports = baseClamp;
|
166
node_modules/dagre-layout/node_modules/lodash/_baseClone.js
generated
vendored
Normal file
166
node_modules/dagre-layout/node_modules/lodash/_baseClone.js
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
var Stack = require('./_Stack'),
|
||||
arrayEach = require('./_arrayEach'),
|
||||
assignValue = require('./_assignValue'),
|
||||
baseAssign = require('./_baseAssign'),
|
||||
baseAssignIn = require('./_baseAssignIn'),
|
||||
cloneBuffer = require('./_cloneBuffer'),
|
||||
copyArray = require('./_copyArray'),
|
||||
copySymbols = require('./_copySymbols'),
|
||||
copySymbolsIn = require('./_copySymbolsIn'),
|
||||
getAllKeys = require('./_getAllKeys'),
|
||||
getAllKeysIn = require('./_getAllKeysIn'),
|
||||
getTag = require('./_getTag'),
|
||||
initCloneArray = require('./_initCloneArray'),
|
||||
initCloneByTag = require('./_initCloneByTag'),
|
||||
initCloneObject = require('./_initCloneObject'),
|
||||
isArray = require('./isArray'),
|
||||
isBuffer = require('./isBuffer'),
|
||||
isMap = require('./isMap'),
|
||||
isObject = require('./isObject'),
|
||||
isSet = require('./isSet'),
|
||||
keys = require('./keys'),
|
||||
keysIn = require('./keysIn');
|
||||
|
||||
/** Used to compose bitmasks for cloning. */
|
||||
var CLONE_DEEP_FLAG = 1,
|
||||
CLONE_FLAT_FLAG = 2,
|
||||
CLONE_SYMBOLS_FLAG = 4;
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
var argsTag = '[object Arguments]',
|
||||
arrayTag = '[object Array]',
|
||||
boolTag = '[object Boolean]',
|
||||
dateTag = '[object Date]',
|
||||
errorTag = '[object Error]',
|
||||
funcTag = '[object Function]',
|
||||
genTag = '[object GeneratorFunction]',
|
||||
mapTag = '[object Map]',
|
||||
numberTag = '[object Number]',
|
||||
objectTag = '[object Object]',
|
||||
regexpTag = '[object RegExp]',
|
||||
setTag = '[object Set]',
|
||||
stringTag = '[object String]',
|
||||
symbolTag = '[object Symbol]',
|
||||
weakMapTag = '[object WeakMap]';
|
||||
|
||||
var arrayBufferTag = '[object ArrayBuffer]',
|
||||
dataViewTag = '[object DataView]',
|
||||
float32Tag = '[object Float32Array]',
|
||||
float64Tag = '[object Float64Array]',
|
||||
int8Tag = '[object Int8Array]',
|
||||
int16Tag = '[object Int16Array]',
|
||||
int32Tag = '[object Int32Array]',
|
||||
uint8Tag = '[object Uint8Array]',
|
||||
uint8ClampedTag = '[object Uint8ClampedArray]',
|
||||
uint16Tag = '[object Uint16Array]',
|
||||
uint32Tag = '[object Uint32Array]';
|
||||
|
||||
/** Used to identify `toStringTag` values supported by `_.clone`. */
|
||||
var cloneableTags = {};
|
||||
cloneableTags[argsTag] = cloneableTags[arrayTag] =
|
||||
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
|
||||
cloneableTags[boolTag] = cloneableTags[dateTag] =
|
||||
cloneableTags[float32Tag] = cloneableTags[float64Tag] =
|
||||
cloneableTags[int8Tag] = cloneableTags[int16Tag] =
|
||||
cloneableTags[int32Tag] = cloneableTags[mapTag] =
|
||||
cloneableTags[numberTag] = cloneableTags[objectTag] =
|
||||
cloneableTags[regexpTag] = cloneableTags[setTag] =
|
||||
cloneableTags[stringTag] = cloneableTags[symbolTag] =
|
||||
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
|
||||
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
||||
cloneableTags[errorTag] = cloneableTags[funcTag] =
|
||||
cloneableTags[weakMapTag] = false;
|
||||
|
||||
/**
|
||||
* The base implementation of `_.clone` and `_.cloneDeep` which tracks
|
||||
* traversed objects.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to clone.
|
||||
* @param {boolean} bitmask The bitmask flags.
|
||||
* 1 - Deep clone
|
||||
* 2 - Flatten inherited properties
|
||||
* 4 - Clone symbols
|
||||
* @param {Function} [customizer] The function to customize cloning.
|
||||
* @param {string} [key] The key of `value`.
|
||||
* @param {Object} [object] The parent object of `value`.
|
||||
* @param {Object} [stack] Tracks traversed objects and their clone counterparts.
|
||||
* @returns {*} Returns the cloned value.
|
||||
*/
|
||||
function baseClone(value, bitmask, customizer, key, object, stack) {
|
||||
var result,
|
||||
isDeep = bitmask & CLONE_DEEP_FLAG,
|
||||
isFlat = bitmask & CLONE_FLAT_FLAG,
|
||||
isFull = bitmask & CLONE_SYMBOLS_FLAG;
|
||||
|
||||
if (customizer) {
|
||||
result = object ? customizer(value, key, object, stack) : customizer(value);
|
||||
}
|
||||
if (result !== undefined) {
|
||||
return result;
|
||||
}
|
||||
if (!isObject(value)) {
|
||||
return value;
|
||||
}
|
||||
var isArr = isArray(value);
|
||||
if (isArr) {
|
||||
result = initCloneArray(value);
|
||||
if (!isDeep) {
|
||||
return copyArray(value, result);
|
||||
}
|
||||
} else {
|
||||
var tag = getTag(value),
|
||||
isFunc = tag == funcTag || tag == genTag;
|
||||
|
||||
if (isBuffer(value)) {
|
||||
return cloneBuffer(value, isDeep);
|
||||
}
|
||||
if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
|
||||
result = (isFlat || isFunc) ? {} : initCloneObject(value);
|
||||
if (!isDeep) {
|
||||
return isFlat
|
||||
? copySymbolsIn(value, baseAssignIn(result, value))
|
||||
: copySymbols(value, baseAssign(result, value));
|
||||
}
|
||||
} else {
|
||||
if (!cloneableTags[tag]) {
|
||||
return object ? value : {};
|
||||
}
|
||||
result = initCloneByTag(value, tag, isDeep);
|
||||
}
|
||||
}
|
||||
// Check for circular references and return its corresponding clone.
|
||||
stack || (stack = new Stack);
|
||||
var stacked = stack.get(value);
|
||||
if (stacked) {
|
||||
return stacked;
|
||||
}
|
||||
stack.set(value, result);
|
||||
|
||||
if (isSet(value)) {
|
||||
value.forEach(function(subValue) {
|
||||
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
|
||||
});
|
||||
} else if (isMap(value)) {
|
||||
value.forEach(function(subValue, key) {
|
||||
result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
|
||||
});
|
||||
}
|
||||
|
||||
var keysFunc = isFull
|
||||
? (isFlat ? getAllKeysIn : getAllKeys)
|
||||
: (isFlat ? keysIn : keys);
|
||||
|
||||
var props = isArr ? undefined : keysFunc(value);
|
||||
arrayEach(props || value, function(subValue, key) {
|
||||
if (props) {
|
||||
key = subValue;
|
||||
subValue = value[key];
|
||||
}
|
||||
// Recursively populate clone (susceptible to call stack limits).
|
||||
assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseClone;
|
18
node_modules/dagre-layout/node_modules/lodash/_baseConforms.js
generated
vendored
Normal file
18
node_modules/dagre-layout/node_modules/lodash/_baseConforms.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
var baseConformsTo = require('./_baseConformsTo'),
|
||||
keys = require('./keys');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.conforms` which doesn't clone `source`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} source The object of property predicates to conform to.
|
||||
* @returns {Function} Returns the new spec function.
|
||||
*/
|
||||
function baseConforms(source) {
|
||||
var props = keys(source);
|
||||
return function(object) {
|
||||
return baseConformsTo(object, source, props);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = baseConforms;
|
27
node_modules/dagre-layout/node_modules/lodash/_baseConformsTo.js
generated
vendored
Normal file
27
node_modules/dagre-layout/node_modules/lodash/_baseConformsTo.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* The base implementation of `_.conformsTo` which accepts `props` to check.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to inspect.
|
||||
* @param {Object} source The object of property predicates to conform to.
|
||||
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
|
||||
*/
|
||||
function baseConformsTo(object, source, props) {
|
||||
var length = props.length;
|
||||
if (object == null) {
|
||||
return !length;
|
||||
}
|
||||
object = Object(object);
|
||||
while (length--) {
|
||||
var key = props[length],
|
||||
predicate = source[key],
|
||||
value = object[key];
|
||||
|
||||
if ((value === undefined && !(key in object)) || !predicate(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = baseConformsTo;
|
30
node_modules/dagre-layout/node_modules/lodash/_baseCreate.js
generated
vendored
Normal file
30
node_modules/dagre-layout/node_modules/lodash/_baseCreate.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
var isObject = require('./isObject');
|
||||
|
||||
/** Built-in value references. */
|
||||
var objectCreate = Object.create;
|
||||
|
||||
/**
|
||||
* The base implementation of `_.create` without support for assigning
|
||||
* properties to the created object.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} proto The object to inherit from.
|
||||
* @returns {Object} Returns the new object.
|
||||
*/
|
||||
var baseCreate = (function() {
|
||||
function object() {}
|
||||
return function(proto) {
|
||||
if (!isObject(proto)) {
|
||||
return {};
|
||||
}
|
||||
if (objectCreate) {
|
||||
return objectCreate(proto);
|
||||
}
|
||||
object.prototype = proto;
|
||||
var result = new object;
|
||||
object.prototype = undefined;
|
||||
return result;
|
||||
};
|
||||
}());
|
||||
|
||||
module.exports = baseCreate;
|
21
node_modules/dagre-layout/node_modules/lodash/_baseDelay.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_baseDelay.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/** Error message constants. */
|
||||
var FUNC_ERROR_TEXT = 'Expected a function';
|
||||
|
||||
/**
|
||||
* The base implementation of `_.delay` and `_.defer` which accepts `args`
|
||||
* to provide to `func`.
|
||||
*
|
||||
* @private
|
||||
* @param {Function} func The function to delay.
|
||||
* @param {number} wait The number of milliseconds to delay invocation.
|
||||
* @param {Array} args The arguments to provide to `func`.
|
||||
* @returns {number|Object} Returns the timer id or timeout object.
|
||||
*/
|
||||
function baseDelay(func, wait, args) {
|
||||
if (typeof func != 'function') {
|
||||
throw new TypeError(FUNC_ERROR_TEXT);
|
||||
}
|
||||
return setTimeout(function() { func.apply(undefined, args); }, wait);
|
||||
}
|
||||
|
||||
module.exports = baseDelay;
|
67
node_modules/dagre-layout/node_modules/lodash/_baseDifference.js
generated
vendored
Normal file
67
node_modules/dagre-layout/node_modules/lodash/_baseDifference.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
var SetCache = require('./_SetCache'),
|
||||
arrayIncludes = require('./_arrayIncludes'),
|
||||
arrayIncludesWith = require('./_arrayIncludesWith'),
|
||||
arrayMap = require('./_arrayMap'),
|
||||
baseUnary = require('./_baseUnary'),
|
||||
cacheHas = require('./_cacheHas');
|
||||
|
||||
/** Used as the size to enable large array optimizations. */
|
||||
var LARGE_ARRAY_SIZE = 200;
|
||||
|
||||
/**
|
||||
* The base implementation of methods like `_.difference` without support
|
||||
* for excluding multiple arrays or iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to inspect.
|
||||
* @param {Array} values The values to exclude.
|
||||
* @param {Function} [iteratee] The iteratee invoked per element.
|
||||
* @param {Function} [comparator] The comparator invoked per element.
|
||||
* @returns {Array} Returns the new array of filtered values.
|
||||
*/
|
||||
function baseDifference(array, values, iteratee, comparator) {
|
||||
var index = -1,
|
||||
includes = arrayIncludes,
|
||||
isCommon = true,
|
||||
length = array.length,
|
||||
result = [],
|
||||
valuesLength = values.length;
|
||||
|
||||
if (!length) {
|
||||
return result;
|
||||
}
|
||||
if (iteratee) {
|
||||
values = arrayMap(values, baseUnary(iteratee));
|
||||
}
|
||||
if (comparator) {
|
||||
includes = arrayIncludesWith;
|
||||
isCommon = false;
|
||||
}
|
||||
else if (values.length >= LARGE_ARRAY_SIZE) {
|
||||
includes = cacheHas;
|
||||
isCommon = false;
|
||||
values = new SetCache(values);
|
||||
}
|
||||
outer:
|
||||
while (++index < length) {
|
||||
var value = array[index],
|
||||
computed = iteratee == null ? value : iteratee(value);
|
||||
|
||||
value = (comparator || value !== 0) ? value : 0;
|
||||
if (isCommon && computed === computed) {
|
||||
var valuesIndex = valuesLength;
|
||||
while (valuesIndex--) {
|
||||
if (values[valuesIndex] === computed) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
result.push(value);
|
||||
}
|
||||
else if (!includes(values, computed, comparator)) {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseDifference;
|
14
node_modules/dagre-layout/node_modules/lodash/_baseEach.js
generated
vendored
Normal file
14
node_modules/dagre-layout/node_modules/lodash/_baseEach.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
var baseForOwn = require('./_baseForOwn'),
|
||||
createBaseEach = require('./_createBaseEach');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.forEach` without support for iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array|Object} Returns `collection`.
|
||||
*/
|
||||
var baseEach = createBaseEach(baseForOwn);
|
||||
|
||||
module.exports = baseEach;
|
14
node_modules/dagre-layout/node_modules/lodash/_baseEachRight.js
generated
vendored
Normal file
14
node_modules/dagre-layout/node_modules/lodash/_baseEachRight.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
var baseForOwnRight = require('./_baseForOwnRight'),
|
||||
createBaseEach = require('./_createBaseEach');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.forEachRight` without support for iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array|Object} Returns `collection`.
|
||||
*/
|
||||
var baseEachRight = createBaseEach(baseForOwnRight, true);
|
||||
|
||||
module.exports = baseEachRight;
|
21
node_modules/dagre-layout/node_modules/lodash/_baseEvery.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_baseEvery.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var baseEach = require('./_baseEach');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.every` without support for iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to iterate over.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
||||
* else `false`
|
||||
*/
|
||||
function baseEvery(collection, predicate) {
|
||||
var result = true;
|
||||
baseEach(collection, function(value, index, collection) {
|
||||
result = !!predicate(value, index, collection);
|
||||
return result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseEvery;
|
32
node_modules/dagre-layout/node_modules/lodash/_baseExtremum.js
generated
vendored
Normal file
32
node_modules/dagre-layout/node_modules/lodash/_baseExtremum.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var isSymbol = require('./isSymbol');
|
||||
|
||||
/**
|
||||
* The base implementation of methods like `_.max` and `_.min` which accepts a
|
||||
* `comparator` to determine the extremum value.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to iterate over.
|
||||
* @param {Function} iteratee The iteratee invoked per iteration.
|
||||
* @param {Function} comparator The comparator used to compare values.
|
||||
* @returns {*} Returns the extremum value.
|
||||
*/
|
||||
function baseExtremum(array, iteratee, comparator) {
|
||||
var index = -1,
|
||||
length = array.length;
|
||||
|
||||
while (++index < length) {
|
||||
var value = array[index],
|
||||
current = iteratee(value);
|
||||
|
||||
if (current != null && (computed === undefined
|
||||
? (current === current && !isSymbol(current))
|
||||
: comparator(current, computed)
|
||||
)) {
|
||||
var computed = current,
|
||||
result = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseExtremum;
|
32
node_modules/dagre-layout/node_modules/lodash/_baseFill.js
generated
vendored
Normal file
32
node_modules/dagre-layout/node_modules/lodash/_baseFill.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var toInteger = require('./toInteger'),
|
||||
toLength = require('./toLength');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.fill` without an iteratee call guard.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to fill.
|
||||
* @param {*} value The value to fill `array` with.
|
||||
* @param {number} [start=0] The start position.
|
||||
* @param {number} [end=array.length] The end position.
|
||||
* @returns {Array} Returns `array`.
|
||||
*/
|
||||
function baseFill(array, value, start, end) {
|
||||
var length = array.length;
|
||||
|
||||
start = toInteger(start);
|
||||
if (start < 0) {
|
||||
start = -start > length ? 0 : (length + start);
|
||||
}
|
||||
end = (end === undefined || end > length) ? length : toInteger(end);
|
||||
if (end < 0) {
|
||||
end += length;
|
||||
}
|
||||
end = start > end ? 0 : toLength(end);
|
||||
while (start < end) {
|
||||
array[start++] = value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
module.exports = baseFill;
|
21
node_modules/dagre-layout/node_modules/lodash/_baseFilter.js
generated
vendored
Normal file
21
node_modules/dagre-layout/node_modules/lodash/_baseFilter.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var baseEach = require('./_baseEach');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.filter` without support for iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to iterate over.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @returns {Array} Returns the new filtered array.
|
||||
*/
|
||||
function baseFilter(collection, predicate) {
|
||||
var result = [];
|
||||
baseEach(collection, function(value, index, collection) {
|
||||
if (predicate(value, index, collection)) {
|
||||
result.push(value);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseFilter;
|
24
node_modules/dagre-layout/node_modules/lodash/_baseFindIndex.js
generated
vendored
Normal file
24
node_modules/dagre-layout/node_modules/lodash/_baseFindIndex.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* The base implementation of `_.findIndex` and `_.findLastIndex` without
|
||||
* support for iteratee shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to inspect.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @param {number} fromIndex The index to search from.
|
||||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||||
*/
|
||||
function baseFindIndex(array, predicate, fromIndex, fromRight) {
|
||||
var length = array.length,
|
||||
index = fromIndex + (fromRight ? 1 : -1);
|
||||
|
||||
while ((fromRight ? index-- : ++index < length)) {
|
||||
if (predicate(array[index], index, array)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
module.exports = baseFindIndex;
|
23
node_modules/dagre-layout/node_modules/lodash/_baseFindKey.js
generated
vendored
Normal file
23
node_modules/dagre-layout/node_modules/lodash/_baseFindKey.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The base implementation of methods like `_.findKey` and `_.findLastKey`,
|
||||
* without support for iteratee shorthands, which iterates over `collection`
|
||||
* using `eachFunc`.
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Object} collection The collection to inspect.
|
||||
* @param {Function} predicate The function invoked per iteration.
|
||||
* @param {Function} eachFunc The function to iterate over `collection`.
|
||||
* @returns {*} Returns the found element or its key, else `undefined`.
|
||||
*/
|
||||
function baseFindKey(collection, predicate, eachFunc) {
|
||||
var result;
|
||||
eachFunc(collection, function(value, key, collection) {
|
||||
if (predicate(value, key, collection)) {
|
||||
result = key;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = baseFindKey;
|
38
node_modules/dagre-layout/node_modules/lodash/_baseFlatten.js
generated
vendored
Normal file
38
node_modules/dagre-layout/node_modules/lodash/_baseFlatten.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
var arrayPush = require('./_arrayPush'),
|
||||
isFlattenable = require('./_isFlattenable');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.flatten` with support for restricting flattening.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} array The array to flatten.
|
||||
* @param {number} depth The maximum recursion depth.
|
||||
* @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
|
||||
* @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
|
||||
* @param {Array} [result=[]] The initial result value.
|
||||
* @returns {Array} Returns the new flattened array.
|
||||
*/
|
||||
function baseFlatten(array, depth, predicate, isStrict, result) {
|
||||
var index = -1,
|
||||
length = array.length;
|
||||
|
||||
predicate || (predicate = isFlattenable);
|
||||
result || (result = []);
|
||||
|
||||
while (++index < length) {
|
||||
var value = array[index];
|
||||
if (depth > 0 && 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;
|
16
node_modules/dagre-layout/node_modules/lodash/_baseFor.js
generated
vendored
Normal file
16
node_modules/dagre-layout/node_modules/lodash/_baseFor.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
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;
|
16
node_modules/dagre-layout/node_modules/lodash/_baseForOwn.js
generated
vendored
Normal file
16
node_modules/dagre-layout/node_modules/lodash/_baseForOwn.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
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;
|
16
node_modules/dagre-layout/node_modules/lodash/_baseForOwnRight.js
generated
vendored
Normal file
16
node_modules/dagre-layout/node_modules/lodash/_baseForOwnRight.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
var baseForRight = require('./_baseForRight'),
|
||||
keys = require('./keys');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.forOwnRight` 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 baseForOwnRight(object, iteratee) {
|
||||
return object && baseForRight(object, iteratee, keys);
|
||||
}
|
||||
|
||||
module.exports = baseForOwnRight;
|
15
node_modules/dagre-layout/node_modules/lodash/_baseForRight.js
generated
vendored
Normal file
15
node_modules/dagre-layout/node_modules/lodash/_baseForRight.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var createBaseFor = require('./_createBaseFor');
|
||||
|
||||
/**
|
||||
* This function is like `baseFor` except that it iterates over properties
|
||||
* in the opposite order.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @param {Function} keysFunc The function to get the keys of `object`.
|
||||
* @returns {Object} Returns `object`.
|
||||
*/
|
||||
var baseForRight = createBaseFor(true);
|
||||
|
||||
module.exports = baseForRight;
|
19
node_modules/dagre-layout/node_modules/lodash/_baseFunctions.js
generated
vendored
Normal file
19
node_modules/dagre-layout/node_modules/lodash/_baseFunctions.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
var arrayFilter = require('./_arrayFilter'),
|
||||
isFunction = require('./isFunction');
|
||||
|
||||
/**
|
||||
* The base implementation of `_.functions` which creates an array of
|
||||
* `object` function property names filtered from `props`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to inspect.
|
||||
* @param {Array} props The property names to filter.
|
||||
* @returns {Array} Returns the function names.
|
||||
*/
|
||||
function baseFunctions(object, props) {
|
||||
return arrayFilter(props, function(key) {
|
||||
return isFunction(object[key]);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = baseFunctions;
|
24
node_modules/dagre-layout/node_modules/lodash/_baseGet.js
generated
vendored
Normal file
24
node_modules/dagre-layout/node_modules/lodash/_baseGet.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
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 && index < length) {
|
||||
object = object[toKey(path[index++])];
|
||||
}
|
||||
return (index && index == length) ? object : undefined;
|
||||
}
|
||||
|
||||
module.exports = baseGet;
|
20
node_modules/dagre-layout/node_modules/lodash/_baseGetAllKeys.js
generated
vendored
Normal file
20
node_modules/dagre-layout/node_modules/lodash/_baseGetAllKeys.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var arrayPush = require('./_arrayPush'),
|
||||
isArray = require('./isArray');
|
||||
|
||||
/**
|
||||
* The base implementation of `getAllKeys` and `getAllKeysIn` which uses
|
||||
* `keysFunc` and `symbolsFunc` to get the enumerable property names and
|
||||
* symbols of `object`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to query.
|
||||
* @param {Function} keysFunc The function to get the keys of `object`.
|
||||
* @param {Function} symbolsFunc The function to get the symbols of `object`.
|
||||
* @returns {Array} Returns the array of property names and symbols.
|
||||
*/
|
||||
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
|
||||
var result = keysFunc(object);
|
||||
return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
|
||||
}
|
||||
|
||||
module.exports = baseGetAllKeys;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user