@agile-team/mach-report 0.5.0 → 0.6.0

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.
Files changed (71) hide show
  1. package/dist/ReportPreview-DWLjYi_p.js +527 -0
  2. package/dist/ReportPreview-rBtmbu3W.cjs +6 -0
  3. package/dist/_commonjsHelpers-DKOUU3wS.cjs +1 -0
  4. package/dist/_commonjsHelpers-DaMA6jEr.js +8 -0
  5. package/dist/builder/template-builder.d.ts +53 -0
  6. package/dist/compat/jh4j-template.d.ts +12 -0
  7. package/dist/defaults.d.ts +27 -0
  8. package/dist/index.cjs +6 -1663
  9. package/dist/index.d.cts +13 -344
  10. package/dist/index.d.ts +13 -344
  11. package/dist/index.js +727 -1419
  12. package/dist/layout/paginate.d.ts +51 -0
  13. package/dist/layout/textwrap.d.ts +36 -0
  14. package/dist/manager/api.d.ts +45 -0
  15. package/dist/manager/index.d.ts +2 -0
  16. package/dist/manager/types.d.ts +50 -0
  17. package/dist/manager.cjs +1 -122
  18. package/dist/manager.d.cts +5 -97
  19. package/dist/manager.d.ts +5 -97
  20. package/dist/manager.js +66 -81
  21. package/dist/pdf/font-loader.d.ts +5 -0
  22. package/dist/pdf/index.d.ts +2 -0
  23. package/dist/pdf/render-pdf.d.ts +25 -0
  24. package/dist/pdf.cjs +84 -52530
  25. package/dist/pdf.d.cts +4 -31
  26. package/dist/pdf.d.ts +4 -31
  27. package/dist/pdf.js +22843 -39218
  28. package/dist/plugin-BIJxGHZX.cjs +1 -0
  29. package/dist/plugin-DrV67_VW.js +89 -0
  30. package/dist/render/canvas.d.ts +61 -0
  31. package/dist/render/dom.d.ts +10 -0
  32. package/dist/render/grid-geometry.d.ts +41 -0
  33. package/dist/render/style.d.ts +33 -0
  34. package/dist/render/window.d.ts +23 -0
  35. package/dist/schema/render-plan.d.ts +96 -0
  36. package/dist/schema/validate.d.ts +15 -0
  37. package/dist/sql/ast-check.d.ts +14 -0
  38. package/dist/sql/compile.d.ts +31 -0
  39. package/dist/sql/expr.d.ts +21 -0
  40. package/dist/sql/index.d.ts +4 -0
  41. package/dist/sql/tokenizer.d.ts +25 -0
  42. package/dist/sql.cjs +68 -45207
  43. package/dist/sql.d.cts +3 -93
  44. package/dist/sql.d.ts +3 -93
  45. package/dist/sql.js +37213 -41613
  46. package/dist/style-B3vxGDZd.cjs +3 -0
  47. package/dist/style-B7Xfo5I-.js +255 -0
  48. package/dist/style.css +1 -0
  49. package/dist/units.d.ts +11 -0
  50. package/dist/vue/ReportPreview.d.ts +141 -0
  51. package/dist/vue/ReportToolbar.d.ts +25 -0
  52. package/dist/vue/adapters.d.ts +37 -0
  53. package/dist/vue/async.d.cts +146 -0
  54. package/dist/vue/async.d.ts +146 -0
  55. package/dist/vue/composables/usePageWindow.d.ts +28 -0
  56. package/dist/vue/composables/usePrintExport.d.ts +19 -0
  57. package/dist/vue/composables/useZoom.d.ts +15 -0
  58. package/dist/vue/config.d.ts +79 -0
  59. package/dist/vue/index.d.cts +11 -0
  60. package/dist/vue/index.d.ts +11 -0
  61. package/dist/vue/injection-keys.d.ts +12 -0
  62. package/dist/vue/local-adapter.d.ts +12 -0
  63. package/dist/vue/pdf-exporter.d.ts +13 -0
  64. package/dist/vue/plugin.d.ts +34 -0
  65. package/dist/vue-async.cjs +1 -0
  66. package/dist/vue-async.js +17 -0
  67. package/dist/vue.cjs +1 -0
  68. package/dist/vue.js +44 -0
  69. package/package.json +44 -6
  70. package/dist/textwrap-DWzM7pt1.d.cts +0 -135
  71. package/dist/textwrap-DWzM7pt1.d.ts +0 -135
package/dist/index.js CHANGED
@@ -1,61 +1,6 @@
1
- // src/defaults.ts
2
- var LINE_HEIGHT = 1.35;
3
- var DEFAULT_FONT_PT = 10.5;
4
- var DEFAULT_BORDER_PT = 0.75;
5
- var DEFAULT_STROKE_COLOR = "#333333";
6
- var DEFAULT_TEXT_COLOR = "#000000";
7
- var SCHEMA_VERSION_MACH = "1.0.0-mach";
8
- var SCHEMA_VERSION_LOCAL = "mach-local";
9
- var SCHEMA_VERSION_JH4J = "jh4j-compatible";
10
-
11
- // src/units.ts
12
- var MM_PER_INCH = 25.4;
13
- var CSS_DPI = 96;
14
- function mmToPxFactor(dpi = CSS_DPI) {
15
- return dpi / MM_PER_INCH;
16
- }
17
- function mmToPx(value, dpi = CSS_DPI) {
18
- return (value || 0) * mmToPxFactor(dpi);
19
- }
20
- function pxToMm(value, dpi = CSS_DPI) {
21
- return value / mmToPxFactor(dpi);
22
- }
23
- function ptToPx(pt, dpi = CSS_DPI) {
24
- return pt * dpi / 72;
25
- }
26
- function round(value, digits) {
27
- const f = 10 ** digits;
28
- return Math.round(value * f) / f;
29
- }
30
- var PAPER_SIZES = {
31
- a3: { widthMm: 297, heightMm: 420 },
32
- a4: { widthMm: 210, heightMm: 297 },
33
- a5: { widthMm: 148, heightMm: 210 },
34
- b4: { widthMm: 250, heightMm: 353 },
35
- b5: { widthMm: 176, heightMm: 250 }
36
- };
37
-
38
- // src/schema/render-plan.ts
39
- var RENDER_PLAN_SCHEMA_VERSION = SCHEMA_VERSION_MACH;
40
- function toRenderPlan(response) {
41
- if (response && response.code != null && response.code !== 200) {
42
- throw new Error(String(response.message || "\u6E32\u67D3\u8BA1\u5212\u52A0\u8F7D\u5931\u8D25"));
43
- }
44
- const pages = response?.data?.pages;
45
- return {
46
- schemaVersion: RENDER_PLAN_SCHEMA_VERSION,
47
- pages: Array.isArray(pages) ? pages : []
48
- };
49
- }
50
- function isImageBackedComponent(comp) {
51
- return (comp.kind === "image" || comp.kind === "barcode" || comp.kind === "qrcode" || comp.kind === "chart") && !!comp.imageData;
52
- }
53
- function isRichText(comp) {
54
- return comp.kind === "text" && Array.isArray(comp.richParagraphs) && comp.richParagraphs.length > 0;
55
- }
56
-
57
- // src/schema/validate.ts
58
- var KNOWN_KINDS = /* @__PURE__ */ new Set([
1
+ import { h as V, R as at, D as j, w as O, L as J, i as st, r as F, m as lt, a as _, b as X, c as z, d as G, p as D, e as dt, f as Z, g as ht, j as ct, P as U } from "./style-B7Xfo5I-.js";
2
+ import { C as qt, k as Ut, l as Kt, M as Yt, S as Xt, n as Zt, o as Qt, q as te, s as ee, t as ne, u as ie, v as re, x as oe, y as ae } from "./style-B7Xfo5I-.js";
3
+ const mt = /* @__PURE__ */ new Set([
59
4
  "text",
60
5
  "image",
61
6
  "barcode",
@@ -65,569 +10,223 @@ var KNOWN_KINDS = /* @__PURE__ */ new Set([
65
10
  "rect",
66
11
  "ellipse"
67
12
  ]);
68
- function isObj(v) {
69
- return typeof v === "object" && v !== null && !Array.isArray(v);
13
+ function L(t) {
14
+ return typeof t == "object" && t !== null && !Array.isArray(t);
70
15
  }
71
- function checkNumber(obj, key, path, errors) {
72
- const v = obj[key];
73
- if (v === void 0 || v === null) return;
74
- if (typeof v !== "number" || !Number.isFinite(v)) {
75
- errors.push({ path: `${path}.${key}`, message: `\u5E94\u4E3A\u6709\u9650\u6570\u5B57\uFF0C\u5B9E\u9645 ${JSON.stringify(v)}` });
76
- }
16
+ function gt(t, n, i, e) {
17
+ const r = t[n];
18
+ r != null && (typeof r != "number" || !Number.isFinite(r)) && e.push({ path: `${i}.${n}`, message: `应为有限数字,实际 ${JSON.stringify(r)}` });
77
19
  }
78
- function validateComponent(comp, path, errors, warnings = []) {
79
- if (!isObj(comp)) {
80
- errors.push({ path, message: "\u7EC4\u4EF6\u5E94\u4E3A\u5BF9\u8C61" });
20
+ function Q(t, n, i, e = []) {
21
+ if (!L(t)) {
22
+ i.push({ path: n, message: "组件应为对象" });
81
23
  return;
82
24
  }
83
- const kind = comp["kind"];
84
- if (typeof kind !== "string") {
85
- errors.push({ path: `${path}.kind`, message: `\u7EC4\u4EF6\u7F3A\u5C11 kind \u5B57\u7B26\u4E32` });
86
- } else if (!KNOWN_KINDS.has(kind)) {
87
- warnings.push({
88
- path: `${path}.kind`,
89
- message: `\u672A\u77E5\u7EC4\u4EF6\u7C7B\u578B ${JSON.stringify(kind)}\uFF0C\u5C06\u4EE5\u515C\u5E95\u65B9\u5F0F\u6E32\u67D3`
90
- });
91
- }
92
- for (const key of ["leftMm", "topMm", "widthMm", "heightMm"]) {
93
- checkNumber(comp, key, path, errors);
94
- }
95
- if (comp["leftMm"] != null && comp["widthMm"] != null) {
96
- if (comp["leftMm"] < -100 || comp["widthMm"] < 0) {
97
- errors.push({ path, message: "\u51E0\u4F55\u6570\u503C\u5F02\u5E38\uFF08leftMm<-100 \u6216 widthMm<0\uFF09" });
98
- }
99
- }
100
- const grid = comp["grid"];
101
- if (grid !== void 0) {
102
- if (!isObj(grid) || !Array.isArray(grid["cells"])) {
103
- errors.push({ path: `${path}.grid.cells`, message: "grid.cells \u5E94\u4E3A\u4E8C\u7EF4\u6570\u7EC4" });
104
- } else {
105
- grid["cells"].forEach((row, ri) => {
106
- if (!Array.isArray(row)) {
107
- errors.push({ path: `${path}.grid.cells.${ri}`, message: "\u884C\u5E94\u4E3A\u6570\u7EC4" });
108
- return;
109
- }
110
- row.forEach((cell, ci) => {
111
- if (cell === void 0 || cell === null) return;
112
- if (isObj(cell) && Array.isArray(cell["children"])) {
113
- cell["children"].forEach((child, ki) => {
114
- validateComponent(child, `${path}.grid.cells.${ri}.${ci}.children.${ki}`, errors, warnings);
115
- });
116
- }
117
- });
118
- });
119
- }
120
- }
121
- const rich = comp["richParagraphs"];
122
- if (rich !== void 0) {
123
- if (!Array.isArray(rich)) {
124
- errors.push({ path: `${path}.richParagraphs`, message: "richParagraphs \u5E94\u4E3A\u6570\u7EC4" });
125
- } else {
126
- rich.forEach((para, i) => {
127
- if (!isObj(para) || !Array.isArray(para["segments"])) {
128
- errors.push({ path: `${path}.richParagraphs.${i}`, message: "\u6BB5\u843D\u7F3A\u5C11 segments \u6570\u7EC4" });
129
- }
25
+ const r = t.kind;
26
+ typeof r != "string" ? i.push({ path: `${n}.kind`, message: "组件缺少 kind 字符串" }) : mt.has(r) || e.push({
27
+ path: `${n}.kind`,
28
+ message: `未知组件类型 ${JSON.stringify(r)},将以兜底方式渲染`
29
+ });
30
+ for (const o of ["leftMm", "topMm", "widthMm", "heightMm"])
31
+ gt(t, o, n, i);
32
+ t.leftMm != null && t.widthMm != null && (t.leftMm < -100 || t.widthMm < 0) && i.push({ path: n, message: "几何数值异常(leftMm<-100 或 widthMm<0)" });
33
+ const l = t.grid;
34
+ l !== void 0 && (!L(l) || !Array.isArray(l.cells) ? i.push({ path: `${n}.grid.cells`, message: "grid.cells 应为二维数组" }) : l.cells.forEach((o, s) => {
35
+ if (!Array.isArray(o)) {
36
+ i.push({ path: `${n}.grid.cells.${s}`, message: "行应为数组" });
37
+ return;
38
+ }
39
+ o.forEach((d, h) => {
40
+ d != null && L(d) && Array.isArray(d.children) && d.children.forEach((c, m) => {
41
+ Q(c, `${n}.grid.cells.${s}.${h}.children.${m}`, i, e);
130
42
  });
131
- }
132
- }
133
- }
134
- function validatePage(page, path, errors, warnings = []) {
135
- if (!isObj(page)) {
136
- errors.push({ path, message: "\u9875\u5E94\u4E3A\u5BF9\u8C61" });
137
- return;
138
- }
139
- const w = page["pageWidthMm"];
140
- const h = page["pageHeightMm"];
141
- if (typeof w !== "number" || !(w > 0 && w < 3e3)) {
142
- errors.push({ path: `${path}.pageWidthMm`, message: `\u9875\u5BBD\u975E\u6CD5: ${JSON.stringify(w)}` });
143
- }
144
- if (typeof h !== "number" || !(h > 0 && h < 5e3)) {
145
- errors.push({ path: `${path}.pageHeightMm`, message: `\u9875\u9AD8\u975E\u6CD5: ${JSON.stringify(h)}` });
146
- }
147
- const comps = page["components"];
148
- if (comps !== void 0 && !Array.isArray(comps)) {
149
- errors.push({ path: `${path}.components`, message: "components \u5E94\u4E3A\u6570\u7EC4" });
150
- } else if (Array.isArray(comps)) {
151
- comps.forEach(
152
- (comp, i) => validateComponent(comp, `${path}.components.${i}`, errors, warnings)
153
- );
154
- }
155
- }
156
- function validateRenderPlan(input) {
157
- const errors = [];
158
- const warnings = [];
159
- const pages = isObj(input) ? input["pages"] : void 0;
160
- if (!Array.isArray(pages)) {
161
- errors.push({
162
- path: "$.pages",
163
- message: input == null ? "\u6E32\u67D3\u8BA1\u5212\u4E3A\u7A7A" : "\u6E32\u67D3\u8BA1\u5212\u7F3A\u5C11 pages \u6570\u7EC4"
164
43
  });
165
- } else {
166
- pages.forEach((page, i) => validatePage(page, `$.pages.${i}`, errors, warnings));
167
- }
168
- return { ok: errors.length === 0, errors, warnings };
169
- }
170
- function assertRenderPlan(input) {
171
- const result = validateRenderPlan(input);
172
- if (!result.ok) {
173
- const head = result.errors.slice(0, 3).map((e) => `${e.path}: ${e.message}`).join("; ");
174
- throw new Error(`\u6E32\u67D3\u8BA1\u5212\u6821\u9A8C\u5931\u8D25(${result.errors.length} \u5904): ${head}`);
44
+ }));
45
+ const a = t.richParagraphs;
46
+ a !== void 0 && (Array.isArray(a) ? a.forEach((o, s) => {
47
+ (!L(o) || !Array.isArray(o.segments)) && i.push({ path: `${n}.richParagraphs.${s}`, message: "段落缺少 segments 数组" });
48
+ }) : i.push({ path: `${n}.richParagraphs`, message: "richParagraphs 应为数组" }));
49
+ }
50
+ function ft(t, n, i, e = []) {
51
+ if (!L(t)) {
52
+ i.push({ path: n, message: "页应为对象" });
53
+ return;
175
54
  }
176
- return input.pages;
177
- }
178
-
179
- // src/layout/textwrap.ts
180
- var CJK_RE = /[\u3000-\u9fff\uff00-\uffef]/;
181
- var LATIN_CLASS = new Uint8Array(128);
182
- {
183
- for (const ch of "iljtf.,:;'`|!()[]") LATIN_CLASS[ch.charCodeAt(0)] = 1;
184
- for (const ch of "mwMW@") LATIN_CLASS[ch.charCodeAt(0)] = 2;
185
- for (let c = 48; c <= 57; c++) LATIN_CLASS[c] = 3;
186
- for (let c = 65; c <= 90; c++) LATIN_CLASS[c] = 4;
187
- LATIN_CLASS[32] = 5;
55
+ const r = t.pageWidthMm, l = t.pageHeightMm;
56
+ (typeof r != "number" || !(r > 0 && r < 3e3)) && i.push({ path: `${n}.pageWidthMm`, message: `页宽非法: ${JSON.stringify(r)}` }), (typeof l != "number" || !(l > 0 && l < 5e3)) && i.push({ path: `${n}.pageHeightMm`, message: `页高非法: ${JSON.stringify(l)}` });
57
+ const a = t.components;
58
+ a !== void 0 && !Array.isArray(a) ? i.push({ path: `${n}.components`, message: "components 应为数组" }) : Array.isArray(a) && a.forEach(
59
+ (o, s) => Q(o, `${n}.components.${s}`, i, e)
60
+ );
188
61
  }
189
- var LATIN_WIDTH = [0.54, 0.26, 0.95, 0.59, 0.67, 0.3];
190
- function charWidthEm(ch) {
191
- const code = ch.charCodeAt(0);
192
- if (code < 128) return LATIN_WIDTH[LATIN_CLASS[code]];
193
- if (CJK_RE.test(ch)) return 1;
194
- if (/[A-Z]/.test(ch)) return 0.67;
195
- return 0.54;
62
+ function ut(t) {
63
+ const n = [], i = [], e = L(t) ? t.pages : void 0;
64
+ return Array.isArray(e) ? e.forEach((r, l) => ft(r, `$.pages.${l}`, n, i)) : n.push({
65
+ path: "$.pages",
66
+ message: t == null ? "渲染计划为空" : "渲染计划缺少 pages 数组"
67
+ }), { ok: n.length === 0, errors: n, warnings: i };
196
68
  }
197
- var heuristicMeasurer = {
198
- measureMm(text, options) {
199
- const { fontSizePt, bold = false, letterSpacingPt = 0 } = options;
200
- const ptToMm = 25.4 / 72;
201
- let units = 0;
202
- for (const ch of text) {
203
- units += charWidthEm(ch);
204
- }
205
- if (bold) units *= 1.04;
206
- return (units * fontSizePt + letterSpacingPt * text.length) * ptToMm;
69
+ function Ft(t) {
70
+ const n = ut(t);
71
+ if (!n.ok) {
72
+ const i = n.errors.slice(0, 3).map((e) => `${e.path}: ${e.message}`).join("; ");
73
+ throw new Error(`渲染计划校验失败(${n.errors.length} 处): ${i}`);
207
74
  }
208
- };
209
- function createHeuristicMeasurer() {
210
- return heuristicMeasurer;
75
+ return t.pages;
211
76
  }
212
- function measureTextMm(text, options) {
213
- return heuristicMeasurer.measureMm(text, options);
214
- }
215
- function createCanvasMeasurer(getCtx2d) {
216
- let ctx;
77
+ function K(t) {
217
78
  return {
218
- measureMm(text, options) {
219
- if (ctx === void 0) ctx = getCtx2d();
220
- if (!ctx) return heuristicMeasurer.measureMm(text, options);
221
- const px = options.fontSizePt * 96 / 72;
222
- ctx.font = `${options.bold ? "bold " : ""}${px}px sans-serif`;
223
- return ctx.measureText(text).width * 25.4 / 96;
224
- }
225
- };
226
- }
227
- function tokenize(text, options, measurer) {
228
- const atoms = [];
229
- let word = "";
230
- let wordWidth = 0;
231
- const flush = () => {
232
- if (word) {
233
- atoms.push({ text: word, widthMm: wordWidth, cjk: false });
234
- word = "";
235
- wordWidth = 0;
236
- }
237
- };
238
- for (const ch of text) {
239
- if (ch === "\n") {
240
- flush();
241
- atoms.push({ text: "\n", widthMm: 0, cjk: false, br: true });
242
- continue;
243
- }
244
- if (ch === " ") {
245
- flush();
246
- atoms.push({ text: ch, widthMm: measurer.measureMm(ch, options), cjk: false, space: true });
247
- continue;
248
- }
249
- if (CJK_RE.test(ch)) {
250
- flush();
251
- atoms.push({ text: ch, widthMm: measurer.measureMm(ch, options), cjk: true });
252
- continue;
253
- }
254
- word += ch;
255
- wordWidth += measurer.measureMm(ch, options);
256
- }
257
- flush();
258
- return atoms;
259
- }
260
- function wrapText(text, maxWidthMm, options, measurer = heuristicMeasurer) {
261
- if (!text) return [""];
262
- const lines = [];
263
- let current = "";
264
- let currentWidth = 0;
265
- const pushLine = () => {
266
- lines.push(current);
267
- current = "";
268
- currentWidth = 0;
269
- };
270
- for (const atom of tokenize(text, options, measurer)) {
271
- if (atom.br) {
272
- pushLine();
273
- continue;
274
- }
275
- if (currentWidth + atom.widthMm <= maxWidthMm) {
276
- current += atom.text;
277
- currentWidth += atom.widthMm;
278
- continue;
279
- }
280
- if (atom.space) {
281
- pushLine();
282
- continue;
283
- }
284
- if (atom.cjk) {
285
- if (current.length > 0) pushLine();
286
- current = atom.text;
287
- currentWidth = atom.widthMm;
288
- continue;
289
- }
290
- if (current.length > 0) pushLine();
291
- if (atom.widthMm <= maxWidthMm) {
292
- current = atom.text;
293
- currentWidth = atom.widthMm;
294
- continue;
295
- }
296
- for (const ch of atom.text) {
297
- const chWidth = measurer.measureMm(ch, options);
298
- if (currentWidth + chWidth > maxWidthMm && current.length > 0) {
299
- pushLine();
300
- }
301
- current += ch;
302
- currentWidth += chWidth;
303
- }
304
- }
305
- pushLine();
306
- return lines;
307
- }
308
-
309
- // src/layout/paginate.ts
310
- function makeWorkingPage(page) {
311
- return {
312
- widthMm: page.widthMm,
313
- heightMm: page.heightMm,
314
- marginTopMm: page.marginTopMm ?? 0,
315
- marginBottomMm: page.marginBottomMm ?? 0,
316
- marginLeftMm: page.marginLeftMm ?? 0,
317
- marginRightMm: page.marginRightMm ?? 0,
79
+ widthMm: t.widthMm,
80
+ heightMm: t.heightMm,
81
+ marginTopMm: t.marginTopMm ?? 0,
82
+ marginBottomMm: t.marginBottomMm ?? 0,
83
+ marginLeftMm: t.marginLeftMm ?? 0,
84
+ marginRightMm: t.marginRightMm ?? 0,
318
85
  components: []
319
86
  };
320
87
  }
321
- function toContentBottom(page, wp) {
322
- return wp.heightMm - (page.marginBottomMm ?? wp.marginBottomMm);
88
+ function pt(t, n) {
89
+ return n.heightMm - (t.marginBottomMm ?? n.marginBottomMm);
323
90
  }
324
- function estRowHeightMm(list, lines) {
325
- const fontSizePt = list.fontSizePt ?? DEFAULT_FONT_PT;
326
- const lineMm = fontSizePt * LINE_HEIGHT * 25.4 / 72;
327
- const padding = (list.paddingMm ?? 1) * 2;
328
- return Math.max(list.rowHeightMm ?? 0, lines * lineMm + padding);
91
+ function Mt(t, n) {
92
+ const e = (t.fontSizePt ?? j) * J * 25.4 / 72, r = (t.paddingMm ?? 1) * 2;
93
+ return Math.max(t.rowHeightMm ?? 0, n * e + r);
329
94
  }
330
- function cellText(value) {
331
- if (value == null) return "";
332
- if (typeof value === "string") return value;
333
- if (typeof value === "number") return String(value);
334
- if (typeof value === "boolean") return value ? "\u662F" : "\u5426";
335
- if (value instanceof Date) return value.toISOString().slice(0, 10);
95
+ function bt(t) {
96
+ if (t == null) return "";
97
+ if (typeof t == "string") return t;
98
+ if (typeof t == "number") return String(t);
99
+ if (typeof t == "boolean") return t ? "是" : "否";
100
+ if (t instanceof Date) return t.toISOString().slice(0, 10);
336
101
  try {
337
- return JSON.stringify(value);
102
+ return JSON.stringify(t);
338
103
  } catch {
339
- return String(value);
104
+ return String(t);
340
105
  }
341
106
  }
342
- function interList(list, measurer) {
343
- const fontSizePt = list.fontSizePt ?? DEFAULT_FONT_PT;
344
- const paddingMm = list.paddingMm ?? 1;
345
- const cellStyles = list.columns.map(
346
- (col) => col.style ? { align: "left", verticalAlign: "middle", ...col.style } : { align: "left", verticalAlign: "middle" }
347
- );
348
- const headerCellStyles = list.columns.map(
349
- (col) => ({
350
- bold: list.headerBold ?? true,
107
+ function yt(t, n) {
108
+ const i = t.fontSizePt ?? j, e = t.paddingMm ?? 1, r = t.columns.map(
109
+ (m) => m.style ? { align: "left", verticalAlign: "middle", ...m.style } : { align: "left", verticalAlign: "middle" }
110
+ ), l = t.columns.map(
111
+ (m) => ({
112
+ bold: t.headerBold ?? !0,
351
113
  align: "center",
352
114
  verticalAlign: "middle",
353
- backgroundColor: list.headerBackgroundColor,
354
- ...col.style || {}
115
+ backgroundColor: t.headerBackgroundColor,
116
+ ...m.style || {}
355
117
  })
356
- );
357
- const headerTexts = list.columns.map((col) => col.header);
358
- const headerLines = headerTexts.map(
359
- (text, i) => wrapText(
360
- text,
361
- list.columns[i].widthMm - paddingMm * 2,
362
- { fontSizePt, bold: list.headerBold ?? true },
363
- measurer
118
+ ), a = t.columns.map((m) => m.header), o = a.map(
119
+ (m, f) => O(
120
+ m,
121
+ t.columns[f].widthMm - e * 2,
122
+ { fontSizePt: i, bold: t.headerBold ?? !0 },
123
+ n
364
124
  )
365
- );
366
- const maxLines = Math.max(...headerLines.map((l) => l.length), 1);
367
- const headerHeight = estRowHeightMm(list, maxLines);
368
- const headerCells = headerTexts.map((text, i) => ({
369
- text,
370
- style: headerCellStyles[i]
371
- }));
372
- const borderStyle = list.border === false ? { borderTop: false, borderRight: false, borderBottom: false, borderLeft: false } : { borderBottom: true, borderLeft: true, borderRight: true, borderTop: true };
125
+ ), s = Math.max(...o.map((m) => m.length), 1), d = Mt(t, s), h = a.map((m, f) => ({
126
+ text: m,
127
+ style: l[f]
128
+ })), c = t.border === !1 ? { borderTop: !1, borderRight: !1, borderBottom: !1, borderLeft: !1 } : { borderBottom: !0, borderLeft: !0, borderRight: !0, borderTop: !0 };
373
129
  return {
374
- fontSizePt,
375
- paddingMm,
376
- cellStyles,
377
- borderStyle,
378
- headerHeightMm: headerHeight,
379
- headerGrid: { cells: [headerCells], rowHeightsMm: [headerHeight] },
380
- columns: list.columns
130
+ fontSizePt: i,
131
+ paddingMm: e,
132
+ cellStyles: r,
133
+ borderStyle: c,
134
+ headerHeightMm: d,
135
+ headerGrid: { cells: [h], rowHeightsMm: [d] },
136
+ columns: t.columns
381
137
  };
382
138
  }
383
- function buildRowGridFast(inter, row, measurer) {
384
- const columns = inter.columns;
385
- const texts = new Array(columns.length);
386
- let maxLines = 1;
387
- for (let i = 0; i < columns.length; i++) {
388
- texts[i] = cellText(row[columns[i].field]);
389
- }
390
- const lines = new Array(columns.length);
391
- for (let i = 0; i < columns.length; i++) {
392
- const wrapped = wrapText(
393
- texts[i],
394
- columns[i].widthMm - inter.paddingMm * 2,
395
- { fontSizePt: inter.fontSizePt },
396
- measurer
139
+ function wt(t, n, i) {
140
+ const e = t.columns, r = new Array(e.length);
141
+ let l = 1;
142
+ for (let h = 0; h < e.length; h++)
143
+ r[h] = bt(n[e[h].field]);
144
+ const a = new Array(e.length);
145
+ for (let h = 0; h < e.length; h++) {
146
+ const c = O(
147
+ r[h],
148
+ e[h].widthMm - t.paddingMm * 2,
149
+ { fontSizePt: t.fontSizePt },
150
+ i
397
151
  );
398
- lines[i] = wrapped;
399
- if (wrapped.length > maxLines) maxLines = wrapped.length;
400
- }
401
- const lineMm = inter.fontSizePt * LINE_HEIGHT * 25.4 / 72;
402
- const height = Math.max(
403
- inter.rowHeightFloorMm,
404
- maxLines * lineMm + inter.paddingMm * 2
405
- );
406
- const cells = new Array(columns.length);
407
- for (let i = 0; i < columns.length; i++) {
408
- cells[i] = { text: texts[i], style: inter.cellStyles[i] };
409
- }
410
- return { grid: { cells: [cells], rowHeightsMm: [height] }, heightMm: height };
411
- }
412
- function paginateTemplate(template, datasets, optionsOrMmPerRow = {}) {
413
- const options = typeof optionsOrMmPerRow === "number" ? { mmPerRow: optionsOrMmPerRow } : optionsOrMmPerRow;
414
- const mmPerRow = options.mmPerRow ?? 0;
415
- const measurer = options.measurer ?? heuristicMeasurer;
416
- const warnings = [];
417
- const pages = [];
418
- let seq = 0;
419
- const nextId = (prefix) => `${prefix}_${(++seq).toString(36)}`;
420
- for (const tplPage of template.pages) {
421
- const current = makeWorkingPage(tplPage);
422
- const contentBottom = () => toContentBottom(tplPage, current);
423
- const contentTop = current.marginTopMm;
424
- const pushCurrent = () => {
425
- pages.push({
426
- pageWidthMm: current.widthMm,
427
- pageHeightMm: current.heightMm,
428
- marginTopMm: current.marginTopMm,
429
- marginBottomMm: current.marginBottomMm,
430
- marginLeftMm: current.marginLeftMm,
431
- marginRightMm: current.marginRightMm,
432
- components: current.components
152
+ a[h] = c, c.length > l && (l = c.length);
153
+ }
154
+ const o = t.fontSizePt * J * 25.4 / 72, s = Math.max(
155
+ t.rowHeightFloorMm,
156
+ l * o + t.paddingMm * 2
157
+ ), d = new Array(e.length);
158
+ for (let h = 0; h < e.length; h++)
159
+ d[h] = { text: r[h], style: t.cellStyles[h] };
160
+ return { grid: { cells: [d], rowHeightsMm: [s] }, heightMm: s };
161
+ }
162
+ function _t(t, n, i = {}) {
163
+ const e = typeof i == "number" ? { mmPerRow: i } : i, r = e.mmPerRow ?? 0, l = e.measurer ?? V, a = [], o = [];
164
+ let s = 0;
165
+ const d = (h) => `${h}_${(++s).toString(36)}`;
166
+ for (const h of t.pages) {
167
+ const c = K(h), m = () => pt(h, c), f = c.marginTopMm, g = () => {
168
+ o.push({
169
+ pageWidthMm: c.widthMm,
170
+ pageHeightMm: c.heightMm,
171
+ marginTopMm: c.marginTopMm,
172
+ marginBottomMm: c.marginBottomMm,
173
+ marginLeftMm: c.marginLeftMm,
174
+ marginRightMm: c.marginRightMm,
175
+ components: c.components
433
176
  });
434
177
  };
435
- for (const comp of tplPage.components) {
436
- if (comp.kind !== "list") {
437
- current.components.push(comp);
178
+ for (const b of h.components) {
179
+ if (b.kind !== "list") {
180
+ c.components.push(b);
438
181
  continue;
439
182
  }
440
- const list = comp;
441
- const rows = datasets[list.dataset];
442
- if (!Array.isArray(rows)) {
443
- warnings.push(`\u6570\u636E\u96C6 ${list.dataset} \u672A\u63D0\u4F9B\u6570\u636E\uFF0C\u5217\u8868 ${list.id ?? ""} \u8F93\u51FA\u4E3A\u7A7A`);
444
- }
445
- const dataRows = Array.isArray(rows) ? rows : [];
446
- const columnsWidth = list.columns.reduce((s, c) => s + c.widthMm, 0);
447
- const scale = columnsWidth > list.widthMm ? list.widthMm / columnsWidth : 1;
448
- const scaledList = scale === 1 ? list : { ...list, columns: list.columns.map((c) => ({ ...c, widthMm: c.widthMm * scale })) };
449
- const inter = {
450
- ...interList(scaledList, measurer),
451
- rowHeightFloorMm: scaledList.rowHeightMm ?? 0
452
- };
453
- const headerComp = {
183
+ const p = b, C = n[p.dataset];
184
+ Array.isArray(C) || a.push(`数据集 ${p.dataset} 未提供数据,列表 ${p.id ?? ""} 输出为空`);
185
+ const v = Array.isArray(C) ? C : [], E = p.columns.reduce((y, S) => y + S.widthMm, 0), w = E > p.widthMm ? p.widthMm / E : 1, W = w === 1 ? p : { ...p, columns: p.columns.map((y) => ({ ...y, widthMm: y.widthMm * w })) }, R = {
186
+ ...yt(W, l),
187
+ rowHeightFloorMm: W.rowHeightMm ?? 0
188
+ }, I = {
454
189
  kind: "rect",
455
- leftMm: list.leftMm,
190
+ leftMm: p.leftMm,
456
191
  topMm: 0,
457
- widthMm: list.widthMm,
458
- heightMm: inter.headerHeightMm,
459
- grid: inter.headerGrid,
460
- nid: nextId("listh"),
461
- style: inter.borderStyle
192
+ widthMm: p.widthMm,
193
+ heightMm: R.headerHeightMm,
194
+ grid: R.headerGrid,
195
+ nid: d("listh"),
196
+ style: R.borderStyle
462
197
  };
463
- let y = list.topMm;
464
- const placeHeader = (target, topMm) => {
465
- target.components.push({ ...headerComp, topMm });
198
+ let H = p.topMm;
199
+ const u = (y, S) => {
200
+ y.components.push({ ...I, topMm: S });
466
201
  };
467
- placeHeader(current, y);
468
- y += inter.headerHeightMm + mmPerRow;
469
- for (let i = 0; i < dataRows.length; i++) {
470
- const rowGrid = buildRowGridFast(inter, dataRows[i], measurer);
471
- if (y + rowGrid.heightMm > contentBottom()) {
472
- pushCurrent();
473
- const next = makeWorkingPage(tplPage);
474
- current.components = next.components;
475
- current.heightMm = next.heightMm;
476
- if (scaledList.headerEveryPage !== false) {
477
- placeHeader(current, list.topMm);
478
- y = list.topMm + inter.headerHeightMm;
479
- } else {
480
- y = contentTop;
481
- }
202
+ u(c, H), H += R.headerHeightMm + r;
203
+ for (let y = 0; y < v.length; y++) {
204
+ const S = wt(R, v[y], l);
205
+ if (H + S.heightMm > m()) {
206
+ g();
207
+ const M = K(h);
208
+ c.components = M.components, c.heightMm = M.heightMm, W.headerEveryPage !== !1 ? (u(c, p.topMm), H = p.topMm + R.headerHeightMm) : H = f;
482
209
  }
483
- current.components.push({
210
+ c.components.push({
484
211
  kind: "rect",
485
- leftMm: list.leftMm,
486
- topMm: y,
487
- widthMm: list.widthMm,
488
- heightMm: rowGrid.heightMm,
489
- grid: rowGrid.grid,
490
- nid: nextId("listr"),
491
- style: inter.borderStyle
492
- });
493
- y += rowGrid.heightMm;
494
- }
495
- }
496
- pushCurrent();
497
- }
498
- return {
499
- plan: { schemaVersion: RENDER_PLAN_SCHEMA_VERSION, pages },
500
- warnings
501
- };
502
- }
503
-
504
- // src/render/grid-geometry.ts
505
- function cumulate(sizesMm, totalMm) {
506
- const n = sizesMm.length;
507
- if (n === 0) return [];
508
- const sum = sizesMm.reduce((s, v) => s + v, 0);
509
- const scale = sum > 0 && totalMm > 0 ? totalMm / sum : 1;
510
- const out = [];
511
- let acc = 0;
512
- for (let i = 0; i < n; i++) {
513
- const size = Math.max(0, sizesMm[i] * scale);
514
- out.push({ pos: acc, size });
515
- acc += size;
516
- }
517
- return out;
518
- }
519
- function resolveGridLayout(grid, compWidthMm, compHeightMm) {
520
- const rowsRaw = grid.cells ?? [];
521
- const rowCount = Math.max(rowsRaw.length, 1);
522
- const colCount = grid.colWidthsMm?.length ?? Math.max(1, ...rowsRaw.map((r) => Array.isArray(r) ? r.length : 0));
523
- const widths = grid.colWidthsMm?.length ? cumulate(grid.colWidthsMm, compWidthMm) : Array.from({ length: colCount }, (_, i) => ({
524
- pos: compWidthMm * i / colCount,
525
- size: compWidthMm / colCount
526
- }));
527
- const colPos = (ci) => ci <= 0 ? 0 : ci >= colCount ? widths[widths.length - 1].pos + widths[widths.length - 1].size : widths[ci].pos;
528
- const heights = grid.rowHeightsMm?.length ? cumulate(grid.rowHeightsMm, compHeightMm) : Array.from({ length: rowCount }, (_, i) => ({
529
- pos: compHeightMm * i / rowCount,
530
- size: compHeightMm / rowCount
531
- }));
532
- const rowPos = (ri) => ri <= 0 ? 0 : ri >= rowCount ? heights[heights.length - 1].pos + heights[heights.length - 1].size : heights[ri].pos;
533
- const occupied = /* @__PURE__ */ new Set();
534
- const key = (r, c) => `${r}:${c}`;
535
- const cells = [];
536
- const vBridge = /* @__PURE__ */ new Set();
537
- const hBridge = /* @__PURE__ */ new Set();
538
- const vKey = (c, r) => `v${c}:${r}`;
539
- const hKey = (r, c) => `h${r}:${c}`;
540
- rowsRaw.forEach((row, ri) => {
541
- if (!Array.isArray(row)) return;
542
- let ci = 0;
543
- for (const cell of row) {
544
- while (ci < colCount && occupied.has(key(ri, ci))) ci++;
545
- if (ci >= colCount) break;
546
- const colSpan = Math.max(1, Math.min(cell?.colSpan ?? 1, colCount - ci));
547
- const rowSpan = Math.max(1, cell?.rowSpan ?? 1);
548
- const rowEnd = Math.min(rowCount, ri + rowSpan);
549
- const colEnd = Math.min(colCount, ci + colSpan);
550
- for (let dr = ri; dr < rowEnd; dr++) {
551
- for (let dc = ci; dc < colEnd; dc++) {
552
- occupied.add(key(dr, dc));
553
- }
554
- }
555
- for (let c = ci + 1; c < colEnd; c++) {
556
- for (let r = ri; r < rowEnd; r++) vBridge.add(vKey(c, r));
557
- }
558
- for (let r = ri + 1; r < rowEnd; r++) {
559
- for (let c = ci; c < colEnd; c++) hBridge.add(hKey(r, c));
560
- }
561
- const xMm = colPos(ci);
562
- const yMm = rowPos(ri);
563
- cells.push({
564
- ri,
565
- ci,
566
- cell: cell ?? {},
567
- xMm,
568
- yMm,
569
- widthMm: colPos(colEnd) - xMm,
570
- heightMm: rowPos(rowEnd) - yMm
571
- });
572
- ci = colEnd;
573
- }
574
- });
575
- const edges = [];
576
- for (let c = 1; c < colCount; c++) {
577
- let runStart = -1;
578
- for (let r = 0; r <= rowCount; r++) {
579
- const open = r < rowCount && !vBridge.has(vKey(c, r));
580
- if (open && runStart < 0) runStart = r;
581
- if (!open && runStart >= 0) {
582
- edges.push({ kind: "v", pos: colPos(c), from: rowPos(runStart), to: rowPos(r) });
583
- runStart = -1;
212
+ leftMm: p.leftMm,
213
+ topMm: H,
214
+ widthMm: p.widthMm,
215
+ heightMm: S.heightMm,
216
+ grid: S.grid,
217
+ nid: d("listr"),
218
+ style: R.borderStyle
219
+ }), H += S.heightMm;
584
220
  }
585
221
  }
222
+ g();
586
223
  }
587
- for (let r = 1; r < rowCount; r++) {
588
- let runStart = -1;
589
- for (let c = 0; c <= colCount; c++) {
590
- const open = c < colCount && !hBridge.has(hKey(r, c));
591
- if (open && runStart < 0) runStart = c;
592
- if (!open && runStart >= 0) {
593
- edges.push({ kind: "h", pos: rowPos(r), from: colPos(runStart), to: colPos(c) });
594
- runStart = -1;
595
- }
596
- }
597
- }
598
- return { columns: widths, rows: heights, cells, edges };
599
- }
600
-
601
- // src/render/style.ts
602
- function resolveFontSize(style, dpi = 96, defaultPt = DEFAULT_FONT_PT) {
603
- if (style?.fontSizePx != null) {
604
- return { fontSizePt: style.fontSizePx * 72 / dpi, fontSizePx: style.fontSizePx };
605
- }
606
- const pt = style?.fontSize ?? defaultPt;
607
- return { fontSizePt: pt, fontSizePx: ptToPx(pt, dpi) };
608
- }
609
- function resolveStroke(style, fallbackColor = DEFAULT_STROKE_COLOR) {
610
224
  return {
611
- color: style?.borderColor ?? style?.lineColor ?? fallbackColor,
612
- widthPt: style?.lineWidthPt ?? DEFAULT_BORDER_PT
225
+ plan: { schemaVersion: at, pages: o },
226
+ warnings: a
613
227
  };
614
228
  }
615
- function resolveTextColor(style, fallback = DEFAULT_TEXT_COLOR) {
616
- return style?.color ?? fallback;
617
- }
618
- function resolveLineHeight(style) {
619
- return style?.lineHeight ?? LINE_HEIGHT;
620
- }
621
- function resolveBoxBorders(style) {
622
- const top = style?.borderTop !== false;
623
- const right = style?.borderRight !== false;
624
- const bottom = style?.borderBottom !== false;
625
- const left = style?.borderLeft !== false;
626
- return { top, right, bottom, left, inner: top || right || bottom || left };
627
- }
628
-
629
- // src/render/dom.ts
630
- var CLS = {
229
+ const St = {
631
230
  root: "mr-root",
632
231
  page: "mr-page",
633
232
  comp: "mr-comp",
@@ -644,848 +243,523 @@ var CLS = {
644
243
  cell: "mr-cell",
645
244
  unknown: "mr-unknown"
646
245
  };
647
- function classOf(key, options) {
648
- return options?.classNames?.[key] ?? CLS[key];
246
+ function x(t, n) {
247
+ return n?.classNames?.[t] ?? St[t];
649
248
  }
650
- var StyleBag = class {
249
+ class $ {
651
250
  constructor() {
652
251
  this.props = [];
653
252
  }
654
- add(prop, value) {
655
- if (value === void 0 || value === null || value === false || value === "") return this;
656
- this.props.push([prop, String(value)]);
657
- return this;
253
+ add(n, i) {
254
+ return i == null || i === !1 || i === "" ? this : (this.props.push([n, String(i)]), this);
658
255
  }
659
- mm(prop, valueMm, dpi, digits = 2) {
660
- return this.add(prop, `${round(mmToPx(valueMm, dpi), digits)}px`);
256
+ mm(n, i, e, r = 2) {
257
+ return this.add(n, `${F(lt(i, e), r)}px`);
661
258
  }
662
259
  toString() {
663
- let css = "";
664
- for (const [prop, value] of this.props) {
665
- css += `${prop}:${value};`;
666
- }
667
- return css;
668
- }
669
- applyTo(el) {
670
- const css = this.toString();
671
- if (css) el.style.cssText = css;
672
- }
673
- };
674
- function applyComponentStyle(bag, comp, dpi) {
675
- const s = comp.style || {};
676
- bag.add("color", s.color).add("background-color", s.backgroundColor).add("font-family", s.fontFamily).add("font-weight", s.bold ? "700" : void 0).add("font-style", s.italic ? "italic" : void 0).add("text-decoration", s.underline ? "underline" : void 0).add("letter-spacing", s.letterSpacing != null ? `${s.letterSpacing}pt` : void 0).add("opacity", s.opacity != null ? String(s.opacity) : void 0).add("transform", s.rotateDeg ? `rotate(${s.rotateDeg}deg)` : void 0);
677
- const font = resolveFontSize(s, dpi);
678
- bag.add("font-size", `${round(font.fontSizePx, 2)}px`);
679
- }
680
- function renderGrid(grid, comp, dpi, options, doc) {
681
- const table = doc.createElement("table");
682
- table.className = classOf("grid", options);
683
- new StyleBag().add("width", "100%").add("height", "100%").add("border-collapse", "collapse").add("table-layout", grid.colWidthsMm ? "fixed" : "auto").applyTo(table);
684
- if (grid.colWidthsMm) {
685
- const colGroup = doc.createElement("colgroup");
686
- for (const w of grid.colWidthsMm) {
687
- const col = doc.createElement("col");
688
- new StyleBag().mm("width", w, dpi).applyTo(col);
689
- colGroup.appendChild(col);
690
- }
691
- table.appendChild(colGroup);
692
- }
693
- const borders = resolveBoxBorders(comp.style);
694
- const stroke = resolveStroke(comp.style);
695
- const border = borders.inner ? `${round(stroke.widthPt * dpi / 72, 2)}px solid ${stroke.color}` : "";
696
- grid.cells.forEach((row, ri) => {
697
- const rowEl = doc.createElement("tr");
698
- rowEl.className = classOf("row", options);
699
- if (grid.rowHeightsMm?.[ri] != null) {
700
- new StyleBag().mm("height", grid.rowHeightsMm[ri], dpi).applyTo(rowEl);
701
- }
702
- (row || []).forEach((cell) => {
703
- const cellEl = doc.createElement("td");
704
- cellEl.className = classOf("cell", options);
705
- if (cell?.colSpan) cellEl.colSpan = cell.colSpan;
706
- if (cell?.rowSpan) cellEl.rowSpan = cell.rowSpan;
707
- const cellBag = new StyleBag();
708
- if (border) cellBag.add("border", border);
709
- if (cell?.style) {
710
- const st = cell.style;
711
- cellBag.add("text-align", st.align).add("vertical-align", st.verticalAlign).add("background-color", st.backgroundColor).add("color", st.color).add("font-weight", st.bold ? "700" : void 0);
712
- cellBag.add("font-size", `${round(resolveFontSize(st, dpi).fontSizePx, 2)}px`);
260
+ let n = "";
261
+ for (const [i, e] of this.props)
262
+ n += `${i}:${e};`;
263
+ return n;
264
+ }
265
+ applyTo(n) {
266
+ const i = this.toString();
267
+ i && (n.style.cssText = i);
268
+ }
269
+ }
270
+ function tt(t, n, i) {
271
+ const e = n.style || {};
272
+ t.add("color", e.color).add("background-color", e.backgroundColor).add("font-family", e.fontFamily).add("font-weight", e.bold ? "700" : void 0).add("font-style", e.italic ? "italic" : void 0).add("text-decoration", e.underline ? "underline" : void 0).add("letter-spacing", e.letterSpacing != null ? `${e.letterSpacing}pt` : void 0).add("opacity", e.opacity != null ? String(e.opacity) : void 0).add("transform", e.rotateDeg ? `rotate(${e.rotateDeg}deg)` : void 0);
273
+ const r = _(e, i);
274
+ t.add("font-size", `${F(r.fontSizePx, 2)}px`);
275
+ }
276
+ function Tt(t, n, i, e, r) {
277
+ const l = r.createElement("table");
278
+ if (l.className = x("grid", e), new $().add("width", "100%").add("height", "100%").add("border-collapse", "collapse").add("table-layout", t.colWidthsMm ? "fixed" : "auto").applyTo(l), t.colWidthsMm) {
279
+ const d = r.createElement("colgroup");
280
+ for (const h of t.colWidthsMm) {
281
+ const c = r.createElement("col");
282
+ new $().mm("width", h, i).applyTo(c), d.appendChild(c);
283
+ }
284
+ l.appendChild(d);
285
+ }
286
+ const a = G(n.style), o = z(n.style), s = a.inner ? `${F(o.widthPt * i / 72, 2)}px solid ${o.color}` : "";
287
+ return t.cells.forEach((d, h) => {
288
+ const c = r.createElement("tr");
289
+ c.className = x("row", e), t.rowHeightsMm?.[h] != null && new $().mm("height", t.rowHeightsMm[h], i).applyTo(c), (d || []).forEach((m) => {
290
+ const f = r.createElement("td");
291
+ f.className = x("cell", e), m?.colSpan && (f.colSpan = m.colSpan), m?.rowSpan && (f.rowSpan = m.rowSpan);
292
+ const g = new $();
293
+ if (s && g.add("border", s), m?.style) {
294
+ const b = m.style;
295
+ g.add("text-align", b.align).add("vertical-align", b.verticalAlign).add("background-color", b.backgroundColor).add("color", b.color).add("font-weight", b.bold ? "700" : void 0), g.add("font-size", `${F(_(b, i).fontSizePx, 2)}px`);
713
296
  }
714
- cellBag.applyTo(cellEl);
715
- if (cell?.text != null) cellEl.textContent = cell.text;
716
- if (cell?.children?.length) {
717
- for (const child of cell.children) {
718
- cellEl.appendChild(renderComponent(child, dpi, options, doc));
719
- }
720
- }
721
- rowEl.appendChild(cellEl);
722
- });
723
- table.appendChild(rowEl);
724
- });
725
- return table;
726
- }
727
- function renderText(comp, dpi, options, doc) {
728
- const el = doc.createElement("div");
729
- el.className = classOf("text", options);
730
- const s = comp.style || {};
731
- const bag = new StyleBag().add("text-align", s.align).add("display", "flex").add("flex-direction", "column").add(
297
+ if (g.applyTo(f), m?.text != null && (f.textContent = m.text), m?.children?.length)
298
+ for (const b of m.children)
299
+ f.appendChild(et(b, i, e, r));
300
+ c.appendChild(f);
301
+ }), l.appendChild(c);
302
+ }), l;
303
+ }
304
+ function vt(t, n, i, e) {
305
+ const r = e.createElement("div");
306
+ r.className = x("text", i);
307
+ const l = t.style || {}, a = new $().add("text-align", l.align).add("display", "flex").add("flex-direction", "column").add(
732
308
  "justify-content",
733
- s.verticalAlign === "middle" ? "center" : s.verticalAlign === "bottom" ? "flex-end" : "flex-start"
309
+ l.verticalAlign === "middle" ? "center" : l.verticalAlign === "bottom" ? "flex-end" : "flex-start"
734
310
  ).add("overflow", "hidden");
735
- applyComponentStyle(bag, comp, dpi);
736
- bag.applyTo(el);
737
- if (isRichText(comp)) {
738
- const richBox = doc.createElement("div");
739
- richBox.className = classOf("rich", options);
740
- for (const para of comp.richParagraphs) {
741
- const p = doc.createElement("div");
742
- p.className = classOf("paragraph", options);
743
- const pBag = new StyleBag().add("text-align", para.align).add("line-height", para.lineHeight != null ? String(para.lineHeight) : void 0).mm("margin-top", para.spaceBeforeMm ?? 0, dpi).mm("margin-bottom", para.spaceAfterMm ?? 0, dpi).mm("text-indent", para.indentMm ?? 0, dpi);
744
- pBag.applyTo(p);
745
- for (const seg of para.segments || []) {
746
- const segEl = doc.createElement("span");
747
- segEl.className = classOf("segment", options);
748
- segEl.textContent = seg.kind === "field" ? seg.field ?? "" : seg.text ?? "";
749
- if (seg.style) {
750
- const segBag = new StyleBag().add("color", seg.style.color).add("font-weight", seg.style.bold ? "700" : void 0);
751
- segBag.add("font-size", `${round(resolveFontSize(seg.style, dpi).fontSizePx, 2)}px`);
752
- segBag.applyTo(segEl);
311
+ if (tt(a, t, n), a.applyTo(r), X(t)) {
312
+ const o = e.createElement("div");
313
+ o.className = x("rich", i);
314
+ for (const s of t.richParagraphs) {
315
+ const d = e.createElement("div");
316
+ d.className = x("paragraph", i), new $().add("text-align", s.align).add("line-height", s.lineHeight != null ? String(s.lineHeight) : void 0).mm("margin-top", s.spaceBeforeMm ?? 0, n).mm("margin-bottom", s.spaceAfterMm ?? 0, n).mm("text-indent", s.indentMm ?? 0, n).applyTo(d);
317
+ for (const c of s.segments || []) {
318
+ const m = e.createElement("span");
319
+ if (m.className = x("segment", i), m.textContent = c.kind === "field" ? c.field ?? "" : c.text ?? "", c.style) {
320
+ const f = new $().add("color", c.style.color).add("font-weight", c.style.bold ? "700" : void 0);
321
+ f.add("font-size", `${F(_(c.style, n).fontSizePx, 2)}px`), f.applyTo(m);
753
322
  }
754
- p.appendChild(segEl);
323
+ d.appendChild(m);
755
324
  }
756
- richBox.appendChild(p);
757
- }
758
- el.appendChild(richBox);
759
- return el;
760
- }
761
- if (Array.isArray(comp.lines) && comp.lines.length > 0) {
762
- const box = doc.createElement("div");
763
- box.className = classOf("lines", options);
764
- if (s.lineHeight != null) new StyleBag().add("line-height", String(s.lineHeight)).applyTo(box);
765
- for (const line of comp.lines) {
766
- const lineEl = doc.createElement("div");
767
- lineEl.className = classOf("line", options);
768
- lineEl.textContent = line;
769
- box.appendChild(lineEl);
770
- }
771
- el.appendChild(box);
772
- return el;
773
- }
774
- el.textContent = comp.text ?? "";
775
- return el;
776
- }
777
- function renderImage(comp, options, doc) {
778
- const img = doc.createElement("img");
779
- img.className = classOf("image", options);
780
- img.src = comp.imageData;
781
- new StyleBag().add("width", "100%").add("height", "100%").add("object-fit", "contain").add("display", "block").applyTo(img);
782
- img.alt = comp.kind;
783
- return img;
784
- }
785
- function renderShape(comp, dpi, options, doc) {
786
- const el = doc.createElement("div");
787
- el.className = classOf("shape", options);
788
- const s = comp.style || {};
789
- const stroke = resolveStroke(s);
790
- const borders = resolveBoxBorders(s);
791
- const border = `${round(stroke.widthPt * dpi / 72, 2)}px solid ${stroke.color}`;
792
- const bag = new StyleBag();
793
- if (comp.grid) {
794
- if (borders.top) bag.add("border-top", border);
795
- if (borders.right) bag.add("border-right", border);
796
- if (borders.bottom) bag.add("border-bottom", border);
797
- if (borders.left) bag.add("border-left", border);
798
- } else if (comp.kind === "rect") {
799
- if (borders.top) bag.add("border-top", border);
800
- if (borders.right) bag.add("border-right", border);
801
- if (borders.bottom) bag.add("border-bottom", border);
802
- if (borders.left) bag.add("border-left", border);
803
- } else if (comp.kind === "ellipse") {
804
- if (borders.inner) bag.add("border", border).add("border-radius", "50%");
805
- if (s.backgroundColor) bag.add("background-color", s.backgroundColor);
806
- } else if (comp.kind === "line") {
807
- bag.add("height", "0").add("border-top", border);
808
- }
809
- bag.add("box-sizing", "border-box").add("width", "100%").add("height", "100%");
810
- bag.applyTo(el);
811
- return el;
812
- }
813
- function renderComponent(comp, dpi, options, doc) {
814
- const wrap = doc.createElement("div");
815
- wrap.className = `${classOf("comp", options)} mr-kind-${comp.kind}`;
816
- const bag = new StyleBag().add("position", "absolute").mm("left", comp.leftMm, dpi).mm("top", comp.topMm, dpi).mm("width", comp.widthMm, dpi).mm("height", comp.heightMm, dpi).add("box-sizing", "border-box");
817
- applyComponentStyle(bag, comp, dpi);
818
- bag.applyTo(wrap);
819
- if (isImageBackedComponent(comp)) {
820
- wrap.appendChild(renderImage(comp, options, doc));
821
- return wrap;
822
- }
823
- if (comp.kind === "text") {
824
- wrap.appendChild(renderText(comp, dpi, options, doc));
825
- return wrap;
826
- }
827
- if (comp.grid) {
828
- const shape = renderShape(comp, dpi, options, doc);
829
- shape.appendChild(renderGrid(comp.grid, comp, dpi, options, doc));
830
- wrap.appendChild(shape);
831
- return wrap;
832
- }
833
- if (comp.kind === "line" || comp.kind === "rect" || comp.kind === "ellipse" || comp.kind === "chart") {
834
- wrap.appendChild(renderShape(comp, dpi, options, doc));
835
- return wrap;
836
- }
837
- const ph = doc.createElement("div");
838
- ph.className = classOf("unknown", options);
839
- ph.textContent = comp.fallbackText ?? "";
840
- wrap.appendChild(ph);
841
- return wrap;
842
- }
843
- function renderPage(page, dpi, options, doc) {
844
- const el = doc.createElement("div");
845
- el.className = classOf("page", options);
846
- new StyleBag().add("position", "relative").mm("width", page.pageWidthMm, dpi).mm("height", page.pageHeightMm, dpi).add("background-color", "#fff").add("overflow", "hidden").add("box-sizing", "border-box").applyTo(el);
847
- for (const comp of page.components) {
848
- el.appendChild(renderComponent(comp, dpi, options, doc));
849
- }
850
- return el;
851
- }
852
- function renderPlan(plan, doc, options = {}) {
853
- const dpi = options.dpi ?? 96;
854
- const root = doc.createElement("div");
855
- root.className = classOf("root", options);
856
- root.dataset.schemaVersion = plan.schemaVersion;
857
- plan.pages.forEach((page) => {
858
- root.appendChild(renderPage(page, dpi, options, doc));
859
- });
860
- return root;
861
- }
862
-
863
- // src/render/window.ts
864
- function computePageWindow(input) {
865
- const { pageHeightsPx, viewportHeightPx, scrollTopPx, overscan = 1, gapPx = 0 } = input;
866
- const n = pageHeightsPx.length;
867
- if (n === 0) {
325
+ o.appendChild(d);
326
+ }
327
+ return r.appendChild(o), r;
328
+ }
329
+ if (Array.isArray(t.lines) && t.lines.length > 0) {
330
+ const o = e.createElement("div");
331
+ o.className = x("lines", i), l.lineHeight != null && new $().add("line-height", String(l.lineHeight)).applyTo(o);
332
+ for (const s of t.lines) {
333
+ const d = e.createElement("div");
334
+ d.className = x("line", i), d.textContent = s, o.appendChild(d);
335
+ }
336
+ return r.appendChild(o), r;
337
+ }
338
+ return r.textContent = t.text ?? "", r;
339
+ }
340
+ function kt(t, n, i) {
341
+ const e = i.createElement("img");
342
+ return e.className = x("image", n), e.src = t.imageData, new $().add("width", "100%").add("height", "100%").add("object-fit", "contain").add("display", "block").applyTo(e), e.alt = t.kind, e;
343
+ }
344
+ function Y(t, n, i, e) {
345
+ const r = e.createElement("div");
346
+ r.className = x("shape", i);
347
+ const l = t.style || {}, a = z(l), o = G(l), s = `${F(a.widthPt * n / 72, 2)}px solid ${a.color}`, d = new $();
348
+ return t.grid || t.kind === "rect" ? (o.top && d.add("border-top", s), o.right && d.add("border-right", s), o.bottom && d.add("border-bottom", s), o.left && d.add("border-left", s)) : t.kind === "ellipse" ? (o.inner && d.add("border", s).add("border-radius", "50%"), l.backgroundColor && d.add("background-color", l.backgroundColor)) : t.kind === "line" && d.add("height", "0").add("border-top", s), d.add("box-sizing", "border-box").add("width", "100%").add("height", "100%"), d.applyTo(r), r;
349
+ }
350
+ function et(t, n, i, e) {
351
+ const r = e.createElement("div");
352
+ r.className = `${x("comp", i)} mr-kind-${t.kind}`;
353
+ const l = new $().add("position", "absolute").mm("left", t.leftMm, n).mm("top", t.topMm, n).mm("width", t.widthMm, n).mm("height", t.heightMm, n).add("box-sizing", "border-box");
354
+ if (tt(l, t, n), l.applyTo(r), st(t))
355
+ return r.appendChild(kt(t, i, e)), r;
356
+ if (t.kind === "text")
357
+ return r.appendChild(vt(t, n, i, e)), r;
358
+ if (t.grid) {
359
+ const o = Y(t, n, i, e);
360
+ return o.appendChild(Tt(t.grid, t, n, i, e)), r.appendChild(o), r;
361
+ }
362
+ if (t.kind === "line" || t.kind === "rect" || t.kind === "ellipse" || t.kind === "chart")
363
+ return r.appendChild(Y(t, n, i, e)), r;
364
+ const a = e.createElement("div");
365
+ return a.className = x("unknown", i), a.textContent = t.fallbackText ?? "", r.appendChild(a), r;
366
+ }
367
+ function xt(t, n, i, e) {
368
+ const r = e.createElement("div");
369
+ r.className = x("page", i), new $().add("position", "relative").mm("width", t.pageWidthMm, n).mm("height", t.pageHeightMm, n).add("background-color", "#fff").add("overflow", "hidden").add("box-sizing", "border-box").applyTo(r);
370
+ for (const l of t.components)
371
+ r.appendChild(et(l, n, i, e));
372
+ return r;
373
+ }
374
+ function Wt(t, n, i = {}) {
375
+ const e = i.dpi ?? 96, r = n.createElement("div");
376
+ return r.className = x("root", i), r.dataset.schemaVersion = t.schemaVersion, t.pages.forEach((l) => {
377
+ r.appendChild(xt(l, e, i, n));
378
+ }), r;
379
+ }
380
+ function Ct(t) {
381
+ const { pageHeightsPx: n, viewportHeightPx: i, scrollTopPx: e, overscan: r = 1, gapPx: l = 0 } = t, a = n.length;
382
+ if (a === 0)
868
383
  return { start: 0, end: -1, padTopPx: 0, padBottomPx: 0 };
869
- }
870
- const gap = Math.max(0, gapPx);
871
- const offsets = new Array(n + 1);
872
- offsets[0] = 0;
873
- for (let i = 0; i < n; i++) {
874
- offsets[i + 1] = offsets[i] + Math.max(0, pageHeightsPx[i] ?? 0) + gap;
875
- }
876
- const total = offsets[n];
877
- const top = Math.max(0, scrollTopPx);
878
- let cover = 0;
879
- let lo = 0;
880
- let hi = n - 1;
881
- while (lo <= hi) {
882
- const mid = lo + hi >> 1;
883
- if (offsets[mid] <= top) {
884
- cover = mid;
885
- lo = mid + 1;
886
- } else {
887
- hi = mid - 1;
888
- }
889
- }
890
- const start = Math.max(0, Math.min(n - 1, cover - overscan));
891
- const target = offsets[cover] + Math.max(0, viewportHeightPx);
892
- let visibleEnd = n - 1;
893
- lo = 0;
894
- hi = n - 1;
895
- while (lo <= hi) {
896
- const mid = lo + hi >> 1;
897
- if (offsets[mid + 1] < target) {
898
- lo = mid + 1;
899
- } else {
900
- visibleEnd = mid;
901
- hi = mid - 1;
902
- }
903
- }
904
- const end = Math.min(n - 1, visibleEnd + overscan);
905
- const padTopPx = offsets[start];
906
- const padBottomPx = Math.max(0, total - offsets[end + 1]);
907
- return { start, end, padTopPx, padBottomPx };
908
- }
909
-
910
- // src/render/canvas.ts
911
- var PX_PER_MM_BASE = 96 / 25.4;
912
- function measurePageSizePx(page, dpi = 96) {
913
- const pxPerMm = dpi / 96 * PX_PER_MM_BASE;
384
+ const o = Math.max(0, l), s = new Array(a + 1);
385
+ s[0] = 0;
386
+ for (let w = 0; w < a; w++)
387
+ s[w + 1] = s[w] + Math.max(0, n[w] ?? 0) + o;
388
+ const d = s[a], h = Math.max(0, e);
389
+ let c = 0, m = 0, f = a - 1;
390
+ for (; m <= f; ) {
391
+ const w = m + f >> 1;
392
+ s[w] <= h ? (c = w, m = w + 1) : f = w - 1;
393
+ }
394
+ const g = Math.max(0, Math.min(a - 1, c - r)), b = s[c] + Math.max(0, i);
395
+ let p = a - 1;
396
+ for (m = 0, f = a - 1; m <= f; ) {
397
+ const w = m + f >> 1;
398
+ s[w + 1] < b ? m = w + 1 : (p = w, f = w - 1);
399
+ }
400
+ const C = Math.min(a - 1, p + r), v = s[g], E = Math.max(0, d - s[C + 1]);
401
+ return { start: g, end: C, padTopPx: v, padBottomPx: E };
402
+ }
403
+ const q = 96 / 25.4;
404
+ function nt(t, n = 96) {
405
+ const i = n / 96 * q;
914
406
  return {
915
- widthPx: Math.max(1, Math.round(page.pageWidthMm * pxPerMm)),
916
- heightPx: Math.max(1, Math.round(page.pageHeightMm * pxPerMm))
407
+ widthPx: Math.max(1, Math.round(t.pageWidthMm * i)),
408
+ heightPx: Math.max(1, Math.round(t.pageHeightMm * i))
917
409
  };
918
410
  }
919
- function createPageCanvas(page, dpr, dpi) {
920
- const canvas = document.createElement("canvas");
921
- const { widthPx: w, heightPx: h } = measurePageSizePx(page, dpi);
922
- canvas.width = Math.round(w * dpr);
923
- canvas.height = Math.round(h * dpr);
924
- canvas.style.width = `${w}px`;
925
- canvas.style.height = `${h}px`;
926
- const ctx = canvas.getContext("2d");
927
- if (!ctx) {
928
- throw new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 Canvas 2D\uFF08\u6D4B\u8BD5\u9700\u771F\u6D4F\u89C8\u5668\uFF0C\u89C1 e2e/canvas.spec.ts\uFF09");
929
- }
930
- ctx.scale(dpr, dpr);
931
- ctx.fillStyle = "#ffffff";
932
- ctx.fillRect(0, 0, w, h);
933
- return { canvas, ctx };
934
- }
935
- function planFontSizePx(style, dpi = 96) {
936
- return resolveFontSize(style, dpi).fontSizePx;
937
- }
938
- function drawTextBlock(ctx, spec, x, y, w, h, fontFamily, verticalAlign = "top") {
939
- ctx.font = `${spec.bold ? "bold " : ""}${spec.fontSizePx}px ${fontFamily}`;
940
- ctx.fillStyle = spec.color;
941
- ctx.textBaseline = "alphabetic";
942
- const lineH = spec.fontSizePx * spec.lineHeight;
943
- const lines = spec.text === "" ? [""] : spec.text.split("\n");
944
- const totalH = lines.length * lineH;
945
- let topY = y;
946
- if (verticalAlign === "middle") topY = y + (h - totalH) / 2;
947
- else if (verticalAlign === "bottom") topY = y + h - totalH;
948
- lines.forEach((line, i) => {
949
- ctx.textAlign = spec.align === "center" ? "center" : spec.align === "right" ? "right" : "left";
950
- const tx = spec.align === "center" ? x + w / 2 : spec.align === "right" ? x + w : x;
951
- ctx.fillText(line, tx, topY + i * lineH + spec.fontSizePx * 0.8, w);
952
- });
953
- ctx.textAlign = "left";
954
- }
955
- function drawGrid(ctx, grid, comp, x, y, w, h, pxPerMm, dpi, fontFamily, measurer) {
956
- const layout = resolveGridLayout(grid, w / pxPerMm, h / pxPerMm);
957
- const borders = resolveBoxBorders(comp.style);
958
- const stroke = resolveStroke(comp.style);
959
- for (const box of layout.cells) {
960
- const bg = box.cell.style?.backgroundColor;
961
- if (bg) {
962
- ctx.fillStyle = bg;
963
- ctx.fillRect(
964
- x + box.xMm * pxPerMm,
965
- y + box.yMm * pxPerMm,
966
- box.widthMm * pxPerMm,
967
- box.heightMm * pxPerMm
968
- );
969
- }
970
- }
971
- if (borders.inner) {
972
- ctx.strokeStyle = stroke.color;
973
- ctx.lineWidth = ptToPx(stroke.widthPt, dpi);
974
- for (const e of layout.edges) {
975
- ctx.beginPath();
976
- if (e.kind === "v") {
977
- ctx.moveTo(x + e.pos * pxPerMm, y + e.from * pxPerMm);
978
- ctx.lineTo(x + e.pos * pxPerMm, y + e.to * pxPerMm);
979
- } else {
980
- ctx.moveTo(x + e.from * pxPerMm, y + e.pos * pxPerMm);
981
- ctx.lineTo(x + e.to * pxPerMm, y + e.pos * pxPerMm);
982
- }
983
- ctx.stroke();
984
- }
985
- ctx.beginPath();
986
- if (borders.top) {
987
- ctx.moveTo(x, y);
988
- ctx.lineTo(x + w, y);
989
- }
990
- if (borders.right) {
991
- ctx.moveTo(x + w, y);
992
- ctx.lineTo(x + w, y + h);
993
- }
994
- if (borders.bottom) {
995
- ctx.moveTo(x + w, y + h);
996
- ctx.lineTo(x, y + h);
997
- }
998
- if (borders.left) {
999
- ctx.moveTo(x, y + h);
1000
- ctx.lineTo(x, y);
1001
- }
1002
- ctx.stroke();
1003
- }
1004
- for (const box of layout.cells) {
1005
- const text = typeof box.cell.text === "string" ? box.cell.text : "";
1006
- if (!text) continue;
1007
- const st = box.cell.style;
1008
- const fontSizePt = st?.fontSize ?? DEFAULT_FONT_PT;
1009
- const lines = wrapText(
1010
- text,
1011
- box.widthMm - 1,
1012
- { fontSizePt },
1013
- measurer
1014
- ).join("\n");
1015
- drawTextBlock(
1016
- ctx,
411
+ function Pt(t, n, i) {
412
+ const e = document.createElement("canvas"), { widthPx: r, heightPx: l } = nt(t, i);
413
+ e.width = Math.round(r * n), e.height = Math.round(l * n), e.style.width = `${r}px`, e.style.height = `${l}px`;
414
+ const a = e.getContext("2d");
415
+ if (!a)
416
+ throw new Error("当前环境不支持 Canvas 2D(测试需真浏览器,见 e2e/canvas.spec.ts)");
417
+ return a.scale(n, n), a.fillStyle = "#ffffff", a.fillRect(0, 0, r, l), { canvas: e, ctx: a };
418
+ }
419
+ function It(t, n = 96) {
420
+ return _(t, n).fontSizePx;
421
+ }
422
+ function it(t, n, i, e, r, l, a, o = "top") {
423
+ t.font = `${n.bold ? "bold " : ""}${n.fontSizePx}px ${a}`, t.fillStyle = n.color, t.textBaseline = "alphabetic";
424
+ const s = n.fontSizePx * n.lineHeight, d = n.text === "" ? [""] : n.text.split(`
425
+ `), h = d.length * s;
426
+ let c = e;
427
+ o === "middle" ? c = e + (l - h) / 2 : o === "bottom" && (c = e + l - h), d.forEach((m, f) => {
428
+ t.textAlign = n.align === "center" ? "center" : n.align === "right" ? "right" : "left";
429
+ const g = n.align === "center" ? i + r / 2 : n.align === "right" ? i + r : i;
430
+ t.fillText(m, g, c + f * s + n.fontSizePx * 0.8, r);
431
+ }), t.textAlign = "left";
432
+ }
433
+ function At(t, n, i, e, r, l, a, o, s, d, h) {
434
+ const c = ht(n, l / o, a / o), m = G(i.style), f = z(i.style);
435
+ for (const g of c.cells) {
436
+ const b = g.cell.style?.backgroundColor;
437
+ b && (t.fillStyle = b, t.fillRect(
438
+ e + g.xMm * o,
439
+ r + g.yMm * o,
440
+ g.widthMm * o,
441
+ g.heightMm * o
442
+ ));
443
+ }
444
+ if (m.inner) {
445
+ t.strokeStyle = f.color, t.lineWidth = D(f.widthPt, s);
446
+ for (const g of c.edges)
447
+ t.beginPath(), g.kind === "v" ? (t.moveTo(e + g.pos * o, r + g.from * o), t.lineTo(e + g.pos * o, r + g.to * o)) : (t.moveTo(e + g.from * o, r + g.pos * o), t.lineTo(e + g.to * o, r + g.pos * o)), t.stroke();
448
+ t.beginPath(), m.top && (t.moveTo(e, r), t.lineTo(e + l, r)), m.right && (t.moveTo(e + l, r), t.lineTo(e + l, r + a)), m.bottom && (t.moveTo(e + l, r + a), t.lineTo(e, r + a)), m.left && (t.moveTo(e, r + a), t.lineTo(e, r)), t.stroke();
449
+ }
450
+ for (const g of c.cells) {
451
+ const b = typeof g.cell.text == "string" ? g.cell.text : "";
452
+ if (!b) continue;
453
+ const p = g.cell.style, C = p?.fontSize ?? j, v = O(
454
+ b,
455
+ g.widthMm - 1,
456
+ { fontSizePt: C },
457
+ h
458
+ ).join(`
459
+ `);
460
+ it(
461
+ t,
1017
462
  {
1018
- text: lines,
1019
- fontSizePx: resolveFontSize(st, dpi).fontSizePx,
1020
- bold: st?.bold ?? false,
1021
- color: st?.color ?? resolveTextColor(comp.style, DEFAULT_TEXT_COLOR),
1022
- align: st?.align ?? "left",
1023
- lineHeight: LINE_HEIGHT
463
+ text: v,
464
+ fontSizePx: _(p, s).fontSizePx,
465
+ bold: p?.bold ?? !1,
466
+ color: p?.color ?? Z(i.style, ct),
467
+ align: p?.align ?? "left",
468
+ lineHeight: J
1024
469
  },
1025
- x + (box.xMm + 0.5) * pxPerMm,
1026
- y + box.yMm * pxPerMm,
1027
- Math.max(0, (box.widthMm - 1) * pxPerMm),
1028
- box.heightMm * pxPerMm,
1029
- fontFamily,
1030
- st?.verticalAlign ?? "middle"
470
+ e + (g.xMm + 0.5) * o,
471
+ r + g.yMm * o,
472
+ Math.max(0, (g.widthMm - 1) * o),
473
+ g.heightMm * o,
474
+ d,
475
+ p?.verticalAlign ?? "middle"
1031
476
  );
1032
477
  }
1033
478
  }
1034
- function drawComponent(ctx, comp, pxPerMm, dpi, fontFamily, measurer) {
1035
- const x = comp.leftMm * pxPerMm;
1036
- const y = comp.topMm * pxPerMm;
1037
- const w = comp.widthMm * pxPerMm;
1038
- const h = comp.heightMm * pxPerMm;
1039
- const s = comp.style ?? {};
1040
- if (comp.grid) {
1041
- drawGrid(ctx, comp.grid, comp, x, y, w, h, pxPerMm, dpi, fontFamily, measurer);
479
+ function rt(t, n, i, e, r, l) {
480
+ const a = n.leftMm * i, o = n.topMm * i, s = n.widthMm * i, d = n.heightMm * i, h = n.style ?? {};
481
+ if (n.grid) {
482
+ At(t, n.grid, n, a, o, s, d, i, e, r, l);
1042
483
  return;
1043
484
  }
1044
- switch (comp.kind) {
485
+ switch (n.kind) {
1045
486
  case "text": {
1046
- const fontSizePt = s.fontSize ?? DEFAULT_FONT_PT;
1047
- const text = isRichText(comp) ? comp.richParagraphs.map((p) => (p.segments ?? []).map((seg) => seg.text ?? seg.field ?? "").join("")).join("\n") : Array.isArray(comp.lines) && comp.lines.length > 0 ? comp.lines.join("\n") : wrapText(comp.text ?? "", comp.widthMm, { fontSizePt }, measurer).join("\n");
1048
- drawTextBlock(
1049
- ctx,
487
+ const c = h.fontSize ?? j, m = X(n) ? n.richParagraphs.map((f) => (f.segments ?? []).map((g) => g.text ?? g.field ?? "").join("")).join(`
488
+ `) : Array.isArray(n.lines) && n.lines.length > 0 ? n.lines.join(`
489
+ `) : O(n.text ?? "", n.widthMm, { fontSizePt: c }, l).join(`
490
+ `);
491
+ it(
492
+ t,
1050
493
  {
1051
- text,
1052
- fontSizePx: resolveFontSize(s, dpi).fontSizePx,
1053
- bold: s.bold ?? false,
1054
- color: resolveTextColor(s),
1055
- align: s.align ?? "left",
1056
- lineHeight: resolveLineHeight(s)
494
+ text: m,
495
+ fontSizePx: _(h, e).fontSizePx,
496
+ bold: h.bold ?? !1,
497
+ color: Z(h),
498
+ align: h.align ?? "left",
499
+ lineHeight: dt(h)
1057
500
  },
1058
- x,
1059
- y,
1060
- w,
1061
- h,
1062
- fontFamily,
1063
- s.verticalAlign
501
+ a,
502
+ o,
503
+ s,
504
+ d,
505
+ r,
506
+ h.verticalAlign
1064
507
  );
1065
508
  break;
1066
509
  }
1067
510
  case "rect": {
1068
- const stroke = resolveStroke(s);
1069
- const borders = resolveBoxBorders(s);
1070
- if (s.backgroundColor) {
1071
- ctx.fillStyle = s.backgroundColor;
1072
- ctx.fillRect(x, y, w, h);
1073
- }
1074
- if (borders.inner) {
1075
- ctx.strokeStyle = stroke.color;
1076
- ctx.lineWidth = ptToPx(stroke.widthPt, dpi);
1077
- ctx.beginPath();
1078
- if (borders.top) {
1079
- ctx.moveTo(x, y);
1080
- ctx.lineTo(x + w, y);
1081
- }
1082
- if (borders.right) {
1083
- ctx.moveTo(x + w, y);
1084
- ctx.lineTo(x + w, y + h);
1085
- }
1086
- if (borders.bottom) {
1087
- ctx.moveTo(x + w, y + h);
1088
- ctx.lineTo(x, y + h);
1089
- }
1090
- if (borders.left) {
1091
- ctx.moveTo(x, y + h);
1092
- ctx.lineTo(x, y);
1093
- }
1094
- ctx.stroke();
1095
- }
511
+ const c = z(h), m = G(h);
512
+ h.backgroundColor && (t.fillStyle = h.backgroundColor, t.fillRect(a, o, s, d)), m.inner && (t.strokeStyle = c.color, t.lineWidth = D(c.widthPt, e), t.beginPath(), m.top && (t.moveTo(a, o), t.lineTo(a + s, o)), m.right && (t.moveTo(a + s, o), t.lineTo(a + s, o + d)), m.bottom && (t.moveTo(a + s, o + d), t.lineTo(a, o + d)), m.left && (t.moveTo(a, o + d), t.lineTo(a, o)), t.stroke());
1096
513
  break;
1097
514
  }
1098
515
  case "line": {
1099
- const stroke = resolveStroke({ ...s, borderColor: s.lineColor ?? s.borderColor });
1100
- ctx.strokeStyle = stroke.color;
1101
- ctx.lineWidth = ptToPx(stroke.widthPt, dpi);
1102
- ctx.beginPath();
1103
- ctx.moveTo(x, y + h / 2);
1104
- ctx.lineTo(x + w, y + h / 2);
1105
- ctx.stroke();
516
+ const c = z({ ...h, borderColor: h.lineColor ?? h.borderColor });
517
+ t.strokeStyle = c.color, t.lineWidth = D(c.widthPt, e), t.beginPath(), t.moveTo(a, o + d / 2), t.lineTo(a + s, o + d / 2), t.stroke();
1106
518
  break;
1107
519
  }
1108
520
  case "ellipse": {
1109
- const stroke = resolveStroke(s);
1110
- ctx.strokeStyle = stroke.color;
1111
- ctx.lineWidth = ptToPx(stroke.widthPt, dpi);
1112
- if (s.backgroundColor) {
1113
- ctx.fillStyle = s.backgroundColor;
1114
- ctx.beginPath();
1115
- ctx.ellipse(x + w / 2, y + h / 2, w / 2, h / 2, 0, 0, Math.PI * 2);
1116
- ctx.fill();
1117
- }
1118
- ctx.beginPath();
1119
- ctx.ellipse(x + w / 2, y + h / 2, w / 2, h / 2, 0, 0, Math.PI * 2);
1120
- ctx.stroke();
521
+ const c = z(h);
522
+ t.strokeStyle = c.color, t.lineWidth = D(c.widthPt, e), h.backgroundColor && (t.fillStyle = h.backgroundColor, t.beginPath(), t.ellipse(a + s / 2, o + d / 2, s / 2, d / 2, 0, 0, Math.PI * 2), t.fill()), t.beginPath(), t.ellipse(a + s / 2, o + d / 2, s / 2, d / 2, 0, 0, Math.PI * 2), t.stroke();
1121
523
  break;
1122
524
  }
1123
525
  }
1124
526
  }
1125
- function renderPlanToCanvas(plan, options = {}) {
1126
- const dpr = options.dpr ?? (typeof devicePixelRatio === "number" ? devicePixelRatio : 1);
1127
- const dpi = options.dpi ?? 96;
1128
- const pxPerMm = dpi / 96 * PX_PER_MM_BASE;
1129
- const fontFamily = options.fontFamily ?? '"Microsoft YaHei", sans-serif';
1130
- const measurer = options.measurer ?? heuristicMeasurer;
1131
- const start = Math.max(0, options.start ?? 0);
1132
- const end = Math.min(plan.pages.length - 1, options.end ?? plan.pages.length - 1);
1133
- const canvases = [];
1134
- for (let i = start; i <= end; i++) {
1135
- const page = plan.pages[i];
1136
- const { canvas, ctx } = createPageCanvas(page, dpr, dpi);
1137
- for (const comp of page.components) {
1138
- drawComponent(ctx, comp, pxPerMm, dpi, fontFamily, measurer);
1139
- }
1140
- canvases.push(canvas);
1141
- }
1142
- return { canvases };
1143
- }
1144
- function createCanvasPager(plan, options = {}) {
1145
- const dpr = options.dpr ?? (typeof devicePixelRatio === "number" ? devicePixelRatio : 1);
1146
- const dpi = options.dpi ?? 96;
1147
- const pxPerMm = dpi / 96 * PX_PER_MM_BASE;
1148
- const fontFamily = options.fontFamily ?? '"Microsoft YaHei", sans-serif';
1149
- const measurer = options.measurer ?? heuristicMeasurer;
1150
- const overscan = options.overscan ?? 1;
1151
- const gapPx = options.gapPx ?? 18;
1152
- const pagesPerFrame = options.pagesPerFrame ?? 1;
1153
- const pageHeightsPx = plan.pages.map((p) => p.pageHeightMm * pxPerMm);
1154
- const maxPageWidthPx = Math.max(1, ...plan.pages.map((p) => p.pageWidthMm * pxPerMm));
1155
- const windowState = { start: 0, end: -1 };
1156
- let viewport = null;
1157
- let contentEl = null;
1158
- let topSpacer = null;
1159
- let bottomSpacer = null;
1160
- let slots = [];
1161
- let raf = 0;
1162
- let queued = [];
1163
- function ensureLayout() {
1164
- const vp = viewport;
1165
- vp.innerHTML = "";
1166
- contentEl = document.createElement("div");
1167
- contentEl.style.cssText = `width:${maxPageWidthPx}px;margin:0 auto;`;
1168
- topSpacer = document.createElement("div");
1169
- bottomSpacer = document.createElement("div");
1170
- contentEl.appendChild(topSpacer);
1171
- slots = [];
1172
- const slotCount = Math.min(plan.pages.length, 3 + overscan * 2);
1173
- for (let i = 0; i < slotCount; i++) {
1174
- const slot = document.createElement("div");
1175
- slot.style.cssText = `margin:0 auto ${gapPx}px;box-shadow:0 2px 8px rgba(0,0,0,.35);background:#fff;`;
1176
- contentEl.appendChild(slot);
1177
- slots.push(slot);
1178
- }
1179
- contentEl.appendChild(bottomSpacer);
1180
- vp.appendChild(contentEl);
1181
- }
1182
- function drawPageInto(slot, pageIndex) {
1183
- const page = plan.pages[pageIndex];
1184
- const { widthPx: w, heightPx: h } = measurePageSizePx(page, dpi);
1185
- let canvas = slot.firstElementChild;
1186
- if (!canvas || canvas.tagName !== "CANVAS") {
1187
- canvas = document.createElement("canvas");
1188
- slot.innerHTML = "";
1189
- slot.appendChild(canvas);
1190
- }
1191
- canvas.width = Math.round(w * dpr);
1192
- canvas.height = Math.round(h * dpr);
1193
- canvas.style.width = `${w}px`;
1194
- canvas.style.height = `${h}px`;
1195
- const ctx = canvas.getContext("2d");
1196
- if (!ctx) return;
1197
- ctx.setTransform(1, 0, 0, 1, 0, 0);
1198
- ctx.scale(dpr, dpr);
1199
- ctx.fillStyle = "#ffffff";
1200
- ctx.fillRect(0, 0, w, h);
1201
- for (const comp of page.components) {
1202
- drawComponent(ctx, comp, pxPerMm, dpi, fontFamily, measurer);
1203
- }
1204
- canvas.dataset.canvasPage = String(pageIndex);
1205
- slot.style.height = `${h}px`;
1206
- slot.style.width = `${w}px`;
1207
- }
1208
- function applyWindow(win) {
1209
- windowState.start = win.start;
1210
- windowState.end = win.end;
1211
- topSpacer.style.height = `${win.start * gapPx + pageHeightsPx.slice(0, win.start).reduce((s, h) => s + h, 0)}px`;
1212
- const below = plan.pages.length - 1 - win.end;
1213
- bottomSpacer.style.height = `${below * gapPx + pageHeightsPx.slice(win.end + 1).reduce((s, h) => s + h, 0)}px`;
1214
- const used = win.end - win.start + 1;
1215
- slots.forEach((slot, i) => {
1216
- if (i < used) {
1217
- slot.style.display = "";
1218
- const pageIndex = win.start + i;
1219
- slot.style.height = `${pageHeightsPx[pageIndex] ?? 0}px`;
1220
- } else {
1221
- slot.style.display = "none";
1222
- }
1223
- });
1224
- queued = [];
1225
- for (let i = win.start; i <= win.end; i++) {
1226
- const slot = slots[i - win.start];
1227
- if (!slot) continue;
1228
- const already = slot.firstElementChild;
1229
- if (already?.dataset?.canvasPage !== String(i)) queued.push(i);
1230
- }
1231
- scheduleFrame();
1232
- }
1233
- function scheduleFrame() {
1234
- if (raf || queued.length === 0) return;
1235
- raf = requestAnimationFrame(() => {
1236
- raf = 0;
1237
- let budget = Math.max(1, pagesPerFrame);
1238
- while (queued.length > 0 && budget-- > 0) {
1239
- const pageIndex = queued.shift();
1240
- const slot = slots[pageIndex - windowState.start];
1241
- if (slot) drawPageInto(slot, pageIndex);
527
+ function Dt(t, n = {}) {
528
+ const i = n.dpr ?? (typeof devicePixelRatio == "number" ? devicePixelRatio : 1), e = n.dpi ?? 96, r = e / 96 * q, l = n.fontFamily ?? '"Microsoft YaHei", sans-serif', a = n.measurer ?? V, o = Math.max(0, n.start ?? 0), s = Math.min(t.pages.length - 1, n.end ?? t.pages.length - 1), d = [];
529
+ for (let h = o; h <= s; h++) {
530
+ const c = t.pages[h], { canvas: m, ctx: f } = Pt(c, i, e);
531
+ for (const g of c.components)
532
+ rt(f, g, r, e, l, a);
533
+ d.push(m);
534
+ }
535
+ return { canvases: d };
536
+ }
537
+ function jt(t, n = {}) {
538
+ const i = n.dpr ?? (typeof devicePixelRatio == "number" ? devicePixelRatio : 1), e = n.dpi ?? 96, r = e / 96 * q, l = n.fontFamily ?? '"Microsoft YaHei", sans-serif', a = n.measurer ?? V, o = n.overscan ?? 1, s = n.gapPx ?? 18, d = n.pagesPerFrame ?? 1, h = t.pages.map((u) => u.pageHeightMm * r), c = Math.max(1, ...t.pages.map((u) => u.pageWidthMm * r)), m = { start: 0, end: -1 };
539
+ let f = null, g = null, b = null, p = null, C = [], v = 0, E = [];
540
+ function w() {
541
+ const u = f;
542
+ u.innerHTML = "", g = document.createElement("div"), g.style.cssText = `width:${c}px;margin:0 auto;`, b = document.createElement("div"), p = document.createElement("div"), g.appendChild(b), C = [];
543
+ const y = Math.min(t.pages.length, 3 + o * 2);
544
+ for (let S = 0; S < y; S++) {
545
+ const M = document.createElement("div");
546
+ M.style.cssText = `margin:0 auto ${s}px;box-shadow:0 2px 8px rgba(0,0,0,.35);background:#fff;`, g.appendChild(M), C.push(M);
547
+ }
548
+ g.appendChild(p), u.appendChild(g);
549
+ }
550
+ function W(u, y) {
551
+ const S = t.pages[y], { widthPx: M, heightPx: P } = nt(S, e);
552
+ let A = u.firstElementChild;
553
+ (!A || A.tagName !== "CANVAS") && (A = document.createElement("canvas"), u.innerHTML = "", u.appendChild(A)), A.width = Math.round(M * i), A.height = Math.round(P * i), A.style.width = `${M}px`, A.style.height = `${P}px`;
554
+ const N = A.getContext("2d");
555
+ if (N) {
556
+ N.setTransform(1, 0, 0, 1, 0, 0), N.scale(i, i), N.fillStyle = "#ffffff", N.fillRect(0, 0, M, P);
557
+ for (const ot of S.components)
558
+ rt(N, ot, r, e, l, a);
559
+ A.dataset.canvasPage = String(y), u.style.height = `${P}px`, u.style.width = `${M}px`;
560
+ }
561
+ }
562
+ function R(u) {
563
+ m.start = u.start, m.end = u.end, b.style.height = `${u.start * s + h.slice(0, u.start).reduce((M, P) => M + P, 0)}px`;
564
+ const y = t.pages.length - 1 - u.end;
565
+ p.style.height = `${y * s + h.slice(u.end + 1).reduce((M, P) => M + P, 0)}px`;
566
+ const S = u.end - u.start + 1;
567
+ C.forEach((M, P) => {
568
+ if (P < S) {
569
+ M.style.display = "";
570
+ const A = u.start + P;
571
+ M.style.height = `${h[A] ?? 0}px`;
572
+ } else
573
+ M.style.display = "none";
574
+ }), E = [];
575
+ for (let M = u.start; M <= u.end; M++) {
576
+ const P = C[M - u.start];
577
+ if (!P) continue;
578
+ P.firstElementChild?.dataset?.canvasPage !== String(M) && E.push(M);
579
+ }
580
+ I();
581
+ }
582
+ function I() {
583
+ v || E.length === 0 || (v = requestAnimationFrame(() => {
584
+ v = 0;
585
+ let u = Math.max(1, d);
586
+ for (; E.length > 0 && u-- > 0; ) {
587
+ const y = E.shift(), S = C[y - m.start];
588
+ S && W(S, y);
1242
589
  }
1243
- if (queued.length > 0) scheduleFrame();
1244
- });
1245
- }
1246
- function onScroll() {
1247
- if (raf) return;
1248
- raf = requestAnimationFrame(() => {
1249
- raf = 0;
1250
- const vp = viewport;
1251
- const win = computePageWindow({
1252
- pageHeightsPx,
1253
- viewportHeightPx: vp.clientHeight,
1254
- scrollTopPx: vp.scrollTop,
1255
- overscan,
1256
- gapPx
590
+ E.length > 0 && I();
591
+ }));
592
+ }
593
+ function H() {
594
+ v || (v = requestAnimationFrame(() => {
595
+ v = 0;
596
+ const u = f, y = Ct({
597
+ pageHeightsPx: h,
598
+ viewportHeightPx: u.clientHeight,
599
+ scrollTopPx: u.scrollTop,
600
+ overscan: o,
601
+ gapPx: s
1257
602
  });
1258
- if (win.start !== windowState.start || win.end !== windowState.end) {
1259
- applyWindow(win);
1260
- } else {
1261
- scheduleFrame();
1262
- }
1263
- });
603
+ y.start !== m.start || y.end !== m.end ? R(y) : I();
604
+ }));
1264
605
  }
1265
606
  return {
1266
- attach(vp) {
1267
- viewport = vp;
1268
- ensureLayout();
1269
- vp.addEventListener("scroll", onScroll, { passive: true });
1270
- onScroll();
607
+ attach(u) {
608
+ f = u, w(), u.addEventListener("scroll", H, { passive: !0 }), H();
1271
609
  },
1272
610
  destroy() {
1273
- if (raf) cancelAnimationFrame(raf);
1274
- raf = 0;
1275
- viewport?.removeEventListener("scroll", onScroll);
1276
- queued = [];
1277
- contentEl?.remove();
1278
- viewport = null;
611
+ v && cancelAnimationFrame(v), v = 0, f?.removeEventListener("scroll", H), E = [], g?.remove(), f = null;
1279
612
  },
1280
613
  window() {
1281
- return { ...windowState };
614
+ return { ...m };
1282
615
  }
1283
616
  };
1284
617
  }
1285
-
1286
- // src/compat/jh4j-template.ts
1287
- function num(v, fallback) {
1288
- return typeof v === "number" && Number.isFinite(v) ? v : fallback;
618
+ function T(t, n) {
619
+ return typeof t == "number" && Number.isFinite(t) ? t : n;
1289
620
  }
1290
- function str(v, fallback = "") {
1291
- return typeof v === "string" ? v : fallback;
621
+ function k(t, n = "") {
622
+ return typeof t == "string" ? t : n;
1292
623
  }
1293
- function isRaw(v) {
1294
- return typeof v === "object" && v !== null && !Array.isArray(v);
624
+ function B(t) {
625
+ return typeof t == "object" && t !== null && !Array.isArray(t);
1295
626
  }
1296
- function mapAlign(h) {
1297
- if (h === "Center") return "center";
1298
- if (h === "Right") return "right";
1299
- return "left";
627
+ function Et(t) {
628
+ return t === "Center" ? "center" : t === "Right" ? "right" : "left";
1300
629
  }
1301
- function mapVAlign(v) {
1302
- if (v === "Center") return "middle";
1303
- if (v === "Bottom") return "bottom";
1304
- return "top";
630
+ function $t(t) {
631
+ return t === "Center" ? "middle" : t === "Bottom" ? "bottom" : "top";
1305
632
  }
1306
- function baseStyle(node) {
1307
- const fontSize = parseFloat(str(node["FontSize"], "10.5"));
633
+ function Ht(t) {
634
+ const n = parseFloat(k(t.FontSize, "10.5"));
1308
635
  return {
1309
- fontSize: Number.isFinite(fontSize) ? fontSize : 10.5,
1310
- fontFamily: str(node["FontFamily"], "\u9ED1\u4F53") || void 0,
1311
- bold: str(node["FontWeight"]) === "bold" || void 0,
1312
- italic: str(node["FontStyle"]) === "italic" || void 0,
1313
- underline: node["Underline"] === true || void 0,
1314
- color: str(node["FontColor"]) || void 0,
1315
- backgroundColor: str(node["BackgroundColor"]) || void 0,
1316
- align: mapAlign(str(node["HorAlignment"], "Left")),
1317
- verticalAlign: mapVAlign(str(node["VertAlignment"], "Top")),
636
+ fontSize: Number.isFinite(n) ? n : 10.5,
637
+ fontFamily: k(t.FontFamily, "黑体") || void 0,
638
+ bold: k(t.FontWeight) === "bold" || void 0,
639
+ italic: k(t.FontStyle) === "italic" || void 0,
640
+ underline: t.Underline === !0 || void 0,
641
+ color: k(t.FontColor) || void 0,
642
+ backgroundColor: k(t.BackgroundColor) || void 0,
643
+ align: Et(k(t.HorAlignment, "Left")),
644
+ verticalAlign: $t(k(t.VertAlignment, "Top")),
1318
645
  lineHeight: (() => {
1319
- const lh = parseFloat(str(node["RowSpace"], "1"));
1320
- return Number.isFinite(lh) && lh !== 1 ? lh : void 0;
646
+ const i = parseFloat(k(t.RowSpace, "1"));
647
+ return Number.isFinite(i) && i !== 1 ? i : void 0;
1321
648
  })(),
1322
- borderColor: str(node["BorderColor"]) || void 0,
1323
- borderTop: node["BorderTop"] !== false,
1324
- borderRight: node["BorderRight"] !== false,
1325
- borderBottom: node["BorderBottom"] !== false,
1326
- borderLeft: node["BorderLeft"] !== false
649
+ borderColor: k(t.BorderColor) || void 0,
650
+ borderTop: t.BorderTop !== !1,
651
+ borderRight: t.BorderRight !== !1,
652
+ borderBottom: t.BorderBottom !== !1,
653
+ borderLeft: t.BorderLeft !== !1
1327
654
  };
1328
655
  }
1329
- function convertElement(node, warnings) {
1330
- const uitype = str(node["uitype"]);
1331
- const comp = {
656
+ function Rt(t, n) {
657
+ const i = k(t.uitype), e = {
1332
658
  kind: "text",
1333
- leftMm: num(node["left"], 0),
1334
- topMm: num(node["top"], 0),
1335
- widthMm: num(node["width"], 40),
1336
- heightMm: num(node["height"], 8),
1337
- nid: str(node["nid"]) || void 0,
1338
- style: baseStyle(node)
659
+ leftMm: T(t.left, 0),
660
+ topMm: T(t.top, 0),
661
+ widthMm: T(t.width, 40),
662
+ heightMm: T(t.height, 8),
663
+ nid: k(t.nid) || void 0,
664
+ style: Ht(t)
1339
665
  };
1340
- switch (uitype) {
666
+ switch (i) {
1341
667
  case "text": {
1342
- comp.kind = "text";
1343
- const text = node["Text"] ?? node["text"] ?? node["Value"];
1344
- comp.text = text == null ? "" : String(text);
1345
- const lines = node["Lines"] ?? node["lines"];
1346
- if (Array.isArray(lines)) {
1347
- comp.lines = lines.map((l) => String(l));
1348
- }
1349
- return comp;
668
+ e.kind = "text";
669
+ const r = t.Text ?? t.text ?? t.Value;
670
+ e.text = r == null ? "" : String(r);
671
+ const l = t.Lines ?? t.lines;
672
+ return Array.isArray(l) && (e.lines = l.map((a) => String(a))), e;
1350
673
  }
1351
674
  case "richtext":
1352
- comp.kind = "text";
1353
- comp.text = str(node["Text"]);
1354
- warnings.push(`\u5BCC\u6587\u672C ${comp.nid ?? ""} \u5BFC\u5165\u4E3A\u7EAF\u6587\u672C\uFF08\u7248\u5F0F\u7EC6\u8282\u53EF\u80FD\u635F\u5931\uFF09`);
1355
- return comp;
675
+ return e.kind = "text", e.text = k(t.Text), n.push(`富文本 ${e.nid ?? ""} 导入为纯文本(版式细节可能损失)`), e;
1356
676
  case "image":
1357
677
  case "barcode":
1358
678
  case "qrcode":
1359
679
  case "chart":
1360
- comp.kind = uitype === "image" ? "image" : uitype;
1361
- comp.fallbackText = `[${uitype}]`;
1362
- warnings.push(`\u56FE\u7247\u7C7B\u7EC4\u4EF6 ${comp.nid ?? ""} \u9700\u8FD0\u884C\u65F6\u6570\u636E\uFF08imageData\uFF09\uFF0C\u5DF2\u5BFC\u5165\u4E3A\u5360\u4F4D`);
1363
- return comp;
680
+ return e.kind = i === "image" ? "image" : i, e.fallbackText = `[${i}]`, n.push(`图片类组件 ${e.nid ?? ""} 需运行时数据(imageData),已导入为占位`), e;
1364
681
  case "table": {
1365
- comp.kind = "rect";
1366
- const cellsRaw = node["Cells"] ?? node["cells"];
1367
- if (Array.isArray(cellsRaw)) {
1368
- const grid = {
1369
- cells: cellsRaw.map(
1370
- (row) => Array.isArray(row) ? row.map((cell) => ({
1371
- text: isRaw(cell) ? str(cell["Text"] ?? cell["text"]) : "",
1372
- colSpan: isRaw(cell) ? num(cell["ColSpan"], 1) : 1
682
+ e.kind = "rect";
683
+ const r = t.Cells ?? t.cells;
684
+ if (Array.isArray(r)) {
685
+ const l = {
686
+ cells: r.map(
687
+ (a) => Array.isArray(a) ? a.map((o) => ({
688
+ text: B(o) ? k(o.Text ?? o.text) : "",
689
+ colSpan: B(o) ? T(o.ColSpan, 1) : 1
1373
690
  })) : []
1374
691
  )
1375
692
  };
1376
- comp.grid = grid;
1377
- } else {
1378
- comp.fallbackText = "[table]";
1379
- warnings.push(`\u8868\u683C ${comp.nid ?? ""} \u7F3A\u5C11 Cells\uFF0C\u5BFC\u5165\u4E3A\u7A7A\u6846`);
1380
- }
1381
- return comp;
693
+ e.grid = l;
694
+ } else
695
+ e.fallbackText = "[table]", n.push(`表格 ${e.nid ?? ""} 缺少 Cells,导入为空框`);
696
+ return e;
1382
697
  }
1383
698
  case "subreport":
1384
- warnings.push(`\u5B50\u62A5\u8868 ${comp.nid ?? ""} \u6682\u4E0D\u652F\u6301\u5BFC\u5165\uFF0C\u5DF2\u8DF3\u8FC7`);
1385
- return null;
1386
- default: {
1387
- if (str(node["ShapeType"]) === "hline" || uitype === "hline") {
1388
- comp.kind = "line";
1389
- return comp;
1390
- }
1391
- if (uitype === "vline") {
1392
- comp.kind = "line";
1393
- return comp;
1394
- }
1395
- if (uitype === "rect" || uitype === "oval" || uitype === "shape") {
1396
- comp.kind = uitype === "oval" ? "ellipse" : "rect";
1397
- return comp;
1398
- }
1399
- warnings.push(`\u672A\u77E5\u7EC4\u4EF6\u7C7B\u578B ${uitype}\uFF0C\u5DF2\u8DF3\u8FC7`);
1400
- return null;
1401
- }
699
+ return n.push(`子报表 ${e.nid ?? ""} 暂不支持导入,已跳过`), null;
700
+ default:
701
+ return k(t.ShapeType) === "hline" || i === "hline" || i === "vline" ? (e.kind = "line", e) : i === "rect" || i === "oval" || i === "shape" ? (e.kind = i === "oval" ? "ellipse" : "rect", e) : (n.push(`未知组件类型 ${i},已跳过`), null);
1402
702
  }
1403
703
  }
1404
- function importJh4jTemplateContent(content) {
1405
- const warnings = [];
1406
- let root = null;
1407
- if (typeof content === "string") {
704
+ function Ot(t) {
705
+ const n = [];
706
+ let i = null;
707
+ if (typeof t == "string")
1408
708
  try {
1409
- const parsed = JSON.parse(content);
1410
- if (isRaw(parsed)) root = parsed;
709
+ const d = JSON.parse(t);
710
+ B(d) && (i = d);
1411
711
  } catch {
1412
712
  return {
1413
713
  template: { pages: [] },
1414
- warnings: ["content \u4E0D\u662F\u5408\u6CD5 JSON"]
714
+ warnings: ["content 不是合法 JSON"]
1415
715
  };
1416
716
  }
1417
- } else if (isRaw(content)) {
1418
- root = content;
1419
- }
1420
- if (!root) {
1421
- return { template: { pages: [] }, warnings: ["content \u4E3A\u7A7A"] };
1422
- }
1423
- const globalConfig = isRaw(root["GlobalConfig"]) ? root["GlobalConfig"] : {};
1424
- const defaultWidth = num(globalConfig["paperWidthMm"], 210);
1425
- const defaultHeight = num(globalConfig["paperHeightMm"], 297);
1426
- const defaultMargins = {
1427
- top: num(globalConfig["marginTop"], 10),
1428
- bottom: num(globalConfig["marginBottom"], 10),
1429
- left: num(globalConfig["marginLeft"], 10),
1430
- right: num(globalConfig["marginRight"], 10)
1431
- };
1432
- const pageNodes = Array.isArray(root["children"]) ? root["children"].filter((c) => isRaw(c) && str(c["uitype"]) === "page") : [];
1433
- if (pageNodes.length === 0) {
1434
- warnings.push("content \u4E2D\u6CA1\u6709 uitype=page \u7684\u9875\u8282\u70B9");
1435
- }
1436
- const pages = pageNodes.map((raw) => {
1437
- const node = raw;
1438
- const elements = Array.isArray(node["children"]) ? node["children"] : [];
1439
- const components = [];
1440
- for (const el of elements) {
1441
- if (!isRaw(el)) continue;
1442
- const converted = convertElement(el, warnings);
1443
- if (converted) components.push(converted);
717
+ else B(t) && (i = t);
718
+ if (!i)
719
+ return { template: { pages: [] }, warnings: ["content 为空"] };
720
+ const e = B(i.GlobalConfig) ? i.GlobalConfig : {}, r = T(e.paperWidthMm, 210), l = T(e.paperHeightMm, 297), a = {
721
+ top: T(e.marginTop, 10),
722
+ bottom: T(e.marginBottom, 10),
723
+ left: T(e.marginLeft, 10),
724
+ right: T(e.marginRight, 10)
725
+ }, o = Array.isArray(i.children) ? i.children.filter((d) => B(d) && k(d.uitype) === "page") : [];
726
+ o.length === 0 && n.push("content 中没有 uitype=page 的页节点");
727
+ const s = o.map((d) => {
728
+ const h = d, c = Array.isArray(h.children) ? h.children : [], m = [];
729
+ for (const f of c) {
730
+ if (!B(f)) continue;
731
+ const g = Rt(f, n);
732
+ g && m.push(g);
1444
733
  }
1445
734
  return {
1446
- widthMm: num(node["width"], defaultWidth),
1447
- heightMm: num(node["DesignHeight"], defaultHeight),
1448
- marginTopMm: num(node["MarginTop"], defaultMargins.top),
1449
- marginBottomMm: num(node["MarginBottom"], defaultMargins.bottom),
1450
- marginLeftMm: num(node["MarginLeft"], defaultMargins.left),
1451
- marginRightMm: num(node["MarginRight"], defaultMargins.right),
1452
- components
735
+ widthMm: T(h.width, r),
736
+ heightMm: T(h.DesignHeight, l),
737
+ marginTopMm: T(h.MarginTop, a.top),
738
+ marginBottomMm: T(h.MarginBottom, a.bottom),
739
+ marginLeftMm: T(h.MarginLeft, a.left),
740
+ marginRightMm: T(h.MarginRight, a.right),
741
+ components: m
1453
742
  };
1454
743
  });
1455
- if (pages.length === 0) {
1456
- warnings.push("\u8F6C\u6362\u7ED3\u679C\u4E3A\u7A7A\u9875\uFF0C\u5DF2\u56DE\u9000\u4E00\u5F20\u7A7A\u767D\u9875");
1457
- pages.push({
1458
- widthMm: defaultWidth,
1459
- heightMm: defaultHeight,
1460
- ...defaultMargins,
1461
- components: []
1462
- });
1463
- }
1464
- return { template: { pages }, warnings };
1465
- }
1466
-
1467
- // src/builder/template-builder.ts
1468
- function resolvePaper(paper, heightArg, landscape) {
1469
- let widthMm;
1470
- let heightMm;
1471
- if (typeof paper === "string") {
1472
- const preset = PAPER_SIZES[paper];
1473
- if (!preset) throw new Error(`\u672A\u77E5\u7EB8\u5F20\u9884\u8BBE "${paper}"\uFF08\u53EF\u7528\uFF1A${Object.keys(PAPER_SIZES).join("/")}\uFF09`);
1474
- widthMm = preset.widthMm;
1475
- heightMm = preset.heightMm;
1476
- } else if (typeof paper === "number") {
1477
- widthMm = paper;
1478
- heightMm = heightArg ?? 297;
1479
- } else {
1480
- widthMm = paper.widthMm;
1481
- heightMm = paper.heightMm;
1482
- }
1483
- return landscape ? { widthMm: heightMm, heightMm: widthMm } : { widthMm, heightMm };
1484
- }
1485
- var TemplateBuilder = class {
744
+ return s.length === 0 && (n.push("转换结果为空页,已回退一张空白页"), s.push({
745
+ widthMm: r,
746
+ heightMm: l,
747
+ ...a,
748
+ components: []
749
+ })), { template: { pages: s }, warnings: n };
750
+ }
751
+ function Bt(t, n, i) {
752
+ let e, r;
753
+ if (typeof t == "string") {
754
+ const l = U[t];
755
+ if (!l) throw new Error(`未知纸张预设 "${t}"(可用:${Object.keys(U).join("/")})`);
756
+ e = l.widthMm, r = l.heightMm;
757
+ } else typeof t == "number" ? (e = t, r = n ?? 297) : (e = t.widthMm, r = t.heightMm);
758
+ return i ? { widthMm: r, heightMm: e } : { widthMm: e, heightMm: r };
759
+ }
760
+ class Nt {
1486
761
  constructor() {
1487
- this.pages = [];
1488
- this.pending = null;
762
+ this.pages = [], this.pending = null;
1489
763
  }
1490
764
  /**
1491
765
  * 新建页。纸张支持三种写法:
@@ -1493,106 +767,89 @@ var TemplateBuilder = class {
1493
767
  * - 数字:.page(210, 297)(第三参数兼容旧 margins 对象或新 options)
1494
768
  * - 对象:.page({ widthMm: 210, heightMm: 297 })
1495
769
  */
1496
- page(paper = "a4", optionsOrHeight = {}, maybeOptions) {
770
+ page(n = "a4", i = {}, e) {
1497
771
  this.collect();
1498
- const legacyMargins = maybeOptions != null && !("margins" in maybeOptions) && !("landscape" in maybeOptions) && ("marginTopMm" in maybeOptions || "marginBottomMm" in maybeOptions || "marginLeftMm" in maybeOptions || "marginRightMm" in maybeOptions);
1499
- const options = legacyMargins ? { margins: maybeOptions } : maybeOptions ?? {};
1500
- const { widthMm, heightMm } = resolvePaper(
1501
- paper,
1502
- typeof optionsOrHeight === "number" ? optionsOrHeight : void 0,
1503
- options.landscape
1504
- );
1505
- const margins = options.margins ?? {};
1506
- this.pending = new PageBuilder(this, {
1507
- widthMm,
1508
- heightMm,
1509
- marginTopMm: margins.marginTopMm ?? 10,
1510
- marginBottomMm: margins.marginBottomMm ?? 10,
1511
- marginLeftMm: margins.marginLeftMm ?? 10,
1512
- marginRightMm: margins.marginRightMm ?? 10
1513
- });
1514
- return this.pending;
772
+ const l = e != null && !("margins" in e) && !("landscape" in e) && ("marginTopMm" in e || "marginBottomMm" in e || "marginLeftMm" in e || "marginRightMm" in e) ? { margins: e } : e ?? {}, { widthMm: a, heightMm: o } = Bt(
773
+ n,
774
+ typeof i == "number" ? i : void 0,
775
+ l.landscape
776
+ ), s = l.margins ?? {};
777
+ return this.pending = new Lt(this, {
778
+ widthMm: a,
779
+ heightMm: o,
780
+ marginTopMm: s.marginTopMm ?? 10,
781
+ marginBottomMm: s.marginBottomMm ?? 10,
782
+ marginLeftMm: s.marginLeftMm ?? 10,
783
+ marginRightMm: s.marginRightMm ?? 10
784
+ }), this.pending;
1515
785
  }
1516
786
  collect() {
1517
- if (this.pending) {
1518
- this.pages.push(this.pending.buildPage());
1519
- this.pending = null;
1520
- }
787
+ this.pending && (this.pages.push(this.pending.buildPage()), this.pending = null);
1521
788
  }
1522
789
  build() {
1523
- this.collect();
1524
- if (this.pages.length === 0) {
1525
- throw new Error("\u6A21\u677F\u81F3\u5C11\u9700\u8981\u4E00\u9875\uFF1A\u5148\u8C03\u7528 .page() \u6DFB\u52A0\u5185\u5BB9");
1526
- }
790
+ if (this.collect(), this.pages.length === 0)
791
+ throw new Error("模板至少需要一页:先调用 .page() 添加内容");
1527
792
  return { pages: this.pages };
1528
793
  }
1529
- };
1530
- var PageBuilder = class {
1531
- constructor(parent, page) {
1532
- this.parent = parent;
1533
- this.page = page;
1534
- this.components = [];
794
+ }
795
+ class Lt {
796
+ constructor(n, i) {
797
+ this.parent = n, this.page = i, this.components = [];
1535
798
  }
1536
- text(content, geometry = {}, style = {}) {
1537
- this.components.push({
799
+ text(n, i = {}, e = {}) {
800
+ return this.components.push({
1538
801
  kind: "text",
1539
- leftMm: geometry.leftMm ?? 0,
1540
- topMm: geometry.topMm ?? 0,
1541
- widthMm: geometry.widthMm ?? 60,
1542
- heightMm: geometry.heightMm ?? 8,
1543
- text: content,
1544
- style
1545
- });
1546
- return this;
1547
- }
1548
- list(dataset, geometry, columns, options = {}) {
1549
- this.components.push({
802
+ leftMm: i.leftMm ?? 0,
803
+ topMm: i.topMm ?? 0,
804
+ widthMm: i.widthMm ?? 60,
805
+ heightMm: i.heightMm ?? 8,
806
+ text: n,
807
+ style: e
808
+ }), this;
809
+ }
810
+ list(n, i, e, r = {}) {
811
+ return this.components.push({
1550
812
  kind: "list",
1551
- leftMm: geometry.leftMm ?? 10,
1552
- topMm: geometry.topMm ?? 30,
1553
- widthMm: geometry.widthMm ?? 180,
1554
- dataset,
1555
- columns,
1556
- ...options
1557
- });
1558
- return this;
1559
- }
1560
- rect(geometry, style = {}) {
1561
- this.components.push({ kind: "rect", ...geometry, style });
1562
- return this;
1563
- }
1564
- line(leftMm, topMm, widthMm, style = {}) {
1565
- this.components.push({
813
+ leftMm: i.leftMm ?? 10,
814
+ topMm: i.topMm ?? 30,
815
+ widthMm: i.widthMm ?? 180,
816
+ dataset: n,
817
+ columns: e,
818
+ ...r
819
+ }), this;
820
+ }
821
+ rect(n, i = {}) {
822
+ return this.components.push({ kind: "rect", ...n, style: i }), this;
823
+ }
824
+ line(n, i, e, r = {}) {
825
+ return this.components.push({
1566
826
  kind: "line",
1567
- leftMm,
1568
- topMm,
1569
- widthMm,
827
+ leftMm: n,
828
+ topMm: i,
829
+ widthMm: e,
1570
830
  heightMm: 0.5,
1571
- style
1572
- });
1573
- return this;
831
+ style: r
832
+ }), this;
1574
833
  }
1575
- barcode(content, geometry) {
1576
- this.components.push({
834
+ barcode(n, i) {
835
+ return this.components.push({
1577
836
  kind: "barcode",
1578
- leftMm: geometry.leftMm ?? 0,
1579
- topMm: geometry.topMm ?? 0,
1580
- widthMm: geometry.widthMm ?? 40,
1581
- heightMm: geometry.heightMm ?? 12,
1582
- fallbackText: content
1583
- });
1584
- return this;
1585
- }
1586
- qrcode(content, sizeMm, leftMm, topMm) {
1587
- this.components.push({
837
+ leftMm: i.leftMm ?? 0,
838
+ topMm: i.topMm ?? 0,
839
+ widthMm: i.widthMm ?? 40,
840
+ heightMm: i.heightMm ?? 12,
841
+ fallbackText: n
842
+ }), this;
843
+ }
844
+ qrcode(n, i, e, r) {
845
+ return this.components.push({
1588
846
  kind: "qrcode",
1589
- leftMm,
1590
- topMm,
1591
- widthMm: sizeMm,
1592
- heightMm: sizeMm,
1593
- fallbackText: content
1594
- });
1595
- return this;
847
+ leftMm: e,
848
+ topMm: r,
849
+ widthMm: i,
850
+ heightMm: i,
851
+ fallbackText: n
852
+ }), this;
1596
853
  }
1597
854
  buildPage() {
1598
855
  return { ...this.page, components: this.components };
@@ -1603,9 +860,60 @@ var PageBuilder = class {
1603
860
  build() {
1604
861
  return this.done().build();
1605
862
  }
1606
- };
1607
- function createTemplate() {
1608
- return new TemplateBuilder();
1609
863
  }
1610
-
1611
- export { CSS_DPI, DEFAULT_BORDER_PT, DEFAULT_FONT_PT, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, LINE_HEIGHT, MM_PER_INCH, PAPER_SIZES, PageBuilder, RENDER_PLAN_SCHEMA_VERSION, SCHEMA_VERSION_JH4J, SCHEMA_VERSION_LOCAL, SCHEMA_VERSION_MACH, TemplateBuilder, assertRenderPlan, charWidthEm, classOf, computePageWindow, createCanvasMeasurer, createCanvasPager, createHeuristicMeasurer, createTemplate, heuristicMeasurer, importJh4jTemplateContent, isImageBackedComponent, isRichText, measurePageSizePx, measureTextMm, mmToPx, mmToPxFactor, paginateTemplate, planFontSizePx, ptToPx, pxToMm, renderComponent, renderPage, renderPlan, renderPlanToCanvas, resolveBoxBorders, resolveFontSize, resolveGridLayout, resolveLineHeight, resolvePaper, resolveStroke, resolveTextColor, round, toRenderPlan, validateComponent, validatePage, validateRenderPlan, wrapText };
864
+ function Gt() {
865
+ return new Nt();
866
+ }
867
+ export {
868
+ qt as CSS_DPI,
869
+ Ut as DEFAULT_BORDER_PT,
870
+ j as DEFAULT_FONT_PT,
871
+ Kt as DEFAULT_STROKE_COLOR,
872
+ ct as DEFAULT_TEXT_COLOR,
873
+ J as LINE_HEIGHT,
874
+ Yt as MM_PER_INCH,
875
+ U as PAPER_SIZES,
876
+ Lt as PageBuilder,
877
+ at as RENDER_PLAN_SCHEMA_VERSION,
878
+ Xt as SCHEMA_VERSION_JH4J,
879
+ Zt as SCHEMA_VERSION_LOCAL,
880
+ Qt as SCHEMA_VERSION_MACH,
881
+ Nt as TemplateBuilder,
882
+ Ft as assertRenderPlan,
883
+ te as charWidthEm,
884
+ x as classOf,
885
+ Ct as computePageWindow,
886
+ ee as createCanvasMeasurer,
887
+ jt as createCanvasPager,
888
+ ne as createHeuristicMeasurer,
889
+ Gt as createTemplate,
890
+ V as heuristicMeasurer,
891
+ Ot as importJh4jTemplateContent,
892
+ st as isImageBackedComponent,
893
+ X as isRichText,
894
+ nt as measurePageSizePx,
895
+ ie as measureTextMm,
896
+ lt as mmToPx,
897
+ re as mmToPxFactor,
898
+ _t as paginateTemplate,
899
+ It as planFontSizePx,
900
+ D as ptToPx,
901
+ oe as pxToMm,
902
+ et as renderComponent,
903
+ xt as renderPage,
904
+ Wt as renderPlan,
905
+ Dt as renderPlanToCanvas,
906
+ G as resolveBoxBorders,
907
+ _ as resolveFontSize,
908
+ ht as resolveGridLayout,
909
+ dt as resolveLineHeight,
910
+ Bt as resolvePaper,
911
+ z as resolveStroke,
912
+ Z as resolveTextColor,
913
+ F as round,
914
+ ae as toRenderPlan,
915
+ Q as validateComponent,
916
+ ft as validatePage,
917
+ ut as validateRenderPlan,
918
+ O as wrapText
919
+ };