@rhinostone/swig 2.0.0-alpha.7 → 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/.changes/v1.0.0-pre1.md +2 -2
- package/.changes/v1.0.0.md +1 -1
- package/.changes/v2.0.0-alpha.8.md +4 -0
- package/.changes/v2.0.0.md +6 -0
- package/.playwright-mcp/console-2026-04-22T15-34-20-480Z.log +2 -0
- package/.playwright-mcp/console-2026-04-22T15-35-04-265Z.log +11 -0
- package/.playwright-mcp/console-2026-04-22T15-37-26-953Z.log +1 -0
- package/.playwright-mcp/console-2026-04-22T15-51-15-160Z.log +148 -0
- package/.playwright-mcp/console-2026-04-22T15-51-33-405Z.log +74 -0
- package/.playwright-mcp/console-2026-04-22T15-51-53-922Z.log +74 -0
- package/.playwright-mcp/console-2026-04-22T15-53-10-736Z.log +74 -0
- package/.playwright-mcp/console-2026-04-22T15-53-40-091Z.log +883 -0
- package/.playwright-mcp/console-2026-04-22T16-12-02-541Z.log +74 -0
- package/.playwright-mcp/console-2026-04-22T16-33-44-982Z.log +13973 -0
- package/.playwright-mcp/page-2026-04-22T15-34-24-524Z.yml +1 -0
- package/.playwright-mcp/page-2026-04-22T15-35-04-346Z.yml +0 -0
- package/.playwright-mcp/page-2026-04-22T15-37-27-039Z.yml +5 -0
- package/.playwright-mcp/page-2026-04-22T15-51-15-600Z.yml +76 -0
- package/.playwright-mcp/page-2026-04-22T15-51-33-605Z.yml +0 -0
- package/.playwright-mcp/page-2026-04-22T15-51-54-206Z.yml +676 -0
- package/.playwright-mcp/page-2026-04-22T15-53-11-277Z.yml +632 -0
- package/.playwright-mcp/page-2026-04-22T15-53-40-297Z.yml +0 -0
- package/.playwright-mcp/page-2026-04-22T16-12-02-855Z.yml +0 -0
- package/.playwright-mcp/page-2026-04-22T16-33-45-281Z.yml +0 -0
- package/HISTORY.md +15 -3
- package/README.md +32 -6
- package/ROADMAP.md +29 -6
- package/dist/swig.js +3 -3
- package/dist/swig.min.js +3 -3
- package/dist/swig.min.js.map +1 -1
- package/lib/swig.js +2 -2
- package/package.json +2 -2
- package/rhinostone-swig-2.0.0-alpha.7.tgz +0 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
- generic [ref=e2]:
|
|
2
|
+
- region "Skip to main content":
|
|
3
|
+
- link "Skip to main content" [ref=e3] [cursor=pointer]:
|
|
4
|
+
- /url: "#__docusaurus_skipToContent_fallback"
|
|
5
|
+
- navigation "Main" [ref=e4]:
|
|
6
|
+
- generic [ref=e5]:
|
|
7
|
+
- generic [ref=e6]:
|
|
8
|
+
- link "Gina logo Gina" [ref=e7] [cursor=pointer]:
|
|
9
|
+
- /url: /docs/
|
|
10
|
+
- img "Gina logo" [ref=e9]
|
|
11
|
+
- generic [ref=e10]: Gina
|
|
12
|
+
- link "Docs" [ref=e11] [cursor=pointer]:
|
|
13
|
+
- /url: /docs/intro
|
|
14
|
+
- link "Tutorials" [ref=e12] [cursor=pointer]:
|
|
15
|
+
- /url: /docs/tutorials
|
|
16
|
+
- link "Swig" [ref=e13] [cursor=pointer]:
|
|
17
|
+
- /url: /docs/swig/
|
|
18
|
+
- link "Roadmap" [ref=e14] [cursor=pointer]:
|
|
19
|
+
- /url: /docs/roadmap
|
|
20
|
+
- generic [ref=e15]:
|
|
21
|
+
- link "v0.3.6(opens in new tab)" [ref=e16] [cursor=pointer]:
|
|
22
|
+
- /url: https://github.com/gina-io/gina/releases
|
|
23
|
+
- text: v0.3.6
|
|
24
|
+
- img "(opens in new tab)" [ref=e17]
|
|
25
|
+
- link "GitHub(opens in new tab)" [ref=e19] [cursor=pointer]:
|
|
26
|
+
- /url: https://github.com/gina-io/gina
|
|
27
|
+
- text: GitHub
|
|
28
|
+
- img "(opens in new tab)" [ref=e20]
|
|
29
|
+
- button "Switch between dark and light mode (currently system mode)" [ref=e23] [cursor=pointer]:
|
|
30
|
+
- img [ref=e24]
|
|
31
|
+
- generic [ref=e27]:
|
|
32
|
+
- textbox "Search" [ref=e28]
|
|
33
|
+
- generic:
|
|
34
|
+
- generic: ⌘
|
|
35
|
+
- generic: K
|
|
36
|
+
- generic [ref=e31]:
|
|
37
|
+
- complementary [ref=e32]:
|
|
38
|
+
- generic [ref=e33]:
|
|
39
|
+
- generic [ref=e34]:
|
|
40
|
+
- link "@rhinostone/swig v1.6.0" [ref=e35] [cursor=pointer]:
|
|
41
|
+
- /url: https://www.npmjs.com/package/@rhinostone/swig
|
|
42
|
+
- generic [ref=e36]: "@rhinostone/swig"
|
|
43
|
+
- generic [ref=e37]: v1.6.0
|
|
44
|
+
- link "gina-io/swig on GitHub" [ref=e38] [cursor=pointer]:
|
|
45
|
+
- /url: https://github.com/gina-io/swig
|
|
46
|
+
- img [ref=e39]
|
|
47
|
+
- navigation "Docs sidebar" [ref=e42]:
|
|
48
|
+
- list [ref=e43]:
|
|
49
|
+
- listitem [ref=e44]:
|
|
50
|
+
- link "Overview" [ref=e45] [cursor=pointer]:
|
|
51
|
+
- /url: /docs/swig/
|
|
52
|
+
- img [ref=e47]
|
|
53
|
+
- generic "Overview" [ref=e50]
|
|
54
|
+
- listitem [ref=e51]:
|
|
55
|
+
- link "Getting Started" [ref=e52] [cursor=pointer]:
|
|
56
|
+
- /url: /docs/swig/getting-started
|
|
57
|
+
- img [ref=e54]
|
|
58
|
+
- generic "Getting Started" [ref=e59]
|
|
59
|
+
- listitem [ref=e60]:
|
|
60
|
+
- link "Template Syntax" [ref=e61] [cursor=pointer]:
|
|
61
|
+
- /url: /docs/swig/syntax
|
|
62
|
+
- img [ref=e63]
|
|
63
|
+
- generic "Template Syntax" [ref=e66]
|
|
64
|
+
- listitem [ref=e67]:
|
|
65
|
+
- link "Tags" [ref=e68] [cursor=pointer]:
|
|
66
|
+
- /url: /docs/swig/tags
|
|
67
|
+
- img [ref=e70]
|
|
68
|
+
- generic "Tags" [ref=e72]
|
|
69
|
+
- listitem [ref=e73]:
|
|
70
|
+
- link "Filters" [ref=e74] [cursor=pointer]:
|
|
71
|
+
- /url: /docs/swig/filters
|
|
72
|
+
- img [ref=e76]
|
|
73
|
+
- generic "Filters" [ref=e78]
|
|
74
|
+
- listitem [ref=e79]:
|
|
75
|
+
- link "API" [ref=e80] [cursor=pointer]:
|
|
76
|
+
- /url: /docs/swig/api
|
|
77
|
+
- img [ref=e82]
|
|
78
|
+
- generic "API" [ref=e85]
|
|
79
|
+
- listitem [ref=e86]:
|
|
80
|
+
- link "Loaders" [ref=e87] [cursor=pointer]:
|
|
81
|
+
- /url: /docs/swig/loaders
|
|
82
|
+
- img [ref=e89]
|
|
83
|
+
- generic "Loaders" [ref=e93]
|
|
84
|
+
- listitem [ref=e94]:
|
|
85
|
+
- link "Extending Swig" [ref=e95] [cursor=pointer]:
|
|
86
|
+
- /url: /docs/swig/extending
|
|
87
|
+
- img [ref=e97]
|
|
88
|
+
- generic "Extending Swig" [ref=e99]
|
|
89
|
+
- listitem [ref=e100]:
|
|
90
|
+
- link "CLI" [ref=e101] [cursor=pointer]:
|
|
91
|
+
- /url: /docs/swig/cli
|
|
92
|
+
- img [ref=e103]
|
|
93
|
+
- generic "CLI" [ref=e105]
|
|
94
|
+
- listitem [ref=e106]:
|
|
95
|
+
- link "Browser Usage" [ref=e107] [cursor=pointer]:
|
|
96
|
+
- /url: /docs/swig/browser
|
|
97
|
+
- img [ref=e109]
|
|
98
|
+
- generic "Browser Usage" [ref=e111]
|
|
99
|
+
- listitem [ref=e112]:
|
|
100
|
+
- link "Security" [ref=e113] [cursor=pointer]:
|
|
101
|
+
- /url: /docs/swig/security
|
|
102
|
+
- img [ref=e115]
|
|
103
|
+
- generic "Security" [ref=e117]
|
|
104
|
+
- listitem [ref=e118]:
|
|
105
|
+
- generic [ref=e119]:
|
|
106
|
+
- link "Twig Frontend" [ref=e120] [cursor=pointer]:
|
|
107
|
+
- /url: /docs/swig/twig/
|
|
108
|
+
- generic "Twig Frontend" [ref=e121]
|
|
109
|
+
- button "Collapse sidebar category 'Twig Frontend'" [expanded] [ref=e122] [cursor=pointer]
|
|
110
|
+
- list [ref=e123]:
|
|
111
|
+
- listitem [ref=e124]:
|
|
112
|
+
- link "Parity" [ref=e125] [cursor=pointer]:
|
|
113
|
+
- /url: /docs/swig/twig/parity
|
|
114
|
+
- generic "Parity" [ref=e126]
|
|
115
|
+
- listitem [ref=e127]:
|
|
116
|
+
- link "Non-Goals" [ref=e128] [cursor=pointer]:
|
|
117
|
+
- /url: /docs/swig/twig/non-goals
|
|
118
|
+
- generic "Non-Goals" [ref=e129]
|
|
119
|
+
- listitem [ref=e130]:
|
|
120
|
+
- link "From upstream Twig" [ref=e131] [cursor=pointer]:
|
|
121
|
+
- /url: /docs/swig/twig/migration
|
|
122
|
+
- generic "From upstream Twig" [ref=e132]
|
|
123
|
+
- listitem [ref=e133]:
|
|
124
|
+
- link "Browser Usage" [ref=e134] [cursor=pointer]:
|
|
125
|
+
- /url: /docs/swig/twig/browser
|
|
126
|
+
- img [ref=e136]
|
|
127
|
+
- generic "Browser Usage" [ref=e138]
|
|
128
|
+
- listitem [ref=e139]:
|
|
129
|
+
- link "Migration Guide" [ref=e140] [cursor=pointer]:
|
|
130
|
+
- /url: /docs/swig/migration
|
|
131
|
+
- img [ref=e142]
|
|
132
|
+
- generic "Migration Guide" [ref=e144]
|
|
133
|
+
- main [ref=e145]:
|
|
134
|
+
- generic [ref=e147]:
|
|
135
|
+
- generic [ref=e149]:
|
|
136
|
+
- article [ref=e150]:
|
|
137
|
+
- navigation "Breadcrumbs" [ref=e151]:
|
|
138
|
+
- list [ref=e152]:
|
|
139
|
+
- listitem [ref=e153]:
|
|
140
|
+
- link "Home page" [ref=e154] [cursor=pointer]:
|
|
141
|
+
- /url: /docs/
|
|
142
|
+
- img [ref=e155]
|
|
143
|
+
- listitem [ref=e157]:
|
|
144
|
+
- link "Twig Frontend" [ref=e158] [cursor=pointer]:
|
|
145
|
+
- /url: /docs/swig/twig/
|
|
146
|
+
- listitem [ref=e159]:
|
|
147
|
+
- generic [ref=e160]: Browser Usage
|
|
148
|
+
- generic [ref=e161]:
|
|
149
|
+
- heading "Twig in the Browser" [level=1] [ref=e163]
|
|
150
|
+
- generic [ref=e164]:
|
|
151
|
+
- generic [ref=e165]:
|
|
152
|
+
- generic [ref=e166]:
|
|
153
|
+
- img [ref=e167]
|
|
154
|
+
- text: 4 min read
|
|
155
|
+
- generic [ref=e170]: Intermediate
|
|
156
|
+
- generic [ref=e171]:
|
|
157
|
+
- generic [ref=e172]: Prerequisites
|
|
158
|
+
- list [ref=e173]:
|
|
159
|
+
- listitem [ref=e174]:
|
|
160
|
+
- link "Overview" [ref=e175] [cursor=pointer]:
|
|
161
|
+
- /url: /docs/swig/twig/
|
|
162
|
+
- listitem [ref=e176]:
|
|
163
|
+
- link "Swig Browser Usage" [ref=e177] [cursor=pointer]:
|
|
164
|
+
- /url: /docs/swig/browser
|
|
165
|
+
- listitem [ref=e178]:
|
|
166
|
+
- link "Security — the parser is the boundary" [ref=e179] [cursor=pointer]:
|
|
167
|
+
- /url: /docs/swig/security#the-parser-is-the-boundary
|
|
168
|
+
- listitem [ref=e180]:
|
|
169
|
+
- link "Loaders" [ref=e181] [cursor=pointer]:
|
|
170
|
+
- /url: /docs/swig/loaders
|
|
171
|
+
- paragraph [ref=e182]:
|
|
172
|
+
- code [ref=e183]: "@rhinostone/swig-twig"
|
|
173
|
+
- text: runs in the browser the same way
|
|
174
|
+
- code [ref=e184]: "@rhinostone/swig"
|
|
175
|
+
- text: does — memory loader only, no
|
|
176
|
+
- code [ref=e185]: fs
|
|
177
|
+
- text: access, identical autoescape and CVE-2023-25345 guard perimeter inherited from
|
|
178
|
+
- code [ref=e186]: "@rhinostone/swig-core"
|
|
179
|
+
- text: . The package does not ship a pre-built browser bundle; consumers bundle through their own toolchain (esbuild, Vite, Webpack, Rollup).
|
|
180
|
+
- paragraph [ref=e187]:
|
|
181
|
+
- text: "This page covers the Twig-specific bits: how to bundle, how to install the peer-dependency pair during alpha, and a minimal first-template example using Twig syntax. For the shared-engine flow — AOT pre-compile + prime + render, memory-loader idiom, cache semantics,"
|
|
182
|
+
- code [ref=e188]: swig run
|
|
183
|
+
- text: warnings — see
|
|
184
|
+
- link "Swig Browser Usage" [ref=e189] [cursor=pointer]:
|
|
185
|
+
- /url: /docs/swig/browser
|
|
186
|
+
- text: . It applies verbatim because both frontends lower to the same
|
|
187
|
+
- code [ref=e190]: swig-core
|
|
188
|
+
- text: backend.
|
|
189
|
+
- heading "ArchitectureDirect link to Architecture" [level=2] [ref=e191]:
|
|
190
|
+
- text: Architecture
|
|
191
|
+
- link "Direct link to Architecture" [ref=e192] [cursor=pointer]:
|
|
192
|
+
- /url: "#architecture"
|
|
193
|
+
- text: "#"
|
|
194
|
+
- paragraph [ref=e193]: "Same flow as native swig, with two deltas:"
|
|
195
|
+
- list [ref=e194]:
|
|
196
|
+
- listitem [ref=e195]:
|
|
197
|
+
- text: The entry point is
|
|
198
|
+
- code [ref=e196]: "@rhinostone/swig-twig"
|
|
199
|
+
- text: instead of
|
|
200
|
+
- code [ref=e197]: "@rhinostone/swig"
|
|
201
|
+
- text: .
|
|
202
|
+
- listitem [ref=e198]:
|
|
203
|
+
- text: Your bundler resolves both
|
|
204
|
+
- code [ref=e199]: "@rhinostone/swig-twig"
|
|
205
|
+
- text: and its peer
|
|
206
|
+
- code [ref=e200]: "@rhinostone/swig-core"
|
|
207
|
+
- text: .
|
|
208
|
+
- heading "InstallDirect link to Install" [level=2] [ref=e201]:
|
|
209
|
+
- text: Install
|
|
210
|
+
- link "Direct link to Install" [ref=e202] [cursor=pointer]:
|
|
211
|
+
- /url: "#install"
|
|
212
|
+
- text: "#"
|
|
213
|
+
- generic [ref=e204]:
|
|
214
|
+
- code [ref=e206]:
|
|
215
|
+
- generic [ref=e207]: npm install @rhinostone/swig-twig@alpha @rhinostone/swig-core@alpha
|
|
216
|
+
- button "Copy code to clipboard" [ref=e209] [cursor=pointer]:
|
|
217
|
+
- generic [ref=e210]:
|
|
218
|
+
- img [ref=e211]
|
|
219
|
+
- img [ref=e213]
|
|
220
|
+
- paragraph [ref=e215]:
|
|
221
|
+
- text: During the
|
|
222
|
+
- code [ref=e216]: 2.0.0-alpha.x
|
|
223
|
+
- text: cycle the IR ABI is unstable across minors, so
|
|
224
|
+
- code [ref=e217]: "@rhinostone/swig-twig"
|
|
225
|
+
- text: "'s"
|
|
226
|
+
- code [ref=e218]: peerDependencies
|
|
227
|
+
- text: pin
|
|
228
|
+
- code [ref=e219]: "@rhinostone/swig-core"
|
|
229
|
+
- text: to the
|
|
230
|
+
- strong [ref=e220]: exact matching version
|
|
231
|
+
- text: (no caret). Install both together at the same alpha — mixing minors is not supported.
|
|
232
|
+
- generic [ref=e222]:
|
|
233
|
+
- code [ref=e224]:
|
|
234
|
+
- generic [ref=e225]: // package.json — example consumer during alpha
|
|
235
|
+
- generic [ref=e226]: "{"
|
|
236
|
+
- generic [ref=e227]: "\"dependencies\": {"
|
|
237
|
+
- generic [ref=e228]: "\"@rhinostone/swig-core\": \"2.0.0-alpha.8\","
|
|
238
|
+
- generic [ref=e229]: "\"@rhinostone/swig-twig\": \"2.0.0-alpha.8\""
|
|
239
|
+
- generic [ref=e230]: "}"
|
|
240
|
+
- generic [ref=e231]: "}"
|
|
241
|
+
- button "Copy code to clipboard" [ref=e233] [cursor=pointer]:
|
|
242
|
+
- generic [ref=e234]:
|
|
243
|
+
- img [ref=e235]
|
|
244
|
+
- img [ref=e237]
|
|
245
|
+
- paragraph [ref=e239]:
|
|
246
|
+
- text: At
|
|
247
|
+
- code [ref=e240]: 2.0.0
|
|
248
|
+
- text: stable the pin loosens to
|
|
249
|
+
- code [ref=e241]: ^2.0.0
|
|
250
|
+
- text: .
|
|
251
|
+
- heading "Bundle with esbuildDirect link to Bundle with esbuild" [level=2] [ref=e242]:
|
|
252
|
+
- text: Bundle with esbuild
|
|
253
|
+
- link "Direct link to Bundle with esbuild" [ref=e243] [cursor=pointer]:
|
|
254
|
+
- /url: "#bundle-with-esbuild"
|
|
255
|
+
- text: "#"
|
|
256
|
+
- paragraph [ref=e244]: "Minimal recipe. Two things to wire up:"
|
|
257
|
+
- list [ref=e245]:
|
|
258
|
+
- listitem [ref=e246]:
|
|
259
|
+
- code [ref=e247]: fs
|
|
260
|
+
- text: is stubbed to an empty object (the filesystem loader at
|
|
261
|
+
- code [ref=e248]: "@rhinostone/swig-core/lib/loaders/filesystem.js"
|
|
262
|
+
- text: guards itself when
|
|
263
|
+
- code [ref=e249]: fs.readFileSync
|
|
264
|
+
- text: is missing, so an empty stub is enough to make it a no-op in the browser).
|
|
265
|
+
- listitem [ref=e250]:
|
|
266
|
+
- code [ref=e251]: path
|
|
267
|
+
- text: is aliased to
|
|
268
|
+
- link "path-browserify" [ref=e252] [cursor=pointer]:
|
|
269
|
+
- /url: https://www.npmjs.com/package/path-browserify
|
|
270
|
+
- code [ref=e253]: path-browserify
|
|
271
|
+
- text: because the shared loader normalises paths.
|
|
272
|
+
- paragraph [ref=e254]:
|
|
273
|
+
- text: This mirrors the native-swig build recipe at
|
|
274
|
+
- link "gina-io/swig/Makefile:58" [ref=e255] [cursor=pointer]:
|
|
275
|
+
- /url: https://github.com/gina-io/swig/blob/develop/Makefile#L58
|
|
276
|
+
- text: .
|
|
277
|
+
- generic [ref=e257]:
|
|
278
|
+
- code [ref=e259]:
|
|
279
|
+
- generic [ref=e260]: // entry.js
|
|
280
|
+
- generic [ref=e261]: var twig = require('@rhinostone/swig-twig');
|
|
281
|
+
- generic [ref=e262]: "twig.setDefaults({"
|
|
282
|
+
- generic [ref=e263]: "loader: twig.loaders.memory({"
|
|
283
|
+
- generic [ref=e264]: "'greeting.twig': 'Hello {{ name|upper }}!'"
|
|
284
|
+
- generic [ref=e265]: "})"
|
|
285
|
+
- generic [ref=e266]: "});"
|
|
286
|
+
- generic [ref=e267]: window.twig = twig;
|
|
287
|
+
- button "Copy code to clipboard" [ref=e269] [cursor=pointer]:
|
|
288
|
+
- generic [ref=e270]:
|
|
289
|
+
- img [ref=e271]
|
|
290
|
+
- img [ref=e273]
|
|
291
|
+
- generic [ref=e276]:
|
|
292
|
+
- code [ref=e278]:
|
|
293
|
+
- generic [ref=e279]: // stubs/fs.js — empty stub, turns the filesystem loader into a no-op
|
|
294
|
+
- generic [ref=e280]: "module.exports = {};"
|
|
295
|
+
- button "Copy code to clipboard" [ref=e282] [cursor=pointer]:
|
|
296
|
+
- generic [ref=e283]:
|
|
297
|
+
- img [ref=e284]
|
|
298
|
+
- img [ref=e286]
|
|
299
|
+
- generic [ref=e289]:
|
|
300
|
+
- code [ref=e291]:
|
|
301
|
+
- generic [ref=e292]: // build.js
|
|
302
|
+
- generic [ref=e293]: "require('esbuild').build({"
|
|
303
|
+
- generic [ref=e294]: "entryPoints: ['entry.js'],"
|
|
304
|
+
- generic [ref=e295]: "bundle: true,"
|
|
305
|
+
- generic [ref=e296]: "format: 'iife',"
|
|
306
|
+
- generic [ref=e297]: "outfile: 'dist/browser.js',"
|
|
307
|
+
- generic [ref=e298]: "alias: {"
|
|
308
|
+
- generic [ref=e299]: "fs: './stubs/fs.js',"
|
|
309
|
+
- generic [ref=e300]: "path: 'path-browserify'"
|
|
310
|
+
- generic [ref=e301]: "},"
|
|
311
|
+
- generic [ref=e302]: "minify: true,"
|
|
312
|
+
- generic [ref=e303]: "sourcemap: true"
|
|
313
|
+
- generic [ref=e304]: "}).catch(function (err) { console.error(err); process.exit(1); });"
|
|
314
|
+
- button "Copy code to clipboard" [ref=e306] [cursor=pointer]:
|
|
315
|
+
- generic [ref=e307]:
|
|
316
|
+
- img [ref=e308]
|
|
317
|
+
- img [ref=e310]
|
|
318
|
+
- generic [ref=e313]:
|
|
319
|
+
- code [ref=e315]:
|
|
320
|
+
- generic [ref=e316]: node build.js
|
|
321
|
+
- button "Copy code to clipboard" [ref=e318] [cursor=pointer]:
|
|
322
|
+
- generic [ref=e319]:
|
|
323
|
+
- img [ref=e320]
|
|
324
|
+
- img [ref=e322]
|
|
325
|
+
- paragraph [ref=e324]:
|
|
326
|
+
- text: Load it with a
|
|
327
|
+
- code [ref=e325]: <script>
|
|
328
|
+
- text: "tag:"
|
|
329
|
+
- generic [ref=e327]:
|
|
330
|
+
- code [ref=e329]:
|
|
331
|
+
- generic [ref=e330]: <!doctype html>
|
|
332
|
+
- generic [ref=e331]: <html>
|
|
333
|
+
- generic [ref=e332]: <body>
|
|
334
|
+
- generic [ref=e333]: <div id="out"></div>
|
|
335
|
+
- generic [ref=e334]:
|
|
336
|
+
- text: <script src="dist/browser.js">
|
|
337
|
+
- text: </script>
|
|
338
|
+
- generic [ref=e335]: <script>
|
|
339
|
+
- generic [ref=e336]: "var out = window.twig.render('Hello {{ name|upper }}!', {"
|
|
340
|
+
- generic [ref=e337]: "locals: { name: 'world' }"
|
|
341
|
+
- generic [ref=e338]: "});"
|
|
342
|
+
- generic [ref=e339]: document.querySelector('#out').textContent = out;
|
|
343
|
+
- generic [ref=e340]: // → "Hello WORLD!"
|
|
344
|
+
- generic [ref=e341]: </script>
|
|
345
|
+
- generic [ref=e342]: </body>
|
|
346
|
+
- generic [ref=e343]: </html>
|
|
347
|
+
- button "Copy code to clipboard" [ref=e345] [cursor=pointer]:
|
|
348
|
+
- generic [ref=e346]:
|
|
349
|
+
- img [ref=e347]
|
|
350
|
+
- img [ref=e349]
|
|
351
|
+
- paragraph [ref=e351]:
|
|
352
|
+
- strong [ref=e352]: Other bundlers follow the same shape.
|
|
353
|
+
- link "Vite" [ref=e353] [cursor=pointer]:
|
|
354
|
+
- /url: https://vitejs.dev/
|
|
355
|
+
- text: and
|
|
356
|
+
- link "Rollup" [ref=e354] [cursor=pointer]:
|
|
357
|
+
- /url: https://rollupjs.org/
|
|
358
|
+
- text: use
|
|
359
|
+
- code [ref=e355]: resolve.alias
|
|
360
|
+
- text: (Vite) or the
|
|
361
|
+
- link "@rollup/plugin-alias" [ref=e356] [cursor=pointer]:
|
|
362
|
+
- /url: https://www.npmjs.com/package/@rollup/plugin-alias
|
|
363
|
+
- code [ref=e357]: "@rollup/plugin-alias"
|
|
364
|
+
- text: plugin.
|
|
365
|
+
- link "Webpack" [ref=e358] [cursor=pointer]:
|
|
366
|
+
- /url: https://webpack.js.org/
|
|
367
|
+
- text: uses
|
|
368
|
+
- code [ref=e359]: resolve.alias
|
|
369
|
+
- text: +
|
|
370
|
+
- code [ref=e360]: "resolve.fallback: { fs: false }"
|
|
371
|
+
- text: ". The requirement is always: stub"
|
|
372
|
+
- code [ref=e361]: fs
|
|
373
|
+
- text: ", alias"
|
|
374
|
+
- code [ref=e362]: path
|
|
375
|
+
- text: .
|
|
376
|
+
- heading "Extends + includeDirect link to Extends + include" [level=2] [ref=e363]:
|
|
377
|
+
- text: Extends + include
|
|
378
|
+
- link "Direct link to Extends + include" [ref=e364] [cursor=pointer]:
|
|
379
|
+
- /url: "#extends--include"
|
|
380
|
+
- text: "#"
|
|
381
|
+
- paragraph [ref=e365]:
|
|
382
|
+
- text: For templates using
|
|
383
|
+
- code [ref=e366]: "{% extends %}"
|
|
384
|
+
- text: or
|
|
385
|
+
- code [ref=e367]: "{% include %}"
|
|
386
|
+
- text: ", prime the memory loader with every referenced file before rendering:"
|
|
387
|
+
- generic [ref=e369]:
|
|
388
|
+
- code [ref=e371]:
|
|
389
|
+
- generic [ref=e372]: "twig.setDefaults({"
|
|
390
|
+
- generic [ref=e373]: "loader: twig.loaders.memory({"
|
|
391
|
+
- generic [ref=e374]: "'layout.twig': '<!doctype html><title>{{ title }}</title>{% block body %}{% endblock %}',"
|
|
392
|
+
- generic [ref=e375]: "'page.twig': '{% extends \"layout.twig\" %}{% block body %}Hello {{ name|upper }}!{% endblock %}'"
|
|
393
|
+
- generic [ref=e376]: "})"
|
|
394
|
+
- generic [ref=e377]: "});"
|
|
395
|
+
- generic [ref=e378]: "twig.renderFile('page.twig', { title: 'Hi', name: 'world' });"
|
|
396
|
+
- generic [ref=e379]: // → "<!doctype html><title>Hi</title>Hello WORLD!"
|
|
397
|
+
- generic [ref=e380]:
|
|
398
|
+
- button "Toggle word wrap" [ref=e381] [cursor=pointer]:
|
|
399
|
+
- img [ref=e382]
|
|
400
|
+
- button "Copy code to clipboard" [ref=e384] [cursor=pointer]:
|
|
401
|
+
- generic [ref=e385]:
|
|
402
|
+
- img [ref=e386]
|
|
403
|
+
- img [ref=e388]
|
|
404
|
+
- paragraph [ref=e390]:
|
|
405
|
+
- text: The loader contract is identical across frontends — see
|
|
406
|
+
- link "Loaders" [ref=e391] [cursor=pointer]:
|
|
407
|
+
- /url: /docs/swig/loaders
|
|
408
|
+
- text: .
|
|
409
|
+
- heading "AOT pre-compilationDirect link to AOT pre-compilation" [level=2] [ref=e392]:
|
|
410
|
+
- text: AOT pre-compilation
|
|
411
|
+
- link "Direct link to AOT pre-compilation" [ref=e393] [cursor=pointer]:
|
|
412
|
+
- /url: "#aot-pre-compilation"
|
|
413
|
+
- text: "#"
|
|
414
|
+
- paragraph [ref=e394]:
|
|
415
|
+
- text: If bundle size or cold-render latency matters, pre-compile Twig templates to plain JavaScript at build time, ship only the runtime (the compiled
|
|
416
|
+
- code [ref=e395]: _output += …
|
|
417
|
+
- text: functions) to the browser, and skip the parser entirely. The flow is identical to native swig's — see
|
|
418
|
+
- link "Swig Browser Usage → Pre-compile + prime + render" [ref=e396] [cursor=pointer]:
|
|
419
|
+
- /url: /docs/swig/browser#pre-compile--prime--render
|
|
420
|
+
- text: . The compiled output is the same shape regardless of which frontend produced it, because both lower to
|
|
421
|
+
- code [ref=e397]: swig-core
|
|
422
|
+
- text: IR before codegen.
|
|
423
|
+
- heading "Bundle sizeDirect link to Bundle size" [level=2] [ref=e398]:
|
|
424
|
+
- text: Bundle size
|
|
425
|
+
- link "Direct link to Bundle size" [ref=e399] [cursor=pointer]:
|
|
426
|
+
- /url: "#bundle-size"
|
|
427
|
+
- text: "#"
|
|
428
|
+
- paragraph [ref=e400]:
|
|
429
|
+
- text: As of
|
|
430
|
+
- code [ref=e401]: 2.0.0-alpha.8
|
|
431
|
+
- text: ", a minified browser bundle of"
|
|
432
|
+
- code [ref=e402]: "@rhinostone/swig-twig"
|
|
433
|
+
- text: plus its transitive
|
|
434
|
+
- code [ref=e403]: "@rhinostone/swig-core"
|
|
435
|
+
- text: dependency weighs approximately
|
|
436
|
+
- strong [ref=e404]: 82 KB minified
|
|
437
|
+
- text: (~27 KB gzipped) via esbuild
|
|
438
|
+
- code [ref=e405]: "--minify --format=iife"
|
|
439
|
+
- text: — measured against an entry point that imports the default Twig instance, wires up a memory loader, and exposes it on
|
|
440
|
+
- code [ref=e406]: window.twig
|
|
441
|
+
- text: .
|
|
442
|
+
- paragraph [ref=e407]: For perf-critical paths, prefer AOT pre-compilation (previous section) — the runtime footprint drops substantially because the lexer and parser are not shipped.
|
|
443
|
+
- heading "Security modelDirect link to Security model" [level=2] [ref=e408]:
|
|
444
|
+
- text: Security model
|
|
445
|
+
- link "Direct link to Security model" [ref=e409] [cursor=pointer]:
|
|
446
|
+
- /url: "#security-model"
|
|
447
|
+
- text: "#"
|
|
448
|
+
- paragraph [ref=e410]:
|
|
449
|
+
- code [ref=e411]: "@rhinostone/swig-twig"
|
|
450
|
+
- text: inherits every security guarantee of
|
|
451
|
+
- code [ref=e412]: "@rhinostone/swig-core"
|
|
452
|
+
- text: ":"
|
|
453
|
+
- list [ref=e413]:
|
|
454
|
+
- listitem [ref=e414]:
|
|
455
|
+
- strong [ref=e415]: Autoescape is on by default.
|
|
456
|
+
- text: HTML entities are escaped on every
|
|
457
|
+
- code [ref=e416]: "{{ … }}"
|
|
458
|
+
- text: output unless the expression is explicitly marked
|
|
459
|
+
- code [ref=e417]: safe
|
|
460
|
+
- text: (built-in filter) or produced by a user filter declaring
|
|
461
|
+
- code [ref=e418]: .safe = true
|
|
462
|
+
- text: .
|
|
463
|
+
- listitem [ref=e419]:
|
|
464
|
+
- strong [ref=e420]:
|
|
465
|
+
- text: CVE-2023-25345
|
|
466
|
+
- code [ref=e421]: _dangerousProps
|
|
467
|
+
- text: guards.
|
|
468
|
+
- code [ref=e422]: __proto__
|
|
469
|
+
- text: ","
|
|
470
|
+
- code [ref=e423]: constructor
|
|
471
|
+
- text: ", and"
|
|
472
|
+
- code [ref=e424]: prototype
|
|
473
|
+
- text: are rejected at parse time in every context that writes to
|
|
474
|
+
- code [ref=e425]: _ctx
|
|
475
|
+
- text: ": dotted access, bracket-notation with string literals,"
|
|
476
|
+
- code [ref=e426]: "{% set %}"
|
|
477
|
+
- text: LHS,
|
|
478
|
+
- code [ref=e427]: "{% for %}"
|
|
479
|
+
- text: loop variables,
|
|
480
|
+
- code [ref=e428]: "{% macro %}"
|
|
481
|
+
- text: names, and
|
|
482
|
+
- code [ref=e429]: "{% import %}"
|
|
483
|
+
- text: aliases. The guards are frontend-agnostic — both native swig and Twig run them.
|
|
484
|
+
- listitem [ref=e430]:
|
|
485
|
+
- strong [ref=e431]: Template source is trusted.
|
|
486
|
+
- text: Same model as upstream Twig, Jinja2, and Django. Never pass user-controlled strings directly to
|
|
487
|
+
- code [ref=e432]: twig.render(source, locals)
|
|
488
|
+
- text: ; keep locals data-only.
|
|
489
|
+
- paragraph [ref=e433]:
|
|
490
|
+
- text: See
|
|
491
|
+
- link "Security — the parser is the boundary" [ref=e434] [cursor=pointer]:
|
|
492
|
+
- /url: /docs/swig/security#the-parser-is-the-boundary
|
|
493
|
+
- text: for the full story.
|
|
494
|
+
- heading "GotchasDirect link to Gotchas" [level=2] [ref=e435]:
|
|
495
|
+
- text: Gotchas
|
|
496
|
+
- link "Direct link to Gotchas" [ref=e436] [cursor=pointer]:
|
|
497
|
+
- /url: "#gotchas"
|
|
498
|
+
- text: "#"
|
|
499
|
+
- list [ref=e437]:
|
|
500
|
+
- listitem [ref=e438]:
|
|
501
|
+
- strong [ref=e439]: Filesystem loader throws in the browser.
|
|
502
|
+
- text: Always call
|
|
503
|
+
- code [ref=e440]: "twig.setDefaults({ loader: twig.loaders.memory({}) })"
|
|
504
|
+
- text: at module init time — before any render.
|
|
505
|
+
- listitem [ref=e441]:
|
|
506
|
+
- strong [ref=e442]: Peer-dependency pinning.
|
|
507
|
+
- text: During alpha,
|
|
508
|
+
- code [ref=e443]: "@rhinostone/swig-core"
|
|
509
|
+
- text: and
|
|
510
|
+
- code [ref=e444]: "@rhinostone/swig-twig"
|
|
511
|
+
- text: must be installed at the
|
|
512
|
+
- strong [ref=e445]: exact same version
|
|
513
|
+
- text: . Bundlers that rely on npm's
|
|
514
|
+
- code [ref=e446]: node_modules/@rhinostone/swig-core
|
|
515
|
+
- text: symlink (as in a workspace dev checkout) can mask a missing
|
|
516
|
+
- code [ref=e447]: dependencies
|
|
517
|
+
- text: declaration. Verify by bundling against a fresh
|
|
518
|
+
- code [ref=e448]: node_modules
|
|
519
|
+
- text: .
|
|
520
|
+
- listitem [ref=e449]:
|
|
521
|
+
- strong [ref=e450]: Cache persistence.
|
|
522
|
+
- text: The compiled-template cache lives on the Twig instance — reset on page reload. Hot-reload consumers should call
|
|
523
|
+
- code [ref=e451]: twig.invalidateCache()
|
|
524
|
+
- text: before re-priming.
|
|
525
|
+
- listitem [ref=e452]:
|
|
526
|
+
- strong [ref=e453]:
|
|
527
|
+
- code [ref=e454]: swig run
|
|
528
|
+
- text: is not a sandbox.
|
|
529
|
+
- text: Same warning as the native frontend — the function body is
|
|
530
|
+
- code [ref=e455]: eval
|
|
531
|
+
- text: "'d. Never hand user-controlled strings to it."
|
|
532
|
+
- heading "Gina's browser buildDirect link to Gina's browser build" [level=2] [ref=e456]:
|
|
533
|
+
- text: Gina's browser build
|
|
534
|
+
- link "Direct link to Gina's browser build" [ref=e457] [cursor=pointer]:
|
|
535
|
+
- /url: "#ginas-browser-build"
|
|
536
|
+
- text: "#"
|
|
537
|
+
- paragraph [ref=e458]:
|
|
538
|
+
- text: Gina's vendored browser build at
|
|
539
|
+
- code [ref=e459]: framework/v*/core/deps/swig-client/swig.js
|
|
540
|
+
- text: currently ships the native-swig bundle only. A vendored swig-twig bundle is scheduled for the
|
|
541
|
+
- code [ref=e460]: 2.0.0
|
|
542
|
+
- text: stable release; track progress in the
|
|
543
|
+
- link "project roadmap" [ref=e461] [cursor=pointer]:
|
|
544
|
+
- /url: https://github.com/gina-io/swig/blob/develop/ROADMAP.md
|
|
545
|
+
- text: .
|
|
546
|
+
- generic [ref=e462]:
|
|
547
|
+
- generic [ref=e463]:
|
|
548
|
+
- generic [ref=e464]: Was this page helpful?
|
|
549
|
+
- generic [ref=e465]:
|
|
550
|
+
- button "Yes, this was helpful" [ref=e466] [cursor=pointer]:
|
|
551
|
+
- generic [ref=e467]: 👍
|
|
552
|
+
- generic [ref=e468]: –
|
|
553
|
+
- button "No, this was not helpful" [ref=e469] [cursor=pointer]:
|
|
554
|
+
- generic [ref=e470]: 👎
|
|
555
|
+
- generic [ref=e471]: –
|
|
556
|
+
- link "Edit this page" [ref=e475] [cursor=pointer]:
|
|
557
|
+
- /url: https://github.com/gina-io/docs/tree/main/docs/swig/twig/browser.mdx
|
|
558
|
+
- img [ref=e476]
|
|
559
|
+
- text: Edit this page
|
|
560
|
+
- navigation "Docs pages" [ref=e480]:
|
|
561
|
+
- link "Previous « From upstream Twig" [ref=e481] [cursor=pointer]:
|
|
562
|
+
- /url: /docs/swig/twig/migration
|
|
563
|
+
- generic [ref=e482]: Previous
|
|
564
|
+
- generic [ref=e483]: « From upstream Twig
|
|
565
|
+
- link "Next Migration Guide »" [ref=e484] [cursor=pointer]:
|
|
566
|
+
- /url: /docs/swig/migration
|
|
567
|
+
- generic [ref=e485]: Next
|
|
568
|
+
- generic [ref=e486]: Migration Guide »
|
|
569
|
+
- list [ref=e490]:
|
|
570
|
+
- listitem [ref=e491]:
|
|
571
|
+
- link "Architecture" [ref=e492] [cursor=pointer]:
|
|
572
|
+
- /url: "#architecture"
|
|
573
|
+
- listitem [ref=e493]:
|
|
574
|
+
- link "Install" [ref=e494] [cursor=pointer]:
|
|
575
|
+
- /url: "#install"
|
|
576
|
+
- listitem [ref=e495]:
|
|
577
|
+
- link "Bundle with esbuild" [ref=e496] [cursor=pointer]:
|
|
578
|
+
- /url: "#bundle-with-esbuild"
|
|
579
|
+
- listitem [ref=e497]:
|
|
580
|
+
- link "Extends + include" [ref=e498] [cursor=pointer]:
|
|
581
|
+
- /url: "#extends--include"
|
|
582
|
+
- listitem [ref=e499]:
|
|
583
|
+
- link "AOT pre-compilation" [ref=e500] [cursor=pointer]:
|
|
584
|
+
- /url: "#aot-pre-compilation"
|
|
585
|
+
- listitem [ref=e501]:
|
|
586
|
+
- link "Bundle size" [ref=e502] [cursor=pointer]:
|
|
587
|
+
- /url: "#bundle-size"
|
|
588
|
+
- listitem [ref=e503]:
|
|
589
|
+
- link "Security model" [ref=e504] [cursor=pointer]:
|
|
590
|
+
- /url: "#security-model"
|
|
591
|
+
- listitem [ref=e505]:
|
|
592
|
+
- link "Gotchas" [ref=e506] [cursor=pointer]:
|
|
593
|
+
- /url: "#gotchas"
|
|
594
|
+
- listitem [ref=e507]:
|
|
595
|
+
- link "Gina's browser build" [ref=e508] [cursor=pointer]:
|
|
596
|
+
- /url: "#ginas-browser-build"
|
|
597
|
+
- contentinfo [ref=e509]:
|
|
598
|
+
- generic [ref=e510]:
|
|
599
|
+
- generic [ref=e511]:
|
|
600
|
+
- generic [ref=e512]:
|
|
601
|
+
- generic [ref=e513]: Docs
|
|
602
|
+
- list [ref=e514]:
|
|
603
|
+
- listitem [ref=e515]:
|
|
604
|
+
- link "Getting Started" [ref=e516] [cursor=pointer]:
|
|
605
|
+
- /url: /docs/intro
|
|
606
|
+
- generic [ref=e517]:
|
|
607
|
+
- generic [ref=e518]: Community
|
|
608
|
+
- list [ref=e519]:
|
|
609
|
+
- listitem [ref=e520]:
|
|
610
|
+
- link "GitHub Issues(opens in new tab)" [ref=e521] [cursor=pointer]:
|
|
611
|
+
- /url: https://github.com/gina-io/gina/issues
|
|
612
|
+
- text: GitHub Issues
|
|
613
|
+
- img "(opens in new tab)" [ref=e522]
|
|
614
|
+
- listitem [ref=e524]:
|
|
615
|
+
- link "GitHub Discussions(opens in new tab)" [ref=e525] [cursor=pointer]:
|
|
616
|
+
- /url: https://github.com/gina-io/gina/discussions
|
|
617
|
+
- text: GitHub Discussions
|
|
618
|
+
- img "(opens in new tab)" [ref=e526]
|
|
619
|
+
- listitem [ref=e528]:
|
|
620
|
+
- link "Support Gina" [ref=e529] [cursor=pointer]:
|
|
621
|
+
- /url: /docs/support
|
|
622
|
+
- generic [ref=e530]:
|
|
623
|
+
- generic [ref=e531]: More
|
|
624
|
+
- list [ref=e532]:
|
|
625
|
+
- listitem [ref=e533]:
|
|
626
|
+
- link "npm(opens in new tab)" [ref=e534] [cursor=pointer]:
|
|
627
|
+
- /url: https://www.npmjs.com/package/gina
|
|
628
|
+
- text: npm
|
|
629
|
+
- img "(opens in new tab)" [ref=e535]
|
|
630
|
+
- generic [ref=e538]: Copyright © 2009-2026 gina-io.
|
|
631
|
+
- button "Collapse sidebar" [ref=e540] [cursor=pointer]:
|
|
632
|
+
- img [ref=e541]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|