@fluixi/template-parser 0.1.0-alpha.4 → 1.0.0-alpha.100

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.
@@ -1 +1,206 @@
1
- "use strict";var c=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var b=(e,i)=>{for(var t in i)c(e,t,{get:i[t],enumerable:!0})},p=(e,i,t,n)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of m(i))!h.call(e,o)&&o!==t&&c(e,o,{get:()=>i[o],enumerable:!(n=v(i,o))||n.enumerable});return e};var f=e=>p(c({},"__esModule",{value:!0}),e);var g={};b(g,{CORE_DIRECTIVES:()=>a,EVENT_MODIFIERS:()=>d,resolveAttribute:()=>D});module.exports=f(g);var d=new Set(["capture","once","passive","prevent","stop","self"]);function l(e,i){return e.value&&e.value.kind==="hole"?e.value.hole:(e.report("invalid-binding",`${i} requires an expression value: ${e.name}=\${…}`),-1)}var s=(e,i)=>({kind:"Attribute",name:i?e.name.slice(1):e.name,value:e.value,boolean:i,loc:e.loc}),a=[{id:"event",match:e=>e[0]==="@"||e.startsWith("on:")||/^on[A-Z]/.test(e),build:e=>{let i,t;e.name[0]==="@"?(i="at",t=e.name.slice(1)):e.name.startsWith("on:")?(i="colon",t=e.name.slice(3)):(i="on",t=e.name.slice(2));let[n,...o]=t.split("."),u=n.toLowerCase();for(let r of o)d.has(r)||e.report("invalid-directive",`Unknown event modifier ".${r}" — expected one of ${[...d].join(", ")}`);return{kind:"EventBinding",name:u,syntax:i,modifiers:o,hole:l(e,"event binding"),loc:e.loc}}},{id:"bind",elementOnly:!0,match:e=>e.startsWith("bind:"),build:e=>({kind:"BindDirective",name:e.name.slice(5),hole:l(e,"two-way binding"),loc:e.loc})},{id:"class-directive",elementOnly:!0,match:e=>e.startsWith("class:"),build:e=>({kind:"ClassDirective",name:e.name.slice(6),hole:l(e,"class directive"),loc:e.loc})},{id:"style-directive",elementOnly:!0,match:e=>e.startsWith("style:"),build:e=>({kind:"StyleDirective",name:e.name.slice(6),hole:l(e,"style directive"),loc:e.loc})},{id:"load",match:e=>e.startsWith("load:"),build:e=>({kind:"LoadDirective",strategy:e.name.slice(5),modifier:e.value&&e.value.kind==="static"?e.value.value:null,loc:e.loc})},{id:"use",match:e=>e==="use"||e.startsWith("use:"),build:e=>({kind:"UseDirective",name:e.name.startsWith("use:")?e.name.slice(4):null,hole:e.value&&e.value.kind==="hole"?e.value.hole:null,loc:e.loc})},{id:"if",elementOnly:!0,match:e=>e==="if",build:e=>({kind:"IfDirective",hole:l(e,"if directive"),loc:e.loc})},{id:"each",elementOnly:!0,match:e=>e==="each",build:e=>({kind:"EachDirective",hole:l(e,"each directive"),key:null,loc:e.loc})},{id:"else",elementOnly:!0,match:e=>e==="else",build:e=>(e.value!==null&&e.report("invalid-directive","`else` takes no value"),{kind:"ElseDirective",loc:e.loc})},{id:"ref",match:e=>e==="ref",build:e=>({kind:"RefBinding",hole:l(e,"ref binding"),loc:e.loc})},{id:"property",match:e=>e[0]===".",build:e=>({kind:"PropertyBinding",name:e.name.slice(1),hole:l(e,"property binding"),loc:e.loc})},{id:"boolean",match:e=>e[0]==="?",build:e=>s(e,!0)}];function D(e,i=a,t={component:!1}){for(let n of i)if(!(n.elementOnly&&t.component)&&n.match(e.name))return n.build(e);return s(e,!1)}
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/directives.ts
21
+ var directives_exports = {};
22
+ __export(directives_exports, {
23
+ CORE_DIRECTIVES: () => CORE_DIRECTIVES,
24
+ EVENT_MODIFIERS: () => EVENT_MODIFIERS,
25
+ resolveAttribute: () => resolveAttribute
26
+ });
27
+ module.exports = __toCommonJS(directives_exports);
28
+ var EVENT_MODIFIERS = /* @__PURE__ */ new Set(["capture", "once", "passive", "prevent", "stop", "self"]);
29
+ function requireHole(raw, what) {
30
+ if (raw.value && raw.value.kind === "hole") return raw.value.hole;
31
+ raw.report("invalid-binding", `${what} requires an expression value: ${raw.name}=\${…}`);
32
+ return -1;
33
+ }
34
+ var attribute = (raw, boolean) => ({
35
+ kind: "Attribute",
36
+ name: boolean ? raw.name.slice(1) : raw.name,
37
+ value: raw.value,
38
+ boolean,
39
+ loc: raw.loc
40
+ });
41
+ var CORE_DIRECTIVES = [
42
+ // Events: `@click=${h}`, `on:click=${h}` (native), `onClick=${h}`, each with
43
+ // optional dotted modifiers (`@click.capture.once`, `on:input.passive`).
44
+ {
45
+ id: "event",
46
+ match: (n) => n[0] === "@" || n.startsWith("on:") || /^on[A-Z]/.test(n),
47
+ build: (raw) => {
48
+ let syntax;
49
+ let rest;
50
+ if (raw.name[0] === "@") {
51
+ syntax = "at";
52
+ rest = raw.name.slice(1);
53
+ } else if (raw.name.startsWith("on:")) {
54
+ syntax = "colon";
55
+ rest = raw.name.slice(3);
56
+ } else {
57
+ syntax = "on";
58
+ rest = raw.name.slice(2);
59
+ }
60
+ const [raw_name, ...modifiers] = rest.split(".");
61
+ const name = raw_name.toLowerCase();
62
+ for (const m of modifiers) {
63
+ if (!EVENT_MODIFIERS.has(m)) {
64
+ raw.report("invalid-directive", `Unknown event modifier ".${m}" — expected one of ${[...EVENT_MODIFIERS].join(", ")}`);
65
+ }
66
+ }
67
+ return {
68
+ kind: "EventBinding",
69
+ name,
70
+ syntax,
71
+ modifiers,
72
+ hole: requireHole(raw, "event binding"),
73
+ loc: raw.loc
74
+ };
75
+ }
76
+ },
77
+ // Two-way binding: `bind:value=${signal}`.
78
+ {
79
+ id: "bind",
80
+ elementOnly: true,
81
+ match: (n) => n.startsWith("bind:"),
82
+ build: (raw) => ({
83
+ kind: "BindDirective",
84
+ name: raw.name.slice("bind:".length),
85
+ hole: requireHole(raw, "two-way binding"),
86
+ loc: raw.loc
87
+ })
88
+ },
89
+ // Dynamic class toggle: `class:active=${flag}`.
90
+ {
91
+ id: "class-directive",
92
+ elementOnly: true,
93
+ match: (n) => n.startsWith("class:"),
94
+ build: (raw) => ({
95
+ kind: "ClassDirective",
96
+ name: raw.name.slice("class:".length),
97
+ hole: requireHole(raw, "class directive"),
98
+ loc: raw.loc
99
+ })
100
+ },
101
+ // Dynamic style: `style:color=${c}`.
102
+ {
103
+ id: "style-directive",
104
+ elementOnly: true,
105
+ match: (n) => n.startsWith("style:"),
106
+ build: (raw) => ({
107
+ kind: "StyleDirective",
108
+ name: raw.name.slice("style:".length),
109
+ hole: requireHole(raw, "style directive"),
110
+ loc: raw.loc
111
+ })
112
+ },
113
+ // Load strategy: `load:visible[="200px"]`. Components only, an intrinsic element
114
+ // has no module to defer.
115
+ {
116
+ id: "load",
117
+ match: (n) => n.startsWith("load:"),
118
+ build: (raw) => ({
119
+ kind: "LoadDirective",
120
+ strategy: raw.name.slice("load:".length),
121
+ modifier: raw.value && raw.value.kind === "static" ? raw.value.value : null,
122
+ loc: raw.loc
123
+ })
124
+ },
125
+ // Custom directive: `use=${d}` or `use:tooltip[=${opts}]`.
126
+ {
127
+ id: "use",
128
+ match: (n) => n === "use" || n.startsWith("use:"),
129
+ build: (raw) => {
130
+ const named = raw.name.startsWith("use:");
131
+ return {
132
+ kind: "UseDirective",
133
+ name: named ? raw.name.slice("use:".length) : null,
134
+ hole: raw.value && raw.value.kind === "hole" ? raw.value.hole : null,
135
+ loc: raw.loc
136
+ };
137
+ }
138
+ },
139
+ // Conditional rendering: `if=${cond}`.
140
+ {
141
+ id: "if",
142
+ elementOnly: true,
143
+ match: (n) => n === "if",
144
+ build: (raw) => ({
145
+ kind: "IfDirective",
146
+ hole: requireHole(raw, "if directive"),
147
+ loc: raw.loc
148
+ })
149
+ },
150
+ // Loop rendering: `each=${items}` (a sibling `key` folds in at parse time).
151
+ {
152
+ id: "each",
153
+ elementOnly: true,
154
+ match: (n) => n === "each",
155
+ build: (raw) => ({
156
+ kind: "EachDirective",
157
+ hole: requireHole(raw, "each directive"),
158
+ key: null,
159
+ loc: raw.loc
160
+ })
161
+ },
162
+ // `else` (valueless).
163
+ {
164
+ id: "else",
165
+ elementOnly: true,
166
+ match: (n) => n === "else",
167
+ build: (raw) => {
168
+ if (raw.value !== null) raw.report("invalid-directive", "`else` takes no value");
169
+ return { kind: "ElseDirective", loc: raw.loc };
170
+ }
171
+ },
172
+ // Ref binding: `ref=${el}`.
173
+ {
174
+ id: "ref",
175
+ match: (n) => n === "ref",
176
+ build: (raw) => ({
177
+ kind: "RefBinding",
178
+ hole: requireHole(raw, "ref binding"),
179
+ loc: raw.loc
180
+ })
181
+ },
182
+ // Property binding: `.currentTime=${t}`.
183
+ {
184
+ id: "property",
185
+ match: (n) => n[0] === ".",
186
+ build: (raw) => ({
187
+ kind: "PropertyBinding",
188
+ name: raw.name.slice(1),
189
+ hole: requireHole(raw, "property binding"),
190
+ loc: raw.loc
191
+ })
192
+ },
193
+ // Boolean attribute (lit `?disabled`): a plain attribute flagged boolean.
194
+ {
195
+ id: "boolean",
196
+ match: (n) => n[0] === "?",
197
+ build: (raw) => attribute(raw, true)
198
+ }
199
+ ];
200
+ function resolveAttribute(raw, directives = CORE_DIRECTIVES, ctx = { component: false }) {
201
+ for (const d of directives) {
202
+ if (d.elementOnly && ctx.component) continue;
203
+ if (d.match(raw.name)) return d.build(raw);
204
+ }
205
+ return attribute(raw, false);
206
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The directive registry: the extensibility seam.
3
+ *
4
+ * The core parser never hard-codes what `if`, `each`, `bind:value`, `@click`,
5
+ * `.prop` etc. mean. It parses a raw `name[=value]` pair, then asks the registry
6
+ * to turn it into a typed node. Adding future syntax is therefore a new
7
+ * descriptor here (or registered by a downstream tool), never a change to the
8
+ * parser's control flow. Descriptors are tried in order; the first whose
9
+ * `match` returns true owns the attribute. Anything unmatched falls back to a
10
+ * plain {@link AttributeNode}.
11
+ */
12
+ import type { AttributeLikeNode, AttrValue, Diagnostic, DiagnosticCode, SourceSpan } from './ast.cjs';
13
+ /** Recognized event modifiers (`@click.capture.once`, `on:input.passive`, …). */
14
+ export declare const EVENT_MODIFIERS: Set<string>;
15
+ /** A parsed-but-unclassified attribute handed to the registry. */
16
+ export interface RawAttribute {
17
+ /** Name exactly as written (`class`, `@click`, `bind:value`, `?disabled`). */
18
+ name: string;
19
+ nameLoc: SourceSpan;
20
+ /** null = valueless attribute. */
21
+ value: AttrValue | null;
22
+ loc: SourceSpan;
23
+ /** Emit a located diagnostic from inside a descriptor. */
24
+ report(code: DiagnosticCode, message: string): void;
25
+ }
26
+ export interface DirectiveDescriptor {
27
+ /** Stable id (for docs/debugging). */
28
+ id: string;
29
+ /** DOM-only sugar (`if`/`each`/`class:`…) is ignored on component tags. */
30
+ elementOnly?: boolean;
31
+ match(name: string): boolean;
32
+ build(raw: RawAttribute): AttributeLikeNode;
33
+ }
34
+ /** Where an attribute sits: a native element or a component tag. */
35
+ export interface AttrContext {
36
+ component: boolean;
37
+ }
38
+ /**
39
+ * The built-in directives. Order matters: prefix forms are matched before the
40
+ * plain-attribute fallback. Downstream tools can prepend their own.
41
+ */
42
+ export declare const CORE_DIRECTIVES: DirectiveDescriptor[];
43
+ /**
44
+ * Resolve a raw attribute to a typed node using `directives` (defaults to the
45
+ * core set). `each`/`key` are handled by the parser afterward because `key` is
46
+ * a sibling attribute that folds into the preceding `each` node.
47
+ */
48
+ export declare function resolveAttribute(raw: RawAttribute, directives?: DirectiveDescriptor[], ctx?: AttrContext): AttributeLikeNode;
49
+ export type { Diagnostic };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The directive registry — the extensibility seam.
2
+ * The directive registry: the extensibility seam.
3
3
  *
4
4
  * The core parser never hard-codes what `if`, `each`, `bind:value`, `@click`,
5
5
  * `.prop` etc. mean. It parses a raw `name[=value]` pair, then asks the registry
@@ -31,7 +31,7 @@ export interface DirectiveDescriptor {
31
31
  match(name: string): boolean;
32
32
  build(raw: RawAttribute): AttributeLikeNode;
33
33
  }
34
- /** Where an attribute sits — a native element or a component tag. */
34
+ /** Where an attribute sits: a native element or a component tag. */
35
35
  export interface AttrContext {
36
36
  component: boolean;
37
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,iBAAiB,EAEjB,SAAS,EAGT,UAAU,EACV,cAAc,EAOd,UAAU,EAIX,MAAM,UAAU,CAAC;AAElB,iFAAiF;AACjF,eAAO,MAAM,eAAe,aAAqE,CAAC;AAElG,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,kCAAkC;IAClC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,UAAU,CAAC;IAChB,0DAA0D;IAC1D,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAAC;CAC7C;AAED,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;CACpB;AAkBD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,mBAAmB,EA4JhD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,YAAY,EACjB,UAAU,GAAE,mBAAmB,EAAoB,EACnD,GAAG,GAAE,WAAkC,GACtC,iBAAiB,CAMnB;AAED,YAAY,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,iBAAiB,EAEjB,SAAS,EAGT,UAAU,EACV,cAAc,EAOd,UAAU,EAIX,MAAM,UAAU,CAAC;AAElB,iFAAiF;AACjF,eAAO,MAAM,eAAe,aAAqE,CAAC;AAElG,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,kCAAkC;IAClC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,UAAU,CAAC;IAChB,0DAA0D;IAC1D,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAAC;CAC7C;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;CACpB;AAkBD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,mBAAmB,EA4JhD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,YAAY,EACjB,UAAU,GAAE,mBAAmB,EAAoB,EACnD,GAAG,GAAE,WAAkC,GACtC,iBAAiB,CAMnB;AAED,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -42,7 +42,7 @@ export const CORE_DIRECTIVES = [
42
42
  }
43
43
  // Dotted modifiers apply to the @/on: forms; the camelCase name has no dots.
44
44
  // Lowercase the name so `onClick`, `@click` and `on:click` all yield `click`
45
- // — the AST documents this field as the DOM event name, and a consumer that
45
+ //: the AST documents this field as the DOM event name, and a consumer that
46
46
  // trusts that shouldn't have to know which spelling was written. (`syntax`
47
47
  // still records the spelling; the ts-plugin reads the written form from source.)
48
48
  const [raw_name, ...modifiers] = rest.split('.');
@@ -98,7 +98,7 @@ export const CORE_DIRECTIVES = [
98
98
  loc: raw.loc,
99
99
  }),
100
100
  },
101
- // Load strategy: `load:visible[="200px"]`. Components only — an intrinsic element
101
+ // Load strategy: `load:visible[="200px"]`. Components only, an intrinsic element
102
102
  // has no module to defer.
103
103
  {
104
104
  id: 'load',
@@ -1 +1,185 @@
1
- var d=new Set(["capture","once","passive","prevent","stop","self"]);function t(e,i){return e.value&&e.value.kind==="hole"?e.value.hole:(e.report("invalid-binding",`${i} requires an expression value: ${e.name}=\${…}`),-1)}var r=(e,i)=>({kind:"Attribute",name:i?e.name.slice(1):e.name,value:e.value,boolean:i,loc:e.loc}),a=[{id:"event",match:e=>e[0]==="@"||e.startsWith("on:")||/^on[A-Z]/.test(e),build:e=>{let i,n;e.name[0]==="@"?(i="at",n=e.name.slice(1)):e.name.startsWith("on:")?(i="colon",n=e.name.slice(3)):(i="on",n=e.name.slice(2));let[o,...l]=n.split("."),s=o.toLowerCase();for(let c of l)d.has(c)||e.report("invalid-directive",`Unknown event modifier ".${c}" — expected one of ${[...d].join(", ")}`);return{kind:"EventBinding",name:s,syntax:i,modifiers:l,hole:t(e,"event binding"),loc:e.loc}}},{id:"bind",elementOnly:!0,match:e=>e.startsWith("bind:"),build:e=>({kind:"BindDirective",name:e.name.slice(5),hole:t(e,"two-way binding"),loc:e.loc})},{id:"class-directive",elementOnly:!0,match:e=>e.startsWith("class:"),build:e=>({kind:"ClassDirective",name:e.name.slice(6),hole:t(e,"class directive"),loc:e.loc})},{id:"style-directive",elementOnly:!0,match:e=>e.startsWith("style:"),build:e=>({kind:"StyleDirective",name:e.name.slice(6),hole:t(e,"style directive"),loc:e.loc})},{id:"load",match:e=>e.startsWith("load:"),build:e=>({kind:"LoadDirective",strategy:e.name.slice(5),modifier:e.value&&e.value.kind==="static"?e.value.value:null,loc:e.loc})},{id:"use",match:e=>e==="use"||e.startsWith("use:"),build:e=>({kind:"UseDirective",name:e.name.startsWith("use:")?e.name.slice(4):null,hole:e.value&&e.value.kind==="hole"?e.value.hole:null,loc:e.loc})},{id:"if",elementOnly:!0,match:e=>e==="if",build:e=>({kind:"IfDirective",hole:t(e,"if directive"),loc:e.loc})},{id:"each",elementOnly:!0,match:e=>e==="each",build:e=>({kind:"EachDirective",hole:t(e,"each directive"),key:null,loc:e.loc})},{id:"else",elementOnly:!0,match:e=>e==="else",build:e=>(e.value!==null&&e.report("invalid-directive","`else` takes no value"),{kind:"ElseDirective",loc:e.loc})},{id:"ref",match:e=>e==="ref",build:e=>({kind:"RefBinding",hole:t(e,"ref binding"),loc:e.loc})},{id:"property",match:e=>e[0]===".",build:e=>({kind:"PropertyBinding",name:e.name.slice(1),hole:t(e,"property binding"),loc:e.loc})},{id:"boolean",match:e=>e[0]==="?",build:e=>r(e,!0)}];function u(e,i=a,n={component:!1}){for(let o of i)if(!(o.elementOnly&&n.component)&&o.match(e.name))return o.build(e);return r(e,!1)}export{a as CORE_DIRECTIVES,d as EVENT_MODIFIERS,u as resolveAttribute};
1
+ // src/directives.ts
2
+ var EVENT_MODIFIERS = /* @__PURE__ */ new Set(["capture", "once", "passive", "prevent", "stop", "self"]);
3
+ function requireHole(raw, what) {
4
+ if (raw.value && raw.value.kind === "hole") return raw.value.hole;
5
+ raw.report("invalid-binding", `${what} requires an expression value: ${raw.name}=\${…}`);
6
+ return -1;
7
+ }
8
+ var attribute = (raw, boolean) => ({
9
+ kind: "Attribute",
10
+ name: boolean ? raw.name.slice(1) : raw.name,
11
+ value: raw.value,
12
+ boolean,
13
+ loc: raw.loc
14
+ });
15
+ var CORE_DIRECTIVES = [
16
+ // Events: `@click=${h}`, `on:click=${h}` (native), `onClick=${h}`, each with
17
+ // optional dotted modifiers (`@click.capture.once`, `on:input.passive`).
18
+ {
19
+ id: "event",
20
+ match: (n) => n[0] === "@" || n.startsWith("on:") || /^on[A-Z]/.test(n),
21
+ build: (raw) => {
22
+ let syntax;
23
+ let rest;
24
+ if (raw.name[0] === "@") {
25
+ syntax = "at";
26
+ rest = raw.name.slice(1);
27
+ } else if (raw.name.startsWith("on:")) {
28
+ syntax = "colon";
29
+ rest = raw.name.slice(3);
30
+ } else {
31
+ syntax = "on";
32
+ rest = raw.name.slice(2);
33
+ }
34
+ const [raw_name, ...modifiers] = rest.split(".");
35
+ const name = raw_name.toLowerCase();
36
+ for (const m of modifiers) {
37
+ if (!EVENT_MODIFIERS.has(m)) {
38
+ raw.report("invalid-directive", `Unknown event modifier ".${m}" — expected one of ${[...EVENT_MODIFIERS].join(", ")}`);
39
+ }
40
+ }
41
+ return {
42
+ kind: "EventBinding",
43
+ name,
44
+ syntax,
45
+ modifiers,
46
+ hole: requireHole(raw, "event binding"),
47
+ loc: raw.loc
48
+ };
49
+ }
50
+ },
51
+ // Two-way binding: `bind:value=${signal}`.
52
+ {
53
+ id: "bind",
54
+ elementOnly: true,
55
+ match: (n) => n.startsWith("bind:"),
56
+ build: (raw) => ({
57
+ kind: "BindDirective",
58
+ name: raw.name.slice("bind:".length),
59
+ hole: requireHole(raw, "two-way binding"),
60
+ loc: raw.loc
61
+ })
62
+ },
63
+ // Dynamic class toggle: `class:active=${flag}`.
64
+ {
65
+ id: "class-directive",
66
+ elementOnly: true,
67
+ match: (n) => n.startsWith("class:"),
68
+ build: (raw) => ({
69
+ kind: "ClassDirective",
70
+ name: raw.name.slice("class:".length),
71
+ hole: requireHole(raw, "class directive"),
72
+ loc: raw.loc
73
+ })
74
+ },
75
+ // Dynamic style: `style:color=${c}`.
76
+ {
77
+ id: "style-directive",
78
+ elementOnly: true,
79
+ match: (n) => n.startsWith("style:"),
80
+ build: (raw) => ({
81
+ kind: "StyleDirective",
82
+ name: raw.name.slice("style:".length),
83
+ hole: requireHole(raw, "style directive"),
84
+ loc: raw.loc
85
+ })
86
+ },
87
+ // Load strategy: `load:visible[="200px"]`. Components only, an intrinsic element
88
+ // has no module to defer.
89
+ {
90
+ id: "load",
91
+ match: (n) => n.startsWith("load:"),
92
+ build: (raw) => ({
93
+ kind: "LoadDirective",
94
+ strategy: raw.name.slice("load:".length),
95
+ modifier: raw.value && raw.value.kind === "static" ? raw.value.value : null,
96
+ loc: raw.loc
97
+ })
98
+ },
99
+ // Custom directive: `use=${d}` or `use:tooltip[=${opts}]`.
100
+ {
101
+ id: "use",
102
+ match: (n) => n === "use" || n.startsWith("use:"),
103
+ build: (raw) => {
104
+ const named = raw.name.startsWith("use:");
105
+ return {
106
+ kind: "UseDirective",
107
+ name: named ? raw.name.slice("use:".length) : null,
108
+ hole: raw.value && raw.value.kind === "hole" ? raw.value.hole : null,
109
+ loc: raw.loc
110
+ };
111
+ }
112
+ },
113
+ // Conditional rendering: `if=${cond}`.
114
+ {
115
+ id: "if",
116
+ elementOnly: true,
117
+ match: (n) => n === "if",
118
+ build: (raw) => ({
119
+ kind: "IfDirective",
120
+ hole: requireHole(raw, "if directive"),
121
+ loc: raw.loc
122
+ })
123
+ },
124
+ // Loop rendering: `each=${items}` (a sibling `key` folds in at parse time).
125
+ {
126
+ id: "each",
127
+ elementOnly: true,
128
+ match: (n) => n === "each",
129
+ build: (raw) => ({
130
+ kind: "EachDirective",
131
+ hole: requireHole(raw, "each directive"),
132
+ key: null,
133
+ loc: raw.loc
134
+ })
135
+ },
136
+ // `else` (valueless).
137
+ {
138
+ id: "else",
139
+ elementOnly: true,
140
+ match: (n) => n === "else",
141
+ build: (raw) => {
142
+ if (raw.value !== null) raw.report("invalid-directive", "`else` takes no value");
143
+ return { kind: "ElseDirective", loc: raw.loc };
144
+ }
145
+ },
146
+ // Ref binding: `ref=${el}`.
147
+ {
148
+ id: "ref",
149
+ match: (n) => n === "ref",
150
+ build: (raw) => ({
151
+ kind: "RefBinding",
152
+ hole: requireHole(raw, "ref binding"),
153
+ loc: raw.loc
154
+ })
155
+ },
156
+ // Property binding: `.currentTime=${t}`.
157
+ {
158
+ id: "property",
159
+ match: (n) => n[0] === ".",
160
+ build: (raw) => ({
161
+ kind: "PropertyBinding",
162
+ name: raw.name.slice(1),
163
+ hole: requireHole(raw, "property binding"),
164
+ loc: raw.loc
165
+ })
166
+ },
167
+ // Boolean attribute (lit `?disabled`): a plain attribute flagged boolean.
168
+ {
169
+ id: "boolean",
170
+ match: (n) => n[0] === "?",
171
+ build: (raw) => attribute(raw, true)
172
+ }
173
+ ];
174
+ function resolveAttribute(raw, directives = CORE_DIRECTIVES, ctx = { component: false }) {
175
+ for (const d of directives) {
176
+ if (d.elementOnly && ctx.component) continue;
177
+ if (d.match(raw.name)) return d.build(raw);
178
+ }
179
+ return attribute(raw, false);
180
+ }
181
+ export {
182
+ CORE_DIRECTIVES,
183
+ EVENT_MODIFIERS,
184
+ resolveAttribute
185
+ };