mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 14:29:25 +02:00
Merge branch 'next' into sidv/tinyMermaid
* next: chore: Move SVG import to comment. build docs Remove whitespace on empty line chore: Fix minify Documentation for #2509 Update all minor dependencies Update all patch dependencies make more `RectData` required and remove optional assignment use lineBreakRegex in `svgDrawCommon` fix svgDrawCommon import by adding `.js` add types to `svgDrawCommon.ts` convert `svgDrawCommon` to TS
This commit is contained in:
@@ -60,7 +60,7 @@ const getFileName = (
|
||||
};
|
||||
|
||||
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
const { core, entryName, metafile, format, includeLargeDiagrams } = options;
|
||||
const { core, entryName, metafile, format, includeLargeDiagrams, minify } = options;
|
||||
const external: string[] = ['require', 'fs', 'path'];
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
const outFileName = getFileName(name, options);
|
||||
@@ -70,6 +70,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
[outFileName]: `src/${file}`,
|
||||
},
|
||||
metafile,
|
||||
minify,
|
||||
logLevel: 'info',
|
||||
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
|
||||
define: {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
mermaid:
|
||||
image: node:18.17.0-alpine3.18
|
||||
image: node:18.17.1-alpine3.18
|
||||
stdin_open: true
|
||||
tty: true
|
||||
working_dir: /mermaid
|
||||
@@ -17,7 +17,7 @@ services:
|
||||
- 9000:9000
|
||||
- 3333:3333
|
||||
cypress:
|
||||
image: cypress/included:12.17.2
|
||||
image: cypress/included:12.17.3
|
||||
stdin_open: true
|
||||
tty: true
|
||||
working_dir: /mermaid
|
||||
|
@@ -748,6 +748,48 @@ flowchart LR
|
||||
B1 --> B2
|
||||
```
|
||||
|
||||
#### Limitation
|
||||
|
||||
If any of a subgraph's nodes are linked to the outside, subgraph direction will be ignored. Instead the subgraph will inherit the direction of the parent graph:
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
subgraph subgraph1
|
||||
direction TB
|
||||
top1[top] --> bottom1[bottom]
|
||||
end
|
||||
subgraph subgraph2
|
||||
direction TB
|
||||
top2[top] --> bottom2[bottom]
|
||||
end
|
||||
%% ^ These subgraphs are identical, except for the links to them:
|
||||
|
||||
%% Link *to* subgraph1: subgraph1 direction is mantained
|
||||
outside --> subgraph1
|
||||
%% Link *within* subgraph2:
|
||||
%% subgraph2 inherits the direction of the top-level graph (LR)
|
||||
outside ---> top2
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph subgraph1
|
||||
direction TB
|
||||
top1[top] --> bottom1[bottom]
|
||||
end
|
||||
subgraph subgraph2
|
||||
direction TB
|
||||
top2[top] --> bottom2[bottom]
|
||||
end
|
||||
%% ^ These subgraphs are identical, except for the links to them:
|
||||
|
||||
%% Link *to* subgraph1: subgraph1 direction is mantained
|
||||
outside --> subgraph1
|
||||
%% Link *within* subgraph2:
|
||||
%% subgraph2 inherits the direction of the top-level graph (LR)
|
||||
outside ---> top2
|
||||
```
|
||||
|
||||
## Markdown Strings
|
||||
|
||||
The "Markdown Strings" feature enhances flowcharts and mind maps by offering a more versatile string type, which supports text formatting options such as bold and italics, and automatically wraps text within labels.
|
||||
|
12
package.json
12
package.json
@@ -4,7 +4,7 @@
|
||||
"version": "10.2.4",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@8.6.11",
|
||||
"packageManager": "pnpm@8.6.12",
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
@@ -78,9 +78,9 @@
|
||||
"@types/rollup-plugin-visualizer": "^4.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.0",
|
||||
"@typescript-eslint/parser": "^5.59.0",
|
||||
"@vitest/coverage-v8": "^0.33.0",
|
||||
"@vitest/spy": "^0.33.0",
|
||||
"@vitest/ui": "^0.33.0",
|
||||
"@vitest/coverage-v8": "^0.34.0",
|
||||
"@vitest/spy": "^0.34.0",
|
||||
"@vitest/ui": "^0.34.0",
|
||||
"ajv": "^8.12.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"concurrently": "^8.0.1",
|
||||
@@ -120,10 +120,10 @@
|
||||
"typescript": "^5.1.3",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-istanbul": "^4.1.0",
|
||||
"vitest": "^0.33.0"
|
||||
"vitest": "^0.34.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "18.17.0"
|
||||
"node": "18.17.1"
|
||||
},
|
||||
"nyc": {
|
||||
"report-dir": "coverage/cypress"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import common from '../common/common.js';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
|
||||
export const drawRect = function (elem, rectData) {
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import { sanitizeText, removeScript, parseGenericTypes } from './common.js';
|
||||
|
||||
describe('when securityLevel is antiscript, all script must be removed', function () {
|
||||
describe('when securityLevel is antiscript, all script must be removed', () => {
|
||||
/**
|
||||
* @param {string} original The original text
|
||||
* @param {string} result The expected sanitized text
|
||||
* @param original - The original text
|
||||
* @param result - The expected sanitized text
|
||||
*/
|
||||
function compareRemoveScript(original, result) {
|
||||
function compareRemoveScript(original: string, result: string) {
|
||||
expect(removeScript(original).trim()).toEqual(result);
|
||||
}
|
||||
|
||||
it('should remove all script block, script inline.', function () {
|
||||
it('should remove all script block, script inline.', () => {
|
||||
const labelString = `1
|
||||
Act1: Hello 1<script src="http://abc.com/script1.js"></script>1
|
||||
<b>Act2</b>:
|
||||
@@ -25,7 +25,7 @@ describe('when securityLevel is antiscript, all script must be removed', functio
|
||||
compareRemoveScript(labelString, exactlyString);
|
||||
});
|
||||
|
||||
it('should remove all javascript urls', function () {
|
||||
it('should remove all javascript urls', () => {
|
||||
compareRemoveScript(
|
||||
`This is a <a href="javascript:runHijackingScript();">clean link</a> + <a href="javascript:runHijackingScript();">clean link</a>
|
||||
and <a href="javascript:bipassedMining();">me too</a>`,
|
||||
@@ -34,11 +34,11 @@ describe('when securityLevel is antiscript, all script must be removed', functio
|
||||
);
|
||||
});
|
||||
|
||||
it('should detect malicious images', function () {
|
||||
it('should detect malicious images', () => {
|
||||
compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`);
|
||||
});
|
||||
|
||||
it('should detect iframes', function () {
|
||||
it('should detect iframes', () => {
|
||||
compareRemoveScript(
|
||||
`<iframe src="http://abc.com/script1.js"></iframe>
|
||||
<iframe src="http://example.com/iframeexample"></iframe>`,
|
||||
@@ -47,8 +47,8 @@ describe('when securityLevel is antiscript, all script must be removed', functio
|
||||
});
|
||||
});
|
||||
|
||||
describe('Sanitize text', function () {
|
||||
it('should remove script tag', function () {
|
||||
describe('Sanitize text', () => {
|
||||
it('should remove script tag', () => {
|
||||
const maliciousStr = 'javajavascript:script:alert(1)';
|
||||
const result = sanitizeText(maliciousStr, {
|
||||
securityLevel: 'strict',
|
||||
@@ -58,8 +58,8 @@ describe('Sanitize text', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('generic parser', function () {
|
||||
it('should parse generic types', function () {
|
||||
describe('generic parser', () => {
|
||||
it('should parse generic types', () => {
|
||||
expect(parseGenericTypes('test~T~')).toEqual('test<T>');
|
||||
expect(parseGenericTypes('test~Array~Array~string~~~')).toEqual('test<Array<Array<string>>>');
|
||||
expect(parseGenericTypes('test~Array~Array~string[]~~~')).toEqual(
|
@@ -1,6 +1,7 @@
|
||||
import DOMPurify from 'dompurify';
|
||||
import { MermaidConfig } from '../../config.type.js';
|
||||
|
||||
// Remove and ignore br:s
|
||||
export const lineBreakRegex = /<br\s*\/?>/gi;
|
||||
|
||||
/**
|
||||
|
58
packages/mermaid/src/diagrams/common/commonTypes.ts
Normal file
58
packages/mermaid/src/diagrams/common/commonTypes.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
export interface RectData {
|
||||
x: number;
|
||||
y: number;
|
||||
fill: string;
|
||||
width: number;
|
||||
height: number;
|
||||
stroke: string;
|
||||
class?: string;
|
||||
color?: string;
|
||||
rx?: number;
|
||||
ry?: number;
|
||||
attrs?: Record<string, string | number>;
|
||||
anchor?: string;
|
||||
}
|
||||
|
||||
export interface Bound {
|
||||
startx: number;
|
||||
stopx: number;
|
||||
starty: number;
|
||||
stopy: number;
|
||||
fill: string;
|
||||
stroke: string;
|
||||
}
|
||||
|
||||
export interface TextData {
|
||||
x: number;
|
||||
y: number;
|
||||
anchor: string;
|
||||
text: string;
|
||||
textMargin: number;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
export interface TextObject {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
fill?: string;
|
||||
anchor?: string;
|
||||
'text-anchor': string;
|
||||
style: string;
|
||||
textMargin: number;
|
||||
rx: number;
|
||||
ry: number;
|
||||
tspan: boolean;
|
||||
valign?: string;
|
||||
}
|
||||
|
||||
export type D3RectElement = d3.Selection<SVGRectElement, unknown, Element | null, unknown>;
|
||||
|
||||
export type D3UseElement = d3.Selection<SVGUseElement, unknown, Element | null, unknown>;
|
||||
|
||||
export type D3ImageElement = d3.Selection<SVGImageElement, unknown, Element | null, unknown>;
|
||||
|
||||
export type D3TextElement = d3.Selection<SVGTextElement, unknown, Element | null, unknown>;
|
||||
|
||||
export type D3TSpanElement = d3.Selection<SVGTSpanElement, unknown, Element | null, unknown>;
|
@@ -1,114 +0,0 @@
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
|
||||
export const drawRect = function (elem, rectData) {
|
||||
const rectElem = elem.append('rect');
|
||||
rectElem.attr('x', rectData.x);
|
||||
rectElem.attr('y', rectData.y);
|
||||
rectElem.attr('fill', rectData.fill);
|
||||
rectElem.attr('stroke', rectData.stroke);
|
||||
rectElem.attr('width', rectData.width);
|
||||
rectElem.attr('height', rectData.height);
|
||||
rectElem.attr('rx', rectData.rx);
|
||||
rectElem.attr('ry', rectData.ry);
|
||||
|
||||
if (rectData.attrs !== 'undefined' && rectData.attrs !== null) {
|
||||
for (let attrKey in rectData.attrs) {
|
||||
rectElem.attr(attrKey, rectData.attrs[attrKey]);
|
||||
}
|
||||
}
|
||||
|
||||
if (rectData.class !== 'undefined') {
|
||||
rectElem.attr('class', rectData.class);
|
||||
}
|
||||
|
||||
return rectElem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a background rectangle
|
||||
*
|
||||
* @param {any} elem Diagram (reference for bounds)
|
||||
* @param {any} bounds Shape of the rectangle
|
||||
*/
|
||||
export const drawBackgroundRect = function (elem, bounds) {
|
||||
const rectElem = drawRect(elem, {
|
||||
x: bounds.startx,
|
||||
y: bounds.starty,
|
||||
width: bounds.stopx - bounds.startx,
|
||||
height: bounds.stopy - bounds.starty,
|
||||
fill: bounds.fill,
|
||||
stroke: bounds.stroke,
|
||||
class: 'rect',
|
||||
});
|
||||
rectElem.lower();
|
||||
};
|
||||
|
||||
export const drawText = function (elem, textData) {
|
||||
// Remove and ignore br:s
|
||||
const nText = textData.text.replace(/<br\s*\/?>/gi, ' ');
|
||||
|
||||
const textElem = elem.append('text');
|
||||
textElem.attr('x', textData.x);
|
||||
textElem.attr('y', textData.y);
|
||||
textElem.attr('class', 'legend');
|
||||
|
||||
textElem.style('text-anchor', textData.anchor);
|
||||
|
||||
if (textData.class !== undefined) {
|
||||
textElem.attr('class', textData.class);
|
||||
}
|
||||
|
||||
const span = textElem.append('tspan');
|
||||
span.attr('x', textData.x + textData.textMargin * 2);
|
||||
span.text(nText);
|
||||
|
||||
return textElem;
|
||||
};
|
||||
|
||||
export const drawImage = function (elem, x, y, link) {
|
||||
const imageElem = elem.append('image');
|
||||
imageElem.attr('x', x);
|
||||
imageElem.attr('y', y);
|
||||
var sanitizedLink = sanitizeUrl(link);
|
||||
imageElem.attr('xlink:href', sanitizedLink);
|
||||
};
|
||||
|
||||
export const drawEmbeddedImage = function (elem, x, y, link) {
|
||||
const imageElem = elem.append('use');
|
||||
imageElem.attr('x', x);
|
||||
imageElem.attr('y', y);
|
||||
const sanitizedLink = sanitizeUrl(link);
|
||||
imageElem.attr('xlink:href', '#' + sanitizedLink);
|
||||
};
|
||||
|
||||
export const getNoteRect = function () {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
fill: '#EDF2AE',
|
||||
stroke: '#666',
|
||||
anchor: 'start',
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
};
|
||||
};
|
||||
|
||||
export const getTextObj = function () {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
fill: undefined,
|
||||
anchor: undefined,
|
||||
'text-anchor': 'start',
|
||||
style: '#666',
|
||||
textMargin: 0,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
tspan: true,
|
||||
valign: undefined,
|
||||
};
|
||||
};
|
126
packages/mermaid/src/diagrams/common/svgDrawCommon.ts
Normal file
126
packages/mermaid/src/diagrams/common/svgDrawCommon.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import type { Group, SVG } from '../../diagram-api/types.js';
|
||||
import type {
|
||||
Bound,
|
||||
D3ImageElement,
|
||||
D3RectElement,
|
||||
D3TSpanElement,
|
||||
D3TextElement,
|
||||
D3UseElement,
|
||||
RectData,
|
||||
TextData,
|
||||
TextObject,
|
||||
} from './commonTypes.js';
|
||||
import { lineBreakRegex } from './common.js';
|
||||
|
||||
export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElement => {
|
||||
const rectElement: D3RectElement = element.append('rect');
|
||||
rectElement.attr('x', rectData.x);
|
||||
rectElement.attr('y', rectData.y);
|
||||
rectElement.attr('fill', rectData.fill);
|
||||
rectElement.attr('stroke', rectData.stroke);
|
||||
rectElement.attr('width', rectData.width);
|
||||
rectElement.attr('height', rectData.height);
|
||||
rectData.rx !== undefined && rectElement.attr('rx', rectData.rx);
|
||||
rectData.ry !== undefined && rectElement.attr('ry', rectData.ry);
|
||||
|
||||
if (rectData.attrs !== undefined) {
|
||||
for (const attrKey in rectData.attrs) {
|
||||
rectElement.attr(attrKey, rectData.attrs[attrKey]);
|
||||
}
|
||||
}
|
||||
|
||||
rectData.class !== undefined && rectElement.attr('class', rectData.class);
|
||||
|
||||
return rectElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a background rectangle
|
||||
*
|
||||
* @param element - Diagram (reference for bounds)
|
||||
* @param bounds - Shape of the rectangle
|
||||
*/
|
||||
export const drawBackgroundRect = (element: SVG | Group, bounds: Bound): void => {
|
||||
const rectData: RectData = {
|
||||
x: bounds.startx,
|
||||
y: bounds.starty,
|
||||
width: bounds.stopx - bounds.startx,
|
||||
height: bounds.stopy - bounds.starty,
|
||||
fill: bounds.fill,
|
||||
stroke: bounds.stroke,
|
||||
class: 'rect',
|
||||
};
|
||||
const rectElement: D3RectElement = drawRect(element, rectData);
|
||||
rectElement.lower();
|
||||
};
|
||||
|
||||
export const drawText = (element: SVG | Group, textData: TextData): D3TextElement => {
|
||||
const nText: string = textData.text.replace(lineBreakRegex, ' ');
|
||||
|
||||
const textElem: D3TextElement = element.append('text');
|
||||
textElem.attr('x', textData.x);
|
||||
textElem.attr('y', textData.y);
|
||||
textElem.attr('class', 'legend');
|
||||
|
||||
textElem.style('text-anchor', textData.anchor);
|
||||
textData.class !== undefined && textElem.attr('class', textData.class);
|
||||
|
||||
const tspan: D3TSpanElement = textElem.append('tspan');
|
||||
tspan.attr('x', textData.x + textData.textMargin * 2);
|
||||
tspan.text(nText);
|
||||
|
||||
return textElem;
|
||||
};
|
||||
|
||||
export const drawImage = (elem: SVG | Group, x: number, y: number, link: string): void => {
|
||||
const imageElement: D3ImageElement = elem.append('image');
|
||||
imageElement.attr('x', x);
|
||||
imageElement.attr('y', y);
|
||||
const sanitizedLink: string = sanitizeUrl(link);
|
||||
imageElement.attr('xlink:href', sanitizedLink);
|
||||
};
|
||||
|
||||
export const drawEmbeddedImage = (
|
||||
element: SVG | Group,
|
||||
x: number,
|
||||
y: number,
|
||||
link: string
|
||||
): void => {
|
||||
const imageElement: D3UseElement = element.append('use');
|
||||
imageElement.attr('x', x);
|
||||
imageElement.attr('y', y);
|
||||
const sanitizedLink: string = sanitizeUrl(link);
|
||||
imageElement.attr('xlink:href', `#${sanitizedLink}`);
|
||||
};
|
||||
|
||||
export const getNoteRect = (): RectData => {
|
||||
const noteRectData: RectData = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
fill: '#EDF2AE',
|
||||
stroke: '#666',
|
||||
anchor: 'start',
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
};
|
||||
return noteRectData;
|
||||
};
|
||||
|
||||
export const getTextObj = (): TextObject => {
|
||||
const testObject: TextObject = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
'text-anchor': 'start',
|
||||
style: '#666',
|
||||
textMargin: 0,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
tspan: true,
|
||||
};
|
||||
return testObject;
|
||||
};
|
@@ -3,7 +3,7 @@ import { select, selectAll } from 'd3';
|
||||
import svgDraw, { ACTOR_TYPE_WIDTH, drawText, fixLifeLineHeights } from './svgDraw.js';
|
||||
import { log } from '../../logger.js';
|
||||
import common from '../common/common.js';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
import * as configApi from '../../config.js';
|
||||
import assignWithDepth from '../../assignWithDepth.js';
|
||||
import utils from '../../utils.js';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import common from '../common/common.js';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
import { addFunction } from '../../interactionDb.js';
|
||||
import { ZERO_WIDTH_SPACE, parseFontSize } from '../../utils.js';
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { arc as d3arc } from 'd3';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
|
||||
export const drawRect = function (elem, rectData) {
|
||||
return svgDrawCommon.drawRect(elem, rectData);
|
||||
|
@@ -21,17 +21,17 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/carbon": "^1.1.16",
|
||||
"@unocss/reset": "^0.54.0",
|
||||
"@unocss/reset": "^0.55.0",
|
||||
"@vite-pwa/vitepress": "^0.2.0",
|
||||
"@vitejs/plugin-vue": "^4.2.1",
|
||||
"fast-glob": "^3.2.12",
|
||||
"https-localhost": "^4.7.1",
|
||||
"pathe": "^1.1.0",
|
||||
"unocss": "^0.54.0",
|
||||
"unocss": "^0.55.0",
|
||||
"unplugin-vue-components": "^0.25.0",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-pwa": "^0.16.0",
|
||||
"vitepress": "1.0.0-beta.7",
|
||||
"vitepress": "1.0.0-rc.4",
|
||||
"workbox-window": "^7.0.0"
|
||||
}
|
||||
}
|
||||
|
@@ -471,6 +471,29 @@ flowchart LR
|
||||
B1 --> B2
|
||||
```
|
||||
|
||||
#### Limitation
|
||||
|
||||
If any of a subgraph's nodes are linked to the outside, subgraph direction will be ignored. Instead the subgraph will inherit the direction of the parent graph:
|
||||
|
||||
```mermaid-example
|
||||
flowchart LR
|
||||
subgraph subgraph1
|
||||
direction TB
|
||||
top1[top] --> bottom1[bottom]
|
||||
end
|
||||
subgraph subgraph2
|
||||
direction TB
|
||||
top2[top] --> bottom2[bottom]
|
||||
end
|
||||
%% ^ These subgraphs are identical, except for the links to them:
|
||||
|
||||
%% Link *to* subgraph1: subgraph1 direction is mantained
|
||||
outside --> subgraph1
|
||||
%% Link *within* subgraph2:
|
||||
%% subgraph2 inherits the direction of the top-level graph (LR)
|
||||
outside ---> top2
|
||||
```
|
||||
|
||||
## Markdown Strings
|
||||
|
||||
The "Markdown Strings" feature enhances flowcharts and mind maps by offering a more versatile string type, which supports text formatting options such as bold and italics, and automatically wraps text within labels.
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { log } from './logger.js';
|
||||
import { SVG } from './diagram-api/types.js';
|
||||
|
||||
/**
|
||||
* Applies d3 attributes
|
||||
@@ -36,7 +35,7 @@ export const calculateSvgSizeAttrs = function (height, width, useMaxWidth) {
|
||||
/**
|
||||
* Applies attributes from `calculateSvgSizeAttrs`
|
||||
*
|
||||
* @param {SVG} svgElem The SVG Element to configure
|
||||
* @param {import('./diagram-api/types.js').SVG} svgElem The SVG Element to configure
|
||||
* @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%
|
||||
|
7054
pnpm-lock.yaml
generated
7054
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user