Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@
"version": "0.54.3"
},
"dependencies": {
"@xmldom/xmldom": "^0.8.6",
"entities": "^4.4.0"
"@xmldom/xmldom": "^0.8.6"
}
}
60 changes: 59 additions & 1 deletion src/svg/SVGCore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// source from https://github.com/ecomfe/zrender/blob/master/src/svg/core.ts
// under BSD-3-Clause license
// add some patch for skia
import { encodeXML } from 'entities';

export type SVGVNodeAttrs = Record<
string,
Expand All @@ -18,6 +17,65 @@ export interface SVGVNode {
key: string;
}

// Custom implementation of encodeXML to avoid issues with deprecated methods in entities package
// This is based on the entities package implementation but uses substring instead of substr
const xmlReplacer = /["&'<>$\x80-\uFFFF]/g;
const xmlCodeMap = new Map([
[34, '&quot;'],
[38, '&amp;'],
[39, '&apos;'],
[60, '&lt;'],
[62, '&gt;'],
]);

/**
* Gets the Unicode code point at the specified index in a string.
* Provides a fallback for environments that don't support String.prototype.codePointAt.
* Handles surrogate pairs correctly to get the full Unicode code point.
*/
const getCodePoint =
String.prototype.codePointAt != null
? (str: string, index: number) => str.codePointAt(index)!
: // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
(str: string, index: number) =>
// eslint-disable-next-line no-bitwise
(str.charCodeAt(index) & 0xfc00) === 0xd800
? (str.charCodeAt(index) - 0xd800) * 0x400 +
str.charCodeAt(index + 1) -
0xdc00 +
0x10000
: str.charCodeAt(index);

/**
* Encodes all non-ASCII characters and special XML characters using XML entities.
* Special characters (<, >, &, ", ') are encoded as named entities.
* Non-ASCII characters are encoded as numeric hexadecimal references (e.g., &#xfc;).
*
* @param str - The string to encode
* @returns The encoded string with XML entities
*/
function encodeXML(str: string): string {
let ret = '';
let lastIdx = 0;
let match;
while ((match = xmlReplacer.exec(str)) !== null) {
const i = match.index;
const char = str.charCodeAt(i);
const next = xmlCodeMap.get(char);
if (next !== undefined) {
ret += str.substring(lastIdx, i) + next;
lastIdx = i + 1;
} else {
ret += `${str.substring(lastIdx, i)}&#x${getCodePoint(str, i).toString(16)};`;
// Increase by 1 if we have a surrogate pair
// eslint-disable-next-line no-bitwise
lastIdx = xmlReplacer.lastIndex += Number((char & 0xfc00) === 0xd800);
}
}
// Use substring instead of deprecated substr
return ret + str.substring(lastIdx);
}

function createElementOpen(name: string, attrs?: SVGVNodeAttrs) {
const attrsStr: string[] = [];
if (attrs) {
Expand Down