@hyperframes/inspector 0.8.155 → 0.8.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/live.js CHANGED
@@ -11,64 +11,64 @@ function collectElementDom() {
11
11
  const nodes = [];
12
12
  const paths = /* @__PURE__ */ new Map();
13
13
  const siblingGroups = /* @__PURE__ */ new WeakMap();
14
- function siblingCount(element2, selector) {
15
- const owner = element2.parentElement ?? element2;
14
+ function siblingCount(element, selector) {
15
+ const owner = element.parentElement ?? element;
16
16
  let counts = siblingGroups.get(owner);
17
17
  if (!counts) {
18
18
  counts = /* @__PURE__ */ new Map();
19
19
  siblingGroups.set(owner, counts);
20
20
  }
21
21
  if (!counts.has(selector)) {
22
- const siblings = element2.parentElement ? [...element2.parentElement.children] : [element2];
22
+ const siblings = element.parentElement ? [...element.parentElement.children] : [element];
23
23
  counts.set(selector, siblings.filter((sibling) => sibling.matches(selector)).length);
24
24
  }
25
25
  return counts.get(selector);
26
26
  }
27
27
  const quote = (value) => JSON.stringify(value);
28
- function path(element2) {
29
- if (paths.has(element2)) return paths.get(element2);
28
+ function path(element) {
29
+ if (paths.has(element)) return paths.get(element);
30
30
  const candidates = [];
31
- if (element2.id) candidates.push(`#${CSS.escape(element2.id)}`);
32
- const hfId = element2.getAttribute("data-hf-id");
31
+ if (element.id) candidates.push(`#${CSS.escape(element.id)}`);
32
+ const hfId = element.getAttribute("data-hf-id");
33
33
  if (hfId) candidates.push(`[data-hf-id=${quote(hfId)}]`);
34
34
  const unique = candidates.find((selector2) => document.querySelectorAll(selector2).length === 1);
35
- const parent = element2.parentElement;
36
- const tag = element2.localName;
37
- const position2 = parent ? [...parent.children].indexOf(element2) + 1 : 1;
35
+ const parent = element.parentElement;
36
+ const tag = element.localName;
37
+ const position2 = parent ? [...parent.children].indexOf(element) + 1 : 1;
38
38
  const selector = unique ?? (parent ? `${path(parent)} > ${CSS.escape(tag)}:nth-child(${position2})` : CSS.escape(tag));
39
- paths.set(element2, selector);
39
+ paths.set(element, selector);
40
40
  return selector;
41
41
  }
42
- function visit(element2, parent) {
43
- if (excluded2.has(element2.tagName)) return;
44
- const selector = path(element2);
45
- if (document.querySelectorAll(selector).length !== 1 || document.querySelector(selector) !== element2) {
42
+ function visit(element, parent) {
43
+ if (excluded2.has(element.tagName)) return;
44
+ const selector = path(element);
45
+ if (document.querySelectorAll(selector).length !== 1 || document.querySelector(selector) !== element) {
46
46
  throw new Error(`Element map selector does not resolve uniquely: ${selector}`);
47
47
  }
48
- const classes = [...element2.classList].sort();
49
- const tag = element2.localName;
48
+ const classes = [...element.classList].sort();
49
+ const tag = element.localName;
50
50
  const simple = `${CSS.escape(tag)}${classes.map((value) => `.${CSS.escape(value)}`).join("")}`;
51
- const siblings = element2.parentElement ? [...element2.parentElement.children] : [element2];
51
+ const siblings = element.parentElement ? [...element.parentElement.children] : [element];
52
52
  const index = nodes.length;
53
53
  const node = {
54
54
  index,
55
55
  parent,
56
56
  selector,
57
57
  tag,
58
- id: element2.id,
59
- hfId: element2.getAttribute("data-hf-id"),
58
+ id: element.id,
59
+ hfId: element.getAttribute("data-hf-id"),
60
60
  classes,
61
- composition: element2.getAttribute("data-composition-id"),
62
- compositionSrc: element2.getAttribute("data-composition-src"),
63
- text: [...element2.childNodes].filter((child) => child.nodeType === 3).map((child) => child.textContent).join("").replace(/\s+/g, " ").trim(),
64
- media: ["img", "video", "audio", "source", "iframe"].includes(tag) ? element2.getAttribute("src") : null,
65
- relative: element2.id && document.querySelectorAll(`#${CSS.escape(element2.id)}`).length === 1 ? `#${CSS.escape(element2.id)}` : siblingCount(element2, simple) === 1 ? simple : `${CSS.escape(tag)}:nth-child(${siblings.indexOf(element2) + 1})`,
61
+ composition: element.getAttribute("data-composition-id"),
62
+ compositionSrc: element.getAttribute("data-composition-src"),
63
+ text: [...element.childNodes].filter((child) => child.nodeType === 3).map((child) => child.textContent).join("").replace(/\s+/g, " ").trim(),
64
+ media: ["img", "video", "audio", "source", "iframe"].includes(tag) ? element.getAttribute("src") : null,
65
+ relative: element.id && document.querySelectorAll(`#${CSS.escape(element.id)}`).length === 1 ? `#${CSS.escape(element.id)}` : siblingCount(element, simple) === 1 ? simple : `${CSS.escape(tag)}:nth-child(${siblings.indexOf(element) + 1})`,
66
66
  groupSelector: simple,
67
- siblingMatchCount: siblingCount(element2, simple),
67
+ siblingMatchCount: siblingCount(element, simple),
68
68
  children: []
69
69
  };
70
70
  nodes.push(node);
71
- for (const child of element2.children) {
71
+ for (const child of element.children) {
72
72
  const childIndex = visit(child, index);
73
73
  if (childIndex !== void 0) node.children.push(childIndex);
74
74
  }
@@ -262,14 +262,14 @@ var PREVIEW_IGNORED_DIRS = /* @__PURE__ */ new Set([
262
262
 
263
263
  // src/sources.ts
264
264
  var starts = (text) => [0, ...[...text.matchAll(/\n/g)].map((m) => m.index + 1)];
265
- function position(lines, offset2) {
265
+ function position(lines, offset) {
266
266
  let lo = 0, hi = lines.length - 1;
267
267
  while (lo < hi) {
268
268
  const mid = Math.ceil((lo + hi) / 2);
269
- if (lines[mid] <= offset2) lo = mid;
269
+ if (lines[mid] <= offset) lo = mid;
270
270
  else hi = mid - 1;
271
271
  }
272
- return { line: lo + 1, column: offset2 - lines[lo] };
272
+ return { line: lo + 1, column: offset - lines[lo] };
273
273
  }
274
274
  function occurrences(text, needle) {
275
275
  const hits = [];
@@ -413,7 +413,7 @@ var Sources = class {
413
413
  chunks = [];
414
414
  cssRules = [];
415
415
  htmlTags = [];
416
- addChunk(file, source, offset2) {
416
+ addChunk(file, source, offset) {
417
417
  const text = source.trim();
418
418
  const lead = source.length - source.trimStart().length;
419
419
  if (text) {
@@ -422,7 +422,7 @@ var Sources = class {
422
422
  this.chunks.push({
423
423
  file,
424
424
  text,
425
- offset: offset2 + lead,
425
+ offset: offset + lead,
426
426
  get statements() {
427
427
  return ranges ??= statements(text);
428
428
  },
@@ -432,7 +432,7 @@ var Sources = class {
432
432
  });
433
433
  }
434
434
  }
435
- addCss(file, text, offset2) {
435
+ addCss(file, text, offset) {
436
436
  try {
437
437
  postcss.parse(text).walkRules((rule) => {
438
438
  const start = rule.source?.start?.offset;
@@ -442,14 +442,14 @@ var Sources = class {
442
442
  id: `css:${this.cssRules.length}`,
443
443
  selector: rule.selector,
444
444
  file,
445
- start: offset2 + start,
446
- end: offset2 + end + 1
445
+ start: offset + start,
446
+ end: offset + end + 1
447
447
  });
448
448
  });
449
449
  } catch {
450
450
  }
451
451
  }
452
- slice(file, start, end, kind, target2) {
452
+ slice(file, start, end, kind, target) {
453
453
  const source = this.files.get(file);
454
454
  if (!source) return null;
455
455
  const first = position(source.lines, start).line;
@@ -464,16 +464,16 @@ var Sources = class {
464
464
  startLine: first,
465
465
  endLine: last,
466
466
  kind: [kind],
467
- targets: [target2],
467
+ targets: [target],
468
468
  code,
469
469
  uniqueInFile: occurrences(source.text, code).length === 1
470
470
  };
471
471
  }
472
- markup(element2, target2) {
472
+ markup(element, target) {
473
473
  const tags = this.htmlTags.filter(
474
- (tag) => tag.tag === element2.tag && (element2.hfId ? tag.hfId === element2.hfId : element2.id ? tag.id === element2.id : element2.classes.length > 0 && element2.classes.every((c) => tag.classes.includes(c)))
474
+ (tag) => tag.tag === element.tag && (element.hfId ? tag.hfId === element.hfId : element.id ? tag.id === element.id : element.classes.length > 0 && element.classes.every((c) => tag.classes.includes(c)))
475
475
  );
476
- return tags.length === 1 ? this.slice(tags[0].file, tags[0].start, tags[0].end, "html opening tag", target2) : null;
476
+ return tags.length === 1 ? this.slice(tags[0].file, tags[0].start, tags[0].end, "html opening tag", target) : null;
477
477
  }
478
478
  mapper(html, provenance) {
479
479
  const htmlLines = starts(html);
@@ -492,29 +492,29 @@ var Sources = class {
492
492
  text,
493
493
  this.chunks.flatMap((chunk) => occurrences(text, chunk.text).map((at2) => ({ chunk, at: at2 })))
494
494
  );
495
- const locate = (text, offset2) => {
496
- const found = (ranges.get(text) ?? []).filter(({ chunk, at: at2 }) => offset2 >= at2 && offset2 < at2 + chunk.text.length).map(({ chunk, at: at2 }) => ({ chunk, local: offset2 - at2 }));
495
+ const locate = (text, offset) => {
496
+ const found = (ranges.get(text) ?? []).filter(({ chunk, at: at2 }) => offset >= at2 && offset < at2 + chunk.text.length).map(({ chunk, at: at2 }) => ({ chunk, local: offset - at2 }));
497
497
  const unique = new Map(
498
498
  found.map((hit) => [`${hit.chunk.file}:${hit.chunk.offset + hit.local}`, hit])
499
499
  );
500
500
  return unique.size === 1 ? [...unique.values()][0] : null;
501
501
  };
502
502
  const cache = /* @__PURE__ */ new Map();
503
- return (stack, target2) => {
503
+ return (stack, target) => {
504
504
  const cached = cache.get(stack);
505
- if (cached) return cached.map((snippet2) => ({ ...snippet2, targets: [target2] }));
505
+ if (cached) return cached.map((snippet) => ({ ...snippet, targets: [target] }));
506
506
  const result = [];
507
507
  for (const frame of stack.split("\n")) {
508
508
  const script = /(hf-inspect-[a-f0-9]+\.js):(\d+):(\d+)\)?$/.exec(frame);
509
509
  const m = /https?:\/\/[^/]+\/(?:index\.html)?:(\d+):(\d+)\)?$/.exec(frame);
510
510
  if (!m && !script) continue;
511
- const offset2 = m ? htmlLines[Number(m[1]) - 1] + Number(m[2]) - 1 : -1;
512
- let hit = m ? locate(html, offset2) : null;
511
+ const offset = m ? htmlLines[Number(m[1]) - 1] + Number(m[2]) - 1 : -1;
512
+ let hit = m ? locate(html, offset) : null;
513
513
  if (!hit)
514
514
  for (const map of maps) {
515
- if (script ? map.p.sourceURL !== script[1] : offset2 < map.at || offset2 >= map.at + map.p.output.length)
515
+ if (script ? map.p.sourceURL !== script[1] : offset < map.at || offset >= map.at + map.p.output.length)
516
516
  continue;
517
- const generated = script ? { line: Number(script[2]), column: Number(script[3]) - 1 } : position(map.lines, offset2 - map.at);
517
+ const generated = script ? { line: Number(script[2]), column: Number(script[3]) - 1 } : position(map.lines, offset - map.at);
518
518
  const original = originalPositionFor(map.map, generated);
519
519
  if (original.line != null && original.column != null)
520
520
  hit = locate(map.p.input, map.inputLines[original.line - 1] + original.column);
@@ -526,21 +526,21 @@ var Sources = class {
526
526
  (s) => s.type === "FunctionDeclaration" && hit.local >= s.start && hit.local < s.end && s.end - s.start <= 2e3
527
527
  ).sort((a, b) => a.end - a.start - (b.end - b.start))[0];
528
528
  const range = helper ?? enclosing;
529
- const snippet2 = this.slice(
529
+ const snippet = this.slice(
530
530
  hit.chunk.file,
531
531
  hit.chunk.offset + range.start,
532
532
  hit.chunk.offset + range.end,
533
533
  result.length ? "animation caller" : "animation creation",
534
- target2
534
+ target
535
535
  );
536
- if (snippet2) result.push(snippet2);
536
+ if (snippet) result.push(snippet);
537
537
  for (const dependency of hit.chunk.dependencies(range)) {
538
538
  const definition = this.slice(
539
539
  hit.chunk.file,
540
540
  hit.chunk.offset + dependency.start,
541
541
  hit.chunk.offset + dependency.end,
542
542
  "animation source dependency",
543
- target2
543
+ target
544
544
  );
545
545
  if (definition) result.push(definition);
546
546
  }
@@ -550,26 +550,26 @@ var Sources = class {
550
550
  };
551
551
  }
552
552
  };
553
- function markupSnippet(sources, element2, target2) {
554
- return sources.markup(element2, target2);
553
+ function markupSnippet(sources, element, target) {
554
+ return sources.markup(element, target);
555
555
  }
556
556
  function mergeSnippets(snippets, sources) {
557
557
  const sorted = snippets.sort((a, b) => a.file.localeCompare(b.file) || a.startLine - b.startLine);
558
558
  const output = [];
559
- for (const snippet2 of sorted) {
559
+ for (const snippet of sorted) {
560
560
  const last = output.at(-1);
561
- if (last && last.file === snippet2.file && snippet2.startLine <= last.endLine + 1) {
562
- last.endLine = Math.max(last.endLine, snippet2.endLine);
561
+ if (last && last.file === snippet.file && snippet.startLine <= last.endLine + 1) {
562
+ last.endLine = Math.max(last.endLine, snippet.endLine);
563
563
  last.id = `${last.file}:${last.startLine}-${last.endLine}`;
564
564
  const source = sources.files.get(last.file);
565
565
  last.code = source.text.slice(
566
566
  source.lines[last.startLine - 1],
567
567
  source.lines[last.endLine] ?? source.text.length
568
568
  );
569
- last.targets = [.../* @__PURE__ */ new Set([...last.targets, ...snippet2.targets])];
570
- last.kind = [.../* @__PURE__ */ new Set([...last.kind, ...snippet2.kind])];
569
+ last.targets = [.../* @__PURE__ */ new Set([...last.targets, ...snippet.targets])];
570
+ last.kind = [.../* @__PURE__ */ new Set([...last.kind, ...snippet.kind])];
571
571
  last.uniqueInFile = occurrences(source.text, last.code).length === 1;
572
- } else output.push({ ...snippet2 });
572
+ } else output.push({ ...snippet });
573
573
  }
574
574
  return output;
575
575
  }
@@ -582,7 +582,7 @@ var coverage = [
582
582
  "Direct constructors, other animation systems, iframe contents, removed animations and unexecuted paths may be absent; missing origins are reported."
583
583
  ];
584
584
  function mapInspection(raw, request, context) {
585
- const { sources, map, catalog, generation: generation2, sourceVersion, reused, start, visualState } = context;
585
+ const { sources, map, catalog, generation, sourceVersion, reused, start, visualState } = context;
586
586
  const maxBytes = request.maxBytes ?? 12e3;
587
587
  const collected = [];
588
588
  const results = raw.results.map((result, index) => {
@@ -593,24 +593,24 @@ function mapInspection(raw, request, context) {
593
593
  collected.push(...mapped);
594
594
  for (const stack of animation.attachmentStacks)
595
595
  collected.push(
596
- ...map(stack, index).map((snippet2) => ({ ...snippet2, kind: ["timeline attachment"] }))
596
+ ...map(stack, index).map((snippet) => ({ ...snippet, kind: ["timeline attachment"] }))
597
597
  );
598
598
  }
599
599
  for (const el of result.elements) {
600
- const snippet2 = markupSnippet(sources, el, index);
601
- if (snippet2) collected.push(snippet2);
600
+ const snippet = markupSnippet(sources, el, index);
601
+ if (snippet) collected.push(snippet);
602
602
  }
603
603
  for (const id of result.css) {
604
604
  const rule = sources.cssRules.find((rule2) => rule2.id === id);
605
605
  if (rule) {
606
- const snippet2 = sources.slice(
606
+ const snippet = sources.slice(
607
607
  rule.file,
608
608
  rule.start,
609
609
  rule.end,
610
610
  "matched CSS candidate",
611
611
  index
612
612
  );
613
- if (snippet2) collected.push(snippet2);
613
+ if (snippet) collected.push(snippet);
614
614
  }
615
615
  }
616
616
  return {
@@ -621,7 +621,7 @@ function mapInspection(raw, request, context) {
621
621
  animations: result.animations.length,
622
622
  coTargets: [
623
623
  ...new Map(
624
- result.animations.flatMap((animation) => animation.targets).filter((element2) => !result.elements.some((own) => own.ref === element2.ref)).map((element2) => [element2.ref, element2])
624
+ result.animations.flatMap((animation) => animation.targets).filter((element) => !result.elements.some((own) => own.ref === element.ref)).map((element) => [element.ref, element])
625
625
  ).values()
626
626
  ].slice(0, 10),
627
627
  unmappedAnimations,
@@ -629,16 +629,16 @@ function mapInspection(raw, request, context) {
629
629
  };
630
630
  });
631
631
  const merged = mergeSnippets(collected, sources);
632
- for (const snippet2 of merged) catalog.set(snippet2.id, snippet2);
632
+ for (const snippet of merged) catalog.set(snippet.id, snippet);
633
633
  let selected = merged;
634
634
  if (request.snippets)
635
635
  selected = request.snippets.map((id) => {
636
- const snippet2 = catalog.get(id);
637
- if (!snippet2) throw new Error(`unknown_snippet: ${id}`);
638
- return snippet2;
636
+ const snippet = catalog.get(id);
637
+ if (!snippet) throw new Error(`unknown_snippet: ${id}`);
638
+ return snippet;
639
639
  });
640
640
  const response = {
641
- generation: generation2,
641
+ generation,
642
642
  visualState,
643
643
  sourceVersion,
644
644
  reused,
@@ -653,12 +653,12 @@ function mapInspection(raw, request, context) {
653
653
  debugAvailable: true,
654
654
  elapsedMs: Math.round(performance.now() - start)
655
655
  };
656
- const offset2 = request.offset ?? 0;
657
- if (!Number.isInteger(offset2) || offset2 < 0)
656
+ const offset = request.offset ?? 0;
657
+ if (!Number.isInteger(offset) || offset < 0)
658
658
  throw new Error("offset must be a non-negative integer");
659
- for (let i = offset2; i < selected.length; i++) {
660
- const snippet2 = selected[i];
661
- response.snippets.push(snippet2);
659
+ for (let i = offset; i < selected.length; i++) {
660
+ const snippet = selected[i];
661
+ response.snippets.push(snippet);
662
662
  if (Buffer.byteLength(JSON.stringify(response)) > maxBytes - 700) {
663
663
  response.snippets.pop();
664
664
  response.omittedCount = selected.length - i;
@@ -694,20 +694,20 @@ function timelinePage(request) {
694
694
  if (!inspection) throw new Error("inspector_unavailable");
695
695
  const result = inspection.timeline(request);
696
696
  const following = [];
697
- const generation2 = inspected.__hfLiveInspection?.generation ?? null;
698
- if (request.boundary === void 0) return { ...result, following, generation: generation2 };
697
+ const generation = inspected.__hfLiveInspection?.generation ?? null;
698
+ if (request.boundary === void 0) return { ...result, following, generation };
699
699
  const boundary = request.boundary;
700
700
  const schedule = inspection.timeline({ ...request, boundary: void 0 });
701
701
  for (const crossing of result.events) {
702
702
  if (crossing.kind !== "animation" || crossing.relation !== "crosses") continue;
703
- for (const target2 of crossing.targets) {
703
+ for (const target of crossing.targets) {
704
704
  const next = schedule.events.filter(
705
- (event) => event.kind === "animation" && event.start > boundary && event.targets.some((t) => t.ref === target2.ref) && event.properties.some((p) => crossing.properties.includes(p))
705
+ (event) => event.kind === "animation" && event.start > boundary && event.targets.some((t) => t.ref === target.ref) && event.properties.some((p) => crossing.properties.includes(p))
706
706
  ).sort((a, b) => a.start - b.start)[0];
707
707
  if (next && !following.includes(next)) following.push(next);
708
708
  }
709
709
  }
710
- return { ...result, following, generation: generation2 };
710
+ return { ...result, following, generation };
711
711
  }
712
712
  function liveGenerationPage() {
713
713
  return window.__hfLiveInspection?.generation ?? null;
@@ -721,9 +721,9 @@ var RELATIONS_SHOWN = 8;
721
721
  var COVERAGE_NOTE = "Observed DOM-target GSAP and explicit HF items only; callbacks/object tweens/unexecuted code are not inspected. Scheduled intervals do not establish visibility; no visual verification. at/range are half-open; boundary includes exact endpoints. No seek performed.";
722
722
  var BOUNDARY_NOTE = "only actions crossing, starting, ending or instantaneous here. Later stagger members are excluded, not absent. Group spans do not imply simultaneous starts. Target labels T1, T2, ... identify the same element within this response, not DOM order.";
723
723
  function formatTimeline(raw, request, view) {
724
- const offset2 = request.offset ?? 0;
724
+ const offset = request.offset ?? 0;
725
725
  const allGroups = groupEvents(raw.events);
726
- const groups = allGroups.slice(offset2, offset2 + GROUPS_PER_PAGE);
726
+ const groups = allGroups.slice(offset, offset + GROUPS_PER_PAGE);
727
727
  const label = labeler();
728
728
  const events = groups.flat().map((event, index) => ({
729
729
  ...event,
@@ -733,7 +733,7 @@ function formatTimeline(raw, request, view) {
733
733
  line: s.startLine
734
734
  }))
735
735
  }));
736
- const nextOffset = offset2 + groups.length < allGroups.length ? offset2 + groups.length : null;
736
+ const nextOffset = offset + groups.length < allGroups.length ? offset + groups.length : null;
737
737
  const lines = [
738
738
  `Timeline \xB7 global seconds \xB7 ${raw.status}`,
739
739
  `generation: ${view.generation}`,
@@ -834,8 +834,8 @@ ${heading}${component ? ` [${component.ref}]` : ""}`);
834
834
  }
835
835
  function targetSummary(targets) {
836
836
  const counts = /* @__PURE__ */ new Map();
837
- for (const target2 of targets) {
838
- const name = target2.id ? `#${target2.id}` : target2.hfId ?? (target2.classes.length ? `.${target2.classes.join(".")}` : target2.tag);
837
+ for (const target of targets) {
838
+ const name = target.id ? `#${target.id}` : target.hfId ?? (target.classes.length ? `.${target.classes.join(".")}` : target.tag);
839
839
  counts.set(name, (counts.get(name) ?? 0) + 1);
840
840
  }
841
841
  return [...counts].map(([name, count]) => count > 1 ? `${name} \xD7${count}` : name);
@@ -945,10 +945,10 @@ async function inspectElementMap(runner, view, file = "index.html") {
945
945
  function validateInspectRequest(request) {
946
946
  if (!Array.isArray(request.targets) || request.targets.length > 20 || !request.targets.length && !request.snippets?.length)
947
947
  throw new Error("Provide 1\u201320 targets, or snippet IDs from a previous query.");
948
- for (const target2 of request.targets) {
949
- if (!target2 || typeof target2 !== "object") throw new Error("Invalid target");
950
- const keys = ["selector", "hfId", "ref"].filter((key) => key in target2);
951
- if (keys.length !== 1 || Object.values(target2).some(
948
+ for (const target of request.targets) {
949
+ if (!target || typeof target !== "object") throw new Error("Invalid target");
950
+ const keys = ["selector", "hfId", "ref"].filter((key) => key in target);
951
+ if (keys.length !== 1 || Object.values(target).some(
952
952
  (value) => typeof value !== "string" || !value || value.length > 1e3
953
953
  ))
954
954
  throw new Error("Each target needs exactly one selector, hfId or ref; within is optional.");
@@ -982,250 +982,24 @@ function validateTimelineRequest(request) {
982
982
  const component = request.component;
983
983
  if (component && (typeof component !== "object" || Object.keys(component).some((key) => !COMPONENT_KEYS.includes(key)) || ["selector", "hfId", "ref"].filter((key) => key in component).length !== 1 || Object.values(component).some((v) => typeof v !== "string" || !v)))
984
984
  throw new Error("component requires one selector, hfId or ref");
985
- const offset2 = request.offset ?? 0;
986
- if (!Number.isInteger(offset2) || offset2 < 0)
985
+ const offset = request.offset ?? 0;
986
+ if (!Number.isInteger(offset) || offset < 0)
987
987
  throw new Error("offset must be non-negative integer");
988
- if (offset2 && !request.generation) throw new Error("pagination requires generation");
988
+ if (offset && !request.generation) throw new Error("pagination requires generation");
989
989
  }
990
990
  function assertGeneration(requested, current) {
991
991
  if (requested && requested !== current)
992
992
  throw new Error("stale_generation: query targets again after source changes or idle disposal");
993
993
  }
994
994
 
995
- // src/outputSchemas.ts
996
- var string = { type: "string" };
997
- var number = { type: "number" };
998
- var boolean = { type: "boolean" };
999
- var array = (items) => ({ type: "array", items });
1000
- var nullable = (schema) => ({ oneOf: [schema, { type: "null" }] });
1001
- var object = (properties, optional = []) => ({
1002
- type: "object",
1003
- properties,
1004
- required: Object.keys(properties).filter((key) => !optional.includes(key)),
1005
- additionalProperties: false
1006
- });
1007
- var element = object({
1008
- ref: string,
1009
- tag: string,
1010
- id: string,
1011
- hfId: nullable(string),
1012
- classes: array(string),
1013
- composition: nullable(string)
1014
- });
1015
- var snippet = object({
1016
- id: string,
1017
- file: string,
1018
- startLine: number,
1019
- endLine: number,
1020
- kind: array(string),
1021
- targets: array(number),
1022
- code: string,
1023
- uniqueInFile: boolean
1024
- });
1025
- var componentOutputSchema = object(
1026
- {
1027
- generation: string,
1028
- sourceVersion: string,
1029
- reused: boolean,
1030
- visualState: object({ time: number, duration: number }, ["time", "duration"]),
1031
- results: array(
1032
- object({
1033
- target: number,
1034
- status: {
1035
- type: "string",
1036
- enum: ["found", "missing", "ambiguous", "stale-ref", "invalid-selector"]
1037
- },
1038
- candidates: array(element),
1039
- candidatesOmitted: number,
1040
- animations: number,
1041
- coTargets: array(element),
1042
- unmappedAnimations: number,
1043
- scopeTruncated: boolean
1044
- })
1045
- ),
1046
- snippets: array(snippet),
1047
- omitted: array(object({ id: string, bytes: number })),
1048
- omittedCount: number,
1049
- nextOffset: nullable(number),
1050
- coverage: array(string),
1051
- recordLimitReached: boolean,
1052
- hooked: boolean,
1053
- debugAvailable: boolean,
1054
- elapsedMs: number
1055
- },
1056
- ["visualState"]
1057
- );
1058
- var declaredValue = object({
1059
- kind: { type: "string", enum: ["literal", "relative", "expression", "unknown"] },
1060
- value: { oneOf: [number, string, { type: "null" }] }
1061
- });
1062
- var animationValues = object({
1063
- basis: { type: "string", enum: ["authored-tween"] },
1064
- properties: array(object({ property: string, from: declaredValue, to: declaredValue })),
1065
- ease: declaredValue
1066
- });
1067
- var timelineOutputSchema = object({
1068
- text: string,
1069
- generation: string,
1070
- reused: boolean,
1071
- status: string,
1072
- candidates: array(element),
1073
- events: array(
1074
- object(
1075
- {
1076
- kind: { type: "string", enum: ["animation", "item"] },
1077
- relation: string,
1078
- component: nullable(element),
1079
- targets: array(element),
1080
- properties: array(string),
1081
- values: animationValues,
1082
- start: number,
1083
- end: number,
1084
- sources: array(object({ file: string, line: number }))
1085
- },
1086
- ["values"]
1087
- )
1088
- ),
1089
- eventCount: number,
1090
- groupCount: number,
1091
- nextOffset: nullable(number),
1092
- warnings: array(string)
1093
- });
1094
-
1095
- // src/tools.ts
1096
- var within = {
1097
- type: "string",
1098
- description: "Optional CSS selector restricting target lookup; omit for an unambiguous target."
1099
- };
1100
- var target = {
1101
- oneOf: [
1102
- {
1103
- type: "object",
1104
- required: ["selector"],
1105
- additionalProperties: false,
1106
- properties: {
1107
- selector: { type: "string", description: "CSS selector, such as #title or .word." },
1108
- within
1109
- }
1110
- },
1111
- {
1112
- type: "object",
1113
- required: ["hfId"],
1114
- additionalProperties: false,
1115
- properties: {
1116
- hfId: { type: "string", description: "Existing element data-hf-id value." },
1117
- within
1118
- }
1119
- },
1120
- {
1121
- type: "object",
1122
- required: ["ref"],
1123
- additionalProperties: false,
1124
- properties: {
1125
- ref: {
1126
- type: "string",
1127
- description: "Element ref returned by this inspector session; do not invent it. Rediscover after reload."
1128
- }
1129
- }
1130
- }
1131
- ]
1132
- };
1133
- var generation = {
1134
- type: "string",
1135
- description: "Generation returned by the previous query. Use for continuation; if stale, query targets again."
1136
- };
1137
- var offset = {
1138
- type: "integer",
1139
- minimum: 0,
1140
- description: "Returned nextOffset for continuation; repeat the same query with its generation."
1141
- };
1142
- var componentsTool = {
1143
- description: "HyperFrames-native grep for element-related source. Retrieve related HTML/CSS/GSAP snippets with file paths and line numbers to understand, debug, or edit known elements without whole-file lookup. Batch targets. Shared code may affect other elements; unknown animation origins are explicit.",
1144
- inputSchema: {
1145
- type: "object",
1146
- required: ["targets"],
1147
- additionalProperties: false,
1148
- properties: {
1149
- targets: {
1150
- type: "array",
1151
- maxItems: 20,
1152
- description: "Batch 1\u201320 targets. Use an empty array only when retrieving snippets by ID.",
1153
- items: target
1154
- },
1155
- descendants: {
1156
- type: "boolean",
1157
- default: true,
1158
- description: "Include source related to descendant elements."
1159
- },
1160
- maxBytes: {
1161
- type: "integer",
1162
- minimum: 2048,
1163
- maximum: 256e3,
1164
- default: 12e3,
1165
- description: "Response budget in bytes. Whole snippets may be omitted; use returned continuation data or increase the budget."
1166
- },
1167
- snippets: {
1168
- type: "array",
1169
- items: { type: "string" },
1170
- description: "Snippet IDs returned by a prior query; requires its generation. May use targets: []."
1171
- },
1172
- generation,
1173
- offset,
1174
- time: {
1175
- type: "number",
1176
- minimum: 0,
1177
- description: "Optional exact preview seek in global seconds. Does not filter animations by time; omit for ordinary source lookup."
1178
- }
1179
- }
1180
- },
1181
- outputSchema: componentOutputSchema
1182
- };
1183
- var timelineTool = {
1184
- description: "HyperFrames-native structured search for animation timing and activity. Use to find animations by time or boundary, including when the target element is unknown. Return scheduled HF entries and observed DOM-target GSAP timing, targets, properties and source locations, not full source blocks. Use at, range or boundary (at most one); omit all for the full schedule. Does not seek. Callbacks and unexecuted animation code are outside coverage.",
1185
- inputSchema: {
1186
- type: "object",
1187
- additionalProperties: false,
1188
- properties: {
1189
- component: {
1190
- ...target,
1191
- description: "Optional element/component scope including descendants; omit for the full project. Uses the same target format as the components tool."
1192
- },
1193
- at: {
1194
- type: "number",
1195
- minimum: 0,
1196
- description: "Global second: active scheduled intervals use start <= at < end; includes instantaneous actions at that time."
1197
- },
1198
- range: {
1199
- type: "array",
1200
- items: { type: "number", minimum: 0 },
1201
- minItems: 2,
1202
- maxItems: 2,
1203
- description: "Global [start, end) seconds, start < end. Return intersecting scheduled intervals and instantaneous actions inside the range."
1204
- },
1205
- boundary: {
1206
- type: "number",
1207
- minimum: 0,
1208
- description: "Global second: return only actions crossing, starting, ending or instantaneous here. Later stagger members are excluded. Group spans are not simultaneous per-target schedules; match target labels and member intervals before inferring overlap."
1209
- },
1210
- generation,
1211
- offset
1212
- }
1213
- },
1214
- outputSchema: timelineOutputSchema
1215
- };
1216
- function toolContent(tool, report) {
1217
- const text = tool === "timeline" && report.text ? report.text : JSON.stringify(report);
1218
- return { content: [{ type: "text", text }], structuredContent: report };
1219
- }
1220
-
1221
995
  // src/live.ts
1222
996
  var runtime = () => readFileSync2(new URL(`./inspection.${"js"}`, import.meta.url), "utf8");
1223
997
  function prepareLiveInspection(projectDir, html, provenance, sourceVersion) {
1224
998
  const project = realpathSync(projectDir);
1225
999
  if (fingerprint(project) !== sourceVersion) throw new Error("source_changed_during_load");
1226
1000
  if (!/<head\b[^>]*>/i.test(html)) throw new Error("preview_head_missing");
1227
- const generation2 = randomUUID();
1228
- const stamp = `window.__hfLiveInspection=${JSON.stringify({ generation: generation2, project })};`;
1001
+ const generation = randomUUID();
1002
+ const stamp = `window.__hfLiveInspection=${JSON.stringify({ generation, project })};`;
1229
1003
  const script = `${stamp}
1230
1004
  ${runtime()}`.replace(/<\/script/gi, "<\\/script");
1231
1005
  const prepared = html.replace(/<head\b[^>]*>/i, (head) => `${head}<script>${script}</script>`);
@@ -1233,9 +1007,9 @@ ${runtime()}`.replace(/<\/script/gi, "<\\/script");
1233
1007
  let context;
1234
1008
  const catalog = /* @__PURE__ */ new Map();
1235
1009
  const view = {
1236
- generation: generation2,
1010
+ generation,
1237
1011
  sourceVersion,
1238
- pageGeneration: generation2,
1012
+ pageGeneration: generation,
1239
1013
  sourceContext() {
1240
1014
  if (!context) {
1241
1015
  const sources = new Sources(project);
@@ -1249,13 +1023,13 @@ ${runtime()}`.replace(/<\/script/gi, "<\\/script");
1249
1023
  }
1250
1024
  };
1251
1025
  async function current(runner) {
1252
- if (await previewGeneration(runner) !== generation2)
1026
+ if (await previewGeneration(runner) !== generation)
1253
1027
  throw new Error("stale_preview: the preview reloaded; query again");
1254
1028
  await view.assertCurrent();
1255
1029
  }
1256
1030
  return {
1257
1031
  html: prepared,
1258
- generation: generation2,
1032
+ generation,
1259
1033
  finalizeDocument(servedHtml) {
1260
1034
  document2 = servedHtml;
1261
1035
  context = void 0;
@@ -1263,7 +1037,7 @@ ${runtime()}`.replace(/<\/script/gi, "<\\/script");
1263
1037
  async inspect(runner, request) {
1264
1038
  validateInspectRequest(request);
1265
1039
  if (request.time != null) throw new Error("live_query_does_not_seek");
1266
- assertGeneration(request.generation, generation2);
1040
+ assertGeneration(request.generation, generation);
1267
1041
  await current(runner);
1268
1042
  return inspectComponents(runner, view, request, {
1269
1043
  catalog,
@@ -1273,7 +1047,7 @@ ${runtime()}`.replace(/<\/script/gi, "<\\/script");
1273
1047
  },
1274
1048
  async timeline(runner, request) {
1275
1049
  validateTimelineRequest(request);
1276
- assertGeneration(request.generation, generation2);
1050
+ assertGeneration(request.generation, generation);
1277
1051
  await current(runner);
1278
1052
  return inspectTimeline(runner, view, request, true);
1279
1053
  },
@@ -1287,10 +1061,7 @@ function previewGeneration(runner) {
1287
1061
  return runner.run(liveGenerationPage, void 0);
1288
1062
  }
1289
1063
  export {
1290
- componentsTool,
1291
1064
  fingerprint,
1292
1065
  prepareLiveInspection,
1293
- previewGeneration,
1294
- timelineTool,
1295
- toolContent
1066
+ previewGeneration
1296
1067
  };