miki-template 2.2.3 → 2.3.1
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/README.md +17 -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,273 +1,546 @@
|
|
|
1
|
-
# Template Inheritance
|
|
1
|
+
# Template Inheritance
|
|
2
|
+
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
miki-template supports Django-style template inheritance via `{% extends %}` and `{% block %}`. This lets you build layout hierarchies where child templates override parent blocks.
|
|
4
6
|
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
## Table of Contents
|
|
6
10
|
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
- [Basic Inheritance](#basic-inheritance)
|
|
14
|
+
|
|
8
15
|
- [block.super](#blocksuper)
|
|
16
|
+
|
|
9
17
|
- [Multi-Level Inheritance](#multi-level-inheritance)
|
|
18
|
+
|
|
10
19
|
- [Rendering a Single Block](#rendering-a-single-block)
|
|
20
|
+
|
|
11
21
|
- [block Default Behavior](#block-default-behavior)
|
|
22
|
+
|
|
12
23
|
- [Path Traversal Protection](#path-traversal-protection)
|
|
24
|
+
|
|
13
25
|
- [Smart Template Discovery for Inheritance](#smart-template-discovery-for-inheritance)
|
|
14
26
|
|
|
27
|
+
|
|
28
|
+
|
|
15
29
|
---
|
|
16
30
|
|
|
31
|
+
|
|
32
|
+
|
|
17
33
|
## Basic Inheritance
|
|
18
34
|
|
|
35
|
+
|
|
36
|
+
|
|
19
37
|
### base.html
|
|
20
38
|
|
|
39
|
+
|
|
40
|
+
|
|
21
41
|
```html
|
|
42
|
+
|
|
22
43
|
<!DOCTYPE html>
|
|
44
|
+
|
|
23
45
|
<html>
|
|
46
|
+
|
|
24
47
|
<head>
|
|
48
|
+
|
|
25
49
|
<title>{% block title %}Default Title{% endblock %}</title>
|
|
50
|
+
|
|
26
51
|
</head>
|
|
52
|
+
|
|
27
53
|
<body>
|
|
54
|
+
|
|
28
55
|
<header>{% block header %}Default Header{% endblock %}</header>
|
|
56
|
+
|
|
29
57
|
<main>{% block content %}Default Content{% endblock %}</main>
|
|
58
|
+
|
|
30
59
|
<footer>{% block footer %}Default Footer{% endblock %}</footer>
|
|
60
|
+
|
|
31
61
|
</body>
|
|
62
|
+
|
|
32
63
|
</html>
|
|
64
|
+
|
|
33
65
|
```
|
|
34
66
|
|
|
67
|
+
|
|
68
|
+
|
|
35
69
|
### child.html
|
|
36
70
|
|
|
71
|
+
|
|
72
|
+
|
|
37
73
|
```html
|
|
74
|
+
|
|
38
75
|
{% extends "base.html" %}
|
|
39
76
|
|
|
77
|
+
|
|
78
|
+
|
|
40
79
|
{% block title %}My Page{% endblock %}
|
|
41
80
|
|
|
81
|
+
|
|
82
|
+
|
|
42
83
|
{% block content %}
|
|
84
|
+
|
|
43
85
|
<h1>Hello, {{ user.name }}!</h1>
|
|
86
|
+
|
|
44
87
|
{% for item in items %}
|
|
88
|
+
|
|
45
89
|
<p>{{ item }}</p>
|
|
90
|
+
|
|
46
91
|
{% endfor %}
|
|
92
|
+
|
|
47
93
|
{% endblock %}
|
|
94
|
+
|
|
48
95
|
```
|
|
49
96
|
|
|
97
|
+
|
|
98
|
+
|
|
50
99
|
**Key behaviors:**
|
|
51
100
|
|
|
101
|
+
|
|
102
|
+
|
|
52
103
|
- The child template's text outside `{% block %}` tags is **ignored** — only the blocks are used to override the parent.
|
|
104
|
+
|
|
53
105
|
- Any blocks not overridden in the child use the parent's default content.
|
|
106
|
+
|
|
54
107
|
- The parent is located using the `views` option (or Express's `views` directory).
|
|
55
108
|
|
|
109
|
+
|
|
110
|
+
|
|
56
111
|
## block.super
|
|
57
112
|
|
|
113
|
+
|
|
114
|
+
|
|
58
115
|
Inside a block, `{{ block.super }}` renders the parent template's version of that block. This is useful for augmentation rather than replacement.
|
|
59
116
|
|
|
117
|
+
|
|
118
|
+
|
|
60
119
|
=== "Example"
|
|
61
120
|
|
|
121
|
+
|
|
122
|
+
|
|
62
123
|
```html
|
|
124
|
+
|
|
63
125
|
{% extends "base.html" %}
|
|
64
126
|
|
|
127
|
+
|
|
128
|
+
|
|
65
129
|
{% block content %}
|
|
130
|
+
|
|
66
131
|
<h1>My Content</h1>
|
|
132
|
+
|
|
67
133
|
{{ block.super }}
|
|
134
|
+
|
|
68
135
|
{% endblock %}
|
|
136
|
+
|
|
69
137
|
```
|
|
70
138
|
|
|
139
|
+
|
|
140
|
+
|
|
71
141
|
If `base.html`'s content block is `<p>Original</p>`, the output is:
|
|
72
142
|
|
|
143
|
+
|
|
144
|
+
|
|
73
145
|
```html
|
|
146
|
+
|
|
74
147
|
<h1>My Content</h1>
|
|
148
|
+
|
|
75
149
|
<p>Original</p>
|
|
150
|
+
|
|
76
151
|
```
|
|
77
152
|
|
|
153
|
+
|
|
154
|
+
|
|
78
155
|
**Real-world sidebar that adds to the parent:**
|
|
79
156
|
|
|
157
|
+
|
|
158
|
+
|
|
80
159
|
```html
|
|
160
|
+
|
|
81
161
|
<!-- base.html -->
|
|
162
|
+
|
|
82
163
|
{% block sidebar %}
|
|
164
|
+
|
|
83
165
|
<ul class="nav">
|
|
166
|
+
|
|
84
167
|
<li><a href="/">Home</a></li>
|
|
168
|
+
|
|
85
169
|
</ul>
|
|
170
|
+
|
|
86
171
|
{% endblock %}
|
|
87
172
|
|
|
173
|
+
|
|
174
|
+
|
|
88
175
|
<!-- admin.html -->
|
|
176
|
+
|
|
89
177
|
{% extends "base.html" %}
|
|
178
|
+
|
|
90
179
|
{% block sidebar %}
|
|
180
|
+
|
|
91
181
|
{{ block.super }}
|
|
182
|
+
|
|
92
183
|
<li><a href="/admin">Admin Panel</a></li>
|
|
184
|
+
|
|
93
185
|
{% endblock %}
|
|
186
|
+
|
|
94
187
|
```
|
|
95
188
|
|
|
189
|
+
|
|
190
|
+
|
|
96
191
|
## Multi-Level Inheritance
|
|
97
192
|
|
|
193
|
+
|
|
194
|
+
|
|
98
195
|
Inheritance chains can be arbitrarily deep:
|
|
99
196
|
|
|
197
|
+
|
|
198
|
+
|
|
100
199
|
```text
|
|
200
|
+
|
|
101
201
|
base.html
|
|
202
|
+
|
|
102
203
|
└── child.html
|
|
204
|
+
|
|
103
205
|
└── grandchild.html
|
|
206
|
+
|
|
104
207
|
```
|
|
105
208
|
|
|
209
|
+
|
|
210
|
+
|
|
106
211
|
Each level can override blocks from its parent, and `{{ block.super }}` traverses the chain correctly.
|
|
107
212
|
|
|
213
|
+
|
|
214
|
+
|
|
108
215
|
### Three-level example
|
|
109
216
|
|
|
217
|
+
|
|
218
|
+
|
|
110
219
|
**base.html:**
|
|
111
220
|
|
|
221
|
+
|
|
222
|
+
|
|
112
223
|
```html
|
|
224
|
+
|
|
113
225
|
<html>
|
|
226
|
+
|
|
114
227
|
<body>
|
|
228
|
+
|
|
115
229
|
{% block content %}Base content{% endblock %}
|
|
230
|
+
|
|
116
231
|
</body>
|
|
232
|
+
|
|
117
233
|
</html>
|
|
234
|
+
|
|
118
235
|
```
|
|
119
236
|
|
|
237
|
+
|
|
238
|
+
|
|
120
239
|
**child.html:**
|
|
121
240
|
|
|
241
|
+
|
|
242
|
+
|
|
122
243
|
```html
|
|
244
|
+
|
|
123
245
|
{% extends "base.html" %}
|
|
124
246
|
|
|
247
|
+
|
|
248
|
+
|
|
125
249
|
{% block content %}
|
|
250
|
+
|
|
126
251
|
<h2>Child content</h2>
|
|
252
|
+
|
|
127
253
|
{{ block.super }}
|
|
254
|
+
|
|
128
255
|
{% endblock %}
|
|
256
|
+
|
|
129
257
|
```
|
|
130
258
|
|
|
259
|
+
|
|
260
|
+
|
|
131
261
|
**grandchild.html:**
|
|
132
262
|
|
|
263
|
+
|
|
264
|
+
|
|
133
265
|
```html
|
|
266
|
+
|
|
134
267
|
{% extends "child.html" %}
|
|
135
268
|
|
|
269
|
+
|
|
270
|
+
|
|
136
271
|
{% block content %}
|
|
272
|
+
|
|
137
273
|
<h1>Grandchild content</h1>
|
|
274
|
+
|
|
138
275
|
{{ block.super }}
|
|
276
|
+
|
|
139
277
|
{% endblock %}
|
|
278
|
+
|
|
140
279
|
```
|
|
141
280
|
|
|
281
|
+
|
|
282
|
+
|
|
142
283
|
Rendering `grandchild.html` produces:
|
|
143
284
|
|
|
285
|
+
|
|
286
|
+
|
|
144
287
|
```html
|
|
288
|
+
|
|
145
289
|
<html>
|
|
290
|
+
|
|
146
291
|
<body>
|
|
292
|
+
|
|
147
293
|
<h1>Grandchild content</h1>
|
|
294
|
+
|
|
148
295
|
<h2>Child content</h2>
|
|
296
|
+
|
|
149
297
|
Base content
|
|
298
|
+
|
|
150
299
|
</body>
|
|
300
|
+
|
|
151
301
|
</html>
|
|
302
|
+
|
|
152
303
|
```
|
|
153
304
|
|
|
305
|
+
|
|
306
|
+
|
|
154
307
|
## Rendering a Single Block
|
|
155
308
|
|
|
309
|
+
|
|
310
|
+
|
|
156
311
|
Compile a template and render only one block — useful for AJAX or HTMX responses where you only need a portion of the page:
|
|
157
312
|
|
|
313
|
+
|
|
314
|
+
|
|
158
315
|
=== "CommonJS"
|
|
159
316
|
|
|
317
|
+
|
|
318
|
+
|
|
160
319
|
```javascript
|
|
320
|
+
|
|
161
321
|
const { compile } = require('miki-template');
|
|
162
322
|
|
|
323
|
+
|
|
324
|
+
|
|
163
325
|
const compiled = compile(childTemplateStr, { views: './templates' });
|
|
326
|
+
|
|
164
327
|
const partialHtml = compiled.renderBlock('content', context);
|
|
328
|
+
|
|
165
329
|
```
|
|
166
330
|
|
|
331
|
+
|
|
332
|
+
|
|
167
333
|
=== "ES Modules"
|
|
168
334
|
|
|
335
|
+
|
|
336
|
+
|
|
169
337
|
```javascript
|
|
338
|
+
|
|
170
339
|
import { compile } from 'miki-template';
|
|
171
340
|
|
|
341
|
+
|
|
342
|
+
|
|
172
343
|
const compiled = compile(childTemplateStr, { views: './templates' });
|
|
344
|
+
|
|
173
345
|
const partialHtml = compiled.renderBlock('content', context);
|
|
346
|
+
|
|
174
347
|
```
|
|
175
348
|
|
|
349
|
+
|
|
350
|
+
|
|
176
351
|
### renderBlock behavior
|
|
177
352
|
|
|
353
|
+
|
|
354
|
+
|
|
178
355
|
- If the block is not found, throws `Block 'blockName' not found in template`.
|
|
356
|
+
|
|
179
357
|
- If the block has no overrides, renders the default body.
|
|
358
|
+
|
|
180
359
|
- If the block has overrides, renders the child-most block first, then traverses up for `{{ block.super }}`.
|
|
181
360
|
|
|
361
|
+
|
|
362
|
+
|
|
182
363
|
**Real-world HTMX use case:**
|
|
183
364
|
|
|
365
|
+
|
|
366
|
+
|
|
184
367
|
```html
|
|
368
|
+
|
|
185
369
|
<!-- layout.html -->
|
|
370
|
+
|
|
186
371
|
{% block main %}
|
|
372
|
+
|
|
187
373
|
<div id="main-content">
|
|
374
|
+
|
|
188
375
|
<!-- default content -->
|
|
376
|
+
|
|
189
377
|
</div>
|
|
378
|
+
|
|
190
379
|
{% endblock %}
|
|
380
|
+
|
|
191
381
|
```
|
|
192
382
|
|
|
383
|
+
|
|
384
|
+
|
|
193
385
|
```javascript
|
|
386
|
+
|
|
194
387
|
// Return only the main block for an AJAX update
|
|
388
|
+
|
|
195
389
|
app.get('/ajax/content', (req, res) => {
|
|
390
|
+
|
|
196
391
|
const compiled = miki.compile(template, { views: './views' });
|
|
392
|
+
|
|
197
393
|
res.send(compiled.renderBlock('main', { user: req.user }));
|
|
394
|
+
|
|
198
395
|
});
|
|
396
|
+
|
|
199
397
|
```
|
|
200
398
|
|
|
399
|
+
|
|
400
|
+
|
|
201
401
|
## block Default Behavior
|
|
202
402
|
|
|
403
|
+
|
|
404
|
+
|
|
203
405
|
If a child template does not override a block, the parent's default content is rendered:
|
|
204
406
|
|
|
407
|
+
|
|
408
|
+
|
|
205
409
|
```html
|
|
410
|
+
|
|
206
411
|
<!-- base.html -->
|
|
412
|
+
|
|
207
413
|
<html>
|
|
414
|
+
|
|
208
415
|
<body>
|
|
416
|
+
|
|
209
417
|
{% block sidebar %}Default sidebar{% endblock %}
|
|
418
|
+
|
|
210
419
|
</body>
|
|
420
|
+
|
|
211
421
|
</html>
|
|
422
|
+
|
|
212
423
|
```
|
|
213
424
|
|
|
425
|
+
|
|
426
|
+
|
|
214
427
|
```html
|
|
428
|
+
|
|
215
429
|
<!-- child.html -->
|
|
430
|
+
|
|
216
431
|
{% extends "base.html" %}
|
|
217
432
|
|
|
433
|
+
|
|
434
|
+
|
|
218
435
|
{% block content %}Main content{% endblock %}
|
|
436
|
+
|
|
219
437
|
<!-- sidebar block is not overridden, so "Default sidebar" is used -->
|
|
438
|
+
|
|
220
439
|
```
|
|
221
440
|
|
|
441
|
+
|
|
442
|
+
|
|
222
443
|
## Dynamic extends
|
|
223
444
|
|
|
445
|
+
|
|
446
|
+
|
|
224
447
|
You can use expressions in `extends` for device-specific or conditional layouts:
|
|
225
448
|
|
|
449
|
+
|
|
450
|
+
|
|
226
451
|
```html
|
|
452
|
+
|
|
227
453
|
{% extends device_type|default:"base.html" %}
|
|
454
|
+
|
|
228
455
|
```
|
|
229
456
|
|
|
457
|
+
|
|
458
|
+
|
|
230
459
|
```html
|
|
460
|
+
|
|
231
461
|
{% extends user.theme|default:"default.html" %}
|
|
462
|
+
|
|
232
463
|
```
|
|
233
464
|
|
|
465
|
+
|
|
466
|
+
|
|
234
467
|
## Path Traversal Protection
|
|
235
468
|
|
|
469
|
+
|
|
470
|
+
|
|
236
471
|
`{% extends %}` and `{% include %}` paths are validated to prevent directory traversal attacks:
|
|
237
472
|
|
|
473
|
+
|
|
474
|
+
|
|
238
475
|
```html
|
|
476
|
+
|
|
239
477
|
{% extends "../../etc/passwd" %} {# REJECTED #}
|
|
478
|
+
|
|
240
479
|
{% include "../../secrets" %} {# REJECTED #}
|
|
480
|
+
|
|
241
481
|
```
|
|
242
482
|
|
|
483
|
+
|
|
484
|
+
|
|
243
485
|
The engine checks that resolved paths stay within the allowed views directories. An `Error` with message starting `path traversal` is thrown if a path escapes the views root.
|
|
244
486
|
|
|
487
|
+
|
|
488
|
+
|
|
245
489
|
## Smart Template Discovery for Inheritance
|
|
246
490
|
|
|
491
|
+
|
|
492
|
+
|
|
247
493
|
When using `setupExpress()`, the engine automatically searches for parent templates in:
|
|
248
494
|
|
|
495
|
+
|
|
496
|
+
|
|
249
497
|
- The configured `views` directory
|
|
498
|
+
|
|
250
499
|
- Nested `templates/` directories inside the views root
|
|
500
|
+
|
|
251
501
|
- Subdirectories of the views root
|
|
502
|
+
|
|
252
503
|
- App-style `app/templates/...`, `packages/*/templates/...`, etc.
|
|
253
504
|
|
|
505
|
+
|
|
506
|
+
|
|
254
507
|
This means you can organize templates like:
|
|
255
508
|
|
|
509
|
+
|
|
510
|
+
|
|
256
511
|
```text
|
|
512
|
+
|
|
257
513
|
project/
|
|
514
|
+
|
|
258
515
|
├── views/
|
|
516
|
+
|
|
259
517
|
│ ├── base.html
|
|
518
|
+
|
|
260
519
|
│ └── home.html
|
|
520
|
+
|
|
261
521
|
├── app/
|
|
522
|
+
|
|
262
523
|
│ └── templates/
|
|
524
|
+
|
|
263
525
|
│ └── admin/
|
|
526
|
+
|
|
264
527
|
│ └── dashboard.html
|
|
528
|
+
|
|
265
529
|
```
|
|
266
530
|
|
|
531
|
+
|
|
532
|
+
|
|
267
533
|
And `{% extends "base.html" %}` will be found regardless of where the child template lives.
|
|
268
534
|
|
|
535
|
+
|
|
536
|
+
|
|
269
537
|
## Next Steps
|
|
270
538
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
- [
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
- [Partial Templates](./partial-templates.md)
|
|
542
|
+
|
|
543
|
+
- [Tags: extends and block](./tags.md#inheritance-tags)
|
|
544
|
+
|
|
545
|
+
- [Template Discovery](./template-discovery.md)
|
|
546
|
+
|
package/docs/index.md
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<img src="assets/banner.png" alt="miki-template banner" style="max-width: 100%; height: auto; border-radius: 0.5rem; box-shadow: 0 4px 12px var(--md-shadow-color); max-height: 200px;">
|
|
13
|
-
</div>
|
|
14
|
-
<div style="margin-top: 1rem; display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; position: relative; align-items: center;">
|
|
15
|
-
<a href="https://www.npmjs.com/package/miki-template" target="_blank" rel="noopener">
|
|
16
|
-
<img src="https://img.shields.io/npm/v/miki-template.svg" alt="npm version" style="height: 20px;">
|
|
17
|
-
</a>
|
|
18
|
-
<a href="https://www.npmjs.com/package/miki-template" target="_blank" rel="noopener">
|
|
19
|
-
<img src="https://img.shields.io/npm/dm/miki-template.svg" alt="npm downloads" style="height: 20px;">
|
|
20
|
-
</a>
|
|
21
|
-
<a href="https://github.com/alainmiki/miki-template" target="_blank" rel="noopener">
|
|
22
|
-
<img src="https://img.shields.io/github/actions/workflow/status/alainmiki/miki-template/ci.yml?branch=main" alt="CI status" style="height: 20px;">
|
|
23
|
-
</a>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<div class="md-typeset">
|
|
1
|
+
# miki-template
|
|
2
|
+
|
|
3
|
+
Django-style template magic for Node.js — blazing fast partials, smart template discovery, and zero friction for HTMX.
|
|
4
|
+
miki comes with more tags and filters that are not in django/jinja and miki templates supports all django tags and filters plus it own additional tags and filters.
|
|
5
|
+
you can register your own custom filters and filters in miki templates.
|
|
6
|
+
|
|
7
|
+
miki is secure and production ready with active maintainer and performance improvements.
|
|
8
|
+
|
|
9
|
+
[Get Started](guide/quick-start.md) | [API Reference](api/index.md) | [GitHub](https://github.com/alainmiki/miki-template)
|
|
10
|
+
|
|
11
|
+

|
|
28
12
|
|
|
29
13
|
## Why miki-template?
|
|
30
14
|
|
|
@@ -80,25 +64,23 @@ miki-template brings Django's beloved template language to Node.js and Express.
|
|
|
80
64
|
npm install miki-template
|
|
81
65
|
```
|
|
82
66
|
|
|
83
|
-
See the [Installation guide](guide/installation) for pnpm, yarn, and Bun instructions.
|
|
67
|
+
See the [Installation guide](guide/installation.md) for pnpm, yarn, and Bun instructions.
|
|
84
68
|
|
|
85
69
|
## Documentation
|
|
86
70
|
|
|
87
|
-
- [What is miki-template?](guide/what-is-miki-template)
|
|
88
|
-
- [Getting Started](guide/getting-started)
|
|
89
|
-
- [Quick Start](guide/quick-start)
|
|
90
|
-
- [Filters](guide/filters)
|
|
91
|
-
- [Tags](guide/tags)
|
|
92
|
-
- [Partial Templates](guide/partial-templates)
|
|
93
|
-
- [Template Inheritance](guide/template-inheritance)
|
|
94
|
-
- [Template Discovery](guide/template-discovery)
|
|
95
|
-
- [Security](guide/security)
|
|
96
|
-
- [Integrations](integrations/)
|
|
97
|
-
- [API Reference](api/)
|
|
98
|
-
- [Performance](performance)
|
|
71
|
+
- [What is miki-template?](guide/what-is-miki-template.md)
|
|
72
|
+
- [Getting Started](guide/getting-started.md)
|
|
73
|
+
- [Quick Start](guide/quick-start.md)
|
|
74
|
+
- [Filters](guide/filters.md)
|
|
75
|
+
- [Tags](guide/tags.md)
|
|
76
|
+
- [Partial Templates](guide/partial-templates.md)
|
|
77
|
+
- [Template Inheritance](guide/template-inheritance.md)
|
|
78
|
+
- [Template Discovery](guide/template-discovery.md)
|
|
79
|
+
- [Security](guide/security.md)
|
|
80
|
+
- [Integrations](integrations/index.md)
|
|
81
|
+
- [API Reference](api/index.md)
|
|
82
|
+
- [Performance](performance.md)
|
|
99
83
|
|
|
100
84
|
## License
|
|
101
85
|
|
|
102
86
|
MIT
|
|
103
|
-
|
|
104
|
-
</div>
|
|
@@ -74,5 +74,7 @@ Use miki-template with Elysia (Bun-native framework) by calling `asyncRender()`
|
|
|
74
74
|
|
|
75
75
|
## Next Steps
|
|
76
76
|
|
|
77
|
-
- [Integrations Overview](../)
|
|
78
|
-
- [API Reference: asyncRender
|
|
77
|
+
- [Integrations Overview](../index.md)
|
|
78
|
+
- [API Reference: asyncRender param($m) $m.Value -replace '([a-z][a-z0-9-]+)\.md
|
|
79
|
+
, '../.md' -replace '([a-z][a-z0-9-]+)
|
|
80
|
+
, '../.md'
|