@agile-team/mach-report 0.4.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 (85) hide show
  1. package/dist/builder/template-builder.d.ts +53 -0
  2. package/dist/builder/template-builder.js +153 -0
  3. package/dist/builder/template-builder.js.map +1 -0
  4. package/dist/compat/jh4j-template.d.ts +12 -0
  5. package/dist/compat/jh4j-template.js +196 -0
  6. package/dist/compat/jh4j-template.js.map +1 -0
  7. package/dist/defaults.d.ts +27 -0
  8. package/dist/defaults.js +28 -0
  9. package/dist/defaults.js.map +1 -0
  10. package/dist/index.d.ts +13 -0
  11. package/dist/index.js +14 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/layout/paginate.d.ts +51 -0
  14. package/dist/layout/paginate.js +197 -0
  15. package/dist/layout/paginate.js.map +1 -0
  16. package/dist/layout/textwrap.d.ts +36 -0
  17. package/dist/layout/textwrap.js +173 -0
  18. package/dist/layout/textwrap.js.map +1 -0
  19. package/dist/manager/api.d.ts +45 -0
  20. package/dist/manager/api.js +101 -0
  21. package/dist/manager/api.js.map +1 -0
  22. package/dist/manager/index.d.ts +2 -0
  23. package/dist/manager/index.js +3 -0
  24. package/dist/manager/index.js.map +1 -0
  25. package/dist/manager/types.d.ts +50 -0
  26. package/dist/manager/types.js +8 -0
  27. package/dist/manager/types.js.map +1 -0
  28. package/dist/manager.d.ts +5 -0
  29. package/dist/manager.js +6 -0
  30. package/dist/manager.js.map +1 -0
  31. package/dist/pdf/font-loader.d.ts +5 -0
  32. package/dist/pdf/font-loader.js +84 -0
  33. package/dist/pdf/font-loader.js.map +1 -0
  34. package/dist/pdf/index.d.ts +2 -0
  35. package/dist/pdf/index.js +3 -0
  36. package/dist/pdf/index.js.map +1 -0
  37. package/dist/pdf/render-pdf.d.ts +19 -0
  38. package/dist/pdf/render-pdf.js +284 -0
  39. package/dist/pdf/render-pdf.js.map +1 -0
  40. package/dist/pdf.d.ts +6 -0
  41. package/dist/pdf.js +7 -0
  42. package/dist/pdf.js.map +1 -0
  43. package/dist/render/canvas.d.ts +61 -0
  44. package/dist/render/canvas.js +402 -0
  45. package/dist/render/canvas.js.map +1 -0
  46. package/dist/render/dom.d.ts +10 -0
  47. package/dist/render/dom.js +311 -0
  48. package/dist/render/dom.js.map +1 -0
  49. package/dist/render/grid-geometry.d.ts +41 -0
  50. package/dist/render/grid-geometry.js +131 -0
  51. package/dist/render/grid-geometry.js.map +1 -0
  52. package/dist/render/style.d.ts +40 -0
  53. package/dist/render/style.js +39 -0
  54. package/dist/render/style.js.map +1 -0
  55. package/dist/render/window.d.ts +23 -0
  56. package/dist/render/window.js +58 -0
  57. package/dist/render/window.js.map +1 -0
  58. package/dist/schema/render-plan.d.ts +96 -0
  59. package/dist/schema/render-plan.js +25 -0
  60. package/dist/schema/render-plan.js.map +1 -0
  61. package/dist/schema/validate.d.ts +15 -0
  62. package/dist/schema/validate.js +129 -0
  63. package/dist/schema/validate.js.map +1 -0
  64. package/dist/sql/ast-check.d.ts +14 -0
  65. package/dist/sql/ast-check.js +44 -0
  66. package/dist/sql/ast-check.js.map +1 -0
  67. package/dist/sql/compile.d.ts +31 -0
  68. package/dist/sql/compile.js +145 -0
  69. package/dist/sql/compile.js.map +1 -0
  70. package/dist/sql/expr.d.ts +21 -0
  71. package/dist/sql/expr.js +123 -0
  72. package/dist/sql/expr.js.map +1 -0
  73. package/dist/sql/index.d.ts +4 -0
  74. package/dist/sql/index.js +5 -0
  75. package/dist/sql/index.js.map +1 -0
  76. package/dist/sql/tokenizer.d.ts +25 -0
  77. package/dist/sql/tokenizer.js +124 -0
  78. package/dist/sql/tokenizer.js.map +1 -0
  79. package/dist/sql.d.ts +5 -0
  80. package/dist/sql.js +6 -0
  81. package/dist/sql.js.map +1 -0
  82. package/dist/units.d.ts +11 -0
  83. package/dist/units.js +26 -0
  84. package/dist/units.js.map +1 -0
  85. package/package.json +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/manager/types.ts"],"names":[],"mappings":"AAqDA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe,EAAkB,GAAW;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,QAAG,GAAH,GAAG,CAAQ;QAEtD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 管理端 API 子路径入口(@agile-team/mach-report/manager):
3
+ * 模板/数据集/参数/导入导出/模板锁(接口面对齐 jh4j 逆向结果)。
4
+ */
5
+ export * from "./manager/index";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 管理端 API 子路径入口(@agile-team/mach-report/manager):
3
+ * 模板/数据集/参数/导入导出/模板锁(接口面对齐 jh4j 逆向结果)。
4
+ */
5
+ export * from "./manager/index";
6
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 字体加载(IndexedDB 持久缓存 + 内存缓存):
3
+ * 中文字体体积大(simhei ~9MB),首次 fetch 后缓存,后续导出零网络等待。
4
+ */
5
+ export declare function loadFontWithCache(url: string): Promise<Uint8Array | null>;
@@ -0,0 +1,84 @@
1
+ const DB_NAME = "mach-report-fonts";
2
+ const STORE = "fonts";
3
+ function openDb() {
4
+ return new Promise((resolve, reject) => {
5
+ const req = indexedDB.open(DB_NAME, 1);
6
+ req.onupgradeneeded = () => {
7
+ const db = req.result;
8
+ if (!db.objectStoreNames.contains(STORE))
9
+ db.createObjectStore(STORE);
10
+ };
11
+ req.onsuccess = () => resolve(req.result);
12
+ req.onerror = () => reject(req.error);
13
+ });
14
+ }
15
+ async function readCache(key) {
16
+ try {
17
+ const db = await openDb();
18
+ return await new Promise((resolve, reject) => {
19
+ const tx = db.transaction(STORE, "readonly");
20
+ const req = tx.objectStore(STORE).get(key);
21
+ req.onsuccess = () => resolve(req.result ?? null);
22
+ req.onerror = () => reject(req.error);
23
+ });
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ async function writeCache(key, bytes) {
30
+ try {
31
+ const db = await openDb();
32
+ await new Promise((resolve, reject) => {
33
+ const tx = db.transaction(STORE, "readwrite");
34
+ tx.objectStore(STORE).put(bytes, key);
35
+ tx.oncomplete = () => resolve();
36
+ tx.onerror = () => reject(tx.error);
37
+ });
38
+ }
39
+ catch {
40
+ /* 缓存写失败静默降级 */
41
+ }
42
+ }
43
+ const memory = new Map();
44
+ /** 并发去重:同一 URL 的并行加载共享同一个 Promise,避免大字体重复拉取 */
45
+ const inFlight = new Map();
46
+ /**
47
+ * 字体加载(IndexedDB 持久缓存 + 内存缓存):
48
+ * 中文字体体积大(simhei ~9MB),首次 fetch 后缓存,后续导出零网络等待。
49
+ */
50
+ export async function loadFontWithCache(url) {
51
+ const memo = memory.get(url);
52
+ if (memo)
53
+ return memo;
54
+ const pending = inFlight.get(url);
55
+ if (pending)
56
+ return pending;
57
+ const task = (async () => {
58
+ const cached = await readCache(url);
59
+ if (cached) {
60
+ memory.set(url, cached);
61
+ return cached;
62
+ }
63
+ try {
64
+ const res = await fetch(url);
65
+ if (!res.ok)
66
+ return null;
67
+ const bytes = new Uint8Array(await res.arrayBuffer());
68
+ memory.set(url, bytes);
69
+ void writeCache(url, bytes);
70
+ return bytes;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ })();
76
+ inFlight.set(url, task);
77
+ try {
78
+ return await task;
79
+ }
80
+ finally {
81
+ inFlight.delete(url);
82
+ }
83
+ }
84
+ //# sourceMappingURL=font-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font-loader.js","sourceRoot":"","sources":["../../src/pdf/font-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./render-pdf";
2
+ export * from "./font-loader";
@@ -0,0 +1,3 @@
1
+ export * from "./render-pdf";
2
+ export * from "./font-loader";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { PDFDocument } from "pdf-lib";
2
+ import type { RenderPlan } from "../schema/render-plan";
3
+ import { type TextMeasurer } from "../index";
4
+ export interface PdfRenderOptions {
5
+ /** 嵌入字体字节(TTF,如黑体);缺省用 Helvetica(不支持 CJK) */
6
+ customFontBytes?: Uint8Array | ArrayBuffer;
7
+ customFontName?: string;
8
+ /** 文本测量器(默认启发式;与分页/Canvas 注入同一实例可消除折行差异) */
9
+ measurer?: TextMeasurer;
10
+ }
11
+ export interface PdfRenderResult {
12
+ pdfDoc: PDFDocument;
13
+ bytes: Uint8Array;
14
+ pageErrors: string[];
15
+ unsupportedTextCount: number;
16
+ /** 保真度降级清单(富文本转纯文本、图片格式不支持等),供上层提示 */
17
+ fidelityWarnings: string[];
18
+ }
19
+ export declare function renderPlanToPdf(plan: RenderPlan, options?: PdfRenderOptions): Promise<PdfRenderResult>;
@@ -0,0 +1,284 @@
1
+ import fontkit from "@pdf-lib/fontkit";
2
+ import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
3
+ import { heuristicMeasurer, isImageBackedComponent, isRichText, LINE_HEIGHT, resolveBoxBorders, resolveFontSize, resolveStroke, resolveGridLayout, wrapText } from "../index";
4
+ const MM_TO_PT = 72 / 25.4;
5
+ function mmToPt(mm) {
6
+ return (mm || 0) * MM_TO_PT;
7
+ }
8
+ function colorOf(value, fallback = [0, 0, 0]) {
9
+ if (!value)
10
+ return rgb(fallback[0], fallback[1], fallback[2]);
11
+ const hex = value.replace("#", "");
12
+ if (/^[0-9a-f]{6}$/i.test(hex)) {
13
+ return rgb(parseInt(hex.slice(0, 2), 16) / 255, parseInt(hex.slice(2, 4), 16) / 255, parseInt(hex.slice(4, 6), 16) / 255);
14
+ }
15
+ return rgb(fallback[0], fallback[1], fallback[2]);
16
+ }
17
+ function fontSizePtOf(comp) {
18
+ return resolveFontSize(comp.style).fontSizePt;
19
+ }
20
+ function cellFontSizePt(style) {
21
+ return resolveFontSize(style).fontSizePt;
22
+ }
23
+ function encodeText(font, text) {
24
+ try {
25
+ font.encodeText(text);
26
+ return { encoded: text, supported: true };
27
+ }
28
+ catch {
29
+ return { encoded: "", supported: false };
30
+ }
31
+ }
32
+ /** 富文本降级:段落 → 纯文本行(保留段落顺序,丢内联样式;计入保真告警) */
33
+ function richTextToLines(comp) {
34
+ const out = [];
35
+ for (const para of comp.richParagraphs ?? []) {
36
+ const line = (para.segments ?? [])
37
+ .map((seg) => (seg.kind === "field" ? (seg.field ?? "") : (seg.text ?? "")))
38
+ .join("");
39
+ out.push(line);
40
+ }
41
+ return out;
42
+ }
43
+ export async function renderPlanToPdf(plan, options = {}) {
44
+ const pdfDoc = await PDFDocument.create();
45
+ pdfDoc.registerFontkit(fontkit);
46
+ const pageErrors = [];
47
+ const fidelityWarnings = [];
48
+ let unsupportedTextCount = 0;
49
+ const measurer = options.measurer ?? heuristicMeasurer;
50
+ const fallbackFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
51
+ const customFont = options.customFontBytes
52
+ ? await pdfDoc.embedFont(options.customFontBytes, {
53
+ subset: true
54
+ })
55
+ : undefined;
56
+ const font = customFont ?? fallbackFont;
57
+ const imageCache = new Map();
58
+ function wrapLines(text, widthMm, fontSizePt) {
59
+ if (!text)
60
+ return [];
61
+ return wrapText(text, widthMm, { fontSizePt }, measurer);
62
+ }
63
+ function embedImage(dataUrl) {
64
+ const cached = imageCache.get(dataUrl);
65
+ if (cached)
66
+ return cached;
67
+ const p = (async () => {
68
+ try {
69
+ const match = /^data:image\/(png|jpe?g);base64,(.*)$/s.exec(dataUrl);
70
+ if (!match)
71
+ return null;
72
+ const bytes = Uint8Array.from(atob(match[2]), (c) => c.charCodeAt(0));
73
+ if (match[1] === "png")
74
+ return await pdfDoc.embedPng(bytes);
75
+ return await pdfDoc.embedJpg(bytes);
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ })();
81
+ imageCache.set(dataUrl, p);
82
+ return p;
83
+ }
84
+ function drawTextLines(page, spec, xPt, yTopPt, widthPt, comp, cellStyle) {
85
+ const align = cellStyle?.align ?? comp.style?.align;
86
+ const lineH = spec.fontSizePt * LINE_HEIGHT;
87
+ spec.lines.forEach((line, i) => {
88
+ const { encoded, supported } = encodeText(font, line);
89
+ if (line && !supported)
90
+ unsupportedTextCount++;
91
+ if (!encoded)
92
+ return;
93
+ const w = font.widthOfTextAtSize(encoded, spec.fontSizePt);
94
+ let x = xPt;
95
+ if (align === "center")
96
+ x = xPt + (widthPt - w) / 2;
97
+ else if (align === "right")
98
+ x = xPt + widthPt - w;
99
+ page.drawText(encoded, {
100
+ x,
101
+ y: yTopPt - spec.fontSizePt - i * lineH,
102
+ size: spec.fontSizePt,
103
+ font,
104
+ color: colorOf(cellStyle?.color ?? comp.style?.color)
105
+ });
106
+ });
107
+ }
108
+ function drawGrid(page, grid, comp, originXPt, originYPt) {
109
+ const layout = resolveGridLayout(grid, comp.widthMm, comp.heightMm);
110
+ const borders = resolveBoxBorders(comp.style);
111
+ const stroke = resolveStroke(comp.style);
112
+ const lineColor = colorOf(stroke.color, [0.2, 0.2, 0.2]);
113
+ const borderWidth = Math.max(0.1, stroke.widthPt);
114
+ // 单元格底色(独立于边框开关)
115
+ for (const box of layout.cells) {
116
+ const bg = box.cell.style?.backgroundColor;
117
+ if (!bg)
118
+ continue;
119
+ page.drawRectangle({
120
+ x: originXPt + mmToPt(box.xMm),
121
+ y: originYPt - mmToPt(box.yMm) - mmToPt(box.heightMm),
122
+ width: mmToPt(box.widthMm),
123
+ height: mmToPt(box.heightMm),
124
+ color: colorOf(bg, [1, 1, 1])
125
+ });
126
+ }
127
+ if (borders.inner) {
128
+ // 内部线段(span 感知:合并单元格中间无线)+ 外框四边开关
129
+ for (const e of layout.edges) {
130
+ if (e.kind === "v") {
131
+ page.drawLine({
132
+ start: { x: originXPt + mmToPt(e.pos), y: originYPt - mmToPt(e.to) },
133
+ end: { x: originXPt + mmToPt(e.pos), y: originYPt - mmToPt(e.from) },
134
+ thickness: borderWidth,
135
+ color: lineColor
136
+ });
137
+ }
138
+ else {
139
+ page.drawLine({
140
+ start: { x: originXPt + mmToPt(e.from), y: originYPt - mmToPt(e.pos) },
141
+ end: { x: originXPt + mmToPt(e.to), y: originYPt - mmToPt(e.pos) },
142
+ thickness: borderWidth,
143
+ color: lineColor
144
+ });
145
+ }
146
+ }
147
+ const x0 = originXPt;
148
+ const y0 = originYPt - mmToPt(comp.heightMm);
149
+ const x1 = originXPt + mmToPt(comp.widthMm);
150
+ const y1 = originYPt;
151
+ const drawEdge = (ax, ay, bx, by) => page.drawLine({
152
+ start: { x: ax, y: ay },
153
+ end: { x: bx, y: by },
154
+ thickness: borderWidth,
155
+ color: lineColor
156
+ });
157
+ if (borders.top)
158
+ drawEdge(x0, y1, x1, y1);
159
+ if (borders.right)
160
+ drawEdge(x1, y1, x1, y0);
161
+ if (borders.bottom)
162
+ drawEdge(x1, y0, x0, y0);
163
+ if (borders.left)
164
+ drawEdge(x0, y0, x0, y1);
165
+ }
166
+ for (const box of layout.cells) {
167
+ const st = box.cell.style;
168
+ const x = originXPt + mmToPt(box.xMm);
169
+ const yTop = originYPt - mmToPt(box.yMm);
170
+ const w = mmToPt(box.widthMm);
171
+ const h = mmToPt(box.heightMm);
172
+ const text = typeof box.cell.text === "string" ? box.cell.text : "";
173
+ if (!text)
174
+ continue;
175
+ const fontSizePt = cellFontSizePt(st);
176
+ const maxLines = Math.max(1, Math.floor(h / (fontSizePt * LINE_HEIGHT)));
177
+ const lines = wrapLines(text, box.widthMm - 1, fontSizePt).slice(0, maxLines);
178
+ drawTextLines(page, { lines, fontSizePt }, x + 1, yTop - (h - lines.length * fontSizePt * LINE_HEIGHT) / 2, w - 2, comp, { color: st?.color, align: st?.align });
179
+ }
180
+ }
181
+ for (let pageIndex = 0; pageIndex < plan.pages.length; pageIndex++) {
182
+ const planPage = plan.pages[pageIndex];
183
+ const widthPt = mmToPt(planPage.pageWidthMm);
184
+ const heightPt = mmToPt(planPage.pageHeightMm);
185
+ const page = pdfDoc.addPage([widthPt, heightPt]);
186
+ for (const comp of planPage.components) {
187
+ const x = mmToPt(comp.leftMm);
188
+ const yTop = heightPt - mmToPt(comp.topMm);
189
+ const w = mmToPt(comp.widthMm);
190
+ const h = mmToPt(comp.heightMm);
191
+ try {
192
+ if (isImageBackedComponent(comp)) {
193
+ const img = await embedImage(comp.imageData);
194
+ if (img) {
195
+ page.drawImage(img, { x, y: yTop - h, width: w, height: h });
196
+ }
197
+ else {
198
+ fidelityWarnings.push(`page ${pageIndex + 1} ${comp.nid ?? comp.kind}: 图片仅支持 data:image/(png|jpeg) base64,已跳过`);
199
+ }
200
+ continue;
201
+ }
202
+ switch (comp.kind) {
203
+ case "text": {
204
+ const fontSizePt = fontSizePtOf(comp);
205
+ const lines = isRichText(comp)
206
+ ? richTextToLines(comp)
207
+ : Array.isArray(comp.lines) && comp.lines.length > 0
208
+ ? comp.lines
209
+ : wrapLines(comp.text ?? "", comp.widthMm, fontSizePt);
210
+ if (isRichText(comp)) {
211
+ fidelityWarnings.push(`page ${pageIndex + 1} ${comp.nid ?? "text"}: 富文本按纯文本降级导出(内联样式丢失)`);
212
+ }
213
+ drawTextLines(page, { lines, fontSizePt }, x, yTop, w, comp);
214
+ break;
215
+ }
216
+ case "rect": {
217
+ const borders = resolveBoxBorders(comp.style);
218
+ const stroke = resolveStroke(comp.style);
219
+ if (comp.style?.backgroundColor) {
220
+ page.drawRectangle({
221
+ x,
222
+ y: yTop - h,
223
+ width: w,
224
+ height: h,
225
+ color: colorOf(comp.style.backgroundColor, [1, 1, 1])
226
+ });
227
+ }
228
+ if (borders.inner) {
229
+ page.drawRectangle({
230
+ x,
231
+ y: yTop - h,
232
+ width: w,
233
+ height: h,
234
+ borderColor: colorOf(stroke.color, [0.2, 0.2, 0.2]),
235
+ borderWidth: Math.max(0.1, stroke.widthPt)
236
+ });
237
+ }
238
+ if (comp.grid) {
239
+ drawGrid(page, comp.grid, comp, x, yTop);
240
+ }
241
+ break;
242
+ }
243
+ case "line": {
244
+ const stroke = resolveStroke({ ...comp.style, borderColor: comp.style?.lineColor ?? comp.style?.borderColor });
245
+ page.drawLine({
246
+ start: { x, y: yTop - h / 2 },
247
+ end: { x: x + w, y: yTop - h / 2 },
248
+ thickness: Math.max(0.1, stroke.widthPt),
249
+ color: colorOf(stroke.color, [0.2, 0.2, 0.2])
250
+ });
251
+ break;
252
+ }
253
+ case "ellipse": {
254
+ const stroke = resolveStroke(comp.style);
255
+ page.drawEllipse({
256
+ x: x + w / 2,
257
+ y: yTop - h / 2,
258
+ xScale: w / 2,
259
+ yScale: h / 2,
260
+ borderColor: colorOf(stroke.color, [0.2, 0.2, 0.2]),
261
+ borderWidth: Math.max(0.1, stroke.widthPt)
262
+ });
263
+ break;
264
+ }
265
+ default: {
266
+ if (comp.grid) {
267
+ drawGrid(page, comp.grid, comp, x, yTop);
268
+ }
269
+ else if (comp.text) {
270
+ drawTextLines(page, { lines: [comp.text], fontSizePt: fontSizePtOf(comp) }, x, yTop, w, comp);
271
+ }
272
+ break;
273
+ }
274
+ }
275
+ }
276
+ catch (e) {
277
+ pageErrors.push(`page ${pageIndex + 1} comp ${comp.nid ?? comp.kind}: ${String(e)}`);
278
+ }
279
+ }
280
+ }
281
+ const bytes = await pdfDoc.save();
282
+ return { pdfDoc, bytes, pageErrors, unsupportedTextCount, fidelityWarnings };
283
+ }
284
+ //# sourceMappingURL=render-pdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-pdf.js","sourceRoot":"","sources":["../../src/pdf/render-pdf.ts"],"names":[],"mappings":"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"}
package/dist/pdf.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * PDF 直出子路径入口(@agile-team/mach-report/pdf):
3
+ * 矢量 PDF 生成 + 字体缓存。pdf-lib 为常规依赖,
4
+ * 仅当导入本子路径或触发懒加载导出时才进入产物图。
5
+ */
6
+ export * from "./pdf/index";
package/dist/pdf.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * PDF 直出子路径入口(@agile-team/mach-report/pdf):
3
+ * 矢量 PDF 生成 + 字体缓存。pdf-lib 为常规依赖,
4
+ * 仅当导入本子路径或触发懒加载导出时才进入产物图。
5
+ */
6
+ export * from "./pdf/index";
7
+ //# sourceMappingURL=pdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.js","sourceRoot":"","sources":["../src/pdf.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,aAAa,CAAC"}
@@ -0,0 +1,61 @@
1
+ import type { PlanPage, RenderPlan } from "../schema/render-plan";
2
+ import { type TextMeasurer } from "../layout/textwrap";
3
+ export interface CanvasRenderOptions {
4
+ /** 设备像素比,默认取运行环境 devicePixelRatio */
5
+ dpr?: number;
6
+ dpi?: number;
7
+ /** 文本默认字体族 */
8
+ fontFamily?: string;
9
+ /** 文本测量器(默认启发式) */
10
+ measurer?: TextMeasurer;
11
+ /** 只渲染页区间(闭区间索引;缺省全渲染——仅小报表使用,大报表请用 createCanvasPager) */
12
+ start?: number;
13
+ end?: number;
14
+ }
15
+ export declare function measurePageSizePx(page: Pick<PlanPage, "pageWidthMm" | "pageHeightMm">, dpi?: number): {
16
+ widthPx: number;
17
+ heightPx: number;
18
+ };
19
+ /** pt→px 换算(与 DOM 后端 units.ptToPx 同一真相源),供单测直接断言 */
20
+ export declare function planFontSizePx(style: {
21
+ fontSizePx?: number;
22
+ fontSize?: number;
23
+ } | undefined, dpi?: number): number;
24
+ export interface CanvasRenderResult {
25
+ canvases: HTMLCanvasElement[];
26
+ }
27
+ /**
28
+ * RenderPlan → Canvas 位图页(顶点原点坐标系,与 DOM/PDF 一致)。
29
+ *
30
+ * ⚠️ 内存模型:A4 @dpr2 ≈ 14MB/页,全量渲染 100 页 ≈ 1.4GB。
31
+ * 大报表必须使用 createCanvasPager(窗口化 + 画布池 + 分帧渲染),
32
+ * 本函数适合页数少或已指定 start/end 区间的场景。
33
+ */
34
+ export declare function renderPlanToCanvas(plan: RenderPlan, options?: CanvasRenderOptions): CanvasRenderResult;
35
+ export interface CanvasPagerOptions extends CanvasRenderOptions {
36
+ /** 预渲染页数缓冲(窗口两侧各加 N 页),默认 1 */
37
+ overscan?: number;
38
+ /** 页间距 px,默认 18 */
39
+ gapPx?: number;
40
+ /** 每帧渲染页数上限(分帧,防长任务),默认 1 */
41
+ pagesPerFrame?: number;
42
+ }
43
+ export interface CanvasPager {
44
+ /** 挂载到滚动容器(viewport,overflow:auto),接管其内容 */
45
+ attach(viewport: HTMLElement): void;
46
+ destroy(): void;
47
+ /** 当前实际渲染的页区间 */
48
+ window(): {
49
+ start: number;
50
+ end: number;
51
+ };
52
+ }
53
+ /**
54
+ * Canvas 虚拟化分页器(大报表专用):
55
+ * - 视口窗口化:只绘制窗口内页(computePageWindow 与 DOM 后端共用)
56
+ * - 画布池:固定数量 canvas 复用重绘,滚动零新增位图
57
+ * - 分帧:每帧最多 pagesPerFrame 页,滚动期间不产生长任务
58
+ *
59
+ * 内存从 O(总页数) 降到 O(窗口+2×overscan)。
60
+ */
61
+ export declare function createCanvasPager(plan: RenderPlan, options?: CanvasPagerOptions): CanvasPager;