@fluixi/devtools 0.2.0-alpha.2 → 0.2.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +80 -2
  2. package/dist/callsite.cjs +72 -0
  3. package/dist/callsite.d.ts +22 -0
  4. package/dist/callsite.d.ts.map +1 -0
  5. package/dist/callsite.js +82 -0
  6. package/dist/callsite.mjs +51 -0
  7. package/dist/change-view.cjs +134 -0
  8. package/dist/change-view.d.ts +10 -0
  9. package/dist/change-view.d.ts.map +1 -0
  10. package/dist/change-view.js +102 -0
  11. package/dist/change-view.mjs +111 -0
  12. package/dist/copy.cjs +63 -0
  13. package/dist/copy.d.ts +9 -0
  14. package/dist/copy.d.ts.map +1 -0
  15. package/dist/copy.js +52 -0
  16. package/dist/copy.mjs +42 -0
  17. package/dist/describe.cjs +55 -0
  18. package/dist/describe.d.ts +3 -0
  19. package/dist/describe.d.ts.map +1 -0
  20. package/dist/describe.js +47 -0
  21. package/dist/describe.mjs +34 -0
  22. package/dist/detail-panel.cjs +307 -0
  23. package/dist/detail-panel.d.ts +17 -0
  24. package/dist/detail-panel.d.ts.map +1 -0
  25. package/dist/detail-panel.js +217 -0
  26. package/dist/detail-panel.mjs +284 -0
  27. package/dist/diff.cjs +225 -0
  28. package/dist/diff.d.ts +31 -0
  29. package/dist/diff.d.ts.map +1 -0
  30. package/dist/diff.js +132 -0
  31. package/dist/diff.mjs +202 -0
  32. package/dist/dom.cjs +204 -0
  33. package/dist/dom.d.ts +81 -0
  34. package/dist/dom.d.ts.map +1 -0
  35. package/dist/dom.js +269 -0
  36. package/dist/dom.mjs +183 -0
  37. package/dist/export.cjs +221 -0
  38. package/dist/export.d.ts +55 -0
  39. package/dist/export.d.ts.map +1 -0
  40. package/dist/export.js +90 -0
  41. package/dist/export.mjs +209 -0
  42. package/dist/float.cjs +232 -0
  43. package/dist/float.d.ts +54 -0
  44. package/dist/float.d.ts.map +1 -0
  45. package/dist/float.js +256 -0
  46. package/dist/float.mjs +211 -0
  47. package/dist/format.cjs +175 -0
  48. package/dist/format.d.ts +16 -0
  49. package/dist/format.d.ts.map +1 -0
  50. package/dist/format.js +188 -0
  51. package/dist/format.mjs +154 -0
  52. package/dist/graph-view.cjs +893 -0
  53. package/dist/graph-view.d.ts +79 -2
  54. package/dist/graph-view.d.ts.map +1 -1
  55. package/dist/graph-view.js +866 -50
  56. package/dist/graph-view.mjs +870 -0
  57. package/dist/highlight.cjs +140 -0
  58. package/dist/highlight.d.ts +56 -0
  59. package/dist/highlight.d.ts.map +1 -0
  60. package/dist/highlight.js +154 -0
  61. package/dist/highlight.mjs +119 -0
  62. package/dist/history.cjs +95 -0
  63. package/dist/history.d.ts +59 -0
  64. package/dist/history.d.ts.map +1 -0
  65. package/dist/history.js +85 -0
  66. package/dist/history.mjs +74 -0
  67. package/dist/hook.cjs +1562 -0
  68. package/dist/hook.d.ts +60 -0
  69. package/dist/hook.d.ts.map +1 -0
  70. package/dist/hook.js +142 -0
  71. package/dist/hook.mjs +1553 -0
  72. package/dist/index.cjs +4552 -0
  73. package/dist/index.d.ts +44 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +25 -1
  76. package/dist/index.mjs +4544 -0
  77. package/dist/inspector.cjs +688 -0
  78. package/dist/inspector.d.ts +60 -0
  79. package/dist/inspector.d.ts.map +1 -0
  80. package/dist/inspector.js +415 -0
  81. package/dist/inspector.mjs +676 -0
  82. package/dist/instrument.cjs +497 -0
  83. package/dist/instrument.d.ts +147 -5
  84. package/dist/instrument.d.ts.map +1 -1
  85. package/dist/instrument.js +164 -44
  86. package/dist/instrument.mjs +487 -0
  87. package/dist/kind-filter.cjs +172 -0
  88. package/dist/kind-filter.d.ts +39 -0
  89. package/dist/kind-filter.d.ts.map +1 -0
  90. package/dist/kind-filter.js +151 -0
  91. package/dist/kind-filter.mjs +151 -0
  92. package/dist/menu.cjs +141 -0
  93. package/dist/menu.d.ts +37 -0
  94. package/dist/menu.d.ts.map +1 -0
  95. package/dist/menu.js +125 -0
  96. package/dist/menu.mjs +120 -0
  97. package/dist/observe.cjs +1352 -0
  98. package/dist/observe.d.ts +80 -0
  99. package/dist/observe.d.ts.map +1 -0
  100. package/dist/observe.js +893 -0
  101. package/dist/observe.mjs +1345 -0
  102. package/dist/palette.cjs +52 -0
  103. package/dist/palette.d.ts +11 -0
  104. package/dist/palette.d.ts.map +1 -0
  105. package/dist/palette.js +27 -0
  106. package/dist/palette.mjs +31 -0
  107. package/dist/path.cjs +45 -0
  108. package/dist/path.d.ts +19 -0
  109. package/dist/path.d.ts.map +1 -0
  110. package/dist/path.js +49 -0
  111. package/dist/path.mjs +24 -0
  112. package/dist/plugin.cjs +87 -0
  113. package/dist/plugin.d.ts +121 -0
  114. package/dist/plugin.d.ts.map +1 -0
  115. package/dist/plugin.js +74 -0
  116. package/dist/plugin.mjs +66 -0
  117. package/dist/plugins/context.cjs +98 -0
  118. package/dist/plugins/context.d.ts +10 -0
  119. package/dist/plugins/context.d.ts.map +1 -0
  120. package/dist/plugins/context.js +80 -0
  121. package/dist/plugins/context.mjs +75 -0
  122. package/dist/plugins/directives.cjs +98 -0
  123. package/dist/plugins/directives.d.ts +25 -0
  124. package/dist/plugins/directives.d.ts.map +1 -0
  125. package/dist/plugins/directives.js +78 -0
  126. package/dist/plugins/directives.mjs +75 -0
  127. package/dist/plugins/index.cjs +162 -0
  128. package/dist/plugins/index.d.ts +7 -0
  129. package/dist/plugins/index.d.ts.map +1 -0
  130. package/dist/plugins/index.js +9 -0
  131. package/dist/plugins/index.mjs +140 -0
  132. package/dist/source.cjs +111 -0
  133. package/dist/source.d.ts +72 -0
  134. package/dist/source.d.ts.map +1 -0
  135. package/dist/source.js +153 -0
  136. package/dist/source.mjs +90 -0
  137. package/dist/timeline.cjs +350 -0
  138. package/dist/timeline.d.ts +30 -0
  139. package/dist/timeline.d.ts.map +1 -0
  140. package/dist/timeline.js +271 -0
  141. package/dist/timeline.mjs +327 -0
  142. package/dist/tree.cjs +574 -0
  143. package/dist/tree.d.ts +128 -0
  144. package/dist/tree.d.ts.map +1 -0
  145. package/dist/tree.js +645 -0
  146. package/dist/tree.mjs +551 -0
  147. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  148. package/dist/value-pane.cjs +223 -0
  149. package/dist/value-pane.d.ts +10 -0
  150. package/dist/value-pane.d.ts.map +1 -0
  151. package/dist/value-pane.js +61 -0
  152. package/dist/value-pane.mjs +200 -0
  153. package/dist/wire.cjs +109 -0
  154. package/dist/wire.d.ts +100 -0
  155. package/dist/wire.d.ts.map +1 -0
  156. package/dist/wire.js +93 -0
  157. package/dist/wire.mjs +89 -0
  158. package/package.json +17 -5
@@ -0,0 +1,111 @@
1
+ // src/copy.ts
2
+ function confirmOn(button, said = "copied") {
3
+ if (!button) return;
4
+ const was = button.textContent;
5
+ button.textContent = said;
6
+ setTimeout(() => {
7
+ button.textContent = was;
8
+ }, 1200);
9
+ }
10
+ function fallback(text, button) {
11
+ try {
12
+ const doc = button?.ownerDocument ?? document;
13
+ const area = doc.createElement("textarea");
14
+ area.value = text;
15
+ area.setAttribute("readonly", "");
16
+ area.style.position = "fixed";
17
+ area.style.opacity = "0";
18
+ doc.body.appendChild(area);
19
+ area.select();
20
+ doc.execCommand("copy");
21
+ area.remove();
22
+ confirmOn(button);
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ async function copyText(text, button) {
29
+ const clipboard = globalThis.navigator?.clipboard;
30
+ if (clipboard?.writeText) {
31
+ try {
32
+ await clipboard.writeText(text);
33
+ confirmOn(button);
34
+ return true;
35
+ } catch {
36
+ }
37
+ }
38
+ return fallback(text, button);
39
+ }
40
+
41
+ // src/change-view.ts
42
+ var escape = (text) => text.replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[c]);
43
+ var SIGN = { added: "+", removed: "−", changed: "~" };
44
+ function pretty(json) {
45
+ if (!json) return void 0;
46
+ try {
47
+ return JSON.stringify(JSON.parse(json), null, 2);
48
+ } catch {
49
+ return void 0;
50
+ }
51
+ }
52
+ function sideOf(text, json, cls) {
53
+ const block = pretty(json);
54
+ if (!block) return `<span class="ch-${cls}">${escape(text ?? "")}</span>`;
55
+ return `<div class="ch-block ch-${cls}"><button type="button" class="ch-copy" title="Copy" data-copy="${escape(block)}">copy</button><pre class="ch-json">${escape(block)}</pre></div>`;
56
+ }
57
+ function changeRows(change, limit = Infinity) {
58
+ if (!change?.entries?.length) return "";
59
+ const shown = change.entries.slice(0, limit);
60
+ const hidden = change.entries.length - shown.length + (change.more ?? 0);
61
+ const rows = shown.map((entry) => {
62
+ const from = sideOf(entry.from, entry.fromJson, "from");
63
+ const to = sideOf(entry.to, entry.toJson, "to");
64
+ const sides = entry.op === "changed" ? `${from}<span class="ch-arrow">→</span>${to}` : entry.op === "added" ? to : from;
65
+ const stacked = entry.fromJson || entry.toJson ? " ch-stacked" : "";
66
+ return `<div class="ch-row ch-${entry.op}${stacked}"><span class="ch-sign">${SIGN[entry.op] ?? "·"}</span><span class="ch-key">${escape(entry.key)}</span><span class="ch-sides">${sides}</span></div>`;
67
+ }).join("");
68
+ const size = change.length ? `<div class="ch-size">${change.length.from} → ${change.length.to} items</div>` : "";
69
+ return `<div class="ch-list">${size}${rows}${hidden > 0 ? `<div class="ch-more">and ${hidden} more</div>` : ""}</div>`;
70
+ }
71
+ function handleCopyClick(event) {
72
+ const button = event.target?.closest?.(".ch-copy");
73
+ if (!button) return false;
74
+ void copyText(button.dataset.copy ?? "", button);
75
+ return true;
76
+ }
77
+ var CHANGE_CSS = `
78
+ .ch-list { margin-top: 4px; font-family: ui-monospace, monospace; font-size: 11px; }
79
+ .ch-size { color: var(--fx-muted, #8a90a2); margin-bottom: 2px; }
80
+ .ch-row { display: flex; gap: 6px; align-items: baseline; padding: 1px 0; }
81
+ .ch-row.ch-stacked { align-items: flex-start; padding: 3px 0; }
82
+ .ch-sign { flex: none; width: 9px; text-align: center; }
83
+ .ch-added .ch-sign { color: var(--state, #34d399); }
84
+ .ch-removed .ch-sign { color: var(--fx-write, #fb7185); }
85
+ .ch-changed .ch-sign { color: var(--effect, #fbbf24); }
86
+ .ch-key { flex: none; color: var(--fx-muted, #8a90a2); }
87
+ .ch-sides { min-width: 0; flex: 1; overflow-wrap: anywhere; }
88
+ .ch-stacked .ch-sides { display: flex; flex-direction: column; gap: 2px; }
89
+ .ch-from { color: var(--fx-muted, #8a90a2); }
90
+ .ch-row:not(.ch-stacked) .ch-from { text-decoration: line-through; }
91
+ .ch-arrow { color: var(--fx-muted, #8a90a2); margin: 0 4px; }
92
+ .ch-to { color: var(--fx-label, #e7e9ee); }
93
+ .ch-more { color: var(--fx-muted, #8a90a2); margin-top: 2px; }
94
+ /* In the corner: an object can be tall, and a button under it is a scroll away. */
95
+ .ch-block { position: relative; border-radius: 4px; border: 1px solid var(--fx-line, #ffffff14); }
96
+ .ch-block.ch-from { opacity: .72; }
97
+ .ch-json { margin: 0; padding: 5px 7px; overflow-x: auto; white-space: pre; font: inherit; }
98
+ .ch-copy {
99
+ position: absolute; top: 3px; right: 3px; padding: 1px 6px; cursor: pointer;
100
+ font: inherit; font-size: 9.5px; opacity: 0; transition: opacity .12s;
101
+ border: 1px solid var(--fx-line, #ffffff26); border-radius: 3px;
102
+ background: var(--fx-panel, #14161c); color: var(--fx-muted, #8a90a2);
103
+ }
104
+ .ch-block:hover .ch-copy, .ch-copy:focus { opacity: 1; }
105
+ .ch-copy:hover { color: var(--fx-label, #e7e9ee); }
106
+ `;
107
+ export {
108
+ CHANGE_CSS,
109
+ changeRows,
110
+ handleCopyClick
111
+ };
package/dist/copy.cjs ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/copy.ts
21
+ var copy_exports = {};
22
+ __export(copy_exports, {
23
+ copyText: () => copyText
24
+ });
25
+ module.exports = __toCommonJS(copy_exports);
26
+ function confirmOn(button, said = "copied") {
27
+ if (!button) return;
28
+ const was = button.textContent;
29
+ button.textContent = said;
30
+ setTimeout(() => {
31
+ button.textContent = was;
32
+ }, 1200);
33
+ }
34
+ function fallback(text, button) {
35
+ try {
36
+ const doc = button?.ownerDocument ?? document;
37
+ const area = doc.createElement("textarea");
38
+ area.value = text;
39
+ area.setAttribute("readonly", "");
40
+ area.style.position = "fixed";
41
+ area.style.opacity = "0";
42
+ doc.body.appendChild(area);
43
+ area.select();
44
+ doc.execCommand("copy");
45
+ area.remove();
46
+ confirmOn(button);
47
+ return true;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+ async function copyText(text, button) {
53
+ const clipboard = globalThis.navigator?.clipboard;
54
+ if (clipboard?.writeText) {
55
+ try {
56
+ await clipboard.writeText(text);
57
+ confirmOn(button);
58
+ return true;
59
+ } catch {
60
+ }
61
+ }
62
+ return fallback(text, button);
63
+ }
package/dist/copy.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Putting text on the clipboard from wherever a panel happens to be running.
3
+ *
4
+ * `navigator.clipboard` is not there in a vscode webview without permission, nor on an
5
+ * insecure origin. The hidden textarea is the old way and still the one that works in both.
6
+ */
7
+ /** True when the text reached the clipboard. */
8
+ export declare function copyText(text: string, button?: HTMLElement): Promise<boolean>;
9
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgCH,gDAAgD;AAChD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAanF"}
package/dist/copy.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Putting text on the clipboard from wherever a panel happens to be running.
3
+ *
4
+ * `navigator.clipboard` is not there in a vscode webview without permission, nor on an
5
+ * insecure origin. The hidden textarea is the old way and still the one that works in both.
6
+ */
7
+ /** Says so on the control that was pressed: a toast needs somewhere to live. */
8
+ function confirmOn(button, said = 'copied') {
9
+ if (!button)
10
+ return;
11
+ const was = button.textContent;
12
+ button.textContent = said;
13
+ setTimeout(() => {
14
+ button.textContent = was;
15
+ }, 1200);
16
+ }
17
+ function fallback(text, button) {
18
+ try {
19
+ const doc = button?.ownerDocument ?? document;
20
+ const area = doc.createElement('textarea');
21
+ area.value = text;
22
+ area.setAttribute('readonly', '');
23
+ area.style.position = 'fixed';
24
+ area.style.opacity = '0';
25
+ doc.body.appendChild(area);
26
+ area.select();
27
+ doc.execCommand('copy');
28
+ area.remove();
29
+ confirmOn(button);
30
+ return true;
31
+ }
32
+ catch {
33
+ // Nothing left to try; whatever is on screen can still be selected by hand.
34
+ return false;
35
+ }
36
+ }
37
+ /** True when the text reached the clipboard. */
38
+ export async function copyText(text, button) {
39
+ const clipboard = globalThis
40
+ .navigator?.clipboard;
41
+ if (clipboard?.writeText) {
42
+ try {
43
+ await clipboard.writeText(text);
44
+ confirmOn(button);
45
+ return true;
46
+ }
47
+ catch {
48
+ // Denied, or a context the api refuses to work in.
49
+ }
50
+ }
51
+ return fallback(text, button);
52
+ }
package/dist/copy.mjs ADDED
@@ -0,0 +1,42 @@
1
+ // src/copy.ts
2
+ function confirmOn(button, said = "copied") {
3
+ if (!button) return;
4
+ const was = button.textContent;
5
+ button.textContent = said;
6
+ setTimeout(() => {
7
+ button.textContent = was;
8
+ }, 1200);
9
+ }
10
+ function fallback(text, button) {
11
+ try {
12
+ const doc = button?.ownerDocument ?? document;
13
+ const area = doc.createElement("textarea");
14
+ area.value = text;
15
+ area.setAttribute("readonly", "");
16
+ area.style.position = "fixed";
17
+ area.style.opacity = "0";
18
+ doc.body.appendChild(area);
19
+ area.select();
20
+ doc.execCommand("copy");
21
+ area.remove();
22
+ confirmOn(button);
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ async function copyText(text, button) {
29
+ const clipboard = globalThis.navigator?.clipboard;
30
+ if (clipboard?.writeText) {
31
+ try {
32
+ await clipboard.writeText(text);
33
+ confirmOn(button);
34
+ return true;
35
+ } catch {
36
+ }
37
+ }
38
+ return fallback(text, button);
39
+ }
40
+ export {
41
+ copyText
42
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/describe.ts
21
+ var describe_exports = {};
22
+ __export(describe_exports, {
23
+ describeNode: () => describeNode
24
+ });
25
+ module.exports = __toCommonJS(describe_exports);
26
+ var MAX_CLASSES = 2;
27
+ function textOwner(node) {
28
+ const parent = node.parentElement;
29
+ return parent ? `text in ${describeElement(parent)}` : "text";
30
+ }
31
+ function describeElement(el) {
32
+ const tag = el.tagName.toLowerCase();
33
+ const id = el.id ? `#${el.id}` : "";
34
+ const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") ?? "";
35
+ const classes = raw.split(/\s+/).filter(Boolean).slice(0, MAX_CLASSES).map((c) => `.${c}`).join("");
36
+ return `${tag}${id}${classes}`;
37
+ }
38
+ function describeNode(target) {
39
+ const node = target;
40
+ if (!node || typeof node.nodeType !== "number") return "detached";
41
+ switch (node.nodeType) {
42
+ case 1:
43
+ return describeElement(node);
44
+ case 3:
45
+ return textOwner(node);
46
+ case 8: {
47
+ const parent = node.parentElement;
48
+ return parent ? `slot in ${describeElement(parent)}` : "slot";
49
+ }
50
+ case 11:
51
+ return "fragment";
52
+ default:
53
+ return node.nodeName?.toLowerCase() ?? "node";
54
+ }
55
+ }
@@ -0,0 +1,3 @@
1
+ /** An element, the text node it writes, or the marker for a hole with nothing in it yet. */
2
+ export declare function describeNode(target: unknown): string;
3
+ //# sourceMappingURL=describe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AA8BA,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAkBpD"}
@@ -0,0 +1,47 @@
1
+ // A dom node, in words.
2
+ //
3
+ // The element is described at the moment it is reported and the reference dropped: holding
4
+ // one would keep a removed subtree alive for as long as the panel is open.
5
+ //
6
+ // Enough to find it on the page — tag, id, a class or two — without being a selector.
7
+ /** More than this is a selector, not a label. */
8
+ const MAX_CLASSES = 2;
9
+ /** `text in li` — the element it sits in is what locates it. */
10
+ function textOwner(node) {
11
+ const parent = node.parentElement;
12
+ return parent ? `text in ${describeElement(parent)}` : 'text';
13
+ }
14
+ function describeElement(el) {
15
+ const tag = el.tagName.toLowerCase();
16
+ const id = el.id ? `#${el.id}` : '';
17
+ // Not a string on an SVG element.
18
+ const raw = typeof el.className === 'string' ? el.className : el.getAttribute('class') ?? '';
19
+ const classes = raw
20
+ .split(/\s+/)
21
+ .filter(Boolean)
22
+ .slice(0, MAX_CLASSES)
23
+ .map((c) => `.${c}`)
24
+ .join('');
25
+ return `${tag}${id}${classes}`;
26
+ }
27
+ /** An element, the text node it writes, or the marker for a hole with nothing in it yet. */
28
+ export function describeNode(target) {
29
+ const node = target;
30
+ if (!node || typeof node.nodeType !== 'number')
31
+ return 'detached';
32
+ switch (node.nodeType) {
33
+ case 1:
34
+ return describeElement(node);
35
+ case 3:
36
+ return textOwner(node);
37
+ case 8: {
38
+ // The hole is empty; where it will go is what matters.
39
+ const parent = node.parentElement;
40
+ return parent ? `slot in ${describeElement(parent)}` : 'slot';
41
+ }
42
+ case 11:
43
+ return 'fragment';
44
+ default:
45
+ return node.nodeName?.toLowerCase() ?? 'node';
46
+ }
47
+ }
@@ -0,0 +1,34 @@
1
+ // src/describe.ts
2
+ var MAX_CLASSES = 2;
3
+ function textOwner(node) {
4
+ const parent = node.parentElement;
5
+ return parent ? `text in ${describeElement(parent)}` : "text";
6
+ }
7
+ function describeElement(el) {
8
+ const tag = el.tagName.toLowerCase();
9
+ const id = el.id ? `#${el.id}` : "";
10
+ const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") ?? "";
11
+ const classes = raw.split(/\s+/).filter(Boolean).slice(0, MAX_CLASSES).map((c) => `.${c}`).join("");
12
+ return `${tag}${id}${classes}`;
13
+ }
14
+ function describeNode(target) {
15
+ const node = target;
16
+ if (!node || typeof node.nodeType !== "number") return "detached";
17
+ switch (node.nodeType) {
18
+ case 1:
19
+ return describeElement(node);
20
+ case 3:
21
+ return textOwner(node);
22
+ case 8: {
23
+ const parent = node.parentElement;
24
+ return parent ? `slot in ${describeElement(parent)}` : "slot";
25
+ }
26
+ case 11:
27
+ return "fragment";
28
+ default:
29
+ return node.nodeName?.toLowerCase() ?? "node";
30
+ }
31
+ }
32
+ export {
33
+ describeNode
34
+ };