Merge pull request #5520 from iansan5653/fix-sandbox-utf16

Fix `sandbox` mode with UTF-16 characters
This commit is contained in:
Sidharth Vinod
2024-06-20 18:07:40 +00:00
committed by GitHub
7 changed files with 24 additions and 19 deletions

View File

@@ -69,6 +69,7 @@ vi.mock('stylis', () => {
import { compile, serialize } from 'stylis';
import { decodeEntities, encodeEntities } from './utils.js';
import { Diagram } from './Diagram.js';
import { toBase64 } from './utils/base64.js';
/**
* @see https://vitest.dev/guide/mocking.html Mock part of a module
@@ -176,7 +177,7 @@ describe('mermaidAPI', () => {
});
describe('putIntoIFrame', () => {
const inputSvgCode = 'this is the SVG code';
const inputSvgCode = 'this is the SVG code';
it('uses the default SVG iFrame height is used if no svgElement given', () => {
const result = putIntoIFrame(inputSvgCode);
@@ -199,11 +200,10 @@ describe('mermaidAPI', () => {
});
it('sets src to base64 version of <body style="IFRAME_SVG_BODY_STYLE">svgCode<//body>', () => {
const base64encodedSrc = btoa('<body style="' + 'margin:0' + '">' + inputSvgCode + '</body>');
const expectedRegExp = new RegExp('src="data:text/html;base64,' + base64encodedSrc + '"');
const base64encodedSrc = toBase64(`<body style="margin:0">${inputSvgCode}</body>`);
const expectedSrc = `src="data:text/html;charset=UTF-8;base64,${base64encodedSrc}"`;
const result = putIntoIFrame(inputSvgCode);
expect(result).toMatch(expectedRegExp);
expect(result).toContain(expectedSrc);
});
it('uses the height and appends px from the svgElement given', () => {

View File

@@ -31,6 +31,7 @@ import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.
import type { DiagramMetadata, DiagramStyleClassDef } from './diagram-api/types.js';
import { preprocessDiagram } from './preprocess.js';
import { decodeEntities } from './utils.js';
import { toBase64 } from './utils/base64.js';
const MAX_TEXTLENGTH = 50_000;
const MAX_TEXTLENGTH_EXCEEDED_MSG =
@@ -248,14 +249,13 @@ export const cleanUpSvgCode = (
* @param svgCode - the svg code to put inside the iFrame
* @param svgElement - the d3 node that has the current svgElement so we can get the height from it
* @returns - the code with the iFrame that now contains the svgCode
* TODO replace btoa(). Replace with buf.toString('base64')?
*/
export const putIntoIFrame = (svgCode = '', svgElement?: D3Element): string => {
const height = svgElement?.viewBox?.baseVal?.height
? svgElement.viewBox.baseVal.height + 'px'
: IFRAME_HEIGHT;
const base64encodedSrc = btoa('<body style="' + IFRAME_BODY_STYLE + '">' + svgCode + '</body>');
return `<iframe style="width:${IFRAME_WIDTH};height:${height};${IFRAME_STYLES}" src="data:text/html;base64,${base64encodedSrc}" sandbox="${IFRAME_SANDBOX_OPTS}">
const base64encodedSrc = toBase64(`<body style="${IFRAME_BODY_STYLE}">${svgCode}</body>`);
return `<iframe style="width:${IFRAME_WIDTH};height:${height};${IFRAME_STYLES}" src="data:text/html;charset=UTF-8;base64,${base64encodedSrc}" sandbox="${IFRAME_SANDBOX_OPTS}">
${IFRAME_NOT_SUPPORTED_MSG}
</iframe>`;
};

View File

@@ -0,0 +1,6 @@
export function toBase64(str: string) {
// ref: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
const utf8Bytes = new TextEncoder().encode(str);
const utf8Str = Array.from(utf8Bytes, (byte) => String.fromCodePoint(byte)).join('');
return btoa(utf8Str);
}