@stll/template-conditions 0.6.4 → 0.6.5
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 +1 -23
- package/dist/index.js +11 -22
- package/dist/path.d.ts +1 -3
- package/dist/path.js +1 -2
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { resolvePath } from "./path.js";
|
|
2
1
|
import { CompareNode, CompareOp, Condition, ConditionNode, ConditionNode as ConditionNode$1, GroupNode, Operand, PredicateNode, PredicateOp, conditionHasFormula, conditionNodeSchema, conditionSchema, emptyCondition } from "@stll/conditions";
|
|
3
|
-
|
|
2
|
+
import { resolvePath } from "./path.js";
|
|
4
3
|
/** Maximum combined nesting of parentheses and unary negation. */
|
|
5
4
|
export declare const MAX_CONDITION_NESTING = 256;
|
|
6
5
|
/** Bare words the tokenizer reads as operators or literals; a data path can
|
|
7
6
|
* never be one of them. */
|
|
8
7
|
export declare const CONDITION_RESERVED_WORDS: readonly ["and", "or", "not", "in", "is", "defined", "true", "false"];
|
|
9
8
|
export declare const parseCondition: (expression: string) => ConditionNode$1 | null;
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/referenced-paths.d.ts
|
|
12
9
|
/**
|
|
13
10
|
* What a `{% if %}` expression reads. Structural, not evaluative: the paths a
|
|
14
11
|
* condition depends on, for callers that decide something about the condition
|
|
@@ -23,8 +20,6 @@ export declare const parseCondition: (expression: string) => ConditionNode$1 | n
|
|
|
23
20
|
* nothing".
|
|
24
21
|
*/
|
|
25
22
|
export declare const referencedConditionPaths: (expression: string) => string[] | null;
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/compute.d.ts
|
|
28
23
|
/**
|
|
29
24
|
* Arithmetic evaluator for computed template fields.
|
|
30
25
|
*
|
|
@@ -45,8 +40,6 @@ export declare const referencedConditionPaths: (expression: string) => string[]
|
|
|
45
40
|
export declare const NUMERIC_FUNCTION_NAMES: readonly ["min", "max", "round", "abs", "floor", "ceil"];
|
|
46
41
|
type NumericFunctionName = (typeof NUMERIC_FUNCTION_NAMES)[number];
|
|
47
42
|
export declare const evaluateNumericExpression: (expression: string, data: Record<string, unknown>) => number | undefined;
|
|
48
|
-
//#endregion
|
|
49
|
-
//#region src/field-values.d.ts
|
|
50
43
|
/**
|
|
51
44
|
* Single source of truth for the DETERMINISTIC field-value transforms a
|
|
52
45
|
* template fill applies: formula (arithmetic over the other values) and
|
|
@@ -112,16 +105,12 @@ type DeterministicFieldConfig = {
|
|
|
112
105
|
* value, so the caller leaves the field as-is.
|
|
113
106
|
*/
|
|
114
107
|
export declare const renderDeterministicFieldValue: (field: DeterministicFieldConfig, values: Record<string, unknown>) => string | null;
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region src/condition-builder.d.ts
|
|
117
108
|
/**
|
|
118
109
|
* Serialize a condition tree into an expression for `evaluateCondition`.
|
|
119
110
|
* Returns an empty string for an empty tree (caller treats that as "no
|
|
120
111
|
* condition" / always-visible).
|
|
121
112
|
*/
|
|
122
113
|
export declare const serializeCondition: (node: ConditionNode$1) => string;
|
|
123
|
-
//#endregion
|
|
124
|
-
//#region src/markers.d.ts
|
|
125
114
|
/**
|
|
126
115
|
* Canonical grammar for the docxtpl dialect of Jinja — the single source of
|
|
127
116
|
* truth shared by the fill pipeline (api), the editor highlighter (folio), and
|
|
@@ -385,8 +374,6 @@ type MarkerDefect = {
|
|
|
385
374
|
export declare const classifyMarkerDefect: (innerRaw: string, form?: MarkerForm) => MarkerDefect | null;
|
|
386
375
|
/** Exhaustiveness guard — pass the discriminant in a `switch` default branch. */
|
|
387
376
|
export declare const assertNever: (value: never) => never;
|
|
388
|
-
//#endregion
|
|
389
|
-
//#region src/loop-scope.d.ts
|
|
390
377
|
/**
|
|
391
378
|
* The path a marker names, once the loops around it are taken into account.
|
|
392
379
|
*
|
|
@@ -415,8 +402,6 @@ export declare const qualifyRowScopedPath: (path: string, rowPaths?: readonly st
|
|
|
415
402
|
export declare const qualifyRowScopedPlaceholder: (path: string, rowScopes: readonly RowScope[]) => string;
|
|
416
403
|
/** The manifest path for an array a `{% for %}` opens inside these loops. */
|
|
417
404
|
export declare const qualifyLoopPath: (declaredPath: string, rowScopes: readonly RowScope[]) => string;
|
|
418
|
-
//#endregion
|
|
419
|
-
//#region src/field-config.d.ts
|
|
420
405
|
/** Where a field's value comes from, when a record supplies it. Only the shape
|
|
421
406
|
* the filters read: each caller's own union satisfies it. */
|
|
422
407
|
type MarkerFieldSource = {
|
|
@@ -500,8 +485,6 @@ export declare const filtersFromFieldConfig: (field: MarkerFieldConfig) => Filte
|
|
|
500
485
|
* value filter can never be written where the reader refuses it.
|
|
501
486
|
*/
|
|
502
487
|
export declare const arrayFiltersFromFieldConfig: (field: MarkerFieldConfig) => FilterCall[];
|
|
503
|
-
//#endregion
|
|
504
|
-
//#region src/render.d.ts
|
|
505
488
|
/** Why a value has no spelling the scanner reads back as itself. */
|
|
506
489
|
type UnwritableReason = "tag-delimiter" | "number-spelling";
|
|
507
490
|
/** The reason this literal cannot be written in a marker of this form, or
|
|
@@ -558,8 +541,6 @@ type ForOpenerOptions = {
|
|
|
558
541
|
};
|
|
559
542
|
/** One `{% for %}` opener, keeping its placement prefix. */
|
|
560
543
|
export declare const renderForOpener: ({ alias, filters, path, prefix }: ForOpenerOptions) => string;
|
|
561
|
-
//#endregion
|
|
562
|
-
//#region src/row-blocks.d.ts
|
|
563
544
|
/** One end of a row block, addressed within the row that was scanned. */
|
|
564
545
|
type RowBlockMarker = {
|
|
565
546
|
/** Index into the row's cells. */
|
|
@@ -586,8 +567,6 @@ type RowBlockPair = {
|
|
|
586
567
|
* engine's existing structure errors rather than guessed at.
|
|
587
568
|
*/
|
|
588
569
|
export declare const detectRowBlockPair: (cells: readonly (readonly string[])[]) => RowBlockPair | null;
|
|
589
|
-
//#endregion
|
|
590
|
-
//#region src/index.d.ts
|
|
591
570
|
export type NamedCondition = {
|
|
592
571
|
name: string;
|
|
593
572
|
/** The `{% if %}` expression string. Authoritative unless `node` is set. */
|
|
@@ -620,5 +599,4 @@ export declare const MAX_CONDITION_DEPTH = 50;
|
|
|
620
599
|
* branch true).
|
|
621
600
|
*/
|
|
622
601
|
export declare const evaluateCondition: (expression: string, data: Record<string, unknown>, namedConditions?: readonly NamedCondition[], _resolved?: ReadonlySet<string>, _depth?: number) => boolean;
|
|
623
|
-
//#endregion
|
|
624
602
|
export { type BlockDirectiveKind, type CompareNode, type CompareOp, type Condition, type ConditionNode, type ConditionTagOptions, type DateFormatStyle, type DeterministicFieldConfig, type DirectiveKind, type FieldDateFormat, type FilterArgument, type FilterCall, type FilterName, type ForOpenerOptions, type GroupNode, type InvalidMarker, type LoopProperty, type MarkerDefect, type MarkerDefectKind, type MarkerFieldConfig, type MarkerFieldInputType, type MarkerFieldLookup, type MarkerFieldSource, type MarkerFieldValidation, type MarkerForm, type MarkerLiteral, type MarkerMeta, type MarkerPrefix, type NumericFunctionName, type Operand, type PredicateNode, type PredicateOp, type RowBlockMarker, type RowBlockPair, type RowScope, type ScannedMarker, type UnwritableReason, conditionHasFormula, conditionNodeSchema, conditionSchema, emptyCondition, resolvePath };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { resolvePath } from "./path.js";
|
|
|
2
2
|
import { conditionHasFormula, conditionNodeSchema, conditionSchema, emptyCondition, evaluateCondition as evaluateCondition$1 } from "@stll/conditions";
|
|
3
3
|
import { Result, panic } from "better-result";
|
|
4
4
|
import { Temporal } from "temporal-polyfill/full";
|
|
5
|
-
|
|
5
|
+
// src/compute.ts
|
|
6
6
|
/**
|
|
7
7
|
* Arithmetic evaluator for computed template fields.
|
|
8
8
|
*
|
|
@@ -163,8 +163,7 @@ const evaluateNumericExpression = (expression, data) => {
|
|
|
163
163
|
return;
|
|
164
164
|
}
|
|
165
165
|
};
|
|
166
|
-
|
|
167
|
-
//#region src/parse.ts
|
|
166
|
+
// src/parse.ts
|
|
168
167
|
/** Maximum combined nesting of parentheses and unary negation. */
|
|
169
168
|
const MAX_CONDITION_NESTING = 256;
|
|
170
169
|
const COMPARE_SYMBOL_TO_OP = {
|
|
@@ -426,8 +425,7 @@ const parseCondition = (expression) => {
|
|
|
426
425
|
};
|
|
427
426
|
return parseOr(0);
|
|
428
427
|
};
|
|
429
|
-
|
|
430
|
-
//#region src/referenced-paths.ts
|
|
428
|
+
// src/referenced-paths.ts
|
|
431
429
|
const operandsOf = (node) => node.type === "compare" ? [node.left, node.right] : [node.operand];
|
|
432
430
|
/** Every field path the tree reads, or `null` when an operand names something
|
|
433
431
|
* whose own references cannot be enumerated (a formula over other fields). */
|
|
@@ -460,8 +458,7 @@ const referencedConditionPaths = (expression) => {
|
|
|
460
458
|
const node = parseCondition(expression);
|
|
461
459
|
return node === null ? null : nodePaths(node);
|
|
462
460
|
};
|
|
463
|
-
|
|
464
|
-
//#region src/field-values.ts
|
|
461
|
+
// src/field-values.ts
|
|
465
462
|
/**
|
|
466
463
|
* Single source of truth for the DETERMINISTIC field-value transforms a
|
|
467
464
|
* template fill applies: formula (arithmetic over the other values) and
|
|
@@ -560,8 +557,7 @@ const renderDeterministicFieldValue = (field, values) => {
|
|
|
560
557
|
}
|
|
561
558
|
return null;
|
|
562
559
|
};
|
|
563
|
-
|
|
564
|
-
//#region src/condition-builder.ts
|
|
560
|
+
// src/condition-builder.ts
|
|
565
561
|
const COMPARE_OP_TO_SYMBOL = {
|
|
566
562
|
eq: "==",
|
|
567
563
|
neq: "!=",
|
|
@@ -618,8 +614,7 @@ const serializeNode = (node, top) => {
|
|
|
618
614
|
* condition" / always-visible).
|
|
619
615
|
*/
|
|
620
616
|
const serializeCondition = (node) => serializeNode(node, true);
|
|
621
|
-
|
|
622
|
-
//#region src/markers.ts
|
|
617
|
+
// src/markers.ts
|
|
623
618
|
/**
|
|
624
619
|
* Canonical grammar for the docxtpl dialect of Jinja — the single source of
|
|
625
620
|
* truth shared by the fill pipeline (api), the editor highlighter (folio), and
|
|
@@ -1298,8 +1293,7 @@ const classifyMarkerDefect = (innerRaw, form = "output") => {
|
|
|
1298
1293
|
};
|
|
1299
1294
|
/** Exhaustiveness guard — pass the discriminant in a `switch` default branch. */
|
|
1300
1295
|
const assertNever = (value) => panic(`Unhandled template directive: ${JSON.stringify(value)}`);
|
|
1301
|
-
|
|
1302
|
-
//#region src/loop-scope.ts
|
|
1296
|
+
// src/loop-scope.ts
|
|
1303
1297
|
const rowScopePaths = (rowScopes) => rowScopes.map(({ scopedPath }) => scopedPath);
|
|
1304
1298
|
/** A path already under the innermost repeat is left alone; anything else is
|
|
1305
1299
|
* read as a name relative to it. */
|
|
@@ -1319,8 +1313,7 @@ const qualifyRowScopedPlaceholder = (path, rowScopes) => {
|
|
|
1319
1313
|
};
|
|
1320
1314
|
/** The manifest path for an array a `{% for %}` opens inside these loops. */
|
|
1321
1315
|
const qualifyLoopPath = (declaredPath, rowScopes) => qualifyRowScopedPath(qualifyRowScopedPlaceholder(declaredPath, rowScopes), rowScopePaths(rowScopes));
|
|
1322
|
-
|
|
1323
|
-
//#region src/field-config.ts
|
|
1316
|
+
// src/field-config.ts
|
|
1324
1317
|
/**
|
|
1325
1318
|
* The filters that describe a REPEAT rather than a value: how many rows it
|
|
1326
1319
|
* takes and what to call it. These are the ones a `{% for %}` tag may carry,
|
|
@@ -1442,8 +1435,7 @@ const filtersFromFieldConfig = (field) => Object.values(MARKER_FIELD_FILTERS).fl
|
|
|
1442
1435
|
* value filter can never be written where the reader refuses it.
|
|
1443
1436
|
*/
|
|
1444
1437
|
const arrayFiltersFromFieldConfig = (field) => filtersFromFieldConfig(field).filter(({ name }) => isArrayFilterName(name));
|
|
1445
|
-
|
|
1446
|
-
//#region src/render.ts
|
|
1438
|
+
// src/render.ts
|
|
1447
1439
|
/** The number literals the scanner reads: no exponent, no `Infinity`. */
|
|
1448
1440
|
const WRITABLE_NUMBER = /^-?\d+(?:\.\d+)?$/u;
|
|
1449
1441
|
/** What a tag's body cannot carry: it has no quoted-run escape hatch, so a
|
|
@@ -1516,8 +1508,7 @@ const renderForOpener = ({ alias, filters, path, prefix }) => {
|
|
|
1516
1508
|
const head = `{%${PREFIX_TOKEN[prefix]} for ${alias} in ${path}`;
|
|
1517
1509
|
return chain === "" ? `${head} %}` : `${head} | ${chain} %}`;
|
|
1518
1510
|
};
|
|
1519
|
-
|
|
1520
|
-
//#region src/row-blocks.ts
|
|
1511
|
+
// src/row-blocks.ts
|
|
1521
1512
|
/**
|
|
1522
1513
|
* Row-form block markers: the lenient placement authoring agents actually
|
|
1523
1514
|
* write for a "one row per item" table.
|
|
@@ -1626,8 +1617,7 @@ const detectRowBlockPair = (cells) => {
|
|
|
1626
1617
|
close
|
|
1627
1618
|
};
|
|
1628
1619
|
};
|
|
1629
|
-
|
|
1630
|
-
//#region src/index.ts
|
|
1620
|
+
// src/index.ts
|
|
1631
1621
|
/**
|
|
1632
1622
|
* Shared condition evaluation + marker grammar for DOCX templates. Small,
|
|
1633
1623
|
* side-effect-free functions usable on both backend (Bun) and frontend
|
|
@@ -1700,5 +1690,4 @@ const evaluateCondition = (expression, data, namedConditions, _resolved = /* @__
|
|
|
1700
1690
|
if (node === null) return false;
|
|
1701
1691
|
return evaluateCondition$1(node, makeResolver(data, namedConditions, _resolved, _depth));
|
|
1702
1692
|
};
|
|
1703
|
-
//#endregion
|
|
1704
1693
|
export { ARRAY_FILTER_NAMES, BLOCK_DIRECTIVE_KINDS, CONDITION_RESERVED_WORDS, DATE_FORMAT_EXAMPLE_ISO, DATE_FORMAT_STYLES, DIRECTIVE_KINDS, FILTER_NAMES, LOOP_PROPERTIES, MARKER_DEFECT_KINDS, MARKER_OUTPUT_BODY, MARKER_STATEMENT_BODY, MAX_CONDITION_DEPTH, MAX_CONDITION_NESTING, NUMERIC_FUNCTION_NAMES, arrayFiltersFromFieldConfig, assertNever, blockDirectiveLinePattern, classifyMarker, classifyMarkerDefect, clauseSlotKey, clauseSlotPattern, conditionHasFormula, conditionNodeSchema, conditionSchema, detectRowBlockPair, emptyCondition, evaluateCondition, evaluateNumericExpression, filtersFromFieldConfig, formatDate, hasBlockDirectivePattern, hasNumberingPattern, isArrayFilterName, isBlockDirectiveKind, isClauseSlotName, isFieldPath, isSafeFieldPath, legacyLoopAlias, legacyMarkerReplacement, loopPattern, markerPattern, normalizeMarkerInner, numPattern, parseCondition, placeholderPattern, qualifyLoopPath, qualifyRowScopedPath, qualifyRowScopedPlaceholder, refPattern, referencedConditionPaths, renderConditionTag, renderDeterministicFieldValue, renderFilterChain, renderForOpener, renderValueMarker, replaceOutputMarkers, resolvePath, rowScopePaths, scanInvalidMarkers, scanMarkers, serializeCondition, substitutionKey, translateLegacyExpression, unwritableFilterValues, unwritableMarkerLiteral };
|
package/dist/path.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/path.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Dotted-path resolution against a data record. Extracted from index.ts so both
|
|
4
3
|
* the condition engine (index.ts) and the arithmetic evaluator (compute.ts) can
|
|
@@ -13,5 +12,4 @@
|
|
|
13
12
|
*/
|
|
14
13
|
export declare const isNonNullObject: (v: unknown) => v is Record<string, unknown>;
|
|
15
14
|
/** Resolve a dotted path like `company.name` against data. */
|
|
16
|
-
export declare const resolvePath: (path: string, data: Record<string, unknown>) => unknown;
|
|
17
|
-
//#endregion
|
|
15
|
+
export declare const resolvePath: (path: string, data: Record<string, unknown>) => unknown;
|
package/dist/path.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/path.ts
|
|
2
2
|
/**
|
|
3
3
|
* Dotted-path resolution against a data record. Extracted from index.ts so both
|
|
4
4
|
* the condition engine (index.ts) and the arithmetic evaluator (compute.ts) can
|
|
@@ -23,5 +23,4 @@ const resolvePath = (path, data) => {
|
|
|
23
23
|
}
|
|
24
24
|
return current;
|
|
25
25
|
};
|
|
26
|
-
//#endregion
|
|
27
26
|
export { isNonNullObject, resolvePath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/template-conditions",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "A document-template marker and condition engine: {{...}} marker grammar, parse, compute, serialize, field values.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"condition",
|
|
@@ -46,23 +46,23 @@
|
|
|
46
46
|
"pack:dry-run": "bun pm pack --dry-run",
|
|
47
47
|
"test": "bun test",
|
|
48
48
|
"test:property": "bun test --preload @stll/property-testing/preload $(grep -rlE 'fc\\.assert|assertProperty' src --include='*.test.ts')",
|
|
49
|
-
"typecheck": "bun
|
|
49
|
+
"typecheck": "bun check --no-pretty --all --project=tsconfig.json",
|
|
50
50
|
"lint": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --report-unused-disable-directives-severity=error --type-aware --type-check packages/template-conditions",
|
|
51
51
|
"lint:fix": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --type-aware --fix packages/template-conditions",
|
|
52
|
-
"format": "bun ../../scripts/run-oxfmt.ts .",
|
|
53
52
|
"prepack": "bun run build"
|
|
54
53
|
},
|
|
55
54
|
"dependencies": {
|
|
56
55
|
"@stll/conditions": "^0.4.0",
|
|
57
56
|
"better-result": "3.0.1",
|
|
58
|
-
"temporal-polyfill": "1.0.
|
|
57
|
+
"temporal-polyfill": "1.0.6"
|
|
59
58
|
},
|
|
60
59
|
"devDependencies": {
|
|
61
60
|
"@stll/property-testing": "0.0.0",
|
|
62
61
|
"@stll/typescript-config": "0.0.0",
|
|
63
|
-
"bun-types": "1.4.
|
|
62
|
+
"bun-types": "1.4.4",
|
|
64
63
|
"fast-check": "^4.10.2",
|
|
65
|
-
"tsdown": "0.23.
|
|
64
|
+
"tsdown": "0.23.4",
|
|
65
|
+
"tsrs": "0.20.1-ts7.1.0-beta"
|
|
66
66
|
},
|
|
67
67
|
"main": "./dist/index.js",
|
|
68
68
|
"types": "./dist/index.d.ts"
|