web-remarq 0.6.0 → 0.7.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/README.md +27 -2
- package/dist/core/index.cjs +101 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +39 -3
- package/dist/core/index.d.ts +39 -3
- package/dist/core/index.js +96 -4
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +456 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -3
- package/dist/index.d.ts +34 -3
- package/dist/index.js +456 -76
- package/dist/index.js.map +1 -1
- package/dist/web-remarq.global.global.js +456 -76
- package/dist/web-remarq.global.global.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -118,6 +118,31 @@ The interface is async by design — supports remote backends (Supabase, REST, I
|
|
|
118
118
|
|
|
119
119
|
`@web-remarq/cloud` (planned) will ship a Supabase-backed `StorageAdapter` implementation for team collaboration.
|
|
120
120
|
|
|
121
|
+
## Lifecycle states
|
|
122
|
+
|
|
123
|
+
Annotations follow a 5-state lifecycle with a verification gate between AI-claimed fixes and human confirmation. Every transition is recorded in `annotation.lifecycle: AnnotationEvent[]` (`{ type, actor, actorName?, timestamp, reason? }`).
|
|
124
|
+
|
|
125
|
+
| Status | Semantics |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `pending` | Newly created — needs attention |
|
|
128
|
+
| `in_progress` | Acknowledged, work started |
|
|
129
|
+
| `fixed_unverified` | Agent claims it's fixed, awaiting human verification |
|
|
130
|
+
| `verified` | Human confirmed the fix |
|
|
131
|
+
| `dismissed` | Won't fix (terminal) |
|
|
132
|
+
|
|
133
|
+
### Lifecycle API
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
WebRemarq.acknowledge(id, opts?) // → in_progress
|
|
137
|
+
WebRemarq.claimFix(id, opts?) // → fixed_unverified (agent-only — no UI button)
|
|
138
|
+
WebRemarq.verify(id, opts?) // → verified (from in_progress or fixed_unverified)
|
|
139
|
+
WebRemarq.reject(id, opts?: { reason?: string }) // fixed_unverified → pending
|
|
140
|
+
WebRemarq.dismiss(id, opts?: { reason?: string }) // → dismissed
|
|
141
|
+
WebRemarq.reopen(id, opts?) // verified | dismissed → pending
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`opts?: { actor?: 'designer' | 'agent' | 'developer', actorName?: string }`. `claimFix` is intended for agents over MCP; humans skip it and call `verify` directly from `in_progress` for manual fixes. Legacy `'resolved'` status migrates to `'verified'` on load with a synthetic `migrated` event appended to `lifecycle`.
|
|
145
|
+
|
|
121
146
|
## Agent Export Format
|
|
122
147
|
|
|
123
148
|
The `export('agent')` format is optimized for AI coding agents:
|
|
@@ -213,8 +238,8 @@ Works without any markup changes, but for guaranteed stable matching add `data-a
|
|
|
213
238
|
- **Toolbar** — fixed bottom-right panel with inspect, spacing, copy, export, import, clear, theme, minimize
|
|
214
239
|
- **Inspect mode** — hover to highlight, click to annotate
|
|
215
240
|
- **Spacing inspector** — visualizes margin, padding, content, flex gap on hover
|
|
216
|
-
- **Markers** — numbered circles (orange = pending, green =
|
|
217
|
-
- **Popup** — comment input / detail view with
|
|
241
|
+
- **Markers** — numbered circles, color per lifecycle state (orange = pending, yellow = in_progress, blue = fixed_unverified, green = verified, gray = dismissed)
|
|
242
|
+
- **Popup** — comment input / detail view with dynamic lifecycle actions + history viewer
|
|
218
243
|
|
|
219
244
|
## License
|
|
220
245
|
|
package/dist/core/index.cjs
CHANGED
|
@@ -50,12 +50,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
50
50
|
var core_exports = {};
|
|
51
51
|
__export(core_exports, {
|
|
52
52
|
AnnotationStorage: () => AnnotationStorage,
|
|
53
|
+
InvalidTransitionError: () => InvalidTransitionError,
|
|
53
54
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
55
|
+
createEvent: () => createEvent,
|
|
54
56
|
createFingerprint: () => createFingerprint,
|
|
55
57
|
detectRemarqPlugin: () => detectRemarqPlugin,
|
|
56
58
|
detectSource: () => detectSource,
|
|
57
59
|
generateAgentExport: () => generateAgentExport,
|
|
58
|
-
matchElement: () => matchElement
|
|
60
|
+
matchElement: () => matchElement,
|
|
61
|
+
migrateAnnotation: () => migrateAnnotation,
|
|
62
|
+
transition: () => transition
|
|
59
63
|
});
|
|
60
64
|
module.exports = __toCommonJS(core_exports);
|
|
61
65
|
|
|
@@ -380,6 +384,21 @@ function toBucket(width) {
|
|
|
380
384
|
}
|
|
381
385
|
|
|
382
386
|
// src/core/storage.ts
|
|
387
|
+
function migrateAnnotation(legacy) {
|
|
388
|
+
const rawStatus = legacy.status;
|
|
389
|
+
const status = rawStatus === "resolved" ? "verified" : rawStatus;
|
|
390
|
+
if (Array.isArray(legacy.lifecycle) && legacy.lifecycle.length > 0) {
|
|
391
|
+
return __spreadProps(__spreadValues({}, legacy), { status, lifecycle: legacy.lifecycle });
|
|
392
|
+
}
|
|
393
|
+
const createdTs = typeof legacy.timestamp === "number" ? legacy.timestamp : Date.now();
|
|
394
|
+
const lifecycle = [
|
|
395
|
+
{ type: "created", actor: "designer", timestamp: createdTs }
|
|
396
|
+
];
|
|
397
|
+
if (rawStatus === "resolved") {
|
|
398
|
+
lifecycle.push({ type: "migrated", actor: null, timestamp: Date.now() });
|
|
399
|
+
}
|
|
400
|
+
return __spreadProps(__spreadValues({}, legacy), { status, lifecycle });
|
|
401
|
+
}
|
|
383
402
|
var AnnotationStorage = class {
|
|
384
403
|
constructor(adapter) {
|
|
385
404
|
this.adapter = adapter;
|
|
@@ -396,6 +415,9 @@ var AnnotationStorage = class {
|
|
|
396
415
|
getByRoute(route) {
|
|
397
416
|
return this.cache.filter((a) => a.route === route);
|
|
398
417
|
}
|
|
418
|
+
getById(id) {
|
|
419
|
+
return this.cache.find((a) => a.id === id);
|
|
420
|
+
}
|
|
399
421
|
async add(annotation) {
|
|
400
422
|
this.cache.push(annotation);
|
|
401
423
|
await this.adapter.save(annotation);
|
|
@@ -422,7 +444,7 @@ var AnnotationStorage = class {
|
|
|
422
444
|
};
|
|
423
445
|
}
|
|
424
446
|
async importJSON(data) {
|
|
425
|
-
this.cache =
|
|
447
|
+
this.cache = data.annotations.map(migrateAnnotation);
|
|
426
448
|
this.migrateViewportBuckets();
|
|
427
449
|
await this.adapter.clear();
|
|
428
450
|
for (const ann of this.cache) {
|
|
@@ -432,7 +454,7 @@ var AnnotationStorage = class {
|
|
|
432
454
|
async init() {
|
|
433
455
|
const data = await this.adapter.load();
|
|
434
456
|
if (data) {
|
|
435
|
-
this.cache = data.annotations;
|
|
457
|
+
this.cache = data.annotations.map(migrateAnnotation);
|
|
436
458
|
this.migrateViewportBuckets();
|
|
437
459
|
}
|
|
438
460
|
}
|
|
@@ -587,7 +609,16 @@ function generateAgentExport(annotations, viewportBucket) {
|
|
|
587
609
|
status: ann.status,
|
|
588
610
|
timestamp: ann.timestamp,
|
|
589
611
|
source: resolveSource(ann.fingerprint),
|
|
590
|
-
searchHints: buildSearchHints(ann.fingerprint)
|
|
612
|
+
searchHints: buildSearchHints(ann.fingerprint),
|
|
613
|
+
lifecycle: ann.lifecycle.map((ev) => {
|
|
614
|
+
const out = {
|
|
615
|
+
type: ev.type,
|
|
616
|
+
actor: ev.actor,
|
|
617
|
+
timestamp: ev.timestamp
|
|
618
|
+
};
|
|
619
|
+
if (ev.reason !== void 0) out.reason = ev.reason;
|
|
620
|
+
return out;
|
|
621
|
+
})
|
|
591
622
|
}));
|
|
592
623
|
return {
|
|
593
624
|
version: 1,
|
|
@@ -596,14 +627,79 @@ function generateAgentExport(annotations, viewportBucket) {
|
|
|
596
627
|
annotations: agentAnnotations
|
|
597
628
|
};
|
|
598
629
|
}
|
|
630
|
+
|
|
631
|
+
// src/core/lifecycle.ts
|
|
632
|
+
var InvalidTransitionError = class extends Error {
|
|
633
|
+
constructor(from, action) {
|
|
634
|
+
super(`Cannot ${action} from status "${from}"`);
|
|
635
|
+
this.name = "InvalidTransitionError";
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
var ACTION_TO_EVENT = {
|
|
639
|
+
acknowledge: "acknowledged",
|
|
640
|
+
claimFix: "fix_claimed",
|
|
641
|
+
verify: "verified",
|
|
642
|
+
reject: "rejected",
|
|
643
|
+
dismiss: "dismissed",
|
|
644
|
+
reopen: "reopened"
|
|
645
|
+
};
|
|
646
|
+
var DEFAULT_ACTOR_BY_EVENT = {
|
|
647
|
+
created: "designer",
|
|
648
|
+
acknowledged: "developer",
|
|
649
|
+
fix_claimed: "agent",
|
|
650
|
+
verified: "developer",
|
|
651
|
+
rejected: "developer",
|
|
652
|
+
dismissed: "developer",
|
|
653
|
+
reopened: "developer",
|
|
654
|
+
migrated: null
|
|
655
|
+
};
|
|
656
|
+
function createEvent(type, opts = {}) {
|
|
657
|
+
var _a, _b;
|
|
658
|
+
const event = {
|
|
659
|
+
type,
|
|
660
|
+
actor: (_a = opts.actor) != null ? _a : DEFAULT_ACTOR_BY_EVENT[type],
|
|
661
|
+
timestamp: (_b = opts.timestamp) != null ? _b : Date.now()
|
|
662
|
+
};
|
|
663
|
+
if (opts.actorName !== void 0) event.actorName = opts.actorName;
|
|
664
|
+
if (opts.reason !== void 0) event.reason = opts.reason;
|
|
665
|
+
return event;
|
|
666
|
+
}
|
|
667
|
+
function nextStatus(from, action) {
|
|
668
|
+
switch (action) {
|
|
669
|
+
case "acknowledge":
|
|
670
|
+
return from === "pending" ? "in_progress" : null;
|
|
671
|
+
case "claimFix":
|
|
672
|
+
return from === "pending" || from === "in_progress" ? "fixed_unverified" : null;
|
|
673
|
+
case "verify":
|
|
674
|
+
return from === "fixed_unverified" || from === "in_progress" ? "verified" : null;
|
|
675
|
+
case "reject":
|
|
676
|
+
return from === "fixed_unverified" ? "pending" : null;
|
|
677
|
+
case "dismiss":
|
|
678
|
+
return from === "pending" || from === "in_progress" || from === "fixed_unverified" ? "dismissed" : null;
|
|
679
|
+
case "reopen":
|
|
680
|
+
return from === "dismissed" || from === "verified" ? "pending" : null;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
function transition(annotation, action, opts = {}) {
|
|
684
|
+
const next = nextStatus(annotation.status, action);
|
|
685
|
+
if (next === null) {
|
|
686
|
+
throw new InvalidTransitionError(annotation.status, action);
|
|
687
|
+
}
|
|
688
|
+
const event = createEvent(ACTION_TO_EVENT[action], opts);
|
|
689
|
+
return { status: next, event };
|
|
690
|
+
}
|
|
599
691
|
// Annotate the CommonJS export names for ESM import in node:
|
|
600
692
|
0 && (module.exports = {
|
|
601
693
|
AnnotationStorage,
|
|
694
|
+
InvalidTransitionError,
|
|
602
695
|
LocalStorageAdapter,
|
|
696
|
+
createEvent,
|
|
603
697
|
createFingerprint,
|
|
604
698
|
detectRemarqPlugin,
|
|
605
699
|
detectSource,
|
|
606
700
|
generateAgentExport,
|
|
607
|
-
matchElement
|
|
701
|
+
matchElement,
|
|
702
|
+
migrateAnnotation,
|
|
703
|
+
transition
|
|
608
704
|
});
|
|
609
705
|
//# sourceMappingURL=index.cjs.map
|
package/dist/core/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts","../../src/core/hash-detect.ts","../../src/core/source-detect.ts","../../src/core/fingerprint.ts","../../src/core/matcher.ts","../../src/core/viewport.ts","../../src/core/storage.ts","../../src/core/local-storage-adapter.ts","../../src/core/agent-export.ts"],"sourcesContent":["export type {\n Annotation,\n AnnotationStore,\n ElementFingerprint,\n CSSModuleClass,\n SourceDetectionResult,\n SearchConfidence,\n GrepQuery,\n AgentSearchHints,\n AgentAnnotationSource,\n AgentAnnotation,\n AgentExport,\n ToolbarPosition,\n StorageAdapter,\n StorageChangeEvent,\n} from './types'\nexport { createFingerprint } from './fingerprint'\nexport { matchElement } from './matcher'\nexport { AnnotationStorage } from './storage'\nexport { LocalStorageAdapter } from './local-storage-adapter'\nexport { detectRemarqPlugin, detectSource } from './source-detect'\nexport { generateAgentExport } from './agent-export'\n","import type { CSSModuleClass } from './types'\n\nconst CSS_MODULES_RE = /^(.+)__([a-zA-Z0-9]{3,})$/\nconst CSS_MODULES_3SEG_RE = /^([^_]+(?:[_-][^_]+)*)__([a-zA-Z][a-zA-Z0-9]*)__([a-zA-Z0-9]{3,})$/\nconst STYLED_COMPONENTS_RE = /^sc-/\nconst EMOTION_RE = /^css-[a-zA-Z0-9]+$/\nconst PURE_HASH_RE = /^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9]{8,}$/\n\nexport function isHashedClass(className: string): boolean {\n if (STYLED_COMPONENTS_RE.test(className)) return true\n if (EMOTION_RE.test(className)) return true\n if (CSS_MODULES_RE.test(className)) return true\n if (PURE_HASH_RE.test(className)) return true\n return false\n}\n\nexport function stripHash(className: string): string {\n const match = className.match(CSS_MODULES_RE)\n if (match) {\n const prefix = className.slice(0, className.lastIndexOf('__'))\n return prefix\n }\n return className\n}\n\nexport function filterClasses(\n classes: string[],\n classFilter?: (className: string) => boolean,\n): string[] {\n const result: string[] = []\n\n for (const cls of classes) {\n if (STYLED_COMPONENTS_RE.test(cls)) continue\n if (EMOTION_RE.test(cls)) continue\n if (PURE_HASH_RE.test(cls)) continue\n\n let stable = stripHash(cls)\n\n if (classFilter && !classFilter(stable)) continue\n\n result.push(stable)\n }\n\n return result\n}\n\nexport function decomposeCSSModules(classes: string[]): CSSModuleClass[] {\n const result: CSSModuleClass[] = []\n for (const cls of classes) {\n const match = cls.match(CSS_MODULES_3SEG_RE)\n if (match) {\n result.push({\n raw: cls,\n moduleHint: match[1],\n localName: match[2],\n })\n }\n }\n return result\n}\n","import type { SourceDetectionResult } from './types'\n\n/**\n * Level 1: Read data-remarq-source/data-remarq-component attrs\n * injected by @web-remarq/babel-plugin or @web-remarq/unplugin.\n */\nexport function detectRemarqPlugin(el: HTMLElement): SourceDetectionResult {\n const source = el.getAttribute('data-remarq-source')\n if (!source) return { source: null, component: null }\n return {\n source,\n component: el.getAttribute('data-remarq-component'),\n }\n}\n\n/**\n * Level 2a: Read data-source or data-locator attrs\n * from locator.js or similar external tools.\n */\nexport function detectExternalSource(el: HTMLElement): SourceDetectionResult {\n const source = el.dataset.source ?? el.getAttribute('data-locator')\n if (!source) return { source: null, component: null }\n return { source, component: null }\n}\n\n/**\n * Level 2b: Read React fiber _debugSource (dev mode only).\n * Unstable/best-effort — React internals are not public API.\n * Walks up the fiber tree because _debugSource lives on component fibers,\n * not on host (DOM element) fibers.\n */\nexport function detectReactFiber(el: HTMLElement): SourceDetectionResult {\n const key = Object.keys(el).find(k => k.startsWith('__reactFiber$'))\n if (!key) return { source: null, component: null }\n\n let current = (el as unknown as Record<string, unknown>)[key] as Record<string, unknown> | null\n // Walk up fiber tree to find nearest fiber with _debugSource (max 15 levels)\n let depth = 0\n while (current && depth < 15) {\n const debugSource = current._debugSource as { fileName?: string; lineNumber?: number; columnNumber?: number } | undefined\n if (debugSource?.fileName) {\n const source = `${debugSource.fileName}:${debugSource.lineNumber ?? 0}:${debugSource.columnNumber ?? 0}`\n\n // Try to get component name from fiber.type\n const fiberType = current.type as { displayName?: string; name?: string } | string | undefined\n const component = typeof fiberType === 'object' && fiberType\n ? (fiberType.displayName ?? fiberType.name ?? null)\n : null\n\n return { source, component }\n }\n current = current.return as Record<string, unknown> | null\n depth++\n }\n\n return { source: null, component: null }\n}\n\n/**\n * Runs Level 2 detectors in order. Returns first non-null result.\n */\nexport function detectSource(el: HTMLElement): SourceDetectionResult {\n const external = detectExternalSource(el)\n if (external.source) return external\n\n const fiber = detectReactFiber(el)\n if (fiber.source) return fiber\n\n return { source: null, component: null }\n}\n","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses, isHashedClass, decomposeCSSModules } from './hash-detect'\nimport { detectRemarqPlugin, detectSource } from './source-detect'\n\nconst TEXT_MAX_LENGTH = 50\n\nexport function createFingerprint(\n el: HTMLElement,\n options?: Pick<WebRemarqOptions, 'classFilter' | 'dataAttribute'>,\n): ElementFingerprint {\n const dataAttr = options?.dataAttribute ?? 'data-annotate'\n\n return {\n dataAnnotate: el.getAttribute(dataAttr) ?? null,\n dataTestId: el.getAttribute('data-testid')\n ?? el.getAttribute('data-test')\n ?? el.getAttribute('data-cy')\n ?? null,\n id: getStableId(el),\n tagName: el.tagName.toLowerCase(),\n textContent: getTextContent(el),\n role: el.getAttribute('role') ?? null,\n ariaLabel: el.getAttribute('aria-label') ?? null,\n stableClasses: filterClasses(\n Array.from(el.classList),\n options?.classFilter,\n ),\n domPath: buildDomPath(el),\n siblingIndex: getSiblingIndex(el),\n parentAnchor: findParentAnchor(el, dataAttr),\n rawClasses: Array.from(el.classList),\n cssModules: decomposeCSSModules(Array.from(el.classList)),\n ...resolveSourceFields(el),\n }\n}\n\nfunction resolveSourceFields(el: HTMLElement): {\n sourceLocation: string | null\n componentName: string | null\n detectedSource: string | null\n detectedComponent: string | null\n} {\n const plugin = detectRemarqPlugin(el)\n if (plugin.source) {\n return {\n sourceLocation: plugin.source,\n componentName: plugin.component,\n detectedSource: null,\n detectedComponent: null,\n }\n }\n\n const detected = detectSource(el)\n return {\n sourceLocation: null,\n componentName: null,\n detectedSource: detected.source,\n detectedComponent: detected.component,\n }\n}\n\nfunction getStableId(el: HTMLElement): string | null {\n const id = el.id\n if (!id) return null\n if (isHashedClass(id)) return null\n return id\n}\n\nfunction getTextContent(el: HTMLElement): string | null {\n // Use only direct text nodes, not nested children's text\n let text = ''\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent ?? ''\n }\n }\n text = text.trim()\n\n // If no direct text, try first meaningful child's text (for wrappers like <span><b>Text</b></span>)\n if (!text && el.children.length <= 3) {\n text = el.textContent?.trim() ?? ''\n }\n\n if (!text) return null\n return text.length > TEXT_MAX_LENGTH ? text.slice(0, TEXT_MAX_LENGTH) : text\n}\n\nfunction buildDomPath(el: HTMLElement): string {\n const parts: string[] = []\n let current: HTMLElement | null = el\n\n while (current && current !== document.body && parts.length < 5) {\n let segment = current.tagName.toLowerCase()\n const stable = filterClasses(Array.from(current.classList))\n if (stable.length > 0) {\n segment += '.' + stable.slice(0, 2).join('.')\n }\n parts.unshift(segment)\n current = current.parentElement\n }\n\n return parts.join(' > ')\n}\n\nfunction getSiblingIndex(el: HTMLElement): number {\n const parent = el.parentElement\n if (!parent) return 0\n const children = Array.from(parent.children)\n return children.indexOf(el)\n}\n\nfunction findParentAnchor(el: HTMLElement, dataAttr: string): string | null {\n let current = el.parentElement\n while (current && current !== document.body) {\n const value = current.getAttribute(dataAttr)\n if (value) return value\n current = current.parentElement\n }\n return null\n}\n","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses } from './hash-detect'\n\nconst MATCH_THRESHOLD = 50\n\nexport function levenshteinSimilarity(a: string, b: string): number {\n if (a === b) return 1\n if (!a.length || !b.length) return 0\n\n const matrix: number[][] = []\n for (let i = 0; i <= a.length; i++) {\n matrix[i] = [i]\n }\n for (let j = 0; j <= b.length; j++) {\n matrix[0][j] = j\n }\n\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j - 1] + cost,\n )\n }\n }\n\n const distance = matrix[a.length][b.length]\n return 1 - distance / Math.max(a.length, b.length)\n}\n\nfunction textSimilarity(a: string | null, b: string | null): number {\n if (!a || !b) return 0\n const na = a.trim().toLowerCase()\n const nb = b.trim().toLowerCase()\n if (na === nb) return 1\n if (na.includes(nb) || nb.includes(na)) return 1\n return levenshteinSimilarity(na, nb)\n}\n\nfunction jaccardSimilarity(a: string[], b: string[]): number {\n if (!a.length && !b.length) return 0\n const setA = new Set(a)\n const setB = new Set(b)\n let intersection = 0\n for (const item of setA) {\n if (setB.has(item)) intersection++\n }\n const union = new Set([...a, ...b]).size\n return union === 0 ? 0 : intersection / union\n}\n\nfunction scoreCandidate(el: HTMLElement, fp: ElementFingerprint, dataAttr: string): number {\n let score = 0\n\n // dataAnnotate match (+100)\n const elAnnotate = el.getAttribute(dataAttr)\n if (fp.dataAnnotate && elAnnotate === fp.dataAnnotate) {\n score += 100\n }\n\n // textContent match (+35 scaled)\n const elText = el.textContent?.trim().slice(0, 50) ?? null\n const textSim = textSimilarity(fp.textContent, elText)\n if (textSim > 0.7) {\n score += textSim * 35\n }\n\n // role + ariaLabel match (+30)\n if (fp.role && el.getAttribute('role') === fp.role &&\n fp.ariaLabel && el.getAttribute('aria-label') === fp.ariaLabel) {\n score += 30\n }\n\n // parentAnchor match (+15)\n if (fp.parentAnchor) {\n let parent = el.parentElement\n while (parent && parent !== document.body) {\n if (parent.getAttribute(dataAttr) === fp.parentAnchor) {\n score += 15\n break\n }\n parent = parent.parentElement\n }\n }\n\n // stableClasses overlap (+30 scaled)\n if (fp.stableClasses.length > 0) {\n const elClasses = filterClasses(Array.from(el.classList))\n const jaccard = jaccardSimilarity(fp.stableClasses, elClasses)\n score += jaccard * 30\n }\n\n // domPath match (+20 scaled)\n if (fp.domPath) {\n const elPath = buildDomPath(el)\n const pathSim = levenshteinSimilarity(fp.domPath, elPath)\n score += pathSim * 20\n }\n\n // siblingIndex match (+5)\n const parent = el.parentElement\n if (parent) {\n const idx = Array.from(parent.children).indexOf(el)\n if (idx === fp.siblingIndex) {\n score += 5\n }\n }\n\n return score\n}\n\nfunction buildDomPath(el: HTMLElement): string {\n const parts: string[] = []\n let current: HTMLElement | null = el\n while (current && current !== document.body && parts.length < 5) {\n let segment = current.tagName.toLowerCase()\n const stable = filterClasses(Array.from(current.classList))\n if (stable.length > 0) {\n segment += '.' + stable.slice(0, 2).join('.')\n }\n parts.unshift(segment)\n current = current.parentElement\n }\n return parts.join(' > ')\n}\n\nexport function matchElement(\n fp: ElementFingerprint,\n options?: Pick<WebRemarqOptions, 'dataAttribute'>,\n): HTMLElement | null {\n const dataAttr = options?.dataAttribute ?? 'data-annotate'\n\n // 1. Exact match by data-annotate\n if (fp.dataAnnotate) {\n const el = document.querySelector<HTMLElement>(`[${dataAttr}=\"${fp.dataAnnotate}\"]`)\n if (el) return el\n }\n\n // 2. Exact match by data-testid\n if (fp.dataTestId) {\n const el = document.querySelector<HTMLElement>(\n `[data-testid=\"${fp.dataTestId}\"], [data-test=\"${fp.dataTestId}\"], [data-cy=\"${fp.dataTestId}\"]`,\n )\n if (el) return el\n }\n\n // 3. Exact match by id\n if (fp.id) {\n const el = document.getElementById(fp.id) as HTMLElement | null\n if (el) return el\n }\n\n // 4. Fuzzy match by tagName + weighted scoring\n const candidates = document.querySelectorAll<HTMLElement>(fp.tagName)\n let bestEl: HTMLElement | null = null\n let bestScore = 0\n\n for (const candidate of candidates) {\n const score = scoreCandidate(candidate, fp, dataAttr)\n if (score > bestScore) {\n bestScore = score\n bestEl = candidate\n }\n }\n\n return bestScore >= MATCH_THRESHOLD ? bestEl : null\n}\n","type BucketChangeCallback = () => void\n\nlet currentBucket: number = 0\nlet onBucketChange: BucketChangeCallback | null = null\nlet resizeHandler: (() => void) | null = null\n\nexport function toBucket(width: number): number {\n return Math.floor(width / 100) * 100\n}\n\nfunction debounce(fn: () => void, ms: number): () => void {\n let timer: ReturnType<typeof setTimeout>\n return () => {\n clearTimeout(timer)\n timer = setTimeout(fn, ms)\n }\n}\n\nexport function initViewportListener(callback: BucketChangeCallback): void {\n currentBucket = toBucket(window.innerWidth)\n onBucketChange = callback\n\n resizeHandler = debounce(() => {\n const newBucket = toBucket(window.innerWidth)\n if (newBucket !== currentBucket) {\n currentBucket = newBucket\n onBucketChange?.()\n }\n }, 300)\n\n window.addEventListener('resize', resizeHandler)\n}\n\nexport function destroyViewportListener(): void {\n if (resizeHandler) {\n window.removeEventListener('resize', resizeHandler)\n resizeHandler = null\n }\n onBucketChange = null\n}\n","import type { Annotation, AnnotationStore, StorageAdapter } from './types'\nimport { toBucket } from './viewport'\n\nexport class AnnotationStorage {\n private cache: Annotation[] = []\n readonly ready: Promise<void>\n\n constructor(private adapter: StorageAdapter) {\n this.ready = this.init()\n }\n\n get isMemoryOnly(): boolean {\n return this.adapter.isMemoryOnly ?? false\n }\n\n getAll(): Annotation[] {\n return [...this.cache]\n }\n\n getByRoute(route: string): Annotation[] {\n return this.cache.filter((a) => a.route === route)\n }\n\n async add(annotation: Annotation): Promise<void> {\n this.cache.push(annotation)\n await this.adapter.save(annotation)\n }\n\n async remove(id: string): Promise<void> {\n this.cache = this.cache.filter((a) => a.id !== id)\n await this.adapter.remove(id)\n }\n\n async update(id: string, changes: Partial<Annotation>): Promise<void> {\n const idx = this.cache.findIndex((a) => a.id === id)\n if (idx === -1) return\n const updated = { ...this.cache[idx], ...changes }\n this.cache[idx] = updated\n await this.adapter.save(updated)\n }\n\n async clearAll(): Promise<void> {\n this.cache = []\n await this.adapter.clear()\n }\n\n exportJSON(): AnnotationStore {\n return {\n version: 1,\n annotations: [...this.cache],\n }\n }\n\n async importJSON(data: AnnotationStore): Promise<void> {\n this.cache = [...data.annotations]\n this.migrateViewportBuckets()\n await this.adapter.clear()\n for (const ann of this.cache) {\n await this.adapter.save(ann)\n }\n }\n\n private async init(): Promise<void> {\n const data = await this.adapter.load()\n if (data) {\n this.cache = data.annotations\n this.migrateViewportBuckets()\n }\n }\n\n private migrateViewportBuckets(): void {\n for (const ann of this.cache) {\n if (ann.viewportBucket == null && ann.viewport) {\n const width = parseInt(ann.viewport.split('x')[0], 10)\n ann.viewportBucket = toBucket(width)\n }\n }\n }\n}\n","import type { Annotation, AnnotationStore, StorageAdapter } from './types';\n\nconst STORAGE_KEY = 'remarq:annotations';\n\nexport class LocalStorageAdapter implements StorageAdapter {\n isMemoryOnly = false;\n private extraFields: Record<string, unknown> = {};\n private memoryStore: AnnotationStore | null = null;\n\n async load(): Promise<AnnotationStore | null> {\n if (this.isMemoryOnly) return this.memoryStore;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n const { version, annotations, ...rest } = parsed;\n this.extraFields = rest;\n const store: AnnotationStore = {\n version: 1,\n annotations: Array.isArray(annotations) ? annotations : [],\n };\n this.memoryStore = store;\n return store;\n } catch {\n this.isMemoryOnly = true;\n return this.memoryStore;\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n const store = await this.ensureStore();\n const idx = store.annotations.findIndex((a) => a.id === annotation.id);\n if (idx === -1) {\n store.annotations.push(annotation);\n } else {\n store.annotations[idx] = annotation;\n }\n this.persist(store);\n }\n\n async remove(id: string): Promise<void> {\n const store = await this.ensureStore();\n store.annotations = store.annotations.filter((a) => a.id !== id);\n this.persist(store);\n }\n\n async clear(): Promise<void> {\n const store = await this.ensureStore();\n store.annotations = [];\n this.persist(store);\n }\n\n private async ensureStore(): Promise<AnnotationStore> {\n if (this.memoryStore) return this.memoryStore;\n const loaded = await this.load();\n if (loaded) return loaded;\n this.memoryStore = { version: 1, annotations: [] };\n return this.memoryStore;\n }\n\n private persist(store: AnnotationStore): void {\n if (this.isMemoryOnly) return;\n try {\n const data = {\n version: 1,\n ...this.extraFields,\n annotations: store.annotations,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n this.isMemoryOnly = true;\n }\n }\n}\n","import type {\n Annotation,\n AgentExport,\n AgentAnnotation,\n AgentAnnotationSource,\n AgentSearchHints,\n GrepQuery,\n ElementFingerprint,\n} from './types'\n\nfunction parseSourceLocation(raw: string): { file: string; line: number; column: number } | null {\n const parts = raw.split(':')\n if (parts.length < 2) return null\n // file path may contain \":\" on Windows (C:\\...), so rejoin all but last 2\n const column = parseInt(parts.pop()!, 10)\n const line = parseInt(parts.pop()!, 10)\n const file = parts.join(':')\n if (!file || isNaN(line)) return null\n return { file, line, column: isNaN(column) ? 0 : column }\n}\n\nfunction resolveSource(fp: ElementFingerprint): AgentAnnotationSource | null {\n // Level 1: plugin source\n if (fp.sourceLocation) {\n const parsed = parseSourceLocation(fp.sourceLocation)\n if (parsed) return { ...parsed, component: fp.componentName ?? null }\n }\n\n // Level 2: detected source\n if (fp.detectedSource) {\n const parsed = parseSourceLocation(fp.detectedSource)\n if (parsed) return { ...parsed, component: fp.detectedComponent ?? null }\n }\n\n return null\n}\n\nconst TEMPLATE_GLOB = '*.{tsx,jsx,vue,svelte,html}'\nconst CSS_MODULE_GLOB = '*.module.{css,scss,less}'\nconst COMPONENT_GLOB = '*.{tsx,jsx,vue,ts,js}'\n\nfunction buildSearchHints(fp: ElementFingerprint): AgentSearchHints {\n const grepQueries: GrepQuery[] = []\n\n // High confidence — unique selectors\n if (fp.dataAnnotate) {\n grepQueries.push({ query: `data-annotate=\"${fp.dataAnnotate}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.dataTestId) {\n grepQueries.push({ query: `data-testid=\"${fp.dataTestId}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.id) {\n grepQueries.push({ query: `id=\"${fp.id}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.ariaLabel) {\n grepQueries.push({ query: `aria-label=\"${fp.ariaLabel}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n\n // Medium confidence — text, CSS modules, role\n if (fp.textContent) {\n grepQueries.push({ query: `\"${fp.textContent}\"`, glob: TEMPLATE_GLOB, confidence: 'medium' })\n }\n if (fp.role) {\n grepQueries.push({ query: `role=\"${fp.role}\"`, glob: TEMPLATE_GLOB, confidence: 'medium' })\n }\n if (fp.cssModules?.length) {\n for (const mod of fp.cssModules) {\n grepQueries.push({ query: `.${mod.localName}`, glob: CSS_MODULE_GLOB, confidence: 'medium' })\n grepQueries.push({ query: `styles.${mod.localName}`, glob: COMPONENT_GLOB, confidence: 'medium' })\n }\n }\n\n // Low confidence — classes, domPath\n if (fp.stableClasses.length) {\n for (const cls of fp.stableClasses.slice(0, 3)) {\n grepQueries.push({ query: `\"${cls}\"`, glob: TEMPLATE_GLOB, confidence: 'low' })\n }\n }\n\n return {\n grepQueries,\n domContext: fp.domPath,\n tagName: fp.tagName,\n classes: fp.rawClasses ?? fp.stableClasses,\n }\n}\n\nexport function generateAgentExport(annotations: Annotation[], viewportBucket: number): AgentExport {\n const agentAnnotations: AgentAnnotation[] = annotations.map(ann => ({\n id: ann.id,\n route: ann.route,\n comment: ann.comment,\n status: ann.status,\n timestamp: ann.timestamp,\n source: resolveSource(ann.fingerprint),\n searchHints: buildSearchHints(ann.fingerprint),\n }))\n\n return {\n version: 1,\n format: 'agent',\n viewportBucket,\n annotations: agentAnnotations,\n }\n}\n"],"mappings":"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","names":["parent","buildDomPath"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts","../../src/core/hash-detect.ts","../../src/core/source-detect.ts","../../src/core/fingerprint.ts","../../src/core/matcher.ts","../../src/core/viewport.ts","../../src/core/storage.ts","../../src/core/local-storage-adapter.ts","../../src/core/agent-export.ts","../../src/core/lifecycle.ts"],"sourcesContent":["export type {\n Annotation,\n AnnotationStatus,\n AnnotationEvent,\n AnnotationEventType,\n Actor,\n AnnotationStore,\n ElementFingerprint,\n CSSModuleClass,\n SourceDetectionResult,\n SearchConfidence,\n GrepQuery,\n AgentSearchHints,\n AgentAnnotationSource,\n AgentAnnotation,\n AgentLifecycleEvent,\n AgentExport,\n ToolbarPosition,\n StorageAdapter,\n StorageChangeEvent,\n} from './types'\nexport { createFingerprint } from './fingerprint'\nexport { matchElement } from './matcher'\nexport { AnnotationStorage, migrateAnnotation } from './storage'\nexport { LocalStorageAdapter } from './local-storage-adapter'\nexport { detectRemarqPlugin, detectSource } from './source-detect'\nexport { generateAgentExport } from './agent-export'\nexport { transition, createEvent, InvalidTransitionError } from './lifecycle'\nexport type { LifecycleAction, EventOpts } from './lifecycle'\n","import type { CSSModuleClass } from './types'\n\nconst CSS_MODULES_RE = /^(.+)__([a-zA-Z0-9]{3,})$/\nconst CSS_MODULES_3SEG_RE = /^([^_]+(?:[_-][^_]+)*)__([a-zA-Z][a-zA-Z0-9]*)__([a-zA-Z0-9]{3,})$/\nconst STYLED_COMPONENTS_RE = /^sc-/\nconst EMOTION_RE = /^css-[a-zA-Z0-9]+$/\nconst PURE_HASH_RE = /^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9]{8,}$/\n\nexport function isHashedClass(className: string): boolean {\n if (STYLED_COMPONENTS_RE.test(className)) return true\n if (EMOTION_RE.test(className)) return true\n if (CSS_MODULES_RE.test(className)) return true\n if (PURE_HASH_RE.test(className)) return true\n return false\n}\n\nexport function stripHash(className: string): string {\n const match = className.match(CSS_MODULES_RE)\n if (match) {\n const prefix = className.slice(0, className.lastIndexOf('__'))\n return prefix\n }\n return className\n}\n\nexport function filterClasses(\n classes: string[],\n classFilter?: (className: string) => boolean,\n): string[] {\n const result: string[] = []\n\n for (const cls of classes) {\n if (STYLED_COMPONENTS_RE.test(cls)) continue\n if (EMOTION_RE.test(cls)) continue\n if (PURE_HASH_RE.test(cls)) continue\n\n let stable = stripHash(cls)\n\n if (classFilter && !classFilter(stable)) continue\n\n result.push(stable)\n }\n\n return result\n}\n\nexport function decomposeCSSModules(classes: string[]): CSSModuleClass[] {\n const result: CSSModuleClass[] = []\n for (const cls of classes) {\n const match = cls.match(CSS_MODULES_3SEG_RE)\n if (match) {\n result.push({\n raw: cls,\n moduleHint: match[1],\n localName: match[2],\n })\n }\n }\n return result\n}\n","import type { SourceDetectionResult } from './types'\n\n/**\n * Level 1: Read data-remarq-source/data-remarq-component attrs\n * injected by @web-remarq/babel-plugin or @web-remarq/unplugin.\n */\nexport function detectRemarqPlugin(el: HTMLElement): SourceDetectionResult {\n const source = el.getAttribute('data-remarq-source')\n if (!source) return { source: null, component: null }\n return {\n source,\n component: el.getAttribute('data-remarq-component'),\n }\n}\n\n/**\n * Level 2a: Read data-source or data-locator attrs\n * from locator.js or similar external tools.\n */\nexport function detectExternalSource(el: HTMLElement): SourceDetectionResult {\n const source = el.dataset.source ?? el.getAttribute('data-locator')\n if (!source) return { source: null, component: null }\n return { source, component: null }\n}\n\n/**\n * Level 2b: Read React fiber _debugSource (dev mode only).\n * Unstable/best-effort — React internals are not public API.\n * Walks up the fiber tree because _debugSource lives on component fibers,\n * not on host (DOM element) fibers.\n */\nexport function detectReactFiber(el: HTMLElement): SourceDetectionResult {\n const key = Object.keys(el).find(k => k.startsWith('__reactFiber$'))\n if (!key) return { source: null, component: null }\n\n let current = (el as unknown as Record<string, unknown>)[key] as Record<string, unknown> | null\n // Walk up fiber tree to find nearest fiber with _debugSource (max 15 levels)\n let depth = 0\n while (current && depth < 15) {\n const debugSource = current._debugSource as { fileName?: string; lineNumber?: number; columnNumber?: number } | undefined\n if (debugSource?.fileName) {\n const source = `${debugSource.fileName}:${debugSource.lineNumber ?? 0}:${debugSource.columnNumber ?? 0}`\n\n // Try to get component name from fiber.type\n const fiberType = current.type as { displayName?: string; name?: string } | string | undefined\n const component = typeof fiberType === 'object' && fiberType\n ? (fiberType.displayName ?? fiberType.name ?? null)\n : null\n\n return { source, component }\n }\n current = current.return as Record<string, unknown> | null\n depth++\n }\n\n return { source: null, component: null }\n}\n\n/**\n * Runs Level 2 detectors in order. Returns first non-null result.\n */\nexport function detectSource(el: HTMLElement): SourceDetectionResult {\n const external = detectExternalSource(el)\n if (external.source) return external\n\n const fiber = detectReactFiber(el)\n if (fiber.source) return fiber\n\n return { source: null, component: null }\n}\n","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses, isHashedClass, decomposeCSSModules } from './hash-detect'\nimport { detectRemarqPlugin, detectSource } from './source-detect'\n\nconst TEXT_MAX_LENGTH = 50\n\nexport function createFingerprint(\n el: HTMLElement,\n options?: Pick<WebRemarqOptions, 'classFilter' | 'dataAttribute'>,\n): ElementFingerprint {\n const dataAttr = options?.dataAttribute ?? 'data-annotate'\n\n return {\n dataAnnotate: el.getAttribute(dataAttr) ?? null,\n dataTestId: el.getAttribute('data-testid')\n ?? el.getAttribute('data-test')\n ?? el.getAttribute('data-cy')\n ?? null,\n id: getStableId(el),\n tagName: el.tagName.toLowerCase(),\n textContent: getTextContent(el),\n role: el.getAttribute('role') ?? null,\n ariaLabel: el.getAttribute('aria-label') ?? null,\n stableClasses: filterClasses(\n Array.from(el.classList),\n options?.classFilter,\n ),\n domPath: buildDomPath(el),\n siblingIndex: getSiblingIndex(el),\n parentAnchor: findParentAnchor(el, dataAttr),\n rawClasses: Array.from(el.classList),\n cssModules: decomposeCSSModules(Array.from(el.classList)),\n ...resolveSourceFields(el),\n }\n}\n\nfunction resolveSourceFields(el: HTMLElement): {\n sourceLocation: string | null\n componentName: string | null\n detectedSource: string | null\n detectedComponent: string | null\n} {\n const plugin = detectRemarqPlugin(el)\n if (plugin.source) {\n return {\n sourceLocation: plugin.source,\n componentName: plugin.component,\n detectedSource: null,\n detectedComponent: null,\n }\n }\n\n const detected = detectSource(el)\n return {\n sourceLocation: null,\n componentName: null,\n detectedSource: detected.source,\n detectedComponent: detected.component,\n }\n}\n\nfunction getStableId(el: HTMLElement): string | null {\n const id = el.id\n if (!id) return null\n if (isHashedClass(id)) return null\n return id\n}\n\nfunction getTextContent(el: HTMLElement): string | null {\n // Use only direct text nodes, not nested children's text\n let text = ''\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) {\n text += node.textContent ?? ''\n }\n }\n text = text.trim()\n\n // If no direct text, try first meaningful child's text (for wrappers like <span><b>Text</b></span>)\n if (!text && el.children.length <= 3) {\n text = el.textContent?.trim() ?? ''\n }\n\n if (!text) return null\n return text.length > TEXT_MAX_LENGTH ? text.slice(0, TEXT_MAX_LENGTH) : text\n}\n\nfunction buildDomPath(el: HTMLElement): string {\n const parts: string[] = []\n let current: HTMLElement | null = el\n\n while (current && current !== document.body && parts.length < 5) {\n let segment = current.tagName.toLowerCase()\n const stable = filterClasses(Array.from(current.classList))\n if (stable.length > 0) {\n segment += '.' + stable.slice(0, 2).join('.')\n }\n parts.unshift(segment)\n current = current.parentElement\n }\n\n return parts.join(' > ')\n}\n\nfunction getSiblingIndex(el: HTMLElement): number {\n const parent = el.parentElement\n if (!parent) return 0\n const children = Array.from(parent.children)\n return children.indexOf(el)\n}\n\nfunction findParentAnchor(el: HTMLElement, dataAttr: string): string | null {\n let current = el.parentElement\n while (current && current !== document.body) {\n const value = current.getAttribute(dataAttr)\n if (value) return value\n current = current.parentElement\n }\n return null\n}\n","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses } from './hash-detect'\n\nconst MATCH_THRESHOLD = 50\n\nexport function levenshteinSimilarity(a: string, b: string): number {\n if (a === b) return 1\n if (!a.length || !b.length) return 0\n\n const matrix: number[][] = []\n for (let i = 0; i <= a.length; i++) {\n matrix[i] = [i]\n }\n for (let j = 0; j <= b.length; j++) {\n matrix[0][j] = j\n }\n\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j - 1] + cost,\n )\n }\n }\n\n const distance = matrix[a.length][b.length]\n return 1 - distance / Math.max(a.length, b.length)\n}\n\nfunction textSimilarity(a: string | null, b: string | null): number {\n if (!a || !b) return 0\n const na = a.trim().toLowerCase()\n const nb = b.trim().toLowerCase()\n if (na === nb) return 1\n if (na.includes(nb) || nb.includes(na)) return 1\n return levenshteinSimilarity(na, nb)\n}\n\nfunction jaccardSimilarity(a: string[], b: string[]): number {\n if (!a.length && !b.length) return 0\n const setA = new Set(a)\n const setB = new Set(b)\n let intersection = 0\n for (const item of setA) {\n if (setB.has(item)) intersection++\n }\n const union = new Set([...a, ...b]).size\n return union === 0 ? 0 : intersection / union\n}\n\nfunction scoreCandidate(el: HTMLElement, fp: ElementFingerprint, dataAttr: string): number {\n let score = 0\n\n // dataAnnotate match (+100)\n const elAnnotate = el.getAttribute(dataAttr)\n if (fp.dataAnnotate && elAnnotate === fp.dataAnnotate) {\n score += 100\n }\n\n // textContent match (+35 scaled)\n const elText = el.textContent?.trim().slice(0, 50) ?? null\n const textSim = textSimilarity(fp.textContent, elText)\n if (textSim > 0.7) {\n score += textSim * 35\n }\n\n // role + ariaLabel match (+30)\n if (fp.role && el.getAttribute('role') === fp.role &&\n fp.ariaLabel && el.getAttribute('aria-label') === fp.ariaLabel) {\n score += 30\n }\n\n // parentAnchor match (+15)\n if (fp.parentAnchor) {\n let parent = el.parentElement\n while (parent && parent !== document.body) {\n if (parent.getAttribute(dataAttr) === fp.parentAnchor) {\n score += 15\n break\n }\n parent = parent.parentElement\n }\n }\n\n // stableClasses overlap (+30 scaled)\n if (fp.stableClasses.length > 0) {\n const elClasses = filterClasses(Array.from(el.classList))\n const jaccard = jaccardSimilarity(fp.stableClasses, elClasses)\n score += jaccard * 30\n }\n\n // domPath match (+20 scaled)\n if (fp.domPath) {\n const elPath = buildDomPath(el)\n const pathSim = levenshteinSimilarity(fp.domPath, elPath)\n score += pathSim * 20\n }\n\n // siblingIndex match (+5)\n const parent = el.parentElement\n if (parent) {\n const idx = Array.from(parent.children).indexOf(el)\n if (idx === fp.siblingIndex) {\n score += 5\n }\n }\n\n return score\n}\n\nfunction buildDomPath(el: HTMLElement): string {\n const parts: string[] = []\n let current: HTMLElement | null = el\n while (current && current !== document.body && parts.length < 5) {\n let segment = current.tagName.toLowerCase()\n const stable = filterClasses(Array.from(current.classList))\n if (stable.length > 0) {\n segment += '.' + stable.slice(0, 2).join('.')\n }\n parts.unshift(segment)\n current = current.parentElement\n }\n return parts.join(' > ')\n}\n\nexport function matchElement(\n fp: ElementFingerprint,\n options?: Pick<WebRemarqOptions, 'dataAttribute'>,\n): HTMLElement | null {\n const dataAttr = options?.dataAttribute ?? 'data-annotate'\n\n // 1. Exact match by data-annotate\n if (fp.dataAnnotate) {\n const el = document.querySelector<HTMLElement>(`[${dataAttr}=\"${fp.dataAnnotate}\"]`)\n if (el) return el\n }\n\n // 2. Exact match by data-testid\n if (fp.dataTestId) {\n const el = document.querySelector<HTMLElement>(\n `[data-testid=\"${fp.dataTestId}\"], [data-test=\"${fp.dataTestId}\"], [data-cy=\"${fp.dataTestId}\"]`,\n )\n if (el) return el\n }\n\n // 3. Exact match by id\n if (fp.id) {\n const el = document.getElementById(fp.id) as HTMLElement | null\n if (el) return el\n }\n\n // 4. Fuzzy match by tagName + weighted scoring\n const candidates = document.querySelectorAll<HTMLElement>(fp.tagName)\n let bestEl: HTMLElement | null = null\n let bestScore = 0\n\n for (const candidate of candidates) {\n const score = scoreCandidate(candidate, fp, dataAttr)\n if (score > bestScore) {\n bestScore = score\n bestEl = candidate\n }\n }\n\n return bestScore >= MATCH_THRESHOLD ? bestEl : null\n}\n","type BucketChangeCallback = () => void\n\nlet currentBucket: number = 0\nlet onBucketChange: BucketChangeCallback | null = null\nlet resizeHandler: (() => void) | null = null\n\nexport function toBucket(width: number): number {\n return Math.floor(width / 100) * 100\n}\n\nfunction debounce(fn: () => void, ms: number): () => void {\n let timer: ReturnType<typeof setTimeout>\n return () => {\n clearTimeout(timer)\n timer = setTimeout(fn, ms)\n }\n}\n\nexport function initViewportListener(callback: BucketChangeCallback): void {\n currentBucket = toBucket(window.innerWidth)\n onBucketChange = callback\n\n resizeHandler = debounce(() => {\n const newBucket = toBucket(window.innerWidth)\n if (newBucket !== currentBucket) {\n currentBucket = newBucket\n onBucketChange?.()\n }\n }, 300)\n\n window.addEventListener('resize', resizeHandler)\n}\n\nexport function destroyViewportListener(): void {\n if (resizeHandler) {\n window.removeEventListener('resize', resizeHandler)\n resizeHandler = null\n }\n onBucketChange = null\n}\n","import type { Annotation, AnnotationEvent, AnnotationStatus, AnnotationStore, StorageAdapter } from './types'\nimport { toBucket } from './viewport'\n\nexport function migrateAnnotation(legacy: any): Annotation {\n const rawStatus = legacy.status\n const status: AnnotationStatus =\n rawStatus === 'resolved' ? 'verified' : rawStatus\n\n if (Array.isArray(legacy.lifecycle) && legacy.lifecycle.length > 0) {\n return { ...legacy, status, lifecycle: legacy.lifecycle }\n }\n\n const createdTs = typeof legacy.timestamp === 'number' ? legacy.timestamp : Date.now()\n const lifecycle: AnnotationEvent[] = [\n { type: 'created', actor: 'designer', timestamp: createdTs },\n ]\n if (rawStatus === 'resolved') {\n lifecycle.push({ type: 'migrated', actor: null, timestamp: Date.now() })\n }\n\n return { ...legacy, status, lifecycle }\n}\n\nexport class AnnotationStorage {\n private cache: Annotation[] = []\n readonly ready: Promise<void>\n\n constructor(private adapter: StorageAdapter) {\n this.ready = this.init()\n }\n\n get isMemoryOnly(): boolean {\n return this.adapter.isMemoryOnly ?? false\n }\n\n getAll(): Annotation[] {\n return [...this.cache]\n }\n\n getByRoute(route: string): Annotation[] {\n return this.cache.filter((a) => a.route === route)\n }\n\n getById(id: string): Annotation | undefined {\n return this.cache.find((a) => a.id === id)\n }\n\n async add(annotation: Annotation): Promise<void> {\n this.cache.push(annotation)\n await this.adapter.save(annotation)\n }\n\n async remove(id: string): Promise<void> {\n this.cache = this.cache.filter((a) => a.id !== id)\n await this.adapter.remove(id)\n }\n\n async update(id: string, changes: Partial<Annotation>): Promise<void> {\n const idx = this.cache.findIndex((a) => a.id === id)\n if (idx === -1) return\n const updated = { ...this.cache[idx], ...changes }\n this.cache[idx] = updated\n await this.adapter.save(updated)\n }\n\n async clearAll(): Promise<void> {\n this.cache = []\n await this.adapter.clear()\n }\n\n exportJSON(): AnnotationStore {\n return {\n version: 1,\n annotations: [...this.cache],\n }\n }\n\n async importJSON(data: AnnotationStore): Promise<void> {\n this.cache = data.annotations.map(migrateAnnotation)\n this.migrateViewportBuckets()\n await this.adapter.clear()\n for (const ann of this.cache) {\n await this.adapter.save(ann)\n }\n }\n\n private async init(): Promise<void> {\n const data = await this.adapter.load()\n if (data) {\n this.cache = data.annotations.map(migrateAnnotation)\n this.migrateViewportBuckets()\n }\n }\n\n private migrateViewportBuckets(): void {\n for (const ann of this.cache) {\n if (ann.viewportBucket == null && ann.viewport) {\n const width = parseInt(ann.viewport.split('x')[0], 10)\n ann.viewportBucket = toBucket(width)\n }\n }\n }\n}\n","import type { Annotation, AnnotationStore, StorageAdapter } from './types';\n\nconst STORAGE_KEY = 'remarq:annotations';\n\nexport class LocalStorageAdapter implements StorageAdapter {\n isMemoryOnly = false;\n private extraFields: Record<string, unknown> = {};\n private memoryStore: AnnotationStore | null = null;\n\n async load(): Promise<AnnotationStore | null> {\n if (this.isMemoryOnly) return this.memoryStore;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n const { version, annotations, ...rest } = parsed;\n this.extraFields = rest;\n const store: AnnotationStore = {\n version: 1,\n annotations: Array.isArray(annotations) ? annotations : [],\n };\n this.memoryStore = store;\n return store;\n } catch {\n this.isMemoryOnly = true;\n return this.memoryStore;\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n const store = await this.ensureStore();\n const idx = store.annotations.findIndex((a) => a.id === annotation.id);\n if (idx === -1) {\n store.annotations.push(annotation);\n } else {\n store.annotations[idx] = annotation;\n }\n this.persist(store);\n }\n\n async remove(id: string): Promise<void> {\n const store = await this.ensureStore();\n store.annotations = store.annotations.filter((a) => a.id !== id);\n this.persist(store);\n }\n\n async clear(): Promise<void> {\n const store = await this.ensureStore();\n store.annotations = [];\n this.persist(store);\n }\n\n private async ensureStore(): Promise<AnnotationStore> {\n if (this.memoryStore) return this.memoryStore;\n const loaded = await this.load();\n if (loaded) return loaded;\n this.memoryStore = { version: 1, annotations: [] };\n return this.memoryStore;\n }\n\n private persist(store: AnnotationStore): void {\n if (this.isMemoryOnly) return;\n try {\n const data = {\n version: 1,\n ...this.extraFields,\n annotations: store.annotations,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n this.isMemoryOnly = true;\n }\n }\n}\n","import type {\n Annotation,\n AgentExport,\n AgentAnnotation,\n AgentAnnotationSource,\n AgentSearchHints,\n GrepQuery,\n ElementFingerprint,\n} from './types'\n\nfunction parseSourceLocation(raw: string): { file: string; line: number; column: number } | null {\n const parts = raw.split(':')\n if (parts.length < 2) return null\n // file path may contain \":\" on Windows (C:\\...), so rejoin all but last 2\n const column = parseInt(parts.pop()!, 10)\n const line = parseInt(parts.pop()!, 10)\n const file = parts.join(':')\n if (!file || isNaN(line)) return null\n return { file, line, column: isNaN(column) ? 0 : column }\n}\n\nfunction resolveSource(fp: ElementFingerprint): AgentAnnotationSource | null {\n // Level 1: plugin source\n if (fp.sourceLocation) {\n const parsed = parseSourceLocation(fp.sourceLocation)\n if (parsed) return { ...parsed, component: fp.componentName ?? null }\n }\n\n // Level 2: detected source\n if (fp.detectedSource) {\n const parsed = parseSourceLocation(fp.detectedSource)\n if (parsed) return { ...parsed, component: fp.detectedComponent ?? null }\n }\n\n return null\n}\n\nconst TEMPLATE_GLOB = '*.{tsx,jsx,vue,svelte,html}'\nconst CSS_MODULE_GLOB = '*.module.{css,scss,less}'\nconst COMPONENT_GLOB = '*.{tsx,jsx,vue,ts,js}'\n\nfunction buildSearchHints(fp: ElementFingerprint): AgentSearchHints {\n const grepQueries: GrepQuery[] = []\n\n // High confidence — unique selectors\n if (fp.dataAnnotate) {\n grepQueries.push({ query: `data-annotate=\"${fp.dataAnnotate}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.dataTestId) {\n grepQueries.push({ query: `data-testid=\"${fp.dataTestId}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.id) {\n grepQueries.push({ query: `id=\"${fp.id}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n if (fp.ariaLabel) {\n grepQueries.push({ query: `aria-label=\"${fp.ariaLabel}\"`, glob: TEMPLATE_GLOB, confidence: 'high' })\n }\n\n // Medium confidence — text, CSS modules, role\n if (fp.textContent) {\n grepQueries.push({ query: `\"${fp.textContent}\"`, glob: TEMPLATE_GLOB, confidence: 'medium' })\n }\n if (fp.role) {\n grepQueries.push({ query: `role=\"${fp.role}\"`, glob: TEMPLATE_GLOB, confidence: 'medium' })\n }\n if (fp.cssModules?.length) {\n for (const mod of fp.cssModules) {\n grepQueries.push({ query: `.${mod.localName}`, glob: CSS_MODULE_GLOB, confidence: 'medium' })\n grepQueries.push({ query: `styles.${mod.localName}`, glob: COMPONENT_GLOB, confidence: 'medium' })\n }\n }\n\n // Low confidence — classes, domPath\n if (fp.stableClasses.length) {\n for (const cls of fp.stableClasses.slice(0, 3)) {\n grepQueries.push({ query: `\"${cls}\"`, glob: TEMPLATE_GLOB, confidence: 'low' })\n }\n }\n\n return {\n grepQueries,\n domContext: fp.domPath,\n tagName: fp.tagName,\n classes: fp.rawClasses ?? fp.stableClasses,\n }\n}\n\nexport function generateAgentExport(annotations: Annotation[], viewportBucket: number): AgentExport {\n const agentAnnotations: AgentAnnotation[] = annotations.map(ann => ({\n id: ann.id,\n route: ann.route,\n comment: ann.comment,\n status: ann.status,\n timestamp: ann.timestamp,\n source: resolveSource(ann.fingerprint),\n searchHints: buildSearchHints(ann.fingerprint),\n lifecycle: ann.lifecycle.map((ev) => {\n const out: { type: typeof ev.type; actor: typeof ev.actor; timestamp: number; reason?: string } = {\n type: ev.type,\n actor: ev.actor,\n timestamp: ev.timestamp,\n }\n if (ev.reason !== undefined) out.reason = ev.reason\n return out\n }),\n }))\n\n return {\n version: 1,\n format: 'agent',\n viewportBucket,\n annotations: agentAnnotations,\n }\n}\n","import type {\n Annotation,\n AnnotationEvent,\n AnnotationEventType,\n AnnotationStatus,\n Actor,\n} from './types'\n\nexport type LifecycleAction =\n | 'acknowledge'\n | 'claimFix'\n | 'verify'\n | 'reject'\n | 'dismiss'\n | 'reopen'\n\nexport class InvalidTransitionError extends Error {\n constructor(from: AnnotationStatus, action: LifecycleAction) {\n super(`Cannot ${action} from status \"${from}\"`)\n this.name = 'InvalidTransitionError'\n }\n}\n\nexport interface EventOpts {\n actor?: Actor\n actorName?: string\n reason?: string\n timestamp?: number\n}\n\nconst ACTION_TO_EVENT: Record<LifecycleAction, AnnotationEventType> = {\n acknowledge: 'acknowledged',\n claimFix: 'fix_claimed',\n verify: 'verified',\n reject: 'rejected',\n dismiss: 'dismissed',\n reopen: 'reopened',\n}\n\nconst DEFAULT_ACTOR_BY_EVENT: Record<AnnotationEventType, Actor | null> = {\n created: 'designer',\n acknowledged: 'developer',\n fix_claimed: 'agent',\n verified: 'developer',\n rejected: 'developer',\n dismissed: 'developer',\n reopened: 'developer',\n migrated: null,\n}\n\nexport function createEvent(type: AnnotationEventType, opts: EventOpts = {}): AnnotationEvent {\n const event: AnnotationEvent = {\n type,\n actor: opts.actor ?? DEFAULT_ACTOR_BY_EVENT[type],\n timestamp: opts.timestamp ?? Date.now(),\n }\n if (opts.actorName !== undefined) event.actorName = opts.actorName\n if (opts.reason !== undefined) event.reason = opts.reason\n return event\n}\n\nfunction nextStatus(\n from: AnnotationStatus,\n action: LifecycleAction,\n): AnnotationStatus | null {\n switch (action) {\n case 'acknowledge':\n return from === 'pending' ? 'in_progress' : null\n case 'claimFix':\n return from === 'pending' || from === 'in_progress' ? 'fixed_unverified' : null\n case 'verify':\n return from === 'fixed_unverified' || from === 'in_progress' ? 'verified' : null\n case 'reject':\n return from === 'fixed_unverified' ? 'pending' : null\n case 'dismiss':\n return from === 'pending' || from === 'in_progress' || from === 'fixed_unverified'\n ? 'dismissed'\n : null\n case 'reopen':\n return from === 'dismissed' || from === 'verified' ? 'pending' : null\n }\n}\n\nexport function transition(\n annotation: Annotation,\n action: LifecycleAction,\n opts: EventOpts = {},\n): { status: AnnotationStatus; event: AnnotationEvent } {\n const next = nextStatus(annotation.status, action)\n if (next === null) {\n throw new InvalidTransitionError(annotation.status, action)\n }\n const event = createEvent(ACTION_TO_EVENT[action], opts)\n return { status: next, event }\n}\n"],"mappings":"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","names":["parent","buildDomPath"]}
|
package/dist/core/index.d.cts
CHANGED
|
@@ -26,6 +26,16 @@ interface ElementFingerprint {
|
|
|
26
26
|
detectedSource: string | null;
|
|
27
27
|
detectedComponent: string | null;
|
|
28
28
|
}
|
|
29
|
+
type AnnotationStatus = 'pending' | 'in_progress' | 'fixed_unverified' | 'verified' | 'dismissed';
|
|
30
|
+
type Actor = 'designer' | 'agent' | 'developer';
|
|
31
|
+
type AnnotationEventType = 'created' | 'acknowledged' | 'fix_claimed' | 'verified' | 'rejected' | 'dismissed' | 'reopened' | 'migrated';
|
|
32
|
+
interface AnnotationEvent {
|
|
33
|
+
type: AnnotationEventType;
|
|
34
|
+
actor: Actor | null;
|
|
35
|
+
actorName?: string;
|
|
36
|
+
timestamp: number;
|
|
37
|
+
reason?: string;
|
|
38
|
+
}
|
|
29
39
|
interface Annotation {
|
|
30
40
|
id: string;
|
|
31
41
|
comment: string;
|
|
@@ -34,7 +44,8 @@ interface Annotation {
|
|
|
34
44
|
viewport: string;
|
|
35
45
|
viewportBucket: number;
|
|
36
46
|
timestamp: number;
|
|
37
|
-
status:
|
|
47
|
+
status: AnnotationStatus;
|
|
48
|
+
lifecycle: AnnotationEvent[];
|
|
38
49
|
}
|
|
39
50
|
interface AnnotationStore {
|
|
40
51
|
version: 1;
|
|
@@ -67,14 +78,21 @@ interface AgentAnnotationSource {
|
|
|
67
78
|
column: number;
|
|
68
79
|
component: string | null;
|
|
69
80
|
}
|
|
81
|
+
interface AgentLifecycleEvent {
|
|
82
|
+
type: AnnotationEventType;
|
|
83
|
+
actor: Actor | null;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
reason?: string;
|
|
86
|
+
}
|
|
70
87
|
interface AgentAnnotation {
|
|
71
88
|
id: string;
|
|
72
89
|
route: string;
|
|
73
90
|
comment: string;
|
|
74
|
-
status:
|
|
91
|
+
status: AnnotationStatus;
|
|
75
92
|
timestamp: number;
|
|
76
93
|
source: AgentAnnotationSource | null;
|
|
77
94
|
searchHints: AgentSearchHints;
|
|
95
|
+
lifecycle: AgentLifecycleEvent[];
|
|
78
96
|
}
|
|
79
97
|
interface AgentExport {
|
|
80
98
|
version: 1;
|
|
@@ -100,6 +118,7 @@ declare function createFingerprint(el: HTMLElement, options?: Pick<WebRemarqOpti
|
|
|
100
118
|
|
|
101
119
|
declare function matchElement(fp: ElementFingerprint, options?: Pick<WebRemarqOptions, 'dataAttribute'>): HTMLElement | null;
|
|
102
120
|
|
|
121
|
+
declare function migrateAnnotation(legacy: any): Annotation;
|
|
103
122
|
declare class AnnotationStorage {
|
|
104
123
|
private adapter;
|
|
105
124
|
private cache;
|
|
@@ -108,6 +127,7 @@ declare class AnnotationStorage {
|
|
|
108
127
|
get isMemoryOnly(): boolean;
|
|
109
128
|
getAll(): Annotation[];
|
|
110
129
|
getByRoute(route: string): Annotation[];
|
|
130
|
+
getById(id: string): Annotation | undefined;
|
|
111
131
|
add(annotation: Annotation): Promise<void>;
|
|
112
132
|
remove(id: string): Promise<void>;
|
|
113
133
|
update(id: string, changes: Partial<Annotation>): Promise<void>;
|
|
@@ -142,4 +162,20 @@ declare function detectSource(el: HTMLElement): SourceDetectionResult;
|
|
|
142
162
|
|
|
143
163
|
declare function generateAgentExport(annotations: Annotation[], viewportBucket: number): AgentExport;
|
|
144
164
|
|
|
145
|
-
|
|
165
|
+
type LifecycleAction = 'acknowledge' | 'claimFix' | 'verify' | 'reject' | 'dismiss' | 'reopen';
|
|
166
|
+
declare class InvalidTransitionError extends Error {
|
|
167
|
+
constructor(from: AnnotationStatus, action: LifecycleAction);
|
|
168
|
+
}
|
|
169
|
+
interface EventOpts {
|
|
170
|
+
actor?: Actor;
|
|
171
|
+
actorName?: string;
|
|
172
|
+
reason?: string;
|
|
173
|
+
timestamp?: number;
|
|
174
|
+
}
|
|
175
|
+
declare function createEvent(type: AnnotationEventType, opts?: EventOpts): AnnotationEvent;
|
|
176
|
+
declare function transition(annotation: Annotation, action: LifecycleAction, opts?: EventOpts): {
|
|
177
|
+
status: AnnotationStatus;
|
|
178
|
+
event: AnnotationEvent;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export { type Actor, type AgentAnnotation, type AgentAnnotationSource, type AgentExport, type AgentLifecycleEvent, type AgentSearchHints, type Annotation, type AnnotationEvent, type AnnotationEventType, type AnnotationStatus, AnnotationStorage, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type EventOpts, type GrepQuery, InvalidTransitionError, type LifecycleAction, LocalStorageAdapter, type SearchConfidence, type SourceDetectionResult, type StorageAdapter, type StorageChangeEvent, type ToolbarPosition, createEvent, createFingerprint, detectRemarqPlugin, detectSource, generateAgentExport, matchElement, migrateAnnotation, transition };
|
package/dist/core/index.d.ts
CHANGED
|
@@ -26,6 +26,16 @@ interface ElementFingerprint {
|
|
|
26
26
|
detectedSource: string | null;
|
|
27
27
|
detectedComponent: string | null;
|
|
28
28
|
}
|
|
29
|
+
type AnnotationStatus = 'pending' | 'in_progress' | 'fixed_unverified' | 'verified' | 'dismissed';
|
|
30
|
+
type Actor = 'designer' | 'agent' | 'developer';
|
|
31
|
+
type AnnotationEventType = 'created' | 'acknowledged' | 'fix_claimed' | 'verified' | 'rejected' | 'dismissed' | 'reopened' | 'migrated';
|
|
32
|
+
interface AnnotationEvent {
|
|
33
|
+
type: AnnotationEventType;
|
|
34
|
+
actor: Actor | null;
|
|
35
|
+
actorName?: string;
|
|
36
|
+
timestamp: number;
|
|
37
|
+
reason?: string;
|
|
38
|
+
}
|
|
29
39
|
interface Annotation {
|
|
30
40
|
id: string;
|
|
31
41
|
comment: string;
|
|
@@ -34,7 +44,8 @@ interface Annotation {
|
|
|
34
44
|
viewport: string;
|
|
35
45
|
viewportBucket: number;
|
|
36
46
|
timestamp: number;
|
|
37
|
-
status:
|
|
47
|
+
status: AnnotationStatus;
|
|
48
|
+
lifecycle: AnnotationEvent[];
|
|
38
49
|
}
|
|
39
50
|
interface AnnotationStore {
|
|
40
51
|
version: 1;
|
|
@@ -67,14 +78,21 @@ interface AgentAnnotationSource {
|
|
|
67
78
|
column: number;
|
|
68
79
|
component: string | null;
|
|
69
80
|
}
|
|
81
|
+
interface AgentLifecycleEvent {
|
|
82
|
+
type: AnnotationEventType;
|
|
83
|
+
actor: Actor | null;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
reason?: string;
|
|
86
|
+
}
|
|
70
87
|
interface AgentAnnotation {
|
|
71
88
|
id: string;
|
|
72
89
|
route: string;
|
|
73
90
|
comment: string;
|
|
74
|
-
status:
|
|
91
|
+
status: AnnotationStatus;
|
|
75
92
|
timestamp: number;
|
|
76
93
|
source: AgentAnnotationSource | null;
|
|
77
94
|
searchHints: AgentSearchHints;
|
|
95
|
+
lifecycle: AgentLifecycleEvent[];
|
|
78
96
|
}
|
|
79
97
|
interface AgentExport {
|
|
80
98
|
version: 1;
|
|
@@ -100,6 +118,7 @@ declare function createFingerprint(el: HTMLElement, options?: Pick<WebRemarqOpti
|
|
|
100
118
|
|
|
101
119
|
declare function matchElement(fp: ElementFingerprint, options?: Pick<WebRemarqOptions, 'dataAttribute'>): HTMLElement | null;
|
|
102
120
|
|
|
121
|
+
declare function migrateAnnotation(legacy: any): Annotation;
|
|
103
122
|
declare class AnnotationStorage {
|
|
104
123
|
private adapter;
|
|
105
124
|
private cache;
|
|
@@ -108,6 +127,7 @@ declare class AnnotationStorage {
|
|
|
108
127
|
get isMemoryOnly(): boolean;
|
|
109
128
|
getAll(): Annotation[];
|
|
110
129
|
getByRoute(route: string): Annotation[];
|
|
130
|
+
getById(id: string): Annotation | undefined;
|
|
111
131
|
add(annotation: Annotation): Promise<void>;
|
|
112
132
|
remove(id: string): Promise<void>;
|
|
113
133
|
update(id: string, changes: Partial<Annotation>): Promise<void>;
|
|
@@ -142,4 +162,20 @@ declare function detectSource(el: HTMLElement): SourceDetectionResult;
|
|
|
142
162
|
|
|
143
163
|
declare function generateAgentExport(annotations: Annotation[], viewportBucket: number): AgentExport;
|
|
144
164
|
|
|
145
|
-
|
|
165
|
+
type LifecycleAction = 'acknowledge' | 'claimFix' | 'verify' | 'reject' | 'dismiss' | 'reopen';
|
|
166
|
+
declare class InvalidTransitionError extends Error {
|
|
167
|
+
constructor(from: AnnotationStatus, action: LifecycleAction);
|
|
168
|
+
}
|
|
169
|
+
interface EventOpts {
|
|
170
|
+
actor?: Actor;
|
|
171
|
+
actorName?: string;
|
|
172
|
+
reason?: string;
|
|
173
|
+
timestamp?: number;
|
|
174
|
+
}
|
|
175
|
+
declare function createEvent(type: AnnotationEventType, opts?: EventOpts): AnnotationEvent;
|
|
176
|
+
declare function transition(annotation: Annotation, action: LifecycleAction, opts?: EventOpts): {
|
|
177
|
+
status: AnnotationStatus;
|
|
178
|
+
event: AnnotationEvent;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export { type Actor, type AgentAnnotation, type AgentAnnotationSource, type AgentExport, type AgentLifecycleEvent, type AgentSearchHints, type Annotation, type AnnotationEvent, type AnnotationEventType, type AnnotationStatus, AnnotationStorage, type AnnotationStore, type CSSModuleClass, type ElementFingerprint, type EventOpts, type GrepQuery, InvalidTransitionError, type LifecycleAction, LocalStorageAdapter, type SearchConfidence, type SourceDetectionResult, type StorageAdapter, type StorageChangeEvent, type ToolbarPosition, createEvent, createFingerprint, detectRemarqPlugin, detectSource, generateAgentExport, matchElement, migrateAnnotation, transition };
|