@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
@@ -0,0 +1,58 @@
1
+ /**
2
+ * One merge for the crosswind config, used by every render path.
3
+ *
4
+ * There were two, and they disagreed (stacksjs/stx#1867). The dev-server path
5
+ * read only `theme.extend` and pinned the result after the user spread, so a
6
+ * project writing `theme: { colors: { … } }` the Tailwind-classic way lost its
7
+ * entire theme with no error and no warning. The serve path shallow-spread the
8
+ * same key instead, so there the user's `colors` replaced the whole stock
9
+ * palette — the opposite failure, from the same config file, decided by which
10
+ * binary rendered the page. It also read only `safelist`, `shortcuts` and
11
+ * `theme`, dropping `darkMode`, `preflights`, `cssVariables`, `rules`,
12
+ * `blocklist` and `variants` entirely.
13
+ *
14
+ * ## Why theme keys merge instead of replacing
15
+ *
16
+ * Tailwind treats a non-`extend` `theme.colors` as a replacement for the
17
+ * default palette. That semantic depends on generation being driven by
18
+ * globbing source files: an unused default color costs bytes, so dropping the
19
+ * stock palette is the point.
20
+ *
21
+ * Here it is driven by scanning the rendered page — a color nothing references
22
+ * generates nothing, so carrying the base palette along is free. Replacement
23
+ * would mean adding one token to `theme.colors` silently kills `bg-red-500`
24
+ * everywhere, which is a far worse failure than an unused key costing nothing.
25
+ * So base and user theme keys deep-merge, and `extend` is passed through
26
+ * untouched for CSSGenerator to apply on top.
27
+ *
28
+ * @module crosswind-config
29
+ */
30
+ type Dict = Record<string, any>;
31
+ /**
32
+ * Deep-merge `source` over `target`, recursing into plain objects only.
33
+ *
34
+ * Arrays replace rather than concatenate — a theme's `fontFamily: ['Inter',
35
+ * 'sans-serif']` is a complete stack, not an addition to one.
36
+ */
37
+ export declare function deepMergeThemes(target: Dict, source: Dict): Dict;
38
+ export interface MergedCrosswindConfig {
39
+ /** Ready to hand to `new CSSGenerator(...)`. */
40
+ config: Dict;
41
+ /** Merged safelist, also needed by callers to pre-generate those classes. */
42
+ safelist: string[];
43
+ /** Merged shortcuts, needed by callers that emit grouped shortcut rules. */
44
+ shortcuts: Record<string, string>;
45
+ /** Honours the user's `preflight` key (default true). */
46
+ includePreflight: boolean;
47
+ /** Honours the user's `minify` key (default false). */
48
+ minify: boolean;
49
+ }
50
+ /**
51
+ * Merge a project's crosswind config over the package defaults.
52
+ *
53
+ * `content` and `output` are stx-owned and pinned last: classes come from
54
+ * scanning the rendered page, not from globbing, and the CSS is returned rather
55
+ * than written to disk (#1822).
56
+ */
57
+ export declare function mergeCrosswindConfig(base?: Dict, user?: Dict): MergedCrosswindConfig;
58
+ export {};
@@ -0,0 +1,40 @@
1
+ function isPlainObject(value) {
2
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3
+ }
4
+ export function deepMergeThemes(target, source) {
5
+ const out = { ...target };
6
+ for (const [key, value] of Object.entries(source))
7
+ out[key] = isPlainObject(value) && isPlainObject(out[key]) ? deepMergeThemes(out[key], value) : value;
8
+ return out;
9
+ }
10
+ export function mergeCrosswindConfig(base = {}, user = {}) {
11
+ const baseTheme = base.theme || {}, userTheme = user.theme || {}, { extend: userExtend, ...userThemeKeys } = userTheme, { extend: baseExtend, ...baseThemeKeys } = baseTheme, theme = deepMergeThemes(baseThemeKeys, userThemeKeys), extend = deepMergeThemes(baseExtend || {}, userExtend || {});
12
+ if (Object.keys(extend).length > 0)
13
+ theme.extend = extend;
14
+ const safelist = [
15
+ ...base.safelist || [],
16
+ ...user.safelist || []
17
+ ], shortcuts = {
18
+ ...base.shortcuts || {},
19
+ ...user.shortcuts || {}
20
+ }, preflights = [
21
+ ...base.preflights || [],
22
+ ...user.preflights || []
23
+ ];
24
+ return {
25
+ config: {
26
+ ...base,
27
+ ...user,
28
+ theme,
29
+ safelist,
30
+ shortcuts,
31
+ ...preflights.length > 0 ? { preflights } : {},
32
+ content: [],
33
+ output: ""
34
+ },
35
+ safelist,
36
+ shortcuts,
37
+ includePreflight: user.preflight !== !1,
38
+ minify: user.minify === !0
39
+ };
40
+ }
package/dist/csp.d.ts CHANGED
@@ -1,3 +1,69 @@
1
+ /**
2
+ * Content Security Policy (CSP) Module
3
+ *
4
+ * Provides utilities for generating and managing Content Security Policy headers
5
+ * and meta tags to protect against XSS and other injection attacks.
6
+ *
7
+ * ## Features
8
+ *
9
+ * - Generate CSP headers from configuration
10
+ * - Inject CSP meta tags into HTML
11
+ * - Nonce generation for inline scripts/styles
12
+ * - Preset configurations for common use cases
13
+ * - Template directives for CSP integration
14
+ *
15
+ * ## Usage
16
+ *
17
+ * ### Configuration in stx.config.ts
18
+ *
19
+ * ```typescript
20
+ * export default {
21
+ * csp: {
22
+ * enabled: true,
23
+ * directives: {
24
+ * 'default-src': ["'self'"],
25
+ * 'script-src': ["'self'", "'strict-dynamic'"],
26
+ * 'style-src': ["'self'", "'unsafe-inline'"],
27
+ * 'img-src': ["'self'", 'data:', 'https:'],
28
+ * 'connect-src': ["'self'", 'https://api.example.com'],
29
+ * },
30
+ * useNonce: true,
31
+ * addMetaTag: true,
32
+ * }
33
+ * }
34
+ * ```
35
+ *
36
+ * ### Using Presets
37
+ *
38
+ * ```typescript
39
+ * import { getCspPreset, generateCspHeader } from 'stx'
40
+ *
41
+ * const config = getCspPreset('strict')
42
+ * const header = generateCspHeader(config.directives)
43
+ * ```
44
+ *
45
+ * ### Template Directives
46
+ *
47
+ * ```html
48
+ * <!-- Insert CSP meta tag -->
49
+ * @csp
50
+ *
51
+ * <!-- Get current nonce for inline scripts -->
52
+ * <script nonce="{{ cspNonce }}">
53
+ * console.log('Safe inline script')
54
+ * </script>
55
+ * ```
56
+ *
57
+ * ### HTTP Headers
58
+ *
59
+ * ```typescript
60
+ * import { generateCspHeader } from 'stx'
61
+ *
62
+ * // In your server handler
63
+ * const cspHeader = generateCspHeader(config.csp.directives)
64
+ * response.setHeader('Content-Security-Policy', cspHeader)
65
+ * ```
66
+ */
1
67
  import type { CspConfig, CspDirectives, CspPreset, CustomDirective, StxOptions } from './types';
2
68
  /**
3
69
  * Generate a cryptographically secure nonce for CSP
@@ -72,6 +138,37 @@ export declare function generateCspHeader(directives: CspDirectives, nonce?: str
72
138
  * ```
73
139
  */
74
140
  export declare function generateCspMetaTag(directives: CspDirectives, nonce?: string): string;
141
+ /**
142
+ * Strict CSP preset - Maximum security, may require nonces for inline content
143
+ *
144
+ * - No unsafe-inline or unsafe-eval
145
+ * - Uses strict-dynamic for scripts
146
+ * - Blocks object/embed
147
+ * - Restricts form actions to same origin
148
+ */
149
+ export declare const strictCspPreset: CspDirectives;
150
+ /**
151
+ * Moderate CSP preset - Balanced security and compatibility
152
+ *
153
+ * - Allows unsafe-inline for styles (common requirement)
154
+ * - Blocks unsafe-eval
155
+ * - Allows data: URIs for images
156
+ */
157
+ export declare const moderateCspPreset: CspDirectives;
158
+ /**
159
+ * Relaxed CSP preset - Basic protection, maximum compatibility
160
+ *
161
+ * - Allows unsafe-inline for both scripts and styles
162
+ * - Still blocks unsafe-eval and object embeds
163
+ */
164
+ export declare const relaxedCspPreset: CspDirectives;
165
+ /**
166
+ * API-only CSP preset - For JSON API responses
167
+ *
168
+ * - Blocks all content loading (APIs shouldn't render HTML)
169
+ * - Prevents framing
170
+ */
171
+ export declare const apiCspPreset: CspDirectives;
75
172
  /**
76
173
  * Get a CSP preset configuration by name
77
174
  *
@@ -140,6 +237,16 @@ export declare function addNonceToInlineContent(html: string, nonce: string): st
140
237
  * @returns Processed template
141
238
  */
142
239
  export declare function processCspDirectives(template: string, context: Record<string, any>, _filePath: string, options: StxOptions): string;
240
+ /**
241
+ * CSP meta tag directive
242
+ * Usage: @csp
243
+ */
244
+ export declare const cspDirective: CustomDirective;
245
+ /**
246
+ * CSP nonce directive
247
+ * Usage: @cspNonce
248
+ */
249
+ export declare const cspNonceDirective: CustomDirective;
143
250
  /**
144
251
  * Register CSP-related custom directives
145
252
  *
@@ -182,47 +289,6 @@ export declare function getCspHeaderName(reportOnly?: boolean): string;
182
289
  * ```
183
290
  */
184
291
  export declare function createCspHeaders(config: CspConfig, context?: object): Record<string, string>;
185
- /**
186
- * Strict CSP preset - Maximum security, may require nonces for inline content
187
- *
188
- * - No unsafe-inline or unsafe-eval
189
- * - Uses strict-dynamic for scripts
190
- * - Blocks object/embed
191
- * - Restricts form actions to same origin
192
- */
193
- export declare const strictCspPreset: CspDirectives;
194
- /**
195
- * Moderate CSP preset - Balanced security and compatibility
196
- *
197
- * - Allows unsafe-inline for styles (common requirement)
198
- * - Blocks unsafe-eval
199
- * - Allows data: URIs for images
200
- */
201
- export declare const moderateCspPreset: CspDirectives;
202
- /**
203
- * Relaxed CSP preset - Basic protection, maximum compatibility
204
- *
205
- * - Allows unsafe-inline for both scripts and styles
206
- * - Still blocks unsafe-eval and object embeds
207
- */
208
- export declare const relaxedCspPreset: CspDirectives;
209
- /**
210
- * API-only CSP preset - For JSON API responses
211
- *
212
- * - Blocks all content loading (APIs shouldn't render HTML)
213
- * - Prevents framing
214
- */
215
- export declare const apiCspPreset: CspDirectives;
216
- /**
217
- * CSP meta tag directive
218
- * Usage: @csp
219
- */
220
- export declare const cspDirective: CustomDirective;
221
- /**
222
- * CSP nonce directive
223
- * Usage: @cspNonce
224
- */
225
- export declare const cspNonceDirective: CustomDirective;
226
292
  /**
227
293
  * Default CSP configuration - moderate preset
228
294
  */
package/dist/defer.d.ts CHANGED
@@ -1,3 +1,27 @@
1
+ /**
2
+ * Defer Directive
3
+ *
4
+ * Lazy loads content based on various triggers.
5
+ *
6
+ * Usage:
7
+ * @defer(on: 'visible')
8
+ * <HeavyComponent />
9
+ * @placeholder
10
+ * <Skeleton />
11
+ * @loading
12
+ * <Spinner />
13
+ * @error
14
+ * <div>Failed to load</div>
15
+ * @enddefer
16
+ *
17
+ * Triggers:
18
+ * - 'visible' - Load when element enters viewport (IntersectionObserver)
19
+ * - 'idle' - Load when browser is idle (requestIdleCallback)
20
+ * - 'interaction' - Load on first interaction (click, focus)
21
+ * - 'hover' - Load on hover
22
+ * - 'timer(ms)' - Load after specified milliseconds
23
+ * - 'immediate' - Load immediately but async (default)
24
+ */
1
25
  /**
2
26
  * Process @defer directives in template
3
27
  */
@@ -1,3 +1,37 @@
1
+ /**
2
+ * Crosswind CSS Generation Module
3
+ * Provides on-the-fly Tailwind CSS generation using Crosswind
4
+ */
5
+ interface CrosswindModule {
6
+ CSSGenerator: new (config: CrosswindConfig) => CSSGenerator;
7
+ config: CrosswindConfig;
8
+ build?: (config: CrosswindConfig) => Promise<CrosswindBuildResult>;
9
+ defaultConfig?: CrosswindConfig;
10
+ /**
11
+ * Crosswind's own extractor. Preferred over the local fallback below —
12
+ * it is the authority on what counts as a class candidate, and it keeps
13
+ * up with syntax this package would otherwise have to mirror by hand.
14
+ */
15
+ extractClasses?: (content: string) => Set<string>;
16
+ }
17
+ interface CrosswindConfig {
18
+ content?: string[];
19
+ output?: string;
20
+ preflight?: boolean;
21
+ minify?: boolean;
22
+ preflights?: unknown[];
23
+ safelist?: string[];
24
+ [key: string]: unknown;
25
+ }
26
+ interface CrosswindBuildResult {
27
+ css: string;
28
+ classes: Set<string>;
29
+ duration: number;
30
+ }
31
+ interface CSSGenerator {
32
+ generate(className: string): void;
33
+ toCSS(preflight: boolean, minify: boolean): string;
34
+ }
1
35
  export declare function getCrosswindServeAsset(hash: string): string | undefined;
2
36
  /**
3
37
  * Lazily load the Crosswind module
@@ -72,29 +106,4 @@ export declare function generateCrosswindCSS(htmlContent: string, appDir?: strin
72
106
  * Tries to inject before </head>, falls back to <body> or prepends
73
107
  */
74
108
  export declare function injectCrosswindCSS(htmlContent: string, appDir?: string, serveMode?: boolean): Promise<string>;
75
- // Type for Crosswind module
76
- declare interface CrosswindModule {
77
- CSSGenerator: new (config: CrosswindConfig) => CSSGenerator
78
- config: CrosswindConfig
79
- build?: (config: CrosswindConfig) => Promise<CrosswindBuildResult>
80
- defaultConfig?: CrosswindConfig
81
- extractClasses?: (content: string) => Set<string>
82
- }
83
- declare interface CrosswindConfig {
84
- content?: string[]
85
- output?: string
86
- preflight?: boolean
87
- minify?: boolean
88
- preflights?: unknown[]
89
- safelist?: string[]
90
- [key: string]: unknown
91
- }
92
- declare interface CrosswindBuildResult {
93
- css: string
94
- classes: Set<string>
95
- duration: number
96
- }
97
- declare interface CSSGenerator {
98
- generate(className: string): void
99
- toCSS(preflight: boolean, minify: boolean): string
100
- }
109
+ export {};
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { hasLocalConfig } from "bunfig";
3
+ import { mergeCrosswindConfig } from "../crosswind-config.js";
3
4
  import { stateDir } from "../state-dir.js";
4
5
  import { colors } from "./terminal-colors.js";
5
6
  let crosswindModule = null, crosswindLoadAttempted = !1, cachedConfig = null, cachedCSS = "", isBuilding = !1;
@@ -323,24 +324,7 @@ export async function generateCrosswindCSS(htmlContent, appDir) {
323
324
  configFingerprint = "unhashable";
324
325
  }
325
326
  }
326
- const baseConfig = hw.defaultConfig || hw.config, userConfig = cachedConfig || {}, baseTheme = baseConfig.theme || {}, userExtend = (userConfig.theme || {}).extend || {}, theme = { ...baseTheme };
327
- if (Object.keys(userExtend).length > 0)
328
- theme.extend = userExtend;
329
- const safelist = [
330
- ...baseConfig.safelist || [],
331
- ...userConfig.safelist || []
332
- ], preflights = [
333
- ...baseConfig.preflights || [],
334
- ...userConfig.preflights || []
335
- ], includePreflight = userConfig.preflight !== !1, minify = userConfig.minify === !0, crosswindConfig = {
336
- ...baseConfig,
337
- ...userConfig,
338
- content: [],
339
- output: "",
340
- theme,
341
- safelist,
342
- ...preflights.length > 0 && { preflights }
343
- }, generator = new hw.CSSGenerator(crosswindConfig);
327
+ const baseConfig = hw.defaultConfig || hw.config, userConfig = cachedConfig || {}, merged = mergeCrosswindConfig(baseConfig, userConfig), { safelist, includePreflight, minify } = merged, crosswindConfig = merged.config, generator = new hw.CSSGenerator(crosswindConfig);
344
328
  for (const cls of safelist)
345
329
  generator.generate(cls);
346
330
  for (const className of classes)
@@ -24,7 +24,8 @@ import {
24
24
  clearMiddleware,
25
25
  getMiddlewareNames
26
26
  } from "../route-middleware.js";
27
- import { getPageMeta, resetHead } from "../head.js";
27
+ import { resetHead } from "../head.js";
28
+ import { extractPageMetaFromSource } from "../page-meta.js";
28
29
  import { clearComponentCache } from "../utils.js";
29
30
  import { extractPageResponseStatus } from "../page-response.js";
30
31
  import {
@@ -396,7 +397,7 @@ export async function serveApp(appDir = ".", options = {}) {
396
397
  builtPage = rebuilt;
397
398
  }
398
399
  if (builtPage) {
399
- const responseStatus = builtPage.status ?? 200, pageMeta = getPageMeta();
400
+ const responseStatus = builtPage.status ?? 200, pageMeta = (routeMatch.route.filePath ? extractPageMetaFromSource(await Bun.file(routeMatch.route.filePath).text().catch(() => "")) : null) ?? {};
400
401
  if (pageMeta.validate) {
401
402
  if (!await pageMeta.validate({ params: routeMatch.params })) {
402
403
  const custom404 = await renderErrorPage(404);
@@ -414,7 +415,7 @@ export async function serveApp(appDir = ".", options = {}) {
414
415
  }
415
416
  }
416
417
  if (pageMeta.middleware) {
417
- const toRoute = createRouteLocation(url.pathname, routeMatch.params, pageMeta, url.search), middlewareContext = createMiddlewareContext(toRoute, null, request), middlewareResult = await runMiddleware(pageMeta.middleware, middlewareContext);
418
+ const toRoute = createRouteLocation(url.pathname, routeMatch.params, pageMeta, url.search), middlewareContext = createMiddlewareContext(toRoute, null, request, { isServer: !0 }), middlewareResult = await runMiddleware(pageMeta.middleware, middlewareContext);
418
419
  if (middlewareResult.redirect) {
419
420
  const redirectUrl = middlewareResult.redirect.path, statusCode = middlewareResult.redirect.options.redirectCode || 302, headers = new Headers(middlewareResult.responseHeaders);
420
421
  headers.set("Location", redirectUrl);
@@ -1,3 +1,35 @@
1
+ /**
2
+ * ANSI color codes for terminal output
3
+ * Provides consistent coloring for CLI messages
4
+ */
5
+ export declare const colors: {
6
+ readonly reset: '\u001B[0m';
7
+ readonly bright: '\u001B[1m';
8
+ readonly dim: '\u001B[2m';
9
+ readonly underscore: '\u001B[4m';
10
+ readonly blink: '\u001B[5m';
11
+ readonly reverse: '\u001B[7m';
12
+ readonly hidden: '\u001B[8m';
13
+ readonly black: '\u001B[30m';
14
+ readonly red: '\u001B[31m';
15
+ readonly green: '\u001B[32m';
16
+ readonly yellow: '\u001B[33m';
17
+ readonly blue: '\u001B[34m';
18
+ readonly magenta: '\u001B[35m';
19
+ readonly cyan: '\u001B[36m';
20
+ readonly white: '\u001B[37m';
21
+ readonly gray: '\u001B[90m';
22
+ readonly bgBlack: '\u001B[40m';
23
+ readonly bgRed: '\u001B[41m';
24
+ readonly bgGreen: '\u001B[42m';
25
+ readonly bgYellow: '\u001B[43m';
26
+ readonly bgBlue: '\u001B[44m';
27
+ readonly bgMagenta: '\u001B[45m';
28
+ readonly bgCyan: '\u001B[46m';
29
+ readonly bgWhite: '\u001B[47m';
30
+ readonly bgGray: '\u001B[100m';
31
+ };
32
+ export type ColorName = keyof typeof colors;
1
33
  /**
2
34
  * Colorize a string with the specified color
3
35
  */
@@ -22,35 +54,3 @@ export declare function info(text: string): string;
22
54
  * Create a dim/muted message (gray)
23
55
  */
24
56
  export declare function dim(text: string): string;
25
- /**
26
- * ANSI color codes for terminal output
27
- * Provides consistent coloring for CLI messages
28
- */
29
- export declare const colors: {
30
- reset: '\x1B[0m';
31
- bright: '\x1B[1m';
32
- dim: '\x1B[2m';
33
- underscore: '\x1B[4m';
34
- blink: '\x1B[5m';
35
- reverse: '\x1B[7m';
36
- hidden: '\x1B[8m';
37
- black: '\x1B[30m';
38
- red: '\x1B[31m';
39
- green: '\x1B[32m';
40
- yellow: '\x1B[33m';
41
- blue: '\x1B[34m';
42
- magenta: '\x1B[35m';
43
- cyan: '\x1B[36m';
44
- white: '\x1B[37m';
45
- gray: '\x1B[90m';
46
- bgBlack: '\x1B[40m';
47
- bgRed: '\x1B[41m';
48
- bgGreen: '\x1B[42m';
49
- bgYellow: '\x1B[43m';
50
- bgBlue: '\x1B[44m';
51
- bgMagenta: '\x1B[45m';
52
- bgCyan: '\x1B[46m';
53
- bgWhite: '\x1B[47m';
54
- bgGray: '\x1B[100m'
55
- };
56
- export type ColorName = keyof typeof colors;
@@ -1,4 +1,88 @@
1
+ /**
2
+ * STX Directive API
3
+ *
4
+ * Enhanced API for creating custom directives with lifecycle hooks,
5
+ * client-side support, and built-in utilities.
6
+ *
7
+ * @module directive-api
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { defineDirective } from 'stx'
12
+ *
13
+ * // Simple directive
14
+ * const uppercase = defineDirective({
15
+ * name: 'uppercase',
16
+ * transform: (content) => content.toUpperCase()
17
+ * })
18
+ *
19
+ * // Directive with parameters
20
+ * const highlight = defineDirective({
21
+ * name: 'highlight',
22
+ * transform: (content, { color = 'yellow' }) =>
23
+ * `<mark style="background: ${color}">${content}</mark>`
24
+ * })
25
+ * ```
26
+ */
1
27
  import type { CustomDirective } from './types';
28
+ /** Directive parameter types */
29
+ export type DirectiveParams = Record<string, unknown>;
30
+ /** Directive binding for client-side directives */
31
+ export interface DirectiveBinding<T = unknown> {
32
+ /** The value passed to the directive */
33
+ value: T;
34
+ /** Previous value (for updates) */
35
+ oldValue?: T;
36
+ /** Argument passed after colon (v-directive:arg) */
37
+ arg?: string;
38
+ /** Modifiers passed after dots (v-directive.mod1.mod2) */
39
+ modifiers: Record<string, boolean>;
40
+ /** The directive instance */
41
+ instance: unknown;
42
+ /** The directive definition */
43
+ dir: ClientDirectiveDefinition<T>;
44
+ }
45
+ /** Server-side directive definition */
46
+ export interface DirectiveDefinition<P extends DirectiveParams = DirectiveParams> {
47
+ /** Directive name (without @) */
48
+ name: string;
49
+ /** Whether directive has end tag (@name...@endname) */
50
+ hasEndTag?: boolean;
51
+ /** Description for documentation */
52
+ description?: string;
53
+ /** Transform content (server-side) */
54
+ transform?: (content: string, params: P, context: Record<string, unknown>, filePath: string) => string | Promise<string>;
55
+ /** Validate parameters */
56
+ validate?: (params: P) => boolean | string;
57
+ /** Default parameter values */
58
+ defaults?: Partial<P>;
59
+ /** Generate client-side code */
60
+ clientScript?: (params: P) => string;
61
+ /** Generate CSS */
62
+ css?: (params: P) => string;
63
+ }
64
+ /** Client-side directive hooks */
65
+ export interface ClientDirectiveDefinition<T = unknown> {
66
+ /** Called when directive is first bound to element */
67
+ created?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
68
+ /** Called before element is inserted into DOM */
69
+ beforeMount?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
70
+ /** Called when element is inserted into DOM */
71
+ mounted?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
72
+ /** Called before the component is updated */
73
+ beforeUpdate?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
74
+ /** Called after the component has updated */
75
+ updated?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
76
+ /** Called before element is unmounted */
77
+ beforeUnmount?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
78
+ /** Called when element is unmounted */
79
+ unmounted?: (el: HTMLElement, binding: DirectiveBinding<T>) => void;
80
+ }
81
+ /** Combined directive (server + client) */
82
+ export interface FullDirectiveDefinition<P extends DirectiveParams = DirectiveParams, T = unknown> extends DirectiveDefinition<P> {
83
+ /** Client-side hooks */
84
+ client?: ClientDirectiveDefinition<T>;
85
+ }
2
86
  /**
3
87
  * Register a directive globally.
4
88
  */
@@ -50,11 +134,11 @@ export declare function unregisterDirective(name: string): boolean;
50
134
  * })
51
135
  * ```
52
136
  */
53
- export declare function defineDirective<P extends DirectiveParams = DirectiveParams, T = unknown,>(definition: FullDirectiveDefinition<P, T>): CustomDirective;
137
+ export declare function defineDirective<P extends DirectiveParams = DirectiveParams, T = unknown>(definition: FullDirectiveDefinition<P, T>): CustomDirective;
54
138
  /**
55
139
  * Define a client-only directive.
56
140
  */
57
- export declare function defineClientDirective<T = unknown>(name: string): ClientDirectiveDefinition<T>;
141
+ export declare function defineClientDirective<T = unknown>(name: string, definition: ClientDirectiveDefinition<T> | ((el: HTMLElement, binding: DirectiveBinding<T>) => void)): ClientDirectiveDefinition<T>;
58
142
  /**
59
143
  * Create common built-in directives.
60
144
  */
@@ -68,44 +152,3 @@ export declare function generateDirectiveRuntime(): string;
68
152
  * Converts v-directive:arg.mod="value" to data attributes and client setup.
69
153
  */
70
154
  export declare function processDirectiveAttributes(template: string): string;
71
- /** Directive binding for client-side directives */
72
- export declare interface DirectiveBinding<T = unknown> {
73
- value: T
74
- oldValue?: T
75
- arg?: string
76
- modifiers: Record<string, boolean>
77
- instance: unknown
78
- dir: ClientDirectiveDefinition<T>
79
- }
80
- /** Server-side directive definition */
81
- export declare interface DirectiveDefinition<P extends DirectiveParams = DirectiveParams> {
82
- name: string
83
- hasEndTag?: boolean
84
- description?: string
85
- transform?: (
86
- content: string,
87
- params: P,
88
- context: Record<string, unknown>,
89
- filePath: string,
90
- ) => string | Promise<string>
91
- validate?: (params: P) => boolean | string
92
- defaults?: Partial<P>
93
- clientScript?: (params: P) => string
94
- css?: (params: P) => string
95
- }
96
- /** Client-side directive hooks */
97
- export declare interface ClientDirectiveDefinition<T = unknown> {
98
- created?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
99
- beforeMount?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
100
- mounted?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
101
- beforeUpdate?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
102
- updated?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
103
- beforeUnmount?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
104
- unmounted?: (el: HTMLElement, binding: DirectiveBinding<T>) => void
105
- }
106
- /** Combined directive (server + client) */
107
- export declare interface FullDirectiveDefinition<P extends DirectiveParams = DirectiveParams, T = unknown,> extends DirectiveDefinition<P> {
108
- client?: ClientDirectiveDefinition<T>
109
- }
110
- /** Directive parameter types */
111
- export type DirectiveParams = Record<string, unknown>;