diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index 0d870e1a3..fc68f0259 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -41,6 +41,16 @@ journey Go downstairs: 5: Me Sit down: 5: Mee +
+mindmap + root[ + The root where the things + hap
+ hap
+ pen! + ] + Child1 +
pie accTitle: My Pie Chart Accessibility Title @@ -52,8 +62,8 @@ journey "Magnesium" : 10.01 "Iron" : 5
-
- gitGraph +
+ gitGraph TB commit commit branch develop @@ -217,7 +227,7 @@ class Class10 { size() }
-
+
%%{init: {'config': {'wrap': true }}}%% sequenceDiagram participant A as Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be @@ -332,7 +342,7 @@ flowchart TD rankSpacing: 50, defaultRenderer: 'dagre-d3', }, - logLevel: 0, + logLevel: 1, fontSize: 18, curve: 'cardinal', // securityLevel: 'sandbox', diff --git a/src/defaultConfig.js b/src/defaultConfig.js index acf85055f..14001f167 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -1818,6 +1818,11 @@ const config = { external_component_queue_bg_color: '#CCCCCC', external_component_queue_border_color: '#BFBFBF', }, + mindmap: { + useMaxWidth: true, + diagramPadding: 10, + maxNodeWidth: 200, + }, }; config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute; diff --git a/src/diagram-api/detectType.js b/src/diagram-api/detectType.js index a5f074e3e..0bcde1e17 100644 --- a/src/diagram-api/detectType.js +++ b/src/diagram-api/detectType.js @@ -83,8 +83,10 @@ const detectType = function (text, cnf) { if (cnf && cnf.flowchart && cnf.flowchart.defaultRenderer === 'dagre-wrapper') return 'flowchart-v2'; const k = Object.keys(detectors); + console.log('here', k); for (let i = 0; i < k.length; i++) { const key = k[i]; + console.log('Detecting type for', key); const dia = detectors[key]; if (dia && dia.detector(text)) { return key; diff --git a/src/diagram-api/diagram-orchestration.js b/src/diagram-api/diagram-orchestration.js index d73bc1bbb..488a708ee 100644 --- a/src/diagram-api/diagram-orchestration.js +++ b/src/diagram-api/diagram-orchestration.js @@ -1,24 +1,17 @@ import { registerDiagram } from './diagramAPI.js'; -// import mindmapDb from '../diagrams/mindmap/mindmapDb'; -// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; -// import mindmapParser from '../diagrams/mindmap/parser/mindmapDiagram'; -// import mindmapDetector from '../diagrams/mindmap/mindmapDetector'; +import mindmapDb from '../diagrams/mindmap/mindmapDb'; +import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; +import mindmapParser from '../diagrams/mindmap/parser/mindmap'; +import mindmapDetector from '../diagrams/mindmap/mindmapDetector'; +import mindmapStyles from '../diagrams/mindmap/styles'; import gitGraphDb from '../diagrams/git/gitGraphAst'; import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; import gitGraphParser from '../diagrams/git/parser/gitGraph'; import gitGraphDetector from '../diagrams/git/gitGraphDetector'; +import gitGraphStyles from '../diagrams/git/styles'; // Register mindmap and other built-in diagrams -// registerDiagram( -// 'mindmap', -// mindmapParser, -// mindmapDb, -// mindmapRenderer, -// undefined, -// mindmapRenderer, -// mindmapDetector -// ); const addDiagrams = () => { registerDiagram( 'gitGraph', @@ -26,7 +19,17 @@ const addDiagrams = () => { gitGraphDb, gitGraphRenderer, undefined, - gitGraphDetector + gitGraphDetector, + gitGraphStyles + ); + registerDiagram( + 'mindmap', + mindmapParser, + mindmapDb, + mindmapRenderer, + undefined, + mindmapDetector, + mindmapStyles ); }; export default addDiagrams; diff --git a/src/diagram-api/diagramAPI.js b/src/diagram-api/diagramAPI.js index e8339ca37..837cbb4ff 100644 --- a/src/diagram-api/diagramAPI.js +++ b/src/diagram-api/diagramAPI.js @@ -35,15 +35,19 @@ import journeyDb from '../diagrams/user-journey/journeyDb'; import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; import journeyParser from '../diagrams/user-journey/parser/journey'; import { addDetector } from './detectType'; +import { addStylesForDiagram } from '../styles'; import { sanitizeText as _sanitizeText } from '../diagrams/common/common'; import { getConfig as _getConfig } from '../config'; +import { log as _log } from '../logger'; +import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox'; + let title = ''; let diagramTitle = ''; let description = ''; export const getConfig = _getConfig; export const sanitizeText = (txt) => _sanitizeText(txt, getConfig()); - +export const log = _log; const diagrams = { c4: { db: c4Db, @@ -171,13 +175,16 @@ const diagrams = { }, }, }; -// console.log(sequenceDb); -export const registerDiagram = (id, parser, db, renderer, init, detector) => { + +export const registerDiagram = (id, parser, db, renderer, init, detector, styles) => { diagrams[id] = { parser, db, renderer, init }; addDetector(id, detector); + addStylesForDiagram(id, styles); }; export const getDiagrams = () => { // console.log('diagrams', diagrams); return diagrams; }; + +export const setupGraphViewbox = _setupGraphViewbox; diff --git a/src/diagram-api/text-wrap b/src/diagram-api/text-wrap new file mode 100644 index 000000000..173baecec --- /dev/null +++ b/src/diagram-api/text-wrap @@ -0,0 +1,227 @@ +export const lineBreakRegex = //gi; + +/** + * Caches results of functions based on input + * + * @param {Function} fn Function to run + * @param {Function} resolver Function that resolves to an ID given arguments the `fn` takes + * @returns {Function} An optimized caching function + */ +const memoize = (fn, resolver) => { + let cache = {}; + return (...args) => { + let n = resolver ? resolver.apply(this, args) : args[0]; + if (n in cache) { + return cache[n]; + } else { + let result = fn(...args); + cache[n] = result; + return result; + } + }; +}; +/** + * This calculates the width of the given text, font size and family. + * + * @param {any} text - The text to calculate the width of + * @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the resulting size + * @returns {any} - The width for the given text + */ +export const calculateTextWidth = function (text, config) { + config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config); + return calculateTextDimensions(text, config).width; +}; + +export const getTextObj = function () { + return { + x: 0, + y: 0, + fill: undefined, + anchor: 'start', + style: '#666', + width: 100, + height: 100, + textMargin: 0, + rx: 0, + ry: 0, + valign: undefined, + }; +}; + +/** + * Adds text to an element + * + * @param {SVGElement} elem Element to add text to + * @param {{ + * text: string; + * x: number; + * y: number; + * anchor: 'start' | 'middle' | 'end'; + * fontFamily: string; + * fontSize: string | number; + * fontWeight: string | number; + * fill: string; + * class: string | undefined; + * textMargin: number; + * }} textData + * @returns {SVGTextElement} Text element with given styling and content + */ +export const drawSimpleText = function (elem, textData) { + // Remove and ignore br:s + const nText = textData.text.replace(lineBreakRegex, ' '); + + const textElem = elem.append('text'); + textElem.attr('x', textData.x); + textElem.attr('y', textData.y); + textElem.style('text-anchor', textData.anchor); + textElem.style('font-family', textData.fontFamily); + textElem.style('font-size', textData.fontSize); + textElem.style('font-weight', textData.fontWeight); + textElem.attr('fill', textData.fill); + if (typeof textData.class !== 'undefined') { + textElem.attr('class', textData.class); + } + + const span = textElem.append('tspan'); + span.attr('x', textData.x + textData.textMargin * 2); + span.attr('fill', textData.fill); + span.text(nText); + + return textElem; +}; + +/** + * This calculates the dimensions of the given text, font size, font family, font weight, and margins. + * + * @param {any} text - The text to calculate the width of + * @param {any} config - The config for fontSize, fontFamily, fontWeight, and margin all impacting + * the resulting size + * @returns - The width for the given text + */ +export const calculateTextDimensions = memoize( + function (text, config) { + config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config); + const { fontSize, fontFamily, fontWeight } = config; + if (!text) { + return { width: 0, height: 0 }; + } + + // We can't really know if the user supplied font family will render on the user agent; + // thus, we'll take the max width between the user supplied font family, and a default + // of sans-serif. + const fontFamilies = ['sans-serif', fontFamily]; + const lines = text.split(common.lineBreakRegex); + let dims = []; + + const body = select('body'); + // We don't want to leak DOM elements - if a removal operation isn't available + // for any reason, do not continue. + if (!body.remove) { + return { width: 0, height: 0, lineHeight: 0 }; + } + + const g = body.append('svg'); + + for (let fontFamily of fontFamilies) { + let cheight = 0; + let dim = { width: 0, height: 0, lineHeight: 0 }; + for (let line of lines) { + const textObj = getTextObj(); + textObj.text = line; + const textElem = drawSimpleText(g, textObj) + .style('font-size', fontSize) + .style('font-weight', fontWeight) + .style('font-family', fontFamily); + + let bBox = (textElem._groups || textElem)[0][0].getBBox(); + dim.width = Math.round(Math.max(dim.width, bBox.width)); + cheight = Math.round(bBox.height); + dim.height += cheight; + dim.lineHeight = Math.round(Math.max(dim.lineHeight, cheight)); + } + dims.push(dim); + } + + g.remove(); + + let index = + isNaN(dims[1].height) || + isNaN(dims[1].width) || + isNaN(dims[1].lineHeight) || + (dims[0].height > dims[1].height && + dims[0].width > dims[1].width && + dims[0].lineHeight > dims[1].lineHeight) + ? 0 + : 1; + return dims[index]; + }, + (text, config) => `${text}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}` +); + +const breakString = memoize( + (word, maxWidth, hyphenCharacter = '-', config) => { + config = Object.assign( + { fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 }, + config + ); + const characters = word.split(''); + const lines = []; + let currentLine = ''; + characters.forEach((character, index) => { + const nextLine = `${currentLine}${character}`; + const lineWidth = calculateTextWidth(nextLine, config); + if (lineWidth >= maxWidth) { + const currentCharacter = index + 1; + const isLastLine = characters.length === currentCharacter; + const hyphenatedNextLine = `${nextLine}${hyphenCharacter}`; + lines.push(isLastLine ? nextLine : hyphenatedNextLine); + currentLine = ''; + } else { + currentLine = nextLine; + } + }); + return { hyphenatedStrings: lines, remainingWord: currentLine }; + }, + (word, maxWidth, hyphenCharacter = '-', config) => + `${word}-${maxWidth}-${hyphenCharacter}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}` +); + +export const wrapLabel = memoize( + (label, maxWidth, config) => { + if (!label) { + return label; + } + config = Object.assign( + { fontSize: 12, fontWeight: 400, fontFamily: 'Arial', joinWith: '
' }, + config + ); + if (lineBreakRegex.test(label)) { + return label; + } + const words = label.split(' '); + const completedLines = []; + let nextLine = ''; + words.forEach((word, index) => { + const wordLength = calculateTextWidth(`${word} `, config); + const nextLineLength = calculateTextWidth(nextLine, config); + if (wordLength > maxWidth) { + const { hyphenatedStrings, remainingWord } = breakString(word, maxWidth, '-', config); + completedLines.push(nextLine, ...hyphenatedStrings); + nextLine = remainingWord; + } else if (nextLineLength + wordLength >= maxWidth) { + completedLines.push(nextLine); + nextLine = word; + } else { + nextLine = [nextLine, word].filter(Boolean).join(' '); + } + const currentWord = index + 1; + const isLastWord = currentWord === words.length; + if (isLastWord) { + completedLines.push(nextLine); + } + }); + return completedLines.filter((line) => line !== '').join(config.joinWith); + }, + (label, maxWidth, config) => + `${label}-${maxWidth}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}-${config.joinWith}` +); diff --git a/src/diagrams/mindmap/mindmapDb.js b/src/diagrams/mindmap/mindmapDb.js index 8aed2dd2e..29a982cea 100644 --- a/src/diagrams/mindmap/mindmapDb.js +++ b/src/diagrams/mindmap/mindmapDb.js @@ -1,6 +1,5 @@ /** Created by knut on 15-01-14. */ -import { log } from '../../logger'; -import { sanitizeText } from '../../diagram-api/diagramAPI'; +import { log, sanitizeText, getConfig } from '../../diagram-api/diagramAPI'; var message = ''; var info = false; @@ -26,7 +25,14 @@ export const getMindmap = () => { return nodes.length > 0 ? nodes[0] : null; }; export const addNode = (level, id, descr, type) => { - const node = { id: sanitizeText(id), level, descr: sanitizeText(descr), type, children: [] }; + const node = { + id: sanitizeText(id), + level, + descr: sanitizeText(descr), + type, + children: [], + width: getConfig().mindmap.maxNodeWidth, + }; const parent = getParent(level); if (parent) { parent.children.push(node); diff --git a/src/diagrams/mindmap/mindamapDetector.js b/src/diagrams/mindmap/mindmapDetector.js similarity index 72% rename from src/diagrams/mindmap/mindamapDetector.js rename to src/diagrams/mindmap/mindmapDetector.js index 341e3968c..4fe85af03 100644 --- a/src/diagrams/mindmap/mindamapDetector.js +++ b/src/diagrams/mindmap/mindmapDetector.js @@ -1,4 +1,4 @@ -const detector = (txt) => { +const detector = function detect(txt) { if (txt.match(/^\s*mindmap/)) { return 'mindmap'; } diff --git a/src/diagrams/mindmap/mindmapRenderer.js b/src/diagrams/mindmap/mindmapRenderer.js index cbe3c52f8..5cc8549df 100644 --- a/src/diagrams/mindmap/mindmapRenderer.js +++ b/src/diagrams/mindmap/mindmapRenderer.js @@ -1,7 +1,33 @@ /** Created by knut on 14-12-11. */ import { select } from 'd3'; -import { log } from '../../logger'; -import { getConfig } from '../../config'; +import { log, getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI'; +import svgDraw from './svgDraw'; + +/** + * @param {any} svg The svg element to draw the diagram onto + * @param {object} mindmap The maindmap data and hierarchy + * @param {object} conf The configuration object + */ +function drawNodes(svg, mindmap, conf) { + svgDraw.drawNode(svg, mindmap, conf); + if (mindmap.children) { + mindmap.children.forEach((child) => { + drawNodes(svg, child, conf); + }); + } +} + +function drawEdges() {} +/** + * @param node + * @param isRoot + */ +function layoutMindmap(node, isRoot) {} +/** + * @param node + * @param isRoot + */ +function positionNodes(node, isRoot) {} /** * Draws a an info picture in the tag with id: id based on the graph definition in text. @@ -12,6 +38,7 @@ import { getConfig } from '../../config'; * @param diagObj */ export const draw = (text, id, version, diagObj) => { + const conf = getConfig(); try { // const parser = infoParser.parser; // parser.yy = db; @@ -30,24 +57,40 @@ export const draw = (text, id, version, diagObj) => { const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; // Parse the graph definition - // parser.parse(text); - // log.debug('Parsed info diagram'); - // Fetch the default direction, use TD if none was found + const svg = root.select('#' + id); const g = svg.append('g'); + const mm = diagObj.db.getMindmap(); - g.append('text') // text label for the x axis - .attr('x', 100) - .attr('y', 40) - .attr('class', 'version') - .attr('font-size', '32px') - .style('text-anchor', 'middle') - .text('v ' + version); + // mm.x = 0; + // mm.y = 0; + // svgDraw.drawNode(g, mm, getConfig()); + // mm.children.forEach((child) => { + // child.x = 200; + // child.y = 200; + // child.width = 200; + // svgDraw.drawNode(g, child, getConfig()); + // }); - svg.attr('height', 100); - svg.attr('width', 400); - // svg.attr('viewBox', '0 0 300 150'); + // Draw the graph and start with drawing the nodes without proper position + // this gives us the size of the nodes and we can set the positions later + + const nodesElem = svg.append('g'); + nodesElem.attr('class', 'mindmap-nodes'); + drawNodes(nodesElem, mm, conf); + + // Next step is to layout the mindmap, giving each node a position + + // layoutMindmap(mm, conf); + + // After this we can draw, first the edges and the then nodes with the correct position + // drawEdges(svg, mm, conf); + + // positionNodes(svg, mm, conf); + + // Setup the view box and size of the svg element + setupGraphViewbox(undefined, svg, conf.mindmap.diagramPadding, conf.mindmap.useMaxWidth); } catch (e) { log.error('Error while rendering info diagram'); log.error(e.message); diff --git a/src/diagrams/mindmap/styles.js b/src/diagrams/mindmap/styles.js index 0b0729813..eba4ed284 100644 --- a/src/diagrams/mindmap/styles.js +++ b/src/diagrams/mindmap/styles.js @@ -1,3 +1,9 @@ -const getStyles = () => ``; - +const getStyles = (options) => + ` + .node{ + stroke: ${options.pieStrokeColor}; + stroke-width : ${options.pieStrokeWidth}; + opacity : ${options.pieOpacity}; + } +`; export default getStyles; diff --git a/src/diagrams/mindmap/svgDraw.js b/src/diagrams/mindmap/svgDraw.js new file mode 100644 index 000000000..edb4d2f72 --- /dev/null +++ b/src/diagrams/mindmap/svgDraw.js @@ -0,0 +1,100 @@ +const lineBreakRegex = //gi; +import { select } from 'd3'; +/** + * @param {string} text The text to be wrapped + * @param {number} width The max width of the text + */ +function wrap(text, width) { + text.each(function () { + var text = select(this), + words = text + .text() + .split(/(\s+|
)/) + .reverse(), + word, + line = [], + lineNumber = 0, + lineHeight = 1.1, // ems + y = text.attr('y'), + dy = parseFloat(text.attr('dy')), + tspan = text + .text(null) + .append('tspan') + .attr('x', 0) + .attr('y', y) + .attr('dy', dy + 'em'); + for (let j = 0; j < words.length; j++) { + word = words[words.length - 1 - j]; + line.push(word); + tspan.text(line.join(' ').trim()); + if (tspan.node().getComputedTextLength() > width || word === '
') { + line.pop(); + tspan.text(line.join(' ').trim()); + if (word === '
') { + line = ['']; + } else { + line = [word]; + } + + tspan = text + .append('tspan') + .attr('x', 0) + .attr('y', y) + .attr('dy', lineHeight + 'em') + .text(word); + } + } + }); +} +/** + * @param {object} elem The D3 dom element in which the node is to be added + * @param {object} node The node to be added + * @param {object} conf The configuration object + * @returns {number} The height nodes dom element + */ +export const drawNode = function (elem, node, conf) { + const nodeElem = elem.append('g'); + nodeElem.attr('class', 'mindmap-node'); + + const rect = { + fill: '#EDF2AE', + stroke: '#666', + width: node.width, + anchor: 'start', + height: 100, + rx: 3, + ry: 3, + }; + + const r = nodeElem + .append('rect') + .attr('x', (-1 * node.width) / 2) + .attr('width', node.width) + .attr('fill', rect.fill) + .attr('stroke', rect.stroke) + .attr('rx', rect.rx) + .attr('ry', rect.ry); + + const textElem = nodeElem.append('g'); + // .attr('transform', 'translate(' + node.x + ', ' + node.y + ')'); + + const txt = textElem + .append('text') + .text(node.descr) + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle') + .call(wrap, node.width); + const bbox = txt.node().getBBox(); + node.height = bbox.height + conf.fontSize * 1.1 * 0.5; + r.attr('height', node.height).attr('y', (-1 * node.height) / 2); + + txt.attr('transform', 'translate( 0,' + (-1 * node.height) / 2 + ')'); + // Position the node to its coordinate + if (node.x || node.y) { + nodeElem.attr('transform', 'translate(' + node.x + ',' + node.y + ')'); + } + return node.height; +}; +export default { drawNode }; diff --git a/src/setupGraphViewbox.js b/src/setupGraphViewbox.js new file mode 100644 index 000000000..d5c00718c --- /dev/null +++ b/src/setupGraphViewbox.js @@ -0,0 +1,102 @@ +import { log } from './logger'; + +/** + * Applys d3 attributes + * + * @param {any} d3Elem D3 Element to apply the attributes onto + * @param {[string, string][]} attrs Object.keys equivalent format of key to value mapping of attributes + */ +const d3Attrs = function (d3Elem, attrs) { + for (let attr of attrs) { + d3Elem.attr(attr[0], attr[1]); + } +}; + +/** + * Gives attributes for an SVG's size given arguments + * + * @param {number} height The height of the SVG + * @param {number} width The width of the SVG + * @param {boolean} useMaxWidth Whether or not to use max-width and set width to 100% + * @returns {Map<'height' | 'width' | 'style', string>} Attributes for the SVG + */ +export const calculateSvgSizeAttrs = function (height, width, useMaxWidth) { + let attrs = new Map(); + attrs.set('height', height); + if (useMaxWidth) { + attrs.set('width', '100%'); + attrs.set('style', `max-width: ${width}px;`); + } else { + attrs.set('width', width); + } + return attrs; +}; + +/** + * Applies attributes from `calculateSvgSizeAttrs` + * + * @param {SVGSVGElement} svgElem The SVG Element to configure + * @param {number} height The height of the SVG + * @param {number} width The width of the SVG + * @param tx + * @param ty + * @param {boolean} useMaxWidth Whether or not to use max-width and set width to 100% + */ +export const configureSvgSize = function (svgElem, height, width, tx, ty, useMaxWidth) { + const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth); + d3Attrs(svgElem, attrs); +}; +export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) { + const svgBounds = svgElem.node().getBBox(); + const sWidth = svgBounds.width; + const sHeight = svgBounds.height; + + let width; + let height; + let tx = 0; + let ty = 0; + if (graph) { + width = graph._label.width; + height = graph._label.height; + if (sWidth > width) { + tx = (sWidth - width) / 2 + padding; + width = sWidth + padding * 2; + } else { + if (Math.abs(sWidth - width) >= 2 * padding + 1) { + width = width - padding; + } + } + if (sHeight > height) { + ty = (sHeight - height) / 2 + padding; + height = sHeight + padding * 2; + } + } else { + width = sWidth + padding * 2; + height = sHeight + padding * 2; + } + + // Ensure the viewBox includes the whole svgBounds area with extra space for padding + const vBox = graph + ? `0 0 ${width} ${height}` + : `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; + console.log( + 'Graph.label', + graph ? graph._label : null, + 'swidth', + sWidth, + 'sheight', + sHeight, + 'width', + width, + 'height', + height, + 'tx', + tx, + 'ty', + ty, + 'vBox', + vBox + ); + svgElem.attr('viewBox', vBox); + svgElem.select('g').attr('transform', `translate(${tx}, ${ty})`); +}; diff --git a/src/styles.js b/src/styles.js index 15e804ef9..50da58545 100644 --- a/src/styles.js +++ b/src/styles.js @@ -2,7 +2,7 @@ import classDiagram from './diagrams/class/styles'; import er from './diagrams/er/styles'; import flowchart from './diagrams/flowchart/styles'; import gantt from './diagrams/gantt/styles'; -import gitGraph from './diagrams/git/styles'; +// import gitGraph from './diagrams/git/styles'; import info from './diagrams/info/styles'; import pie from './diagrams/pie/styles'; import requirement from './diagrams/requirement/styles'; @@ -22,7 +22,7 @@ const themes = { class: classDiagram, stateDiagram, state: stateDiagram, - gitGraph, + // gitGraph, info, pie, er, @@ -89,4 +89,8 @@ const getStyles = (type, userStyles, options) => { `; }; +export const addStylesForDiagram = (type, diagramTheme, options) => { + themes[type] = diagramTheme; +}; + export default getStyles; diff --git a/src/utils.spec.js b/src/utils.spec.js index 31517c43a..c84987879 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -1,7 +1,10 @@ import utils from './utils'; import assignWithDepth from './assignWithDepth'; import detectType from './diagram-api/detectType'; -import './diagram-api/diagram-orchestration'; +import addDiagrams from './diagram-api/diagram-orchestration'; + +// Orchestrating diagrams and adding the dynamic ones to the list of diagrams +addDiagrams(); describe('when assignWithDepth: should merge objects within objects', function () { it('should handle simple, depth:1 types (identity)', function () { @@ -214,7 +217,7 @@ Alice->Bob: hi`; const type = detectType(str); expect(type).toBe('flowchart'); }); - it('should handle a graph definition for gitGraph', function () { + fit('should handle a graph definition for gitGraph', function () { const str = ' \n gitGraph TB:\nbfs1:queue'; const type = detectType(str); expect(type).toBe('gitGraph');