miki-template 2.3.1 → 2.3.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 (159) hide show
  1. package/package.json +45 -1
  2. package/.eslintrc.json +0 -16
  3. package/.github/release-notes/v1.3.1.md +0 -55
  4. package/.github/release-notes/v1.3.3.md +0 -77
  5. package/.github/release-notes/v1.3.7.md +0 -20
  6. package/.github/workflows/ci.yml +0 -42
  7. package/.github/workflows/docs.yml +0 -107
  8. package/.github/workflows/release.yml +0 -107
  9. package/AGENT.md +0 -71
  10. package/API_REFERENCE.md +0 -341
  11. package/CHANGELOG.md +0 -173
  12. package/CODE_OF_CONDUCT.md +0 -14
  13. package/CONTRIBUTING.md +0 -27
  14. package/ROADMAP.md +0 -40
  15. package/assets/banner.png +0 -0
  16. package/assets/logo.png +0 -0
  17. package/benchmarks/ejs-results.json +0 -17
  18. package/benchmarks/ejs.js +0 -38
  19. package/benchmarks/handlebars-results.json +0 -17
  20. package/benchmarks/handlebars.js +0 -45
  21. package/benchmarks/miki-results.json +0 -17
  22. package/benchmarks/miki.js +0 -39
  23. package/benchmarks/pug-results.json +0 -17
  24. package/benchmarks/pug.js +0 -38
  25. package/benchmarks/report.json +0 -17
  26. package/benchmarks/run.js +0 -81
  27. package/benchmarks/stress.mjs +0 -647
  28. package/benchmarks/templates/large.dtpl +0 -7
  29. package/benchmarks/templates/medium.dtpl +0 -3
  30. package/benchmarks/templates/small.dtpl +0 -7
  31. package/context/component.md +0 -109
  32. package/context/prd.md +0 -131
  33. package/context/project-structure.md +0 -33
  34. package/dir/base.html +0 -23
  35. package/dir/cmpnt.html +0 -11
  36. package/dir/footer.html +0 -3
  37. package/dir/home.html +0 -80
  38. package/dir/index.html +0 -80
  39. package/dir/navbar.html +0 -9
  40. package/docs/api/async-render.md +0 -170
  41. package/docs/api/cache.md +0 -174
  42. package/docs/api/compile.md +0 -256
  43. package/docs/api/context-processors.md +0 -154
  44. package/docs/api/filters.md +0 -437
  45. package/docs/api/finder.md +0 -188
  46. package/docs/api/helpers.md +0 -106
  47. package/docs/api/i18n.md +0 -314
  48. package/docs/api/index.md +0 -108
  49. package/docs/api/libraries.md +0 -414
  50. package/docs/api/render-partial.md +0 -162
  51. package/docs/api/render.md +0 -184
  52. package/docs/api/security.md +0 -290
  53. package/docs/api/setup-express.md +0 -152
  54. package/docs/api/tags.md +0 -268
  55. package/docs/assets/banner.png +0 -0
  56. package/docs/assets/logo.png +0 -0
  57. package/docs/filter.md +0 -0
  58. package/docs/guide/advanced-usage.md +0 -794
  59. package/docs/guide/async-rendering.md +0 -616
  60. package/docs/guide/context-processors.md +0 -514
  61. package/docs/guide/custom-filters.md +0 -622
  62. package/docs/guide/custom-tags.md +0 -542
  63. package/docs/guide/filters.md +0 -1314
  64. package/docs/guide/getting-started.md +0 -204
  65. package/docs/guide/installation.md +0 -190
  66. package/docs/guide/partial-templates.md +0 -734
  67. package/docs/guide/quick-start.md +0 -444
  68. package/docs/guide/security.md +0 -690
  69. package/docs/guide/tags.md +0 -1566
  70. package/docs/guide/template-discovery.md +0 -340
  71. package/docs/guide/template-inheritance.md +0 -546
  72. package/docs/guide/what-is-miki-template.md +0 -28
  73. package/docs/guide/why-miki-template.md +0 -75
  74. package/docs/index.md +0 -86
  75. package/docs/integrations/elysia.md +0 -80
  76. package/docs/integrations/express.md +0 -219
  77. package/docs/integrations/fastify.md +0 -79
  78. package/docs/integrations/hono.md +0 -80
  79. package/docs/integrations/index.md +0 -68
  80. package/docs/integrations/koa.md +0 -90
  81. package/docs/integrations/nestjs.md +0 -80
  82. package/docs/integrations/tsed.md +0 -83
  83. package/docs/performance.md +0 -74
  84. package/eslint.config.mjs +0 -42
  85. package/ex.mjs +0 -36
  86. package/live-test/integrations/elysia-example.js +0 -16
  87. package/live-test/integrations/express-example.js +0 -24
  88. package/live-test/integrations/fastify-example.js +0 -20
  89. package/live-test/integrations/hono-example.js +0 -16
  90. package/live-test/integrations/koa-example.js +0 -30
  91. package/live-test/integrations/nestjs-example.js +0 -25
  92. package/live-test/integrations/smoke-test.js +0 -166
  93. package/live-test/integrations/tsed-example.js +0 -23
  94. package/live-test/package-lock.json +0 -1150
  95. package/live-test/package.json +0 -13
  96. package/live-test/packages/product/templates/product/detail.html +0 -7
  97. package/live-test/server.js +0 -38
  98. package/live-test/templates/app_templates/detail.html +0 -6
  99. package/live-test/views/base.html +0 -8
  100. package/live-test/views/child.html +0 -7
  101. package/live-test/views/home.html +0 -17
  102. package/live-test/views/index.html +0 -1
  103. package/miki-template-extension/.github/workflows/ci.yml +0 -116
  104. package/miki-template-extension/.vscodeignore +0 -7
  105. package/miki-template-extension/CHANGELOG.md +0 -99
  106. package/miki-template-extension/LICENSE +0 -21
  107. package/miki-template-extension/README.md +0 -273
  108. package/miki-template-extension/extension.js +0 -1013
  109. package/miki-template-extension/icon.png +0 -0
  110. package/miki-template-extension/icon.svg +0 -10
  111. package/miki-template-extension/miki-template-1.7.1.vsix +0 -0
  112. package/miki-template-extension/package.json +0 -280
  113. package/miki-template-extension/snippets/miki-template.json +0 -717
  114. package/miki-template-extension/syntaxes/language-configuration.json +0 -114
  115. package/miki-template-extension/syntaxes/miki-template.tmLanguage.json +0 -355
  116. package/miki-template-extension/tests/grammar-tests.json +0 -162
  117. package/miki-template-extension/tests/run-grammar-tests.js +0 -82
  118. package/mkdocs.yml +0 -195
  119. package/overrides/main.html +0 -26
  120. package/requirements-docs.txt +0 -2
  121. package/sample-app/package-lock.json +0 -901
  122. package/sample-app/package.json +0 -9
  123. package/sample-app/server.js +0 -14
  124. package/sample-app/views/index.html +0 -1
  125. package/scripts/build-vsix.js +0 -129
  126. package/scripts/build-vsix.ps1 +0 -15
  127. package/snippets/miki-template.json +0 -177
  128. package/src/asyncRender.js +0 -21
  129. package/src/types.d.ts +0 -107
  130. package/syntaxes/language-configuration.json +0 -26
  131. package/syntaxes/miki-template.tmLanguage.json +0 -146
  132. package/tests/asyncRender.test.js +0 -17
  133. package/tests/base.html +0 -6
  134. package/tests/child.html +0 -3
  135. package/tests/context_processors.test.js +0 -13
  136. package/tests/esm.test.mjs +0 -61
  137. package/tests/filters.test.js +0 -263
  138. package/tests/finder-appdirs.test.js +0 -19
  139. package/tests/finder.test.js +0 -17
  140. package/tests/fixtures/views/nested/index.html +0 -1
  141. package/tests/fixtures/views/partial.html +0 -1
  142. package/tests/fixtures/views/sub/deepfile.html +0 -1
  143. package/tests/fixtures/views-appdirs/product/site/detail.html +0 -1
  144. package/tests/include_security.test.js +0 -9
  145. package/tests/integration/README.md +0 -32
  146. package/tests/integration/features.test.cjs +0 -1681
  147. package/tests/integration/features.test.mjs +0 -1697
  148. package/tests/integration/finder.esm.test.mjs +0 -13
  149. package/tests/integration/partial-render.test.cjs +0 -13
  150. package/tests/integration/templates/base.miki +0 -6
  151. package/tests/integration/templates/child.miki +0 -6
  152. package/tests/integration/templates/index.html +0 -17
  153. package/tests/lexer.test.js +0 -45
  154. package/tests/parser.test.js +0 -57
  155. package/tests/partial.html +0 -1
  156. package/tests/partialdef.test.js +0 -79
  157. package/tests/production_checks.js +0 -57
  158. package/tests/security.test.js +0 -28
  159. package/tests/tags.test.js +0 -233
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miki-template",
3
- "version": "2.3.1",
3
+ "version": "2.3.2",
4
4
  "description": "Django-Style template engine for Node.js and Express",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -10,6 +10,50 @@
10
10
  "default": "./src/index.js"
11
11
  }
12
12
  },
13
+ "files": [
14
+ "src/index.js",
15
+ "src/esm.mjs",
16
+ "src/lexer.js",
17
+ "src/parser.js",
18
+ "src/context.js",
19
+ "src/context_processors.js",
20
+ "src/filters.js",
21
+ "src/security.js",
22
+ "src/cache.js",
23
+ "src/utils.js",
24
+ "src/codegen.js",
25
+ "src/i18n.js",
26
+ "src/libraries.js",
27
+ "src/tags/helpers.js",
28
+ "src/tags/registry.js",
29
+ "src/tags/control.js",
30
+ "src/tags/inheritance.js",
31
+ "src/tags/util.js",
32
+ "src/tags/i18n.js",
33
+ "src/tags/extra.js"
34
+ ],
35
+ "files": [
36
+ "src/index.js",
37
+ "src/esm.mjs",
38
+ "src/lexer.js",
39
+ "src/parser.js",
40
+ "src/context.js",
41
+ "src/context_processors.js",
42
+ "src/filters.js",
43
+ "src/security.js",
44
+ "src/cache.js",
45
+ "src/utils.js",
46
+ "src/codegen.js",
47
+ "src/i18n.js",
48
+ "src/libraries.js",
49
+ "src/tags/helpers.js",
50
+ "src/tags/registry.js",
51
+ "src/tags/control.js",
52
+ "src/tags/inheritance.js",
53
+ "src/tags/util.js",
54
+ "src/tags/i18n.js",
55
+ "src/tags/extra.js"
56
+ ],
13
57
  "keywords": [
14
58
  "django",
15
59
  "template",
package/.eslintrc.json DELETED
@@ -1,16 +0,0 @@
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
- }
@@ -1,55 +0,0 @@
1
- # miki-template v1.3.1
2
-
3
- ## Highlights
4
-
5
- - **One-line Express integration**: `miki.setupExpress(app, { extension: 'html', views: dir })` wires the view engine, the views directory, and a `res.render` shim that makes HTMX-style partial responses Just Work.
6
-
7
- ```js
8
- const express = require('express');
9
- const miki = require('miki-template');
10
-
11
- const app = express();
12
- miki.setupExpress(app, { extension: 'html', views: './views' });
13
-
14
- // Full page
15
- app.get('/', (req, res) => res.render('home', { user: req.user }));
16
-
17
- // Partial — just append `#partialName` to the view name
18
- app.get('/partials/:name', (req, res) =>
19
- res.render(`home#${req.params.name}`, { user: req.user })
20
- );
21
- ```
22
-
23
- - **`miki.expressPartialRenderer()` middleware** for drop-in `res.renderPartial(view, locals)` without changing your existing `app.engine()` setup.
24
- - **`miki.express()`** factory for `app.engine('html', miki.express())` — honors `view#partial` selectors.
25
- - **`renderPartialFromSource(source, partialName, ctx, opts)`** and **`renderPartialFromFile(...)`** — render a single named `{% partialdef %}` from a string or file. Walks the AST (and the `extends` chain) to find partials nested inside blocks.
26
- - **`{% include "file.html#partial" with ... %}`** — partial-selector syntax works with `include`, not just `res.render`.
27
- - **Built-in libraries** (`humanize`, `cache`, `lorem`) are now auto-activated on module load. `{% lorem 5 p %}` works without `{% load lorem %}`.
28
-
29
- ## Tag fixes
30
-
31
- - `{% with x=1, y=2 as pair %}` (multi-pair + alias) parses correctly.
32
- - `{% with a=x b=y %}` (multi-pair, no alias) now binds each pair instead of being treated as one expression.
33
- - `{% cycle 'a' 'b' as name %}` now emits nothing but stores the value (Django semantics).
34
- - `{{ block.super }}` works inside partials that override blocks.
35
- - `extends` resolves `views` from `options.settings.views` (Express path), `options.views`, or default.
36
- - Path-traversal protection applies to `extends` *and* `include`, including `include "file#partial"`.
37
- - `default` vs `default_if_none`: `default` falls back on `''`, `null`, and `undefined`; `default_if_none` only on `null`/`undefined` (Django parity).
38
- - `removetags` accepts multiple tag names.
39
- - `Context.get('a.b.c')` returns `undefined` for missing keys (was `''`), so `{% if x %}` and `default_if_none` work correctly.
40
-
41
- ## Test coverage
42
-
43
- **382/382 tests pass.** Added a 190-test integration suite (`tests/integration/`) covering every tag, filter, and feature under both CommonJS and ESM, exercised against a real Express HTTP server on ephemeral ports. The test runner recursively picks up `.test.{cjs,mjs,js}` files.
44
-
45
- ## Docs
46
-
47
- - `README.md` — promoted `miki.setupExpress` to the first listed feature; the Express section leads with the one-liner.
48
- - `docs/usage.md` — full Express section rewritten with the new setup, options table, and middleware variant.
49
- - `docs/api.md` — added rows for the new APIs; updated CJS/ESM import snippets.
50
- - `docs/partialdef.md` — documented `include "file#partial"`, `renderPartialFromSource/File`, and the HTMX-over-HTTP flow.
51
- - `CHANGELOG.md` — full entry for 1.3.1.
52
-
53
- ## Compatibility
54
-
55
- No breaking changes. All existing public APIs continue to work; new APIs are opt-in.
@@ -1,77 +0,0 @@
1
- # miki-template v1.3.3
2
-
3
- ## Highlights
4
-
5
- - **Date/time filter fixed** — `{{ d|date:"yyyy-MM-dd" }}` now returns `"2024-06-15"` instead of `"24242424-JunJun-1515"`. Multi-character tokens (`yyyy`, `MM`, `dd`, `HH`, `mm`, `ii`, `ss`) are matched longest-first; backward-compatible single-character aliases (`m`/`d`/`H`/`i`/`s`) still work for Django-style unpadded values.
6
- - **Inheritance 4× faster** — `{% extends %}` no longer re-reads the parent file from disk on every render. A 64-entry LRU cache in `src/cache.js` memoises the parent source. Inheritance rendering improved from ~481 rps to **~2,056 rps** in the strict benchmark.
7
-
8
- ## Installation
9
-
10
- ```bash
11
- npm install miki-template@1.3.3
12
- ```
13
-
14
- ## Quick start
15
-
16
- ```js
17
- const miki = require('miki-template');
18
- const express = require('express');
19
-
20
- const app = express();
21
- miki.setupExpress(app, { extension: 'html', views: './views' });
22
-
23
- // Full page
24
- app.get('/', (req, res) => res.render('home', { user: req.user }));
25
-
26
- // HTMX partial — just append #partialName
27
- app.get('/partials/:name', (req, res) =>
28
- res.render(`home#${req.params.name}`, { user: req.user })
29
- );
30
-
31
- app.listen(3000);
32
- ```
33
-
34
- ## What's changed
35
-
36
- ### Fixed
37
- - `date` and `time` filters — multi-character tokens render correctly.
38
-
39
- ### Performance
40
- - Inheritance parent-source LRU cache in `src/cache.js` (`getParentSource` / `hasParentSource`). `clearCache()` also clears it.
41
-
42
- ### Tooling
43
- - New `benchmarks/stress.mjs` — 37-check strict benchmark (correctness, compile speed, render speed, cache, scale, endurance, partial rendering, async, concurrency). Run with `node benchmarks/stress.mjs`. Exits with code 1 on any failure.
44
- - `eslint.config.mjs` — added `URL`, `URLSearchParams`, `TextEncoder`, `TextDecoder`, `fetch`, `crypto`, `performance` to the Node 18+ globals list.
45
- - Removed dead code: unused `elifBranches` variable in `parseIfChanged`, unused `extractPluralMappings` function in `i18n.js`.
46
- - Renamed unused tag-parser `parser` parameters to `_parser` in `lorem` library and `parseLoad`.
47
-
48
- ## Verification
49
-
50
- | Check | Result |
51
- |---|---|
52
- | `npx eslint src/**/*.js` | 0 errors, 0 warnings |
53
- | `npm test` | 397/397 passing |
54
- | `node benchmarks/stress.mjs` | 37/37 passing |
55
-
56
- ## Performance (from the stress benchmark)
57
-
58
- | Template | Speed |
59
- |---|---|
60
- | Small (76 B) | **175,439 rps** (0.006 ms) |
61
- | Medium (595 B) | 13,947 rps (0.072 ms) |
62
- | Large (1.6 KB, 6 sections × 12 items) | 2,277 rps (0.439 ms) |
63
- | Inheritance child | 2,056 rps (0.486 ms) |
64
- | Partials (50 entries) | 2,235 rps (0.447 ms) |
65
- | Scale: 50,000 items | 107 ms median |
66
- | Endurance: 100,000 renders | 7.5s total, RSS +0.9 MB |
67
- | Async: 200 concurrent LARGE | 237 ms total |
68
-
69
- ## Compatibility
70
-
71
- No breaking changes. All existing public APIs continue to work; new APIs are opt-in.
72
-
73
- ## Links
74
-
75
- - **Repository**: https://github.com/alainmiki/miki-template
76
- - **Tag**: https://github.com/alainmiki/miki-template/releases/tag/v1.3.3
77
- - **Previous**: [v1.3.1](https://github.com/alainmiki/miki-template/releases/tag/v1.3.1)
@@ -1,20 +0,0 @@
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.
@@ -1,42 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
- workflow_dispatch:
9
-
10
- jobs:
11
- lint:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v4
15
- - name: Setup Node.js
16
- uses: actions/setup-node@v4
17
- with:
18
- node-version: '20'
19
- cache: 'npm'
20
- - run: npm ci
21
- - name: Lint code
22
- run: npx eslint src/**/*.js
23
-
24
- test:
25
- runs-on: ubuntu-latest
26
- needs: lint
27
- strategy:
28
- matrix:
29
- node-version: [18.x, 20.x]
30
- steps:
31
- - uses: actions/checkout@v4
32
- - name: Use Node.js
33
- uses: actions/setup-node@v4
34
- with:
35
- node-version: ${{ matrix.node-version }}
36
- cache: 'npm'
37
- - run: npm ci
38
- - name: Run unit tests
39
- run: npm test
40
- - name: Run integration smoke-test
41
- if: github.event_name == 'workflow_dispatch'
42
- run: node live-test/integrations/smoke-test.js
@@ -1,107 +0,0 @@
1
- name: Deploy Documentation
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
- workflow_dispatch:
9
-
10
- permissions:
11
- contents: write
12
- pages: write
13
- id-token: write
14
-
15
- concurrency:
16
- group: "pages"
17
- cancel-in-progress: false
18
-
19
- jobs:
20
- deploy-docs:
21
- runs-on: ubuntu-latest
22
- steps:
23
- - name: Checkout repository
24
- uses: actions/checkout@v4
25
-
26
- - name: Setup Python
27
- uses: actions/setup-python@v5
28
- with:
29
- python-version: '3.12'
30
- cache: 'pip'
31
- cache-dependency-path: 'requirements-docs.txt'
32
-
33
- - name: Install MkDocs Material with imaging support
34
- run: |
35
- python -m pip install --upgrade pip
36
- pip install -r requirements-docs.txt
37
-
38
- - name: Verify docs build
39
- run: mkdocs build --strict
40
- env:
41
- NO_MKDOCS_2_WARNING: 1
42
-
43
- - name: Deploy docs to GitHub Pages
44
- run: 'mkdocs gh-deploy --force --message "chore: deploy docs to GitHub Pages"'
45
-
46
- - name: Output Pages URL
47
- run: echo "Docs deployed to https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
48
-
49
- sync-wiki:
50
- runs-on: ubuntu-latest
51
- needs: deploy-docs
52
- steps:
53
- - name: Checkout repository
54
- uses: actions/checkout@v4
55
- with:
56
- fetch-depth: 0
57
-
58
- - name: Setup Git config
59
- run: |
60
- git config --global user.name "github-actions[bot]"
61
- git config --global user.email "github-actions[bot]@users.noreply.github.com"
62
-
63
- - name: Create wiki clone directory
64
- run: mkdir -p wiki-repo
65
-
66
- - name: Clone wiki repository
67
- run: |
68
- git clone https://github.com/${{ github.repository }}.wiki.git wiki-repo || true
69
-
70
- - name: Sync docs to wiki
71
- if: hashFiles('wiki-repo/.git/config') != ''
72
- run: |
73
- cd wiki-repo
74
-
75
- # Copy all markdown docs preserving directory structure
76
- cp -r ../docs/*.md .
77
- cp -r ../docs/guide/*.md ./guide/ 2>/dev/null || true
78
- cp -r ../docs/api/*.md ./api/ 2>/dev/null || true
79
- cp -r ../docs/integrations/*.md ./integrations/ 2>/dev/null || true
80
-
81
- # Remove index.md if it exists (GitHub wiki uses README.md as home page)
82
- if [ -f index.md ]; then
83
- if [ -f README.md ]; then
84
- rm index.md
85
- else
86
- mv index.md README.md
87
- fi
88
- fi
89
-
90
- # Create Home.md from index.md if README.md doesn't exist
91
- if [ ! -f README.md ] && [ ! -f Home.md ] && [ -f docs/index.md ]; then
92
- cp docs/index.md Home.md
93
- fi
94
-
95
- # Commit and push if there are changes
96
- git add -A
97
- git diff --cached --quiet || {
98
- git commit -m "docs: sync documentation to wiki"
99
- git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.wiki.git master
100
- }
101
-
102
- - name: Wiki initialization hint
103
- if: hashFiles('wiki-repo/.git/config') == ''
104
- run: |
105
- echo "::warning::Wiki repository not found. Enable the wiki in repository settings first."
106
- echo "Go to https://github.com/${{ github.repository }}/settings/wiki and click 'Create the first page'"
107
- continue-on-error: true
@@ -1,107 +0,0 @@
1
- # Release workflow
2
- #
3
- # Fully automatic release pipeline. Triggered when a commit to main matches
4
- # the `chore(release): v*` pattern produced by `npm run release:patch|minor|major`.
5
- #
6
- # Flow:
7
- # 1. Detect the new version in package.json.
8
- # 2. Lint + test + stress benchmark (must pass before continuing).
9
- # 3. Create an annotated git tag v<version> and push it.
10
- # 4. Create a GitHub Release with notes from .github/release-notes/v<version>.md
11
- # (or a generic message if the file is missing).
12
- # 5. Publish the package to npm using the NPM_TOKEN secret.
13
- #
14
- # Local usage:
15
- # npm run release:patch # 1.3.3 → 1.3.4
16
- # npm run release:minor # 1.3.3 → 1.4.0
17
- # npm run release:major # 1.3.3 → 2.0.0
18
- # That bumps package.json, creates a commit, pushes to main, and the rest
19
- # happens here.
20
-
21
- name: Release
22
-
23
- on:
24
- push:
25
- branches: [main]
26
-
27
- permissions:
28
- contents: write
29
- packages: write
30
-
31
- jobs:
32
- release:
33
- # Only run for the explicit "chore(release):" commits. Any other
34
- # push to main is ignored so contributors can edit package.json
35
- # without accidentally publishing.
36
- if: startsWith(github.event.head_commit.message, 'chore(release):')
37
- runs-on: ubuntu-latest
38
- steps:
39
- - uses: actions/checkout@v4
40
- with:
41
- fetch-depth: 0
42
- token: ${{ secrets.GITHUB_TOKEN }}
43
-
44
- - uses: actions/setup-node@v4
45
- with:
46
- node-version: '20'
47
- registry-url: 'https://registry.npmjs.org'
48
-
49
- - name: Install dependencies
50
- run: npm ci
51
-
52
- - name: Lint
53
- run: npx eslint src/**/*.js
54
-
55
- - name: Test
56
- run: npm test
57
-
58
- - name: Stress benchmark
59
- run: node benchmarks/stress.mjs
60
-
61
- - name: Read package version
62
- id: ver
63
- run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
64
-
65
- - name: Check tag does not already exist
66
- run: |
67
- if git rev-parse "v${{ steps.ver.outputs.version }}" >/dev/null 2>&1; then
68
- echo "::error::Tag v${{ steps.ver.outputs.version }} already exists."
69
- exit 1
70
- fi
71
-
72
- - name: Create and push git tag
73
- run: |
74
- git config user.name "github-actions[bot]"
75
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
76
- git tag -a "v${{ steps.ver.outputs.version }}" -m "v${{ steps.ver.outputs.version }}"
77
- git push origin "v${{ steps.ver.outputs.version }}"
78
-
79
- - name: Build release body
80
- id: notes
81
- env:
82
- NOTES_FILE: .github/release-notes/v${{ steps.ver.outputs.version }}.md
83
- VERSION: ${{ steps.ver.outputs.version }}
84
- run: |
85
- {
86
- echo "body<<EOF_RELEASE"
87
- if [ -f "$NOTES_FILE" ]; then
88
- cat "$NOTES_FILE"
89
- else
90
- echo "## v${VERSION}"
91
- echo ""
92
- echo "See [CHANGELOG.md](../../blob/main/CHANGELOG.md) for details."
93
- fi
94
- echo "EOF_RELEASE"
95
- } >> "$GITHUB_OUTPUT"
96
-
97
- - name: Create GitHub Release
98
- uses: softprops/action-gh-release@v2
99
- with:
100
- tag_name: v${{ steps.ver.outputs.version }}
101
- name: v${{ steps.ver.outputs.version }}
102
- body: ${{ steps.notes.outputs.body }}
103
-
104
- - name: Publish to npm
105
- run: npm publish --access public
106
- env:
107
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/AGENT.md DELETED
@@ -1,71 +0,0 @@
1
- # AGENT.md - Agent Instructions, Guardrails, & Architecture Rules
2
-
3
- This repository implements a Django-Style Template Engine for Node.js/Express. To ensure high code quality, consistent architecture, and full feature parity with Django without guesswork, all AI agents and developers must strictly follow these instructions and guardrails.
4
-
5
- ---
6
-
7
- ## 🎯 Core Objectives
8
- 1. **Full Feature Parity**: Match Django's template engine rules for rendering variables, dotted lookups, built-in tags, filters, and template inheritance.
9
- 2. **Deterministic & Secure**: Escape output by default using a safe-string mechanism.
10
- 3. **No Spaghetti Code**: Maintain a strict separation of Lexer, Parser, Renderer, Context, and Tag/Filter registries.
11
-
12
- ---
13
-
14
- ## ⚠️ Strict Guardrails & Anti-Hallucination Rules
15
-
16
- > [!IMPORTANT]
17
- > **No Guesswork / Assumptions**
18
- > - If a tag or filter's behavior is not clearly defined in [prd.md](file:///c:/Users/Coder%20Miki/Desktop/miki-template/context/prd.md) or Django documentation, **DO NOT guess**.
19
- > - If you notice ambiguities (e.g., how to handle circular extends or nested cycles), raise a question to the user immediately or throw a descriptive compilation error.
20
-
21
- > [!WARNING]
22
- > **No Regex-Based Global Search & Replace**
23
- > - You **must not** implement tags or filters using global regex replacements on the final string. All templates must go through:
24
- > `Lexer (String -> Tokens) -> Parser (Tokens -> AST) -> Renderer (AST + Context -> HTML)`.
25
- > - Direct regex replacement on HTML bypasses nesting, escaping, and blocks, which introduces severe bugs.
26
-
27
- > [!CAUTION]
28
- > **Security Guardrails**
29
- > - All variable output must be HTML-escaped by default.
30
- > - A variable is only safe from escaping if it is marked as a `SafeString` (e.g., using the `safe` filter or internally flagged).
31
- > - Dynamic expression evaluation (such as in `if` tags) **must not** use direct JS `eval()`. Use a safe AST evaluator or sandboxed parser to prevent remote code execution.
32
-
33
- ---
34
-
35
- ## 🧩 Architectural Guidelines
36
-
37
- ### 1. Lexing (`src/lexer.js`)
38
- * Tokens must be generated for three primary types:
39
- - `TEXT`: Plain HTML/text.
40
- - `VAR`: Variables wrapped in `{{ ... }}`.
41
- - `BLOCK`: Structural tags wrapped in `{% ... %}`.
42
- * The Lexer must correctly handle verbatim blocks `{% verbatim %}` and comments `{% comment %}` by suppressing token output or passing raw text tokens.
43
-
44
- ### 2. Parsing (`src/parser.js`)
45
- * The Parser takes a stream of tokens and constructs an AST of nodes.
46
- * Every node must implement a `.render(context)` method (async or sync).
47
- * For tags that have closing tags (e.g., `{% if %}`...`{% endif %}`), the parser must parse nested tokens recursively until the matching close tag is encountered.
48
-
49
- ### 3. Context & Scope Isolation (`src/context.js`)
50
- * Context must support a stack-like structure: `.push()` to create a new scope, and `.pop()` to revert.
51
- * **Variable Lookups**: Support dotted lookups:
52
- - Example: `{{ user.profile.name }}` should search `user` in context, then resolve property `profile`, then property `name`.
53
- - If a resolved value is a function, call it (without arguments, just like Django).
54
- - If a lookup fails, return an empty string `""` by default, unless configured otherwise.
55
-
56
- ### 4. Template Inheritance (`src/tags/inheritance.js`)
57
- * Inheritance works by having a child template load a parent template via `{% extends "parent.html" %}`.
58
- * The child overrides blocks defined as `{% block block_name %}`.
59
- * During render, the parent's AST is evaluated, but block nodes are replaced by the child's corresponding block nodes.
60
- * Support block nesting and the `{{ block.super }}` variable to render parent block content.
61
-
62
- ---
63
-
64
- ## 🛠️ Step-by-Step Task Execution Protocol
65
-
66
- When executing tasks:
67
- 1. **Analyze Requirements**: Check [prd.md](file:///c:/Users/Coder%20Miki/Desktop/miki-template/context/prd.md) and [component.md](file:///c:/Users/Coder%20Miki/Desktop/miki-template/context/component.md).
68
- 2. **Check Existing Tests**: Run current test suite using `npm test` or `node --test` to ensure a green state.
69
- 3. **Write Tests First**: For any new filter, tag, or parser logic, write a corresponding unit test in `tests/` showing the expected template string and its expected output.
70
- 4. **Implement Modular Code**: Put tag handlers in `src/tags/`, filters in `src/filters.js`, and maintain registry isolation.
71
- 5. **Verify**: Ensure the test suite passes, check for escaping vulnerabilities, and check that no scope leaks occur.