web-remarq 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.cjs +149 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +54 -1
- package/dist/core/index.d.ts +54 -1
- package/dist/core/index.js +146 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +164 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -3
- package/dist/index.d.ts +40 -3
- package/dist/index.js +164 -4
- package/dist/index.js.map +1 -1
- package/dist/web-remarq.global.global.js +164 -4
- package/dist/web-remarq.global.global.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -17,6 +17,10 @@ interface ElementFingerprint {
|
|
|
17
17
|
parentAnchor: string | null;
|
|
18
18
|
rawClasses?: string[];
|
|
19
19
|
cssModules?: CSSModuleClass[];
|
|
20
|
+
sourceLocation: string | null;
|
|
21
|
+
componentName: string | null;
|
|
22
|
+
detectedSource: string | null;
|
|
23
|
+
detectedComponent: string | null;
|
|
20
24
|
}
|
|
21
25
|
interface Annotation {
|
|
22
26
|
id: string;
|
|
@@ -43,16 +47,49 @@ interface ImportResult {
|
|
|
43
47
|
otherBreakpoint: number;
|
|
44
48
|
detached: number;
|
|
45
49
|
}
|
|
50
|
+
type SearchConfidence = 'high' | 'medium' | 'low';
|
|
51
|
+
interface GrepQuery {
|
|
52
|
+
query: string;
|
|
53
|
+
glob: string;
|
|
54
|
+
confidence: SearchConfidence;
|
|
55
|
+
}
|
|
56
|
+
interface AgentSearchHints {
|
|
57
|
+
grepQueries: GrepQuery[];
|
|
58
|
+
domContext: string;
|
|
59
|
+
tagName: string;
|
|
60
|
+
classes: string[];
|
|
61
|
+
}
|
|
62
|
+
interface AgentAnnotationSource {
|
|
63
|
+
file: string;
|
|
64
|
+
line: number;
|
|
65
|
+
column: number;
|
|
66
|
+
component: string | null;
|
|
67
|
+
}
|
|
68
|
+
interface AgentAnnotation {
|
|
69
|
+
id: string;
|
|
70
|
+
route: string;
|
|
71
|
+
comment: string;
|
|
72
|
+
status: 'pending' | 'resolved';
|
|
73
|
+
timestamp: number;
|
|
74
|
+
source: AgentAnnotationSource | null;
|
|
75
|
+
searchHints: AgentSearchHints;
|
|
76
|
+
}
|
|
77
|
+
interface AgentExport {
|
|
78
|
+
version: 1;
|
|
79
|
+
format: 'agent';
|
|
80
|
+
viewportBucket: number;
|
|
81
|
+
annotations: AgentAnnotation[];
|
|
82
|
+
}
|
|
46
83
|
|
|
47
84
|
declare const WebRemarq: {
|
|
48
85
|
init(opts?: WebRemarqOptions): void;
|
|
49
86
|
destroy(): void;
|
|
50
87
|
setTheme(theme: "light" | "dark"): void;
|
|
51
|
-
export(format: "md" | "json"): void;
|
|
52
|
-
copy(): void;
|
|
88
|
+
export(format: "md" | "json" | "agent"): void;
|
|
89
|
+
copy(format?: "md" | "agent"): void;
|
|
53
90
|
import(file: File): Promise<ImportResult>;
|
|
54
91
|
getAnnotations(route?: string): Annotation[];
|
|
55
92
|
clearAll(): void;
|
|
56
93
|
};
|
|
57
94
|
|
|
58
|
-
export { type Annotation, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|
|
95
|
+
export { type AgentAnnotation, type AgentExport, type Annotation, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ interface ElementFingerprint {
|
|
|
17
17
|
parentAnchor: string | null;
|
|
18
18
|
rawClasses?: string[];
|
|
19
19
|
cssModules?: CSSModuleClass[];
|
|
20
|
+
sourceLocation: string | null;
|
|
21
|
+
componentName: string | null;
|
|
22
|
+
detectedSource: string | null;
|
|
23
|
+
detectedComponent: string | null;
|
|
20
24
|
}
|
|
21
25
|
interface Annotation {
|
|
22
26
|
id: string;
|
|
@@ -43,16 +47,49 @@ interface ImportResult {
|
|
|
43
47
|
otherBreakpoint: number;
|
|
44
48
|
detached: number;
|
|
45
49
|
}
|
|
50
|
+
type SearchConfidence = 'high' | 'medium' | 'low';
|
|
51
|
+
interface GrepQuery {
|
|
52
|
+
query: string;
|
|
53
|
+
glob: string;
|
|
54
|
+
confidence: SearchConfidence;
|
|
55
|
+
}
|
|
56
|
+
interface AgentSearchHints {
|
|
57
|
+
grepQueries: GrepQuery[];
|
|
58
|
+
domContext: string;
|
|
59
|
+
tagName: string;
|
|
60
|
+
classes: string[];
|
|
61
|
+
}
|
|
62
|
+
interface AgentAnnotationSource {
|
|
63
|
+
file: string;
|
|
64
|
+
line: number;
|
|
65
|
+
column: number;
|
|
66
|
+
component: string | null;
|
|
67
|
+
}
|
|
68
|
+
interface AgentAnnotation {
|
|
69
|
+
id: string;
|
|
70
|
+
route: string;
|
|
71
|
+
comment: string;
|
|
72
|
+
status: 'pending' | 'resolved';
|
|
73
|
+
timestamp: number;
|
|
74
|
+
source: AgentAnnotationSource | null;
|
|
75
|
+
searchHints: AgentSearchHints;
|
|
76
|
+
}
|
|
77
|
+
interface AgentExport {
|
|
78
|
+
version: 1;
|
|
79
|
+
format: 'agent';
|
|
80
|
+
viewportBucket: number;
|
|
81
|
+
annotations: AgentAnnotation[];
|
|
82
|
+
}
|
|
46
83
|
|
|
47
84
|
declare const WebRemarq: {
|
|
48
85
|
init(opts?: WebRemarqOptions): void;
|
|
49
86
|
destroy(): void;
|
|
50
87
|
setTheme(theme: "light" | "dark"): void;
|
|
51
|
-
export(format: "md" | "json"): void;
|
|
52
|
-
copy(): void;
|
|
88
|
+
export(format: "md" | "json" | "agent"): void;
|
|
89
|
+
copy(format?: "md" | "agent"): void;
|
|
53
90
|
import(file: File): Promise<ImportResult>;
|
|
54
91
|
getAnnotations(route?: string): Annotation[];
|
|
55
92
|
clearAll(): void;
|
|
56
93
|
};
|
|
57
94
|
|
|
58
|
-
export { type Annotation, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|
|
95
|
+
export { type AgentAnnotation, type AgentExport, type Annotation, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|
package/dist/index.js
CHANGED
|
@@ -194,12 +194,54 @@ function decomposeCSSModules(classes) {
|
|
|
194
194
|
return result;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// src/core/source-detect.ts
|
|
198
|
+
function detectRemarqPlugin(el) {
|
|
199
|
+
const source = el.getAttribute("data-remarq-source");
|
|
200
|
+
if (!source) return { source: null, component: null };
|
|
201
|
+
return {
|
|
202
|
+
source,
|
|
203
|
+
component: el.getAttribute("data-remarq-component")
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function detectExternalSource(el) {
|
|
207
|
+
var _a;
|
|
208
|
+
const source = (_a = el.dataset.source) != null ? _a : el.getAttribute("data-locator");
|
|
209
|
+
if (!source) return { source: null, component: null };
|
|
210
|
+
return { source, component: null };
|
|
211
|
+
}
|
|
212
|
+
function detectReactFiber(el) {
|
|
213
|
+
var _a, _b, _c, _d;
|
|
214
|
+
const key = Object.keys(el).find((k) => k.startsWith("__reactFiber$"));
|
|
215
|
+
if (!key) return { source: null, component: null };
|
|
216
|
+
let current = el[key];
|
|
217
|
+
let depth = 0;
|
|
218
|
+
while (current && depth < 15) {
|
|
219
|
+
const debugSource = current._debugSource;
|
|
220
|
+
if (debugSource == null ? void 0 : debugSource.fileName) {
|
|
221
|
+
const source = `${debugSource.fileName}:${(_a = debugSource.lineNumber) != null ? _a : 0}:${(_b = debugSource.columnNumber) != null ? _b : 0}`;
|
|
222
|
+
const fiberType = current.type;
|
|
223
|
+
const component = typeof fiberType === "object" && fiberType ? (_d = (_c = fiberType.displayName) != null ? _c : fiberType.name) != null ? _d : null : null;
|
|
224
|
+
return { source, component };
|
|
225
|
+
}
|
|
226
|
+
current = current.return;
|
|
227
|
+
depth++;
|
|
228
|
+
}
|
|
229
|
+
return { source: null, component: null };
|
|
230
|
+
}
|
|
231
|
+
function detectSource(el) {
|
|
232
|
+
const external = detectExternalSource(el);
|
|
233
|
+
if (external.source) return external;
|
|
234
|
+
const fiber = detectReactFiber(el);
|
|
235
|
+
if (fiber.source) return fiber;
|
|
236
|
+
return { source: null, component: null };
|
|
237
|
+
}
|
|
238
|
+
|
|
197
239
|
// src/core/fingerprint.ts
|
|
198
240
|
var TEXT_MAX_LENGTH = 50;
|
|
199
241
|
function createFingerprint(el, options2) {
|
|
200
242
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
201
243
|
const dataAttr = (_a = options2 == null ? void 0 : options2.dataAttribute) != null ? _a : "data-annotate";
|
|
202
|
-
return {
|
|
244
|
+
return __spreadValues({
|
|
203
245
|
dataAnnotate: (_b = el.getAttribute(dataAttr)) != null ? _b : null,
|
|
204
246
|
dataTestId: (_e = (_d = (_c = el.getAttribute("data-testid")) != null ? _c : el.getAttribute("data-test")) != null ? _d : el.getAttribute("data-cy")) != null ? _e : null,
|
|
205
247
|
id: getStableId(el),
|
|
@@ -216,6 +258,24 @@ function createFingerprint(el, options2) {
|
|
|
216
258
|
parentAnchor: findParentAnchor(el, dataAttr),
|
|
217
259
|
rawClasses: Array.from(el.classList),
|
|
218
260
|
cssModules: decomposeCSSModules(Array.from(el.classList))
|
|
261
|
+
}, resolveSourceFields(el));
|
|
262
|
+
}
|
|
263
|
+
function resolveSourceFields(el) {
|
|
264
|
+
const plugin = detectRemarqPlugin(el);
|
|
265
|
+
if (plugin.source) {
|
|
266
|
+
return {
|
|
267
|
+
sourceLocation: plugin.source,
|
|
268
|
+
componentName: plugin.component,
|
|
269
|
+
detectedSource: null,
|
|
270
|
+
detectedComponent: null
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const detected = detectSource(el);
|
|
274
|
+
return {
|
|
275
|
+
sourceLocation: null,
|
|
276
|
+
componentName: null,
|
|
277
|
+
detectedSource: detected.source,
|
|
278
|
+
detectedComponent: detected.component
|
|
219
279
|
};
|
|
220
280
|
}
|
|
221
281
|
function getStableId(el) {
|
|
@@ -401,6 +461,88 @@ function matchElement(fp, options2) {
|
|
|
401
461
|
return bestScore >= MATCH_THRESHOLD ? bestEl : null;
|
|
402
462
|
}
|
|
403
463
|
|
|
464
|
+
// src/core/agent-export.ts
|
|
465
|
+
function parseSourceLocation(raw) {
|
|
466
|
+
const parts = raw.split(":");
|
|
467
|
+
if (parts.length < 2) return null;
|
|
468
|
+
const column = parseInt(parts.pop(), 10);
|
|
469
|
+
const line = parseInt(parts.pop(), 10);
|
|
470
|
+
const file = parts.join(":");
|
|
471
|
+
if (!file || isNaN(line)) return null;
|
|
472
|
+
return { file, line, column: isNaN(column) ? 0 : column };
|
|
473
|
+
}
|
|
474
|
+
function resolveSource(fp) {
|
|
475
|
+
var _a, _b;
|
|
476
|
+
if (fp.sourceLocation) {
|
|
477
|
+
const parsed = parseSourceLocation(fp.sourceLocation);
|
|
478
|
+
if (parsed) return __spreadProps(__spreadValues({}, parsed), { component: (_a = fp.componentName) != null ? _a : null });
|
|
479
|
+
}
|
|
480
|
+
if (fp.detectedSource) {
|
|
481
|
+
const parsed = parseSourceLocation(fp.detectedSource);
|
|
482
|
+
if (parsed) return __spreadProps(__spreadValues({}, parsed), { component: (_b = fp.detectedComponent) != null ? _b : null });
|
|
483
|
+
}
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
var TEMPLATE_GLOB = "*.{tsx,jsx,vue,svelte,html}";
|
|
487
|
+
var CSS_MODULE_GLOB = "*.module.{css,scss,less}";
|
|
488
|
+
var COMPONENT_GLOB = "*.{tsx,jsx,vue,ts,js}";
|
|
489
|
+
function buildSearchHints(fp) {
|
|
490
|
+
var _a, _b;
|
|
491
|
+
const grepQueries = [];
|
|
492
|
+
if (fp.dataAnnotate) {
|
|
493
|
+
grepQueries.push({ query: `data-annotate="${fp.dataAnnotate}"`, glob: TEMPLATE_GLOB, confidence: "high" });
|
|
494
|
+
}
|
|
495
|
+
if (fp.dataTestId) {
|
|
496
|
+
grepQueries.push({ query: `data-testid="${fp.dataTestId}"`, glob: TEMPLATE_GLOB, confidence: "high" });
|
|
497
|
+
}
|
|
498
|
+
if (fp.id) {
|
|
499
|
+
grepQueries.push({ query: `id="${fp.id}"`, glob: TEMPLATE_GLOB, confidence: "high" });
|
|
500
|
+
}
|
|
501
|
+
if (fp.ariaLabel) {
|
|
502
|
+
grepQueries.push({ query: `aria-label="${fp.ariaLabel}"`, glob: TEMPLATE_GLOB, confidence: "high" });
|
|
503
|
+
}
|
|
504
|
+
if (fp.textContent) {
|
|
505
|
+
grepQueries.push({ query: `"${fp.textContent}"`, glob: TEMPLATE_GLOB, confidence: "medium" });
|
|
506
|
+
}
|
|
507
|
+
if (fp.role) {
|
|
508
|
+
grepQueries.push({ query: `role="${fp.role}"`, glob: TEMPLATE_GLOB, confidence: "medium" });
|
|
509
|
+
}
|
|
510
|
+
if ((_a = fp.cssModules) == null ? void 0 : _a.length) {
|
|
511
|
+
for (const mod of fp.cssModules) {
|
|
512
|
+
grepQueries.push({ query: `.${mod.localName}`, glob: CSS_MODULE_GLOB, confidence: "medium" });
|
|
513
|
+
grepQueries.push({ query: `styles.${mod.localName}`, glob: COMPONENT_GLOB, confidence: "medium" });
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (fp.stableClasses.length) {
|
|
517
|
+
for (const cls of fp.stableClasses.slice(0, 3)) {
|
|
518
|
+
grepQueries.push({ query: `"${cls}"`, glob: TEMPLATE_GLOB, confidence: "low" });
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return {
|
|
522
|
+
grepQueries,
|
|
523
|
+
domContext: fp.domPath,
|
|
524
|
+
tagName: fp.tagName,
|
|
525
|
+
classes: (_b = fp.rawClasses) != null ? _b : fp.stableClasses
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function generateAgentExport(annotations, viewportBucket) {
|
|
529
|
+
const agentAnnotations = annotations.map((ann) => ({
|
|
530
|
+
id: ann.id,
|
|
531
|
+
route: ann.route,
|
|
532
|
+
comment: ann.comment,
|
|
533
|
+
status: ann.status,
|
|
534
|
+
timestamp: ann.timestamp,
|
|
535
|
+
source: resolveSource(ann.fingerprint),
|
|
536
|
+
searchHints: buildSearchHints(ann.fingerprint)
|
|
537
|
+
}));
|
|
538
|
+
return {
|
|
539
|
+
version: 1,
|
|
540
|
+
format: "agent",
|
|
541
|
+
viewportBucket,
|
|
542
|
+
annotations: agentAnnotations
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
404
546
|
// src/ui/styles.ts
|
|
405
547
|
var STYLES_ID = "data-remarq-styles";
|
|
406
548
|
var CSS = `
|
|
@@ -1955,6 +2097,22 @@ function copyToClipboard() {
|
|
|
1955
2097
|
console.warn("[web-remarq] Clipboard write failed");
|
|
1956
2098
|
});
|
|
1957
2099
|
}
|
|
2100
|
+
function exportAgent() {
|
|
2101
|
+
const anns = storage.getAll();
|
|
2102
|
+
if (!anns.length) return;
|
|
2103
|
+
const data = generateAgentExport(anns, toBucket(window.innerWidth));
|
|
2104
|
+
const json = JSON.stringify(data, null, 2);
|
|
2105
|
+
downloadFile(json, `remarq-agent-${Date.now()}.json`, "application/json");
|
|
2106
|
+
}
|
|
2107
|
+
function copyAgentToClipboard() {
|
|
2108
|
+
const anns = storage.getAll();
|
|
2109
|
+
if (!anns.length) return;
|
|
2110
|
+
const data = generateAgentExport(anns, toBucket(window.innerWidth));
|
|
2111
|
+
const json = JSON.stringify(data, null, 2);
|
|
2112
|
+
navigator.clipboard.writeText(json).catch(() => {
|
|
2113
|
+
console.warn("[web-remarq] Clipboard write failed");
|
|
2114
|
+
});
|
|
2115
|
+
}
|
|
1958
2116
|
function setupMutationObserver() {
|
|
1959
2117
|
mutationObserver = new MutationObserver((mutations) => {
|
|
1960
2118
|
for (const m of mutations) {
|
|
@@ -2060,10 +2218,12 @@ var WebRemarq = {
|
|
|
2060
2218
|
},
|
|
2061
2219
|
export(format) {
|
|
2062
2220
|
if (format === "md") exportMarkdown();
|
|
2063
|
-
else exportJSON();
|
|
2221
|
+
else if (format === "json") exportJSON();
|
|
2222
|
+
else exportAgent();
|
|
2064
2223
|
},
|
|
2065
|
-
copy() {
|
|
2066
|
-
|
|
2224
|
+
copy(format) {
|
|
2225
|
+
if (format === "agent") copyAgentToClipboard();
|
|
2226
|
+
else copyToClipboard();
|
|
2067
2227
|
},
|
|
2068
2228
|
async import(file) {
|
|
2069
2229
|
const text = await file.text();
|