miki-template 1.3.6 → 2.0.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/.eslintrc.json +16 -0
- package/.github/release-notes/v1.3.7.md +20 -0
- package/API_REFERENCE.md +27 -0
- package/README.md +10 -0
- package/benchmarks/report.json +3 -3
- package/docs/api.md +3 -0
- package/docs/overview.md +22 -0
- package/ex.mjs +4 -1
- package/live-test/package-lock.json +915 -0
- package/live-test/package.json +9 -0
- package/live-test/packages/product/templates/product/detail.html +7 -0
- package/live-test/server.js +38 -0
- package/live-test/templates/app_templates/detail.html +6 -0
- package/live-test/views/base.html +8 -0
- package/live-test/views/child.html +7 -0
- package/live-test/views/index.html +1 -0
- package/miki-template-extension/extension.js +3 -3
- package/package.json +12 -9
- package/src/esm.mjs +5 -0
- package/src/index.js +279 -7
- package/tests/finder-appdirs.test.js +19 -0
- package/tests/finder.test.js +17 -0
- package/tests/fixtures/views/nested/index.html +1 -0
- package/tests/fixtures/views/partial.html +1 -0
- package/tests/fixtures/views/sub/deepfile.html +1 -0
- package/tests/fixtures/views-appdirs/product/site/detail.html +1 -0
- package/tests/integration/finder.esm.test.mjs +13 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"node": true,
|
|
4
|
+
"es2024": true
|
|
5
|
+
},
|
|
6
|
+
"extends": "eslint:recommended",
|
|
7
|
+
"parserOptions": {
|
|
8
|
+
"ecmaVersion": "latest",
|
|
9
|
+
"sourceType": "module"
|
|
10
|
+
},
|
|
11
|
+
"rules": {
|
|
12
|
+
"no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
|
|
13
|
+
"no-console": "off",
|
|
14
|
+
"semi": ["error", "always"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## v1.3.7 — Template discovery improvements
|
|
2
|
+
|
|
3
|
+
- Add recursive/app-style template discovery so projects can place
|
|
4
|
+
templates in nested `templates/` folders (Django-style) and have
|
|
5
|
+
them discovered automatically.
|
|
6
|
+
- `setupExpress` now expands `app.get('views')` to include nested
|
|
7
|
+
directories that contain template files so `res.render('name')`
|
|
8
|
+
works for templates located in project-level or package-level
|
|
9
|
+
`templates/` directories.
|
|
10
|
+
- Expose `findTemplateInViews(name, roots)` helper and
|
|
11
|
+
`setAppTemplateDirNames()/getAppTemplateDirNames()` to configure
|
|
12
|
+
app-style template folder names.
|
|
13
|
+
- Improve `res.render` fallback to use the recursive finder before
|
|
14
|
+
throwing Express's "Failed to lookup view" error.
|
|
15
|
+
- Update docs and API reference with usage examples and migration
|
|
16
|
+
notes.
|
|
17
|
+
|
|
18
|
+
CI: runs lint + tests (all passing locally). If you'd like a more
|
|
19
|
+
comprehensive changelog, I can expand this with links to issues and
|
|
20
|
+
code snippets.
|
package/API_REFERENCE.md
CHANGED
|
@@ -107,6 +107,33 @@ app.get('/', (req, res) => {
|
|
|
107
107
|
});
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
### Template discovery helpers
|
|
111
|
+
|
|
112
|
+
`miki-template` exposes helpers to discover templates across multiple
|
|
113
|
+
`views` roots and to configure what directory names are considered
|
|
114
|
+
app-style template folders (e.g. `templates` or `app_templates`). These
|
|
115
|
+
are useful for projects that place templates in nested app folders or
|
|
116
|
+
package-level `templates/` directories.
|
|
117
|
+
|
|
118
|
+
#### `findTemplateInViews(name, viewsDirs)`
|
|
119
|
+
|
|
120
|
+
Search for a template by `name` across the provided `viewsDirs` array
|
|
121
|
+
or single string. Performs direct resolution first, then a recursive
|
|
122
|
+
search for bare filenames. Returns the absolute file path or `null`.
|
|
123
|
+
|
|
124
|
+
Example:
|
|
125
|
+
```js
|
|
126
|
+
const found = require('miki-template').findTemplateInViews('detail', ['./views', './templates']);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### `setAppTemplateDirNames(names)` / `getAppTemplateDirNames()`
|
|
130
|
+
|
|
131
|
+
Configure and retrieve the directory names treated as app-style
|
|
132
|
+
template folders when scanning the project tree. The default is
|
|
133
|
+
`['templates']`. Use `setAppTemplateDirNames(['templates','app_templates'])`
|
|
134
|
+
to include additional conventions.
|
|
135
|
+
|
|
136
|
+
|
|
110
137
|
---
|
|
111
138
|
|
|
112
139
|
### `registerTag(name, parserFn)`
|
package/README.md
CHANGED
|
@@ -132,6 +132,16 @@ app.listen(3000);
|
|
|
132
132
|
|
|
133
133
|
> `setupExpress` calls `app.engine()`, `app.set('views')`, and `app.set('view engine')` for you, and patches `res.render` so `view#partial` is dispatched to the partial renderer (not the file system). It works equally well for `.miki` files — just pass `extension: 'miki'`.
|
|
134
134
|
|
|
135
|
+
Note on template discovery: `setupExpress` now expands the `app.get('views')`
|
|
136
|
+
value to include nested directories that contain template files. This
|
|
137
|
+
means templates placed in project-level `templates/`, package-level
|
|
138
|
+
`packages/*/templates/...`, or app-specific folders (e.g. `app_templates/`)
|
|
139
|
+
will be discovered automatically when calling `res.render('name')`.
|
|
140
|
+
|
|
141
|
+
If your project uses a different convention than `templates`, call
|
|
142
|
+
`setAppTemplateDirNames()` to customize the names that the engine
|
|
143
|
+
recognizes when scanning for app-style template folders.
|
|
144
|
+
|
|
135
145
|
**The classic, fully manual setup still works** if you prefer it:
|
|
136
146
|
|
|
137
147
|
```javascript
|
package/benchmarks/report.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "small",
|
|
4
|
-
"syncAvgMs": "0.
|
|
4
|
+
"syncAvgMs": "0.01",
|
|
5
5
|
"asyncAvgMs": "0.03"
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "medium",
|
|
9
|
-
"syncAvgMs": "0.
|
|
9
|
+
"syncAvgMs": "0.01",
|
|
10
10
|
"asyncAvgMs": "0.01"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "large",
|
|
14
|
-
"syncAvgMs": "0.
|
|
14
|
+
"syncAvgMs": "0.01",
|
|
15
15
|
"asyncAvgMs": "0.01"
|
|
16
16
|
}
|
|
17
17
|
]
|
package/docs/api.md
CHANGED
|
@@ -12,6 +12,9 @@ This document lists the public API exported by **miki-template** for developers
|
|
|
12
12
|
| `express(options?)` | `express(object?) → function` | Factory that returns a view-engine function suitable for `app.engine(...)`. Honors `view#partial` selectors. | `app.engine('html', miki.express());` |
|
|
13
13
|
| `setupExpress(app, opts?)` | `setupExpress(expressApp, object?) → void` | **One-line Express integration.** Wires `app.engine(...)`, `app.set('views')`, and patches `res.render` so `res.render('view#partial', ...)` returns just that partial. Options: `{ extension?, views?, async? }`. | `miki.setupExpress(app, { extension: 'html', views: './views' });` |
|
|
14
14
|
| `expressPartialRenderer()` | `expressPartialRenderer() → function` | Express middleware that adds `res.renderPartial(view, locals)`. Useful as a drop-in HTMX helper without the full `setupExpress` shim. | `app.use(miki.expressPartialRenderer());` |
|
|
15
|
+
| `findTemplateInViews(name, viewsDirs)` | `findTemplateInViews(string, string[]|string) → string|null` | Search for a template by name across one or more `views` roots. Performs direct resolution first (supports explicit paths and extensions), then a recursive search for bare filenames in subdirectories. Returns the absolute file path or `null` if not found. | `miki.findTemplateInViews('detail', ['./views', './templates'])` |
|
|
16
|
+
| `setAppTemplateDirNames(names)` | `setAppTemplateDirNames(string[]|string) → void` | Configure which directory names are treated as app-style template folders when scanning (default: `['templates']`). Useful when projects use a different convention. | `miki.setAppTemplateDirNames(['templates','app_templates'])` |
|
|
17
|
+
| `getAppTemplateDirNames()` | `getAppTemplateDirNames() → string[]` | Retrieve the current configured app-template directory names. | `const names = miki.getAppTemplateDirNames()` |
|
|
15
18
|
| `renderPartialFromFile(filePath, partialName, context?, options?)` | `renderPartialFromFile(string, string, object?, object?) → string` | Load a file from disk and render only the named `{% partialdef %}`. | `miki.renderPartialFromFile('views/home.html', 'card', { user });` |
|
|
16
19
|
| `renderPartialFromSource(source, partialName, context?, options?)` | `renderPartialFromSource(string, string, object?, object?) → string` | Render a single named partial directly from a template string. Walks the AST (and `extends` chain) to discover partials nested inside blocks. | `miki.renderPartialFromSource(src, 'card', ctx, { views });` |
|
|
17
20
|
| `stripExpressContext(options)` | `stripExpressContext(object) → object` | Remove Express framework keys (`_locals`, `settings`, `cache`) from an options object. | `const ctx = stripExpressContext(res.locals);` |
|
package/docs/overview.md
CHANGED
|
@@ -44,6 +44,28 @@ Each module is deliberately **single‑responsibility** and fully typed via JSDo
|
|
|
44
44
|
- **Partial definitions** – see `docs/partialdef.md`.
|
|
45
45
|
- **Security considerations** – see `docs/security.md`.
|
|
46
46
|
|
|
47
|
+
## Recursive and app-style template discovery
|
|
48
|
+
|
|
49
|
+
`miki-template` now supports Django-style recursive template discovery. When you configure your views directory (via `miki.setupExpress(app, { views: './views' })` or by passing `views` to `render()`), the engine will:
|
|
50
|
+
|
|
51
|
+
- Resolve direct paths like `nested/index` relative to each `views` directory.
|
|
52
|
+
- If a bare template name (e.g. `card`) is used, recursively scan subfolders of the configured `views` directories to find `card.html` or `card.miki`.
|
|
53
|
+
- Discover app-style `templates` directories located under application packages (e.g. `project/apps/product/templates/...`) and include them in the search.
|
|
54
|
+
|
|
55
|
+
Configuration:
|
|
56
|
+
|
|
57
|
+
- Programmatically set which folder names should be treated as app template roots via the API:
|
|
58
|
+
|
|
59
|
+
- `setAppTemplateDirNames(['templates', 'site_templates'])` — sets the list of folder names that will be discovered under the views root.
|
|
60
|
+
- `getAppTemplateDirNames()` — returns the current list.
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
|
|
64
|
+
- `render('home#card', ctx, { views: './views' })` will search `./views` and any `templates/` subfolders for `home.html` or `home.miki`, and render the `card` partial.
|
|
65
|
+
- If your project places templates under `packages/product/templates/detail.html`, `render('detail', ..., { views: './views' })` will find it automatically.
|
|
66
|
+
|
|
67
|
+
This behavior is opt‑out by simply clearing the app-dir names: `setAppTemplateDirNames([])` will disable app-style discovery.
|
|
68
|
+
|
|
47
69
|
For API‑level details (e.g., `compile().renderPartial`) check `docs/api.md`.
|
|
48
70
|
|
|
49
71
|
---
|
package/ex.mjs
CHANGED
|
@@ -10,6 +10,8 @@ const dir=path.join(process.cwd(),"dir")
|
|
|
10
10
|
// app.set('views', dir);
|
|
11
11
|
miki.setupExpress(app, { extension: 'html', views: dir });
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
|
|
13
15
|
// registerContextProcessor((cx)=>({
|
|
14
16
|
// siteName:"code with miki",
|
|
15
17
|
// login:{'name':"miki", 'email':"miki@example.com"}
|
|
@@ -24,10 +26,11 @@ const dir=path.join(process.cwd(),"dir")
|
|
|
24
26
|
{name:"miki", email:"jack@miki.com",address:"kumba"},
|
|
25
27
|
{name:"luis",email:"luis@miki.com",address:"kumba"}
|
|
26
28
|
]
|
|
27
|
-
res.render("index",{name:"miki-template context", users:users, data:data})
|
|
29
|
+
res.render("index#card",{name:"miki-template context", users:users, data:data})
|
|
28
30
|
// res.send(content)
|
|
29
31
|
})
|
|
30
32
|
|
|
33
|
+
|
|
31
34
|
app.listen(3000, () => {
|
|
32
35
|
console.log('Server is running on port 3000 click: http://localhost:3000')
|
|
33
36
|
} )
|