miki-template 2.2.3 → 2.3.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/.github/workflows/docs.yml +3 -1
- package/.github/workflows/release.yml +0 -5
- package/benchmarks/ejs-results.json +6 -6
- package/benchmarks/ejs.js +5 -3
- package/benchmarks/handlebars-results.json +6 -6
- package/benchmarks/handlebars.js +5 -8
- package/benchmarks/miki-results.json +6 -6
- package/benchmarks/miki.js +6 -3
- package/benchmarks/pug-results.json +6 -6
- package/benchmarks/pug.js +5 -3
- package/docs/api/async-render.md +88 -3
- package/docs/api/cache.md +90 -3
- package/docs/api/compile.md +131 -3
- package/docs/api/context-processors.md +80 -3
- package/docs/api/filters.md +223 -3
- package/docs/api/finder.md +97 -3
- package/docs/api/helpers.md +56 -3
- package/docs/api/i18n.md +160 -3
- package/docs/api/index.md +82 -28
- package/docs/api/libraries.md +210 -3
- package/docs/api/render-partial.md +84 -3
- package/docs/api/render.md +95 -3
- package/docs/api/security.md +148 -3
- package/docs/api/setup-express.md +78 -2
- package/docs/api/tags.md +138 -4
- package/docs/filter.md +0 -0
- package/docs/guide/advanced-usage.md +403 -6
- package/docs/guide/async-rendering.md +312 -4
- package/docs/guide/context-processors.md +261 -4
- package/docs/guide/custom-filters.md +315 -4
- package/docs/guide/custom-tags.md +275 -4
- package/docs/guide/filters.md +675 -3
- package/docs/guide/getting-started.md +109 -7
- package/docs/guide/installation.md +99 -4
- package/docs/guide/partial-templates.md +371 -4
- package/docs/guide/quick-start.md +228 -6
- package/docs/guide/security.md +348 -3
- package/docs/guide/tags.md +789 -6
- package/docs/guide/template-discovery.md +174 -4
- package/docs/guide/template-inheritance.md +277 -4
- package/docs/index.md +24 -42
- package/docs/integrations/elysia.md +4 -2
- package/docs/integrations/express.md +219 -219
- package/docs/integrations/fastify.md +4 -2
- package/docs/integrations/hono.md +4 -2
- package/docs/integrations/index.md +68 -68
- package/docs/integrations/koa.md +4 -2
- package/docs/integrations/nestjs.md +4 -2
- package/docs/integrations/tsed.md +4 -2
- package/docs/performance.md +45 -8
- package/ex.mjs +1 -1
- package/mkdocs.yml +0 -22
- package/overrides/main.html +1 -1
- package/package.json +1 -1
- package/requirements-docs.txt +2 -1
- package/src/codegen.js +905 -0
- package/src/context.js +42 -30
- package/src/filters.js +16 -0
- package/src/index.js +66 -61
- package/src/tags/control.js +15 -12
- package/src/utils.js +60 -0
- package/tests/filters.test.js +9 -0
- package/docs/javascripts/extra.js +0 -174
- package/docs/stylesheets/extra.css +0 -819
- package/overrides/partials/footer.html +0 -9
|
@@ -37,9 +37,11 @@ jobs:
|
|
|
37
37
|
|
|
38
38
|
- name: Verify docs build
|
|
39
39
|
run: mkdocs build --strict
|
|
40
|
+
env:
|
|
41
|
+
NO_MKDOCS_2_WARNING: 1
|
|
40
42
|
|
|
41
43
|
- name: Deploy docs to GitHub Pages
|
|
42
|
-
run: 'mkdocs gh-deploy --force --message "chore: deploy docs to GitHub Pages
|
|
44
|
+
run: 'mkdocs gh-deploy --force --message "chore: deploy docs to GitHub Pages"'
|
|
43
45
|
|
|
44
46
|
- name: Output Pages URL
|
|
45
47
|
run: echo "Docs deployed to https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "ejs:small",
|
|
4
|
-
"medianMs": 0.
|
|
5
|
-
"rps":
|
|
4
|
+
"medianMs": 0.005599999999994054,
|
|
5
|
+
"rps": 178571
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "ejs:medium",
|
|
9
|
-
"medianMs": 0.
|
|
10
|
-
"rps":
|
|
9
|
+
"medianMs": 0.3426000000000613,
|
|
10
|
+
"rps": 2919
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "ejs:large",
|
|
14
|
-
"medianMs":
|
|
15
|
-
"rps":
|
|
14
|
+
"medianMs": 4.021499999999833,
|
|
15
|
+
"rps": 249
|
|
16
16
|
}
|
|
17
17
|
]
|
package/benchmarks/ejs.js
CHANGED
|
@@ -2,11 +2,13 @@ const ejs = require('ejs');
|
|
|
2
2
|
const { performance } = require('perf_hooks');
|
|
3
3
|
|
|
4
4
|
const SMALL = `<% items.forEach(item => { %>\n<%= item.toUpperCase() %>:<%= item.length %>\n<% }) %>`;
|
|
5
|
-
const MEDIUM = `<%
|
|
6
|
-
const LARGE = `<%
|
|
5
|
+
const MEDIUM = `<% big_items.forEach(i => { %>\n<% if (i % 2 === 0) { %>Even: <%= i %>\n<% } else { %>Odd: <%= i %>\n<% } }) %>`;
|
|
6
|
+
const LARGE = `<% big_items.forEach(i => { %>\n<% small_items.forEach(j => { %>\n<%= i %>:<%= j %> <%= 'x'.repeat(10) %>\n<% }) }) %>`;
|
|
7
7
|
|
|
8
8
|
const data = {
|
|
9
|
-
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon']
|
|
9
|
+
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
10
|
+
big_items: Array.from({ length: 500 }, (_, i) => i),
|
|
11
|
+
small_items: Array.from({ length: 5 }, (_, j) => j)
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
function bench(name, tpl, data, iterations = 5000) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "handlebars:small",
|
|
4
|
-
"medianMs": 0.
|
|
5
|
-
"rps":
|
|
4
|
+
"medianMs": 0.0024000000000086175,
|
|
5
|
+
"rps": 416667
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "handlebars:medium",
|
|
9
|
-
"medianMs": 0.
|
|
10
|
-
"rps":
|
|
9
|
+
"medianMs": 0.16540000000009059,
|
|
10
|
+
"rps": 6046
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "handlebars:large",
|
|
14
|
-
"medianMs": 1.
|
|
15
|
-
"rps":
|
|
14
|
+
"medianMs": 1.5188000000000557,
|
|
15
|
+
"rps": 658
|
|
16
16
|
}
|
|
17
17
|
]
|
package/benchmarks/handlebars.js
CHANGED
|
@@ -2,14 +2,9 @@ const Handlebars = require('handlebars');
|
|
|
2
2
|
const { performance } = require('perf_hooks');
|
|
3
3
|
|
|
4
4
|
const SMALL = `{{#each items}}{{this}}:{{this.length}}\n{{/each}}`;
|
|
5
|
-
const MEDIUM = `{{#each
|
|
6
|
-
const LARGE = `{{#each
|
|
5
|
+
const MEDIUM = `{{#each big_items}}{{#if (isEven this)}}Even: {{this}}\n{{else}}Odd: {{this}}\n{{/if}}{{/each}}`;
|
|
6
|
+
const LARGE = `{{#each big_items}}{{#each ../small_items}}{{this}}:{{../this}} {{repeat "x" 10}}\n{{/each}}{{/each}}`;
|
|
7
7
|
|
|
8
|
-
Handlebars.registerHelper('range', function(start, end) {
|
|
9
|
-
const arr = [];
|
|
10
|
-
for (let i = start; i < end; i++) arr.push(i);
|
|
11
|
-
return arr;
|
|
12
|
-
});
|
|
13
8
|
Handlebars.registerHelper('isEven', function(n) {
|
|
14
9
|
return n % 2 === 0;
|
|
15
10
|
});
|
|
@@ -18,7 +13,9 @@ Handlebars.registerHelper('repeat', function(str, n) {
|
|
|
18
13
|
});
|
|
19
14
|
|
|
20
15
|
const data = {
|
|
21
|
-
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon']
|
|
16
|
+
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
17
|
+
big_items: Array.from({ length: 500 }, (_, i) => i),
|
|
18
|
+
small_items: Array.from({ length: 5 }, (_, j) => j)
|
|
22
19
|
};
|
|
23
20
|
|
|
24
21
|
function bench(name, tpl, data, iterations = 5000) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "miki:small",
|
|
4
|
-
"medianMs": 0.
|
|
5
|
-
"rps":
|
|
4
|
+
"medianMs": 0.0009000000000014552,
|
|
5
|
+
"rps": 1111111
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "miki:medium",
|
|
9
|
-
"medianMs": 0.
|
|
10
|
-
"rps":
|
|
9
|
+
"medianMs": 0.009999999999990905,
|
|
10
|
+
"rps": 100000
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "miki:large",
|
|
14
|
-
"medianMs": 0.
|
|
15
|
-
"rps":
|
|
14
|
+
"medianMs": 0.30579999999997654,
|
|
15
|
+
"rps": 3270
|
|
16
16
|
}
|
|
17
17
|
]
|
package/benchmarks/miki.js
CHANGED
|
@@ -2,11 +2,14 @@ const miki = require('../src');
|
|
|
2
2
|
const { performance } = require('perf_hooks');
|
|
3
3
|
|
|
4
4
|
const SMALL = `{% for item in items %}{{ item|upper }}:{{ item|length }}\n{% endfor %}`;
|
|
5
|
-
const MEDIUM = `{% for i in
|
|
6
|
-
const LARGE = `{% for i in
|
|
5
|
+
const MEDIUM = `{% for i in big_items %}{% if i % 2 == 0 %}Even: {{ i }}\n{% else %}Odd: {{ i }}\n{% endif %}{% endfor %}`;
|
|
6
|
+
const LARGE = `{% for i in big_items %}{% for j in small_items %}{{ i }}:{{ j }} {{ x10|repeat:5 }}\n{% endfor %}{% endfor %}`;
|
|
7
7
|
|
|
8
8
|
const data = {
|
|
9
|
-
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon']
|
|
9
|
+
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
10
|
+
big_items: Array.from({ length: 500 }, (_, i) => i),
|
|
11
|
+
small_items: Array.from({ length: 5 }, (_, j) => j),
|
|
12
|
+
x10: 'x'
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
function bench(name, tpl, data, iterations = 5000) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "pug:small",
|
|
4
|
-
"medianMs": 0.
|
|
5
|
-
"rps":
|
|
4
|
+
"medianMs": 0.0006000000000199179,
|
|
5
|
+
"rps": 1666667
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "pug:medium",
|
|
9
|
-
"medianMs": 0.
|
|
10
|
-
"rps":
|
|
9
|
+
"medianMs": 0.019200000000012096,
|
|
10
|
+
"rps": 52083
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"name": "pug:large",
|
|
14
|
-
"medianMs": 0.
|
|
15
|
-
"rps":
|
|
14
|
+
"medianMs": 0.3955999999999449,
|
|
15
|
+
"rps": 2528
|
|
16
16
|
}
|
|
17
17
|
]
|
package/benchmarks/pug.js
CHANGED
|
@@ -2,11 +2,13 @@ const pug = require('pug');
|
|
|
2
2
|
const { performance } = require('perf_hooks');
|
|
3
3
|
|
|
4
4
|
const SMALL = `each item in items\n = item.toUpperCase() + ':' + item.length\n`;
|
|
5
|
-
const MEDIUM =
|
|
6
|
-
const LARGE =
|
|
5
|
+
const MEDIUM = `each i in big_items\n if i % 2 === 0\n | Even: #{i}\n else\n | Odd: #{i}\n`;
|
|
6
|
+
const LARGE = `each i in big_items\n each j in small_items\n | #{i}:#{j} #{'x'.repeat(10)}\n`;
|
|
7
7
|
|
|
8
8
|
const data = {
|
|
9
|
-
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon']
|
|
9
|
+
items: ['alpha', 'beta', 'gamma', 'delta', 'epsilon'],
|
|
10
|
+
big_items: Array.from({ length: 500 }, (_, i) => i),
|
|
11
|
+
small_items: Array.from({ length: 5 }, (_, j) => j)
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
function bench(name, tpl, data, iterations = 5000) {
|
package/docs/api/async-render.md
CHANGED
|
@@ -1,85 +1,170 @@
|
|
|
1
|
-
# asyncRender()
|
|
1
|
+
# asyncRender()
|
|
2
|
+
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
Async version of `render()`. Returns a Promise. Use this when your templates contain async filters, async custom tags, or async library components.
|
|
4
6
|
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
## Signature
|
|
6
10
|
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
```javascript
|
|
14
|
+
|
|
8
15
|
asyncRender(templateStr, contextObj = {}, options = {})
|
|
16
|
+
|
|
9
17
|
```
|
|
10
18
|
|
|
19
|
+
|
|
20
|
+
|
|
11
21
|
## Returns
|
|
12
22
|
|
|
23
|
+
|
|
24
|
+
|
|
13
25
|
`Promise<string>` — The rendered HTML.
|
|
14
26
|
|
|
27
|
+
|
|
28
|
+
|
|
15
29
|
## When to Use
|
|
16
30
|
|
|
31
|
+
|
|
32
|
+
|
|
17
33
|
Use `asyncRender()` when your templates contain:
|
|
18
34
|
|
|
35
|
+
|
|
36
|
+
|
|
19
37
|
- Async filters (returning Promises)
|
|
38
|
+
|
|
20
39
|
- Async custom tags (render return a Promise)
|
|
40
|
+
|
|
21
41
|
- Async library helpers
|
|
42
|
+
|
|
22
43
|
- `{% load %}` libraries with async components
|
|
23
44
|
|
|
45
|
+
|
|
46
|
+
|
|
24
47
|
Using async features with `render()` throws: `Async node encountered during sync render. Use asyncRender() instead.`
|
|
25
48
|
|
|
49
|
+
|
|
50
|
+
|
|
26
51
|
## Examples
|
|
27
52
|
|
|
53
|
+
|
|
54
|
+
|
|
28
55
|
### Basic async render
|
|
29
56
|
|
|
57
|
+
|
|
58
|
+
|
|
30
59
|
=== "CommonJS"
|
|
31
60
|
|
|
61
|
+
|
|
62
|
+
|
|
32
63
|
```javascript
|
|
64
|
+
|
|
33
65
|
const { asyncRender } = require('miki-template');
|
|
34
66
|
|
|
67
|
+
|
|
68
|
+
|
|
35
69
|
const html = await asyncRender('Hello {{ name }}!', { name: 'World' });
|
|
70
|
+
|
|
36
71
|
```
|
|
37
72
|
|
|
73
|
+
|
|
74
|
+
|
|
38
75
|
=== "ES Modules"
|
|
39
76
|
|
|
77
|
+
|
|
78
|
+
|
|
40
79
|
```javascript
|
|
80
|
+
|
|
41
81
|
import { asyncRender } from 'miki-template';
|
|
42
82
|
|
|
83
|
+
|
|
84
|
+
|
|
43
85
|
const html = await asyncRender('Hello {{ name }}!', { name: 'World' });
|
|
86
|
+
|
|
44
87
|
```
|
|
45
88
|
|
|
89
|
+
|
|
90
|
+
|
|
46
91
|
### With async tags/filters
|
|
47
92
|
|
|
93
|
+
|
|
94
|
+
|
|
48
95
|
=== "CommonJS"
|
|
49
96
|
|
|
97
|
+
|
|
98
|
+
|
|
50
99
|
```javascript
|
|
100
|
+
|
|
51
101
|
const { asyncRender } = require('miki-template');
|
|
52
102
|
|
|
103
|
+
|
|
104
|
+
|
|
53
105
|
const html = await asyncRender(templateWithAsyncHelpers, context, options);
|
|
106
|
+
|
|
54
107
|
```
|
|
55
108
|
|
|
109
|
+
|
|
110
|
+
|
|
56
111
|
=== "ES Modules"
|
|
57
112
|
|
|
113
|
+
|
|
114
|
+
|
|
58
115
|
```javascript
|
|
116
|
+
|
|
59
117
|
import { asyncRender } from 'miki-template';
|
|
60
118
|
|
|
119
|
+
|
|
120
|
+
|
|
61
121
|
const html = await asyncRender(templateWithAsyncHelpers, context, options);
|
|
122
|
+
|
|
62
123
|
```
|
|
63
124
|
|
|
125
|
+
|
|
126
|
+
|
|
64
127
|
### Async partial from file
|
|
65
128
|
|
|
129
|
+
|
|
130
|
+
|
|
66
131
|
=== "CommonJS"
|
|
67
132
|
|
|
133
|
+
|
|
134
|
+
|
|
68
135
|
```javascript
|
|
136
|
+
|
|
69
137
|
const { asyncRender } = require('miki-template');
|
|
70
138
|
|
|
139
|
+
|
|
140
|
+
|
|
71
141
|
const html = await asyncRender('home#card', context, { views: './views' });
|
|
142
|
+
|
|
72
143
|
```
|
|
73
144
|
|
|
145
|
+
|
|
146
|
+
|
|
74
147
|
=== "ES Modules"
|
|
75
148
|
|
|
149
|
+
|
|
150
|
+
|
|
76
151
|
```javascript
|
|
152
|
+
|
|
77
153
|
import { asyncRender } from 'miki-template';
|
|
78
154
|
|
|
155
|
+
|
|
156
|
+
|
|
79
157
|
const html = await asyncRender('home#card', context, { views: './views' });
|
|
158
|
+
|
|
80
159
|
```
|
|
81
160
|
|
|
161
|
+
|
|
162
|
+
|
|
82
163
|
## Related
|
|
83
164
|
|
|
84
|
-
|
|
85
|
-
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
- [render()](./render.md)
|
|
168
|
+
|
|
169
|
+
- [compile()](./compile.md)
|
|
170
|
+
|
package/docs/api/cache.md
CHANGED
|
@@ -1,87 +1,174 @@
|
|
|
1
|
-
# Cache API
|
|
1
|
+
# Cache API
|
|
2
|
+
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
## clearCache
|
|
4
6
|
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
Clear the compiled template cache. Templates are cached in-memory (LRU, 100 entries max). Call this when templates change on disk during development, in tests, or when dynamically registering tags/filters.
|
|
6
10
|
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
=== "CommonJS"
|
|
8
14
|
|
|
15
|
+
|
|
16
|
+
|
|
9
17
|
```javascript
|
|
18
|
+
|
|
10
19
|
const { clearCache } = require('miki-template');
|
|
11
20
|
|
|
21
|
+
|
|
22
|
+
|
|
12
23
|
clearCache();
|
|
24
|
+
|
|
13
25
|
```
|
|
14
26
|
|
|
27
|
+
|
|
28
|
+
|
|
15
29
|
=== "ES Modules"
|
|
16
30
|
|
|
31
|
+
|
|
32
|
+
|
|
17
33
|
```javascript
|
|
34
|
+
|
|
18
35
|
import { clearCache } from 'miki-template';
|
|
19
36
|
|
|
37
|
+
|
|
38
|
+
|
|
20
39
|
clearCache();
|
|
40
|
+
|
|
21
41
|
```
|
|
22
42
|
|
|
43
|
+
|
|
44
|
+
|
|
23
45
|
## How Caching Works
|
|
24
46
|
|
|
47
|
+
|
|
48
|
+
|
|
25
49
|
- Templates are cached by a key combining the source string and compile options (views, custom settings).
|
|
50
|
+
|
|
26
51
|
- The cache is an in-memory LRU cache limited to 100 entries.
|
|
52
|
+
|
|
27
53
|
- Cached compiled templates are reused across renders, improving performance for repeated templates.
|
|
54
|
+
|
|
28
55
|
- Partials defined via `{% partialdef %}` are cached along with their parent template.
|
|
29
56
|
|
|
57
|
+
|
|
58
|
+
|
|
30
59
|
## When to Clear Cache
|
|
31
60
|
|
|
61
|
+
|
|
62
|
+
|
|
32
63
|
- During development when templates change frequently on disk
|
|
64
|
+
|
|
33
65
|
- In tests to ensure fresh compilation
|
|
66
|
+
|
|
34
67
|
- When dynamically registering custom tags/filters at runtime
|
|
35
68
|
|
|
69
|
+
|
|
70
|
+
|
|
36
71
|
### Development File Watcher
|
|
37
72
|
|
|
73
|
+
|
|
74
|
+
|
|
38
75
|
=== "CommonJS"
|
|
39
76
|
|
|
77
|
+
|
|
78
|
+
|
|
40
79
|
```javascript
|
|
80
|
+
|
|
41
81
|
const fs = require('fs');
|
|
82
|
+
|
|
42
83
|
const { clearCache } = require('miki-template');
|
|
43
84
|
|
|
85
|
+
|
|
86
|
+
|
|
44
87
|
if (process.env.NODE_ENV !== 'production') {
|
|
88
|
+
|
|
45
89
|
fs.watch('./views', () => {
|
|
90
|
+
|
|
46
91
|
clearCache();
|
|
92
|
+
|
|
47
93
|
console.log('Template cache cleared');
|
|
94
|
+
|
|
48
95
|
});
|
|
96
|
+
|
|
49
97
|
}
|
|
98
|
+
|
|
50
99
|
```
|
|
51
100
|
|
|
101
|
+
|
|
102
|
+
|
|
52
103
|
=== "ES Modules"
|
|
53
104
|
|
|
105
|
+
|
|
106
|
+
|
|
54
107
|
```javascript
|
|
108
|
+
|
|
55
109
|
import fs from 'node:fs';
|
|
110
|
+
|
|
56
111
|
import { clearCache } from 'miki-template';
|
|
57
112
|
|
|
113
|
+
|
|
114
|
+
|
|
58
115
|
if (process.env.NODE_ENV !== 'production') {
|
|
116
|
+
|
|
59
117
|
fs.watch('./views', () => {
|
|
118
|
+
|
|
60
119
|
clearCache();
|
|
120
|
+
|
|
61
121
|
console.log('Template cache cleared');
|
|
122
|
+
|
|
62
123
|
});
|
|
124
|
+
|
|
63
125
|
}
|
|
126
|
+
|
|
64
127
|
```
|
|
65
128
|
|
|
129
|
+
|
|
130
|
+
|
|
66
131
|
## cache Library
|
|
67
132
|
|
|
133
|
+
|
|
134
|
+
|
|
68
135
|
The built-in `cache` library (auto-activated) provides a template tag for caching fragments:
|
|
69
136
|
|
|
137
|
+
|
|
138
|
+
|
|
70
139
|
```html
|
|
140
|
+
|
|
71
141
|
{% load cache %}
|
|
72
142
|
|
|
143
|
+
|
|
144
|
+
|
|
73
145
|
{% cache 300 sidebar_key %}
|
|
146
|
+
|
|
74
147
|
<div class="sidebar">
|
|
148
|
+
|
|
75
149
|
{% for item in sidebar_items %}
|
|
150
|
+
|
|
76
151
|
<a href="{{ item.url }}">{{ item.title }}</a>
|
|
152
|
+
|
|
77
153
|
{% endfor %}
|
|
154
|
+
|
|
78
155
|
</div>
|
|
156
|
+
|
|
79
157
|
{% endcache %}
|
|
158
|
+
|
|
80
159
|
```
|
|
81
160
|
|
|
161
|
+
|
|
162
|
+
|
|
82
163
|
The first argument is the TTL in seconds. The second is a cache key. Additional arguments serve as key components.
|
|
83
164
|
|
|
165
|
+
|
|
166
|
+
|
|
84
167
|
## Next Steps
|
|
85
168
|
|
|
86
|
-
|
|
87
|
-
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
- [Advanced Usage: Caching](../guide/advanced-usage.md#caching)
|
|
172
|
+
|
|
173
|
+
- [API Reference](../index.md)
|
|
174
|
+
|