@rose42/feedback-capture 0.1.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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/dist/clipboard.d.ts +7 -0
  4. package/dist/clipboard.d.ts.map +1 -0
  5. package/dist/clipboard.js +33 -0
  6. package/dist/clipboard.js.map +1 -0
  7. package/dist/context.d.ts +10 -0
  8. package/dist/context.d.ts.map +1 -0
  9. package/dist/context.js +7 -0
  10. package/dist/context.js.map +1 -0
  11. package/dist/crop.d.ts +61 -0
  12. package/dist/crop.d.ts.map +1 -0
  13. package/dist/crop.js +112 -0
  14. package/dist/crop.js.map +1 -0
  15. package/dist/index.d.ts +16 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +11 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/plugins/comment.d.ts +11 -0
  20. package/dist/plugins/comment.d.ts.map +1 -0
  21. package/dist/plugins/comment.js +14 -0
  22. package/dist/plugins/comment.js.map +1 -0
  23. package/dist/plugins/consoleLogs.d.ts +14 -0
  24. package/dist/plugins/consoleLogs.d.ts.map +1 -0
  25. package/dist/plugins/consoleLogs.js +98 -0
  26. package/dist/plugins/consoleLogs.js.map +1 -0
  27. package/dist/plugins/core.d.ts +24 -0
  28. package/dist/plugins/core.d.ts.map +1 -0
  29. package/dist/plugins/core.js +62 -0
  30. package/dist/plugins/core.js.map +1 -0
  31. package/dist/plugins/elementTarget.d.ts +156 -0
  32. package/dist/plugins/elementTarget.d.ts.map +1 -0
  33. package/dist/plugins/elementTarget.js +537 -0
  34. package/dist/plugins/elementTarget.js.map +1 -0
  35. package/dist/plugins/frameBurst.d.ts +60 -0
  36. package/dist/plugins/frameBurst.d.ts.map +1 -0
  37. package/dist/plugins/frameBurst.js +260 -0
  38. package/dist/plugins/frameBurst.js.map +1 -0
  39. package/dist/plugins/index.d.ts +17 -0
  40. package/dist/plugins/index.d.ts.map +1 -0
  41. package/dist/plugins/index.js +9 -0
  42. package/dist/plugins/index.js.map +1 -0
  43. package/dist/plugins/pageContext.d.ts +13 -0
  44. package/dist/plugins/pageContext.d.ts.map +1 -0
  45. package/dist/plugins/pageContext.js +23 -0
  46. package/dist/plugins/pageContext.js.map +1 -0
  47. package/dist/plugins/screenshot.d.ts +34 -0
  48. package/dist/plugins/screenshot.d.ts.map +1 -0
  49. package/dist/plugins/screenshot.js +183 -0
  50. package/dist/plugins/screenshot.js.map +1 -0
  51. package/dist/plugins/version.d.ts +16 -0
  52. package/dist/plugins/version.d.ts.map +1 -0
  53. package/dist/plugins/version.js +21 -0
  54. package/dist/plugins/version.js.map +1 -0
  55. package/dist/session.d.ts +19 -0
  56. package/dist/session.d.ts.map +1 -0
  57. package/dist/session.js +18 -0
  58. package/dist/session.js.map +1 -0
  59. package/dist/source/adapters/compose.d.ts +7 -0
  60. package/dist/source/adapters/compose.d.ts.map +1 -0
  61. package/dist/source/adapters/compose.js +21 -0
  62. package/dist/source/adapters/compose.js.map +1 -0
  63. package/dist/source/adapters/createSourceResolver.d.ts +28 -0
  64. package/dist/source/adapters/createSourceResolver.d.ts.map +1 -0
  65. package/dist/source/adapters/createSourceResolver.js +59 -0
  66. package/dist/source/adapters/createSourceResolver.js.map +1 -0
  67. package/dist/source/adapters/detect.d.ts +22 -0
  68. package/dist/source/adapters/detect.d.ts.map +1 -0
  69. package/dist/source/adapters/detect.js +133 -0
  70. package/dist/source/adapters/detect.js.map +1 -0
  71. package/dist/source/adapters/index.d.ts +18 -0
  72. package/dist/source/adapters/index.d.ts.map +1 -0
  73. package/dist/source/adapters/index.js +10 -0
  74. package/dist/source/adapters/index.js.map +1 -0
  75. package/dist/source/adapters/locator.d.ts +14 -0
  76. package/dist/source/adapters/locator.d.ts.map +1 -0
  77. package/dist/source/adapters/locator.js +69 -0
  78. package/dist/source/adapters/locator.js.map +1 -0
  79. package/dist/source/adapters/next.d.ts +46 -0
  80. package/dist/source/adapters/next.d.ts.map +1 -0
  81. package/dist/source/adapters/next.js +124 -0
  82. package/dist/source/adapters/next.js.map +1 -0
  83. package/dist/source/adapters/nextFlight.d.ts +19 -0
  84. package/dist/source/adapters/nextFlight.d.ts.map +1 -0
  85. package/dist/source/adapters/nextFlight.js +80 -0
  86. package/dist/source/adapters/nextFlight.js.map +1 -0
  87. package/dist/source/adapters/qwik.d.ts +16 -0
  88. package/dist/source/adapters/qwik.d.ts.map +1 -0
  89. package/dist/source/adapters/qwik.js +49 -0
  90. package/dist/source/adapters/qwik.js.map +1 -0
  91. package/dist/source/adapters/react.d.ts +46 -0
  92. package/dist/source/adapters/react.d.ts.map +1 -0
  93. package/dist/source/adapters/react.js +201 -0
  94. package/dist/source/adapters/react.js.map +1 -0
  95. package/dist/source/adapters/svelte.d.ts +23 -0
  96. package/dist/source/adapters/svelte.d.ts.map +1 -0
  97. package/dist/source/adapters/svelte.js +64 -0
  98. package/dist/source/adapters/svelte.js.map +1 -0
  99. package/dist/source/adapters/vue.d.ts +27 -0
  100. package/dist/source/adapters/vue.d.ts.map +1 -0
  101. package/dist/source/adapters/vue.js +76 -0
  102. package/dist/source/adapters/vue.js.map +1 -0
  103. package/dist/source/locateJsx.d.ts +25 -0
  104. package/dist/source/locateJsx.d.ts.map +1 -0
  105. package/dist/source/locateJsx.js +67 -0
  106. package/dist/source/locateJsx.js.map +1 -0
  107. package/dist/source/rankSourceHierarchy.d.ts +25 -0
  108. package/dist/source/rankSourceHierarchy.d.ts.map +1 -0
  109. package/dist/source/rankSourceHierarchy.js +60 -0
  110. package/dist/source/rankSourceHierarchy.js.map +1 -0
  111. package/dist/source/reactSourceResolver.d.ts +3 -0
  112. package/dist/source/reactSourceResolver.d.ts.map +1 -0
  113. package/dist/source/reactSourceResolver.js +3 -0
  114. package/dist/source/reactSourceResolver.js.map +1 -0
  115. package/dist/source/sourceMap.d.ts +41 -0
  116. package/dist/source/sourceMap.d.ts.map +1 -0
  117. package/dist/source/sourceMap.js +235 -0
  118. package/dist/source/sourceMap.js.map +1 -0
  119. package/dist/transport.d.ts +13 -0
  120. package/dist/transport.d.ts.map +1 -0
  121. package/dist/transport.js +37 -0
  122. package/dist/transport.js.map +1 -0
  123. package/dist/types.d.ts +28 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +2 -0
  126. package/dist/types.js.map +1 -0
  127. package/package.json +68 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rose42
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # feedback-capture
2
+
3
+ **Browser feedback capture as a typed plugin envelope** — screenshot, URL, comment, console logs, element pick with source enrichment — for DX tools (Vite / [T3 Code](https://github.com/pingdotgg/t3code)) and production feedback flows.
4
+
5
+ UI-free: own the panel in React/Vue/Angular/vanilla; this package registers collectors and builds the envelope.
6
+
7
+ Until the first npm release, install from this repo via the [local link workflow](./docs/local-link.md). After publish:
8
+
9
+ ```bash
10
+ pnpm add @rose42/feedback-capture
11
+ ```
12
+
13
+ ## What you get
14
+
15
+ Compose collectors as plugins. Each plugin owns one key on a typed `FeedbackEnvelope`. Init runs `setup`, `build()` snapshots everything, `dispose()` tears down.
16
+
17
+ - **Screenshots & frame bursts** tab capture, clipboard image read, paste handler, multi-image gallery helpers, smart change detection
18
+ - **Element pick** CSS selector + bbox; optional silent crop around the target
19
+ - **Source enrichment** best-effort file/line via React, Next.js, _untested: Vue, Svelte, Qwik, or LocatorJS_
20
+ - **Page context** URL and viewport
21
+ - **App version** optional metadata via `createVersionPlugin`
22
+ - **Console buffer** ring buffer of logs from setup until send
23
+ - **Pluggable transport** `createHttpTransport`, or your own `send(envelope)`
24
+
25
+ Host UI (FAB, panels, report-type gating, labels) lives in consumers such as [`@rose42/t3-feedback`](https://gitlab.com/rose42/t3-feedback).
26
+
27
+ ## Quick start
28
+
29
+ ```ts
30
+ import {
31
+ captureScreenshot,
32
+ createCommentPlugin,
33
+ createConsoleLogsPlugin,
34
+ createElementTargetPlugin,
35
+ createHttpTransport,
36
+ createPageContextPlugin,
37
+ createScreenshotPlugin,
38
+ initFeedbackCapture,
39
+ } from "@rose42/feedback-capture";
40
+
41
+ const element = createElementTargetPlugin();
42
+ const feedback = initFeedbackCapture({
43
+ plugins: [
44
+ createPageContextPlugin(),
45
+ element,
46
+ createConsoleLogsPlugin({ maxEntries: 200 }),
47
+ ] as const,
48
+ });
49
+
50
+ await element.pick();
51
+
52
+ const shot = await captureScreenshot();
53
+ const envelope = await feedback.build([
54
+ createCommentPlugin({ getComment: () => "Button looks off on mobile" }),
55
+ ...(shot !== undefined ? [createScreenshotPlugin({ getDataUrl: () => shot })] : []),
56
+ ]);
57
+
58
+ const transport = createHttpTransport({ url: "/api/feedback" });
59
+ await transport.send(envelope);
60
+ feedback.dispose();
61
+ ```
62
+
63
+ For a T3 Code / Vite overlay, use [`@rose42/t3-feedback`](https://gitlab.com/rose42/t3-feedback) (or link the sibling package while developing).
64
+
65
+ ## Documentation
66
+
67
+ | Doc | Contents |
68
+ | ------------------------------------------- | ----------------------------------------------- |
69
+ | [API reference](./docs/api.md) | Exports, plugins, source adapters, init → build |
70
+ | [Local link workflow](./docs/local-link.md) | Develop against a consumer before npm publish |
71
+ | [Release](./docs/release.md) | Tag-driven GitLab → npm publish |
72
+ | [Dev Container](./docs/devcontainer.md) | One-click Node / pnpm / T3 Code setup |
73
+
74
+ ## Status
75
+
76
+ Early. The API is usable and covered by tests; treat `0.x` as subject to change. First public npm release is still ahead — until then, use the [local link workflow](./docs/local-link.md).
77
+
78
+ ## Develop
79
+
80
+ ```bash
81
+ git clone https://gitlab.com/rose42/feedback-capture.git
82
+ cursor feedback-capture
83
+ ```
84
+
85
+ ### Devcontainer
86
+
87
+ One-click Dev Container (Node, pnpm, T3 via `T3CODE_PORT`, default **3774** — [change in `.devcontainer/devcontainer.json`](./.devcontainer/devcontainer.json)). See [docs/devcontainer.md](./docs/devcontainer.md).
88
+
89
+ ### Scripts
90
+
91
+ ```bash
92
+ pnpm typecheck
93
+ pnpm lint
94
+ pnpm format:check
95
+ pnpm test
96
+ pnpm build
97
+ ```
98
+
99
+ Watch `dist/` while iterating against a consumer:
100
+
101
+ ```bash
102
+ pnpm dev
103
+ ```
104
+
105
+ ## License
106
+
107
+ [MIT](./LICENSE)
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Best-effort read of the first image on the system clipboard as a data URL.
3
+ * Returns undefined when the Clipboard API is unavailable, permission is denied,
4
+ * or the clipboard has no image.
5
+ */
6
+ export declare function readClipboardImageDataUrl(): Promise<string | undefined>;
7
+ //# sourceMappingURL=clipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgB7E"}
@@ -0,0 +1,33 @@
1
+ function blobToDataUrl(blob) {
2
+ return new Promise((resolve, reject) => {
3
+ const reader = new FileReader();
4
+ reader.onload = () => resolve(String(reader.result));
5
+ reader.onerror = () => reject(reader.error ?? new Error("Failed to read clipboard image"));
6
+ reader.readAsDataURL(blob);
7
+ });
8
+ }
9
+ /**
10
+ * Best-effort read of the first image on the system clipboard as a data URL.
11
+ * Returns undefined when the Clipboard API is unavailable, permission is denied,
12
+ * or the clipboard has no image.
13
+ */
14
+ export async function readClipboardImageDataUrl() {
15
+ try {
16
+ if (typeof navigator === "undefined" || !navigator.clipboard?.read) {
17
+ return undefined;
18
+ }
19
+ const items = await navigator.clipboard.read();
20
+ for (const item of items) {
21
+ const type = item.types.find((t) => t.startsWith("image/"));
22
+ if (!type)
23
+ continue;
24
+ const blob = await item.getType(type);
25
+ return await blobToDataUrl(blob);
26
+ }
27
+ return undefined;
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AAAA,SAAS,aAAa,CAAC,IAAU;IAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC3F,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,IAAI,CAAC;QACH,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;YACnE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { collectPageContext, type FeedbackCapturePlugin, type PageContext } from "./plugins/index.js";
2
+ import type { FeedbackEnvelope } from "./types.js";
3
+ export type { PageContext };
4
+ export type BuildFeedbackEnvelopeInput<Ps extends readonly FeedbackCapturePlugin[] = readonly FeedbackCapturePlugin[]> = {
5
+ plugins: Ps;
6
+ };
7
+ /** Assemble a FeedbackEnvelope by collecting all registered plugins. */
8
+ export declare function buildFeedbackEnvelope<const Ps extends readonly FeedbackCapturePlugin[]>(input: BuildFeedbackEnvelopeInput<Ps>): Promise<FeedbackEnvelope<Ps>>;
9
+ export { collectPageContext };
10
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAElB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B,MAAM,MAAM,0BAA0B,CACpC,EAAE,SAAS,SAAS,qBAAqB,EAAE,GAAG,SAAS,qBAAqB,EAAE,IAC5E;IACF,OAAO,EAAE,EAAE,CAAC;CACb,CAAC;AAEF,wEAAwE;AACxE,wBAAsB,qBAAqB,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,qBAAqB,EAAE,EAC3F,KAAK,EAAE,0BAA0B,CAAC,EAAE,CAAC,GACpC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAE/B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { collectPageContext, collectPluginExtras, } from "./plugins/index.js";
2
+ /** Assemble a FeedbackEnvelope by collecting all registered plugins. */
3
+ export async function buildFeedbackEnvelope(input) {
4
+ return collectPluginExtras(input.plugins);
5
+ }
6
+ export { collectPageContext };
7
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAGpB,MAAM,oBAAoB,CAAC;AAW5B,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAqC;IAErC,OAAO,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
package/dist/crop.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ /** Axis-aligned crop in natural image pixels. */
2
+ export type CropRect = {
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ };
8
+ export type ElementBox = {
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ };
14
+ export type ViewportMetrics = {
15
+ width: number;
16
+ height: number;
17
+ devicePixelRatio: number;
18
+ };
19
+ export type ImageNaturalSize = {
20
+ width: number;
21
+ height: number;
22
+ };
23
+ export type ElementBoxToCropRectOptions = {
24
+ /** Extra CSS pixels expanded around the box before scaling (default: 12). */
25
+ paddingPx?: number;
26
+ /** Minimum crop edge in natural pixels (default: 8). */
27
+ minSize?: number;
28
+ };
29
+ /**
30
+ * Map a CSS-viewport element box to a crop rect in screenshot natural pixels.
31
+ * Uses `devicePixelRatio` scaling (best-effort for preferCurrentTab captures).
32
+ */
33
+ export declare function elementBoxToCropRect(box: ElementBox, viewport: ViewportMetrics, image: ImageNaturalSize, options?: ElementBoxToCropRectOptions): CropRect | null;
34
+ /** Crop a PNG/JPEG data URL to `rect` (natural pixels); returns a PNG data URL. */
35
+ export declare function cropDataUrl(dataUrl: string, rect: CropRect): Promise<string>;
36
+ /** Where an object-fit:contain image sits inside its element box. */
37
+ export type ContainedImageLayout = {
38
+ offsetX: number;
39
+ offsetY: number;
40
+ displayWidth: number;
41
+ displayHeight: number;
42
+ naturalWidth: number;
43
+ naturalHeight: number;
44
+ scale: number;
45
+ };
46
+ /** Layout of a natural-size image inside a contain-fitted display box. */
47
+ export declare function containedImageLayout(naturalWidth: number, naturalHeight: number, boxWidth: number, boxHeight: number): ContainedImageLayout;
48
+ /** Map a point in the element’s client box to natural image pixels (clamped). */
49
+ export declare function clientPointToNatural(layout: ContainedImageLayout, localX: number, localY: number): {
50
+ x: number;
51
+ y: number;
52
+ };
53
+ /** Normalize a drag from two natural-space points into a CropRect (or null if tiny). */
54
+ export declare function rectFromPoints(a: {
55
+ x: number;
56
+ y: number;
57
+ }, b: {
58
+ x: number;
59
+ y: number;
60
+ }, naturalWidth: number, naturalHeight: number, minSize?: number): CropRect | null;
61
+ //# sourceMappingURL=crop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crop.d.ts","sourceRoot":"","sources":["../src/crop.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,MAAM,MAAM,QAAQ,GAAG;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,2BAAgC,GACxC,QAAQ,GAAG,IAAI,CAuCjB;AAWD,mFAAmF;AACnF,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAWlF;AAED,qEAAqE;AACrE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAIF,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,oBAAoB,CAwBtB;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,oBAAoB,EAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAO1B;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAC5B,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,SAA2B,GACjC,QAAQ,GAAG,IAAI,CAajB"}
package/dist/crop.js ADDED
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Map a CSS-viewport element box to a crop rect in screenshot natural pixels.
3
+ * Uses `devicePixelRatio` scaling (best-effort for preferCurrentTab captures).
4
+ */
5
+ export function elementBoxToCropRect(box, viewport, image, options = {}) {
6
+ if (box.width <= 0 || box.height <= 0 || image.width <= 0 || image.height <= 0) {
7
+ return null;
8
+ }
9
+ const padding = options.paddingPx ?? 12;
10
+ const minSize = options.minSize ?? 8;
11
+ const dpr = Number.isFinite(viewport.devicePixelRatio) && viewport.devicePixelRatio > 0
12
+ ? viewport.devicePixelRatio
13
+ : 1;
14
+ // Prefer mapping through expected CSS→device size when the frame matches the
15
+ // viewport closely; otherwise fall back to uniform scale from image size.
16
+ const expectedW = Math.max(1, viewport.width * dpr);
17
+ const expectedH = Math.max(1, viewport.height * dpr);
18
+ const scaleX = Math.abs(image.width - expectedW) / expectedW < 0.08
19
+ ? dpr
20
+ : image.width / Math.max(1, viewport.width);
21
+ const scaleY = Math.abs(image.height - expectedH) / expectedH < 0.08
22
+ ? dpr
23
+ : image.height / Math.max(1, viewport.height);
24
+ const left = (box.x - padding) * scaleX;
25
+ const top = (box.y - padding) * scaleY;
26
+ const right = (box.x + box.width + padding) * scaleX;
27
+ const bottom = (box.y + box.height + padding) * scaleY;
28
+ const x = Math.max(0, Math.floor(left));
29
+ const y = Math.max(0, Math.floor(top));
30
+ const maxRight = Math.min(image.width, Math.ceil(right));
31
+ const maxBottom = Math.min(image.height, Math.ceil(bottom));
32
+ const width = maxRight - x;
33
+ const height = maxBottom - y;
34
+ if (width < minSize || height < minSize)
35
+ return null;
36
+ return { x, y, width, height };
37
+ }
38
+ function loadImage(dataUrl) {
39
+ return new Promise((resolve, reject) => {
40
+ const img = new Image();
41
+ img.onload = () => resolve(img);
42
+ img.onerror = () => reject(new Error("Failed to load image for crop"));
43
+ img.src = dataUrl;
44
+ });
45
+ }
46
+ /** Crop a PNG/JPEG data URL to `rect` (natural pixels); returns a PNG data URL. */
47
+ export async function cropDataUrl(dataUrl, rect) {
48
+ const img = await loadImage(dataUrl);
49
+ const width = Math.max(1, Math.min(rect.width, img.naturalWidth - rect.x));
50
+ const height = Math.max(1, Math.min(rect.height, img.naturalHeight - rect.y));
51
+ const canvas = document.createElement("canvas");
52
+ canvas.width = width;
53
+ canvas.height = height;
54
+ const ctx = canvas.getContext("2d");
55
+ if (!ctx)
56
+ throw new Error("Canvas 2D unavailable");
57
+ ctx.drawImage(img, rect.x, rect.y, width, height, 0, 0, width, height);
58
+ return canvas.toDataURL("image/png");
59
+ }
60
+ const DEFAULT_MIN_SELECTION_PX = 8;
61
+ /** Layout of a natural-size image inside a contain-fitted display box. */
62
+ export function containedImageLayout(naturalWidth, naturalHeight, boxWidth, boxHeight) {
63
+ if (naturalWidth <= 0 || naturalHeight <= 0 || boxWidth <= 0 || boxHeight <= 0) {
64
+ return {
65
+ offsetX: 0,
66
+ offsetY: 0,
67
+ displayWidth: 0,
68
+ displayHeight: 0,
69
+ naturalWidth,
70
+ naturalHeight,
71
+ scale: 1,
72
+ };
73
+ }
74
+ const scale = Math.min(boxWidth / naturalWidth, boxHeight / naturalHeight);
75
+ const displayWidth = naturalWidth * scale;
76
+ const displayHeight = naturalHeight * scale;
77
+ return {
78
+ offsetX: (boxWidth - displayWidth) / 2,
79
+ offsetY: (boxHeight - displayHeight) / 2,
80
+ displayWidth,
81
+ displayHeight,
82
+ naturalWidth,
83
+ naturalHeight,
84
+ scale,
85
+ };
86
+ }
87
+ /** Map a point in the element’s client box to natural image pixels (clamped). */
88
+ export function clientPointToNatural(layout, localX, localY) {
89
+ const x = (localX - layout.offsetX) / layout.scale;
90
+ const y = (localY - layout.offsetY) / layout.scale;
91
+ return {
92
+ x: Math.min(Math.max(0, x), layout.naturalWidth),
93
+ y: Math.min(Math.max(0, y), layout.naturalHeight),
94
+ };
95
+ }
96
+ /** Normalize a drag from two natural-space points into a CropRect (or null if tiny). */
97
+ export function rectFromPoints(a, b, naturalWidth, naturalHeight, minSize = DEFAULT_MIN_SELECTION_PX) {
98
+ const x1 = Math.min(a.x, b.x);
99
+ const y1 = Math.min(a.y, b.y);
100
+ const x2 = Math.max(a.x, b.x);
101
+ const y2 = Math.max(a.y, b.y);
102
+ const x = Math.max(0, Math.floor(x1));
103
+ const y = Math.max(0, Math.floor(y1));
104
+ const right = Math.min(naturalWidth, Math.ceil(x2));
105
+ const bottom = Math.min(naturalHeight, Math.ceil(y2));
106
+ const width = right - x;
107
+ const height = bottom - y;
108
+ if (width < minSize || height < minSize)
109
+ return null;
110
+ return { x, y, width, height };
111
+ }
112
+ //# sourceMappingURL=crop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crop.js","sourceRoot":"","sources":["../src/crop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type { FeedbackEnvelope, FeedbackTransport, FeedbackViewport, PluginCollectData, PluginResult, } from "./types.js";
2
+ export { buildFeedbackEnvelope, collectPageContext, type BuildFeedbackEnvelopeInput, type PageContext, } from "./context.js";
3
+ export { initFeedbackCapture, type FeedbackCaptureSession } from "./session.js";
4
+ export { createHttpTransport, type HttpTransportOptions } from "./transport.js";
5
+ export { readClipboardImageDataUrl } from "./clipboard.js";
6
+ export type { ContainedImageLayout, CropRect, ElementBox, ElementBoxToCropRectOptions, ImageNaturalSize, ViewportMetrics, } from "./crop.js";
7
+ export { clientPointToNatural, containedImageLayout, cropDataUrl, elementBoxToCropRect, rectFromPoints, } from "./crop.js";
8
+ export type { AppVersionInfo, BurstFrame, CaptureFrameBurstOptions, CaptureScreenshotOptions, CommentPluginOptions, ComponentSourceLocation, ConsoleLogEntry, ConsoleLogLevel, ConsoleLogsPluginOptions, ElementBoundingBox, ElementSourceEnrichment, ElementStylesMode, ElementTarget, ElementTargetPlugin, ElementTargetPluginOptions, FeedbackCapturePlugin, PickElementOptions, ResolveElementSource, SampledFrame, ScreenshotPluginOptions, SelectChangedFramesOptions, VersionPluginOptions, } from "./plugins/index.js";
9
+ export { attachImagePasteHandler, buildCssSelector, captureFrameBurst, captureScreenshot, clampMaxImages, collectComputedStyles, collectElementTarget, collectElementTargetAsync, collectPluginExtras, createCommentPlugin, createConsoleLogsPlugin, createElementTargetPlugin, createPageContextPlugin, createScreenshotPlugin, createVersionPlugin, installCapturePlugins, pickElement, resolveInteractiveTarget, selectChangedFrames, COMPUTED_EXTRA_STYLE_PROPS, DEFAULT_BURST_DIFF_THRESHOLD, DEFAULT_BURST_MAX_CANDIDATES, DEFAULT_BURST_MAX_DURATION_MS, DEFAULT_BURST_MIN_SPACING_MS, DEFAULT_BURST_SAMPLE_FPS, DEFAULT_BURST_THUMB_WIDTH, DEFAULT_MAX_IMAGES, LAYOUT_STYLE_PROPS, } from "./plugins/index.js";
10
+ export type { CreateSourceResolverOptions, LocatorSourceResolverOptions, NextSourceResolverOptions, QwikSourceResolverOptions, ReactSourceResolverOptions, SourceFrameworkChoice, SourceFrameworkId, SvelteSourceResolverOptions, VueSourceResolverOptions, } from "./source/adapters/index.js";
11
+ export { composeSourceResolvers, createFiberStackSourceResolver, createLocatorSourceResolver, createNextSourceResolver, createQwikSourceResolver, createReactSourceResolver, createSourceResolver, createSvelteSourceResolver, createVueSourceResolver, defaultFrameworkOrder, detectFrameworkOnElement, detectFrameworkOrder, findCompositeFiber, flightPagePathMatchesUrl, flightPagePathToAppFile, isSourceFrameworkChoice, normalizeNextSourcePath, pageLooksLikeNext, parseLocatorValue, parseNextFlightPagePaths, parseQwikInspectorValue, pickNextFlightPagePath, } from "./source/adapters/index.js";
12
+ export { clearSourceMapCaches, isAppFrame, isAppSourcePath, normalizeSourcePath, parseStackFrames, resolveOriginalPosition, } from "./source/sourceMap.js";
13
+ export { classNameOf, locateJsxInSource } from "./source/locateJsx.js";
14
+ export type { RankedSourceEnrichment } from "./source/rankSourceHierarchy.js";
15
+ export { isUiPrimitiveSource, rankSourceHierarchy, sameSourceLocation, } from "./source/rankSourceHierarchy.js";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAAE,KAAK,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,YAAY,EACV,oBAAoB,EACpB,QAAQ,EACR,UAAU,EACV,2BAA2B,EAC3B,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,cAAc,GACf,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,cAAc,EACd,UAAU,EACV,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,EACX,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,iCAAiC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { buildFeedbackEnvelope, collectPageContext, } from "./context.js";
2
+ export { initFeedbackCapture } from "./session.js";
3
+ export { createHttpTransport } from "./transport.js";
4
+ export { readClipboardImageDataUrl } from "./clipboard.js";
5
+ export { clientPointToNatural, containedImageLayout, cropDataUrl, elementBoxToCropRect, rectFromPoints, } from "./crop.js";
6
+ export { attachImagePasteHandler, buildCssSelector, captureFrameBurst, captureScreenshot, clampMaxImages, collectComputedStyles, collectElementTarget, collectElementTargetAsync, collectPluginExtras, createCommentPlugin, createConsoleLogsPlugin, createElementTargetPlugin, createPageContextPlugin, createScreenshotPlugin, createVersionPlugin, installCapturePlugins, pickElement, resolveInteractiveTarget, selectChangedFrames, COMPUTED_EXTRA_STYLE_PROPS, DEFAULT_BURST_DIFF_THRESHOLD, DEFAULT_BURST_MAX_CANDIDATES, DEFAULT_BURST_MAX_DURATION_MS, DEFAULT_BURST_MIN_SPACING_MS, DEFAULT_BURST_SAMPLE_FPS, DEFAULT_BURST_THUMB_WIDTH, DEFAULT_MAX_IMAGES, LAYOUT_STYLE_PROPS, } from "./plugins/index.js";
7
+ export { composeSourceResolvers, createFiberStackSourceResolver, createLocatorSourceResolver, createNextSourceResolver, createQwikSourceResolver, createReactSourceResolver, createSourceResolver, createSvelteSourceResolver, createVueSourceResolver, defaultFrameworkOrder, detectFrameworkOnElement, detectFrameworkOrder, findCompositeFiber, flightPagePathMatchesUrl, flightPagePathToAppFile, isSourceFrameworkChoice, normalizeNextSourcePath, pageLooksLikeNext, parseLocatorValue, parseNextFlightPagePaths, parseQwikInspectorValue, pickNextFlightPagePath, } from "./source/adapters/index.js";
8
+ export { clearSourceMapCaches, isAppFrame, isAppSourcePath, normalizeSourcePath, parseStackFrames, resolveOriginalPosition, } from "./source/sourceMap.js";
9
+ export { classNameOf, locateJsxInSource } from "./source/locateJsx.js";
10
+ export { isUiPrimitiveSource, rankSourceHierarchy, sameSourceLocation, } from "./source/rankSourceHierarchy.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAA+B,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,mBAAmB,EAA6B,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAU3D,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,cAAc,GACf,MAAM,WAAW,CAAC;AA2BnB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,EACX,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAa5B,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FeedbackCapturePlugin } from "./core.js";
2
+ export type CommentPluginOptions = {
3
+ /** Read the current comment at collect time. */
4
+ getComment: () => string;
5
+ };
6
+ /**
7
+ * Built-in plugin that contributes the user comment as `envelope.comment`.
8
+ * Empty/whitespace-only comments return `undefined` (key omitted).
9
+ */
10
+ export declare function createCommentPlugin(options: CommentPluginOptions): FeedbackCapturePlugin<"comment", string>;
11
+ //# sourceMappingURL=comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/plugins/comment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG;IACjC,gDAAgD;IAChD,UAAU,EAAE,MAAM,MAAM,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,GAC5B,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,CAQ1C"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Built-in plugin that contributes the user comment as `envelope.comment`.
3
+ * Empty/whitespace-only comments return `undefined` (key omitted).
4
+ */
5
+ export function createCommentPlugin(options) {
6
+ return {
7
+ id: "comment",
8
+ collect() {
9
+ const comment = options.getComment().trim();
10
+ return comment.length > 0 ? comment : undefined;
11
+ },
12
+ };
13
+ }
14
+ //# sourceMappingURL=comment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.js","sourceRoot":"","sources":["../../src/plugins/comment.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAA6B;IAE7B,OAAO;QACL,EAAE,EAAE,SAAS;QACb,OAAO;YACL,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FeedbackCapturePlugin } from "./core.js";
2
+ export type ConsoleLogLevel = "log" | "info" | "warn" | "error" | "debug";
3
+ export type ConsoleLogsPluginOptions = {
4
+ maxEntries?: number;
5
+ levels?: ConsoleLogLevel[];
6
+ };
7
+ export type ConsoleLogEntry = {
8
+ level: ConsoleLogLevel;
9
+ args: unknown[];
10
+ timestamp: string;
11
+ };
12
+ /** Built-in plugin that buffers console output for inclusion in `envelope.consoleLogs`. */
13
+ export declare function createConsoleLogsPlugin(options?: ConsoleLogsPluginOptions): FeedbackCapturePlugin<"consoleLogs", ConsoleLogEntry[]>;
14
+ //# sourceMappingURL=consoleLogs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consoleLogs.d.ts","sourceRoot":"","sources":["../../src/plugins/consoleLogs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEvD,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AA+CF,2FAA2F;AAC3F,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,qBAAqB,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC,CAgDzD"}
@@ -0,0 +1,98 @@
1
+ const DEFAULT_LEVELS = ["log", "info", "warn", "error", "debug"];
2
+ function serializeArg(value, seen) {
3
+ if (value === null || value === undefined)
4
+ return value;
5
+ const t = typeof value;
6
+ if (t === "string" || t === "number" || t === "boolean" || t === "bigint") {
7
+ return t === "bigint" ? value.toString() : value;
8
+ }
9
+ if (t === "symbol")
10
+ return value.toString();
11
+ if (t === "function") {
12
+ return `[Function ${value.name || "anonymous"}]`;
13
+ }
14
+ if (value instanceof Error) {
15
+ return {
16
+ name: value.name,
17
+ message: value.message,
18
+ stack: value.stack,
19
+ };
20
+ }
21
+ if (typeof Node !== "undefined" && value instanceof Node) {
22
+ if (value instanceof Element) {
23
+ return `[${value.tagName.toLowerCase()}]`;
24
+ }
25
+ return `[${value.nodeName}]`;
26
+ }
27
+ if (t === "object") {
28
+ const obj = value;
29
+ if (seen.has(obj))
30
+ return "[Circular]";
31
+ seen.add(obj);
32
+ if (Array.isArray(value)) {
33
+ return value.map((item) => serializeArg(item, seen));
34
+ }
35
+ try {
36
+ const out = {};
37
+ for (const [k, v] of Object.entries(value)) {
38
+ out[k] = serializeArg(v, seen);
39
+ }
40
+ return out;
41
+ }
42
+ catch {
43
+ return String(value);
44
+ }
45
+ }
46
+ return String(value);
47
+ }
48
+ /** Built-in plugin that buffers console output for inclusion in `envelope.consoleLogs`. */
49
+ export function createConsoleLogsPlugin(options = {}) {
50
+ const maxEntries = options.maxEntries ?? 200;
51
+ const levels = options.levels ?? DEFAULT_LEVELS;
52
+ const entries = [];
53
+ const originals = new Map();
54
+ let installed = false;
55
+ const push = (level, args) => {
56
+ const seen = new WeakSet();
57
+ entries.push({
58
+ level,
59
+ args: args.map((arg) => serializeArg(arg, seen)),
60
+ timestamp: new Date().toISOString(),
61
+ });
62
+ while (entries.length > maxEntries) {
63
+ entries.shift();
64
+ }
65
+ };
66
+ return {
67
+ id: "consoleLogs",
68
+ setup() {
69
+ if (installed || typeof console === "undefined")
70
+ return;
71
+ installed = true;
72
+ for (const level of levels) {
73
+ const original = console[level].bind(console);
74
+ originals.set(level, original);
75
+ console[level] = (...args) => {
76
+ push(level, args);
77
+ original(...args);
78
+ };
79
+ }
80
+ },
81
+ collect() {
82
+ return entries.slice();
83
+ },
84
+ dispose() {
85
+ if (!installed)
86
+ return;
87
+ for (const level of levels) {
88
+ const original = originals.get(level);
89
+ if (original) {
90
+ console[level] = original;
91
+ }
92
+ }
93
+ originals.clear();
94
+ installed = false;
95
+ },
96
+ };
97
+ }
98
+ //# sourceMappingURL=consoleLogs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consoleLogs.js","sourceRoot":"","sources":["../../src/plugins/consoleLogs.ts"],"names":[],"mappings":"AAeA,MAAM,cAAc,GAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAEpF,SAAS,YAAY,CAAC,KAAc,EAAE,IAAqB;IACzD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1E,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5C,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;QACrB,OAAO,aAAc,KAA2B,CAAC,IAAI,IAAI,WAAW,GAAG,CAAC;IAC1E,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QACzD,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;YAC7B,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,KAAe,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,YAAY,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAA4B,EAAE,CAAC;YACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;gBACtE,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,uBAAuB,CACrC,UAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC;IAChD,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiD,CAAC;IAC3E,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,IAAI,GAAG,CAAC,KAAsB,EAAE,IAAe,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,IAAI,OAAO,EAAU,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC;YACX,KAAK;YACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAChD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,KAAK;YACH,IAAI,SAAS,IAAI,OAAO,OAAO,KAAK,WAAW;gBAAE,OAAO;YACxD,SAAS,GAAG,IAAI,CAAC;YACjB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAiC,CAAC;gBAC9E,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC/B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;oBACtC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAClB,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;gBACpB,CAAC,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO;YACL,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;QACD,OAAO;YACL,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACtC,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,GAAG,QAA8B,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ export type FeedbackCapturePlugin<Id extends string = string, Data = unknown> = {
2
+ /** Key under the feedback envelope. */
3
+ id: Id;
4
+ /**
5
+ * Optional early install (e.g. patch console).
6
+ * May return a disposer; otherwise use `dispose`.
7
+ */
8
+ setup?: () => void | (() => void);
9
+ /** Snapshot at send time. Return `undefined` to omit this plugin’s key. */
10
+ collect: () => Data | undefined | Promise<Data | undefined>;
11
+ /** Cleanup (also called on unmount). */
12
+ dispose?: () => void;
13
+ };
14
+ /**
15
+ * Run each plugin's `setup`, returning a single dispose that runs all
16
+ * setup-returned disposers and `dispose` hooks (idempotent).
17
+ */
18
+ export declare function installCapturePlugins(plugins: readonly FeedbackCapturePlugin[]): () => void;
19
+ /**
20
+ * Await all `collect()` calls and merge into an envelope keyed by plugin id.
21
+ * Skips `undefined`. On collect throw, stores `{ ok: false, error }` under that id.
22
+ */
23
+ export declare function collectPluginExtras<const Ps extends readonly FeedbackCapturePlugin[]>(plugins: Ps): Promise<import("../types.js").FeedbackEnvelope<Ps>>;
24
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,CAAC,EAAE,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,GAAG,OAAO,IAAI;IAC9E,uCAAuC;IACvC,EAAE,EAAE,EAAE,CAAC;IACP;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAClC,2EAA2E;IAC3E,OAAO,EAAE,MAAM,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC5D,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GAAG,MAAM,IAAI,CAiC3F;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,qBAAqB,EAAE,EACzF,OAAO,EAAE,EAAE,GACV,OAAO,CAAC,OAAO,aAAa,EAAE,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAkBrD"}