08-27-周三_17-09-29

This commit is contained in:
2025-08-27 17:10:05 +08:00
commit 86df397d8f
12735 changed files with 1145479 additions and 0 deletions

71
node_modules/dagre-d3-renderer/lib/arrows.js generated vendored Normal file
View File

@@ -0,0 +1,71 @@
import util from './util'
function normal (parent, id, edge, type) {
const marker = parent.append('marker')
.attr('id', id)
.attr('viewBox', '0 0 10 10')
.attr('refX', 9)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('orient', 'auto')
const path = marker.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0')
util.applyStyle(path, edge[type + 'Style'])
if (edge[type + 'Class']) {
path.attr('class', edge[type + 'Class'])
}
}
function vee (parent, id, edge, type) {
const marker = parent.append('marker')
.attr('id', id)
.attr('viewBox', '0 0 10 10')
.attr('refX', 9)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('orient', 'auto')
const path = marker.append('path')
.attr('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0')
util.applyStyle(path, edge[type + 'Style'])
if (edge[type + 'Class']) {
path.attr('class', edge[type + 'Class'])
}
}
function undirected (parent, id, edge, type) {
const marker = parent.append('marker')
.attr('id', id)
.attr('viewBox', '0 0 10 10')
.attr('refX', 9)
.attr('refY', 5)
.attr('markerUnits', 'strokeWidth')
.attr('markerWidth', 8)
.attr('markerHeight', 6)
.attr('orient', 'auto')
const path = marker.append('path')
.attr('d', 'M 0 5 L 10 5')
.style('stroke-width', 1)
.style('stroke-dasharray', '1,0')
util.applyStyle(path, edge[type + 'Style'])
if (edge[type + 'Class']) {
path.attr('class', edge[type + 'Class'])
}
}
export default {
normal,
vee,
undirected,
default: normal
}

45
node_modules/dagre-d3-renderer/lib/create-clusters.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import d3 from 'd3'
import util from './util'
import addLabel from './label/add-label'
function createClusters (selection, g) {
const clusters = g.nodes().filter(function (v) { return util.isSubgraph(g, v) })
const svgClusters = selection.selectAll('g.cluster')
.data(clusters, function (v) { return v })
svgClusters.selectAll('*').remove()
svgClusters.enter()
.append('g')
.attr('class', 'cluster')
.attr('id', function (v) {
const node = g.node(v)
return node.id
})
.style('opacity', 0)
util.applyTransition(svgClusters, g)
.style('opacity', 1)
svgClusters.each(function (v) {
const node = g.node(v)
const thisGroup = d3.select(this)
d3.select(this).append('rect')
const labelGroup = thisGroup.append('g').attr('class', 'label')
addLabel(labelGroup, node, node.clusterLabelPos)
})
svgClusters.selectAll('rect').each(function (c) {
const node = g.node(c)
const domCluster = d3.select(this)
util.applyStyle(domCluster, node.style)
})
util.applyTransition(svgClusters.exit(), g)
.style('opacity', 0)
.remove()
return svgClusters
}
export default createClusters

View File

@@ -0,0 +1,34 @@
import d3 from 'd3'
import _ from 'lodash'
import addLabel from './label/add-label'
import util from './util'
function createEdgeLabels (selection, g) {
const svgEdgeLabels = selection.selectAll('g.edgeLabel')
.data(g.edges(), function (e) { return util.edgeToId(e) })
.classed('update', true)
svgEdgeLabels.selectAll('*').remove()
svgEdgeLabels.enter()
.append('g')
.classed('edgeLabel', true)
.style('opacity', 0)
svgEdgeLabels.each(function (e) {
const edge = g.edge(e)
const label = addLabel(d3.select(this), g.edge(e), 0, 0).classed('label', true)
const bbox = label.node().getBBox()
if (edge.labelId) { label.attr('id', edge.labelId) }
if (!_.has(edge, 'width')) { edge.width = bbox.width }
if (!_.has(edge, 'height')) { edge.height = bbox.height }
})
util.applyTransition(svgEdgeLabels.exit(), g)
.style('opacity', 0)
.remove()
return svgEdgeLabels
}
export default createEdgeLabels

131
node_modules/dagre-d3-renderer/lib/create-edge-paths.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
import d3 from 'd3'
import _ from 'lodash'
import intersectNode from './intersect/intersect-node'
import util from './util'
function createEdgePaths (selection, g, arrows) {
const svgPaths = selection.selectAll('g.edgePath')
.data(g.edges(), function (e) { return util.edgeToId(e) })
.classed('update', true)
enter(svgPaths, g)
exit(svgPaths, g)
util.applyTransition(svgPaths, g)
.style('opacity', 1)
// Save DOM element in the path group, and set ID and class
svgPaths.each(function (e) {
const domEdge = d3.select(this)
const edge = g.edge(e)
edge.elem = this
if (edge.id) {
domEdge.attr('id', edge.id)
}
util.applyClass(domEdge, edge['class'],
(domEdge.classed('update') ? 'update ' : '') + 'edgePath')
})
svgPaths.selectAll('path.path')
.each(function (e) {
const edge = g.edge(e)
edge.arrowheadId = _.uniqueId('arrowhead')
const domEdge = d3.select(this)
.attr('marker-end', function () {
return 'url(#' + edge.arrowheadId + ')'
})
.style('fill', 'none')
util.applyTransition(domEdge, g)
.attr('d', function (e) { return calcPoints(g, e) })
util.applyStyle(domEdge, edge.style)
})
svgPaths.selectAll('defs *').remove()
svgPaths.selectAll('defs')
.each(function (e) {
const edge = g.edge(e)
const arrowhead = arrows[edge.arrowhead]
arrowhead(d3.select(this), edge.arrowheadId, edge, 'arrowhead')
})
return svgPaths
}
function calcPoints (g, e) {
const edge = g.edge(e)
const tail = g.node(e.v)
const head = g.node(e.w)
const points = edge.points.slice(1, edge.points.length - 1)
points.unshift(intersectNode(tail, points[0]))
points.push(intersectNode(head, points[points.length - 1]))
return createLine(edge, points)
}
function createLine (edge, points) {
const line = d3.svg.line()
.x(function (d) { return d.x })
.y(function (d) { return d.y })
if (_.has(edge, 'lineInterpolate')) {
line.interpolate(edge.lineInterpolate)
}
if (_.has(edge, 'lineTension')) {
line.tension(Number(edge.lineTension))
}
return line(points)
}
function getCoords (elem) {
const bbox = elem.getBBox()
const matrix = elem.ownerSVGElement.getScreenCTM()
.inverse()
.multiply(elem.getScreenCTM())
.translate(bbox.width / 2, bbox.height / 2)
return { x: matrix.e, y: matrix.f }
}
function enter (svgPaths, g) {
const svgPathsEnter = svgPaths.enter()
.append('g')
.attr('class', 'edgePath')
.style('opacity', 0)
svgPathsEnter.append('path')
.attr('class', 'path')
.attr('d', function (e) {
const edge = g.edge(e)
const sourceElem = g.node(e.v).elem
const points = _.range(edge.points.length).map(function () { return getCoords(sourceElem) })
return createLine(edge, points)
})
svgPathsEnter.append('defs')
}
function exit (svgPaths, g) {
const svgPathExit = svgPaths.exit()
util.applyTransition(svgPathExit, g)
.style('opacity', 0)
.remove()
util.applyTransition(svgPathExit.select('path.path'), g)
.attr('d', function (e) {
const source = g.node(e.v)
if (source) {
const points = _.range(this.getTotalLength()).map(function () { return source })
return createLine({}, points)
} else {
return d3.select(this).attr('d')
}
})
}
export default createEdgePaths

57
node_modules/dagre-d3-renderer/lib/create-nodes.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
import _ from 'lodash'
import d3 from 'd3'
import addLabel from './label/add-label'
import util from './util'
function createNodes (selection, g, shapes) {
const simpleNodes = g.nodes().filter(function (v) { return !util.isSubgraph(g, v) })
const svgNodes = selection.selectAll('g.node')
.data(simpleNodes, function (v) { return v })
.classed('update', true)
svgNodes.selectAll('*').remove()
svgNodes.enter()
.append('g')
.attr('class', 'node')
.style('opacity', 0)
svgNodes.each(function (v) {
const node = g.node(v)
const thisGroup = d3.select(this)
const labelGroup = thisGroup.append('g').attr('class', 'label')
const labelDom = addLabel(labelGroup, node)
const shape = shapes[node.shape]
const bbox = _.pick(labelDom.node().getBBox(), 'width', 'height')
node.elem = this
if (node.id) { thisGroup.attr('id', node.id) }
if (node.labelId) { labelGroup.attr('id', node.labelId) }
util.applyClass(thisGroup, node['class'],
(thisGroup.classed('update') ? 'update ' : '') + 'node')
if (_.has(node, 'width')) { bbox.width = node.width }
if (_.has(node, 'height')) { bbox.height = node.height }
bbox.width += node.paddingLeft + node.paddingRight
bbox.height += node.paddingTop + node.paddingBottom
labelGroup.attr('transform', 'translate(' +
((node.paddingLeft - node.paddingRight) / 2) + ',' +
((node.paddingTop - node.paddingBottom) / 2) + ')')
const shapeSvg = shape(d3.select(this), bbox, node)
util.applyStyle(shapeSvg, node.style)
const shapeBBox = shapeSvg.node().getBBox()
node.width = shapeBBox.width
node.height = shapeBBox.height
})
util.applyTransition(svgNodes.exit(), g)
.style('opacity', 0)
.remove()
return svgNodes
}
export default createNodes

13
node_modules/dagre-d3-renderer/lib/intersect/index.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import node from './intersect-node'
import circle from './intersect-circle'
import ellipse from './intersect-ellipse'
import polygon from './intersect-polygon'
import rect from './intersect-rect'
export default {
node,
circle,
ellipse,
polygon,
rect
}

View File

@@ -0,0 +1,7 @@
import intersectEllipse from './intersect-ellipse'
function intersectCircle (node, rx, point) {
return intersectEllipse(node, rx, rx, point)
}
export default intersectCircle

View File

@@ -0,0 +1,24 @@
function intersectEllipse (node, rx, ry, point) {
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
const cx = node.x
const cy = node.y
const px = cx - point.x
const py = cy - point.y
const det = Math.sqrt(rx * rx * py * py + ry * ry * px * px)
let dx = Math.abs(rx * ry * px / det)
if (point.x < cx) {
dx = -dx
}
let dy = Math.abs(rx * ry * py / det)
if (point.y < cy) {
dy = -dy
}
return {x: cx + dx, y: cy + dy}
}
export default intersectEllipse

View File

@@ -0,0 +1,65 @@
/*
* Returns the point at which two lines, p and q, intersect or returns
* undefined if they do not intersect.
*/
function intersectLine (p1, p2, q1, q2) {
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
// p7 and p473.
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
// b1 y + c1 = 0.
const a1 = p2.y - p1.y
const b1 = p1.x - p2.x
const c1 = (p2.x * p1.y) - (p1.x * p2.y)
// Compute r3 and r4.
const r3 = ((a1 * q1.x) + (b1 * q1.y) + c1)
const r4 = ((a1 * q2.x) + (b1 * q2.y) + c1)
// Check signs of r3 and r4. If both point 3 and point 4 lie on
// same side of line 1, the line segments do not intersect.
if ((r3 !== 0) && (r4 !== 0) && sameSign(r3, r4)) {
return /* DONT_INTERSECT */
}
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
const a2 = q2.y - q1.y
const b2 = q1.x - q2.x
const c2 = (q2.x * q1.y) - (q1.x * q2.y)
// Compute r1 and r2
const r1 = (a2 * p1.x) + (b2 * p1.y) + c2
const r2 = (a2 * p2.x) + (b2 * p2.y) + c2
// Check signs of r1 and r2. If both point 1 and point 2 lie
// on same side of second line segment, the line segments do
// not intersect.
if ((r1 !== 0) && (r2 !== 0) && (sameSign(r1, r2))) {
return /* DONT_INTERSECT */
}
// Line segments intersect: compute intersection point.
const denom = (a1 * b2) - (a2 * b1)
if (denom === 0) {
return /* COLLINEAR */
}
const offset = Math.abs(denom / 2)
// The denom/2 is to get rounding instead of truncating. It
// is added or subtracted to the numerator, depending upon the
// sign of the numerator.
let num = (b1 * c2) - (b2 * c1)
const x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom)
num = (a2 * c1) - (a1 * c2)
const y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom)
return { x, y }
}
function sameSign (r1, r2) {
return r1 * r2 > 0
}
export default intersectLine

View File

@@ -0,0 +1,5 @@
function intersectNode (node, point) {
return node.intersect(point)
}
export default intersectNode

View File

@@ -0,0 +1,55 @@
import intersectLine from './intersect-line'
/*
* Returns the point ({x, y}) at which the point argument intersects with the
* node argument assuming that it has the shape specified by polygon.
*/
function intersectPolygon (node, polyPoints, point) {
const x1 = node.x
const y1 = node.y
const intersections = []
let minX = Number.POSITIVE_INFINITY
let minY = Number.POSITIVE_INFINITY
polyPoints.forEach(function (entry) {
minX = Math.min(minX, entry.x)
minY = Math.min(minY, entry.y)
})
const left = x1 - node.width / 2 - minX
const top = y1 - node.height / 2 - minY
for (let i = 0; i < polyPoints.length; i += 1) {
const p1 = polyPoints[i]
const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0]
const intersect = intersectLine(node, point,
{x: left + p1.x, y: top + p1.y}, {x: left + p2.x, y: top + p2.y})
if (intersect) {
intersections.push(intersect)
}
}
if (!intersections.length) {
console.log('NO INTERSECTION FOUND, RETURN NODE CENTER', node)
return node
}
if (intersections.length > 1) {
// More intersections, find the one nearest to edge end point
intersections.sort(function (p, q) {
const pdx = p.x - point.x
const pdy = p.y - point.y
const distp = Math.sqrt(pdx * pdx + pdy * pdy)
const qdx = q.x - point.x
const qdy = q.y - point.y
const distq = Math.sqrt(qdx * qdx + qdy * qdy)
return (distp < distq) ? -1 : (distp === distq ? 0 : 1)
})
}
return intersections[0]
}
export default intersectPolygon

View File

@@ -0,0 +1,32 @@
function intersectRect (node, point) {
const x = node.x
const y = node.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 = node.width / 2
let h = node.height / 2
let sx, sy
if (Math.abs(dy) * w > Math.abs(dx) * h) {
// Intersection is top or bottom of rect.
if (dy < 0) {
h = -h
}
sx = dy === 0 ? 0 : h * dx / dy
sy = h
} else {
// Intersection is left or right of rect.
if (dx < 0) {
w = -w
}
sx = w
sy = dx === 0 ? 0 : w * dy / dx
}
return {x: x + sx, y: y + sy}
}
export default intersectRect

View File

@@ -0,0 +1,37 @@
import util from '../util'
function addHtmlLabel (root, node) {
const fo = root
.append('foreignObject')
.attr('width', '100000')
const div = fo
.append('xhtml:div')
div.attr('xmlns', 'http://www.w3.org/1999/xhtml')
const label = node.label
switch (typeof label) {
case 'function':
div.insert(label)
break
case 'object':
// Currently we assume this is a DOM object.
div.insert(function () { return label })
break
default: div.html(label)
}
util.applyStyle(div, node.labelStyle)
div.style('display', 'inline-block')
// Fix for firefox
div.style('white-space', 'nowrap')
const client = div[0][0].getBoundingClientRect()
fo
.attr('width', client.width)
.attr('height', client.height)
return fo
}
export default addHtmlLabel

37
node_modules/dagre-d3-renderer/lib/label/add-label.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import addTextLabel from './add-text-label'
import addHtmlLabel from './add-html-label'
import addSVGLabel from './add-svg-label'
function addLabel (root, node, location) {
const label = node.label
const labelSvg = root.append('g')
// Allow the label to be a string, a function that returns a DOM element, or
// a DOM element itself.
if (node.labelType === 'svg') {
addSVGLabel(labelSvg, node)
} else if (typeof label !== 'string' || node.labelType === 'html') {
addHtmlLabel(labelSvg, node)
} else {
addTextLabel(labelSvg, node)
}
const labelBBox = labelSvg.node().getBBox()
let y
switch (location) {
case 'top':
y = (-node.height / 2)
break
case 'bottom':
y = (node.height / 2) - labelBBox.height
break
default:
y = (-labelBBox.height / 2)
}
labelSvg.attr('transform',
'translate(' + (-labelBBox.width / 2) + ',' + y + ')')
return labelSvg
}
export default addLabel

View File

@@ -0,0 +1,13 @@
import util from '../util'
function addSVGLabel (root, node) {
const domNode = root
domNode.node().appendChild(node.label)
util.applyStyle(domNode, node.labelStyle)
return domNode
}
export default addSVGLabel

View File

@@ -0,0 +1,45 @@
import util from '../util'
/*
* Attaches a text label to the specified root. Handles escape sequences.
*/
function addTextLabel (root, node) {
const domNode = root.append('text')
const lines = processEscapeSequences(node.label).split('\n')
for (let i = 0; i < lines.length; i += 1) {
domNode
.append('tspan')
.attr('xml:space', 'preserve')
.attr('dy', '1em')
.attr('x', '1')
.text(lines[i])
}
util.applyStyle(domNode, node.labelStyle)
return domNode
}
function processEscapeSequences (text) {
let newText = ''
let escaped = false
let ch = null
for (let i = 0; i < text.length; i += 1) {
ch = text[i]
if (escaped) {
switch (ch) {
case 'n': newText += '\n'; break
default: newText += ch
}
escaped = false
} else if (ch === '\\') {
escaped = true
} else {
newText += ch
}
}
return newText
}
export default addTextLabel

View File

@@ -0,0 +1,31 @@
import d3 from 'd3'
import util from './util'
function positionClusters (selection, g) {
const created = selection.filter(function () { return !d3.select(this).classed('update') })
function translate (v) {
const node = g.node(v)
return 'translate(' + node.x + ',' + node.y + ')'
}
created.attr('transform', translate)
util.applyTransition(selection, g)
.style('opacity', 1)
.attr('transform', translate)
util.applyTransition(created.selectAll('rect'), g)
.attr('width', function (v) { return g.node(v).width })
.attr('height', function (v) { return g.node(v).height })
.attr('x', function (v) {
const node = g.node(v)
return -node.width / 2
})
.attr('y', function (v) {
const node = g.node(v)
return -node.height / 2
})
}
export default positionClusters

View File

@@ -0,0 +1,21 @@
import d3 from 'd3'
import _ from 'lodash'
import util from './util'
function positionEdgeLabels (selection, g) {
const created = selection.filter(function () { return !d3.select(this).classed('update') })
function translate (e) {
const edge = g.edge(e)
return _.has(edge, 'x') ? 'translate(' + edge.x + ',' + edge.y + ')' : ''
}
created.attr('transform', translate)
util.applyTransition(selection, g)
.style('opacity', 1)
.attr('transform', translate)
}
export default positionEdgeLabels

20
node_modules/dagre-d3-renderer/lib/position-nodes.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
import d3 from 'd3'
import util from './util'
function positionNodes (selection, g) {
const created = selection.filter(function () { return !d3.select(this).classed('update') })
function translate (v) {
const node = g.node(v)
return 'translate(' + node.x + ',' + node.y + ')'
}
created.attr('transform', translate)
util.applyTransition(selection, g)
.style('opacity', 1)
.attr('transform', translate)
}
export default positionNodes

186
node_modules/dagre-d3-renderer/lib/render.js generated vendored Normal file
View File

@@ -0,0 +1,186 @@
import _ from 'lodash'
import { layout } from 'dagre-layout'
import positionNodes from './position-nodes'
import positionEdgeLabels from './position-edge-labels'
import positionClusters from './position-clusters'
import createNodes from './create-nodes'
import createClusters from './create-clusters'
import createEdgeLabels from './create-edge-labels'
import createEdgePaths from './create-edge-paths'
import shapes from './shapes'
import arrows from './arrows'
// This design is based on http://bost.ocks.org/mike/chart/.
function render () {
let _createNodes = createNodes
let _createClusters = createClusters
let _createEdgeLabels = createEdgeLabels
let _createEdgePaths = createEdgePaths
let _shapes = shapes
let _arrows = arrows
const fn = function (svg, g) {
preProcessGraph(g)
const outputGroup = createOrSelectGroup(svg, 'output')
const clustersGroup = createOrSelectGroup(outputGroup, 'clusters')
const edgePathsGroup = createOrSelectGroup(outputGroup, 'edgePaths')
const edgeLabels = _createEdgeLabels(createOrSelectGroup(outputGroup, 'edgeLabels'), g)
const nodes = _createNodes(createOrSelectGroup(outputGroup, 'nodes'), g, _shapes)
layout(g)
positionNodes(nodes, g)
positionEdgeLabels(edgeLabels, g)
_createEdgePaths(edgePathsGroup, g, _arrows)
const clusters = _createClusters(clustersGroup, g)
positionClusters(clusters, g)
postProcessGraph(g)
}
fn.createNodes = function (value) {
if (!arguments.length) {
return _createNodes
}
_createNodes = value
return fn
}
fn.createClusters = function (value) {
if (!arguments.length) {
return _createClusters
}
_createClusters = value
return fn
}
fn.createEdgeLabels = function (value) {
if (!arguments.length) {
return _createEdgeLabels
}
_createEdgeLabels = value
return fn
}
fn.createEdgePaths = function (value) {
if (!arguments.length) {
return _createEdgePaths
}
_createEdgePaths = value
return fn
}
fn.shapes = function (value) {
if (!arguments.length) {
return _shapes
}
_shapes = value
return fn
}
fn.arrows = function (value) {
if (!arguments.length) {
return _arrows
}
_arrows = value
return fn
}
return fn
}
const NODE_DEFAULT_ATTRS = {
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
rx: 0,
ry: 0,
shape: 'rect'
}
const EDGE_DEFAULT_ATTRS = {
arrowhead: 'normal',
lineInterpolate: 'linear'
}
function preProcessGraph (g) {
g.nodes().forEach(function (v) {
const node = g.node(v)
if (!_.has(node, 'label') && !g.children(v).length) { node.label = v }
if (_.has(node, 'paddingX')) {
_.defaults(node, {
paddingLeft: node.paddingX,
paddingRight: node.paddingX
})
}
if (_.has(node, 'paddingY')) {
_.defaults(node, {
paddingTop: node.paddingY,
paddingBottom: node.paddingY
})
}
if (_.has(node, 'padding')) {
_.defaults(node, {
paddingLeft: node.padding,
paddingRight: node.padding,
paddingTop: node.padding,
paddingBottom: node.padding
})
}
_.defaults(node, NODE_DEFAULT_ATTRS)
_.each(['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'], function (k) {
node[k] = Number(node[k])
})
// Save dimensions for restore during post-processing
if (_.has(node, 'width')) { node._prevWidth = node.width }
if (_.has(node, 'height')) { node._prevHeight = node.height }
})
g.edges().forEach(function (e) {
const edge = g.edge(e)
if (!_.has(edge, 'label')) { edge.label = '' }
_.defaults(edge, EDGE_DEFAULT_ATTRS)
})
}
function postProcessGraph (g) {
_.each(g.nodes(), function (v) {
const node = g.node(v)
// Restore original dimensions
if (_.has(node, '_prevWidth')) {
node.width = node._prevWidth
} else {
delete node.width
}
if (_.has(node, '_prevHeight')) {
node.height = node._prevHeight
} else {
delete node.height
}
delete node._prevWidth
delete node._prevHeight
})
}
function createOrSelectGroup (root, name) {
let selection = root.select('g.' + name)
if (selection.empty()) {
selection = root.append('g').attr('class', name)
}
return selection
}
export default render

79
node_modules/dagre-d3-renderer/lib/shapes.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
import intersectRect from './intersect/intersect-rect'
import intersectEllipse from './intersect/intersect-ellipse'
import intersectCircle from './intersect/intersect-circle'
import intersectPolygon from './intersect/intersect-polygon'
function rect (parent, bbox, node) {
const shapeSvg = parent.insert('rect', ':first-child')
.attr('rx', node.rx)
.attr('ry', node.ry)
.attr('x', -bbox.width / 2)
.attr('y', -bbox.height / 2)
.attr('width', bbox.width)
.attr('height', bbox.height)
node.intersect = function (point) {
return intersectRect(node, point)
}
return shapeSvg
}
function ellipse (parent, bbox, node) {
const rx = bbox.width / 2
const ry = bbox.height / 2
const shapeSvg = parent.insert('ellipse', ':first-child')
.attr('x', -bbox.width / 2)
.attr('y', -bbox.height / 2)
.attr('rx', rx)
.attr('ry', ry)
node.intersect = function (point) {
return intersectEllipse(node, rx, ry, point)
}
return shapeSvg
}
function circle (parent, bbox, node) {
const r = Math.max(bbox.width, bbox.height) / 2
const shapeSvg = parent.insert('circle', ':first-child')
.attr('x', -bbox.width / 2)
.attr('y', -bbox.height / 2)
.attr('r', r)
node.intersect = function (point) {
return intersectCircle(node, r, point)
}
return shapeSvg
}
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
// the function to calculate the diamond shape from:
// http://mathforum.org/kb/message.jspa?messageID=3750236
function diamond (parent, bbox, node) {
const w = (bbox.width * Math.SQRT2) / 2
const h = (bbox.height * Math.SQRT2) / 2
const points = [
{ x: 0, y: -h },
{ x: -w, y: 0 },
{ x: 0, y: h },
{ x: w, y: 0 }
]
const shapeSvg = parent.insert('polygon', ':first-child')
.attr('points', points.map(function (p) { return p.x + ',' + p.y }).join(' '))
node.intersect = function (p) {
return intersectPolygon(node, points, p)
}
return shapeSvg
}
export default {
rect,
ellipse,
circle,
diamond
}

54
node_modules/dagre-d3-renderer/lib/util.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import _ from 'lodash'
/*
* Returns true if the specified node in the graph is a subgraph node. A
* subgraph node is one that contains other nodes.
*/
function isSubgraph (g, v) {
return !!g.children(v).length
}
function edgeToId (e) {
return escapeId(e.v) + ':' + escapeId(e.w) + ':' + escapeId(e.name)
}
const ID_DELIM = /:/g
function escapeId (str) {
return str ? String(str).replace(ID_DELIM, '\\:') : ''
}
function applyStyle (dom, styleFn) {
if (styleFn) {
dom.attr('style', styleFn)
}
}
function applyClass (dom, classFn, otherClasses) {
if (classFn) {
dom
.attr('class', classFn)
.attr('class', otherClasses + ' ' + dom.attr('class'))
}
}
function applyTransition (selection, g) {
const graph = g.graph()
if (_.isPlainObject(graph)) {
const transition = graph.transition
if (_.isFunction(transition)) {
return transition(selection)
}
}
return selection
}
// Public utility functions
export default {
isSubgraph,
edgeToId,
applyStyle,
applyClass,
applyTransition
}