@twinfinity/printing 6.0.1-ci.28952-beta → 6.0.2-beta

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 (82) hide show
  1. package/README.md +3 -3
  2. package/dist/BuildInfo.js +3 -3
  3. package/dist/BuildInfo.js.map +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/layout/analyzeTemplate.js.map +1 -1
  6. package/dist/layout/clipUtils.js.map +1 -1
  7. package/dist/layout/colorConstants.js.map +1 -1
  8. package/dist/layout/elementKinds.js.map +1 -1
  9. package/dist/layout/exportDrawing.js.map +1 -1
  10. package/dist/layout/filters.js.map +1 -1
  11. package/dist/layout/geometryConstants.js.map +1 -1
  12. package/dist/layout/index.js.map +1 -1
  13. package/dist/layout/itemBuilders.js.map +1 -1
  14. package/dist/layout/labelsRender.js.map +1 -1
  15. package/dist/layout/legendConstants.js.map +1 -1
  16. package/dist/layout/legendRender.js.map +1 -1
  17. package/dist/layout/legendRows.js.map +1 -1
  18. package/dist/layout/legendUtils.js.map +1 -1
  19. package/dist/layout/metadata.js.map +1 -1
  20. package/dist/layout/model.js.map +1 -1
  21. package/dist/layout/options.js.map +1 -1
  22. package/dist/layout/presets.js.map +1 -1
  23. package/dist/layout/qrRender.js.map +1 -1
  24. package/dist/layout/renderDrawing.js.map +1 -1
  25. package/dist/layout/renderUtils.js.map +1 -1
  26. package/dist/layout/sectionValidation.js.map +1 -1
  27. package/dist/layout/templateVariables.js.map +1 -1
  28. package/dist/layout/typeGuards.js.map +1 -1
  29. package/dist/layout/types.js.map +1 -1
  30. package/dist/layout/utils.js.map +1 -1
  31. package/dist/layout/validation.js.map +1 -1
  32. package/dist/layout/validationHelpers.js.map +1 -1
  33. package/dist/layout/validationUtils.js.map +1 -1
  34. package/dist/layout/viewportPrep.js.map +1 -1
  35. package/dist/layout/viewportRender.js.map +1 -1
  36. package/dist/layout/viewportUtils.js.map +1 -1
  37. package/dist/layout/warnings.js.map +1 -1
  38. package/dist/printToPdf.js.map +1 -1
  39. package/dist/printToSvg.js.map +1 -1
  40. package/dist/sections.js.map +1 -1
  41. package/dist/types.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/BuildInfo.ts +41 -41
  44. package/src/index.ts +10 -10
  45. package/src/layout/analyzeTemplate.ts +218 -218
  46. package/src/layout/clipUtils.ts +193 -193
  47. package/src/layout/colorConstants.ts +16 -16
  48. package/src/layout/elementKinds.ts +35 -35
  49. package/src/layout/exportDrawing.ts +206 -206
  50. package/src/layout/filters.ts +80 -80
  51. package/src/layout/geometryConstants.ts +11 -11
  52. package/src/layout/index.ts +671 -671
  53. package/src/layout/itemBuilders.ts +159 -159
  54. package/src/layout/labelsRender.ts +170 -170
  55. package/src/layout/legendConstants.ts +11 -11
  56. package/src/layout/legendRender.ts +543 -543
  57. package/src/layout/legendRows.ts +62 -62
  58. package/src/layout/legendUtils.ts +144 -144
  59. package/src/layout/metadata.ts +210 -210
  60. package/src/layout/model.ts +372 -372
  61. package/src/layout/options.ts +17 -17
  62. package/src/layout/presets.ts +51 -51
  63. package/src/layout/qrRender.ts +126 -126
  64. package/src/layout/qrcode.d.ts +2 -2
  65. package/src/layout/renderDrawing.ts +710 -710
  66. package/src/layout/renderUtils.ts +138 -138
  67. package/src/layout/sectionValidation.ts +2 -2
  68. package/src/layout/templateVariables.ts +317 -317
  69. package/src/layout/typeGuards.ts +9 -9
  70. package/src/layout/types.ts +835 -835
  71. package/src/layout/utils.ts +85 -85
  72. package/src/layout/validation.ts +392 -392
  73. package/src/layout/validationHelpers.ts +59 -59
  74. package/src/layout/validationUtils.ts +6 -6
  75. package/src/layout/viewportPrep.ts +351 -351
  76. package/src/layout/viewportRender.ts +442 -442
  77. package/src/layout/viewportUtils.ts +50 -50
  78. package/src/layout/warnings.ts +3 -3
  79. package/src/printToPdf.ts +108 -108
  80. package/src/printToSvg.ts +188 -188
  81. package/src/sections.ts +1019 -1019
  82. package/src/types.ts +49 -49
@@ -1,218 +1,218 @@
1
- import { normalizeClass } from './filters';
2
- import type {
3
- LayoutTemplate,
4
- LayoutElement,
5
- ViewportElement,
6
- TextElement,
7
- ImageElement,
8
- QrElement,
9
- LabelsElement,
10
- LegendElement,
11
- GroupElement,
12
- ScaleBarElement,
13
- WhereCondition
14
- } from './types';
15
-
16
- /**
17
- * Describes the input requirements inferred from a layout template.
18
- * Use `analyzeTemplate()` to scan a template and discover what data it needs.
19
- */
20
- export interface TemplateRequirements {
21
- /** Viewport IDs the template declares. */
22
- viewportIds: string[];
23
-
24
- /** Property paths referenced by legends, where-filters, and labels.
25
- * Short-path format: "SetName.propName" (e.g. "BIP.spacename"). */
26
- propertyPaths: string[];
27
-
28
- /** Class filters referenced (e.g. "space", "walls"). Already lowercase. */
29
- classFilters: string[];
30
-
31
- /** Asset IDs referenced by image/northArrow elements. */
32
- assetIds: string[];
33
-
34
- /** Text interpolation variables (e.g. "viewport.main.scaleText"). */
35
- interpolationVars: string[];
36
-
37
- /** Whether the template references remote (http/https) asset URLs. */
38
- usesRemoteAssets: boolean;
39
- }
40
-
41
- const INTERPOLATION_RE = /\{\{\s*([^}]+?)\s*\}\}/g;
42
-
43
- /** Extract `{{path}}` tokens from a template string. */
44
- function extractInterpolationVars(text: string): string[] {
45
- const vars: string[] = [];
46
- let m: RegExpExecArray | null;
47
- INTERPOLATION_RE.lastIndex = 0;
48
- while ((m = INTERPOLATION_RE.exec(text)) !== null) {
49
- vars.push(m[1]);
50
- }
51
- return vars;
52
- }
53
-
54
- /** Collect keys from a WhereCondition (each key is a property short-path). */
55
- function collectWherePaths(where: WhereCondition | undefined, out: Set<string>): void {
56
- if (!where || typeof where !== 'object') return;
57
- for (const key of Object.keys(where)) {
58
- out.add(key);
59
- }
60
- }
61
-
62
- /** Collect class filter values, normalizing to lowercase. */
63
- function collectClassFilter(classFilter: string | string[] | undefined, out: Set<string>): void {
64
- if (!classFilter) return;
65
- const classes = Array.isArray(classFilter) ? classFilter : [classFilter];
66
- for (const c of classes) {
67
- const normalized = normalizeClass(c);
68
- if (normalized) out.add(normalized);
69
- }
70
- }
71
-
72
- /**
73
- * Scan a layout template and return its input requirements.
74
- *
75
- * This is a pure, read-only analysis — it does not modify the template or
76
- * perform any rendering. Use the result to validate inputs before calling
77
- * `renderDrawing()` or `renderLayout()`.
78
- */
79
- export function analyzeTemplate(template: LayoutTemplate): TemplateRequirements {
80
- const viewportIds = new Set<string>();
81
- const propertyPaths = new Set<string>();
82
- const classFilters = new Set<string>();
83
- const assetIds = new Set<string>();
84
- const interpolationVars = new Set<string>();
85
- let usesRemoteAssets = false;
86
-
87
- // Check assets for remote URLs
88
- if (template.assets) {
89
- for (const asset of template.assets) {
90
- if (asset.src && /^https?:\/\//i.test(asset.src)) {
91
- usesRemoteAssets = true;
92
- }
93
- }
94
- }
95
-
96
- // Walk all elements (recursing into groups)
97
- const walk = (elements: LayoutElement[]): void => {
98
- for (const el of elements) {
99
- switch (el.kind) {
100
- case 'viewport': {
101
- const vp = el as ViewportElement;
102
- viewportIds.add(vp.id);
103
-
104
- // Clip filter
105
- if (vp.clip) {
106
- collectClassFilter(vp.clip.class, classFilters);
107
- collectWherePaths(vp.clip.where, propertyPaths);
108
- }
109
-
110
- // Highlight filter
111
- if (vp.highlight) {
112
- collectClassFilter(vp.highlight.class, classFilters);
113
- collectWherePaths(vp.highlight.where, propertyPaths);
114
- }
115
-
116
- // includeClasses
117
- if (vp.includeClasses) {
118
- if (Array.isArray(vp.includeClasses)) {
119
- for (const c of vp.includeClasses) {
120
- const normalized = normalizeClass(c);
121
- if (normalized) classFilters.add(normalized);
122
- }
123
- }
124
- // Preset references are resolved at render time, nothing to collect
125
- }
126
-
127
- // North arrow asset
128
- if (vp.northArrow?.assetId) {
129
- assetIds.add(vp.northArrow.assetId);
130
- }
131
- break;
132
- }
133
-
134
- case 'text': {
135
- const txt = el as TextElement;
136
- if (txt.text) {
137
- for (const v of extractInterpolationVars(txt.text)) {
138
- interpolationVars.add(v);
139
- }
140
- }
141
- break;
142
- }
143
-
144
- case 'image': {
145
- const img = el as ImageElement;
146
- if (img.assetId) assetIds.add(img.assetId);
147
- break;
148
- }
149
-
150
- case 'qr': {
151
- const qr = el as QrElement;
152
- if (qr.dataTemplate) {
153
- for (const v of extractInterpolationVars(qr.dataTemplate)) {
154
- interpolationVars.add(v);
155
- }
156
- }
157
- break;
158
- }
159
-
160
- case 'labels': {
161
- const sl = el as LabelsElement;
162
- collectClassFilter(sl.class, classFilters);
163
- collectWherePaths(sl.where, propertyPaths);
164
-
165
- // Extract property paths from text interpolation (skip viewport.* which are computed)
166
- if (sl.text) {
167
- for (const v of extractInterpolationVars(sl.text)) {
168
- if (!v.startsWith('viewport.')) {
169
- propertyPaths.add(v);
170
- } else {
171
- interpolationVars.add(v);
172
- }
173
- }
174
- }
175
- break;
176
- }
177
-
178
- case 'legend': {
179
- const leg = el as LegendElement;
180
- collectClassFilter(leg.class, classFilters);
181
- collectWherePaths(leg.where, propertyPaths);
182
-
183
- // Column property paths
184
- if (leg.columns) {
185
- for (const col of leg.columns) {
186
- if (col.property) propertyPaths.add(col.property);
187
- }
188
- }
189
- break;
190
- }
191
-
192
- case 'scaleBar': {
193
- // scaleBar references a viewport by ID (informational)
194
- const sb = el as ScaleBarElement;
195
- if (sb.viewport) viewportIds.add(sb.viewport);
196
- break;
197
- }
198
-
199
- case 'group': {
200
- const grp = el as GroupElement;
201
- if (grp.children) walk(grp.children);
202
- break;
203
- }
204
- }
205
- }
206
- };
207
-
208
- walk(template.elements);
209
-
210
- return {
211
- viewportIds: [...viewportIds],
212
- propertyPaths: [...propertyPaths],
213
- classFilters: [...classFilters],
214
- assetIds: [...assetIds],
215
- interpolationVars: [...interpolationVars],
216
- usesRemoteAssets
217
- };
218
- }
1
+ import { normalizeClass } from './filters';
2
+ import type {
3
+ LayoutTemplate,
4
+ LayoutElement,
5
+ ViewportElement,
6
+ TextElement,
7
+ ImageElement,
8
+ QrElement,
9
+ LabelsElement,
10
+ LegendElement,
11
+ GroupElement,
12
+ ScaleBarElement,
13
+ WhereCondition
14
+ } from './types';
15
+
16
+ /**
17
+ * Describes the input requirements inferred from a layout template.
18
+ * Use `analyzeTemplate()` to scan a template and discover what data it needs.
19
+ */
20
+ export interface TemplateRequirements {
21
+ /** Viewport IDs the template declares. */
22
+ viewportIds: string[];
23
+
24
+ /** Property paths referenced by legends, where-filters, and labels.
25
+ * Short-path format: "SetName.propName" (e.g. "BIP.spacename"). */
26
+ propertyPaths: string[];
27
+
28
+ /** Class filters referenced (e.g. "space", "walls"). Already lowercase. */
29
+ classFilters: string[];
30
+
31
+ /** Asset IDs referenced by image/northArrow elements. */
32
+ assetIds: string[];
33
+
34
+ /** Text interpolation variables (e.g. "viewport.main.scaleText"). */
35
+ interpolationVars: string[];
36
+
37
+ /** Whether the template references remote (http/https) asset URLs. */
38
+ usesRemoteAssets: boolean;
39
+ }
40
+
41
+ const INTERPOLATION_RE = /\{\{\s*([^}]+?)\s*\}\}/g;
42
+
43
+ /** Extract `{{path}}` tokens from a template string. */
44
+ function extractInterpolationVars(text: string): string[] {
45
+ const vars: string[] = [];
46
+ let m: RegExpExecArray | null;
47
+ INTERPOLATION_RE.lastIndex = 0;
48
+ while ((m = INTERPOLATION_RE.exec(text)) !== null) {
49
+ vars.push(m[1]);
50
+ }
51
+ return vars;
52
+ }
53
+
54
+ /** Collect keys from a WhereCondition (each key is a property short-path). */
55
+ function collectWherePaths(where: WhereCondition | undefined, out: Set<string>): void {
56
+ if (!where || typeof where !== 'object') return;
57
+ for (const key of Object.keys(where)) {
58
+ out.add(key);
59
+ }
60
+ }
61
+
62
+ /** Collect class filter values, normalizing to lowercase. */
63
+ function collectClassFilter(classFilter: string | string[] | undefined, out: Set<string>): void {
64
+ if (!classFilter) return;
65
+ const classes = Array.isArray(classFilter) ? classFilter : [classFilter];
66
+ for (const c of classes) {
67
+ const normalized = normalizeClass(c);
68
+ if (normalized) out.add(normalized);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Scan a layout template and return its input requirements.
74
+ *
75
+ * This is a pure, read-only analysis — it does not modify the template or
76
+ * perform any rendering. Use the result to validate inputs before calling
77
+ * `renderDrawing()` or `renderLayout()`.
78
+ */
79
+ export function analyzeTemplate(template: LayoutTemplate): TemplateRequirements {
80
+ const viewportIds = new Set<string>();
81
+ const propertyPaths = new Set<string>();
82
+ const classFilters = new Set<string>();
83
+ const assetIds = new Set<string>();
84
+ const interpolationVars = new Set<string>();
85
+ let usesRemoteAssets = false;
86
+
87
+ // Check assets for remote URLs
88
+ if (template.assets) {
89
+ for (const asset of template.assets) {
90
+ if (asset.src && /^https?:\/\//i.test(asset.src)) {
91
+ usesRemoteAssets = true;
92
+ }
93
+ }
94
+ }
95
+
96
+ // Walk all elements (recursing into groups)
97
+ const walk = (elements: LayoutElement[]): void => {
98
+ for (const el of elements) {
99
+ switch (el.kind) {
100
+ case 'viewport': {
101
+ const vp = el as ViewportElement;
102
+ viewportIds.add(vp.id);
103
+
104
+ // Clip filter
105
+ if (vp.clip) {
106
+ collectClassFilter(vp.clip.class, classFilters);
107
+ collectWherePaths(vp.clip.where, propertyPaths);
108
+ }
109
+
110
+ // Highlight filter
111
+ if (vp.highlight) {
112
+ collectClassFilter(vp.highlight.class, classFilters);
113
+ collectWherePaths(vp.highlight.where, propertyPaths);
114
+ }
115
+
116
+ // includeClasses
117
+ if (vp.includeClasses) {
118
+ if (Array.isArray(vp.includeClasses)) {
119
+ for (const c of vp.includeClasses) {
120
+ const normalized = normalizeClass(c);
121
+ if (normalized) classFilters.add(normalized);
122
+ }
123
+ }
124
+ // Preset references are resolved at render time, nothing to collect
125
+ }
126
+
127
+ // North arrow asset
128
+ if (vp.northArrow?.assetId) {
129
+ assetIds.add(vp.northArrow.assetId);
130
+ }
131
+ break;
132
+ }
133
+
134
+ case 'text': {
135
+ const txt = el as TextElement;
136
+ if (txt.text) {
137
+ for (const v of extractInterpolationVars(txt.text)) {
138
+ interpolationVars.add(v);
139
+ }
140
+ }
141
+ break;
142
+ }
143
+
144
+ case 'image': {
145
+ const img = el as ImageElement;
146
+ if (img.assetId) assetIds.add(img.assetId);
147
+ break;
148
+ }
149
+
150
+ case 'qr': {
151
+ const qr = el as QrElement;
152
+ if (qr.dataTemplate) {
153
+ for (const v of extractInterpolationVars(qr.dataTemplate)) {
154
+ interpolationVars.add(v);
155
+ }
156
+ }
157
+ break;
158
+ }
159
+
160
+ case 'labels': {
161
+ const sl = el as LabelsElement;
162
+ collectClassFilter(sl.class, classFilters);
163
+ collectWherePaths(sl.where, propertyPaths);
164
+
165
+ // Extract property paths from text interpolation (skip viewport.* which are computed)
166
+ if (sl.text) {
167
+ for (const v of extractInterpolationVars(sl.text)) {
168
+ if (!v.startsWith('viewport.')) {
169
+ propertyPaths.add(v);
170
+ } else {
171
+ interpolationVars.add(v);
172
+ }
173
+ }
174
+ }
175
+ break;
176
+ }
177
+
178
+ case 'legend': {
179
+ const leg = el as LegendElement;
180
+ collectClassFilter(leg.class, classFilters);
181
+ collectWherePaths(leg.where, propertyPaths);
182
+
183
+ // Column property paths
184
+ if (leg.columns) {
185
+ for (const col of leg.columns) {
186
+ if (col.property) propertyPaths.add(col.property);
187
+ }
188
+ }
189
+ break;
190
+ }
191
+
192
+ case 'scaleBar': {
193
+ // scaleBar references a viewport by ID (informational)
194
+ const sb = el as ScaleBarElement;
195
+ if (sb.viewport) viewportIds.add(sb.viewport);
196
+ break;
197
+ }
198
+
199
+ case 'group': {
200
+ const grp = el as GroupElement;
201
+ if (grp.children) walk(grp.children);
202
+ break;
203
+ }
204
+ }
205
+ }
206
+ };
207
+
208
+ walk(template.elements);
209
+
210
+ return {
211
+ viewportIds: [...viewportIds],
212
+ propertyPaths: [...propertyPaths],
213
+ classFilters: [...classFilters],
214
+ assetIds: [...assetIds],
215
+ interpolationVars: [...interpolationVars],
216
+ usesRemoteAssets
217
+ };
218
+ }