@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,4 +1,195 @@
1
+ /**
2
+ * Plugin System for stx
3
+ *
4
+ * Provides a robust plugin architecture with lifecycle hooks for extending
5
+ * the template processing pipeline.
6
+ *
7
+ * ## Plugin Lifecycle
8
+ *
9
+ * Plugins can hook into various stages of template processing:
10
+ *
11
+ * 1. **beforeProcess** - Before any directive processing begins
12
+ * 2. **afterParse** - After template is parsed but before directives run
13
+ * 3. **beforeDirective** - Before each directive type is processed
14
+ * 4. **afterDirective** - After each directive type is processed
15
+ * 5. **beforeRender** - Before final output is generated
16
+ * 6. **afterRender** - After final output is generated
17
+ * 7. **onError** - When an error occurs during processing
18
+ *
19
+ * ## Example Plugin
20
+ *
21
+ * ```typescript
22
+ * const myPlugin: StxPlugin = {
23
+ * name: 'my-plugin',
24
+ * version: '1.0.0',
25
+ *
26
+ * beforeProcess({ template, context }) {
27
+ * // Add global variables
28
+ * context.myPluginData = { initialized: true }
29
+ * return { template, context }
30
+ * },
31
+ *
32
+ * registerDirectives() {
33
+ * return [{
34
+ * name: 'myDirective',
35
+ * handler: (content, params) => content.toUpperCase(),
36
+ * hasEndTag: true
37
+ * }]
38
+ * }
39
+ * }
40
+ * ```
41
+ *
42
+ * @module plugin-system
43
+ */
1
44
  import type { CustomDirective, StxOptions } from './types';
45
+ /**
46
+ * Context passed to lifecycle hooks
47
+ */
48
+ export interface PluginContext {
49
+ /** Current template content */
50
+ template: string;
51
+ /** Template context/variables */
52
+ context: Record<string, unknown>;
53
+ /** Source file path */
54
+ filePath: string;
55
+ /** Stx options */
56
+ options: StxOptions;
57
+ /** Dependencies tracked during processing */
58
+ dependencies: Set<string>;
59
+ /** Metadata for plugin communication */
60
+ metadata: Record<string, unknown>;
61
+ }
62
+ /**
63
+ * Result from a lifecycle hook
64
+ */
65
+ export interface PluginHookResult {
66
+ /** Modified template (optional) */
67
+ template?: string;
68
+ /** Modified context (optional) */
69
+ context?: Record<string, unknown>;
70
+ /** Whether to skip further processing (optional) */
71
+ skip?: boolean;
72
+ /** Additional metadata to pass along */
73
+ metadata?: Record<string, unknown>;
74
+ }
75
+ /**
76
+ * Error context passed to onError hook
77
+ */
78
+ export interface PluginErrorContext extends PluginContext {
79
+ /** The error that occurred */
80
+ error: Error;
81
+ /** Phase where error occurred */
82
+ phase: string;
83
+ /** Directive being processed (if applicable) */
84
+ directive?: string;
85
+ }
86
+ /**
87
+ * Directive type identifier for beforeDirective/afterDirective hooks
88
+ */
89
+ export type DirectivePhase = 'comments' | 'escaped' | 'stacks' | 'layouts' | 'includes' | 'js' | 'ts' | 'custom' | 'components' | 'animation' | 'routes' | 'auth' | 'csrf' | 'method' | 'loops' | 'conditionals' | 'forms' | 'markdown' | 'i18n' | 'a11y' | 'seo' | 'expressions';
90
+ /**
91
+ * Plugin definition interface
92
+ */
93
+ export interface StxPlugin {
94
+ /** Unique plugin name */
95
+ name: string;
96
+ /** Plugin version (semver) */
97
+ version?: string;
98
+ /** Plugin description */
99
+ description?: string;
100
+ /** Plugin dependencies (other plugin names) */
101
+ dependencies?: string[];
102
+ /** Order priority (lower runs first, default: 100) */
103
+ priority?: number;
104
+ /**
105
+ * Called before any template processing begins.
106
+ * Use this to initialize plugin state or modify the initial template.
107
+ */
108
+ beforeProcess?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
109
+ /**
110
+ * Called after the template is parsed but before directives are processed.
111
+ * Useful for template analysis or pre-processing.
112
+ */
113
+ afterParse?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
114
+ /**
115
+ * Called before a specific directive type is processed.
116
+ * @param phase - The directive phase being processed
117
+ * @param ctx - Plugin context
118
+ */
119
+ beforeDirective?: (phase: DirectivePhase, ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
120
+ /**
121
+ * Called after a specific directive type is processed.
122
+ * @param phase - The directive phase that was processed
123
+ * @param ctx - Plugin context
124
+ */
125
+ afterDirective?: (phase: DirectivePhase, ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
126
+ /**
127
+ * Called before the final render output is generated.
128
+ */
129
+ beforeRender?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
130
+ /**
131
+ * Called after the final render output is generated.
132
+ */
133
+ afterRender?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void;
134
+ /**
135
+ * Called when an error occurs during processing.
136
+ * Can return a recovery template or rethrow the error.
137
+ */
138
+ onError?: (ctx: PluginErrorContext) => PluginHookResult | Promise<PluginHookResult> | void;
139
+ /**
140
+ * Register custom directives provided by this plugin.
141
+ * Called during plugin initialization.
142
+ */
143
+ registerDirectives?: () => CustomDirective[];
144
+ /**
145
+ * Register custom expression filters.
146
+ * Called during plugin initialization.
147
+ */
148
+ registerFilters?: () => Record<string, (value: unknown, ...args: unknown[]) => unknown>;
149
+ /**
150
+ * Called when the plugin is registered.
151
+ * Use for one-time initialization.
152
+ */
153
+ onRegister?: (options: StxOptions) => void | Promise<void>;
154
+ /**
155
+ * Called when the plugin is unregistered.
156
+ * Use for cleanup.
157
+ */
158
+ onUnregister?: () => void | Promise<void>;
159
+ /** Directory of .stx components — auto-registered, available in all templates */
160
+ /**
161
+ * Component directory, or directories.
162
+ *
163
+ * An array lets one package register several roots — @stacksjs/components
164
+ * ships src/ui and src/components as siblings (#1823).
165
+ */
166
+ components?: string | string[];
167
+ /** Directory of composable functions — importable via @/functions/ */
168
+ functions?: string;
169
+ /** Directory of store definitions — auto-registered */
170
+ stores?: string;
171
+ /** Directory of page templates — merged into file-based routing */
172
+ pages?: string;
173
+ /** Directory of route middleware */
174
+ middleware?: string;
175
+ /** Setup function called when plugin is loaded — receives options and stx context */
176
+ setup?: (options: Record<string, any>, stx: PluginSetupContext) => void | Promise<void>;
177
+ }
178
+ /**
179
+ * Context passed to plugin setup() function
180
+ */
181
+ export interface PluginSetupContext {
182
+ /** Register a custom directive */
183
+ addDirective: (directive: CustomDirective) => void;
184
+ /** Register an API route handler */
185
+ addRoute: (path: string, handler: (req: Request) => Response | Promise<Response>) => void;
186
+ /** Register route middleware */
187
+ addMiddleware: (middleware: any) => void;
188
+ /** The resolved plugin directory path */
189
+ pluginDir: string;
190
+ /** The stx config */
191
+ config: StxOptions;
192
+ }
2
193
  /**
3
194
  * Define an stx plugin with type safety.
4
195
  *
@@ -18,21 +209,84 @@ import type { CustomDirective, StxOptions } from './types';
18
209
  */
19
210
  export declare function definePlugin(config: StxPlugin): StxPlugin;
20
211
  /**
21
- * Create a simple directive plugin
212
+ * Plugin manager that handles registration, lifecycle, and execution
22
213
  */
23
- export declare function createDirectivePlugin(name: string, directives: CustomDirective[], options?: Partial<Omit<StxPlugin, 'name' | 'registerDirectives'>>): StxPlugin;
214
+ export declare class PluginManager {
215
+ private plugins;
216
+ private sortedPlugins;
217
+ private initialized;
218
+ /**
219
+ * Register a plugin
220
+ */
221
+ register(plugin: StxPlugin, options: StxOptions): Promise<void>;
222
+ /**
223
+ * Unregister a plugin
224
+ */
225
+ unregister(name: string): Promise<boolean>;
226
+ /**
227
+ * Get a registered plugin by name
228
+ */
229
+ get(name: string): StxPlugin | undefined;
230
+ /**
231
+ * Check if a plugin is registered
232
+ */
233
+ has(name: string): boolean;
234
+ /**
235
+ * Get all registered plugins (sorted by priority)
236
+ */
237
+ getAll(): StxPlugin[];
238
+ /**
239
+ * Get all custom directives from all plugins
240
+ */
241
+ getAllDirectives(): CustomDirective[];
242
+ /**
243
+ * Get all filters from all plugins
244
+ */
245
+ getAllFilters(): Record<string, (value: unknown, ...args: unknown[]) => unknown>;
246
+ /**
247
+ * Run beforeProcess hooks on all plugins
248
+ */
249
+ runBeforeProcess(ctx: PluginContext): Promise<PluginContext>;
250
+ /**
251
+ * Run afterParse hooks on all plugins
252
+ */
253
+ runAfterParse(ctx: PluginContext): Promise<PluginContext>;
254
+ /**
255
+ * Run beforeDirective hooks on all plugins
256
+ */
257
+ runBeforeDirective(phase: DirectivePhase, ctx: PluginContext): Promise<PluginContext>;
258
+ /**
259
+ * Run afterDirective hooks on all plugins
260
+ */
261
+ runAfterDirective(phase: DirectivePhase, ctx: PluginContext): Promise<PluginContext>;
262
+ /**
263
+ * Run beforeRender hooks on all plugins
264
+ */
265
+ runBeforeRender(ctx: PluginContext): Promise<PluginContext>;
266
+ /**
267
+ * Run afterRender hooks on all plugins
268
+ */
269
+ runAfterRender(ctx: PluginContext): Promise<PluginContext>;
270
+ /**
271
+ * Run onError hooks on all plugins
272
+ */
273
+ runOnError(ctx: PluginErrorContext): Promise<PluginContext | null>;
274
+ private sortPlugins;
275
+ private runHooks;
276
+ private runDirectiveHooks;
277
+ }
24
278
  /**
25
- * Create a simple filter plugin
279
+ * Global plugin manager instance
26
280
  */
27
- export declare function createFilterPlugin(name: string, filters: Record<string, (value: unknown, ...args: unknown[]) => unknown>, options?: Partial<Omit<StxPlugin, 'name' | 'registerFilters'>>): StxPlugin;
281
+ export declare const pluginManager: PluginManager;
28
282
  /**
29
- * Variables plugin that adds common variables to context
283
+ * Create a simple directive plugin
30
284
  */
31
- export declare function createVariablesPlugin(variables: Record<string, unknown>): StxPlugin;
285
+ export declare function createDirectivePlugin(name: string, directives: CustomDirective[], options?: Partial<Omit<StxPlugin, 'name' | 'registerDirectives'>>): StxPlugin;
32
286
  /**
33
- * Global plugin manager instance
287
+ * Create a simple filter plugin
34
288
  */
35
- export declare const pluginManager: PluginManager;
289
+ export declare function createFilterPlugin(name: string, filters: Record<string, (value: unknown, ...args: unknown[]) => unknown>, options?: Partial<Omit<StxPlugin, 'name' | 'registerFilters'>>): StxPlugin;
36
290
  /**
37
291
  * Debug plugin that logs all lifecycle events
38
292
  */
@@ -42,111 +296,6 @@ export declare const debugPlugin: StxPlugin;
42
296
  */
43
297
  export declare const timingPlugin: StxPlugin;
44
298
  /**
45
- * Context passed to lifecycle hooks
46
- */
47
- export declare interface PluginContext {
48
- template: string
49
- context: Record<string, unknown>
50
- filePath: string
51
- options: StxOptions
52
- dependencies: Set<string>
53
- metadata: Record<string, unknown>
54
- }
55
- /**
56
- * Result from a lifecycle hook
57
- */
58
- export declare interface PluginHookResult {
59
- template?: string
60
- context?: Record<string, unknown>
61
- skip?: boolean
62
- metadata?: Record<string, unknown>
63
- }
64
- /**
65
- * Error context passed to onError hook
66
- */
67
- export declare interface PluginErrorContext extends PluginContext {
68
- error: Error
69
- phase: string
70
- directive?: string
71
- }
72
- /**
73
- * Plugin definition interface
74
- */
75
- export declare interface StxPlugin {
76
- name: string
77
- version?: string
78
- description?: string
79
- dependencies?: string[]
80
- priority?: number
81
- beforeProcess?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
82
- afterParse?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
83
- beforeDirective?: (phase: DirectivePhase, ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
84
- afterDirective?: (phase: DirectivePhase, ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
85
- beforeRender?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
86
- afterRender?: (ctx: PluginContext) => PluginHookResult | Promise<PluginHookResult> | void
87
- onError?: (ctx: PluginErrorContext) => PluginHookResult | Promise<PluginHookResult> | void
88
- registerDirectives?: () => CustomDirective[]
89
- registerFilters?: () => Record<string, (value: unknown, ...args: unknown[]) => unknown>
90
- onRegister?: (options: StxOptions) => void | Promise<void>
91
- onUnregister?: () => void | Promise<void>
92
- components?: string | string[]
93
- functions?: string
94
- stores?: string
95
- pages?: string
96
- middleware?: string
97
- setup?: (options: Record<string, any>, stx: PluginSetupContext) => void | Promise<void>
98
- }
99
- /**
100
- * Context passed to plugin setup() function
101
- */
102
- export declare interface PluginSetupContext {
103
- addDirective: (directive: CustomDirective) => void
104
- addRoute: (path: string, handler: (req: Request) => Response | Promise<Response>) => void
105
- addMiddleware: (middleware: any) => void
106
- pluginDir: string
107
- config: StxOptions
108
- }
109
- /**
110
- * Directive type identifier for beforeDirective/afterDirective hooks
111
- */
112
- export type DirectivePhase = | 'comments'
113
- | 'escaped'
114
- | 'stacks'
115
- | 'layouts'
116
- | 'includes'
117
- | 'js'
118
- | 'ts'
119
- | 'custom'
120
- | 'components'
121
- | 'animation'
122
- | 'routes'
123
- | 'auth'
124
- | 'csrf'
125
- | 'method'
126
- | 'loops'
127
- | 'conditionals'
128
- | 'forms'
129
- | 'markdown'
130
- | 'i18n'
131
- | 'a11y'
132
- | 'seo'
133
- | 'expressions';
134
- /**
135
- * Plugin manager that handles registration, lifecycle, and execution
299
+ * Variables plugin that adds common variables to context
136
300
  */
137
- export declare class PluginManager {
138
- register(plugin: StxPlugin, options: StxOptions): Promise<void>;
139
- unregister(name: string): Promise<boolean>;
140
- get(name: string): StxPlugin | undefined;
141
- has(name: string): boolean;
142
- getAll(): StxPlugin[];
143
- getAllDirectives(): CustomDirective[];
144
- getAllFilters(): Record<string, (value: unknown, ...args: unknown[]) => unknown>;
145
- runBeforeProcess(ctx: PluginContext): Promise<PluginContext>;
146
- runAfterParse(ctx: PluginContext): Promise<PluginContext>;
147
- runBeforeDirective(phase: DirectivePhase, ctx: PluginContext): Promise<PluginContext>;
148
- runAfterDirective(phase: DirectivePhase, ctx: PluginContext): Promise<PluginContext>;
149
- runBeforeRender(ctx: PluginContext): Promise<PluginContext>;
150
- runAfterRender(ctx: PluginContext): Promise<PluginContext>;
151
- runOnError(ctx: PluginErrorContext): Promise<PluginContext | null>;
152
- }
301
+ export declare function createVariablesPlugin(variables: Record<string, unknown>): StxPlugin;
package/dist/process.d.ts CHANGED
@@ -1,11 +1,16 @@
1
- import { processJsonDirective, processOnceDirective } from './misc-directives';
2
- import { validateClientScript } from './script-validation';
3
- import type { StxOptions } from './types';
4
1
  /**
5
- * Process all template directives with enhanced error handling and performance monitoring
2
+ * Core Template Processing Pipeline
3
+ *
4
+ * Orchestrates the full directive processing pipeline for STX templates.
5
+ * Delegates to specialized modules for signals, components, runtime injection, etc.
6
+ *
7
+ * @module process
6
8
  */
7
- export declare function processDirectives(template: string, context: Record<string, any>, filePath: string, options: StxOptions, dependencies: Set<string>): Promise<string>;
8
- // Re-export public API from extracted modules (preserves backwards compatibility)
9
+ import type { StxOptions } from './types';
9
10
  export { injectRouterScript } from './runtime-injection';
10
11
  export { processJsonDirective, processOnceDirective } from './misc-directives';
11
12
  export { validateClientScript } from './script-validation';
13
+ /**
14
+ * Process all template directives with enhanced error handling and performance monitoring
15
+ */
16
+ export declare function processDirectives(template: string, context: Record<string, any>, filePath: string, options: StxOptions, dependencies: Set<string>): Promise<string>;
package/dist/process.js CHANGED
@@ -1,3 +1,4 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
2
3
  import { injectCrosswindCSS } from "./dev-server/crosswind.js";
3
4
  import { matchHtmlComment, matchStyleElement, maskAtElementPosition, stashScriptElements } from "./html-masking.js";
@@ -9,6 +10,7 @@ import { injectHeatmap } from "./heatmap.js";
9
10
  import { processAnimationDirectives } from "./animation.js";
10
11
  import { generateRuntimeScript, processEventDirectives } from "./events.js";
11
12
  import { extractBridgeData, processClientScript } from "./client-script.js";
13
+ import { extractPageMetaFromSource, pageMetaLayout } from "./page-meta.js";
12
14
  import { processReactiveDirectives } from "./reactive.js";
13
15
  import { processMarkdownFileDirectives } from "./assets.js";
14
16
  import { processAuthDirectives, processConditionals, processEnvDirective, processIssetEmptyDirectives } from "./conditionals.js";
@@ -391,13 +393,19 @@ async function processDirectivesInternal(template, context, filePath, options, d
391
393
  output = processStackPushDirectives(output, stacks);
392
394
  const sections = { ...context.__sections || {} };
393
395
  let layoutPath = "";
394
- const hasNoLayout = /@nolayout\b/.test(output);
395
- if (hasNoLayout)
396
+ const declaredLayout = pageMetaLayout(extractPageMetaFromSource(template)), hasNoLayout = /@nolayout\b/.test(output) || declaredLayout === !1;
397
+ if (/@nolayout\b/.test(output))
396
398
  output = output.replace(/@nolayout\b\s*/g, "");
397
399
  const layoutMatch = output.match(/@(?:layout|extends)\(\s*['"]([^'"]+)['"]\s*\)/);
398
400
  if (layoutMatch) {
399
401
  layoutPath = layoutMatch[1];
400
402
  output = output.replace(/@(?:layout|extends)\(\s*['"]([^'"]+)['"]\s*\)/g, "");
403
+ } else if (typeof declaredLayout === "string") {
404
+ layoutPath = declaredLayout;
405
+ if (!/@section\s*\(/.test(output))
406
+ output = `@section('content')
407
+ ${output.trim()}
408
+ @endsection`;
401
409
  }
402
410
  if (!layoutPath && !hasNoLayout && opts.defaultLayout) {
403
411
  const isDocument = startsDocument(output), hasSections = /@section\s*\(/.test(output);
@@ -488,8 +496,17 @@ ${joined}` : joined;
488
496
  throw new StxRuntimeError(`Failed to resolve layout path: ${layoutPath}`, filePath, void 0, void 0, `Layout referenced from ${filePath}`);
489
497
  });
490
498
  if (!layoutFullPath) {
491
- const warning = `Layout not found: ${layoutPath} (referenced from ${filePath})`;
492
- errorLogger.log(Error(warning), { layoutPath, filePath }, "warning");
499
+ let available = [];
500
+ try {
501
+ const dir = resolvedOptions.layoutsDir;
502
+ if (dir) {
503
+ const abs = path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir);
504
+ available = fs.readdirSync(abs).filter((f) => f.endsWith(".stx")).map((f) => f.replace(/\.stx$/, "")).sort();
505
+ }
506
+ } catch {}
507
+ const warning = `Layout not found: ${layoutPath} (referenced from ${filePath})` + (available.length > 0 ? `. Available layouts: ${available.join(", ")}` : resolvedOptions.layoutsDir ? `. No .stx layouts found in ${resolvedOptions.layoutsDir}` : "");
508
+ errorLogger.log(Error(warning), { layoutPath, filePath, available }, "error");
509
+ console.error(`[stx] ${warning}`);
493
510
  if (resolvedOptions.debug)
494
511
  throw new StxRuntimeError(warning, filePath);
495
512
  return output;
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { CONVENTIONAL_ASSET_OUTPUT, CONVENTIONAL_ASSET_ROOT, resolveConventionalAssetRoot } from "./asset-roots.js";
3
4
  import { createRouter } from "./router.js";
4
5
  import { buildRuntimeAsset, buildRouterAsset } from "./build-assets.js";
5
6
  import { compileTemplate } from "./template-compiler.js";
@@ -121,6 +122,12 @@ export async function buildForProduction(options = {}) {
121
122
  if (copied > 0)
122
123
  console.log(`[stx build] Copied ${copied} public asset${copied === 1 ? "" : "s"} (${(bytes / 1024).toFixed(1)}KB) from ${publicDir}/`);
123
124
  }
125
+ const conventionalAssetSrc = resolveConventionalAssetRoot(root);
126
+ if (conventionalAssetSrc) {
127
+ const { copied, bytes } = copyPublicAssets(conventionalAssetSrc, path.join(outputDir, "public", CONVENTIONAL_ASSET_OUTPUT));
128
+ if (copied > 0)
129
+ console.log(`[stx build] Copied ${copied} asset${copied === 1 ? "" : "s"} (${(bytes / 1024).toFixed(1)}KB) from ${CONVENTIONAL_ASSET_ROOT}/`);
130
+ }
124
131
  const assets = {
125
132
  runtime: runtimeAsset.filename,
126
133
  router: routerAsset.filename
@@ -1,13 +1,3 @@
1
- /** Is this value the bare-boolean-attribute marker? */
2
- export declare function isBooleanAttributeSentinel(value: unknown): boolean;
3
- /**
4
- * Last-resort guard for anything about to be written into a response.
5
- *
6
- * Nothing should reach output carrying a NUL, but the cost of one escaping is
7
- * an invalid document and a silent grep, which is far worse than the cost of
8
- * this check.
9
- */
10
- export declare function stripControlChars(value: string): string;
11
1
  /**
12
2
  * Sentinel values used while resolving component props.
13
3
  *
@@ -28,4 +18,14 @@ export declare function stripControlChars(value: string): string;
28
18
  * verification step that greps rendered HTML returns an empty string and reads
29
19
  * as a pass (stacksjs/stx#1816).
30
20
  */
31
- export declare const BOOLEAN_ATTRIBUTE_SENTINEL: '\0stx-boolean-attribute';
21
+ export declare const BOOLEAN_ATTRIBUTE_SENTINEL = "\0stx-boolean-attribute";
22
+ /** Is this value the bare-boolean-attribute marker? */
23
+ export declare function isBooleanAttributeSentinel(value: unknown): boolean;
24
+ /**
25
+ * Last-resort guard for anything about to be written into a response.
26
+ *
27
+ * Nothing should reach output carrying a NUL, but the cost of one escaping is
28
+ * an invalid document and a silent grep, which is far worse than the cost of
29
+ * this check.
30
+ */
31
+ export declare function stripControlChars(value: string): string;
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Public env exposure for client bundles
3
+ *
4
+ * Mirrors the server-side `$env` template context (process.ts:762) onto the
5
+ * client side via build-time substitution. Any env var matching `envPrefix`
6
+ * (default `STX_PUBLIC_`) gets inlined as `import.meta.env.STX_PUBLIC_*` in
7
+ * scripts bundled for the browser.
8
+ *
9
+ * .env: STX_PUBLIC_API_URL=https://api.example.com
10
+ * store: const api = import.meta.env.STX_PUBLIC_API_URL
11
+ * built: const api = "https://api.example.com"
12
+ *
13
+ * Vite-style. Build-time, zero runtime cost.
14
+ */
1
15
  /**
2
16
  * Build the `define` map every client bundler/transpiler should pass to
3
17
  * Bun.build / new Bun.Transpiler({ define }).
@@ -1,8 +1,13 @@
1
- import type { CustomDirective } from '../types';
2
1
  /**
3
- * Register all PWA directives with the config
2
+ * PWA Template Directives
3
+ *
4
+ * Provides template directives for PWA functionality:
5
+ * - @pwa.installButton - Install prompt button
6
+ * - @pwa.updatePrompt - Update notification UI
7
+ * - @pwa.offlineIndicator - Offline status indicator
8
+ * - @pwa.pushSubscribe - Push notification subscription button
4
9
  */
5
- export declare function registerPwaDirectives(customDirectives: CustomDirective[]): CustomDirective[];
10
+ import type { CustomDirective } from '../types';
6
11
  /**
7
12
  * PWA Install Button Directive
8
13
  * Usage: @pwa.installButton ... @endpwa.installButton
@@ -27,3 +32,7 @@ export declare const pwaPushDirective: CustomDirective;
27
32
  * All PWA directives
28
33
  */
29
34
  export declare const pwaDirectives: CustomDirective[];
35
+ /**
36
+ * Register all PWA directives with the config
37
+ */
38
+ export declare function registerPwaDirectives(customDirectives: CustomDirective[]): CustomDirective[];
@@ -1,3 +1,13 @@
1
+ /**
2
+ * PWA HTML Tag Injection
3
+ *
4
+ * Injects PWA-related meta tags, links, and scripts into HTML output.
5
+ * Handles:
6
+ * - manifest.json link
7
+ * - theme-color meta tag
8
+ * - Apple touch icons
9
+ * - Service worker registration script
10
+ */
1
11
  import type { StxOptions } from '../types';
2
12
  /**
3
13
  * Generate PWA HTML tags for injection into <head>
@@ -1,4 +1,26 @@
1
+ /**
2
+ * PWA Auto-Precaching
3
+ *
4
+ * Automatically discovers and precaches build output files.
5
+ * Scans the output directory and generates a precache manifest.
6
+ */
1
7
  import type { StxOptions } from '../types';
8
+ /**
9
+ * Precache manifest entry
10
+ */
11
+ export interface PrecacheEntry {
12
+ url: string;
13
+ revision: string;
14
+ size: number;
15
+ }
16
+ /**
17
+ * Precache manifest result
18
+ */
19
+ export interface PrecacheManifest {
20
+ entries: PrecacheEntry[];
21
+ totalSize: number;
22
+ fileCount: number;
23
+ }
2
24
  /**
3
25
  * Generate precache manifest from build output directory
4
26
  */
@@ -11,19 +33,3 @@ export declare function generatePrecacheManifestJs(manifest: PrecacheManifest):
11
33
  * Get human-readable size
12
34
  */
13
35
  export declare function formatSize(bytes: number): string;
14
- /**
15
- * Precache manifest entry
16
- */
17
- export declare interface PrecacheEntry {
18
- url: string
19
- revision: string
20
- size: number
21
- }
22
- /**
23
- * Precache manifest result
24
- */
25
- export declare interface PrecacheManifest {
26
- entries: PrecacheEntry[]
27
- totalSize: number
28
- fileCount: number
29
- }
@@ -1,3 +1,15 @@
1
+ /**
2
+ * PWA Service Worker Generation
3
+ *
4
+ * Generates a service worker JavaScript file with configurable caching strategies.
5
+ * Supports: cache-first, network-first, stale-while-revalidate, network-only, cache-only
6
+ *
7
+ * Additional features:
8
+ * - Push notifications handling
9
+ * - Background sync for form submissions
10
+ * - Cache storage limits and purge strategies
11
+ * - Update notifications
12
+ */
1
13
  import type { StxOptions } from '../types';
2
14
  /**
3
15
  * Generate the service worker JavaScript code