miki-template 2.0.1 → 2.2.2

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 (71) hide show
  1. package/.github/workflows/ci.yml +13 -37
  2. package/.github/workflows/docs.yml +105 -0
  3. package/.github/workflows/npm-publish-github-packages.yml +36 -0
  4. package/README.md +69 -14
  5. package/assets/logo.png +0 -0
  6. package/benchmarks/ejs-results.json +4 -4
  7. package/benchmarks/handlebars-results.json +6 -6
  8. package/benchmarks/miki-results.json +4 -4
  9. package/benchmarks/pug-results.json +4 -4
  10. package/benchmarks/stress.mjs +1 -1
  11. package/docs/api/async-render.md +85 -0
  12. package/docs/api/cache.md +87 -0
  13. package/docs/api/compile.md +128 -0
  14. package/docs/api/context-processors.md +77 -0
  15. package/docs/api/filters.md +217 -0
  16. package/docs/api/finder.md +94 -0
  17. package/docs/api/helpers.md +53 -0
  18. package/docs/api/i18n.md +157 -0
  19. package/docs/api/index.md +54 -0
  20. package/docs/api/libraries.md +207 -0
  21. package/docs/api/render-partial.md +81 -0
  22. package/docs/api/render.md +92 -0
  23. package/docs/api/security.md +145 -0
  24. package/docs/api/setup-express.md +76 -0
  25. package/docs/api/tags.md +134 -0
  26. package/docs/assets/banner.png +0 -0
  27. package/docs/assets/logo.png +0 -0
  28. package/docs/guide/advanced-usage.md +397 -0
  29. package/docs/guide/async-rendering.md +308 -0
  30. package/docs/guide/context-processors.md +257 -0
  31. package/docs/guide/custom-filters.md +311 -0
  32. package/docs/guide/custom-tags.md +271 -0
  33. package/docs/guide/filters.md +642 -0
  34. package/docs/guide/getting-started.md +102 -0
  35. package/docs/guide/installation.md +95 -0
  36. package/docs/guide/partial-templates.md +367 -0
  37. package/docs/guide/quick-start.md +222 -0
  38. package/docs/guide/security.md +345 -0
  39. package/docs/guide/tags.md +783 -0
  40. package/docs/guide/template-discovery.md +170 -0
  41. package/docs/guide/template-inheritance.md +273 -0
  42. package/docs/guide/what-is-miki-template.md +28 -0
  43. package/docs/guide/why-miki-template.md +75 -0
  44. package/docs/index.md +104 -0
  45. package/docs/integrations/elysia.md +78 -0
  46. package/docs/integrations/express.md +219 -0
  47. package/docs/integrations/fastify.md +77 -0
  48. package/docs/integrations/hono.md +78 -0
  49. package/docs/integrations/index.md +68 -0
  50. package/docs/integrations/koa.md +88 -0
  51. package/docs/integrations/nestjs.md +78 -0
  52. package/docs/integrations/tsed.md +81 -0
  53. package/docs/javascripts/extra.js +174 -0
  54. package/docs/performance.md +37 -0
  55. package/docs/stylesheets/extra.css +819 -0
  56. package/mkdocs.yml +217 -0
  57. package/overrides/main.html +26 -0
  58. package/overrides/partials/footer.html +9 -0
  59. package/package.json +4 -2
  60. package/requirements-docs.txt +1 -0
  61. package/docs/README.md +0 -18
  62. package/docs/advanced_usage.md +0 -71
  63. package/docs/api.md +0 -122
  64. package/docs/filters.md +0 -708
  65. package/docs/installation.md +0 -106
  66. package/docs/integrations.md +0 -214
  67. package/docs/overview.md +0 -79
  68. package/docs/partialdef.md +0 -70
  69. package/docs/security.md +0 -27
  70. package/docs/tags.md +0 -673
  71. package/docs/usage.md +0 -646
@@ -0,0 +1,157 @@
1
+ # i18n API
2
+
3
+ ## registerTranslation
4
+
5
+ Register translations for a language. Keys match the `{% trans "text" %}` source string.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { registerTranslation } = require('miki-template');
11
+
12
+ registerTranslation('en', {
13
+ hello: 'Hello',
14
+ goodbye: 'Goodbye'
15
+ });
16
+ ```
17
+
18
+ === "ES Modules"
19
+
20
+ ```javascript
21
+ import { registerTranslation } from 'miki-template';
22
+
23
+ registerTranslation('en', {
24
+ hello: 'Hello',
25
+ goodbye: 'Goodbye'
26
+ });
27
+ ```
28
+
29
+ You can also register nested keys for `blocktrans` with variables:
30
+
31
+ === "CommonJS"
32
+
33
+ ```javascript
34
+ const { registerTranslation, setLanguage } = require('miki-template');
35
+
36
+ setLanguage('en');
37
+ registerTranslation('en', {
38
+ 'Welcome, {name}!': 'Welcome, {name}!',
39
+ 'Goodbye, {name}!': 'Goodbye, {name}!'
40
+ });
41
+ ```
42
+
43
+ === "ES Modules"
44
+
45
+ ```javascript
46
+ import { registerTranslation, setLanguage } from 'miki-template';
47
+
48
+ setLanguage('en');
49
+ registerTranslation('en', {
50
+ 'Welcome, {name}!': 'Welcome, {name}!',
51
+ 'Goodbye, {name}!': 'Goodbye, {name}!'
52
+ });
53
+ ```
54
+
55
+ ## unregisterTranslation
56
+
57
+ === "CommonJS"
58
+
59
+ ```javascript
60
+ const { unregisterTranslation } = require('miki-template');
61
+
62
+ // Unregister a specific key
63
+ unregisterTranslation('en', 'hello');
64
+
65
+ // Unregister entire language
66
+ unregisterTranslation('en');
67
+
68
+ // Unregister all translations
69
+ unregisterTranslation();
70
+ ```
71
+
72
+ === "ES Modules"
73
+
74
+ ```javascript
75
+ import { unregisterTranslation } from 'miki-template';
76
+
77
+ unregisterTranslation('en', 'hello');
78
+ ```
79
+
80
+ ## setLanguage / getLanguage
81
+
82
+ Set or get the active language.
83
+
84
+ === "CommonJS"
85
+
86
+ ```javascript
87
+ const { setLanguage, getLanguage } = require('miki-template');
88
+
89
+ setLanguage('fr');
90
+ console.log(getLanguage()); // 'fr'
91
+ ```
92
+
93
+ === "ES Modules"
94
+
95
+ ```javascript
96
+ import { setLanguage, getLanguage } from 'miki-template';
97
+
98
+ setLanguage('fr');
99
+ console.log(getLanguage()); // 'fr'
100
+ ```
101
+
102
+ ## setFallbackLanguage / getFallbackLanguage
103
+
104
+ Set or get the fallback language (used when a key is missing from the active language).
105
+
106
+ === "CommonJS"
107
+
108
+ ```javascript
109
+ const { setFallbackLanguage, getFallbackLanguage } = require('miki-template');
110
+
111
+ setFallbackLanguage('en');
112
+ console.log(getFallbackLanguage()); // 'en'
113
+ ```
114
+
115
+ === "ES Modules"
116
+
117
+ ```javascript
118
+ import { setFallbackLanguage, getFallbackLanguage } from 'miki-template';
119
+
120
+ setFallbackLanguage('en');
121
+ ```
122
+
123
+ ## getAvailableLanguages
124
+
125
+ List all registered languages.
126
+
127
+ === "CommonJS"
128
+
129
+ ```javascript
130
+ const { getAvailableLanguages } = require('miki-template');
131
+
132
+ console.log(getAvailableLanguages());
133
+ // ['en', 'fr', 'es']
134
+ ```
135
+
136
+ === "ES Modules"
137
+
138
+ ```javascript
139
+ import { getAvailableLanguages } from 'miki-template';
140
+
141
+ console.log(getAvailableLanguages());
142
+ ```
143
+
144
+ ## Template Tags
145
+
146
+ The `{% trans %}` and `{% blocktrans %}` tags are provided by the auto-activated `i18n` library:
147
+
148
+ ```html
149
+ {% trans "Hello" %}
150
+ {% blocktrans %}Welcome, {{ name }}!{% endblocktrans %}
151
+ {% language "fr" %}...{% endlanguage %}
152
+ ```
153
+
154
+ ## Next Steps
155
+
156
+ - [Advanced Usage: i18n](../guide/advanced-usage#i18n--internationalization)
157
+ - [API Reference](../)
@@ -0,0 +1,54 @@
1
+ # API Reference
2
+
3
+ ## Core Functions
4
+
5
+ - [render()](./render) — Render a template string or file partial
6
+ - [compile()](./compile) — Compile a template into a reusable object with `render()`, `asyncRender()`, `renderBlock()`, `renderPartial()`
7
+ - [asyncRender()](./async-render) — Asynchronous rendering (supports async filters/tags)
8
+ - [renderPartialFromFile()](./render-partial) — Render a named partial from a file
9
+ - [renderPartialFromSource()](./render-partial) — Render a named partial from source
10
+ - [setupExpress()](./setup-express) — One-line Express integration
11
+
12
+ ## Tag and Filter Registration
13
+
14
+ - [registerFilter()](./filters) — Register a custom filter
15
+ - [getFilter()](./filters) — Retrieve a registered filter
16
+ - [registerTag()](./tags) — Register a custom tag
17
+ - [registerHelper()](./helpers) — Register a custom helper
18
+
19
+ ## Utilities
20
+
21
+ - [findTemplateInViews()](./finder) — Locate a template in views directories
22
+ - [setAppTemplateDirNames()](./finder) — Configure app-style template directory names
23
+ - [clearCache()](./cache) — Clear the compiled template cache
24
+ - [registerContextProcessor()](./context-processors) — Register a global context processor
25
+ - [clearContextProcessors()](./context-processors) — Clear all context processors
26
+
27
+ ## Security
28
+
29
+ - [markSafe()](./security) — Mark a string as safe (bypass escaping)
30
+ - [isSafe()](./security) — Check if a value is marked safe
31
+ - [escapeHtml()](./security) — Escape HTML special characters
32
+ - [SafeString](./security) — SafeString class
33
+
34
+ ## Express Engine Functions
35
+
36
+ - `__express(filePath, options, callback)` — Express-compatible sync view engine
37
+ - `__expressAsync(filePath, options)` — Express 5 async view engine (returns Promise)
38
+ - `express(options)` — Returns a view engine function for `app.engine()`
39
+ - `expressPartialRenderer()` — Express middleware adding `res.renderPartial()`
40
+ - `stripExpressContext(options)` — Remove Express framework keys from context
41
+
42
+ ## i18n
43
+
44
+ - [registerTranslation()](./i18n) — Register translations for a language
45
+ - [unregisterTranslation()](./i18n) — Unregister translations
46
+ - [setLanguage()](./i18n) / [getLanguage()](./i18n) — Set/get active language
47
+ - [setFallbackLanguage()](./i18n) / [getFallbackLanguage()](./i18n) — Set/get fallback language
48
+ - [getAvailableLanguages()](./i18n) — List registered languages
49
+
50
+ ## Libraries
51
+
52
+ - [registerLibrary()](./libraries) — Register a named library (filters, tags, helpers)
53
+ - [activateLibrary()](./libraries) / [registerLibraryFromPath()](./libraries) — Activate or load from file
54
+ - [unregisterLibrary()](./libraries) / [hasLibrary()](./libraries) / [getLibraryNames()](./libraries) — Library management
@@ -0,0 +1,207 @@
1
+ # Libraries API
2
+
3
+ ## registerLibrary
4
+
5
+ Register a library — a named bundle of filters, tags, and helpers.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { registerLibrary } = require('miki-template');
11
+
12
+ registerLibrary('mylib', {
13
+ filters: {
14
+ shout: (val) => String(val).toUpperCase() + '!'
15
+ },
16
+ tags: {
17
+ hello: (tagContent, parser) => ({
18
+ render: (context) => 'Hello!'
19
+ })
20
+ },
21
+ helpers: {
22
+ bold: (inner, context) => `<b>${inner}</b>`
23
+ }
24
+ });
25
+ ```
26
+
27
+ === "ES Modules"
28
+
29
+ ```javascript
30
+ import { registerLibrary } from 'miki-template';
31
+
32
+ registerLibrary('mylib', {
33
+ filters: {
34
+ shout: (val) => String(val).toUpperCase() + '!'
35
+ },
36
+ tags: {
37
+ hello: (tagContent, parser) => ({
38
+ render: (context) => 'Hello!'
39
+ })
40
+ },
41
+ helpers: {
42
+ bold: (inner, context) => `<b>${inner}</b>`
43
+ }
44
+ });
45
+ ```
46
+
47
+ ## activateLibrary
48
+
49
+ Activate a library so its filters and tags become available.
50
+
51
+ === "CommonJS"
52
+
53
+ ```javascript
54
+ const { activateLibrary } = require('miki-template');
55
+
56
+ activateLibrary('mylib');
57
+ ```
58
+
59
+ === "ES Modules"
60
+
61
+ ```javascript
62
+ import { activateLibrary } from 'miki-template';
63
+
64
+ activateLibrary('mylib');
65
+ ```
66
+
67
+ Built-in libraries (`humanize`, `cache`, `lorem`, `markdown`, `i18n`) are auto-activated on import.
68
+
69
+ ## unregisterLibrary
70
+
71
+ === "CommonJS"
72
+
73
+ ```javascript
74
+ const { unregisterLibrary } = require('miki-template');
75
+
76
+ // Unregister specific library
77
+ unregisterLibrary('mylib');
78
+
79
+ // Unregister all libraries
80
+ unregisterLibrary();
81
+ ```
82
+
83
+ === "ES Modules"
84
+
85
+ ```javascript
86
+ import { unregisterLibrary } from 'miki-template';
87
+
88
+ unregisterLibrary('mylib');
89
+ ```
90
+
91
+ ## hasLibrary
92
+
93
+ === "CommonJS"
94
+
95
+ ```javascript
96
+ const { hasLibrary } = require('miki-template');
97
+
98
+ if (hasLibrary('humanize')) {
99
+ // library is registered
100
+ }
101
+ ```
102
+
103
+ === "ES Modules"
104
+
105
+ ```javascript
106
+ import { hasLibrary } from 'miki-template';
107
+
108
+ if (hasLibrary('humanize')) {
109
+ // library is registered
110
+ }
111
+ ```
112
+
113
+ ## getLibrary
114
+
115
+ Retrieve a library by name.
116
+
117
+ === "CommonJS"
118
+
119
+ ```javascript
120
+ const { getLibrary } = require('miki-template');
121
+
122
+ const lib = getLibrary('humanize');
123
+ console.log(Object.keys(lib.filters));
124
+ ```
125
+
126
+ === "ES Modules"
127
+
128
+ ```javascript
129
+ import { getLibrary } from 'miki-template';
130
+
131
+ const lib = getLibrary('humanize');
132
+ ```
133
+
134
+ ## getLibraryNames
135
+
136
+ === "CommonJS"
137
+
138
+ ```javascript
139
+ const { getLibraryNames } = require('miki-template');
140
+
141
+ console.log(getLibraryNames());
142
+ // ['humanize', 'cache', 'lorem']
143
+ ```
144
+
145
+ === "ES Modules"
146
+
147
+ ```javascript
148
+ import { getLibraryNames } from 'miki-template';
149
+
150
+ console.log(getLibraryNames());
151
+ ```
152
+
153
+ ## registerLibraryFromPath
154
+
155
+ Load a library from a JavaScript file on disk. The file must export `{ tags, filters, helpers }`.
156
+
157
+ === "CommonJS"
158
+
159
+ ```javascript
160
+ const { registerLibraryFromPath } = require('miki-template');
161
+
162
+ registerLibraryFromPath('mylib', './libs/mylib.js');
163
+ ```
164
+
165
+ === "ES Modules"
166
+
167
+ ```javascript
168
+ import { registerLibraryFromPath } from 'miki-template';
169
+
170
+ await registerLibraryFromPath('mylib', './libs/mylib.mjs');
171
+ ```
172
+
173
+ ## Built-in Libraries
174
+
175
+ ### humanize
176
+
177
+ Provides natural formatting filters: `intcomma`, `intword`, `ordinal`, `naturalday`, `naturaltime`.
178
+
179
+ | Filter | Description |
180
+ |--------|-------------|
181
+ | `intcomma` | `1234567` → `1,234,567` |
182
+ | `intword` | `1234567` → `1.2M` |
183
+ | `ordinal` | `1` → `1st`, `2` → `2nd` |
184
+ | `naturalday` | Format dates as "today", "yesterday" |
185
+ | `naturaltime` | Format times as "just now", "2 hours ago" |
186
+ | `ordinal` | Convert numbers to ordinal (1st, 2nd, 3rd) |
187
+
188
+ ### cache
189
+
190
+ Provides `{% cache timeout key %}...{% endcache %}` tag for caching template fragments.
191
+
192
+ ### lorem
193
+
194
+ Provides `{% lorem count random_words %}` tag and `lorem` filter for placeholder text.
195
+
196
+ ### markdown
197
+
198
+ Provides `markdown` filter for Markdown→HTML conversion.
199
+
200
+ ### i18n
201
+
202
+ Provides `{% trans %}`, `{% blocktrans %}`, `{% language %}` tags and translation functions.
203
+
204
+ ## Next Steps
205
+
206
+ - [Advanced Usage: Libraries](../guide/advanced-usage#library-system)
207
+ - [API Reference](../)
@@ -0,0 +1,81 @@
1
+ # renderPartialFromFile / renderPartialFromSource
2
+
3
+ Render a named partial from a template file or source string.
4
+
5
+ ## renderPartialFromFile
6
+
7
+ Render a named partial from a template file.
8
+
9
+ ```javascript
10
+ renderPartialFromFile(fileName, partialName, contextObj, options)
11
+ ```
12
+
13
+ ### Parameters
14
+
15
+ | Parameter | Type | Description |
16
+ |-----------|------|-------------|
17
+ | `fileName` | `string` | Template file name (without extension) |
18
+ | `partialName` | `string` | Name of the partial to render |
19
+ | `contextObj` | `object` | Variables to inject |
20
+ | `options` | `object` | Options including `views` directories |
21
+
22
+ ### Example
23
+
24
+ === "CommonJS"
25
+
26
+ ```javascript
27
+ const { renderPartialFromFile } = require('miki-template');
28
+
29
+ const html = renderPartialFromFile('home', 'card', { title: 'Hello' }, { views: './views' });
30
+ ```
31
+
32
+ === "ES Modules"
33
+
34
+ ```javascript
35
+ import { renderPartialFromFile } from 'miki-template';
36
+
37
+ const html = renderPartialFromFile('home', 'card', { title: 'Hello' }, { views: './views' });
38
+ ```
39
+
40
+ ## renderPartialFromSource
41
+
42
+ Render a named partial from a template source string.
43
+
44
+ ```javascript
45
+ renderPartialFromSource(fileContent, partialName, contextObj, options, filePath?)
46
+ ```
47
+
48
+ ### Parameters
49
+
50
+ | Parameter | Type | Description |
51
+ |-----------|------|-------------|
52
+ | `fileContent` | `string` | Template source string |
53
+ | `partialName` | `string` | Name of the partial to render |
54
+ | `contextObj` | `object` | Variables to inject |
55
+ | `options` | `object` | Options |
56
+ | `filePath` | `string?` | Optional file path for error messages |
57
+
58
+ ### Example
59
+
60
+ === "CommonJS"
61
+
62
+ ```javascript
63
+ const { renderPartialFromSource } = require('miki-template');
64
+
65
+ const source = `{% partialdef card %}<div>{{ title }}</div>{% endpartialdef %}`;
66
+ const html = renderPartialFromSource(source, 'card', { title: 'Hello' });
67
+ ```
68
+
69
+ === "ES Modules"
70
+
71
+ ```javascript
72
+ import { renderPartialFromSource } from 'miki-template';
73
+
74
+ const source = `{% partialdef card %}<div>{{ title }}</div>{% endpartialdef %}`;
75
+ const html = renderPartialFromSource(source, 'card', { title: 'Hello' });
76
+ ```
77
+
78
+ ## Related
79
+
80
+ - [render()](./render)
81
+ - [compile()](./compile)
@@ -0,0 +1,92 @@
1
+ # render()
2
+
3
+ Render a template string or file partial.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ render(templateStr, contextObj = {}, options = {})
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `templateStr` | `string` | Template string or file path with `#partial` suffix |
16
+ | `contextObj` | `object` | Variables to inject into the template |
17
+ | `options` | `object` | Options including `views` directories and custom settings |
18
+
19
+ ## Returns
20
+
21
+ `string` — The rendered HTML.
22
+
23
+ ## Examples
24
+
25
+ ### Render a template string
26
+
27
+ === "CommonJS"
28
+
29
+ ```javascript
30
+ const { render } = require('miki-template');
31
+
32
+ const html = render('Hello {{ name }}!', { name: 'World' });
33
+ // Output: Hello World!
34
+ ```
35
+
36
+ === "ES Modules"
37
+
38
+ ```javascript
39
+ import { render } from 'miki-template';
40
+
41
+ const html = render('Hello {{ name }}!', { name: 'World' });
42
+ // Output: Hello World!
43
+ ```
44
+
45
+ ### Render a partial from file
46
+
47
+ === "CommonJS"
48
+
49
+ ```javascript
50
+ const { render } = require('miki-template');
51
+
52
+ const html = render('home#card', { title: 'Hello' }, { views: './views' });
53
+ ```
54
+
55
+ === "ES Modules"
56
+
57
+ ```javascript
58
+ import { render } from 'miki-template';
59
+
60
+ const html = render('home#card', { title: 'Hello' }, { views: './views' });
61
+ ```
62
+
63
+ ### Render with options
64
+
65
+ === "CommonJS"
66
+
67
+ ```javascript
68
+ const { render } = require('miki-template');
69
+
70
+ const html = render(template, context, {
71
+ views: ['./views', './app/templates'],
72
+ staticUrl: '/static',
73
+ urlHelper: (name, ...args) => '/' + name + '/' + args.join('/')
74
+ });
75
+ ```
76
+
77
+ === "ES Modules"
78
+
79
+ ```javascript
80
+ import { render } from 'miki-template';
81
+
82
+ const html = render(template, context, {
83
+ views: ['./views', './app/templates'],
84
+ staticUrl: '/static',
85
+ urlHelper: (name, ...args) => '/' + name + '/' + args.join('/')
86
+ });
87
+ ```
88
+
89
+ ## Related
90
+
91
+ - [compile()](./compile)
92
+ - [asyncRender()](./async-render)