@stacksjs/stx 0.2.155 → 0.2.156

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 (240) hide show
  1. package/dist/a11y.d.ts +87 -46
  2. package/dist/animation.d.ts +96 -42
  3. package/dist/appearance-bootstrap.d.ts +49 -15
  4. package/dist/asset-roots.d.ts +32 -0
  5. package/dist/asset-roots.js +7 -0
  6. package/dist/assets.d.ts +9 -7
  7. package/dist/async-components.d.ts +78 -56
  8. package/dist/auth.d.ts +3 -0
  9. package/dist/build-externalize.d.ts +40 -0
  10. package/dist/build-externalize.js +63 -0
  11. package/dist/build-id.d.ts +22 -22
  12. package/dist/build-message.d.ts +73 -2
  13. package/dist/build-message.js +47 -8
  14. package/dist/builtins/attrs.d.ts +14 -0
  15. package/dist/builtins/drawer.d.ts +22 -0
  16. package/dist/builtins/icon.d.ts +16 -2
  17. package/dist/builtins/index.d.ts +5 -15
  18. package/dist/builtins/modal.d.ts +24 -0
  19. package/dist/builtins/safe-image.d.ts +42 -0
  20. package/dist/builtins/stx-image.d.ts +27 -0
  21. package/dist/builtins/stx-link.d.ts +9 -0
  22. package/dist/builtins/stx-loading-indicator.d.ts +11 -0
  23. package/dist/builtins/suspense.d.ts +28 -0
  24. package/dist/builtins/toast.d.ts +17 -0
  25. package/dist/builtins/transition-group.d.ts +25 -0
  26. package/dist/caching.d.ts +12 -15
  27. package/dist/cli.js +1798 -908
  28. package/dist/client/directive.d.ts +7 -0
  29. package/dist/client/index.d.ts +0 -1
  30. package/dist/client-script-bundler.d.ts +63 -5
  31. package/dist/client-script-bundler.js +30 -2
  32. package/dist/client-script.d.ts +102 -47
  33. package/dist/client-script.js +15 -3
  34. package/dist/codemod.d.ts +56 -0
  35. package/dist/codemod.js +192 -0
  36. package/dist/color-mode-boot.d.ts +83 -65
  37. package/dist/component-client-factories.d.ts +1 -6
  38. package/dist/component-processing.d.ts +58 -49
  39. package/dist/component-processing.js +1 -1
  40. package/dist/component-registry.d.ts +94 -31
  41. package/dist/component-renderer.d.ts +18 -0
  42. package/dist/composable-loader.d.ts +24 -0
  43. package/dist/composable-loader.js +12 -9
  44. package/dist/composables/index.d.ts +7 -0
  45. package/dist/composables/index.js +1 -0
  46. package/dist/composables/use-fetch.js +30 -2
  47. package/dist/composables/use-form.d.ts +91 -0
  48. package/dist/composables/use-form.js +112 -0
  49. package/dist/composables.d.ts +64 -60
  50. package/dist/computed.d.ts +86 -92
  51. package/dist/conditionals.d.ts +24 -8
  52. package/dist/conditionals.js +16 -0
  53. package/dist/config.d.ts +34 -21
  54. package/dist/config.js +35 -14
  55. package/dist/craft.js +1476 -768
  56. package/dist/crosswind-config.d.ts +58 -0
  57. package/dist/crosswind-config.js +40 -0
  58. package/dist/csp.d.ts +107 -41
  59. package/dist/defer.d.ts +24 -0
  60. package/dist/dev-server/crosswind.d.ts +35 -26
  61. package/dist/dev-server/crosswind.js +2 -18
  62. package/dist/dev-server/serve-app.js +4 -3
  63. package/dist/dev-server/terminal-colors.d.ts +32 -32
  64. package/dist/directive-api.d.ts +86 -43
  65. package/dist/document-shell.d.ts +54 -41
  66. package/dist/dynamic-components.d.ts +9 -0
  67. package/dist/error-boundaries.d.ts +47 -41
  68. package/dist/error-handling.d.ts +1 -1
  69. package/dist/errors/codes.d.ts +51 -43
  70. package/dist/errors/formatter.d.ts +58 -38
  71. package/dist/errors/index.d.ts +5 -61
  72. package/dist/errors/logger.d.ts +114 -40
  73. package/dist/errors/sanitizer.d.ts +53 -23
  74. package/dist/errors/types.d.ts +44 -31
  75. package/dist/events.d.ts +86 -25
  76. package/dist/expressions.d.ts +50 -42
  77. package/dist/forms-validation.d.ts +138 -123
  78. package/dist/forms-validation.js +1 -90
  79. package/dist/forms.d.ts +120 -66
  80. package/dist/forms.js +31 -11
  81. package/dist/fragment-container.d.ts +57 -0
  82. package/dist/fragment-container.js +109 -0
  83. package/dist/framework-composables.d.ts +32 -0
  84. package/dist/head.d.ts +156 -114
  85. package/dist/heatmap.d.ts +152 -72
  86. package/dist/html-masking.d.ts +40 -34
  87. package/dist/hydration-runtime.d.ts +20 -24
  88. package/dist/i18n.d.ts +93 -32
  89. package/dist/image-optimization/auto-sibling.d.ts +32 -4
  90. package/dist/includes.d.ts +69 -7
  91. package/dist/index.d.ts +66 -0
  92. package/dist/index.js +23 -0
  93. package/dist/internal-markdown.d.ts +12 -8
  94. package/dist/island-chunking.d.ts +30 -13
  95. package/dist/keep-alive.d.ts +72 -52
  96. package/dist/layout-types.d.ts +45 -0
  97. package/dist/layout-types.js +56 -0
  98. package/dist/lazy-module.d.ts +10 -0
  99. package/dist/loops.d.ts +66 -0
  100. package/dist/loops.js +47 -6
  101. package/dist/markdown.d.ts +0 -1
  102. package/dist/media/image/component.d.ts +25 -9
  103. package/dist/media/image/directive.d.ts +15 -1
  104. package/dist/media/image/placeholder.d.ts +20 -9
  105. package/dist/media/image/processor/cache.d.ts +40 -18
  106. package/dist/media/image/processor/index.d.ts +1 -10
  107. package/dist/media/image/processor/optimizer.d.ts +12 -1
  108. package/dist/media/image/processor/responsive.d.ts +16 -6
  109. package/dist/media/image/srcset.d.ts +47 -50
  110. package/dist/media/shared/cache.d.ts +51 -31
  111. package/dist/media/shared/hash.d.ts +7 -0
  112. package/dist/media/types.d.ts +1235 -754
  113. package/dist/media/video/directive.d.ts +15 -1
  114. package/dist/media/video/index.d.ts +39 -17
  115. package/dist/media/video/processor/cache.d.ts +42 -19
  116. package/dist/media/video/processor/index.d.ts +1 -18
  117. package/dist/media/video/processor/streaming.d.ts +17 -10
  118. package/dist/media/video/processor/thumbnail.d.ts +21 -15
  119. package/dist/media/video/processor/transcoder.d.ts +11 -1
  120. package/dist/method-spoofing.d.ts +7 -0
  121. package/dist/middleware.d.ts +60 -0
  122. package/dist/owned-routes.d.ts +42 -0
  123. package/dist/owned-routes.js +26 -0
  124. package/dist/page-meta.d.ts +38 -0
  125. package/dist/page-meta.js +16 -0
  126. package/dist/parser/directive-parser.d.ts +57 -45
  127. package/dist/parser/expression-parser.d.ts +33 -35
  128. package/dist/parser/index.d.ts +4 -39
  129. package/dist/parser/tokenizer.d.ts +61 -49
  130. package/dist/partial-hydration.d.ts +82 -50
  131. package/dist/performance-utils.d.ts +217 -124
  132. package/dist/placeholder.d.ts +18 -9
  133. package/dist/plugin-system.d.ts +264 -115
  134. package/dist/process.d.ts +11 -6
  135. package/dist/process.js +21 -4
  136. package/dist/production-builder.js +7 -0
  137. package/dist/prop-sentinels.d.ts +11 -11
  138. package/dist/public-env.d.ts +14 -0
  139. package/dist/pwa/directives.d.ts +12 -3
  140. package/dist/pwa/inject.d.ts +10 -0
  141. package/dist/pwa/precache.d.ts +22 -16
  142. package/dist/pwa/service-worker.d.ts +12 -0
  143. package/dist/pwa.js +1318 -610
  144. package/dist/reactive-bindings.d.ts +34 -11
  145. package/dist/reactive.d.ts +58 -30
  146. package/dist/reactive.js +56 -31
  147. package/dist/render.js +1 -0
  148. package/dist/route-middleware.d.ts +2 -35
  149. package/dist/route-types.d.ts +134 -0
  150. package/dist/route-types.js +24 -0
  151. package/dist/router.d.ts +5 -7
  152. package/dist/routes.d.ts +1 -3
  153. package/dist/runtime-globals.d.ts +147 -24
  154. package/dist/runtime-globals.js +16 -1
  155. package/dist/runtime-injection.d.ts +8 -0
  156. package/dist/runtime-injection.js +33 -24
  157. package/dist/script-emit.d.ts +30 -0
  158. package/dist/script-json.d.ts +36 -0
  159. package/dist/script-json.js +6 -0
  160. package/dist/script-validation.d.ts +21 -4
  161. package/dist/seo.d.ts +118 -47
  162. package/dist/server-bindings.d.ts +21 -0
  163. package/dist/sfc-template.d.ts +8 -8
  164. package/dist/signal-processing.d.ts +35 -15
  165. package/dist/signals-api.d.ts +117 -58
  166. package/dist/signals-api.js +7 -4
  167. package/dist/signals.d.ts +24 -17
  168. package/dist/signals.js +765 -60
  169. package/dist/site-builder/build.js +8 -0
  170. package/dist/site-url.d.ts +46 -0
  171. package/dist/site-url.js +70 -0
  172. package/dist/slots.d.ts +86 -20
  173. package/dist/source-signature.d.ts +45 -0
  174. package/dist/source-signature.js +20 -0
  175. package/dist/ssg.d.ts +285 -142
  176. package/dist/ssg.js +1268 -556
  177. package/dist/state-dir.d.ts +4 -4
  178. package/dist/state-management.d.ts +0 -12
  179. package/dist/state-management.js +8 -25
  180. package/dist/store-imports.d.ts +23 -0
  181. package/dist/store-imports.js +3 -0
  182. package/dist/store-loader.d.ts +10 -0
  183. package/dist/store-loader.js +10 -9
  184. package/dist/story/analytics.d.ts +138 -60
  185. package/dist/story/bookmarks.d.ts +87 -34
  186. package/dist/story/cli.d.ts +123 -69
  187. package/dist/story/collect/scanner.d.ts +4 -0
  188. package/dist/story/collect/tree.d.ts +8 -1
  189. package/dist/story/commands/build.d.ts +11 -6
  190. package/dist/story/commands/dev.d.ts +15 -8
  191. package/dist/story/commands/preview.d.ts +13 -7
  192. package/dist/story/config-watcher.d.ts +20 -13
  193. package/dist/story/config.d.ts +11 -8
  194. package/dist/story/context.d.ts +14 -8
  195. package/dist/story/hmr.d.ts +24 -26
  196. package/dist/story/hot-swap.d.ts +34 -23
  197. package/dist/story/keyboard-shortcuts.d.ts +23 -18
  198. package/dist/story/output.d.ts +46 -44
  199. package/dist/story/performance.d.ts +107 -45
  200. package/dist/story/presets.d.ts +107 -41
  201. package/dist/story/renderer.d.ts +41 -27
  202. package/dist/story/search.d.ts +23 -12
  203. package/dist/story/server.d.ts +21 -11
  204. package/dist/story/setup.d.ts +23 -15
  205. package/dist/story/testing.d.ts +65 -40
  206. package/dist/story/types.d.ts +262 -160
  207. package/dist/streaming.d.ts +119 -57
  208. package/dist/stx-virtual-ts.d.ts +165 -0
  209. package/dist/stx-virtual-ts.js +372 -0
  210. package/dist/stx.d.ts +78 -1
  211. package/dist/style-scoping.d.ts +17 -4
  212. package/dist/suspense.d.ts +67 -52
  213. package/dist/teleport.d.ts +22 -0
  214. package/dist/template-tag-balance.d.ts +22 -6
  215. package/dist/transitions.d.ts +66 -55
  216. package/dist/typecheck.d.ts +77 -0
  217. package/dist/typecheck.js +156 -0
  218. package/dist/types/component-types.d.ts +187 -122
  219. package/dist/types/config-types.d.ts +758 -297
  220. package/dist/types/context-types.d.ts +46 -24
  221. package/dist/types/csp-types.d.ts +70 -66
  222. package/dist/types/directive-types.d.ts +211 -155
  223. package/dist/types/index.d.ts +6 -109
  224. package/dist/types/pwa-types.d.ts +273 -148
  225. package/dist/types.d.ts +0 -1
  226. package/dist/typescript-templates.d.ts +11 -0
  227. package/dist/unresolved-identifiers.d.ts +24 -22
  228. package/dist/unresolved-identifiers.js +2 -0
  229. package/dist/utils.d.ts +24 -21
  230. package/dist/validator.d.ts +28 -26
  231. package/dist/variable-extractor.d.ts +48 -13
  232. package/dist/variable-extractor.js +27 -4
  233. package/dist/view-composers.d.ts +80 -81
  234. package/dist/virtual-scrolling.d.ts +101 -81
  235. package/dist/vue-template.d.ts +23 -0
  236. package/dist/web-components/css-scoping.d.ts +21 -11
  237. package/dist/web-components.d.ts +81 -58
  238. package/dist/x-element.d.ts +0 -1
  239. package/package.json +5 -5
  240. package/stx.d.ts +78 -1
@@ -1,27 +1,3 @@
1
- /**
2
- * Build the destructuring statement that pulls {@link STX_RUNTIME_GLOBALS} into
3
- * a generated client script's scope.
4
- *
5
- * @param declaration `var` for scripts that reassign a binding (the `@include`
6
- * wrapper rebinds `onDestroy` to tee into its teardown channel — an assignment,
7
- * which `var` permits), `const` otherwise.
8
- * @param exclude names the generated wrapper or user script declares itself.
9
- * A local declaration is intentionally allowed to shadow a runtime convenience
10
- * global, just as an explicit import would. Omitting it from this destructure
11
- * prevents duplicate-binding syntax errors.
12
- * @param source optionally limits bindings to identifiers referenced by one
13
- * component script. Page-level callers omit it and retain the full authoring
14
- * surface.
15
- */
16
- export declare function buildRuntimeGlobalsDestructure(declaration?: 'const' | 'var', exclude?: readonly string[], source?: string): string;
17
- /**
18
- * Does this script call anything that needs the reactive runtime?
19
- *
20
- * Matches a CALL, not a mention: a bare word can be a property, a string or a
21
- * comment. Tolerates a generic argument list, since `state<Foo>(…)` is valid
22
- * TypeScript and common.
23
- */
24
- export declare function usesReactiveRuntime(source: string): boolean;
25
1
  /**
26
2
  * Runtime Globals
27
3
  *
@@ -78,6 +54,22 @@ export declare const STX_RUNTIME_GLOBALS: readonly string[];
78
54
  * #1785 fixed, so it is declared here rather than left implicit.
79
55
  */
80
56
  export declare const COMPONENT_SCOPE_LOCAL_GLOBALS: readonly string[];
57
+ /**
58
+ * Build the destructuring statement that pulls {@link STX_RUNTIME_GLOBALS} into
59
+ * a generated client script's scope.
60
+ *
61
+ * @param declaration `var` for scripts that reassign a binding (the `@include`
62
+ * wrapper rebinds `onDestroy` to tee into its teardown channel — an assignment,
63
+ * which `var` permits), `const` otherwise.
64
+ * @param exclude names the generated wrapper or user script declares itself.
65
+ * A local declaration is intentionally allowed to shadow a runtime convenience
66
+ * global, just as an explicit import would. Omitting it from this destructure
67
+ * prevents duplicate-binding syntax errors.
68
+ * @param source optionally limits bindings to identifiers referenced by one
69
+ * component script. Page-level callers omit it and retain the full authoring
70
+ * surface.
71
+ */
72
+ export declare function buildRuntimeGlobalsDestructure(declaration?: 'const' | 'var', exclude?: readonly string[], source?: string): string;
81
73
  /**
82
74
  * Runtime globals that are COMPILE-TIME macros rather than reactive APIs.
83
75
  *
@@ -86,6 +78,33 @@ export declare const COMPONENT_SCOPE_LOCAL_GLOBALS: readonly string[];
86
78
  * below must not treat them as evidence that a block needs mounting.
87
79
  */
88
80
  export declare const COMPILE_TIME_ONLY_GLOBALS: readonly string[];
81
+ /**
82
+ * Public authoring primitives that are NOT reachable as a bare identifier in a
83
+ * `<script client>` block, each tagged with WHY — so the client/server boundary
84
+ * is discoverable in source instead of inferred from a `ReferenceError` at
85
+ * runtime (stacksjs/stx#1846).
86
+ *
87
+ * Paired with the export-side guard in `authoring-surface.test.ts`: a newly
88
+ * exported composable that is reachable by neither client path — a bare global
89
+ * in {@link STX_RUNTIME_GLOBALS} (path 1), nor the demand-bundle allowlist
90
+ * `SERVER_ONLY_COMPOSABLES` (path 2) — must be classified here, or the test
91
+ * fails. Same "force a decision" contract that COMPILE_TIME_ONLY_GLOBALS and
92
+ * DELIBERATELY_NOT_GLOBAL already apply in their own directions.
93
+ *
94
+ * `client-gap` is deliberately distinct from `server-only`: it marks a primitive
95
+ * that SHOULD be callable from a client script but is not yet wired into either
96
+ * client path — a tracked gap, not a boundary.
97
+ *
98
+ * `isomorphic-import` is distinct again: the primitive is pure and WOULD run in a
99
+ * browser, but the project has decided it is not part of the auto-delivered
100
+ * client surface — an app imports it explicitly. Not a gap to close; a boundary
101
+ * drawn on purpose.
102
+ */
103
+ export type NonClientCategory = 'server-only' | 'builtin-component' | 'compile-time-directive' | 'browser-composable' | 'client-gap' | 'isomorphic-import';
104
+ export declare const NON_CLIENT_PRIMITIVES: Readonly<Record<string, {
105
+ category: NonClientCategory;
106
+ reason: string;
107
+ }>>;
89
108
  /**
90
109
  * Names whose presence in a client script means it needs the signals runtime
91
110
  * and an `stx.mount()` wrapper.
@@ -100,3 +119,107 @@ export declare const COMPILE_TIME_ONLY_GLOBALS: readonly string[];
100
119
  * Exactly the drift #1804 removed for STX_AUTO_IMPORTS, one file away.
101
120
  */
102
121
  export declare const REACTIVE_RUNTIME_GLOBALS: readonly string[];
122
+ /**
123
+ * Does this script call anything that needs the reactive runtime?
124
+ *
125
+ * Matches a CALL, not a mention: a bare word can be a property, a string or a
126
+ * comment. Tolerates a generic argument list, since `state<Foo>(…)` is valid
127
+ * TypeScript and common.
128
+ */
129
+ export declare function usesReactiveRuntime(source: string): boolean;
130
+ /**
131
+ * Does this template have a reactive context — a signal, a bound attribute, a
132
+ * reactive directive, or a client script — that will own its event handlers?
133
+ *
134
+ * This is the question `processEventDirectives` (events.ts) needs. It decides
135
+ * whether to leave `@click` in the markup for the signals runtime to bind, or to
136
+ * strip it and bind it imperatively through `__stx_runHandler`.
137
+ *
138
+ * It used to answer that with its own regex matching only `state`/`derived`/
139
+ * `effect` plus four directives, so a client block built out of `useStore` (or
140
+ * any of the other ~65 reactive globals) failed it. The handler was stripped and
141
+ * rebound to code that resolves it through a `[data-stx-scope]` ancestor that
142
+ * page-level client blocks never get, then fell back to evaluating the bare
143
+ * name — which lives inside the setup closure and is not a global. Every handler
144
+ * on the page died with a ReferenceError on click (#1824).
145
+ *
146
+ * Note this is NOT the same question as {@link templateNeedsRuntime}: a template
147
+ * whose only client-side behaviour is `<button @click="doIt()">` needs the
148
+ * runtime injected, but has no reactive scope to own the handler, so events.ts
149
+ * must still bind it imperatively. Conflating the two makes that fallback
150
+ * unreachable.
151
+ */
152
+ export declare function templateHasReactiveContext(template: string): boolean;
153
+ /**
154
+ * Will this template get the client signals runtime?
155
+ *
156
+ * A reactive context needs it, and so does a lone event handler — something has
157
+ * to bind that, and the runtime is what binds it when a reactive scope exists.
158
+ *
159
+ * This had three independent implementations that disagreed, and every
160
+ * disagreement was a bug: `hasSignalsSyntax` (signal-processing.ts) decides
161
+ * whether to INJECT the runtime; the auto-mount test (client-script.ts) decides
162
+ * whether to wrap a client block in `stx.mount()` — when it said yes and the
163
+ * first said no, the page emitted `stx.mount(...)` with nothing to mount onto
164
+ * (#1819, #1820); and events.ts asked the related-but-distinct question above
165
+ * (#1824).
166
+ *
167
+ * They live here because events.ts is a leaf module and importing
168
+ * signal-processing.ts would close a cycle through client-script.ts.
169
+ */
170
+ export declare function templateNeedsRuntime(template: string): boolean;
171
+ /**
172
+ * `x-` attributes the signals runtime consumes itself.
173
+ *
174
+ * The runtime treats any unrecognised `x-foo` as a generic attribute binding
175
+ * (`x-href`, `x-src`, `x-alt` all work that way), so the ones it handles
176
+ * through their own code paths have to be excluded — that exclusion is what
177
+ * this list is.
178
+ *
179
+ * It is also what decides whether a component may carry the attribute, which
180
+ * is why it lives here rather than only inside the generated runtime. Those
181
+ * were two hand-maintained lists, and they disagreed about exactly two names:
182
+ * `x-tooltip` and `x-tooltip-position`, the most recently added pair (#1673).
183
+ * Putting one on a COMPONENT rewrote it to `:tooltip="Settings"`, a signal
184
+ * binding over an identifier that does not exist — so the tooltip silently
185
+ * vanished AND the page reported a hydration invariant failure naming the
186
+ * tooltip's text rather than the tooltip (#1830). The same attribute on a
187
+ * plain element worked, which made it unguessable from the authoring side.
188
+ */
189
+ export declare const RUNTIME_HANDLED_X_ATTRS: readonly string[];
190
+ /**
191
+ * `x-` attributes owned by the Alpine-style reactive bridge, not the signals
192
+ * runtime. They never reach `X_HANDLED`, but must still survive on a component
193
+ * for the bridge to find them on the rendered element.
194
+ */
195
+ export declare const ALPINE_BRIDGE_X_ATTRS: readonly string[];
196
+ /**
197
+ * Every `x-` attribute that must reach the rendered DOM element untouched when
198
+ * it is written on a component, rather than being captured as a prop binding.
199
+ */
200
+ export declare const COMPONENT_PASSTHROUGH_X_ATTRS: readonly string[];
201
+ /** The `X_HANDLED` lookup the generated runtime embeds, as JS source. */
202
+ export declare function runtimeHandledXAttrsLiteral(): string;
203
+ /**
204
+ * Blank the parts of an HTML template that cannot carry a live directive,
205
+ * for DETECTION only — never for output.
206
+ *
207
+ * `hasSignalsSyntax` and friends scan raw template text, so a documentation
208
+ * page quoting stx syntax inside a code sample counted as reactive and shipped
209
+ * the whole ~159KB signals runtime for markup that is inert text
210
+ * (stacksjs/stx#1835).
211
+ *
212
+ * Only TEXT is blanked, and only inside `<pre>` / `<code>` and HTML comments.
213
+ * Tags are kept intact, including their attributes, because that is where a
214
+ * directive actually lives:
215
+ *
216
+ * <pre><code>&lt;div :if="open"&gt;</code></pre> -> blanked, it is text
217
+ * <pre><code><span>&lt;div :if="x"&gt;</span></pre> -> span kept, text blanked
218
+ * <pre><button @click="go()">run</button></pre> -> kept, it is a real button
219
+ *
220
+ * Dropping whole regions instead would have been simpler and wrong in the
221
+ * expensive direction: a page whose only reactive element sits inside a `<pre>`
222
+ * would lose its runtime and break, which is worse than shipping bytes it does
223
+ * not need.
224
+ */
225
+ export declare function blankInertHtmlRegions(html: string): string;
@@ -1,6 +1,7 @@
1
1
  export const STX_RUNTIME_GLOBALS = [
2
2
  "batch",
3
3
  "computed",
4
+ "configureFetch",
4
5
  "defineEmits",
5
6
  "defineExpose",
6
7
  "definePageMeta",
@@ -12,6 +13,7 @@ export const STX_RUNTIME_GLOBALS = [
12
13
  "goBack",
13
14
  "goForward",
14
15
  "inject",
16
+ "invalidateRoute",
15
17
  "isDerived",
16
18
  "isSignal",
17
19
  "navigate",
@@ -26,6 +28,7 @@ export const STX_RUNTIME_GLOBALS = [
26
28
  "provide",
27
29
  "reactive",
28
30
  "ref",
31
+ "refresh",
29
32
  "registerStoresClient",
30
33
  "setRouteParams",
31
34
  "state",
@@ -56,6 +59,8 @@ export const STX_RUNTIME_GLOBALS = [
56
59
  "useReactiveProp",
57
60
  "useRef",
58
61
  "useRoute",
62
+ "useRouteParam",
63
+ "useRouteParams",
59
64
  "useScrollLock",
60
65
  "useSearchParams",
61
66
  "useSeoMeta",
@@ -87,7 +92,17 @@ export const COMPILE_TIME_ONLY_GLOBALS = [
87
92
  "defineProps",
88
93
  "defineSlots",
89
94
  "withDefaults"
90
- ], REACTIVE_RUNTIME_GLOBALS = STX_RUNTIME_GLOBALS.filter((name) => !COMPILE_TIME_ONLY_GLOBALS.includes(name));
95
+ ], NON_CLIENT_PRIMITIVES = {
96
+ redirect: { category: "server-only", reason: "returns an HTTP Response for <script server>/edge/build; use navigate() on the client." },
97
+ useAsyncData: { category: "browser-composable", reason: "inlined on demand from src/composables when a script references it; reachable, not a bare global." },
98
+ Teleport: { category: "compile-time-directive", reason: "template tag resolved by processTeleportDirectives; not a script callable." },
99
+ StxModalBuiltin: { category: "builtin-component", reason: "builtin component used as a template tag; drive open/close from the modal store." },
100
+ StxToastBuiltin: { category: "builtin-component", reason: "builtin component used as a template tag; push toasts via the toast store." },
101
+ useForm: { category: "browser-composable", reason: "reactive form primitive; lives in src/composables/use-form.ts and is inlined on demand when a <script client> references it (#1846)." },
102
+ defineForm: { category: "browser-composable", reason: "deprecated alias of useForm, kept for a minor (#1843). Same delivery path \u2014 inlined on demand from src/composables/use-form.ts." },
103
+ validateFields: { category: "isomorphic-import", reason: "pure validation helper; import it directly, not auto-delivered to <script client> (per client-api-delivery.test.ts)." },
104
+ validateField: { category: "isomorphic-import", reason: "singular pure validation helper; same explicit-import boundary as validateFields." }
105
+ }, REACTIVE_RUNTIME_GLOBALS = STX_RUNTIME_GLOBALS.filter((name) => !COMPILE_TIME_ONLY_GLOBALS.includes(name));
91
106
  export function usesReactiveRuntime(source) {
92
107
  if (!source)
93
108
  return !1;
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Runtime Injection Module
3
+ *
4
+ * Handles injecting the signals runtime, browser runtime, and SPA router
5
+ * script into rendered HTML templates.
6
+ *
7
+ * @module runtime-injection
8
+ */
1
9
  import type { StxOptions } from './types';
2
10
  /**
3
11
  * Inject an @stacksjs/browser initialization input into a template that will
@@ -1,3 +1,5 @@
1
+ import { getOwnedRouteMatchers } from "./owned-routes.js";
2
+ import { toScriptJson } from "./script-json.js";
1
3
  export function injectBrowserRuntime(template) {
2
4
  if (template.includes("window.StacksBrowser") || template.includes("StacksBrowser ="))
3
5
  return template;
@@ -126,32 +128,39 @@ export async function injectRouterScript(template, options) {
126
128
  return template;
127
129
  const routerConfig = options?.router;
128
130
  let configScript = "";
129
- if (routerConfig) {
131
+ {
130
132
  const configObj = {};
131
- if (routerConfig.container)
132
- configObj.container = routerConfig.container;
133
- if (routerConfig.interceptAllLinks !== void 0)
134
- configObj.interceptAllLinks = routerConfig.interceptAllLinks;
135
- if (routerConfig.progress !== void 0)
136
- configObj.progress = routerConfig.progress;
137
- if (routerConfig.viewTransitions !== void 0)
138
- configObj.viewTransitions = routerConfig.viewTransitions;
139
- if (routerConfig.viewTransitionDuration !== void 0)
140
- configObj.viewTransitionDuration = routerConfig.viewTransitionDuration;
141
- if (routerConfig.viewTransitionEasing !== void 0)
142
- configObj.viewTransitionEasing = routerConfig.viewTransitionEasing;
143
- if (routerConfig.scrollToTop !== void 0)
144
- configObj.scrollToTop = routerConfig.scrollToTop;
145
- if (routerConfig.prefetch !== void 0)
146
- configObj.prefetch = routerConfig.prefetch;
147
- if (routerConfig.cache !== void 0)
148
- configObj.cache = routerConfig.cache;
149
- if (routerConfig.progressColor !== void 0)
150
- configObj.progressColor = routerConfig.progressColor;
151
- if (routerConfig.progressHeight !== void 0)
152
- configObj.progressHeight = routerConfig.progressHeight;
133
+ if (routerConfig) {
134
+ if (routerConfig.container)
135
+ configObj.container = routerConfig.container;
136
+ if (routerConfig.interceptAllLinks !== void 0)
137
+ configObj.interceptAllLinks = routerConfig.interceptAllLinks;
138
+ if (routerConfig.progress !== void 0)
139
+ configObj.progress = routerConfig.progress;
140
+ if (routerConfig.viewTransitions !== void 0)
141
+ configObj.viewTransitions = routerConfig.viewTransitions;
142
+ if (routerConfig.viewTransitionDuration !== void 0)
143
+ configObj.viewTransitionDuration = routerConfig.viewTransitionDuration;
144
+ if (routerConfig.viewTransitionEasing !== void 0)
145
+ configObj.viewTransitionEasing = routerConfig.viewTransitionEasing;
146
+ if (routerConfig.scrollToTop !== void 0)
147
+ configObj.scrollToTop = routerConfig.scrollToTop;
148
+ if (routerConfig.prefetch !== void 0)
149
+ configObj.prefetch = routerConfig.prefetch;
150
+ if (routerConfig.cache !== void 0)
151
+ configObj.cache = routerConfig.cache;
152
+ if (routerConfig.progressColor !== void 0)
153
+ configObj.progressColor = routerConfig.progressColor;
154
+ if (routerConfig.progressHeight !== void 0)
155
+ configObj.progressHeight = routerConfig.progressHeight;
156
+ }
157
+ try {
158
+ const owned = await getOwnedRouteMatchers(options?.pagesDir);
159
+ if (owned.length > 0)
160
+ configObj.ownedRoutes = owned;
161
+ } catch {}
153
162
  if (Object.keys(configObj).length > 0)
154
- configScript = `<script>window.__stxRouterConfig=${JSON.stringify(configObj)};</script>
163
+ configScript = `<script>window.__stxRouterConfig=${toScriptJson(configObj)};</script>
155
164
  `;
156
165
  }
157
166
  const { getCachedRouterScript } = await import("./caching.js"), routerScript = options?.buildMode === "compile" ? '<script data-stx-router src="/__stx/router.__STX_HASH__.js"></script>' : options?.buildMode === "serve" ? '<script data-stx-router src="/_stx/router.js"></script>' : `<script data-stx-router>${await getCachedRouterScript()}</script>`, bodyCloseIdx = template.lastIndexOf("</body>");
@@ -1,3 +1,33 @@
1
+ /**
2
+ * Escape script bodies at EMIT time (stacksjs/stx#1792, part one item 2).
3
+ *
4
+ * A `</script>` anywhere inside a script body — in a string, a comment, or a
5
+ * runtime value — ends the element as far as the HTML parser is concerned. The
6
+ * rest of the script is then painted onto the page as text, and everything
7
+ * defined below the offending line silently does not exist.
8
+ *
9
+ * The documented workaround is to write `<\/script>` in the source. It does not
10
+ * work, and that is the crux of the report: `transpileTypeScript` runs every
11
+ * non-server block through Bun's transpiler, which NORMALISES the escape away
12
+ * before the browser ever sees it.
13
+ *
14
+ * in : const s = "<\/script>"
15
+ * out: const s = "</script>";
16
+ *
17
+ * So the escape protects the source from stx's own scanners and is then
18
+ * stripped, leaving the HTML parser to apply exactly the rule it was meant to
19
+ * dodge. Escaping on emit is the only place the protection can survive, because
20
+ * it happens after the transpiler.
21
+ *
22
+ * The transform is semantically inert for JavaScript: `\/` inside a string, a
23
+ * template literal, a regex literal or a comment parses as `/`. It is also
24
+ * valid inside JSON, where `\/` is an explicit escape — so a JSON-LD or
25
+ * importmap body would survive it, though those bodies are excluded upstream
26
+ * and never reach here.
27
+ *
28
+ * This is a leaf module on purpose: no stx imports, so every emit site can use
29
+ * it without creating a cycle.
30
+ */
1
31
  /**
2
32
  * Neutralise closing script tags in a JavaScript body about to be embedded in
3
33
  * an HTML `<script>` element.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Embed JSON inside a `<script>` tag safely.
3
+ *
4
+ * `JSON.stringify` alone is not enough for script content, in two ways that both
5
+ * end with the browser parsing something the author did not write:
6
+ *
7
+ * - A `</script>` sequence inside any string value closes the tag early. The
8
+ * rest of the JSON then lands in the document as markup, so whoever controls
9
+ * that string controls the page.
10
+ * - U+2028 and U+2029 are literal line terminators in JavaScript, though legal
11
+ * unescaped in JSON. A value containing one splits the statement it sits in.
12
+ *
13
+ * This existed as five separate private copies — `spa-shell.ts`,
14
+ * `appearance-bootstrap.ts`, `color-mode-boot.ts`, `misc-directives.ts` and
15
+ * `bun-plugin/src/serve.ts`. That is the shape of bug this repo keeps paying
16
+ * for: a sixth injection site (`runtime-injection.ts`, added with the
17
+ * `ownedRoutes` table in #1864) had no escaping at all, because nothing
18
+ * connected it to the others.
19
+ *
20
+ * The escapes below are written as `\u` sequences rather than literal
21
+ * characters, and that is load-bearing. Writing a raw U+2028 inside the regex
22
+ * terminates the line mid-literal and the file stops parsing — this module's
23
+ * own first draft did exactly that, which is a fair demonstration of why the
24
+ * function needs to exist.
25
+ *
26
+ * @module script-json
27
+ */
28
+ /**
29
+ * Escape an already-serialised JSON string for inclusion in a `<script>` body.
30
+ *
31
+ * `<` and `>` are escaped rather than only the `</script>` sequence, so no
32
+ * variant spelling (`</SCRIPT`, `</script foo`) can slip through.
33
+ */
34
+ export declare function escapeJsonForScript(json: string): string;
35
+ /** Serialise a value and escape it for a `<script>` body in one step. */
36
+ export declare function toScriptJson(value: unknown): string;
@@ -0,0 +1,6 @@
1
+ export function escapeJsonForScript(json) {
2
+ return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
3
+ }
4
+ export function toScriptJson(value) {
5
+ return escapeJsonForScript(JSON.stringify(value));
6
+ }
@@ -1,4 +1,20 @@
1
+ /**
2
+ * Script validation module for STX templates.
3
+ *
4
+ * Validates client-side script content against prohibited DOM API patterns,
5
+ * enforcing the use of STX composables and Vue-style alternatives instead
6
+ * of raw browser APIs.
7
+ */
1
8
  import type { StrictModeConfig } from './types';
9
+ /**
10
+ * Prohibited DOM API patterns in client scripts.
11
+ * STX provides Vue-style alternatives via the STX global object.
12
+ */
13
+ export declare const PROHIBITED_DOM_PATTERNS: Array<{
14
+ pattern: RegExp;
15
+ message: string;
16
+ suggestion: string;
17
+ }>;
2
18
  /**
3
19
  * Validate client script content for prohibited DOM API patterns.
4
20
  * When strict mode is enabled with `failOnViolation`, throws an error.
@@ -8,9 +24,10 @@ import type { StrictModeConfig } from './types';
8
24
  * @param filePath - The file path for error reporting
9
25
  * @param strict - Strict mode configuration
10
26
  */
11
- export declare function validateClientScript(content: string, filePath: string, strict?: boolean | StrictModeConfig): void;
27
+ export declare function validateClientScript(content: string, filePath: string, strict?: boolean | StrictModeConfig,
12
28
  /**
13
- * Prohibited DOM API patterns in client scripts.
14
- * STX provides Vue-style alternatives via the STX global object.
29
+ * The view this script was authored in, when `filePath` is a layout that view
30
+ * was composed into. Reported alongside, because naming only the layout sends
31
+ * the reader to a file that does not contain the offending code (#1836).
15
32
  */
16
- export declare const PROHIBITED_DOM_PATTERNS: readonly [unknown];
33
+ originFilePath?: string): void;
package/dist/seo.d.ts CHANGED
@@ -1,3 +1,59 @@
1
+ /**
2
+ * SEO (Search Engine Optimization) Module
3
+ *
4
+ * Provides directives and utilities for generating SEO-related HTML:
5
+ * - `@meta('name', 'content')` - Generate meta tags
6
+ * - `@metaTag({ name, property, content })` - Meta tags with full control
7
+ * - `@structuredData({ ... })` - JSON-LD structured data
8
+ * - `@seo({ title, description, ... })` - Comprehensive SEO generation
9
+ *
10
+ * Also provides:
11
+ * - Automatic SEO tag injection via `injectSeoTags()`
12
+ * - Sitemap generation via `generateSitemap()`, `scanForSitemapEntries()`
13
+ * - robots.txt generation via `generateRobotsTxt()`
14
+ *
15
+ * ## Sitemap Generation
16
+ *
17
+ * ```typescript
18
+ * import { generateSitemap, scanForSitemapEntries } from 'stx'
19
+ *
20
+ * // Manual entries
21
+ * const sitemap = generateSitemap([
22
+ * { loc: '/', priority: 1.0 },
23
+ * { loc: '/about', priority: 0.8 },
24
+ * ], { baseUrl: 'https://example.com' })
25
+ *
26
+ * // Auto-scan directory
27
+ * const entries = await scanForSitemapEntries('./pages', {
28
+ * baseUrl: 'https://example.com'
29
+ * })
30
+ * ```
31
+ *
32
+ * ## Robots.txt Generation
33
+ *
34
+ * ```typescript
35
+ * import { generateRobotsTxt } from 'stx'
36
+ *
37
+ * const robotsTxt = generateRobotsTxt({
38
+ * rules: [{ userAgent: '*', allow: ['/'], disallow: ['/admin'] }],
39
+ * sitemap: 'https://example.com/sitemap.xml'
40
+ * })
41
+ * ```
42
+ *
43
+ * ## Configuration
44
+ *
45
+ * Default SEO values can be set in `stx.config.ts`:
46
+ * ```typescript
47
+ * export default {
48
+ * defaultTitle: 'My Site',
49
+ * defaultDescription: 'Site description',
50
+ * seo: {
51
+ * enabled: true,
52
+ * defaultConfig: { ... }
53
+ * }
54
+ * }
55
+ * ```
56
+ */
1
57
  import type { CustomDirective, StxOptions } from './types';
2
58
  /**
3
59
  * Process @meta directive for generating meta tags.
@@ -20,10 +76,44 @@ export declare function processSeoDirective(template: string, context: Record<st
20
76
  * Respects seo.enabled config and skipDefaultSeoTags option.
21
77
  */
22
78
  export declare function injectSeoTags(html: string, context: Record<string, any>, options: StxOptions): string;
79
+ /**
80
+ * SEO meta directive for basic meta tag generation
81
+ */
82
+ export declare const metaDirective: CustomDirective;
83
+ /**
84
+ * SEO structured data directive for JSON-LD generation
85
+ */
86
+ export declare const structuredDataDirective: CustomDirective;
23
87
  /**
24
88
  * Register SEO directives
25
89
  */
26
90
  export declare function registerSeoDirectives(): CustomDirective[];
91
+ /**
92
+ * URL entry for sitemap
93
+ */
94
+ export interface SitemapEntry {
95
+ /** Full URL of the page */
96
+ loc: string;
97
+ /** Last modification date (ISO 8601 format) */
98
+ lastmod?: string;
99
+ /** Change frequency */
100
+ changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
101
+ /** Priority (0.0 to 1.0) */
102
+ priority?: number;
103
+ }
104
+ /**
105
+ * Sitemap generation options
106
+ */
107
+ export interface SitemapOptions {
108
+ /** Base URL for the site (e.g., 'https://example.com') */
109
+ baseUrl: string;
110
+ /** Default change frequency */
111
+ defaultChangefreq?: SitemapEntry['changefreq'];
112
+ /** Default priority */
113
+ defaultPriority?: number;
114
+ /** Whether to include lastmod for all entries */
115
+ includeLastmod?: boolean;
116
+ }
27
117
  /**
28
118
  * Generate an XML sitemap from a list of URL entries.
29
119
  *
@@ -60,10 +150,34 @@ export declare function generateSitemapIndex(sitemaps: string[], baseUrl: string
60
150
  * @returns Array of sitemap entries
61
151
  */
62
152
  export declare function scanForSitemapEntries(directory: string, options: {
63
- extensions?: string[]
64
- ignore?: string[]
65
- baseUrl: string
66
- }): Promise<SitemapEntry[]>;
153
+ extensions?: string[];
154
+ ignore?: string[];
155
+ baseUrl: string;
156
+ }): Promise<SitemapEntry[]>;
157
+ /**
158
+ * Robots.txt rule
159
+ */
160
+ export interface RobotsRule {
161
+ /** User agent (e.g., '*', 'Googlebot', 'Bingbot') */
162
+ userAgent: string;
163
+ /** Allowed paths */
164
+ allow?: string[];
165
+ /** Disallowed paths */
166
+ disallow?: string[];
167
+ /** Crawl delay in seconds */
168
+ crawlDelay?: number;
169
+ }
170
+ /**
171
+ * Robots.txt generation options
172
+ */
173
+ export interface RobotsOptions {
174
+ /** Array of rules */
175
+ rules: RobotsRule[];
176
+ /** Sitemap URL(s) */
177
+ sitemap?: string | string[];
178
+ /** Host directive (for Yandex) */
179
+ host?: string;
180
+ }
67
181
  /**
68
182
  * Generate a robots.txt file content.
69
183
  *
@@ -97,46 +211,3 @@ export declare function generateRobotsTxt(options: RobotsOptions): string;
97
211
  * @returns robots.txt content string
98
212
  */
99
213
  export declare function generateDefaultRobotsTxt(sitemapUrl?: string): string;
100
- /**
101
- * SEO meta directive for basic meta tag generation
102
- */
103
- export declare const metaDirective: CustomDirective;
104
- /**
105
- * SEO structured data directive for JSON-LD generation
106
- */
107
- export declare const structuredDataDirective: CustomDirective;
108
- /**
109
- * URL entry for sitemap
110
- */
111
- export declare interface SitemapEntry {
112
- loc: string
113
- lastmod?: string
114
- changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'
115
- priority?: number
116
- }
117
- /**
118
- * Sitemap generation options
119
- */
120
- export declare interface SitemapOptions {
121
- baseUrl: string
122
- defaultChangefreq?: SitemapEntry['changefreq']
123
- defaultPriority?: number
124
- includeLastmod?: boolean
125
- }
126
- /**
127
- * Robots.txt rule
128
- */
129
- export declare interface RobotsRule {
130
- userAgent: string
131
- allow?: string[]
132
- disallow?: string[]
133
- crawlDelay?: number
134
- }
135
- /**
136
- * Robots.txt generation options
137
- */
138
- export declare interface RobotsOptions {
139
- rules: RobotsRule[]
140
- sitemap?: string | string[]
141
- host?: string
142
- }
@@ -1,3 +1,24 @@
1
+ /**
2
+ * Server-Side Attribute Binding Resolution
3
+ *
4
+ * Resolves `:attr="expr"` bindings server-side when the expression can be
5
+ * evaluated in the server context. This allows Vue-style shorthand binding
6
+ * syntax to work in server-rendered templates without client-side JS.
7
+ *
8
+ * Supported patterns:
9
+ * - `:src="imageUrl"` → `src="https://example.com/image.png"`
10
+ * - `:href="link.url"` → `href="/about"`
11
+ * - `:class="isActive ? 'active' : ''"` → `class="active"`
12
+ * - `:class="{ active: isActive, hidden: !show }"` → `class="active"`
13
+ * - `:class="[baseClass, isActive && 'active']"` → `class="btn active"`
14
+ * - `:disabled="isLoading"` → `disabled` (boolean attributes)
15
+ * - `:id="'item-' + item.id"` → `id="item-42"`
16
+ *
17
+ * Bindings that can't be resolved server-side (e.g., referencing signals or
18
+ * undefined variables) are left intact for client-side processing.
19
+ *
20
+ * @module server-bindings
21
+ */
1
22
  /**
2
23
  * Process server-side `:attr="expr"` bindings in a template.
3
24
  *