From 184fcab0b78bfa0dea84432245663c5ccbb692b6 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Sun, 23 Aug 2020 15:45:23 +0200 Subject: [PATCH] resolves #1490 consistent SVG height and width between diagrams --- .../rendering/classDiagram.spec.js | 150 +++++++++++------- src/defaultConfig.js | 75 ++++++++- src/diagrams/class/classRenderer-v2.js | 18 +-- src/diagrams/class/classRenderer.js | 9 +- src/diagrams/er/erRenderer.js | 9 +- src/diagrams/flowchart/flowRenderer-v2.js | 10 +- src/diagrams/flowchart/flowRenderer.js | 10 +- src/diagrams/gantt/ganttRenderer.js | 7 +- src/diagrams/pie/pieRenderer.js | 24 +-- src/diagrams/sequence/sequenceRenderer.js | 13 +- src/diagrams/state/stateRenderer-v2.js | 43 +---- src/diagrams/state/stateRenderer.js | 13 +- src/diagrams/user-journey/journeyRenderer.js | 11 +- src/utils.js | 25 +++ src/utils.spec.js | 17 +- 15 files changed, 242 insertions(+), 192 deletions(-) diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index 84de183c8..139ce1cb9 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('Class diagram', () => { it('1: should render a simple class diagram', () => { @@ -65,7 +65,7 @@ describe('Class diagram', () => { cy.get('svg'); }); - it('should render a simple class diagram with different visibilities', () => { + it('3: should render a simple class diagram with different visibilities', () => { imgSnapshotTest( ` classDiagram @@ -83,59 +83,6 @@ describe('Class diagram', () => { cy.get('svg'); }); - it('should render multiple class diagrams', () => { - imgSnapshotTest( - [ - ` - classDiagram - Class01 "1" <|--|> "*" AveryLongClass : Cool - <<interface>> Class01 - Class03 "1" *-- "*" Class04 - Class05 "1" o-- "many" Class06 - Class07 "1" .. "*" Class08 - Class09 "1" --> "*" C2 : Where am i? - Class09 "*" --* "*" C3 - Class09 "1" --|> "1" Class07 - Class07 : equals() - Class07 : Object[] elementData - Class01 : size() - Class01 : int chimp - Class01 : int gorilla - Class08 "1" <--> "*" C2: Cool label - class Class10 { - <<service>> - int id - test() - } - `, - ` - classDiagram - Class01 "1" <|--|> "*" AveryLongClass : Cool - <<interface>> Class01 - Class03 "1" *-- "*" Class04 - Class05 "1" o-- "many" Class06 - Class07 "1" .. "*" Class08 - Class09 "1" --> "*" C2 : Where am i? - Class09 "*" --* "*" C3 - Class09 "1" --|> "1" Class07 - Class07 : equals() - Class07 : Object[] elementData - Class01 : size() - Class01 : int chimp - Class01 : int gorilla - Class08 "1" <--> "*" C2: Cool label - class Class10 { - <<service>> - int id - test() - } - `, - ], - {} - ); - cy.get('svg'); - }); - it('4: should render a simple class diagram with comments', () => { imgSnapshotTest( ` @@ -353,4 +300,97 @@ describe('Class diagram', () => { ); cy.get('svg'); }); + + it('16: should render multiple class diagrams', () => { + imgSnapshotTest( + [ + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ], + {} + ); + cy.get('svg'); + }); + + it('17: should render a class diagrams when useMaxWidth is true (default)', () => { + renderGraph( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { class: { useMaxWidth: true } } + ); + cy.get('svg') + .should('have.attr', 'width', '100%') + .should('have.attr', 'height', '218') + .should('have.attr', 'style', 'max-width: 162.28125px;') + }); + + it('18: should render a class diagrams when useMaxWidth is false', () => { + renderGraph( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { class: { useMaxWidth: false } } + ); + cy.get('svg') + .should('have.attr', 'width', '162.28125') + .should('have.attr', 'height', '218') + .should('not.have.attr', 'style') + }); }); diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 8d1348b5b..7c44d5a95 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -173,8 +173,20 @@ const config = { */ curve: 'linear', // Only used in new experimental rendering - // repreesents the padding between the labels and the shape - padding: 15 + // represents the padding between the labels and the shape + padding: 15, + + /** + *| Parameter | Description |Type | Required | Values| + *| --- | --- | --- | --- | --- | + *| useMaxWidth | See notes | Boolean | 4 | True, False | + * + ***Notes:**when this flag is set the height and width is set to 100% and is then scaling with the + *available space if not the absolute space required is used. + * + ***Default value true**. + */ + useMaxWidth: true }, /** @@ -572,8 +584,23 @@ const config = { * This might need adjustment to match your locale and preferences ***Default value '%Y-%m-%d'**. */ - axisFormat: '%Y-%m-%d' + axisFormat: '%Y-%m-%d', + + /** + *| Parameter | Description |Type | Required | Values| + *| --- | --- | --- | --- | --- | + *| useMaxWidth | See notes | Boolean | 4 | True, False | + * + ***Notes:**when this flag is set the height and width is set to 100% and is then scaling with the + *available space if not the absolute space required is used. + * + ***Default value true**. + */ + useMaxWidth: true, + + useWidth: undefined }, + /** * The object containing configurations specific for journey diagrams */ @@ -711,10 +738,35 @@ const config = { rightAngles: false }, class: { - arrowMarkerAbsolute: false + arrowMarkerAbsolute: false, + /** + *| Parameter | Description |Type | Required | Values| + *| --- | --- | --- | --- | --- | + *| useMaxWidth | See notes | Boolean | 4 | True, False | + * + ***Notes:**when this flag is set the height and width is set to 100% and is then scaling with the + *available space if not the absolute space required is used. + * + ***Default value true**. + */ + useMaxWidth: true }, git: { - arrowMarkerAbsolute: false + arrowMarkerAbsolute: false, + + useWidth: undefined, + + /** + *| Parameter | Description |Type | Required | Values| + *| --- | --- | --- | --- | --- | + *| useMaxWidth | See notes | Boolean | 4 | True, False | + * + ***Notes:**when this flag is set the height and width is set to 100% and is then scaling with the + *available space if not the absolute space required is used. + * + ***Default value true**. + */ + useMaxWidth: true }, state: { dividerMargin: 10, @@ -734,7 +786,18 @@ const config = { labelHeight: 16, edgeLengthFactor: '20', compositTitleSize: 35, - radius: 5 + radius: 5, + /** + *| Parameter | Description |Type | Required | Values| + *| --- | --- | --- | --- | --- | + *| useMaxWidth | See notes | Boolean | 4 | True, False | + * + ***Notes:**when this flag is set the height and width is set to 100% and is then scaling with the + *available space if not the absolute space required is used. + * + ***Default value true**. + */ + useMaxWidth: true }, /** diff --git a/src/diagrams/class/classRenderer-v2.js b/src/diagrams/class/classRenderer-v2.js index 07ed68d2a..3419b6b7d 100644 --- a/src/diagrams/class/classRenderer-v2.js +++ b/src/diagrams/class/classRenderer-v2.js @@ -9,7 +9,7 @@ import { getConfig } from '../../config'; import { render } from '../../dagre-wrapper/index.js'; // import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import { curveLinear } from 'd3'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; +import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; import common from '../common/common'; parser.yy = classDb; @@ -325,13 +325,7 @@ export const drawOld = function(text, id) { const width = svgBounds.width + padding * 2; const height = svgBounds.height + padding * 2; - if (conf.useMaxWidth) { - diagram.attr('width', '100%'); - diagram.attr('style', `max-width: ${width}px;`); - } else { - diagram.attr('height', height); - diagram.attr('width', width); - } + configureSvgSize(diagram, height, width, conf.useMaxWidth); // Ensure the viewBox includes the whole svgBounds area with extra space for padding const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; @@ -427,13 +421,7 @@ export const draw = function(text, id) { `translate(${padding - g._label.marginx}, ${padding - g._label.marginy})` ); - if (conf.useMaxWidth) { - svg.attr('width', '100%'); - svg.attr('style', `max-width: ${width}px;`); - } else { - svg.attr('height', height); - svg.attr('width', width); - } + configureSvgSize(svg, height, width, conf.useMaxWidth); svg.attr('viewBox', `0 0 ${width} ${height}`); svg diff --git a/src/diagrams/class/classRenderer.js b/src/diagrams/class/classRenderer.js index 93e0a8dfc..727ecca20 100644 --- a/src/diagrams/class/classRenderer.js +++ b/src/diagrams/class/classRenderer.js @@ -5,6 +5,7 @@ import { logger } from '../../logger'; import classDb, { lookUpDomId } from './classDb'; import { parser } from './parser/classDiagram'; import svgDraw from './svgDraw'; +import { configureSvgSize } from '../../utils'; parser.yy = classDb; @@ -232,13 +233,7 @@ export const draw = function(text, id) { const width = svgBounds.width + padding * 2; const height = svgBounds.height + padding * 2; - if (conf.useMaxWidth) { - diagram.attr('width', '100%'); - diagram.attr('style', `max-width: ${width}px;`); - } else { - diagram.attr('height', height); - diagram.attr('width', width); - } + configureSvgSize(diagram, height, width, conf.useMaxWidth); // Ensure the viewBox includes the whole svgBounds area with extra space for padding const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; diff --git a/src/diagrams/er/erRenderer.js b/src/diagrams/er/erRenderer.js index e73dcd667..ead9612db 100644 --- a/src/diagrams/er/erRenderer.js +++ b/src/diagrams/er/erRenderer.js @@ -6,6 +6,7 @@ import dagre from 'dagre'; import { getConfig } from '../../config'; import { logger } from '../../logger'; import erMarkers from './erMarkers'; +import { configureSvgSize } from '../../utils'; const conf = {}; @@ -344,13 +345,7 @@ export const draw = function(text, id) { const width = svgBounds.width + padding * 2; const height = svgBounds.height + padding * 2; - if (conf.useMaxWidth) { - svg.attr('width', '100%'); - svg.attr('style', `max-width: ${width}px;`); - } else { - svg.attr('height', height); - svg.attr('width', width); - } + configureSvgSize(svg, height, width, conf.useMaxWidth); svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`); }; // draw diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js index 03c795e3f..d89ef118b 100644 --- a/src/diagrams/flowchart/flowRenderer-v2.js +++ b/src/diagrams/flowchart/flowRenderer-v2.js @@ -9,7 +9,7 @@ import { render } from '../../dagre-wrapper/index.js'; import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import { logger } from '../../logger'; import common from '../common/common'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; +import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; const conf = {}; export const setConf = function(cnf) { @@ -418,13 +418,7 @@ export const draw = function(text, id) { `translate(${padding - g._label.marginx}, ${padding - g._label.marginy})` ); - if (conf.useMaxWidth) { - svg.attr('width', '100%'); - svg.attr('style', `max-width: ${width}px;`); - } else { - svg.attr('height', height); - svg.attr('width', width); - } + configureSvgSize(svg, height, width, conf.useMaxWidth); svg.attr('viewBox', `0 0 ${width} ${height}`); svg diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 5ab9ec293..be60bf4b3 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -9,7 +9,7 @@ import dagreD3 from 'dagre-d3'; import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import { logger } from '../../logger'; import common from '../common/common'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; +import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; import flowChartShapes from './flowChartShapes'; const conf = {}; @@ -401,13 +401,7 @@ export const draw = function(text, id) { const width = svgBounds.width + padding * 2; const height = svgBounds.height + padding * 2; - if (conf.useMaxWidth) { - svg.attr('width', '100%'); - svg.attr('style', `max-width: ${width}px;`); - } else { - svg.attr('height', height); - svg.attr('width', width); - } + configureSvgSize(svg, height, width, conf.useMaxWidth); // Ensure the viewBox includes the whole svgBounds area with extra space for padding const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index 98e6391a9..95711f85c 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -11,6 +11,7 @@ import { import { parser } from './parser/gantt'; import common from '../common/common'; import ganttDb from './ganttDb'; +import { configureSvgSize } from '../../utils'; parser.yy = ganttDb; @@ -53,7 +54,6 @@ export const draw = function(text, id) { // Set height based on number of tasks const h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding; - elem.setAttribute('height', '100%'); // Set viewBox elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h); const svg = select(`[id="${id}"]`); @@ -97,9 +97,8 @@ export const draw = function(text, id) { taskArray.sort(taskCompare); makeGant(taskArray, w, h); - if (typeof conf.useWidth !== 'undefined') { - elem.setAttribute('width', w); - } + + configureSvgSize(elem, h, w, conf.useMaxWidth); svg .append('text') diff --git a/src/diagrams/pie/pieRenderer.js b/src/diagrams/pie/pieRenderer.js index ee725b9f5..3dc4352fe 100644 --- a/src/diagrams/pie/pieRenderer.js +++ b/src/diagrams/pie/pieRenderer.js @@ -5,6 +5,7 @@ import { select, scaleOrdinal, schemeSet2, pie as d3pie, entries, arc } from 'd3 import pieData from './pieDb'; import pieParser from './parser/pie'; import { logger } from '../../logger'; +import { configureSvgSize } from '../../utils'; const conf = {}; export const setConf = function(cnf) { @@ -20,7 +21,8 @@ export const setConf = function(cnf) { * @param text * @param id */ -let w; +let width; +const height = 450; export const draw = (txt, id) => { try { const parser = pieParser.parser; @@ -31,24 +33,22 @@ export const draw = (txt, id) => { parser.parse(txt); logger.debug('Parsed info diagram'); const elem = document.getElementById(id); - w = elem.parentElement.offsetWidth; + width = elem.parentElement.offsetWidth; - if (typeof w === 'undefined') { - w = 1200; + if (typeof width === 'undefined') { + width = 1200; } if (typeof conf.useWidth !== 'undefined') { - w = conf.useWidth; + width = conf.useWidth; } - const h = 450; - elem.setAttribute('height', '100%'); + + configureSvgSize(elem, height, width, conf.useMaxWidth); + // Set viewBox - elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h); + elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height); // Fetch the default direction, use TD if none was found - - var width = w; // 450 - var height = 450; var margin = 40; var legendRectSize = 18; var legendSpacing = 4; @@ -119,7 +119,7 @@ export const draw = (txt, id) => { .append('text') .text(parser.yy.getTitle()) .attr('x', 0) - .attr('y', -(h - 50) / 2) + .attr('y', -(height - 50) / 2) .attr('class', 'pieTitleText'); //Add the slegend/annotations for each section diff --git a/src/diagrams/sequence/sequenceRenderer.js b/src/diagrams/sequence/sequenceRenderer.js index cc2e140f2..b4fda5400 100644 --- a/src/diagrams/sequence/sequenceRenderer.js +++ b/src/diagrams/sequence/sequenceRenderer.js @@ -5,7 +5,7 @@ import { parser } from './parser/sequenceDiagram'; import common from '../common/common'; import sequenceDb from './sequenceDb'; import * as configApi from '../../config'; -import utils, { assignWithDepth } from '../../utils'; +import utils, { assignWithDepth, configureSvgSize } from '../../utils'; parser.yy = sequenceDb; @@ -706,15 +706,8 @@ export const draw = function(text, id) { .attr('y', -25); } - if (conf.useMaxWidth) { - diagram.attr('height', '100%'); - diagram.attr('width', '100%'); - diagram.attr('style', 'max-width:' + width + 'px;'); - // diagram.attr('style', 'max-width:100%;'); - } else { - diagram.attr('height', height); - diagram.attr('width', width); - } + configureSvgSize(diagram, height, width, conf.useMaxWidth); + const extraVertForTitle = title ? 40 : 0; diagram.attr( 'viewBox', diff --git a/src/diagrams/state/stateRenderer-v2.js b/src/diagrams/state/stateRenderer-v2.js index 90683d2d4..057307fbb 100644 --- a/src/diagrams/state/stateRenderer-v2.js +++ b/src/diagrams/state/stateRenderer-v2.js @@ -6,6 +6,7 @@ import { getConfig } from '../../config'; import { render } from '../../dagre-wrapper/index.js'; import { logger } from '../../logger'; +import { configureSvgSize } from '../../utils'; const conf = {}; export const setConf = function(cnf) { @@ -211,11 +212,7 @@ export const draw = function(text, id) { parser.yy = stateDb; // Parse the graph definition - // try { parser.parse(text); - // } catch (err) { - // logger.error('Parsing failed', err); - // } // Fetch the default direction, use TD if none was found let dir = stateDb.getDirection(); @@ -256,54 +253,18 @@ export const draw = function(text, id) { render(element, g, ['barb'], 'statediagram', id); const padding = 8; - // const svgBounds = svg.node().getBBox(); - // const width = svgBounds.width + padding * 2; - // const height = svgBounds.height + padding * 2; - // logger.debug( - // `new ViewBox 0 0 ${width} ${height}`, - // `translate(${padding + g._label.marginx}, ${padding + g._label.marginy})` - // ); - - // if (conf.useMaxWidth) { - // svg.attr('width', '100%'); - // svg.attr('style', `max-width: ${width}px;`); - // } else { - // svg.attr('height', height); - // svg.attr('width', width); - // } - - // svg.attr('viewBox', `0 0 ${width} ${height}`); - // svg - // .select('g') - // .attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`); const bounds = svg.node().getBBox(); const width = bounds.width + padding * 2; const height = bounds.height + padding * 2; - // diagram.attr('height', '100%'); - // diagram.attr('style', `width: ${bounds.width * 3 + conf.padding * 2};`); - // diagram.attr('height', height); - // Zoom in a bit - svg.attr('width', width * 1.75); svg.attr('class', 'statediagram'); - // diagram.attr('height', bounds.height * 3 + conf.padding * 2); - // svg.attr( - // 'viewBox', - // `${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + ' ' + height - // ); const svgBounds = svg.node().getBBox(); - if (conf.useMaxWidth) { - svg.attr('width', '100%'); - svg.attr('style', `max-width: ${width}px;`); - } else { - svg.attr('height', height); - svg.attr('width', width); - } + configureSvgSize(svg, height, width * 1.75, conf.useMaxWidth); // Ensure the viewBox includes the whole svgBounds area with extra space for padding const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; diff --git a/src/diagrams/state/stateRenderer.js b/src/diagrams/state/stateRenderer.js index f6489851a..e52969ee7 100644 --- a/src/diagrams/state/stateRenderer.js +++ b/src/diagrams/state/stateRenderer.js @@ -8,6 +8,7 @@ import { parser } from './parser/stateDiagram'; // import idCache from './id-cache'; import { drawState, addTitleAndBox, drawEdge } from './shapes'; import { getConfig } from '../../config'; +import { configureSvgSize } from '../../utils'; parser.yy = stateDb; @@ -75,14 +76,10 @@ export const draw = function(text, id) { const width = bounds.width + padding * 2; const height = bounds.height + padding * 2; - if (conf.useMaxWidth) { - diagram.attr('width', '100%'); - diagram.attr('style', `max-width: ${width * 1.75}px;`); - } else { - // Zoom in a bit - diagram.attr('width', width * 1.75); - } - // diagram.attr('height', bounds.height * 3 + conf.padding * 2); + // zoom in a bit + const svgWidth = width * 1.75; + configureSvgSize(diagram, height, svgWidth, conf.useMaxWidth); + diagram.attr( 'viewBox', `${bounds.x - conf.padding} ${bounds.y - conf.padding} ` + width + ' ' + height diff --git a/src/diagrams/user-journey/journeyRenderer.js b/src/diagrams/user-journey/journeyRenderer.js index e871a4693..854f2ce37 100644 --- a/src/diagrams/user-journey/journeyRenderer.js +++ b/src/diagrams/user-journey/journeyRenderer.js @@ -2,6 +2,7 @@ import { select } from 'd3'; import { parser } from './parser/journey'; import journeyDb from './journeyDb'; import svgDraw from './svgDraw'; +import { configureSvgSize } from '../../utils'; parser.yy = journeyDb; @@ -118,14 +119,8 @@ export const draw = function(text, id) { } const height = box.stopy - box.starty + 2 * conf.diagramMarginY; const width = LEFT_MARGIN + box.stopx + 2 * conf.diagramMarginX; - if (conf.useMaxWidth) { - diagram.attr('height', '100%'); - diagram.attr('width', '100%'); - diagram.attr('style', 'max-width:' + width + 'px;'); - } else { - diagram.attr('height', height); - diagram.attr('width', width); - } + + configureSvgSize(diagram, height, width, conf.useMaxWidth); // Draw activity line diagram diff --git a/src/utils.js b/src/utils.js index 8fe374b00..0f54c4212 100644 --- a/src/utils.js +++ b/src/utils.js @@ -695,12 +695,37 @@ export const calculateTextDimensions = memoize( (text, config) => `${text}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}` ); +const d3Attrs = function(d3Elem, attrs) { + for (let attr of attrs) { + d3Elem.attr(attr[0], attr[1]); + } +}; + +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; +}; + +export const configureSvgSize = function(svgElem, height, width, useMaxWidth) { + const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth); + d3Attrs(svgElem, attrs); +}; + export default { assignWithDepth, wrapLabel, calculateTextHeight, calculateTextWidth, calculateTextDimensions, + calculateSvgSizeAttrs, + configureSvgSize, detectInit, detectDirective, detectType, diff --git a/src/utils.spec.js b/src/utils.spec.js index 08c4654e0..c3fd94f93 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -1,5 +1,5 @@ /* eslint-env jasmine */ -import utils from './utils'; +import utils from './utils'; describe('when assignWithDepth: should merge objects within objects', function() { it('should handle simple, depth:1 types (identity)', function() { @@ -171,7 +171,6 @@ Alice->Bob: hi`; expect(type).toBe('git'); }); }); - describe('when finding substring in array ', function() { it('should return the array index that contains the substring', function() { const arr = ['stroke:val1', 'fill:val2']; @@ -184,7 +183,6 @@ describe('when finding substring in array ', function() { expect(result).toEqual(-1); }); }); - describe('when formatting urls', function() { it('should handle links', function() { const url = 'https://mermaid-js.github.io/mermaid/#/'; @@ -242,3 +240,16 @@ describe('when formatting urls', function() { expect(result).toEqual('about:blank'); }); }); +describe('when calculating SVG size', function() { + it('should return width 100% when useMaxWidth is true', function () { + const attrs = utils.calculateSvgSizeAttrs(100, 200, true); + expect(attrs.get('height')).toEqual(100); + expect(attrs.get('style')).toEqual('max-width: 200px;'); + expect(attrs.get('width')).toEqual('100%'); + }); + it('should return absolute width when useMaxWidth is false', function () { + const attrs = utils.calculateSvgSizeAttrs(100, 200, false); + expect(attrs.get('height')).toEqual(100); + expect(attrs.get('width')).toEqual(200); + }); +});