0
# Compilation
1
2
Runtime compilation capabilities for compiling riot components from templates and URLs. Available only in the riot+compiler build, these functions enable dynamic component compilation and template processing in the browser.
3
4
## Capabilities
5
6
### Compile DOM Scripts
7
8
Automatically discovers and compiles riot script tags in the DOM.
9
10
```typescript { .api }
11
/**
12
* Compile riot script tags found in the DOM
13
* @param options - Optional compilation configuration
14
* @returns Promise that resolves when all scripts are compiled and registered
15
*/
16
function compile(options?: CompileOptions): Promise<void>;
17
```
18
19
**Usage Example:**
20
21
```html
22
<!-- HTML with riot script tags -->
23
<script type="riot" src="./components/my-timer.riot"></script>
24
<script type="riot" data-src="./components/my-widget.riot"></script>
25
```
26
27
```javascript
28
import { compile, mount } from "riot+compiler";
29
30
// Compile all riot script tags and register components
31
await compile({
32
// Optional compilation options
33
compact: true,
34
expression: "javascript"
35
});
36
37
// Components are now registered and can be mounted
38
mount("my-timer");
39
mount("my-widget");
40
```
41
42
### Compile from String
43
44
Compiles a riot component from a template string.
45
46
```typescript { .api }
47
/**
48
* Compile riot component from string template
49
* @param string - Component template string
50
* @param options - Optional compilation configuration
51
* @returns Compilation result with code and metadata
52
*/
53
function compileFromString(
54
string: string,
55
options?: CompileOptions
56
): CompilationResult;
57
```
58
59
**Usage Example:**
60
61
```javascript
62
import { compileFromString, register } from "riot+compiler";
63
64
const template = `
65
<my-dynamic-component>
66
<h1>{ props.title }</h1>
67
<p>Generated at: { state.timestamp }</p>
68
69
<script>
70
export default {
71
onBeforeMount() {
72
this.state = { timestamp: new Date().toISOString() };
73
}
74
}
75
</script>
76
77
<style>
78
my-dynamic-component {
79
padding: 1rem;
80
border: 1px solid #ccc;
81
}
82
</style>
83
</my-dynamic-component>
84
`;
85
86
// Compile the template
87
const result = compileFromString(template, {
88
file: 'dynamic-component.riot'
89
});
90
91
// Register the compiled component
92
register("my-dynamic-component", eval(result.code));
93
```
94
95
### Compile from URL
96
97
Fetches and compiles a riot component from a URL.
98
99
```typescript { .api }
100
/**
101
* Compile riot component from URL
102
* @param url - URL to fetch component template from
103
* @param options - Optional compilation configuration
104
* @returns Promise with compilation result
105
*/
106
function compileFromUrl(
107
url: string,
108
options?: CompileOptions
109
): Promise<CompilationResult>;
110
```
111
112
**Usage Example:**
113
114
```javascript
115
import { compileFromUrl, register } from "riot+compiler";
116
117
// Fetch and compile remote component
118
const result = await compileFromUrl("https://example.com/components/remote-widget.riot", {
119
compact: false,
120
expression: "javascript"
121
});
122
123
// Register the compiled component
124
register("remote-widget", eval(result.code));
125
126
// Mount the component
127
mount("remote-widget", { apiKey: "abc123" });
128
```
129
130
### Inject Compiled Component
131
132
Evaluates and registers compiled component code in the global registry.
133
134
```typescript { .api }
135
/**
136
* Inject compiled component code into global registry
137
* @param code - Compiled component JavaScript code
138
* @param tagName - Component tag name for registration
139
* @param url - Source URL for debugging/error reporting
140
* @returns void
141
*/
142
function inject(code: string, tagName: string, url: string): void;
143
```
144
145
**Usage Example:**
146
147
```javascript
148
import { inject } from "riot+compiler";
149
150
// Manually inject pre-compiled code
151
const compiledCode = `({
152
css: 'injected-component { color: red; }',
153
template: (template) => template('<h1>Injected!</h1>'),
154
exports: {
155
onMounted() {
156
console.log('Injected component mounted');
157
}
158
}
159
})`;
160
161
inject(compiledCode, "injected-component", "manual-injection");
162
163
// Component is now registered and ready to mount
164
mount("injected-component");
165
```
166
167
## Enhanced Mounting with Slots
168
169
The compiler build provides enhanced versions of `mount` and `component` that automatically create slots from DOM content:
170
171
### Enhanced Mount
172
173
```typescript { .api }
174
/**
175
* Enhanced mounting function that creates slots from DOM content
176
* @param selector - CSS selector or HTMLElement to mount to
177
* @param initialProps - Initial component properties
178
* @param componentName - Optional component name
179
* @returns Array of component instances
180
*/
181
function mount<Props, State>(
182
selector: string | HTMLElement,
183
initialProps?: Props,
184
componentName?: string
185
): RiotComponent<Props, State>[];
186
```
187
188
**Usage Example:**
189
190
```html
191
<!-- Existing DOM content becomes slots -->
192
<my-card>
193
<div slot="header">Card Title</div>
194
<div slot="content">Card content goes here</div>
195
</my-card>
196
```
197
198
```javascript
199
import { mount } from "riot+compiler";
200
201
// DOM content is automatically converted to slots
202
const cards = mount("my-card", { theme: "dark" });
203
```
204
205
### Enhanced Component Factory
206
207
```typescript { .api }
208
/**
209
* Enhanced component factory with automatic slot creation
210
* @param wrapper - Component wrapper implementation
211
* @returns Enhanced factory function
212
*/
213
function component(wrapper: RiotComponentWrapper): (
214
el: HTMLElement,
215
props?: any,
216
meta?: ComponentMeta
217
) => RiotComponent;
218
```
219
220
## Compilation Options
221
222
```typescript { .api }
223
interface CompileOptions {
224
/** Generate compact output (minified) */
225
compact?: boolean;
226
227
/** Expression parser type */
228
expression?: "javascript" | "typescript";
229
230
/** File path for source maps and error reporting */
231
file?: string;
232
233
/** Custom preprocessors */
234
preprocessors?: {
235
[key: string]: PreprocessorFunction;
236
};
237
238
/** Template parser options */
239
template?: TemplateOptions;
240
241
/** CSS parser options */
242
css?: CSSOptions;
243
}
244
245
interface CompilationResult {
246
/** Compiled JavaScript code */
247
code: string;
248
249
/** Component metadata */
250
meta: {
251
tagName: string;
252
dependencies?: string[];
253
css?: boolean;
254
javascript?: boolean;
255
};
256
257
/** Source map (if enabled) */
258
map?: string;
259
}
260
```
261
262
## Advanced Compilation Patterns
263
264
### Dynamic Component Loading
265
266
```javascript
267
import { compileFromUrl, register, mount } from "riot+compiler";
268
269
class ComponentLoader {
270
constructor() {
271
this.cache = new Map();
272
}
273
274
async loadComponent(name, url) {
275
if (this.cache.has(name)) {
276
return this.cache.get(name);
277
}
278
279
try {
280
const result = await compileFromUrl(url);
281
const component = eval(result.code);
282
283
register(name, component);
284
this.cache.set(name, component);
285
286
return component;
287
} catch (error) {
288
console.error(`Failed to load component ${name}:`, error);
289
throw error;
290
}
291
}
292
293
async loadAndMount(name, url, selector, props) {
294
await this.loadComponent(name, url);
295
return mount(selector, props, name);
296
}
297
}
298
299
// Usage
300
const loader = new ComponentLoader();
301
await loader.loadAndMount(
302
"lazy-widget",
303
"/components/lazy-widget.riot",
304
".widget-container",
305
{ data: apiData }
306
);
307
```
308
309
### Template Preprocessing
310
311
```javascript
312
import { compileFromString } from "riot+compiler";
313
314
// Template with custom preprocessing
315
const preprocessTemplate = (template, context) => {
316
return template
317
.replace(/\{\{(\w+)\}\}/g, '{ $1 }') // Convert {{}} to {}
318
.replace(/\$\{(\w+)\}/g, '{ props.$1 }'); // Convert ${} to props
319
};
320
321
const rawTemplate = `
322
<preprocessed-component>
323
<h1>{{title}}</h1>
324
<p>Value: \${value}</p>
325
</preprocessed-component>
326
`;
327
328
const processedTemplate = preprocessTemplate(rawTemplate);
329
const result = compileFromString(processedTemplate);
330
```
331
332
## Types
333
334
```typescript { .api }
335
type CompileOptions = {
336
compact?: boolean;
337
expression?: "javascript" | "typescript";
338
file?: string;
339
preprocessors?: Record<string, PreprocessorFunction>;
340
template?: TemplateOptions;
341
css?: CSSOptions;
342
};
343
344
type CompilationResult = {
345
code: string;
346
meta: {
347
tagName: string;
348
dependencies?: string[];
349
css?: boolean;
350
javascript?: boolean;
351
};
352
map?: string;
353
};
354
355
type PreprocessorFunction = (
356
code: string,
357
options: any
358
) => { code: string; map?: string };
359
360
type TemplateOptions = {
361
brackets?: [string, string];
362
[key: string]: any;
363
};
364
365
type CSSOptions = {
366
parser?: string;
367
[key: string]: any;
368
};
369
```