@lokascript/framework 2.7.1 → 2.8.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.js CHANGED
@@ -1420,7 +1420,8 @@ function buildFormatString(schema, profile, keyword) {
1420
1420
  if (profile.wordOrder === "SVO" || profile.wordOrder === "VSO") {
1421
1421
  parts.push(keyword);
1422
1422
  }
1423
- for (const role of schema.roles) {
1423
+ const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);
1424
+ for (const role of sortedRoles) {
1424
1425
  const marker = getMarkerForRole(role, profile);
1425
1426
  const roleName = `{${role.role}}`;
1426
1427
  if (marker) {
@@ -2878,7 +2879,9 @@ function buildProtocolSection() {
2878
2879
  3. No spaces around the colon in role:value pairs
2879
2880
  4. Strings with spaces must be quoted: \`patient:"hello world"\`
2880
2881
  5. Selectors start with \`#\`, \`.\`, \`[\`, \`@\`, or \`*\`
2881
- 6. Output must be valid bracket syntax: \`[action role:value ...]\``;
2882
+ 6. A selector containing a space, a combinator (\`>\` \`+\` \`~\`), or a comma must use a selector literal: \`patient:<ul > li/>\`, \`patient:<.a, .b/>\`
2883
+ 7. Inside a structural role (\`body\`, \`then\`, \`else\`, \`condition\`, \`loop-body\`, \`variable\`, \`catch\`, \`finally\`) a \`[...]\` value is always a nested command. Write an attribute selector there as \`condition:<[data-active]/>\`
2884
+ 8. Output must be valid bracket syntax: \`[action role:value ...]\``;
2882
2885
  return {
2883
2886
  id: "protocol",
2884
2887
  title: "LSE Protocol",
@@ -2891,6 +2894,7 @@ function buildValueTypeSection() {
2891
2894
 
2892
2895
  | Type | Syntax | Example |
2893
2896
  |------|--------|---------|
2897
+ | Selector literal | Delimited by \`<\` and \`/>\` | \`<ul > li/>\`, \`<.a, .b/>\`, \`<[data-id]/>\` |
2894
2898
  | Selector | Starts with \`#\` \`.\` \`[\` \`@\` \`*\` | \`#button\`, \`.active\`, \`[data-id]\` |
2895
2899
  | String | Quoted with \`"\` or \`'\` | \`"hello world"\`, \`'json'\` |
2896
2900
  | Boolean | Exact: \`true\` / \`false\` | \`visible:true\` |
@@ -5086,7 +5090,39 @@ var _BaseTokenizer = class _BaseTokenizer {
5086
5090
  pos++;
5087
5091
  }
5088
5092
  }
5089
- return new TokenStreamImpl(tokens, this.language);
5093
+ return new TokenStreamImpl(this.mergeColonQualifiedNames(tokens), this.language);
5094
+ }
5095
+ /**
5096
+ * Fuse `name` + `:qualifier` into ONE identifier (`draggable:start`).
5097
+ *
5098
+ * `:name` is hyperscript's local-variable sigil, but a colon IMMEDIATELY
5099
+ * preceded by an identifier is a qualifier (custom event namespace), not a
5100
+ * sigil. The English tokenizer already merges these inside
5101
+ * EnglishKeywordExtractor; this post-pass gives the other 23 languages the
5102
+ * same stream. Strict position adjacency is the discriminator: whitespace
5103
+ * between the tokens (`trigger :start`) breaks `end === start`, so a spaced
5104
+ * local-variable reference survives untouched.
5105
+ *
5106
+ * Self-gating for non-hyperscript tokenizers (domain DSLs): their extractor
5107
+ * sets tokenize `:` as bare punctuation (length 1), which never matches
5108
+ * COLON_QUALIFIER, so this pass is a no-op for them.
5109
+ */
5110
+ mergeColonQualifiedNames(tokens) {
5111
+ const out = [];
5112
+ for (const tok of tokens) {
5113
+ const prev = out[out.length - 1];
5114
+ if (prev && _BaseTokenizer.ASCII_WORD.test(prev.value) && _BaseTokenizer.COLON_QUALIFIER.test(tok.value) && prev.position.end === tok.position.start) {
5115
+ const merged = prev.value + tok.value;
5116
+ out[out.length - 1] = createToken(
5117
+ merged,
5118
+ this.classifyToken(merged),
5119
+ createPosition(prev.position.start, tok.position.end)
5120
+ );
5121
+ continue;
5122
+ }
5123
+ out.push(tok);
5124
+ }
5125
+ return out;
5090
5126
  }
5091
5127
  /**
5092
5128
  * Classify an unknown character when no extractor matches.
@@ -5592,6 +5628,14 @@ var _BaseTokenizer = class _BaseTokenizer {
5592
5628
  return null;
5593
5629
  }
5594
5630
  };
5631
+ /**
5632
+ * ASCII word of the shape the English word-walker produces. Excludes `:`, so a
5633
+ * token that already carries a qualifier never merges again — `a:b:c` yields
5634
+ * `a:b` + `:c`, byte-matching the English extractor's single-segment merge.
5635
+ */
5636
+ _BaseTokenizer.ASCII_WORD = /^[A-Za-z_][A-Za-z0-9_]*$/;
5637
+ /** `:name` — only a variable-ref-style extractor ever emits this token shape. */
5638
+ _BaseTokenizer.COLON_QUALIFIER = /^:[A-Za-z_][A-Za-z0-9_]*$/;
5595
5639
  /**
5596
5640
  * Configuration for native language time units.
5597
5641
  * Maps patterns to their standard suffix (ms, s, m, h).