Files
remoteconn-gitea/apps/miniprogram/utils/svgDataUri.js
2026-03-21 18:57:10 +08:00

81 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* 把 SVG 文本编码成 UTF-8 字节。
* 说明:
* 1. 小程序运行时没有稳定可用的 Buffer因此这里使用纯 JS 编码;
* 2. 需要显式处理代理对,避免非 ASCII 字符在 data URI 中损坏;
* 3. 非法代理项统一替换成 U+FFFD保证输出始终可编码。
*/
function encodeUtf8Bytes(input) {
const source = String(input || "");
const bytes = [];
for (let index = 0; index < source.length; index += 1) {
const first = source.charCodeAt(index);
if (first < 0x80) {
bytes.push(first);
continue;
}
if (first < 0x800) {
bytes.push(0xc0 | (first >> 6), 0x80 | (first & 0x3f));
continue;
}
let codePoint = first;
if (first >= 0xd800 && first <= 0xdbff) {
const second = source.charCodeAt(index + 1);
if (second >= 0xdc00 && second <= 0xdfff) {
codePoint = ((first - 0xd800) << 10) + (second - 0xdc00) + 0x10000;
index += 1;
} else {
codePoint = 0xfffd;
}
} else if (first >= 0xdc00 && first <= 0xdfff) {
codePoint = 0xfffd;
}
if (codePoint < 0x10000) {
bytes.push(0xe0 | (codePoint >> 12), 0x80 | ((codePoint >> 6) & 0x3f), 0x80 | (codePoint & 0x3f));
continue;
}
bytes.push(
0xf0 | (codePoint >> 18),
0x80 | ((codePoint >> 12) & 0x3f),
0x80 | ((codePoint >> 6) & 0x3f),
0x80 | (codePoint & 0x3f)
);
}
return bytes;
}
/**
* 把 UTF-8 字节数组转成 base64。
* 这样生成的 data URI 可以避开开发者工具对 `utf8,...` 形式 SVG URI 的兼容问题。
*/
function encodeBase64FromBytes(bytes) {
const output = [];
for (let index = 0; index < bytes.length; index += 3) {
const first = bytes[index];
const second = index + 1 < bytes.length ? bytes[index + 1] : null;
const third = index + 2 < bytes.length ? bytes[index + 2] : null;
const triplet = (first << 16) | ((second || 0) << 8) | (third || 0);
output.push(
BASE64_ALPHABET[(triplet >> 18) & 0x3f],
BASE64_ALPHABET[(triplet >> 12) & 0x3f],
second === null ? "=" : BASE64_ALPHABET[(triplet >> 6) & 0x3f],
third === null ? "=" : BASE64_ALPHABET[triplet & 0x3f]
);
}
return output.join("");
}
function toSvgDataUri(svg) {
const base64 = encodeBase64FromBytes(encodeUtf8Bytes(svg));
return `data:image/svg+xml;base64,${base64}`;
}
module.exports = {
toSvgDataUri
};