miki-template 2.0.0 → 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.
- package/.github/workflows/ci.yml +14 -10
- package/.github/workflows/docs.yml +105 -0
- package/.github/workflows/npm-publish-github-packages.yml +36 -0
- package/README.md +142 -26
- package/assets/logo.png +0 -0
- package/benchmarks/ejs-results.json +17 -0
- package/benchmarks/ejs.js +36 -0
- package/benchmarks/handlebars-results.json +17 -0
- package/benchmarks/handlebars.js +48 -0
- package/benchmarks/miki-results.json +17 -0
- package/benchmarks/miki.js +36 -0
- package/benchmarks/pug-results.json +17 -0
- package/benchmarks/pug.js +36 -0
- package/benchmarks/run.js +69 -37
- package/benchmarks/stress.mjs +1 -1
- package/docs/api/async-render.md +85 -0
- package/docs/api/cache.md +87 -0
- package/docs/api/compile.md +128 -0
- package/docs/api/context-processors.md +77 -0
- package/docs/api/filters.md +217 -0
- package/docs/api/finder.md +94 -0
- package/docs/api/helpers.md +53 -0
- package/docs/api/i18n.md +157 -0
- package/docs/api/index.md +54 -0
- package/docs/api/libraries.md +207 -0
- package/docs/api/render-partial.md +81 -0
- package/docs/api/render.md +92 -0
- package/docs/api/security.md +145 -0
- package/docs/api/setup-express.md +76 -0
- package/docs/api/tags.md +134 -0
- package/docs/assets/banner.png +0 -0
- package/docs/assets/logo.png +0 -0
- package/docs/guide/advanced-usage.md +397 -0
- package/docs/guide/async-rendering.md +308 -0
- package/docs/guide/context-processors.md +257 -0
- package/docs/guide/custom-filters.md +311 -0
- package/docs/guide/custom-tags.md +271 -0
- package/docs/guide/filters.md +642 -0
- package/docs/guide/getting-started.md +102 -0
- package/docs/guide/installation.md +95 -0
- package/docs/guide/partial-templates.md +367 -0
- package/docs/guide/quick-start.md +222 -0
- package/docs/guide/security.md +345 -0
- package/docs/guide/tags.md +783 -0
- package/docs/guide/template-discovery.md +170 -0
- package/docs/guide/template-inheritance.md +273 -0
- package/docs/guide/what-is-miki-template.md +28 -0
- package/docs/guide/why-miki-template.md +75 -0
- package/docs/index.md +104 -0
- package/docs/integrations/elysia.md +78 -0
- package/docs/integrations/express.md +219 -0
- package/docs/integrations/fastify.md +77 -0
- package/docs/integrations/hono.md +78 -0
- package/docs/integrations/index.md +68 -0
- package/docs/integrations/koa.md +88 -0
- package/docs/integrations/nestjs.md +78 -0
- package/docs/integrations/tsed.md +81 -0
- package/docs/javascripts/extra.js +174 -0
- package/docs/performance.md +37 -0
- package/docs/stylesheets/extra.css +819 -0
- package/live-test/integrations/elysia-example.js +16 -0
- package/live-test/integrations/express-example.js +24 -0
- package/live-test/integrations/fastify-example.js +20 -0
- package/live-test/integrations/hono-example.js +16 -0
- package/live-test/integrations/koa-example.js +30 -0
- package/live-test/integrations/nestjs-example.js +25 -0
- package/live-test/integrations/smoke-test.js +166 -0
- package/live-test/integrations/tsed-example.js +23 -0
- package/live-test/package-lock.json +235 -0
- package/live-test/package.json +4 -0
- package/live-test/views/home.html +17 -0
- package/mkdocs.yml +217 -0
- package/overrides/main.html +26 -0
- package/overrides/partials/footer.html +9 -0
- package/package.json +16 -6
- package/requirements-docs.txt +1 -0
- package/tests/integration/partial-render.test.cjs +13 -0
- package/docs/README.md +0 -18
- package/docs/advanced_usage.md +0 -71
- package/docs/api.md +0 -122
- package/docs/filters.md +0 -708
- package/docs/installation.md +0 -106
- package/docs/overview.md +0 -79
- package/docs/partialdef.md +0 -70
- package/docs/security.md +0 -27
- package/docs/tags.md +0 -673
- package/docs/usage.md +0 -646
package/docs/installation.md
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# Installation
|
|
2
|
-
|
|
3
|
-
## npm
|
|
4
|
-
```bash
|
|
5
|
-
npm install miki-template
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
## Prerequisites
|
|
9
|
-
- **Node.js** >= 14 (ES6+ support)
|
|
10
|
-
- **npm** (or **yarn**) for package management
|
|
11
|
-
|
|
12
|
-
## Optional dependencies
|
|
13
|
-
- **express** – for server‑side rendering integration (recommended).
|
|
14
|
-
- **eslint** – for linting your project (dev dependency).
|
|
15
|
-
|
|
16
|
-
## Module System Support
|
|
17
|
-
|
|
18
|
-
`miki-template` supports both **CommonJS** (`require`) and **ESM** (`import`).
|
|
19
|
-
|
|
20
|
-
### CommonJS (CJS)
|
|
21
|
-
|
|
22
|
-
```js
|
|
23
|
-
const { render, compile, __express, SafeString, markSafe } = require('miki-template');
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### ES Modules (ESM)
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
// Named imports
|
|
30
|
-
import { render, compile, __express, SafeString, markSafe } from 'miki-template';
|
|
31
|
-
|
|
32
|
-
// Default import (all exports)
|
|
33
|
-
import miki from 'miki-template';
|
|
34
|
-
const result = miki.render('Hello {{ name }}', { name: 'World' });
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
> **Note:** When using ESM in Node.js, either name your files `.mjs` or set `"type": "module"` in your `package.json`.
|
|
38
|
-
|
|
39
|
-
## Publishing to npm
|
|
40
|
-
|
|
41
|
-
This project is configured for automatic npm publishing via GitHub Actions. When you push to `main`, the CI workflow runs tests and, if they pass, publishes the package to npm.
|
|
42
|
-
|
|
43
|
-
### Prerequisites for publishing
|
|
44
|
-
|
|
45
|
-
1. You must have an npm account and be a maintainer of the `miki-template` package on npm.
|
|
46
|
-
2. In your GitHub repository, go to **Settings → Secrets and variables → Actions**.
|
|
47
|
-
3. Add a new repository secret named `NPM_TOKEN` with your npm automation token.
|
|
48
|
-
- Generate it at https://www.npmjs.com/settings/YOUR_USERNAME/tokens
|
|
49
|
-
- Select **Automation** as the token type.
|
|
50
|
-
|
|
51
|
-
The CI workflow will then automatically publish on every push to `main`.
|
|
52
|
-
|
|
53
|
-
### Manual publishing
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
npm version patch # or minor/major
|
|
57
|
-
npm publish --access public
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Quick Start
|
|
63
|
-
|
|
64
|
-
### 1. Add the engine to your project
|
|
65
|
-
|
|
66
|
-
**CJS:**
|
|
67
|
-
```js
|
|
68
|
-
const { render, compile } = require('miki-template');
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**ESM:**
|
|
72
|
-
```js
|
|
73
|
-
import { render, compile } from 'miki-template';
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 2. (Express) Register the view engine
|
|
77
|
-
|
|
78
|
-
**CJS:**
|
|
79
|
-
```js
|
|
80
|
-
const express = require('express');
|
|
81
|
-
const { __express: renderDtpl } = require('miki-template');
|
|
82
|
-
const app = express();
|
|
83
|
-
app.engine('html', renderDtpl);
|
|
84
|
-
app.set('view engine', 'html');
|
|
85
|
-
app.set('views', './views');
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**ESM:**
|
|
89
|
-
```js
|
|
90
|
-
import express from 'express';
|
|
91
|
-
import { __express as renderDtpl } from 'miki-template';
|
|
92
|
-
|
|
93
|
-
const app = express();
|
|
94
|
-
app.engine('html', renderDtpl);
|
|
95
|
-
app.set('view engine', 'html');
|
|
96
|
-
app.set('views', './views');
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### 3. Run the test suite to verify
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
npm test
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
package/docs/overview.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Overview
|
|
2
|
-
|
|
3
|
-
Welcome to **miki-template** – a production‑ready, Django‑style template engine for Node.js and Express. This documentation mirrors the layout of popular open‑source libraries (e.g., Django, Jinja2, Mustache) and provides a clear, hierarchical guide for developers of all skill levels.
|
|
4
|
-
|
|
5
|
-
- **Project structure** – quick glance at the repository layout.
|
|
6
|
-
- **Feature list** – exhaustive rundown of supported tags, filters, security helpers, and the new `partialdef` system.
|
|
7
|
-
- **Getting started** – installation, basic rendering, and Express integration.
|
|
8
|
-
- **Advanced usage** – inheritance, block rendering, custom tags/filters, and performance tips.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Repository layout
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
📦 miki-template/
|
|
16
|
-
├─ 📁 src/ # Core engine source files
|
|
17
|
-
│ ├─ index.js # Entry point, compile/render APIs
|
|
18
|
-
│ ├─ lexer.js # Tokenizer
|
|
19
|
-
│ ├─ parser.js # AST builder
|
|
20
|
-
│ ├─ context.js # Scope & partial registry
|
|
21
|
-
│ └─ tags/ # Built‑in tag parsers (control, inheritance, util)
|
|
22
|
-
│ ├─ control.js # if, for, with, cycle, partialdef, …
|
|
23
|
-
│ ├─ inheritance.js # extends, block, super
|
|
24
|
-
│ └─ util.js # comment, verbatim, etc.
|
|
25
|
-
├─ 📁 filters/ # Built‑in filter implementations
|
|
26
|
-
├─ 📁 tests/ # Jest‑style test suite
|
|
27
|
-
├─ 📁 docs/ # 📖 Documentation (this folder)
|
|
28
|
-
├─ README.md # Project landing page (high‑level intro)
|
|
29
|
-
├─ AGENT.md # Agent guardrails (internal)
|
|
30
|
-
├─ ROADMAP.md # Future roadmap & milestones
|
|
31
|
-
└─ package.json # npm package definition
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Each module is deliberately **single‑responsibility** and fully typed via JSDoc comments, making it easy to extend.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Where to start
|
|
39
|
-
|
|
40
|
-
- **Installation** – see `docs/installation.md`.
|
|
41
|
-
- **Basic rendering** – see `docs/usage.md`.
|
|
42
|
-
- **Tag reference** – see `docs/tags.md`.
|
|
43
|
-
- **Filter reference** – see `docs/filters.md`.
|
|
44
|
-
- **Partial definitions** – see `docs/partialdef.md`.
|
|
45
|
-
- **Security considerations** – see `docs/security.md`.
|
|
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
|
-
|
|
69
|
-
For API‑level details (e.g., `compile().renderPartial`) check `docs/api.md`.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Contributing
|
|
74
|
-
|
|
75
|
-
We follow the standard open‑source workflow. Details are in `docs/contributing.md`.
|
|
76
|
-
|
|
77
|
-
---
|
|
78
|
-
|
|
79
|
-
> **Tip**: All documentation files are located under `c:/Users/Coder Miki/Desktop/miki-template/docs/`.
|
package/docs/partialdef.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# Partial Definition (`partialdef`)
|
|
2
|
-
|
|
3
|
-
`partialdef` is the cornerstone feature that brings Django‑style **named template fragments** to Node.js. It allows you to define a reusable block once and render it multiple times, optionally **inline** for immediate output. Combined with the `setupExpress` helper, partials can be served as standalone HTTP responses for HTMX-style UIs.
|
|
4
|
-
|
|
5
|
-
## Syntax
|
|
6
|
-
```html
|
|
7
|
-
{% partialdef name [inline] %}
|
|
8
|
-
...template code...
|
|
9
|
-
{% endpartialdef %}
|
|
10
|
-
```
|
|
11
|
-
- `name` – identifier used with `{% partial name %}`.
|
|
12
|
-
- Optional `inline` – if present, the block is rendered **where it is defined**; no separate `{% partial %}` call is required.
|
|
13
|
-
|
|
14
|
-
## Rendering a Partial
|
|
15
|
-
```html
|
|
16
|
-
{% partial greeting %}
|
|
17
|
-
```
|
|
18
|
-
The engine looks up the definition in the current rendering **Context** (`context.partialDefs`) and injects the rendered output.
|
|
19
|
-
|
|
20
|
-
## Including a Partial From Another File
|
|
21
|
-
Use the `file#partial` syntax to include just a single named partial:
|
|
22
|
-
```html
|
|
23
|
-
{% include "home.html#card" with title="Hi" %}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## API Usage
|
|
27
|
-
```js
|
|
28
|
-
const tpl = `{% partialdef api %}API {{ data }}{% endpartialdef %}`;
|
|
29
|
-
const compiled = compile(tpl);
|
|
30
|
-
const out = compiled.renderPartial('api', { data: 123 }); // "API 123"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
`renderPartialFromSource` and `renderPartialFromFile` are also exported at the top level:
|
|
34
|
-
```js
|
|
35
|
-
const miki = require('miki-template');
|
|
36
|
-
miki.renderPartialFromFile('views/home.html', 'card', { user: req.user });
|
|
37
|
-
miki.renderPartialFromSource(src, 'card', { user: req.user }, { views: 'views' });
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Serving a Partial Over HTTP (HTMX)
|
|
41
|
-
With `miki.setupExpress(app, { extension: 'html', views: './views' })`, the same `res.render(...)` call you use for full pages also serves a single partial by appending `#partialName` to the view name:
|
|
42
|
-
|
|
43
|
-
```javascript
|
|
44
|
-
app.get('/partials/:name', (req, res) =>
|
|
45
|
-
res.render(`home#${req.params.name}`, { user: req.user })
|
|
46
|
-
);
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The same effect can be obtained via the lighter `expressPartialRenderer()` middleware:
|
|
50
|
-
```javascript
|
|
51
|
-
app.use(miki.expressPartialRenderer());
|
|
52
|
-
app.get('/card', (req, res) => res.renderPartial('home#card', { user: req.user }));
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Features
|
|
56
|
-
- **Full tag parity** – conditionals (`if`), loops (`for`), variable scoping (`with`) work inside a `partialdef`.
|
|
57
|
-
- **Nested partials** – you can define a partial inside another; inner definitions are registered first and can be used by the outer.
|
|
58
|
-
- **Scope isolation** – each rendering of a partial receives its own scope, mirroring Django’s behavior.
|
|
59
|
-
- **Inline rendering** – render inline without an extra `{% partial %}` tag (`{% partialdef foo inline %}…{% endpartialdef %}`).
|
|
60
|
-
- **`with` arguments** – bind extra context values when rendering: `{% partial card with title="Hello" description="World" %}`.
|
|
61
|
-
- **Performance** – partials are compiled once per template; subsequent renders reuse the compiled AST.
|
|
62
|
-
|
|
63
|
-
## Common Pitfalls
|
|
64
|
-
| Issue | Symptom | Fix |
|
|
65
|
-
|-------|---------|-----|
|
|
66
|
-
| Missing partial name | `{% partial %}` renders nothing | Ensure the name matches a defined `partialdef`. |
|
|
67
|
-
| Variable not found | Appears empty | Variables are resolved in the current context; use `{% with %}` inside the partial if you need a local alias. |
|
|
68
|
-
| Inline vs non‑inline confusion | Duplicate output | Use `inline` only when you want immediate rendering. |
|
|
69
|
-
|
|
70
|
-
> Implementation lives in `src/tags/control.js` (class `PartialDefNode` and `PartialNode`).
|
package/docs/security.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
`miki-template` is built with **secure defaults**. All variables are **auto‑escaped** unless explicitly marked safe.
|
|
4
|
-
|
|
5
|
-
## Auto‑escaping
|
|
6
|
-
- Every string output goes through `escapeHtml` before being concatenated.
|
|
7
|
-
- Use the `|safe` filter or `markSafe(value)` to bypass escaping when you trust the data.
|
|
8
|
-
|
|
9
|
-
## CSRF Protection
|
|
10
|
-
- The `{% csrf_token %}` tag renders a hidden `<input>` containing the `csrf_token` value from the rendering context.
|
|
11
|
-
- Example:
|
|
12
|
-
```html
|
|
13
|
-
<form method="post">{% csrf_token %} ... </form>
|
|
14
|
-
```
|
|
15
|
-
- It is a thin wrapper; you must generate and store `csrf_token` in your Express middleware.
|
|
16
|
-
|
|
17
|
-
## CSP Nonce
|
|
18
|
-
- `{% csp_nonce_attr %}` injects `nonce="{{ csp_nonce }}"` when `csp_nonce` is present in the context.
|
|
19
|
-
- Useful for inline scripts when you have a CSP policy with `script-src 'nonce-...';`.
|
|
20
|
-
|
|
21
|
-
## SafeString Wrapper
|
|
22
|
-
- Filters returning `SafeString` bypass auto‑escaping. The wrapper is applied automatically by the `safe` filter.
|
|
23
|
-
|
|
24
|
-
## No `eval`
|
|
25
|
-
- Template expressions are parsed into an AST and evaluated using a sandboxed evaluator that **never calls `eval` or `new Function`**.
|
|
26
|
-
|
|
27
|
-
> Security‑related code lives in `src/security.js` and the tag implementations in `src/tags/control.js`.
|