@pixldocs/canvas-renderer 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +92 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +92 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11900,8 +11900,47 @@ async function embedFontsForConfig(pdf, config, fontBaseUrl) {
|
|
|
11900
11900
|
console.log(`[pdf-fonts] Embedded ${embedded.size} font variants from config`);
|
|
11901
11901
|
return embedded;
|
|
11902
11902
|
}
|
|
11903
|
+
function isDevanagari(char) {
|
|
11904
|
+
const c = char.codePointAt(0) ?? 0;
|
|
11905
|
+
return c >= 2304 && c <= 2431 || c >= 43232 && c <= 43263 || c >= 7376 && c <= 7423;
|
|
11906
|
+
}
|
|
11907
|
+
function containsDevanagari(text) {
|
|
11908
|
+
if (!text) return false;
|
|
11909
|
+
for (const char of text) {
|
|
11910
|
+
if (isDevanagari(char)) return true;
|
|
11911
|
+
}
|
|
11912
|
+
return false;
|
|
11913
|
+
}
|
|
11914
|
+
function isBasicLatinOrLatin1(char) {
|
|
11915
|
+
const c = char.codePointAt(0) ?? 0;
|
|
11916
|
+
return c <= 591;
|
|
11917
|
+
}
|
|
11918
|
+
function classifyChar(char) {
|
|
11919
|
+
if (isBasicLatinOrLatin1(char)) return "main";
|
|
11920
|
+
if (isDevanagari(char)) return "devanagari";
|
|
11921
|
+
return "symbol";
|
|
11922
|
+
}
|
|
11923
|
+
function splitIntoRuns(text) {
|
|
11924
|
+
if (!text) return [];
|
|
11925
|
+
const runs = [];
|
|
11926
|
+
let currentType = null;
|
|
11927
|
+
let currentText = "";
|
|
11928
|
+
for (const char of text) {
|
|
11929
|
+
const type = classifyChar(char);
|
|
11930
|
+
if (type !== currentType && currentText) {
|
|
11931
|
+
runs.push({ text: currentText, runType: currentType });
|
|
11932
|
+
currentText = "";
|
|
11933
|
+
}
|
|
11934
|
+
currentType = type;
|
|
11935
|
+
currentText += char;
|
|
11936
|
+
}
|
|
11937
|
+
if (currentText && currentType) {
|
|
11938
|
+
runs.push({ text: currentText, runType: currentType });
|
|
11939
|
+
}
|
|
11940
|
+
return runs;
|
|
11941
|
+
}
|
|
11903
11942
|
function rewriteSvgFontsForJsPDF(svgStr) {
|
|
11904
|
-
var _a;
|
|
11943
|
+
var _a, _b;
|
|
11905
11944
|
const parser = new DOMParser();
|
|
11906
11945
|
const doc = parser.parseFromString(svgStr, "image/svg+xml");
|
|
11907
11946
|
const textEls = doc.querySelectorAll("text, tspan, textPath");
|
|
@@ -11922,6 +11961,17 @@ function rewriteSvgFontsForJsPDF(svgStr) {
|
|
|
11922
11961
|
}
|
|
11923
11962
|
return null;
|
|
11924
11963
|
};
|
|
11964
|
+
const resolveWeightNum = (weightRaw) => {
|
|
11965
|
+
const parsedWeight = Number.parseInt(weightRaw, 10);
|
|
11966
|
+
return Number.isFinite(parsedWeight) ? parsedWeight : /bold/i.test(weightRaw) ? 700 : /medium/i.test(weightRaw) ? 500 : /semi/i.test(weightRaw) ? 600 : /light/i.test(weightRaw) ? 300 : 400;
|
|
11967
|
+
};
|
|
11968
|
+
const buildStyleString = (existingStyle, fontName) => {
|
|
11969
|
+
const stylePairs = existingStyle.split(";").map((part) => part.trim()).filter(Boolean).filter((part) => !/^font-family\s*:/i.test(part) && !/^font-weight\s*:/i.test(part) && !/^font-style\s*:/i.test(part));
|
|
11970
|
+
stylePairs.push(`font-family: ${fontName}`);
|
|
11971
|
+
stylePairs.push(`font-weight: normal`);
|
|
11972
|
+
stylePairs.push(`font-style: normal`);
|
|
11973
|
+
return stylePairs.join("; ");
|
|
11974
|
+
};
|
|
11925
11975
|
for (const el of textEls) {
|
|
11926
11976
|
const inlineStyle = el.getAttribute("style") || "";
|
|
11927
11977
|
const rawFf = resolveInheritedValue(el, "font-family");
|
|
@@ -11930,19 +11980,50 @@ function rewriteSvgFontsForJsPDF(svgStr) {
|
|
|
11930
11980
|
if (!isFontAvailable(clean)) continue;
|
|
11931
11981
|
const weightRaw = resolveInheritedValue(el, "font-weight") || "400";
|
|
11932
11982
|
const styleRaw = resolveInheritedValue(el, "font-style") || "normal";
|
|
11933
|
-
const
|
|
11934
|
-
const weight = Number.isFinite(parsedWeight) ? parsedWeight : /bold/i.test(weightRaw) ? 700 : /medium/i.test(weightRaw) ? 500 : /semi/i.test(weightRaw) ? 600 : /light/i.test(weightRaw) ? 300 : 400;
|
|
11983
|
+
const weight = resolveWeightNum(weightRaw);
|
|
11935
11984
|
const resolved = resolveFontWeight(weight);
|
|
11936
11985
|
const isItalic = /italic|oblique/i.test(styleRaw);
|
|
11937
11986
|
const jsPdfName = getEmbeddedJsPDFFontName(clean, resolved, isItalic);
|
|
11938
|
-
el.
|
|
11939
|
-
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11987
|
+
const directText = Array.from(el.childNodes).filter((n) => n.nodeType === 3).map((n) => n.textContent || "").join("");
|
|
11988
|
+
const hasDevanagari = containsDevanagari(directText);
|
|
11989
|
+
if (hasDevanagari && directText.length > 0) {
|
|
11990
|
+
const devanagariWeight = resolveFontWeight(weight);
|
|
11991
|
+
const devanagariJsPdfName = getEmbeddedJsPDFFontName(FONT_FALLBACK_DEVANAGARI, devanagariWeight);
|
|
11992
|
+
const symbolJsPdfName = isFontAvailable(FONT_FALLBACK_SYMBOLS) ? getEmbeddedJsPDFFontName(FONT_FALLBACK_SYMBOLS, 400) : jsPdfName;
|
|
11993
|
+
const childNodes = Array.from(el.childNodes);
|
|
11994
|
+
for (const node of childNodes) {
|
|
11995
|
+
if (node.nodeType !== 3 || !node.textContent) continue;
|
|
11996
|
+
const runs = splitIntoRuns(node.textContent);
|
|
11997
|
+
if (runs.length <= 1 && ((_b = runs[0]) == null ? void 0 : _b.runType) !== "devanagari") continue;
|
|
11998
|
+
const fragment = doc.createDocumentFragment();
|
|
11999
|
+
for (const run of runs) {
|
|
12000
|
+
const tspan = doc.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
|
12001
|
+
let runFont;
|
|
12002
|
+
if (run.runType === "devanagari") {
|
|
12003
|
+
runFont = devanagariJsPdfName;
|
|
12004
|
+
} else if (run.runType === "symbol") {
|
|
12005
|
+
runFont = symbolJsPdfName;
|
|
12006
|
+
} else {
|
|
12007
|
+
runFont = jsPdfName;
|
|
12008
|
+
}
|
|
12009
|
+
tspan.setAttribute("font-family", runFont);
|
|
12010
|
+
tspan.setAttribute("font-weight", "normal");
|
|
12011
|
+
tspan.setAttribute("font-style", "normal");
|
|
12012
|
+
tspan.textContent = run.text;
|
|
12013
|
+
fragment.appendChild(tspan);
|
|
12014
|
+
}
|
|
12015
|
+
el.replaceChild(fragment, node);
|
|
12016
|
+
}
|
|
12017
|
+
el.setAttribute("font-family", jsPdfName);
|
|
12018
|
+
el.setAttribute("font-weight", "normal");
|
|
12019
|
+
el.setAttribute("font-style", "normal");
|
|
12020
|
+
el.setAttribute("style", buildStyleString(inlineStyle, jsPdfName));
|
|
12021
|
+
} else {
|
|
12022
|
+
el.setAttribute("font-family", jsPdfName);
|
|
12023
|
+
el.setAttribute("font-weight", "normal");
|
|
12024
|
+
el.setAttribute("font-style", "normal");
|
|
12025
|
+
el.setAttribute("style", buildStyleString(inlineStyle, jsPdfName));
|
|
12026
|
+
}
|
|
11946
12027
|
}
|
|
11947
12028
|
return new XMLSerializer().serializeToString(doc.documentElement);
|
|
11948
12029
|
}
|