miki-template 2.2.2 → 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 +1 -0
- 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/.github/workflows/npm-publish-github-packages.yml +0 -36
- package/docs/javascripts/extra.js +0 -174
- package/docs/stylesheets/extra.css +0 -819
- package/overrides/partials/footer.html +0 -9
|
@@ -1,367 +1,734 @@
|
|
|
1
|
-
# Partial Templates
|
|
1
|
+
# Partial Templates
|
|
2
|
+
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
Partial templates let you define reusable UI chunks once and render them anywhere. This is especially powerful with HTMX, Turbo, or any AJAX-style partial response pattern.
|
|
4
6
|
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
## Table of Contents
|
|
6
10
|
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
- [Defining Partials](#defining-partials)
|
|
14
|
+
|
|
8
15
|
- [Rendering Partials by Name](#rendering-partials-by-name)
|
|
16
|
+
|
|
9
17
|
- [Nested Partials](#nested-partials)
|
|
18
|
+
|
|
10
19
|
- [Partials with Context](#partials-with-context)
|
|
20
|
+
|
|
11
21
|
- [Partials with Include](#partials-with-include)
|
|
22
|
+
|
|
12
23
|
- [Rendering Partials Programmatically](#rendering-partials-programmatically)
|
|
24
|
+
|
|
13
25
|
- [Express Partial Rendering](#express-partial-rendering)
|
|
26
|
+
|
|
14
27
|
- [Common Pitfalls](#common-pitfalls)
|
|
15
28
|
|
|
29
|
+
|
|
30
|
+
|
|
16
31
|
---
|
|
17
32
|
|
|
33
|
+
|
|
34
|
+
|
|
18
35
|
## Defining Partials
|
|
19
36
|
|
|
37
|
+
|
|
38
|
+
|
|
20
39
|
Use `{% partialdef %}` to define a named partial inside any template:
|
|
21
40
|
|
|
41
|
+
|
|
42
|
+
|
|
22
43
|
```html
|
|
44
|
+
|
|
23
45
|
<!-- views/home.html -->
|
|
46
|
+
|
|
24
47
|
{% partialdef card %}
|
|
48
|
+
|
|
25
49
|
<div class="card">
|
|
50
|
+
|
|
26
51
|
<h3>{{ title|default:"Untitled" }}</h3>
|
|
52
|
+
|
|
27
53
|
<p>{{ body|truncatewords:30 }}</p>
|
|
54
|
+
|
|
28
55
|
{% if featured %}<em>Featured</em>{% endif %}
|
|
56
|
+
|
|
29
57
|
</div>
|
|
58
|
+
|
|
30
59
|
{% endpartialdef %}
|
|
31
60
|
|
|
61
|
+
|
|
62
|
+
|
|
32
63
|
{% for entry in entries %}
|
|
64
|
+
|
|
33
65
|
{% partial card with title=entry.title body=entry.body featured=entry.featured %}
|
|
66
|
+
|
|
34
67
|
{% endfor %}
|
|
68
|
+
|
|
35
69
|
```
|
|
36
70
|
|
|
71
|
+
|
|
72
|
+
|
|
37
73
|
### Inline Partials
|
|
38
74
|
|
|
75
|
+
|
|
76
|
+
|
|
39
77
|
A `{% partialdef %}` block renders its body inline where it is defined **and** registers itself for later use:
|
|
40
78
|
|
|
79
|
+
|
|
80
|
+
|
|
41
81
|
```html
|
|
82
|
+
|
|
42
83
|
{% partialdef notice %}
|
|
84
|
+
|
|
43
85
|
<div class="alert">{{ message }}</div>
|
|
86
|
+
|
|
44
87
|
{% endpartialdef %}
|
|
88
|
+
|
|
45
89
|
```
|
|
46
90
|
|
|
91
|
+
|
|
92
|
+
|
|
47
93
|
This means you get immediate output and a reusable partial in one declaration.
|
|
48
94
|
|
|
95
|
+
|
|
96
|
+
|
|
49
97
|
Use the `inline` option explicitly:
|
|
50
98
|
|
|
99
|
+
|
|
100
|
+
|
|
51
101
|
```html
|
|
102
|
+
|
|
52
103
|
{% partialdef greeting inline %}
|
|
104
|
+
|
|
53
105
|
Hello {{ name }}!
|
|
106
|
+
|
|
54
107
|
{% endpartialdef %}
|
|
108
|
+
|
|
55
109
|
<!-- Above line ALSO outputs "Hello World!" when rendered -->
|
|
110
|
+
|
|
56
111
|
```
|
|
57
112
|
|
|
113
|
+
|
|
114
|
+
|
|
58
115
|
## Rendering Partials by Name
|
|
59
116
|
|
|
117
|
+
|
|
118
|
+
|
|
60
119
|
Once defined, you can render a partial by name from your routes using the `view#partial` syntax:
|
|
61
120
|
|
|
121
|
+
|
|
122
|
+
|
|
62
123
|
=== "CommonJS"
|
|
63
124
|
|
|
125
|
+
|
|
126
|
+
|
|
64
127
|
```javascript
|
|
128
|
+
|
|
65
129
|
const express = require('express');
|
|
130
|
+
|
|
66
131
|
const miki = require('miki-template');
|
|
67
132
|
|
|
133
|
+
|
|
134
|
+
|
|
68
135
|
const app = express();
|
|
136
|
+
|
|
69
137
|
miki.setupExpress(app, { extension: 'html', views: './views' });
|
|
70
138
|
|
|
139
|
+
|
|
140
|
+
|
|
71
141
|
app.get('/card/:id', (req, res) =>
|
|
142
|
+
|
|
72
143
|
res.render(`home#card`, { title: 'Hello', body: 'World...', featured: true })
|
|
144
|
+
|
|
73
145
|
);
|
|
146
|
+
|
|
74
147
|
```
|
|
75
148
|
|
|
149
|
+
|
|
150
|
+
|
|
76
151
|
=== "ES Modules"
|
|
77
152
|
|
|
153
|
+
|
|
154
|
+
|
|
78
155
|
```javascript
|
|
156
|
+
|
|
79
157
|
import express from 'express';
|
|
158
|
+
|
|
80
159
|
import miki from 'miki-template';
|
|
81
160
|
|
|
161
|
+
|
|
162
|
+
|
|
82
163
|
const app = express();
|
|
164
|
+
|
|
83
165
|
miki.setupExpress(app, { extension: 'html', views: './views' });
|
|
84
166
|
|
|
167
|
+
|
|
168
|
+
|
|
85
169
|
app.get('/card/:id', (req, res) =>
|
|
170
|
+
|
|
86
171
|
res.render(`home#card`, { title: 'Hello', body: 'World...', featured: true })
|
|
172
|
+
|
|
87
173
|
);
|
|
174
|
+
|
|
88
175
|
```
|
|
89
176
|
|
|
177
|
+
|
|
178
|
+
|
|
90
179
|
The syntax is `viewName#partialName`. The engine resolves the file, extracts the named partial, and renders only that block.
|
|
91
180
|
|
|
181
|
+
|
|
182
|
+
|
|
92
183
|
**Real-world HTMX example:**
|
|
93
184
|
|
|
185
|
+
|
|
186
|
+
|
|
94
187
|
```html
|
|
188
|
+
|
|
95
189
|
<!-- views/products.html -->
|
|
190
|
+
|
|
96
191
|
{% partialdef product_card %}
|
|
192
|
+
|
|
97
193
|
<div class="product-card" id="product-{{ product.id }}">
|
|
194
|
+
|
|
98
195
|
<img src="{{ product.image|static }}" alt="{{ product.name }}">
|
|
196
|
+
|
|
99
197
|
<h3>{{ product.name|capfirst }}</h3>
|
|
198
|
+
|
|
100
199
|
<p class="price">${{ product.price|floatformat:2 }}</p>
|
|
200
|
+
|
|
101
201
|
<button hx-post="/cart/add/{{ product.id }}" hx-swap="outerHTML">
|
|
202
|
+
|
|
102
203
|
Add to Cart
|
|
204
|
+
|
|
103
205
|
</button>
|
|
206
|
+
|
|
104
207
|
</div>
|
|
208
|
+
|
|
105
209
|
{% endpartialdef %}
|
|
106
210
|
|
|
211
|
+
|
|
212
|
+
|
|
107
213
|
{% for product in products %}
|
|
214
|
+
|
|
108
215
|
{% partial product_card with product=product %}
|
|
216
|
+
|
|
109
217
|
{% endfor %}
|
|
218
|
+
|
|
110
219
|
```
|
|
111
220
|
|
|
221
|
+
|
|
222
|
+
|
|
112
223
|
```javascript
|
|
224
|
+
|
|
113
225
|
// The entire page renders all cards
|
|
226
|
+
|
|
114
227
|
app.get('/shop', (req, res) =>
|
|
228
|
+
|
|
115
229
|
res.render('products', { products: catalog })
|
|
230
|
+
|
|
116
231
|
);
|
|
117
232
|
|
|
233
|
+
|
|
234
|
+
|
|
118
235
|
// HTMX swaps just one card after an action
|
|
236
|
+
|
|
119
237
|
app.post('/cart/add/:id', (req, res) =>
|
|
238
|
+
|
|
120
239
|
res.render('products#product_card', {
|
|
240
|
+
|
|
121
241
|
product: catalog.find(p => p.id == req.params.id)
|
|
242
|
+
|
|
122
243
|
})
|
|
244
|
+
|
|
123
245
|
);
|
|
246
|
+
|
|
124
247
|
```
|
|
125
248
|
|
|
249
|
+
|
|
250
|
+
|
|
126
251
|
## Nested Partials
|
|
127
252
|
|
|
253
|
+
|
|
254
|
+
|
|
128
255
|
Partials can call other partials:
|
|
129
256
|
|
|
257
|
+
|
|
258
|
+
|
|
130
259
|
```html
|
|
260
|
+
|
|
131
261
|
{% partialdef header %}
|
|
262
|
+
|
|
132
263
|
<div class="card-header">
|
|
264
|
+
|
|
133
265
|
<h3>{{ title }}</h3>
|
|
266
|
+
|
|
134
267
|
</div>
|
|
268
|
+
|
|
135
269
|
{% endpartialdef %}
|
|
136
270
|
|
|
271
|
+
|
|
272
|
+
|
|
137
273
|
{% partialdef card %}
|
|
274
|
+
|
|
138
275
|
<div class="card">
|
|
276
|
+
|
|
139
277
|
{% partial header with title=title %}
|
|
278
|
+
|
|
140
279
|
<p>{{ body }}</p>
|
|
280
|
+
|
|
141
281
|
</div>
|
|
282
|
+
|
|
142
283
|
{% endpartialdef %}
|
|
284
|
+
|
|
143
285
|
```
|
|
144
286
|
|
|
287
|
+
|
|
288
|
+
|
|
145
289
|
## Partials with Context
|
|
146
290
|
|
|
291
|
+
|
|
292
|
+
|
|
147
293
|
By default, partials inherit the parent context. Use `with` to pass explicit values:
|
|
148
294
|
|
|
295
|
+
|
|
296
|
+
|
|
149
297
|
```html
|
|
298
|
+
|
|
150
299
|
{% partial card with title="Hello" body="World" %}
|
|
300
|
+
|
|
151
301
|
```
|
|
152
302
|
|
|
303
|
+
|
|
304
|
+
|
|
153
305
|
You can also pass context variables:
|
|
154
306
|
|
|
307
|
+
|
|
308
|
+
|
|
155
309
|
```html
|
|
310
|
+
|
|
156
311
|
{% partial card with title=entry.title body=entry.body %}
|
|
312
|
+
|
|
157
313
|
```
|
|
158
314
|
|
|
315
|
+
|
|
316
|
+
|
|
159
317
|
## Partials with Include
|
|
160
318
|
|
|
319
|
+
|
|
320
|
+
|
|
161
321
|
You can include a partial from another template file using the `#partialName` syntax:
|
|
162
322
|
|
|
323
|
+
|
|
324
|
+
|
|
163
325
|
```html
|
|
326
|
+
|
|
164
327
|
{% include "header.html#partial_name" %}
|
|
328
|
+
|
|
165
329
|
```
|
|
166
330
|
|
|
331
|
+
|
|
332
|
+
|
|
167
333
|
This loads `header.html`, registers all its partials, and renders only the named one.
|
|
168
334
|
|
|
335
|
+
|
|
336
|
+
|
|
169
337
|
**Real-world navigation include:**
|
|
170
338
|
|
|
339
|
+
|
|
340
|
+
|
|
171
341
|
```html
|
|
342
|
+
|
|
172
343
|
<!-- views/nav.html -->
|
|
344
|
+
|
|
173
345
|
{% partialdef navigation %}
|
|
346
|
+
|
|
174
347
|
<nav>
|
|
348
|
+
|
|
175
349
|
{% for link in links %}
|
|
350
|
+
|
|
176
351
|
<a href="{{ link.url }}" class="{% if link.active %}current{% endif %}">{{ link.label }}</a>
|
|
352
|
+
|
|
177
353
|
{% endfor %}
|
|
354
|
+
|
|
178
355
|
</nav>
|
|
356
|
+
|
|
179
357
|
{% endpartialdef %}
|
|
358
|
+
|
|
180
359
|
```
|
|
181
360
|
|
|
361
|
+
|
|
362
|
+
|
|
182
363
|
```html
|
|
364
|
+
|
|
183
365
|
<!-- In any template -->
|
|
366
|
+
|
|
184
367
|
{% include "nav.html#navigation" with links=nav_links %}
|
|
368
|
+
|
|
185
369
|
```
|
|
186
370
|
|
|
371
|
+
|
|
372
|
+
|
|
187
373
|
## Rendering Partials Programmatically
|
|
188
374
|
|
|
375
|
+
|
|
376
|
+
|
|
189
377
|
### renderPartialFromSource
|
|
190
378
|
|
|
379
|
+
|
|
380
|
+
|
|
191
381
|
Render a named partial from a template source string:
|
|
192
382
|
|
|
383
|
+
|
|
384
|
+
|
|
193
385
|
=== "CommonJS"
|
|
194
386
|
|
|
387
|
+
|
|
388
|
+
|
|
195
389
|
```javascript
|
|
390
|
+
|
|
196
391
|
const { renderPartialFromSource } = require('miki-template');
|
|
197
392
|
|
|
393
|
+
|
|
394
|
+
|
|
198
395
|
const source = `{% partialdef card %}<div>{{ title }}</div>{% endpartialdef %}`;
|
|
396
|
+
|
|
199
397
|
const html = renderPartialFromSource(source, 'card', { title: 'Hello' });
|
|
398
|
+
|
|
200
399
|
```
|
|
201
400
|
|
|
401
|
+
|
|
402
|
+
|
|
202
403
|
=== "ES Modules"
|
|
203
404
|
|
|
405
|
+
|
|
406
|
+
|
|
204
407
|
```javascript
|
|
408
|
+
|
|
205
409
|
import { renderPartialFromSource } from 'miki-template';
|
|
206
410
|
|
|
411
|
+
|
|
412
|
+
|
|
207
413
|
const source = `{% partialdef card %}<div>{{ title }}</div>{% endpartialdef %}`;
|
|
414
|
+
|
|
208
415
|
const html = renderPartialFromSource(source, 'card', { title: 'Hello' });
|
|
416
|
+
|
|
209
417
|
```
|
|
210
418
|
|
|
419
|
+
|
|
420
|
+
|
|
211
421
|
### renderPartialFromFile
|
|
212
422
|
|
|
423
|
+
|
|
424
|
+
|
|
213
425
|
Render a named partial from a template file:
|
|
214
426
|
|
|
427
|
+
|
|
428
|
+
|
|
215
429
|
=== "CommonJS"
|
|
216
430
|
|
|
431
|
+
|
|
432
|
+
|
|
217
433
|
```javascript
|
|
434
|
+
|
|
218
435
|
const { renderPartialFromFile } = require('miki-template');
|
|
219
436
|
|
|
437
|
+
|
|
438
|
+
|
|
220
439
|
const html = renderPartialFromFile('home', 'card', { title: 'Hello' }, { views: './views' });
|
|
440
|
+
|
|
221
441
|
```
|
|
222
442
|
|
|
443
|
+
|
|
444
|
+
|
|
223
445
|
=== "ES Modules"
|
|
224
446
|
|
|
447
|
+
|
|
448
|
+
|
|
225
449
|
```javascript
|
|
450
|
+
|
|
226
451
|
import { renderPartialFromFile } from 'miki-template';
|
|
227
452
|
|
|
453
|
+
|
|
454
|
+
|
|
228
455
|
const html = renderPartialFromFile('home', 'card', { title: 'Hello' }, { views: './views' });
|
|
456
|
+
|
|
229
457
|
```
|
|
230
458
|
|
|
459
|
+
|
|
460
|
+
|
|
231
461
|
### compiled.renderPartial
|
|
232
462
|
|
|
463
|
+
|
|
464
|
+
|
|
233
465
|
Render a partial from a compiled template:
|
|
234
466
|
|
|
467
|
+
|
|
468
|
+
|
|
235
469
|
=== "CommonJS"
|
|
236
470
|
|
|
471
|
+
|
|
472
|
+
|
|
237
473
|
```javascript
|
|
474
|
+
|
|
238
475
|
const { compile } = require('miki-template');
|
|
239
476
|
|
|
477
|
+
|
|
478
|
+
|
|
240
479
|
const compiled = compile('<h1>{{ title }}</h1>', { views: './templates' });
|
|
480
|
+
|
|
241
481
|
const html = compiled.renderPartial('card', { title: 'Hello' });
|
|
482
|
+
|
|
242
483
|
```
|
|
243
484
|
|
|
485
|
+
|
|
486
|
+
|
|
244
487
|
=== "ES Modules"
|
|
245
488
|
|
|
489
|
+
|
|
490
|
+
|
|
246
491
|
```javascript
|
|
492
|
+
|
|
247
493
|
import { compile } from 'miki-template';
|
|
248
494
|
|
|
495
|
+
|
|
496
|
+
|
|
249
497
|
const compiled = compile('<h1>{{ title }}</h1>', { views: './templates' });
|
|
498
|
+
|
|
250
499
|
const html = compiled.renderPartial('card', { title: 'Hello' });
|
|
500
|
+
|
|
251
501
|
```
|
|
252
502
|
|
|
503
|
+
|
|
504
|
+
|
|
253
505
|
### compiled.renderBlock
|
|
254
506
|
|
|
507
|
+
|
|
508
|
+
|
|
255
509
|
Render a single block from a compiled template — useful for AJAX responses:
|
|
256
510
|
|
|
511
|
+
|
|
512
|
+
|
|
257
513
|
=== "CommonJS"
|
|
258
514
|
|
|
515
|
+
|
|
516
|
+
|
|
259
517
|
```javascript
|
|
518
|
+
|
|
260
519
|
const { compile } = require('miki-template');
|
|
261
520
|
|
|
521
|
+
|
|
522
|
+
|
|
262
523
|
const compiled = compile(childTemplate, { views: './templates' });
|
|
524
|
+
|
|
263
525
|
const html = compiled.renderBlock('content', context);
|
|
526
|
+
|
|
264
527
|
```
|
|
265
528
|
|
|
529
|
+
|
|
530
|
+
|
|
266
531
|
=== "ES Modules"
|
|
267
532
|
|
|
533
|
+
|
|
534
|
+
|
|
268
535
|
```javascript
|
|
536
|
+
|
|
269
537
|
import { compile } from 'miki-template';
|
|
270
538
|
|
|
539
|
+
|
|
540
|
+
|
|
271
541
|
const compiled = compile(childTemplate, { views: './templates' });
|
|
542
|
+
|
|
272
543
|
const html = compiled.renderBlock('content', context);
|
|
544
|
+
|
|
273
545
|
```
|
|
274
546
|
|
|
547
|
+
|
|
548
|
+
|
|
275
549
|
## Express Partial Rendering
|
|
276
550
|
|
|
551
|
+
|
|
552
|
+
|
|
277
553
|
### res.render with `#partial`
|
|
278
554
|
|
|
555
|
+
|
|
556
|
+
|
|
279
557
|
When using `setupExpress()`, you can render partials directly:
|
|
280
558
|
|
|
559
|
+
|
|
560
|
+
|
|
281
561
|
=== "CommonJS"
|
|
282
562
|
|
|
563
|
+
|
|
564
|
+
|
|
283
565
|
```javascript
|
|
566
|
+
|
|
284
567
|
app.get('/card/:id', (req, res) =>
|
|
568
|
+
|
|
285
569
|
res.render(`home#card`, { title: 'Hello', body: '...' })
|
|
570
|
+
|
|
286
571
|
);
|
|
572
|
+
|
|
287
573
|
```
|
|
288
574
|
|
|
575
|
+
|
|
576
|
+
|
|
289
577
|
=== "ES Modules"
|
|
290
578
|
|
|
579
|
+
|
|
580
|
+
|
|
291
581
|
```javascript
|
|
582
|
+
|
|
292
583
|
app.get('/card/:id', (req, res) =>
|
|
584
|
+
|
|
293
585
|
res.render(`home#card`, { title: 'Hello', body: '...' })
|
|
586
|
+
|
|
294
587
|
);
|
|
588
|
+
|
|
295
589
|
```
|
|
296
590
|
|
|
591
|
+
|
|
592
|
+
|
|
297
593
|
### res.renderPartial middleware
|
|
298
594
|
|
|
595
|
+
|
|
596
|
+
|
|
299
597
|
If you don't want to patch `res.render`, add the partial renderer middleware instead:
|
|
300
598
|
|
|
599
|
+
|
|
600
|
+
|
|
301
601
|
=== "CommonJS"
|
|
302
602
|
|
|
603
|
+
|
|
604
|
+
|
|
303
605
|
```javascript
|
|
606
|
+
|
|
304
607
|
const express = require('express');
|
|
608
|
+
|
|
305
609
|
const miki = require('miki-template');
|
|
306
610
|
|
|
611
|
+
|
|
612
|
+
|
|
307
613
|
const app = express();
|
|
614
|
+
|
|
308
615
|
app.use(miki.expressPartialRenderer());
|
|
309
616
|
|
|
617
|
+
|
|
618
|
+
|
|
310
619
|
app.get('/card', (req, res) =>
|
|
620
|
+
|
|
311
621
|
res.renderPartial('home#card', { user: req.user })
|
|
622
|
+
|
|
312
623
|
);
|
|
624
|
+
|
|
313
625
|
```
|
|
314
626
|
|
|
627
|
+
|
|
628
|
+
|
|
315
629
|
=== "ES Modules"
|
|
316
630
|
|
|
631
|
+
|
|
632
|
+
|
|
317
633
|
```javascript
|
|
634
|
+
|
|
318
635
|
import express from 'express';
|
|
636
|
+
|
|
319
637
|
import miki from 'miki-template';
|
|
320
638
|
|
|
639
|
+
|
|
640
|
+
|
|
321
641
|
const app = express();
|
|
642
|
+
|
|
322
643
|
app.use(miki.expressPartialRenderer());
|
|
323
644
|
|
|
645
|
+
|
|
646
|
+
|
|
324
647
|
app.get('/card', (req, res) =>
|
|
648
|
+
|
|
325
649
|
res.renderPartial('home#card', { user: req.user })
|
|
650
|
+
|
|
326
651
|
);
|
|
652
|
+
|
|
327
653
|
```
|
|
328
654
|
|
|
655
|
+
|
|
656
|
+
|
|
329
657
|
## Partial API Reference
|
|
330
658
|
|
|
659
|
+
|
|
660
|
+
|
|
331
661
|
### renderPartialFromSource(fileContent, partialName, contextObj, options, filePath?)
|
|
332
662
|
|
|
663
|
+
|
|
664
|
+
|
|
333
665
|
Render a named partial from a template source string.
|
|
334
666
|
|
|
667
|
+
|
|
668
|
+
|
|
335
669
|
| Parameter | Type | Description |
|
|
670
|
+
|
|
336
671
|
|-----------|------|-------------|
|
|
672
|
+
|
|
337
673
|
| `fileContent` | `string` | Template source string |
|
|
674
|
+
|
|
338
675
|
| `partialName` | `string` | Name of the partial to render |
|
|
676
|
+
|
|
339
677
|
| `contextObj` | `object` | Variables to inject |
|
|
678
|
+
|
|
340
679
|
| `options` | `object` | Options |
|
|
680
|
+
|
|
341
681
|
| `filePath` | `string?` | Optional file path for error messages |
|
|
342
682
|
|
|
683
|
+
|
|
684
|
+
|
|
343
685
|
### renderPartialFromFile(fileName, partialName, contextObj, options)
|
|
344
686
|
|
|
687
|
+
|
|
688
|
+
|
|
345
689
|
Render a named partial from a template file.
|
|
346
690
|
|
|
691
|
+
|
|
692
|
+
|
|
347
693
|
| Parameter | Type | Description |
|
|
694
|
+
|
|
348
695
|
|-----------|------|-------------|
|
|
696
|
+
|
|
349
697
|
| `fileName` | `string` | Template file name (without extension) |
|
|
698
|
+
|
|
350
699
|
| `partialName` | `string` | Name of the partial to render |
|
|
700
|
+
|
|
351
701
|
| `contextObj` | `object` | Variables to inject |
|
|
702
|
+
|
|
352
703
|
| `options` | `object` | Options including `views` directories |
|
|
353
704
|
|
|
705
|
+
|
|
706
|
+
|
|
354
707
|
## Common Pitfalls
|
|
355
708
|
|
|
709
|
+
|
|
710
|
+
|
|
356
711
|
| Issue | Symptom | Fix |
|
|
712
|
+
|
|
357
713
|
|-------|---------|-----|
|
|
714
|
+
|
|
358
715
|
| Missing partial name | `{% partial %}` renders nothing | Ensure the name matches a defined `partialdef`. |
|
|
716
|
+
|
|
359
717
|
| Variable not found | Appears empty | Variables are resolved in the current context; use `with` to pass explicit values. |
|
|
718
|
+
|
|
360
719
|
| Inline vs non-inline confusion | Duplicate output | Use `inline` only when you want immediate rendering at the declaration site. |
|
|
720
|
+
|
|
361
721
|
| Partial leaks across includes | Unexpected partials available | `include "file#partial"` isolates partials; `include "file"` (full) makes all partials available. |
|
|
362
722
|
|
|
723
|
+
|
|
724
|
+
|
|
363
725
|
## Next Steps
|
|
364
726
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
- [
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
- [Template Inheritance](./template-inheritance.md)
|
|
730
|
+
|
|
731
|
+
- [Tags: partialdef and partial](./tags.md#partial-tags)
|
|
732
|
+
|
|
733
|
+
- [API Reference: renderPartial](../api/render-partial.md)
|
|
734
|
+
|