@samva/markup 0.8.0 → 0.9.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.
Files changed (171) hide show
  1. package/AGENTS.md +90 -37
  2. package/README.md +188 -52
  3. package/dist/assets-C5duwTya.d.ts +40 -0
  4. package/dist/{brand-DcoVkh_S.d.ts → brand-B-0bN_Ir.d.ts} +2 -2
  5. package/dist/{render-vAv_4r9v.js → cascade-t6kxlgEI.js} +93 -280
  6. package/dist/channel-edit.d.ts +121 -0
  7. package/dist/channel-edit.js +609 -0
  8. package/dist/channel-specs-B6M_HlaV.js +29 -0
  9. package/dist/channel-specs-C2feJwuP.d.ts +13 -0
  10. package/dist/compatibility-DbISoFIq.js +589 -0
  11. package/dist/compiler.d.ts +10 -257
  12. package/dist/compiler.js +10 -730
  13. package/dist/{css-CS2jLID6.d.ts → css-BVQKICKC.d.ts} +3 -3
  14. package/dist/diagnostic-codes.d.ts +403 -0
  15. package/dist/diagnostic-codes.js +399 -0
  16. package/dist/{diagnostics-BMYtBCQk.d.ts → diagnostics-B-Gym34R.d.ts} +8 -4
  17. package/dist/diagnostics.d.ts +31 -2
  18. package/dist/diagnostics.js +1 -19
  19. package/dist/{elements-BzjjnoCS.d.ts → elements-cqldpaJt.d.ts} +3 -3
  20. package/dist/email/assets.d.ts +2 -40
  21. package/dist/email/brand-footer.d.ts +2 -2
  22. package/dist/email/brand-footer.js +4 -3
  23. package/dist/email/brand.d.ts +1 -1
  24. package/dist/email/brand.js +1 -1
  25. package/dist/email/components.d.ts +21 -10
  26. package/dist/email/components.js +46 -11
  27. package/dist/email/diagnostics.d.ts +2 -2
  28. package/dist/email/diagnostics.js +2 -1
  29. package/dist/email/elements.d.ts +1 -1
  30. package/dist/email/html.d.ts +2 -2
  31. package/dist/email/html.js +45 -2
  32. package/dist/email/jsx-dev-runtime.d.ts +2 -2
  33. package/dist/email/jsx-runtime.d.ts +1 -1
  34. package/dist/email/render.d.ts +8 -18
  35. package/dist/email/render.js +163 -3
  36. package/dist/email/text.d.ts +1 -1
  37. package/dist/fmt.d.ts +32 -0
  38. package/dist/fmt.js +174 -0
  39. package/dist/{html-Bl9BAdqc.d.ts → html-BJepOwZ4.d.ts} +19 -5
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.js +2 -0
  42. package/dist/ir-aaqNE987.d.ts +252 -0
  43. package/dist/ir.d.ts +2 -0
  44. package/dist/ir.js +7 -0
  45. package/dist/preview-Ekdg1dXG.d.ts +100 -0
  46. package/dist/preview.d.ts +2 -0
  47. package/dist/preview.js +160 -0
  48. package/dist/profile-BH-OtdDA.js +3670 -0
  49. package/dist/render-ir.d.ts +19 -0
  50. package/dist/render-ir.js +826 -0
  51. package/dist/sms-segments.d.ts +13 -2
  52. package/dist/sms.d.ts +16 -0
  53. package/dist/sms.js +12 -0
  54. package/dist/{email/source-edit.d.ts → source-edit.d.ts} +55 -6
  55. package/dist/source-edit.js +343 -0
  56. package/dist/source-locations-C8wCsiAy.d.ts +23 -0
  57. package/dist/source-locations.d.ts +2 -2
  58. package/dist/source-locations.js +3 -89
  59. package/dist/static.d.ts +57 -0
  60. package/dist/static.js +69 -0
  61. package/dist/tailwind-CMYpZf1v.js +614 -0
  62. package/dist/template-_QE_rQND.d.ts +65 -0
  63. package/dist/template.d.ts +2 -2
  64. package/dist/template.js +15 -10
  65. package/dist/theme-css.d.ts +1 -1
  66. package/dist/theme-imports-lvBw3AD1.js +109 -0
  67. package/dist/transform-Ct2OMkFN.d.ts +153 -0
  68. package/dist/whatsapp.d.ts +57 -0
  69. package/dist/whatsapp.js +22 -0
  70. package/generated/contract.json +1782 -0
  71. package/generated/reference.md +353 -0
  72. package/package.json +41 -151
  73. package/skills/sml/SKILL.md +123 -0
  74. package/dist/ast-BrDtApwS.d.ts +0 -107
  75. package/dist/ast.d.ts +0 -2
  76. package/dist/ast.js +0 -124
  77. package/dist/candidate.d.ts +0 -29
  78. package/dist/candidate.js +0 -88
  79. package/dist/catalog-CKuOooB8.d.ts +0 -354
  80. package/dist/checks-D73Xizbw.js +0 -59366
  81. package/dist/checks.d.ts +0 -33
  82. package/dist/checks.js +0 -2
  83. package/dist/classes.d.ts +0 -26
  84. package/dist/classes.js +0 -184
  85. package/dist/compile-sms.d.ts +0 -28
  86. package/dist/compile-sms.js +0 -44
  87. package/dist/compile-whatsapp.d.ts +0 -56
  88. package/dist/compile-whatsapp.js +0 -186
  89. package/dist/compile.d.ts +0 -18
  90. package/dist/compile.js +0 -29
  91. package/dist/components.d.ts +0 -289
  92. package/dist/components.js +0 -106
  93. package/dist/conditionals.d.ts +0 -10
  94. package/dist/conditionals.js +0 -74
  95. package/dist/corpus-CPPfgAHN.d.ts +0 -106
  96. package/dist/diagnostics-OcQKQYSY.d.ts +0 -49
  97. package/dist/email/selection.d.ts +0 -2
  98. package/dist/email/selection.js +0 -91
  99. package/dist/email/source-edit.js +0 -185
  100. package/dist/email/stylesheets.d.ts +0 -15
  101. package/dist/email/stylesheets.js +0 -48
  102. package/dist/emit.d.ts +0 -51
  103. package/dist/emit.js +0 -151
  104. package/dist/interpolate.d.ts +0 -24
  105. package/dist/interpolate.js +0 -43
  106. package/dist/jsx-dev-runtime.d.ts +0 -11
  107. package/dist/jsx-dev-runtime.js +0 -15
  108. package/dist/jsx-runtime-I-1nCtl2.d.ts +0 -57
  109. package/dist/jsx-runtime.d.ts +0 -2
  110. package/dist/jsx-runtime.js +0 -121
  111. package/dist/lexer.d.ts +0 -60
  112. package/dist/lexer.js +0 -281
  113. package/dist/model.d.ts +0 -24
  114. package/dist/model.js +0 -77
  115. package/dist/ops-BvwqHl7V.js +0 -630
  116. package/dist/ops.d.ts +0 -114
  117. package/dist/ops.js +0 -2
  118. package/dist/parser-t29cHLVL.d.ts +0 -396
  119. package/dist/parser.d.ts +0 -2
  120. package/dist/parser.js +0 -859
  121. package/dist/predicate-BI6uRRM-.js +0 -549
  122. package/dist/predicate-M-05Nd7R.d.ts +0 -56
  123. package/dist/predicate.d.ts +0 -2
  124. package/dist/predicate.js +0 -2
  125. package/dist/printer.d.ts +0 -6
  126. package/dist/printer.js +0 -122
  127. package/dist/registry-Dcp6QEK_.d.ts +0 -73
  128. package/dist/registry.d.ts +0 -2
  129. package/dist/registry.js +0 -646
  130. package/dist/render-template.d.ts +0 -45
  131. package/dist/render-template.js +0 -76
  132. package/dist/selection-CCArx9lU.d.ts +0 -91
  133. package/dist/showcase-egkusQBf.d.ts +0 -415
  134. package/dist/sms-segments-y4FpPilJ.d.ts +0 -13
  135. package/dist/source-locations-DrCM82Ym.d.ts +0 -67
  136. package/dist/starters/category-mapping.d.ts +0 -13
  137. package/dist/starters/category-mapping.js +0 -49
  138. package/dist/starters/corpus.d.ts +0 -2
  139. package/dist/starters/corpus.js +0 -194
  140. package/dist/starters/library.d.ts +0 -18
  141. package/dist/starters/library.js +0 -692
  142. package/dist/starters/public-gallery.d.ts +0 -266
  143. package/dist/starters/public-gallery.js +0 -916
  144. package/dist/starters/public-handoff.d.ts +0 -164
  145. package/dist/starters/public-handoff.js +0 -361
  146. package/dist/starters/public-preview-artifacts.d.ts +0 -43
  147. package/dist/starters/public-preview-artifacts.js +0 -104
  148. package/dist/starters/public-preview.d.ts +0 -61
  149. package/dist/starters/public-preview.js +0 -83
  150. package/dist/starters/showcase.d.ts +0 -2
  151. package/dist/starters/showcase.js +0 -335
  152. package/dist/starters/sources.d.ts +0 -45
  153. package/dist/starters/sources.js +0 -7762
  154. package/dist/starters/theme.d.ts +0 -45
  155. package/dist/starters/theme.js +0 -77
  156. package/dist/starters.d.ts +0 -2
  157. package/dist/starters.js +0 -874
  158. package/dist/tailwind-BYq7Lo6u.js +0 -727
  159. package/dist/template-DWftqh4x.d.ts +0 -60
  160. package/dist/tsx-source-instrumentation.d.ts +0 -30
  161. package/dist/tsx-source-instrumentation.js +0 -115
  162. package/dist/tsx-tracer.d.ts +0 -112
  163. package/dist/tsx-tracer.js +0 -985
  164. package/dist/variables-J_L3qxRa.d.ts +0 -77
  165. package/dist/variables.d.ts +0 -2
  166. package/dist/variables.js +0 -141
  167. package/dist/version-BITr58kk.js +0 -96
  168. package/generated/sml-agent-contract.json +0 -709
  169. package/generated/sml-email-agent-contract.json +0 -615
  170. package/generated/sml-email-language-reference.md +0 -94
  171. package/generated/sml-language-reference.md +0 -195
@@ -1,57 +0,0 @@
1
- import { f as ElementNode, n as Attribute, x as SmlNode } from "./ast-BrDtApwS.js";
2
- import { s as VariableRef } from "./variables-J_L3qxRa.js";
3
- //#region src/jsx-runtime.d.ts
4
- /** A component is a plain function of its props that returns a draft node. */
5
- type Component<P> = (props: P) => SmlNode;
6
- /**
7
- * What may appear in a component's `children`. Booleans/null/undefined are
8
- * skipped (so `{cond && <X/>}` and `{cond ? <A/> : null}` are BUILD-TIME
9
- * conditionals that evaluate away); strings/numbers become text; VariableRefs
10
- * become `{{interpolation}}` nodes; arrays flatten; nested nodes nest. Anything
11
- * else is a typed authoring error.
12
- */
13
- type SmlChild = SmlNode | FragmentDraft | VariableRef<unknown> | string | number | boolean | null | undefined | ReadonlyArray<SmlChild>;
14
- type SmlChildren = SmlChild | ReadonlyArray<SmlChild>;
15
- /** Fragment children pass through un-wrapped — a Fragment is not an element. */
16
- interface FragmentDraft {
17
- readonly kind: "fragment";
18
- readonly children: ReadonlyArray<SmlNode>;
19
- }
20
- type JsxResult = SmlNode | FragmentDraft;
21
- /**
22
- * Flattens and normalizes a component's raw `children` prop into AST child
23
- * nodes. Fragments splice their children in; booleans/null/undefined drop out.
24
- */
25
- declare const normalizeChildren: (children: unknown) => Array<SmlNode>;
26
- /**
27
- * Builds an element draft from a tag, attribute list (already in authored
28
- * order), and normalized children. Kept here so the runtime owns the AST shape;
29
- * ./components maps typed props onto attributes and calls this.
30
- */
31
- declare const elementDraft: (tag: ElementNode["tag"], attributes: ReadonlyArray<Attribute>, children: ReadonlyArray<SmlNode>) => ElementNode;
32
- interface JsxProps {
33
- readonly children?: unknown;
34
- readonly [key: string]: unknown;
35
- }
36
- /**
37
- * The automatic-runtime entry point. `type` is always one of our typed
38
- * component functions (or `Fragment`); we invoke it with its props. The JSX
39
- * transform routes single-child elements here and multi-child elements to
40
- * `jsxs` — behaviour is identical for us (components normalize their own
41
- * children), so `jsxs` re-exports this.
42
- */
43
- declare const jsx: (type: Component<JsxProps> | typeof Fragment, props: JsxProps) => JsxResult;
44
- declare const jsxs: typeof jsx;
45
- /** Groups children without an element wrapper. Its children splice into the parent. */
46
- declare const Fragment: unique symbol;
47
- declare namespace JSX {
48
- type Element = JsxResult;
49
- type ElementType = Component<never> | typeof Fragment;
50
- interface ElementChildrenAttribute {
51
- readonly children: object;
52
- }
53
- type IntrinsicElements = Record<string, never>;
54
- }
55
- //#endregion
56
- export { JsxResult as a, elementDraft as c, normalizeChildren as d, JSX as i, jsx as l, Fragment as n, SmlChild as o, FragmentDraft as r, SmlChildren as s, Component as t, jsxs as u };
57
- //# sourceMappingURL=jsx-runtime-I-1nCtl2.d.ts.map
@@ -1,2 +0,0 @@
1
- import { a as JsxResult, c as elementDraft, d as normalizeChildren, i as JSX, l as jsx, n as Fragment, o as SmlChild, r as FragmentDraft, s as SmlChildren, t as Component, u as jsxs } from "./jsx-runtime-I-1nCtl2.js";
2
- export { Component, Fragment, FragmentDraft, JSX, JsxResult, SmlChild, SmlChildren, elementDraft, jsx, jsxs, normalizeChildren };
@@ -1,121 +0,0 @@
1
- import { t as hasProperty } from "./guards-eV1qLbf2.js";
2
- import { JSX_SOURCE_LOCATION_PROP, attachJsxSourceLocation, completeJsxSourceLocation } from "./source-locations.js";
3
- import { VARIABLE_REF, isVariableRef } from "./variables.js";
4
- //#region src/jsx-runtime.ts
5
- const PLACEHOLDER_SPAN = {
6
- start: 0,
7
- end: 0
8
- };
9
- const isFragmentDraft = (value) => hasProperty(value, "kind") && value.kind === "fragment";
10
- const isSmlNode = (value) => {
11
- if (!hasProperty(value, "kind")) return false;
12
- const kind = value.kind;
13
- return kind === "element" || kind === "text" || kind === "interpolation";
14
- };
15
- const textNode = (value) => ({
16
- kind: "text",
17
- id: "",
18
- value,
19
- span: PLACEHOLDER_SPAN
20
- });
21
- const interpolationNode = (ref) => ({
22
- kind: "interpolation",
23
- id: "",
24
- name: ref[VARIABLE_REF].path,
25
- syntax: "curly",
26
- span: PLACEHOLDER_SPAN
27
- });
28
- /**
29
- * Flattens and normalizes a component's raw `children` prop into AST child
30
- * nodes. Fragments splice their children in; booleans/null/undefined drop out.
31
- */
32
- const normalizeChildren = (children) => {
33
- const out = [];
34
- const push = (child) => {
35
- if (child === null || child === void 0 || typeof child === "boolean") return;
36
- if (typeof child === "string") {
37
- out.push(textNode(child));
38
- return;
39
- }
40
- if (typeof child === "number") {
41
- out.push(textNode(String(child)));
42
- return;
43
- }
44
- if (Array.isArray(child)) {
45
- for (const item of child) push(item);
46
- return;
47
- }
48
- if (isVariableRef(child)) {
49
- out.push(interpolationNode(child));
50
- return;
51
- }
52
- if (isFragmentDraft(child)) {
53
- for (const node of child.children) out.push(node);
54
- return;
55
- }
56
- if (isSmlNode(child)) {
57
- out.push(child);
58
- return;
59
- }
60
- throw new TypeError(`invalid SML child: ${describe(child)} — children may be text, numbers, variables, elements, arrays of these, or false/null/undefined (which are skipped)`);
61
- };
62
- push(children);
63
- return out;
64
- };
65
- const describe = (value) => {
66
- if (typeof value === "function") return "a function (did you pass a component instead of an element?)";
67
- if (typeof value === "object") return `an object (${JSON.stringify(value)})`;
68
- return `${typeof value} (${JSON.stringify(value)})`;
69
- };
70
- /**
71
- * Builds an element draft from a tag, attribute list (already in authored
72
- * order), and normalized children. Kept here so the runtime owns the AST shape;
73
- * ./components maps typed props onto attributes and calls this.
74
- */
75
- const elementDraft = (tag, attributes, children) => ({
76
- kind: "element",
77
- id: "",
78
- tag,
79
- attributes,
80
- children,
81
- span: PLACEHOLDER_SPAN
82
- });
83
- const stripSourceLocation = (props) => {
84
- const source = props[JSX_SOURCE_LOCATION_PROP];
85
- if (source === void 0) return {
86
- props,
87
- source: void 0
88
- };
89
- const { [JSX_SOURCE_LOCATION_PROP]: _source, ...rest } = props;
90
- return {
91
- props: rest,
92
- source
93
- };
94
- };
95
- /**
96
- * The automatic-runtime entry point. `type` is always one of our typed
97
- * component functions (or `Fragment`); we invoke it with its props. The JSX
98
- * transform routes single-child elements here and multi-child elements to
99
- * `jsxs` — behaviour is identical for us (components normalize their own
100
- * children), so `jsxs` re-exports this.
101
- */
102
- const jsx = (type, props) => {
103
- if (type === Fragment) return {
104
- kind: "fragment",
105
- children: normalizeChildren(props.children)
106
- };
107
- const { props: cleanProps, source } = stripSourceLocation(props);
108
- const result = type(cleanProps);
109
- if (source !== void 0 && result.kind === "element") {
110
- const location = completeJsxSourceLocation(source);
111
- if (location !== void 0) attachJsxSourceLocation(result, location);
112
- }
113
- return result;
114
- };
115
- const jsxs = jsx;
116
- /** Groups children without an element wrapper. Its children splice into the parent. */
117
- const Fragment = Symbol.for("@samva/markup/Fragment");
118
- //#endregion
119
- export { Fragment, elementDraft, jsx, jsxs, normalizeChildren };
120
-
121
- //# sourceMappingURL=jsx-runtime.js.map
package/dist/lexer.d.ts DELETED
@@ -1,60 +0,0 @@
1
- //#region src/lexer.d.ts
2
- declare const TokenKind: {
3
- readonly EndOfFile: 0;
4
- /** `<` opening a start tag (text mode). */
5
- readonly LessThan: 1;
6
- /** `</` opening a close tag (text mode). */
7
- readonly LessThanSlash: 2;
8
- readonly GreaterThan: 3;
9
- readonly SlashGreaterThan: 4;
10
- readonly Identifier: 5;
11
- readonly Equals: 6;
12
- /** Quoted attribute value; getStringValue decodes entities. */
13
- readonly String: 7;
14
- readonly OpenBrace: 8;
15
- readonly CloseBrace: 9;
16
- /** Unsigned integer inside a brace attribute value. */
17
- readonly Number: 10;
18
- /** Raw text run; getTextValue decodes entities. */
19
- readonly Text: 11;
20
- /** `{{name}}` or `${name}`; name/syntax carried on the token. */
21
- readonly Interpolation: 12;
22
- /** Lexically invalid input; error carried on the token. */
23
- readonly Unknown: 13;
24
- };
25
- type TokenKind = (typeof TokenKind)[keyof typeof TokenKind];
26
- interface TokenError {
27
- readonly code: string;
28
- readonly message: string;
29
- }
30
- interface Token {
31
- readonly kind: TokenKind;
32
- readonly start: number;
33
- readonly end: number;
34
- /** Interpolation only. */
35
- readonly name?: string | undefined;
36
- /** Interpolation only. */
37
- readonly syntax?: "curly" | "dollar" | undefined;
38
- /** Unknown only. */
39
- readonly error?: TokenError | undefined;
40
- }
41
- /** Decodes entities in text that already passed `scanEntity` validation. */
42
- declare const decodeEntities: (raw: string) => string;
43
- interface Lexer {
44
- /** Current scan position (start of the next token). */
45
- readonly position: () => number;
46
- /** Scan one token in text mode (between tags). */
47
- readonly scanTextToken: () => Token;
48
- /** Scan one token in tag mode (inside `<...>`), skipping whitespace. */
49
- readonly scanTagToken: () => Token;
50
- /** Lazy raw source slice for a token. */
51
- readonly getText: (token: Token) => string;
52
- /** Entity-decoded value of a Text token. */
53
- readonly getTextValue: (token: Token) => string;
54
- /** Entity-decoded contents of a String token (without quotes). */
55
- readonly getStringValue: (token: Token) => string;
56
- }
57
- declare const createLexer: (source: string) => Lexer;
58
- //#endregion
59
- export { Lexer, Token, TokenError, TokenKind, createLexer, decodeEntities };
60
- //# sourceMappingURL=lexer.d.ts.map
package/dist/lexer.js DELETED
@@ -1,281 +0,0 @@
1
- //#region src/lexer.ts
2
- const CHAR_TAB = 9;
3
- const CHAR_LINE_FEED = 10;
4
- const CHAR_CARRIAGE_RETURN = 13;
5
- const CHAR_SPACE = 32;
6
- const CHAR_BANG = 33;
7
- const CHAR_DOUBLE_QUOTE = 34;
8
- const CHAR_HASH = 35;
9
- const CHAR_DOLLAR = 36;
10
- const CHAR_AMPERSAND = 38;
11
- const CHAR_SINGLE_QUOTE = 39;
12
- const CHAR_SLASH = 47;
13
- const CHAR_SEMICOLON = 59;
14
- const CHAR_LESS_THAN = 60;
15
- const CHAR_EQUALS = 61;
16
- const CHAR_GREATER_THAN = 62;
17
- const CHAR_OPEN_BRACE = 123;
18
- const CHAR_CLOSE_BRACE = 125;
19
- const CHAR_DOT = 46;
20
- const CHAR_UNDERSCORE = 95;
21
- const CHAR_0 = 48;
22
- const CHAR_9 = 57;
23
- const CHAR_UPPER_A = 65;
24
- const CHAR_UPPER_X = 88;
25
- const CHAR_UPPER_Z = 90;
26
- const CHAR_LOWER_A = 97;
27
- const CHAR_LOWER_X = 120;
28
- const CHAR_LOWER_Z = 122;
29
- const TokenKind = {
30
- EndOfFile: 0,
31
- /** `<` opening a start tag (text mode). */
32
- LessThan: 1,
33
- /** `</` opening a close tag (text mode). */
34
- LessThanSlash: 2,
35
- GreaterThan: 3,
36
- SlashGreaterThan: 4,
37
- Identifier: 5,
38
- Equals: 6,
39
- /** Quoted attribute value; getStringValue decodes entities. */
40
- String: 7,
41
- OpenBrace: 8,
42
- CloseBrace: 9,
43
- /** Unsigned integer inside a brace attribute value. */
44
- Number: 10,
45
- /** Raw text run; getTextValue decodes entities. */
46
- Text: 11,
47
- /** `{{name}}` or `${name}`; name/syntax carried on the token. */
48
- Interpolation: 12,
49
- /** Lexically invalid input; error carried on the token. */
50
- Unknown: 13
51
- };
52
- const isWhitespace = (code) => code === CHAR_SPACE || code === CHAR_TAB || code === CHAR_LINE_FEED || code === CHAR_CARRIAGE_RETURN;
53
- const isDigit = (code) => code >= CHAR_0 && code <= CHAR_9;
54
- const isLetter = (code) => code >= CHAR_UPPER_A && code <= CHAR_UPPER_Z || code >= CHAR_LOWER_A && code <= CHAR_LOWER_Z;
55
- const isNameChar = (code) => isLetter(code) || isDigit(code) || code === CHAR_UNDERSCORE || code === CHAR_DOT;
56
- const NAMED_ENTITIES = {
57
- amp: "&",
58
- lt: "<",
59
- gt: ">",
60
- quot: "\"",
61
- apos: "'",
62
- nbsp: "\xA0"
63
- };
64
- const numericEntityCodePoint = (digits, radix) => {
65
- const codePoint = Number.parseInt(digits, radix);
66
- return Number.isFinite(codePoint) && codePoint <= 1114111 ? codePoint : void 0;
67
- };
68
- /**
69
- * Validates the entity starting at `offset` (which points at `&`).
70
- * Returns the end offset (past `;`) or -1 when malformed.
71
- */
72
- const scanEntity = (source, offset) => {
73
- let index = offset + 1;
74
- if (source.charCodeAt(index) === CHAR_HASH) {
75
- index++;
76
- const marker = source.charCodeAt(index);
77
- const hex = marker === CHAR_LOWER_X || marker === CHAR_UPPER_X;
78
- if (hex) index++;
79
- const digitsStart = index;
80
- while (index < source.length) {
81
- const code = source.charCodeAt(index);
82
- if (!(isDigit(code) || hex && (code >= 97 && code <= 102 || code >= 65 && code <= 70))) break;
83
- index++;
84
- }
85
- if (index === digitsStart) return -1;
86
- if (numericEntityCodePoint(source.slice(digitsStart, index), hex ? 16 : 10) === void 0) return -1;
87
- return source.charCodeAt(index) === CHAR_SEMICOLON ? index + 1 : -1;
88
- }
89
- const nameStart = index;
90
- while (index < source.length && isLetter(source.charCodeAt(index))) index++;
91
- const name = source.slice(nameStart, index);
92
- if (!Object.hasOwn(NAMED_ENTITIES, name)) return -1;
93
- return source.charCodeAt(index) === CHAR_SEMICOLON ? index + 1 : -1;
94
- };
95
- /** Decodes entities in text that already passed `scanEntity` validation. */
96
- const decodeEntities = (raw) => {
97
- if (!raw.includes("&")) return raw;
98
- let result = "";
99
- let index = 0;
100
- while (index < raw.length) {
101
- const ampersand = raw.indexOf("&", index);
102
- if (ampersand === -1) {
103
- result += raw.slice(index);
104
- break;
105
- }
106
- result += raw.slice(index, ampersand);
107
- const semicolon = raw.indexOf(";", ampersand);
108
- if (semicolon === -1) {
109
- result += raw.slice(ampersand);
110
- break;
111
- }
112
- const body = raw.slice(ampersand + 1, semicolon);
113
- if (body.startsWith("#x") || body.startsWith("#X")) {
114
- const codePoint = numericEntityCodePoint(body.slice(2), 16);
115
- result += codePoint === void 0 ? raw.slice(ampersand, semicolon + 1) : String.fromCodePoint(codePoint);
116
- } else if (body.startsWith("#")) {
117
- const codePoint = numericEntityCodePoint(body.slice(1), 10);
118
- result += codePoint === void 0 ? raw.slice(ampersand, semicolon + 1) : String.fromCodePoint(codePoint);
119
- } else result += Object.hasOwn(NAMED_ENTITIES, body) ? NAMED_ENTITIES[body] : raw.slice(ampersand, semicolon + 1);
120
- index = semicolon + 1;
121
- }
122
- return result;
123
- };
124
- const createLexer = (source) => {
125
- let position = 0;
126
- const length = source.length;
127
- const token = (kind, start, extra) => {
128
- return {
129
- kind,
130
- start,
131
- end: position,
132
- ...extra
133
- };
134
- };
135
- const unknown = (start, code, message) => {
136
- if (position === start) position = Math.min(start + 1, length);
137
- return token(TokenKind.Unknown, start, { error: {
138
- code,
139
- message
140
- } });
141
- };
142
- const scanInterpolation = (start, syntax) => {
143
- position = start + 2;
144
- while (position < length && isWhitespace(source.charCodeAt(position))) position++;
145
- if (syntax === "dollar" && source.charCodeAt(position) === CHAR_SLASH) position++;
146
- const nameStart = position;
147
- while (position < length && isNameChar(source.charCodeAt(position))) position++;
148
- const name = source.slice(nameStart, position);
149
- while (position < length && isWhitespace(source.charCodeAt(position))) position++;
150
- const closed = syntax === "curly" ? source.charCodeAt(position) === CHAR_CLOSE_BRACE && source.charCodeAt(position + 1) === CHAR_CLOSE_BRACE : source.charCodeAt(position) === CHAR_CLOSE_BRACE;
151
- if (name.length === 0 || !closed) {
152
- position = start;
153
- return unknown(start, "invalid-interpolation", `malformed interpolation — write ${syntax === "curly" ? "{{variableName}}" : "${variableName}"} using letters, digits, underscore, or dot`);
154
- }
155
- position += syntax === "curly" ? 2 : 1;
156
- return token(TokenKind.Interpolation, start, {
157
- name,
158
- syntax
159
- });
160
- };
161
- const scanTextToken = () => {
162
- const start = position;
163
- if (position >= length) return token(TokenKind.EndOfFile, start);
164
- const first = source.charCodeAt(position);
165
- if (first === CHAR_LESS_THAN) {
166
- const next = source.charCodeAt(position + 1);
167
- if (next === CHAR_SLASH) {
168
- position += 2;
169
- return token(TokenKind.LessThanSlash, start);
170
- }
171
- if (isLetter(next)) {
172
- position += 1;
173
- return token(TokenKind.LessThan, start);
174
- }
175
- if (next === CHAR_BANG) return unknown(start, "comment-not-supported", source.startsWith("<!--", position) ? "comments are not part of SML — remove the <!-- ... --> block" : "unexpected <! — SML has no doctype or declaration syntax; remove it");
176
- return unknown(start, "stray-angle-bracket", "stray < in text — escape it as &lt;");
177
- }
178
- if (first === CHAR_OPEN_BRACE && source.charCodeAt(position + 1) === CHAR_OPEN_BRACE) return scanInterpolation(start, "curly");
179
- if (first === CHAR_DOLLAR && source.charCodeAt(position + 1) === CHAR_OPEN_BRACE) return scanInterpolation(start, "dollar");
180
- while (position < length) {
181
- const code = source.charCodeAt(position);
182
- if (code === CHAR_LESS_THAN) break;
183
- if (code === CHAR_OPEN_BRACE && source.charCodeAt(position + 1) === CHAR_OPEN_BRACE) break;
184
- if (code === CHAR_DOLLAR && source.charCodeAt(position + 1) === CHAR_OPEN_BRACE) break;
185
- if (code === CHAR_AMPERSAND) {
186
- const entityEnd = scanEntity(source, position);
187
- if (entityEnd === -1) {
188
- if (position > start) return token(TokenKind.Text, start);
189
- return unknown(start, "bare-ampersand", "bare & in text — escape it as &amp; (or use a supported entity like &lt;)");
190
- }
191
- position = entityEnd;
192
- continue;
193
- }
194
- position++;
195
- }
196
- return token(TokenKind.Text, start);
197
- };
198
- const scanTagToken = () => {
199
- while (position < length && isWhitespace(source.charCodeAt(position))) position++;
200
- const start = position;
201
- if (position >= length) return token(TokenKind.EndOfFile, start);
202
- const code = source.charCodeAt(position);
203
- switch (code) {
204
- case CHAR_GREATER_THAN:
205
- position++;
206
- return token(TokenKind.GreaterThan, start);
207
- case CHAR_SLASH:
208
- if (source.charCodeAt(position + 1) === CHAR_GREATER_THAN) {
209
- position += 2;
210
- return token(TokenKind.SlashGreaterThan, start);
211
- }
212
- return unknown(start, "unexpected-character", "unexpected / inside tag — write /> to self-close");
213
- case CHAR_EQUALS:
214
- position++;
215
- return token(TokenKind.Equals, start);
216
- case CHAR_OPEN_BRACE:
217
- position++;
218
- return token(TokenKind.OpenBrace, start);
219
- case CHAR_CLOSE_BRACE:
220
- position++;
221
- return token(TokenKind.CloseBrace, start);
222
- case CHAR_DOUBLE_QUOTE:
223
- case CHAR_SINGLE_QUOTE:
224
- position++;
225
- while (position < length) {
226
- const current = source.charCodeAt(position);
227
- if (current === code) break;
228
- if (current === CHAR_AMPERSAND) {
229
- const entityEnd = scanEntity(source, position);
230
- if (entityEnd === -1) return unknown(position, "bare-ampersand", "bare & in attribute value — escape it as &amp;");
231
- position = entityEnd;
232
- continue;
233
- }
234
- if (current === CHAR_LESS_THAN || current === CHAR_LINE_FEED) break;
235
- position++;
236
- }
237
- if (source.charCodeAt(position) !== code) {
238
- const quote = String.fromCharCode(code);
239
- return {
240
- kind: TokenKind.Unknown,
241
- start,
242
- end: position,
243
- error: {
244
- code: "unterminated-string",
245
- message: `unterminated attribute value — add a closing ${quote}`
246
- }
247
- };
248
- }
249
- position++;
250
- return token(TokenKind.String, start);
251
- default:
252
- if (isLetter(code)) {
253
- position++;
254
- while (position < length) {
255
- const current = source.charCodeAt(position);
256
- if (!isLetter(current) && !isDigit(current)) break;
257
- position++;
258
- }
259
- return token(TokenKind.Identifier, start);
260
- }
261
- if (isDigit(code)) {
262
- position++;
263
- while (position < length && isDigit(source.charCodeAt(position))) position++;
264
- return token(TokenKind.Number, start);
265
- }
266
- return unknown(start, "unexpected-character", `unexpected character ${JSON.stringify(String.fromCharCode(code))} inside tag`);
267
- }
268
- };
269
- return {
270
- position: () => position,
271
- scanTextToken,
272
- scanTagToken,
273
- getText: (t) => source.slice(t.start, t.end),
274
- getTextValue: (t) => decodeEntities(source.slice(t.start, t.end)),
275
- getStringValue: (t) => decodeEntities(source.slice(t.start + 1, t.end - 1))
276
- };
277
- };
278
- //#endregion
279
- export { TokenKind, createLexer, decodeEntities };
280
-
281
- //# sourceMappingURL=lexer.js.map
package/dist/model.d.ts DELETED
@@ -1,24 +0,0 @@
1
- import { S as SmlTag, b as SmlDocument } from "./ast-BrDtApwS.js";
2
- import { Result } from "better-result";
3
- //#region src/model.d.ts
4
- /** The subset of an element's attributes the navigator and agent tools read. */
5
- type SmlNodeKeyAttrs = Readonly<Record<string, string | number>>;
6
- interface SmlNodeIndexEntry {
7
- readonly id: string;
8
- readonly tag: SmlTag;
9
- readonly order: number;
10
- readonly parentId: string | null;
11
- readonly childIndex: number;
12
- readonly depth: number;
13
- readonly path: string;
14
- readonly textPreview: string;
15
- readonly attrs: SmlNodeKeyAttrs;
16
- }
17
- interface SmlNodeIndex {
18
- readonly nodes: readonly SmlNodeIndexEntry[];
19
- }
20
- declare const deriveNodeIndexFromDocument: (document: SmlDocument) => SmlNodeIndex;
21
- declare const deriveNodeIndex: (source: string) => Result<SmlNodeIndex, string>;
22
- //#endregion
23
- export { SmlNodeIndex, SmlNodeIndexEntry, SmlNodeKeyAttrs, deriveNodeIndex, deriveNodeIndexFromDocument };
24
- //# sourceMappingURL=model.d.ts.map
package/dist/model.js DELETED
@@ -1,77 +0,0 @@
1
- import { parseSml } from "./parser.js";
2
- import { Result } from "better-result";
3
- //#region src/model.ts
4
- const KEY_ATTRS = /* @__PURE__ */ new Set([
5
- "alt",
6
- "class",
7
- "dir",
8
- "height",
9
- "hidden",
10
- "href",
11
- "label",
12
- "lang",
13
- "level",
14
- "name",
15
- "scheme",
16
- "src",
17
- "test",
18
- "valign",
19
- "width"
20
- ]);
21
- const attrValue = (value) => value.value;
22
- const truncate = (value, length) => value.length <= length ? value : `${value.slice(0, length - 3)}...`;
23
- const normalizePreview = (value) => truncate(value.replace(/\s+/g, " ").trim(), 96);
24
- const textPreview = (node) => {
25
- const parts = [];
26
- const visit = (child) => {
27
- if (child.kind === "text") {
28
- parts.push(child.value);
29
- return;
30
- }
31
- if (child.kind === "interpolation") {
32
- parts.push(`{{${child.name}}}`);
33
- return;
34
- }
35
- for (const nested of child.children) visit(nested);
36
- };
37
- for (const child of node.children) visit(child);
38
- return normalizePreview(parts.join(" "));
39
- };
40
- const keyAttrs = (node) => Object.fromEntries(node.attributes.filter((attribute) => KEY_ATTRS.has(attribute.name)).map((attribute) => [attribute.name, attrValue(attribute.value)]));
41
- const deriveNodeIndexFromDocument = (document) => {
42
- const nodes = [];
43
- let order = 0;
44
- const visit = (node, parentId, childIndex, depth, parentPath) => {
45
- if (node.kind !== "element") return;
46
- if (node.tag === "Source") return;
47
- const pathSegment = `${node.tag}[${childIndex}]`;
48
- const path = parentPath ? `${parentPath}/${pathSegment}` : pathSegment;
49
- nodes.push({
50
- id: node.id,
51
- tag: node.tag,
52
- order: order++,
53
- parentId,
54
- childIndex,
55
- depth,
56
- path,
57
- textPreview: textPreview(node),
58
- attrs: keyAttrs(node)
59
- });
60
- let elementChildIndex = 0;
61
- for (const child of node.children) if (child.kind === "element") {
62
- visit(child, node.id, elementChildIndex, depth + 1, path);
63
- elementChildIndex++;
64
- }
65
- };
66
- visit(document.root, null, 0, 0, "");
67
- return { nodes };
68
- };
69
- const deriveNodeIndex = (source) => {
70
- const parsed = parseSml(source);
71
- if (Result.isError(parsed)) return Result.err(parsed.error.diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
72
- return Result.ok(deriveNodeIndexFromDocument(parsed.value));
73
- };
74
- //#endregion
75
- export { deriveNodeIndex, deriveNodeIndexFromDocument };
76
-
77
- //# sourceMappingURL=model.js.map