@ym-print/core 0.0.0-stage → 0.1.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +54 -2
- package/THIRD_PARTY_NOTICES.md +19 -0
- package/dependency-licenses.json +149 -0
- package/dist/advanced-elements.d.ts +6 -0
- package/dist/barcode.d.ts +22 -0
- package/dist/capabilities.d.ts +22 -0
- package/dist/cell-plugins.d.ts +3 -0
- package/dist/composite-cell.d.ts +27 -0
- package/dist/data.d.ts +14 -0
- package/dist/expression.d.ts +16 -0
- package/dist/font-ToGNY599.js +136 -0
- package/dist/font-file.d.ts +18 -0
- package/dist/font-file.js +45 -0
- package/dist/font.d.ts +44 -0
- package/dist/formatting.d.ts +8 -0
- package/dist/functions.d.ts +22 -0
- package/dist/html.d.ts +19 -0
- package/dist/imposition.d.ts +4 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +9130 -0
- package/dist/layout.d.ts +12 -0
- package/dist/page-settings.d.ts +15 -0
- package/dist/plugins.d.ts +61 -0
- package/dist/protocol.d.ts +584 -0
- package/dist/resources.d.ts +6 -0
- package/dist/rich-text.d.ts +34 -0
- package/dist/rules.d.ts +4 -0
- package/dist/stamp.d.ts +21 -0
- package/dist/table-header.d.ts +17 -0
- package/dist/table-model.d.ts +15 -0
- package/dist/table-report-layout.d.ts +5 -0
- package/dist/table-report.d.ts +17 -0
- package/dist/table.d.ts +49 -0
- package/dist/text-output.d.ts +3 -0
- package/dist/vector.d.ts +3 -0
- package/package.json +55 -4
- package/third-party-licenses/ajv@8.20.0/LICENSE +22 -0
- package/third-party-licenses/bwip-js@4.11.4/LICENSE +23 -0
- package/third-party-licenses/bwip-js@4.11.4/LICENSE.CANVASTOBLOB +31 -0
- package/third-party-licenses/bwip-js@4.11.4/LICENSE.FILESAVER +9 -0
- package/third-party-licenses/bwip-js@4.11.4/LICENSE.INCONSOLATA +97 -0
- package/third-party-licenses/decimal.js@10.6.0/LICENCE.md +23 -0
- package/third-party-licenses/entities@8.1.0/LICENSE +11 -0
- package/third-party-licenses/fast-deep-equal@3.1.3/LICENSE +21 -0
- package/third-party-licenses/fast-uri@3.1.9/LICENSE +30 -0
- package/third-party-licenses/json-schema-traverse@1.0.0/LICENSE +21 -0
- package/third-party-licenses/pako@1.0.11/LICENSE +21 -0
- package/third-party-licenses/parse5@8.0.1/LICENSE +19 -0
- package/third-party-licenses/require-from-string@2.0.2/license +21 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
UNLICENSED
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YmPrintUnit contributors. All rights reserved.
|
|
4
|
+
|
|
5
|
+
No open-source license is granted for the original YmPrintUnit code.
|
|
6
|
+
|
|
7
|
+
Third-party components retain their own licenses. See THIRD_PARTY_NOTICES.md
|
|
8
|
+
and dependency-licenses.json; this notice does not change those licenses.
|
package/README.md
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ym-print/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
YmPrintUnit 的模板类型、数据表达式和排版内核。根据模板、业务数据及字体测量器生成 `LayoutDocument`,供页面渲染、打印和文件输出使用。
|
|
4
|
+
|
|
5
|
+
## npm 安装
|
|
6
|
+
|
|
7
|
+
首次 npm 发布完成后安装预发布版:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add @ym-print/core@next
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
正式版发布后将 `@next` 改为 `@latest`。原始代码保持 `UNLICENSED`,详见随包附带的 `LICENSE`;第三方许可见 `THIRD_PARTY_NOTICES.md`。
|
|
14
|
+
|
|
15
|
+
## 项目内容
|
|
16
|
+
|
|
17
|
+
- 纸张、分节、页眉页脚、流式与绝对定位。
|
|
18
|
+
- 长文字、表格、分组统计、组合单元格与标签拼版。
|
|
19
|
+
- JSON Pointer 字段引用、十进制计算、格式化和条件规则。
|
|
20
|
+
- 元素插件、业务函数注册和资源检查。
|
|
21
|
+
|
|
22
|
+
## 使用方法
|
|
23
|
+
|
|
24
|
+
包使用 ESM,并提供 TypeScript 类型。将模板、业务数据和实现 `TextFont` 的字体测量器传入排版函数:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import {createPrintRegistry, layoutTemplate} from '@ym-print/core';
|
|
28
|
+
import type {Template, TextFont} from '@ym-print/core';
|
|
29
|
+
|
|
30
|
+
export function createLayout(
|
|
31
|
+
template: Template,
|
|
32
|
+
data: Record<string, unknown>,
|
|
33
|
+
font: TextFont,
|
|
34
|
+
) {
|
|
35
|
+
const registry = createPrintRegistry();
|
|
36
|
+
return layoutTemplate(template, data, font, {registry, mode:'w2'});
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`LayoutDocument.pages` 包含分页后的物理尺寸和绘制命令。调用方可把它传给 `@ym-print/renderer-dom` 渲染或打印,或者交给 `@ym-print/renderer-pdf` 导出。
|
|
41
|
+
|
|
42
|
+
Web 页面可使用 `@ym-print/renderer-dom` 的 `BrowserFont` 作为测量器。自定义元素或业务函数通过 `createPrintRegistry` 注册,再将同一注册表传入排版与输出流程。
|
|
43
|
+
|
|
44
|
+
## 数据与单位
|
|
45
|
+
|
|
46
|
+
| 内容 | 用法 |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| 字段路径 | JSON Pointer,例如 `/supplier/name` |
|
|
49
|
+
| 表格数据 | 列值使用行作用域,数组来源由模板指定 |
|
|
50
|
+
| 金额 | 使用十进制字符串,例如 `"12.35"` |
|
|
51
|
+
| 坐标与尺寸 | 微米,`1000 μm = 1 mm` |
|
|
52
|
+
| 字号 | 毫点,`1000 mpt = 1 pt` |
|
|
53
|
+
| 旋转 | 毫度,`1000 mdeg = 1°` |
|
|
54
|
+
|
|
55
|
+
模板、业务数据、图片资源和字体测量器由调用方提供。排版结果用于预览和输出,保存模板时使用原设计内容。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
@ym-print/core 0.1.0-rc.2 — original code: UNLICENSED.
|
|
4
|
+
|
|
5
|
+
Bundled code and external packages keep their original licenses. Optional peers are loaded through their documented opt-in entry.
|
|
6
|
+
|
|
7
|
+
| Package | License | Delivery | Notices |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| @pdf-lib/fontkit@1.1.1 | MIT | optional-peer | License declared upstream; not bundled here |
|
|
10
|
+
| ajv@8.20.0 | MIT | external | [LICENSE](third-party-licenses/ajv@8.20.0/LICENSE) |
|
|
11
|
+
| bwip-js@4.11.4 | MIT | external | [LICENSE](third-party-licenses/bwip-js@4.11.4/LICENSE), [LICENSE.CANVASTOBLOB](third-party-licenses/bwip-js@4.11.4/LICENSE.CANVASTOBLOB), [LICENSE.FILESAVER](third-party-licenses/bwip-js@4.11.4/LICENSE.FILESAVER), [LICENSE.INCONSOLATA](third-party-licenses/bwip-js@4.11.4/LICENSE.INCONSOLATA) |
|
|
12
|
+
| decimal.js@10.6.0 | MIT | external | [LICENCE.md](third-party-licenses/decimal.js@10.6.0/LICENCE.md) |
|
|
13
|
+
| entities@8.1.0 | BSD-2-Clause | external | [LICENSE](third-party-licenses/entities@8.1.0/LICENSE) |
|
|
14
|
+
| fast-deep-equal@3.1.3 | MIT | external | [LICENSE](third-party-licenses/fast-deep-equal@3.1.3/LICENSE) |
|
|
15
|
+
| fast-uri@3.1.9 | BSD-3-Clause | external | [LICENSE](third-party-licenses/fast-uri@3.1.9/LICENSE) |
|
|
16
|
+
| json-schema-traverse@1.0.0 | MIT | external | [LICENSE](third-party-licenses/json-schema-traverse@1.0.0/LICENSE) |
|
|
17
|
+
| pako@1.0.11 | (MIT AND Zlib) | external | [LICENSE](third-party-licenses/pako@1.0.11/LICENSE) |
|
|
18
|
+
| parse5@8.0.1 | MIT | external | [LICENSE](third-party-licenses/parse5@8.0.1/LICENSE) |
|
|
19
|
+
| require-from-string@2.0.2 | MIT | external | [license](third-party-licenses/require-from-string@2.0.2/license) |
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": "@ym-print/core",
|
|
3
|
+
"version": "0.1.0-rc.2",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"licenseScope": "original YmPrintUnit code only",
|
|
6
|
+
"dependencies": [
|
|
7
|
+
{
|
|
8
|
+
"name": "@pdf-lib/fontkit",
|
|
9
|
+
"version": "1.1.1",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"kind": "optional-peer",
|
|
12
|
+
"notices": [],
|
|
13
|
+
"noticeStatus": "upstream declares license but ships no license-named file; external code is not copied"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "ajv",
|
|
17
|
+
"version": "8.20.0",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"kind": "external",
|
|
20
|
+
"notices": [
|
|
21
|
+
{
|
|
22
|
+
"path": "third-party-licenses/ajv@8.20.0/LICENSE",
|
|
23
|
+
"sha256": "a05350a88e318e4f5f2c2a1ff1e2e88daa4dd38e6e78b71cccae422bdc762cc3"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "bwip-js",
|
|
29
|
+
"version": "4.11.4",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"kind": "external",
|
|
32
|
+
"notices": [
|
|
33
|
+
{
|
|
34
|
+
"path": "third-party-licenses/bwip-js@4.11.4/LICENSE",
|
|
35
|
+
"sha256": "cc393d55aa77ec8e5aa27065244596b5ed8b2c6a1bc5c014045e11f91f343492"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "third-party-licenses/bwip-js@4.11.4/LICENSE.CANVASTOBLOB",
|
|
39
|
+
"sha256": "4ad7a94085f65777827e9cd3b87c37aefebfc963029320a3054b84e234c3ae18"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"path": "third-party-licenses/bwip-js@4.11.4/LICENSE.FILESAVER",
|
|
43
|
+
"sha256": "dfb1a94504fac1c72b69b9f89a3b95f7f6643de79e5efb1fc4ba350766402188"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"path": "third-party-licenses/bwip-js@4.11.4/LICENSE.INCONSOLATA",
|
|
47
|
+
"sha256": "1a7adaa2c86cedfd6c7f5c0c7c72fd6d3e02cd0c9593f21fdb53c89bb2b130ec"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "decimal.js",
|
|
53
|
+
"version": "10.6.0",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"kind": "external",
|
|
56
|
+
"notices": [
|
|
57
|
+
{
|
|
58
|
+
"path": "third-party-licenses/decimal.js@10.6.0/LICENCE.md",
|
|
59
|
+
"sha256": "3108b546bcff5d346923a82f48b2d252ca722f9088076db6d145f6b67757ad6c"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "entities",
|
|
65
|
+
"version": "8.1.0",
|
|
66
|
+
"license": "BSD-2-Clause",
|
|
67
|
+
"kind": "external",
|
|
68
|
+
"notices": [
|
|
69
|
+
{
|
|
70
|
+
"path": "third-party-licenses/entities@8.1.0/LICENSE",
|
|
71
|
+
"sha256": "cb992345949ccd6e8394b2cd6c465f7b897c864f845937dbf64e8997f389e164"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "fast-deep-equal",
|
|
77
|
+
"version": "3.1.3",
|
|
78
|
+
"license": "MIT",
|
|
79
|
+
"kind": "external",
|
|
80
|
+
"notices": [
|
|
81
|
+
{
|
|
82
|
+
"path": "third-party-licenses/fast-deep-equal@3.1.3/LICENSE",
|
|
83
|
+
"sha256": "7bf9b2de73a6b356761c948d0e9eeb4be6c1270bd04c79cd489c1e400ffdfc1a"
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "fast-uri",
|
|
89
|
+
"version": "3.1.9",
|
|
90
|
+
"license": "BSD-3-Clause",
|
|
91
|
+
"kind": "external",
|
|
92
|
+
"notices": [
|
|
93
|
+
{
|
|
94
|
+
"path": "third-party-licenses/fast-uri@3.1.9/LICENSE",
|
|
95
|
+
"sha256": "b010b0dfdfdb23d7396e03b82cd4621fc9bb8f95d6b0aea70b9c24e12074c786"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "json-schema-traverse",
|
|
101
|
+
"version": "1.0.0",
|
|
102
|
+
"license": "MIT",
|
|
103
|
+
"kind": "external",
|
|
104
|
+
"notices": [
|
|
105
|
+
{
|
|
106
|
+
"path": "third-party-licenses/json-schema-traverse@1.0.0/LICENSE",
|
|
107
|
+
"sha256": "7bf9b2de73a6b356761c948d0e9eeb4be6c1270bd04c79cd489c1e400ffdfc1a"
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "pako",
|
|
113
|
+
"version": "1.0.11",
|
|
114
|
+
"license": "(MIT AND Zlib)",
|
|
115
|
+
"kind": "external",
|
|
116
|
+
"notices": [
|
|
117
|
+
{
|
|
118
|
+
"path": "third-party-licenses/pako@1.0.11/LICENSE",
|
|
119
|
+
"sha256": "a04665b3b2de56c66730c1f720f528175739e4104f79073614aa611da1e85539"
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "parse5",
|
|
125
|
+
"version": "8.0.1",
|
|
126
|
+
"license": "MIT",
|
|
127
|
+
"kind": "external",
|
|
128
|
+
"notices": [
|
|
129
|
+
{
|
|
130
|
+
"path": "third-party-licenses/parse5@8.0.1/LICENSE",
|
|
131
|
+
"sha256": "8c535800331e1e4439835555b3f9edc7fe9dee2fab0d8bbbd5a982e8b8343d4d"
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "require-from-string",
|
|
137
|
+
"version": "2.0.2",
|
|
138
|
+
"license": "MIT",
|
|
139
|
+
"kind": "external",
|
|
140
|
+
"notices": [
|
|
141
|
+
{
|
|
142
|
+
"path": "third-party-licenses/require-from-string@2.0.2/license",
|
|
143
|
+
"sha256": "6ee0feb1f6ef996ff5a68600f8cf98909cf412d39ef3cdceaefd87d636fa1b7f"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"resourceLicenses": []
|
|
149
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ElementPlugin } from './plugins.js';
|
|
2
|
+
export declare const richTextPlugin: ElementPlugin;
|
|
3
|
+
export declare const svgPlugin: ElementPlugin;
|
|
4
|
+
export declare const pdfPagePlugin: ElementPlugin;
|
|
5
|
+
export declare const seamSealPlugin: ElementPlugin;
|
|
6
|
+
export declare const advancedElements: readonly [ElementPlugin, ElementPlugin, ElementPlugin, ElementPlugin, ElementPlugin];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const isMatrixSymbol: (s: string) => boolean;
|
|
2
|
+
export declare function barcodeRects(value: string, symbology: string, moduleUm: number, quietUm: number, widthUm: number, heightUm: number): {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}[];
|
|
8
|
+
/** Whole integer modules and quiet zones are preserved when the editing frame changes. */
|
|
9
|
+
export declare function barcodeSizing(value: string, symbology: string, moduleUm: number, quietZoneUm: number): {
|
|
10
|
+
columns: number;
|
|
11
|
+
rows: number;
|
|
12
|
+
quietModules: number;
|
|
13
|
+
minModuleUm: number;
|
|
14
|
+
minWidthUm: number;
|
|
15
|
+
minHeightUm: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function fittedBarcodeRects(value: string, symbology: string, referenceModuleUm: number, referenceQuietUm: number, widthUm: number, heightUm: number): {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type PrintRegistry } from './plugins.js';
|
|
2
|
+
import type { Template } from './protocol.js';
|
|
3
|
+
export declare const CAPABILITY_LABELS: Readonly<Record<string, string>>;
|
|
4
|
+
export declare const WEB_CAPABILITIES: readonly string[];
|
|
5
|
+
export interface PreflightIssue {
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
path?: string;
|
|
9
|
+
nodeId?: string;
|
|
10
|
+
dataPath?: string;
|
|
11
|
+
scope?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CapabilityReport {
|
|
14
|
+
valid: boolean;
|
|
15
|
+
requiredCapabilities: string[];
|
|
16
|
+
declaredCapabilities: string[];
|
|
17
|
+
errors: PreflightIssue[];
|
|
18
|
+
warnings: PreflightIssue[];
|
|
19
|
+
}
|
|
20
|
+
/** Derive requirements from actual content; declarations cannot conceal unsupported elements or expressions. */
|
|
21
|
+
export declare function inspectTemplateCapabilities(template: Template, registry?: PrintRegistry): CapabilityReport;
|
|
22
|
+
export declare function assertTemplateCapabilities(template: Template, registry?: PrintRegistry): CapabilityReport;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CellElement, CompositeCell, DrawCommand, EvalContext, Expr, TextStyle } from './protocol.js';
|
|
2
|
+
import type { TextFont } from './font.js';
|
|
3
|
+
import type { PrintRegistry } from './plugins.js';
|
|
4
|
+
export declare const COMPOSITE_CELL_LIMITS: {
|
|
5
|
+
readonly depth: 8;
|
|
6
|
+
readonly elements: 64;
|
|
7
|
+
readonly fragments: 4096;
|
|
8
|
+
readonly commands: 20000;
|
|
9
|
+
readonly heightUm: 2000000;
|
|
10
|
+
};
|
|
11
|
+
export interface CellFragment {
|
|
12
|
+
heightUm: number;
|
|
13
|
+
commands: DrawCommand[];
|
|
14
|
+
}
|
|
15
|
+
/** A bounded layout tree belongs to one cell. It never contains dynamic tables, repetitions or templates. */
|
|
16
|
+
export declare function visitCompositeCell(cell: CompositeCell, visit?: (element: CellElement, path: string) => void): void;
|
|
17
|
+
export declare function compositeBindings(cell: CompositeCell, registry?: PrintRegistry): {
|
|
18
|
+
expr: Expr;
|
|
19
|
+
path: string;
|
|
20
|
+
image?: boolean;
|
|
21
|
+
}[];
|
|
22
|
+
/** Measure first, partition only where no text line/image/code/plugin/keep-together group crosses the cut. */
|
|
23
|
+
export declare function measureCompositeCell(cell: CompositeCell, ctx: EvalContext, font: TextFont, widthUm: number, style: TextStyle, nodeId: string): {
|
|
24
|
+
heightUm: number;
|
|
25
|
+
fragments: CellFragment[];
|
|
26
|
+
commands: DrawCommand[];
|
|
27
|
+
};
|
package/dist/data.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Template, RuntimeInputs, EvalContext, NamedDataSources } from './protocol.js';
|
|
2
|
+
export declare const pointerSegment: (value: string) => string;
|
|
3
|
+
/** Copy JSON without coercing dates, non-finite numbers, accessors, cycles or undefined to other values. */
|
|
4
|
+
export declare function snapshotJson<T>(input: T): T;
|
|
5
|
+
export declare function jsonObject(input: unknown, scope?: string): Record<string, unknown>;
|
|
6
|
+
export declare function validateInputSchema(schema: unknown): void;
|
|
7
|
+
export declare function validateData(schema: Record<string, unknown> | undefined, data: Record<string, unknown>, scope: 'root' | 'params'): void;
|
|
8
|
+
/** Defaults apply to a private print snapshot; null remains distinct from a missing property. */
|
|
9
|
+
/** Named JSON snapshots are supplied by the host; this module never fetches data. */
|
|
10
|
+
export declare function snapshotSources(input?: NamedDataSources): NamedDataSources;
|
|
11
|
+
export declare function preparePrintInputs(template: Template, data: unknown, options?: RuntimeInputs): EvalContext & {
|
|
12
|
+
params: Record<string, unknown>;
|
|
13
|
+
context: Record<string, unknown>;
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EvalContext, Expr } from './protocol.js';
|
|
2
|
+
export { decimalInput, formatDate, formatMoneyUpper, DATE_PATTERNS } from './formatting.js';
|
|
3
|
+
interface FunctionSpec {
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
capability: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const FUNCTION_SIGNATURES: Readonly<Record<string, FunctionSpec>>;
|
|
9
|
+
export declare function expressionLocation(expression: Expr, context: EvalContext): {
|
|
10
|
+
scope: string;
|
|
11
|
+
path: string;
|
|
12
|
+
} | undefined;
|
|
13
|
+
export declare function tableRowContext(context: EvalContext, source: Expr, row: Record<string, unknown>, index: number): EvalContext;
|
|
14
|
+
export declare function evaluate(expression: Expr, context: EvalContext, depth?: number): unknown;
|
|
15
|
+
export declare function evaluateRequired(expression: Expr, context: EvalContext): unknown;
|
|
16
|
+
export declare function evaluateText(expression: Expr, context: EvalContext): string;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// src/protocol.ts
|
|
2
|
+
var e = class extends Error {
|
|
3
|
+
code;
|
|
4
|
+
nodeId;
|
|
5
|
+
path;
|
|
6
|
+
details;
|
|
7
|
+
dataPath;
|
|
8
|
+
scope;
|
|
9
|
+
issues;
|
|
10
|
+
constructor(e, t, n, r, i) {
|
|
11
|
+
super(t), this.code = e, this.nodeId = n, this.path = r, this.details = i, this.name = "PrintError", this.dataPath = i?.dataPath, this.scope = i?.scope, this.issues = i?.issues;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
function t(t, n) {
|
|
15
|
+
if (!Number.isSafeInteger(t)) throw new e("INVALID_GEOMETRY", `${n} 必须为安全整数`);
|
|
16
|
+
}
|
|
17
|
+
function n(n, r) {
|
|
18
|
+
if (r <= 0n) throw new e("INVALID_GEOMETRY", "分母必须大于零");
|
|
19
|
+
let i = n < 0n ? -1n : 1n, a = n * i, o = Number(i * ((a + r / 2n) / r));
|
|
20
|
+
return t(o, "换算结果"), o;
|
|
21
|
+
}
|
|
22
|
+
var r = (e) => n(BigInt(e) * 25400n, 72000n), i = (e) => e * 72 / 25400, a = (e) => e / 1e3;
|
|
23
|
+
// src/font.ts
|
|
24
|
+
function o(t, n) {
|
|
25
|
+
if (!t || typeof t != "object" || Object.keys(t).some((e) => ![
|
|
26
|
+
"minSizeMpt",
|
|
27
|
+
"stepMpt",
|
|
28
|
+
"mode"
|
|
29
|
+
].includes(e)) || !Number.isSafeInteger(t.minSizeMpt) || t.minSizeMpt < 1e3 || t.minSizeMpt > 72e3 || t.stepMpt !== void 0 && (!Number.isSafeInteger(t.stepMpt) || t.stepMpt < 100 || t.stepMpt > 1e4) || t.mode !== void 0 && !["wrap", "single-line"].includes(t.mode) || n && t.minSizeMpt > n.sizeMpt) throw new e("TEXT_FIT_INVALID", "自适应最小字号需为 1–72 pt 且不大于初始字号,步长为 0.1–10 pt");
|
|
30
|
+
}
|
|
31
|
+
function s(t, n, r, i, a, s) {
|
|
32
|
+
if (!s) {
|
|
33
|
+
let e = x(t, n, i.sizeMpt, l(a, i), i.letterSpacingUm);
|
|
34
|
+
return {
|
|
35
|
+
lines: e,
|
|
36
|
+
style: _(i, a, e)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!Number.isSafeInteger(n) || !Number.isSafeInteger(r) || n < 1 || r < 1) throw new e("TEXT_FIT_INVALID", "文字自适应区域需为正整数");
|
|
40
|
+
o(s, i);
|
|
41
|
+
let c = s.stepMpt ?? 500, u = Math.floor((i.sizeMpt - s.minSizeMpt) / c), d = i.sizeMpt, f = (o) => {
|
|
42
|
+
let c = {
|
|
43
|
+
...i,
|
|
44
|
+
sizeMpt: o,
|
|
45
|
+
lineHeightMpt: Math.max(1e3, Math.round(i.lineHeightMpt * o / d))
|
|
46
|
+
}, u = l(a, c);
|
|
47
|
+
try {
|
|
48
|
+
let e = s.mode === "single-line" ? t.includes("\n") ? void 0 : [t] : x(t, n, o, u, c.letterSpacingUm);
|
|
49
|
+
return !e || e.some((e) => u.measure(e, o, c.letterSpacingUm) > n) || e.length * h(c, a, e.join("")).heightUm > r ? void 0 : {
|
|
50
|
+
lines: e,
|
|
51
|
+
style: _(c, a, e)
|
|
52
|
+
};
|
|
53
|
+
} catch (t) {
|
|
54
|
+
if (t instanceof e && t.code === "LAYOUT_OVERFLOW") return;
|
|
55
|
+
throw t;
|
|
56
|
+
}
|
|
57
|
+
}, p = f(d);
|
|
58
|
+
if (p) return p;
|
|
59
|
+
let m = 0, g = u, v;
|
|
60
|
+
for (; m <= g;) {
|
|
61
|
+
let e = Math.floor((m + g) / 2), t = f(s.minSizeMpt + e * c);
|
|
62
|
+
t ? (v = t, m = e + 1) : g = e - 1;
|
|
63
|
+
}
|
|
64
|
+
if (!v) throw new e("TEXT_FIT_FAILED", "缩到最小字号仍无法放入文字框,请增大尺寸或调整最小字号");
|
|
65
|
+
return v;
|
|
66
|
+
}
|
|
67
|
+
var c = "\"Microsoft YaHei\", \"PingFang SC\", \"Noto Sans CJK SC\", Arial, sans-serif", l = (e, t) => e.forStyle?.(t) ?? e;
|
|
68
|
+
function u(t) {
|
|
69
|
+
if (!Number.isSafeInteger(t) || t < -5e3 || t > 2e4) throw new e("TEXT_SPACING_INVALID", "字距需为 -5–20 mm 的整数微米值");
|
|
70
|
+
}
|
|
71
|
+
var d = new Intl.Segmenter("und", { granularity: "grapheme" }), f = new Intl.Segmenter("und", { granularity: "word" }), p = (e) => Array.from(d.segment(e), (e) => e.segment), m = (e) => Array.from(f.segment(e), (e) => e.segment);
|
|
72
|
+
function h(e, t, n = "") {
|
|
73
|
+
let r = l(t, e), i = n ? r.metrics?.(n, e.sizeMpt) : void 0, a = r.toUm(r.ascent - r.descent, e.sizeMpt), o = r.toUm(r.ascent, e.sizeMpt), s = a - o, c = i && i.ascentUm > o + 2 ? i.ascentUm : o, u = i && i.descentUm > s + 2 ? i.descentUm : s, d = Math.round(e.lineHeightMpt * 25400 / 72e3), f = r.system ? Math.max(d, c + u) : d;
|
|
74
|
+
return {
|
|
75
|
+
heightUm: f,
|
|
76
|
+
baselineUm: Math.round((f - c - u) / 2) + c
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function g(e, t) {
|
|
80
|
+
return h(e, t).heightUm;
|
|
81
|
+
}
|
|
82
|
+
function _(e, t, n) {
|
|
83
|
+
let r = h(e, t, n.join("")).heightUm;
|
|
84
|
+
return r > g(e, t) ? {
|
|
85
|
+
...e,
|
|
86
|
+
lineHeightMpt: Math.ceil(r * 72e3 / 25400)
|
|
87
|
+
} : e;
|
|
88
|
+
}
|
|
89
|
+
function v(t) {
|
|
90
|
+
if (typeof t != "string" || !t.trim() || t.length > 256 || /[;{}<>\\()@:\u0000-\u001f]/u.test(t) || [
|
|
91
|
+
"inherit",
|
|
92
|
+
"initial",
|
|
93
|
+
"unset",
|
|
94
|
+
"revert",
|
|
95
|
+
"revert-layer"
|
|
96
|
+
].includes(t.trim().toLowerCase())) throw new e("FONT_FAMILY_INVALID", "字体名称需要 1–256 字,不能包含样式代码或控制字符;继承字体请留空");
|
|
97
|
+
}
|
|
98
|
+
var y = /^[,。!?:;、)》】」』,.!?;:)]$/u, b = /[(《【「『(\[]$/u;
|
|
99
|
+
function x(t, n, r, i, a = 0) {
|
|
100
|
+
if (u(a), n <= 0) throw new e("LAYOUT_OVERFLOW", "文字可用宽度必须大于零");
|
|
101
|
+
let o = [];
|
|
102
|
+
for (let s of t.normalize("NFC").replace(/\r\n?/g, "\n").split("\n")) {
|
|
103
|
+
if (s === "") {
|
|
104
|
+
o.push("");
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
let t = "", c = m(s);
|
|
108
|
+
for (let s of c) if (!t && i.measure(s, r, a) <= n) t = s;
|
|
109
|
+
else if (t && i.measure(t + s, r, a) <= n) t += s;
|
|
110
|
+
else {
|
|
111
|
+
if (t && i.measure(s, r, a) <= n && !y.test(s)) {
|
|
112
|
+
let e = "";
|
|
113
|
+
if (b.test(t)) {
|
|
114
|
+
let n = p(t);
|
|
115
|
+
e = n.pop(), t = n.join("");
|
|
116
|
+
}
|
|
117
|
+
t && o.push(t.replace(/[ \t]+$/u, "")), t = e;
|
|
118
|
+
}
|
|
119
|
+
for (let c of p(s)) {
|
|
120
|
+
if (i.measure(c, r, a) > n) throw new e("LAYOUT_OVERFLOW", `单字宽度超过文字框:${c}`);
|
|
121
|
+
if (t && i.measure(t + c, r, a) > n) {
|
|
122
|
+
let s = "";
|
|
123
|
+
if (y.test(c) || b.test(t)) {
|
|
124
|
+
let e = p(t);
|
|
125
|
+
s = e.pop(), t = e.join("");
|
|
126
|
+
}
|
|
127
|
+
if (t && o.push(t.replace(/[ \t]+$/u, "")), t = s, i.measure(t + c, r, a) > n) throw new e("LAYOUT_OVERFLOW", "标点禁则需要更宽的文字框");
|
|
128
|
+
}
|
|
129
|
+
t += c;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
t && o.push(t.replace(/[ \t]+$/u, ""));
|
|
133
|
+
}
|
|
134
|
+
return o;
|
|
135
|
+
}
|
|
136
|
+
export { a as _, p as a, m as c, u as d, x as f, n as g, r as h, _ as i, o as l, t as m, s as n, h as o, e as p, l as r, g as s, c as t, v as u, i as v };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Opt-in historical file-font adapter. Web uses BrowserFont instead. */
|
|
2
|
+
export declare class PrintFont {
|
|
3
|
+
readonly bytes: Uint8Array;
|
|
4
|
+
readonly sha256: string;
|
|
5
|
+
readonly id = "font.body";
|
|
6
|
+
readonly family: string;
|
|
7
|
+
readonly unitsPerEm: number;
|
|
8
|
+
readonly ascent: number;
|
|
9
|
+
readonly descent: number;
|
|
10
|
+
private readonly font;
|
|
11
|
+
constructor(bytes: Uint8Array, sha256: string);
|
|
12
|
+
glyph(char: string): {
|
|
13
|
+
id: number;
|
|
14
|
+
advance: number;
|
|
15
|
+
};
|
|
16
|
+
toUm(fontUnits: number, sizeMpt: number): number;
|
|
17
|
+
measure(text: string, sizeMpt: number, letterSpacingUm?: number): number;
|
|
18
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { a as e, g as t, p as n } from "./font-ToGNY599.js";
|
|
2
|
+
import r from "@pdf-lib/fontkit";
|
|
3
|
+
// src/font-file.ts
|
|
4
|
+
var i = class {
|
|
5
|
+
bytes;
|
|
6
|
+
sha256;
|
|
7
|
+
id = "font.body";
|
|
8
|
+
family;
|
|
9
|
+
unitsPerEm;
|
|
10
|
+
ascent;
|
|
11
|
+
descent;
|
|
12
|
+
font;
|
|
13
|
+
constructor(e, t) {
|
|
14
|
+
if (this.bytes = e, this.sha256 = t, e.length < 12) throw new n("FONT_INVALID", "字体文件头不完整");
|
|
15
|
+
let i = new DataView(e.buffer, e.byteOffset, e.byteLength), a = String.fromCharCode(...e.subarray(0, 4));
|
|
16
|
+
if (a !== "OTTO" && a !== "true" && i.getUint32(0) !== 65536) throw new n("FONT_INVALID", "W2 支持独立 OTF/CFF1 和 TTF 字体,不支持字体集合");
|
|
17
|
+
let o = i.getUint16(4);
|
|
18
|
+
if (12 + o * 16 > e.length) throw new n("FONT_INVALID", "字体目录不完整");
|
|
19
|
+
for (let t = 0; t < o; t++) {
|
|
20
|
+
let r = 12 + t * 16, a = String.fromCharCode(...e.subarray(r, r + 4));
|
|
21
|
+
if (a === "fvar" || a === "CFF2") throw new n("FONT_UNSUPPORTED", "可变字体和 CFF2 留待后续 profile 实现");
|
|
22
|
+
if (i.getUint32(r + 8) + i.getUint32(r + 12) > e.length) throw new n("FONT_INVALID", "字体表越界");
|
|
23
|
+
}
|
|
24
|
+
this.font = r.create(e), this.family = this.font.familyName ?? "Noto Sans CJK SC", this.unitsPerEm = this.font.unitsPerEm, this.ascent = this.font.ascent, this.descent = this.font.descent;
|
|
25
|
+
}
|
|
26
|
+
glyph(e) {
|
|
27
|
+
let t = e.codePointAt(0);
|
|
28
|
+
if (!this.font.hasGlyphForCodePoint(t)) throw new n("FONT_GLYPH_MISSING", `字体缺字:${e} U+${t.toString(16).toUpperCase()}`);
|
|
29
|
+
if (!/^[\p{Script=Latin}\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Number}\p{Punctuation}\p{Symbol} ]$/u.test(e)) throw new n("W0_UNSUPPORTED_SHAPING", `W0 不支持该字符的 shaping:U+${t.toString(16).toUpperCase()}`);
|
|
30
|
+
let r = this.font.glyphForCodePoint(t);
|
|
31
|
+
return {
|
|
32
|
+
id: r.id,
|
|
33
|
+
advance: r.advanceWidth
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
toUm(e, n) {
|
|
37
|
+
return t(BigInt(e) * BigInt(n) * 25400n, BigInt(this.unitsPerEm) * 72000n);
|
|
38
|
+
}
|
|
39
|
+
measure(t, n, r = 0) {
|
|
40
|
+
let i = 0;
|
|
41
|
+
for (let e of t.normalize("NFC")) i += this.glyph(e).advance;
|
|
42
|
+
return Math.max(0, this.toUm(i, n) + e(t.normalize("NFC")).length * r);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export { i as PrintFont };
|
package/dist/font.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { TextStyle, TextAutoFit } from './protocol.js';
|
|
2
|
+
export declare function validateAutoFit(policy: TextAutoFit, style?: TextStyle): void;
|
|
3
|
+
/** Bounded, quantized binary search; a failed minimum size never truncates content. */
|
|
4
|
+
export declare function fitText(text: string, widthUm: number, heightUm: number, style: TextStyle, font: TextFont, policy?: TextAutoFit): {
|
|
5
|
+
lines: string[];
|
|
6
|
+
style: TextStyle;
|
|
7
|
+
};
|
|
8
|
+
export declare const DEFAULT_FONT_FAMILY = "\"Microsoft YaHei\", \"PingFang SC\", \"Noto Sans CJK SC\", Arial, sans-serif";
|
|
9
|
+
/** Layout consumes measurements; Web implementations resolve installed browser fonts. */
|
|
10
|
+
export interface TextFont {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly family: string;
|
|
13
|
+
readonly sha256: string;
|
|
14
|
+
readonly unitsPerEm: number;
|
|
15
|
+
readonly ascent: number;
|
|
16
|
+
readonly descent: number;
|
|
17
|
+
readonly system?: boolean;
|
|
18
|
+
glyph(char: string): {
|
|
19
|
+
id: number;
|
|
20
|
+
advance: number;
|
|
21
|
+
};
|
|
22
|
+
toUm(units: number, sizeMpt: number): number;
|
|
23
|
+
measure(text: string, sizeMpt: number, letterSpacingUm?: number): number;
|
|
24
|
+
metrics?(text: string, sizeMpt: number): {
|
|
25
|
+
ascentUm: number;
|
|
26
|
+
descentUm: number;
|
|
27
|
+
};
|
|
28
|
+
forStyle?(style: Partial<TextStyle>): TextFont;
|
|
29
|
+
}
|
|
30
|
+
export declare const fontForStyle: (font: TextFont, style: Partial<TextStyle>) => TextFont;
|
|
31
|
+
export declare function validateLetterSpacing(value: unknown): asserts value is number;
|
|
32
|
+
/** Extended grapheme clusters keep combining marks, emoji ZWJ and Indic conjuncts intact. */
|
|
33
|
+
export declare const textGraphemes: (text: string) => string[];
|
|
34
|
+
export declare const textWords: (text: string) => string[];
|
|
35
|
+
export declare function textLineBox(style: TextStyle, font: TextFont, text?: string): {
|
|
36
|
+
heightUm: number;
|
|
37
|
+
baselineUm: number;
|
|
38
|
+
};
|
|
39
|
+
export declare function textLineHeight(style: TextStyle, font: TextFont): number;
|
|
40
|
+
/** Freeze the measured fallback-font line box before pagination or a row is split. */
|
|
41
|
+
export declare function measuredTextStyle(style: TextStyle, font: TextFont, lines: readonly string[]): TextStyle;
|
|
42
|
+
export declare function validateFontFamily(value: unknown): asserts value is string;
|
|
43
|
+
/** Word boundaries use the runtime Unicode dictionary; emergency wrapping never splits a grapheme. */
|
|
44
|
+
export declare function wrapText(text: string, widthUm: number, sizeMpt: number, font: TextFont, letterSpacingUm?: number): string[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Decimal } from 'decimal.js';
|
|
2
|
+
export declare function decimalInput(value: unknown): Decimal;
|
|
3
|
+
export declare function decimalScale(value: unknown): number;
|
|
4
|
+
export declare function roundMode(value: unknown): void;
|
|
5
|
+
export declare const DATE_PATTERNS: readonly ["yyyy-MM-dd", "yyyy/MM/dd", "yyyy年MM月dd日", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "HH:mm", "HH:mm:ss"];
|
|
6
|
+
export declare function formatDate(value: unknown, pattern: unknown): string;
|
|
7
|
+
/** RMB, rounded to cents away from zero at a tie; up to 999999999999.99 after rounding. */
|
|
8
|
+
export declare function formatMoneyUpper(value: unknown): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PrintRegistry } from './plugins.js';
|
|
2
|
+
export declare const FUNCTION_NAME_PATTERN: RegExp;
|
|
3
|
+
export interface PrintFunction {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
capability: string;
|
|
7
|
+
minArgs: number;
|
|
8
|
+
maxArgs: number;
|
|
9
|
+
/** JSON Schema for the argument array, validated before executing host code. */
|
|
10
|
+
argsSchema?: Record<string, unknown>;
|
|
11
|
+
maxInputChars?: number;
|
|
12
|
+
maxOutputChars?: number;
|
|
13
|
+
/** Synchronous host code. Arguments are private, recursively frozen JSON copies. */
|
|
14
|
+
execute: (args: readonly unknown[]) => unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface FunctionSignature {
|
|
17
|
+
min: number;
|
|
18
|
+
max: number;
|
|
19
|
+
capability: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function executePrintFunction(def: PrintFunction, args: unknown[]): unknown;
|
|
22
|
+
export declare function customFunctionSignature(id: string, registry?: PrintRegistry): FunctionSignature | undefined;
|
package/dist/html.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TextStyle, ImageResource, PathShape } from './protocol.js';
|
|
2
|
+
import type { RichTextContent } from './rich-text.js';
|
|
3
|
+
export interface ConversionIssue {
|
|
4
|
+
code: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseColor(value: string): string | null;
|
|
8
|
+
export declare function htmlToRichText(html: string, options?: {
|
|
9
|
+
style?: TextStyle;
|
|
10
|
+
images?: readonly ImageResource[];
|
|
11
|
+
}): {
|
|
12
|
+
content: RichTextContent;
|
|
13
|
+
images: ImageResource[];
|
|
14
|
+
issues: ConversionIssue[];
|
|
15
|
+
};
|
|
16
|
+
export declare function svgToPaths(svg: string): {
|
|
17
|
+
viewBox: [number, number, number, number];
|
|
18
|
+
paths: PathShape[];
|
|
19
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { LabelImposition, LayoutDocument, Media } from './protocol.js';
|
|
2
|
+
export declare function validateImposition(c: LabelImposition, media?: readonly Media[]): void;
|
|
3
|
+
/** Translate whole logical label pages without scaling modules or their quiet zones. */
|
|
4
|
+
export declare function imposeLabels(layout: LayoutDocument, c?: LabelImposition): LayoutDocument;
|