@worm-vue3-print/core 1.3.3 → 1.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Worm Base AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -26,10 +26,10 @@ print-core/
26
26
 
27
27
  ### 打印管线(`print/`,纯 TS)
28
28
 
29
- - 入口:`prepareDocument(job, runtime)`、`renderPdf(job, runtime)`、`renderScreenshot(job, runtime)`;
30
- - 规格:`buildPdfTargetSpec`、`toElectronPrintToPdfOptions`(英寸)、`toPlaywrightPdfOptions`(mm)、`buildScreenshotTargetSpec`;
29
+ - 入口:`prepareDocument(job, runtime)`、`renderPdf(job, runtime)`;
30
+ - 规格:`buildPdfTargetSpec`、`toElectronPrintToPdfOptions`(英寸)、`toPlaywrightPdfOptions`(mm);
31
31
  - 纸张:`resolvePaperMm`(宿主覆盖逃生门)、`paperViewportPx`(测量容器 mm→px)、`escapeHeightMm`(连续纸纸高逃生门);
32
- - 契约:`PageDriver`(宿主只实现 open/setContent/injectExecutor/evaluate 与可选 pdf/screenshot)+
32
+ - 契约:`PageDriver`(宿主只实现 open/setContent/injectExecutor/evaluate 与可选 pdf)+
33
33
  `createDomHostRuntime(driverFactory, bundle)`(共享的载入→注入→就绪→执行→释放时序、超时预算与错误归一化);
34
34
  - 拼版:`computeTileLayout` / `validateTiling` / `computeMaxColumns` / `tilePosition` / `resolveSheetMm` /
35
35
  `composeTiledHtml`(标签多行多列铺到目标纸,如 70×40 标签铺满 A4)。配置为模板级 `TemplateData.tiling`,
@@ -65,8 +65,8 @@ const html = generateHtml(pages)
65
65
  ```ts
66
66
  import { PrintDesigner, PrintHtmlPreview, createDefaultTemplate } from '@worm-vue3-print/canvas'
67
67
  import type { PrintBusinessField, TemplateData } from '@worm-vue3-print/canvas'
68
- // 设计器内部控件基于原生样式,需全局引入一次
69
- import '@worm-vue3-print/canvas/native-controls.css'
68
+ // 设计器控件样式(发布包唯一对外样式入口),需全局引入一次
69
+ import '@worm-vue3-print/canvas/style.css'
70
70
  ```
71
71
 
72
72
  ```vue
@@ -1,3 +1,9 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  "use strict";
2
8
  var __create = Object.create;
3
9
  var __defProp = Object.defineProperty;
@@ -173,23 +179,6 @@ function createDomHostRuntime(factory, bundle) {
173
179
  "RENDER_TIMEOUT",
174
180
  `PDF \u751F\u6210\u8D85\u8FC7 ${ms}ms`
175
181
  );
176
- },
177
- async toScreenshot(html, spec, viewport) {
178
- if (!driver.screenshot) throw new PrintFailure("UNSUPPORTED_RUNTIME", "\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u622A\u56FE");
179
- const ms = budget();
180
- return withTimeout(
181
- (async () => {
182
- try {
183
- await load(html, viewport);
184
- return await driver.screenshot(html, spec);
185
- } catch (err) {
186
- throw fail(err, "SCREENSHOT_FAILED", "\u622A\u56FE\u5931\u8D25");
187
- }
188
- })(),
189
- ms,
190
- "RENDER_TIMEOUT",
191
- `\u622A\u56FE\u8D85\u8FC7 ${ms}ms`
192
- );
193
182
  }
194
183
  };
195
184
  try {
@@ -1517,9 +1506,6 @@ function bindData(template, printData, baseUrl, fontBaseUrl) {
1517
1506
  if (bound.footer?.elements) {
1518
1507
  bound.footer.elements = bound.footer.elements.map((el) => bindElement(el, data, baseUrl));
1519
1508
  }
1520
- if (bound.firstPageOverlay?.elements) {
1521
- bound.firstPageOverlay.elements = bound.firstPageOverlay.elements.map((el) => bindElement(el, data, baseUrl));
1522
- }
1523
1509
  bound.elements = bound.elements.map((el) => bindElement(el, data, baseUrl));
1524
1510
  const fontBase = fontBaseUrl ?? baseUrl;
1525
1511
  if (fontBase && bound.fonts?.length) {
@@ -1960,7 +1946,6 @@ function areaGeometryBlock(template, paper, desc) {
1960
1946
  const { bottom: mb } = template.margins;
1961
1947
  const headerH = template.header?.height ?? 0;
1962
1948
  const footerH = template.footer?.height ?? 0;
1963
- const overlayH = template.firstPageOverlay?.height ?? 0;
1964
1949
  const contentWidth = paper.width - ml - mr;
1965
1950
  return `
1966
1951
  /* \u2500\u2500 \u9875\u7709 \u2500\u2500 */
@@ -1972,13 +1957,14 @@ ${desc}.page-header {
1972
1957
 
1973
1958
  /* \u2500\u2500 \u9875\u811A\uFF1A\u7EDD\u5BF9\u5B9A\u4F4D\u56FA\u5B9A\u5728\u9875\u9762\u5E95\u90E8\uFF08\u5185\u5BB9\u4E0D\u8DB3\u65F6\u4E0D\u968F\u6587\u6863\u6D41\u4E0A\u6D6E\uFF09 \u2500\u2500
1974
1959
  \u7528\u663E\u5F0F top \u5B9A\u4F4D\u5230\u300C\u7EB8\u9AD8 - \u4E0B\u8FB9\u8DDD - \u9875\u811A\u9AD8\u300D\uFF0C\u4FDD\u8BC1\u4E0B\u8FB9\u8DDD\u751F\u6548\u3001
1975
- \u4E0E\u8BBE\u8BA1\u5668 CanvasPaper \u7684\u4E09\u533A\u51E0\u4F55\u4E00\u81F4\u3002 */
1960
+ \u4E0E\u8BBE\u8BA1\u5668 CanvasPaper \u7684\u4E09\u533A\u51E0\u4F55\u4E00\u81F4\u3002
1961
+ \u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5305\u542B\u5757\u662F padding box \u5916\u7F18\uFF08= \u7EB8\u9762\uFF09\uFF0Cleft \u987B\u663E\u5F0F\u8865\u5DE6\u8FB9\u8DDD\u3002 */
1976
1962
  ${desc}.page-footer {
1977
1963
  width: ${mm(contentWidth)};
1978
1964
  height: ${mm(footerH)};
1979
1965
  position: absolute;
1980
1966
  top: ${mm(paper.height - mb - footerH)};
1981
- left: 0;
1967
+ left: ${mm(ml)};
1982
1968
  }
1983
1969
 
1984
1970
  /* \u2500\u2500 \u5185\u5BB9\u533A \u2500\u2500 */
@@ -1987,13 +1973,6 @@ ${desc}.content-area {
1987
1973
  position: relative;
1988
1974
  overflow: visible;
1989
1975
  }
1990
-
1991
- /* \u2500\u2500 \u9996\u9875\u53E0\u52A0\u533A\u57DF \u2500\u2500 */
1992
- ${desc}.first-page-overlay {
1993
- width: ${mm(contentWidth)};
1994
- height: ${mm(overlayH)};
1995
- position: relative;
1996
- }
1997
1976
  `;
1998
1977
  }
1999
1978
  function buildBasePageCss() {
@@ -2115,7 +2094,7 @@ var VALID_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double
2115
2094
  function parseBorder(width, style, color) {
2116
2095
  if (typeof width !== "number" || !Number.isFinite(width) || width <= 0) return null;
2117
2096
  return {
2118
- borderWidth: `${width}px`,
2097
+ borderWidth: `${width}pt`,
2119
2098
  borderStyle: typeof style === "string" && VALID_STYLES.has(style) ? style : "solid",
2120
2099
  borderColor: color || "#000"
2121
2100
  };
@@ -2396,7 +2375,6 @@ function paginate(template, measuredElements) {
2396
2375
  const { top: mt, bottom: mb } = template.margins;
2397
2376
  const headerH = template.header?.height ?? 0;
2398
2377
  const footerH = template.footer?.height ?? 0;
2399
- const overlayH = template.firstPageOverlay?.height ?? 0;
2400
2378
  const continuous = isContinuousPaper(template);
2401
2379
  const contentHeight = continuous ? Number.POSITIVE_INFINITY : paper.height - mt - mb - headerH - footerH;
2402
2380
  if (!continuous && contentHeight <= 0) {
@@ -2436,8 +2414,7 @@ function paginate(template, measuredElements) {
2436
2414
  const unitOf = buildPaginationUnits(sorted, measuredElements, groupMap);
2437
2415
  const pages = [];
2438
2416
  let currentPage = [];
2439
- let remaining = contentHeight - overlayH - SAFETY_MARGIN;
2440
- let isFirstPage = true;
2417
+ let remaining = contentHeight - SAFETY_MARGIN;
2441
2418
  let pageBroken = false;
2442
2419
  function sectionTop(el) {
2443
2420
  return pageBroken ? pageCursorTop() : el.options?.top ?? 0;
@@ -2446,7 +2423,7 @@ function paginate(template, measuredElements) {
2446
2423
  return Math.max(0, fullPageHeight() - remaining);
2447
2424
  }
2448
2425
  function fullPageHeight() {
2449
- return isFirstPage ? contentHeight - overlayH - SAFETY_MARGIN : contentHeight - SAFETY_MARGIN;
2426
+ return contentHeight - SAFETY_MARGIN;
2450
2427
  }
2451
2428
  let overflowOnCurrent = false;
2452
2429
  function pushPage() {
@@ -2465,7 +2442,6 @@ function paginate(template, measuredElements) {
2465
2442
  pushPage();
2466
2443
  currentPage = [];
2467
2444
  remaining = contentHeight - SAFETY_MARGIN;
2468
- isFirstPage = false;
2469
2445
  pageBroken = true;
2470
2446
  overflowOnCurrent = false;
2471
2447
  }
@@ -2768,7 +2744,6 @@ function generateMeasurementHtml(template, css, ctx, printData) {
2768
2744
  // totalPages placeholder
2769
2745
  ctx
2770
2746
  );
2771
- const overlayHtml = renderAreaElements(template.firstPageOverlay?.elements ?? [], contentWidth, void 0, void 0, ctx);
2772
2747
  let html = `<!DOCTYPE html>
2773
2748
  <html lang="zh-CN">
2774
2749
  <head>
@@ -2779,7 +2754,6 @@ function generateMeasurementHtml(template, css, ctx, printData) {
2779
2754
  <section class="print-page" data-measure-page="0">
2780
2755
  ${renderWatermarkLayerHtml(template.watermark, printData, getPaperDims(template))}
2781
2756
  <div class="page-header">${headerHtml}</div>
2782
- <div class="first-page-overlay">${overlayHtml}</div>
2783
2757
  <div class="content-area" style="height:auto;overflow:visible;">
2784
2758
  ${elementsHtml}
2785
2759
  </div>
@@ -2843,14 +2817,12 @@ function renderPage(template, page, pageNum, totalPages, ctx, printData, pageCla
2843
2817
  totalPages,
2844
2818
  pageCtx
2845
2819
  );
2846
- const overlayHtml = page.pageIndex === 0 ? `<div class="first-page-overlay">${renderAreaElements(scoped.firstPageOverlay?.elements ?? [], contentWidth, pageNum, totalPages, pageCtx)}</div>` : "";
2847
2820
  let contentHtml = page.sections.map((section) => renderSection(section, scoped, pageCtx)).join("\n");
2848
2821
  contentHtml = contentHtml.replace(/\{pageIndex\}/g, String(pageNum));
2849
2822
  contentHtml = contentHtml.replace(/\{totalPages\}/g, String(totalPages));
2850
2823
  const pageInner = `
2851
2824
  ${renderWatermarkLayerHtml(template.watermark, printData, paperMm, { pageIndex: pageNum, totalPages })}
2852
2825
  <div class="page-header">${headerHtml}</div>
2853
- ${overlayHtml}
2854
2826
  <div class="content-area">
2855
2827
  ${contentHtml}
2856
2828
  </div>
@@ -2874,16 +2846,14 @@ function withPageNumbers(template, vars) {
2874
2846
  ...template,
2875
2847
  elements: template.elements.map(mapEl),
2876
2848
  header: mapArea(template.header),
2877
- footer: mapArea(template.footer),
2878
- firstPageOverlay: mapArea(template.firstPageOverlay)
2849
+ footer: mapArea(template.footer)
2879
2850
  };
2880
2851
  }
2881
2852
  function templateReferencesPageNumbers(template) {
2882
2853
  const areas = [
2883
2854
  template.elements,
2884
2855
  template.header?.elements,
2885
- template.footer?.elements,
2886
- template.firstPageOverlay?.elements
2856
+ template.footer?.elements
2887
2857
  ];
2888
2858
  return areas.some((list) => (list ?? []).some((el) => typeof el.options?.rawFormatter === "string"));
2889
2859
  }
@@ -2983,13 +2953,13 @@ function renderElement(el, isMeasure, containerStyle, overrideTop, ctx) {
2983
2953
  </div>`;
2984
2954
  }
2985
2955
  case "hline":
2986
- return `<div class="print-element" style="${style};border-top:1px solid #000;height:0;"${measureAttr}></div>`;
2956
+ return `<div class="print-element" style="${style};border-top:${opts.borderWidth || 0.75}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};height:0;"${measureAttr}></div>`;
2987
2957
  case "vline":
2988
- return `<div class="print-element" style="${style};border-left:1px solid #000;width:0;"${measureAttr}></div>`;
2958
+ return `<div class="print-element" style="${style};border-left:${opts.borderWidth || 0.75}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};width:0;"${measureAttr}></div>`;
2989
2959
  case "rect":
2990
- return `<div class="print-element" style="${style};border:${opts.borderWidth ?? 1}px solid ${opts.borderColor ?? "#000"};"${measureAttr}></div>`;
2960
+ return `<div class="print-element" style="${style};border:${opts.borderWidth || 1}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};"${measureAttr}></div>`;
2991
2961
  case "oval":
2992
- return `<div class="print-element" style="${style};border:${opts.borderWidth ?? 1}px solid ${opts.borderColor ?? "#000"};border-radius:50%;"${measureAttr}></div>`;
2962
+ return `<div class="print-element" style="${style};border:${opts.borderWidth || 1}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};border-radius:50%;"${measureAttr}></div>`;
2993
2963
  case "longText":
2994
2964
  return `<div class="print-element" style="${style}${textStyle(opts)}${elementFitStyle(fit, opts)}"${measureAttr}${fitAttr}>${esc(opts.formatter ?? opts.testData ?? "")}</div>`;
2995
2965
  case "html":
@@ -3375,7 +3345,6 @@ function applyTextFitSizes(template, fits) {
3375
3345
  collect(template.elements);
3376
3346
  collect(template.header?.elements);
3377
3347
  collect(template.footer?.elements);
3378
- collect(template.firstPageOverlay?.elements);
3379
3348
  for (const fit of fits) {
3380
3349
  const parsed = parseCellFitKey(fit.key);
3381
3350
  if (!parsed) {
@@ -1,5 +1,11 @@
1
- import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-CNJVZK_L.cjs';
2
- import { P as PrintRuntime, F as FitFontSize } from '../ports-DeEgE2SL.cjs';
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
7
+ import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-CFm0C_yX.cjs';
8
+ import { P as PrintRuntime, F as FitFontSize } from '../ports-BXYcHExa.cjs';
3
9
 
4
10
  interface BrowserRenderResult {
5
11
  /** 最终多页 HTML 字符串 */
@@ -46,7 +52,7 @@ declare function renderHtmlPages(template: TemplateData | MultiPageTemplateData,
46
52
  /** 浏览器条码/二维码渲染器;码值非法或为空时抛错,由渲染管线降级文本占位 */
47
53
  declare const browserCodeRenderer: CodeRenderer;
48
54
 
49
- /** 浏览器端 runtime:iframe driver + 进程内执行器;不提供 PDF/截图 */
55
+ /** 浏览器端 runtime:iframe driver + 进程内执行器;不提供 PDF */
50
56
  declare function createBrowserPrintRuntime(): PrintRuntime;
51
57
 
52
58
  /** 浏览器 iframe driver:进程内直调执行器,无需注入脚本;不提供出图能力 */
@@ -1,5 +1,11 @@
1
- import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-CNJVZK_L.js';
2
- import { P as PrintRuntime, F as FitFontSize } from '../ports-DSfECjvT.js';
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
7
+ import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-CFm0C_yX.js';
8
+ import { P as PrintRuntime, F as FitFontSize } from '../ports-Bdst9MWJ.js';
3
9
 
4
10
  interface BrowserRenderResult {
5
11
  /** 最终多页 HTML 字符串 */
@@ -46,7 +52,7 @@ declare function renderHtmlPages(template: TemplateData | MultiPageTemplateData,
46
52
  /** 浏览器条码/二维码渲染器;码值非法或为空时抛错,由渲染管线降级文本占位 */
47
53
  declare const browserCodeRenderer: CodeRenderer;
48
54
 
49
- /** 浏览器端 runtime:iframe driver + 进程内执行器;不提供 PDF/截图 */
55
+ /** 浏览器端 runtime:iframe driver + 进程内执行器;不提供 PDF */
50
56
  declare function createBrowserPrintRuntime(): PrintRuntime;
51
57
 
52
58
  /** 浏览器 iframe driver:进程内直调执行器,无需注入脚本;不提供出图能力 */
@@ -1,3 +1,9 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  import {
2
8
  BARCODE_BAR_HEIGHT_MODULES,
3
9
  BARCODE_MARGIN_BOTTOM_MODULES,
@@ -11,7 +17,7 @@ import {
11
17
  prepareDocument,
12
18
  resolveBarcodeSize,
13
19
  resolveShrinkMinFontSize
14
- } from "../chunk-DCQGN54P.js";
20
+ } from "../chunk-ZCA33XA6.js";
15
21
 
16
22
  // src/browser/browser-code-renderer.ts
17
23
  import JsBarcode from "jsbarcode";
@@ -1,9 +1,15 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  import {
2
8
  compileTemplate,
3
9
  evaluate,
4
10
  parse,
5
11
  tokenize
6
- } from "./chunk-DCQGN54P.js";
12
+ } from "./chunk-ZCA33XA6.js";
7
13
 
8
14
  // src/index.ts
9
15
  var TemplateEngine = class {
@@ -1,3 +1,10 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
7
+
1
8
  // src/lexer.ts
2
9
  var DANGEROUS_PROPS = /* @__PURE__ */ new Set([
3
10
  "constructor",
@@ -925,9 +932,6 @@ function bindData(template, printData, baseUrl, fontBaseUrl) {
925
932
  if (bound.footer?.elements) {
926
933
  bound.footer.elements = bound.footer.elements.map((el) => bindElement(el, data, baseUrl));
927
934
  }
928
- if (bound.firstPageOverlay?.elements) {
929
- bound.firstPageOverlay.elements = bound.firstPageOverlay.elements.map((el) => bindElement(el, data, baseUrl));
930
- }
931
935
  bound.elements = bound.elements.map((el) => bindElement(el, data, baseUrl));
932
936
  const fontBase = fontBaseUrl ?? baseUrl;
933
937
  if (fontBase && bound.fonts?.length) {
@@ -1368,7 +1372,6 @@ function areaGeometryBlock(template, paper, desc) {
1368
1372
  const { bottom: mb } = template.margins;
1369
1373
  const headerH = template.header?.height ?? 0;
1370
1374
  const footerH = template.footer?.height ?? 0;
1371
- const overlayH = template.firstPageOverlay?.height ?? 0;
1372
1375
  const contentWidth = paper.width - ml - mr;
1373
1376
  return `
1374
1377
  /* \u2500\u2500 \u9875\u7709 \u2500\u2500 */
@@ -1380,13 +1383,14 @@ ${desc}.page-header {
1380
1383
 
1381
1384
  /* \u2500\u2500 \u9875\u811A\uFF1A\u7EDD\u5BF9\u5B9A\u4F4D\u56FA\u5B9A\u5728\u9875\u9762\u5E95\u90E8\uFF08\u5185\u5BB9\u4E0D\u8DB3\u65F6\u4E0D\u968F\u6587\u6863\u6D41\u4E0A\u6D6E\uFF09 \u2500\u2500
1382
1385
  \u7528\u663E\u5F0F top \u5B9A\u4F4D\u5230\u300C\u7EB8\u9AD8 - \u4E0B\u8FB9\u8DDD - \u9875\u811A\u9AD8\u300D\uFF0C\u4FDD\u8BC1\u4E0B\u8FB9\u8DDD\u751F\u6548\u3001
1383
- \u4E0E\u8BBE\u8BA1\u5668 CanvasPaper \u7684\u4E09\u533A\u51E0\u4F55\u4E00\u81F4\u3002 */
1386
+ \u4E0E\u8BBE\u8BA1\u5668 CanvasPaper \u7684\u4E09\u533A\u51E0\u4F55\u4E00\u81F4\u3002
1387
+ \u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5305\u542B\u5757\u662F padding box \u5916\u7F18\uFF08= \u7EB8\u9762\uFF09\uFF0Cleft \u987B\u663E\u5F0F\u8865\u5DE6\u8FB9\u8DDD\u3002 */
1384
1388
  ${desc}.page-footer {
1385
1389
  width: ${mm(contentWidth)};
1386
1390
  height: ${mm(footerH)};
1387
1391
  position: absolute;
1388
1392
  top: ${mm(paper.height - mb - footerH)};
1389
- left: 0;
1393
+ left: ${mm(ml)};
1390
1394
  }
1391
1395
 
1392
1396
  /* \u2500\u2500 \u5185\u5BB9\u533A \u2500\u2500 */
@@ -1395,13 +1399,6 @@ ${desc}.content-area {
1395
1399
  position: relative;
1396
1400
  overflow: visible;
1397
1401
  }
1398
-
1399
- /* \u2500\u2500 \u9996\u9875\u53E0\u52A0\u533A\u57DF \u2500\u2500 */
1400
- ${desc}.first-page-overlay {
1401
- width: ${mm(contentWidth)};
1402
- height: ${mm(overlayH)};
1403
- position: relative;
1404
- }
1405
1402
  `;
1406
1403
  }
1407
1404
  function buildBasePageCss() {
@@ -1599,7 +1596,7 @@ var VALID_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double
1599
1596
  function parseBorder(width, style, color) {
1600
1597
  if (typeof width !== "number" || !Number.isFinite(width) || width <= 0) return null;
1601
1598
  return {
1602
- borderWidth: `${width}px`,
1599
+ borderWidth: `${width}pt`,
1603
1600
  borderStyle: typeof style === "string" && VALID_STYLES.has(style) ? style : "solid",
1604
1601
  borderColor: color || "#000"
1605
1602
  };
@@ -1885,7 +1882,6 @@ function paginate(template, measuredElements) {
1885
1882
  const { top: mt, bottom: mb } = template.margins;
1886
1883
  const headerH = template.header?.height ?? 0;
1887
1884
  const footerH = template.footer?.height ?? 0;
1888
- const overlayH = template.firstPageOverlay?.height ?? 0;
1889
1885
  const continuous = isContinuousPaper(template);
1890
1886
  const contentHeight = continuous ? Number.POSITIVE_INFINITY : paper.height - mt - mb - headerH - footerH;
1891
1887
  if (!continuous && contentHeight <= 0) {
@@ -1925,8 +1921,7 @@ function paginate(template, measuredElements) {
1925
1921
  const unitOf = buildPaginationUnits(sorted, measuredElements, groupMap);
1926
1922
  const pages = [];
1927
1923
  let currentPage = [];
1928
- let remaining = contentHeight - overlayH - SAFETY_MARGIN;
1929
- let isFirstPage = true;
1924
+ let remaining = contentHeight - SAFETY_MARGIN;
1930
1925
  let pageBroken = false;
1931
1926
  function sectionTop(el) {
1932
1927
  return pageBroken ? pageCursorTop() : el.options?.top ?? 0;
@@ -1935,7 +1930,7 @@ function paginate(template, measuredElements) {
1935
1930
  return Math.max(0, fullPageHeight() - remaining);
1936
1931
  }
1937
1932
  function fullPageHeight() {
1938
- return isFirstPage ? contentHeight - overlayH - SAFETY_MARGIN : contentHeight - SAFETY_MARGIN;
1933
+ return contentHeight - SAFETY_MARGIN;
1939
1934
  }
1940
1935
  let overflowOnCurrent = false;
1941
1936
  function pushPage() {
@@ -1954,7 +1949,6 @@ function paginate(template, measuredElements) {
1954
1949
  pushPage();
1955
1950
  currentPage = [];
1956
1951
  remaining = contentHeight - SAFETY_MARGIN;
1957
- isFirstPage = false;
1958
1952
  pageBroken = true;
1959
1953
  overflowOnCurrent = false;
1960
1954
  }
@@ -2311,7 +2305,6 @@ function generateMeasurementHtml(template, css, ctx, printData) {
2311
2305
  // totalPages placeholder
2312
2306
  ctx
2313
2307
  );
2314
- const overlayHtml = renderAreaElements(template.firstPageOverlay?.elements ?? [], contentWidth, void 0, void 0, ctx);
2315
2308
  let html = `<!DOCTYPE html>
2316
2309
  <html lang="zh-CN">
2317
2310
  <head>
@@ -2322,7 +2315,6 @@ function generateMeasurementHtml(template, css, ctx, printData) {
2322
2315
  <section class="print-page" data-measure-page="0">
2323
2316
  ${renderWatermarkLayerHtml(template.watermark, printData, getPaperDims(template))}
2324
2317
  <div class="page-header">${headerHtml}</div>
2325
- <div class="first-page-overlay">${overlayHtml}</div>
2326
2318
  <div class="content-area" style="height:auto;overflow:visible;">
2327
2319
  ${elementsHtml}
2328
2320
  </div>
@@ -2386,14 +2378,12 @@ function renderPage(template, page, pageNum, totalPages, ctx, printData, pageCla
2386
2378
  totalPages,
2387
2379
  pageCtx
2388
2380
  );
2389
- const overlayHtml = page.pageIndex === 0 ? `<div class="first-page-overlay">${renderAreaElements(scoped.firstPageOverlay?.elements ?? [], contentWidth, pageNum, totalPages, pageCtx)}</div>` : "";
2390
2381
  let contentHtml = page.sections.map((section) => renderSection(section, scoped, pageCtx)).join("\n");
2391
2382
  contentHtml = contentHtml.replace(/\{pageIndex\}/g, String(pageNum));
2392
2383
  contentHtml = contentHtml.replace(/\{totalPages\}/g, String(totalPages));
2393
2384
  const pageInner = `
2394
2385
  ${renderWatermarkLayerHtml(template.watermark, printData, paperMm, { pageIndex: pageNum, totalPages })}
2395
2386
  <div class="page-header">${headerHtml}</div>
2396
- ${overlayHtml}
2397
2387
  <div class="content-area">
2398
2388
  ${contentHtml}
2399
2389
  </div>
@@ -2417,16 +2407,14 @@ function withPageNumbers(template, vars) {
2417
2407
  ...template,
2418
2408
  elements: template.elements.map(mapEl),
2419
2409
  header: mapArea(template.header),
2420
- footer: mapArea(template.footer),
2421
- firstPageOverlay: mapArea(template.firstPageOverlay)
2410
+ footer: mapArea(template.footer)
2422
2411
  };
2423
2412
  }
2424
2413
  function templateReferencesPageNumbers(template) {
2425
2414
  const areas = [
2426
2415
  template.elements,
2427
2416
  template.header?.elements,
2428
- template.footer?.elements,
2429
- template.firstPageOverlay?.elements
2417
+ template.footer?.elements
2430
2418
  ];
2431
2419
  return areas.some((list) => (list ?? []).some((el) => typeof el.options?.rawFormatter === "string"));
2432
2420
  }
@@ -2526,13 +2514,13 @@ function renderElement(el, isMeasure, containerStyle, overrideTop, ctx) {
2526
2514
  </div>`;
2527
2515
  }
2528
2516
  case "hline":
2529
- return `<div class="print-element" style="${style};border-top:1px solid #000;height:0;"${measureAttr}></div>`;
2517
+ return `<div class="print-element" style="${style};border-top:${opts.borderWidth || 0.75}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};height:0;"${measureAttr}></div>`;
2530
2518
  case "vline":
2531
- return `<div class="print-element" style="${style};border-left:1px solid #000;width:0;"${measureAttr}></div>`;
2519
+ return `<div class="print-element" style="${style};border-left:${opts.borderWidth || 0.75}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};width:0;"${measureAttr}></div>`;
2532
2520
  case "rect":
2533
- return `<div class="print-element" style="${style};border:${opts.borderWidth ?? 1}px solid ${opts.borderColor ?? "#000"};"${measureAttr}></div>`;
2521
+ return `<div class="print-element" style="${style};border:${opts.borderWidth || 1}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};"${measureAttr}></div>`;
2534
2522
  case "oval":
2535
- return `<div class="print-element" style="${style};border:${opts.borderWidth ?? 1}px solid ${opts.borderColor ?? "#000"};border-radius:50%;"${measureAttr}></div>`;
2523
+ return `<div class="print-element" style="${style};border:${opts.borderWidth || 1}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};border-radius:50%;"${measureAttr}></div>`;
2536
2524
  case "longText":
2537
2525
  return `<div class="print-element" style="${style}${textStyle(opts)}${elementFitStyle(fit, opts)}"${measureAttr}${fitAttr}>${esc(opts.formatter ?? opts.testData ?? "")}</div>`;
2538
2526
  case "html":
@@ -2915,9 +2903,6 @@ function toPlaywrightPdfOptions(spec) {
2915
2903
  preferCSSPageSize: spec.preferCSSPageSize
2916
2904
  };
2917
2905
  }
2918
- function buildScreenshotTargetSpec() {
2919
- return { type: "png", fullPage: true, omitBackground: false };
2920
- }
2921
2906
 
2922
2907
  // src/print/measure.ts
2923
2908
  function normalizeMeasurements(raw, template) {
@@ -2952,7 +2937,6 @@ function applyTextFitSizes(template, fits) {
2952
2937
  collect(template.elements);
2953
2938
  collect(template.header?.elements);
2954
2939
  collect(template.footer?.elements);
2955
- collect(template.firstPageOverlay?.elements);
2956
2940
  for (const fit of fits) {
2957
2941
  const parsed = parseCellFitKey(fit.key);
2958
2942
  if (!parsed) {
@@ -3124,23 +3108,6 @@ function createDomHostRuntime(factory, bundle) {
3124
3108
  "RENDER_TIMEOUT",
3125
3109
  `PDF \u751F\u6210\u8D85\u8FC7 ${ms}ms`
3126
3110
  );
3127
- },
3128
- async toScreenshot(html, spec, viewport) {
3129
- if (!driver.screenshot) throw new PrintFailure("UNSUPPORTED_RUNTIME", "\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u622A\u56FE");
3130
- const ms = budget();
3131
- return withTimeout(
3132
- (async () => {
3133
- try {
3134
- await load(html, viewport);
3135
- return await driver.screenshot(html, spec);
3136
- } catch (err) {
3137
- throw fail(err, "SCREENSHOT_FAILED", "\u622A\u56FE\u5931\u8D25");
3138
- }
3139
- })(),
3140
- ms,
3141
- "RENDER_TIMEOUT",
3142
- `\u622A\u56FE\u8D85\u8FC7 ${ms}ms`
3143
- );
3144
3111
  }
3145
3112
  };
3146
3113
  try {
@@ -3475,33 +3442,6 @@ async function renderPdf(job, runtime) {
3475
3442
  return { pdf, prepared };
3476
3443
  });
3477
3444
  }
3478
- async function renderScreenshot(job, runtime) {
3479
- return runtime.withSession(job, async (session) => {
3480
- const pageTemplates = normalizeTemplate(job.templateJson);
3481
- if (pageTemplates.length > 1) {
3482
- const normalized2 = normalizePrintData(job.printData);
3483
- const data2 = normalized2.mode === "batch" ? normalized2.dataList[0] : normalized2.data;
3484
- const copy = await prepareMultiCopy(job, session, data2);
3485
- const doc = composeMultiPageDocument([copy]);
3486
- const viewport2 = paperViewportPx(getPaperDimensions(pageTemplates[0]));
3487
- return session.toScreenshot(doc.html, buildScreenshotTargetSpec(), viewport2);
3488
- }
3489
- const singleJob = pageTemplates[0] !== job.templateJson ? { ...job, templateJson: pageTemplates[0] } : job;
3490
- const normalized = normalizePrintData(singleJob.printData);
3491
- const data = normalized.mode === "batch" ? normalized.dataList[0] : normalized.data;
3492
- const bound = bindData(singleJob.templateJson, data, singleJob.baseUrl, singleJob.fontBaseUrl);
3493
- const built = await buildHtmlWithCodes({
3494
- bound,
3495
- job: singleJob,
3496
- session,
3497
- data,
3498
- pageLayouts: [],
3499
- isMeasurementPass: true
3500
- });
3501
- const viewport = paperViewportPx(getPaperDimensions(bound));
3502
- return session.toScreenshot(built.html, buildScreenshotTargetSpec(), viewport);
3503
- });
3504
- }
3505
3445
  async function prepareWithSession(job, session) {
3506
3446
  const pageTemplates = normalizeTemplate(job.templateJson);
3507
3447
  if (pageTemplates.length > 1) {
@@ -3836,7 +3776,6 @@ export {
3836
3776
  buildPdfTargetSpec,
3837
3777
  toElectronPrintToPdfOptions,
3838
3778
  toPlaywrightPdfOptions,
3839
- buildScreenshotTargetSpec,
3840
3779
  normalizeMeasurements,
3841
3780
  applyTextFitSizes,
3842
3781
  codeSpecKey,
@@ -3865,6 +3804,5 @@ export {
3865
3804
  mergeFontDeclarations,
3866
3805
  composeMultiPageDocument,
3867
3806
  prepareDocument,
3868
- renderPdf,
3869
- renderScreenshot
3807
+ renderPdf
3870
3808
  };
@@ -1,3 +1,9 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  "use strict";
2
8
  var __defProp = Object.defineProperty;
3
9
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1,3 +1,9 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  declare const APP_ID = "worm-print-client";
2
8
  declare const DEFAULT_PORT = 17521;
3
9
  declare const PORT_SCAN_LIMIT = 20;
@@ -1,3 +1,9 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
1
7
  declare const APP_ID = "worm-print-client";
2
8
  declare const DEFAULT_PORT = 17521;
3
9
  declare const PORT_SCAN_LIMIT = 20;
@@ -1,3 +1,10 @@
1
+ /*!
2
+ * @worm-vue3-print/core v1.3.5
3
+ * Copyright (c) 2026 Worm Base AI
4
+ * SPDX-FileCopyrightText: 2026 Worm Base AI
5
+ * SPDX-License-Identifier: MIT
6
+ */
7
+
1
8
  // src/client/protocol.ts
2
9
  var APP_ID = "worm-print-client";
3
10
  var DEFAULT_PORT = 17521;