youiyoux 0.1.0 → 0.1.3

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.
@@ -45,7 +45,7 @@ import {
45
45
  unifiedDiff,
46
46
  validateTokenSets,
47
47
  writeFileAtomic
48
- } from "./chunk-ZLRFD5JI.js";
48
+ } from "./chunk-C3TSTYP7.js";
49
49
  import {
50
50
  __commonJS,
51
51
  __toESM
@@ -8183,7 +8183,7 @@ async function bundle(sources, { req, parse: userParse, yamlToMomoa }) {
8183
8183
  };
8184
8184
  const originalSourceLength = sources.length;
8185
8185
  const origin = sources[0].filename;
8186
- let document = {};
8186
+ let document2 = {};
8187
8187
  for (let i = 0; i < sources.length; i++) {
8188
8188
  const resolved = {
8189
8189
  ...sources[i],
@@ -8195,8 +8195,8 @@ async function bundle(sources, { req, parse: userParse, yamlToMomoa }) {
8195
8195
  if (typeof resolved.src !== "string") {
8196
8196
  resolved.src = print(resolved.document, { indent: 2 });
8197
8197
  }
8198
- if (!document.type) {
8199
- document = resolved.document;
8198
+ if (!document2.type) {
8199
+ document2 = resolved.document;
8200
8200
  }
8201
8201
  cache[sources[i].filename.href] = resolved;
8202
8202
  await traverseAsync(resolved.document, {
@@ -8222,9 +8222,9 @@ async function bundle(sources, { req, parse: userParse, yamlToMomoa }) {
8222
8222
  });
8223
8223
  if (i > 0) {
8224
8224
  if (i < originalSourceLength) {
8225
- document = mergeDocuments([document, resolved.document]);
8225
+ document2 = mergeDocuments([document2, resolved.document]);
8226
8226
  } else {
8227
- let $defs = getObjMember(document.body, "$defs");
8227
+ let $defs = getObjMember(document2.body, "$defs");
8228
8228
  if (!$defs) {
8229
8229
  const $defsMember = {
8230
8230
  type: "Member",
@@ -8233,7 +8233,7 @@ async function bundle(sources, { req, parse: userParse, yamlToMomoa }) {
8233
8233
  loc: VIRTUAL_LOC
8234
8234
  };
8235
8235
  $defs = $defsMember.value;
8236
- document.body.members.push($defsMember);
8236
+ document2.body.members.push($defsMember);
8237
8237
  }
8238
8238
  $defs.members.push({
8239
8239
  type: "Member",
@@ -8245,7 +8245,7 @@ async function bundle(sources, { req, parse: userParse, yamlToMomoa }) {
8245
8245
  }
8246
8246
  }
8247
8247
  return {
8248
- document,
8248
+ document: document2,
8249
8249
  sources: cache
8250
8250
  };
8251
8251
  }
@@ -10855,10 +10855,10 @@ function processTokens(rootSource, { config, logger, sourceByFilename, resolveAl
10855
10855
  }
10856
10856
 
10857
10857
  // ../../node_modules/.pnpm/@terrazzo+parser@2.7.1_yaml-to-momoa@0.1.0/node_modules/@terrazzo/parser/dist/resolver/normalize.js
10858
- async function normalizeResolver(document, { logger, filename, req, src, yamlToMomoa }) {
10858
+ async function normalizeResolver(document2, { logger, filename, req, src, yamlToMomoa }) {
10859
10859
  const resolverBundle = await bundle([{ filename, src }], { req, yamlToMomoa });
10860
10860
  const resolverSource = evaluate(resolverBundle.document);
10861
- replaceNode(document, resolverBundle.document);
10861
+ replaceNode(document2, resolverBundle.document);
10862
10862
  for (const set2 of Object.values(resolverSource.sets ?? {})) {
10863
10863
  for (const source of set2.sources) {
10864
10864
  resolvePartials(source, { resolver: resolverSource, logger });
@@ -10883,7 +10883,7 @@ async function normalizeResolver(document, { logger, filename, req, src, yamlToM
10883
10883
  resolutionOrder: resolverSource.resolutionOrder,
10884
10884
  _source: {
10885
10885
  filename,
10886
- document
10886
+ document: document2
10887
10887
  }
10888
10888
  };
10889
10889
  }
@@ -11311,12 +11311,12 @@ async function loadResolver(inputs, { config, logger, req, yamlToMomoa }) {
11311
11311
  label: "init"
11312
11312
  };
11313
11313
  for (const input of inputs) {
11314
- let document;
11314
+ let document2;
11315
11315
  if (typeof input.src === "string") {
11316
11316
  if (maybeRawJSON(input.src)) {
11317
- document = toMomoa(input.src);
11317
+ document2 = toMomoa(input.src);
11318
11318
  } else if (yamlToMomoa) {
11319
- document = yamlToMomoa(input.src);
11319
+ document2 = yamlToMomoa(input.src);
11320
11320
  } else {
11321
11321
  logger.error({
11322
11322
  ...entry,
@@ -11329,14 +11329,14 @@ async function loadResolver(inputs, { config, logger, req, yamlToMomoa }) {
11329
11329
  });
11330
11330
  }
11331
11331
  } else if (input.src && typeof input.src === "object") {
11332
- document = toMomoa(JSON.stringify(input.src, void 0, 2));
11332
+ document2 = toMomoa(JSON.stringify(input.src, void 0, 2));
11333
11333
  } else {
11334
11334
  logger.error({
11335
11335
  ...entry,
11336
11336
  message: `Could not parse ${input.filename}. Is this valid JSON or YAML?`
11337
11337
  });
11338
11338
  }
11339
- if (!document || !isLikelyResolver(document)) {
11339
+ if (!document2 || !isLikelyResolver(document2)) {
11340
11340
  continue;
11341
11341
  }
11342
11342
  if (inputs.length > 1) {
@@ -11345,7 +11345,7 @@ async function loadResolver(inputs, { config, logger, req, yamlToMomoa }) {
11345
11345
  message: `Resolver must be the only input, found ${inputs.length} sources.`
11346
11346
  });
11347
11347
  }
11348
- resolverDoc = document;
11348
+ resolverDoc = document2;
11349
11349
  break;
11350
11350
  }
11351
11351
  let resolver;
@@ -11629,7 +11629,7 @@ function simpleFlatten(tokens, { logger }) {
11629
11629
  async function loadSources(inputs, { config, logger, req, continueOnError, yamlToMomoa, resolveAliases: resolveAliases3 = true, transform: transform2 }) {
11630
11630
  const entry = { group: "parser", label: "init" };
11631
11631
  const firstLoad = performance.now();
11632
- let document = {};
11632
+ let document2 = {};
11633
11633
  const sources = inputs.map((input, i) => ({
11634
11634
  ...input,
11635
11635
  document: {},
@@ -11643,7 +11643,7 @@ async function loadSources(inputs, { config, logger, req, continueOnError, yamlT
11643
11643
  parse: transform2 ? transformer(transform2) : void 0,
11644
11644
  yamlToMomoa
11645
11645
  });
11646
- document = result.document;
11646
+ document2 = result.document;
11647
11647
  sourceByFilename = result.sources;
11648
11648
  for (const [filename, source] of Object.entries(result.sources)) {
11649
11649
  const i = sources.findIndex((s) => s.filename.href === filename);
@@ -11670,8 +11670,8 @@ async function loadSources(inputs, { config, logger, req, continueOnError, yamlT
11670
11670
  logger.debug({ ...entry, message: `JSON loaded`, timing: performance.now() - firstLoad });
11671
11671
  const rootSource = {
11672
11672
  filename: sources[0].filename,
11673
- document,
11674
- src: print(document, { indent: 2 }).replaceAll(String.raw`\/`, "/")
11673
+ document: document2,
11674
+ src: print(document2, { indent: 2 }).replaceAll(String.raw`\/`, "/")
11675
11675
  };
11676
11676
  return {
11677
11677
  tokens: processTokens(rootSource, {
@@ -11686,17 +11686,17 @@ async function loadSources(inputs, { config, logger, req, continueOnError, yamlT
11686
11686
  }
11687
11687
  function transformer(transform2) {
11688
11688
  return async (src, filename) => {
11689
- let document = toMomoa(src);
11689
+ let document2 = toMomoa(src);
11690
11690
  let lastPath = "#/";
11691
11691
  let last$type;
11692
11692
  if (transform2.root) {
11693
- const result = transform2.root(document, { filename, parent: void 0, path: [] });
11693
+ const result = transform2.root(document2, { filename, parent: void 0, path: [] });
11694
11694
  if (result) {
11695
- document = result;
11695
+ document2 = result;
11696
11696
  }
11697
11697
  }
11698
- const isResolver = isLikelyResolver(document);
11699
- traverse(document, {
11698
+ const isResolver = isLikelyResolver(document2);
11699
+ traverse(document2, {
11700
11700
  enter(node2, parent, rawPath) {
11701
11701
  const path = isResolver ? filterResolverPaths(rawPath) : rawPath;
11702
11702
  if (node2.type !== "Object" || path.length === 0) {
@@ -11729,7 +11729,7 @@ function transformer(transform2) {
11729
11729
  }
11730
11730
  }
11731
11731
  });
11732
- return document;
11732
+ return document2;
11733
11733
  };
11734
11734
  }
11735
11735
 
@@ -13213,8 +13213,8 @@ function refs(sources, inline) {
13213
13213
  return [];
13214
13214
  });
13215
13215
  }
13216
- function resolverLayout(document, themeModifier) {
13217
- const doc = document ?? {};
13216
+ function resolverLayout(document2, themeModifier) {
13217
+ const doc = document2 ?? {};
13218
13218
  const inline = { count: 0 };
13219
13219
  const order = (doc.resolutionOrder ?? []).map((entry) => /^#\/sets\/(.+)$/.exec(String(entry?.$ref ?? ""))?.[1]).filter((name) => name !== void 0);
13220
13220
  const setNames = order.length > 0 ? order : Object.keys(doc.sets ?? {});
@@ -13588,13 +13588,13 @@ var YOUI_TYPES = /* @__PURE__ */ new Set(["spring", "focusRing"]);
13588
13588
  async function validateSets(repoRoot, system, resolverText) {
13589
13589
  const resolverFile = join2(repoRoot, system.tokens);
13590
13590
  const where2 = (file) => toPosix(relative(repoRoot, file));
13591
- let document;
13591
+ let document2;
13592
13592
  try {
13593
- document = JSON.parse(resolverText);
13593
+ document2 = JSON.parse(resolverText);
13594
13594
  } catch (error) {
13595
13595
  throw new DefinitionError(where2(resolverFile), [`not valid JSON: ${error instanceof Error ? error.message : String(error)}`]);
13596
13596
  }
13597
- const files = resolverLayout(document, system.themeModifier).files.map((ref) => join2(dirname2(resolverFile), ref));
13597
+ const files = resolverLayout(document2, system.themeModifier).files.map((ref) => join2(dirname2(resolverFile), ref));
13598
13598
  const sources = await Promise.all(
13599
13599
  files.map(async (file) => {
13600
13600
  try {
@@ -15902,8 +15902,8 @@ var ExportOrigins = class {
15902
15902
  const found = binding ? await follow(binding.specifier, binding.imported) : null;
15903
15903
  if (!found) return null;
15904
15904
  const change = this.changes.get(found.old);
15905
- const rename = change.renameBarrels || this.elements.isOwned(file) || this.elements.implementationFiles.has(file);
15906
- return { ...found, next: found.next === null ? null : rename && name === found.old ? change.to : name };
15905
+ const rename2 = change.renameBarrels || this.elements.isOwned(file) || this.elements.implementationFiles.has(file);
15906
+ return { ...found, next: found.next === null ? null : rename2 && name === found.old ? change.to : name };
15907
15907
  }
15908
15908
  for (const specifier of module.starExports) {
15909
15909
  const found = await follow(specifier, name);
@@ -20749,7 +20749,7 @@ function composeOf(itemName, exports, label) {
20749
20749
  const main = components.find((e) => e === PASCAL(itemName)) ?? components[0];
20750
20750
  if (!main) return null;
20751
20751
  const has = (suffix) => components.includes(`${main}${suffix}`) ? `${main}${suffix}` : null;
20752
- const [input, list, item, group, trigger, content, header, title, description, footer] = ["Input", "List", "Item", "Group", "Trigger", "Content", "Header", "Title", "Description", "Footer"].map(has);
20752
+ const [input, list, item, group, trigger, content, header, title, description, footer, menu] = ["Input", "List", "Item", "Group", "Trigger", "Content", "Header", "Title", "Description", "Footer", "Menu"].map(has);
20753
20753
  if (list && item) {
20754
20754
  const items = ["Calendar", "Search emoji", "Calculator"].map((text) => node(item, {}, [text]));
20755
20755
  return node(main, { style: { minWidth: 220 } }, [...input ? [node(input, { placeholder: "Type a command or search\u2026" })] : [], node(list, {}, group ? [node(group, { heading: "Suggestions" }, items)] : items)]);
@@ -20761,6 +20761,15 @@ function composeOf(itemName, exports, label) {
20761
20761
  node(content, { value: "password" }, ["Change your password here."])
20762
20762
  ]);
20763
20763
  }
20764
+ if (menu && trigger) {
20765
+ return node(main, {}, ["File", "Edit", "View"].map((text) => node(menu, {}, [node(trigger, {}, [text]), ...content && item ? [node(content, {}, [node(item, {}, ["New tab"])])] : []])));
20766
+ }
20767
+ if (item && trigger && content) {
20768
+ return node(main, { type: "single", collapsible: true, defaultValue: "item-1", style: { width: 320 } }, [
20769
+ node(item, { value: "item-1" }, [node(trigger, {}, ["Is it accessible?"]), node(content, {}, ["Yes, with your tokens."])]),
20770
+ node(item, { value: "item-2" }, [node(trigger, {}, ["Is it styled?"]), node(content, {}, ["In your theme."])])
20771
+ ]);
20772
+ }
20764
20773
  if (trigger && content) {
20765
20774
  const head = header ? [node(header, {}, [...title ? [node(title, {}, [label])] : [], ...description ? [node(description, {}, ["A preview of this part in your theme."])] : []])] : [...title ? [node(title, {}, [label])] : []];
20766
20775
  return node(main, { open: true }, [node(trigger, {}, [`Open ${label}`]), node(content, {}, head.length ? head : [label])]);
@@ -21014,6 +21023,7 @@ async function bundlePreview(job, options = {}) {
21014
21023
  if (message.startsWith("esbuild timed out")) return { error: `bundling took over ${limitOf(timeoutMs)} and was stopped` };
21015
21024
  return { error: `it did not bundle: ${message}` };
21016
21025
  }
21026
+ if (refusals.size > 0) return { error: [...refusals][0] };
21017
21027
  if (radix.size > 0) notes.add(`radix-ui is not installed: its ${[...radix.keys()].sort().join(", ")} ${radix.size === 1 ? "comes" : "come"} from ${[...new Set(radix.values())].sort().join(", ")}`);
21018
21028
  if (fromHub.size > 0) notes.add(`${[...fromHub].sort().join(", ")}: not installed in your project, so the hub's own ${fromHub.size === 1 ? "copy draws it" : "copies draw them"}`);
21019
21029
  const inputs = [];
@@ -21269,7 +21279,7 @@ var Eyes = class {
21269
21279
  }
21270
21280
  async open() {
21271
21281
  if (this.browser) return this.browser;
21272
- const { launchBrowser } = await import("./src-VEHGMKYV.js");
21282
+ const { launchBrowser } = await import("./src-DS43LCRA.js");
21273
21283
  try {
21274
21284
  this.browser = await launchBrowser(this.options.executablePath, { purpose: { what: "youiyoux render", command: "youiyoux render" }, ...this.options.download === false ? { download: false } : {}, ...this.options.log ? { log: this.options.log } : {} });
21275
21285
  } catch (error) {
@@ -21625,6 +21635,344 @@ function shotsText(report, again = (t) => `run youiyoux render${t ? ` ${t}` : ""
21625
21635
  return lines.join("\n");
21626
21636
  }
21627
21637
 
21638
+ // ../scanner/src/screens/capture.ts
21639
+ import { readFileSync as readFileSync7 } from "node:fs";
21640
+ import { rename, writeFile } from "node:fs/promises";
21641
+ import { join as join19 } from "node:path";
21642
+
21643
+ // ../scanner/src/screens/locate.ts
21644
+ import { realpathSync } from "node:fs";
21645
+ import { posix as posix7 } from "node:path";
21646
+ var MAX_PLACES = 4e3;
21647
+ function locateInPage(limit, maxFrames = 6) {
21648
+ const size = { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight };
21649
+ const roots = [];
21650
+ for (const element of document.querySelectorAll("*")) {
21651
+ const key = Object.keys(element).find((k) => k.startsWith("__reactContainer$"));
21652
+ if (!key) continue;
21653
+ const container = element[key];
21654
+ roots.push(container.stateNode?.current ?? container);
21655
+ }
21656
+ if (roots.length === 0) return { react: false, dev: false, size, places: [], capped: false };
21657
+ const COMPONENT = /* @__PURE__ */ new Set([0, 1, 11, 14, 15]);
21658
+ const nameOf = (type2) => {
21659
+ const t = type2;
21660
+ return t?.displayName || t?.name || t?.render?.displayName || t?.render?.name || t?.type?.displayName || t?.type?.name || null;
21661
+ };
21662
+ const INTERNAL = /\/node_modules\/|\/\.vite\/deps\/|\/_next\/static\/chunks\/(?:framework|main|webpack)|react-dom|jsx-dev-runtime|jsx-runtime/;
21663
+ const framesOf = (stack) => {
21664
+ const frames = [];
21665
+ for (const text of (stack ?? "").split("\n").slice(1)) {
21666
+ if (/react[-_]stack[-_]bottom[-_]frame/.test(text)) break;
21667
+ const match = /((?:https?|file):\/\/[^\s()]+?):(\d+):(\d+)\)?\s*$/.exec(text);
21668
+ if (!match || INTERNAL.test(match[1])) continue;
21669
+ frames.push({ url: match[1], line: Number(match[2]), column: Number(match[3]) });
21670
+ if (frames.length >= maxFrames) break;
21671
+ }
21672
+ return frames;
21673
+ };
21674
+ const boxOf = (fiber) => {
21675
+ let left = Infinity;
21676
+ let top = Infinity;
21677
+ let right = -Infinity;
21678
+ let bottom = -Infinity;
21679
+ const walk = (first) => {
21680
+ for (let node2 = first; node2; node2 = node2.sibling) {
21681
+ if (node2.tag === 5) {
21682
+ const rect = node2.stateNode?.getBoundingClientRect?.();
21683
+ if (rect && rect.width > 0 && rect.height > 0) {
21684
+ left = Math.min(left, rect.left);
21685
+ top = Math.min(top, rect.top);
21686
+ right = Math.max(right, rect.right);
21687
+ bottom = Math.max(bottom, rect.bottom);
21688
+ }
21689
+ } else if (node2.tag !== 6) walk(node2.child);
21690
+ }
21691
+ };
21692
+ walk(fiber.child);
21693
+ if (!Number.isFinite(left)) return null;
21694
+ return { x: Math.round(left + scrollX), y: Math.round(top + scrollY), width: Math.round(right - left), height: Math.round(bottom - top) };
21695
+ };
21696
+ const places = [];
21697
+ let dev = false;
21698
+ let capped = false;
21699
+ const visit = (fiber, depth) => {
21700
+ for (let node2 = fiber; node2; node2 = node2.sibling) {
21701
+ let inner = depth;
21702
+ if (COMPONENT.has(node2.tag)) {
21703
+ if (node2._debugStack) dev = true;
21704
+ const box = boxOf(node2);
21705
+ const name = nameOf(node2.type);
21706
+ if (box && name) {
21707
+ if (places.length >= limit) {
21708
+ capped = true;
21709
+ return;
21710
+ }
21711
+ places.push({ name, owner: nameOf(node2._debugOwner?.type), frames: framesOf(node2._debugStack?.stack), box, depth });
21712
+ }
21713
+ inner = depth + 1;
21714
+ }
21715
+ visit(node2.child, inner);
21716
+ if (capped) return;
21717
+ }
21718
+ };
21719
+ for (const root of roots) visit(root.child, 0);
21720
+ return { react: true, dev, size, places, capped };
21721
+ }
21722
+ var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
21723
+ var DIGIT = new Map([...BASE64].map((c, i) => [c, i]));
21724
+ function decodeMap(map) {
21725
+ if (!Array.isArray(map.sources) || typeof map.mappings !== "string") return null;
21726
+ const root = typeof map.sourceRoot === "string" && map.sourceRoot ? map.sourceRoot.replace(/\/?$/, "/") : "";
21727
+ const sources = map.sources.map((s) => typeof s === "string" ? `${root}${s}` : "");
21728
+ const lines = [];
21729
+ let source = 0;
21730
+ let line2 = 0;
21731
+ let column = 0;
21732
+ for (const text of map.mappings.split(";")) {
21733
+ const segments = [];
21734
+ let generated = 0;
21735
+ for (const part2 of text.split(",")) {
21736
+ if (!part2) continue;
21737
+ const values = [];
21738
+ let value = 0;
21739
+ let shift = 0;
21740
+ for (const char of part2) {
21741
+ const digit = DIGIT.get(char);
21742
+ if (digit === void 0) return null;
21743
+ value += (digit & 31) << shift;
21744
+ if (digit & 32) shift += 5;
21745
+ else {
21746
+ values.push(value & 1 ? -(value >>> 1) : value >>> 1);
21747
+ value = 0;
21748
+ shift = 0;
21749
+ }
21750
+ }
21751
+ generated += values[0] ?? 0;
21752
+ if (values.length >= 4) {
21753
+ source += values[1];
21754
+ line2 += values[2];
21755
+ column += values[3];
21756
+ segments.push([generated, source, line2, column]);
21757
+ }
21758
+ }
21759
+ lines.push(segments);
21760
+ }
21761
+ return { sources, lines };
21762
+ }
21763
+ function originalPosition(map, line2, column) {
21764
+ const segments = map.lines[line2 - 1];
21765
+ if (!segments?.length) return null;
21766
+ let found = null;
21767
+ for (const segment of segments) {
21768
+ if (segment[0] > column - 1) break;
21769
+ found = segment;
21770
+ }
21771
+ found ??= segments[0];
21772
+ const source = map.sources[found[1]];
21773
+ return source === void 0 ? null : { source, line: found[2] + 1, column: found[3] + 1 };
21774
+ }
21775
+ async function sourceMapOf(url, text, fetchText) {
21776
+ const at = text.lastIndexOf("sourceMappingURL=");
21777
+ if (at < 0 || !/\/\/[#@]\s*$/.test(text.slice(Math.max(0, at - 8), at))) return null;
21778
+ const target = text.slice(at + "sourceMappingURL=".length).split(/\s/, 1)[0];
21779
+ if (!target) return null;
21780
+ let json;
21781
+ if (target.startsWith("data:")) {
21782
+ const at2 = target.indexOf(",");
21783
+ const payload = target.slice(at2 + 1);
21784
+ json = /;base64/.test(target.slice(0, at2)) ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
21785
+ } else json = await fetchText(new URL(target, url).href);
21786
+ if (!json) return null;
21787
+ try {
21788
+ return decodeMap(JSON.parse(json));
21789
+ } catch {
21790
+ return null;
21791
+ }
21792
+ }
21793
+ function projectPath(source, moduleUrl, root) {
21794
+ let path;
21795
+ const webpack = /^webpack:\/\/[^/]*\/(.*)$/.exec(source);
21796
+ if (webpack) path = `/${webpack[1].replace(/^\.\//, "")}`;
21797
+ else if (/^[a-z]+:\/\//i.test(source) && !source.startsWith("file://")) path = new URL(source).pathname;
21798
+ else if (source.startsWith("file://")) path = new URL(source).pathname;
21799
+ else if (source.startsWith("/")) path = source;
21800
+ else path = new URL(source, moduleUrl).pathname;
21801
+ path = decodeURIComponent(path).replace(/^\/@fs\//, "/");
21802
+ for (const base of root ? /* @__PURE__ */ new Set([root, realOrSelf(root)]) : []) {
21803
+ const prefix = base.replace(/\\/g, "/").replace(/\/?$/, "/");
21804
+ if (path.startsWith(prefix)) return posix7.normalize(path.slice(prefix.length));
21805
+ }
21806
+ if (/^\/(?:Users|home|private|var|tmp|opt|mnt|[A-Za-z]:)\//.test(path)) return null;
21807
+ const relative6 = posix7.normalize(path.replace(/^\/+/, ""));
21808
+ return relative6.startsWith("..") || relative6 === "." ? null : relative6;
21809
+ }
21810
+ function realOrSelf(path) {
21811
+ try {
21812
+ return realpathSync(path);
21813
+ } catch {
21814
+ return path;
21815
+ }
21816
+ }
21817
+ async function resolvePlaces(raw, fetchText, root = null) {
21818
+ const maps = /* @__PURE__ */ new Map();
21819
+ const mapFor = (url) => {
21820
+ const module = url.replace(/[?#].*$/, "");
21821
+ let found = maps.get(module);
21822
+ if (!found) {
21823
+ found = fetchText(url).then((text) => text === null ? null : sourceMapOf(url, text, fetchText), () => null);
21824
+ maps.set(module, found);
21825
+ }
21826
+ return found;
21827
+ };
21828
+ return Promise.all(
21829
+ raw.map(async (place) => {
21830
+ const base = { name: place.name, owner: place.owner, box: place.box, depth: place.depth };
21831
+ for (const frame of place.frames) {
21832
+ const map = await mapFor(frame.url);
21833
+ const original = map ? originalPosition(map, frame.line, frame.column) : null;
21834
+ if (!original) continue;
21835
+ if (/(?:^|\/)node_modules\/|^webpack\/|^\(webpack\)/.test(original.source)) continue;
21836
+ const file = projectPath(original.source, frame.url, root);
21837
+ if (file) return { ...base, file, line: original.line, column: original.column };
21838
+ }
21839
+ const unmapped = place.frames[0];
21840
+ return { ...base, file: unmapped ? projectPath(unmapped.url.replace(/[?#].*$/, ""), unmapped.url, null) : null, line: null, column: null };
21841
+ })
21842
+ );
21843
+ }
21844
+
21845
+ // ../scanner/src/screens/capture.ts
21846
+ var SCREENS_SCHEMA = "youiyoux.screens/v1";
21847
+ var PLACES_SCHEMA = "youiyoux.places/v1";
21848
+ var SCHEMES2 = ["light", "dark"];
21849
+ var PICTURE_SCALE = 2;
21850
+ var FULL_SCALE = PICTURE_SCALE;
21851
+ var THUMB_SCALE = 0.5;
21852
+ var SETTLE_MS = 1200;
21853
+ var NAVIGATION_TIMEOUT_MS = 3e4;
21854
+ var MAX_VIEWPORTS = 6;
21855
+ var WEBP_QUALITY = 0.9;
21856
+ function screenSlug(route) {
21857
+ if (route === "*") return "app-shell";
21858
+ if (route === "?") return "unrouted";
21859
+ return route.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "root";
21860
+ }
21861
+ function readScreensSpec(dir) {
21862
+ const file = join19(dir, "screens.json");
21863
+ let value;
21864
+ try {
21865
+ value = JSON.parse(readFileSync7(file, "utf8"));
21866
+ } catch (error) {
21867
+ throw new Error(`cannot read ${file}: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
21868
+ }
21869
+ const valid = value.schema === SCREENS_SCHEMA && typeof value.project === "string" && typeof value.source === "string" && typeof value.viewport?.width === "number" && typeof value.viewport.height === "number" && Array.isArray(value.screens) && value.screens.every((s) => typeof s?.route === "string" && typeof s.path === "string");
21870
+ if (!valid) throw new Error(`${file} is not a ${SCREENS_SCHEMA} document: it needs project, source, viewport { width, height } and screens [{ route, path }]`);
21871
+ const slugs = /* @__PURE__ */ new Map();
21872
+ for (const { route } of value.screens) {
21873
+ const slug2 = screenSlug(route);
21874
+ if (slugs.has(slug2)) throw new Error(`${file}: routes ${slugs.get(slug2)} and ${route} would share the file name ${slug2}`);
21875
+ slugs.set(slug2, route);
21876
+ }
21877
+ return value;
21878
+ }
21879
+ async function writeBytes(file, bytes) {
21880
+ const temporary = `${file}.${process.pid}.tmp`;
21881
+ await writeFile(temporary, bytes);
21882
+ await rename(temporary, file);
21883
+ }
21884
+ async function encode(page, png, scale) {
21885
+ const url = await page.evaluate(
21886
+ async ({ data, scale: scale2, quality }) => {
21887
+ const image = new Image();
21888
+ image.src = `data:image/png;base64,${data}`;
21889
+ await image.decode();
21890
+ const canvas = document.createElement("canvas");
21891
+ canvas.width = Math.max(1, Math.round(image.naturalWidth * scale2));
21892
+ canvas.height = Math.max(1, Math.round(image.naturalHeight * scale2));
21893
+ const context = canvas.getContext("2d");
21894
+ context.imageSmoothingQuality = "high";
21895
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
21896
+ return canvas.toDataURL("image/webp", quality);
21897
+ },
21898
+ { data: png.toString("base64"), scale, quality: WEBP_QUALITY }
21899
+ );
21900
+ if (!url.startsWith("data:image/webp;base64,")) throw new Error("this Chromium cannot encode WebP");
21901
+ return Buffer.from(url.slice("data:image/webp;base64,".length), "base64");
21902
+ }
21903
+ var sentence = (error) => (error instanceof Error ? error.message : String(error)).split("\n")[0].replace(/\.$/, "");
21904
+ async function captureScreens(dir, options) {
21905
+ const spec = readScreensSpec(dir);
21906
+ const unknown = (options.routes ?? []).filter((route) => !spec.screens.some((s) => s.route === route));
21907
+ if (unknown.length) throw new Error(`${join19(dir, "screens.json")} has no route ${unknown.join(", ")}: it lists ${spec.screens.map((s) => s.route).join(", ")}`);
21908
+ const chosen = options.routes?.length ? spec.screens.filter((s) => options.routes.includes(s.route)) : spec.screens;
21909
+ const log = options.log ?? (() => void 0);
21910
+ const { width, height } = spec.viewport;
21911
+ const results = /* @__PURE__ */ new Map();
21912
+ let dev = false;
21913
+ let react = false;
21914
+ for (const scheme of SCHEMES2) {
21915
+ const context = await options.browser.newContext({ viewport: { width, height }, deviceScaleFactor: FULL_SCALE, colorScheme: scheme, reducedMotion: "reduce", ...options.storageState ? { storageState: options.storageState } : {} });
21916
+ try {
21917
+ const page = await context.newPage();
21918
+ const encoder = await context.newPage();
21919
+ for (const screen of chosen) {
21920
+ const slug2 = screenSlug(screen.route);
21921
+ if (results.get(screen.route)?.error) continue;
21922
+ try {
21923
+ const target = new URL(screen.path, options.base).href;
21924
+ await page.goto(target, { waitUntil: "load", timeout: NAVIGATION_TIMEOUT_MS });
21925
+ await page.evaluate(() => document.fonts?.ready.then(() => void 0));
21926
+ await page.waitForTimeout(SETTLE_MS);
21927
+ let located = scheme === "light" ? await page.evaluate(locateInPage, MAX_PLACES) : null;
21928
+ if (located && !located.react) {
21929
+ await page.waitForLoadState("load");
21930
+ await page.waitForTimeout(SETTLE_MS * 2);
21931
+ located = await page.evaluate(locateInPage, MAX_PLACES);
21932
+ }
21933
+ const pageHeight = located?.size.height ?? await page.evaluate(() => document.documentElement.scrollHeight);
21934
+ const clip = { x: 0, y: 0, width, height: Math.min(Math.max(pageHeight, height), height * MAX_VIEWPORTS) };
21935
+ const png = await page.screenshot({ fullPage: true, clip });
21936
+ await writeBytes(join19(dir, `${slug2}.${scheme}.webp`), await encode(encoder, png, 1));
21937
+ await writeBytes(join19(dir, `${slug2}.${scheme}.thumb.webp`), await encode(encoder, png, THUMB_SCALE / FULL_SCALE));
21938
+ if (located) {
21939
+ react ||= located.react;
21940
+ dev ||= located.dev;
21941
+ const places = await resolvePlaces(located.places, async (url) => {
21942
+ const response = await fetch(url).catch(() => null);
21943
+ return response?.ok ? response.text() : null;
21944
+ }, options.root ?? null);
21945
+ const file = { schema: PLACES_SCHEMA, route: screen.route, path: screen.path, viewport: spec.viewport, size: { width, height: clip.height }, dev: located.dev, capped: located.capped, places: places.filter((p3) => p3.box.y < clip.height) };
21946
+ await writeFileAtomic(join19(dir, `${slug2}.places.json`), `${JSON.stringify(file)}
21947
+ `);
21948
+ results.set(screen.route, { placed: file.places.length, lined: file.places.filter((p3) => p3.line !== null).length, error: null });
21949
+ }
21950
+ log(`${screen.route} (${scheme}) \u2192 ${slug2}.${scheme}.webp${located ? `, ${results.get(screen.route).placed} components placed` : ""}`);
21951
+ } catch (error) {
21952
+ results.set(screen.route, { placed: 0, lined: 0, error: `${sentence(error)} (${screen.path})` });
21953
+ log(`${screen.route} (${scheme}): ${sentence(error)}`);
21954
+ }
21955
+ }
21956
+ } finally {
21957
+ await context.close();
21958
+ }
21959
+ }
21960
+ const now = (options.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
21961
+ if (chosen === spec.screens) await writeFileAtomic(join19(dir, "screens.json"), `${JSON.stringify({ ...spec, capturedAt: now }, null, 2)}
21962
+ `);
21963
+ const screens = chosen.map((s) => ({ route: s.route, path: s.path, ...results.get(s.route) ?? { placed: 0, lined: 0, error: "not captured" } }));
21964
+ return { dir, project: spec.project, screens, production: react && !dev, noReact: !react && screens.some((s) => !s.error) };
21965
+ }
21966
+ function captureText(report) {
21967
+ const ok = report.screens.filter((s) => !s.error);
21968
+ const lines = [`${ok.length} of ${report.screens.length} screens of ${report.project} captured \u2192 ${report.dir}`];
21969
+ for (const s of report.screens) lines.push(s.error ? ` \u2716 ${s.route}: ${s.error}` : ` \u2713 ${s.route}: ${s.placed} components placed, ${s.lined} with their line`);
21970
+ if (report.noReact) lines.push("No React on these pages, so nothing is placed: the pictures are kept without places.");
21971
+ else if (report.production) lines.push("These pages are a production build: components are placed but have no lines. Run the app in development (vite, next dev) and capture again.");
21972
+ lines.push(ok.length ? "Next: youiyoux ui --project <dir> shows them on the Screens page, each component selectable." : "Next: start the app, check --base, and capture again.");
21973
+ return lines.join("\n");
21974
+ }
21975
+
21628
21976
  export {
21629
21977
  parseCssColor,
21630
21978
  resolverLayout,
@@ -21793,5 +22141,19 @@ export {
21793
22141
  compareA11yIssues,
21794
22142
  renderShots,
21795
22143
  shotsNext,
21796
- shotsText
22144
+ shotsText,
22145
+ MAX_PLACES,
22146
+ locateInPage,
22147
+ decodeMap,
22148
+ originalPosition,
22149
+ sourceMapOf,
22150
+ projectPath,
22151
+ resolvePlaces,
22152
+ SCREENS_SCHEMA,
22153
+ PLACES_SCHEMA,
22154
+ PICTURE_SCALE,
22155
+ screenSlug,
22156
+ readScreensSpec,
22157
+ captureScreens,
22158
+ captureText
21797
22159
  };