dalila 1.3.2 → 1.4.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/README.md +87 -611
- package/dist/context/auto-scope.d.ts +65 -0
- package/dist/context/auto-scope.js +28 -0
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/raw.d.ts +1 -1
- package/dist/context/raw.js +1 -1
- package/dist/core/dev.d.ts +5 -0
- package/dist/core/dev.js +7 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/persist.d.ts +63 -0
- package/dist/core/persist.js +371 -0
- package/dist/core/scope.d.ts +17 -0
- package/dist/core/scope.js +29 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime/bind.d.ts +59 -0
- package/dist/runtime/bind.js +336 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.js +9 -0
- package/package.json +18 -1
- package/dist/compiler/dalila-lang.d.ts +0 -85
- package/dist/compiler/dalila-lang.js +0 -442
- package/dist/dom/elements.d.ts +0 -15
- package/dist/dom/elements.js +0 -100
- package/dist/dom/events.d.ts +0 -7
- package/dist/dom/events.js +0 -47
- package/dist/dom/index.d.ts +0 -2
- package/dist/dom/index.js +0 -2
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dalila Template Runtime - bind()
|
|
3
|
+
*
|
|
4
|
+
* Binds a DOM tree to a reactive context using declarative attributes.
|
|
5
|
+
* No eval, no inline JS execution - only identifier resolution from ctx.
|
|
6
|
+
*
|
|
7
|
+
* @module dalila/runtime
|
|
8
|
+
*/
|
|
9
|
+
export interface BindOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Event types to bind (default: click, input, change, submit, keydown, keyup)
|
|
12
|
+
*/
|
|
13
|
+
events?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Selectors for elements where text interpolation should be skipped
|
|
16
|
+
*/
|
|
17
|
+
rawTextSelectors?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BindContext {
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export type DisposeFunction = () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Bind a DOM tree to a reactive context.
|
|
25
|
+
*
|
|
26
|
+
* @param root - The root element to bind
|
|
27
|
+
* @param ctx - The context object containing handlers and reactive values
|
|
28
|
+
* @param options - Binding options
|
|
29
|
+
* @returns A dispose function that removes all bindings
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { bind } from 'dalila/runtime';
|
|
34
|
+
*
|
|
35
|
+
* const ctx = {
|
|
36
|
+
* count: signal(0),
|
|
37
|
+
* increment: () => count.update(n => n + 1),
|
|
38
|
+
* };
|
|
39
|
+
*
|
|
40
|
+
* const dispose = bind(document.getElementById('app')!, ctx);
|
|
41
|
+
*
|
|
42
|
+
* // Later, to cleanup:
|
|
43
|
+
* dispose();
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function bind(root: Element, ctx: BindContext, options?: BindOptions): DisposeFunction;
|
|
47
|
+
/**
|
|
48
|
+
* Automatically bind when DOM is ready.
|
|
49
|
+
* Useful for simple pages without a build step.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```html
|
|
53
|
+
* <script type="module">
|
|
54
|
+
* import { autoBind } from 'dalila/runtime';
|
|
55
|
+
* autoBind('#app', { count: signal(0) });
|
|
56
|
+
* </script>
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function autoBind(selector: string, ctx: BindContext, options?: BindOptions): Promise<DisposeFunction>;
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dalila Template Runtime - bind()
|
|
3
|
+
*
|
|
4
|
+
* Binds a DOM tree to a reactive context using declarative attributes.
|
|
5
|
+
* No eval, no inline JS execution - only identifier resolution from ctx.
|
|
6
|
+
*
|
|
7
|
+
* @module dalila/runtime
|
|
8
|
+
*/
|
|
9
|
+
import { effect, createScope, withScope, isInDevMode } from '../core/index.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Utilities
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Check if a value is a Dalila signal
|
|
15
|
+
*/
|
|
16
|
+
function isSignal(value) {
|
|
17
|
+
return typeof value === 'function' && 'set' in value && 'update' in value;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a value from ctx - handles signals, functions, and plain values
|
|
21
|
+
*/
|
|
22
|
+
function resolve(value) {
|
|
23
|
+
if (isSignal(value))
|
|
24
|
+
return value();
|
|
25
|
+
if (typeof value === 'function')
|
|
26
|
+
return value();
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Normalize binding attribute value
|
|
31
|
+
* Handles both "name" and "{name}" formats
|
|
32
|
+
*/
|
|
33
|
+
function normalizeBinding(raw) {
|
|
34
|
+
if (!raw)
|
|
35
|
+
return null;
|
|
36
|
+
const trimmed = raw.trim();
|
|
37
|
+
// Match {name} format and extract name
|
|
38
|
+
const match = trimmed.match(/^\{\s*([a-zA-Z_$][\w$]*)\s*\}$/);
|
|
39
|
+
return match ? match[1] : trimmed;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Dev mode warning helper
|
|
43
|
+
*/
|
|
44
|
+
function warn(message) {
|
|
45
|
+
if (isInDevMode()) {
|
|
46
|
+
console.warn(`[Dalila] ${message}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Default Options
|
|
51
|
+
// ============================================================================
|
|
52
|
+
const DEFAULT_EVENTS = ['click', 'input', 'change', 'submit', 'keydown', 'keyup'];
|
|
53
|
+
const DEFAULT_RAW_TEXT_SELECTORS = 'pre, code';
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Text Interpolation
|
|
56
|
+
// ============================================================================
|
|
57
|
+
/**
|
|
58
|
+
* Process a text node and replace {tokens} with reactive bindings
|
|
59
|
+
*/
|
|
60
|
+
function bindTextNode(node, ctx, cleanups) {
|
|
61
|
+
const text = node.data;
|
|
62
|
+
const regex = /\{\s*([a-zA-Z_$][\w$]*)\s*\}/g;
|
|
63
|
+
// Check if there are any tokens
|
|
64
|
+
if (!regex.test(text))
|
|
65
|
+
return;
|
|
66
|
+
// Reset regex
|
|
67
|
+
regex.lastIndex = 0;
|
|
68
|
+
const frag = document.createDocumentFragment();
|
|
69
|
+
let cursor = 0;
|
|
70
|
+
let match;
|
|
71
|
+
while ((match = regex.exec(text)) !== null) {
|
|
72
|
+
// Add text before the token
|
|
73
|
+
const before = text.slice(cursor, match.index);
|
|
74
|
+
if (before) {
|
|
75
|
+
frag.appendChild(document.createTextNode(before));
|
|
76
|
+
}
|
|
77
|
+
const key = match[1];
|
|
78
|
+
const value = ctx[key];
|
|
79
|
+
if (value === undefined) {
|
|
80
|
+
warn(`Text interpolation: "${key}" not found in context`);
|
|
81
|
+
frag.appendChild(document.createTextNode(match[0]));
|
|
82
|
+
}
|
|
83
|
+
else if (isSignal(value)) {
|
|
84
|
+
// Reactive text node
|
|
85
|
+
const textNode = document.createTextNode('');
|
|
86
|
+
const stop = effect(() => {
|
|
87
|
+
textNode.data = String(value());
|
|
88
|
+
});
|
|
89
|
+
if (typeof stop === 'function') {
|
|
90
|
+
cleanups.push(stop);
|
|
91
|
+
}
|
|
92
|
+
frag.appendChild(textNode);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Static value - render once
|
|
96
|
+
frag.appendChild(document.createTextNode(String(value)));
|
|
97
|
+
}
|
|
98
|
+
cursor = match.index + match[0].length;
|
|
99
|
+
}
|
|
100
|
+
// Add remaining text
|
|
101
|
+
const after = text.slice(cursor);
|
|
102
|
+
if (after) {
|
|
103
|
+
frag.appendChild(document.createTextNode(after));
|
|
104
|
+
}
|
|
105
|
+
// Replace original node
|
|
106
|
+
if (node.parentNode) {
|
|
107
|
+
node.parentNode.replaceChild(frag, node);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Event Binding
|
|
112
|
+
// ============================================================================
|
|
113
|
+
/**
|
|
114
|
+
* Bind all d-on-* events within root
|
|
115
|
+
*/
|
|
116
|
+
function bindEvents(root, ctx, events, cleanups) {
|
|
117
|
+
for (const eventName of events) {
|
|
118
|
+
const attr = `d-on-${eventName}`;
|
|
119
|
+
const elements = root.querySelectorAll(`[${attr}]`);
|
|
120
|
+
elements.forEach((el) => {
|
|
121
|
+
const handlerName = normalizeBinding(el.getAttribute(attr));
|
|
122
|
+
if (!handlerName)
|
|
123
|
+
return;
|
|
124
|
+
const handler = ctx[handlerName];
|
|
125
|
+
if (handler === undefined) {
|
|
126
|
+
warn(`Event handler "${handlerName}" not found in context`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (typeof handler !== 'function') {
|
|
130
|
+
warn(`Event handler "${handlerName}" is not a function`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
el.addEventListener(eventName, handler);
|
|
134
|
+
cleanups.push(() => el.removeEventListener(eventName, handler));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// when Directive
|
|
140
|
+
// ============================================================================
|
|
141
|
+
/**
|
|
142
|
+
* Bind all [when] directives within root
|
|
143
|
+
*/
|
|
144
|
+
function bindWhen(root, ctx, cleanups) {
|
|
145
|
+
const elements = root.querySelectorAll('[when]');
|
|
146
|
+
elements.forEach((el) => {
|
|
147
|
+
const bindingName = normalizeBinding(el.getAttribute('when'));
|
|
148
|
+
if (!bindingName)
|
|
149
|
+
return;
|
|
150
|
+
const binding = ctx[bindingName];
|
|
151
|
+
if (binding === undefined) {
|
|
152
|
+
warn(`when: "${bindingName}" not found in context`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const htmlEl = el;
|
|
156
|
+
const stop = effect(() => {
|
|
157
|
+
const value = !!resolve(binding);
|
|
158
|
+
htmlEl.style.display = value ? '' : 'none';
|
|
159
|
+
});
|
|
160
|
+
if (typeof stop === 'function') {
|
|
161
|
+
cleanups.push(stop);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// match Directive
|
|
167
|
+
// ============================================================================
|
|
168
|
+
/**
|
|
169
|
+
* Bind all [match] directives within root
|
|
170
|
+
*/
|
|
171
|
+
function bindMatch(root, ctx, cleanups) {
|
|
172
|
+
const elements = root.querySelectorAll('[match]');
|
|
173
|
+
elements.forEach((el) => {
|
|
174
|
+
const bindingName = normalizeBinding(el.getAttribute('match'));
|
|
175
|
+
if (!bindingName)
|
|
176
|
+
return;
|
|
177
|
+
const binding = ctx[bindingName];
|
|
178
|
+
if (binding === undefined) {
|
|
179
|
+
warn(`match: "${bindingName}" not found in context`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const cases = Array.from(el.querySelectorAll('[case]'));
|
|
183
|
+
const stop = effect(() => {
|
|
184
|
+
const value = String(resolve(binding));
|
|
185
|
+
let matchedEl = null;
|
|
186
|
+
let defaultEl = null;
|
|
187
|
+
// First pass: hide all and find match/default
|
|
188
|
+
for (const caseEl of cases) {
|
|
189
|
+
caseEl.style.display = 'none';
|
|
190
|
+
const caseValue = caseEl.getAttribute('case');
|
|
191
|
+
if (caseValue === 'default') {
|
|
192
|
+
defaultEl = caseEl;
|
|
193
|
+
}
|
|
194
|
+
else if (caseValue === value && !matchedEl) {
|
|
195
|
+
matchedEl = caseEl;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Second pass: show match OR default (not both)
|
|
199
|
+
if (matchedEl) {
|
|
200
|
+
matchedEl.style.display = '';
|
|
201
|
+
}
|
|
202
|
+
else if (defaultEl) {
|
|
203
|
+
defaultEl.style.display = '';
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
if (typeof stop === 'function') {
|
|
207
|
+
cleanups.push(stop);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// Main bind() Function
|
|
213
|
+
// ============================================================================
|
|
214
|
+
/**
|
|
215
|
+
* Bind a DOM tree to a reactive context.
|
|
216
|
+
*
|
|
217
|
+
* @param root - The root element to bind
|
|
218
|
+
* @param ctx - The context object containing handlers and reactive values
|
|
219
|
+
* @param options - Binding options
|
|
220
|
+
* @returns A dispose function that removes all bindings
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* import { bind } from 'dalila/runtime';
|
|
225
|
+
*
|
|
226
|
+
* const ctx = {
|
|
227
|
+
* count: signal(0),
|
|
228
|
+
* increment: () => count.update(n => n + 1),
|
|
229
|
+
* };
|
|
230
|
+
*
|
|
231
|
+
* const dispose = bind(document.getElementById('app')!, ctx);
|
|
232
|
+
*
|
|
233
|
+
* // Later, to cleanup:
|
|
234
|
+
* dispose();
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
export function bind(root, ctx, options = {}) {
|
|
238
|
+
const events = options.events ?? DEFAULT_EVENTS;
|
|
239
|
+
const rawTextSelectors = options.rawTextSelectors ?? DEFAULT_RAW_TEXT_SELECTORS;
|
|
240
|
+
const htmlRoot = root;
|
|
241
|
+
// Create a scope for this template binding
|
|
242
|
+
const templateScope = createScope();
|
|
243
|
+
const cleanups = [];
|
|
244
|
+
// Run all bindings within the template scope
|
|
245
|
+
withScope(templateScope, () => {
|
|
246
|
+
// 1. Text interpolation
|
|
247
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
248
|
+
const textNodes = [];
|
|
249
|
+
while (walker.nextNode()) {
|
|
250
|
+
const node = walker.currentNode;
|
|
251
|
+
// Skip nodes inside raw text containers
|
|
252
|
+
const parent = node.parentElement;
|
|
253
|
+
if (parent && parent.closest(rawTextSelectors)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (node.data.includes('{')) {
|
|
257
|
+
textNodes.push(node);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Process text nodes (collect first, then process to avoid walker issues)
|
|
261
|
+
for (const node of textNodes) {
|
|
262
|
+
bindTextNode(node, ctx, cleanups);
|
|
263
|
+
}
|
|
264
|
+
// 2. Event bindings
|
|
265
|
+
bindEvents(root, ctx, events, cleanups);
|
|
266
|
+
// 3. when directive
|
|
267
|
+
bindWhen(root, ctx, cleanups);
|
|
268
|
+
// 4. match directive
|
|
269
|
+
bindMatch(root, ctx, cleanups);
|
|
270
|
+
});
|
|
271
|
+
// Bindings complete: remove loading state and mark as ready
|
|
272
|
+
// Use microtask to ensure all effects have run at least once
|
|
273
|
+
queueMicrotask(() => {
|
|
274
|
+
htmlRoot.removeAttribute('d-loading');
|
|
275
|
+
htmlRoot.setAttribute('d-ready', '');
|
|
276
|
+
});
|
|
277
|
+
// Return dispose function
|
|
278
|
+
return () => {
|
|
279
|
+
// Run manual cleanups (event listeners)
|
|
280
|
+
for (const cleanup of cleanups) {
|
|
281
|
+
if (typeof cleanup === 'function') {
|
|
282
|
+
try {
|
|
283
|
+
cleanup();
|
|
284
|
+
}
|
|
285
|
+
catch (e) {
|
|
286
|
+
if (isInDevMode()) {
|
|
287
|
+
console.warn('[Dalila] Cleanup error:', e);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
cleanups.length = 0;
|
|
293
|
+
// Dispose template scope (stops all effects)
|
|
294
|
+
try {
|
|
295
|
+
templateScope.dispose();
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
if (isInDevMode()) {
|
|
299
|
+
console.warn('[Dalila] Scope dispose error:', e);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// ============================================================================
|
|
305
|
+
// Convenience: Auto-bind on DOMContentLoaded
|
|
306
|
+
// ============================================================================
|
|
307
|
+
/**
|
|
308
|
+
* Automatically bind when DOM is ready.
|
|
309
|
+
* Useful for simple pages without a build step.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```html
|
|
313
|
+
* <script type="module">
|
|
314
|
+
* import { autoBind } from 'dalila/runtime';
|
|
315
|
+
* autoBind('#app', { count: signal(0) });
|
|
316
|
+
* </script>
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
export function autoBind(selector, ctx, options) {
|
|
320
|
+
return new Promise((resolve, reject) => {
|
|
321
|
+
const doBind = () => {
|
|
322
|
+
const root = document.querySelector(selector);
|
|
323
|
+
if (!root) {
|
|
324
|
+
reject(new Error(`[Dalila] Element not found: ${selector}`));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
resolve(bind(root, ctx, options));
|
|
328
|
+
};
|
|
329
|
+
if (document.readyState === 'loading') {
|
|
330
|
+
document.addEventListener('DOMContentLoaded', doBind, { once: true });
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
doBind();
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dalila Runtime Module
|
|
3
|
+
*
|
|
4
|
+
* Provides declarative DOM binding with reactive updates.
|
|
5
|
+
* No eval, no inline JS - only identifier resolution.
|
|
6
|
+
*
|
|
7
|
+
* @module dalila/runtime
|
|
8
|
+
*/
|
|
9
|
+
export { bind, autoBind } from './bind.js';
|
|
10
|
+
export type { BindOptions, BindContext, DisposeFunction } from './bind.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dalila",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "DOM-first reactive framework based on signals",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,6 +9,22 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./core": {
|
|
14
|
+
"types": "./dist/core/index.d.ts",
|
|
15
|
+
"default": "./dist/core/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./context": {
|
|
18
|
+
"types": "./dist/context/index.d.ts",
|
|
19
|
+
"default": "./dist/context/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./context/raw": {
|
|
22
|
+
"types": "./dist/context/raw.d.ts",
|
|
23
|
+
"default": "./dist/context/raw.js"
|
|
24
|
+
},
|
|
25
|
+
"./runtime": {
|
|
26
|
+
"types": "./dist/runtime/index.d.ts",
|
|
27
|
+
"default": "./dist/runtime/index.js"
|
|
12
28
|
}
|
|
13
29
|
},
|
|
14
30
|
"scripts": {
|
|
@@ -34,6 +50,7 @@
|
|
|
34
50
|
"@playwright/test": "^1.57.0",
|
|
35
51
|
"@types/jest": "^29.5.0",
|
|
36
52
|
"@types/node": "^20.0.0",
|
|
53
|
+
"chokidar": "^3.6.0",
|
|
37
54
|
"jest": "^29.5.0",
|
|
38
55
|
"jest-environment-jsdom": "^29.5.0",
|
|
39
56
|
"typescript": "^5.9.3"
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
export interface DalilaTemplate {
|
|
2
|
-
path: string;
|
|
3
|
-
content: string;
|
|
4
|
-
componentName: string;
|
|
5
|
-
}
|
|
6
|
-
export interface CompilationResult {
|
|
7
|
-
source: string;
|
|
8
|
-
typeDefinition: string;
|
|
9
|
-
diagnostics: Diagnostic[];
|
|
10
|
-
}
|
|
11
|
-
export interface Diagnostic {
|
|
12
|
-
message: string;
|
|
13
|
-
line: number;
|
|
14
|
-
column: number;
|
|
15
|
-
severity: 'error' | 'warning' | 'info';
|
|
16
|
-
}
|
|
17
|
-
export interface ElementNode {
|
|
18
|
-
type: 'element';
|
|
19
|
-
tagName: string;
|
|
20
|
-
attributes: Attribute[];
|
|
21
|
-
children: Node[];
|
|
22
|
-
selfClosing: boolean;
|
|
23
|
-
location: Location;
|
|
24
|
-
}
|
|
25
|
-
export interface TextNode {
|
|
26
|
-
type: 'text';
|
|
27
|
-
content: string;
|
|
28
|
-
location: Location;
|
|
29
|
-
}
|
|
30
|
-
export interface InterpolationNode {
|
|
31
|
-
type: 'interpolation';
|
|
32
|
-
identifier: string;
|
|
33
|
-
location: Location;
|
|
34
|
-
}
|
|
35
|
-
export interface Attribute {
|
|
36
|
-
name: string;
|
|
37
|
-
value: string | InterpolationNode | null;
|
|
38
|
-
location: Location;
|
|
39
|
-
}
|
|
40
|
-
export interface Location {
|
|
41
|
-
line: number;
|
|
42
|
-
column: number;
|
|
43
|
-
offset: number;
|
|
44
|
-
}
|
|
45
|
-
export type Node = ElementNode | TextNode | InterpolationNode;
|
|
46
|
-
export declare function isElementNode(node: Node): node is ElementNode;
|
|
47
|
-
export declare function isTextNode(node: Node): node is TextNode;
|
|
48
|
-
export declare function isInterpolationNode(node: Node): node is InterpolationNode;
|
|
49
|
-
export declare class DalilaParser {
|
|
50
|
-
private input;
|
|
51
|
-
private position;
|
|
52
|
-
private line;
|
|
53
|
-
private column;
|
|
54
|
-
private rawTextTags;
|
|
55
|
-
constructor(input: string);
|
|
56
|
-
parse(): {
|
|
57
|
-
ast: Node[];
|
|
58
|
-
diagnostics: Diagnostic[];
|
|
59
|
-
};
|
|
60
|
-
private parseElement;
|
|
61
|
-
private parseTagName;
|
|
62
|
-
private parseAttributes;
|
|
63
|
-
private parseAttribute;
|
|
64
|
-
private parseInterpolation;
|
|
65
|
-
private parseText;
|
|
66
|
-
private skipWhitespace;
|
|
67
|
-
private match;
|
|
68
|
-
private lookingAt;
|
|
69
|
-
private peek;
|
|
70
|
-
private advance;
|
|
71
|
-
private backup;
|
|
72
|
-
private isAtEnd;
|
|
73
|
-
private currentLocation;
|
|
74
|
-
}
|
|
75
|
-
export declare class DalilaCodeGenerator {
|
|
76
|
-
private indentLevel;
|
|
77
|
-
private output;
|
|
78
|
-
generate(ast: Node[], componentName: string): CompilationResult;
|
|
79
|
-
private generateElement;
|
|
80
|
-
private generateAttribute;
|
|
81
|
-
private generateTextInterpolation;
|
|
82
|
-
private generateTypeDefinition;
|
|
83
|
-
private emit;
|
|
84
|
-
}
|
|
85
|
-
export declare function compileDalilaTemplate(template: DalilaTemplate): CompilationResult;
|