@stacksjs/stx 0.2.154 → 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,3 +1,36 @@
1
+ /**
2
+ * STX Reactive Bindings
3
+ *
4
+ * Provides reactive bindings for STX templates with store integration.
5
+ *
6
+ * Syntax:
7
+ * - class="{{ $appStore.isActive ? 'active' : '' }}"
8
+ * - text="{{ $appStore.message }}"
9
+ * - disabled="{{ $appStore.isLoading }}"
10
+ *
11
+ * Store references:
12
+ * - $storeName.property (e.g., $appStore.isRecording)
13
+ *
14
+ * Example:
15
+ * <button
16
+ * class="{{ $appStore.isRecording ? 'border-pink' : 'border-gray' }}"
17
+ * disabled="{{ $appStore.isProcessing }}"
18
+ * @click="voide.toggleRecording()"
19
+ * >
20
+ * <span text="{{ $appStore.isRecording ? '🔴' : '🎤' }}"></span>
21
+ * </button>
22
+ */
23
+ interface BindingInfo {
24
+ elementId: string;
25
+ attribute: string;
26
+ expression: string;
27
+ stores: string[];
28
+ }
29
+ interface ProcessedBindings {
30
+ html: string;
31
+ bindings: BindingInfo[];
32
+ stores: Set<string>;
33
+ }
1
34
  /**
2
35
  * Process reactive bindings in HTML template
3
36
  * Detects {{ $store.value }} patterns in attribute values
@@ -11,14 +44,4 @@ export declare function generateBindingsRuntime(bindings: BindingInfo[], stores:
11
44
  * Process template with reactive bindings and generate runtime
12
45
  */
13
46
  export declare function processTemplateBindings(html: string): string;
14
- declare interface BindingInfo {
15
- elementId: string
16
- attribute: string
17
- expression: string
18
- stores: string[]
19
- }
20
- declare interface ProcessedBindings {
21
- html: string
22
- bindings: BindingInfo[]
23
- stores: Set<string>
24
- }
47
+ export {};
@@ -1,7 +1,3 @@
1
- /**
2
- * Check if a template contains reactive directives
3
- */
4
- export declare function hasReactiveDirectives(template: string): boolean;
5
1
  /**
6
2
  * Reactive Directives Module
7
3
  *
@@ -58,32 +54,64 @@ export declare function hasReactiveDirectives(template: string): boolean;
58
54
  *
59
55
  * @module reactive
60
56
  */
61
- // =============================================================================
62
- // Types
63
- // =============================================================================
64
- export declare interface ReactiveScope {
65
- id: string
66
- selector: string
67
- stateExpr: string
68
- initExpr: string | null
69
- bindings: ReactiveBinding[]
70
- refs: Map<string, string>
57
+ export interface ReactiveScope {
58
+ /** Unique scope ID */
59
+ id: string;
60
+ /** Element selector */
61
+ selector: string;
62
+ /** Initial state expression */
63
+ stateExpr: string;
64
+ /** x-init expression if present */
65
+ initExpr: string | null;
66
+ /** Child bindings within this scope */
67
+ bindings: ReactiveBinding[];
68
+ /** Element references (x-ref) */
69
+ refs: Map<string, string>;
71
70
  }
72
- export declare interface ReactiveBinding {
73
- elementId: string
74
- type: 'model' | 'show' | 'hide' | 'text' | 'html' | 'bind' | 'class' | 'style' | 'event'
75
- expression: string
76
- attribute?: string
77
- inputType?: string
78
- transition?: TransitionConfig
71
+ export interface ReactiveBinding {
72
+ /** Element ID or selector */
73
+ elementId: string;
74
+ /** Binding type */
75
+ type: 'model' | 'show' | 'hide' | 'text' | 'html' | 'bind' | 'class' | 'style' | 'event';
76
+ /** Expression to evaluate */
77
+ expression: string;
78
+ /** For x-bind, the attribute name */
79
+ attribute?: string;
80
+ /** For x-model, the input type */
81
+ inputType?: string;
82
+ /** For x-show/x-hide, transition configuration */
83
+ transition?: TransitionConfig;
79
84
  }
80
- export declare interface TransitionConfig {
81
- enabled: boolean
82
- enter?: string
83
- enterStart?: string
84
- enterEnd?: string
85
- leave?: string
86
- leaveStart?: string
87
- leaveEnd?: string
88
- duration?: number
85
+ export interface TransitionConfig {
86
+ /** Simple transition (uses default classes) */
87
+ enabled: boolean;
88
+ /** Enter transition classes */
89
+ enter?: string;
90
+ /** Enter start classes (applied before insert) */
91
+ enterStart?: string;
92
+ /** Enter end classes (applied one frame after insert) */
93
+ enterEnd?: string;
94
+ /** Leave transition classes */
95
+ leave?: string;
96
+ /** Leave start classes (applied immediately when leaving) */
97
+ leaveStart?: string;
98
+ /** Leave end classes (applied one frame after leave starts) */
99
+ leaveEnd?: string;
100
+ /** Duration in ms (optional, defaults to CSS transition duration) */
101
+ duration?: number;
89
102
  }
103
+ /**
104
+ * Process reactive directives in a template.
105
+ *
106
+ * Transforms `x-data`, `x-model`, `x-show`, etc. into client-side reactivity.
107
+ *
108
+ * @param template - The HTML template string
109
+ * @param context - Template context
110
+ * @param filePath - Source file path for error messages
111
+ * @returns Processed template with reactive runtime script
112
+ */
113
+ export declare function processReactiveDirectives(template: string, context: Record<string, unknown>, _filePath: string): string;
114
+ /**
115
+ * Check if a template contains reactive directives
116
+ */
117
+ export declare function hasReactiveDirectives(template: string): boolean;
package/dist/reactive.js CHANGED
@@ -393,7 +393,7 @@ window.__stx_reactive = (function() {
393
393
  `;
394
394
  }
395
395
  function substituteExpressionsInExpr(expr, context) {
396
- let out = expr.replace(/\{!!([\s\S]*?)!!\}/g, (match, inner) => {
396
+ const source = expr.replace(/\{!!([\s\S]*?)!!\}/g, (match, inner) => {
397
397
  try {
398
398
  const value = evaluateExpression(inner, context, !0);
399
399
  if (value === void 0)
@@ -403,25 +403,55 @@ function substituteExpressionsInExpr(expr, context) {
403
403
  return match;
404
404
  }
405
405
  });
406
- out = out.replace(/\{\{([\s\S]*?)\}\}/g, (match, inner) => {
407
- try {
408
- const value = evaluateExpression(inner, context, !0);
409
- if (value === void 0)
410
- return match;
411
- if (typeof value === "string") {
412
- const trimmed = value.trim();
413
- if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]"))
414
- try {
415
- JSON.parse(trimmed);
416
- return trimmed;
417
- } catch {}
406
+ let out = "", index = 0, quote = null;
407
+ while (index < source.length) {
408
+ const character = source[index];
409
+ if (quote && character === "\\") {
410
+ out += character + (source[index + 1] ?? "");
411
+ index += 2;
412
+ continue;
413
+ }
414
+ if (character === "{" && source[index + 1] === "{") {
415
+ const end = source.indexOf("}}", index + 2);
416
+ if (end !== -1) {
417
+ const match = source.slice(index, end + 2);
418
+ out += splice(source.slice(index + 2, end), match, quote);
419
+ index = end + 2;
420
+ continue;
418
421
  }
419
- return JSON.stringify(value);
422
+ }
423
+ if (quote) {
424
+ if (character === quote)
425
+ quote = null;
426
+ } else if (character === "'" || character === '"' || character === "`")
427
+ quote = character;
428
+ out += character;
429
+ index++;
430
+ }
431
+ return out;
432
+ function splice(inner, match, insideQuote) {
433
+ let value;
434
+ try {
435
+ value = evaluateExpression(inner, context, !0);
420
436
  } catch {
421
437
  return match;
422
438
  }
423
- });
424
- return out;
439
+ if (value === void 0)
440
+ return match;
441
+ if (insideQuote) {
442
+ const text = String(value).replace(/\\/g, "\\\\").replace(new RegExp(insideQuote === "`" ? "`" : insideQuote, "g"), `\\${insideQuote}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
443
+ return insideQuote === "`" ? text.replace(/\$\{/g, "\\${") : text;
444
+ }
445
+ if (typeof value === "string") {
446
+ const trimmed = value.trim();
447
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]"))
448
+ try {
449
+ JSON.parse(trimmed);
450
+ return trimmed;
451
+ } catch {}
452
+ }
453
+ return JSON.stringify(value);
454
+ }
425
455
  }
426
456
  function generateScopeInitializers(scopes, context) {
427
457
  if (scopes.length === 0)
@@ -541,23 +571,18 @@ function addAllReactiveIds(template) {
541
571
  return output;
542
572
  }
543
573
  function finalizeTemplate(template, scopes) {
544
- let output = template;
545
- for (const scope of scopes) {
546
- const existingMatch = new RegExp(`<[a-z][a-z0-9-]*\\s+[^>]*data-stx-scope="([^"]*)"[^>]*x-data\\s*=\\s*["']${escapeRegex(scope.stateExpr)}["']`, "gi").exec(output);
547
- if (existingMatch) {
548
- scope.id = existingMatch[1];
574
+ let index = 0, output = template.replace(/<([a-z][a-z0-9-]*)(\s+[^>]*x-data\s*=\s*(?:"[^"]*"|'[^']*')[^>]*)>/gi, (match, tagName, attributes) => {
575
+ const scope = scopes[index++];
576
+ if (!scope)
577
+ return match;
578
+ const existing = /data-stx-scope="([^"]*)"/.exec(attributes);
579
+ if (existing) {
580
+ scope.id = existing[1];
549
581
  scope.selector = `[data-stx-scope="${scope.id}"]`;
550
- } else {
551
- const reverseMatch = new RegExp(`<[a-z][a-z0-9-]*\\s+[^>]*x-data\\s*=\\s*["']${escapeRegex(scope.stateExpr)}["'][^>]*data-stx-scope="([^"]*)"`, "gi").exec(output);
552
- if (reverseMatch) {
553
- scope.id = reverseMatch[1];
554
- scope.selector = `[data-stx-scope="${scope.id}"]`;
555
- } else {
556
- output = output.replace(new RegExp(`(<[a-z][a-z0-9-]*\\s+)([^>]*)(x-data\\s*=\\s*"${escapeRegex(scope.stateExpr)}")([^>]*>)`, "gi"), `$1data-stx-scope="${scope.id}" $2$3$4`);
557
- output = output.replace(new RegExp(`(<[a-z][a-z0-9-]*\\s+)([^>]*)(x-data\\s*=\\s*'${escapeRegex(scope.stateExpr)}')([^>]*>)`, "gi"), `$1data-stx-scope="${scope.id}" $2$3$4`);
558
- }
582
+ return match;
559
583
  }
560
- }
584
+ return `<${tagName} data-stx-scope="${scope.id}"${attributes}>`;
585
+ });
561
586
  output = output.replace(/\s*x-data\s*=\s*"([^"]*)"/g, ' data-stx-xdata="$1"');
562
587
  output = output.replace(/\s*x-data\s*=\s*'([^']*)'/g, " data-stx-xdata='$1'");
563
588
  output = output.replace(/\s*x-init\s*=\s*"[^"]*"/g, "");
package/dist/render.js CHANGED
@@ -111,6 +111,7 @@ export async function renderTemplateString(content, filePath, renderOptions = {}
111
111
  __stx_options: options,
112
112
  __stx_sfc_mode: !0,
113
113
  __stx_inject_css: renderOptions.injectCSS === !0,
114
+ __stxServeContext: void 0,
114
115
  ...renderOptions.context || {}
115
116
  };
116
117
  for (const scriptContent of serverScripts)
@@ -1,35 +1,2 @@
1
- export type {
2
- AbortNavigationResult,
3
- CookieManager,
4
- CookieOptions,
5
- MiddlewareContext,
6
- MiddlewareMode,
7
- MiddlewareOptions,
8
- MiddlewareResult,
9
- NavigateToOptions,
10
- NavigateToResult,
11
- NavigationError,
12
- NavigationResult,
13
- RouteLocation,
14
- RouteMiddlewareDefinition,
15
- RouteMiddlewareHandler,
16
- StorageManager,
17
- } from 'stx-router';
18
- // Re-export from stx-router
19
- export {
20
- abortNavigation,
21
- clearMiddleware,
22
- createClientCookieManager,
23
- createMiddlewareContext,
24
- createRouteLocation,
25
- createServerCookieManager,
26
- createStorageManager,
27
- defineMiddleware,
28
- getMiddleware,
29
- getMiddlewareNames,
30
- hasMiddleware,
31
- loadMiddlewareFromDirectory,
32
- navigateTo,
33
- registerMiddleware,
34
- runMiddleware,
35
- } from 'stx-router';
1
+ export { abortNavigation, clearMiddleware, createClientCookieManager, createMiddlewareContext, createRouteLocation, createServerCookieManager, createStorageManager, defineMiddleware, getMiddleware, getMiddlewareNames, hasMiddleware, loadMiddlewareFromDirectory, navigateTo, registerMiddleware, runMiddleware, } from 'stx-router';
2
+ export type { AbortNavigationResult, CookieManager, CookieOptions, MiddlewareContext, MiddlewareMode, MiddlewareOptions, MiddlewareResult, NavigateToOptions, NavigateToResult, NavigationError, NavigationResult, RouteLocation, RouteMiddlewareDefinition, RouteMiddlewareHandler, StorageManager, } from 'stx-router';
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Build a concrete URL from a route pattern.
3
+ *
4
+ * The strict half of the pair: `navigate()` stays permissive so computed URLs
5
+ * keep working, and `$path()` is where a dynamic route gets checked —
6
+ * `navigate($path('/cars/:id', { id: car.id }))`.
7
+ *
8
+ * Consumes the `?`/`*` sigil, drops the preceding slash when an optional
9
+ * segment is absent, encodes catch-all segments individually so their slashes
10
+ * survive, and appends anything left over as a query string.
11
+ */
12
+ export declare function $path<P extends RoutePattern>(pattern: P, ...args: ParamsArg<P>): string;
13
+ /**
14
+ * Typed route paths that actually type-check (stacksjs/stx#1887).
15
+ *
16
+ * `generateRouteTypes()` emitted `declare module "stx/routes" { interface
17
+ * RouteMap … }` and nothing in the source tree declared or imported
18
+ * `stx/routes`. Because that specifier does not resolve, TypeScript treated it
19
+ * as an ambient module declaration rather than an augmentation — so it parsed,
20
+ * shipped, and constrained nothing. `navigate('/dashbaord')` type-checked.
21
+ *
22
+ * ## Why the obvious fix does not work
23
+ *
24
+ * The tempting shape is `type RoutePath = KnownRoute | (string & {})`. It
25
+ * cannot catch anything: a parameter that accepts a computed `string`
26
+ * necessarily accepts every string literal too. It buys autocomplete and zero
27
+ * checking, which is the same trade the dangling declaration already made.
28
+ *
29
+ * The other tempting shape — a plain union — rejects real code. This repo's own
30
+ * tests navigate to `'?status=resolved'`, `'guide'` and
31
+ * `'https://example.com/pricing'`; apps build URLs with template literals and
32
+ * ternaries. A union rejects all of it, and measured against a real app it
33
+ * would have produced zero true positives against five false ones, because the
34
+ * generated union holds *patterns* (`/cars/:id`) while callers pass *URLs*
35
+ * (`/cars/42`).
36
+ *
37
+ * ## What this does instead
38
+ *
39
+ * {@link CheckHref} is a generic gate applied to the argument's own literal
40
+ * type. Non-literals pass through untouched, so anything computed still
41
+ * compiles; only a leading-slash string literal is checked, against the routes
42
+ * expanded from patterns. A typo in a hand-written path is the one thing that
43
+ * fails — which is the only thing worth failing.
44
+ *
45
+ * @module route-types
46
+ */
47
+ /**
48
+ * Routes that exist, augmented by the generated
49
+ * `<state-dir>/route-types.d.ts`.
50
+ *
51
+ * Empty here on purpose: while it is empty every route type widens to `string`,
52
+ * so a project that has not generated the declaration — or has not added the
53
+ * state directory to its tsconfig — is unaffected.
54
+ *
55
+ * The value type is the route's params, so one interface serves both the
56
+ * pattern union and per-route param lookup.
57
+ */
58
+ export declare interface KnownRoutes {}
59
+ /**
60
+ * Error carriers. TypeScript reports the property names, so the message says
61
+ * what is wrong rather than naming an internal type.
62
+ */
63
+ export declare interface UnknownRoute<T extends string> {
64
+ 'stx: no page matches this path': T
65
+ 'known routes': RoutePattern
66
+ }
67
+ export declare interface RoutePatternUsedAsHref<T extends string> {
68
+ 'stx: that is a route pattern, not a URL — use $path() to fill its params': T
69
+ }
70
+ declare type RouteKeys = keyof KnownRoutes & string;
71
+ /** Tuple-wrapped so a `never` key set does not distribute into `true`. */
72
+ declare type NoRoutes = [RouteKeys] extends [never] ? true : false;
73
+ /** Every known route pattern, or `string` when none were generated. */
74
+ export type RoutePattern = NoRoutes extends true ? string : RouteKeys;
75
+ /** The params a pattern declares. */
76
+ export type RouteParams<P extends RoutePattern> = P extends RouteKeys
77
+ ? KnownRoutes[P]
78
+ : Record<string, string>;
79
+ /**
80
+ * A pattern with its params replaced by wildcards, so a concrete URL matches.
81
+ *
82
+ * `/cars/:id` becomes `` `/cars/${string}` ``, which is what a caller actually
83
+ * passes. Comparing against the raw pattern would reject every dynamic-route
84
+ * navigation in existence.
85
+ */
86
+ declare type PatternPrefix<P extends string> = P extends `${infer Head}:${string}` ? `${Head}${string}` : P;
87
+ /** `/settings/:tab?` also matches `/settings` with the segment omitted. */
88
+ declare type OptionalBase<P extends string> = P extends `${infer Base}/:${string}?` ? Base : never;
89
+ /** Every shape a caller may legitimately pass for a known route. */
90
+ export type RouteHref = PatternPrefix<RoutePattern> | OptionalBase<RoutePattern>;
91
+ declare type StripHash<S extends string> = S extends `${infer Base}#${string}` ? Base : S;
92
+ declare type StripQuery<S extends string> = S extends `${infer Base}?${string}` ? Base : S;
93
+ /**
94
+ * Gate a route argument on its own literal type.
95
+ *
96
+ * Each step is load-bearing:
97
+ *
98
+ * 1. Not a string literal (a variable, a template literal, a concatenation) —
99
+ * pass. This is what keeps computed URLs compiling.
100
+ * 2. No routes generated — pass, so an un-adopted project is unaffected.
101
+ * 3. Only absolute paths are checked. A relative href, a bare `?query`, a
102
+ * `#hash` and `https://…` all fall through, because the router genuinely
103
+ * accepts them.
104
+ * 4. A raw pattern is a mistake worth naming separately: `/cars/:id` is not a
105
+ * URL.
106
+ * 5. Otherwise the path, minus any query or hash, must match a known route.
107
+ */
108
+ export type CheckHref<T extends string> = string extends T
109
+ ? T
110
+ : string extends RoutePattern
111
+ ? T
112
+ : T extends `/${string}`
113
+ ? T extends `${string}/:${string}`
114
+ ? RoutePatternUsedAsHref<T>
115
+ : StripQuery<StripHash<T>> extends RouteHref ? T : UnknownRoute<T>
116
+ : T;
117
+ /**
118
+ * A route in an assignment position (a config field, an interface property),
119
+ * where no generic parameter exists to gate on.
120
+ *
121
+ * Autocomplete only — it cannot reject a typo, for the reason given at the top
122
+ * of this file. Prefer a `CheckHref`-gated function parameter where one is
123
+ * available.
124
+ */
125
+ export type RoutePath = RoutePattern | (string & {});
126
+ declare type RouteParamsInput<P extends RoutePattern> = {
127
+ [K in keyof RouteParams<P>]: string | number | readonly string[]
128
+ }
129
+ /** Params are required only when the pattern has non-optional ones. */
130
+ declare type ParamsArg<P extends RoutePattern> = [keyof RouteParams<P>] extends [never]
131
+ ? []
132
+ : Record<never, never> extends RouteParams<P>
133
+ ? [params?: RouteParamsInput<P>]
134
+ : [params: RouteParamsInput<P>];
@@ -0,0 +1,24 @@
1
+ export function $path(pattern, ...args) {
2
+ const params = args[0] ?? {}, used = new Set, filled = String(pattern).replace(/(\/)?:([^/?*]+)([?*])?/g, (whole, slash, name, sigil) => {
3
+ const value = params[name];
4
+ used.add(name);
5
+ if (value === void 0 || value === null || value === "") {
6
+ if (sigil === "?")
7
+ return "";
8
+ return whole;
9
+ }
10
+ const encoded = Array.isArray(value) ? value.map((part) => encodeURIComponent(String(part))).join("/") : sigil === "*" ? String(value).split("/").map((part) => encodeURIComponent(part)).join("/") : encodeURIComponent(String(value));
11
+ return `${slash ?? ""}${encoded}`;
12
+ }), extra = Object.keys(params).filter((key) => !used.has(key));
13
+ if (extra.length === 0)
14
+ return filled;
15
+ const query = new URLSearchParams;
16
+ for (const key of extra) {
17
+ const value = params[key];
18
+ if (Array.isArray(value))
19
+ value.forEach((part) => query.append(key, String(part)));
20
+ else if (value !== void 0 && value !== null)
21
+ query.set(key, String(value));
22
+ }
23
+ return `${filled}?${query.toString()}`;
24
+ }
package/dist/router.d.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { matchRoute } from 'stx-router';
2
1
  import type { Route } from 'stx-router';
3
2
  export type { Route, RouteMatch } from 'stx-router';
3
+ export { findErrorPage, formatRoutes, generateRouteManifest, generateRouteTypes, matchRoute } from 'stx-router';
4
+ export interface RouterOptions {
5
+ pagesDir?: string;
6
+ extensions?: string[];
7
+ }
4
8
  export declare function createRouter(baseDir: string, options?: RouterOptions): Route[];
5
9
  export declare function getRouteParams(pathname: string, routes: Route[]): Record<string, string> | null;
6
- // Backwards-compatible createRouter that returns Route[] (original signature)
7
- export declare interface RouterOptions {
8
- pagesDir?: string
9
- extensions?: string[]
10
- }
11
- export { findErrorPage, formatRoutes, generateRouteManifest, generateRouteTypes, matchRoute } from 'stx-router';
package/dist/routes.d.ts CHANGED
@@ -1,8 +1,6 @@
1
- import { route } from 'stx-router';
1
+ export { defineRoute, defineRoutes, resetRoutes, route, setAppUrl } from 'stx-router';
2
2
  /**
3
3
  * Process @route directives in stx templates
4
4
  * (Kept in core stx because it depends on safe-evaluator)
5
5
  */
6
6
  export declare function processRouteDirectives(template: string): string;
7
- // Re-export named route primitives from stx-router
8
- export { defineRoute, defineRoutes, resetRoutes, route, setAppUrl } from 'stx-router';