web-remarq 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.d.cts +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/index.cjs +16 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +16 -14
- package/dist/index.js.map +1 -1
- package/dist/web-remarq.global.global.js +16 -14
- package/dist/web-remarq.global.global.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.d.cts
CHANGED
package/dist/core/index.d.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -789,13 +789,13 @@ var Toolbar = class {
|
|
|
789
789
|
this.exportMenu = document.createElement("div");
|
|
790
790
|
this.exportMenu.className = "remarq-export-menu";
|
|
791
791
|
const mdBtn = document.createElement("button");
|
|
792
|
-
mdBtn.textContent = "Markdown (
|
|
792
|
+
mdBtn.textContent = "Markdown (file)";
|
|
793
793
|
mdBtn.addEventListener("click", () => {
|
|
794
794
|
this.callbacks.onExportMd();
|
|
795
795
|
this.closeExportMenu();
|
|
796
796
|
});
|
|
797
797
|
const jsonBtn = document.createElement("button");
|
|
798
|
-
jsonBtn.textContent = "JSON (
|
|
798
|
+
jsonBtn.textContent = "JSON (clipboard)";
|
|
799
799
|
jsonBtn.addEventListener("click", () => {
|
|
800
800
|
this.callbacks.onExportJson();
|
|
801
801
|
this.closeExportMenu();
|
|
@@ -1345,6 +1345,7 @@ function handleInspectClick(e) {
|
|
|
1345
1345
|
comment,
|
|
1346
1346
|
fingerprint: fp,
|
|
1347
1347
|
route: currentRoute(),
|
|
1348
|
+
viewport: `${window.innerWidth}x${window.innerHeight}`,
|
|
1348
1349
|
timestamp: Date.now(),
|
|
1349
1350
|
status: "pending"
|
|
1350
1351
|
};
|
|
@@ -1419,26 +1420,27 @@ function exportMarkdown() {
|
|
|
1419
1420
|
if (fp.textContent) desc += ` "${fp.textContent}"`;
|
|
1420
1421
|
if (fp.parentAnchor) desc += ` (${fp.parentAnchor})`;
|
|
1421
1422
|
if (fp.dataAnnotate) desc += fp.parentAnchor ? ` > ${fp.dataAnnotate}` : ` (${fp.dataAnnotate})`;
|
|
1422
|
-
|
|
1423
|
+
const viewport = ann.viewport ? ` @${ann.viewport}` : "";
|
|
1424
|
+
lines.push(`${i + 1}. [${ann.status}]${viewport} ${desc}: "${ann.comment}"`);
|
|
1423
1425
|
});
|
|
1424
1426
|
const text = lines.join("\n");
|
|
1425
|
-
|
|
1426
|
-
navigator.clipboard.writeText(text);
|
|
1427
|
-
} catch (e) {
|
|
1428
|
-
console.warn("[web-remarq] Clipboard write failed");
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
function exportJSON() {
|
|
1432
|
-
const data = storage.exportJSON();
|
|
1433
|
-
const json = JSON.stringify(data, null, 2);
|
|
1434
|
-
const blob = new Blob([json], { type: "application/json" });
|
|
1427
|
+
const blob = new Blob([text], { type: "text/markdown" });
|
|
1435
1428
|
const url = URL.createObjectURL(blob);
|
|
1436
1429
|
const a = document.createElement("a");
|
|
1437
1430
|
a.href = url;
|
|
1438
|
-
a.download = `remarq-annotations-${Date.now()}.
|
|
1431
|
+
a.download = `remarq-annotations-${Date.now()}.md`;
|
|
1439
1432
|
a.click();
|
|
1440
1433
|
URL.revokeObjectURL(url);
|
|
1441
1434
|
}
|
|
1435
|
+
function exportJSON() {
|
|
1436
|
+
const data = storage.exportJSON();
|
|
1437
|
+
const json = JSON.stringify(data, null, 2);
|
|
1438
|
+
try {
|
|
1439
|
+
navigator.clipboard.writeText(json);
|
|
1440
|
+
} catch (e) {
|
|
1441
|
+
console.warn("[web-remarq] Clipboard write failed");
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1442
1444
|
function setupMutationObserver() {
|
|
1443
1445
|
mutationObserver = new MutationObserver((mutations) => {
|
|
1444
1446
|
for (const m of mutations) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/storage.ts","../src/core/hash-detect.ts","../src/core/fingerprint.ts","../src/core/matcher.ts","../src/ui/styles.ts","../src/ui/theme.ts","../src/ui/toolbar.ts","../src/ui/overlay.ts","../src/ui/popup.ts","../src/ui/markers.ts","../src/ui/detached-panel.ts","../src/spa.ts","../src/web-remarq.ts"],"sourcesContent":["export { WebRemarq } from './web-remarq'\nexport type { Annotation, AnnotationStore, ElementFingerprint, WebRemarqOptions, ImportResult } from './core/types'\n","import type { Annotation, AnnotationStore } from './types'\n\nconst STORAGE_KEY = 'remarq:annotations'\n\nexport class AnnotationStorage {\n private annotations: Annotation[] = []\n private extraFields: Record<string, unknown> = {}\n isMemoryOnly = false\n\n constructor() {\n this.load()\n }\n\n getAll(): Annotation[] {\n return [...this.annotations]\n }\n\n getByRoute(route: string): Annotation[] {\n return this.annotations.filter((a) => a.route === route)\n }\n\n add(annotation: Annotation): void {\n this.annotations.push(annotation)\n this.save()\n }\n\n remove(id: string): void {\n this.annotations = this.annotations.filter((a) => a.id !== id)\n this.save()\n }\n\n update(id: string, changes: Partial<Annotation>): void {\n const idx = this.annotations.findIndex((a) => a.id === id)\n if (idx !== -1) {\n this.annotations[idx] = { ...this.annotations[idx], ...changes }\n this.save()\n }\n }\n\n clearAll(): void {\n this.annotations = []\n this.save()\n }\n\n exportJSON(): AnnotationStore {\n return {\n version: 1,\n annotations: [...this.annotations],\n }\n }\n\n importJSON(data: AnnotationStore): void {\n this.annotations = [...data.annotations]\n this.save()\n }\n\n private load(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n if (raw) {\n const parsed = JSON.parse(raw)\n const { version, annotations, ...rest } = parsed\n this.annotations = annotations ?? []\n this.extraFields = rest\n }\n } catch {\n this.isMemoryOnly = true\n }\n }\n\n private save(): void {\n if (this.isMemoryOnly) return\n try {\n const data = {\n version: 1,\n ...this.extraFields,\n annotations: this.annotations,\n }\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data))\n } catch {\n this.isMemoryOnly = true\n }\n }\n}\n","const CSS_MODULES_RE = /^(.+)__([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","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses, isHashedClass } from './hash-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 }\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 parts.unshift(current.tagName.toLowerCase())\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'\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 (+15 scaled)\n if (fp.stableClasses.length > 0) {\n const elClasses = Array.from(el.classList)\n const jaccard = jaccardSimilarity(fp.stableClasses, elClasses)\n score += jaccard * 15\n }\n\n // domPath match (+15 scaled)\n if (fp.domPath) {\n const elPath = buildDomPath(el)\n const pathSim = levenshteinSimilarity(fp.domPath, elPath)\n score += pathSim * 15\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 parts.unshift(current.tagName.toLowerCase())\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","const STYLES_ID = 'data-remarq-styles'\n\nconst CSS = `\n[data-remarq-theme=\"light\"] {\n --remarq-bg: #ffffff;\n --remarq-bg-secondary: #f5f5f5;\n --remarq-text: #1a1a1a;\n --remarq-text-secondary: #666666;\n --remarq-border: #e2e8f0;\n --remarq-accent: #3b82f6;\n --remarq-pending: #f97316;\n --remarq-resolved: #22c55e;\n --remarq-overlay: rgba(59, 130, 246, 0.15);\n --remarq-shadow: 0 4px 12px rgba(0,0,0,0.15);\n}\n\n[data-remarq-theme=\"dark\"] {\n --remarq-bg: #1e1e1e;\n --remarq-bg-secondary: #2a2a2a;\n --remarq-text: #e5e5e5;\n --remarq-text-secondary: #999999;\n --remarq-border: #333333;\n --remarq-accent: #60a5fa;\n --remarq-pending: #fb923c;\n --remarq-resolved: #4ade80;\n --remarq-overlay: rgba(96, 165, 250, 0.15);\n --remarq-shadow: 0 4px 12px rgba(0,0,0,0.4);\n}\n\n.remarq-toolbar {\n position: fixed;\n bottom: 16px;\n right: 16px;\n z-index: 2147483647;\n display: flex;\n gap: 4px;\n padding: 8px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-toolbar.remarq-minimized { padding: 4px; }\n\n.remarq-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--remarq-text);\n cursor: pointer;\n position: relative;\n}\n\n.remarq-toolbar-btn:hover { background: var(--remarq-bg-secondary); }\n.remarq-toolbar-btn.remarq-active { background: var(--remarq-accent); color: #ffffff; }\n\n.remarq-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--remarq-pending);\n color: #ffffff;\n font-size: 10px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.remarq-overlay {\n position: fixed;\n pointer-events: none;\n background: var(--remarq-overlay);\n border: 2px solid var(--remarq-accent);\n border-radius: 2px;\n z-index: 2147483646;\n transition: all 0.05s ease-out;\n}\n\n.remarq-tooltip {\n position: fixed;\n z-index: 2147483647;\n padding: 4px 8px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 12px;\n color: var(--remarq-text);\n box-shadow: var(--remarq-shadow);\n pointer-events: none;\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.remarq-marker {\n position: absolute;\n z-index: 2147483645;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n transition: transform 0.1s ease;\n}\n\n.remarq-marker:hover { transform: scale(1.2); }\n.remarq-marker[data-status=\"pending\"] { background: var(--remarq-pending); }\n.remarq-marker[data-status=\"resolved\"] { background: var(--remarq-resolved); opacity: 0.7; }\n\n.remarq-popup {\n position: absolute;\n z-index: 2147483647;\n width: 300px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-popup-header {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n font-size: 12px;\n color: var(--remarq-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.remarq-popup-body { padding: 12px; }\n\n.remarq-popup textarea {\n width: 100%;\n min-height: 60px;\n padding: 8px;\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n background: var(--remarq-bg-secondary);\n color: var(--remarq-text);\n font-family: inherit;\n font-size: 13px;\n resize: vertical;\n box-sizing: border-box;\n}\n\n.remarq-popup textarea:focus { outline: none; border-color: var(--remarq-accent); }\n\n.remarq-popup-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n border-top: 1px solid var(--remarq-border);\n}\n\n.remarq-popup-actions button {\n padding: 4px 12px;\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n background: var(--remarq-bg);\n color: var(--remarq-text);\n cursor: pointer;\n font-size: 12px;\n}\n\n.remarq-popup-actions button.remarq-primary {\n background: var(--remarq-accent);\n border-color: var(--remarq-accent);\n color: #ffffff;\n}\n\n.remarq-detached-panel {\n position: fixed;\n bottom: 60px;\n right: 16px;\n z-index: 2147483646;\n width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-detached-header {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n font-weight: 600;\n font-size: 12px;\n color: var(--remarq-text-secondary);\n}\n\n.remarq-detached-item {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n}\n\n.remarq-detached-item:last-child { border-bottom: none; }\n.remarq-detached-info { flex: 1; min-width: 0; }\n.remarq-detached-comment { margin-bottom: 4px; }\n\n.remarq-detached-element {\n font-size: 11px;\n color: var(--remarq-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.remarq-detached-delete {\n border: none;\n background: none;\n color: var(--remarq-text-secondary);\n cursor: pointer;\n padding: 2px;\n font-size: 14px;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.remarq-detached-delete:hover { color: #ef4444; }\n\n.remarq-export-menu {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 4px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 6px;\n box-shadow: var(--remarq-shadow);\n overflow: hidden;\n}\n\n.remarq-export-menu button {\n display: block;\n width: 100%;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--remarq-text);\n cursor: pointer;\n font-size: 12px;\n text-align: left;\n white-space: nowrap;\n}\n\n.remarq-export-menu button:hover { background: var(--remarq-bg-secondary); }\n`\n\nexport function injectStyles(): void {\n if (document.querySelector(`style[${STYLES_ID}]`)) return\n\n try {\n const style = document.createElement('style')\n style.setAttribute(STYLES_ID, '')\n style.textContent = CSS\n document.head.appendChild(style)\n } catch {\n // CSP fallback: try blob URL via <link>\n try {\n const blob = new Blob([CSS], { type: 'text/css' })\n const link = document.createElement('link')\n link.rel = 'stylesheet'\n link.href = URL.createObjectURL(blob)\n link.setAttribute(STYLES_ID, '')\n document.head.appendChild(link)\n } catch {\n console.warn('[web-remarq] Could not inject styles')\n }\n }\n}\n\nexport function removeStyles(): void {\n const el = document.querySelector(`[${STYLES_ID}]`)\n el?.remove()\n}\n","const THEME_KEY = 'remarq:theme'\n\nexport type Theme = 'light' | 'dark'\n\nexport class ThemeManager {\n container: HTMLElement\n private theme: Theme\n\n constructor(parent: HTMLElement, initialTheme?: Theme) {\n const persisted = this.loadTheme()\n this.theme = initialTheme ?? persisted ?? 'light'\n\n this.container = document.createElement('div')\n this.container.setAttribute('data-remarq-theme', this.theme)\n parent.appendChild(this.container)\n\n this.persist()\n }\n\n getTheme(): Theme {\n return this.theme\n }\n\n setTheme(theme: Theme): void {\n this.theme = theme\n this.container.setAttribute('data-remarq-theme', theme)\n this.persist()\n }\n\n toggle(): void {\n this.setTheme(this.theme === 'light' ? 'dark' : 'light')\n }\n\n destroy(): void {\n this.container.remove()\n }\n\n private persist(): void {\n try {\n localStorage.setItem(THEME_KEY, this.theme)\n } catch {\n // ignore\n }\n }\n\n private loadTheme(): Theme | null {\n try {\n const value = localStorage.getItem(THEME_KEY)\n if (value === 'light' || value === 'dark') return value\n } catch {\n // ignore\n }\n return null\n }\n}\n","export interface ToolbarCallbacks {\n onInspect: () => void\n onExportMd: () => void\n onExportJson: () => void\n onImport: () => void\n onClear: () => void\n onThemeToggle: () => void\n}\n\nconst ICONS = {\n inspect: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"7\" cy=\"7\" r=\"4\"/><line x1=\"10\" y1=\"10\" x2=\"14\" y2=\"14\"/></svg>',\n export: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M8 2v8M4 6l4-4 4 4M2 12h12\"/></svg>',\n import: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M8 10V2M4 6l4 4 4-4M2 12h12\"/></svg>',\n clear: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M3 4h10M6 4V3h4v1M5 4v9h6V4\"/></svg>',\n theme: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"8\" cy=\"8\" r=\"3\"/><path d=\"M8 1v2M8 13v2M1 8h2M13 8h2\"/></svg>',\n minimize: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M4 8h8\"/></svg>',\n}\n\nexport class Toolbar {\n private toolbarEl: HTMLElement\n private badgeEl: HTMLElement\n private inspectBtn: HTMLElement\n private exportMenu: HTMLElement | null = null\n private fileInput: HTMLInputElement\n private minimized = false\n private buttons: HTMLElement[] = []\n\n constructor(\n private container: HTMLElement,\n private callbacks: ToolbarCallbacks,\n ) {\n this.toolbarEl = document.createElement('div')\n this.toolbarEl.className = 'remarq-toolbar'\n\n this.inspectBtn = this.createButton('inspect', ICONS.inspect, () => callbacks.onInspect())\n this.badgeEl = document.createElement('span')\n this.badgeEl.className = 'remarq-badge'\n this.badgeEl.style.display = 'none'\n this.inspectBtn.appendChild(this.badgeEl)\n\n const exportBtn = this.createButton('export', ICONS.export, (e) => this.toggleExportMenu(e))\n\n this.fileInput = document.createElement('input')\n this.fileInput.type = 'file'\n this.fileInput.accept = '.json'\n this.fileInput.style.display = 'none'\n this.fileInput.addEventListener('change', () => {\n callbacks.onImport()\n this.fileInput.value = ''\n })\n const importBtn = this.createButton('import', ICONS.import, () => this.fileInput.click())\n\n const clearBtn = this.createButton('clear', ICONS.clear, () => callbacks.onClear())\n const themeBtn = this.createButton('theme', ICONS.theme, () => callbacks.onThemeToggle())\n const minimizeBtn = this.createButton('minimize', ICONS.minimize, () => this.toggleMinimize())\n\n this.buttons = [this.inspectBtn, exportBtn, importBtn, clearBtn, themeBtn]\n\n this.toolbarEl.appendChild(this.inspectBtn)\n this.toolbarEl.appendChild(exportBtn)\n this.toolbarEl.appendChild(importBtn)\n this.toolbarEl.appendChild(clearBtn)\n this.toolbarEl.appendChild(themeBtn)\n this.toolbarEl.appendChild(minimizeBtn)\n this.toolbarEl.appendChild(this.fileInput)\n\n container.appendChild(this.toolbarEl)\n }\n\n setInspectActive(active: boolean): void {\n this.inspectBtn.classList.toggle('remarq-active', active)\n }\n\n setBadgeCount(count: number): void {\n this.badgeEl.textContent = String(count)\n this.badgeEl.style.display = count > 0 ? 'flex' : 'none'\n }\n\n getFileInput(): HTMLInputElement {\n return this.fileInput\n }\n\n setMemoryWarning(show: boolean): void {\n this.toolbarEl.title = show ? 'localStorage unavailable — annotations stored in memory only' : ''\n }\n\n destroy(): void {\n this.closeExportMenu()\n this.toolbarEl.remove()\n }\n\n private createButton(action: string, icon: string, handler: (e: Event) => void): HTMLElement {\n const btn = document.createElement('button')\n btn.className = 'remarq-toolbar-btn'\n btn.setAttribute('data-remarq-action', action)\n btn.innerHTML = icon\n btn.addEventListener('click', handler)\n return btn\n }\n\n private toggleMinimize(): void {\n this.minimized = !this.minimized\n this.toolbarEl.classList.toggle('remarq-minimized', this.minimized)\n for (const btn of this.buttons) {\n btn.style.display = this.minimized ? 'none' : ''\n }\n }\n\n private toggleExportMenu(e: Event): void {\n if (this.exportMenu) {\n this.closeExportMenu()\n return\n }\n\n this.exportMenu = document.createElement('div')\n this.exportMenu.className = 'remarq-export-menu'\n\n const mdBtn = document.createElement('button')\n mdBtn.textContent = 'Markdown (clipboard)'\n mdBtn.addEventListener('click', () => {\n this.callbacks.onExportMd()\n this.closeExportMenu()\n })\n\n const jsonBtn = document.createElement('button')\n jsonBtn.textContent = 'JSON (file)'\n jsonBtn.addEventListener('click', () => {\n this.callbacks.onExportJson()\n this.closeExportMenu()\n })\n\n this.exportMenu.appendChild(mdBtn)\n this.exportMenu.appendChild(jsonBtn)\n\n const exportBtn = (e.currentTarget as HTMLElement)\n exportBtn.style.position = 'relative'\n exportBtn.appendChild(this.exportMenu)\n }\n\n private closeExportMenu(): void {\n if (this.exportMenu) {\n this.exportMenu.remove()\n this.exportMenu = null\n }\n }\n}\n","export class Overlay {\n private overlayEl: HTMLElement\n private tooltipEl: HTMLElement\n\n constructor(private container: HTMLElement) {\n this.overlayEl = document.createElement('div')\n this.overlayEl.className = 'remarq-overlay'\n this.overlayEl.style.display = 'none'\n\n this.tooltipEl = document.createElement('div')\n this.tooltipEl.className = 'remarq-tooltip'\n this.tooltipEl.style.display = 'none'\n\n container.appendChild(this.overlayEl)\n container.appendChild(this.tooltipEl)\n }\n\n show(target: HTMLElement): void {\n try {\n const rect = target.getBoundingClientRect()\n\n this.overlayEl.style.display = 'block'\n this.overlayEl.style.top = `${rect.top}px`\n this.overlayEl.style.left = `${rect.left}px`\n this.overlayEl.style.width = `${rect.width}px`\n this.overlayEl.style.height = `${rect.height}px`\n\n this.tooltipEl.textContent = describeElement(target)\n this.tooltipEl.style.display = 'block'\n this.tooltipEl.style.top = `${rect.top - 28}px`\n this.tooltipEl.style.left = `${rect.left}px`\n } catch {\n this.hide()\n }\n }\n\n updateTooltipPosition(x: number, y: number): void {\n this.tooltipEl.style.left = `${x + 12}px`\n this.tooltipEl.style.top = `${y - 28}px`\n }\n\n hide(): void {\n this.overlayEl.style.display = 'none'\n this.tooltipEl.style.display = 'none'\n }\n\n destroy(): void {\n this.overlayEl.remove()\n this.tooltipEl.remove()\n }\n}\n\nfunction describeElement(el: HTMLElement): string {\n const tag = el.tagName.toLowerCase()\n const parts: string[] = [`<${tag}>`]\n\n // data-annotate or data-testid\n const dataAnnotate = el.getAttribute('data-annotate')\n const dataTestId = el.getAttribute('data-testid') || el.getAttribute('data-test') || el.getAttribute('data-cy')\n if (dataAnnotate) {\n parts.push(`[${dataAnnotate}]`)\n } else if (dataTestId) {\n parts.push(`[${dataTestId}]`)\n }\n\n // id\n if (el.id) {\n parts.push(`#${el.id}`)\n }\n\n // Meaningful classes (skip hashed ones, max 2)\n const classes = Array.from(el.classList)\n .filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/))\n .slice(0, 2)\n if (classes.length) {\n parts.push(`.${classes.join('.')}`)\n }\n\n // Direct text content only (not nested)\n const directText = getDirectText(el)\n if (directText) {\n parts.push(`\"${directText}\"`)\n }\n\n return parts.join(' ')\n}\n\nfunction getDirectText(el: HTMLElement): string {\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 // Fallback: if no direct text and few children, use shallow textContent\n if (!text && el.children.length <= 2) {\n text = el.textContent?.trim() ?? ''\n }\n\n return text.slice(0, 30)\n}\n","interface ElementInfo {\n tag: string\n text: string\n}\n\ninterface DetailInfo extends ElementInfo {\n comment: string\n status: 'pending' | 'resolved'\n}\n\ninterface DetailCallbacks {\n onResolve: () => void\n onDelete: () => void\n onClose: () => void\n}\n\ninterface Position {\n top: number // absolute page Y below the element\n left: number // absolute page X\n anchorBottom: number // absolute page Y above the element (for flipping)\n}\n\nconst POPUP_WIDTH = 300\nconst POPUP_MARGIN = 8\n\nexport class Popup {\n private popupEl: HTMLElement | null = null\n private keyHandler: ((e: KeyboardEvent) => void) | null = null\n\n constructor(private container: HTMLElement) {}\n\n show(\n info: ElementInfo,\n position: Position,\n onSubmit: (comment: string) => void,\n onCancel: () => void,\n ): void {\n this.hide()\n\n const popup = document.createElement('div')\n popup.className = 'remarq-popup'\n\n const header = document.createElement('div')\n header.className = 'remarq-popup-header'\n header.textContent = `<${info.tag}>${info.text ? ` \"${info.text}\"` : ''}`\n\n const body = document.createElement('div')\n body.className = 'remarq-popup-body'\n\n const textarea = document.createElement('textarea')\n textarea.placeholder = 'Add your comment...'\n\n body.appendChild(textarea)\n\n const actions = document.createElement('div')\n actions.className = 'remarq-popup-actions'\n\n const cancelBtn = document.createElement('button')\n cancelBtn.textContent = 'Cancel'\n cancelBtn.addEventListener('click', () => {\n this.hide()\n onCancel()\n })\n\n const addBtn = document.createElement('button')\n addBtn.className = 'remarq-primary'\n addBtn.textContent = 'Add'\n addBtn.addEventListener('click', () => {\n const comment = textarea.value.trim()\n if (!comment) return\n this.hide()\n onSubmit(comment)\n })\n\n actions.appendChild(cancelBtn)\n actions.appendChild(addBtn)\n\n popup.appendChild(header)\n popup.appendChild(body)\n popup.appendChild(actions)\n\n this.container.appendChild(popup)\n this.popupEl = popup\n\n // Measure after layout, then position\n requestAnimationFrame(() => {\n this.adjustPosition(popup, position)\n textarea.focus()\n })\n\n // Cmd/Ctrl+Enter to submit\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n const comment = textarea.value.trim()\n if (!comment) return\n this.hide()\n onSubmit(comment)\n }\n if (e.key === 'Escape') {\n this.hide()\n onCancel()\n }\n }\n document.addEventListener('keydown', this.keyHandler)\n }\n\n showDetail(\n info: DetailInfo,\n position: Position,\n callbacks: DetailCallbacks,\n ): void {\n this.hide()\n\n const popup = document.createElement('div')\n popup.className = 'remarq-popup'\n\n const header = document.createElement('div')\n header.className = 'remarq-popup-header'\n header.textContent = `<${info.tag}>${info.text ? ` \"${info.text}\"` : ''} [${info.status}]`\n\n const body = document.createElement('div')\n body.className = 'remarq-popup-body'\n body.textContent = info.comment\n\n const actions = document.createElement('div')\n actions.className = 'remarq-popup-actions'\n\n if (info.status === 'pending') {\n const resolveBtn = document.createElement('button')\n resolveBtn.className = 'remarq-primary'\n resolveBtn.textContent = 'Resolve'\n resolveBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onResolve()\n })\n actions.appendChild(resolveBtn)\n }\n\n const deleteBtn = document.createElement('button')\n deleteBtn.textContent = 'Delete'\n deleteBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onDelete()\n })\n actions.appendChild(deleteBtn)\n\n const closeBtn = document.createElement('button')\n closeBtn.textContent = 'Close'\n closeBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onClose()\n })\n actions.appendChild(closeBtn)\n\n popup.appendChild(header)\n popup.appendChild(body)\n popup.appendChild(actions)\n\n this.container.appendChild(popup)\n this.popupEl = popup\n\n // Measure after layout, then position\n requestAnimationFrame(() => {\n this.adjustPosition(popup, position)\n })\n\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.hide()\n callbacks.onClose()\n }\n }\n document.addEventListener('keydown', this.keyHandler)\n }\n\n hide(): void {\n if (this.popupEl) {\n this.popupEl.remove()\n this.popupEl = null\n }\n if (this.keyHandler) {\n document.removeEventListener('keydown', this.keyHandler)\n this.keyHandler = null\n }\n }\n\n destroy(): void {\n this.hide()\n }\n\n private adjustPosition(popup: HTMLElement, position: Position): void {\n const popupHeight = popup.offsetHeight\n const viewportBottom = window.scrollY + window.innerHeight\n const viewportRight = window.scrollX + window.innerWidth\n\n let top = position.top\n let left = position.left\n\n // Flip above element if overflows viewport bottom\n if (top + popupHeight > viewportBottom - POPUP_MARGIN) {\n top = position.anchorBottom - popupHeight\n }\n\n // Clamp: don't go above visible area\n if (top < window.scrollY + POPUP_MARGIN) {\n top = window.scrollY + POPUP_MARGIN\n }\n\n // Clamp right edge\n if (left + POPUP_WIDTH > viewportRight - POPUP_MARGIN) {\n left = viewportRight - POPUP_WIDTH - POPUP_MARGIN\n }\n\n // Clamp left edge\n if (left < window.scrollX + POPUP_MARGIN) {\n left = window.scrollX + POPUP_MARGIN\n }\n\n popup.style.top = `${top}px`\n popup.style.left = `${left}px`\n }\n}\n","import type { Annotation } from '../core/types'\n\ninterface MarkerEntry {\n annotation: Annotation\n target: HTMLElement\n markerEl: HTMLElement\n}\n\nexport class MarkerManager {\n private markers = new Map<string, MarkerEntry>()\n private rafId: number | null = null\n private counter = 0\n\n constructor(\n private container: HTMLElement,\n private onClick?: (annotationId: string) => void,\n ) {\n this.startPositionLoop()\n }\n\n addMarker(annotation: Annotation, target: HTMLElement): void {\n this.counter++\n const markerEl = document.createElement('div')\n markerEl.className = 'remarq-marker'\n markerEl.setAttribute('data-status', annotation.status)\n markerEl.setAttribute('data-annotation-id', annotation.id)\n markerEl.textContent = String(this.counter)\n markerEl.title = annotation.comment\n\n markerEl.addEventListener('click', () => {\n this.onClick?.(annotation.id)\n })\n\n this.container.appendChild(markerEl)\n this.markers.set(annotation.id, { annotation, target, markerEl })\n this.updatePosition(annotation.id)\n }\n\n removeMarker(id: string): void {\n const entry = this.markers.get(id)\n if (entry) {\n entry.markerEl.remove()\n this.markers.delete(id)\n }\n }\n\n updateStatus(id: string, status: 'pending' | 'resolved'): void {\n const entry = this.markers.get(id)\n if (entry) {\n entry.annotation.status = status\n entry.markerEl.setAttribute('data-status', status)\n }\n }\n\n clear(): void {\n for (const entry of this.markers.values()) {\n entry.markerEl.remove()\n }\n this.markers.clear()\n this.counter = 0\n }\n\n destroy(): void {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.clear()\n }\n\n private updatePosition(id: string): void {\n const entry = this.markers.get(id)\n if (!entry) return\n try {\n const rect = entry.target.getBoundingClientRect()\n entry.markerEl.style.top = `${window.scrollY + rect.top - 12}px`\n entry.markerEl.style.left = `${window.scrollX + rect.right - 12}px`\n } catch {\n // element may have been removed\n }\n }\n\n private startPositionLoop(): void {\n const update = () => {\n for (const id of this.markers.keys()) {\n this.updatePosition(id)\n }\n this.rafId = requestAnimationFrame(update)\n }\n this.rafId = requestAnimationFrame(update)\n }\n}\n","import type { Annotation } from '../core/types'\n\nexport class DetachedPanel {\n private panelEl: HTMLElement | null = null\n\n constructor(\n private container: HTMLElement,\n private onDelete?: (id: string) => void,\n ) {}\n\n update(annotations: Annotation[]): void {\n this.remove()\n if (annotations.length === 0) return\n\n const panel = document.createElement('div')\n panel.className = 'remarq-detached-panel'\n\n const header = document.createElement('div')\n header.className = 'remarq-detached-header'\n header.textContent = `Detached (${annotations.length})`\n panel.appendChild(header)\n\n for (const ann of annotations) {\n const item = document.createElement('div')\n item.className = 'remarq-detached-item'\n\n const info = document.createElement('div')\n info.className = 'remarq-detached-info'\n\n const comment = document.createElement('div')\n comment.className = 'remarq-detached-comment'\n comment.textContent = ann.comment\n\n const elDesc = document.createElement('div')\n elDesc.className = 'remarq-detached-element'\n const fp = ann.fingerprint\n let desc = `<${fp.tagName}>`\n if (fp.textContent) desc += ` \"${fp.textContent}\"`\n if (fp.dataAnnotate) desc += ` [${fp.dataAnnotate}]`\n elDesc.textContent = desc\n\n info.appendChild(comment)\n info.appendChild(elDesc)\n\n const deleteBtn = document.createElement('button')\n deleteBtn.className = 'remarq-detached-delete'\n deleteBtn.textContent = '\\u00d7'\n deleteBtn.addEventListener('click', () => {\n this.onDelete?.(ann.id)\n })\n\n item.appendChild(info)\n item.appendChild(deleteBtn)\n panel.appendChild(item)\n }\n\n this.container.appendChild(panel)\n this.panelEl = panel\n }\n\n destroy(): void {\n this.remove()\n }\n\n private remove(): void {\n if (this.panelEl) {\n this.panelEl.remove()\n this.panelEl = null\n }\n }\n}\n","type RouteChangeListener = (route: string) => void\n\nexport class RouteObserver {\n private listeners: Set<RouteChangeListener> = new Set()\n private originalPushState: typeof history.pushState\n private originalReplaceState: typeof history.replaceState\n private boundOnPopState: () => void\n private boundOnHashChange: () => void\n\n constructor() {\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n this.boundOnPopState = () => this.notify()\n this.boundOnHashChange = () => this.notify()\n\n this.patchHistory()\n\n window.addEventListener('popstate', this.boundOnPopState)\n window.addEventListener('hashchange', this.boundOnHashChange)\n }\n\n currentRoute(): string {\n return location.pathname + location.hash\n }\n\n onChange(listener: RouteChangeListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n destroy(): void {\n window.removeEventListener('popstate', this.boundOnPopState)\n window.removeEventListener('hashchange', this.boundOnHashChange)\n history.pushState = this.originalPushState\n history.replaceState = this.originalReplaceState\n this.listeners.clear()\n }\n\n private notify(): void {\n const route = this.currentRoute()\n for (const listener of this.listeners) {\n listener(route)\n }\n }\n\n private patchHistory(): void {\n const self = this\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n self.originalPushState.apply(this, args)\n self.notify()\n }\n\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\n self.originalReplaceState.apply(this, args)\n self.notify()\n }\n }\n}\n","import type { Annotation, ImportResult, WebRemarqOptions } from './core/types'\nimport { AnnotationStorage } from './core/storage'\nimport { createFingerprint } from './core/fingerprint'\nimport { matchElement } from './core/matcher'\nimport { injectStyles, removeStyles } from './ui/styles'\nimport { ThemeManager } from './ui/theme'\nimport { Toolbar } from './ui/toolbar'\nimport { Overlay } from './ui/overlay'\nimport { Popup } from './ui/popup'\nimport { MarkerManager } from './ui/markers'\nimport { DetachedPanel } from './ui/detached-panel'\nimport { RouteObserver } from './spa'\n\nlet initialized = false\nlet options: WebRemarqOptions = {}\nlet storage: AnnotationStorage\nlet themeManager: ThemeManager\nlet toolbar: Toolbar\nlet overlay: Overlay\nlet popup: Popup\nlet markers: MarkerManager\nlet detachedPanel: DetachedPanel\nlet routeObserver: RouteObserver\nlet inspecting = false\nlet mutationObserver: MutationObserver | null = null\nlet unsubRoute: (() => void) | null = null\nlet refreshScheduled = false\n\n// WeakRef cache: annotation id → element (survives GC of element)\nconst elementCache = new Map<string, WeakRef<HTMLElement>>()\n\nfunction describeTarget(el: HTMLElement): string {\n const parts: string[] = []\n\n // id\n if (el.id) parts.push(`#${el.id}`)\n\n // data attributes\n const dataAnnotate = el.getAttribute(options.dataAttribute ?? 'data-annotate')\n const dataTestId = el.getAttribute('data-testid') || el.getAttribute('data-test') || el.getAttribute('data-cy')\n if (dataAnnotate) parts.push(`[${dataAnnotate}]`)\n else if (dataTestId) parts.push(`[${dataTestId}]`)\n\n // Meaningful classes (max 2)\n const classes = Array.from(el.classList)\n .filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/))\n .slice(0, 2)\n if (classes.length) parts.push(`.${classes.join('.')}`)\n\n // Direct text only\n let text = ''\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) text += node.textContent ?? ''\n }\n text = text.trim()\n if (!text && el.children.length <= 2) text = el.textContent?.trim() ?? ''\n if (text) parts.push(`\"${text.slice(0, 30)}\"`)\n\n return parts.join(' ') || ''\n}\n\nfunction currentRoute(): string {\n return location.pathname + location.hash\n}\n\nfunction generateId(): string {\n return `ann-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nfunction cacheElement(annotationId: string, el: HTMLElement): void {\n elementCache.set(annotationId, new WeakRef(el))\n}\n\nfunction getCachedElement(annotationId: string): HTMLElement | null {\n const ref = elementCache.get(annotationId)\n if (!ref) return null\n const el = ref.deref()\n if (!el || !el.isConnected) {\n elementCache.delete(annotationId)\n return null\n }\n return el\n}\n\nfunction resolveElement(ann: Annotation): HTMLElement | null {\n // 1. Check cache first\n const cached = getCachedElement(ann.id)\n if (cached) return cached\n\n // 2. Fall back to fingerprint matching\n const el = matchElement(ann.fingerprint, { dataAttribute: options.dataAttribute })\n if (el) {\n cacheElement(ann.id, el)\n console.debug(`[web-remarq] Matched \"${ann.comment}\" via fingerprint on <${el.tagName.toLowerCase()}>`)\n } else {\n console.debug(`[web-remarq] Could not match \"${ann.comment}\"`, ann.fingerprint)\n }\n return el\n}\n\nfunction refreshMarkers(): void {\n markers.clear()\n const detached: Annotation[] = []\n const route = currentRoute()\n const anns = storage.getByRoute(route)\n\n for (const ann of anns) {\n const el = resolveElement(ann)\n if (el) {\n markers.addMarker(ann, el)\n } else {\n detached.push(ann)\n }\n }\n\n detachedPanel.update(detached)\n\n const pendingCount = anns.filter((a) => a.status === 'pending').length\n toolbar.setBadgeCount(pendingCount)\n}\n\n// Debounced refresh — MutationObserver can fire rapidly\nfunction scheduleRefresh(): void {\n if (refreshScheduled) return\n refreshScheduled = true\n requestAnimationFrame(() => {\n refreshScheduled = false\n refreshMarkers()\n })\n}\n\nfunction handleInspectClick(e: MouseEvent): void {\n if (!inspecting) return\n\n const target = e.target as HTMLElement\n if (!target || target.closest('[data-remarq-theme]')) return\n\n e.preventDefault()\n e.stopPropagation()\n\n overlay.hide()\n setInspecting(false)\n\n const rect = target.getBoundingClientRect()\n popup.show(\n {\n tag: target.tagName.toLowerCase(),\n text: describeTarget(target),\n },\n {\n top: window.scrollY + rect.bottom + 8,\n left: window.scrollX + rect.left,\n anchorBottom: window.scrollY + rect.top - 8,\n },\n (comment) => {\n const fp = createFingerprint(target, {\n classFilter: options.classFilter,\n dataAttribute: options.dataAttribute,\n })\n const ann: Annotation = {\n id: generateId(),\n comment,\n fingerprint: fp,\n route: currentRoute(),\n timestamp: Date.now(),\n status: 'pending',\n }\n // Cache the element immediately — no need to re-match\n cacheElement(ann.id, target)\n storage.add(ann)\n refreshMarkers()\n },\n () => {\n // cancel\n },\n )\n}\n\nfunction handleInspectHover(e: MouseEvent): void {\n if (!inspecting) return\n const target = e.target as HTMLElement\n if (!target || target.closest('[data-remarq-theme]')) return\n overlay.show(target)\n overlay.updateTooltipPosition(e.clientX, e.clientY)\n}\n\nfunction handleInspectKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && inspecting) {\n setInspecting(false)\n overlay.hide()\n }\n}\n\nfunction setInspecting(value: boolean): void {\n inspecting = value\n toolbar.setInspectActive(value)\n if (!value) overlay.hide()\n}\n\nfunction handleMarkerClick(annotationId: string): void {\n const ann = storage.getAll().find((a) => a.id === annotationId)\n if (!ann) return\n\n const el = resolveElement(ann)\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n\n popup.showDetail(\n {\n tag: ann.fingerprint.tagName,\n text: ann.fingerprint.textContent ?? '',\n comment: ann.comment,\n status: ann.status,\n },\n {\n top: window.scrollY + rect.bottom + 8,\n left: window.scrollX + rect.left,\n anchorBottom: window.scrollY + rect.top - 8,\n },\n {\n onResolve: () => {\n storage.update(ann.id, { status: 'resolved' })\n refreshMarkers()\n },\n onDelete: () => {\n elementCache.delete(ann.id)\n storage.remove(ann.id)\n refreshMarkers()\n },\n onClose: () => {},\n },\n )\n}\n\nfunction exportMarkdown(): void {\n const route = currentRoute()\n const anns = storage.getByRoute(route)\n if (!anns.length) return\n\n const lines = [`## Annotations — ${route} (${anns.length})`, '']\n anns.forEach((ann, i) => {\n const fp = ann.fingerprint\n let desc = `<${fp.tagName}>`\n if (fp.textContent) desc += ` \"${fp.textContent}\"`\n if (fp.parentAnchor) desc += ` (${fp.parentAnchor})`\n if (fp.dataAnnotate) desc += fp.parentAnchor ? ` > ${fp.dataAnnotate}` : ` (${fp.dataAnnotate})`\n lines.push(`${i + 1}. [${ann.status}] ${desc}: \"${ann.comment}\"`)\n })\n\n const text = lines.join('\\n')\n try {\n navigator.clipboard.writeText(text)\n } catch {\n console.warn('[web-remarq] Clipboard write failed')\n }\n}\n\nfunction exportJSON(): void {\n const data = storage.exportJSON()\n const json = JSON.stringify(data, null, 2)\n const blob = new Blob([json], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `remarq-annotations-${Date.now()}.json`\n a.click()\n URL.revokeObjectURL(url)\n}\n\nfunction setupMutationObserver(): void {\n mutationObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.target instanceof HTMLElement && m.target.closest('[data-remarq-theme]')) return\n }\n scheduleRefresh()\n })\n\n mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['id', 'class', 'data-annotate', 'data-testid', 'data-test', 'data-cy'],\n })\n}\n\nexport const WebRemarq = {\n init(opts?: WebRemarqOptions): void {\n if (initialized) return\n options = opts ?? {}\n\n try {\n injectStyles()\n storage = new AnnotationStorage()\n themeManager = new ThemeManager(document.body, options.theme)\n overlay = new Overlay(themeManager.container)\n popup = new Popup(themeManager.container)\n markers = new MarkerManager(themeManager.container, handleMarkerClick)\n detachedPanel = new DetachedPanel(themeManager.container, (id) => {\n elementCache.delete(id)\n storage.remove(id)\n refreshMarkers()\n })\n\n toolbar = new Toolbar(themeManager.container, {\n onInspect: () => setInspecting(!inspecting),\n onExportMd: exportMarkdown,\n onExportJson: exportJSON,\n onImport: () => {\n const file = toolbar.getFileInput().files?.[0]\n if (file) {\n WebRemarq.import(file)\n }\n },\n onClear: () => {\n elementCache.clear()\n storage.clearAll()\n refreshMarkers()\n },\n onThemeToggle: () => themeManager.toggle(),\n })\n\n if (storage.isMemoryOnly) {\n toolbar.setMemoryWarning(true)\n }\n\n routeObserver = new RouteObserver()\n unsubRoute = routeObserver.onChange(() => refreshMarkers())\n\n document.addEventListener('click', handleInspectClick, true)\n document.addEventListener('mousemove', handleInspectHover)\n document.addEventListener('keydown', handleInspectKeydown)\n\n setupMutationObserver()\n\n console.debug(`[web-remarq] Initialized on route: ${currentRoute()}`)\n refreshMarkers()\n initialized = true\n } catch (err) {\n console.error('[web-remarq] Init failed:', err)\n }\n },\n\n destroy(): void {\n if (!initialized) return\n try {\n document.removeEventListener('click', handleInspectClick, true)\n document.removeEventListener('mousemove', handleInspectHover)\n document.removeEventListener('keydown', handleInspectKeydown)\n mutationObserver?.disconnect()\n mutationObserver = null\n unsubRoute?.()\n routeObserver?.destroy()\n markers?.destroy()\n detachedPanel?.destroy()\n popup?.destroy()\n overlay?.destroy()\n toolbar?.destroy()\n themeManager?.destroy()\n removeStyles()\n elementCache.clear()\n inspecting = false\n initialized = false\n } catch (err) {\n console.error('[web-remarq] Destroy failed:', err)\n }\n },\n\n setTheme(theme: 'light' | 'dark'): void {\n themeManager?.setTheme(theme)\n },\n\n export(format: 'md' | 'json'): void {\n if (format === 'md') exportMarkdown()\n else exportJSON()\n },\n\n async import(file: File): Promise<ImportResult> {\n const text = await file.text()\n const data = JSON.parse(text)\n storage.importJSON(data)\n refreshMarkers()\n\n const allAnns = storage.getAll()\n let matched = 0\n let detached = 0\n for (const ann of allAnns) {\n if (resolveElement(ann)) {\n matched++\n } else {\n detached++\n }\n }\n return { total: allAnns.length, matched, detached }\n },\n\n getAnnotations(route?: string): Annotation[] {\n if (!storage) return []\n return route ? storage.getByRoute(route) : storage.getAll()\n },\n\n clearAll(): void {\n elementCache.clear()\n storage?.clearAll()\n if (initialized) refreshMarkers()\n },\n}\n"],"mappings":"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","names":["options","parent","buildDomPath","options","e","popup"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/storage.ts","../src/core/hash-detect.ts","../src/core/fingerprint.ts","../src/core/matcher.ts","../src/ui/styles.ts","../src/ui/theme.ts","../src/ui/toolbar.ts","../src/ui/overlay.ts","../src/ui/popup.ts","../src/ui/markers.ts","../src/ui/detached-panel.ts","../src/spa.ts","../src/web-remarq.ts"],"sourcesContent":["export { WebRemarq } from './web-remarq'\nexport type { Annotation, AnnotationStore, ElementFingerprint, WebRemarqOptions, ImportResult } from './core/types'\n","import type { Annotation, AnnotationStore } from './types'\n\nconst STORAGE_KEY = 'remarq:annotations'\n\nexport class AnnotationStorage {\n private annotations: Annotation[] = []\n private extraFields: Record<string, unknown> = {}\n isMemoryOnly = false\n\n constructor() {\n this.load()\n }\n\n getAll(): Annotation[] {\n return [...this.annotations]\n }\n\n getByRoute(route: string): Annotation[] {\n return this.annotations.filter((a) => a.route === route)\n }\n\n add(annotation: Annotation): void {\n this.annotations.push(annotation)\n this.save()\n }\n\n remove(id: string): void {\n this.annotations = this.annotations.filter((a) => a.id !== id)\n this.save()\n }\n\n update(id: string, changes: Partial<Annotation>): void {\n const idx = this.annotations.findIndex((a) => a.id === id)\n if (idx !== -1) {\n this.annotations[idx] = { ...this.annotations[idx], ...changes }\n this.save()\n }\n }\n\n clearAll(): void {\n this.annotations = []\n this.save()\n }\n\n exportJSON(): AnnotationStore {\n return {\n version: 1,\n annotations: [...this.annotations],\n }\n }\n\n importJSON(data: AnnotationStore): void {\n this.annotations = [...data.annotations]\n this.save()\n }\n\n private load(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY)\n if (raw) {\n const parsed = JSON.parse(raw)\n const { version, annotations, ...rest } = parsed\n this.annotations = annotations ?? []\n this.extraFields = rest\n }\n } catch {\n this.isMemoryOnly = true\n }\n }\n\n private save(): void {\n if (this.isMemoryOnly) return\n try {\n const data = {\n version: 1,\n ...this.extraFields,\n annotations: this.annotations,\n }\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data))\n } catch {\n this.isMemoryOnly = true\n }\n }\n}\n","const CSS_MODULES_RE = /^(.+)__([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","import type { ElementFingerprint, WebRemarqOptions } from './types'\nimport { filterClasses, isHashedClass } from './hash-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 }\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 parts.unshift(current.tagName.toLowerCase())\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'\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 (+15 scaled)\n if (fp.stableClasses.length > 0) {\n const elClasses = Array.from(el.classList)\n const jaccard = jaccardSimilarity(fp.stableClasses, elClasses)\n score += jaccard * 15\n }\n\n // domPath match (+15 scaled)\n if (fp.domPath) {\n const elPath = buildDomPath(el)\n const pathSim = levenshteinSimilarity(fp.domPath, elPath)\n score += pathSim * 15\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 parts.unshift(current.tagName.toLowerCase())\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","const STYLES_ID = 'data-remarq-styles'\n\nconst CSS = `\n[data-remarq-theme=\"light\"] {\n --remarq-bg: #ffffff;\n --remarq-bg-secondary: #f5f5f5;\n --remarq-text: #1a1a1a;\n --remarq-text-secondary: #666666;\n --remarq-border: #e2e8f0;\n --remarq-accent: #3b82f6;\n --remarq-pending: #f97316;\n --remarq-resolved: #22c55e;\n --remarq-overlay: rgba(59, 130, 246, 0.15);\n --remarq-shadow: 0 4px 12px rgba(0,0,0,0.15);\n}\n\n[data-remarq-theme=\"dark\"] {\n --remarq-bg: #1e1e1e;\n --remarq-bg-secondary: #2a2a2a;\n --remarq-text: #e5e5e5;\n --remarq-text-secondary: #999999;\n --remarq-border: #333333;\n --remarq-accent: #60a5fa;\n --remarq-pending: #fb923c;\n --remarq-resolved: #4ade80;\n --remarq-overlay: rgba(96, 165, 250, 0.15);\n --remarq-shadow: 0 4px 12px rgba(0,0,0,0.4);\n}\n\n.remarq-toolbar {\n position: fixed;\n bottom: 16px;\n right: 16px;\n z-index: 2147483647;\n display: flex;\n gap: 4px;\n padding: 8px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-toolbar.remarq-minimized { padding: 4px; }\n\n.remarq-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--remarq-text);\n cursor: pointer;\n position: relative;\n}\n\n.remarq-toolbar-btn:hover { background: var(--remarq-bg-secondary); }\n.remarq-toolbar-btn.remarq-active { background: var(--remarq-accent); color: #ffffff; }\n\n.remarq-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--remarq-pending);\n color: #ffffff;\n font-size: 10px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.remarq-overlay {\n position: fixed;\n pointer-events: none;\n background: var(--remarq-overlay);\n border: 2px solid var(--remarq-accent);\n border-radius: 2px;\n z-index: 2147483646;\n transition: all 0.05s ease-out;\n}\n\n.remarq-tooltip {\n position: fixed;\n z-index: 2147483647;\n padding: 4px 8px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 12px;\n color: var(--remarq-text);\n box-shadow: var(--remarq-shadow);\n pointer-events: none;\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.remarq-marker {\n position: absolute;\n z-index: 2147483645;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n transition: transform 0.1s ease;\n}\n\n.remarq-marker:hover { transform: scale(1.2); }\n.remarq-marker[data-status=\"pending\"] { background: var(--remarq-pending); }\n.remarq-marker[data-status=\"resolved\"] { background: var(--remarq-resolved); opacity: 0.7; }\n\n.remarq-popup {\n position: absolute;\n z-index: 2147483647;\n width: 300px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-popup-header {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n font-size: 12px;\n color: var(--remarq-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.remarq-popup-body { padding: 12px; }\n\n.remarq-popup textarea {\n width: 100%;\n min-height: 60px;\n padding: 8px;\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n background: var(--remarq-bg-secondary);\n color: var(--remarq-text);\n font-family: inherit;\n font-size: 13px;\n resize: vertical;\n box-sizing: border-box;\n}\n\n.remarq-popup textarea:focus { outline: none; border-color: var(--remarq-accent); }\n\n.remarq-popup-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n border-top: 1px solid var(--remarq-border);\n}\n\n.remarq-popup-actions button {\n padding: 4px 12px;\n border: 1px solid var(--remarq-border);\n border-radius: 4px;\n background: var(--remarq-bg);\n color: var(--remarq-text);\n cursor: pointer;\n font-size: 12px;\n}\n\n.remarq-popup-actions button.remarq-primary {\n background: var(--remarq-accent);\n border-color: var(--remarq-accent);\n color: #ffffff;\n}\n\n.remarq-detached-panel {\n position: fixed;\n bottom: 60px;\n right: 16px;\n z-index: 2147483646;\n width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 8px;\n box-shadow: var(--remarq-shadow);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--remarq-text);\n}\n\n.remarq-detached-header {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n font-weight: 600;\n font-size: 12px;\n color: var(--remarq-text-secondary);\n}\n\n.remarq-detached-item {\n padding: 8px 12px;\n border-bottom: 1px solid var(--remarq-border);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n}\n\n.remarq-detached-item:last-child { border-bottom: none; }\n.remarq-detached-info { flex: 1; min-width: 0; }\n.remarq-detached-comment { margin-bottom: 4px; }\n\n.remarq-detached-element {\n font-size: 11px;\n color: var(--remarq-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.remarq-detached-delete {\n border: none;\n background: none;\n color: var(--remarq-text-secondary);\n cursor: pointer;\n padding: 2px;\n font-size: 14px;\n line-height: 1;\n flex-shrink: 0;\n}\n\n.remarq-detached-delete:hover { color: #ef4444; }\n\n.remarq-export-menu {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 4px;\n background: var(--remarq-bg);\n border: 1px solid var(--remarq-border);\n border-radius: 6px;\n box-shadow: var(--remarq-shadow);\n overflow: hidden;\n}\n\n.remarq-export-menu button {\n display: block;\n width: 100%;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--remarq-text);\n cursor: pointer;\n font-size: 12px;\n text-align: left;\n white-space: nowrap;\n}\n\n.remarq-export-menu button:hover { background: var(--remarq-bg-secondary); }\n`\n\nexport function injectStyles(): void {\n if (document.querySelector(`style[${STYLES_ID}]`)) return\n\n try {\n const style = document.createElement('style')\n style.setAttribute(STYLES_ID, '')\n style.textContent = CSS\n document.head.appendChild(style)\n } catch {\n // CSP fallback: try blob URL via <link>\n try {\n const blob = new Blob([CSS], { type: 'text/css' })\n const link = document.createElement('link')\n link.rel = 'stylesheet'\n link.href = URL.createObjectURL(blob)\n link.setAttribute(STYLES_ID, '')\n document.head.appendChild(link)\n } catch {\n console.warn('[web-remarq] Could not inject styles')\n }\n }\n}\n\nexport function removeStyles(): void {\n const el = document.querySelector(`[${STYLES_ID}]`)\n el?.remove()\n}\n","const THEME_KEY = 'remarq:theme'\n\nexport type Theme = 'light' | 'dark'\n\nexport class ThemeManager {\n container: HTMLElement\n private theme: Theme\n\n constructor(parent: HTMLElement, initialTheme?: Theme) {\n const persisted = this.loadTheme()\n this.theme = initialTheme ?? persisted ?? 'light'\n\n this.container = document.createElement('div')\n this.container.setAttribute('data-remarq-theme', this.theme)\n parent.appendChild(this.container)\n\n this.persist()\n }\n\n getTheme(): Theme {\n return this.theme\n }\n\n setTheme(theme: Theme): void {\n this.theme = theme\n this.container.setAttribute('data-remarq-theme', theme)\n this.persist()\n }\n\n toggle(): void {\n this.setTheme(this.theme === 'light' ? 'dark' : 'light')\n }\n\n destroy(): void {\n this.container.remove()\n }\n\n private persist(): void {\n try {\n localStorage.setItem(THEME_KEY, this.theme)\n } catch {\n // ignore\n }\n }\n\n private loadTheme(): Theme | null {\n try {\n const value = localStorage.getItem(THEME_KEY)\n if (value === 'light' || value === 'dark') return value\n } catch {\n // ignore\n }\n return null\n }\n}\n","export interface ToolbarCallbacks {\n onInspect: () => void\n onExportMd: () => void\n onExportJson: () => void\n onImport: () => void\n onClear: () => void\n onThemeToggle: () => void\n}\n\nconst ICONS = {\n inspect: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"7\" cy=\"7\" r=\"4\"/><line x1=\"10\" y1=\"10\" x2=\"14\" y2=\"14\"/></svg>',\n export: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M8 2v8M4 6l4-4 4 4M2 12h12\"/></svg>',\n import: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M8 10V2M4 6l4 4 4-4M2 12h12\"/></svg>',\n clear: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M3 4h10M6 4V3h4v1M5 4v9h6V4\"/></svg>',\n theme: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"8\" cy=\"8\" r=\"3\"/><path d=\"M8 1v2M8 13v2M1 8h2M13 8h2\"/></svg>',\n minimize: '<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M4 8h8\"/></svg>',\n}\n\nexport class Toolbar {\n private toolbarEl: HTMLElement\n private badgeEl: HTMLElement\n private inspectBtn: HTMLElement\n private exportMenu: HTMLElement | null = null\n private fileInput: HTMLInputElement\n private minimized = false\n private buttons: HTMLElement[] = []\n\n constructor(\n private container: HTMLElement,\n private callbacks: ToolbarCallbacks,\n ) {\n this.toolbarEl = document.createElement('div')\n this.toolbarEl.className = 'remarq-toolbar'\n\n this.inspectBtn = this.createButton('inspect', ICONS.inspect, () => callbacks.onInspect())\n this.badgeEl = document.createElement('span')\n this.badgeEl.className = 'remarq-badge'\n this.badgeEl.style.display = 'none'\n this.inspectBtn.appendChild(this.badgeEl)\n\n const exportBtn = this.createButton('export', ICONS.export, (e) => this.toggleExportMenu(e))\n\n this.fileInput = document.createElement('input')\n this.fileInput.type = 'file'\n this.fileInput.accept = '.json'\n this.fileInput.style.display = 'none'\n this.fileInput.addEventListener('change', () => {\n callbacks.onImport()\n this.fileInput.value = ''\n })\n const importBtn = this.createButton('import', ICONS.import, () => this.fileInput.click())\n\n const clearBtn = this.createButton('clear', ICONS.clear, () => callbacks.onClear())\n const themeBtn = this.createButton('theme', ICONS.theme, () => callbacks.onThemeToggle())\n const minimizeBtn = this.createButton('minimize', ICONS.minimize, () => this.toggleMinimize())\n\n this.buttons = [this.inspectBtn, exportBtn, importBtn, clearBtn, themeBtn]\n\n this.toolbarEl.appendChild(this.inspectBtn)\n this.toolbarEl.appendChild(exportBtn)\n this.toolbarEl.appendChild(importBtn)\n this.toolbarEl.appendChild(clearBtn)\n this.toolbarEl.appendChild(themeBtn)\n this.toolbarEl.appendChild(minimizeBtn)\n this.toolbarEl.appendChild(this.fileInput)\n\n container.appendChild(this.toolbarEl)\n }\n\n setInspectActive(active: boolean): void {\n this.inspectBtn.classList.toggle('remarq-active', active)\n }\n\n setBadgeCount(count: number): void {\n this.badgeEl.textContent = String(count)\n this.badgeEl.style.display = count > 0 ? 'flex' : 'none'\n }\n\n getFileInput(): HTMLInputElement {\n return this.fileInput\n }\n\n setMemoryWarning(show: boolean): void {\n this.toolbarEl.title = show ? 'localStorage unavailable — annotations stored in memory only' : ''\n }\n\n destroy(): void {\n this.closeExportMenu()\n this.toolbarEl.remove()\n }\n\n private createButton(action: string, icon: string, handler: (e: Event) => void): HTMLElement {\n const btn = document.createElement('button')\n btn.className = 'remarq-toolbar-btn'\n btn.setAttribute('data-remarq-action', action)\n btn.innerHTML = icon\n btn.addEventListener('click', handler)\n return btn\n }\n\n private toggleMinimize(): void {\n this.minimized = !this.minimized\n this.toolbarEl.classList.toggle('remarq-minimized', this.minimized)\n for (const btn of this.buttons) {\n btn.style.display = this.minimized ? 'none' : ''\n }\n }\n\n private toggleExportMenu(e: Event): void {\n if (this.exportMenu) {\n this.closeExportMenu()\n return\n }\n\n this.exportMenu = document.createElement('div')\n this.exportMenu.className = 'remarq-export-menu'\n\n const mdBtn = document.createElement('button')\n mdBtn.textContent = 'Markdown (file)'\n mdBtn.addEventListener('click', () => {\n this.callbacks.onExportMd()\n this.closeExportMenu()\n })\n\n const jsonBtn = document.createElement('button')\n jsonBtn.textContent = 'JSON (clipboard)'\n jsonBtn.addEventListener('click', () => {\n this.callbacks.onExportJson()\n this.closeExportMenu()\n })\n\n this.exportMenu.appendChild(mdBtn)\n this.exportMenu.appendChild(jsonBtn)\n\n const exportBtn = (e.currentTarget as HTMLElement)\n exportBtn.style.position = 'relative'\n exportBtn.appendChild(this.exportMenu)\n }\n\n private closeExportMenu(): void {\n if (this.exportMenu) {\n this.exportMenu.remove()\n this.exportMenu = null\n }\n }\n}\n","export class Overlay {\n private overlayEl: HTMLElement\n private tooltipEl: HTMLElement\n\n constructor(private container: HTMLElement) {\n this.overlayEl = document.createElement('div')\n this.overlayEl.className = 'remarq-overlay'\n this.overlayEl.style.display = 'none'\n\n this.tooltipEl = document.createElement('div')\n this.tooltipEl.className = 'remarq-tooltip'\n this.tooltipEl.style.display = 'none'\n\n container.appendChild(this.overlayEl)\n container.appendChild(this.tooltipEl)\n }\n\n show(target: HTMLElement): void {\n try {\n const rect = target.getBoundingClientRect()\n\n this.overlayEl.style.display = 'block'\n this.overlayEl.style.top = `${rect.top}px`\n this.overlayEl.style.left = `${rect.left}px`\n this.overlayEl.style.width = `${rect.width}px`\n this.overlayEl.style.height = `${rect.height}px`\n\n this.tooltipEl.textContent = describeElement(target)\n this.tooltipEl.style.display = 'block'\n this.tooltipEl.style.top = `${rect.top - 28}px`\n this.tooltipEl.style.left = `${rect.left}px`\n } catch {\n this.hide()\n }\n }\n\n updateTooltipPosition(x: number, y: number): void {\n this.tooltipEl.style.left = `${x + 12}px`\n this.tooltipEl.style.top = `${y - 28}px`\n }\n\n hide(): void {\n this.overlayEl.style.display = 'none'\n this.tooltipEl.style.display = 'none'\n }\n\n destroy(): void {\n this.overlayEl.remove()\n this.tooltipEl.remove()\n }\n}\n\nfunction describeElement(el: HTMLElement): string {\n const tag = el.tagName.toLowerCase()\n const parts: string[] = [`<${tag}>`]\n\n // data-annotate or data-testid\n const dataAnnotate = el.getAttribute('data-annotate')\n const dataTestId = el.getAttribute('data-testid') || el.getAttribute('data-test') || el.getAttribute('data-cy')\n if (dataAnnotate) {\n parts.push(`[${dataAnnotate}]`)\n } else if (dataTestId) {\n parts.push(`[${dataTestId}]`)\n }\n\n // id\n if (el.id) {\n parts.push(`#${el.id}`)\n }\n\n // Meaningful classes (skip hashed ones, max 2)\n const classes = Array.from(el.classList)\n .filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/))\n .slice(0, 2)\n if (classes.length) {\n parts.push(`.${classes.join('.')}`)\n }\n\n // Direct text content only (not nested)\n const directText = getDirectText(el)\n if (directText) {\n parts.push(`\"${directText}\"`)\n }\n\n return parts.join(' ')\n}\n\nfunction getDirectText(el: HTMLElement): string {\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 // Fallback: if no direct text and few children, use shallow textContent\n if (!text && el.children.length <= 2) {\n text = el.textContent?.trim() ?? ''\n }\n\n return text.slice(0, 30)\n}\n","interface ElementInfo {\n tag: string\n text: string\n}\n\ninterface DetailInfo extends ElementInfo {\n comment: string\n status: 'pending' | 'resolved'\n}\n\ninterface DetailCallbacks {\n onResolve: () => void\n onDelete: () => void\n onClose: () => void\n}\n\ninterface Position {\n top: number // absolute page Y below the element\n left: number // absolute page X\n anchorBottom: number // absolute page Y above the element (for flipping)\n}\n\nconst POPUP_WIDTH = 300\nconst POPUP_MARGIN = 8\n\nexport class Popup {\n private popupEl: HTMLElement | null = null\n private keyHandler: ((e: KeyboardEvent) => void) | null = null\n\n constructor(private container: HTMLElement) {}\n\n show(\n info: ElementInfo,\n position: Position,\n onSubmit: (comment: string) => void,\n onCancel: () => void,\n ): void {\n this.hide()\n\n const popup = document.createElement('div')\n popup.className = 'remarq-popup'\n\n const header = document.createElement('div')\n header.className = 'remarq-popup-header'\n header.textContent = `<${info.tag}>${info.text ? ` \"${info.text}\"` : ''}`\n\n const body = document.createElement('div')\n body.className = 'remarq-popup-body'\n\n const textarea = document.createElement('textarea')\n textarea.placeholder = 'Add your comment...'\n\n body.appendChild(textarea)\n\n const actions = document.createElement('div')\n actions.className = 'remarq-popup-actions'\n\n const cancelBtn = document.createElement('button')\n cancelBtn.textContent = 'Cancel'\n cancelBtn.addEventListener('click', () => {\n this.hide()\n onCancel()\n })\n\n const addBtn = document.createElement('button')\n addBtn.className = 'remarq-primary'\n addBtn.textContent = 'Add'\n addBtn.addEventListener('click', () => {\n const comment = textarea.value.trim()\n if (!comment) return\n this.hide()\n onSubmit(comment)\n })\n\n actions.appendChild(cancelBtn)\n actions.appendChild(addBtn)\n\n popup.appendChild(header)\n popup.appendChild(body)\n popup.appendChild(actions)\n\n this.container.appendChild(popup)\n this.popupEl = popup\n\n // Measure after layout, then position\n requestAnimationFrame(() => {\n this.adjustPosition(popup, position)\n textarea.focus()\n })\n\n // Cmd/Ctrl+Enter to submit\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n const comment = textarea.value.trim()\n if (!comment) return\n this.hide()\n onSubmit(comment)\n }\n if (e.key === 'Escape') {\n this.hide()\n onCancel()\n }\n }\n document.addEventListener('keydown', this.keyHandler)\n }\n\n showDetail(\n info: DetailInfo,\n position: Position,\n callbacks: DetailCallbacks,\n ): void {\n this.hide()\n\n const popup = document.createElement('div')\n popup.className = 'remarq-popup'\n\n const header = document.createElement('div')\n header.className = 'remarq-popup-header'\n header.textContent = `<${info.tag}>${info.text ? ` \"${info.text}\"` : ''} [${info.status}]`\n\n const body = document.createElement('div')\n body.className = 'remarq-popup-body'\n body.textContent = info.comment\n\n const actions = document.createElement('div')\n actions.className = 'remarq-popup-actions'\n\n if (info.status === 'pending') {\n const resolveBtn = document.createElement('button')\n resolveBtn.className = 'remarq-primary'\n resolveBtn.textContent = 'Resolve'\n resolveBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onResolve()\n })\n actions.appendChild(resolveBtn)\n }\n\n const deleteBtn = document.createElement('button')\n deleteBtn.textContent = 'Delete'\n deleteBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onDelete()\n })\n actions.appendChild(deleteBtn)\n\n const closeBtn = document.createElement('button')\n closeBtn.textContent = 'Close'\n closeBtn.addEventListener('click', () => {\n this.hide()\n callbacks.onClose()\n })\n actions.appendChild(closeBtn)\n\n popup.appendChild(header)\n popup.appendChild(body)\n popup.appendChild(actions)\n\n this.container.appendChild(popup)\n this.popupEl = popup\n\n // Measure after layout, then position\n requestAnimationFrame(() => {\n this.adjustPosition(popup, position)\n })\n\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.hide()\n callbacks.onClose()\n }\n }\n document.addEventListener('keydown', this.keyHandler)\n }\n\n hide(): void {\n if (this.popupEl) {\n this.popupEl.remove()\n this.popupEl = null\n }\n if (this.keyHandler) {\n document.removeEventListener('keydown', this.keyHandler)\n this.keyHandler = null\n }\n }\n\n destroy(): void {\n this.hide()\n }\n\n private adjustPosition(popup: HTMLElement, position: Position): void {\n const popupHeight = popup.offsetHeight\n const viewportBottom = window.scrollY + window.innerHeight\n const viewportRight = window.scrollX + window.innerWidth\n\n let top = position.top\n let left = position.left\n\n // Flip above element if overflows viewport bottom\n if (top + popupHeight > viewportBottom - POPUP_MARGIN) {\n top = position.anchorBottom - popupHeight\n }\n\n // Clamp: don't go above visible area\n if (top < window.scrollY + POPUP_MARGIN) {\n top = window.scrollY + POPUP_MARGIN\n }\n\n // Clamp right edge\n if (left + POPUP_WIDTH > viewportRight - POPUP_MARGIN) {\n left = viewportRight - POPUP_WIDTH - POPUP_MARGIN\n }\n\n // Clamp left edge\n if (left < window.scrollX + POPUP_MARGIN) {\n left = window.scrollX + POPUP_MARGIN\n }\n\n popup.style.top = `${top}px`\n popup.style.left = `${left}px`\n }\n}\n","import type { Annotation } from '../core/types'\n\ninterface MarkerEntry {\n annotation: Annotation\n target: HTMLElement\n markerEl: HTMLElement\n}\n\nexport class MarkerManager {\n private markers = new Map<string, MarkerEntry>()\n private rafId: number | null = null\n private counter = 0\n\n constructor(\n private container: HTMLElement,\n private onClick?: (annotationId: string) => void,\n ) {\n this.startPositionLoop()\n }\n\n addMarker(annotation: Annotation, target: HTMLElement): void {\n this.counter++\n const markerEl = document.createElement('div')\n markerEl.className = 'remarq-marker'\n markerEl.setAttribute('data-status', annotation.status)\n markerEl.setAttribute('data-annotation-id', annotation.id)\n markerEl.textContent = String(this.counter)\n markerEl.title = annotation.comment\n\n markerEl.addEventListener('click', () => {\n this.onClick?.(annotation.id)\n })\n\n this.container.appendChild(markerEl)\n this.markers.set(annotation.id, { annotation, target, markerEl })\n this.updatePosition(annotation.id)\n }\n\n removeMarker(id: string): void {\n const entry = this.markers.get(id)\n if (entry) {\n entry.markerEl.remove()\n this.markers.delete(id)\n }\n }\n\n updateStatus(id: string, status: 'pending' | 'resolved'): void {\n const entry = this.markers.get(id)\n if (entry) {\n entry.annotation.status = status\n entry.markerEl.setAttribute('data-status', status)\n }\n }\n\n clear(): void {\n for (const entry of this.markers.values()) {\n entry.markerEl.remove()\n }\n this.markers.clear()\n this.counter = 0\n }\n\n destroy(): void {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n this.clear()\n }\n\n private updatePosition(id: string): void {\n const entry = this.markers.get(id)\n if (!entry) return\n try {\n const rect = entry.target.getBoundingClientRect()\n entry.markerEl.style.top = `${window.scrollY + rect.top - 12}px`\n entry.markerEl.style.left = `${window.scrollX + rect.right - 12}px`\n } catch {\n // element may have been removed\n }\n }\n\n private startPositionLoop(): void {\n const update = () => {\n for (const id of this.markers.keys()) {\n this.updatePosition(id)\n }\n this.rafId = requestAnimationFrame(update)\n }\n this.rafId = requestAnimationFrame(update)\n }\n}\n","import type { Annotation } from '../core/types'\n\nexport class DetachedPanel {\n private panelEl: HTMLElement | null = null\n\n constructor(\n private container: HTMLElement,\n private onDelete?: (id: string) => void,\n ) {}\n\n update(annotations: Annotation[]): void {\n this.remove()\n if (annotations.length === 0) return\n\n const panel = document.createElement('div')\n panel.className = 'remarq-detached-panel'\n\n const header = document.createElement('div')\n header.className = 'remarq-detached-header'\n header.textContent = `Detached (${annotations.length})`\n panel.appendChild(header)\n\n for (const ann of annotations) {\n const item = document.createElement('div')\n item.className = 'remarq-detached-item'\n\n const info = document.createElement('div')\n info.className = 'remarq-detached-info'\n\n const comment = document.createElement('div')\n comment.className = 'remarq-detached-comment'\n comment.textContent = ann.comment\n\n const elDesc = document.createElement('div')\n elDesc.className = 'remarq-detached-element'\n const fp = ann.fingerprint\n let desc = `<${fp.tagName}>`\n if (fp.textContent) desc += ` \"${fp.textContent}\"`\n if (fp.dataAnnotate) desc += ` [${fp.dataAnnotate}]`\n elDesc.textContent = desc\n\n info.appendChild(comment)\n info.appendChild(elDesc)\n\n const deleteBtn = document.createElement('button')\n deleteBtn.className = 'remarq-detached-delete'\n deleteBtn.textContent = '\\u00d7'\n deleteBtn.addEventListener('click', () => {\n this.onDelete?.(ann.id)\n })\n\n item.appendChild(info)\n item.appendChild(deleteBtn)\n panel.appendChild(item)\n }\n\n this.container.appendChild(panel)\n this.panelEl = panel\n }\n\n destroy(): void {\n this.remove()\n }\n\n private remove(): void {\n if (this.panelEl) {\n this.panelEl.remove()\n this.panelEl = null\n }\n }\n}\n","type RouteChangeListener = (route: string) => void\n\nexport class RouteObserver {\n private listeners: Set<RouteChangeListener> = new Set()\n private originalPushState: typeof history.pushState\n private originalReplaceState: typeof history.replaceState\n private boundOnPopState: () => void\n private boundOnHashChange: () => void\n\n constructor() {\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n this.boundOnPopState = () => this.notify()\n this.boundOnHashChange = () => this.notify()\n\n this.patchHistory()\n\n window.addEventListener('popstate', this.boundOnPopState)\n window.addEventListener('hashchange', this.boundOnHashChange)\n }\n\n currentRoute(): string {\n return location.pathname + location.hash\n }\n\n onChange(listener: RouteChangeListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n destroy(): void {\n window.removeEventListener('popstate', this.boundOnPopState)\n window.removeEventListener('hashchange', this.boundOnHashChange)\n history.pushState = this.originalPushState\n history.replaceState = this.originalReplaceState\n this.listeners.clear()\n }\n\n private notify(): void {\n const route = this.currentRoute()\n for (const listener of this.listeners) {\n listener(route)\n }\n }\n\n private patchHistory(): void {\n const self = this\n\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n self.originalPushState.apply(this, args)\n self.notify()\n }\n\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\n self.originalReplaceState.apply(this, args)\n self.notify()\n }\n }\n}\n","import type { Annotation, ImportResult, WebRemarqOptions } from './core/types'\nimport { AnnotationStorage } from './core/storage'\nimport { createFingerprint } from './core/fingerprint'\nimport { matchElement } from './core/matcher'\nimport { injectStyles, removeStyles } from './ui/styles'\nimport { ThemeManager } from './ui/theme'\nimport { Toolbar } from './ui/toolbar'\nimport { Overlay } from './ui/overlay'\nimport { Popup } from './ui/popup'\nimport { MarkerManager } from './ui/markers'\nimport { DetachedPanel } from './ui/detached-panel'\nimport { RouteObserver } from './spa'\n\nlet initialized = false\nlet options: WebRemarqOptions = {}\nlet storage: AnnotationStorage\nlet themeManager: ThemeManager\nlet toolbar: Toolbar\nlet overlay: Overlay\nlet popup: Popup\nlet markers: MarkerManager\nlet detachedPanel: DetachedPanel\nlet routeObserver: RouteObserver\nlet inspecting = false\nlet mutationObserver: MutationObserver | null = null\nlet unsubRoute: (() => void) | null = null\nlet refreshScheduled = false\n\n// WeakRef cache: annotation id → element (survives GC of element)\nconst elementCache = new Map<string, WeakRef<HTMLElement>>()\n\nfunction describeTarget(el: HTMLElement): string {\n const parts: string[] = []\n\n // id\n if (el.id) parts.push(`#${el.id}`)\n\n // data attributes\n const dataAnnotate = el.getAttribute(options.dataAttribute ?? 'data-annotate')\n const dataTestId = el.getAttribute('data-testid') || el.getAttribute('data-test') || el.getAttribute('data-cy')\n if (dataAnnotate) parts.push(`[${dataAnnotate}]`)\n else if (dataTestId) parts.push(`[${dataTestId}]`)\n\n // Meaningful classes (max 2)\n const classes = Array.from(el.classList)\n .filter((c) => !c.match(/^(sc-|css-)/) && !c.match(/^[a-zA-Z0-9]{8,}$/) && !c.match(/__[a-zA-Z0-9]{3,}$/))\n .slice(0, 2)\n if (classes.length) parts.push(`.${classes.join('.')}`)\n\n // Direct text only\n let text = ''\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) text += node.textContent ?? ''\n }\n text = text.trim()\n if (!text && el.children.length <= 2) text = el.textContent?.trim() ?? ''\n if (text) parts.push(`\"${text.slice(0, 30)}\"`)\n\n return parts.join(' ') || ''\n}\n\nfunction currentRoute(): string {\n return location.pathname + location.hash\n}\n\nfunction generateId(): string {\n return `ann-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nfunction cacheElement(annotationId: string, el: HTMLElement): void {\n elementCache.set(annotationId, new WeakRef(el))\n}\n\nfunction getCachedElement(annotationId: string): HTMLElement | null {\n const ref = elementCache.get(annotationId)\n if (!ref) return null\n const el = ref.deref()\n if (!el || !el.isConnected) {\n elementCache.delete(annotationId)\n return null\n }\n return el\n}\n\nfunction resolveElement(ann: Annotation): HTMLElement | null {\n // 1. Check cache first\n const cached = getCachedElement(ann.id)\n if (cached) return cached\n\n // 2. Fall back to fingerprint matching\n const el = matchElement(ann.fingerprint, { dataAttribute: options.dataAttribute })\n if (el) {\n cacheElement(ann.id, el)\n console.debug(`[web-remarq] Matched \"${ann.comment}\" via fingerprint on <${el.tagName.toLowerCase()}>`)\n } else {\n console.debug(`[web-remarq] Could not match \"${ann.comment}\"`, ann.fingerprint)\n }\n return el\n}\n\nfunction refreshMarkers(): void {\n markers.clear()\n const detached: Annotation[] = []\n const route = currentRoute()\n const anns = storage.getByRoute(route)\n\n for (const ann of anns) {\n const el = resolveElement(ann)\n if (el) {\n markers.addMarker(ann, el)\n } else {\n detached.push(ann)\n }\n }\n\n detachedPanel.update(detached)\n\n const pendingCount = anns.filter((a) => a.status === 'pending').length\n toolbar.setBadgeCount(pendingCount)\n}\n\n// Debounced refresh — MutationObserver can fire rapidly\nfunction scheduleRefresh(): void {\n if (refreshScheduled) return\n refreshScheduled = true\n requestAnimationFrame(() => {\n refreshScheduled = false\n refreshMarkers()\n })\n}\n\nfunction handleInspectClick(e: MouseEvent): void {\n if (!inspecting) return\n\n const target = e.target as HTMLElement\n if (!target || target.closest('[data-remarq-theme]')) return\n\n e.preventDefault()\n e.stopPropagation()\n\n overlay.hide()\n setInspecting(false)\n\n const rect = target.getBoundingClientRect()\n popup.show(\n {\n tag: target.tagName.toLowerCase(),\n text: describeTarget(target),\n },\n {\n top: window.scrollY + rect.bottom + 8,\n left: window.scrollX + rect.left,\n anchorBottom: window.scrollY + rect.top - 8,\n },\n (comment) => {\n const fp = createFingerprint(target, {\n classFilter: options.classFilter,\n dataAttribute: options.dataAttribute,\n })\n const ann: Annotation = {\n id: generateId(),\n comment,\n fingerprint: fp,\n route: currentRoute(),\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n timestamp: Date.now(),\n status: 'pending',\n }\n // Cache the element immediately — no need to re-match\n cacheElement(ann.id, target)\n storage.add(ann)\n refreshMarkers()\n },\n () => {\n // cancel\n },\n )\n}\n\nfunction handleInspectHover(e: MouseEvent): void {\n if (!inspecting) return\n const target = e.target as HTMLElement\n if (!target || target.closest('[data-remarq-theme]')) return\n overlay.show(target)\n overlay.updateTooltipPosition(e.clientX, e.clientY)\n}\n\nfunction handleInspectKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape' && inspecting) {\n setInspecting(false)\n overlay.hide()\n }\n}\n\nfunction setInspecting(value: boolean): void {\n inspecting = value\n toolbar.setInspectActive(value)\n if (!value) overlay.hide()\n}\n\nfunction handleMarkerClick(annotationId: string): void {\n const ann = storage.getAll().find((a) => a.id === annotationId)\n if (!ann) return\n\n const el = resolveElement(ann)\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n\n popup.showDetail(\n {\n tag: ann.fingerprint.tagName,\n text: ann.fingerprint.textContent ?? '',\n comment: ann.comment,\n status: ann.status,\n },\n {\n top: window.scrollY + rect.bottom + 8,\n left: window.scrollX + rect.left,\n anchorBottom: window.scrollY + rect.top - 8,\n },\n {\n onResolve: () => {\n storage.update(ann.id, { status: 'resolved' })\n refreshMarkers()\n },\n onDelete: () => {\n elementCache.delete(ann.id)\n storage.remove(ann.id)\n refreshMarkers()\n },\n onClose: () => {},\n },\n )\n}\n\nfunction exportMarkdown(): void {\n const route = currentRoute()\n const anns = storage.getByRoute(route)\n if (!anns.length) return\n\n const lines = [`## Annotations — ${route} (${anns.length})`, '']\n anns.forEach((ann, i) => {\n const fp = ann.fingerprint\n let desc = `<${fp.tagName}>`\n if (fp.textContent) desc += ` \"${fp.textContent}\"`\n if (fp.parentAnchor) desc += ` (${fp.parentAnchor})`\n if (fp.dataAnnotate) desc += fp.parentAnchor ? ` > ${fp.dataAnnotate}` : ` (${fp.dataAnnotate})`\n const viewport = ann.viewport ? ` @${ann.viewport}` : ''\n lines.push(`${i + 1}. [${ann.status}]${viewport} ${desc}: \"${ann.comment}\"`)\n })\n\n const text = lines.join('\\n')\n const blob = new Blob([text], { type: 'text/markdown' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `remarq-annotations-${Date.now()}.md`\n a.click()\n URL.revokeObjectURL(url)\n}\n\nfunction exportJSON(): void {\n const data = storage.exportJSON()\n const json = JSON.stringify(data, null, 2)\n try {\n navigator.clipboard.writeText(json)\n } catch {\n console.warn('[web-remarq] Clipboard write failed')\n }\n}\n\nfunction setupMutationObserver(): void {\n mutationObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.target instanceof HTMLElement && m.target.closest('[data-remarq-theme]')) return\n }\n scheduleRefresh()\n })\n\n mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['id', 'class', 'data-annotate', 'data-testid', 'data-test', 'data-cy'],\n })\n}\n\nexport const WebRemarq = {\n init(opts?: WebRemarqOptions): void {\n if (initialized) return\n options = opts ?? {}\n\n try {\n injectStyles()\n storage = new AnnotationStorage()\n themeManager = new ThemeManager(document.body, options.theme)\n overlay = new Overlay(themeManager.container)\n popup = new Popup(themeManager.container)\n markers = new MarkerManager(themeManager.container, handleMarkerClick)\n detachedPanel = new DetachedPanel(themeManager.container, (id) => {\n elementCache.delete(id)\n storage.remove(id)\n refreshMarkers()\n })\n\n toolbar = new Toolbar(themeManager.container, {\n onInspect: () => setInspecting(!inspecting),\n onExportMd: exportMarkdown,\n onExportJson: exportJSON,\n onImport: () => {\n const file = toolbar.getFileInput().files?.[0]\n if (file) {\n WebRemarq.import(file)\n }\n },\n onClear: () => {\n elementCache.clear()\n storage.clearAll()\n refreshMarkers()\n },\n onThemeToggle: () => themeManager.toggle(),\n })\n\n if (storage.isMemoryOnly) {\n toolbar.setMemoryWarning(true)\n }\n\n routeObserver = new RouteObserver()\n unsubRoute = routeObserver.onChange(() => refreshMarkers())\n\n document.addEventListener('click', handleInspectClick, true)\n document.addEventListener('mousemove', handleInspectHover)\n document.addEventListener('keydown', handleInspectKeydown)\n\n setupMutationObserver()\n\n console.debug(`[web-remarq] Initialized on route: ${currentRoute()}`)\n refreshMarkers()\n initialized = true\n } catch (err) {\n console.error('[web-remarq] Init failed:', err)\n }\n },\n\n destroy(): void {\n if (!initialized) return\n try {\n document.removeEventListener('click', handleInspectClick, true)\n document.removeEventListener('mousemove', handleInspectHover)\n document.removeEventListener('keydown', handleInspectKeydown)\n mutationObserver?.disconnect()\n mutationObserver = null\n unsubRoute?.()\n routeObserver?.destroy()\n markers?.destroy()\n detachedPanel?.destroy()\n popup?.destroy()\n overlay?.destroy()\n toolbar?.destroy()\n themeManager?.destroy()\n removeStyles()\n elementCache.clear()\n inspecting = false\n initialized = false\n } catch (err) {\n console.error('[web-remarq] Destroy failed:', err)\n }\n },\n\n setTheme(theme: 'light' | 'dark'): void {\n themeManager?.setTheme(theme)\n },\n\n export(format: 'md' | 'json'): void {\n if (format === 'md') exportMarkdown()\n else exportJSON()\n },\n\n async import(file: File): Promise<ImportResult> {\n const text = await file.text()\n const data = JSON.parse(text)\n storage.importJSON(data)\n refreshMarkers()\n\n const allAnns = storage.getAll()\n let matched = 0\n let detached = 0\n for (const ann of allAnns) {\n if (resolveElement(ann)) {\n matched++\n } else {\n detached++\n }\n }\n return { total: allAnns.length, matched, detached }\n },\n\n getAnnotations(route?: string): Annotation[] {\n if (!storage) return []\n return route ? storage.getByRoute(route) : storage.getAll()\n },\n\n clearAll(): void {\n elementCache.clear()\n storage?.clearAll()\n if (initialized) refreshMarkers()\n },\n}\n"],"mappings":"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","names":["options","parent","buildDomPath","options","e","popup"]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -766,13 +766,13 @@ var Toolbar = class {
|
|
|
766
766
|
this.exportMenu = document.createElement("div");
|
|
767
767
|
this.exportMenu.className = "remarq-export-menu";
|
|
768
768
|
const mdBtn = document.createElement("button");
|
|
769
|
-
mdBtn.textContent = "Markdown (
|
|
769
|
+
mdBtn.textContent = "Markdown (file)";
|
|
770
770
|
mdBtn.addEventListener("click", () => {
|
|
771
771
|
this.callbacks.onExportMd();
|
|
772
772
|
this.closeExportMenu();
|
|
773
773
|
});
|
|
774
774
|
const jsonBtn = document.createElement("button");
|
|
775
|
-
jsonBtn.textContent = "JSON (
|
|
775
|
+
jsonBtn.textContent = "JSON (clipboard)";
|
|
776
776
|
jsonBtn.addEventListener("click", () => {
|
|
777
777
|
this.callbacks.onExportJson();
|
|
778
778
|
this.closeExportMenu();
|
|
@@ -1322,6 +1322,7 @@ function handleInspectClick(e) {
|
|
|
1322
1322
|
comment,
|
|
1323
1323
|
fingerprint: fp,
|
|
1324
1324
|
route: currentRoute(),
|
|
1325
|
+
viewport: `${window.innerWidth}x${window.innerHeight}`,
|
|
1325
1326
|
timestamp: Date.now(),
|
|
1326
1327
|
status: "pending"
|
|
1327
1328
|
};
|
|
@@ -1396,26 +1397,27 @@ function exportMarkdown() {
|
|
|
1396
1397
|
if (fp.textContent) desc += ` "${fp.textContent}"`;
|
|
1397
1398
|
if (fp.parentAnchor) desc += ` (${fp.parentAnchor})`;
|
|
1398
1399
|
if (fp.dataAnnotate) desc += fp.parentAnchor ? ` > ${fp.dataAnnotate}` : ` (${fp.dataAnnotate})`;
|
|
1399
|
-
|
|
1400
|
+
const viewport = ann.viewport ? ` @${ann.viewport}` : "";
|
|
1401
|
+
lines.push(`${i + 1}. [${ann.status}]${viewport} ${desc}: "${ann.comment}"`);
|
|
1400
1402
|
});
|
|
1401
1403
|
const text = lines.join("\n");
|
|
1402
|
-
|
|
1403
|
-
navigator.clipboard.writeText(text);
|
|
1404
|
-
} catch (e) {
|
|
1405
|
-
console.warn("[web-remarq] Clipboard write failed");
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
function exportJSON() {
|
|
1409
|
-
const data = storage.exportJSON();
|
|
1410
|
-
const json = JSON.stringify(data, null, 2);
|
|
1411
|
-
const blob = new Blob([json], { type: "application/json" });
|
|
1404
|
+
const blob = new Blob([text], { type: "text/markdown" });
|
|
1412
1405
|
const url = URL.createObjectURL(blob);
|
|
1413
1406
|
const a = document.createElement("a");
|
|
1414
1407
|
a.href = url;
|
|
1415
|
-
a.download = `remarq-annotations-${Date.now()}.
|
|
1408
|
+
a.download = `remarq-annotations-${Date.now()}.md`;
|
|
1416
1409
|
a.click();
|
|
1417
1410
|
URL.revokeObjectURL(url);
|
|
1418
1411
|
}
|
|
1412
|
+
function exportJSON() {
|
|
1413
|
+
const data = storage.exportJSON();
|
|
1414
|
+
const json = JSON.stringify(data, null, 2);
|
|
1415
|
+
try {
|
|
1416
|
+
navigator.clipboard.writeText(json);
|
|
1417
|
+
} catch (e) {
|
|
1418
|
+
console.warn("[web-remarq] Clipboard write failed");
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1419
1421
|
function setupMutationObserver() {
|
|
1420
1422
|
mutationObserver = new MutationObserver((mutations) => {
|
|
1421
1423
|
for (const m of mutations) {
|