miki-template 2.2.3 → 2.3.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/.github/workflows/docs.yml +3 -1
- package/.github/workflows/release.yml +0 -5
- package/benchmarks/ejs-results.json +6 -6
- package/benchmarks/ejs.js +5 -3
- package/benchmarks/handlebars-results.json +6 -6
- package/benchmarks/handlebars.js +5 -8
- package/benchmarks/miki-results.json +6 -6
- package/benchmarks/miki.js +6 -3
- package/benchmarks/pug-results.json +6 -6
- package/benchmarks/pug.js +5 -3
- package/docs/api/async-render.md +88 -3
- package/docs/api/cache.md +90 -3
- package/docs/api/compile.md +131 -3
- package/docs/api/context-processors.md +80 -3
- package/docs/api/filters.md +223 -3
- package/docs/api/finder.md +97 -3
- package/docs/api/helpers.md +56 -3
- package/docs/api/i18n.md +160 -3
- package/docs/api/index.md +82 -28
- package/docs/api/libraries.md +210 -3
- package/docs/api/render-partial.md +84 -3
- package/docs/api/render.md +95 -3
- package/docs/api/security.md +148 -3
- package/docs/api/setup-express.md +78 -2
- package/docs/api/tags.md +138 -4
- package/docs/filter.md +0 -0
- package/docs/guide/advanced-usage.md +403 -6
- package/docs/guide/async-rendering.md +312 -4
- package/docs/guide/context-processors.md +261 -4
- package/docs/guide/custom-filters.md +315 -4
- package/docs/guide/custom-tags.md +275 -4
- package/docs/guide/filters.md +675 -3
- package/docs/guide/getting-started.md +109 -7
- package/docs/guide/installation.md +99 -4
- package/docs/guide/partial-templates.md +371 -4
- package/docs/guide/quick-start.md +228 -6
- package/docs/guide/security.md +348 -3
- package/docs/guide/tags.md +789 -6
- package/docs/guide/template-discovery.md +174 -4
- package/docs/guide/template-inheritance.md +277 -4
- package/docs/index.md +24 -42
- package/docs/integrations/elysia.md +4 -2
- package/docs/integrations/express.md +219 -219
- package/docs/integrations/fastify.md +4 -2
- package/docs/integrations/hono.md +4 -2
- package/docs/integrations/index.md +68 -68
- package/docs/integrations/koa.md +4 -2
- package/docs/integrations/nestjs.md +4 -2
- package/docs/integrations/tsed.md +4 -2
- package/docs/performance.md +45 -8
- package/ex.mjs +1 -1
- package/mkdocs.yml +0 -22
- package/overrides/main.html +1 -1
- package/package.json +1 -1
- package/requirements-docs.txt +2 -1
- package/src/codegen.js +905 -0
- package/src/context.js +42 -30
- package/src/filters.js +16 -0
- package/src/index.js +66 -61
- package/src/tags/control.js +15 -12
- package/src/utils.js +60 -0
- package/tests/filters.test.js +9 -0
- package/docs/javascripts/extra.js +0 -174
- package/docs/stylesheets/extra.css +0 -819
- package/overrides/partials/footer.html +0 -9
|
@@ -1,397 +1,794 @@
|
|
|
1
|
-
# Advanced Usage
|
|
1
|
+
# Advanced Usage
|
|
2
|
+
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
This guide covers advanced miki-template features: caching, library system, i18n, and more.
|
|
4
6
|
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
## Table of Contents
|
|
6
10
|
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
- [Caching](#caching)
|
|
14
|
+
|
|
8
15
|
- [Library System](#library-system)
|
|
16
|
+
|
|
9
17
|
- [i18n / Internationalization](#i18n--internationalization)
|
|
18
|
+
|
|
10
19
|
- [Template Discovery](#template-discovery)
|
|
20
|
+
|
|
11
21
|
- [Partial Templates](#partial-templates)
|
|
22
|
+
|
|
12
23
|
- [Extending the Engine](#extending-the-engine)
|
|
13
24
|
|
|
25
|
+
|
|
26
|
+
|
|
14
27
|
---
|
|
15
28
|
|
|
29
|
+
|
|
30
|
+
|
|
16
31
|
## Caching
|
|
17
32
|
|
|
33
|
+
|
|
34
|
+
|
|
18
35
|
miki-template caches compiled templates for performance. The cache is an in-memory LRU with a 100-entry limit.
|
|
19
36
|
|
|
37
|
+
|
|
38
|
+
|
|
20
39
|
### Clearing the Cache
|
|
21
40
|
|
|
41
|
+
|
|
42
|
+
|
|
22
43
|
=== "CommonJS"
|
|
23
44
|
|
|
45
|
+
|
|
46
|
+
|
|
24
47
|
```javascript
|
|
48
|
+
|
|
25
49
|
const { clearCache } = require('miki-template');
|
|
26
50
|
|
|
51
|
+
|
|
52
|
+
|
|
27
53
|
clearCache();
|
|
54
|
+
|
|
28
55
|
```
|
|
29
56
|
|
|
57
|
+
|
|
58
|
+
|
|
30
59
|
=== "ES Modules"
|
|
31
60
|
|
|
61
|
+
|
|
62
|
+
|
|
32
63
|
```javascript
|
|
64
|
+
|
|
33
65
|
import { clearCache } from 'miki-template';
|
|
34
66
|
|
|
67
|
+
|
|
68
|
+
|
|
35
69
|
clearCache();
|
|
70
|
+
|
|
36
71
|
```
|
|
37
72
|
|
|
73
|
+
|
|
74
|
+
|
|
38
75
|
### When to Clear Cache
|
|
39
76
|
|
|
77
|
+
|
|
78
|
+
|
|
40
79
|
- **Development** — when templates change frequently on disk
|
|
80
|
+
|
|
41
81
|
- **Tests** — to ensure fresh compilation
|
|
82
|
+
|
|
42
83
|
- **Runtime filter/tag registration** — when dynamically registering custom tags/filters
|
|
43
84
|
|
|
85
|
+
|
|
86
|
+
|
|
44
87
|
```javascript
|
|
88
|
+
|
|
45
89
|
// Development middleware that clears cache on file changes
|
|
90
|
+
|
|
46
91
|
const { clearCache } = require('miki-template');
|
|
47
92
|
|
|
93
|
+
|
|
94
|
+
|
|
48
95
|
if (process.env.NODE_ENV !== 'production') {
|
|
96
|
+
|
|
49
97
|
fs.watch('./views', () => {
|
|
98
|
+
|
|
50
99
|
clearCache();
|
|
100
|
+
|
|
51
101
|
console.log('Template cache cleared');
|
|
102
|
+
|
|
52
103
|
});
|
|
104
|
+
|
|
53
105
|
}
|
|
106
|
+
|
|
54
107
|
```
|
|
55
108
|
|
|
109
|
+
|
|
110
|
+
|
|
56
111
|
### How Caching Works
|
|
57
112
|
|
|
113
|
+
|
|
114
|
+
|
|
58
115
|
- Templates are cached by source string and compile options.
|
|
116
|
+
|
|
59
117
|
- The cache key combines the template source and the options object (views, custom settings).
|
|
118
|
+
|
|
60
119
|
- Cached templates are reused across renders, improving performance for repeated templates.
|
|
61
120
|
|
|
121
|
+
|
|
122
|
+
|
|
62
123
|
## Library System
|
|
63
124
|
|
|
125
|
+
|
|
126
|
+
|
|
64
127
|
Libraries are bundles of filters, tags, and helpers that can be loaded into templates. Built-in libraries (humanize, cache, lorem, markdown, i18n) are auto-activated.
|
|
65
128
|
|
|
129
|
+
|
|
130
|
+
|
|
66
131
|
### Registering a Library
|
|
67
132
|
|
|
133
|
+
|
|
134
|
+
|
|
68
135
|
=== "CommonJS"
|
|
69
136
|
|
|
137
|
+
|
|
138
|
+
|
|
70
139
|
```javascript
|
|
140
|
+
|
|
71
141
|
const { registerLibrary } = require('miki-template');
|
|
72
142
|
|
|
143
|
+
|
|
144
|
+
|
|
73
145
|
registerLibrary('myutils', {
|
|
146
|
+
|
|
74
147
|
filters: {
|
|
148
|
+
|
|
75
149
|
shout: (val) => String(val).toUpperCase() + '!',
|
|
150
|
+
|
|
76
151
|
whisper: (val) => String(val).toLowerCase() + '...'
|
|
152
|
+
|
|
77
153
|
},
|
|
154
|
+
|
|
78
155
|
tags: {
|
|
156
|
+
|
|
79
157
|
timestamp: (tagContent, parser) => ({
|
|
158
|
+
|
|
80
159
|
render: () => new Date().toISOString()
|
|
160
|
+
|
|
81
161
|
})
|
|
162
|
+
|
|
82
163
|
},
|
|
164
|
+
|
|
83
165
|
helpers: {
|
|
166
|
+
|
|
84
167
|
formatPrice: (val) => `$${Number(val).toFixed(2)}`
|
|
168
|
+
|
|
85
169
|
}
|
|
170
|
+
|
|
86
171
|
});
|
|
172
|
+
|
|
87
173
|
```
|
|
88
174
|
|
|
175
|
+
|
|
176
|
+
|
|
89
177
|
=== "ES Modules"
|
|
90
178
|
|
|
179
|
+
|
|
180
|
+
|
|
91
181
|
```javascript
|
|
182
|
+
|
|
92
183
|
import { registerLibrary } from 'miki-template';
|
|
93
184
|
|
|
185
|
+
|
|
186
|
+
|
|
94
187
|
registerLibrary('myutils', {
|
|
188
|
+
|
|
95
189
|
filters: {
|
|
190
|
+
|
|
96
191
|
shout: (val) => String(val).toUpperCase() + '!',
|
|
192
|
+
|
|
97
193
|
whisper: (val) => String(val).toLowerCase() + '...'
|
|
194
|
+
|
|
98
195
|
},
|
|
196
|
+
|
|
99
197
|
tags: {
|
|
198
|
+
|
|
100
199
|
timestamp: (tagContent, parser) => ({
|
|
200
|
+
|
|
101
201
|
render: () => new Date().toISOString()
|
|
202
|
+
|
|
102
203
|
})
|
|
204
|
+
|
|
103
205
|
},
|
|
206
|
+
|
|
104
207
|
helpers: {
|
|
208
|
+
|
|
105
209
|
formatPrice: (val) => `$${Number(val).toFixed(2)}`
|
|
210
|
+
|
|
106
211
|
}
|
|
212
|
+
|
|
107
213
|
});
|
|
214
|
+
|
|
108
215
|
```
|
|
109
216
|
|
|
217
|
+
|
|
218
|
+
|
|
110
219
|
### Loading Libraries in Templates
|
|
111
220
|
|
|
221
|
+
|
|
222
|
+
|
|
112
223
|
Once registered, load the library with `{% load %}`:
|
|
113
224
|
|
|
225
|
+
|
|
226
|
+
|
|
114
227
|
```html
|
|
228
|
+
|
|
115
229
|
{% load myutils %}
|
|
116
230
|
|
|
231
|
+
|
|
232
|
+
|
|
117
233
|
{{ price|formatPrice }}
|
|
234
|
+
|
|
118
235
|
{{ message|shout }}
|
|
236
|
+
|
|
119
237
|
{% timestamp %}
|
|
238
|
+
|
|
120
239
|
```
|
|
121
240
|
|
|
241
|
+
|
|
242
|
+
|
|
122
243
|
### Built-in Libraries
|
|
123
244
|
|
|
245
|
+
|
|
246
|
+
|
|
124
247
|
The following libraries are auto-activated (no `{% load %}` needed):
|
|
125
248
|
|
|
249
|
+
|
|
250
|
+
|
|
126
251
|
| Library | Features |
|
|
252
|
+
|
|
127
253
|
|---------|----------|
|
|
254
|
+
|
|
128
255
|
| `humanize` | Natural date formatting, number formatting |
|
|
256
|
+
|
|
129
257
|
| `cache` | Cache control tags and filters |
|
|
258
|
+
|
|
130
259
|
| `lorem` | Lorem ipsum placeholder text |
|
|
260
|
+
|
|
131
261
|
| `markdown` | `{{ content|markdown }}` filter for Markdown→HTML |
|
|
262
|
+
|
|
132
263
|
| `i18n` | `{% trans %}` and `{% blocktrans %}` for translations |
|
|
133
264
|
|
|
265
|
+
|
|
266
|
+
|
|
134
267
|
### Deactivating and Re-registering
|
|
135
268
|
|
|
269
|
+
|
|
270
|
+
|
|
136
271
|
=== "CommonJS"
|
|
137
272
|
|
|
273
|
+
|
|
274
|
+
|
|
138
275
|
```javascript
|
|
276
|
+
|
|
139
277
|
const { unregisterLibrary, activateLibrary } = require('miki-template');
|
|
140
278
|
|
|
279
|
+
|
|
280
|
+
|
|
141
281
|
// Remove a library
|
|
282
|
+
|
|
142
283
|
unregisterLibrary('lorem');
|
|
143
284
|
|
|
285
|
+
|
|
286
|
+
|
|
144
287
|
// Re-activate
|
|
288
|
+
|
|
145
289
|
activateLibrary('lorem');
|
|
290
|
+
|
|
146
291
|
```
|
|
147
292
|
|
|
293
|
+
|
|
294
|
+
|
|
148
295
|
=== "ES Modules"
|
|
149
296
|
|
|
297
|
+
|
|
298
|
+
|
|
150
299
|
```javascript
|
|
300
|
+
|
|
151
301
|
import { unregisterLibrary, activateLibrary } from 'miki-template';
|
|
152
302
|
|
|
303
|
+
|
|
304
|
+
|
|
153
305
|
unregisterLibrary('lorem');
|
|
306
|
+
|
|
154
307
|
activateLibrary('lorem');
|
|
308
|
+
|
|
155
309
|
```
|
|
156
310
|
|
|
311
|
+
|
|
312
|
+
|
|
157
313
|
## i18n / Internationalization
|
|
158
314
|
|
|
315
|
+
|
|
316
|
+
|
|
159
317
|
miki-template includes a built-in i18n system supporting `{% trans %}` and `{% blocktrans %}` tags.
|
|
160
318
|
|
|
319
|
+
|
|
320
|
+
|
|
161
321
|
### Registering Translations
|
|
162
322
|
|
|
323
|
+
|
|
324
|
+
|
|
163
325
|
=== "CommonJS"
|
|
164
326
|
|
|
327
|
+
|
|
328
|
+
|
|
165
329
|
```javascript
|
|
330
|
+
|
|
166
331
|
const miki = require('miki-template');
|
|
167
332
|
|
|
333
|
+
|
|
334
|
+
|
|
168
335
|
miki.setLanguage('fr');
|
|
336
|
+
|
|
169
337
|
miki.registerTranslation('fr', {
|
|
338
|
+
|
|
170
339
|
'Hello': 'Bonjour',
|
|
340
|
+
|
|
171
341
|
'Goodbye': 'Au revoir',
|
|
342
|
+
|
|
172
343
|
'Welcome, {name}!': 'Bienvenue, {name} !'
|
|
344
|
+
|
|
173
345
|
});
|
|
346
|
+
|
|
174
347
|
```
|
|
175
348
|
|
|
349
|
+
|
|
350
|
+
|
|
176
351
|
=== "ES Modules"
|
|
177
352
|
|
|
353
|
+
|
|
354
|
+
|
|
178
355
|
```javascript
|
|
356
|
+
|
|
179
357
|
import { setLanguage, registerTranslation } from 'miki-template';
|
|
180
358
|
|
|
359
|
+
|
|
360
|
+
|
|
181
361
|
setLanguage('fr');
|
|
362
|
+
|
|
182
363
|
registerTranslation('fr', {
|
|
364
|
+
|
|
183
365
|
'Hello': 'Bonjour',
|
|
366
|
+
|
|
184
367
|
'Goodbye': 'Au revoir',
|
|
368
|
+
|
|
185
369
|
'Welcome, {name}!': 'Bienvenue, {name} !'
|
|
370
|
+
|
|
186
371
|
});
|
|
372
|
+
|
|
187
373
|
```
|
|
188
374
|
|
|
375
|
+
|
|
376
|
+
|
|
189
377
|
### Setting Fallback Language
|
|
190
378
|
|
|
379
|
+
|
|
380
|
+
|
|
191
381
|
=== "CommonJS"
|
|
192
382
|
|
|
383
|
+
|
|
384
|
+
|
|
193
385
|
```javascript
|
|
386
|
+
|
|
194
387
|
const { setLanguage, setFallbackLanguage } = require('miki-template');
|
|
195
388
|
|
|
389
|
+
|
|
390
|
+
|
|
196
391
|
setLanguage('fr');
|
|
392
|
+
|
|
197
393
|
setFallbackLanguage('en');
|
|
394
|
+
|
|
198
395
|
```
|
|
199
396
|
|
|
397
|
+
|
|
398
|
+
|
|
200
399
|
=== "ES Modules"
|
|
201
400
|
|
|
401
|
+
|
|
402
|
+
|
|
202
403
|
```javascript
|
|
404
|
+
|
|
203
405
|
import { setLanguage, setFallbackLanguage } from 'miki-template';
|
|
204
406
|
|
|
407
|
+
|
|
408
|
+
|
|
205
409
|
setLanguage('fr');
|
|
410
|
+
|
|
206
411
|
setFallbackLanguage('en');
|
|
412
|
+
|
|
207
413
|
```
|
|
208
414
|
|
|
415
|
+
|
|
416
|
+
|
|
209
417
|
### Template Usage
|
|
210
418
|
|
|
419
|
+
|
|
420
|
+
|
|
211
421
|
```html
|
|
422
|
+
|
|
212
423
|
{% trans "Hello" %}
|
|
424
|
+
|
|
213
425
|
{% blocktrans %}Welcome, {{ name }}!{% endblocktrans %}
|
|
426
|
+
|
|
214
427
|
```
|
|
215
428
|
|
|
429
|
+
|
|
430
|
+
|
|
216
431
|
### Managing Languages
|
|
217
432
|
|
|
433
|
+
|
|
434
|
+
|
|
218
435
|
=== "CommonJS"
|
|
219
436
|
|
|
437
|
+
|
|
438
|
+
|
|
220
439
|
```javascript
|
|
440
|
+
|
|
221
441
|
const {
|
|
442
|
+
|
|
222
443
|
registerTranslation,
|
|
444
|
+
|
|
223
445
|
unregisterTranslation,
|
|
446
|
+
|
|
224
447
|
setLanguage,
|
|
448
|
+
|
|
225
449
|
getLanguage,
|
|
450
|
+
|
|
226
451
|
setFallbackLanguage,
|
|
452
|
+
|
|
227
453
|
getFallbackLanguage,
|
|
454
|
+
|
|
228
455
|
getAvailableLanguages
|
|
456
|
+
|
|
229
457
|
} = require('miki-template');
|
|
458
|
+
|
|
230
459
|
```
|
|
231
460
|
|
|
461
|
+
|
|
462
|
+
|
|
232
463
|
=== "ES Modules"
|
|
233
464
|
|
|
465
|
+
|
|
466
|
+
|
|
234
467
|
```javascript
|
|
468
|
+
|
|
235
469
|
import {
|
|
470
|
+
|
|
236
471
|
registerTranslation,
|
|
472
|
+
|
|
237
473
|
unregisterTranslation,
|
|
474
|
+
|
|
238
475
|
setLanguage,
|
|
476
|
+
|
|
239
477
|
getLanguage,
|
|
478
|
+
|
|
240
479
|
setFallbackLanguage,
|
|
480
|
+
|
|
241
481
|
getFallbackLanguage,
|
|
482
|
+
|
|
242
483
|
getAvailableLanguages
|
|
484
|
+
|
|
243
485
|
} from 'miki-template';
|
|
486
|
+
|
|
244
487
|
```
|
|
245
488
|
|
|
489
|
+
|
|
490
|
+
|
|
246
491
|
## Template Discovery
|
|
247
492
|
|
|
493
|
+
|
|
494
|
+
|
|
248
495
|
The `findTemplateInViews()` function intelligently locates templates in nested directories.
|
|
249
496
|
|
|
497
|
+
|
|
498
|
+
|
|
250
499
|
=== "CommonJS"
|
|
251
500
|
|
|
501
|
+
|
|
502
|
+
|
|
252
503
|
```javascript
|
|
504
|
+
|
|
253
505
|
const { findTemplateInViews, setAppTemplateDirNames } = require('miki-template');
|
|
254
506
|
|
|
507
|
+
|
|
508
|
+
|
|
255
509
|
// Customize which directory names are treated as app template roots
|
|
510
|
+
|
|
256
511
|
setAppTemplateDirNames(['templates', 'views', 'pages']);
|
|
257
512
|
|
|
513
|
+
|
|
514
|
+
|
|
258
515
|
// Search for a template by name
|
|
516
|
+
|
|
259
517
|
const found = findTemplateInViews('home', ['./views', './app/templates']);
|
|
518
|
+
|
|
260
519
|
console.log(found);
|
|
520
|
+
|
|
261
521
|
// → /absolute/path/to/app/templates/home.html
|
|
522
|
+
|
|
262
523
|
```
|
|
263
524
|
|
|
525
|
+
|
|
526
|
+
|
|
264
527
|
=== "ES Modules"
|
|
265
528
|
|
|
529
|
+
|
|
530
|
+
|
|
266
531
|
```javascript
|
|
532
|
+
|
|
267
533
|
import { findTemplateInViews, setAppTemplateDirNames } from 'miki-template';
|
|
268
534
|
|
|
535
|
+
|
|
536
|
+
|
|
269
537
|
setAppTemplateDirNames(['templates', 'views', 'pages']);
|
|
538
|
+
|
|
270
539
|
const found = findTemplateInViews('home', ['./views', './app/templates']);
|
|
540
|
+
|
|
271
541
|
console.log(found);
|
|
542
|
+
|
|
272
543
|
```
|
|
273
544
|
|
|
545
|
+
|
|
546
|
+
|
|
274
547
|
## Partial Templates
|
|
275
548
|
|
|
549
|
+
|
|
550
|
+
|
|
276
551
|
Partials let you define reusable template fragments using `{% partialdef %}` and render them on demand.
|
|
277
552
|
|
|
553
|
+
|
|
554
|
+
|
|
278
555
|
### Defining and Rendering Partials
|
|
279
556
|
|
|
557
|
+
|
|
558
|
+
|
|
280
559
|
```html
|
|
560
|
+
|
|
281
561
|
{% partialdef card %}
|
|
562
|
+
|
|
282
563
|
<div class="card">
|
|
564
|
+
|
|
283
565
|
<h3>{{ user.name }}</h3>
|
|
566
|
+
|
|
284
567
|
<p>{{ user.email }}</p>
|
|
568
|
+
|
|
285
569
|
</div>
|
|
570
|
+
|
|
286
571
|
{% endpartialdef %}
|
|
572
|
+
|
|
287
573
|
```
|
|
288
574
|
|
|
575
|
+
|
|
576
|
+
|
|
289
577
|
Render a partial:
|
|
290
578
|
|
|
579
|
+
|
|
580
|
+
|
|
291
581
|
=== "CommonJS"
|
|
292
582
|
|
|
583
|
+
|
|
584
|
+
|
|
293
585
|
```javascript
|
|
586
|
+
|
|
294
587
|
const { render, compile } = require('miki-template');
|
|
295
588
|
|
|
589
|
+
|
|
590
|
+
|
|
296
591
|
// Using render() with file partials:
|
|
592
|
+
|
|
297
593
|
const html = render('home#card', { user: userData }, { views: './views' });
|
|
298
594
|
|
|
595
|
+
|
|
596
|
+
|
|
299
597
|
// Using compiled.renderPartial():
|
|
598
|
+
|
|
300
599
|
const compiled = compile(templateString);
|
|
600
|
+
|
|
301
601
|
const partialHtml = compiled.renderPartial('card', { user: userData });
|
|
602
|
+
|
|
302
603
|
```
|
|
303
604
|
|
|
605
|
+
|
|
606
|
+
|
|
304
607
|
=== "ES Modules"
|
|
305
608
|
|
|
609
|
+
|
|
610
|
+
|
|
306
611
|
```javascript
|
|
612
|
+
|
|
307
613
|
import { render, compile } from 'miki-template';
|
|
308
614
|
|
|
615
|
+
|
|
616
|
+
|
|
309
617
|
const html = render('home#card', { user: userData }, { views: './views' });
|
|
310
618
|
|
|
619
|
+
|
|
620
|
+
|
|
311
621
|
const compiled = compile(templateString);
|
|
622
|
+
|
|
312
623
|
const partialHtml = compiled.renderPartial('card', { user: userData });
|
|
624
|
+
|
|
313
625
|
```
|
|
314
626
|
|
|
627
|
+
|
|
628
|
+
|
|
315
629
|
### Partial with Context
|
|
316
630
|
|
|
631
|
+
|
|
632
|
+
|
|
317
633
|
```html
|
|
634
|
+
|
|
318
635
|
{% partialdef greeting %}
|
|
636
|
+
|
|
319
637
|
Hello, {{ name }}! You have {{ count }} messages.
|
|
638
|
+
|
|
320
639
|
{% endpartialdef %}
|
|
321
640
|
|
|
641
|
+
|
|
642
|
+
|
|
322
643
|
{% partial greeting with name="Alice" count=3 %}
|
|
644
|
+
|
|
323
645
|
```
|
|
324
646
|
|
|
647
|
+
|
|
648
|
+
|
|
325
649
|
## Extending the Engine
|
|
326
650
|
|
|
651
|
+
|
|
652
|
+
|
|
327
653
|
### Registering Custom Tags
|
|
328
654
|
|
|
655
|
+
|
|
656
|
+
|
|
329
657
|
=== "CommonJS"
|
|
330
658
|
|
|
659
|
+
|
|
660
|
+
|
|
331
661
|
```javascript
|
|
662
|
+
|
|
332
663
|
const { registerTag } = require('miki-template');
|
|
333
664
|
|
|
665
|
+
|
|
666
|
+
|
|
334
667
|
registerTag('markdown', (tagContent, parser) => {
|
|
668
|
+
|
|
335
669
|
const nodelist = parser.parse(['endmarkdown']);
|
|
670
|
+
|
|
336
671
|
parser.skipTag();
|
|
672
|
+
|
|
337
673
|
const { marked } = require('marked');
|
|
338
674
|
|
|
675
|
+
|
|
676
|
+
|
|
339
677
|
return {
|
|
678
|
+
|
|
340
679
|
render: (context) => {
|
|
680
|
+
|
|
341
681
|
const body = nodelist.map(n => n.render(context)).join('');
|
|
682
|
+
|
|
342
683
|
return markSafe(marked(body));
|
|
684
|
+
|
|
343
685
|
}
|
|
686
|
+
|
|
344
687
|
};
|
|
688
|
+
|
|
345
689
|
});
|
|
690
|
+
|
|
346
691
|
```
|
|
347
692
|
|
|
693
|
+
|
|
694
|
+
|
|
348
695
|
=== "ES Modules"
|
|
349
696
|
|
|
697
|
+
|
|
698
|
+
|
|
350
699
|
```javascript
|
|
700
|
+
|
|
351
701
|
import { registerTag, markSafe } from 'miki-template';
|
|
702
|
+
|
|
352
703
|
import { marked } from 'marked';
|
|
353
704
|
|
|
705
|
+
|
|
706
|
+
|
|
354
707
|
registerTag('markdown', (tagContent, parser) => {
|
|
708
|
+
|
|
355
709
|
const nodelist = parser.parse(['endmarkdown']);
|
|
710
|
+
|
|
356
711
|
parser.skipTag();
|
|
357
712
|
|
|
713
|
+
|
|
714
|
+
|
|
358
715
|
return {
|
|
716
|
+
|
|
359
717
|
render: (context) => {
|
|
718
|
+
|
|
360
719
|
const body = nodelist.map(n => n.render(context)).join('');
|
|
720
|
+
|
|
361
721
|
return markSafe(marked(body));
|
|
722
|
+
|
|
362
723
|
}
|
|
724
|
+
|
|
363
725
|
};
|
|
726
|
+
|
|
364
727
|
});
|
|
728
|
+
|
|
365
729
|
```
|
|
366
730
|
|
|
731
|
+
|
|
732
|
+
|
|
367
733
|
### Registering Custom Helpers
|
|
368
734
|
|
|
735
|
+
|
|
736
|
+
|
|
369
737
|
=== "CommonJS"
|
|
370
738
|
|
|
739
|
+
|
|
740
|
+
|
|
371
741
|
```javascript
|
|
742
|
+
|
|
372
743
|
const { registerHelper } = require('miki-template');
|
|
373
744
|
|
|
745
|
+
|
|
746
|
+
|
|
374
747
|
registerHelper('truncate_words', (str, count) => {
|
|
748
|
+
|
|
375
749
|
const words = String(str).split(/\s+/);
|
|
750
|
+
|
|
376
751
|
return words.slice(0, count).join(' ') + (words.length > count ? '...' : '');
|
|
752
|
+
|
|
377
753
|
});
|
|
754
|
+
|
|
378
755
|
```
|
|
379
756
|
|
|
757
|
+
|
|
758
|
+
|
|
380
759
|
=== "ES Modules"
|
|
381
760
|
|
|
761
|
+
|
|
762
|
+
|
|
382
763
|
```javascript
|
|
764
|
+
|
|
383
765
|
import { registerHelper } from 'miki-template';
|
|
384
766
|
|
|
767
|
+
|
|
768
|
+
|
|
385
769
|
registerHelper('truncate_words', (str, count) => {
|
|
770
|
+
|
|
386
771
|
const words = String(str).split(/\s+/);
|
|
772
|
+
|
|
387
773
|
return words.slice(0, count).join(' ') + (words.length > count ? '...' : '');
|
|
774
|
+
|
|
388
775
|
});
|
|
776
|
+
|
|
389
777
|
```
|
|
390
778
|
|
|
779
|
+
|
|
780
|
+
|
|
391
781
|
## Next Steps
|
|
392
782
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
- [
|
|
396
|
-
|
|
397
|
-
- [
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
- [Custom Tags](./custom-tags.md)
|
|
786
|
+
|
|
787
|
+
- [Custom Filters](./custom-filters.md)
|
|
788
|
+
|
|
789
|
+
- [API Reference: Libraries](../api/libraries.md)
|
|
790
|
+
|
|
791
|
+
- [API Reference: Cache](../api/cache.md)
|
|
792
|
+
|
|
793
|
+
- [API Reference: i18n](../api/i18n.md)
|
|
794
|
+
|