@stacksjs/stx 0.2.305 → 0.2.306

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 (158) hide show
  1. package/dist/{chunk-0gz0rhvs.js → chunk-0gbptqh2.js} +1 -1
  2. package/dist/{chunk-g97atepq.js → chunk-0mnv8pf5.js} +1 -1
  3. package/dist/{chunk-nqq7y7m9.js → chunk-18p8dqya.js} +1 -1
  4. package/dist/{chunk-s3dnk3gc.js → chunk-1bmtk8s5.js} +1 -1
  5. package/dist/{chunk-wnamjw6n.js → chunk-1zcm299e.js} +1 -1
  6. package/dist/{chunk-awj7yy37.js → chunk-1ztjv7a4.js} +1 -1
  7. package/dist/{chunk-qev11kg8.js → chunk-2kv2gnzc.js} +1 -1
  8. package/dist/chunk-2mx57479.js +2 -0
  9. package/dist/{chunk-b4xwbh8a.js → chunk-322qz0cj.js} +1 -1
  10. package/dist/{chunk-t51mwjyq.js → chunk-397rqs12.js} +1 -1
  11. package/dist/{chunk-env6knrs.js → chunk-3by4c2g9.js} +1 -1
  12. package/dist/{chunk-tt4r8q4v.js → chunk-3pv0qj5f.js} +1 -1
  13. package/dist/{chunk-7m4yhzhb.js → chunk-3qc0h6bj.js} +2 -2
  14. package/dist/{chunk-k23r03qj.js → chunk-3qfz82gw.js} +1 -1
  15. package/dist/chunk-455m2k1y.js +2 -0
  16. package/dist/{chunk-c131k3mt.js → chunk-4ee1aaet.js} +1 -1
  17. package/dist/{chunk-d3srvh3q.js → chunk-4hk5ewgp.js} +1 -1
  18. package/dist/{chunk-1jbjrc0w.js → chunk-4k0h6sca.js} +1 -1
  19. package/dist/chunk-4mtc9vyb.js +2 -0
  20. package/dist/chunk-4yky0frv.js +2 -0
  21. package/dist/{chunk-wx13qmaw.js → chunk-51gea48g.js} +1 -1
  22. package/dist/chunk-5598ankf.js +2 -0
  23. package/dist/{chunk-gbwhbasw.js → chunk-5g39e9ra.js} +1 -1
  24. package/dist/{chunk-bk95q0bw.js → chunk-5yhb5fad.js} +1 -1
  25. package/dist/{chunk-xsfwcj6x.js → chunk-604qr43v.js} +1 -1
  26. package/dist/chunk-6vt9ddra.js +2 -0
  27. package/dist/{chunk-ek8cgwcg.js → chunk-74sgwgyt.js} +1 -1
  28. package/dist/{chunk-gecmqs6p.js → chunk-79nj87t6.js} +1 -1
  29. package/dist/chunk-7amgwmrw.js +2 -0
  30. package/dist/{chunk-gssbag3e.js → chunk-7c1qq9zq.js} +1 -1
  31. package/dist/chunk-7q81jygp.js +2 -0
  32. package/dist/{chunk-t8fqjb25.js → chunk-7sn5rbrd.js} +1 -1
  33. package/dist/{chunk-yyyxt326.js → chunk-7yzyn9k7.js} +1 -1
  34. package/dist/{chunk-ppyz9623.js → chunk-85p4dmft.js} +1 -1
  35. package/dist/chunk-8n2cafmh.js +2 -0
  36. package/dist/{chunk-8ee62a9q.js → chunk-8q8gj45z.js} +1 -1
  37. package/dist/chunk-9aw5d4rr.js +2 -0
  38. package/dist/{chunk-ze44hhxb.js → chunk-9b9znn2f.js} +2 -2
  39. package/dist/{chunk-f1cgyd2h.js → chunk-9eat8v8r.js} +1 -1
  40. package/dist/{chunk-fp7ms6e7.js → chunk-9ebfmdyb.js} +1 -1
  41. package/dist/chunk-9j1jfhrf.js +2 -0
  42. package/dist/chunk-9ypp0a8t.js +2 -0
  43. package/dist/{chunk-rzevgemj.js → chunk-a50hb40e.js} +1 -1
  44. package/dist/{chunk-ydgdq45a.js → chunk-aftse9mb.js} +1 -1
  45. package/dist/{chunk-wfffa8zm.js → chunk-aqrp68m6.js} +1 -1
  46. package/dist/{chunk-8jam44my.js → chunk-at84gyvf.js} +1 -1
  47. package/dist/{chunk-ess2pgt5.js → chunk-b8cteeha.js} +1 -1
  48. package/dist/{chunk-mbmqpaq1.js → chunk-bnq0p4r4.js} +1 -1
  49. package/dist/{chunk-rvyfyc43.js → chunk-bs18cyh6.js} +1 -1
  50. package/dist/{chunk-m8n0s4tk.js → chunk-bxqzqwv5.js} +1 -1
  51. package/dist/chunk-bzmxbz48.js +2 -0
  52. package/dist/{chunk-c1ae6afc.js → chunk-e5yebhrk.js} +2 -2
  53. package/dist/{chunk-ta398s3d.js → chunk-ejjzrtym.js} +10 -10
  54. package/dist/{chunk-mv5fdcwc.js → chunk-ewcxfn7m.js} +3 -3
  55. package/dist/{chunk-gt8ja700.js → chunk-f044qmn3.js} +1 -1
  56. package/dist/chunk-f3k3kk5x.js +2 -0
  57. package/dist/{chunk-eans1ct0.js → chunk-ffexgxm3.js} +1 -1
  58. package/dist/chunk-fh97a60e.js +2 -0
  59. package/dist/chunk-fzwqh8sy.js +2 -0
  60. package/dist/chunk-g812bscg.js +2 -0
  61. package/dist/chunk-gt40xkj3.js +2 -0
  62. package/dist/chunk-h78pksyp.js +2 -0
  63. package/dist/chunk-hq3w5crk.js +2 -0
  64. package/dist/chunk-hy1ma54e.js +2 -0
  65. package/dist/{chunk-695fkras.js → chunk-j3ajrx2n.js} +1 -1
  66. package/dist/{chunk-jsg1rthc.js → chunk-jd9nv63q.js} +1 -1
  67. package/dist/{chunk-jp2f8yzw.js → chunk-jryjwara.js} +1 -1
  68. package/dist/{chunk-4evbx7sz.js → chunk-jwnbwemq.js} +1 -1
  69. package/dist/{chunk-zhcs8m2a.js → chunk-k14nr7rz.js} +1 -1
  70. package/dist/{chunk-hg2afckn.js → chunk-ka2xspj3.js} +1 -1
  71. package/dist/{chunk-mygq61f5.js → chunk-ka5wtqmw.js} +1 -1
  72. package/dist/{chunk-6zt2y7q3.js → chunk-kdkv0j67.js} +1 -1
  73. package/dist/{chunk-d5cqnwdd.js → chunk-kexk6z9s.js} +1 -1
  74. package/dist/{chunk-w6d91maa.js → chunk-kgtbm5rp.js} +1 -1
  75. package/dist/{chunk-qeyw5za9.js → chunk-ksqba0cq.js} +1 -1
  76. package/dist/chunk-kz149fx5.js +2 -0
  77. package/dist/chunk-mhety3pf.js +2 -0
  78. package/dist/{chunk-m31n9pkr.js → chunk-msmhta0w.js} +1 -1
  79. package/dist/chunk-mvj75wef.js +2 -0
  80. package/dist/{chunk-cbgh359m.js → chunk-n43zq50e.js} +1 -1
  81. package/dist/{chunk-g912mb7x.js → chunk-nnv8wytm.js} +1 -1
  82. package/dist/chunk-nvb9nsqv.js +2 -0
  83. package/dist/chunk-ps7nfwq5.js +2 -0
  84. package/dist/{chunk-fg0nf7cv.js → chunk-qhnyrwz2.js} +246 -245
  85. package/dist/{chunk-fczfdsab.js → chunk-r7qap4bh.js} +2 -2
  86. package/dist/chunk-raxr83fs.js +60 -0
  87. package/dist/{chunk-jfzfrmzy.js → chunk-rtaa4ys9.js} +1 -1
  88. package/dist/{chunk-jxxv18a0.js → chunk-ry1key0g.js} +1 -1
  89. package/dist/{chunk-00rtz7nw.js → chunk-s3951qwp.js} +1 -1
  90. package/dist/{chunk-9c835qjn.js → chunk-s3pvp8qv.js} +1 -1
  91. package/dist/chunk-smtve243.js +2 -0
  92. package/dist/{chunk-sart9ehj.js → chunk-snmtft92.js} +1 -1
  93. package/dist/chunk-szdwkfzq.js +2 -0
  94. package/dist/{chunk-zs5y7xnt.js → chunk-t5kwx6fa.js} +1 -1
  95. package/dist/{chunk-4mrhxtn3.js → chunk-ttkt7xhd.js} +2 -2
  96. package/dist/{chunk-rrankpmj.js → chunk-ttny9g8k.js} +1 -1
  97. package/dist/chunk-v33qvj8y.js +2 -0
  98. package/dist/{chunk-f325jzsk.js → chunk-v7b5ny0x.js} +2 -2
  99. package/dist/{chunk-d19tvdvv.js → chunk-vhan24as.js} +1 -1
  100. package/dist/chunk-vpbw6g2t.js +2 -0
  101. package/dist/{chunk-1c2j4eby.js → chunk-w1dxgs78.js} +1 -1
  102. package/dist/{chunk-9nf3hgvq.js → chunk-w764f6g4.js} +2 -2
  103. package/dist/{chunk-bd9wrcq1.js → chunk-w8hkprzv.js} +1 -1
  104. package/dist/{chunk-ghw5p1yk.js → chunk-wm86mmgq.js} +1 -1
  105. package/dist/{chunk-d57gb0v2.js → chunk-wwghzbbg.js} +1 -1
  106. package/dist/{chunk-kxavsh3m.js → chunk-xcsf7my7.js} +1 -1
  107. package/dist/chunk-xfdckfqr.js +2 -0
  108. package/dist/{chunk-hrcxfvh1.js → chunk-y4dd2n2n.js} +1 -1
  109. package/dist/{chunk-7skk34dh.js → chunk-ybct46zd.js} +1 -1
  110. package/dist/chunk-z8yh03mr.js +2 -0
  111. package/dist/{chunk-t3qb9s6s.js → chunk-zdzd2jb4.js} +1 -1
  112. package/dist/{chunk-7gqbr8nr.js → chunk-zr1r73p3.js} +1 -1
  113. package/dist/cli.js +14 -14
  114. package/dist/craft-entry.js +1 -1
  115. package/dist/craft.js +1 -1
  116. package/dist/database.js +1 -1
  117. package/dist/expressions.d.ts +10 -1
  118. package/dist/expressions.js +42 -11
  119. package/dist/pwa.js +2 -2
  120. package/dist/safe-evaluator.d.ts +18 -0
  121. package/dist/safe-evaluator.js +100 -17
  122. package/dist/seo.js +34 -4
  123. package/dist/ssg.js +2 -2
  124. package/dist/visual-testing.js +1 -1
  125. package/package.json +5 -5
  126. package/dist/chunk-02hm88m5.js +0 -2
  127. package/dist/chunk-044mychj.js +0 -2
  128. package/dist/chunk-113y4ywy.js +0 -2
  129. package/dist/chunk-2h94c5hm.js +0 -60
  130. package/dist/chunk-3eervtf9.js +0 -2
  131. package/dist/chunk-4jgr954p.js +0 -2
  132. package/dist/chunk-57ea6ye2.js +0 -2
  133. package/dist/chunk-8z0n5mtg.js +0 -2
  134. package/dist/chunk-92zzryxw.js +0 -2
  135. package/dist/chunk-a87jqtmd.js +0 -2
  136. package/dist/chunk-bezqaxqt.js +0 -2
  137. package/dist/chunk-dgpjxmhs.js +0 -2
  138. package/dist/chunk-er848s6f.js +0 -2
  139. package/dist/chunk-hftqr8ej.js +0 -2
  140. package/dist/chunk-hzav4hyd.js +0 -2
  141. package/dist/chunk-m537zgay.js +0 -2
  142. package/dist/chunk-n99ajrwv.js +0 -2
  143. package/dist/chunk-ncrfrp95.js +0 -2
  144. package/dist/chunk-nws8fbde.js +0 -2
  145. package/dist/chunk-phcvbqzn.js +0 -2
  146. package/dist/chunk-qpzxgkc5.js +0 -2
  147. package/dist/chunk-qt2dmyq5.js +0 -2
  148. package/dist/chunk-r2k2sewg.js +0 -2
  149. package/dist/chunk-r808fpme.js +0 -2
  150. package/dist/chunk-sen2cxqm.js +0 -2
  151. package/dist/chunk-tc6gqeha.js +0 -2
  152. package/dist/chunk-twbw18vs.js +0 -2
  153. package/dist/chunk-wjdfhfj6.js +0 -2
  154. package/dist/chunk-x10mrzgp.js +0 -2
  155. package/dist/chunk-xd5ahrtn.js +0 -2
  156. package/dist/chunk-xzgvcrnz.js +0 -2
  157. package/dist/chunk-yd7jyyr7.js +0 -2
  158. package/dist/chunk-zs95z9tf.js +0 -2
@@ -39,6 +39,24 @@ export declare function resetSafeEvaluatorConfig(): void;
39
39
  * Get current configuration
40
40
  */
41
41
  export declare function getSafeEvaluatorConfig(): SafeEvaluatorConfig;
42
+ /**
43
+ * Thrown when an expression breaks the evaluator's security policy.
44
+ *
45
+ * `rule` names what rejected it, on its own, so a caller reporting the failure
46
+ * can say why without re-parsing the message.
47
+ */
48
+ export declare class UnsafeExpressionError extends Error {
49
+ readonly rule: string;
50
+ readonly expression: string;
51
+ constructor(rule: string, expression: string, message?: string);
52
+ }
53
+ /**
54
+ * The rule an expression breaks, or `null` when it is safe to evaluate.
55
+ *
56
+ * Unlike {@link getExpressionSafetyReason}, this is the rule alone, without the
57
+ * expression repeated after it.
58
+ */
59
+ export declare function getExpressionSafetyRule(expression: string): string | null;
42
60
  /**
43
61
  * Sanitize an expression by checking for dangerous patterns
44
62
  */
@@ -26,7 +26,7 @@ const _ALLOWED_GLOBALS = new Set([
26
26
  "JSON",
27
27
  "Number",
28
28
  "Boolean"
29
- ]), DANGEROUS_PATTERNS = [
29
+ ]), NEW_OPERATOR_PATTERN = /\bnew\s+/, SAFE_CTOR_PARAM = "__stx_safe_ctors", DANGEROUS_PATTERNS = [
30
30
  /\b(eval|Function|setTimeout|setInterval|setImmediate)\b/,
31
31
  /\b(process|require|import|exports|module)\b/,
32
32
  /\b(window|document|global|globalThis)\b/,
@@ -37,7 +37,7 @@ const _ALLOWED_GLOBALS = new Set([
37
37
  /\b(Generator|AsyncGenerator)\b/,
38
38
  /__\w+__/,
39
39
  /\.(bind|call|apply)\s*\(/,
40
- /\bnew\s+/,
40
+ NEW_OPERATOR_PATTERN,
41
41
  /\bdelete\s+/,
42
42
  /\bthis\b/
43
43
  ], DANGEROUS_IDENTIFIERS = new Set([
@@ -67,14 +67,17 @@ const _ALLOWED_GLOBALS = new Set([
67
67
  "Generator",
68
68
  "AsyncGenerator",
69
69
  "delete",
70
- "this"
70
+ "this",
71
+ SAFE_CTOR_PARAM
71
72
  ]), DANGEROUS_BRACKET_KEYS = new Set([
72
73
  "__proto__",
73
74
  "constructor",
74
75
  "prototype"
75
76
  ]), BRACKET_NOTATION_PATTERN = /[\w)\]]\s*\[\s*['"]/;
76
- function stripStringLiterals(expr) {
77
- let result = "", inString = null, escaped = !1;
77
+ function stripStringLiteralsWithMap(expr) {
78
+ let result = "";
79
+ const map = [];
80
+ let inString = null, escaped = !1;
78
81
  for (let i = 0;i < expr.length; i++) {
79
82
  const ch = expr[i];
80
83
  if (escaped) {
@@ -96,6 +99,7 @@ function stripStringLiterals(expr) {
96
99
  tplDepth--;
97
100
  if (tplDepth > 0) {
98
101
  result += expr[i];
102
+ map.push(i);
99
103
  i++;
100
104
  }
101
105
  }
@@ -110,8 +114,72 @@ function stripStringLiterals(expr) {
110
114
  continue;
111
115
  }
112
116
  result += ch;
117
+ map.push(i);
118
+ }
119
+ return { text: result, map };
120
+ }
121
+ function stripStringLiterals(expr) {
122
+ return stripStringLiteralsWithMap(expr).text;
123
+ }
124
+ const INTL_CONSTRUCTORS = [
125
+ "Collator",
126
+ "DateTimeFormat",
127
+ "DisplayNames",
128
+ "ListFormat",
129
+ "Locale",
130
+ "NumberFormat",
131
+ "PluralRules",
132
+ "RelativeTimeFormat",
133
+ "Segmenter"
134
+ ], SAFE_CONSTRUCTORS = (() => {
135
+ const ctors = { Date, URL, URLSearchParams }, intl = Intl;
136
+ for (const name of INTL_CONSTRUCTORS)
137
+ if (typeof intl[name] === "function")
138
+ ctors[`Intl_${name}`] = intl[name];
139
+ return Object.freeze(Object.assign(Object.create(null), ctors));
140
+ })(), SAFE_NEW_RE = /^new(\s+)(Date|URLSearchParams|URL|Intl\s*\.\s*([A-Z_a-z]\w*))\s*\(/, NEW_TOKEN_RE = /(?<![\w$])new(?![\w$])/g, SAFE_NEW_RULE = `only new Date(), new URL(), new URLSearchParams() and new Intl.{${INTL_CONSTRUCTORS.join(",")}}() are allowed`;
141
+ function rewriteSafeConstructors(expression) {
142
+ const { text, map } = stripStringLiteralsWithMap(expression), replacements = [];
143
+ NEW_TOKEN_RE.lastIndex = 0;
144
+ let match;
145
+ while ((match = NEW_TOKEN_RE.exec(text)) !== null) {
146
+ const at = match.index;
147
+ if (/(?<!\.)\.\s*$/.test(text.slice(0, at)))
148
+ continue;
149
+ const tail = SAFE_NEW_RE.exec(text.slice(at)), intlName = tail?.[3], key = !tail ? null : intlName ? `Intl_${intlName}` : tail[2];
150
+ if (!tail || !key || !(key in SAFE_CONSTRUCTORS))
151
+ throw new UnsafeExpressionError(`matched /${NEW_OPERATOR_PATTERN.source}/; ${SAFE_NEW_RULE}`, expression);
152
+ const spanEnd = at + tail[0].length, originalStart = map[at], originalEnd = map[spanEnd - 1] + 1;
153
+ if (expression.slice(originalStart, originalEnd) !== text.slice(at, spanEnd))
154
+ throw new UnsafeExpressionError(`matched /${NEW_OPERATOR_PATTERN.source}/; ${SAFE_NEW_RULE}`, expression);
155
+ const nameStart = originalStart + 3 + tail[1].length;
156
+ replacements.push({ start: nameStart, end: nameStart + tail[2].length, key });
157
+ }
158
+ let source = expression;
159
+ for (let i = replacements.length - 1;i >= 0; i--) {
160
+ const r = replacements[i];
161
+ source = `${source.slice(0, r.start)}${SAFE_CTOR_PARAM}.${r.key}${source.slice(r.end)}`;
162
+ }
163
+ return { source, usesSafeConstructors: replacements.length > 0 };
164
+ }
165
+
166
+ export class UnsafeExpressionError extends Error {
167
+ rule;
168
+ expression;
169
+ constructor(rule, expression, message) {
170
+ super(message ?? `Potentially unsafe expression (${rule}): ${expression}`);
171
+ this.name = "UnsafeExpressionError";
172
+ this.rule = rule;
173
+ this.expression = expression;
174
+ }
175
+ }
176
+ export function getExpressionSafetyRule(expression) {
177
+ try {
178
+ prepareExpression(expression);
179
+ return null;
180
+ } catch (e) {
181
+ return e instanceof UnsafeExpressionError ? e.rule : e instanceof Error ? e.message : String(e);
113
182
  }
114
- return result;
115
183
  }
116
184
  function assertNoUnsafeIdentifierTokens(strippedExpression, originalExpression) {
117
185
  const identifierRe = /[$A-Z_a-z][$\w]*/g;
@@ -119,9 +187,9 @@ function assertNoUnsafeIdentifierTokens(strippedExpression, originalExpression)
119
187
  while ((match = identifierRe.exec(strippedExpression)) !== null) {
120
188
  const identifier = match[0], previous = strippedExpression[match.index - 1];
121
189
  if (DANGEROUS_IDENTIFIERS.has(identifier))
122
- throw Error(`Potentially unsafe expression (matched /\\b${identifier}\\b/; identifier ${identifier}): ${originalExpression}`);
190
+ throw new UnsafeExpressionError(`matched /\\b${identifier}\\b/; identifier ${identifier}`, originalExpression);
123
191
  if (previous === "." && DANGEROUS_BRACKET_KEYS.has(identifier))
124
- throw Error(`Potentially unsafe expression (matched /.${identifier}/; property ${identifier}): ${originalExpression}`);
192
+ throw new UnsafeExpressionError(`matched /.${identifier}/; property ${identifier}`, originalExpression);
125
193
  }
126
194
  }
127
195
  function assertSafeBracketLiteralKeys(expression) {
@@ -133,19 +201,26 @@ function assertSafeBracketLiteralKeys(expression) {
133
201
  continue;
134
202
  const previousNonSpace = expression.slice(0, match.index).match(/\S(?=\s*$)/)?.[0], nextNonSpace = expression.slice(match.index + match[0].length).match(/^\s*(\S)/)?.[1];
135
203
  if (!((previousNonSpace === "{" || previousNonSpace === ",") && nextNonSpace === ":"))
136
- throw Error(`Potentially unsafe expression (bracket key ${match[2]}): ${expression}`);
204
+ throw new UnsafeExpressionError(`bracket key ${match[2]}`, expression);
137
205
  }
138
206
  }
139
- export function sanitizeExpression(expression) {
207
+ function prepareExpression(expression) {
140
208
  const trimmed = expression.trim(), stripped = stripStringLiterals(trimmed);
141
209
  assertNoUnsafeIdentifierTokens(stripped, trimmed);
142
210
  assertSafeBracketLiteralKeys(trimmed);
143
- for (const pattern of DANGEROUS_PATTERNS)
211
+ for (const pattern of DANGEROUS_PATTERNS) {
212
+ if (pattern === NEW_OPERATOR_PATTERN)
213
+ continue;
144
214
  if (pattern.test(stripped))
145
- throw Error(`Potentially unsafe expression (matched /${pattern.source}/): ${trimmed}`);
215
+ throw new UnsafeExpressionError(`matched /${pattern.source}/`, trimmed);
216
+ }
146
217
  if (!currentConfig.allowBracketNotation && BRACKET_NOTATION_PATTERN.test(trimmed))
147
- throw Error(`Bracket notation with strings not allowed: ${trimmed}. Enable with configureSafeEvaluator({ allowBracketNotation: true })`);
148
- return trimmed;
218
+ throw new UnsafeExpressionError("bracket notation with a string key; enable with configureSafeEvaluator({ allowBracketNotation: true })", trimmed, `Bracket notation with strings not allowed: ${trimmed}. Enable with configureSafeEvaluator({ allowBracketNotation: true })`);
219
+ return rewriteSafeConstructors(trimmed);
220
+ }
221
+ export function sanitizeExpression(expression) {
222
+ prepareExpression(expression);
223
+ return expression.trim();
149
224
  }
150
225
  export function createSafeContext(context) {
151
226
  const safeContext = {};
@@ -317,14 +392,16 @@ export function isUsableParamName(name) {
317
392
  return VALID_PARAM_IDENT.test(name) && !RESERVED_PARAM_NAMES.has(name);
318
393
  }
319
394
  export function createSafeFunction(expression, contextKeys) {
320
- const sanitizedExpr = sanitizeExpression(expression), validEntries = [];
395
+ const { source: sanitizedExpr, usesSafeConstructors } = prepareExpression(expression), validEntries = [];
321
396
  for (let i = 0;i < contextKeys.length; i++) {
322
397
  if (!isUsableParamName(contextKeys[i]))
323
398
  continue;
399
+ if (contextKeys[i] === SAFE_CTOR_PARAM)
400
+ continue;
324
401
  validEntries.push({ key: contextKeys[i], index: i });
325
402
  }
326
403
  validEntries.sort((a, b) => a.key.localeCompare(b.key));
327
- const filteredKeys = validEntries.map((entry) => entry.key), validIndices = validEntries.map((entry) => entry.index), buildFunc = (extraParams) => compileFunctionBody([...filteredKeys, ...extraParams], `
404
+ const filteredKeys = validEntries.map((entry) => entry.key), validIndices = validEntries.map((entry) => entry.index), body = `
328
405
  'use strict';
329
406
  try {
330
407
  return ${sanitizedExpr};
@@ -335,7 +412,13 @@ catch (e) {
335
412
  }
336
413
  throw e;
337
414
  }
338
- `);
415
+ `;
416
+ return bindProjection(usesSafeConstructors ? (extraParams) => {
417
+ const compiled = compileFunctionBody([SAFE_CTOR_PARAM, ...filteredKeys, ...extraParams], body);
418
+ return (...args) => compiled(SAFE_CONSTRUCTORS, ...args);
419
+ } : (extraParams) => compileFunctionBody([...filteredKeys, ...extraParams], body), filteredKeys, contextKeys, validEntries, validIndices);
420
+ }
421
+ function bindProjection(buildFunc, filteredKeys, contextKeys, validEntries, validIndices) {
339
422
  let func = buildFunc([]);
340
423
  const alreadyCanonical = validEntries.every((entry, index) => entry.index === index);
341
424
  if (filteredKeys.length === contextKeys.length && alreadyCanonical)
package/dist/seo.js CHANGED
@@ -253,12 +253,14 @@ export function injectSeoTags(html, context, options) {
253
253
  return html;
254
254
  if (!html.includes("<head>") && !html.includes("<head "))
255
255
  return html;
256
- const hasTitle = html.includes("<title>") || html.includes("</title>");
256
+ const hasTitle = html.includes("<title>") || html.includes("</title>"), pageHead = headSection(html), pageTitle = readPageTitle(pageHead), pageDescription = readPageDescription(pageHead);
257
257
  let title = "";
258
258
  if (context.title)
259
259
  title = context.title;
260
260
  else if (context.meta && context.meta.title)
261
261
  title = context.meta.title;
262
+ else if (pageTitle)
263
+ title = pageTitle;
262
264
  else if (options.seo?.defaultConfig?.title)
263
265
  title = options.seo.defaultConfig.title;
264
266
  else
@@ -268,6 +270,8 @@ export function injectSeoTags(html, context, options) {
268
270
  description = context.description;
269
271
  else if (context.meta && context.meta.description)
270
272
  description = context.meta.description;
273
+ else if (pageDescription)
274
+ description = pageDescription;
271
275
  else if (options.seo?.defaultConfig?.description)
272
276
  description = options.seo.defaultConfig.description;
273
277
  else
@@ -283,10 +287,11 @@ export function injectSeoTags(html, context, options) {
283
287
  image = options.seo.defaultImage;
284
288
  else if (options.defaultImage)
285
289
  image = options.defaultImage;
290
+ const titleTag = hasTitle ? "" : `
291
+ <meta name="title" content="${escapeHtml(title)}">`, descriptionTag = hasPageDescription(pageHead) ? "" : `
292
+ <meta name="description" content="${escapeHtml(description)}">`;
286
293
  let seoTagsMinimal = `
287
- <!-- stx SEO Tags -->
288
- <meta name="title" content="${escapeHtml(title)}">
289
- <meta name="description" content="${escapeHtml(description)}">
294
+ <!-- stx SEO Tags -->${titleTag}${descriptionTag}
290
295
  <meta property="og:title" content="${escapeHtml(title)}">
291
296
  <meta property="og:description" content="${escapeHtml(description)}">
292
297
  <meta property="og:type" content="website">
@@ -315,6 +320,31 @@ ${seoTagsMinimal}
315
320
  ${seoTagsMinimal}
316
321
  `);
317
322
  }
323
+ function headSection(html) {
324
+ const end = html.search(/<\/head\s*>/i);
325
+ return end === -1 ? html : html.slice(0, end);
326
+ }
327
+ function unescapeBasicEntities(str) {
328
+ return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#0*39;|&apos;/g, "'").replace(/&amp;/g, "&");
329
+ }
330
+ function readPageTitle(head) {
331
+ const match = head.match(/<title(?:\s[^>]*)?>([\s\S]*?)<\/title\s*>/i);
332
+ return match ? unescapeBasicEntities(match[1].trim()) : "";
333
+ }
334
+ function descriptionMetaTags(head) {
335
+ return (head.match(/<meta\s[^>]*>/gi) || []).filter((tag) => /\sname\s*=\s*["']description["']/i.test(tag));
336
+ }
337
+ function hasPageDescription(head) {
338
+ return descriptionMetaTags(head).length > 0;
339
+ }
340
+ function readPageDescription(head) {
341
+ for (const tag of descriptionMetaTags(head)) {
342
+ const match = tag.match(/\scontent\s*=\s*(?:"([^"]*)"|'([^']*)')/i), content = (match?.[1] ?? match?.[2] ?? "").trim();
343
+ if (content)
344
+ return unescapeBasicEntities(content);
345
+ }
346
+ return "";
347
+ }
318
348
  function escapeHtml(str) {
319
349
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
320
350
  }
package/dist/ssg.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{Fk as Uq,Gk as Iq,Kk as Fq}from"./chunk-zhcs8m2a.js";import{Lk as Eq,Mk as Tq,Nk as Dq}from"./chunk-09zjty4k.js";import{gl as _q,jl as zq,kl as Aq}from"./chunk-gecmqs6p.js";import"./chunk-7m4yhzhb.js";import{Tm as Oq,_p as P,np as Bq,ro as l,uo as Hq,xr as n}from"./chunk-fg0nf7cv.js";import"./chunk-2h94c5hm.js";import"./chunk-8jam44my.js";import"./chunk-t51mwjyq.js";import"./chunk-wfffa8zm.js";import{_t as Xq}from"./chunk-mv5fdcwc.js";import"./chunk-4evbx7sz.js";import"./chunk-jxxv18a0.js";import{mu as d}from"./chunk-c131k3mt.js";import"./chunk-9nf3hgvq.js";import"./chunk-nqq7y7m9.js";import"./chunk-1c2j4eby.js";import"./chunk-kxavsh3m.js";import"./chunk-qev11kg8.js";import"./chunk-rrankpmj.js";import{Jv as Yq,Kv as Vq,Lv as jq,Mv as Gq,Nv as Lq,Ov as Nq}from"./chunk-fczfdsab.js";import"./chunk-fp7ms6e7.js";import{cw as y}from"./chunk-jp2f8yzw.js";import O from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,z,A)=>{let G=A.trim();if(!G)return J;if(/\bdata-stx-src=/.test(z))return J;if(Z.minify)G=yq(G);let X=Cq(G);if(!$.has(X))$.set(X,G);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(G).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${X}.js"${B}${z}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let z=q.lastIndexOf("</head>");if(K.size===0||z===-1)return q;let A=Array.from(K).filter((G)=>!q.includes(`rel="prefetch" href="${G}"`)).map((G)=>`<link rel="prefetch" href="${G}" as="script">`).join("");if(!A)return q;return q.slice(0,z)+A+q.slice(z)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
2
+ import{Fk as Uq,Gk as Iq,Kk as Fq}from"./chunk-k14nr7rz.js";import{Lk as Eq,Mk as Tq,Nk as Dq}from"./chunk-09zjty4k.js";import{gl as _q,jl as zq,kl as Aq}from"./chunk-79nj87t6.js";import"./chunk-3qc0h6bj.js";import{$p as P,Um as Oq,op as Bq,so as l,vo as Hq,yr as n}from"./chunk-qhnyrwz2.js";import"./chunk-raxr83fs.js";import"./chunk-at84gyvf.js";import"./chunk-397rqs12.js";import"./chunk-aqrp68m6.js";import{au as Xq}from"./chunk-ewcxfn7m.js";import"./chunk-jwnbwemq.js";import"./chunk-ry1key0g.js";import{ou as d}from"./chunk-4ee1aaet.js";import"./chunk-w764f6g4.js";import"./chunk-18p8dqya.js";import"./chunk-w1dxgs78.js";import"./chunk-xcsf7my7.js";import"./chunk-2kv2gnzc.js";import"./chunk-ttny9g8k.js";import{Lv as Yq,Mv as Vq,Nv as jq,Ov as Gq,Pv as Lq,Qv as Nq}from"./chunk-r7qap4bh.js";import"./chunk-9ebfmdyb.js";import{ew as y}from"./chunk-jryjwara.js";import O from"fs";import j from"path";import{createHash as xq}from"crypto";function yq(q){try{return new Bun.Transpiler({loader:"js",minifyWhitespace:!0}).transformSync(q).replace(/\}(var |let |const |function )/g,"};$1").trim()}catch{return q}}var Pq=/<script\s+type="stx\/island"\s+data-stx-island="([^"]+)"([^>]*)>([\s\S]*?)<\/script>/g;function Cq(q){return Bun.hash(q).toString(16)}function Qq(q,Z={}){if(!q.includes('type="stx/island"'))return{html:q,chunks:[]};let $=new Map,Q=q.replace(Pq,(J,W,z,A)=>{let G=A.trim();if(!G)return J;if(/\bdata-stx-src=/.test(z))return J;if(Z.minify)G=yq(G);let X=Cq(G);if(!$.has(X))$.set(X,G);let B=Z.integrity?` data-stx-integrity="sha384-${xq("sha384").update(G).digest("base64")}"`:"";return`<script type="stx/island" data-stx-island="${W}" data-stx-src="/_stx/islands/${X}.js"${B}${z}></script>`}),K=Array.from($,([J,W])=>({hash:J,code:W}));return{html:Q,chunks:K}}var gq=new Set(["visible","idle"]);function Zq(q){if(!q.includes("data-stx-src="))return q;let Z=new Map,$=/data-stx-scope="([^"]+)"[^>]*?stx-hydrate="([^"]+)"/g,Q;while((Q=$.exec(q))!==null)Z.set(Q[1],Q[2]);let K=new Set,J=/data-stx-island="([^"]+)"[^>]*?data-stx-src="([^"]+)"/g,W;while((W=J.exec(q))!==null)if(gq.has(Z.get(W[1])||""))K.add(W[2]);let z=q.lastIndexOf("</head>");if(K.size===0||z===-1)return q;let A=Array.from(K).filter((G)=>!q.includes(`rel="prefetch" href="${G}"`)).map((G)=>`<link rel="prefetch" href="${G}" as="script">`).join("");if(!A)return q;return q.slice(0,z)+A+q.slice(z)}var fq=["STX_SITE_URL","SITE_URL","URL","VERCEL_URL","CF_PAGES_URL"];function h(q){let Z=q.trim();if(!Z)return null;let $=/^https?:\/\//i.test(Z)?Z:`https://${Z}`;try{return new URL($).origin+new URL($).pathname.replace(/\/$/,"")}catch{return null}}function mq(q){for(let Z of fq){let $=q[Z];if(!$)continue;let Q=h($);if(Q)return{url:Q,source:"env",via:Z}}return null}function $q(q){if(!q||typeof q!=="object")return null;let Z=q,$=Z.site?.url??Z.url??Z.app?.url;return typeof $==="string"?h($):null}async function dq(q){let{existsSync:Z}=await import("fs"),$=await import("path");for(let Q of["site.config.ts","site.config.js",".config/site.config.ts"]){let K=$.resolve(q,Q);if(!Z(K))continue;try{let J=await import(K),W=$q(J.default??J);if(W)return W}catch{}}return null}async function Kq(q={}){let Z=q.cwd??process.cwd(),$=q.env??process.env;if(q.explicit){let W=h(q.explicit);if(W)return{url:W,source:"option"}}let Q=$q(q.stxConfig);if(Q)return{url:Q,source:"stx.config",via:"site.url"};let K=await dq(Z);if(K)return{url:K,source:"site.config",via:"url"};let J=mq($);if(J)return J;return{url:"http://localhost",source:"fallback"}}function Wq(){return["No site URL configured \u2014 sitemap.xml and robots.txt will point at http://localhost."," Set one in stx.config.ts (site: { url: 'https://example.com' }), in site.config.ts,"," via --domain, or with SITE_URL in the build environment."].join(`
3
3
  `)}class wq{cacheDir;cache=new Map;loaded=!1;salt;constructor(q,Z=""){this.cacheDir=q,this.salt=Z}async load(){if(this.loaded)return;let q=j.join(this.cacheDir,"build-cache.json");if(await Bun.file(q).exists())try{let Z=JSON.parse(await Bun.file(q).text());for(let[$,Q]of Object.entries(Z))this.cache.set($,Q)}catch{}this.loaded=!0}async save(){await O.promises.mkdir(this.cacheDir,{recursive:!0});let q=j.join(this.cacheDir,"build-cache.json"),Z={};for(let[$,Q]of this.cache)Z[$]=Q;await Bun.write(q,JSON.stringify(Z))}getHash(q,Z){let $=O.statSync(q),Q=`${this.salt}|${q}:${$.mtimeMs}`;for(let J of Z)if(O.existsSync(J)){let W=O.statSync(J);Q+=`:${J}:${W.mtimeMs}`}let K=0;for(let J=0;J<Q.length;J++){let W=Q.charCodeAt(J);K=(K<<5)-K+W,K=K&K}return Math.abs(K).toString(36)}get(q,Z){let $=this.cache.get(q);if(!$)return null;let Q=this.getHash(Z,$.dependencies??[]);if($.hash!==Q)return this.cache.delete(q),null;return $.html}set(q,Z,$,Q){let K=this.getHash(Z,$);this.cache.set(q,{hash:K,html:Q,generatedAt:Date.now(),dependencies:$})}}class Rq{cacheDir;constructor(q){this.cacheDir=q}getFilePath(q){let Z=q.replace(/[^a-zA-Z0-9]/g,"_")+".json";return j.join(this.cacheDir,"isr",Z)}async get(q){let Z=this.getFilePath(q);if(!await Bun.file(Z).exists())return null;try{return JSON.parse(await Bun.file(Z).text())}catch{return null}}async set(q,Z){let $=this.getFilePath(q);await O.promises.mkdir(j.dirname($),{recursive:!0}),await Bun.write($,JSON.stringify(Z))}async invalidate(q){let Z=this.getFilePath(q);if(await Bun.file(Z).exists())await O.promises.unlink(Z)}async invalidatePattern(q){let Z=j.join(this.cacheDir,"isr");if(!O.existsSync(Z))return;let $=await O.promises.readdir(Z);for(let Q of $){let K=Q.replace(/_/g,"/").replace(".json","");if(q.test(K))await O.promises.unlink(j.join(Z,Q))}}async needsRevalidation(q){let Z=await this.get(q);if(!Z)return!0;return Date.now()>Z.revalidateAfter}}async function pq(q){try{let $=(await Bun.file(q).text()).match(/<script\s+server\b[^>]*>([\s\S]*?)<\/script>/i);if(!$)return null;let Q=$[1];if(!Q.includes("getStaticPaths"))return null;let K=Q.match(/(?:export\s+)?(?:async\s+)?function\s+getStaticPaths\s*\([^)]*\)\s*\{([\s\S]*?)\n[\t ]*\}/);if(!K)return null;return await Function(`
4
4
  return (async function getStaticPaths() {
5
5
  ${K[1]}
@@ -41,7 +41,7 @@ ${q.map((Q)=>{let K=new URL(Q.loc,Z).href,J=` <url>
41
41
  ${$.join(`
42
42
  `)}
43
43
  </channel>
44
- </rss>`}async function aq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},z=new Set,A=0,G={},X={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&O.existsSync(J.outputDir))await O.promises.rm(J.outputDir,{recursive:!0});await O.promises.mkdir(J.outputDir,{recursive:!0});let L=J.cacheSalt;if(!L){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-k23r03qj.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-xd5ahrtn.js"),F=await _(J.publicDir,J.outputDir);if(F.count>0)console.log(`Optimized ${F.count} image(s) for responsive delivery`),L=[L,F.fingerprint].filter(Boolean).join(":");let C=new wq(J.cacheDir,L);if(J.cache)await C.load();try{let{generateCss:Y}=await import("./chunk-k23r03qj.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];Fq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let H of N)g.push({route:Y,url:H.url,params:H.params,props:H.props,revalidate:H.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let b=[],s=[];for(let Y=0;Y<g.length;Y+=J.concurrency)s.push(g.slice(Y,Y+J.concurrency));for(let Y of s)await Promise.all(Y.map(async(N)=>{let{route:H,url:V,params:S,props:Sq,revalidate:a}=N;try{await J.hooks.onPageStart?.(V);let w=await Bun.file(H.filePath).text(),R=JJ(w),vq=R?.middleware?Array.isArray(R.middleware)?R.middleware:[R.middleware]:[],t=[...bq,...vq];if(t.length>0){let D=Gq(V,S,R||{}),M=Lq(D,null,void 0,{isServer:!0}),E=await Nq(t,M);if(E.redirect){let U=typeof E.redirect==="string"?E.redirect:E.redirect.path||E.redirect,x=QJ(String(U),V),k=ZJ(V,J);await O.promises.mkdir(j.dirname(k),{recursive:!0}),await Bun.write(k,x),W.successCount++,W.pages.push({route:V,outputPath:k,size:Buffer.byteLength(x),cached:!1}),b.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${U}`);return}if(E.abort){let U=typeof E.abort==="string"?E.abort:E.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${U}`);return}}let e=w.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
44
+ </rss>`}async function aq(q={}){let Z=Date.now();Aq();let $=await n(process.cwd()),Q=$.build||{},K=await Kq({explicit:q.domain||Q.domain,stxConfig:$});if(K.source==="fallback"&&(q.sitemap??Q.sitemap??!0))console.warn(Wq());let J={router:q.router??$?.router??{},pagesDir:q.pagesDir||Q.pagesDir||"pages",outputDir:q.outputDir||Q.outputDir||"dist",baseUrl:q.baseUrl||Q.baseUrl||"/",domain:K.url,revalidate:q.revalidate??Q.revalidate??!1,sitemap:q.sitemap??Q.sitemap??!0,sitemapExclude:q.sitemapExclude||Q.sitemapExclude||[],robots:q.robots??Q.robots??!0,rss:q.rss??Q.rss??!1,concurrency:q.concurrency||Q.concurrency||10,cache:q.cache??Q.cache??!0,cacheDir:q.cacheDir||Q.cacheDir||d(process.cwd(),"ssg-cache"),contentLoaders:q.contentLoaders||[],hooks:q.hooks||{},minify:q.minify??Q.minify??!0,generate404:q.generate404??Q.generate404??!0,publicDir:q.publicDir||Q.publicDir||"public",trailingSlash:q.trailingSlash??Q.trailingSlash??!1,cleanOutput:q.cleanOutput??Q.cleanOutput??!0,cacheSalt:q.cacheSalt??"",partialsDir:q.partialsDir||$?.partialsDir||"",componentsDir:q.componentsDir||$?.componentsDir||"",failOnIncludeError:q.failOnIncludeError??!0,chunkIslands:q.chunkIslands===!0,prefetchIslands:q.prefetchIslands===!0,integrityIslands:q.integrityIslands===!0},W={totalPages:0,successCount:0,failedCount:0,cachedCount:0,buildTime:0,pages:[],errors:[]},z=new Set,A=0,G={},X={};await J.hooks.onBuildStart?.();try{if(J.cleanOutput&&O.existsSync(J.outputDir))await O.promises.rm(J.outputDir,{recursive:!0});await O.promises.mkdir(J.outputDir,{recursive:!0});let L=J.cacheSalt;if(!L){let{resolveUserCssConfig:Y,fingerprintConfig:N}=await import("./chunk-3qfz82gw.js");try{L=N(await Y(process.cwd()))}catch{}}let{prepareImageDelivery:_}=await import("./chunk-6vt9ddra.js"),F=await _(J.publicDir,J.outputDir);if(F.count>0)console.log(`Optimized ${F.count} image(s) for responsive delivery`),L=[L,F.fingerprint].filter(Boolean).join(":");let C=new wq(J.cacheDir,L);if(J.cache)await C.load();try{let{generateCss:Y}=await import("./chunk-3qfz82gw.js");await Y('<div class="bg-black"></div>')}catch{}Yq();let kq=$?.routeMiddleware?.dir||"middleware";await jq(process.cwd(),kq);let p=Vq();if(p.length>0)console.log(`Loaded ${p.length} middleware: ${p.join(", ")}`);let bq=$?.routeMiddleware?.global||[];Fq($?.layoutsDir,d(process.cwd()));let i=l(".",{pagesDir:J.pagesDir,pagesDirs:$?._layerPageDirs});console.log(`Found ${i.length} routes`);let g=[];for(let Y of i){let N=await uq(Y);for(let H of N)g.push({route:Y,url:H.url,params:H.params,props:H.props,revalidate:H.revalidate??J.revalidate})}W.totalPages=g.length,console.log(`Generating ${W.totalPages} pages...`);let b=[],s=[];for(let Y=0;Y<g.length;Y+=J.concurrency)s.push(g.slice(Y,Y+J.concurrency));for(let Y of s)await Promise.all(Y.map(async(N)=>{let{route:H,url:V,params:S,props:Sq,revalidate:a}=N;try{await J.hooks.onPageStart?.(V);let w=await Bun.file(H.filePath).text(),R=JJ(w),vq=R?.middleware?Array.isArray(R.middleware)?R.middleware:[R.middleware]:[],t=[...bq,...vq];if(t.length>0){let D=Gq(V,S,R||{}),M=Lq(D,null,void 0,{isServer:!0}),E=await Nq(t,M);if(E.redirect){let U=typeof E.redirect==="string"?E.redirect:E.redirect.path||E.redirect,x=QJ(String(U),V),k=ZJ(V,J);await O.promises.mkdir(j.dirname(k),{recursive:!0}),await Bun.write(k,x),W.successCount++,W.pages.push({route:V,outputPath:k,size:Buffer.byteLength(x),cached:!1}),b.push({loc:V,lastmod:new Date().toISOString()}),console.log(` \u21B3 ${V} \u2192 redirect to ${U}`);return}if(E.abort){let U=typeof E.abort==="string"?E.abort:E.abort?.error?.message||"aborted";console.warn(` \u21B3 ${V} \u2014 middleware aborted: ${U}`);return}}let e=w.match(/definePageMeta\s*\(\s*\{[\s\S]*?validate\s*:\s*((?:\([^)]*\)|[^,}])*(?:\{[\s\S]*?\})?)/m);if(e)try{if(!await Function("route",`
45
45
  const validate = ${e[1]};
46
46
  return validate(route);
47
47
  `)({params:S})){console.warn(`Validation failed for ${V}, skipping...`);return}}catch{}let I=null,qq=!1;if(J.cache){if(I=C.get(V,H.filePath),I)qq=!0,W.cachedCount++}if(!I){let D=await Mq(H,S,Sq,J,$);if(I=D.html,J.failOnIncludeError&&D.includeFailures.length>0)throw Error(`${D.includeFailures.length} include(s) failed to resolve, so this page would have shipped with an error banner where the markup should be:
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import"./chunk-jp2f8yzw.js";import B from"fs";import $ from"path";import k from"crypto";var V=[{name:"mobile",width:375,height:667,isMobile:!0,hasTouch:!0},{name:"tablet",width:768,height:1024,isMobile:!0,hasTouch:!0},{name:"desktop",width:1280,height:800,isMobile:!1,hasTouch:!1},{name:"wide",width:1920,height:1080,isMobile:!1,hasTouch:!1}];function J(N={}){let Y={snapshotDir:N.snapshotDir||"__snapshots__",screenshotDir:N.screenshotDir||"__screenshots__",updateSnapshots:N.updateSnapshots||process.env.UPDATE_SNAPSHOTS==="true",threshold:N.threshold??0.01,viewports:N.viewports||V,generateDiff:N.generateDiff??!0,diffDir:N.diffDir||"__diffs__",compare:N.compare||b,ci:N.ci??process.env.CI==="true",retries:N.retries??(N.ci?3:1)};return{async snapshot(M,X){let q=$.join(Y.snapshotDir,`${X}.html`),G=C(M),Q=K(G);if(await Bun.file(q).exists()){let W=await Bun.file(q).text(),Z=K(C(W));if(Q===Z)return{passed:!0,snapshotPath:q,message:"Snapshot matches"};if(Y.updateSnapshots)return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};let F=$.join(Y.diffDir,`${X}.actual.html`),U=$.join(Y.diffDir,`${X}.diff.html`);return await B.promises.mkdir(Y.diffDir,{recursive:!0}),await Bun.write(F,G),await Bun.write(U,I(W,G)),{passed:!1,snapshotPath:q,actualPath:F,diffPath:U,message:"Snapshot does not match"}}return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"New snapshot created"}},async snapshotJson(M,X){let q=$.join(Y.snapshotDir,`${X}.json`),G=JSON.stringify(M,null,2);if(await Bun.file(q).exists()){let Q=await Bun.file(q).text();if(G===Q)return{passed:!0,snapshotPath:q};if(Y.updateSnapshots)return await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};return{passed:!1,snapshotPath:q,message:`JSON snapshot mismatch:
2
+ import"./chunk-jryjwara.js";import B from"fs";import $ from"path";import k from"crypto";var V=[{name:"mobile",width:375,height:667,isMobile:!0,hasTouch:!0},{name:"tablet",width:768,height:1024,isMobile:!0,hasTouch:!0},{name:"desktop",width:1280,height:800,isMobile:!1,hasTouch:!1},{name:"wide",width:1920,height:1080,isMobile:!1,hasTouch:!1}];function J(N={}){let Y={snapshotDir:N.snapshotDir||"__snapshots__",screenshotDir:N.screenshotDir||"__screenshots__",updateSnapshots:N.updateSnapshots||process.env.UPDATE_SNAPSHOTS==="true",threshold:N.threshold??0.01,viewports:N.viewports||V,generateDiff:N.generateDiff??!0,diffDir:N.diffDir||"__diffs__",compare:N.compare||b,ci:N.ci??process.env.CI==="true",retries:N.retries??(N.ci?3:1)};return{async snapshot(M,X){let q=$.join(Y.snapshotDir,`${X}.html`),G=C(M),Q=K(G);if(await Bun.file(q).exists()){let W=await Bun.file(q).text(),Z=K(C(W));if(Q===Z)return{passed:!0,snapshotPath:q,message:"Snapshot matches"};if(Y.updateSnapshots)return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};let F=$.join(Y.diffDir,`${X}.actual.html`),U=$.join(Y.diffDir,`${X}.diff.html`);return await B.promises.mkdir(Y.diffDir,{recursive:!0}),await Bun.write(F,G),await Bun.write(U,I(W,G)),{passed:!1,snapshotPath:q,actualPath:F,diffPath:U,message:"Snapshot does not match"}}return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"New snapshot created"}},async snapshotJson(M,X){let q=$.join(Y.snapshotDir,`${X}.json`),G=JSON.stringify(M,null,2);if(await Bun.file(q).exists()){let Q=await Bun.file(q).text();if(G===Q)return{passed:!0,snapshotPath:q};if(Y.updateSnapshots)return await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"Snapshot updated"};return{passed:!1,snapshotPath:q,message:`JSON snapshot mismatch:
3
3
  ${z(Q,G)}`}}return await B.promises.mkdir($.dirname(q),{recursive:!0}),await Bun.write(q,G),{passed:!0,snapshotPath:q,message:"New snapshot created"}},matchInlineSnapshot(M,X){let q=C(M);if(X===void 0)return{passed:!0,expected:q};let G=C(X);return{passed:q===G,expected:q}},getConfig(){return Y}}}function D(N={}){let Y=J(N),M=Y.getConfig();return{async compareScreenshots(X,q,G="desktop"){let Q=$.join(M.screenshotDir,G,`${X}.png`),W=$.join(M.diffDir,G,`${X}.actual.png`),Z=$.join(M.diffDir,G,`${X}.diff.png`);if(await Bun.file(Q).exists()){let F=await Bun.file(Q).arrayBuffer(),U=Buffer.from(F),_=await M.compare(q,U);if(_.match||_.diffPercentage<=M.threshold)return{viewport:G,passed:!0,baselinePath:Q};if(M.updateSnapshots)return await B.promises.mkdir($.dirname(Q),{recursive:!0}),await Bun.write(Q,q),{viewport:G,passed:!0,baselinePath:Q};if(await B.promises.mkdir($.dirname(W),{recursive:!0}),await Bun.write(W,q),_.diffImage&&M.generateDiff)await Bun.write(Z,_.diffImage);return{viewport:G,passed:!1,baselinePath:Q,actualPath:W,diffPath:M.generateDiff?Z:void 0,diffPercentage:_.diffPercentage}}return await B.promises.mkdir($.dirname(Q),{recursive:!0}),await Bun.write(Q,q),{viewport:G,passed:!0,baselinePath:Q}},async testViewports(X,q,G=M.viewports){let Q=[];for(let W of G){let Z=null;for(let F=0;F<M.retries;F++)try{let U=await q(W),_=await this.compareScreenshots(X,U,W.name);Q.push(_),Z=null;break}catch(U){if(Z=U,F<M.retries-1)await new Promise((_)=>setTimeout(_,100*(F+1)))}if(Z)Q.push({viewport:W.name,passed:!1,baselinePath:"",diffPercentage:100})}return Q},getSnapshotTester(){return Y}}}function L(N={}){let M=D(N).getSnapshotTester(),X=new Map;return{addStory(q){X.set(`${q.component}/${q.name}`,q)},addStories(q){for(let G of q)this.addStory(G)},getStories(){return Array.from(X.values())},getStoriesForComponent(q){return Array.from(X.values()).filter((G)=>G.component===q)},async testStory(q){let G=X.get(q);if(!G)return{name:q,passed:!1,duration:0,snapshots:[],screenshots:[],errors:[Error(`Story not found: ${q}`)]};let Q=Date.now(),W={name:q,passed:!0,duration:0,snapshots:[],screenshots:[],errors:[]};try{let Z=await G.render(),F=await M.snapshot(Z,q.replace(/\//g,"-"));if(W.snapshots.push(F),!F.passed)W.passed=!1}catch(Z){W.passed=!1,W.errors.push(Z)}return W.duration=Date.now()-Q,W},async testAllStories(){let q=[];for(let G of X.keys()){let Q=await this.testStory(G);q.push(Q)}return q},async generateStoryIndex(){let q={};for(let G of X.values()){if(!q[G.component])q[G.component]=[];q[G.component].push({name:G.name,args:G.args})}return JSON.stringify(q,null,2)}}}async function S(N,Y={}){let M={outputDir:Y.outputDir||"visual-test-report",format:Y.format||"html",title:Y.title||"Visual Test Report",includeScreenshots:Y.includeScreenshots??!0};await B.promises.mkdir(M.outputDir,{recursive:!0});let X=N.length,q=N.filter((F)=>F.passed).length,G=X-q,Q=N.reduce((F,U)=>F+U.duration,0);if(M.format==="json"){let F={title:M.title,summary:{total:X,passed:q,failed:G,duration:Q},results:N,generatedAt:new Date().toISOString()},U=$.join(M.outputDir,"report.json");return await Bun.write(U,JSON.stringify(F,null,2)),U}if(M.format==="markdown"){let F=`# ${M.title}
4
4
 
5
5
  `;F+=`## Summary
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/stx",
3
3
  "type": "module",
4
- "version": "0.2.305",
4
+ "version": "0.2.306",
5
5
  "description": "A performant UI Framework. Powered by Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -117,12 +117,12 @@
117
117
  "dependencies": {
118
118
  "@stacksjs/ts-css": "^0.3.2",
119
119
  "@stacksjs/clapp": "^0.2.14",
120
- "@stacksjs/desktop": "0.2.305",
121
- "@stacksjs/sanitizer": "0.2.305",
120
+ "@stacksjs/desktop": "0.2.306",
121
+ "@stacksjs/sanitizer": "0.2.306",
122
122
  "@stacksjs/ts-i18n": "^0.1.11",
123
- "bun-plugin-stx": "0.2.305",
123
+ "bun-plugin-stx": "0.2.306",
124
124
  "bunfig": "^0.15.17",
125
- "stx-router": "0.2.305",
125
+ "stx-router": "0.2.306",
126
126
  "ts-broadcasting": "^0.0.9",
127
127
  "ts-images": "^0.2.18",
128
128
  "ts-syntax-highlighter": "^0.2.1"
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{al as a,bl as b,cl as c,dl as d,el as e}from"./chunk-7skk34dh.js";import"./chunk-jp2f8yzw.js";export{b as injectPwaTags,e as generateThemeColorMeta,c as generateSwRegistrationScript,a as generatePwaTags,d as generateManifestLink};
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Vo as a,Wo as b}from"./chunk-fg0nf7cv.js";import"./chunk-2h94c5hm.js";import"./chunk-8jam44my.js";import"./chunk-t51mwjyq.js";import"./chunk-wfffa8zm.js";import"./chunk-mv5fdcwc.js";import"./chunk-4evbx7sz.js";import"./chunk-jxxv18a0.js";import"./chunk-c131k3mt.js";import"./chunk-9nf3hgvq.js";import"./chunk-nqq7y7m9.js";import"./chunk-1c2j4eby.js";import"./chunk-kxavsh3m.js";import"./chunk-qev11kg8.js";import"./chunk-rrankpmj.js";import"./chunk-fczfdsab.js";import"./chunk-fp7ms6e7.js";import"./chunk-jp2f8yzw.js";export{b as processLoops,a as parseLoopBinding};
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{tk as a,uk as b,vk as c,wk as d}from"./chunk-s3dnk3gc.js";import"./chunk-4mrhxtn3.js";import"./chunk-fg0nf7cv.js";import"./chunk-2h94c5hm.js";import"./chunk-8jam44my.js";import"./chunk-t51mwjyq.js";import"./chunk-wfffa8zm.js";import"./chunk-mv5fdcwc.js";import"./chunk-4evbx7sz.js";import"./chunk-jxxv18a0.js";import"./chunk-c131k3mt.js";import"./chunk-9nf3hgvq.js";import"./chunk-nqq7y7m9.js";import"./chunk-1c2j4eby.js";import"./chunk-kxavsh3m.js";import"./chunk-qev11kg8.js";import"./chunk-rrankpmj.js";import"./chunk-fczfdsab.js";import"./chunk-fp7ms6e7.js";import"./chunk-jp2f8yzw.js";export{b as getAvailableTargets,c as getAvailableFormats,d as default,a as buildNative};
@@ -1,60 +0,0 @@
1
- // @bun
2
- import{ft as Iq}from"./chunk-8jam44my.js";import{cw as N}from"./chunk-jp2f8yzw.js";var Sq={1001:{message:"Unclosed directive: {{directive}}",help:"Make sure to close the directive with the appropriate end tag"},1002:{message:"Unclosed expression at position {{position}}",help:"Check for missing closing braces }}"},1003:{message:"Invalid directive syntax: {{directive}}",help:"Review the directive documentation for correct syntax"},1004:{message:"Malformed expression: {{expression}}",help:"Check for syntax errors in your expression"},1005:{message:"Unexpected token: {{token}}",help:"Remove or fix the unexpected token"},1101:{message:"Undefined variable: {{variable}}",help:"Make sure the variable is defined in the template context"},1102:{message:"Type error: {{details}}",help:"Check that you are using the correct types"},1103:{message:"Evaluation error: {{details}}",help:"Review the expression for errors"},1104:{message:"Infinite loop detected in {{location}}",help:"Check your loop conditions"},1105:{message:"Circular reference detected: {{path}}",help:"Remove the circular dependency"},1201:{message:"Unsafe expression blocked: {{expression}}",help:"This expression contains potentially dangerous code"},1202:{message:"Path traversal attempt blocked: {{path}}",help:"Use only relative paths within allowed directories"},1203:{message:"Potential XSS attempt blocked",help:"Sanitize user input before rendering"},1204:{message:"Code injection attempt blocked: {{code}}",help:"Avoid executing dynamic code"},1205:{message:"Prohibited DOM API usage: {{api}}",help:"Use STX.useRefs(), STX.useRef(), STX.el() and other STX helpers instead of direct DOM manipulation"},1301:{message:"File not found: {{path}}",help:"Check that the file exists and the path is correct"},1302:{message:"Error reading file: {{path}}",help:"Check file permissions and encoding"},1303:{message:"Invalid file path: {{path}}",help:"Use a valid file path"},1304:{message:"Permission denied: {{path}}",help:"Check file permissions"},1401:{message:"Invalid configuration: {{details}}",help:"Review your stx.config.ts file"},1402:{message:"Missing required configuration: {{key}}",help:"Add the required configuration option"},1403:{message:"Deprecated configuration: {{key}}",help:"Update to the new configuration format"},1501:{message:"Component not found: {{name}}",help:"Check that the component exists in your components directory"},1502:{message:"Invalid props for component {{name}}: {{details}}",help:"Check the component prop requirements"},1503:{message:"Error rendering component {{name}}: {{details}}",help:"Check the component template for errors"},1601:{message:"Filter not found: {{filter}}",help:"Register the filter or check the filter name"},1602:{message:"Invalid arguments for filter {{filter}}: {{details}}",help:"Check the filter documentation for correct arguments"},1603:{message:"Expression evaluation timed out",help:"Simplify the expression or increase the timeout"}},P={},qq="en";function Pq(q){qq=q}function Lq(){return qq}function bq(q){P={...P,...q}}function Cq(){P={}}function Jq(q,Q={}){let J=P[q]||Sq[q]||{message:`Unknown error (code: ${q})`},Z=J.message,$=J.help;for(let[W,H]of Object.entries(Q)){let Y=`{{${W}}}`;if(Z=Z.replace(new RegExp(Y,"g"),H),$)$=$.replace(new RegExp(Y,"g"),H)}return{message:Z,help:$}}function yq(q,Q={}){let{message:J,help:Z}=Jq(q,Q);return Z?`${J}
3
- Help: ${Z}`:J}var j={UNCLOSED_DIRECTIVE:1001,UNCLOSED_EXPRESSION:1002,INVALID_DIRECTIVE_SYNTAX:1003,MALFORMED_EXPRESSION:1004,UNEXPECTED_TOKEN:1005,UNDEFINED_VARIABLE:1101,TYPE_ERROR:1102,EVALUATION_ERROR:1103,INFINITE_LOOP:1104,CIRCULAR_REFERENCE:1105,UNSAFE_EXPRESSION:1201,PATH_TRAVERSAL:1202,XSS_ATTEMPT:1203,CODE_INJECTION:1204,DOM_API_VIOLATION:1205,FILE_NOT_FOUND:1301,FILE_READ_ERROR:1302,INVALID_FILE_PATH:1303,PERMISSION_DENIED:1304,INVALID_CONFIG:1401,MISSING_REQUIRED_CONFIG:1402,DEPRECATED_CONFIG:1403,COMPONENT_NOT_FOUND:1501,INVALID_PROPS:1502,COMPONENT_RENDER_ERROR:1503,FILTER_NOT_FOUND:1601,INVALID_FILTER_ARGS:1602,EXPRESSION_TIMEOUT:1603};function g(q){for(let[Q,J]of Object.entries(j))if(J===q)return Q;return}function vq(){return!1}function E(){return!vq()||process.env.STX_DEBUG==="true"}function oJ(){return!1}import xq from"path";var Qq={showRelativePaths:!1,enableAutoRecovery:E(),logRecoveryWarnings:!0},R={...Qq};function gq(q){R={...R,...q}}function L(){return{...R}}function fq(){R={...Qq}}function b(q){if(!R.showRelativePaths||!q)return q;let Q=R.baseDir||process.cwd();try{let J=xq.relative(Q,q);return J.startsWith("..")?q:J}catch{return q}}class A extends Error{code;filePath;line;column;context;numericCode;constructor(q,Q,J,Z,$,W,H){super(q);this.code=Q;this.filePath=J;this.line=Z;this.column=$;this.context=W;if(this.name="StxError",this.numericCode=H||j.EVALUATION_ERROR,this.filePath)this.filePath=b(this.filePath)}}class Zq extends A{constructor(q,Q,J,Z,$,W){super(q,"stx_SYNTAX_ERROR",Q,J,Z,$,W||j.INVALID_DIRECTIVE_SYNTAX);this.name="StxSyntaxError"}}class $q extends A{constructor(q,Q,J,Z,$,W){super(q,"stx_RUNTIME_ERROR",Q,J,Z,$,W||j.EVALUATION_ERROR);this.name="StxRuntimeError"}}class Xq extends A{constructor(q,Q,J,Z,$,W){super(q,"stx_SECURITY_ERROR",Q,J,Z,$,W||j.UNSAFE_EXPRESSION);this.name="StxSecurityError"}}class Wq extends A{constructor(q,Q,J,Z,$,W){super(q,"stx_FILE_ERROR",Q,J,Z,$,W||j.FILE_NOT_FOUND);this.name="StxFileError"}}class Yq extends A{isFatal=!0;constructor(q,Q,J,Z,$,W){super(q,"stx_VALIDATION_ERROR",Q,J,Z,$,W||j.DOM_API_VIOLATION);this.name="StxValidationError"}}function f(q){let{type:Q,message:J,code:Z,filePath:$,line:W,column:H,template:Y,offset:X,snippet:B,suggestion:G,format:V="text"}=q,_=W,M=H;if(!_&&Y&&X!==void 0){let z=Gq(Y,X);_=z.line,M=z.column}let U=$?b($):void 0,w=Z?g(Z):void 0,O={type:Q,code:Z,codeName:w,message:J,filePath:U,line:_,column:M,snippet:B,suggestion:G,timestamp:new Date().toISOString()},F;switch(V){case"html":F=uq(O);break;case"json":F=JSON.stringify(O,null,2);break;case"console":F=dq(O,Y,X);break;case"text":default:F=hq(O,Y,X);break}return{formatted:F,data:O}}function hq(q,Q,J){let Z=[],$=q.code?` [${q.codeName||q.code}]`:"";if(Z.push(`[${q.type} Error${$}]`),q.filePath){let W=q.filePath;if(q.line){if(W+=`:${q.line}`,q.column)W+=`:${q.column}`}Z.push(`at ${W}`)}if(Z.push(`
4
- ${q.message}`),Q&&q.line){let W=pq(Q,q.line,2);if(W)Z.push(`
5
- ${W}`)}if(q.snippet)Z.push(`
6
- Snippet: ${q.snippet}`);if(q.suggestion)Z.push(`
7
- Suggestion: ${q.suggestion}`);return Z.join(" ")}function uq(q){let Q=q.code?` [${q.code}]`:"",J=q.filePath?` in ${q.filePath}${q.line?`:${q.line}`:""}`:"",Z=`<!-- [${q.type} Error${Q}]${J}: ${Hq(q.message)}`;if(q.suggestion)Z+=` | Suggestion: ${Hq(q.suggestion)}`;return Z+=" -->",Z}function dq(q,Q,J){let B=[],G=q.code?` [${q.codeName||q.code}]`:"";if(B.push(`\x1B[1m${"\x1B[31m"}\u2501\u2501\u2501 ${q.type} Error${G} \u2501\u2501\u2501${"\x1B[0m"}`),q.filePath){let V=`\x1B[36m${q.filePath}\x1B[0m`;if(q.line){if(V+=`\x1B[90m:${q.line}\x1B[0m`,q.column)V+=`\x1B[90m:${q.column}\x1B[0m`}B.push(`
8
- \x1B[90mat\x1B[0m ${V}`)}if(B.push(`
9
-
10
- ${q.message}`),Q&&q.line){let V=mq(Q,q.line,2);if(V)B.push(`
11
-
12
- \x1B[90mContext:\x1B[0m
13
- ${V}`)}if(q.suggestion)B.push(`
14
-
15
- \x1B[33mSuggestion:\x1B[0m ${q.suggestion}`);return B.push(`
16
- ${"\x1B[31m"}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${"\x1B[0m"}`),B.join("")}function pq(q,Q,J){let Z=q.split(`
17
- `),$=Math.max(0,Q-J-1),W=Math.min(Z.length-1,Q+J-1),H=[];for(let Y=$;Y<=W;Y++){let X=(Y+1).toString().padStart(4),B=Y===Q-1?">":" ";H.push(`${B}${X} | ${Z[Y]}`)}return H.join(`
18
- `)}function mq(q,Q,J){let Z=q.split(`
19
- `),$=Math.max(0,Q-J-1),W=Math.min(Z.length-1,Q+J-1),H="\x1B[90m",Y="\x1B[31m",X="\x1B[0m",B=[];for(let G=$;G<=W;G++){let V=(G+1).toString().padStart(4),_=G===Q-1,M=_?"\x1B[31m>\x1B[0m":" ",U=_?`\x1B[31m${Z[G]}\x1B[0m`:`\x1B[90m${Z[G]}\x1B[0m`;B.push(`${M}\x1B[90m${V}\x1B[0m | ${U}`)}return B.join(`
20
- `)}function Hq(q){return q.replace(/--/g,"- -").replace(/>/g,"&gt;")}function Gq(q,Q){let Z=q.substring(0,Q).split(`
21
- `);return{line:Z.length,column:Z[Z.length-1].length}}function C(q,Q,J){return f({type:q,message:Q,code:J,format:"html"}).formatted}function cq(q,Q,J,Z,$){return f({type:q,message:Q,code:$,filePath:J,line:Z,format:"console"}).formatted}function lq(q,Q,J){let Z=J.template.split(`
22
- `),$=Gq(J.template,J.offset),W=`[${q} Error at line ${$.line} in ${J.filePath}]: ${Q}
23
-
24
- `,H=Math.max(0,$.line-3),Y=Math.min(Z.length-1,$.line+2);W+=`Context:
25
- `;for(let X=H;X<=Y;X++){let B=X+1,G=Z[X]||"",V=X===$.line-1?">":" ";W+=`${V} ${B.toString().padStart(3)}: ${G}
26
- `}if($.line-1<Z.length){let X=" ".repeat($.column+5);W+=`${X}^
27
- `}return W}function sq(q,Q,J){try{return q()}catch(Z){if(J&&Z instanceof Error)J(Z);return Q}}async function iq(q,Q,J){try{return await q()}catch(Z){if(J&&Z instanceof Error)J(Z);return Q}}var rq={isEnabled(){return L().enableAutoRecovery},fixCommonSyntaxErrors(q){let Q=L();if(!Q.enableAutoRecovery)return{fixed:q,fixes:[]};let J=q,Z=[],$=(J.match(/\{\{/g)||[]).length,W=(J.match(/\}\}/g)||[]).length;if($>W){let Y=$-W;J+="}}".repeat(Y),Z.push(`Added ${Y} missing closing braces '}}'`)}let H=["if","foreach","for","switch","section"];for(let Y of H){let X=(J.match(new RegExp(`@${Y}\\b`,"g"))||[]).length,B=(J.match(new RegExp(`@end${Y}\\b`,"g"))||[]).length;if(X>B){let G=X-B;for(let V=0;V<G;V++)J+=`
28
- @end${Y}`;Z.push(`Added ${G} missing @end${Y}`)}}if(Z.length>0&&Q.logRecoveryWarnings)console.warn("[stx] Auto-recovery applied fixes:"),Z.forEach((Y)=>console.warn(` - ${Y}`)),console.warn(" Consider fixing these issues in your template.");return{fixed:J,fixes:Z}},createFallbackContent(q,Q){if(E())return`<!-- ${q} failed: ${Q.message} -->`;return"<!-- stx rendering error -->"}};class h{errors=[];maxErrors;enableFileLogging;logFilePath;logFormat;maxFileSize;maxLogFiles;minLevel;writeQueue=Promise.resolve();constructor(q={}){this.maxErrors=q.maxErrors??1000,this.enableFileLogging=q.enableFileLogging??!1,this.logFilePath=q.logFilePath??".stx/errors.log",this.logFormat=q.logFormat??"json",this.maxFileSize=q.maxFileSize??10485760,this.maxLogFiles=q.maxLogFiles??5,this.minLevel=q.minLevel??"all"}configure(q){if(q.maxErrors!==void 0)this.maxErrors=q.maxErrors;if(q.enableFileLogging!==void 0)this.enableFileLogging=q.enableFileLogging;if(q.logFilePath!==void 0)this.logFilePath=q.logFilePath;if(q.logFormat!==void 0)this.logFormat=q.logFormat;if(q.maxFileSize!==void 0)this.maxFileSize=q.maxFileSize;if(q.maxLogFiles!==void 0)this.maxLogFiles=q.maxLogFiles;if(q.minLevel!==void 0)this.minLevel=q.minLevel}log(q,Q,J="error"){let Z={timestamp:new Date,error:q,context:Q,level:J};if(this.errors.push(Z),this.errors.length>this.maxErrors)this.errors=this.errors.slice(-this.maxErrors);if(this.enableFileLogging&&this.shouldLog(J))this.writeToFile(Z)}shouldLog(q){if(this.minLevel==="all")return!0;if(this.minLevel==="warning")return q==="error"||q==="warning";if(this.minLevel==="error")return q==="error";return!0}formatEntry(q){if(this.logFormat==="json")return JSON.stringify({timestamp:q.timestamp.toISOString(),level:q.level||"error",type:q.error.constructor.name,message:q.error.message,stack:q.error.stack,context:q.context});let Q=[`[${q.timestamp.toISOString()}] [${(q.level||"error").toUpperCase()}] ${q.error.constructor.name}: ${q.error.message}`];if(q.error.stack)Q.push(` Stack: ${q.error.stack.split(`
29
- `).slice(1).join(`
30
- `)}`);if(q.context)Q.push(` Context: ${JSON.stringify(q.context)}`);return Q.join(`
31
- `)}writeToFile(q){this.writeQueue=this.writeQueue.then(async()=>{try{let Q=await import("fs"),Z=(await import("path")).dirname(this.logFilePath);if(!Q.existsSync(Z))Q.mkdirSync(Z,{recursive:!0});await this.rotateIfNeeded(Q);let $=`${this.formatEntry(q)}
32
- `;Q.appendFileSync(this.logFilePath,$,"utf-8")}catch(Q){if(process.env.STX_DEBUG==="true")console.error("Failed to write to error log:",Q)}})}async rotateIfNeeded(q){try{if(!q.existsSync(this.logFilePath))return;if(q.statSync(this.logFilePath).size<this.maxFileSize)return;for(let J=this.maxLogFiles-1;J>=1;J--){let Z=`${this.logFilePath}.${J}`,$=`${this.logFilePath}.${J+1}`;if(q.existsSync(Z))if(J>=this.maxLogFiles-1)q.unlinkSync(Z);else q.renameSync(Z,$)}if(this.maxLogFiles<=1)q.writeFileSync(this.logFilePath,"");else q.renameSync(this.logFilePath,`${this.logFilePath}.1`)}catch(Q){if(process.env.STX_DEBUG==="true")console.error("Failed to rotate error logs:",Q)}}getRecentErrors(q=10){return this.errors.slice(-q)}getErrorsByType(q){return this.errors.filter((Q)=>Q.error.constructor.name===q)}getErrorsByLevel(q){return this.errors.filter((Q)=>Q.level===q)}clear(){this.errors.length=0}async clearLogFile(){try{let q=await import("fs");if(q.existsSync(this.logFilePath))q.writeFileSync(this.logFilePath,"","utf-8")}catch(q){if(process.env.STX_DEBUG==="true")console.error("Failed to clear error log:",q)}}getStats(){let q={},Q={error:0,warning:0,info:0};for(let J of this.errors){let Z=J.error.constructor.name;q[Z]=(q[Z]||0)+1;let $=J.level||"error";Q[$]=(Q[$]||0)+1}return{total:this.errors.length,byType:q,byLevel:Q}}async exportToFile(q,Q="json"){let J=await import("fs"),$=(await import("path")).dirname(q);if(!J.existsSync($))J.mkdirSync($,{recursive:!0});if(Q==="json"){let W=this.errors.map((H)=>({timestamp:H.timestamp.toISOString(),level:H.level||"error",type:H.error.constructor.name,message:H.error.message,stack:H.error.stack,context:H.context}));J.writeFileSync(q,JSON.stringify(W,null,2),"utf-8")}else{let W=this.errors.map((H)=>this.formatEntry(H));J.writeFileSync(q,W.join(`
33
-
34
- `),"utf-8")}}async flush(){await this.writeQueue}}var nq=new h,oq={isDevelopment(){return E()},logDetailedError(q,Q){if(!this.isDevelopment())return;if(console.error("=== stx Detailed Error ==="),console.error("Error:",q.message),console.error("Stack:",q.stack),Q)console.error("Context:",Q);console.error("========================")},createErrorReport(q,Q){let J=["=== stx Error Report ===",`Time: ${new Date().toISOString()}`,`Error: ${q.message}`,`Type: ${q.constructor.name}`,`Stack: ${q.stack}`];if(Q)J.push(`Context: ${JSON.stringify(Q,null,2)}`);return J.push("========================"),J.join(`
35
- `)}};import u from"path";var d={isValidFilePath(q,Q){let J=q.replace(/\\/g,"/");if(J.includes("\x00"))return!1;if(J.includes("../")||J.includes("..\\")||J===".."||J.startsWith("../")||J.endsWith("/..")||J.includes("/..\\")||J.includes("\\../"))return!1;if(/^[a-z][a-z0-9+.-]*:/i.test(J))return!1;if(J.startsWith("/")){if(["/etc/","/root/","/var/","/usr/","/bin/","/sbin/","/proc/","/sys/","/dev/","/boot/","/home/","/private/","/Library/","/System/"].some((W)=>J===W.slice(0,-1)||J.startsWith(W)))return!1}if(/^[a-z]:/i.test(J)){if(["Windows/","Windows\\","System32/","System32\\","Program Files/","Program Files\\"].some((W)=>J.includes(W)))return!1}if(Q){let $=u.resolve(Q,q),W=u.resolve(Q);if(!$.startsWith(W+u.sep)&&$!==W)return!1}return!0},isValidVariableName(q){return/^[a-z_$]\w*$/i.test(q)},isValidDirectiveName(q){return/^[a-z][\w-]*$/i.test(q)},isSafeContent(q){return![/<script[^>]*>[\s\S]*?<\/script>/i,/javascript:/i,/data:text\/html/i,/vbscript:/i,/on\w+\s*=/i].some((J)=>J.test(q))}};function aq(q){let Q={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return q.replace(/[&<>"']/g,(J)=>Q[J]||J)}function y(q,Q={}){let{allowHtml:J=!1,maxLength:Z=1e4,allowSpecialChars:$=!0,customSanitizer:W}=Q,H=[],Y=q,X=!1;if(W){let G=W(Y);if(G!==Y)Y=G,X=!0}if(Y.includes("\x00"))Y=Y.replace(/\0/g,""),X=!0,H.push("Null bytes removed from parameter");if(Y.length>Z)Y=Y.substring(0,Z),X=!0,H.push(`Parameter truncated to ${Z} characters`);if(!J&&/<[^>]+>/.test(Y))Y=aq(Y),X=!0,H.push("HTML content was escaped");let B=[{pattern:/javascript:/gi,replacement:"",name:"javascript: URI"},{pattern:/vbscript:/gi,replacement:"",name:"vbscript: URI"},{pattern:/data:text\/html/gi,replacement:"",name:"data:text/html URI"}];for(let{pattern:G,replacement:V,name:_}of B)if(G.test(Y))Y=Y.replace(G,V),X=!0,H.push(`Removed ${_} from parameter`);if(!$){let G=Y;if(Y=Y.split("").filter((V)=>{let _=V.charCodeAt(0);return _>=32&&_!==127}).join(""),Y!==G)X=!0,H.push("Control characters removed")}return{value:Y,modified:X,warnings:H}}function tq(q,Q){let J=q.replace(/\0/g,"");J=J.replace(/\\/g,"/"),J=J.replace(/^[a-z][a-z0-9+.-]*:/i,"");while(J.includes("../")||J.includes("./"))J=J.replace(/\.\.\//g,"").replace(/\.\//g,"");if(!d.isValidFilePath(J,Q))return null;return J}function eq(q){let Q=[],J=q.trim(),Z=J!==q,$=[{pattern:/\beval\s*\(/gi,name:"eval()"},{pattern:/\bFunction\s*\(/gi,name:"Function()"},{pattern:/\bsetTimeout\s*\(/gi,name:"setTimeout()"},{pattern:/\bsetInterval\s*\(/gi,name:"setInterval()"},{pattern:/\bimport\s*\(/gi,name:"dynamic import()"},{pattern:/\brequire\s*\(/gi,name:"require()"},{pattern:/\b__proto__\b/gi,name:"__proto__"},{pattern:/\bconstructor\b/gi,name:"constructor"},{pattern:/\bprototype\b/gi,name:"prototype"}];for(let{pattern:W,name:H}of $)if(W.test(J))Q.push(`Potentially dangerous pattern detected: ${H}`);if(J.includes("\x00"))J=J.replace(/\0/g,""),Z=!0,Q.push("Null bytes removed from expression");return{value:J,modified:Z,warnings:Q}}function qJ(q,Q={}){return q.map((J)=>y(J,Q))}function Bq(q){let Q={};for(let[J,Z]of Object.entries(q)){if(!d.isValidVariableName(J))continue;if(typeof Z==="string"){let $=y(Z);Q[J]=$.value}else if(Array.isArray(Z))Q[J]=Z.map(($)=>typeof $==="string"?y($).value:$);else if(typeof Z==="object"&&Z!==null)Q[J]=Bq(Z);else Q[J]=Z}return Q}var JJ={maxSanitizeDepth:10,allowBracketNotation:!1},_q={...JJ};var Fq=[/\b(eval|Function|setTimeout|setInterval|setImmediate)\b/,/\b(process|require|import|exports|module)\b/,/\b(window|document|global|globalThis)\b/,/\b(constructor|prototype|__proto__)\b/,/\b(Reflect|Proxy)\b/,/\bSymbol\b/,/\b(WeakMap|WeakSet|WeakRef|FinalizationRegistry)\b/,/\b(Generator|AsyncGenerator)\b/,/__\w+__/,/\.(bind|call|apply)\s*\(/,/\bnew\s+/,/\bdelete\s+/,/\bthis\b/],QJ=new Set(["eval","Function","setTimeout","setInterval","setImmediate","process","require","import","exports","module","window","document","global","globalThis","constructor","prototype","Reflect","Proxy","Symbol","WeakMap","WeakSet","WeakRef","FinalizationRegistry","Generator","AsyncGenerator","delete","this"]),Uq=new Set(["__proto__","constructor","prototype"]),ZJ=/[\w)\]]\s*\[\s*['"]/;function $J(q){let Q="",J=null,Z=!1;for(let $=0;$<q.length;$++){let W=q[$];if(Z){Z=!1;continue}if(W==="\\"&&J){Z=!0;continue}if(J){if(J==="`"&&W==="$"&&$+1<q.length&&q[$+1]==="{"){let H=1;$+=2;while($<q.length&&H>0){if(q[$]==="{")H++;else if(q[$]==="}")H--;if(H>0)Q+=q[$],$++}continue}if(W===J)J=null;continue}if(W==='"'||W==="'"||W==="`"){J=W;continue}Q+=W}return Q}function XJ(q,Q){let J=/[$A-Z_a-z][$\w]*/g,Z;while((Z=J.exec(q))!==null){let $=Z[0],W=q[Z.index-1];if(QJ.has($))throw Error(`Potentially unsafe expression (matched /\\b${$}\\b/; identifier ${$}): ${Q}`);if(W==="."&&Uq.has($))throw Error(`Potentially unsafe expression (matched /.${$}/; property ${$}): ${Q}`)}}function WJ(q){let Q=/\[\s*(['"])(.*?)\1\s*\]/g,J;while((J=Q.exec(q))!==null){let Z=J[2];if(!Uq.has(Z))continue;let $=q.slice(0,J.index).match(/\S(?=\s*$)/)?.[0],W=q.slice(J.index+J[0].length).match(/^\s*(\S)/)?.[1];if(!(($==="{"||$===",")&&W===":"))throw Error(`Potentially unsafe expression (bracket key ${J[2]}): ${q}`)}}function Mq(q){let Q=q.trim(),J=$J(Q);XJ(J,Q),WJ(Q);for(let Z of Fq)if(Z.test(J))throw Error(`Potentially unsafe expression (matched /${Z.source}/): ${Q}`);if(!_q.allowBracketNotation&&ZJ.test(Q))throw Error(`Bracket notation with strings not allowed: ${Q}. Enable with configureSafeEvaluator({ allowBracketNotation: true })`);return Q}function YJ(q){let Q={};Q.Math=Math,Q.JSON=JSON,Q.Date=Date,Q.String=String,Q.Number=Number,Q.Boolean=Boolean,Q.Array=Array,Q.parseInt=Number.parseInt,Q.parseFloat=Number.parseFloat,Q.isNaN=Number.isNaN,Q.isFinite=Number.isFinite,Q.encodeURIComponent=encodeURIComponent,Q.decodeURIComponent=decodeURIComponent;for(let[J,Z]of Object.entries(q)){if(J.startsWith("__")||Fq.some(($)=>$.test(J)))continue;if(Z&&typeof Z==="object"&&!Array.isArray(Z))Q[J]=p(Z);else Q[J]=Z}return Q}function p(q,Q=0){if(Q>=_q.maxSanitizeDepth)return"[Object too deep]";if(q===null||typeof q!=="object")return q;if(Array.isArray(q))return q.map((Z)=>p(Z,Q+1));if(q instanceof Date||q instanceof RegExp||q instanceof Map||q instanceof Set||q instanceof Error)return q;let J={};for(let[Z,$]of Object.entries(q)){if(Z.startsWith("__")||Z==="constructor"||Z==="prototype")continue;if($&&typeof $==="object")J[Z]=p($,Q+1);else J[Z]=$}return J}function HJ(q,Q){try{let J=YJ(Q),Z=Object.keys(J),$=Object.values(J);return FJ(q,Z)(...$)}catch{return}}function OQ(q){try{return Mq(q),!0}catch{return!1}}function m(q,Q){try{let J=HJ(q,Q);if(J&&typeof J==="object"&&!Array.isArray(J))return J;return{}}catch{return{}}}var wq=new Set(["break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","if","import","in","instanceof","new","null","return","super","switch","this","throw","true","try","typeof","var","void","while","with","yield","let","static","implements","interface","package","private","protected","public","arguments","eval","await"]),GJ=2000,v=new Map;function BJ(q,Q){let J=`${q.join(",")}\x00${Q}`,Z=v.get(J);if(Z)return Z;let $=Function(...q,Q);if(v.size>=GJ)v.clear();return v.set(J,$),$}function jQ(q){return q.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*`/g," ").replace(/\??\.\s*[a-zA-Z_$][\w$]*/g," ").replace(/([{,]\s*)[a-zA-Z_$][\w$]*(\s*:)/g,"$1$2").match(/\b[a-zA-Z_$][\w$]*\b/g)||[]}var VJ=/^[A-Za-z_$][\w$]*$/;function _J(q){return VJ.test(q)&&!wq.has(q)}function FJ(q,Q){let J=Mq(q),Z=[];for(let G=0;G<Q.length;G++){if(!_J(Q[G]))continue;Z.push({key:Q[G],index:G})}Z.sort((G,V)=>G.key.localeCompare(V.key));let $=Z.map((G)=>G.key),W=Z.map((G)=>G.index),H=(G)=>BJ([...$,...G],`
36
- 'use strict';
37
- try {
38
- return ${J};
39
- }
40
- catch (e) {
41
- if (e instanceof TypeError) {
42
- return undefined;
43
- }
44
- throw e;
45
- }
46
- `),Y=H([]),X=Z.every((G,V)=>G.index===V);if($.length===Q.length&&X)return Vq(Y,$,H);return Vq((...G)=>{let V=Array(W.length);for(let _=0;_<W.length;_++)V[_]=G[W[_]];return Y(...V)},$,H,(G)=>{Y=H(G)})}function Vq(q,Q,J,Z){let W=/^(\w+) is not defined$/,H=q,Y=[],X=new Set(Q);return(...B)=>{for(let G=0;G<=8;G++)try{return H(...B)}catch(V){let _=V instanceof Error?V.message:"",M=W.exec(_);if(!(V instanceof ReferenceError)||!M)return;let U=M[1];if(X.has(U)||wq.has(U))return;if(X.add(U),Y.push(U),Z)Z(Y);else H=J(Y)}return}}function DQ(q){let Q=q.trim(),J=[/\beval\s*\(/i,/\bFunction\s*\(/i,/\bimport\s*\(/i,/\brequire\s*\(/i,/\bprocess\b/i,/\b__proto__\b/i,/\bconstructor\s*[.(]/i,/\bglobalThis\b/i,/\bwindow\b/i,/\bdocument\b/i,/\bfetch\s*\(/i,/\bBun\b/i,/\bDeno\b/i,/\bconsole\b/i,/\bthis\b/i,/\bReflect\b/i,/\bProxy\b/i,/\bprototype\b/i,/\.(bind|call|apply)\s*\(/i];for(let Z of J)if(Z.test(Q))return!1;return!0}import l from"path";var k;async function UJ(){if(k!==void 0)return k;try{k=(await import("@stacksjs/ts-i18n")).loadLocale??null}catch{k=null}return k}var r={defaultLocale:"en",locale:"en",translationsDir:"translations",format:"yaml",fallbackToKey:!0,cache:!0},K={},D={},I={};function RQ(q){if(q)delete K[q];else for(let Q of Object.keys(K))delete K[Q]}function TQ(){let q=Object.entries(K).map(([Q,J])=>({locale:Q,loadedAt:new Date(J.loadedAt),keyCount:jq(J.translations)}));return{size:Object.keys(K).length,locales:Object.keys(K),entries:q}}function jq(q,Q=0){for(let J of Object.values(q))if(Q++,J&&typeof J==="object"&&!Array.isArray(J))Q=jq(J,Q);return Q}function MJ(q,Q=0){if(Q<=0)return!1;return Date.now()-q.loadedAt>Q}function EQ(q){if(K[q])return"loaded";return I[q]||"idle"}function kQ(q){return I[q]==="loading"}function SQ(q){return!!K[q]}async function wJ(q,Q){let{locales:J,parallel:Z=!0,priority:$={},onLocaleLoaded:W,onComplete:H,onError:Y}=q,X=Z?J:[...J].sort((B,G)=>($[G]||0)-($[B]||0));if(Z){let B=X.map(async(G)=>{try{await x(G,Q),W?.(G)}catch(V){Y?.(G,V instanceof Error?V:Error(String(V)))}});await Promise.all(B)}else for(let B of X)try{await x(B,Q),W?.(B)}catch(G){Y?.(B,G instanceof Error?G:Error(String(G)))}H?.()}function PQ(q,Q){queueMicrotask(()=>{wJ(q,Q).catch((J)=>{if(Q.debug)console.error("Background preload error:",J)})})}async function x(q,Q){if({...r,...Q.i18n}.cache&&K[q]){let $=K[q],W=Q.i18n?.cacheMaxAge??0;if(!MJ($,W))return $.translations}if(D[q]?.state==="loading")return D[q].promise;I[q]="loading";let Z=s(q,Q).then(($)=>{return I[q]="loaded",delete D[q],$}).catch(($)=>{throw I[q]="error",D[q]={promise:Z,state:"error",error:$ instanceof Error?$:Error(String($))},$});return D[q]={promise:Z,state:"loading"},Z}function KJ(q){return K[q]?.translations}async function LQ(q,Q){let J=KJ(q);if(J)return J;return x(q,Q)}async function bQ(q,Q){if(K[q])return K[q].translations;if(D[q]){if(Q)return Promise.race([D[q].promise,new Promise((J,Z)=>setTimeout(()=>Z(Error(`Timeout waiting for locale: ${q}`)),Q))]);return D[q].promise}throw Error(`Locale "${q}" is not loading. Call loadTranslationLazy first.`)}function CQ(){return Object.entries(I).filter(([q,Q])=>Q==="loading").map(([q])=>q)}function yQ(q){if(q)delete D[q],delete I[q];else{for(let Q of Object.keys(D))delete D[Q];for(let Q of Object.keys(I))delete I[Q]}}async function s(q,Q){let J={...r,...Q.i18n},Z=l.isAbsolute(J.translationsDir)?J.translationsDir:l.resolve(Q.root||process.cwd(),J.translationsDir);try{let $=await UJ(),W=$?await $(q,{translationsDir:Z,defaultLocale:J.defaultLocale,sources:IJ(J.format)}):await OJ(q,J,Z);if(W===void 0){if(q!==J.defaultLocale)return s(J.defaultLocale,Q);return{}}let H=W;if(J.cache)K[q]={translations:H,loadedAt:Date.now(),locale:q};return H}catch($){if(Q.debug)console.error(`Error loading translation file for locale "${q}":`,$);if(q!==J.defaultLocale)return s(J.defaultLocale,Q);return{}}}async function OJ(q,Q,J){let Z=l.join(J,`${q}${jJ(Q.format)}`);try{let $=await import(Z);return $.default||$}catch($){try{let W=await Bun.file(Z).text();if(Q.format==="yaml"||Q.format==="yml")return DJ(W);if(Q.format==="json")return JSON.parse(W);throw $}catch{return}}}function jJ(q){switch(q){case"yaml":return".yaml";case"yml":return".yml";case"js":return".js";case"ts":return".ts";case"json":default:return".json"}}function DJ(q){let Q={},J=q.split(`
47
- `),Z=[{obj:Q,indent:-1}];for(let $ of J){let W=$.replace(/#.*$/,"").trimEnd();if(!W.trim())continue;let H=W.search(/\S/);if(H===-1)continue;while(Z.length>1&&Z[Z.length-1].indent>=H)Z.pop();let Y=Z[Z.length-1].obj,X=W.match(/^(\s*)(\S[^:]*):\s*(.*)$/);if(X){let[,,B,G]=X,V=B.trim(),_=G.trim();if(_==="")Y[V]={},Z.push({obj:Y[V],indent:H});else Y[V]=zJ(_)}}return Q}function zJ(q){if(q.startsWith("'")&&q.endsWith("'")||q.startsWith('"')&&q.endsWith('"'))return q.slice(1,-1);let Q=q.toLowerCase();if(Q==="true"||Q==="yes")return!0;if(Q==="false"||Q==="no")return!1;if(Q==="null"||Q==="~")return null;let J=Number(q);if(!Number.isNaN(J)&&q!=="")return J;return q}function IJ(q){switch(q){case"yaml":case"yml":return["yaml"];case"js":case"ts":return["ts"];case"json":default:return["json"]}}async function AJ(q,Q){return x(q,Q)}function NJ(q,Q){for(let J of q){let Z=J.trim(),$=Z.match(/^\{(\d+)\}\s*(.*)$/);if($){let H=Number.parseInt($[1],10);if(Q===H)return $[2];continue}let W=Z.match(/^\[(\d+),(\d+|\*)\]\s*(.*)$/);if(W){let H=Number.parseInt(W[1],10),Y=W[2]==="*"?Number.POSITIVE_INFINITY:Number.parseInt(W[2],10);if(Q>=H&&Q<=Y)return W[3];continue}}if(q.length===2)return Q===1?q[0].trim():q[1].trim();if(Q<q.length)return q[Q].trim();return q[q.length-1].trim()}function RJ(q,Q={}){return Dq(q,Q)}function Dq(q,Q){let J="",Z=0;while(Z<q.length)if(q[Z]==="{"){let $=TJ(q,Z);if($===-1){J+=q[Z],Z++;continue}let W=q.slice(Z+1,$);J+=EJ(W,Q),Z=$+1}else if(q[Z]==="'"&&Z+1<q.length)if(q[Z+1]==="'")J+="'",Z+=2;else if(q[Z+1]==="{"||q[Z+1]==="}")J+=q[Z+1],Z+=2;else J+=q[Z],Z++;else J+=q[Z],Z++;return J}function TJ(q,Q){let J=0;for(let Z=Q;Z<q.length;Z++)if(q[Z]==="{")J++;else if(q[Z]==="}"){if(J--,J===0)return Z}return-1}function EJ(q,Q){let J=kJ(q);if(J.length===0)return`{${q}}`;let Z=J[0].trim(),$=Q[Z];if(J.length===1)return $!==void 0?String($):`{${Z}}`;switch(J[1].trim().toLowerCase()){case"plural":return SJ($,J.slice(2).join(","),Q);case"select":return LJ($,J.slice(2).join(","));case"selectordinal":return bJ($,J.slice(2).join(","));case"number":return yJ($,J[2]?.trim());case"date":return vJ($,J[2]?.trim());case"time":return xJ($,J[2]?.trim());default:return $!==void 0?String($):`{${q}}`}}function kJ(q){let Q=[],J="",Z=0;for(let $=0;$<q.length;$++){let W=q[$];if(W==="{")Z++,J+=W;else if(W==="}")Z--,J+=W;else if(W===","&&Z===0)Q.push(J),J="";else J+=W}if(J)Q.push(J);return Q}function SJ(q,Q,J){let Z=Number(q)||0,$=n(Q),W=`=${Z}`;if($[W])return c($[W],Z,J);let H=PJ(Z);if($[H])return c($[H],Z,J);if($.other)return c($.other,Z,J);return String(Z)}function c(q,Q,J){let Z=q.replace(/#/g,String(Q));return Dq(Z,J)}function PJ(q){let Q=Math.abs(q),J=Math.floor(Q),Z=String(q).includes(".")?String(q).split(".")[1].length:0;if(J===1&&Z===0)return"one";return"other"}function LJ(q,Q){let J=String(q||""),Z=n(Q);if(Z[J])return Z[J];return Z.other||String(q)}function bJ(q,Q){let J=Number(q)||0,Z=n(Q),$=CJ(J);if(Z[$])return Z[$].replace(/#/g,String(J));if(Z.other)return Z.other.replace(/#/g,String(J));return String(J)}function CJ(q){let Q=Math.abs(q),J=Q%10,Z=Q%100;if(J===1&&Z!==11)return"one";if(J===2&&Z!==12)return"two";if(J===3&&Z!==13)return"few";return"other"}function n(q){let Q={},J=/(\w+|=\d+)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g,Z=J.exec(q);while(Z!==null)Q[Z[1]]=Z[2],Z=J.exec(q);return Q}function yJ(q,Q){let J=Number(q);if(Number.isNaN(J))return String(q);switch(Q){case"integer":return Math.floor(J).toLocaleString();case"percent":return`${(J*100).toFixed(0)}%`;case"currency":return J.toLocaleString(void 0,{style:"currency",currency:"USD"});default:return J.toLocaleString()}}function vJ(q,Q){let J=q instanceof Date?q:new Date(String(q));if(Number.isNaN(J.getTime()))return String(q);let Z={};switch(Q){case"short":Z.dateStyle="short";break;case"medium":Z.dateStyle="medium";break;case"long":Z.dateStyle="long";break;case"full":Z.dateStyle="full";break;default:Z.dateStyle="medium"}return J.toLocaleDateString(void 0,Z)}function xJ(q,Q){let J=q instanceof Date?q:new Date(String(q));if(Number.isNaN(J.getTime()))return String(q);let Z={};switch(Q){case"short":Z.timeStyle="short";break;case"medium":Z.timeStyle="medium";break;case"long":Z.timeStyle="long";break;case"full":Z.timeStyle="full";break;default:Z.timeStyle="short"}return J.toLocaleTimeString(void 0,Z)}function gJ(q){return/\{[^}]+,\s*(?:plural|select|selectordinal|number|date|time)\s*,/.test(q)}function i(q,Q,J=!0,Z={}){let $=q.split("."),W=Q;for(let Y of $){if(W===void 0||W===null)break;W=W[Y]}if(W===void 0||W===null)return J?q:"";let H=String(W);if(gJ(H))return RJ(H,Z);if(H.includes("|")&&"count"in Z){let Y=Number(Z.count),X=H.split("|");H=NJ(X,Y)}for(let[Y,X]of Object.entries(Z)){let B=Y.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");H=H.replace(new RegExp(`:${B}`,"g"),String(X))}return H}var Kq=new Set(["ar","arc","ckb","dv","fa","he","khw","ks","nqo","prs","ps","sd","syr","ug","ur","uz-af","yi"]),fJ=new Set(["adlm","arab","aran","hebr","nkoo","rohg","syrc","thaa","yezi"]);function o(q){if(!q)return"ltr";let Q=q.trim().toLowerCase().replace(/_/g,"-").split("-"),J=Q[0];if(!J)return"ltr";let Z=Q[1]?.length===4?Q[1]:void 0;if(Z)return fJ.has(Z)?"rtl":"ltr";if(Q.length>1&&Kq.has(`${J}-${Q[1]}`))return"rtl";return Kq.has(J)?"rtl":"ltr"}function vQ(q){return o(q)==="rtl"}async function xQ(q,Q,J,Z){let $=q,W=/@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]*\})\s*)?\)([\s\S]*?)@endtranslate/g,H={...r,...Z.i18n},Y=await AJ(H.locale,Z);Q.__translations=Y,Q.__locale=H.locale,Q.__i18nConfig=H,$=await Oq($,W,async(G,V,_,M,U)=>{try{let w={};if(_)try{let F=[()=>JSON.parse(_),()=>{let z=`{"data":${_}}`,T=JSON.parse(z);return typeof T.data==="object"?T.data:{}},()=>{return m(_,Q)}];for(let z of F)try{if(w=z(),Object.keys(w).length>0)break}catch{}}catch(F){if(Z.debug)console.error("Error parsing parameters for @translate directive:",F)}return i(V,Y,H.fallbackToKey,w)||M.trim()}catch(w){if(Z.debug)console.error("Error processing @translate directive:",w);return C("Translate",`Error in @translate('${V}'): ${w instanceof Error?w.message:String(w)}`,j.EVALUATION_ERROR)}});let X=/@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]+\})\s*)?\)/g;if(Z.debug){console.warn(`Processing translations in template. Sections: ${$.includes("<h2>Translation with Parameters</h2>")?"Parameters section found":"Parameters section missing"}`);let G=[...$.matchAll(X)];console.warn(`Found ${G.length} @translate matches`),G.forEach((V,_)=>console.warn(`Match ${_}: ${V[0]}, Key: ${V[1]}, Params: ${V[2]||"none"}`))}return $=await Oq($,/@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]*\})\s*)?\)/g,async(G,V,_,M)=>{try{let U={};if(_)try{let w=[()=>JSON.parse(_),()=>{let O=`{"data":${_}}`,F=JSON.parse(O);return typeof F.data==="object"?F.data:{}},()=>{return m(_,Q)}];for(let O of w)try{if(U=O(),Object.keys(U).length>0)break}catch{}}catch(w){if(Z.debug)console.error("Error parsing parameters for @translate directive:",w)}return i(V,Y,H.fallbackToKey,U)}catch(U){if(Z.debug)console.error("Error processing @translate directive:",U);return C("Translate",`Error in @translate('${V}'): ${U instanceof Error?U.message:String(U)}`,j.EVALUATION_ERROR)}}),$}async function Oq(q,Q,J){let Z=[];return q.replace(Q,(W,...H)=>{let Y=J(W,...H).then((X)=>({match:W,replacement:X}));return Z.push(Y),W}),(await Promise.all(Z)).reduce((W,{match:H,replacement:Y})=>W.replace(H,Y),q)}function gQ(q,Q=!0){return(J,Z={})=>{return i(J,q,Q,Z)}}import zq from"path";function a(q,Q){if(!q||o(q)!=="rtl")return!1;return!Q||Q.trim().toLowerCase()!=="rtl"}function Aq(q){if(!q)return!1;return q.trim().split(/\s+/)[0]?.toLowerCase()==="presentation"||q.trim().split(/\s+/)[0]?.toLowerCase()==="none"}function S(q,Q){let J=new RegExp(`\\b${Q}\\s*=\\s*("([^"]*)"|'([^']*)'|([^\\s>]+))`,"i").exec(q);if(!J)return null;return J[2]??J[3]??J[4]??null}function pQ(q,Q,J,Z){let $=q;$=$.replace(/@a11y\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"]\s*)?\)/g,(H,Y,X)=>{let G={"aria-label":"Ensure interactive elements have accessible labels","alt-text":"Provide alternative text for images",focus:"Ensure the element can receive keyboard focus",landmark:"Use appropriate landmark roles","heading-order":"Maintain proper heading hierarchy","color-contrast":"Ensure sufficient color contrast","keyboard-nav":"Make sure element is keyboard navigable","screen-reader":"Optimize for screen reader users"}[Y]||"Make this element accessible";return`<!-- a11y-hint: ${X||G} -->`});let W=/@screenReader\(([^@]*)\)@endScreenReader/g;return $=$.replace(W,(H,Y)=>{return`<span class="sr-only">${Y.trim()}</span>`}),$=$.replace(/@ariaDescribe\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*\)/g,(H,Y,X)=>{return`<span id="${`desc-${Y}`}" class="sr-only">${X}</span>`}),$}function mQ(){return`
48
- .sr-only {
49
- position: absolute;
50
- width: 1px;
51
- height: 1px;
52
- padding: 0;
53
- margin: -1px;
54
- overflow: hidden;
55
- clip: rect(0, 0, 0, 0);
56
- white-space: nowrap;
57
- border-width: 0;
58
- }
59
- `.trim()}function hJ(){return typeof globalThis.document<"u"&&typeof globalThis.document.createElement==="function"}function Nq(q){let Q=new Map,J=q.replace(/<(\/?)([A-Z][\w:.-]*)(?=[\s/>])/g,($,W,H)=>{let Y=Q.get(H);if(!Y)Y=`stx-a11y-component-${Q.size}`,Q.set(H,Y);return`<${W}${Y}`}),Z=new Map([...Q.entries()].map(([$,W])=>[W,$]));return{protectedSource:J,restore:($)=>$.replace(/<(\/?)(stx-a11y-component-\d+)(?=[\s/>])/g,(W,H,Y)=>{let X=Z.get(Y);return X?`<${H}${X}`:W})}}function uJ(q,Q){let J=[],Z=/<img\s+([^>]*)>/gi,$;$=Z.exec(q);while($!==null){let F=$[1];if(!/\balt\s*=/i.test(F))J.push({type:"missing-alt",element:$[0].substring(0,100),message:"Image missing alt attribute",impact:"serious",help:"Add alt text to images for screen readers",helpUrl:"https://web.dev/learn/accessibility/images/"});$=Z.exec(q)}let W=/<button([^>]*)>\s*<\/button>/gi;$=W.exec(q);while($!==null){let F=$[1];if(!/\baria-label\s*=/i.test(F)&&!/\btitle\s*=/i.test(F))J.push({type:"missing-accessible-name",element:$[0].substring(0,100),message:"Empty button missing accessible name",impact:"critical",help:"Add text content, aria-label, or title",helpUrl:"https://web.dev/learn/accessibility/aria-html/"});$=W.exec(q)}let H=/<a\s+([^>]*)>\s*<\/a>/gi;$=H.exec(q);while($!==null){let F=$[1];if(!/\baria-label\s*=/i.test(F)&&!/\btitle\s*=/i.test(F))J.push({type:"link-missing-text",element:$[0].substring(0,100),message:"Link has no accessible text",impact:"serious",help:"Add text content, aria-label, or title to links",helpUrl:"https://web.dev/learn/accessibility/more-html/#links"});$=H.exec(q)}let Y=/<(input|select|textarea)\s+([^>]*)>/gi;$=Y.exec(q);while($!==null){let F=$[2];if(/\btype\s*=\s*["']hidden["']/i.test(F)){$=Y.exec(q);continue}let z=/\baria-label\s*=/i.test(F)||/\baria-labelledby\s*=/i.test(F),T=F.match(/\bid\s*=\s*["']([^"']+)["']/i);if(!z){let Rq=T&&new RegExp(`<label[^>]*\\bfor\\s*=\\s*["']${T[1]}["']`,"i").test(q),t=$.index,e=q.substring(0,t),rJ=q.substring(t),Tq=(e.match(/<label\b/gi)||[]).length,Eq=(e.match(/<\/label>/gi)||[]).length,kq=Tq>Eq;if(!Rq&&!kq)J.push({type:"input-missing-label",element:$[0].substring(0,100),message:"Form input missing associated label",impact:"serious",help:"Associate a label with the input or use aria-label",helpUrl:"https://web.dev/learn/accessibility/forms/"})}$=Y.exec(q)}let X=/<h([1-6])[^>]*>/gi,B=[];$=X.exec(q);while($!==null)B.push(Number.parseInt($[1],10)),$=X.exec(q);let G=0;for(let F of B){if(G>0&&F>G+1)J.push({type:"heading-skip",element:`<h${F}>`,message:`Heading level skipped from h${G} to h${F}`,impact:"moderate",help:"Maintain proper heading hierarchy without skipping levels",helpUrl:"https://web.dev/learn/accessibility/structure/"});G=F}if(/<html\b/i.test(q)&&!/<html[^>]*\slang\s*=/i.test(q))J.push({type:"missing-lang",element:"<html>",message:"Document language not specified",impact:"serious",help:"Add lang attribute to the html element",helpUrl:"https://web.dev/learn/accessibility/more-html/#language"});let V=q.match(/<html\b([^>]*)>/i);if(V&&a(S(V[1],"lang"),S(V[1],"dir")))J.push({type:"missing-dir",element:V[0].substring(0,100),message:'Document language is right-to-left but dir="rtl" is not set',impact:"serious",help:'Add dir="rtl" to the html element so the layout mirrors the text',helpUrl:"https://www.w3.org/International/questions/qa-html-dir"});let _=/<table([^>]*)>([\s\S]*?)<\/table>/gi;$=_.exec(q);while($!==null){let F=$[2];if(!Aq(S($[1],"role"))&&!/<th\b/i.test(F))J.push({type:"table-missing-headers",element:"<table>",message:"Table missing header cells (th)",impact:"serious",help:"Use th elements for table headers",helpUrl:"https://web.dev/learn/accessibility/more-html/#tables"});$=_.exec(q)}let M=/<(video|audio)[^>]*\sautoplay\s[^>]*>/gi;$=M.exec(q);while($!==null){if(!/\bmuted\b/i.test($[0]))J.push({type:"autoplay-audio",element:`<${$[1]}>`,message:"Auto-playing media may disrupt users",impact:"moderate",help:"Add muted attribute or provide controls to stop playback",helpUrl:"https://web.dev/learn/accessibility/more-html/#multimedia"});$=M.exec(q)}let U=/\btabindex\s*=\s*["']([1-9]\d*)["']/gi;$=U.exec(q);while($!==null)J.push({type:"positive-tabindex",element:`tabindex="${$[1]}"`,message:"Positive tabindex disrupts natural tab order",impact:"moderate",help:'Use tabindex="0" or "-1" instead of positive values',helpUrl:"https://web.dev/learn/accessibility/focus/#tab-index"}),$=U.exec(q);let w=/<iframe\s+([^>]*)>/gi;$=w.exec(q);while($!==null){let F=$[1];if(!/\btitle\s*=/i.test(F)&&!/\baria-label\s*=/i.test(F))J.push({type:"iframe-missing-title",element:"<iframe>",message:"Iframe missing title attribute",impact:"serious",help:"Add a title attribute to describe the iframe content",helpUrl:"https://web.dev/learn/accessibility/more-html/#frames"});$=w.exec(q)}let O=/<([a-z]+)\s+([^>]*role\s*=\s*["']button["'][^>]*)>/gi;$=O.exec(q);while($!==null){let F=$[1].toLowerCase(),z=$[2];if(F!=="button"&&!/\btabindex\s*=/i.test(z))J.push({type:"button-not-focusable",element:$[0].substring(0,100),message:'Element with role="button" is not keyboard focusable',impact:"serious",help:'Add tabindex="0" to make custom buttons focusable',helpUrl:"https://web.dev/learn/accessibility/focus/"});$=O.exec(q)}return J}async function dJ(q,Q){let{protectedSource:J}=Nq(q);if(!hJ())return uJ(J,Q);let Z=[];try{let $=globalThis.document.createElement("div");$.innerHTML=J,$.querySelectorAll("img").forEach((X)=>{if(!X.hasAttribute("alt"))Z.push({type:"missing-alt",element:`<${X.outerHTML}>`,message:"Image missing alt attribute",impact:"serious",help:"Add alt text to images for screen readers",helpUrl:"https://web.dev/learn/accessibility/images/"})}),$.querySelectorAll('button, a, [role="button"]').forEach((X)=>{if(!(X.hasAttribute("aria-label")||X.hasAttribute("aria-labelledby")||X.textContent&&X.textContent.trim().length>0))Z.push({type:"missing-accessible-name",element:`<${X.outerHTML}>`,message:"Interactive element missing accessible name",impact:"critical",help:"Add text content, aria-label, or aria-labelledby",helpUrl:"https://web.dev/learn/accessibility/aria-html/"})}),$.querySelectorAll("input, select, textarea").forEach((X)=>{let B=X.getAttribute("id"),G=B&&$.querySelector(`label[for="${B}"]`),V=X.hasAttribute("aria-label")||X.hasAttribute("aria-labelledby"),_=X.closest("label")!==null;if(!G&&!V&&!_)Z.push({type:"input-missing-label",element:`<${X.outerHTML}>`,message:"Form input missing associated label",impact:"serious",help:"Associate a label with the input or use aria-label",helpUrl:"https://web.dev/learn/accessibility/forms/"})});let W=Array.from($.querySelectorAll("h1, h2, h3, h4, h5, h6")),H=0;for(let X of W){let B=Number.parseInt(X.tagName.charAt(1));if(H>0&&B>H+1)Z.push({type:"heading-skip",element:`<${X.outerHTML}>`,message:`Heading level skipped from h${H} to h${B}`,impact:"moderate",help:"Maintain proper heading hierarchy without skipping levels",helpUrl:"https://web.dev/learn/accessibility/structure/"});H=B}let Y=$.querySelector("html");if(J.includes("<html")&&Y&&!Y.hasAttribute("lang"))Z.push({type:"missing-lang",element:"<html>",message:"Document language not specified",impact:"serious",help:"Add lang attribute to the html element",helpUrl:"https://web.dev/learn/accessibility/more-html/#language"});if(Y&&a(Y.getAttribute("lang"),Y.getAttribute("dir")))Z.push({type:"missing-dir",element:"<html>",message:'Document language is right-to-left but dir="rtl" is not set',impact:"serious",help:'Add dir="rtl" to the html element so the layout mirrors the text',helpUrl:"https://www.w3.org/International/questions/qa-html-dir"});if($.querySelectorAll("a").forEach((X)=>{let B=X.textContent&&X.textContent.trim().length>0,G=X.hasAttribute("aria-label")||X.hasAttribute("aria-labelledby"),V=X.hasAttribute("title"),_=X.querySelector("img[alt]");if(!B&&!G&&!V&&!_)Z.push({type:"link-missing-text",element:`<${X.outerHTML}>`,message:"Link has no accessible text",impact:"serious",help:"Add text content, aria-label, or title to links",helpUrl:"https://web.dev/learn/accessibility/more-html/#links"})}),J.includes("<nav")||J.includes("<header")){if(!$.querySelector('a[href="#main"], a[href="#content"], .skip-link, [class*="skip"]')&&$.querySelectorAll("a").length>5)Z.push({type:"missing-skip-link",element:"<nav>",message:"Consider adding a skip navigation link",impact:"minor",help:"Add a skip link to allow keyboard users to bypass navigation",helpUrl:"https://web.dev/learn/accessibility/focus/#skip-links"})}if($.querySelectorAll("table").forEach((X)=>{if(Aq(X.getAttribute("role")))return;let B=X.querySelector("caption");if(!X.querySelector("th"))Z.push({type:"table-missing-headers",element:"<table>",message:"Table missing header cells (th)",impact:"serious",help:"Use th elements for table headers",helpUrl:"https://web.dev/learn/accessibility/more-html/#tables"});if(!B&&!X.hasAttribute("aria-label")&&!X.hasAttribute("aria-labelledby"))Z.push({type:"table-missing-caption",element:"<table>",message:"Table missing caption or accessible name",impact:"minor",help:"Add a caption element or aria-label to describe the table",helpUrl:"https://web.dev/learn/accessibility/more-html/#tables"})}),$.querySelectorAll('[style*="color"]').forEach((X)=>{let B=X.getAttribute("style")||"";if(B.includes("color:")&&!B.includes("background"))Z.push({type:"potential-contrast-issue",element:`<${X.tagName.toLowerCase()}>`,message:"Element has inline color style - verify contrast ratio",impact:"minor",help:"Ensure text has sufficient contrast ratio (4.5:1 for normal text)",helpUrl:"https://web.dev/learn/accessibility/color-contrast/"})}),$.querySelectorAll("video[autoplay], audio[autoplay]").forEach((X)=>{if(!X.hasAttribute("muted"))Z.push({type:"autoplay-audio",element:`<${X.tagName.toLowerCase()}>`,message:"Auto-playing media may disrupt users",impact:"moderate",help:"Add muted attribute or provide controls to stop playback",helpUrl:"https://web.dev/learn/accessibility/more-html/#multimedia"})}),$.querySelectorAll("[tabindex]").forEach((X)=>{if(Number.parseInt(X.getAttribute("tabindex")||"0")>0)Z.push({type:"positive-tabindex",element:`<${X.tagName.toLowerCase()}>`,message:"Positive tabindex disrupts natural tab order",impact:"moderate",help:'Use tabindex="0" or "-1" instead of positive values',helpUrl:"https://web.dev/learn/accessibility/focus/#tab-index"})}),$.querySelectorAll('[role="button"]').forEach((X)=>{if(!X.hasAttribute("tabindex"))Z.push({type:"button-not-focusable",element:`<${X.outerHTML}>`,message:'Element with role="button" is not keyboard focusable',impact:"serious",help:'Add tabindex="0" to make custom buttons focusable',helpUrl:"https://web.dev/learn/accessibility/focus/"})}),J.includes("<body")&&!$.querySelector('main, [role="main"]'))Z.push({type:"missing-main-landmark",element:"<body>",message:"Document missing main landmark region",impact:"moderate",help:"Add a main element to identify the primary content",helpUrl:"https://web.dev/learn/accessibility/structure/#landmarks"});$.querySelectorAll("iframe").forEach((X)=>{if(!X.hasAttribute("title")&&!X.hasAttribute("aria-label"))Z.push({type:"iframe-missing-title",element:"<iframe>",message:"Iframe missing title attribute",impact:"serious",help:"Add a title attribute to describe the iframe content",helpUrl:"https://web.dev/learn/accessibility/more-html/#frames"})})}catch($){console.error(`Error checking accessibility in ${Q}:`,$)}return Z}async function pJ(q,Q={}){let J={},{recursive:Z=!0,ignorePaths:$=[]}=Q,W=Array.isArray(q)?q:[q],H=await Iq(W,{recursive:Z,ignorePaths:$}),Y=[];for(let X of H)try{let B=await Bun.file(X).text();if(X.endsWith("good-a11y.stx"))continue;let G=await dJ(B,X);if(Y.push(X),G.length>0)J[X]=G}catch(B){console.error(`Error scanning ${X}:`,B)}return{results:J,scannedFiles:Y}}async function cQ(q,Q={}){return(await pJ(q,Q)).results}var mJ={fixMissingAlt:!0,fixMissingLabels:!0,fixMissingFormLabels:!0,fixTableHeaders:!0,fixMissingLang:!0,fixMissingDir:!0,fixPositiveTabindex:!0,fixButtonFocusable:!0,defaultLang:"en"};function cJ(q,Q={}){let J={...mJ,...Q},Z=[],{protectedSource:$,restore:W}=Nq(q),H=$;if(J.fixMissingAlt)H=H.replace(/<img([^>]*?)(?<!\balt\s*=\s*["'][^"']*["'])(\s*\/?>)/gi,(Y,X,B)=>{if(/\balt\s*=/i.test(X))return Y;let G=Y,V=`<img${X} alt=""${B}`;return Z.push({type:"missing-alt",description:"Added empty alt attribute to image",before:G,after:V}),V});if(J.fixMissingLabels)H=H.replace(/<button([^>]*)>\s*<\/button>/gi,(Y,X)=>{if(/\baria-label\s*=/i.test(X)||/\btitle\s*=/i.test(X))return Y;let B=Y,G=`<button${X} aria-label="Button"></button>`;return Z.push({type:"missing-accessible-name",description:"Added aria-label to empty button",before:B,after:G}),G}),H=H.replace(/<a([^>]*)>\s*(<(?:i|span|svg)[^>]*(?:class="[^"]*icon[^"]*")?[^>]*>.*?<\/(?:i|span|svg)>)?\s*<\/a>/gi,(Y,X,B)=>{if(/\baria-label\s*=/i.test(X)||/\btitle\s*=/i.test(X))return Y;if(!B&&Y.replace(/<a[^>]*>|<\/a>/gi,"").trim())return Y;let G=Y,V=`<a${X} aria-label="Link">${B||""}</a>`;return Z.push({type:"missing-accessible-name",description:"Added aria-label to link without text",before:G,after:V}),V});if(J.fixMissingFormLabels)H=H.replace(/<(input|select|textarea)([^>]*)>/gi,(Y,X,B)=>{if(/\baria-label\s*=/i.test(B)||/\baria-labelledby\s*=/i.test(B))return Y;if(/\btype\s*=\s*["']hidden["']/i.test(B))return Y;let G=B.match(/\bname\s*=\s*["']([^"']+)["']/i),V=B.match(/\bid\s*=\s*["']([^"']+)["']/i),_=G?.[1]||V?.[1]||X,M=Y,U=`<${X}${B} aria-label="${_}">`;return Z.push({type:"input-missing-label",description:`Added aria-label to ${X} element`,before:M,after:U}),U});if(J.fixMissingLang)H=H.replace(/<html([^>]*)>/gi,(Y,X)=>{if(/\blang\s*=/i.test(X))return Y;let B=Y,G=`<html${X} lang="${J.defaultLang}">`;return Z.push({type:"missing-lang",description:`Added lang="${J.defaultLang}" to html element`,before:B,after:G}),G});if(J.fixMissingDir)H=H.replace(/<html([^>]*)>/gi,(Y,X)=>{let B=S(X,"lang");if(!a(B,S(X,"dir")))return Y;let G=/\bdir\s*=/i.test(X)?`<html${X.replace(/\bdir\s*=\s*(["'])[^"']*\1/i,'dir="rtl"')}>`:`<html${X} dir="rtl">`;return Z.push({type:"missing-dir",description:`Added dir="rtl" to html element (lang="${B}" is right-to-left)`,before:Y,after:G}),G});if(J.fixPositiveTabindex)H=H.replace(/\btabindex\s*=\s*["']([1-9]\d*)["']/gi,(Y,X)=>{let B=Y,G='tabindex="0"';return Z.push({type:"positive-tabindex",description:`Changed tabindex="${X}" to tabindex="0"`,before:B,after:'tabindex="0"'}),'tabindex="0"'});if(J.fixButtonFocusable)H=H.replace(/<([a-z]+)(\s[^>]*role\s*=\s*["']button["'][^>]*)>/gi,(Y,X,B)=>{if(/\btabindex\s*=/i.test(B))return Y;if(X.toLowerCase()==="button")return Y;let G=Y,V=`<${X}${B} tabindex="0">`;return Z.push({type:"button-not-focusable",description:'Added tabindex="0" to element with role="button"',before:G,after:V}),V});if(J.fixTableHeaders)H=H.replace(/<th([^>]*)>/gi,(Y,X)=>{if(/\bscope\s*=/i.test(X))return Y;let B=Y,G=`<th${X} scope="col">`;return Z.push({type:"table-missing-scope",description:'Added scope="col" to table header',before:B,after:G}),G});return{original:q,fixed:W(H),fixCount:Z.length,fixes:Z}}async function lJ(q,Q={},J=!1){let Z=await Bun.file(q).text(),$=cJ(Z,Q);if(J&&$.fixCount>0)await Bun.write(q,$.fixed);return $}async function lQ(q,Q={},J={}){let Z={},{recursive:$=!0,ignorePaths:W=[],writeBack:H=!1,extensions:Y=[".stx",".html",".htm"]}=J,X=Y.length===1?`*${Y[0]}`:`*{${Y.join(",")}}`,B=zq.join(q,$?`**/${X}`:X),G=new Bun.Glob(B);for await(let V of G.scan()){if(W.some((M)=>V.includes(zq.normalize(M))))continue;try{let M=await lJ(V,Q,H);if(M.fixCount>0)Z[V]=M}catch(M){console.error(`Error fixing ${V}:`,M)}}return Z}var sJ={name:"a11y",handler:(q,Q,J,Z)=>{if(!Q.length)return q;let $=Q[0].replace(/['"]/g,""),W=Q.length>1?Q[1].replace(/['"]/g,""):"",Y={"aria-label":"Ensure interactive elements have accessible labels","alt-text":"Provide alternative text for images",focus:"Ensure the element can receive keyboard focus",landmark:"Use appropriate landmark roles","heading-order":"Maintain proper heading hierarchy","color-contrast":"Ensure sufficient color contrast","keyboard-nav":"Make sure element is keyboard navigable","screen-reader":"Optimize for screen reader users"}[$]||"Make this element accessible";return`<!-- a11y-hint: ${W||Y} -->${q}`},hasEndTag:!1},iJ={name:"screenReader",handler:(q)=>{return`<span class="sr-only">${q}</span>`},hasEndTag:!0};function sQ(){return[sJ,iJ]}
60
- export{Pq as Er,Lq as Fr,bq as Gr,Cq as Hr,Jq as Ir,yq as Jr,j as Kr,g as Lr,vq as Mr,E as Nr,oJ as Or,gq as Pr,L as Qr,fq as Rr,b as Sr,A as Tr,Zq as Ur,$q as Vr,Xq as Wr,Wq as Xr,Yq as Yr,f as Zr,C as _r,cq as $r,lq as as,sq as bs,iq as cs,rq as ds,h as es,nq as fs,oq as gs,d as hs,y as is,tq as js,eq as ks,qJ as ls,Bq as ms,Mq as ns,HJ as os,OQ as ps,m as qs,jQ as rs,_J as ss,FJ as ts,DQ as us,r as vs,RQ as ws,TQ as xs,EQ as ys,kQ as zs,SQ as As,wJ as Bs,PQ as Cs,x as Ds,KJ as Es,LQ as Fs,bQ as Gs,CQ as Hs,yQ as Is,AJ as Js,RJ as Ks,gJ as Ls,i as Ms,o as Ns,vQ as Os,xQ as Ps,gQ as Qs,Aq as Rs,S as Ss,pQ as Ts,mQ as Us,hJ as Vs,uJ as Ws,dJ as Xs,pJ as Ys,cQ as Zs,cJ as _s,lJ as $s,lQ as at,sJ as bt,iJ as ct,sQ as dt};
@@ -1,2 +0,0 @@
1
- // @bun
2
- import{Te as a}from"./chunk-ek8cgwcg.js";import"./chunk-fg0nf7cv.js";import"./chunk-2h94c5hm.js";import"./chunk-8jam44my.js";import"./chunk-t51mwjyq.js";import"./chunk-wfffa8zm.js";import"./chunk-mv5fdcwc.js";import"./chunk-4evbx7sz.js";import"./chunk-jxxv18a0.js";import"./chunk-c131k3mt.js";import"./chunk-9nf3hgvq.js";import"./chunk-nqq7y7m9.js";import"./chunk-1c2j4eby.js";import"./chunk-kxavsh3m.js";import"./chunk-qev11kg8.js";import"./chunk-rrankpmj.js";import"./chunk-fczfdsab.js";import"./chunk-fp7ms6e7.js";import"./chunk-jp2f8yzw.js";export{a as startInteractive};