Merge pull request #791 from flying-sheep/svg-links

SVG link rendering
This commit is contained in:
Knut Sveidqvist 2019-05-28 23:18:39 +02:00 committed by GitHub
commit ee0cb8793f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 54 deletions

View File

@ -1,5 +0,0 @@
{
"presets": [
"@babel/preset-env"
]
}

5
babel.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
'presets': [
'@babel/preset-env'
]
}

View File

@ -75,6 +75,12 @@
"src" "src"
], ],
"jest": { "jest": {
"transform": {
"^.+\\.jsx?$": "./transformer.js"
},
"transformIgnorePatterns": [
"/node_modules/(?!dagre-d3-renderer/lib).*\\.js"
],
"moduleNameMapper": { "moduleNameMapper": {
"\\.(css|scss)$": "identity-obj-proxy" "\\.(css|scss)$": "identity-obj-proxy"
} }

View File

@ -4,6 +4,7 @@ import * as d3 from 'd3'
import flowDb from './flowDb' import flowDb from './flowDb'
import flow from './parser/flow' import flow from './parser/flow'
import dagreD3 from 'dagre-d3-renderer' import dagreD3 from 'dagre-d3-renderer'
import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js'
import { logger } from '../../logger' import { logger } from '../../logger'
import { interpolateToCurve } from '../../utils' import { interpolateToCurve } from '../../utils'
@ -21,7 +22,8 @@ export const setConf = function (cnf) {
* @param vert Object containing the vertices. * @param vert Object containing the vertices.
* @param g The graph that is to be drawn. * @param g The graph that is to be drawn.
*/ */
export const addVertices = function (vert, g) { export const addVertices = function (vert, g, svgId) {
const svg = d3.select(`[id="${svgId}"]`)
const keys = Object.keys(vert) const keys = Object.keys(vert)
const styleFromStyleArr = function (styleStr, arr) { const styleFromStyleArr = function (styleStr, arr) {
@ -35,46 +37,41 @@ export const addVertices = function (vert, g) {
return styleStr return styleStr
} }
// Iterate through each item in the vertice object (containing all the vertices found) in the graph definition // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
keys.forEach(function (id) { keys.forEach(function (id) {
const vertice = vert[id] const vertex = vert[id]
let verticeText
/** /**
* Variable for storing the classes for the vertice * Variable for storing the classes for the vertex
* @type {string} * @type {string}
*/ */
let classStr = '' let classStr = ''
if (vertice.classes.length > 0) { if (vertex.classes.length > 0) {
classStr = vertice.classes.join(' ') classStr = vertex.classes.join(' ')
} }
/** /**
* Variable for storing the extracted style for the vertice * Variable for storing the extracted style for the vertex
* @type {string} * @type {string}
*/ */
let style = '' let style = ''
// Create a compound style definition from the style definitions found for the node in the graph definition // Create a compound style definition from the style definitions found for the node in the graph definition
style = styleFromStyleArr(style, vertice.styles) style = styleFromStyleArr(style, vertex.styles)
// Use vertice id as text in the box if no text is provided by the graph definition // Use vertex id as text in the box if no text is provided by the graph definition
if (typeof vertice.text === 'undefined') { let vertexText = vertex.text !== undefined ? vertex.text : vertex.id
verticeText = vertice.id
} else {
verticeText = vertice.text
}
let labelTypeStr = '' // We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode
if (conf.htmlLabels) { if (conf.htmlLabels) {
labelTypeStr = 'html' // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
verticeText = verticeText.replace(/fa[lrsb]?:fa-[\w-]+/g, s => `<i class='${s.replace(':', ' ')}'></i>`) const node = { label: vertexText.replace(/fa[lrsb]?:fa-[\w-]+/g, s => `<i class='${s.replace(':', ' ')}'></i>`) }
if (vertice.link) { vertexNode = addHtmlLabel(svg, node).node()
verticeText = '<a href="' + vertice.link + '" rel="noopener">' + verticeText + '</a>' vertexNode.parentNode.removeChild(vertexNode)
}
} else { } else {
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text') const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text')
const rows = verticeText.split(/<br>/) const rows = vertexText.split(/<br>/)
for (let j = 0; j < rows.length; j++) { for (let j = 0; j < rows.length; j++) {
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan') const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')
@ -84,22 +81,22 @@ export const addVertices = function (vert, g) {
tspan.textContent = rows[j] tspan.textContent = rows[j]
svgLabel.appendChild(tspan) svgLabel.appendChild(tspan)
} }
vertexNode = svgLabel
}
labelTypeStr = 'svg' // If the node has a link, we wrap it in a SVG link
if (vertice.link) { if (vertex.link) {
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a') const link = document.createElementNS('http://www.w3.org/2000/svg', 'a')
link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertice.link) link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link)
link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener') link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener')
verticeText = link link.appendChild(vertexNode)
} else { vertexNode = link
verticeText = svgLabel
}
} }
let radious = 0 let radious = 0
let _shape = '' let _shape = ''
// Set the shape based parameters // Set the shape based parameters
switch (vertice.type) { switch (vertex.type) {
case 'round': case 'round':
radious = 5 radious = 5
_shape = 'rect' _shape = 'rect'
@ -124,14 +121,12 @@ export const addVertices = function (vert, g) {
break break
case 'group': case 'group':
_shape = 'rect' _shape = 'rect'
// Need to create a text node if using svg labels, see #367
verticeText = conf.htmlLabels ? '' : document.createElementNS('http://www.w3.org/2000/svg', 'text')
break break
default: default:
_shape = 'rect' _shape = 'rect'
} }
// Add the node // Add the node
g.setNode(vertice.id, { labelType: labelTypeStr, shape: _shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id: vertice.id }) g.setNode(vertex.id, { labelType: 'svg', shape: _shape, label: vertexNode, rx: radious, ry: radious, 'class': classStr, style: style, id: vertex.id })
}) })
} }
@ -290,7 +285,7 @@ export const draw = function (text, id) {
g.setParent(subG.nodes[j], subG.id) g.setParent(subG.nodes[j], subG.id)
} }
} }
addVertices(vert, g) addVertices(vert, g, id)
addEdges(edges, g) addEdges(edges, g)
// Create the renderer // Create the renderer
@ -424,6 +419,7 @@ export const draw = function (text, id) {
// Index nodes // Index nodes
flowDb.indexNodes('subGraph' + i) flowDb.indexNodes('subGraph' + i)
// reposition labels
for (i = 0; i < subGraphs.length; i++) { for (i = 0; i < subGraphs.length; i++) {
subG = subGraphs[i] subG = subGraphs[i]
@ -435,19 +431,9 @@ export const draw = function (text, id) {
const yPos = clusterRects[0].y.baseVal.value const yPos = clusterRects[0].y.baseVal.value
const width = clusterRects[0].width.baseVal.value const width = clusterRects[0].width.baseVal.value
const cluster = d3.select(clusterEl[0]) const cluster = d3.select(clusterEl[0])
const te = cluster.append('text') const te = cluster.select('.label')
te.attr('x', xPos + width / 2) te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`)
te.attr('y', yPos + 14)
te.attr('fill', 'black')
te.attr('stroke', 'none')
te.attr('id', id + 'Text') te.attr('id', id + 'Text')
te.style('text-anchor', 'middle')
if (typeof subG.title === 'undefined') {
te.text('Undef')
} else {
te.text(subG.title)
}
} }
} }

3
transformer.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = require('babel-jest').createTransformer({
rootMode: 'upward'
})

View File

@ -8,7 +8,10 @@ const amdRule = {
const jsRule = { const jsRule = {
test: /\.js$/, test: /\.js$/,
exclude: /node_modules/, include: [
path.resolve(__dirname, './src'),
path.resolve(__dirname, './node_modules/dagre-d3-renderer/lib')
],
use: { use: {
loader: 'babel-loader' loader: 'babel-loader'
} }