@spintax/core 0.3.0 → 0.3.1

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.cts CHANGED
@@ -81,7 +81,7 @@ interface PluralIssue {
81
81
  * (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what
82
82
  * lets the deterministic parity fixtures assert exact output.
83
83
  *
84
- * Order: strip stray sentinels → collapse-once #set + tree-walk (+ #include) →
84
+ * Order: strip stray sentinels → build vars, roll #def, tree-walk (+ #include) →
85
85
  * cosmetic post-process (if on) → mandatory neutralize safety-restore (always).
86
86
  */
87
87
 
package/dist/index.d.ts CHANGED
@@ -81,7 +81,7 @@ interface PluralIssue {
81
81
  * (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what
82
82
  * lets the deterministic parity fixtures assert exact output.
83
83
  *
84
- * Order: strip stray sentinels → collapse-once #set + tree-walk (+ #include) →
84
+ * Order: strip stray sentinels → build vars, roll #def, tree-walk (+ #include) →
85
85
  * cosmetic post-process (if on) → mandatory neutralize safety-restore (always).
86
86
  */
87
87
 
package/dist/index.js CHANGED
@@ -21,13 +21,38 @@ function isParsedAst(value) {
21
21
  return typeof value === "object" && value !== null && value.astVersion === AST_VERSION && typeof value.source === "string" && Array.isArray(value.nodes);
22
22
  }
23
23
 
24
+ // src/internal/neutralize.ts
25
+ var STRUCTURAL = ["{", "}", "[", "]", "%", "#"];
26
+ var SENTINEL_BASE = 57344;
27
+ var SHIELD = /* @__PURE__ */ new Map();
28
+ var RESTORE = /* @__PURE__ */ new Map();
29
+ STRUCTURAL.forEach((ch, i) => {
30
+ const sentinel = String.fromCharCode(SENTINEL_BASE + i);
31
+ SHIELD.set(ch, sentinel);
32
+ RESTORE.set(sentinel, ch);
33
+ });
34
+ var SHIELD_RE = /[{}[\]%#]/gu;
35
+ var RESTORE_RE = new RegExp(
36
+ `[${String.fromCharCode(SENTINEL_BASE)}-${String.fromCharCode(SENTINEL_BASE + STRUCTURAL.length - 1)}]`,
37
+ "gu"
38
+ );
39
+ function neutralize(value) {
40
+ return value.replace(SHIELD_RE, (ch) => SHIELD.get(ch) ?? ch);
41
+ }
42
+ function safetyRestore(text) {
43
+ return text.replace(RESTORE_RE, (ch) => RESTORE.get(ch) ?? ch);
44
+ }
45
+ function stripSentinels(text) {
46
+ return text.replace(RESTORE_RE, "");
47
+ }
48
+
24
49
  // src/internal/parser.ts
25
50
  var VARIABLE_RE = /^%(\w+)%/;
26
51
  var DIRECTIVE_RE = /^[ \t]*#(set|def)[ \t]+%(\w+)%[ \t]*=[ \t]*(.*?)[ \t]*\r?$/gmu;
27
52
  var CONDITIONAL_NAME_RE = /^[A-Za-z_]\w*/;
28
53
  var PLURAL_PREFIX = "plural ";
29
54
  function parseTemplate(src) {
30
- const { body, setDefs, defDefs } = extractDirectives(stripComments(src));
55
+ const { body, setDefs, defDefs } = extractDirectives(stripComments(stripSentinels(src)));
31
56
  return { astVersion: AST_VERSION, source: src, setDefs, defDefs, nodes: parseSequence(body) };
32
57
  }
33
58
  function extractDirectives(text) {
@@ -700,31 +725,6 @@ var NotImplementedError = class extends SpintaxError {
700
725
  }
701
726
  };
702
727
 
703
- // src/internal/neutralize.ts
704
- var STRUCTURAL = ["{", "}", "[", "]", "%", "#"];
705
- var SENTINEL_BASE = 57344;
706
- var SHIELD = /* @__PURE__ */ new Map();
707
- var RESTORE = /* @__PURE__ */ new Map();
708
- STRUCTURAL.forEach((ch, i) => {
709
- const sentinel = String.fromCharCode(SENTINEL_BASE + i);
710
- SHIELD.set(ch, sentinel);
711
- RESTORE.set(sentinel, ch);
712
- });
713
- var SHIELD_RE = /[{}[\]%#]/gu;
714
- var RESTORE_RE = new RegExp(
715
- `[${String.fromCharCode(SENTINEL_BASE)}-${String.fromCharCode(SENTINEL_BASE + STRUCTURAL.length - 1)}]`,
716
- "gu"
717
- );
718
- function neutralize(value) {
719
- return value.replace(SHIELD_RE, (ch) => SHIELD.get(ch) ?? ch);
720
- }
721
- function safetyRestore(text) {
722
- return text.replace(RESTORE_RE, (ch) => RESTORE.get(ch) ?? ch);
723
- }
724
- function stripSentinels(text) {
725
- return text.replace(RESTORE_RE, "");
726
- }
727
-
728
728
  // src/internal/render.ts
729
729
  var MAX_VARIABLE_DEPTH = 50;
730
730
  var INCLUDE_LINE_RE = /^[ \t]*#include[ \t\n\r\f\x0B]+"([^"]+)"[ \t\n\r\f\x0B]*$/gmu;
@@ -751,7 +751,7 @@ function resolveIncludes(text, ctx) {
751
751
  throw new IncludeResolverError(`includeResolver threw for "${ref}"`, { cause });
752
752
  }
753
753
  if (included === null) return "";
754
- return renderAst(parseTemplate(stripSentinels(included)), {
754
+ return renderAst(parseTemplate(included), {
755
755
  ...ctx,
756
756
  runtimeContext: ctx.runtimeContext,
757
757
  // child inherits runtime, not parent #set
@@ -877,7 +877,7 @@ function renderPlural(node, opts) {
877
877
  if (/[{}[\]]/u.test(formsRaw)) {
878
878
  report({
879
879
  code: "plural.nested-brackets",
880
- message: "Plural form slot contains nested spintax brackets; extract via #set first.",
880
+ message: "Plural form slot contains nested spintax brackets; extract via #def first \u2014 a #set is substituted verbatim and would put the brackets straight back.",
881
881
  construct: rawConstruct(countRaw, formsRaw),
882
882
  locale: base
883
883
  });
@@ -1111,7 +1111,7 @@ function renderWith(input, rng, opts = {}) {
1111
1111
  includeStack: [],
1112
1112
  onPluralError: opts.onPluralError
1113
1113
  };
1114
- const ast = resolveAst(typeof input === "string" ? stripSentinels(input) : input);
1114
+ const ast = resolveAst(input);
1115
1115
  let out = renderAst(ast, ctx);
1116
1116
  if (opts.postProcess !== false) out = postProcess(out);
1117
1117
  return safetyRestore(out);