@pixldocs/canvas-renderer 0.5.80 → 0.5.82

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 CHANGED
@@ -12609,7 +12609,7 @@ function PixldocsPreview(props) {
12609
12609
  !canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
12610
12610
  ] });
12611
12611
  }
12612
- const PACKAGE_VERSION = "0.5.80";
12612
+ const PACKAGE_VERSION = "0.5.81";
12613
12613
  const roundParityValue = (value) => {
12614
12614
  if (typeof value !== "number") return value;
12615
12615
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -12884,7 +12884,7 @@ class PixldocsRenderer {
12884
12884
  async renderPdf(templateConfig, options) {
12885
12885
  const svgs = await this.renderAllPageSvgs(templateConfig);
12886
12886
  const { assemblePdfFromSvgs: assemblePdfFromSvgs2 } = await Promise.resolve().then(() => pdfExport);
12887
- return assemblePdfFromSvgs2(svgs, { title: options == null ? void 0 : options.title, fontBaseUrl: options == null ? void 0 : options.fontBaseUrl });
12887
+ return assemblePdfFromSvgs2(svgs, { title: options == null ? void 0 : options.title, fontBaseUrl: options == null ? void 0 : options.fontBaseUrl, textMode: (options == null ? void 0 : options.textMode) ?? templateConfig.pdfTextMode ?? "selectable" });
12888
12888
  }
12889
12889
  /**
12890
12890
  * Resolve from V2 sectionState and render a vector PDF.
@@ -12909,7 +12909,7 @@ class PixldocsRenderer {
12909
12909
  }
12910
12910
  const svgs = await this.renderAllPageSvgs(configToRender);
12911
12911
  const { assemblePdfFromSvgs: assemblePdfFromSvgs2 } = await Promise.resolve().then(() => pdfExport);
12912
- return assemblePdfFromSvgs2(svgs, { title: title ?? resolved.config.name, fontBaseUrl });
12912
+ return assemblePdfFromSvgs2(svgs, { title: title ?? resolved.config.name, fontBaseUrl, textMode: options.textMode ?? configToRender.pdfTextMode ?? "selectable" });
12913
12913
  }
12914
12914
  async renderById(templateId, formData, options) {
12915
12915
  const resolved = await resolveTemplateData({
@@ -14159,10 +14159,22 @@ async function embedFont(pdf, fontName, weight, fontBaseUrl, isItalic = false) {
14159
14159
  async function embedFontsForConfig(pdf, config, fontBaseUrl) {
14160
14160
  const fontKeys = /* @__PURE__ */ new Set();
14161
14161
  const SEP = "";
14162
+ const normalizeWeight = (raw) => {
14163
+ if (raw == null) return 400;
14164
+ if (typeof raw === "number" && Number.isFinite(raw)) return resolveFontWeight(raw);
14165
+ const str = String(raw).trim().toLowerCase();
14166
+ const parsed = Number.parseInt(str, 10);
14167
+ if (Number.isFinite(parsed)) return resolveFontWeight(parsed);
14168
+ if (str === "bold" || str === "bolder") return 700;
14169
+ if (str === "semibold" || str === "demibold") return 600;
14170
+ if (str === "medium") return 500;
14171
+ if (str === "light" || str === "lighter" || str === "thin") return 300;
14172
+ return 400;
14173
+ };
14162
14174
  const walkElements = (elements) => {
14163
14175
  for (const el of elements) {
14164
14176
  if (el.fontFamily) {
14165
- const w = resolveFontWeight(el.fontWeight ?? 400);
14177
+ const w = normalizeWeight(el.fontWeight);
14166
14178
  fontKeys.add(`${el.fontFamily}${SEP}${w}`);
14167
14179
  }
14168
14180
  if (el.styles && typeof el.styles === "object") {
@@ -14172,7 +14184,7 @@ async function embedFontsForConfig(pdf, config, fontBaseUrl) {
14172
14184
  for (const charKey of Object.keys(lineStyles)) {
14173
14185
  const s = lineStyles[charKey];
14174
14186
  if (s == null ? void 0 : s.fontFamily) {
14175
- const w = resolveFontWeight(s.fontWeight ?? 400);
14187
+ const w = normalizeWeight(s.fontWeight);
14176
14188
  fontKeys.add(`${s.fontFamily}${SEP}${w}`);
14177
14189
  }
14178
14190
  }
@@ -15454,7 +15466,9 @@ async function convertTextDecorationsToLines(svg) {
15454
15466
  const fontFamily = tspan.getAttribute("data-source-font-family") || textEl.getAttribute("data-source-font-family") || resolveInheritedSvgValue(tspan, "font-family") || "sans-serif";
15455
15467
  const fontWeight = tspan.getAttribute("data-source-font-weight") || textEl.getAttribute("data-source-font-weight") || resolveInheritedSvgValue(tspan, "font-weight") || "normal";
15456
15468
  const fontStyle = tspan.getAttribute("data-source-font-style") || textEl.getAttribute("data-source-font-style") || resolveInheritedSvgValue(tspan, "font-style") || "normal";
15457
- const fill = tspan.getAttribute("fill") || textEl.getAttribute("fill") || "#000000";
15469
+ const resolvedFill = tspan.getAttribute("fill") || getInlineStyleValue(tspan, "fill") || resolveInheritedSvgValue(tspan, "fill") || textEl.getAttribute("fill") || getInlineStyleValue(textEl, "fill") || "#000000";
15470
+ const fill = resolvedFill;
15471
+ const fillOpacity = tspan.getAttribute("fill-opacity") || getInlineStyleValue(tspan, "fill-opacity") || resolveInheritedSvgValue(tspan, "fill-opacity") || textEl.getAttribute("fill-opacity") || getInlineStyleValue(textEl, "fill-opacity") || null;
15458
15472
  let textWidth = content.length * fontSize * 0.6;
15459
15473
  if (ctx) {
15460
15474
  ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily.replace(/'/g, "")}`;
@@ -15505,6 +15519,7 @@ async function convertTextDecorationsToLines(svg) {
15505
15519
  line.setAttribute("stroke-width", String(thickness));
15506
15520
  line.setAttribute("stroke-linecap", "butt");
15507
15521
  line.setAttribute("fill", "none");
15522
+ if (fillOpacity) line.setAttribute("stroke-opacity", fillOpacity);
15508
15523
  if (textEl.parentElement) {
15509
15524
  textEl.parentElement.insertBefore(line, textEl.nextSibling);
15510
15525
  }
@@ -15804,7 +15819,9 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15804
15819
  const hasGradient = !!((_b = (_a = page.backgroundGradient) == null ? void 0 : _a.stops) == null ? void 0 : _b.length);
15805
15820
  drawPageBackground(pdf, i, page.width, page.height, page.backgroundColor, page.backgroundGradient);
15806
15821
  const shouldStripBg = stripPageBackground ?? hasGradient;
15807
- const shouldOutlineText = options.outlineText !== false;
15822
+ const textMode = options.textMode ?? (options.outlineText ? "pixel-perfect" : "selectable");
15823
+ const shouldOutlineText = textMode === "pixel-perfect" || textMode === "auto";
15824
+ const outlineSubMode = textMode === "auto" ? "complex-only" : "all";
15808
15825
  let pageSvg = page.svg;
15809
15826
  try {
15810
15827
  pageSvg = await convertSvgTextDecorationsToLinesString(pageSvg);
@@ -15816,8 +15833,8 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15816
15833
  }
15817
15834
  if (shouldOutlineText) {
15818
15835
  try {
15819
- const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-BTHnqJpM.cjs"));
15820
- pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl);
15836
+ const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-DHAXuVMF.cjs"));
15837
+ pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl, { mode: outlineSubMode });
15821
15838
  try {
15822
15839
  dumpSvgTextDiagnostics(pageSvg, i, PARITY_TAG, "STAGE-1b-after-text-to-path-raw");
15823
15840
  } catch {