@frontman-ai/astro 0.5.2 → 0.6.0

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.
package/dist/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import * as Fs7 from 'fs';
2
2
  import { existsSync, readFileSync } from 'fs';
3
+ import * as Nodemodule from 'module';
4
+ import { createRequire } from 'module';
3
5
  import * as Nodepath5 from 'path';
4
6
  import { dirname, join } from 'path';
5
7
  import * as Nodebuffer from 'buffer';
6
8
  import * as Nodechild_process from 'child_process';
7
9
  import * as Web from 'stream/web';
8
- import { createRequire } from 'module';
9
10
 
10
11
  var __getOwnPropNames = Object.getOwnPropertyNames;
11
12
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -74,7 +75,7 @@ function getOrThrow(x, message4) {
74
75
  if (x !== void 0) {
75
76
  return valFromOption(x);
76
77
  } else {
77
- return panic("Option.getOrThrow called for None value");
78
+ return panic(message4 !== void 0 ? message4 : "Option.getOrThrow called for None value");
78
79
  }
79
80
  }
80
81
  function mapOr(opt, $$default, f) {
@@ -122,7 +123,7 @@ var clientCss = "https://app.frontman.sh/frontman.css";
122
123
  var devClientJs = "http://localhost:5173/src/Main.res.mjs";
123
124
 
124
125
  // src/FrontmanAstro__Config.res.mjs
125
- var packageVersion = "0.5.2" ;
126
+ var packageVersion = "0.6.0" ;
126
127
  var host = process.env["FRONTMAN_HOST"];
127
128
  var defaultHost = host !== void 0 ? host : apiHost;
128
129
  var ensureConfig = (function(c2) {
@@ -163,237 +164,6 @@ function makeFromObject(rawConfig) {
163
164
  };
164
165
  }
165
166
 
166
- // src/annotation-capture.mjs
167
- var annotationCaptureScript = `(function() {
168
- var PROPS_PREFIX = '__frontman_props__:';
169
-
170
- function parsePropsPayload(text) {
171
- text = text.trim();
172
- if (text.indexOf(PROPS_PREFIX) !== 0) return null;
173
- try {
174
- var encoded = text.slice(PROPS_PREFIX.length).trim();
175
- return JSON.parse(atob(encoded));
176
- } catch(e) {
177
- return null;
178
- }
179
- }
180
-
181
- function captureAnnotations() {
182
- var annotations = new Map();
183
- var propsMap = new Map();
184
- var pendingProps = [];
185
-
186
- var walker = document.createTreeWalker(
187
- document.documentElement,
188
- NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT,
189
- null
190
- );
191
-
192
- var node;
193
- while (node = walker.nextNode()) {
194
- if (node.nodeType === 8) {
195
- var parsed = parsePropsPayload(node.textContent);
196
- if (parsed) {
197
- pendingProps.push(parsed);
198
- }
199
- } else if (node.nodeType === 1) {
200
- if (pendingProps.length > 0 && node.hasAttribute('data-astro-source-file')) {
201
- propsMap.set(node, pendingProps.slice());
202
- pendingProps = [];
203
- }
204
- }
205
- }
206
-
207
- document.querySelectorAll('[data-astro-source-file]').forEach(function(el) {
208
- var sourceFile = el.getAttribute('data-astro-source-file');
209
- var annotation = {
210
- file: sourceFile,
211
- loc: el.getAttribute('data-astro-source-loc')
212
- };
213
-
214
- var propsChain = propsMap.get(el);
215
-
216
- if (!propsChain) {
217
- var parent = el.parentElement;
218
- var maxSteps = 30;
219
- while (parent && maxSteps-- > 0) {
220
- propsChain = propsMap.get(parent);
221
- if (propsChain) break;
222
- parent = parent.parentElement;
223
- }
224
- }
225
-
226
- if (propsChain && propsChain.length > 0) {
227
- var match = null;
228
- for (var i = 0; i < propsChain.length; i++) {
229
- var entry = propsChain[i];
230
- if (entry.moduleId) {
231
- var entryFile = entry.moduleId.split('/').pop() || '';
232
- var srcFile = sourceFile.split('/').pop() || '';
233
- if (entryFile === srcFile && entryFile !== '') {
234
- match = entry;
235
- break;
236
- }
237
- }
238
- }
239
- if (!match) match = propsChain[0];
240
-
241
- if (match) {
242
- annotation.componentProps = match.props || null;
243
- if (match.displayName) {
244
- annotation.displayName = match.displayName;
245
- }
246
- }
247
- }
248
-
249
- annotations.set(el, annotation);
250
- });
251
-
252
- window.__frontman_annotations__ = {
253
- _map: annotations,
254
- get: function(el) { return annotations.get(el); },
255
- has: function(el) { return annotations.has(el); },
256
- size: function() { return annotations.size; }
257
- };
258
- }
259
-
260
- document.addEventListener('DOMContentLoaded', captureAnnotations);
261
-
262
- var initialLoad = true;
263
- document.addEventListener('astro:page-load', function() {
264
- if (initialLoad) { initialLoad = false; return; }
265
- captureAnnotations();
266
- });
267
- })();`;
268
-
269
- // src/vite-plugin-props-injection.mjs
270
- function frontmanPropsInjectionPlugin() {
271
- return {
272
- name: "frontman:props-injection",
273
- enforce: "pre",
274
- apply: "serve",
275
- // Only apply in SSR (server-side rendering) mode
276
- transform(code, id, options) {
277
- if (!options?.ssr) return null;
278
- if (!id.includes("astro/dist/runtime/server/render/component") && !id.includes("astro/runtime/server/render/component")) {
279
- return null;
280
- }
281
- if (!code.includes("function renderComponent(")) {
282
- console.warn(
283
- "[Frontman] Could not find renderComponent in Astro internals \u2014 component props injection will be disabled. This may happen after an Astro upgrade. File: " + id
284
- );
285
- return null;
286
- }
287
- let transformed = code.replace(
288
- "function renderComponent(",
289
- "function __original_renderComponent("
290
- );
291
- const wrapperCode = `
292
-
293
- // --- Frontman props injection wrapper ---
294
-
295
- function __frontman_safeSerialize(displayName, Component, props) {
296
- try {
297
- const clean = {};
298
- for (const [key, value] of Object.entries(props || {})) {
299
- // Skip internal Astro props (scoped CSS hashes)
300
- if (key.startsWith('data-astro-cid-')) continue;
301
- // Skip class (styling detail, not semantic)
302
- if (key === 'class' || key === 'class:list') continue;
303
-
304
- const t = typeof value;
305
- if (t === 'string' || t === 'number' || t === 'boolean') {
306
- clean[key] = value;
307
- } else if (value === null || value === undefined) {
308
- clean[key] = value;
309
- } else if (Array.isArray(value)) {
310
- try {
311
- const serialized = JSON.stringify(value);
312
- clean[key] = serialized.length < 1000 ? value : '[Array(' + value.length + ')]';
313
- } catch {
314
- clean[key] = '[Array]';
315
- }
316
- } else if (t === 'object') {
317
- try {
318
- const serialized = JSON.stringify(value);
319
- clean[key] = serialized.length < 500 ? value : '{...}';
320
- } catch {
321
- clean[key] = '{...}';
322
- }
323
- }
324
- // Skip functions, symbols, etc.
325
- }
326
-
327
- const entry = { displayName, props: clean };
328
- // Include the component's moduleId (file path) if available
329
- if (Component && Component.moduleId) {
330
- entry.moduleId = Component.moduleId;
331
- }
332
- return JSON.stringify(entry);
333
- } catch {
334
- return null;
335
- }
336
- }
337
-
338
- function __frontman_toBase64(str) {
339
- if (typeof Buffer !== 'undefined') return Buffer.from(str, 'utf-8').toString('base64');
340
- if (typeof btoa === 'function') return btoa(unescape(encodeURIComponent(str)));
341
- return null;
342
- }
343
-
344
- function __frontman_wrapInstance(renderInstance, displayName, Component, props) {
345
- // If no render method (e.g. fragment), pass through
346
- if (!renderInstance || typeof renderInstance.render !== 'function') {
347
- return renderInstance;
348
- }
349
-
350
- const serialized = __frontman_safeSerialize(displayName, Component, props);
351
- if (!serialized) return renderInstance;
352
-
353
- const encoded = __frontman_toBase64(serialized);
354
- if (!encoded) return renderInstance;
355
-
356
- const originalRender = renderInstance.render;
357
-
358
- renderInstance.render = function(destination) {
359
- // Write the props comment BEFORE the component renders.
360
- // This creates a Comment node in the DOM immediately preceding
361
- // the component's first rendered element.
362
- // Guard: markHTMLString is assumed to be in scope from Astro's module.
363
- // If it's missing (e.g., after an Astro upgrade), skip injection gracefully.
364
- if (typeof markHTMLString === 'function') {
365
- destination.write(markHTMLString('<!-- __frontman_props__:' + encoded + ' -->'));
366
- }
367
- return originalRender.call(renderInstance, destination);
368
- };
369
-
370
- return renderInstance;
371
- }
372
-
373
- function renderComponent(result, displayName, Component, props, slots) {
374
- const renderInstance = __original_renderComponent(result, displayName, Component, props, slots);
375
-
376
- // Handle promise (async component resolution)
377
- if (renderInstance && typeof renderInstance.then === 'function') {
378
- return renderInstance.then(function(resolved) {
379
- return __frontman_wrapInstance(resolved, displayName, Component, props);
380
- });
381
- }
382
-
383
- return __frontman_wrapInstance(renderInstance, displayName, Component, props);
384
- }
385
-
386
- // --- End Frontman props injection wrapper ---
387
- `;
388
- transformed += wrapperCode;
389
- return {
390
- code: transformed,
391
- map: null
392
- };
393
- }
394
- };
395
- }
396
-
397
167
  // ../../node_modules/@rescript/runtime/lib/es6/Primitive_int.js
398
168
  function min(x, y) {
399
169
  if (x < y) {
@@ -568,9 +338,9 @@ function stringify(unknown2) {
568
338
  function toExpression(schema3) {
569
339
  let tag = schema3.type;
570
340
  let $$const = schema3.const;
571
- let name15 = schema3.name;
572
- if (name15 !== void 0) {
573
- return name15;
341
+ let name16 = schema3.name;
342
+ if (name16 !== void 0) {
343
+ return name16;
574
344
  }
575
345
  if ($$const !== void 0) {
576
346
  return stringify($$const);
@@ -1609,6 +1379,18 @@ d(sp, "~standard", {
1609
1379
  function parseOrThrow(any, schema3) {
1610
1380
  return operationFn(schema3, 1)(any);
1611
1381
  }
1382
+ function parseJsonStringOrThrow(jsonString2, schema3) {
1383
+ let tmp;
1384
+ try {
1385
+ tmp = JSON.parse(jsonString2);
1386
+ } catch (exn) {
1387
+ throw new SuryError({
1388
+ TAG: "OperationFailed",
1389
+ _0: exn.message
1390
+ }, 1, "");
1391
+ }
1392
+ return parseOrThrow(tmp, schema3);
1393
+ }
1612
1394
  function reverseConvertToJsonOrThrow(value, schema3) {
1613
1395
  return operationFn(schema3, 40)(value);
1614
1396
  }
@@ -1690,10 +1472,10 @@ function isPriority(tagFlag, byKey) {
1690
1472
  }
1691
1473
  }
1692
1474
  function isWiderUnionSchema(schemaAnyOf, inputAnyOf) {
1693
- return inputAnyOf.every((inputSchema14, idx) => {
1475
+ return inputAnyOf.every((inputSchema15, idx) => {
1694
1476
  let schema3 = schemaAnyOf[idx];
1695
- if (schema3 !== void 0 && !(flags[inputSchema14.type] & 9152) && inputSchema14.type === schema3.type) {
1696
- return inputSchema14.const === schema3.const;
1477
+ if (schema3 !== void 0 && !(flags[inputSchema15.type] & 9152) && inputSchema15.type === schema3.type) {
1478
+ return inputSchema15.const === schema3.const;
1697
1479
  } else {
1698
1480
  return false;
1699
1481
  }
@@ -2468,97 +2250,409 @@ function internalToJSONSchema(schema3, defs) {
2468
2250
  if (childSchema.type === "undefined") {
2469
2251
  return;
2470
2252
  }
2471
- items$1.push(internalToJSONSchema(childSchema, defs));
2472
- if (constField in childSchema) {
2473
- literals.push(childSchema.const);
2474
- return;
2253
+ items$1.push(internalToJSONSchema(childSchema, defs));
2254
+ if (constField in childSchema) {
2255
+ literals.push(childSchema.const);
2256
+ return;
2257
+ }
2258
+ });
2259
+ let itemsNumber$1 = items$1.length;
2260
+ let $$default = schema3.default;
2261
+ if ($$default !== void 0) {
2262
+ jsonSchema.default = valFromOption($$default);
2263
+ }
2264
+ if (itemsNumber$1 === 1) {
2265
+ Object.assign(jsonSchema, items$1[0]);
2266
+ } else if (literals.length === itemsNumber$1) {
2267
+ jsonSchema.enum = literals;
2268
+ } else {
2269
+ jsonSchema.anyOf = items$1;
2270
+ }
2271
+ break;
2272
+ case "ref":
2273
+ let ref = schema3.$ref;
2274
+ if (ref === defsPath + jsonName) ; else {
2275
+ jsonSchema.$ref = ref;
2276
+ }
2277
+ break;
2278
+ default:
2279
+ throw new Error(`[Sury] Unexpected schema type`);
2280
+ }
2281
+ let m = schema3.description;
2282
+ if (m !== void 0) {
2283
+ jsonSchema.description = m;
2284
+ }
2285
+ let m$1 = schema3.title;
2286
+ if (m$1 !== void 0) {
2287
+ jsonSchema.title = m$1;
2288
+ }
2289
+ let deprecated = schema3.deprecated;
2290
+ if (deprecated !== void 0) {
2291
+ jsonSchema.deprecated = deprecated;
2292
+ }
2293
+ let examples = schema3.examples;
2294
+ if (examples !== void 0) {
2295
+ jsonSchema.examples = examples;
2296
+ }
2297
+ let schemaDefs = schema3.$defs;
2298
+ if (schemaDefs !== void 0) {
2299
+ Object.assign(defs, schemaDefs);
2300
+ }
2301
+ let metadataRawSchema = schema3[jsonSchemaMetadataId];
2302
+ if (metadataRawSchema !== void 0) {
2303
+ Object.assign(jsonSchema, metadataRawSchema);
2304
+ }
2305
+ return jsonSchema;
2306
+ }
2307
+ function toJSONSchema(schema3) {
2308
+ jsonableValidation(schema3, schema3, "", 8);
2309
+ let defs = {};
2310
+ let jsonSchema = internalToJSONSchema(schema3, defs);
2311
+ delete defs.JSON;
2312
+ let defsKeys = Object.keys(defs);
2313
+ if (defsKeys.length) {
2314
+ defsKeys.forEach((key) => {
2315
+ defs[key] = internalToJSONSchema(defs[key], 0);
2316
+ });
2317
+ jsonSchema.$defs = defs;
2318
+ }
2319
+ return jsonSchema;
2320
+ }
2321
+ var literal = js_schema;
2322
+ var array = factory$2;
2323
+ var dict = factory$3;
2324
+ var union = factory;
2325
+ var schema = factory$4;
2326
+
2327
+ // ../../node_modules/sury/src/S.res.mjs
2328
+ var $$Error2 = $$Error;
2329
+ var string2 = string;
2330
+ var bool2 = bool;
2331
+ var int2 = int;
2332
+ var float2 = float;
2333
+ var json2 = json;
2334
+ var enableJson2 = enableJson;
2335
+ var literal2 = literal;
2336
+ var array2 = array;
2337
+ var dict2 = dict;
2338
+ var option2 = option;
2339
+ var union2 = union;
2340
+ var parseOrThrow2 = parseOrThrow;
2341
+ var parseJsonStringOrThrow2 = parseJsonStringOrThrow;
2342
+ var reverseConvertToJsonOrThrow2 = reverseConvertToJsonOrThrow;
2343
+ var schema2 = schema;
2344
+ var toJSONSchema2 = toJSONSchema;
2345
+
2346
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Array.js
2347
+ function make2(length3, x) {
2348
+ if (length3 <= 0) {
2349
+ return [];
2350
+ }
2351
+ let arr = new Array(length3);
2352
+ arr.fill(x);
2353
+ return arr;
2354
+ }
2355
+ function fromInitializer(length3, f) {
2356
+ if (length3 <= 0) {
2357
+ return [];
2358
+ }
2359
+ let arr = new Array(length3);
2360
+ for (let i = 0; i < length3; ++i) {
2361
+ arr[i] = f(i);
2362
+ }
2363
+ return arr;
2364
+ }
2365
+ function reduce(arr, init, f) {
2366
+ return arr.reduce(f, init);
2367
+ }
2368
+ function reduceWithIndex(arr, init, f) {
2369
+ return arr.reduce(f, init);
2370
+ }
2371
+ function filterMap(a, f) {
2372
+ let l = a.length;
2373
+ let r = new Array(l);
2374
+ let j2 = 0;
2375
+ for (let i = 0; i < l; ++i) {
2376
+ let v = a[i];
2377
+ let v$1 = f(v);
2378
+ if (v$1 !== void 0) {
2379
+ r[j2] = valFromOption(v$1);
2380
+ j2 = j2 + 1 | 0;
2381
+ }
2382
+ }
2383
+ r.length = j2;
2384
+ return r;
2385
+ }
2386
+
2387
+ // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Int.js
2388
+ function fromString2(x, radix) {
2389
+ let maybeInt = parseInt(x);
2390
+ if (Number.isNaN(maybeInt) || maybeInt > 2147483647 || maybeInt < -2147483648) {
2391
+ return;
2392
+ } else {
2393
+ return maybeInt | 0;
2394
+ }
2395
+ }
2396
+
2397
+ // src/annotation-capture.mjs
2398
+ var annotationCaptureScript = `(function() {
2399
+ var PROPS_PREFIX = '__frontman_props__:';
2400
+
2401
+ function parsePropsPayload(text) {
2402
+ text = text.trim();
2403
+ if (text.indexOf(PROPS_PREFIX) !== 0) return null;
2404
+ try {
2405
+ var encoded = text.slice(PROPS_PREFIX.length).trim();
2406
+ return JSON.parse(atob(encoded));
2407
+ } catch(e) {
2408
+ return null;
2409
+ }
2410
+ }
2411
+
2412
+ function captureAnnotations() {
2413
+ var annotations = new Map();
2414
+ var propsMap = new Map();
2415
+ var pendingProps = [];
2416
+ var contentFile = null;
2417
+
2418
+ var walker = document.createTreeWalker(
2419
+ document.documentElement,
2420
+ NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT,
2421
+ null
2422
+ );
2423
+
2424
+ var node;
2425
+ while (node = walker.nextNode()) {
2426
+ if (node.nodeType === 8) {
2427
+ var text = node.textContent;
2428
+ var parsed = parsePropsPayload(text);
2429
+ if (parsed) {
2430
+ pendingProps.push(parsed);
2431
+ } else if (text && text.trim().indexOf('__frontman_content_file__:') === 0) {
2432
+ contentFile = text.trim().slice('__frontman_content_file__:'.length).trim();
2433
+ }
2434
+ } else if (node.nodeType === 1) {
2435
+ if (pendingProps.length > 0 && node.hasAttribute('data-astro-source-file')) {
2436
+ propsMap.set(node, pendingProps.slice());
2437
+ pendingProps = [];
2438
+ }
2439
+ }
2440
+ }
2441
+
2442
+ document.querySelectorAll('[data-astro-source-file]').forEach(function(el) {
2443
+ var sourceFile = el.getAttribute('data-astro-source-file');
2444
+ var annotation = {
2445
+ file: sourceFile,
2446
+ loc: el.getAttribute('data-astro-source-loc')
2447
+ };
2448
+
2449
+ var propsChain = propsMap.get(el);
2450
+
2451
+ if (!propsChain) {
2452
+ var parent = el.parentElement;
2453
+ var maxSteps = 30;
2454
+ while (parent && maxSteps-- > 0) {
2455
+ propsChain = propsMap.get(parent);
2456
+ if (propsChain) break;
2457
+ parent = parent.parentElement;
2458
+ }
2459
+ }
2460
+
2461
+ if (propsChain && propsChain.length > 0) {
2462
+ var match = null;
2463
+ for (var i = 0; i < propsChain.length; i++) {
2464
+ var entry = propsChain[i];
2465
+ if (entry.moduleId) {
2466
+ var entryFile = entry.moduleId.split('/').pop() || '';
2467
+ var srcFile = sourceFile.split('/').pop() || '';
2468
+ if (entryFile === srcFile && entryFile !== '') {
2469
+ match = entry;
2470
+ break;
2471
+ }
2472
+ }
2473
+ }
2474
+ if (!match) match = propsChain[0];
2475
+
2476
+ if (match) {
2477
+ annotation.componentProps = match.props || null;
2478
+ if (match.displayName) {
2479
+ annotation.displayName = match.displayName;
2480
+ }
2481
+ }
2482
+ }
2483
+
2484
+ annotations.set(el, annotation);
2485
+ });
2486
+
2487
+ window.__frontman_annotations__ = {
2488
+ _map: annotations,
2489
+ get: function(el) { return annotations.get(el); },
2490
+ has: function(el) { return annotations.has(el); },
2491
+ size: function() { return annotations.size; },
2492
+ contentFile: contentFile
2493
+ };
2494
+ }
2495
+
2496
+ document.addEventListener('DOMContentLoaded', captureAnnotations);
2497
+
2498
+ var initialLoad = true;
2499
+ document.addEventListener('astro:page-load', function() {
2500
+ if (initialLoad) { initialLoad = false; return; }
2501
+ captureAnnotations();
2502
+ });
2503
+ })();`;
2504
+
2505
+ // src/rehype-content-file.mjs
2506
+ function rehypeContentFile(options) {
2507
+ var raw = options && options.projectRoot || "";
2508
+ var projectRoot = typeof raw === "string" ? raw : raw.pathname || "";
2509
+ if (projectRoot.endsWith("/")) {
2510
+ projectRoot = projectRoot.slice(0, -1);
2511
+ }
2512
+ return function transformer(tree, file) {
2513
+ if (!file || !file.path) {
2514
+ return;
2515
+ }
2516
+ var absolute = file.path;
2517
+ var relative = absolute;
2518
+ if (projectRoot && absolute.startsWith(projectRoot + "/")) {
2519
+ relative = absolute.slice(projectRoot.length + 1);
2520
+ }
2521
+ var comment = {
2522
+ type: "comment",
2523
+ value: " __frontman_content_file__:" + relative + " "
2524
+ };
2525
+ tree.children.unshift(comment);
2526
+ };
2527
+ }
2528
+
2529
+ // src/vite-plugin-props-injection.mjs
2530
+ function frontmanPropsInjectionPlugin() {
2531
+ return {
2532
+ name: "frontman:props-injection",
2533
+ enforce: "pre",
2534
+ apply: "serve",
2535
+ // Only apply in SSR (server-side rendering) mode
2536
+ transform(code, id, options) {
2537
+ if (!options?.ssr) return null;
2538
+ if (!id.includes("astro/dist/runtime/server/render/component") && !id.includes("astro/runtime/server/render/component")) {
2539
+ return null;
2540
+ }
2541
+ if (!code.includes("function renderComponent(")) {
2542
+ console.warn(
2543
+ "[Frontman] Could not find renderComponent in Astro internals \u2014 component props injection will be disabled. This may happen after an Astro upgrade. File: " + id
2544
+ );
2545
+ return null;
2546
+ }
2547
+ let transformed = code.replace(
2548
+ "function renderComponent(",
2549
+ "function __original_renderComponent("
2550
+ );
2551
+ const wrapperCode = `
2552
+
2553
+ // --- Frontman props injection wrapper ---
2554
+
2555
+ function __frontman_safeSerialize(displayName, Component, props) {
2556
+ try {
2557
+ const clean = {};
2558
+ for (const [key, value] of Object.entries(props || {})) {
2559
+ // Skip internal Astro props (scoped CSS hashes)
2560
+ if (key.startsWith('data-astro-cid-')) continue;
2561
+ // Skip class (styling detail, not semantic)
2562
+ if (key === 'class' || key === 'class:list') continue;
2563
+
2564
+ const t = typeof value;
2565
+ if (t === 'string' || t === 'number' || t === 'boolean') {
2566
+ clean[key] = value;
2567
+ } else if (value === null || value === undefined) {
2568
+ clean[key] = value;
2569
+ } else if (Array.isArray(value)) {
2570
+ try {
2571
+ const serialized = JSON.stringify(value);
2572
+ clean[key] = serialized.length < 1000 ? value : '[Array(' + value.length + ')]';
2573
+ } catch {
2574
+ clean[key] = '[Array]';
2575
+ }
2576
+ } else if (t === 'object') {
2577
+ try {
2578
+ const serialized = JSON.stringify(value);
2579
+ clean[key] = serialized.length < 500 ? value : '{...}';
2580
+ } catch {
2581
+ clean[key] = '{...}';
2475
2582
  }
2476
- });
2477
- let itemsNumber$1 = items$1.length;
2478
- let $$default = schema3.default;
2479
- if ($$default !== void 0) {
2480
- jsonSchema.default = valFromOption($$default);
2481
- }
2482
- if (itemsNumber$1 === 1) {
2483
- Object.assign(jsonSchema, items$1[0]);
2484
- } else if (literals.length === itemsNumber$1) {
2485
- jsonSchema.enum = literals;
2486
- } else {
2487
- jsonSchema.anyOf = items$1;
2488
- }
2489
- break;
2490
- case "ref":
2491
- let ref = schema3.$ref;
2492
- if (ref === defsPath + jsonName) ; else {
2493
- jsonSchema.$ref = ref;
2494
2583
  }
2495
- break;
2496
- default:
2497
- throw new Error(`[Sury] Unexpected schema type`);
2498
- }
2499
- let m = schema3.description;
2500
- if (m !== void 0) {
2501
- jsonSchema.description = m;
2502
- }
2503
- let m$1 = schema3.title;
2504
- if (m$1 !== void 0) {
2505
- jsonSchema.title = m$1;
2506
- }
2507
- let deprecated = schema3.deprecated;
2508
- if (deprecated !== void 0) {
2509
- jsonSchema.deprecated = deprecated;
2510
- }
2511
- let examples = schema3.examples;
2512
- if (examples !== void 0) {
2513
- jsonSchema.examples = examples;
2514
- }
2515
- let schemaDefs = schema3.$defs;
2516
- if (schemaDefs !== void 0) {
2517
- Object.assign(defs, schemaDefs);
2584
+ // Skip functions, symbols, etc.
2585
+ }
2586
+
2587
+ const entry = { displayName, props: clean };
2588
+ // Include the component's moduleId (file path) if available
2589
+ if (Component && Component.moduleId) {
2590
+ entry.moduleId = Component.moduleId;
2591
+ }
2592
+ return JSON.stringify(entry);
2593
+ } catch {
2594
+ return null;
2518
2595
  }
2519
- let metadataRawSchema = schema3[jsonSchemaMetadataId];
2520
- if (metadataRawSchema !== void 0) {
2521
- Object.assign(jsonSchema, metadataRawSchema);
2596
+ }
2597
+
2598
+ function __frontman_toBase64(str) {
2599
+ if (typeof Buffer !== 'undefined') return Buffer.from(str, 'utf-8').toString('base64');
2600
+ if (typeof btoa === 'function') return btoa(unescape(encodeURIComponent(str)));
2601
+ return null;
2602
+ }
2603
+
2604
+ function __frontman_wrapInstance(renderInstance, displayName, Component, props) {
2605
+ // If no render method (e.g. fragment), pass through
2606
+ if (!renderInstance || typeof renderInstance.render !== 'function') {
2607
+ return renderInstance;
2522
2608
  }
2523
- return jsonSchema;
2609
+
2610
+ const serialized = __frontman_safeSerialize(displayName, Component, props);
2611
+ if (!serialized) return renderInstance;
2612
+
2613
+ const encoded = __frontman_toBase64(serialized);
2614
+ if (!encoded) return renderInstance;
2615
+
2616
+ const originalRender = renderInstance.render;
2617
+
2618
+ renderInstance.render = function(destination) {
2619
+ // Write the props comment BEFORE the component renders.
2620
+ // This creates a Comment node in the DOM immediately preceding
2621
+ // the component's first rendered element.
2622
+ // Guard: markHTMLString is assumed to be in scope from Astro's module.
2623
+ // If it's missing (e.g., after an Astro upgrade), skip injection gracefully.
2624
+ if (typeof markHTMLString === 'function') {
2625
+ destination.write(markHTMLString('<!-- __frontman_props__:' + encoded + ' -->'));
2626
+ }
2627
+ return originalRender.call(renderInstance, destination);
2628
+ };
2629
+
2630
+ return renderInstance;
2524
2631
  }
2525
- function toJSONSchema(schema3) {
2526
- jsonableValidation(schema3, schema3, "", 8);
2527
- let defs = {};
2528
- let jsonSchema = internalToJSONSchema(schema3, defs);
2529
- delete defs.JSON;
2530
- let defsKeys = Object.keys(defs);
2531
- if (defsKeys.length) {
2532
- defsKeys.forEach((key) => {
2533
- defs[key] = internalToJSONSchema(defs[key], 0);
2632
+
2633
+ function renderComponent(result, displayName, Component, props, slots) {
2634
+ const renderInstance = __original_renderComponent(result, displayName, Component, props, slots);
2635
+
2636
+ // Handle promise (async component resolution)
2637
+ if (renderInstance && typeof renderInstance.then === 'function') {
2638
+ return renderInstance.then(function(resolved) {
2639
+ return __frontman_wrapInstance(resolved, displayName, Component, props);
2534
2640
  });
2535
- jsonSchema.$defs = defs;
2536
2641
  }
2537
- return jsonSchema;
2642
+
2643
+ return __frontman_wrapInstance(renderInstance, displayName, Component, props);
2538
2644
  }
2539
- var literal = js_schema;
2540
- var array = factory$2;
2541
- var dict = factory$3;
2542
- var union = factory;
2543
- var schema = factory$4;
2544
2645
 
2545
- // ../../node_modules/sury/src/S.res.mjs
2546
- var $$Error2 = $$Error;
2547
- var string2 = string;
2548
- var bool2 = bool;
2549
- var int2 = int;
2550
- var float2 = float;
2551
- var json2 = json;
2552
- var enableJson2 = enableJson;
2553
- var literal2 = literal;
2554
- var array2 = array;
2555
- var dict2 = dict;
2556
- var option2 = option;
2557
- var union2 = union;
2558
- var parseOrThrow2 = parseOrThrow;
2559
- var reverseConvertToJsonOrThrow2 = reverseConvertToJsonOrThrow;
2560
- var schema2 = schema;
2561
- var toJSONSchema2 = toJSONSchema;
2646
+ // --- End Frontman props injection wrapper ---
2647
+ `;
2648
+ transformed += wrapperCode;
2649
+ return {
2650
+ code: transformed,
2651
+ map: null
2652
+ };
2653
+ }
2654
+ };
2655
+ }
2562
2656
 
2563
2657
  // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_JsExn.js
2564
2658
  function fromException(exn) {
@@ -2569,47 +2663,6 @@ function fromException(exn) {
2569
2663
  var getOrUndefined = ((fieldName) => (t) => t && typeof t[fieldName] === "string" ? t[fieldName] : void 0);
2570
2664
  var message2 = getOrUndefined("message");
2571
2665
 
2572
- // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Array.js
2573
- function make2(length3, x) {
2574
- if (length3 <= 0) {
2575
- return [];
2576
- }
2577
- let arr = new Array(length3);
2578
- arr.fill(x);
2579
- return arr;
2580
- }
2581
- function fromInitializer(length3, f) {
2582
- if (length3 <= 0) {
2583
- return [];
2584
- }
2585
- let arr = new Array(length3);
2586
- for (let i = 0; i < length3; ++i) {
2587
- arr[i] = f(i);
2588
- }
2589
- return arr;
2590
- }
2591
- function reduce(arr, init, f) {
2592
- return arr.reduce(f, init);
2593
- }
2594
- function reduceWithIndex(arr, init, f) {
2595
- return arr.reduce(f, init);
2596
- }
2597
- function filterMap(a, f) {
2598
- let l = a.length;
2599
- let r = new Array(l);
2600
- let j2 = 0;
2601
- for (let i = 0; i < l; ++i) {
2602
- let v = a[i];
2603
- let v$1 = f(v);
2604
- if (v$1 !== void 0) {
2605
- r[j2] = valFromOption(v$1);
2606
- j2 = j2 + 1 | 0;
2607
- }
2608
- }
2609
- r.length = j2;
2610
- return r;
2611
- }
2612
-
2613
2666
  // ../frontman-core/src/FrontmanCore__CircularBuffer.res.mjs
2614
2667
  function make3(capacity) {
2615
2668
  return {
@@ -3328,24 +3381,24 @@ function levenshtein(a, b) {
3328
3381
  for (let i = 1; i <= match; ++i) {
3329
3382
  for (let j2 = 1; j2 <= match$1; ++j2) {
3330
3383
  let cost = a.charAt(i - 1 | 0) === b.charAt(j2 - 1 | 0) ? 0 : 1;
3331
- let del = getOrThrow(matrix[i - 1 | 0])[j2] + 1 | 0;
3332
- let ins = getOrThrow(matrix[i])[j2 - 1 | 0] + 1 | 0;
3333
- let sub = getOrThrow(matrix[i - 1 | 0])[j2 - 1 | 0] + cost | 0;
3334
- getOrThrow(matrix[i])[j2] = min(del, min(ins, sub));
3384
+ let del = getOrThrow(matrix[i - 1 | 0], void 0)[j2] + 1 | 0;
3385
+ let ins = getOrThrow(matrix[i], void 0)[j2 - 1 | 0] + 1 | 0;
3386
+ let sub = getOrThrow(matrix[i - 1 | 0], void 0)[j2 - 1 | 0] + cost | 0;
3387
+ getOrThrow(matrix[i], void 0)[j2] = min(del, min(ins, sub));
3335
3388
  }
3336
3389
  }
3337
- return getOrThrow(matrix[match])[match$1];
3390
+ return getOrThrow(matrix[match], void 0)[match$1];
3338
3391
  }
3339
3392
  function lineOffset(lines, lineIndex) {
3340
3393
  let offset = 0;
3341
3394
  for (let k2 = 0; k2 < lineIndex; ++k2) {
3342
- offset = (offset + getOrThrow(lines[k2]).length | 0) + 1 | 0;
3395
+ offset = (offset + getOrThrow(lines[k2], void 0).length | 0) + 1 | 0;
3343
3396
  }
3344
3397
  return offset;
3345
3398
  }
3346
3399
  function extractBlock(content, lines, startLine, endLine) {
3347
3400
  let startIdx = lineOffset(lines, startLine);
3348
- let endIdx = lineOffset(lines, endLine) + getOrThrow(lines[endLine]).length | 0;
3401
+ let endIdx = lineOffset(lines, endLine) + getOrThrow(lines[endLine], void 0).length | 0;
3349
3402
  return content.slice(startIdx, endIdx);
3350
3403
  }
3351
3404
  function escapeRegex(str) {
@@ -3369,8 +3422,8 @@ function lineTrimMatch(content, find) {
3369
3422
  let matches2 = true;
3370
3423
  let j2 = 0;
3371
3424
  while (j2 < searchLen && matches2) {
3372
- let origTrimmed = getOrThrow(contentLines[i + j2 | 0]).trim();
3373
- let searchTrimmed = getOrThrow(searchLines$1[j2]).trim();
3425
+ let origTrimmed = getOrThrow(contentLines[i + j2 | 0], void 0).trim();
3426
+ let searchTrimmed = getOrThrow(searchLines$1[j2], void 0).trim();
3374
3427
  if (origTrimmed === searchTrimmed) {
3375
3428
  j2 = j2 + 1 | 0;
3376
3429
  } else {
@@ -3391,15 +3444,15 @@ function anchoredBlockMatch(content, find) {
3391
3444
  if (searchLines$1.length < 3) {
3392
3445
  return [];
3393
3446
  }
3394
- let firstLineSearch = getOrThrow(searchLines$1[0]).trim();
3395
- let lastLineSearch = getOrThrow(searchLines$1[searchLines$1.length - 1 | 0]).trim();
3447
+ let firstLineSearch = getOrThrow(searchLines$1[0], void 0).trim();
3448
+ let lastLineSearch = getOrThrow(searchLines$1[searchLines$1.length - 1 | 0], void 0).trim();
3396
3449
  let searchBlockSize = searchLines$1.length;
3397
3450
  let candidates = [];
3398
3451
  for (let i = 0, i_finish = contentLines.length; i < i_finish; ++i) {
3399
- if (getOrThrow(contentLines[i]).trim() === firstLineSearch) {
3452
+ if (getOrThrow(contentLines[i], void 0).trim() === firstLineSearch) {
3400
3453
  let j2 = i + 2 | 0;
3401
3454
  while (j2 < contentLines.length) {
3402
- if (getOrThrow(contentLines[j2]).trim() === lastLineSearch) {
3455
+ if (getOrThrow(contentLines[j2], void 0).trim() === lastLineSearch) {
3403
3456
  candidates.push({
3404
3457
  startLine: i,
3405
3458
  endLine: j2
@@ -3430,8 +3483,8 @@ function anchoredBlockMatch(content, find) {
3430
3483
  if (linesToCheck2 > 0) {
3431
3484
  let sim = 0;
3432
3485
  for (let j2 = 1, j_finish = min(searchBlockSize - 2 | 0, actualBlockSize2 - 2 | 0); j2 <= j_finish; ++j2) {
3433
- let origLine = getOrThrow(contentLines[startLine2 + j2 | 0]).trim();
3434
- let searchLine = getOrThrow(searchLines$1[j2]).trim();
3486
+ let origLine = getOrThrow(contentLines[startLine2 + j2 | 0], void 0).trim();
3487
+ let searchLine = getOrThrow(searchLines$1[j2], void 0).trim();
3435
3488
  let maxLen = max(origLine.length, searchLine.length);
3436
3489
  if (maxLen > 0) {
3437
3490
  let distance = levenshtein(origLine, searchLine);
@@ -3460,7 +3513,7 @@ function anchoredBlockMatch(content, find) {
3460
3513
  return [];
3461
3514
  }
3462
3515
  }
3463
- let match$3 = getOrThrow(candidates[0]);
3516
+ let match$3 = getOrThrow(candidates[0], void 0);
3464
3517
  let endLine = match$3.endLine;
3465
3518
  let startLine = match$3.startLine;
3466
3519
  let actualBlockSize = (endLine - startLine | 0) + 1 | 0;
@@ -3470,8 +3523,8 @@ function anchoredBlockMatch(content, find) {
3470
3523
  let sim = 0;
3471
3524
  let j$1 = 1;
3472
3525
  while (j$1 < (searchBlockSize - 1 | 0) && j$1 < (actualBlockSize - 1 | 0)) {
3473
- let origLine = getOrThrow(contentLines[startLine + j$1 | 0]).trim();
3474
- let searchLine = getOrThrow(searchLines$1[j$1]).trim();
3526
+ let origLine = getOrThrow(contentLines[startLine + j$1 | 0], void 0).trim();
3527
+ let searchLine = getOrThrow(searchLines$1[j$1], void 0).trim();
3475
3528
  let maxLen = max(origLine.length, searchLine.length);
3476
3529
  if (maxLen > 0) {
3477
3530
  let distance = levenshtein(origLine, searchLine);
@@ -3622,21 +3675,21 @@ function contextAnchorMatch(content, find) {
3622
3675
  return [];
3623
3676
  }
3624
3677
  let contentLines = content.split("\n");
3625
- let firstLine = getOrThrow(findLines$1[0]).trim();
3626
- let lastLine = getOrThrow(findLines$1[findLines$1.length - 1 | 0]).trim();
3678
+ let firstLine = getOrThrow(findLines$1[0], void 0).trim();
3679
+ let lastLine = getOrThrow(findLines$1[findLines$1.length - 1 | 0], void 0).trim();
3627
3680
  let results = [];
3628
3681
  for (let i = 0, i_finish = contentLines.length; i < i_finish; ++i) {
3629
- if (getOrThrow(contentLines[i]).trim() === firstLine) {
3682
+ if (getOrThrow(contentLines[i], void 0).trim() === firstLine) {
3630
3683
  let j2 = i + 2 | 0;
3631
3684
  while (j2 < contentLines.length) {
3632
- if (getOrThrow(contentLines[j2]).trim() === lastLine) {
3685
+ if (getOrThrow(contentLines[j2], void 0).trim() === lastLine) {
3633
3686
  let blockLines = contentLines.slice(i, j2 + 1 | 0);
3634
3687
  if (blockLines.length === findLines$1.length) {
3635
3688
  let matchingLines = 0;
3636
3689
  let totalNonEmpty = 0;
3637
3690
  for (let k2 = 1, k_finish = blockLines.length - 2 | 0; k2 <= k_finish; ++k2) {
3638
- let blockLine = getOrThrow(blockLines[k2]).trim();
3639
- let findLine = getOrThrow(findLines$1[k2]).trim();
3691
+ let blockLine = getOrThrow(blockLines[k2], void 0).trim();
3692
+ let findLine = getOrThrow(findLines$1[k2], void 0).trim();
3640
3693
  let match = blockLine.length > 0;
3641
3694
  let match$1 = findLine.length > 0;
3642
3695
  let exit = 0;
@@ -3704,7 +3757,7 @@ function applyEdit(content, oldText, newText, replaceAllOpt) {
3704
3757
  };
3705
3758
  let strategyIdx = 0;
3706
3759
  while (isNone(result.contents) && strategyIdx < strategies.length) {
3707
- let strategy = getOrThrow(strategies[strategyIdx]);
3760
+ let strategy = getOrThrow(strategies[strategyIdx], void 0);
3708
3761
  let candidates = strategy(content, oldText);
3709
3762
  let match = !replaceAll && candidates.length > 1;
3710
3763
  if (match) {
@@ -3879,6 +3932,8 @@ Parameters:
3879
3932
  The tool uses multiple matching strategies (exact, line-trimmed, whitespace-normalized,
3880
3933
  indentation-flexible, etc.) to handle common formatting differences.
3881
3934
 
3935
+ When replacing most of a file, prefer write_file instead \u2014 it avoids reproducing the original content. Use edit_file for surgical changes: a few lines, a function body, a config block. For multiple changes in one file, make several small edit_file calls targeting specific sections rather than one large replacement.
3936
+
3882
3937
  IMPORTANT: You must read_file before editing. The tool will reject edits on unread files.`;
3883
3938
 
3884
3939
  // src/tools/FrontmanAstro__Tool__EditFile.res.mjs
@@ -4057,16 +4112,6 @@ Parameters: None
4057
4112
 
4058
4113
  Returns array of page paths based on file-system routing conventions.
4059
4114
  Excludes API routes (src/pages/api/) - focuses on renderable pages only.`;
4060
-
4061
- // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Int.js
4062
- function fromString2(x, radix) {
4063
- let maybeInt = parseInt(x);
4064
- if (Number.isNaN(maybeInt) || maybeInt > 2147483647 || maybeInt < -2147483648) {
4065
- return;
4066
- } else {
4067
- return maybeInt | 0;
4068
- }
4069
- }
4070
4115
  function execPromise(command, options) {
4071
4116
  let maxBuffer = getOr(options.maxBuffer, 52428800);
4072
4117
  return new Promise((resolve3, _reject) => {
@@ -4662,9 +4707,9 @@ var noiseDirs = [
4662
4707
  "__pycache__",
4663
4708
  "target"
4664
4709
  ];
4665
- function makeTrieNode(name15) {
4710
+ function makeTrieNode(name16) {
4666
4711
  return {
4667
- name: name15,
4712
+ name: name16,
4668
4713
  children: {
4669
4714
  contents: {}
4670
4715
  },
@@ -4883,9 +4928,9 @@ async function detectMonorepo(rootPath) {
4883
4928
  workspaces = await Promise.all(resolvedPaths.map(async (wsPath) => {
4884
4929
  let fullPath = Nodepath5.join(rootPath, wsPath);
4885
4930
  let n = await readPackageName(fullPath);
4886
- let name15 = n !== void 0 ? n : wsPath;
4931
+ let name16 = n !== void 0 ? n : wsPath;
4887
4932
  return {
4888
- name: name15,
4933
+ name: name16,
4889
4934
  path: wsPath
4890
4935
  };
4891
4936
  }));
@@ -5158,19 +5203,19 @@ async function execute8(ctx2, input) {
5158
5203
  let relativePath = match[1];
5159
5204
  let fullPath = match[0];
5160
5205
  let entries = await Fs7.promises.readdir(fullPath);
5161
- let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name15) => !ignored.includes(name15)));
5206
+ let filteredEntriesResult = map3(await getIgnoredEntries(fullPath, entries), (ignored) => entries.filter((name16) => !ignored.includes(name16)));
5162
5207
  if (filteredEntriesResult.TAG !== "Ok") {
5163
5208
  return {
5164
5209
  TAG: "Error",
5165
5210
  _0: filteredEntriesResult._0
5166
5211
  };
5167
5212
  }
5168
- let entriesWithStats = await Promise.all(filteredEntriesResult._0.map(async (name15) => {
5169
- let entryPath = Nodepath5.join(fullPath, name15);
5213
+ let entriesWithStats = await Promise.all(filteredEntriesResult._0.map(async (name16) => {
5214
+ let entryPath = Nodepath5.join(fullPath, name16);
5170
5215
  let stats = await Fs7.promises.stat(entryPath);
5171
5216
  return {
5172
- name: name15,
5173
- path: Nodepath5.join(relativePath, name15),
5217
+ name: name16,
5218
+ path: Nodepath5.join(relativePath, name16),
5174
5219
  isFile: stats.isFile(),
5175
5220
  isDirectory: stats.isDirectory()
5176
5221
  };
@@ -5301,6 +5346,8 @@ Parameters:
5301
5346
  Provide either content OR image_ref, not both.
5302
5347
  Creates parent directories if they don't exist. Overwrites existing files.
5303
5348
 
5349
+ Prefer write_file over edit_file when rewriting most of a file \u2014 it is more efficient since you only provide the final content once.
5350
+
5304
5351
  IMPORTANT: If the file already exists, you MUST read it with read_file first. The tool will reject writes to existing files that haven't been read.`;
5305
5352
 
5306
5353
  // ../frontman-core/src/tools/FrontmanCore__Tool__FileExists.res.mjs
@@ -5331,8 +5378,8 @@ Returns true if the path exists, false otherwise.`;
5331
5378
  var outputSchema10 = bool2;
5332
5379
 
5333
5380
  // ../frontman-core/src/FrontmanCore__Lighthouse.res.mjs
5334
- var run = ((url2, flags2) => import('module').then(({ createRequire }) => {
5335
- const req = createRequire(import.meta.url);
5381
+ var run = ((url2, flags2) => import('module').then(({ createRequire: createRequire2 }) => {
5382
+ const req = createRequire2(import.meta.url);
5336
5383
  try {
5337
5384
  const mod = req("lighthouse");
5338
5385
  const lighthouse = mod.default ?? mod;
@@ -5349,8 +5396,8 @@ var run = ((url2, flags2) => import('module').then(({ createRequire }) => {
5349
5396
  function getPort(prim) {
5350
5397
  return prim.port;
5351
5398
  }
5352
- var launch = ((options) => import('module').then(({ createRequire }) => {
5353
- const req = createRequire(import.meta.url);
5399
+ var launch = ((options) => import('module').then(({ createRequire: createRequire2 }) => {
5400
+ const req = createRequire2(import.meta.url);
5354
5401
  try {
5355
5402
  const mod = req("chrome-launcher");
5356
5403
  return mod.launch(options);
@@ -5529,21 +5576,21 @@ function getTopIssues(category, audits, maxIssues) {
5529
5576
  return match$1 < 1;
5530
5577
  }
5531
5578
  }).toSorted((a, b) => {
5532
- let scoreA = getOrThrow(fromNullable(a.score));
5533
- let scoreB = getOrThrow(fromNullable(b.score));
5579
+ let scoreA = getOrThrow(fromNullable(a.score), void 0);
5580
+ let scoreB = getOrThrow(fromNullable(b.score), void 0);
5534
5581
  return scoreA - scoreB;
5535
5582
  }).slice(0, maxIssues).map((audit) => ({
5536
5583
  id: audit.id,
5537
5584
  title: audit.title,
5538
5585
  description: audit.description,
5539
- score: getOrThrow(fromNullable(audit.score)),
5586
+ score: getOrThrow(fromNullable(audit.score), void 0),
5540
5587
  displayValue: audit.displayValue,
5541
5588
  elements: extractElements(audit.details)
5542
5589
  }));
5543
5590
  }
5544
5591
  function processLhr(lhr) {
5545
5592
  let categories = filterMap(categoryIds, (id) => lhr.categories[id]).map((category) => {
5546
- let score = Math.round(getOrThrow(fromNullable(category.score)) * 100) | 0;
5593
+ let score = Math.round(getOrThrow(fromNullable(category.score), void 0) * 100) | 0;
5547
5594
  let topIssues = getTopIssues(category, lhr.audits, 3);
5548
5595
  return {
5549
5596
  id: category.id,
@@ -6029,8 +6076,8 @@ function replaceByName(registry, replacement) {
6029
6076
  })
6030
6077
  };
6031
6078
  }
6032
- function getToolByName(registry, name15) {
6033
- return registry.tools.find((m) => m.name === name15);
6079
+ function getToolByName(registry, name16) {
6080
+ return registry.tools.find((m) => m.name === name16);
6034
6081
  }
6035
6082
  function serializeTool(m) {
6036
6083
  return {
@@ -6044,6 +6091,55 @@ function getToolDefinitions(registry) {
6044
6091
  return registry.tools.map(serializeTool);
6045
6092
  }
6046
6093
 
6094
+ // src/tools/FrontmanAstro__Tool__GetResolvedRoutes.res.mjs
6095
+ var name15 = "get_client_pages";
6096
+ var description14 = `Lists all routes resolved by Astro's router.
6097
+
6098
+ Parameters: None
6099
+
6100
+ Returns routes from Astro's astro:routes:resolved hook, including pages,
6101
+ API endpoints, redirects, content collection routes, and integration-injected
6102
+ routes. Each route includes its pattern, entrypoint, type, origin, params,
6103
+ and prerender status.`;
6104
+ var inputSchema14 = schema2((s2) => ({
6105
+ placeholder: s2.m(option2(bool2))
6106
+ }));
6107
+ var routeEntrySchema = schema2((s2) => ({
6108
+ path: s2.m(string2),
6109
+ file: s2.m(string2),
6110
+ isDynamic: s2.m(bool2),
6111
+ params: s2.m(array2(string2)),
6112
+ type: s2.m(string2),
6113
+ origin: s2.m(string2),
6114
+ isPrerendered: s2.m(bool2)
6115
+ }));
6116
+ var outputSchema14 = array2(routeEntrySchema);
6117
+ function toRouteEntry(route) {
6118
+ return {
6119
+ path: route.pattern,
6120
+ file: route.entrypoint,
6121
+ isDynamic: route.params.length !== 0,
6122
+ params: route.params,
6123
+ type: route.type,
6124
+ origin: route.origin,
6125
+ isPrerendered: route.isPrerendered
6126
+ };
6127
+ }
6128
+ function make4(getRoutes) {
6129
+ let execute14 = async (_ctx, _input) => ({
6130
+ TAG: "Ok",
6131
+ _0: getRoutes().map(toRouteEntry)
6132
+ });
6133
+ return {
6134
+ name: name15,
6135
+ description: description14,
6136
+ inputSchema: inputSchema14,
6137
+ outputSchema: outputSchema14,
6138
+ execute: execute14,
6139
+ visibleToAgent: true
6140
+ };
6141
+ }
6142
+
6047
6143
  // src/FrontmanAstro__ToolRegistry.res.mjs
6048
6144
  var astroTools = [
6049
6145
  {
@@ -6063,7 +6159,7 @@ var astroTools = [
6063
6159
  visibleToAgent: true
6064
6160
  }
6065
6161
  ];
6066
- function make4() {
6162
+ function make5() {
6067
6163
  return replaceByName(addTools(coreTools(), astroTools), {
6068
6164
  name: name4,
6069
6165
  description: description3,
@@ -6073,6 +6169,27 @@ function make4() {
6073
6169
  visibleToAgent: true
6074
6170
  });
6075
6171
  }
6172
+ function makeWithResolvedRoutes(getRoutes) {
6173
+ let resolvedRoutesTool = make4(getRoutes);
6174
+ return replaceByName(addTools(coreTools(), [
6175
+ resolvedRoutesTool,
6176
+ {
6177
+ name: name2,
6178
+ description,
6179
+ inputSchema,
6180
+ outputSchema,
6181
+ execute,
6182
+ visibleToAgent: true
6183
+ }
6184
+ ]), {
6185
+ name: name4,
6186
+ description: description3,
6187
+ inputSchema: inputSchema3,
6188
+ outputSchema: outputSchema3,
6189
+ execute: execute3,
6190
+ visibleToAgent: true
6191
+ });
6192
+ }
6076
6193
 
6077
6194
  // ../../node_modules/@rescript/runtime/lib/es6/Stdlib_Dict.js
6078
6195
  var forEachWithKey = ((dict3, f) => {
@@ -7939,12 +8056,12 @@ var toolCallRequestSchema = schema2((s2) => ({
7939
8056
  var protocolVersion = "1.0";
7940
8057
 
7941
8058
  // ../frontman-core/src/FrontmanCore__Server.res.mjs
7942
- async function executeTool(registry, ctx2, name15, $$arguments) {
7943
- let toolModule = getToolByName(registry, name15);
8059
+ async function executeTool(registry, ctx2, name16, $$arguments) {
8060
+ let toolModule = getToolByName(registry, name16);
7944
8061
  if (toolModule === void 0) {
7945
8062
  return {
7946
8063
  TAG: "ToolNotFound",
7947
- _0: name15
8064
+ _0: name16
7948
8065
  };
7949
8066
  }
7950
8067
  let toolCtx_projectRoot = ctx2.projectRoot;
@@ -8309,7 +8426,7 @@ function createMiddleware(config, registry) {
8309
8426
  if (!isSome(suffixPrefix)) {
8310
8427
  return;
8311
8428
  }
8312
- let prefixPath = getOrThrow(suffixPrefix);
8429
+ let prefixPath = getOrThrow(suffixPrefix, void 0);
8313
8430
  let canonicalPath = getCanonicalRedirect(prefixPath, basePath);
8314
8431
  if (canonicalPath !== void 0) {
8315
8432
  return new Response("", {
@@ -8320,7 +8437,7 @@ function createMiddleware(config, registry) {
8320
8437
  ]]))
8321
8438
  });
8322
8439
  }
8323
- let originalPrefix = getOrThrow(originalSuffixPrefix);
8440
+ let originalPrefix = getOrThrow(originalSuffixPrefix, void 0);
8324
8441
  let entrypointUrl = buildEntrypointUrl(config, req.url, originalPrefix);
8325
8442
  return withCors(serveWithEntrypoint(config, entrypointUrl));
8326
8443
  case "options":
@@ -8358,8 +8475,9 @@ function toMiddlewareConfig(config) {
8358
8475
  frameworkId: "Astro"
8359
8476
  };
8360
8477
  }
8361
- function createMiddleware2(config) {
8362
- let registry = make4();
8478
+ function createMiddleware2(config, routeDiscovery) {
8479
+ let registry;
8480
+ registry = typeof routeDiscovery !== "object" ? make5() : makeWithResolvedRoutes(routeDiscovery.getRoutes);
8363
8481
  let middlewareConfig = toMiddlewareConfig(config);
8364
8482
  return createMiddleware(middlewareConfig, registry);
8365
8483
  }
@@ -8461,13 +8579,35 @@ function adaptToConnect(middleware, basePath) {
8461
8579
  }
8462
8580
 
8463
8581
  // src/FrontmanAstro__Integration.res.mjs
8582
+ var packageJsonSchema = schema2((s2) => ({
8583
+ version: s2.m(string2)
8584
+ }));
8585
+ function getAstroVersion() {
8586
+ let $$require = Nodemodule.createRequire(import.meta.url);
8587
+ let pkgPath = $$require.resolve("astro/package.json");
8588
+ let raw = Fs7.readFileSync(pkgPath, "utf8");
8589
+ return parseJsonStringOrThrow2(raw, packageJsonSchema).version;
8590
+ }
8591
+ function parseMajorVersion(version) {
8592
+ return getOrThrow(flatMap(version.split(".")[0], (s2) => fromString2(s2)), `[Frontman] Failed to parse Astro major version from "` + version + `"`);
8593
+ }
8464
8594
  var annotationCaptureScript2 = annotationCaptureScript;
8595
+ function rehypeContentFile2(prim) {
8596
+ return rehypeContentFile(prim);
8597
+ }
8465
8598
  var icon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="90 70 230 270" fill="none"><path d="M145.925 316.925C136.175 316.925 129.242 315.517 125.125 312.7C121.008 309.667 118.517 305.875 117.65 301.325C116.783 296.558 116.35 291.792 116.35 287.025V119C116.35 107.733 118.517 100.042 122.85 95.925C127.4 91.5917 135.417 89.425 146.9 89.425H265.85C270.833 89.425 275.492 89.8583 279.825 90.725C284.375 91.5917 288.058 94.0833 290.875 98.2C293.692 102.317 295.1 109.358 295.1 119.325C295.1 129.075 293.583 136.008 290.55 140.125C287.733 144.242 284.05 146.733 279.5 147.6C274.95 148.467 270.183 148.9 265.2 148.9H175.825V177.825H235.625C240.608 177.825 245.05 178.258 248.95 179.125C253.067 179.775 256.208 181.942 258.375 185.625C260.758 189.092 261.95 195.158 261.95 203.825C261.95 212.058 260.758 217.908 258.375 221.375C255.992 224.842 252.742 226.9 248.625 227.55C244.725 228.2 240.283 228.525 235.3 228.525H175.825V287.35C175.825 292.117 175.392 296.775 174.525 301.325C173.658 305.875 171.167 309.667 167.05 312.7C162.933 315.517 155.892 316.925 145.925 316.925Z" fill="currentColor"/></svg>`;
8466
8599
  function getToolbarAppPath() {
8467
8600
  return new URL("./toolbar.js", import.meta.url).pathname;
8468
8601
  }
8469
- function make5(configInput) {
8602
+ function make6(configInput) {
8470
8603
  let config = makeFromObject(configInput);
8604
+ let useResolvedRoutes = parseMajorVersion(getAstroVersion()) >= 5;
8605
+ let resolvedRoutes = {
8606
+ contents: []
8607
+ };
8608
+ let routeDiscovery = useResolvedRoutes ? {
8609
+ getRoutes: () => resolvedRoutes.contents
8610
+ } : "Filesystem";
8471
8611
  return {
8472
8612
  name: "frontman",
8473
8613
  hooks: {
@@ -8478,7 +8618,7 @@ function make5(configInput) {
8478
8618
  if (!ctx2.config.devToolbar.enabled) {
8479
8619
  console.warn("[Frontman] Astro devToolbar is disabled \u2014 element source detection will be limited. Set `devToolbar: { enabled: true }` in your astro.config to enable full component source resolution.");
8480
8620
  }
8481
- let webMiddleware = createMiddleware2(config);
8621
+ let webMiddleware = createMiddleware2(config, routeDiscovery);
8482
8622
  let connectMiddleware = adaptToConnect(webMiddleware, config.basePath);
8483
8623
  let middlewarePlugin_configureServer = (server) => {
8484
8624
  server.middlewares.use(connectMiddleware);
@@ -8495,6 +8635,16 @@ function make5(configInput) {
8495
8635
  ]
8496
8636
  }
8497
8637
  });
8638
+ ctx2.updateConfig({
8639
+ markdown: {
8640
+ rehypePlugins: [[
8641
+ rehypeContentFile2,
8642
+ {
8643
+ projectRoot: config.sourceRoot
8644
+ }
8645
+ ]]
8646
+ }
8647
+ });
8498
8648
  ctx2.addDevToolbarApp({
8499
8649
  id: "frontman:toolbar",
8500
8650
  name: "Frontman",
@@ -8538,13 +8688,16 @@ function make5(configInput) {
8538
8688
  param.toolbar.onAppInitialized("frontman:toolbar", () => {
8539
8689
  console.log("[Frontman] Dev toolbar app initialized");
8540
8690
  });
8541
- }
8691
+ },
8692
+ "astro:routes:resolved": useResolvedRoutes ? (param) => {
8693
+ resolvedRoutes.contents = param.routes;
8694
+ } : void 0
8542
8695
  }
8543
8696
  };
8544
8697
  }
8545
8698
 
8546
8699
  // src/FrontmanAstro.res.mjs
8547
- var frontmanIntegration = make5;
8700
+ var frontmanIntegration = make6;
8548
8701
 
8549
8702
  // index.mjs
8550
8703
  var index_default = frontmanIntegration;