miki-template 1.3.3 → 1.3.6

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.
Files changed (101) hide show
  1. package/.github/release-notes/v1.3.1.md +55 -55
  2. package/.github/release-notes/v1.3.3.md +77 -0
  3. package/.github/workflows/ci.yml +38 -54
  4. package/.github/workflows/release.yml +106 -0
  5. package/AGENT.md +71 -71
  6. package/API_REFERENCE.md +314 -314
  7. package/CHANGELOG.md +173 -169
  8. package/CODE_OF_CONDUCT.md +14 -14
  9. package/CONTRIBUTING.md +27 -27
  10. package/README.md +342 -321
  11. package/ROADMAP.md +40 -40
  12. package/benchmarks/report.json +16 -16
  13. package/benchmarks/run.js +49 -49
  14. package/benchmarks/stress.mjs +647 -647
  15. package/benchmarks/templates/large.dtpl +7 -7
  16. package/benchmarks/templates/medium.dtpl +3 -3
  17. package/benchmarks/templates/small.dtpl +7 -7
  18. package/context/component.md +109 -109
  19. package/context/prd.md +131 -131
  20. package/context/project-structure.md +33 -33
  21. package/dir/base.html +22 -22
  22. package/dir/cmpnt.html +10 -10
  23. package/dir/footer.html +2 -2
  24. package/dir/home.html +80 -80
  25. package/dir/index.html +80 -0
  26. package/dir/navbar.html +8 -8
  27. package/docs/README.md +18 -18
  28. package/docs/advanced_usage.md +71 -71
  29. package/docs/api.md +119 -119
  30. package/docs/filters.md +708 -708
  31. package/docs/installation.md +106 -106
  32. package/docs/overview.md +57 -57
  33. package/docs/partialdef.md +70 -70
  34. package/docs/security.md +27 -27
  35. package/docs/tags.md +673 -673
  36. package/docs/usage.md +646 -646
  37. package/eslint.config.mjs +42 -42
  38. package/ex.mjs +32 -32
  39. package/miki-template-extension/.github/workflows/ci.yml +116 -116
  40. package/miki-template-extension/.vscodeignore +7 -7
  41. package/miki-template-extension/CHANGELOG.md +99 -99
  42. package/miki-template-extension/LICENSE +21 -21
  43. package/miki-template-extension/README.md +273 -273
  44. package/miki-template-extension/extension.js +1013 -1013
  45. package/miki-template-extension/icon.svg +10 -10
  46. package/miki-template-extension/package.json +280 -280
  47. package/miki-template-extension/snippets/miki-template.json +717 -717
  48. package/miki-template-extension/syntaxes/language-configuration.json +114 -114
  49. package/miki-template-extension/syntaxes/miki-template.tmLanguage.json +355 -355
  50. package/miki-template-extension/tests/grammar-tests.json +162 -162
  51. package/miki-template-extension/tests/run-grammar-tests.js +82 -82
  52. package/package.json +37 -34
  53. package/sample-app/package-lock.json +901 -0
  54. package/sample-app/package.json +9 -0
  55. package/sample-app/server.js +14 -0
  56. package/sample-app/views/index.html +1 -0
  57. package/scripts/build-vsix.js +129 -129
  58. package/scripts/build-vsix.ps1 +15 -15
  59. package/snippets/miki-template.json +177 -177
  60. package/src/asyncRender.js +20 -20
  61. package/src/cache.js +80 -80
  62. package/src/context.js +126 -126
  63. package/src/context_processors.js +48 -48
  64. package/src/esm.mjs +84 -84
  65. package/src/filters.js +975 -975
  66. package/src/i18n.js +171 -171
  67. package/src/index.js +974 -940
  68. package/src/lexer.js +114 -114
  69. package/src/libraries.js +371 -371
  70. package/src/parser.js +270 -270
  71. package/src/security.js +53 -53
  72. package/src/tags/control.js +719 -719
  73. package/src/tags/extra.js +154 -154
  74. package/src/tags/helpers.js +26 -26
  75. package/src/tags/i18n.js +256 -256
  76. package/src/tags/inheritance.js +335 -335
  77. package/src/tags/registry.js +18 -18
  78. package/src/tags/util.js +400 -400
  79. package/src/types.d.ts +107 -107
  80. package/syntaxes/language-configuration.json +26 -26
  81. package/syntaxes/miki-template.tmLanguage.json +146 -146
  82. package/tests/asyncRender.test.js +17 -17
  83. package/tests/base.html +6 -6
  84. package/tests/child.html +3 -3
  85. package/tests/context_processors.test.js +13 -13
  86. package/tests/esm.test.mjs +61 -61
  87. package/tests/filters.test.js +254 -254
  88. package/tests/include_security.test.js +9 -9
  89. package/tests/integration/README.md +32 -32
  90. package/tests/integration/features.test.cjs +1681 -1681
  91. package/tests/integration/features.test.mjs +1697 -1697
  92. package/tests/integration/templates/base.miki +6 -6
  93. package/tests/integration/templates/child.miki +6 -6
  94. package/tests/integration/templates/index.html +17 -17
  95. package/tests/lexer.test.js +45 -45
  96. package/tests/parser.test.js +57 -57
  97. package/tests/partial.html +1 -1
  98. package/tests/partialdef.test.js +79 -79
  99. package/tests/production_checks.js +57 -57
  100. package/tests/security.test.js +28 -28
  101. package/tests/tags.test.js +233 -233
package/API_REFERENCE.md CHANGED
@@ -1,314 +1,314 @@
1
- # API Reference - miki-template
2
-
3
- This document provides complete details for the public APIs exported by the **miki-template** engine — a Django-style template engine for Node.js and Express.
4
-
5
- ---
6
-
7
- ## Core Exports
8
-
9
- ```javascript
10
- const {
11
- compile,
12
- render,
13
- asyncRender,
14
- __express,
15
- clearCache,
16
- registerTag,
17
- registerFilter,
18
- registerHelper,
19
- registerContextProcessor,
20
- SafeString,
21
- markSafe,
22
- isSafe,
23
- escapeHtml
24
- } = require('miki-template');
25
- ```
26
-
27
- ---
28
-
29
- ### `compile(templateStr, options)`
30
-
31
- Compiles a raw template string into a reusable compiled template object. The compiled template caches its AST internally.
32
-
33
- **Parameters**:
34
- - `templateStr` (string): The raw template string to compile.
35
- - `options` (object): Config parameters:
36
- - `views` (string|string[]): Directories to search for templates when using `extends` or `include`.
37
- - `staticUrl` (string): Prefix for the `{% static %}` tag. Defaults to `/static/`.
38
- - `urlHelper` (function): Custom URL resolver for `{% url %}` tag.
39
-
40
- **Returns**: An object containing:
41
- - `render(context)` — Synchronously renders the template.
42
- - `asyncRender(context)` — Returns a Promise for async rendering.
43
- - `renderBlock(blockName, context)` — Renders a specific block by name.
44
- - `renderPartial(partialName, context)` — Renders a defined partial by name.
45
-
46
- **Example**:
47
- ```javascript
48
- const { compile } = require('miki-template');
49
-
50
- const template = compile('Hello {{ name }}!');
51
- const output = template.render({ name: 'World' });
52
- console.log(output); // Hello World!
53
- ```
54
-
55
- ---
56
-
57
- ### `render(templateStr, context, options)`
58
-
59
- One-step convenience function that compiles and renders a template.
60
-
61
- **Parameters**:
62
- - `templateStr` (string): Raw template string.
63
- - `context` (object): Variables available to the template.
64
- - `options` (object): Same as `compile()` options.
65
-
66
- **Returns**: Rendered HTML string.
67
-
68
- ---
69
-
70
- ### `asyncRender(templateStr, context, options)`
71
-
72
- Asynchronous rendering for templates with async helpers or async context processors.
73
-
74
- **Parameters**: Same as `render()`.
75
-
76
- **Returns**: `Promise<string>` — resolved rendered HTML.
77
-
78
- **Example**:
79
- ```javascript
80
- const { asyncRender } = require('miki-template');
81
- const html = await asyncRender('Hello {{ name }}!', { name: 'Async' });
82
- ```
83
-
84
- ---
85
-
86
- ### `__express(filePath, options, callback)`
87
-
88
- Express-compatible view engine adapter. Use with `app.engine()`.
89
-
90
- **Parameters**:
91
- - `filePath` (string): Absolute path to the template file.
92
- - `options` (object): Express `res.render()` context (view engine strips `_locals`, `settings`, and other Express internals).
93
- - `callback` (function): Node.js callback `(err, html)`.
94
-
95
- **Example**:
96
- ```javascript
97
- const express = require('express');
98
- const { __express } = require('miki-template');
99
-
100
- const app = express();
101
- app.engine('html', __express);
102
- app.set('view engine', 'html');
103
- app.set('views', './views');
104
-
105
- app.get('/', (req, res) => {
106
- res.render('home', { title: 'Home Page' });
107
- });
108
- ```
109
-
110
- ---
111
-
112
- ### `registerTag(name, parserFn)`
113
-
114
- Registers a custom block tag parser. Must be called **before** compiling templates that use the tag.
115
-
116
- **Parameters**:
117
- - `name` (string): Tag identifier word (e.g. `mytag` for `{% mytag %}`).
118
- - `parserFn` (function): `(tagContent: string, parser: Parser) => ASTNode`. Receives the raw tag content and the parser instance.
119
-
120
- **Returns**: `undefined`.
121
-
122
- **Example**:
123
- ```javascript
124
- const { registerTag } = require('miki-template');
125
-
126
- registerTag('greet', (tagContent, parser) => {
127
- const name = tagContent.slice(5).trim(); // strip 'greet'
128
- return {
129
- render: (context) => `Hello ${context.get(name) || 'Guest'}!`
130
- };
131
- });
132
-
133
- // In template: {% greet user.name %}
134
- ```
135
-
136
- ---
137
-
138
- ### `registerFilter(name, filterFn)`
139
-
140
- Registers a custom filter function.
141
-
142
- **Parameters**:
143
- - `name` (string): Filter name used after the pipe `|`.
144
- - `filterFn` (function): `(value: any, arg?: any) => any`. Receives the filtered value and optional argument.
145
-
146
- **Returns**: `undefined`.
147
-
148
- **Example**:
149
- ```javascript
150
- const { registerFilter } = require('miki-template');
151
-
152
- registerFilter('reverse', (val) => {
153
- return String(val).split('').reverse().join('');
154
- });
155
-
156
- // In template: {{ name|reverse }}
157
- ```
158
-
159
- ---
160
-
161
- ### `registerHelper(name, fn)`
162
-
163
- Registers a custom block helper tag. The helper receives the **rendered** inner content as a string.
164
-
165
- **Parameters**:
166
- - `name` (string): Tag name (e.g. `markdown` creates `{% markdown %}...{% endmarkdown %}`).
167
- - `fn` (function): `(innerContent: string, context: Context) => string | Promise<string>`.
168
-
169
- **Returns**: `undefined`.
170
-
171
- **Example**:
172
- ```javascript
173
- const { registerHelper } = require('miki-template');
174
- const markdownIt = require('markdown-it')();
175
- registerHelper('markdown', (content) => markdownIt.render(content));
176
-
177
- // In template:
178
- // {% markdown %}
179
- // # Hello
180
- // {% endmarkdown %}
181
- ```
182
-
183
- ---
184
-
185
- ### `registerContextProcessor(fn)`
186
-
187
- Adds a context processor function. Similar to Django's custom context processors.
188
-
189
- **Parameters**:
190
- - `fn` (function): `(context: object) => object | undefined`. Receives the render context and returns extra key-value pairs to merge in.
191
-
192
- **Returns**: `undefined`.
193
-
194
- **Example**:
195
- ```javascript
196
- const { registerContextProcessor } = require('miki-template');
197
-
198
- registerContextProcessor((ctx) => ({
199
- siteName: 'MySite',
200
- currentYear: new Date().getFullYear()
201
- }));
202
-
203
- // Available in all templates as {{ siteName }} and {{ currentYear }}
204
- ```
205
-
206
- ---
207
-
208
- ### `SafeString`
209
-
210
- Class for values that should **bypass HTML auto-escaping**. Construct directly or use `markSafe()`.
211
-
212
- **Example**:
213
- ```javascript
214
- const { SafeString } = require('miki-template');
215
-
216
- const html = new SafeString('<b>Bold</b>');
217
- // {{ html }} renders as <b>Bold</b>, NOT &lt;b&gt;Bold&lt;/b&gt;
218
- ```
219
-
220
- ---
221
-
222
- ### `markSafe(value)`
223
-
224
- Wraps any value in a `SafeString`, instructing the engine to skip HTML escaping for that value.
225
-
226
- **Parameters**:
227
- - `value` (any): Value to mark as safe.
228
-
229
- **Returns**: `SafeString`.
230
-
231
- **Example**:
232
- ```javascript
233
- const { markSafe } = require('miki-template');
234
-
235
- const html = markSafe('<script>alert("xss")</script>');
236
- // {{ html }} outputs the script tag literally (use with caution)
237
- ```
238
-
239
- ---
240
-
241
- ### `isSafe(value)`
242
-
243
- Checks whether a value is a `SafeString` instance.
244
-
245
- **Parameters**:
246
- - `value` (any): Value to check.
247
-
248
- **Returns**: `boolean`.
249
-
250
- ---
251
-
252
- ### `escapeHtml(str)`
253
-
254
- Programmatically escapes HTML special characters (`<`, `>`, `&`, `"`, `'`).
255
-
256
- **Parameters**:
257
- - `str` (string): String to escape.
258
-
259
- **Returns**: `string`.
260
-
261
- ---
262
-
263
- ### `clearCache()`
264
-
265
- Clears the in-memory AST cache. Useful for development or when templates change at runtime.
266
-
267
- **Example**:
268
- ```javascript
269
- const { clearCache } = require('miki-template');
270
-
271
- app.on('restart', () => clearCache());
272
- ```
273
-
274
- ---
275
-
276
- ## Compiled Template API
277
-
278
- `compile()` returns an object with these methods:
279
-
280
- ### `compiled.render(context)`
281
-
282
- Synchronously renders the template with the given context.
283
-
284
- ```javascript
285
- const compiled = compile('Hello {{ name }}!');
286
- compiled.render({ name: 'World' }); // "Hello World!"
287
- ```
288
-
289
- ### `compiled.asyncRender(context)`
290
-
291
- Renders asynchronously, awaiting any Promise-returning helpers.
292
-
293
- ```javascript
294
- const html = await compiled.asyncRender({ name: 'Async' });
295
- ```
296
-
297
- ### `compiled.renderBlock(blockName, context)`
298
-
299
- Renders **only** the named block. Useful for HTMX or AJAX partial responses.
300
-
301
- ```javascript
302
- // Template: {% extends "base.html" %}
303
- // {% block content %}Main{% endblock %}
304
- compiled.renderBlock('content', {}); // "Main"
305
- ```
306
-
307
- ### `compiled.renderPartial(partialName, context)`
308
-
309
- Renders a `{% partialdef %}` block by name.
310
-
311
- ```javascript
312
- // Template: {% partialdef header %}My Header{% endpartialdef %}
313
- compiled.renderPartial('header', {}); // "My Header"
314
- ```
1
+ # API Reference - miki-template
2
+
3
+ This document provides complete details for the public APIs exported by the **miki-template** engine — a Django-style template engine for Node.js and Express.
4
+
5
+ ---
6
+
7
+ ## Core Exports
8
+
9
+ ```javascript
10
+ const {
11
+ compile,
12
+ render,
13
+ asyncRender,
14
+ __express,
15
+ clearCache,
16
+ registerTag,
17
+ registerFilter,
18
+ registerHelper,
19
+ registerContextProcessor,
20
+ SafeString,
21
+ markSafe,
22
+ isSafe,
23
+ escapeHtml
24
+ } = require('miki-template');
25
+ ```
26
+
27
+ ---
28
+
29
+ ### `compile(templateStr, options)`
30
+
31
+ Compiles a raw template string into a reusable compiled template object. The compiled template caches its AST internally.
32
+
33
+ **Parameters**:
34
+ - `templateStr` (string): The raw template string to compile.
35
+ - `options` (object): Config parameters:
36
+ - `views` (string|string[]): Directories to search for templates when using `extends` or `include`.
37
+ - `staticUrl` (string): Prefix for the `{% static %}` tag. Defaults to `/static/`.
38
+ - `urlHelper` (function): Custom URL resolver for `{% url %}` tag.
39
+
40
+ **Returns**: An object containing:
41
+ - `render(context)` — Synchronously renders the template.
42
+ - `asyncRender(context)` — Returns a Promise for async rendering.
43
+ - `renderBlock(blockName, context)` — Renders a specific block by name.
44
+ - `renderPartial(partialName, context)` — Renders a defined partial by name.
45
+
46
+ **Example**:
47
+ ```javascript
48
+ const { compile } = require('miki-template');
49
+
50
+ const template = compile('Hello {{ name }}!');
51
+ const output = template.render({ name: 'World' });
52
+ console.log(output); // Hello World!
53
+ ```
54
+
55
+ ---
56
+
57
+ ### `render(templateStr, context, options)`
58
+
59
+ One-step convenience function that compiles and renders a template.
60
+
61
+ **Parameters**:
62
+ - `templateStr` (string): Raw template string.
63
+ - `context` (object): Variables available to the template.
64
+ - `options` (object): Same as `compile()` options.
65
+
66
+ **Returns**: Rendered HTML string.
67
+
68
+ ---
69
+
70
+ ### `asyncRender(templateStr, context, options)`
71
+
72
+ Asynchronous rendering for templates with async helpers or async context processors.
73
+
74
+ **Parameters**: Same as `render()`.
75
+
76
+ **Returns**: `Promise<string>` — resolved rendered HTML.
77
+
78
+ **Example**:
79
+ ```javascript
80
+ const { asyncRender } = require('miki-template');
81
+ const html = await asyncRender('Hello {{ name }}!', { name: 'Async' });
82
+ ```
83
+
84
+ ---
85
+
86
+ ### `__express(filePath, options, callback)`
87
+
88
+ Express-compatible view engine adapter. Use with `app.engine()`.
89
+
90
+ **Parameters**:
91
+ - `filePath` (string): Absolute path to the template file.
92
+ - `options` (object): Express `res.render()` context (view engine strips `_locals`, `settings`, and other Express internals).
93
+ - `callback` (function): Node.js callback `(err, html)`.
94
+
95
+ **Example**:
96
+ ```javascript
97
+ const express = require('express');
98
+ const { __express } = require('miki-template');
99
+
100
+ const app = express();
101
+ app.engine('html', __express);
102
+ app.set('view engine', 'html');
103
+ app.set('views', './views');
104
+
105
+ app.get('/', (req, res) => {
106
+ res.render('home', { title: 'Home Page' });
107
+ });
108
+ ```
109
+
110
+ ---
111
+
112
+ ### `registerTag(name, parserFn)`
113
+
114
+ Registers a custom block tag parser. Must be called **before** compiling templates that use the tag.
115
+
116
+ **Parameters**:
117
+ - `name` (string): Tag identifier word (e.g. `mytag` for `{% mytag %}`).
118
+ - `parserFn` (function): `(tagContent: string, parser: Parser) => ASTNode`. Receives the raw tag content and the parser instance.
119
+
120
+ **Returns**: `undefined`.
121
+
122
+ **Example**:
123
+ ```javascript
124
+ const { registerTag } = require('miki-template');
125
+
126
+ registerTag('greet', (tagContent, parser) => {
127
+ const name = tagContent.slice(5).trim(); // strip 'greet'
128
+ return {
129
+ render: (context) => `Hello ${context.get(name) || 'Guest'}!`
130
+ };
131
+ });
132
+
133
+ // In template: {% greet user.name %}
134
+ ```
135
+
136
+ ---
137
+
138
+ ### `registerFilter(name, filterFn)`
139
+
140
+ Registers a custom filter function.
141
+
142
+ **Parameters**:
143
+ - `name` (string): Filter name used after the pipe `|`.
144
+ - `filterFn` (function): `(value: any, arg?: any) => any`. Receives the filtered value and optional argument.
145
+
146
+ **Returns**: `undefined`.
147
+
148
+ **Example**:
149
+ ```javascript
150
+ const { registerFilter } = require('miki-template');
151
+
152
+ registerFilter('reverse', (val) => {
153
+ return String(val).split('').reverse().join('');
154
+ });
155
+
156
+ // In template: {{ name|reverse }}
157
+ ```
158
+
159
+ ---
160
+
161
+ ### `registerHelper(name, fn)`
162
+
163
+ Registers a custom block helper tag. The helper receives the **rendered** inner content as a string.
164
+
165
+ **Parameters**:
166
+ - `name` (string): Tag name (e.g. `markdown` creates `{% markdown %}...{% endmarkdown %}`).
167
+ - `fn` (function): `(innerContent: string, context: Context) => string | Promise<string>`.
168
+
169
+ **Returns**: `undefined`.
170
+
171
+ **Example**:
172
+ ```javascript
173
+ const { registerHelper } = require('miki-template');
174
+ const markdownIt = require('markdown-it')();
175
+ registerHelper('markdown', (content) => markdownIt.render(content));
176
+
177
+ // In template:
178
+ // {% markdown %}
179
+ // # Hello
180
+ // {% endmarkdown %}
181
+ ```
182
+
183
+ ---
184
+
185
+ ### `registerContextProcessor(fn)`
186
+
187
+ Adds a context processor function. Similar to Django's custom context processors.
188
+
189
+ **Parameters**:
190
+ - `fn` (function): `(context: object) => object | undefined`. Receives the render context and returns extra key-value pairs to merge in.
191
+
192
+ **Returns**: `undefined`.
193
+
194
+ **Example**:
195
+ ```javascript
196
+ const { registerContextProcessor } = require('miki-template');
197
+
198
+ registerContextProcessor((ctx) => ({
199
+ siteName: 'MySite',
200
+ currentYear: new Date().getFullYear()
201
+ }));
202
+
203
+ // Available in all templates as {{ siteName }} and {{ currentYear }}
204
+ ```
205
+
206
+ ---
207
+
208
+ ### `SafeString`
209
+
210
+ Class for values that should **bypass HTML auto-escaping**. Construct directly or use `markSafe()`.
211
+
212
+ **Example**:
213
+ ```javascript
214
+ const { SafeString } = require('miki-template');
215
+
216
+ const html = new SafeString('<b>Bold</b>');
217
+ // {{ html }} renders as <b>Bold</b>, NOT &lt;b&gt;Bold&lt;/b&gt;
218
+ ```
219
+
220
+ ---
221
+
222
+ ### `markSafe(value)`
223
+
224
+ Wraps any value in a `SafeString`, instructing the engine to skip HTML escaping for that value.
225
+
226
+ **Parameters**:
227
+ - `value` (any): Value to mark as safe.
228
+
229
+ **Returns**: `SafeString`.
230
+
231
+ **Example**:
232
+ ```javascript
233
+ const { markSafe } = require('miki-template');
234
+
235
+ const html = markSafe('<script>alert("xss")</script>');
236
+ // {{ html }} outputs the script tag literally (use with caution)
237
+ ```
238
+
239
+ ---
240
+
241
+ ### `isSafe(value)`
242
+
243
+ Checks whether a value is a `SafeString` instance.
244
+
245
+ **Parameters**:
246
+ - `value` (any): Value to check.
247
+
248
+ **Returns**: `boolean`.
249
+
250
+ ---
251
+
252
+ ### `escapeHtml(str)`
253
+
254
+ Programmatically escapes HTML special characters (`<`, `>`, `&`, `"`, `'`).
255
+
256
+ **Parameters**:
257
+ - `str` (string): String to escape.
258
+
259
+ **Returns**: `string`.
260
+
261
+ ---
262
+
263
+ ### `clearCache()`
264
+
265
+ Clears the in-memory AST cache. Useful for development or when templates change at runtime.
266
+
267
+ **Example**:
268
+ ```javascript
269
+ const { clearCache } = require('miki-template');
270
+
271
+ app.on('restart', () => clearCache());
272
+ ```
273
+
274
+ ---
275
+
276
+ ## Compiled Template API
277
+
278
+ `compile()` returns an object with these methods:
279
+
280
+ ### `compiled.render(context)`
281
+
282
+ Synchronously renders the template with the given context.
283
+
284
+ ```javascript
285
+ const compiled = compile('Hello {{ name }}!');
286
+ compiled.render({ name: 'World' }); // "Hello World!"
287
+ ```
288
+
289
+ ### `compiled.asyncRender(context)`
290
+
291
+ Renders asynchronously, awaiting any Promise-returning helpers.
292
+
293
+ ```javascript
294
+ const html = await compiled.asyncRender({ name: 'Async' });
295
+ ```
296
+
297
+ ### `compiled.renderBlock(blockName, context)`
298
+
299
+ Renders **only** the named block. Useful for HTMX or AJAX partial responses.
300
+
301
+ ```javascript
302
+ // Template: {% extends "base.html" %}
303
+ // {% block content %}Main{% endblock %}
304
+ compiled.renderBlock('content', {}); // "Main"
305
+ ```
306
+
307
+ ### `compiled.renderPartial(partialName, context)`
308
+
309
+ Renders a `{% partialdef %}` block by name.
310
+
311
+ ```javascript
312
+ // Template: {% partialdef header %}My Header{% endpartialdef %}
313
+ compiled.renderPartial('header', {}); // "My Header"
314
+ ```