mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-18 14:59:53 +02:00
functions and specs: removeExistingElements
This commit is contained in:

parent
166dca55f2
commit
fcba29f774
@@ -4,7 +4,7 @@ import { vi } from 'vitest';
|
|||||||
import mermaid from './mermaid';
|
import mermaid from './mermaid';
|
||||||
import { MermaidConfig } from './config.type';
|
import { MermaidConfig } from './config.type';
|
||||||
|
|
||||||
import mermaidAPI from './mermaidAPI';
|
import mermaidAPI, { removeExistingElements } from './mermaidAPI';
|
||||||
import {
|
import {
|
||||||
encodeEntities,
|
encodeEntities,
|
||||||
decodeEntities,
|
decodeEntities,
|
||||||
@@ -454,6 +454,76 @@ describe('when using mermaidAPI and ', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('removeExistingElements', () => {
|
||||||
|
const svgId = 'svgId';
|
||||||
|
const tempDivId = 'tempDivId';
|
||||||
|
const tempIframeId = 'tempIFrameId';
|
||||||
|
const givenDocument = new Document();
|
||||||
|
const rootHtml = givenDocument.createElement('html');
|
||||||
|
givenDocument.append(rootHtml);
|
||||||
|
|
||||||
|
const svgElement = givenDocument.createElement('svg'); // doesn't matter what the tag is in the test
|
||||||
|
svgElement.id = svgId;
|
||||||
|
const tempDivElement = givenDocument.createElement('div'); // doesn't matter what the tag is in the test
|
||||||
|
tempDivElement.id = tempDivId;
|
||||||
|
const tempiFrameElement = givenDocument.createElement('div'); // doesn't matter what the tag is in the test
|
||||||
|
tempiFrameElement.id = tempIframeId;
|
||||||
|
|
||||||
|
it('removes an existing element with given id', () => {
|
||||||
|
rootHtml.appendChild(svgElement);
|
||||||
|
expect(givenDocument.getElementById(svgElement.id)).toEqual(svgElement);
|
||||||
|
removeExistingElements(givenDocument, false, svgId, tempDivId, tempIframeId);
|
||||||
|
expect(givenDocument.getElementById(svgElement.id)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('is in sandboxed mode', () => {
|
||||||
|
const inSandboxedMode = true;
|
||||||
|
|
||||||
|
it('removes an existing element with the given iFrame selector', () => {
|
||||||
|
tempiFrameElement.append(svgElement);
|
||||||
|
rootHtml.append(tempiFrameElement);
|
||||||
|
rootHtml.append(tempDivElement);
|
||||||
|
|
||||||
|
expect(givenDocument.getElementById(tempIframeId)).toEqual(tempiFrameElement);
|
||||||
|
expect(givenDocument.getElementById(tempDivId)).toEqual(tempDivElement);
|
||||||
|
expect(givenDocument.getElementById(svgId)).toEqual(svgElement);
|
||||||
|
removeExistingElements(
|
||||||
|
givenDocument,
|
||||||
|
inSandboxedMode,
|
||||||
|
svgId,
|
||||||
|
'#' + tempDivId,
|
||||||
|
'#' + tempIframeId
|
||||||
|
);
|
||||||
|
expect(givenDocument.getElementById(tempDivId)).toEqual(tempDivElement);
|
||||||
|
expect(givenDocument.getElementById(tempIframeId)).toBeNull();
|
||||||
|
expect(givenDocument.getElementById(svgId)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('not in sandboxed mode', () => {
|
||||||
|
const inSandboxedMode = false;
|
||||||
|
|
||||||
|
it('removes an existing element with the given enclosing div selector', () => {
|
||||||
|
tempDivElement.append(svgElement);
|
||||||
|
rootHtml.append(tempDivElement);
|
||||||
|
rootHtml.append(tempiFrameElement);
|
||||||
|
|
||||||
|
expect(givenDocument.getElementById(tempIframeId)).toEqual(tempiFrameElement);
|
||||||
|
expect(givenDocument.getElementById(tempDivId)).toEqual(tempDivElement);
|
||||||
|
expect(givenDocument.getElementById(svgId)).toEqual(svgElement);
|
||||||
|
removeExistingElements(
|
||||||
|
givenDocument,
|
||||||
|
inSandboxedMode,
|
||||||
|
svgId,
|
||||||
|
'#' + tempDivId,
|
||||||
|
'#' + tempIframeId
|
||||||
|
);
|
||||||
|
expect(givenDocument.getElementById(tempIframeId)).toEqual(tempiFrameElement);
|
||||||
|
expect(givenDocument.getElementById(tempDivId)).toBeNull();
|
||||||
|
expect(givenDocument.getElementById(svgId)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('doing initialize ', function () {
|
describe('doing initialize ', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
|
@@ -86,10 +86,10 @@ function parse(text: string, parseError?: ParseErrorFunction): boolean {
|
|||||||
export const encodeEntities = function (text: string): string {
|
export const encodeEntities = function (text: string): string {
|
||||||
let txt = text;
|
let txt = text;
|
||||||
|
|
||||||
txt = txt.replace(/style.*:\S*#.*;/g, function (s) {
|
txt = txt.replace(/style.*:\S*#.*;/g, function (s): string {
|
||||||
return s.substring(0, s.length - 1);
|
return s.substring(0, s.length - 1);
|
||||||
});
|
});
|
||||||
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s) {
|
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s): string {
|
||||||
return s.substring(0, s.length - 1);
|
return s.substring(0, s.length - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -319,6 +319,31 @@ function sandboxedIframe(parentNode: D3Element, iFrameId: string): D3Element {
|
|||||||
.attr('sandbox', '');
|
.attr('sandbox', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove any existing elements from the given document
|
||||||
|
*
|
||||||
|
* @param {Document} doc - the document to removed elements from
|
||||||
|
* @param {string} isSandboxed - whether or not we are in sandboxed mode
|
||||||
|
* @param {string} id - id for any existing SVG element
|
||||||
|
* @param {string} divSelector - selector for any existing enclosing div element
|
||||||
|
* @param {string} iFrameSelector - selector for any existing iFrame element
|
||||||
|
*/
|
||||||
|
export const removeExistingElements = (
|
||||||
|
doc: Document,
|
||||||
|
isSandboxed: boolean,
|
||||||
|
id: string,
|
||||||
|
divSelector: string,
|
||||||
|
iFrameSelector: string
|
||||||
|
) => {
|
||||||
|
// Remove existing SVG element if it exists
|
||||||
|
const existingSvg = doc.getElementById(id);
|
||||||
|
if (existingSvg) existingSvg.remove();
|
||||||
|
|
||||||
|
// Remove previous temporary element if it exists
|
||||||
|
const element = isSandboxed ? doc.querySelector(iFrameSelector) : doc.querySelector(divSelector);
|
||||||
|
if (element) element.remove();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
||||||
*
|
*
|
||||||
@@ -384,8 +409,8 @@ const render = async function (
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Define the root d3 node
|
// Define the root d3 node
|
||||||
|
|
||||||
// In regular execution the svgContainingElement will be the element with a mermaid class
|
// In regular execution the svgContainingElement will be the element with a mermaid class
|
||||||
|
|
||||||
if (typeof svgContainingElement !== 'undefined') {
|
if (typeof svgContainingElement !== 'undefined') {
|
||||||
if (svgContainingElement) svgContainingElement.innerHTML = '';
|
if (svgContainingElement) svgContainingElement.innerHTML = '';
|
||||||
|
|
||||||
@@ -400,19 +425,9 @@ const render = async function (
|
|||||||
appendDivSvgG(root, id, enclosingDivID, `font-family: ${fontFamily}`, XMLNS_XLINK_STD);
|
appendDivSvgG(root, id, enclosingDivID, `font-family: ${fontFamily}`, XMLNS_XLINK_STD);
|
||||||
} else {
|
} else {
|
||||||
// No svgContainingElement was provided
|
// No svgContainingElement was provided
|
||||||
// If there is an existing element with the id, we remove it
|
|
||||||
// this likely a previously rendered diagram
|
|
||||||
const existingSvg = document.getElementById(id);
|
|
||||||
if (existingSvg) existingSvg.remove();
|
|
||||||
|
|
||||||
// Remove previous temporary element if it exists
|
// If there is an existing element with the id, we remove it. This likely a previously rendered diagram
|
||||||
let element;
|
removeExistingElements(document, isSandboxed, id, iFrameID_selector, enclosingDivID_selector);
|
||||||
if (isSandboxed) {
|
|
||||||
element = document.querySelector(iFrameID_selector);
|
|
||||||
} else {
|
|
||||||
element = document.querySelector(enclosingDivID_selector);
|
|
||||||
}
|
|
||||||
if (element) element.remove();
|
|
||||||
|
|
||||||
// Add the temporary div used for rendering with the enclosingDivID.
|
// Add the temporary div used for rendering with the enclosingDivID.
|
||||||
// This temporary div will contain a svg with the id == id
|
// This temporary div will contain a svg with the id == id
|
||||||
@@ -420,7 +435,6 @@ const render = async function (
|
|||||||
if (isSandboxed) {
|
if (isSandboxed) {
|
||||||
// If we are in sandboxed mode, we do everything mermaid related in a (sandboxed) iFrame
|
// If we are in sandboxed mode, we do everything mermaid related in a (sandboxed) iFrame
|
||||||
const iframe = sandboxedIframe(select('body'), iFrameID);
|
const iframe = sandboxedIframe(select('body'), iFrameID);
|
||||||
|
|
||||||
root = select(iframe.nodes()[0]!.contentDocument!.body);
|
root = select(iframe.nodes()[0]!.contentDocument!.body);
|
||||||
root.node().style.margin = 0;
|
root.node().style.margin = 0;
|
||||||
} else root = select('body');
|
} else root = select('body');
|
||||||
|
Reference in New Issue
Block a user