quario 0.1.0 → 0.3.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/CHANGELOG.md +191 -0
- package/README.md +19 -4
- package/lib/format.js +60 -0
- package/lib/index.d.ts +210 -13
- package/lib/index.js +157 -69
- package/lib/license.js +1 -1
- package/lib/locate.js +43 -56
- package/lib/plan.js +498 -164
- package/lib/scope.js +4 -10
- package/lib/stream.js +8 -8
- package/lib/style.js +105 -13
- package/package.json +5 -5
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { PadvinderErrorCode, QueryOptions, QueryPath } from "padvinder";
|
|
1
|
+
import type { PadvinderErrorCode, QueryOptions, QueryPath, TrefferErrorCode } from "padvinder";
|
|
2
|
+
import type { XprsnErrorCode, XprsnSignature } from "xprsn";
|
|
2
3
|
import type {
|
|
3
4
|
LiteralToken as SjabloonLiteralToken,
|
|
4
5
|
SjabloonBlock,
|
|
@@ -44,12 +45,20 @@ export interface StyleDeclarations {
|
|
|
44
45
|
italic?: ExpressionValue<boolean>;
|
|
45
46
|
underline?: ExpressionValue<boolean>;
|
|
46
47
|
strikethrough?: ExpressionValue<boolean>;
|
|
48
|
+
/** Render the text in capitals. Capitals, not small caps. */
|
|
49
|
+
uppercase?: ExpressionValue<boolean>;
|
|
47
50
|
/** Text color, `#rgb`/`#rrggbb`. */
|
|
48
51
|
color?: ExpressionValue<string>;
|
|
49
52
|
/** Background color, `#rgb`/`#rrggbb`. */
|
|
50
53
|
background?: ExpressionValue<string>;
|
|
51
54
|
/** Horizontal alignment within the cell. */
|
|
52
55
|
align?: ExpressionValue<Align>;
|
|
56
|
+
/** How a number or date is presented. Locale stays on the instance. */
|
|
57
|
+
format?: ExpressionValue<FormatKind>;
|
|
58
|
+
/** Blank space before this item, in points. */
|
|
59
|
+
spaceBefore?: ExpressionValue<number>;
|
|
60
|
+
/** Blank space after this item, in points. */
|
|
61
|
+
spaceAfter?: ExpressionValue<number>;
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
export interface SortKey {
|
|
@@ -61,6 +70,7 @@ export interface SortKey {
|
|
|
61
70
|
export type CellValue = string;
|
|
62
71
|
|
|
63
72
|
export type Align = "left" | "center" | "right";
|
|
73
|
+
export type FormatKind = "number" | "currency" | "percent" | "date";
|
|
64
74
|
|
|
65
75
|
export interface Cell {
|
|
66
76
|
value: CellValue;
|
|
@@ -82,7 +92,16 @@ export type ImageFit = "natural" | "width";
|
|
|
82
92
|
* error. A narrowing of the one vocabulary rather than a second list of its
|
|
83
93
|
* own, so the two cannot drift.
|
|
84
94
|
*/
|
|
85
|
-
export type ImageStyleDeclarations = Pick<
|
|
95
|
+
export type ImageStyleDeclarations = Pick<
|
|
96
|
+
StyleDeclarations,
|
|
97
|
+
"background" | "align" | "spaceBefore" | "spaceAfter"
|
|
98
|
+
>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* What a report default declares: the two declarations a typeface is made of.
|
|
102
|
+
* Anything else is a definition error, as on an image item.
|
|
103
|
+
*/
|
|
104
|
+
export type ReportStyleDeclarations = Pick<StyleDeclarations, "family" | "size">;
|
|
86
105
|
|
|
87
106
|
/**
|
|
88
107
|
* A host-supplied raster graphic in the band flow. `source` is an expression
|
|
@@ -101,8 +120,31 @@ export interface ImageItem {
|
|
|
101
120
|
style?: ImageStyleDeclarations;
|
|
102
121
|
}
|
|
103
122
|
|
|
104
|
-
/**
|
|
105
|
-
|
|
123
|
+
/**
|
|
124
|
+
* One slot of a split: an ordinary item, plus the width share that is a slot
|
|
125
|
+
* property rather than an item one. A split may not stand in a slot —
|
|
126
|
+
* placement inside placement is the coordinate system quario does not have.
|
|
127
|
+
*/
|
|
128
|
+
export type SplitSlot = (TextItem | ImageItem) & {
|
|
129
|
+
/** Slot width as a percentage of the content width (0 < width <= 100). */
|
|
130
|
+
width?: number;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Items placed across the content width rather than stacked down the band —
|
|
135
|
+
* the invoice header's "seller left, customer right". A split is always the
|
|
136
|
+
* full content width and never nests; a slot that renders nothing keeps its
|
|
137
|
+
* width, so the line's geometry does not move with the data.
|
|
138
|
+
*/
|
|
139
|
+
export interface SplitItem {
|
|
140
|
+
type: "split";
|
|
141
|
+
slots: [SplitSlot, SplitSlot, ...SplitSlot[]];
|
|
142
|
+
visible?: ExpressionValue<boolean>;
|
|
143
|
+
style?: StyleDeclarations;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** One item in a band: text, an image, or a split. Future types may be additive. */
|
|
147
|
+
export type Item = TextItem | ImageItem | SplitItem;
|
|
106
148
|
|
|
107
149
|
export interface TableHeader {
|
|
108
150
|
value: CellValue;
|
|
@@ -121,10 +163,16 @@ export interface TableRow {
|
|
|
121
163
|
style?: StyleDeclarations;
|
|
122
164
|
}
|
|
123
165
|
|
|
166
|
+
export interface TotalRow {
|
|
167
|
+
cells: [Cell, ...Cell[]];
|
|
168
|
+
visible?: ExpressionValue<boolean>;
|
|
169
|
+
style?: StyleDeclarations;
|
|
170
|
+
}
|
|
171
|
+
|
|
124
172
|
export interface TableDetail {
|
|
125
173
|
row?: TableRow;
|
|
126
174
|
columns: [TableColumn, ...TableColumn[]];
|
|
127
|
-
total?:
|
|
175
|
+
total?: [TotalRow, ...TotalRow[]];
|
|
128
176
|
}
|
|
129
177
|
|
|
130
178
|
export interface Group {
|
|
@@ -163,6 +211,8 @@ export interface Group {
|
|
|
163
211
|
export interface PageBands {
|
|
164
212
|
header?: Item[];
|
|
165
213
|
footer?: Item[];
|
|
214
|
+
/** Inset on all four sides, in points. Required when the report header declares `height`. */
|
|
215
|
+
margin?: number;
|
|
166
216
|
}
|
|
167
217
|
|
|
168
218
|
export interface ReportSchema {
|
|
@@ -178,7 +228,17 @@ export interface ReportSchema {
|
|
|
178
228
|
aggregates?: Record<string, ReducerSpec>;
|
|
179
229
|
/** Running accumulators, read as `run.<name>` on detail rows. */
|
|
180
230
|
run?: Record<string, ReducerSpec>;
|
|
181
|
-
|
|
231
|
+
/**
|
|
232
|
+
* The report default: the typeface this document is set in. It sits under
|
|
233
|
+
* the targets' band-role defaults and under every item's own `style`, so a
|
|
234
|
+
* declared `size` does not change a report header's headline size.
|
|
235
|
+
*/
|
|
236
|
+
style?: ReportStyleDeclarations;
|
|
237
|
+
/**
|
|
238
|
+
* Dual-shaped like `detail`: an item array, or `{ height, items }` when the
|
|
239
|
+
* header pins a flow box from the page top.
|
|
240
|
+
*/
|
|
241
|
+
header?: Item[] | { height: number; items: Item[] };
|
|
182
242
|
empty?: Item[];
|
|
183
243
|
/**
|
|
184
244
|
* Flow the report body in this many page columns (integer >= 2). Columned
|
|
@@ -216,6 +276,12 @@ export interface QuarioOptions {
|
|
|
216
276
|
* report this instance compiles marks its output as unlicensed.
|
|
217
277
|
*/
|
|
218
278
|
license?: string;
|
|
279
|
+
/** Locale for `format`. Defaults to `"en-US"` when a kind is presented. */
|
|
280
|
+
locale?: string;
|
|
281
|
+
/** Currency code for `format: "currency"`. Absent, that kind contributes nothing. */
|
|
282
|
+
currency?: string;
|
|
283
|
+
/** Timezone for `format: "date"`. Defaults to `"UTC"`. */
|
|
284
|
+
timeZone?: string;
|
|
219
285
|
}
|
|
220
286
|
|
|
221
287
|
/** The settled result of an instance's license key verification. */
|
|
@@ -246,6 +312,12 @@ export type Token = LiteralToken | ValueToken;
|
|
|
246
312
|
export interface EventCell {
|
|
247
313
|
tokens: Token[];
|
|
248
314
|
style?: Record<string, unknown>;
|
|
315
|
+
/**
|
|
316
|
+
* The definition's schema path, on cells that belong to one: a `row` cell
|
|
317
|
+
* carries its column's (`detail.columns[i]`), a `total-row` cell its
|
|
318
|
+
* `detail.total[r].cells[i]` entry. Absent on page-band cells reached by closure.
|
|
319
|
+
*/
|
|
320
|
+
path?: string;
|
|
249
321
|
}
|
|
250
322
|
|
|
251
323
|
/** The page anchor a paginated target passes to page band closures. */
|
|
@@ -273,6 +345,15 @@ export interface ReportStartEvent {
|
|
|
273
345
|
page?: PageBandRenderers;
|
|
274
346
|
/** The declared page column count, present when the root declares one. */
|
|
275
347
|
columns?: number;
|
|
348
|
+
/**
|
|
349
|
+
* The resolved report default, present when the report declares one. It is
|
|
350
|
+
* a report-level fact rather than something merged into each item's style,
|
|
351
|
+
* so a consumer composes it once — under its own band-role defaults, and
|
|
352
|
+
* under every event's own `style`. Ignoring it renders the report in the
|
|
353
|
+
* consumer's own baseline, which is what a consumer written before this
|
|
354
|
+
* field already does.
|
|
355
|
+
*/
|
|
356
|
+
style?: Record<string, unknown>;
|
|
276
357
|
/**
|
|
277
358
|
* The marking wording, present when this render is not covered by a valid
|
|
278
359
|
* license key — including while verification is still settling (await the
|
|
@@ -281,11 +362,23 @@ export interface ReportStartEvent {
|
|
|
281
362
|
* states it so no target has to know it.
|
|
282
363
|
*/
|
|
283
364
|
marking?: string;
|
|
365
|
+
/** The document's `page.margin`, when declared. */
|
|
366
|
+
margin?: number;
|
|
367
|
+
/** The report header's authored `height`, when the object form is used. */
|
|
368
|
+
headerHeight?: number;
|
|
369
|
+
/** Present when the instance was constructed with `locale`. */
|
|
370
|
+
locale?: string;
|
|
371
|
+
/** Present when the instance was constructed with `currency`. */
|
|
372
|
+
currency?: string;
|
|
373
|
+
/** Present when the instance was constructed with `timeZone`. */
|
|
374
|
+
timeZone?: string;
|
|
284
375
|
}
|
|
285
376
|
|
|
286
377
|
export interface ItemEvent {
|
|
287
378
|
type: "item";
|
|
288
379
|
role: ItemRole;
|
|
380
|
+
/** The item definition's schema path, e.g. `detail[0]`. */
|
|
381
|
+
path: string;
|
|
289
382
|
tokens: Token[];
|
|
290
383
|
style?: Record<string, unknown>;
|
|
291
384
|
run?: Record<string, unknown>;
|
|
@@ -297,6 +390,8 @@ export type ImageFormat = "png" | "jpeg";
|
|
|
297
390
|
export interface ImageEvent {
|
|
298
391
|
type: "image";
|
|
299
392
|
role: ItemRole;
|
|
393
|
+
/** The image definition's schema path. */
|
|
394
|
+
path: string;
|
|
300
395
|
/** The bytes exactly as the `source` expression yielded them. */
|
|
301
396
|
bytes: Uint8Array;
|
|
302
397
|
/** Sniffed from the bytes' magic numbers, so no consumer repeats it. */
|
|
@@ -308,9 +403,28 @@ export interface ImageEvent {
|
|
|
308
403
|
run?: Record<string, unknown>;
|
|
309
404
|
}
|
|
310
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Opens a split: the slot geometry, then one ordinary `item` or `image` event
|
|
408
|
+
* per slot in order, then `split-end`. A consumer with no handler for the
|
|
409
|
+
* bracket still receives the slot items and renders them stacked.
|
|
410
|
+
*/
|
|
411
|
+
export interface SplitStartEvent {
|
|
412
|
+
type: "split-start";
|
|
413
|
+
role: ItemRole;
|
|
414
|
+
/** One entry per slot, in order; `width` is absent on a width-less slot. */
|
|
415
|
+
slots: { width?: number }[];
|
|
416
|
+
style?: Record<string, unknown>;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export interface SplitEndEvent {
|
|
420
|
+
type: "split-end";
|
|
421
|
+
}
|
|
422
|
+
|
|
311
423
|
export interface GroupStartEvent {
|
|
312
424
|
type: "group-start";
|
|
313
425
|
name: string;
|
|
426
|
+
/** The group definition's schema path, e.g. `groups[0]`. */
|
|
427
|
+
path: string;
|
|
314
428
|
depth: number;
|
|
315
429
|
key: unknown;
|
|
316
430
|
aggregates: Record<string, unknown>;
|
|
@@ -329,7 +443,11 @@ export interface GroupEndEvent {
|
|
|
329
443
|
|
|
330
444
|
export interface TableStartEvent {
|
|
331
445
|
type: "table-start";
|
|
332
|
-
|
|
446
|
+
/** Always `detail` — the table definition's schema path. */
|
|
447
|
+
path: string;
|
|
448
|
+
columns: { header: EventCell; path: string; width?: number }[];
|
|
449
|
+
/** The header-row box from `detail.header`, when declared. */
|
|
450
|
+
style?: Record<string, unknown>;
|
|
333
451
|
}
|
|
334
452
|
|
|
335
453
|
export interface RowEvent {
|
|
@@ -342,6 +460,8 @@ export interface RowEvent {
|
|
|
342
460
|
export interface TotalRowEvent {
|
|
343
461
|
type: "total-row";
|
|
344
462
|
cells: EventCell[];
|
|
463
|
+
/** The total-row box from that row's `style`, when declared. */
|
|
464
|
+
style?: Record<string, unknown>;
|
|
345
465
|
}
|
|
346
466
|
|
|
347
467
|
export interface TableEndEvent {
|
|
@@ -356,6 +476,8 @@ export type ReportEvent =
|
|
|
356
476
|
| ReportStartEvent
|
|
357
477
|
| ItemEvent
|
|
358
478
|
| ImageEvent
|
|
479
|
+
| SplitStartEvent
|
|
480
|
+
| SplitEndEvent
|
|
359
481
|
| GroupStartEvent
|
|
360
482
|
| GroupEndEvent
|
|
361
483
|
| TableStartEvent
|
|
@@ -364,10 +486,19 @@ export type ReportEvent =
|
|
|
364
486
|
| TableEndEvent
|
|
365
487
|
| ReportEndEvent;
|
|
366
488
|
|
|
489
|
+
/**
|
|
490
|
+
* One registry function a compiled report calls: its arity (the function's
|
|
491
|
+
* declared parameter count, or its own numeric `arity` where `length`
|
|
492
|
+
* misleads) and its own `doc` string when it carries one — xprsn's
|
|
493
|
+
* `signatures()` convention, in call-first-seen order. Aliased so hosts type
|
|
494
|
+
* the metadata from 'quario' alone, without their own xprsn dependency.
|
|
495
|
+
*/
|
|
496
|
+
export type FunctionSignature = XprsnSignature;
|
|
497
|
+
|
|
367
498
|
export interface ReportEventStream {
|
|
368
499
|
(data?: unknown): Generator<ReportEvent, void, undefined>;
|
|
369
500
|
readonly names: readonly string[];
|
|
370
|
-
readonly functions: readonly
|
|
501
|
+
readonly functions: readonly FunctionSignature[];
|
|
371
502
|
readonly paths: readonly QueryPath[];
|
|
372
503
|
}
|
|
373
504
|
|
|
@@ -397,10 +528,23 @@ export function walk(events: Iterable<ReportEvent>, handlers: WalkHandlers): Pro
|
|
|
397
528
|
*/
|
|
398
529
|
export function breathe(): Promise<void>;
|
|
399
530
|
|
|
400
|
-
|
|
531
|
+
/**
|
|
532
|
+
* Every code a located diagnostic can carry, which is a code from whichever
|
|
533
|
+
* engine decided the fault: quario relocates xprsn's directly, sjabloon
|
|
534
|
+
* carries xprsn's on a fault inside an expression, and padvinder carries
|
|
535
|
+
* treffer's on a pattern literal rejected when the query compiles.
|
|
536
|
+
*
|
|
537
|
+
* `TrefferErrorCode` reaches this union through padvinder, which re-exports
|
|
538
|
+
* it, so quario needs no treffer dependency to name it here.
|
|
539
|
+
*/
|
|
540
|
+
export type QuarioErrorCode =
|
|
541
|
+
| SjabloonErrorCode
|
|
542
|
+
| XprsnErrorCode
|
|
543
|
+
| PadvinderErrorCode
|
|
544
|
+
| TrefferErrorCode;
|
|
401
545
|
|
|
402
546
|
export interface QuarioDiagnostic extends Error {
|
|
403
|
-
/** Absent on
|
|
547
|
+
/** Absent on option and target-definition faults; present on every other diagnostic. */
|
|
404
548
|
readonly code?: QuarioErrorCode;
|
|
405
549
|
readonly start?: number;
|
|
406
550
|
readonly end?: number;
|
|
@@ -414,7 +558,7 @@ export interface CompiledReport {
|
|
|
414
558
|
/** The raw event seam: one generator of report events per call. */
|
|
415
559
|
stream(data?: unknown): Generator<ReportEvent, void, undefined>;
|
|
416
560
|
readonly names: readonly string[];
|
|
417
|
-
readonly functions: readonly
|
|
561
|
+
readonly functions: readonly FunctionSignature[];
|
|
418
562
|
readonly paths: readonly QueryPath[];
|
|
419
563
|
/**
|
|
420
564
|
* Render this compiled report through one target. Resolves the target's
|
|
@@ -424,6 +568,33 @@ export interface CompiledReport {
|
|
|
424
568
|
render<Out>(target: Target<string, Out>, data?: unknown): Promise<Awaited<Out>>;
|
|
425
569
|
}
|
|
426
570
|
|
|
571
|
+
/**
|
|
572
|
+
* One definition problem, structurally: the schema path it sits at, the
|
|
573
|
+
* offending author source when the problem came from compiling one, the whole
|
|
574
|
+
* located message (`validate()`'s string is exactly this field), and the
|
|
575
|
+
* engine's located diagnostic when one authenticated the fault — every
|
|
576
|
+
* problem keeps its own, offsets included, not only the first.
|
|
577
|
+
*/
|
|
578
|
+
export interface Problem {
|
|
579
|
+
readonly path: string;
|
|
580
|
+
readonly source?: string;
|
|
581
|
+
readonly message: string;
|
|
582
|
+
readonly diagnostic?: QuarioDiagnostic;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* The plan: both readings of the one traversal, kept. `report` is the
|
|
587
|
+
* compiled report, or null while the document has problems; `problems` is the
|
|
588
|
+
* structured list `validate()` flattens to strings; `anchors` maps each
|
|
589
|
+
* compiled source's schema path to the anchors and group handles it reads —
|
|
590
|
+
* the unfiltered complement of `names`, which excludes them.
|
|
591
|
+
*/
|
|
592
|
+
export interface Plan {
|
|
593
|
+
readonly report: CompiledReport | null;
|
|
594
|
+
readonly problems: readonly Problem[];
|
|
595
|
+
readonly anchors: Readonly<Record<string, readonly string[]>>;
|
|
596
|
+
}
|
|
597
|
+
|
|
427
598
|
export interface Quario {
|
|
428
599
|
/**
|
|
429
600
|
* Settles when this instance's license key verification completes;
|
|
@@ -432,6 +603,12 @@ export interface Quario {
|
|
|
432
603
|
readonly license: Promise<LicenseInfo>;
|
|
433
604
|
/** Compile a definition once; every target renders from it. */
|
|
434
605
|
report(schema: ReportSchema, functions?: FunctionRegistry): CompiledReport;
|
|
606
|
+
/**
|
|
607
|
+
* The one traversal, whole: compiled report (null on problems), structured
|
|
608
|
+
* problems, and per-node anchor sets — one descent per edit for a host that
|
|
609
|
+
* validates and renders in a loop.
|
|
610
|
+
*/
|
|
611
|
+
plan(schema: unknown, functions?: FunctionRegistry): Plan;
|
|
435
612
|
}
|
|
436
613
|
|
|
437
614
|
/**
|
|
@@ -451,11 +628,31 @@ export function validate(schema: unknown, functions?: FunctionRegistry): string[
|
|
|
451
628
|
export function isDiagnostic(e: unknown): e is QuarioDiagnostic;
|
|
452
629
|
|
|
453
630
|
/**
|
|
454
|
-
* Join a token stream to display text: literals verbatim, values
|
|
455
|
-
* `
|
|
631
|
+
* Join a token stream to display text: literals verbatim, values through
|
|
632
|
+
* `display()`. Re-exported from sjabloon.
|
|
456
633
|
*/
|
|
457
634
|
export function text(tokens: readonly Token[]): string;
|
|
458
635
|
|
|
636
|
+
/**
|
|
637
|
+
* Display text for one token value — the scalar rule `text()` joins with,
|
|
638
|
+
* re-exported from sjabloon so targets stringify exactly as the stream does.
|
|
639
|
+
* A valid `Date` renders as ISO 8601 UTC (`toISOString()`), deterministically
|
|
640
|
+
* across machines; an invalid `Date` stays `"Invalid Date"`; nullish displays
|
|
641
|
+
* empty; everything else is `String(value)`.
|
|
642
|
+
*/
|
|
643
|
+
export function display(value: unknown): string;
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Present a token for a resolved `format` kind. Returns nothing when the kind
|
|
647
|
+
* does not apply, so the caller falls back to `display()`. Locale defaults to
|
|
648
|
+
* `"en-US"`, dates to UTC.
|
|
649
|
+
*/
|
|
650
|
+
export function format(
|
|
651
|
+
value: unknown,
|
|
652
|
+
kind: unknown,
|
|
653
|
+
options?: { locale?: string; currency?: string; timeZone?: string } | null,
|
|
654
|
+
): string | undefined;
|
|
655
|
+
|
|
459
656
|
/**
|
|
460
657
|
* The typed-cell seam: exactly one value token holding a finite number, a
|
|
461
658
|
* boolean, or a valid Date keeps its pre-stringify value; anything else —
|