web-remarq 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.cjs +321 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +53 -0
- package/dist/core/index.d.ts +53 -0
- package/dist/core/index.js +292 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.cjs +1399 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +47 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +1372 -0
- package/dist/index.js.map +1 -0
- package/dist/web-remarq.global.global.js +1397 -0
- package/dist/web-remarq.global.global.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +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 const text = el.textContent?.trim() ?? null\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: fixed;\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=\"M4 4l8 8M12 4l-8 8\"/></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 const tag = target.tagName.toLowerCase()\n const text = target.textContent?.trim().slice(0, 30) || ''\n const dataAnnotate = target.getAttribute('data-annotate')\n let label = `<${tag}>`\n if (text) label += ` \"${text}\"`\n if (dataAnnotate) label += ` [${dataAnnotate}]`\n\n this.tooltipEl.textContent = label\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","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\n left: number\n}\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 popup.style.top = `${position.top}px`\n popup.style.left = `${position.left}px`\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 // 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 // Focus textarea after render\n requestAnimationFrame(() => textarea.focus())\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 popup.style.top = `${position.top}px`\n popup.style.left = `${position.left}px`\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 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","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\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 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 = matchElement(ann.fingerprint, { dataAttribute: options.dataAttribute })\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\nfunction handleInspectClick(e: MouseEvent): void {\n if (!inspecting) return\n e.preventDefault()\n e.stopPropagation()\n\n const target = e.target as HTMLElement\n if (!target || target.closest('[data-remarq-theme]')) return\n\n overlay.hide()\n setInspecting(false)\n\n const rect = target.getBoundingClientRect()\n popup.show(\n {\n tag: target.tagName.toLowerCase(),\n text: target.textContent?.trim().slice(0, 30) ?? '',\n },\n {\n top: rect.bottom + 8,\n left: rect.left,\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 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 = matchElement(ann.fingerprint, { dataAttribute: options.dataAttribute })\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 { top: rect.bottom + 8, left: rect.left },\n {\n onResolve: () => {\n storage.update(ann.id, { status: 'resolved' })\n refreshMarkers()\n },\n onDelete: () => {\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 refreshMarkers()\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 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 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 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 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 (matchElement(ann.fingerprint, { dataAttribute: options.dataAttribute })) {\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 storage?.clearAll()\n if (initialized) refreshMarkers()\n },\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,cAAc;AAEb,IAAM,oBAAN,MAAwB;AAAA,EAK7B,cAAc;AAJd,SAAQ,cAA4B,CAAC;AACrC,SAAQ,cAAuC,CAAC;AAChD,wBAAe;AAGb,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAuB;AACrB,WAAO,CAAC,GAAG,KAAK,WAAW;AAAA,EAC7B;AAAA,EAEA,WAAW,OAA6B;AACtC,WAAO,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK;AAAA,EACzD;AAAA,EAEA,IAAI,YAA8B;AAChC,SAAK,YAAY,KAAK,UAAU;AAChC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,OAAO,IAAkB;AACvB,SAAK,cAAc,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAC7D,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,OAAO,IAAY,SAAoC;AACrD,UAAM,MAAM,KAAK,YAAY,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACzD,QAAI,QAAQ,IAAI;AACd,WAAK,YAAY,GAAG,IAAI,EAAE,GAAG,KAAK,YAAY,GAAG,GAAG,GAAG,QAAQ;AAC/D,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,WAAiB;AACf,SAAK,cAAc,CAAC;AACpB,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,aAA8B;AAC5B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,CAAC,GAAG,KAAK,WAAW;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,WAAW,MAA6B;AACtC,SAAK,cAAc,CAAC,GAAG,KAAK,WAAW;AACvC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEQ,OAAa;AACnB,QAAI;AACF,YAAM,MAAM,aAAa,QAAQ,WAAW;AAC5C,UAAI,KAAK;AACP,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,cAAM,EAAE,SAAS,aAAa,GAAG,KAAK,IAAI;AAC1C,aAAK,cAAc,eAAe,CAAC;AACnC,aAAK,cAAc;AAAA,MACrB;AAAA,IACF,QAAQ;AACN,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,OAAa;AACnB,QAAI,KAAK,aAAc;AACvB,QAAI;AACF,YAAM,OAAO;AAAA,QACX,SAAS;AAAA,QACT,GAAG,KAAK;AAAA,QACR,aAAa,KAAK;AAAA,MACpB;AACA,mBAAa,QAAQ,aAAa,KAAK,UAAU,IAAI,CAAC;AAAA,IACxD,QAAQ;AACN,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AACF;;;ACnFA,IAAM,iBAAiB;AACvB,IAAM,uBAAuB;AAC7B,IAAM,aAAa;AACnB,IAAM,eAAe;AAEd,SAAS,cAAc,WAA4B;AACxD,MAAI,qBAAqB,KAAK,SAAS,EAAG,QAAO;AACjD,MAAI,WAAW,KAAK,SAAS,EAAG,QAAO;AACvC,MAAI,eAAe,KAAK,SAAS,EAAG,QAAO;AAC3C,MAAI,aAAa,KAAK,SAAS,EAAG,QAAO;AACzC,SAAO;AACT;AAEO,SAAS,UAAU,WAA2B;AACnD,QAAM,QAAQ,UAAU,MAAM,cAAc;AAC5C,MAAI,OAAO;AACT,UAAM,SAAS,UAAU,MAAM,GAAG,UAAU,YAAY,IAAI,CAAC;AAC7D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,cACd,SACA,aACU;AACV,QAAM,SAAmB,CAAC;AAE1B,aAAW,OAAO,SAAS;AACzB,QAAI,qBAAqB,KAAK,GAAG,EAAG;AACpC,QAAI,WAAW,KAAK,GAAG,EAAG;AAC1B,QAAI,aAAa,KAAK,GAAG,EAAG;AAE5B,QAAI,SAAS,UAAU,GAAG;AAE1B,QAAI,eAAe,CAAC,YAAY,MAAM,EAAG;AAEzC,WAAO,KAAK,MAAM;AAAA,EACpB;AAEA,SAAO;AACT;;;ACtCA,IAAM,kBAAkB;AAEjB,SAAS,kBACd,IACAA,UACoB;AACpB,QAAM,WAAWA,UAAS,iBAAiB;AAE3C,SAAO;AAAA,IACL,cAAc,GAAG,aAAa,QAAQ,KAAK;AAAA,IAC3C,YAAY,GAAG,aAAa,aAAa,KACpC,GAAG,aAAa,WAAW,KAC3B,GAAG,aAAa,SAAS,KACzB;AAAA,IACL,IAAI,YAAY,EAAE;AAAA,IAClB,SAAS,GAAG,QAAQ,YAAY;AAAA,IAChC,aAAa,eAAe,EAAE;AAAA,IAC9B,MAAM,GAAG,aAAa,MAAM,KAAK;AAAA,IACjC,WAAW,GAAG,aAAa,YAAY,KAAK;AAAA,IAC5C,eAAe;AAAA,MACb,MAAM,KAAK,GAAG,SAAS;AAAA,MACvBA,UAAS;AAAA,IACX;AAAA,IACA,SAAS,aAAa,EAAE;AAAA,IACxB,cAAc,gBAAgB,EAAE;AAAA,IAChC,cAAc,iBAAiB,IAAI,QAAQ;AAAA,EAC7C;AACF;AAEA,SAAS,YAAY,IAAgC;AACnD,QAAM,KAAK,GAAG;AACd,MAAI,CAAC,GAAI,QAAO;AAChB,MAAI,cAAc,EAAE,EAAG,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,eAAe,IAAgC;AACtD,QAAM,OAAO,GAAG,aAAa,KAAK,KAAK;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,SAAS,kBAAkB,KAAK,MAAM,GAAG,eAAe,IAAI;AAC1E;AAEA,SAAS,aAAa,IAAyB;AAC7C,QAAM,QAAkB,CAAC;AACzB,MAAI,UAA8B;AAElC,SAAO,WAAW,YAAY,SAAS,QAAQ,MAAM,SAAS,GAAG;AAC/D,UAAM,QAAQ,QAAQ,QAAQ,YAAY,CAAC;AAC3C,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO,MAAM,KAAK,KAAK;AACzB;AAEA,SAAS,gBAAgB,IAAyB;AAChD,QAAM,SAAS,GAAG;AAClB,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,WAAW,MAAM,KAAK,OAAO,QAAQ;AAC3C,SAAO,SAAS,QAAQ,EAAE;AAC5B;AAEA,SAAS,iBAAiB,IAAiB,UAAiC;AAC1E,MAAI,UAAU,GAAG;AACjB,SAAO,WAAW,YAAY,SAAS,MAAM;AAC3C,UAAM,QAAQ,QAAQ,aAAa,QAAQ;AAC3C,QAAI,MAAO,QAAO;AAClB,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AACT;;;ACtEA,IAAM,kBAAkB;AAEjB,SAAS,sBAAsB,GAAW,GAAmB;AAClE,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,CAAC,EAAE,UAAU,CAAC,EAAE,OAAQ,QAAO;AAEnC,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,WAAO,CAAC,IAAI,CAAC,CAAC;AAAA,EAChB;AACA,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,WAAO,CAAC,EAAE,CAAC,IAAI;AAAA,EACjB;AAEA,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,aAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,YAAM,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AACzC,aAAO,CAAC,EAAE,CAAC,IAAI,KAAK;AAAA,QAClB,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI;AAAA,QACnB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI;AAAA,QACnB,OAAO,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM;AAC1C,SAAO,IAAI,WAAW,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;AACnD;AAEA,SAAS,eAAe,GAAkB,GAA0B;AAClE,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,QAAM,KAAK,EAAE,KAAK,EAAE,YAAY;AAChC,QAAM,KAAK,EAAE,KAAK,EAAE,YAAY;AAChC,MAAI,OAAO,GAAI,QAAO;AACtB,MAAI,GAAG,SAAS,EAAE,KAAK,GAAG,SAAS,EAAE,EAAG,QAAO;AAC/C,SAAO,sBAAsB,IAAI,EAAE;AACrC;AAEA,SAAS,kBAAkB,GAAa,GAAqB;AAC3D,MAAI,CAAC,EAAE,UAAU,CAAC,EAAE,OAAQ,QAAO;AACnC,QAAM,OAAO,IAAI,IAAI,CAAC;AACtB,QAAM,OAAO,IAAI,IAAI,CAAC;AACtB,MAAI,eAAe;AACnB,aAAW,QAAQ,MAAM;AACvB,QAAI,KAAK,IAAI,IAAI,EAAG;AAAA,EACtB;AACA,QAAM,SAAQ,oBAAI,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAE;AACpC,SAAO,UAAU,IAAI,IAAI,eAAe;AAC1C;AAEA,SAAS,eAAe,IAAiB,IAAwB,UAA0B;AACzF,MAAI,QAAQ;AAGZ,QAAM,aAAa,GAAG,aAAa,QAAQ;AAC3C,MAAI,GAAG,gBAAgB,eAAe,GAAG,cAAc;AACrD,aAAS;AAAA,EACX;AAGA,QAAM,SAAS,GAAG,aAAa,KAAK,EAAE,MAAM,GAAG,EAAE,KAAK;AACtD,QAAM,UAAU,eAAe,GAAG,aAAa,MAAM;AACrD,MAAI,UAAU,KAAK;AACjB,aAAS,UAAU;AAAA,EACrB;AAGA,MAAI,GAAG,QAAQ,GAAG,aAAa,MAAM,MAAM,GAAG,QAC5C,GAAG,aAAa,GAAG,aAAa,YAAY,MAAM,GAAG,WAAW;AAChE,aAAS;AAAA,EACX;AAGA,MAAI,GAAG,cAAc;AACnB,QAAIC,UAAS,GAAG;AAChB,WAAOA,WAAUA,YAAW,SAAS,MAAM;AACzC,UAAIA,QAAO,aAAa,QAAQ,MAAM,GAAG,cAAc;AACrD,iBAAS;AACT;AAAA,MACF;AACA,MAAAA,UAASA,QAAO;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,GAAG,cAAc,SAAS,GAAG;AAC/B,UAAM,YAAY,MAAM,KAAK,GAAG,SAAS;AACzC,UAAM,UAAU,kBAAkB,GAAG,eAAe,SAAS;AAC7D,aAAS,UAAU;AAAA,EACrB;AAGA,MAAI,GAAG,SAAS;AACd,UAAM,SAASC,cAAa,EAAE;AAC9B,UAAM,UAAU,sBAAsB,GAAG,SAAS,MAAM;AACxD,aAAS,UAAU;AAAA,EACrB;AAGA,QAAM,SAAS,GAAG;AAClB,MAAI,QAAQ;AACV,UAAM,MAAM,MAAM,KAAK,OAAO,QAAQ,EAAE,QAAQ,EAAE;AAClD,QAAI,QAAQ,GAAG,cAAc;AAC3B,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAASA,cAAa,IAAyB;AAC7C,QAAM,QAAkB,CAAC;AACzB,MAAI,UAA8B;AAClC,SAAO,WAAW,YAAY,SAAS,QAAQ,MAAM,SAAS,GAAG;AAC/D,UAAM,QAAQ,QAAQ,QAAQ,YAAY,CAAC;AAC3C,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO,MAAM,KAAK,KAAK;AACzB;AAEO,SAAS,aACd,IACAC,UACoB;AACpB,QAAM,WAAWA,UAAS,iBAAiB;AAG3C,MAAI,GAAG,cAAc;AACnB,UAAM,KAAK,SAAS,cAA2B,IAAI,QAAQ,KAAK,GAAG,YAAY,IAAI;AACnF,QAAI,GAAI,QAAO;AAAA,EACjB;AAGA,MAAI,GAAG,YAAY;AACjB,UAAM,KAAK,SAAS;AAAA,MAClB,iBAAiB,GAAG,UAAU,mBAAmB,GAAG,UAAU,iBAAiB,GAAG,UAAU;AAAA,IAC9F;AACA,QAAI,GAAI,QAAO;AAAA,EACjB;AAGA,MAAI,GAAG,IAAI;AACT,UAAM,KAAK,SAAS,eAAe,GAAG,EAAE;AACxC,QAAI,GAAI,QAAO;AAAA,EACjB;AAGA,QAAM,aAAa,SAAS,iBAA8B,GAAG,OAAO;AACpE,MAAI,SAA6B;AACjC,MAAI,YAAY;AAEhB,aAAW,aAAa,YAAY;AAClC,UAAM,QAAQ,eAAe,WAAW,IAAI,QAAQ;AACpD,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,aAAa,kBAAkB,SAAS;AACjD;;;AClKA,IAAM,YAAY;AAElB,IAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0RL,SAAS,eAAqB;AACnC,MAAI,SAAS,cAAc,SAAS,SAAS,GAAG,EAAG;AAEnD,MAAI;AACF,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,aAAa,WAAW,EAAE;AAChC,UAAM,cAAc;AACpB,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC,QAAQ;AAEN,QAAI;AACF,YAAM,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,WAAW,CAAC;AACjD,YAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,WAAK,MAAM;AACX,WAAK,OAAO,IAAI,gBAAgB,IAAI;AACpC,WAAK,aAAa,WAAW,EAAE;AAC/B,eAAS,KAAK,YAAY,IAAI;AAAA,IAChC,QAAQ;AACN,cAAQ,KAAK,sCAAsC;AAAA,IACrD;AAAA,EACF;AACF;AAEO,SAAS,eAAqB;AACnC,QAAM,KAAK,SAAS,cAAc,IAAI,SAAS,GAAG;AAClD,MAAI,OAAO;AACb;;;ACtTA,IAAM,YAAY;AAIX,IAAM,eAAN,MAAmB;AAAA,EAIxB,YAAY,QAAqB,cAAsB;AACrD,UAAM,YAAY,KAAK,UAAU;AACjC,SAAK,QAAQ,gBAAgB,aAAa;AAE1C,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,aAAa,qBAAqB,KAAK,KAAK;AAC3D,WAAO,YAAY,KAAK,SAAS;AAEjC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,WAAkB;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAS,OAAoB;AAC3B,SAAK,QAAQ;AACb,SAAK,UAAU,aAAa,qBAAqB,KAAK;AACtD,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,SAAe;AACb,SAAK,SAAS,KAAK,UAAU,UAAU,SAAS,OAAO;AAAA,EACzD;AAAA,EAEA,UAAgB;AACd,SAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EAEQ,UAAgB;AACtB,QAAI;AACF,mBAAa,QAAQ,WAAW,KAAK,KAAK;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,YAA0B;AAChC,QAAI;AACF,YAAM,QAAQ,aAAa,QAAQ,SAAS;AAC5C,UAAI,UAAU,WAAW,UAAU,OAAQ,QAAO;AAAA,IACpD,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACF;;;AC7CA,IAAM,QAAQ;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AACZ;AAEO,IAAM,UAAN,MAAc;AAAA,EASnB,YACU,WACA,WACR;AAFQ;AACA;AAPV,SAAQ,aAAiC;AAEzC,SAAQ,YAAY;AACpB,SAAQ,UAAyB,CAAC;AAMhC,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAE3B,SAAK,aAAa,KAAK,aAAa,WAAW,MAAM,SAAS,MAAM,UAAU,UAAU,CAAC;AACzF,SAAK,UAAU,SAAS,cAAc,MAAM;AAC5C,SAAK,QAAQ,YAAY;AACzB,SAAK,QAAQ,MAAM,UAAU;AAC7B,SAAK,WAAW,YAAY,KAAK,OAAO;AAExC,UAAM,YAAY,KAAK,aAAa,UAAU,MAAM,QAAQ,CAAC,MAAM,KAAK,iBAAiB,CAAC,CAAC;AAE3F,SAAK,YAAY,SAAS,cAAc,OAAO;AAC/C,SAAK,UAAU,OAAO;AACtB,SAAK,UAAU,SAAS;AACxB,SAAK,UAAU,MAAM,UAAU;AAC/B,SAAK,UAAU,iBAAiB,UAAU,MAAM;AAC9C,gBAAU,SAAS;AACnB,WAAK,UAAU,QAAQ;AAAA,IACzB,CAAC;AACD,UAAM,YAAY,KAAK,aAAa,UAAU,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM,CAAC;AAExF,UAAM,WAAW,KAAK,aAAa,SAAS,MAAM,OAAO,MAAM,UAAU,QAAQ,CAAC;AAClF,UAAM,WAAW,KAAK,aAAa,SAAS,MAAM,OAAO,MAAM,UAAU,cAAc,CAAC;AACxF,UAAM,cAAc,KAAK,aAAa,YAAY,MAAM,UAAU,MAAM,KAAK,eAAe,CAAC;AAE7F,SAAK,UAAU,CAAC,KAAK,YAAY,WAAW,WAAW,UAAU,QAAQ;AAEzE,SAAK,UAAU,YAAY,KAAK,UAAU;AAC1C,SAAK,UAAU,YAAY,SAAS;AACpC,SAAK,UAAU,YAAY,SAAS;AACpC,SAAK,UAAU,YAAY,QAAQ;AACnC,SAAK,UAAU,YAAY,QAAQ;AACnC,SAAK,UAAU,YAAY,WAAW;AACtC,SAAK,UAAU,YAAY,KAAK,SAAS;AAEzC,cAAU,YAAY,KAAK,SAAS;AAAA,EACtC;AAAA,EAEA,iBAAiB,QAAuB;AACtC,SAAK,WAAW,UAAU,OAAO,iBAAiB,MAAM;AAAA,EAC1D;AAAA,EAEA,cAAc,OAAqB;AACjC,SAAK,QAAQ,cAAc,OAAO,KAAK;AACvC,SAAK,QAAQ,MAAM,UAAU,QAAQ,IAAI,SAAS;AAAA,EACpD;AAAA,EAEA,eAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAiB,MAAqB;AACpC,SAAK,UAAU,QAAQ,OAAO,sEAAiE;AAAA,EACjG;AAAA,EAEA,UAAgB;AACd,SAAK,gBAAgB;AACrB,SAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EAEQ,aAAa,QAAgB,MAAc,SAA0C;AAC3F,UAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,QAAI,YAAY;AAChB,QAAI,aAAa,sBAAsB,MAAM;AAC7C,QAAI,YAAY;AAChB,QAAI,iBAAiB,SAAS,OAAO;AACrC,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAuB;AAC7B,SAAK,YAAY,CAAC,KAAK;AACvB,SAAK,UAAU,UAAU,OAAO,oBAAoB,KAAK,SAAS;AAClE,eAAW,OAAO,KAAK,SAAS;AAC9B,UAAI,MAAM,UAAU,KAAK,YAAY,SAAS;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,iBAAiB,GAAgB;AACvC,QAAI,KAAK,YAAY;AACnB,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,SAAK,aAAa,SAAS,cAAc,KAAK;AAC9C,SAAK,WAAW,YAAY;AAE5B,UAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,UAAM,cAAc;AACpB,UAAM,iBAAiB,SAAS,MAAM;AACpC,WAAK,UAAU,WAAW;AAC1B,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,UAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,YAAQ,cAAc;AACtB,YAAQ,iBAAiB,SAAS,MAAM;AACtC,WAAK,UAAU,aAAa;AAC5B,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,WAAW,YAAY,KAAK;AACjC,SAAK,WAAW,YAAY,OAAO;AAEnC,UAAM,YAAa,EAAE;AACrB,cAAU,MAAM,WAAW;AAC3B,cAAU,YAAY,KAAK,UAAU;AAAA,EACvC;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,YAAY;AACnB,WAAK,WAAW,OAAO;AACvB,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AACF;;;ACjJO,IAAM,UAAN,MAAc;AAAA,EAInB,YAAoB,WAAwB;AAAxB;AAClB,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAC3B,SAAK,UAAU,MAAM,UAAU;AAE/B,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAC3B,SAAK,UAAU,MAAM,UAAU;AAE/B,cAAU,YAAY,KAAK,SAAS;AACpC,cAAU,YAAY,KAAK,SAAS;AAAA,EACtC;AAAA,EAEA,KAAK,QAA2B;AAC9B,QAAI;AACF,YAAM,OAAO,OAAO,sBAAsB;AAE1C,WAAK,UAAU,MAAM,UAAU;AAC/B,WAAK,UAAU,MAAM,MAAM,GAAG,KAAK,GAAG;AACtC,WAAK,UAAU,MAAM,OAAO,GAAG,KAAK,IAAI;AACxC,WAAK,UAAU,MAAM,QAAQ,GAAG,KAAK,KAAK;AAC1C,WAAK,UAAU,MAAM,SAAS,GAAG,KAAK,MAAM;AAE5C,YAAM,MAAM,OAAO,QAAQ,YAAY;AACvC,YAAM,OAAO,OAAO,aAAa,KAAK,EAAE,MAAM,GAAG,EAAE,KAAK;AACxD,YAAM,eAAe,OAAO,aAAa,eAAe;AACxD,UAAI,QAAQ,IAAI,GAAG;AACnB,UAAI,KAAM,UAAS,KAAK,IAAI;AAC5B,UAAI,aAAc,UAAS,KAAK,YAAY;AAE5C,WAAK,UAAU,cAAc;AAC7B,WAAK,UAAU,MAAM,UAAU;AAC/B,WAAK,UAAU,MAAM,MAAM,GAAG,KAAK,MAAM,EAAE;AAC3C,WAAK,UAAU,MAAM,OAAO,GAAG,KAAK,IAAI;AAAA,IAC1C,QAAQ;AACN,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,sBAAsB,GAAW,GAAiB;AAChD,SAAK,UAAU,MAAM,OAAO,GAAG,IAAI,EAAE;AACrC,SAAK,UAAU,MAAM,MAAM,GAAG,IAAI,EAAE;AAAA,EACtC;AAAA,EAEA,OAAa;AACX,SAAK,UAAU,MAAM,UAAU;AAC/B,SAAK,UAAU,MAAM,UAAU;AAAA,EACjC;AAAA,EAEA,UAAgB;AACd,SAAK,UAAU,OAAO;AACtB,SAAK,UAAU,OAAO;AAAA,EACxB;AACF;;;ACpCO,IAAM,QAAN,MAAY;AAAA,EAIjB,YAAoB,WAAwB;AAAxB;AAHpB,SAAQ,UAA8B;AACtC,SAAQ,aAAkD;AAAA,EAEb;AAAA,EAE7C,KACE,MACA,UACA,UACA,UACM;AACN,SAAK,KAAK;AAEV,UAAMC,SAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,OAAM,YAAY;AAClB,IAAAA,OAAM,MAAM,MAAM,GAAG,SAAS,GAAG;AACjC,IAAAA,OAAM,MAAM,OAAO,GAAG,SAAS,IAAI;AAEnC,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,YAAY;AACnB,WAAO,cAAc,IAAI,KAAK,GAAG,IAAI,KAAK,OAAO,KAAK,KAAK,IAAI,MAAM,EAAE;AAEvE,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,YAAY;AAEjB,UAAM,WAAW,SAAS,cAAc,UAAU;AAClD,aAAS,cAAc;AAEvB,SAAK,YAAY,QAAQ;AAEzB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,YAAY;AAEpB,UAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,cAAU,cAAc;AACxB,cAAU,iBAAiB,SAAS,MAAM;AACxC,WAAK,KAAK;AACV,eAAS;AAAA,IACX,CAAC;AAED,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,YAAY;AACnB,WAAO,cAAc;AACrB,WAAO,iBAAiB,SAAS,MAAM;AACrC,YAAM,UAAU,SAAS,MAAM,KAAK;AACpC,UAAI,CAAC,QAAS;AACd,WAAK,KAAK;AACV,eAAS,OAAO;AAAA,IAClB,CAAC;AAED,YAAQ,YAAY,SAAS;AAC7B,YAAQ,YAAY,MAAM;AAE1B,IAAAA,OAAM,YAAY,MAAM;AACxB,IAAAA,OAAM,YAAY,IAAI;AACtB,IAAAA,OAAM,YAAY,OAAO;AAEzB,SAAK,UAAU,YAAYA,MAAK;AAChC,SAAK,UAAUA;AAGf,SAAK,aAAa,CAAC,MAAqB;AACtC,UAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,UAAU;AACjD,cAAM,UAAU,SAAS,MAAM,KAAK;AACpC,YAAI,CAAC,QAAS;AACd,aAAK,KAAK;AACV,iBAAS,OAAO;AAAA,MAClB;AACA,UAAI,EAAE,QAAQ,UAAU;AACtB,aAAK,KAAK;AACV,iBAAS;AAAA,MACX;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,KAAK,UAAU;AAGpD,0BAAsB,MAAM,SAAS,MAAM,CAAC;AAAA,EAC9C;AAAA,EAEA,WACE,MACA,UACA,WACM;AACN,SAAK,KAAK;AAEV,UAAMA,SAAQ,SAAS,cAAc,KAAK;AAC1C,IAAAA,OAAM,YAAY;AAClB,IAAAA,OAAM,MAAM,MAAM,GAAG,SAAS,GAAG;AACjC,IAAAA,OAAM,MAAM,OAAO,GAAG,SAAS,IAAI;AAEnC,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,YAAY;AACnB,WAAO,cAAc,IAAI,KAAK,GAAG,IAAI,KAAK,OAAO,KAAK,KAAK,IAAI,MAAM,EAAE,KAAK,KAAK,MAAM;AAEvF,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,YAAY;AACjB,SAAK,cAAc,KAAK;AAExB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,YAAY;AAEpB,QAAI,KAAK,WAAW,WAAW;AAC7B,YAAM,aAAa,SAAS,cAAc,QAAQ;AAClD,iBAAW,YAAY;AACvB,iBAAW,cAAc;AACzB,iBAAW,iBAAiB,SAAS,MAAM;AACzC,aAAK,KAAK;AACV,kBAAU,UAAU;AAAA,MACtB,CAAC;AACD,cAAQ,YAAY,UAAU;AAAA,IAChC;AAEA,UAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,cAAU,cAAc;AACxB,cAAU,iBAAiB,SAAS,MAAM;AACxC,WAAK,KAAK;AACV,gBAAU,SAAS;AAAA,IACrB,CAAC;AACD,YAAQ,YAAY,SAAS;AAE7B,UAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,aAAS,cAAc;AACvB,aAAS,iBAAiB,SAAS,MAAM;AACvC,WAAK,KAAK;AACV,gBAAU,QAAQ;AAAA,IACpB,CAAC;AACD,YAAQ,YAAY,QAAQ;AAE5B,IAAAA,OAAM,YAAY,MAAM;AACxB,IAAAA,OAAM,YAAY,IAAI;AACtB,IAAAA,OAAM,YAAY,OAAO;AAEzB,SAAK,UAAU,YAAYA,MAAK;AAChC,SAAK,UAAUA;AAEf,SAAK,aAAa,CAAC,MAAqB;AACtC,UAAI,EAAE,QAAQ,UAAU;AACtB,aAAK,KAAK;AACV,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,KAAK,UAAU;AAAA,EACtD;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,OAAO;AACpB,WAAK,UAAU;AAAA,IACjB;AACA,QAAI,KAAK,YAAY;AACnB,eAAS,oBAAoB,WAAW,KAAK,UAAU;AACvD,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,KAAK;AAAA,EACZ;AACF;;;AC7KO,IAAM,gBAAN,MAAoB;AAAA,EAKzB,YACU,WACA,SACR;AAFQ;AACA;AANV,SAAQ,UAAU,oBAAI,IAAyB;AAC/C,SAAQ,QAAuB;AAC/B,SAAQ,UAAU;AAMhB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,UAAU,YAAwB,QAA2B;AAC3D,SAAK;AACL,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,YAAY;AACrB,aAAS,aAAa,eAAe,WAAW,MAAM;AACtD,aAAS,aAAa,sBAAsB,WAAW,EAAE;AACzD,aAAS,cAAc,OAAO,KAAK,OAAO;AAC1C,aAAS,QAAQ,WAAW;AAE5B,aAAS,iBAAiB,SAAS,MAAM;AACvC,WAAK,UAAU,WAAW,EAAE;AAAA,IAC9B,CAAC;AAED,SAAK,UAAU,YAAY,QAAQ;AACnC,SAAK,QAAQ,IAAI,WAAW,IAAI,EAAE,YAAY,QAAQ,SAAS,CAAC;AAChE,SAAK,eAAe,WAAW,EAAE;AAAA,EACnC;AAAA,EAEA,aAAa,IAAkB;AAC7B,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,OAAO;AACT,YAAM,SAAS,OAAO;AACtB,WAAK,QAAQ,OAAO,EAAE;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,aAAa,IAAY,QAAsC;AAC7D,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,OAAO;AACT,YAAM,WAAW,SAAS;AAC1B,YAAM,SAAS,aAAa,eAAe,MAAM;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,eAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AACzC,YAAM,SAAS,OAAO;AAAA,IACxB;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,UAAU,MAAM;AACvB,2BAAqB,KAAK,KAAK;AAC/B,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,MAAM;AAAA,EACb;AAAA,EAEQ,eAAe,IAAkB;AACvC,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO;AACZ,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,sBAAsB;AAChD,YAAM,SAAS,MAAM,MAAM,GAAG,OAAO,UAAU,KAAK,MAAM,EAAE;AAC5D,YAAM,SAAS,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,EAAE;AAAA,IACjE,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAChC,UAAM,SAAS,MAAM;AACnB,iBAAW,MAAM,KAAK,QAAQ,KAAK,GAAG;AACpC,aAAK,eAAe,EAAE;AAAA,MACxB;AACA,WAAK,QAAQ,sBAAsB,MAAM;AAAA,IAC3C;AACA,SAAK,QAAQ,sBAAsB,MAAM;AAAA,EAC3C;AACF;;;ACzFO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YACU,WACA,UACR;AAFQ;AACA;AAJV,SAAQ,UAA8B;AAAA,EAKnC;AAAA,EAEH,OAAO,aAAiC;AACtC,SAAK,OAAO;AACZ,QAAI,YAAY,WAAW,EAAG;AAE9B,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAElB,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,YAAY;AACnB,WAAO,cAAc,aAAa,YAAY,MAAM;AACpD,UAAM,YAAY,MAAM;AAExB,eAAW,OAAO,aAAa;AAC7B,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AAEjB,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AAEjB,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,cAAQ,YAAY;AACpB,cAAQ,cAAc,IAAI;AAE1B,YAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,aAAO,YAAY;AACnB,YAAM,KAAK,IAAI;AACf,UAAI,OAAO,IAAI,GAAG,OAAO;AACzB,UAAI,GAAG,YAAa,SAAQ,KAAK,GAAG,WAAW;AAC/C,UAAI,GAAG,aAAc,SAAQ,KAAK,GAAG,YAAY;AACjD,aAAO,cAAc;AAErB,WAAK,YAAY,OAAO;AACxB,WAAK,YAAY,MAAM;AAEvB,YAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,gBAAU,YAAY;AACtB,gBAAU,cAAc;AACxB,gBAAU,iBAAiB,SAAS,MAAM;AACxC,aAAK,WAAW,IAAI,EAAE;AAAA,MACxB,CAAC;AAED,WAAK,YAAY,IAAI;AACrB,WAAK,YAAY,SAAS;AAC1B,YAAM,YAAY,IAAI;AAAA,IACxB;AAEA,SAAK,UAAU,YAAY,KAAK;AAChC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,SAAe;AACrB,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,OAAO;AACpB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AACF;;;ACpEO,IAAM,gBAAN,MAAoB;AAAA,EAOzB,cAAc;AANd,SAAQ,YAAsC,oBAAI,IAAI;AAOpD,SAAK,oBAAoB,QAAQ,UAAU,KAAK,OAAO;AACvD,SAAK,uBAAuB,QAAQ,aAAa,KAAK,OAAO;AAC7D,SAAK,kBAAkB,MAAM,KAAK,OAAO;AACzC,SAAK,oBAAoB,MAAM,KAAK,OAAO;AAE3C,SAAK,aAAa;AAElB,WAAO,iBAAiB,YAAY,KAAK,eAAe;AACxD,WAAO,iBAAiB,cAAc,KAAK,iBAAiB;AAAA,EAC9D;AAAA,EAEA,eAAuB;AACrB,WAAO,SAAS,WAAW,SAAS;AAAA,EACtC;AAAA,EAEA,SAAS,UAA2C;AAClD,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,WAAO,oBAAoB,YAAY,KAAK,eAAe;AAC3D,WAAO,oBAAoB,cAAc,KAAK,iBAAiB;AAC/D,YAAQ,YAAY,KAAK;AACzB,YAAQ,eAAe,KAAK;AAC5B,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEQ,SAAe;AACrB,UAAM,QAAQ,KAAK,aAAa;AAChC,eAAW,YAAY,KAAK,WAAW;AACrC,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,UAAM,OAAO;AAEb,YAAQ,YAAY,YAAa,MAA4C;AAC3E,WAAK,kBAAkB,MAAM,MAAM,IAAI;AACvC,WAAK,OAAO;AAAA,IACd;AAEA,YAAQ,eAAe,YAAa,MAA+C;AACjF,WAAK,qBAAqB,MAAM,MAAM,IAAI;AAC1C,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AACF;;;AC/CA,IAAI,cAAc;AAClB,IAAI,UAA4B,CAAC;AACjC,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI,aAAa;AACjB,IAAI,mBAA4C;AAChD,IAAI,aAAkC;AAEtC,SAAS,eAAuB;AAC9B,SAAO,SAAS,WAAW,SAAS;AACtC;AAEA,SAAS,aAAqB;AAC5B,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACpE;AAEA,SAAS,iBAAuB;AAC9B,UAAQ,MAAM;AACd,QAAM,WAAyB,CAAC;AAChC,QAAM,QAAQ,aAAa;AAC3B,QAAM,OAAO,QAAQ,WAAW,KAAK;AAErC,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK,aAAa,IAAI,aAAa,EAAE,eAAe,QAAQ,cAAc,CAAC;AACjF,QAAI,IAAI;AACN,cAAQ,UAAU,KAAK,EAAE;AAAA,IAC3B,OAAO;AACL,eAAS,KAAK,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,gBAAc,OAAO,QAAQ;AAE7B,QAAM,eAAe,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAChE,UAAQ,cAAc,YAAY;AACpC;AAEA,SAAS,mBAAmB,GAAqB;AAC/C,MAAI,CAAC,WAAY;AACjB,IAAE,eAAe;AACjB,IAAE,gBAAgB;AAElB,QAAM,SAAS,EAAE;AACjB,MAAI,CAAC,UAAU,OAAO,QAAQ,qBAAqB,EAAG;AAEtD,UAAQ,KAAK;AACb,gBAAc,KAAK;AAEnB,QAAM,OAAO,OAAO,sBAAsB;AAC1C,QAAM;AAAA,IACJ;AAAA,MACE,KAAK,OAAO,QAAQ,YAAY;AAAA,MAChC,MAAM,OAAO,aAAa,KAAK,EAAE,MAAM,GAAG,EAAE,KAAK;AAAA,IACnD;AAAA,IACA;AAAA,MACE,KAAK,KAAK,SAAS;AAAA,MACnB,MAAM,KAAK;AAAA,IACb;AAAA,IACA,CAAC,YAAY;AACX,YAAM,KAAK,kBAAkB,QAAQ;AAAA,QACnC,aAAa,QAAQ;AAAA,QACrB,eAAe,QAAQ;AAAA,MACzB,CAAC;AACD,YAAM,MAAkB;AAAA,QACtB,IAAI,WAAW;AAAA,QACf;AAAA,QACA,aAAa;AAAA,QACb,OAAO,aAAa;AAAA,QACpB,WAAW,KAAK,IAAI;AAAA,QACpB,QAAQ;AAAA,MACV;AACA,cAAQ,IAAI,GAAG;AACf,qBAAe;AAAA,IACjB;AAAA,IACA,MAAM;AAAA,IAEN;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,GAAqB;AAC/C,MAAI,CAAC,WAAY;AACjB,QAAM,SAAS,EAAE;AACjB,MAAI,CAAC,UAAU,OAAO,QAAQ,qBAAqB,EAAG;AACtD,UAAQ,KAAK,MAAM;AACnB,UAAQ,sBAAsB,EAAE,SAAS,EAAE,OAAO;AACpD;AAEA,SAAS,qBAAqB,GAAwB;AACpD,MAAI,EAAE,QAAQ,YAAY,YAAY;AACpC,kBAAc,KAAK;AACnB,YAAQ,KAAK;AAAA,EACf;AACF;AAEA,SAAS,cAAc,OAAsB;AAC3C,eAAa;AACb,UAAQ,iBAAiB,KAAK;AAC9B,MAAI,CAAC,MAAO,SAAQ,KAAK;AAC3B;AAEA,SAAS,kBAAkB,cAA4B;AACrD,QAAM,MAAM,QAAQ,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY;AAC9D,MAAI,CAAC,IAAK;AAEV,QAAM,KAAK,aAAa,IAAI,aAAa,EAAE,eAAe,QAAQ,cAAc,CAAC;AACjF,MAAI,CAAC,GAAI;AAET,QAAM,OAAO,GAAG,sBAAsB;AAEtC,QAAM;AAAA,IACJ;AAAA,MACE,KAAK,IAAI,YAAY;AAAA,MACrB,MAAM,IAAI,YAAY,eAAe;AAAA,MACrC,SAAS,IAAI;AAAA,MACb,QAAQ,IAAI;AAAA,IACd;AAAA,IACA,EAAE,KAAK,KAAK,SAAS,GAAG,MAAM,KAAK,KAAK;AAAA,IACxC;AAAA,MACE,WAAW,MAAM;AACf,gBAAQ,OAAO,IAAI,IAAI,EAAE,QAAQ,WAAW,CAAC;AAC7C,uBAAe;AAAA,MACjB;AAAA,MACA,UAAU,MAAM;AACd,gBAAQ,OAAO,IAAI,EAAE;AACrB,uBAAe;AAAA,MACjB;AAAA,MACA,SAAS,MAAM;AAAA,MAAC;AAAA,IAClB;AAAA,EACF;AACF;AAEA,SAAS,iBAAuB;AAC9B,QAAM,QAAQ,aAAa;AAC3B,QAAM,OAAO,QAAQ,WAAW,KAAK;AACrC,MAAI,CAAC,KAAK,OAAQ;AAElB,QAAM,QAAQ,CAAC,yBAAoB,KAAK,KAAK,KAAK,MAAM,KAAK,EAAE;AAC/D,OAAK,QAAQ,CAAC,KAAK,MAAM;AACvB,UAAM,KAAK,IAAI;AACf,QAAI,OAAO,IAAI,GAAG,OAAO;AACzB,QAAI,GAAG,YAAa,SAAQ,KAAK,GAAG,WAAW;AAC/C,QAAI,GAAG,aAAc,SAAQ,KAAK,GAAG,YAAY;AACjD,QAAI,GAAG,aAAc,SAAQ,GAAG,eAAe,MAAM,GAAG,YAAY,KAAK,KAAK,GAAG,YAAY;AAC7F,UAAM,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,IAAI,MAAM,IAAI,OAAO,GAAG;AAAA,EAClE,CAAC;AAED,QAAM,OAAO,MAAM,KAAK,IAAI;AAC5B,MAAI;AACF,cAAU,UAAU,UAAU,IAAI;AAAA,EACpC,QAAQ;AACN,YAAQ,KAAK,qCAAqC;AAAA,EACpD;AACF;AAEA,SAAS,aAAmB;AAC1B,QAAM,OAAO,QAAQ,WAAW;AAChC,QAAM,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACzC,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC1D,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,QAAM,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,sBAAsB,KAAK,IAAI,CAAC;AAC7C,IAAE,MAAM;AACR,MAAI,gBAAgB,GAAG;AACzB;AAEA,SAAS,wBAA8B;AACrC,qBAAmB,IAAI,iBAAiB,CAAC,cAAc;AACrD,eAAW,KAAK,WAAW;AACzB,UAAI,EAAE,kBAAkB,eAAe,EAAE,OAAO,QAAQ,qBAAqB,EAAG;AAAA,IAClF;AACA,mBAAe;AAAA,EACjB,CAAC;AAED,mBAAiB,QAAQ,SAAS,MAAM;AAAA,IACtC,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,iBAAiB,CAAC,MAAM,SAAS,iBAAiB,eAAe,aAAa,SAAS;AAAA,EACzF,CAAC;AACH;AAEO,IAAM,YAAY;AAAA,EACvB,KAAK,MAA+B;AAClC,QAAI,YAAa;AACjB,cAAU,QAAQ,CAAC;AAEnB,QAAI;AACF,mBAAa;AACb,gBAAU,IAAI,kBAAkB;AAChC,qBAAe,IAAI,aAAa,SAAS,MAAM,QAAQ,KAAK;AAC5D,gBAAU,IAAI,QAAQ,aAAa,SAAS;AAC5C,cAAQ,IAAI,MAAM,aAAa,SAAS;AACxC,gBAAU,IAAI,cAAc,aAAa,WAAW,iBAAiB;AACrE,sBAAgB,IAAI,cAAc,aAAa,WAAW,CAAC,OAAO;AAChE,gBAAQ,OAAO,EAAE;AACjB,uBAAe;AAAA,MACjB,CAAC;AAED,gBAAU,IAAI,QAAQ,aAAa,WAAW;AAAA,QAC5C,WAAW,MAAM,cAAc,CAAC,UAAU;AAAA,QAC1C,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,UAAU,MAAM;AACd,gBAAM,OAAO,QAAQ,aAAa,EAAE,QAAQ,CAAC;AAC7C,cAAI,MAAM;AACR,sBAAU,OAAO,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,QACA,SAAS,MAAM;AACb,kBAAQ,SAAS;AACjB,yBAAe;AAAA,QACjB;AAAA,QACA,eAAe,MAAM,aAAa,OAAO;AAAA,MAC3C,CAAC;AAED,UAAI,QAAQ,cAAc;AACxB,gBAAQ,iBAAiB,IAAI;AAAA,MAC/B;AAEA,sBAAgB,IAAI,cAAc;AAClC,mBAAa,cAAc,SAAS,MAAM,eAAe,CAAC;AAE1D,eAAS,iBAAiB,SAAS,oBAAoB,IAAI;AAC3D,eAAS,iBAAiB,aAAa,kBAAkB;AACzD,eAAS,iBAAiB,WAAW,oBAAoB;AAEzD,4BAAsB;AACtB,qBAAe;AACf,oBAAc;AAAA,IAChB,SAAS,KAAK;AACZ,cAAQ,MAAM,6BAA6B,GAAG;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,YAAa;AAClB,QAAI;AACF,eAAS,oBAAoB,SAAS,oBAAoB,IAAI;AAC9D,eAAS,oBAAoB,aAAa,kBAAkB;AAC5D,eAAS,oBAAoB,WAAW,oBAAoB;AAC5D,wBAAkB,WAAW;AAC7B,yBAAmB;AACnB,mBAAa;AACb,qBAAe,QAAQ;AACvB,eAAS,QAAQ;AACjB,qBAAe,QAAQ;AACvB,aAAO,QAAQ;AACf,eAAS,QAAQ;AACjB,eAAS,QAAQ;AACjB,oBAAc,QAAQ;AACtB,mBAAa;AACb,mBAAa;AACb,oBAAc;AAAA,IAChB,SAAS,KAAK;AACZ,cAAQ,MAAM,gCAAgC,GAAG;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,SAAS,OAA+B;AACtC,kBAAc,SAAS,KAAK;AAAA,EAC9B;AAAA,EAEA,OAAO,QAA6B;AAClC,QAAI,WAAW,KAAM,gBAAe;AAAA,QAC/B,YAAW;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,MAAmC;AAC9C,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,UAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,YAAQ,WAAW,IAAI;AACvB,mBAAe;AAEf,UAAM,UAAU,QAAQ,OAAO;AAC/B,QAAI,UAAU;AACd,QAAI,WAAW;AACf,eAAW,OAAO,SAAS;AACzB,UAAI,aAAa,IAAI,aAAa,EAAE,eAAe,QAAQ,cAAc,CAAC,GAAG;AAC3E;AAAA,MACF,OAAO;AACL;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,OAAO,QAAQ,QAAQ,SAAS,SAAS;AAAA,EACpD;AAAA,EAEA,eAAe,OAA8B;AAC3C,QAAI,CAAC,QAAS,QAAO,CAAC;AACtB,WAAO,QAAQ,QAAQ,WAAW,KAAK,IAAI,QAAQ,OAAO;AAAA,EAC5D;AAAA,EAEA,WAAiB;AACf,aAAS,SAAS;AAClB,QAAI,YAAa,gBAAe;AAAA,EAClC;AACF;","names":["options","parent","buildDomPath","options","popup"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
interface ElementFingerprint {
|
|
2
|
+
dataAnnotate: string | null;
|
|
3
|
+
dataTestId: string | null;
|
|
4
|
+
id: string | null;
|
|
5
|
+
tagName: string;
|
|
6
|
+
textContent: string | null;
|
|
7
|
+
role: string | null;
|
|
8
|
+
ariaLabel: string | null;
|
|
9
|
+
stableClasses: string[];
|
|
10
|
+
domPath: string;
|
|
11
|
+
siblingIndex: number;
|
|
12
|
+
parentAnchor: string | null;
|
|
13
|
+
}
|
|
14
|
+
interface Annotation {
|
|
15
|
+
id: string;
|
|
16
|
+
comment: string;
|
|
17
|
+
fingerprint: ElementFingerprint;
|
|
18
|
+
route: string;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
status: 'pending' | 'resolved';
|
|
21
|
+
}
|
|
22
|
+
interface AnnotationStore {
|
|
23
|
+
version: 1;
|
|
24
|
+
annotations: Annotation[];
|
|
25
|
+
}
|
|
26
|
+
interface WebRemarqOptions {
|
|
27
|
+
theme?: 'light' | 'dark';
|
|
28
|
+
classFilter?: (className: string) => boolean;
|
|
29
|
+
dataAttribute?: string;
|
|
30
|
+
}
|
|
31
|
+
interface ImportResult {
|
|
32
|
+
total: number;
|
|
33
|
+
matched: number;
|
|
34
|
+
detached: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare const WebRemarq: {
|
|
38
|
+
init(opts?: WebRemarqOptions): void;
|
|
39
|
+
destroy(): void;
|
|
40
|
+
setTheme(theme: "light" | "dark"): void;
|
|
41
|
+
export(format: "md" | "json"): void;
|
|
42
|
+
import(file: File): Promise<ImportResult>;
|
|
43
|
+
getAnnotations(route?: string): Annotation[];
|
|
44
|
+
clearAll(): void;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { type Annotation, type AnnotationStore, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
interface ElementFingerprint {
|
|
2
|
+
dataAnnotate: string | null;
|
|
3
|
+
dataTestId: string | null;
|
|
4
|
+
id: string | null;
|
|
5
|
+
tagName: string;
|
|
6
|
+
textContent: string | null;
|
|
7
|
+
role: string | null;
|
|
8
|
+
ariaLabel: string | null;
|
|
9
|
+
stableClasses: string[];
|
|
10
|
+
domPath: string;
|
|
11
|
+
siblingIndex: number;
|
|
12
|
+
parentAnchor: string | null;
|
|
13
|
+
}
|
|
14
|
+
interface Annotation {
|
|
15
|
+
id: string;
|
|
16
|
+
comment: string;
|
|
17
|
+
fingerprint: ElementFingerprint;
|
|
18
|
+
route: string;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
status: 'pending' | 'resolved';
|
|
21
|
+
}
|
|
22
|
+
interface AnnotationStore {
|
|
23
|
+
version: 1;
|
|
24
|
+
annotations: Annotation[];
|
|
25
|
+
}
|
|
26
|
+
interface WebRemarqOptions {
|
|
27
|
+
theme?: 'light' | 'dark';
|
|
28
|
+
classFilter?: (className: string) => boolean;
|
|
29
|
+
dataAttribute?: string;
|
|
30
|
+
}
|
|
31
|
+
interface ImportResult {
|
|
32
|
+
total: number;
|
|
33
|
+
matched: number;
|
|
34
|
+
detached: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare const WebRemarq: {
|
|
38
|
+
init(opts?: WebRemarqOptions): void;
|
|
39
|
+
destroy(): void;
|
|
40
|
+
setTheme(theme: "light" | "dark"): void;
|
|
41
|
+
export(format: "md" | "json"): void;
|
|
42
|
+
import(file: File): Promise<ImportResult>;
|
|
43
|
+
getAnnotations(route?: string): Annotation[];
|
|
44
|
+
clearAll(): void;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { type Annotation, type AnnotationStore, type ElementFingerprint, type ImportResult, WebRemarq, type WebRemarqOptions };
|