Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert diagrams/common/svgDrawCommon.js to ts #4724

Merged
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>;
Yokozuna59 marked this conversation as resolved.
Show resolved Hide resolved
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