@liasse/core 0.1.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.
- package/dist/index.d.ts +473 -0
- package/dist/index.js +286 -0
- package/dist/index.js.map +1 -0
- package/package.json +34 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* zod is the source of truth: every model type is inferred from a schema here,
|
|
5
|
+
* and the same schemas validate API payloads later. Nothing in this file may
|
|
6
|
+
* import an office library — the model is format-agnostic by construction.
|
|
7
|
+
*/
|
|
8
|
+
/** How a scalar value should be presented by an adapter. */
|
|
9
|
+
declare const ValueFormatSchema: z.ZodEnum<["text", "number", "currency", "percent", "date"]>;
|
|
10
|
+
type ValueFormat = z.infer<typeof ValueFormatSchema>;
|
|
11
|
+
declare const AlignSchema: z.ZodEnum<["left", "center", "right"]>;
|
|
12
|
+
type Align = z.infer<typeof AlignSchema>;
|
|
13
|
+
/** A buffer (Node/browser binary) or a string source (url / data-uri / path). */
|
|
14
|
+
declare const BinaryOrUrlSchema: z.ZodType<Uint8Array | string>;
|
|
15
|
+
declare const HeadingBlockSchema: z.ZodObject<{
|
|
16
|
+
type: z.ZodLiteral<"heading">;
|
|
17
|
+
text: z.ZodString;
|
|
18
|
+
level: z.ZodUnion<[z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>]>;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
text: string;
|
|
21
|
+
type: "heading";
|
|
22
|
+
level: 1 | 2 | 3;
|
|
23
|
+
}, {
|
|
24
|
+
text: string;
|
|
25
|
+
type: "heading";
|
|
26
|
+
level: 1 | 2 | 3;
|
|
27
|
+
}>;
|
|
28
|
+
type HeadingBlock = z.infer<typeof HeadingBlockSchema>;
|
|
29
|
+
declare const ParagraphBlockSchema: z.ZodObject<{
|
|
30
|
+
type: z.ZodLiteral<"paragraph">;
|
|
31
|
+
text: z.ZodString;
|
|
32
|
+
emphasis: z.ZodOptional<z.ZodBoolean>;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
text: string;
|
|
35
|
+
type: "paragraph";
|
|
36
|
+
emphasis?: boolean | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
text: string;
|
|
39
|
+
type: "paragraph";
|
|
40
|
+
emphasis?: boolean | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
type ParagraphBlock = z.infer<typeof ParagraphBlockSchema>;
|
|
43
|
+
declare const TableColumnSchema: z.ZodObject<{
|
|
44
|
+
key: z.ZodString;
|
|
45
|
+
header: z.ZodString;
|
|
46
|
+
format: z.ZodOptional<z.ZodEnum<["text", "number", "currency", "percent", "date"]>>;
|
|
47
|
+
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
48
|
+
/** Optional explicit column width (character units). */
|
|
49
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
key: string;
|
|
52
|
+
header: string;
|
|
53
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
54
|
+
align?: "left" | "center" | "right" | undefined;
|
|
55
|
+
width?: number | undefined;
|
|
56
|
+
}, {
|
|
57
|
+
key: string;
|
|
58
|
+
header: string;
|
|
59
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
60
|
+
align?: "left" | "center" | "right" | undefined;
|
|
61
|
+
width?: number | undefined;
|
|
62
|
+
}>;
|
|
63
|
+
type TableColumn = z.infer<typeof TableColumnSchema>;
|
|
64
|
+
declare const SummarySchema: z.ZodRecord<z.ZodString, z.ZodEnum<["sum", "avg", "count"]>>;
|
|
65
|
+
type Summary = z.infer<typeof SummarySchema>;
|
|
66
|
+
declare const ConditionalSchema: z.ZodObject<{
|
|
67
|
+
column: z.ZodString;
|
|
68
|
+
rule: z.ZodLiteral<"positiveNegative">;
|
|
69
|
+
}, "strip", z.ZodTypeAny, {
|
|
70
|
+
column: string;
|
|
71
|
+
rule: "positiveNegative";
|
|
72
|
+
}, {
|
|
73
|
+
column: string;
|
|
74
|
+
rule: "positiveNegative";
|
|
75
|
+
}>;
|
|
76
|
+
type Conditional = z.infer<typeof ConditionalSchema>;
|
|
77
|
+
declare const TableBlockSchema: z.ZodObject<{
|
|
78
|
+
type: z.ZodLiteral<"table">;
|
|
79
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
80
|
+
key: z.ZodString;
|
|
81
|
+
header: z.ZodString;
|
|
82
|
+
format: z.ZodOptional<z.ZodEnum<["text", "number", "currency", "percent", "date"]>>;
|
|
83
|
+
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
84
|
+
/** Optional explicit column width (character units). */
|
|
85
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
}, "strip", z.ZodTypeAny, {
|
|
87
|
+
key: string;
|
|
88
|
+
header: string;
|
|
89
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
90
|
+
align?: "left" | "center" | "right" | undefined;
|
|
91
|
+
width?: number | undefined;
|
|
92
|
+
}, {
|
|
93
|
+
key: string;
|
|
94
|
+
header: string;
|
|
95
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
96
|
+
align?: "left" | "center" | "right" | undefined;
|
|
97
|
+
width?: number | undefined;
|
|
98
|
+
}>, "many">;
|
|
99
|
+
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
100
|
+
/** Per-column aggregate → emits a summary row with real formulas. */
|
|
101
|
+
summary: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<["sum", "avg", "count"]>>>;
|
|
102
|
+
/** Colour cues, e.g. positive in green / negative in red. */
|
|
103
|
+
conditional: z.ZodOptional<z.ZodObject<{
|
|
104
|
+
column: z.ZodString;
|
|
105
|
+
rule: z.ZodLiteral<"positiveNegative">;
|
|
106
|
+
}, "strip", z.ZodTypeAny, {
|
|
107
|
+
column: string;
|
|
108
|
+
rule: "positiveNegative";
|
|
109
|
+
}, {
|
|
110
|
+
column: string;
|
|
111
|
+
rule: "positiveNegative";
|
|
112
|
+
}>>;
|
|
113
|
+
/** Format-specific escape hatch, read only by the xlsx adapter. */
|
|
114
|
+
xlsx: z.ZodOptional<z.ZodObject<{
|
|
115
|
+
freezeHeader: z.ZodOptional<z.ZodBoolean>;
|
|
116
|
+
sheetName: z.ZodOptional<z.ZodString>;
|
|
117
|
+
}, "strip", z.ZodTypeAny, {
|
|
118
|
+
freezeHeader?: boolean | undefined;
|
|
119
|
+
sheetName?: string | undefined;
|
|
120
|
+
}, {
|
|
121
|
+
freezeHeader?: boolean | undefined;
|
|
122
|
+
sheetName?: string | undefined;
|
|
123
|
+
}>>;
|
|
124
|
+
}, "strip", z.ZodTypeAny, {
|
|
125
|
+
type: "table";
|
|
126
|
+
columns: {
|
|
127
|
+
key: string;
|
|
128
|
+
header: string;
|
|
129
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
130
|
+
align?: "left" | "center" | "right" | undefined;
|
|
131
|
+
width?: number | undefined;
|
|
132
|
+
}[];
|
|
133
|
+
rows: Record<string, unknown>[];
|
|
134
|
+
summary?: Record<string, "sum" | "avg" | "count"> | undefined;
|
|
135
|
+
conditional?: {
|
|
136
|
+
column: string;
|
|
137
|
+
rule: "positiveNegative";
|
|
138
|
+
} | undefined;
|
|
139
|
+
xlsx?: {
|
|
140
|
+
freezeHeader?: boolean | undefined;
|
|
141
|
+
sheetName?: string | undefined;
|
|
142
|
+
} | undefined;
|
|
143
|
+
}, {
|
|
144
|
+
type: "table";
|
|
145
|
+
columns: {
|
|
146
|
+
key: string;
|
|
147
|
+
header: string;
|
|
148
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
149
|
+
align?: "left" | "center" | "right" | undefined;
|
|
150
|
+
width?: number | undefined;
|
|
151
|
+
}[];
|
|
152
|
+
rows: Record<string, unknown>[];
|
|
153
|
+
summary?: Record<string, "sum" | "avg" | "count"> | undefined;
|
|
154
|
+
conditional?: {
|
|
155
|
+
column: string;
|
|
156
|
+
rule: "positiveNegative";
|
|
157
|
+
} | undefined;
|
|
158
|
+
xlsx?: {
|
|
159
|
+
freezeHeader?: boolean | undefined;
|
|
160
|
+
sheetName?: string | undefined;
|
|
161
|
+
} | undefined;
|
|
162
|
+
}>;
|
|
163
|
+
type TableBlock = z.infer<typeof TableBlockSchema>;
|
|
164
|
+
declare const KeyValueBlockSchema: z.ZodObject<{
|
|
165
|
+
type: z.ZodLiteral<"keyValue">;
|
|
166
|
+
items: z.ZodArray<z.ZodObject<{
|
|
167
|
+
label: z.ZodString;
|
|
168
|
+
value: z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
169
|
+
format: z.ZodOptional<z.ZodEnum<["text", "number", "currency", "percent", "date"]>>;
|
|
170
|
+
}, "strip", z.ZodTypeAny, {
|
|
171
|
+
value: string | number | boolean | null;
|
|
172
|
+
label: string;
|
|
173
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
174
|
+
}, {
|
|
175
|
+
value: string | number | boolean | null;
|
|
176
|
+
label: string;
|
|
177
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
178
|
+
}>, "many">;
|
|
179
|
+
}, "strip", z.ZodTypeAny, {
|
|
180
|
+
type: "keyValue";
|
|
181
|
+
items: {
|
|
182
|
+
value: string | number | boolean | null;
|
|
183
|
+
label: string;
|
|
184
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
185
|
+
}[];
|
|
186
|
+
}, {
|
|
187
|
+
type: "keyValue";
|
|
188
|
+
items: {
|
|
189
|
+
value: string | number | boolean | null;
|
|
190
|
+
label: string;
|
|
191
|
+
format?: "number" | "text" | "currency" | "percent" | "date" | undefined;
|
|
192
|
+
}[];
|
|
193
|
+
}>;
|
|
194
|
+
type KeyValueBlock = z.infer<typeof KeyValueBlockSchema>;
|
|
195
|
+
declare const ChartBlockSchema: z.ZodObject<{
|
|
196
|
+
type: z.ZodLiteral<"chart">;
|
|
197
|
+
chartType: z.ZodEnum<["bar", "line", "pie"]>;
|
|
198
|
+
data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
|
|
199
|
+
/** Key used for the category axis. */
|
|
200
|
+
x: z.ZodString;
|
|
201
|
+
/** One or more series keys for the value axis. */
|
|
202
|
+
y: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
|
|
203
|
+
title: z.ZodOptional<z.ZodString>;
|
|
204
|
+
}, "strip", z.ZodTypeAny, {
|
|
205
|
+
type: "chart";
|
|
206
|
+
chartType: "bar" | "line" | "pie";
|
|
207
|
+
data: Record<string, unknown>[];
|
|
208
|
+
x: string;
|
|
209
|
+
y: string | string[];
|
|
210
|
+
title?: string | undefined;
|
|
211
|
+
}, {
|
|
212
|
+
type: "chart";
|
|
213
|
+
chartType: "bar" | "line" | "pie";
|
|
214
|
+
data: Record<string, unknown>[];
|
|
215
|
+
x: string;
|
|
216
|
+
y: string | string[];
|
|
217
|
+
title?: string | undefined;
|
|
218
|
+
}>;
|
|
219
|
+
type ChartBlock = z.infer<typeof ChartBlockSchema>;
|
|
220
|
+
declare const ImageBlockSchema: z.ZodObject<{
|
|
221
|
+
type: z.ZodLiteral<"image">;
|
|
222
|
+
src: z.ZodType<string | Uint8Array<ArrayBufferLike>, z.ZodTypeDef, string | Uint8Array<ArrayBufferLike>>;
|
|
223
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
224
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
225
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
226
|
+
}, "strip", z.ZodTypeAny, {
|
|
227
|
+
type: "image";
|
|
228
|
+
src: string | Uint8Array<ArrayBufferLike>;
|
|
229
|
+
width?: number | undefined;
|
|
230
|
+
height?: number | undefined;
|
|
231
|
+
alt?: string | undefined;
|
|
232
|
+
}, {
|
|
233
|
+
type: "image";
|
|
234
|
+
src: string | Uint8Array<ArrayBufferLike>;
|
|
235
|
+
width?: number | undefined;
|
|
236
|
+
height?: number | undefined;
|
|
237
|
+
alt?: string | undefined;
|
|
238
|
+
}>;
|
|
239
|
+
type ImageBlock = z.infer<typeof ImageBlockSchema>;
|
|
240
|
+
declare const SpacerBlockSchema: z.ZodObject<{
|
|
241
|
+
type: z.ZodLiteral<"spacer">;
|
|
242
|
+
/** Number of blank rows / units to advance. The `spacer()` helper defaults to 1. */
|
|
243
|
+
size: z.ZodNumber;
|
|
244
|
+
}, "strip", z.ZodTypeAny, {
|
|
245
|
+
type: "spacer";
|
|
246
|
+
size: number;
|
|
247
|
+
}, {
|
|
248
|
+
type: "spacer";
|
|
249
|
+
size: number;
|
|
250
|
+
}>;
|
|
251
|
+
type SpacerBlock = z.infer<typeof SpacerBlockSchema>;
|
|
252
|
+
declare const PageBreakBlockSchema: z.ZodObject<{
|
|
253
|
+
type: z.ZodLiteral<"pageBreak">;
|
|
254
|
+
}, "strip", z.ZodTypeAny, {
|
|
255
|
+
type: "pageBreak";
|
|
256
|
+
}, {
|
|
257
|
+
type: "pageBreak";
|
|
258
|
+
}>;
|
|
259
|
+
type PageBreakBlock = z.infer<typeof PageBreakBlockSchema>;
|
|
260
|
+
/**
|
|
261
|
+
* `Block` and `SectionBlock` are mutually recursive (a section contains blocks).
|
|
262
|
+
* zod cannot infer recursive types, so we declare the TS types by hand and
|
|
263
|
+
* annotate the lazy schemas with `z.ZodType<...>`.
|
|
264
|
+
*/
|
|
265
|
+
interface SectionBlock {
|
|
266
|
+
type: "section";
|
|
267
|
+
title?: string;
|
|
268
|
+
blocks: Block[];
|
|
269
|
+
/** When true, the adapter renders this section onto its own sheet/page. */
|
|
270
|
+
sheet?: boolean;
|
|
271
|
+
}
|
|
272
|
+
type Block = HeadingBlock | ParagraphBlock | TableBlock | KeyValueBlock | SectionBlock | ChartBlock | ImageBlock | SpacerBlock | PageBreakBlock;
|
|
273
|
+
declare const SectionBlockSchema: z.ZodType<SectionBlock>;
|
|
274
|
+
declare const BlockSchema: z.ZodType<Block>;
|
|
275
|
+
declare const DocumentMetaSchema: z.ZodObject<{
|
|
276
|
+
title: z.ZodString;
|
|
277
|
+
author: z.ZodOptional<z.ZodString>;
|
|
278
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
279
|
+
}, "strip", z.ZodTypeAny, {
|
|
280
|
+
title: string;
|
|
281
|
+
author?: string | undefined;
|
|
282
|
+
subject?: string | undefined;
|
|
283
|
+
}, {
|
|
284
|
+
title: string;
|
|
285
|
+
author?: string | undefined;
|
|
286
|
+
subject?: string | undefined;
|
|
287
|
+
}>;
|
|
288
|
+
type DocumentMeta = z.infer<typeof DocumentMetaSchema>;
|
|
289
|
+
declare const DocumentSchema: z.ZodObject<{
|
|
290
|
+
meta: z.ZodObject<{
|
|
291
|
+
title: z.ZodString;
|
|
292
|
+
author: z.ZodOptional<z.ZodString>;
|
|
293
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
294
|
+
}, "strip", z.ZodTypeAny, {
|
|
295
|
+
title: string;
|
|
296
|
+
author?: string | undefined;
|
|
297
|
+
subject?: string | undefined;
|
|
298
|
+
}, {
|
|
299
|
+
title: string;
|
|
300
|
+
author?: string | undefined;
|
|
301
|
+
subject?: string | undefined;
|
|
302
|
+
}>;
|
|
303
|
+
blocks: z.ZodArray<z.ZodType<Block, z.ZodTypeDef, Block>, "many">;
|
|
304
|
+
}, "strip", z.ZodTypeAny, {
|
|
305
|
+
blocks: Block[];
|
|
306
|
+
meta: {
|
|
307
|
+
title: string;
|
|
308
|
+
author?: string | undefined;
|
|
309
|
+
subject?: string | undefined;
|
|
310
|
+
};
|
|
311
|
+
}, {
|
|
312
|
+
blocks: Block[];
|
|
313
|
+
meta: {
|
|
314
|
+
title: string;
|
|
315
|
+
author?: string | undefined;
|
|
316
|
+
subject?: string | undefined;
|
|
317
|
+
};
|
|
318
|
+
}>;
|
|
319
|
+
type Document = z.infer<typeof DocumentSchema>;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* The theme is a plain, JSON-serialisable typed object. Components and adapters
|
|
323
|
+
* must only ever read tokens from here — never hard-code a colour, font or size.
|
|
324
|
+
* The xlsx adapter translates each token into an exceljs style primitive.
|
|
325
|
+
*/
|
|
326
|
+
interface Theme {
|
|
327
|
+
palette: {
|
|
328
|
+
primary: string;
|
|
329
|
+
accent: string;
|
|
330
|
+
neutral: {
|
|
331
|
+
fg: string;
|
|
332
|
+
muted: string;
|
|
333
|
+
border: string;
|
|
334
|
+
bg: string;
|
|
335
|
+
};
|
|
336
|
+
semantic: {
|
|
337
|
+
positive: string;
|
|
338
|
+
negative: string;
|
|
339
|
+
};
|
|
340
|
+
};
|
|
341
|
+
typography: {
|
|
342
|
+
fontFamily: string;
|
|
343
|
+
baseSize: number;
|
|
344
|
+
/** Sizes for heading levels 1, 2 and 3. */
|
|
345
|
+
headingSizes: [number, number, number];
|
|
346
|
+
};
|
|
347
|
+
table: {
|
|
348
|
+
headerFill: string;
|
|
349
|
+
headerFg: string;
|
|
350
|
+
banding: boolean;
|
|
351
|
+
borderColor: string;
|
|
352
|
+
};
|
|
353
|
+
/** Base spacing unit. */
|
|
354
|
+
spacing: number;
|
|
355
|
+
brand?: {
|
|
356
|
+
logo?: Uint8Array;
|
|
357
|
+
headerText?: string;
|
|
358
|
+
footerText?: string;
|
|
359
|
+
};
|
|
360
|
+
/** Mostly for flow formats later (PDF/DOCX). */
|
|
361
|
+
page?: {
|
|
362
|
+
orientation?: "portrait" | "landscape";
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* The one shipped theme: an "ink on paper" editorial look that matches the
|
|
367
|
+
* Liasse brand (deep ink blue, warm paper neutrals, sober finance semantics).
|
|
368
|
+
*/
|
|
369
|
+
declare const defaultTheme: Theme;
|
|
370
|
+
/**
|
|
371
|
+
* Shallow-ish merge to derive a theme from {@link defaultTheme}. Nested token
|
|
372
|
+
* groups are merged one level deep so callers can override just a few tokens.
|
|
373
|
+
*/
|
|
374
|
+
declare function defineTheme(overrides?: DeepPartial<Theme>): Theme;
|
|
375
|
+
type DeepPartial<T> = {
|
|
376
|
+
[K in keyof T]?: T[K] extends string | number | boolean | Uint8Array | readonly unknown[] ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* The builder DSL. Each helper returns a plain block object so components read
|
|
381
|
+
* declaratively. `defineDocument` is the only function that validates — build
|
|
382
|
+
* the tree freely, then validate once at the boundary.
|
|
383
|
+
*/
|
|
384
|
+
/** Validate raw input against the document schema; throws on bad input. */
|
|
385
|
+
declare function defineDocument(input: {
|
|
386
|
+
meta: Document["meta"];
|
|
387
|
+
blocks: Block[];
|
|
388
|
+
}): Document;
|
|
389
|
+
declare function heading(text: string, opts?: {
|
|
390
|
+
level?: HeadingBlock["level"];
|
|
391
|
+
}): HeadingBlock;
|
|
392
|
+
declare function paragraph(text: string, opts?: {
|
|
393
|
+
emphasis?: boolean;
|
|
394
|
+
}): ParagraphBlock;
|
|
395
|
+
declare function table(input: {
|
|
396
|
+
columns: TableColumn[];
|
|
397
|
+
rows: Record<string, unknown>[];
|
|
398
|
+
summary?: TableBlock["summary"];
|
|
399
|
+
conditional?: TableBlock["conditional"];
|
|
400
|
+
xlsx?: TableBlock["xlsx"];
|
|
401
|
+
}): TableBlock;
|
|
402
|
+
declare function keyValue(items: KeyValueBlock["items"]): KeyValueBlock;
|
|
403
|
+
declare function kv(label: string, value: KeyValueBlock["items"][number]["value"], format?: ValueFormat): KeyValueBlock["items"][number];
|
|
404
|
+
declare function section(input: {
|
|
405
|
+
title?: string;
|
|
406
|
+
blocks: Block[];
|
|
407
|
+
sheet?: boolean;
|
|
408
|
+
}): SectionBlock;
|
|
409
|
+
declare function chart(input: {
|
|
410
|
+
chartType: ChartBlock["chartType"];
|
|
411
|
+
data: Record<string, unknown>[];
|
|
412
|
+
x: string;
|
|
413
|
+
y: string | string[];
|
|
414
|
+
title?: string;
|
|
415
|
+
}): ChartBlock;
|
|
416
|
+
declare function image(input: {
|
|
417
|
+
src: Uint8Array | string;
|
|
418
|
+
width?: number;
|
|
419
|
+
height?: number;
|
|
420
|
+
alt?: string;
|
|
421
|
+
}): ImageBlock;
|
|
422
|
+
declare function spacer(size?: number): Block;
|
|
423
|
+
declare function pageBreak(): Block;
|
|
424
|
+
|
|
425
|
+
type RenderFormat = "xlsx" | "pptx" | "docx" | "pdf";
|
|
426
|
+
/**
|
|
427
|
+
* A renderer turns a {@link Document} + {@link Theme} into output bytes.
|
|
428
|
+
* Adapters live in their own packages (e.g. `@liasse/xlsx`) and must not leak
|
|
429
|
+
* format-specific types back into core.
|
|
430
|
+
*
|
|
431
|
+
* Renderers return a `Uint8Array` (Node `Buffer` is a `Uint8Array`); the caller
|
|
432
|
+
* decides what to do with the bytes — packages never touch `fs`.
|
|
433
|
+
*/
|
|
434
|
+
interface Renderer {
|
|
435
|
+
readonly format: RenderFormat;
|
|
436
|
+
render(doc: Document, theme: Theme): Promise<Uint8Array>;
|
|
437
|
+
}
|
|
438
|
+
/** Register (or replace) the renderer for a format. Called by adapter packages. */
|
|
439
|
+
declare function registerRenderer(renderer: Renderer): void;
|
|
440
|
+
/** Look up a previously registered renderer, if any. */
|
|
441
|
+
declare function getRenderer(format: RenderFormat): Renderer | undefined;
|
|
442
|
+
interface RenderOptions {
|
|
443
|
+
format: RenderFormat;
|
|
444
|
+
theme?: Theme;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Thin dispatcher: pick the registered renderer for `format` and run it.
|
|
448
|
+
* For the MVP only the `xlsx` renderer is registered (import `@liasse/xlsx`).
|
|
449
|
+
*/
|
|
450
|
+
declare function render(doc: Document, options: RenderOptions): Promise<Uint8Array>;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Typed error classes for Liasse. Catch these to distinguish a malformed
|
|
454
|
+
* document (validation) from a failure while producing the output bytes (render).
|
|
455
|
+
*/
|
|
456
|
+
/** Thrown by {@link defineDocument} (and other validators) on invalid input. */
|
|
457
|
+
declare class LiasseValidationError extends Error {
|
|
458
|
+
/** Flat list of `path: message` issues, derived from the zod error. */
|
|
459
|
+
readonly issues: {
|
|
460
|
+
path: string;
|
|
461
|
+
message: string;
|
|
462
|
+
}[];
|
|
463
|
+
constructor(message: string, issues?: {
|
|
464
|
+
path: string;
|
|
465
|
+
message: string;
|
|
466
|
+
}[]);
|
|
467
|
+
}
|
|
468
|
+
/** Thrown by a {@link Renderer} (or the `render` dispatcher) when output fails. */
|
|
469
|
+
declare class LiasseRenderError extends Error {
|
|
470
|
+
constructor(message: string);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export { type Align, AlignSchema, BinaryOrUrlSchema, type Block, BlockSchema, type ChartBlock, ChartBlockSchema, type Conditional, ConditionalSchema, type Document, type DocumentMeta, DocumentMetaSchema, DocumentSchema, type HeadingBlock, HeadingBlockSchema, type ImageBlock, ImageBlockSchema, type KeyValueBlock, KeyValueBlockSchema, LiasseRenderError, LiasseValidationError, type PageBreakBlock, PageBreakBlockSchema, type ParagraphBlock, ParagraphBlockSchema, type RenderFormat, type RenderOptions, type Renderer, type SectionBlock, SectionBlockSchema, type SpacerBlock, SpacerBlockSchema, type Summary, SummarySchema, type TableBlock, TableBlockSchema, type TableColumn, TableColumnSchema, type Theme, type ValueFormat, ValueFormatSchema, chart, defaultTheme, defineDocument, defineTheme, getRenderer, heading, image, keyValue, kv, pageBreak, paragraph, registerRenderer, render, section, spacer, table };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// src/schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var ValueFormatSchema = z.enum(["text", "number", "currency", "percent", "date"]);
|
|
4
|
+
var AlignSchema = z.enum(["left", "center", "right"]);
|
|
5
|
+
var BinaryOrUrlSchema = z.union([
|
|
6
|
+
z.instanceof(Uint8Array),
|
|
7
|
+
z.string().min(1)
|
|
8
|
+
]);
|
|
9
|
+
var HeadingBlockSchema = z.object({
|
|
10
|
+
type: z.literal("heading"),
|
|
11
|
+
text: z.string(),
|
|
12
|
+
// Required in the schema (input === output) so the recursive `Block` union
|
|
13
|
+
// type-checks; the builder `heading()` helper supplies the default level.
|
|
14
|
+
level: z.union([z.literal(1), z.literal(2), z.literal(3)])
|
|
15
|
+
});
|
|
16
|
+
var ParagraphBlockSchema = z.object({
|
|
17
|
+
type: z.literal("paragraph"),
|
|
18
|
+
text: z.string(),
|
|
19
|
+
emphasis: z.boolean().optional()
|
|
20
|
+
});
|
|
21
|
+
var TableColumnSchema = z.object({
|
|
22
|
+
key: z.string().min(1),
|
|
23
|
+
header: z.string(),
|
|
24
|
+
format: ValueFormatSchema.optional(),
|
|
25
|
+
align: AlignSchema.optional(),
|
|
26
|
+
/** Optional explicit column width (character units). */
|
|
27
|
+
width: z.number().positive().optional()
|
|
28
|
+
});
|
|
29
|
+
var SummarySchema = z.record(z.string(), z.enum(["sum", "avg", "count"]));
|
|
30
|
+
var ConditionalSchema = z.object({
|
|
31
|
+
column: z.string().min(1),
|
|
32
|
+
rule: z.literal("positiveNegative")
|
|
33
|
+
});
|
|
34
|
+
var TableBlockSchema = z.object({
|
|
35
|
+
type: z.literal("table"),
|
|
36
|
+
columns: z.array(TableColumnSchema).min(1),
|
|
37
|
+
rows: z.array(z.record(z.string(), z.unknown())),
|
|
38
|
+
/** Per-column aggregate → emits a summary row with real formulas. */
|
|
39
|
+
summary: SummarySchema.optional(),
|
|
40
|
+
/** Colour cues, e.g. positive in green / negative in red. */
|
|
41
|
+
conditional: ConditionalSchema.optional(),
|
|
42
|
+
/** Format-specific escape hatch, read only by the xlsx adapter. */
|
|
43
|
+
xlsx: z.object({
|
|
44
|
+
freezeHeader: z.boolean().optional(),
|
|
45
|
+
sheetName: z.string().optional()
|
|
46
|
+
}).optional()
|
|
47
|
+
});
|
|
48
|
+
var KeyValueBlockSchema = z.object({
|
|
49
|
+
type: z.literal("keyValue"),
|
|
50
|
+
items: z.array(
|
|
51
|
+
z.object({
|
|
52
|
+
label: z.string(),
|
|
53
|
+
value: z.union([z.string(), z.number(), z.boolean(), z.null()]),
|
|
54
|
+
format: ValueFormatSchema.optional()
|
|
55
|
+
})
|
|
56
|
+
)
|
|
57
|
+
});
|
|
58
|
+
var ChartBlockSchema = z.object({
|
|
59
|
+
type: z.literal("chart"),
|
|
60
|
+
chartType: z.enum(["bar", "line", "pie"]),
|
|
61
|
+
data: z.array(z.record(z.string(), z.unknown())),
|
|
62
|
+
/** Key used for the category axis. */
|
|
63
|
+
x: z.string().min(1),
|
|
64
|
+
/** One or more series keys for the value axis. */
|
|
65
|
+
y: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]),
|
|
66
|
+
title: z.string().optional()
|
|
67
|
+
});
|
|
68
|
+
var ImageBlockSchema = z.object({
|
|
69
|
+
type: z.literal("image"),
|
|
70
|
+
src: BinaryOrUrlSchema,
|
|
71
|
+
width: z.number().positive().optional(),
|
|
72
|
+
height: z.number().positive().optional(),
|
|
73
|
+
alt: z.string().optional()
|
|
74
|
+
});
|
|
75
|
+
var SpacerBlockSchema = z.object({
|
|
76
|
+
type: z.literal("spacer"),
|
|
77
|
+
/** Number of blank rows / units to advance. The `spacer()` helper defaults to 1. */
|
|
78
|
+
size: z.number().int().positive()
|
|
79
|
+
});
|
|
80
|
+
var PageBreakBlockSchema = z.object({
|
|
81
|
+
type: z.literal("pageBreak")
|
|
82
|
+
});
|
|
83
|
+
var SectionBlockSchema = z.lazy(
|
|
84
|
+
() => z.object({
|
|
85
|
+
type: z.literal("section"),
|
|
86
|
+
title: z.string().optional(),
|
|
87
|
+
blocks: z.array(BlockSchema),
|
|
88
|
+
sheet: z.boolean().optional()
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
var BlockSchema = z.lazy(
|
|
92
|
+
() => z.union([
|
|
93
|
+
HeadingBlockSchema,
|
|
94
|
+
ParagraphBlockSchema,
|
|
95
|
+
TableBlockSchema,
|
|
96
|
+
KeyValueBlockSchema,
|
|
97
|
+
SectionBlockSchema,
|
|
98
|
+
ChartBlockSchema,
|
|
99
|
+
ImageBlockSchema,
|
|
100
|
+
SpacerBlockSchema,
|
|
101
|
+
PageBreakBlockSchema
|
|
102
|
+
])
|
|
103
|
+
);
|
|
104
|
+
var DocumentMetaSchema = z.object({
|
|
105
|
+
title: z.string().min(1),
|
|
106
|
+
author: z.string().optional(),
|
|
107
|
+
subject: z.string().optional()
|
|
108
|
+
});
|
|
109
|
+
var DocumentSchema = z.object({
|
|
110
|
+
meta: DocumentMetaSchema,
|
|
111
|
+
blocks: z.array(BlockSchema)
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// src/theme.ts
|
|
115
|
+
var defaultTheme = {
|
|
116
|
+
palette: {
|
|
117
|
+
primary: "#25336E",
|
|
118
|
+
accent: "#34489C",
|
|
119
|
+
neutral: {
|
|
120
|
+
fg: "#1B1A16",
|
|
121
|
+
muted: "#837E72",
|
|
122
|
+
border: "#D9D3C5",
|
|
123
|
+
bg: "#F6F2E9"
|
|
124
|
+
},
|
|
125
|
+
semantic: {
|
|
126
|
+
positive: "#1F7A4D",
|
|
127
|
+
negative: "#B23A2E"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
typography: {
|
|
131
|
+
fontFamily: "IBM Plex Sans",
|
|
132
|
+
baseSize: 11,
|
|
133
|
+
headingSizes: [20, 15, 13]
|
|
134
|
+
},
|
|
135
|
+
table: {
|
|
136
|
+
headerFill: "#E7E8F0",
|
|
137
|
+
headerFg: "#1A2550",
|
|
138
|
+
banding: true,
|
|
139
|
+
borderColor: "#E5E0D3"
|
|
140
|
+
},
|
|
141
|
+
spacing: 1
|
|
142
|
+
};
|
|
143
|
+
function defineTheme(overrides = {}) {
|
|
144
|
+
const base = defaultTheme;
|
|
145
|
+
return {
|
|
146
|
+
palette: {
|
|
147
|
+
primary: overrides.palette?.primary ?? base.palette.primary,
|
|
148
|
+
accent: overrides.palette?.accent ?? base.palette.accent,
|
|
149
|
+
neutral: { ...base.palette.neutral, ...overrides.palette?.neutral },
|
|
150
|
+
semantic: { ...base.palette.semantic, ...overrides.palette?.semantic }
|
|
151
|
+
},
|
|
152
|
+
typography: {
|
|
153
|
+
fontFamily: overrides.typography?.fontFamily ?? base.typography.fontFamily,
|
|
154
|
+
baseSize: overrides.typography?.baseSize ?? base.typography.baseSize,
|
|
155
|
+
headingSizes: overrides.typography?.headingSizes ?? base.typography.headingSizes
|
|
156
|
+
},
|
|
157
|
+
table: { ...base.table, ...overrides.table },
|
|
158
|
+
spacing: overrides.spacing ?? base.spacing,
|
|
159
|
+
brand: overrides.brand ? { ...base.brand, ...overrides.brand } : base.brand,
|
|
160
|
+
page: overrides.page ? { ...base.page, ...overrides.page } : base.page
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/errors.ts
|
|
165
|
+
var LiasseValidationError = class _LiasseValidationError extends Error {
|
|
166
|
+
/** Flat list of `path: message` issues, derived from the zod error. */
|
|
167
|
+
issues;
|
|
168
|
+
constructor(message, issues = []) {
|
|
169
|
+
super(message);
|
|
170
|
+
this.name = "LiasseValidationError";
|
|
171
|
+
this.issues = issues;
|
|
172
|
+
Object.setPrototypeOf(this, _LiasseValidationError.prototype);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var LiasseRenderError = class _LiasseRenderError extends Error {
|
|
176
|
+
constructor(message) {
|
|
177
|
+
super(message);
|
|
178
|
+
this.name = "LiasseRenderError";
|
|
179
|
+
Object.setPrototypeOf(this, _LiasseRenderError.prototype);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/builder.ts
|
|
184
|
+
function defineDocument(input) {
|
|
185
|
+
const result = DocumentSchema.safeParse(input);
|
|
186
|
+
if (!result.success) {
|
|
187
|
+
throw toValidationError(result.error);
|
|
188
|
+
}
|
|
189
|
+
return result.data;
|
|
190
|
+
}
|
|
191
|
+
function heading(text, opts = {}) {
|
|
192
|
+
return { type: "heading", text, level: opts.level ?? 1 };
|
|
193
|
+
}
|
|
194
|
+
function paragraph(text, opts = {}) {
|
|
195
|
+
return { type: "paragraph", text, ...opts.emphasis ? { emphasis: true } : {} };
|
|
196
|
+
}
|
|
197
|
+
function table(input) {
|
|
198
|
+
return { type: "table", ...input };
|
|
199
|
+
}
|
|
200
|
+
function keyValue(items) {
|
|
201
|
+
return { type: "keyValue", items };
|
|
202
|
+
}
|
|
203
|
+
function kv(label, value, format) {
|
|
204
|
+
return { label, value, ...format ? { format } : {} };
|
|
205
|
+
}
|
|
206
|
+
function section(input) {
|
|
207
|
+
return { type: "section", ...input };
|
|
208
|
+
}
|
|
209
|
+
function chart(input) {
|
|
210
|
+
return { type: "chart", ...input };
|
|
211
|
+
}
|
|
212
|
+
function image(input) {
|
|
213
|
+
return { type: "image", ...input };
|
|
214
|
+
}
|
|
215
|
+
function spacer(size = 1) {
|
|
216
|
+
return { type: "spacer", size };
|
|
217
|
+
}
|
|
218
|
+
function pageBreak() {
|
|
219
|
+
return { type: "pageBreak" };
|
|
220
|
+
}
|
|
221
|
+
function toValidationError(error) {
|
|
222
|
+
const issues = error.issues.map((i) => ({
|
|
223
|
+
path: i.path.join("."),
|
|
224
|
+
message: i.message
|
|
225
|
+
}));
|
|
226
|
+
const summary = issues.slice(0, 3).map((i) => i.path ? `${i.path}: ${i.message}` : i.message).join("; ");
|
|
227
|
+
const more = issues.length > 3 ? ` (+${issues.length - 3} more)` : "";
|
|
228
|
+
return new LiasseValidationError(`Invalid document: ${summary}${more}`, issues);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/renderer.ts
|
|
232
|
+
var renderers = /* @__PURE__ */ new Map();
|
|
233
|
+
function registerRenderer(renderer) {
|
|
234
|
+
renderers.set(renderer.format, renderer);
|
|
235
|
+
}
|
|
236
|
+
function getRenderer(format) {
|
|
237
|
+
return renderers.get(format);
|
|
238
|
+
}
|
|
239
|
+
async function render(doc, options) {
|
|
240
|
+
const renderer = renderers.get(options.format);
|
|
241
|
+
if (!renderer) {
|
|
242
|
+
throw new LiasseRenderError(
|
|
243
|
+
`No renderer registered for format "${options.format}". Import the matching adapter (e.g. "@liasse/xlsx") to register it.`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return renderer.render(doc, options.theme ?? defaultTheme);
|
|
247
|
+
}
|
|
248
|
+
export {
|
|
249
|
+
AlignSchema,
|
|
250
|
+
BinaryOrUrlSchema,
|
|
251
|
+
BlockSchema,
|
|
252
|
+
ChartBlockSchema,
|
|
253
|
+
ConditionalSchema,
|
|
254
|
+
DocumentMetaSchema,
|
|
255
|
+
DocumentSchema,
|
|
256
|
+
HeadingBlockSchema,
|
|
257
|
+
ImageBlockSchema,
|
|
258
|
+
KeyValueBlockSchema,
|
|
259
|
+
LiasseRenderError,
|
|
260
|
+
LiasseValidationError,
|
|
261
|
+
PageBreakBlockSchema,
|
|
262
|
+
ParagraphBlockSchema,
|
|
263
|
+
SectionBlockSchema,
|
|
264
|
+
SpacerBlockSchema,
|
|
265
|
+
SummarySchema,
|
|
266
|
+
TableBlockSchema,
|
|
267
|
+
TableColumnSchema,
|
|
268
|
+
ValueFormatSchema,
|
|
269
|
+
chart,
|
|
270
|
+
defaultTheme,
|
|
271
|
+
defineDocument,
|
|
272
|
+
defineTheme,
|
|
273
|
+
getRenderer,
|
|
274
|
+
heading,
|
|
275
|
+
image,
|
|
276
|
+
keyValue,
|
|
277
|
+
kv,
|
|
278
|
+
pageBreak,
|
|
279
|
+
paragraph,
|
|
280
|
+
registerRenderer,
|
|
281
|
+
render,
|
|
282
|
+
section,
|
|
283
|
+
spacer,
|
|
284
|
+
table
|
|
285
|
+
};
|
|
286
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/theme.ts","../src/errors.ts","../src/builder.ts","../src/renderer.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * zod is the source of truth: every model type is inferred from a schema here,\n * and the same schemas validate API payloads later. Nothing in this file may\n * import an office library — the model is format-agnostic by construction.\n */\n\n/** How a scalar value should be presented by an adapter. */\nexport const ValueFormatSchema = z.enum([\"text\", \"number\", \"currency\", \"percent\", \"date\"]);\nexport type ValueFormat = z.infer<typeof ValueFormatSchema>;\n\nexport const AlignSchema = z.enum([\"left\", \"center\", \"right\"]);\nexport type Align = z.infer<typeof AlignSchema>;\n\n/** A buffer (Node/browser binary) or a string source (url / data-uri / path). */\n// Explicit `z.ZodType` annotation normalises the inferred binary type to a\n// plain `Uint8Array`, avoiding `ArrayBuffer`/`ArrayBufferLike` generic churn.\nexport const BinaryOrUrlSchema: z.ZodType<Uint8Array | string> = z.union([\n z.instanceof(Uint8Array),\n z.string().min(1),\n]);\n\n/* ------------------------------------------------------------------ blocks */\n\nexport const HeadingBlockSchema = z.object({\n type: z.literal(\"heading\"),\n text: z.string(),\n // Required in the schema (input === output) so the recursive `Block` union\n // type-checks; the builder `heading()` helper supplies the default level.\n level: z.union([z.literal(1), z.literal(2), z.literal(3)]),\n});\nexport type HeadingBlock = z.infer<typeof HeadingBlockSchema>;\n\nexport const ParagraphBlockSchema = z.object({\n type: z.literal(\"paragraph\"),\n text: z.string(),\n emphasis: z.boolean().optional(),\n});\nexport type ParagraphBlock = z.infer<typeof ParagraphBlockSchema>;\n\nexport const TableColumnSchema = z.object({\n key: z.string().min(1),\n header: z.string(),\n format: ValueFormatSchema.optional(),\n align: AlignSchema.optional(),\n /** Optional explicit column width (character units). */\n width: z.number().positive().optional(),\n});\nexport type TableColumn = z.infer<typeof TableColumnSchema>;\n\nexport const SummarySchema = z.record(z.string(), z.enum([\"sum\", \"avg\", \"count\"]));\nexport type Summary = z.infer<typeof SummarySchema>;\n\nexport const ConditionalSchema = z.object({\n column: z.string().min(1),\n rule: z.literal(\"positiveNegative\"),\n});\nexport type Conditional = z.infer<typeof ConditionalSchema>;\n\nexport const TableBlockSchema = z.object({\n type: z.literal(\"table\"),\n columns: z.array(TableColumnSchema).min(1),\n rows: z.array(z.record(z.string(), z.unknown())),\n /** Per-column aggregate → emits a summary row with real formulas. */\n summary: SummarySchema.optional(),\n /** Colour cues, e.g. positive in green / negative in red. */\n conditional: ConditionalSchema.optional(),\n /** Format-specific escape hatch, read only by the xlsx adapter. */\n xlsx: z\n .object({\n freezeHeader: z.boolean().optional(),\n sheetName: z.string().optional(),\n })\n .optional(),\n});\nexport type TableBlock = z.infer<typeof TableBlockSchema>;\n\nexport const KeyValueBlockSchema = z.object({\n type: z.literal(\"keyValue\"),\n items: z.array(\n z.object({\n label: z.string(),\n value: z.union([z.string(), z.number(), z.boolean(), z.null()]),\n format: ValueFormatSchema.optional(),\n }),\n ),\n});\nexport type KeyValueBlock = z.infer<typeof KeyValueBlockSchema>;\n\nexport const ChartBlockSchema = z.object({\n type: z.literal(\"chart\"),\n chartType: z.enum([\"bar\", \"line\", \"pie\"]),\n data: z.array(z.record(z.string(), z.unknown())),\n /** Key used for the category axis. */\n x: z.string().min(1),\n /** One or more series keys for the value axis. */\n y: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]),\n title: z.string().optional(),\n});\nexport type ChartBlock = z.infer<typeof ChartBlockSchema>;\n\nexport const ImageBlockSchema = z.object({\n type: z.literal(\"image\"),\n src: BinaryOrUrlSchema,\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n alt: z.string().optional(),\n});\nexport type ImageBlock = z.infer<typeof ImageBlockSchema>;\n\nexport const SpacerBlockSchema = z.object({\n type: z.literal(\"spacer\"),\n /** Number of blank rows / units to advance. The `spacer()` helper defaults to 1. */\n size: z.number().int().positive(),\n});\nexport type SpacerBlock = z.infer<typeof SpacerBlockSchema>;\n\nexport const PageBreakBlockSchema = z.object({\n type: z.literal(\"pageBreak\"),\n});\nexport type PageBreakBlock = z.infer<typeof PageBreakBlockSchema>;\n\n/* ----------------------------------------------- recursive section + union */\n\n/**\n * `Block` and `SectionBlock` are mutually recursive (a section contains blocks).\n * zod cannot infer recursive types, so we declare the TS types by hand and\n * annotate the lazy schemas with `z.ZodType<...>`.\n */\nexport interface SectionBlock {\n type: \"section\";\n title?: string;\n blocks: Block[];\n /** When true, the adapter renders this section onto its own sheet/page. */\n sheet?: boolean;\n}\n\nexport type Block =\n | HeadingBlock\n | ParagraphBlock\n | TableBlock\n | KeyValueBlock\n | SectionBlock\n | ChartBlock\n | ImageBlock\n | SpacerBlock\n | PageBreakBlock;\n\nexport const SectionBlockSchema: z.ZodType<SectionBlock> = z.lazy(() =>\n z.object({\n type: z.literal(\"section\"),\n title: z.string().optional(),\n blocks: z.array(BlockSchema),\n sheet: z.boolean().optional(),\n }),\n);\n\n// A plain (not discriminated) union is required because `SectionBlock` is\n// recursive: discriminatedUnion cannot take a `z.lazy` member, a plain union can.\nexport const BlockSchema: z.ZodType<Block> = z.lazy(() =>\n z.union([\n HeadingBlockSchema,\n ParagraphBlockSchema,\n TableBlockSchema,\n KeyValueBlockSchema,\n SectionBlockSchema,\n ChartBlockSchema,\n ImageBlockSchema,\n SpacerBlockSchema,\n PageBreakBlockSchema,\n ]),\n);\n\n/* ----------------------------------------------------------------- document */\n\nexport const DocumentMetaSchema = z.object({\n title: z.string().min(1),\n author: z.string().optional(),\n subject: z.string().optional(),\n});\nexport type DocumentMeta = z.infer<typeof DocumentMetaSchema>;\n\nexport const DocumentSchema = z.object({\n meta: DocumentMetaSchema,\n blocks: z.array(BlockSchema),\n});\nexport type Document = z.infer<typeof DocumentSchema>;\n","/**\n * The theme is a plain, JSON-serialisable typed object. Components and adapters\n * must only ever read tokens from here — never hard-code a colour, font or size.\n * The xlsx adapter translates each token into an exceljs style primitive.\n */\nexport interface Theme {\n palette: {\n primary: string;\n accent: string;\n neutral: { fg: string; muted: string; border: string; bg: string };\n semantic: { positive: string; negative: string };\n };\n typography: {\n fontFamily: string;\n baseSize: number;\n /** Sizes for heading levels 1, 2 and 3. */\n headingSizes: [number, number, number];\n };\n table: {\n headerFill: string;\n headerFg: string;\n banding: boolean;\n borderColor: string;\n };\n /** Base spacing unit. */\n spacing: number;\n brand?: {\n logo?: Uint8Array;\n headerText?: string;\n footerText?: string;\n };\n /** Mostly for flow formats later (PDF/DOCX). */\n page?: { orientation?: \"portrait\" | \"landscape\" };\n}\n\n/**\n * The one shipped theme: an \"ink on paper\" editorial look that matches the\n * Liasse brand (deep ink blue, warm paper neutrals, sober finance semantics).\n */\nexport const defaultTheme: Theme = {\n palette: {\n primary: \"#25336E\",\n accent: \"#34489C\",\n neutral: {\n fg: \"#1B1A16\",\n muted: \"#837E72\",\n border: \"#D9D3C5\",\n bg: \"#F6F2E9\",\n },\n semantic: {\n positive: \"#1F7A4D\",\n negative: \"#B23A2E\",\n },\n },\n typography: {\n fontFamily: \"IBM Plex Sans\",\n baseSize: 11,\n headingSizes: [20, 15, 13],\n },\n table: {\n headerFill: \"#E7E8F0\",\n headerFg: \"#1A2550\",\n banding: true,\n borderColor: \"#E5E0D3\",\n },\n spacing: 1,\n};\n\n/**\n * Shallow-ish merge to derive a theme from {@link defaultTheme}. Nested token\n * groups are merged one level deep so callers can override just a few tokens.\n */\nexport function defineTheme(overrides: DeepPartial<Theme> = {}): Theme {\n const base = defaultTheme;\n return {\n palette: {\n primary: overrides.palette?.primary ?? base.palette.primary,\n accent: overrides.palette?.accent ?? base.palette.accent,\n neutral: { ...base.palette.neutral, ...overrides.palette?.neutral },\n semantic: { ...base.palette.semantic, ...overrides.palette?.semantic },\n },\n typography: {\n fontFamily: overrides.typography?.fontFamily ?? base.typography.fontFamily,\n baseSize: overrides.typography?.baseSize ?? base.typography.baseSize,\n headingSizes: overrides.typography?.headingSizes ?? base.typography.headingSizes,\n },\n table: { ...base.table, ...overrides.table },\n spacing: overrides.spacing ?? base.spacing,\n brand: overrides.brand ? { ...base.brand, ...overrides.brand } : base.brand,\n page: overrides.page ? { ...base.page, ...overrides.page } : base.page,\n };\n}\n\ntype DeepPartial<T> = {\n [K in keyof T]?: T[K] extends string | number | boolean | Uint8Array | readonly unknown[]\n ? T[K]\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n","/**\n * Typed error classes for Liasse. Catch these to distinguish a malformed\n * document (validation) from a failure while producing the output bytes (render).\n */\n\n/** Thrown by {@link defineDocument} (and other validators) on invalid input. */\nexport class LiasseValidationError extends Error {\n /** Flat list of `path: message` issues, derived from the zod error. */\n readonly issues: { path: string; message: string }[];\n\n constructor(message: string, issues: { path: string; message: string }[] = []) {\n super(message);\n this.name = \"LiasseValidationError\";\n this.issues = issues;\n Object.setPrototypeOf(this, LiasseValidationError.prototype);\n }\n}\n\n/** Thrown by a {@link Renderer} (or the `render` dispatcher) when output fails. */\nexport class LiasseRenderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LiasseRenderError\";\n Object.setPrototypeOf(this, LiasseRenderError.prototype);\n }\n}\n","import { z } from \"zod\";\nimport { LiasseValidationError } from \"./errors.js\";\nimport {\n DocumentSchema,\n type Block,\n type ChartBlock,\n type Document,\n type HeadingBlock,\n type ImageBlock,\n type KeyValueBlock,\n type ParagraphBlock,\n type SectionBlock,\n type TableBlock,\n type TableColumn,\n type ValueFormat,\n} from \"./schema.js\";\n\n/**\n * The builder DSL. Each helper returns a plain block object so components read\n * declaratively. `defineDocument` is the only function that validates — build\n * the tree freely, then validate once at the boundary.\n */\n\n/** Validate raw input against the document schema; throws on bad input. */\nexport function defineDocument(input: {\n meta: Document[\"meta\"];\n blocks: Block[];\n}): Document {\n const result = DocumentSchema.safeParse(input);\n if (!result.success) {\n throw toValidationError(result.error);\n }\n return result.data;\n}\n\nexport function heading(text: string, opts: { level?: HeadingBlock[\"level\"] } = {}): HeadingBlock {\n return { type: \"heading\", text, level: opts.level ?? 1 };\n}\n\nexport function paragraph(text: string, opts: { emphasis?: boolean } = {}): ParagraphBlock {\n return { type: \"paragraph\", text, ...(opts.emphasis ? { emphasis: true } : {}) };\n}\n\nexport function table(input: {\n columns: TableColumn[];\n rows: Record<string, unknown>[];\n summary?: TableBlock[\"summary\"];\n conditional?: TableBlock[\"conditional\"];\n xlsx?: TableBlock[\"xlsx\"];\n}): TableBlock {\n return { type: \"table\", ...input };\n}\n\nexport function keyValue(items: KeyValueBlock[\"items\"]): KeyValueBlock {\n return { type: \"keyValue\", items };\n}\n\nexport function kv(\n label: string,\n value: KeyValueBlock[\"items\"][number][\"value\"],\n format?: ValueFormat,\n): KeyValueBlock[\"items\"][number] {\n return { label, value, ...(format ? { format } : {}) };\n}\n\nexport function section(input: {\n title?: string;\n blocks: Block[];\n sheet?: boolean;\n}): SectionBlock {\n return { type: \"section\", ...input };\n}\n\nexport function chart(input: {\n chartType: ChartBlock[\"chartType\"];\n data: Record<string, unknown>[];\n x: string;\n y: string | string[];\n title?: string;\n}): ChartBlock {\n return { type: \"chart\", ...input };\n}\n\nexport function image(input: {\n src: Uint8Array | string;\n width?: number;\n height?: number;\n alt?: string;\n}): ImageBlock {\n return { type: \"image\", ...input };\n}\n\nexport function spacer(size = 1): Block {\n return { type: \"spacer\", size };\n}\n\nexport function pageBreak(): Block {\n return { type: \"pageBreak\" };\n}\n\nfunction toValidationError(error: z.ZodError): LiasseValidationError {\n const issues = error.issues.map((i) => ({\n path: i.path.join(\".\"),\n message: i.message,\n }));\n const summary = issues\n .slice(0, 3)\n .map((i) => (i.path ? `${i.path}: ${i.message}` : i.message))\n .join(\"; \");\n const more = issues.length > 3 ? ` (+${issues.length - 3} more)` : \"\";\n return new LiasseValidationError(`Invalid document: ${summary}${more}`, issues);\n}\n","import { LiasseRenderError } from \"./errors.js\";\nimport type { Document } from \"./schema.js\";\nimport { defaultTheme, type Theme } from \"./theme.js\";\n\nexport type RenderFormat = \"xlsx\" | \"pptx\" | \"docx\" | \"pdf\";\n\n/**\n * A renderer turns a {@link Document} + {@link Theme} into output bytes.\n * Adapters live in their own packages (e.g. `@liasse/xlsx`) and must not leak\n * format-specific types back into core.\n *\n * Renderers return a `Uint8Array` (Node `Buffer` is a `Uint8Array`); the caller\n * decides what to do with the bytes — packages never touch `fs`.\n */\nexport interface Renderer {\n readonly format: RenderFormat;\n render(doc: Document, theme: Theme): Promise<Uint8Array>;\n}\n\nconst renderers = new Map<RenderFormat, Renderer>();\n\n/** Register (or replace) the renderer for a format. Called by adapter packages. */\nexport function registerRenderer(renderer: Renderer): void {\n renderers.set(renderer.format, renderer);\n}\n\n/** Look up a previously registered renderer, if any. */\nexport function getRenderer(format: RenderFormat): Renderer | undefined {\n return renderers.get(format);\n}\n\nexport interface RenderOptions {\n format: RenderFormat;\n theme?: Theme;\n}\n\n/**\n * Thin dispatcher: pick the registered renderer for `format` and run it.\n * For the MVP only the `xlsx` renderer is registered (import `@liasse/xlsx`).\n */\nexport async function render(doc: Document, options: RenderOptions): Promise<Uint8Array> {\n const renderer = renderers.get(options.format);\n if (!renderer) {\n throw new LiasseRenderError(\n `No renderer registered for format \"${options.format}\". ` +\n `Import the matching adapter (e.g. \"@liasse/xlsx\") to register it.`,\n );\n }\n return renderer.render(doc, options.theme ?? defaultTheme);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liasse/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Liasse core — format-agnostic document model, theme, builder DSL, zod schemas and the Renderer interface. Zero office dependencies.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"files": ["dist"],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "vitest run"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"zod": "^3.24.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsup": "^8.3.5",
|
|
31
|
+
"typescript": "^5.7.2",
|
|
32
|
+
"vitest": "^2.1.8"
|
|
33
|
+
}
|
|
34
|
+
}
|