@spintax/core 0.1.6 → 0.2.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 +79 -0
- package/dist/index.cjs +58 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -1
- package/dist/index.d.ts +94 -1
- package/dist/index.js +57 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -22,6 +22,63 @@ interface Ast {
|
|
|
22
22
|
readonly astVersion: typeof AST_VERSION;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Tree-walk renderer with the plugin's staged semantics layered on (parity with
|
|
27
|
+
* Renderer::process_template). Not a naive walk — the deterministic stages are
|
|
28
|
+
* reproduced in order:
|
|
29
|
+
* - #set is a global pre-pass (parser) → setDefs; those enum values are
|
|
30
|
+
* COLLAPSED ONCE here (buildVars), skipping values with `{?`/`{plural ` (they
|
|
31
|
+
* reference vars and defer to the body) — plugin Stage 4b.
|
|
32
|
+
* - variables resolve against the merged map (runtime context > #set); a value
|
|
33
|
+
* that itself contains constructs is re-parsed and rendered (recursive, depth
|
|
34
|
+
* capped) — this covers conditionals/plurals introduced by a variable value
|
|
35
|
+
* (Stages 6b–6c), so a separate pre/post conditional pass isn't needed.
|
|
36
|
+
* - conditionals test truthiness against the raw var map; plurals resolve the
|
|
37
|
+
* count (vars already expanded) then pick the bucket, lenient fullwidth
|
|
38
|
+
* fallback (Stage 6d, after vars).
|
|
39
|
+
* - #include (post-tree string pass) and post-process are later PRs.
|
|
40
|
+
*
|
|
41
|
+
* RNG note: cross-engine RNG-sequence parity is a non-goal (§3.2). Enumerations
|
|
42
|
+
* render outer-first and LAZILY (only the picked branch's nested RNG is used) vs
|
|
43
|
+
* the plugin's eager innermost-out; corpus-safe because deterministic nested-enum
|
|
44
|
+
* cases use order-independent sequences. Permutation matches the plugin's exact
|
|
45
|
+
* pick→Fisher-Yates, so its rng-strategy cases are exact.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/** Document-level render context (threads through nested #include resolution). */
|
|
49
|
+
/**
|
|
50
|
+
* A `{plural …}` block the renderer could not resolve, reported through
|
|
51
|
+
* {@link RenderCtx.onPluralError}. Observation only — the render still degrades
|
|
52
|
+
* exactly as it always has (§0.1 lenient contract); the host decides whether a
|
|
53
|
+
* report is fatal. Mirrors the plugin's `on_error` callable.
|
|
54
|
+
*/
|
|
55
|
+
interface PluralIssue {
|
|
56
|
+
/**
|
|
57
|
+
* `plural.nested-brackets` and `plural.arity` are the same codes `validate()`
|
|
58
|
+
* emits. `plural.count` has no validate counterpart on purpose — an unresolved
|
|
59
|
+
* count is a runtime-value fact, invisible to static analysis.
|
|
60
|
+
*/
|
|
61
|
+
readonly code: 'plural.nested-brackets' | 'plural.arity' | 'plural.count';
|
|
62
|
+
readonly message: string;
|
|
63
|
+
/** The construct as the renderer saw it, AFTER variable expansion. */
|
|
64
|
+
readonly construct: string;
|
|
65
|
+
/** Normalized base language the arity was judged against. */
|
|
66
|
+
readonly locale: string;
|
|
67
|
+
/** Arity verdicts only. */
|
|
68
|
+
readonly expected?: number;
|
|
69
|
+
readonly got?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The full render pipeline with an INJECTED rng — the seam shared by the public
|
|
74
|
+
* render() (which seeds the rng from RenderOptions.seed) and the corpus harness
|
|
75
|
+
* (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what
|
|
76
|
+
* lets the deterministic parity fixtures assert exact output.
|
|
77
|
+
*
|
|
78
|
+
* Order: strip stray sentinels → collapse-once #set + tree-walk (+ #include) →
|
|
79
|
+
* cosmetic post-process (if on) → mandatory neutralize safety-restore (always).
|
|
80
|
+
*/
|
|
81
|
+
|
|
25
82
|
/** Default for {@link PipelineOptions.maxDepth} (#include + parse-nesting guard). */
|
|
26
83
|
declare const DEFAULT_MAX_DEPTH = 20;
|
|
27
84
|
|
|
@@ -69,6 +126,17 @@ interface RenderOptions {
|
|
|
69
126
|
postProcess?: boolean;
|
|
70
127
|
/** #include + parse-nesting guard; defaults to {@link DEFAULT_MAX_DEPTH}. */
|
|
71
128
|
maxDepth?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Observer for `{plural …}` blocks the renderer could not resolve — the port of
|
|
131
|
+
* the plugin's `on_error` callable. Observation ONLY: output degrades exactly as
|
|
132
|
+
* it does without it (§0.1 lenient contract — `render()` never throws on template
|
|
133
|
+
* content), and the host decides whether a report is fatal.
|
|
134
|
+
*
|
|
135
|
+
* Worth wiring when a render is PERSISTED rather than shown: an unresolved count
|
|
136
|
+
* erases its block, which is indistinguishable in the output from copy that was
|
|
137
|
+
* meant to be empty.
|
|
138
|
+
*/
|
|
139
|
+
onPluralError?: (issue: PluralIssue) => void;
|
|
72
140
|
}
|
|
73
141
|
interface ValidateOptions {
|
|
74
142
|
/** Plural-bucket locale for arity verdicts (§3.1); omit ⇒ default 2-form. */
|
|
@@ -107,6 +175,31 @@ interface Analysis extends ExtractResult {
|
|
|
107
175
|
constructs: Record<string, number>;
|
|
108
176
|
}
|
|
109
177
|
|
|
178
|
+
/**
|
|
179
|
+
* A locale's base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. Absent or
|
|
180
|
+
* empty gives `''`.
|
|
181
|
+
*
|
|
182
|
+
* Knows nothing of ISO-639-3, so a 3-letter tag is returned whole (`srp`→`srp`)
|
|
183
|
+
* and is NOT recognized as its 2-letter language.
|
|
184
|
+
*/
|
|
185
|
+
declare function normalizeBaseLang(locale?: string | null): string;
|
|
186
|
+
/**
|
|
187
|
+
* How many `{plural …}` forms this locale takes — 3 for the Slavic one/few/other
|
|
188
|
+
* family (ru/uk/be + sr/hr/bs), 2 for everything else.
|
|
189
|
+
*
|
|
190
|
+
* Takes a RAW locale and normalizes internally, unlike the internal helper of the
|
|
191
|
+
* same name: a public function that silently answered 2 for `sr-Latn` would be a
|
|
192
|
+
* trap. Accepts an absent locale, and unknown tags fall back to 2 rather than
|
|
193
|
+
* throwing (§3.1), so the same optional value `RenderOptions.locale` carries can be
|
|
194
|
+
* passed straight through.
|
|
195
|
+
*
|
|
196
|
+
* NOTE the asymmetry with {@link validate}: an absent or empty locale makes the
|
|
197
|
+
* validator skip the arity check ENTIRELY (structural verdicts only), whereas this
|
|
198
|
+
* answers the 2-form default that {@link render} would then apply. Ask this what
|
|
199
|
+
* render will do; do not read it as "what validate will enforce".
|
|
200
|
+
*/
|
|
201
|
+
declare function pluralArity(locale?: string | null): number;
|
|
202
|
+
|
|
110
203
|
declare function parse(src: string): Ast;
|
|
111
204
|
declare function render(input: string | Ast, opts?: RenderOptions): string;
|
|
112
205
|
declare function validate(input: string | Ast, opts?: ValidateOptions): Diagnostic[];
|
|
@@ -114,4 +207,4 @@ declare function extract(input: string | Ast): ExtractResult;
|
|
|
114
207
|
declare function analyze(input: string | Ast, opts?: ValidateOptions): Analysis;
|
|
115
208
|
declare function neutralize(value: string): string;
|
|
116
209
|
|
|
117
|
-
export { type Analysis, type Ast, AstVersionError, DEFAULT_MAX_DEPTH, type Diagnostic, type ExtractResult, IncludeResolverError, NotImplementedError, type RenderOptions, SpintaxError, type ValidateOptions, analyze, extract, neutralize, parse, render, validate };
|
|
210
|
+
export { type Analysis, type Ast, AstVersionError, DEFAULT_MAX_DEPTH, type Diagnostic, type ExtractResult, IncludeResolverError, NotImplementedError, type PluralIssue, type RenderOptions, SpintaxError, type ValidateOptions, analyze, extract, neutralize, normalizeBaseLang, parse, pluralArity, render, validate };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,63 @@ interface Ast {
|
|
|
22
22
|
readonly astVersion: typeof AST_VERSION;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Tree-walk renderer with the plugin's staged semantics layered on (parity with
|
|
27
|
+
* Renderer::process_template). Not a naive walk — the deterministic stages are
|
|
28
|
+
* reproduced in order:
|
|
29
|
+
* - #set is a global pre-pass (parser) → setDefs; those enum values are
|
|
30
|
+
* COLLAPSED ONCE here (buildVars), skipping values with `{?`/`{plural ` (they
|
|
31
|
+
* reference vars and defer to the body) — plugin Stage 4b.
|
|
32
|
+
* - variables resolve against the merged map (runtime context > #set); a value
|
|
33
|
+
* that itself contains constructs is re-parsed and rendered (recursive, depth
|
|
34
|
+
* capped) — this covers conditionals/plurals introduced by a variable value
|
|
35
|
+
* (Stages 6b–6c), so a separate pre/post conditional pass isn't needed.
|
|
36
|
+
* - conditionals test truthiness against the raw var map; plurals resolve the
|
|
37
|
+
* count (vars already expanded) then pick the bucket, lenient fullwidth
|
|
38
|
+
* fallback (Stage 6d, after vars).
|
|
39
|
+
* - #include (post-tree string pass) and post-process are later PRs.
|
|
40
|
+
*
|
|
41
|
+
* RNG note: cross-engine RNG-sequence parity is a non-goal (§3.2). Enumerations
|
|
42
|
+
* render outer-first and LAZILY (only the picked branch's nested RNG is used) vs
|
|
43
|
+
* the plugin's eager innermost-out; corpus-safe because deterministic nested-enum
|
|
44
|
+
* cases use order-independent sequences. Permutation matches the plugin's exact
|
|
45
|
+
* pick→Fisher-Yates, so its rng-strategy cases are exact.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/** Document-level render context (threads through nested #include resolution). */
|
|
49
|
+
/**
|
|
50
|
+
* A `{plural …}` block the renderer could not resolve, reported through
|
|
51
|
+
* {@link RenderCtx.onPluralError}. Observation only — the render still degrades
|
|
52
|
+
* exactly as it always has (§0.1 lenient contract); the host decides whether a
|
|
53
|
+
* report is fatal. Mirrors the plugin's `on_error` callable.
|
|
54
|
+
*/
|
|
55
|
+
interface PluralIssue {
|
|
56
|
+
/**
|
|
57
|
+
* `plural.nested-brackets` and `plural.arity` are the same codes `validate()`
|
|
58
|
+
* emits. `plural.count` has no validate counterpart on purpose — an unresolved
|
|
59
|
+
* count is a runtime-value fact, invisible to static analysis.
|
|
60
|
+
*/
|
|
61
|
+
readonly code: 'plural.nested-brackets' | 'plural.arity' | 'plural.count';
|
|
62
|
+
readonly message: string;
|
|
63
|
+
/** The construct as the renderer saw it, AFTER variable expansion. */
|
|
64
|
+
readonly construct: string;
|
|
65
|
+
/** Normalized base language the arity was judged against. */
|
|
66
|
+
readonly locale: string;
|
|
67
|
+
/** Arity verdicts only. */
|
|
68
|
+
readonly expected?: number;
|
|
69
|
+
readonly got?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The full render pipeline with an INJECTED rng — the seam shared by the public
|
|
74
|
+
* render() (which seeds the rng from RenderOptions.seed) and the corpus harness
|
|
75
|
+
* (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what
|
|
76
|
+
* lets the deterministic parity fixtures assert exact output.
|
|
77
|
+
*
|
|
78
|
+
* Order: strip stray sentinels → collapse-once #set + tree-walk (+ #include) →
|
|
79
|
+
* cosmetic post-process (if on) → mandatory neutralize safety-restore (always).
|
|
80
|
+
*/
|
|
81
|
+
|
|
25
82
|
/** Default for {@link PipelineOptions.maxDepth} (#include + parse-nesting guard). */
|
|
26
83
|
declare const DEFAULT_MAX_DEPTH = 20;
|
|
27
84
|
|
|
@@ -69,6 +126,17 @@ interface RenderOptions {
|
|
|
69
126
|
postProcess?: boolean;
|
|
70
127
|
/** #include + parse-nesting guard; defaults to {@link DEFAULT_MAX_DEPTH}. */
|
|
71
128
|
maxDepth?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Observer for `{plural …}` blocks the renderer could not resolve — the port of
|
|
131
|
+
* the plugin's `on_error` callable. Observation ONLY: output degrades exactly as
|
|
132
|
+
* it does without it (§0.1 lenient contract — `render()` never throws on template
|
|
133
|
+
* content), and the host decides whether a report is fatal.
|
|
134
|
+
*
|
|
135
|
+
* Worth wiring when a render is PERSISTED rather than shown: an unresolved count
|
|
136
|
+
* erases its block, which is indistinguishable in the output from copy that was
|
|
137
|
+
* meant to be empty.
|
|
138
|
+
*/
|
|
139
|
+
onPluralError?: (issue: PluralIssue) => void;
|
|
72
140
|
}
|
|
73
141
|
interface ValidateOptions {
|
|
74
142
|
/** Plural-bucket locale for arity verdicts (§3.1); omit ⇒ default 2-form. */
|
|
@@ -107,6 +175,31 @@ interface Analysis extends ExtractResult {
|
|
|
107
175
|
constructs: Record<string, number>;
|
|
108
176
|
}
|
|
109
177
|
|
|
178
|
+
/**
|
|
179
|
+
* A locale's base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. Absent or
|
|
180
|
+
* empty gives `''`.
|
|
181
|
+
*
|
|
182
|
+
* Knows nothing of ISO-639-3, so a 3-letter tag is returned whole (`srp`→`srp`)
|
|
183
|
+
* and is NOT recognized as its 2-letter language.
|
|
184
|
+
*/
|
|
185
|
+
declare function normalizeBaseLang(locale?: string | null): string;
|
|
186
|
+
/**
|
|
187
|
+
* How many `{plural …}` forms this locale takes — 3 for the Slavic one/few/other
|
|
188
|
+
* family (ru/uk/be + sr/hr/bs), 2 for everything else.
|
|
189
|
+
*
|
|
190
|
+
* Takes a RAW locale and normalizes internally, unlike the internal helper of the
|
|
191
|
+
* same name: a public function that silently answered 2 for `sr-Latn` would be a
|
|
192
|
+
* trap. Accepts an absent locale, and unknown tags fall back to 2 rather than
|
|
193
|
+
* throwing (§3.1), so the same optional value `RenderOptions.locale` carries can be
|
|
194
|
+
* passed straight through.
|
|
195
|
+
*
|
|
196
|
+
* NOTE the asymmetry with {@link validate}: an absent or empty locale makes the
|
|
197
|
+
* validator skip the arity check ENTIRELY (structural verdicts only), whereas this
|
|
198
|
+
* answers the 2-form default that {@link render} would then apply. Ask this what
|
|
199
|
+
* render will do; do not read it as "what validate will enforce".
|
|
200
|
+
*/
|
|
201
|
+
declare function pluralArity(locale?: string | null): number;
|
|
202
|
+
|
|
110
203
|
declare function parse(src: string): Ast;
|
|
111
204
|
declare function render(input: string | Ast, opts?: RenderOptions): string;
|
|
112
205
|
declare function validate(input: string | Ast, opts?: ValidateOptions): Diagnostic[];
|
|
@@ -114,4 +207,4 @@ declare function extract(input: string | Ast): ExtractResult;
|
|
|
114
207
|
declare function analyze(input: string | Ast, opts?: ValidateOptions): Analysis;
|
|
115
208
|
declare function neutralize(value: string): string;
|
|
116
209
|
|
|
117
|
-
export { type Analysis, type Ast, AstVersionError, DEFAULT_MAX_DEPTH, type Diagnostic, type ExtractResult, IncludeResolverError, NotImplementedError, type RenderOptions, SpintaxError, type ValidateOptions, analyze, extract, neutralize, parse, render, validate };
|
|
210
|
+
export { type Analysis, type Ast, AstVersionError, DEFAULT_MAX_DEPTH, type Diagnostic, type ExtractResult, IncludeResolverError, NotImplementedError, type PluralIssue, type RenderOptions, SpintaxError, type ValidateOptions, analyze, extract, neutralize, normalizeBaseLang, parse, pluralArity, render, validate };
|
package/dist/index.js
CHANGED
|
@@ -342,6 +342,9 @@ function pluralArity(baseLang) {
|
|
|
342
342
|
case "ru":
|
|
343
343
|
case "uk":
|
|
344
344
|
case "be":
|
|
345
|
+
case "sr":
|
|
346
|
+
case "hr":
|
|
347
|
+
case "bs":
|
|
345
348
|
return 3;
|
|
346
349
|
default:
|
|
347
350
|
return 2;
|
|
@@ -355,6 +358,9 @@ function pluralFor(baseLang, n, forms) {
|
|
|
355
358
|
case "ru":
|
|
356
359
|
case "uk":
|
|
357
360
|
case "be":
|
|
361
|
+
case "sr":
|
|
362
|
+
case "hr":
|
|
363
|
+
case "bs":
|
|
358
364
|
if (mod10 === 1 && mod100 !== 11) return forms[0] ?? "";
|
|
359
365
|
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return forms[1] ?? "";
|
|
360
366
|
return forms[2] ?? "";
|
|
@@ -646,7 +652,13 @@ var MAX_VARIABLE_DEPTH = 50;
|
|
|
646
652
|
var INCLUDE_LINE_RE = /^[ \t]*#include[ \t\n\r\f\x0B]+"([^"]+)"[ \t\n\r\f\x0B]*$/gmu;
|
|
647
653
|
function renderAst(ast, ctx) {
|
|
648
654
|
const vars = buildVars(ast.setDefs, ctx.runtimeContext, ctx.rng);
|
|
649
|
-
const text = renderNodes(ast.nodes, {
|
|
655
|
+
const text = renderNodes(ast.nodes, {
|
|
656
|
+
vars,
|
|
657
|
+
rng: ctx.rng,
|
|
658
|
+
locale: ctx.locale,
|
|
659
|
+
depth: 0,
|
|
660
|
+
onPluralError: ctx.onPluralError
|
|
661
|
+
});
|
|
650
662
|
return ctx.resolver ? resolveIncludes(text, ctx) : text;
|
|
651
663
|
}
|
|
652
664
|
function resolveIncludes(text, ctx) {
|
|
@@ -749,17 +761,47 @@ function renderConditional(node, opts) {
|
|
|
749
761
|
function renderPlural(node, opts) {
|
|
750
762
|
const countRaw = expandVarsOnly(node.countRaw, opts);
|
|
751
763
|
const formsRaw = expandVarsOnly(node.formsRaw, opts);
|
|
752
|
-
if (/[{}[\]]/u.test(formsRaw)) return fullwidthVerbatim(countRaw, formsRaw);
|
|
753
|
-
const count = phpTrim2(countRaw);
|
|
754
|
-
if (!/^-?\d+$/u.test(count)) return "";
|
|
755
764
|
const base = normalizeBaseLang(opts.locale);
|
|
765
|
+
const report = (issue) => opts.onPluralError?.(issue);
|
|
766
|
+
if (/[{}[\]]/u.test(formsRaw)) {
|
|
767
|
+
report({
|
|
768
|
+
code: "plural.nested-brackets",
|
|
769
|
+
message: "Plural form slot contains nested spintax brackets; extract via #set first.",
|
|
770
|
+
construct: rawConstruct(countRaw, formsRaw),
|
|
771
|
+
locale: base
|
|
772
|
+
});
|
|
773
|
+
return fullwidthVerbatim(countRaw, formsRaw);
|
|
774
|
+
}
|
|
775
|
+
const count = phpTrim2(countRaw);
|
|
776
|
+
if (!/^-?\d+$/u.test(count)) {
|
|
777
|
+
report({
|
|
778
|
+
code: "plural.count",
|
|
779
|
+
message: `Plural count slot is empty or non-numeric (${JSON.stringify(count)}); block erased.`,
|
|
780
|
+
construct: rawConstruct(countRaw, formsRaw),
|
|
781
|
+
locale: base
|
|
782
|
+
});
|
|
783
|
+
return "";
|
|
784
|
+
}
|
|
756
785
|
const forms = formsRaw.split("|").map((f) => phpTrim2(f));
|
|
757
|
-
if (forms.length !== pluralArity(base))
|
|
786
|
+
if (forms.length !== pluralArity(base)) {
|
|
787
|
+
report({
|
|
788
|
+
code: "plural.arity",
|
|
789
|
+
message: `Plural has ${forms.length} form(s); locale "${base}" takes ${pluralArity(base)}.`,
|
|
790
|
+
construct: rawConstruct(countRaw, formsRaw),
|
|
791
|
+
locale: base,
|
|
792
|
+
expected: pluralArity(base),
|
|
793
|
+
got: forms.length
|
|
794
|
+
});
|
|
795
|
+
return fullwidthVerbatim(countRaw, formsRaw);
|
|
796
|
+
}
|
|
758
797
|
const picked = pluralFor(base, Number.parseInt(count, 10), forms);
|
|
759
798
|
return renderNodes(parseSequence(picked), opts);
|
|
760
799
|
}
|
|
800
|
+
function rawConstruct(countRaw, formsRaw) {
|
|
801
|
+
return `{plural ${countRaw}:${formsRaw}}`;
|
|
802
|
+
}
|
|
761
803
|
function fullwidthVerbatim(countRaw, formsRaw) {
|
|
762
|
-
return
|
|
804
|
+
return rawConstruct(countRaw, formsRaw).replace(/\{/gu, "\uFF5B").replace(/\}/gu, "\uFF5D");
|
|
763
805
|
}
|
|
764
806
|
function renderEnumeration(options, opts) {
|
|
765
807
|
if (options.length === 0) return "";
|
|
@@ -975,7 +1017,8 @@ function renderWith(input, rng, opts = {}) {
|
|
|
975
1017
|
locale: opts.locale ?? "",
|
|
976
1018
|
resolver: opts.includeResolver,
|
|
977
1019
|
maxDepth: opts.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
978
|
-
includeStack: []
|
|
1020
|
+
includeStack: [],
|
|
1021
|
+
onPluralError: opts.onPluralError
|
|
979
1022
|
};
|
|
980
1023
|
const ast = resolveAst(typeof input === "string" ? stripSentinels(input) : input);
|
|
981
1024
|
let out = renderAst(ast, ctx);
|
|
@@ -1012,6 +1055,12 @@ function hashString(s) {
|
|
|
1012
1055
|
}
|
|
1013
1056
|
|
|
1014
1057
|
// src/index.ts
|
|
1058
|
+
function normalizeBaseLang2(locale) {
|
|
1059
|
+
return normalizeBaseLang(locale ?? "");
|
|
1060
|
+
}
|
|
1061
|
+
function pluralArity2(locale) {
|
|
1062
|
+
return pluralArity(normalizeBaseLang2(locale));
|
|
1063
|
+
}
|
|
1015
1064
|
function parse(src) {
|
|
1016
1065
|
return parseTemplate(src);
|
|
1017
1066
|
}
|
|
@@ -1062,6 +1111,6 @@ function neutralize2(value) {
|
|
|
1062
1111
|
return neutralize(value);
|
|
1063
1112
|
}
|
|
1064
1113
|
|
|
1065
|
-
export { AstVersionError, DEFAULT_MAX_DEPTH, IncludeResolverError, NotImplementedError, SpintaxError, analyze, extract, neutralize2 as neutralize, parse, render, validate };
|
|
1114
|
+
export { AstVersionError, DEFAULT_MAX_DEPTH, IncludeResolverError, NotImplementedError, SpintaxError, analyze, extract, neutralize2 as neutralize, normalizeBaseLang2 as normalizeBaseLang, parse, pluralArity2 as pluralArity, render, validate };
|
|
1066
1115
|
//# sourceMappingURL=index.js.map
|
|
1067
1116
|
//# sourceMappingURL=index.js.map
|