95 lines
2.3 KiB
Plaintext
95 lines
2.3 KiB
Plaintext
import { toUTF8String } from "./utils.js";
|
|
const svgReg = /<svg\s([^>"']|"[^"]*"|'[^']*')*>/;
|
|
const extractorRegExps = {
|
|
height: /\sheight=(['"])([^%]+?)\1/,
|
|
root: svgReg,
|
|
viewbox: /\sviewBox=(['"])(.+?)\1/i,
|
|
width: /\swidth=(['"])([^%]+?)\1/
|
|
};
|
|
const INCH_CM = 2.54;
|
|
const units = {
|
|
in: 96,
|
|
cm: 96 / INCH_CM,
|
|
em: 16,
|
|
ex: 8,
|
|
m: 96 / INCH_CM * 100,
|
|
mm: 96 / INCH_CM / 10,
|
|
pc: 96 / 72 / 12,
|
|
pt: 96 / 72,
|
|
px: 1
|
|
};
|
|
const unitsReg = new RegExp(
|
|
// eslint-disable-next-line regexp/prefer-d
|
|
`^([0-9.]+(?:e\\d+)?)(${Object.keys(units).join("|")})?$`
|
|
);
|
|
function parseLength(len) {
|
|
const m = unitsReg.exec(len);
|
|
if (!m) {
|
|
return void 0;
|
|
}
|
|
return Math.round(Number(m[1]) * (units[m[2]] || 1));
|
|
}
|
|
function parseViewbox(viewbox) {
|
|
const bounds = viewbox.split(" ");
|
|
return {
|
|
height: parseLength(bounds[3]),
|
|
width: parseLength(bounds[2])
|
|
};
|
|
}
|
|
function parseAttributes(root) {
|
|
const width = root.match(extractorRegExps.width);
|
|
const height = root.match(extractorRegExps.height);
|
|
const viewbox = root.match(extractorRegExps.viewbox);
|
|
return {
|
|
height: height && parseLength(height[2]),
|
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
viewbox: viewbox && parseViewbox(viewbox[2]),
|
|
width: width && parseLength(width[2])
|
|
};
|
|
}
|
|
function calculateByDimensions(attrs) {
|
|
return {
|
|
height: attrs.height,
|
|
width: attrs.width
|
|
};
|
|
}
|
|
function calculateByViewbox(attrs, viewbox) {
|
|
const ratio = viewbox.width / viewbox.height;
|
|
if (attrs.width) {
|
|
return {
|
|
height: Math.floor(attrs.width / ratio),
|
|
width: attrs.width
|
|
};
|
|
}
|
|
if (attrs.height) {
|
|
return {
|
|
height: attrs.height,
|
|
width: Math.floor(attrs.height * ratio)
|
|
};
|
|
}
|
|
return {
|
|
height: viewbox.height,
|
|
width: viewbox.width
|
|
};
|
|
}
|
|
const SVG = {
|
|
// Scan only the first kilo-byte to speed up the check on larger files
|
|
validate: (input) => svgReg.test(toUTF8String(input, 0, 1e3)),
|
|
calculate(input) {
|
|
const root = toUTF8String(input).match(extractorRegExps.root);
|
|
if (root) {
|
|
const attrs = parseAttributes(root[0]);
|
|
if (attrs.width && attrs.height) {
|
|
return calculateByDimensions(attrs);
|
|
}
|
|
if (attrs.viewbox) {
|
|
return calculateByViewbox(attrs, attrs.viewbox);
|
|
}
|
|
}
|
|
throw new TypeError("Invalid SVG");
|
|
}
|
|
};
|
|
export {
|
|
SVG
|
|
};
|