Skip to content

Commit

Permalink
Merge pull request mermaid-js#4724 from Yokozuna59/chore/convert-svgD…
Browse files Browse the repository at this point in the history
…rawCommon-to-ts

convert `diagrams/common/svgDrawCommon.js` to ts
  • Loading branch information
Yokozuna59 committed Aug 15, 2023
2 parents 085e8f7 + 50eb3cf commit 99978da
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 130 deletions.
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagrams/c4/svgDraw.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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>:
Expand All @@ -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&colon;bipassedMining();">me too</a>`,
Expand All @@ -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>`,
Expand All @@ -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',
Expand All @@ -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(
Expand Down
1 change: 1 addition & 0 deletions packages/mermaid/src/diagrams/common/common.ts
Original file line number Diff line number Diff line change
@@ -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;

/**
Expand Down
58 changes: 58 additions & 0 deletions packages/mermaid/src/diagrams/common/commonTypes.ts
Original file line number Diff line number Diff line change
@@ -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>;
114 changes: 0 additions & 114 deletions packages/mermaid/src/diagrams/common/svgDrawCommon.js

This file was deleted.

126 changes: 126 additions & 0 deletions packages/mermaid/src/diagrams/common/svgDrawCommon.ts
Original file line number Diff line number Diff line change
@@ -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;
};
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagrams/sequence/svgDraw.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
Loading

0 comments on commit 99978da

Please sign in to comment.