@recogito/text-annotator 3.1.5 → 3.1.6
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-annotator.umd.js","sources":["../src/utils/isNotAnnotatable.ts","../src/utils/cancelSingleClickEvents.ts","../src/utils/cloneEvents.ts","../src/utils/device.ts","../src/utils/programmaticallyFocusable.ts","../src/utils/debounce.ts","../src/utils/splitAnnotatableRanges.ts","../src/utils/getQuoteContext.ts","../src/utils/isRevived.ts","../src/utils/isWhitespaceOrEmpty.ts","../src/utils/mergeClientRects.ts","../src/utils/rangeToSelector.ts","../src/utils/reviveSelector.ts","../src/utils/reviveTarget.ts","../src/utils/reviveAnnotation.ts","../src/utils/trimRangeToContainer.ts","../src/api/scrollIntoView.ts","../src/highlight/HighlightStyle.ts","../src/highlight/HighlightPainter.ts","../src/highlight/viewport.ts","../src/highlight/baseRenderer.ts","../src/highlight/canvas/canvasRenderer.ts","../src/highlight/highlights/highlightsRenderer.ts","../src/highlight/span/spansRenderer.ts","../src/model/w3c/W3CTextFormatAdapter.ts","../src/state/spatialTree.ts","../src/state/TextAnnotatorState.ts","../src/presence/PresencePainter.ts","../src/SelectionHandler.ts","../src/TextAnnotatorOptions.ts","../src/TextAnnotator.ts"],"sourcesContent":["export const NOT_ANNOTATABLE_CLASS = 'not-annotatable';\n\nexport const NOT_ANNOTATABLE_SELECTOR = `.${NOT_ANNOTATABLE_CLASS}`;\n\nexport const isNotAnnotatable = (container: Node, node: Node): boolean => {\n if (!container.contains(node)) return true;\n\n const closestNotAnnotatable = node instanceof HTMLElement\n ? node.closest(NOT_ANNOTATABLE_SELECTOR)\n : node.parentElement?.closest(NOT_ANNOTATABLE_SELECTOR);\n return Boolean(closestNotAnnotatable);\n}\n\nexport const isRangeAnnotatable = (container: Node, range: Range): boolean => {\n const ancestor = range.commonAncestorContainer;\n return !isNotAnnotatable(container, ancestor);\n}","import { NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\n/**\n * Calls .preventDefault() on click events in annotable areas, in order\n * to prevent problematic default browser behavior. (Specifically: keep\n * Chrome Android from triggering word selection on single click.)\n */\nexport const cancelSingleClickEvents = (container: HTMLElement) =>\n container.addEventListener('click', event => {\n const targetElement = event.target as HTMLElement;\n\n const shouldPrevent =\n // Allow clicks within not-annotatable elements\n !targetElement.closest(NOT_ANNOTATABLE_SELECTOR)\n // Allow clicks on links\n && !(event.target as Element).closest('a');\n\n if (shouldPrevent)\n event.preventDefault();\n });\n","/**\n * Events need to be manually mapped into new objects:\n * 1. It preserves the `target` and `currentTarget` properties.\n * Otherwise, they will be `null` when the event is read beyond the handler.\n * 2. Spread operator can copy only own enumerable properties, not inherited ones.\n * Therefore, we need to manually copy the props we're interested in.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget\n * @see https://github.com/recogito/text-annotator-js/commit/65d13f3108c429311cf8c2523f6babbbc946013d#r144041390\n */\n\nexport const clonePointerEvent = (event: PointerEvent): PointerEvent => ({\n ...event,\n type: event.type,\n x: event.x,\n y: event.y,\n clientX: event.clientX,\n clientY: event.clientY,\n offsetX: event.offsetX,\n offsetY: event.offsetY,\n screenX: event.screenX,\n screenY: event.screenY,\n isPrimary: event.isPrimary,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n button: event.button,\n buttons: event.buttons,\n currentTarget: event.currentTarget,\n target: event.target,\n defaultPrevented: event.defaultPrevented,\n detail: event.detail,\n eventPhase: event.eventPhase,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n timeStamp: event.timeStamp\n})\n\nexport const cloneKeyboardEvent = (event: KeyboardEvent): KeyboardEvent => ({\n ...event,\n type: event.type,\n key: event.key,\n code: event.code,\n location: event.location,\n repeat: event.repeat,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n currentTarget: event.currentTarget,\n target: event.target,\n defaultPrevented: event.defaultPrevented,\n detail: event.detail,\n timeStamp: event.timeStamp\n})\n","export const isMac = typeof navigator !== 'undefined' &&\n // @ts-ignore\n /mac/i.test(navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform);\n","/**\n * Makes an element programmatically focusable by adding a `tabindex=\"-1\"` attribute.\n * Or does nothing if the element is already focusable 🤷🏻\n * It's required to process keyboard events on an element that is not natively focusable.\n */\nexport const programmaticallyFocusable = (container: HTMLElement) => {\n if (!container.hasAttribute('tabindex') && container.tabIndex < 0) {\n container.setAttribute('tabindex', '-1');\n }\n\n container.classList.add('no-focus-outline');\n};\n","export const debounce = <T extends (...args: any[]) => void>(func: T, delay = 10): T => {\n\tlet timeoutId: ReturnType<typeof setTimeout>;\n\n\treturn ((...args: any[]) => {\n\t\tclearTimeout(timeoutId);\n\t\ttimeoutId = setTimeout(() => func.apply(this, args), delay);\n\t}) as T;\n}\n","import { isRangeAnnotatable, NOT_ANNOTATABLE_CLASS, NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\nconst iterateNotAnnotatableElements = function*(range: Range): Generator<HTMLElement> {\n const notAnnotatableIterator = document.createNodeIterator(\n range.commonAncestorContainer,\n NodeFilter.SHOW_ELEMENT,\n (node) =>\n node instanceof HTMLElement // Only elements that can have the class applied\n && node.classList.contains(NOT_ANNOTATABLE_CLASS) // Only elements that are not annotatable\n && !node.parentElement.closest(NOT_ANNOTATABLE_SELECTOR) // Only elements that are not descendants of a not annotatable element\n && range.intersectsNode(node) // Only elements that are within the range\n ? NodeFilter.FILTER_ACCEPT\n : NodeFilter.FILTER_SKIP\n );\n\n let notAnnotatableNode: Node | null;\n\n while ((notAnnotatableNode = notAnnotatableIterator.nextNode())) {\n if (notAnnotatableNode instanceof HTMLElement) {\n yield notAnnotatableNode;\n }\n }\n}\n\n/**\n * Splits a DOM Range into one or more ranges that span annotatable content only.\n */\nexport const splitAnnotatableRanges = (container: Node, range: Range): Range[] => {\n if (!isRangeAnnotatable(container, range)) return [];\n\n const annotatableRanges: Range[] = [];\n\n let prevNotAnnotatable: HTMLElement | null = null;\n\n for (const notAnnotatable of iterateNotAnnotatableElements(range)) {\n let subRange: Range;\n\n // From the start of the range to the not annotatable element.\n // If selection starts on the non-annotatable element, a collapsed range will be created and ignored.\n if (!prevNotAnnotatable) {\n subRange = range.cloneRange();\n subRange.setEndBefore(notAnnotatable);\n } else {\n // From the previous not annotatable element to the current not annotatable element\n subRange = document.createRange();\n subRange.setStartAfter(prevNotAnnotatable);\n subRange.setEndBefore(notAnnotatable);\n }\n\n if (!subRange.collapsed)\n annotatableRanges.push(subRange);\n\n prevNotAnnotatable = notAnnotatable;\n }\n\n // From the last not annotatable element to the end of the parent range\n if (prevNotAnnotatable) {\n const lastRange = range.cloneRange();\n lastRange.setStartAfter(prevNotAnnotatable);\n if (!lastRange.collapsed) {\n annotatableRanges.push(lastRange);\n }\n }\n\n return annotatableRanges.length > 0 ? annotatableRanges : [range];\n}\n\nexport const getRangeAnnotatableContents = (range: Range): DocumentFragment => {\n const contents = range.cloneContents();\n contents.querySelectorAll(NOT_ANNOTATABLE_SELECTOR).forEach((el) => el.remove());\n return contents;\n}\n","import { getRangeAnnotatableContents } from './splitAnnotatableRanges';\n\nexport const getQuoteContext = (\n range: Range, \n container: HTMLElement, \n length = 10,\n offsetReferenceSelector?: string\n) => {\n const offsetReference: HTMLElement = offsetReferenceSelector\n ? (range.startContainer.parentElement as HTMLElement).closest(offsetReferenceSelector)!\n : container;\n\n const rangeBefore = document.createRange();\n rangeBefore.setStart(offsetReference, 0);\n rangeBefore.setEnd(range.startContainer, range.startOffset);\n\n const before = getRangeAnnotatableContents(rangeBefore).textContent;\n \n const rangeAfter = document.createRange();\n rangeAfter.setStart(range.endContainer, range.endOffset);\n\n if (offsetReference === document.body)\n rangeAfter.setEnd(offsetReference, offsetReference.childNodes.length);\n else\n rangeAfter.setEndAfter(offsetReference);\n\n const after = getRangeAnnotatableContents(rangeAfter).textContent;\n\n return {\n prefix: before.substring(before.length - length),\n suffix: after.substring(0, length)\n }\n}\n","import type { TextSelector } from '../model';\n\nexport const isRevived = (selector: TextSelector[]) =>\n selector.every(s => s.range instanceof Range && !s.range.collapsed);\n","export const whitespaceOrEmptyRegex = /^\\s*$/;\n\nexport const isWhitespaceOrEmpty = (range: Range): boolean => whitespaceOrEmptyRegex.test(range.toString())\n","// The three topological relations we need to check for\ntype Relation = \n // Inline elements, same height, directly adjacent\n 'inline-adjacent' |\n // Inline elements, A fully contains B\n 'inline-contains' |\n // Inline elements, A is fully contained inside B\n 'inline-is-contained' |\n // At least one block element, A fully contains B\n 'block-contains' |\n // At least one block element, A is fully contained in B\n 'block-is-contained';\n\n// Note that this is not a general topology test. Takes a \n// few shortcuts to test ONLY the situations we'll encounter\n// with text selections.\nconst getRelation = (rectA: DOMRect, rectB: DOMRect): Relation | undefined => {\n const round = (num: number ) => Math.round(num * 10) / 10;\n\n // Some browsers have fractional pixel differences (looking at you FF!)\n const a = {\n top: round(rectA.top),\n bottom: round(rectA.bottom),\n left: round(rectA.left),\n right: round(rectA.right)\n };\n\n const b = {\n top: round(rectB.top),\n bottom: round(rectB.bottom),\n left: round(rectB.left),\n right: round(rectB.right)\n };\n\n if (Math.abs(a.top - b.top) < 0.5 && Math.abs(a.bottom - b.bottom) < 0.5) {\n // Same height - check for containment and adjacency\n if (Math.abs(a.left - b.right) < 0.5 || Math.abs(a.right - b.left) < 0.5)\n return 'inline-adjacent';\n\n if (a.left >= b.left && a.right <= b.right)\n return 'inline-is-contained';\n\n if (a.left <= b.left && a.right >= b.right)\n return 'inline-contains';\n } else {\n // Different heights - check for containment\n if (a.top <= b.top && a.bottom >= b.bottom) {\n if (a.left <= b.left && a.right >= b.right) {\n return 'block-contains'\n }\n } else if (a.top >= b.top && a.bottom <= b.bottom) {\n if (a.left >= b.left && a.right <= b.right) {\n return 'block-is-contained';\n }\n }\n }\n}\n\nconst union = (a: DOMRect, b: DOMRect): DOMRect => {\n const left = Math.min(a.left, b.left);\n const right = Math.max(a.right, b.right);\n const top = Math.min(a.top, b.top);\n const bottom = Math.max(a.bottom, b.bottom);\n\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\nexport const mergeClientRects = (rects: DOMRect[]) => rects.reduce<DOMRect[]>((merged, rectA) => {\n // Some browser report empty rects - discard\n if (rectA.width === 0 || rectA.height === 0)\n return merged;\n\n let next = [...merged];\n\n let wasMerged = false;\n\n for (const rectB of merged) {\n const relation = getRelation(rectA, rectB);\n \n if (relation === 'inline-adjacent') {\n // A and B are adjacent - remove B and keep union\n next = next.map(r => r === rectB ? union(rectA, rectB) : r);\n wasMerged = true;\n break;\n } else if (relation === 'inline-contains') {\n // A contains B - remove B and keep A\n next = next.map(r => r === rectB ? rectA : r);\n wasMerged = true;\n break;\n } else if (relation === 'inline-is-contained') {\n // B contains A - skip A\n wasMerged = true;\n break;\n } else if (relation === 'block-contains' || relation === 'block-is-contained') {\n // Block containment - keep the element with smaller width\n if (rectA.width < rectB.width) {\n next = next.map(r => r === rectB ? rectA : r);\n }\n wasMerged = true;\n break;\n }\n }\n\n return wasMerged ? next : [ ...next, rectA ];\n}, []);\n\nexport const toDomRectList = (rects: DOMRect[]): DOMRectList => ({\n length: rects.length,\n item: (index) => rects[index],\n [Symbol.iterator]: function* (): ArrayIterator<DOMRect> {\n for (let i = 0; i < this.length; i++)\n yield this.item(i)!;\n }\n})\n\n/* Pixels that rects can be apart vertically while still\n// being considered to be on the same line.\nconst TOLERANCE = 3;\n\nexport const mergeClientRects = (rects: DOMRect[]) => {\n const lines: DOMRect[][] = [];\n\n // Sort rects from the top, to make grouping simpler\n rects.sort((a, b) => a.top - b.top);\n\n // Group rects into lines\n for (const rect of rects) {\n if (lines.length === 0 || Math.abs(rect.top - lines[lines.length - 1][0].top) > TOLERANCE) {\n // Start a new line\n lines.push([rect]);\n } else {\n lines[lines.length - 1].push(rect);\n }\n }\n\n // Merge lines\n const mergedRects = lines.map(line => {\n const top = Math.min(...line.map(r => r.top));\n const bottom = Math.max(...line.map(r => r.bottom));\n const left = Math.min(...line.map(r => r.left));\n const right = Math.max(...line.map(r => r.right));\n\n return {\n top: top,\n bottom: bottom,\n left: left,\n right: right,\n height: bottom - top,\n width: right - left\n } as DOMRect;\n }).filter(r => r.height > 0 && r.width > 0);\n\n // Checks if the given rect contains any other rects\n const containsOthers = (rect: DOMRect) => mergedRects.some(other =>\n other !== rect &&\n other.left >= rect.left &&\n other.right <= rect.right &&\n other.top >= rect.top &&\n other.bottom <= rect.bottom\n );\n\n // Remove all rects that contain other rects (block-level elements!)\n return mergedRects.filter(rect => !containsOthers(rect));\n}\n*/\n","import { getRangeAnnotatableContents } from './splitAnnotatableRanges';\nimport type { TextSelector } from '../model';\n\nexport const rangeToSelector = (\n range: Range,\n container: HTMLElement,\n offsetReferenceSelector?: string\n): TextSelector => {\n const rangeBefore = document.createRange();\n\n const offsetReference: HTMLElement = offsetReferenceSelector\n ? (range.startContainer.parentElement as HTMLElement).closest(offsetReferenceSelector)!\n : container;\n\n // A helper range from the start of the container to the start of the selection\n rangeBefore.setStart(offsetReference, 0);\n rangeBefore.setEnd(range.startContainer, range.startOffset);\n\n // A content range before content w/o not annotatable elements\n const before = getRangeAnnotatableContents(rangeBefore).textContent;\n\n const quote = range.toString();\n const start = before.length || 0;\n const end = start + quote.length;\n\n return offsetReferenceSelector\n ? { quote, start, end, range, offsetReference }\n : { quote, start, end, range };\n}\n","import type { TextSelector } from '../model';\nimport { NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\n/**\n * Creates a new selector object with the revived DOM range from the given text annotation position\n * Only the annotatable elements are processed and counted towards the range\n *\n * @param selector annotation selector with start and end positions\n * @param container the HTML container of the annotated content\n *\n * @returns the revived selector\n */\nexport const reviveSelector = <T extends TextSelector>(selector: T, container: HTMLElement): T => {\n\n const { start, end } = selector;\n\n const offsetReference = selector.offsetReference || container;\n\n const iterator = document.createNodeIterator(container, NodeFilter.SHOW_TEXT, (node) =>\n node.parentElement?.closest(NOT_ANNOTATABLE_SELECTOR)\n ? NodeFilter.FILTER_SKIP\n : NodeFilter.FILTER_ACCEPT\n );\n\n // Position that contains the length of the preceding annotatable text nodes\n let runningOffset = 0;\n\n const range = document.createRange();\n\n let n = iterator.nextNode();\n if (n === null) console.error('Could not revive annotation target. Content missing.');\n\n // If there's no offset reference, start immediately\n let startCounting = !offsetReference;\n while (n !== null) {\n startCounting ||= (typeof offsetReference?.contains === 'function') ? offsetReference.contains(n) : false;\n\n if (startCounting) {\n const len = n.textContent?.length || 0;\n\n if (runningOffset + len > start) {\n range.setStart(n, start - runningOffset);\n break;\n }\n\n runningOffset += len;\n }\n\n n = iterator.nextNode();\n }\n\n // set range end\n while (n !== null) {\n const len = n.textContent?.length || 0;\n\n if (runningOffset + len >= end) {\n range.setEnd(n, end - runningOffset);\n break;\n }\n\n runningOffset += len;\n\n n = iterator.nextNode();\n }\n \n return {\n ...selector,\n range\n }\n\n}\n","import type { TextAnnotationTarget } from '../model';\nimport { isRevived } from './isRevived';\nimport { reviveSelector } from './reviveSelector';\n\nexport const reviveTarget = <T extends TextAnnotationTarget = TextAnnotationTarget>(target: T, container: HTMLElement): T =>\n isRevived(target.selector)\n ? target\n : ({\n ...target,\n selector: target.selector.map(s => s.range instanceof Range && !s.range.collapsed ? s : reviveSelector(s, container))\n });\n\n\n","import type { TextAnnotation } from '../model';\nimport { isRevived } from './isRevived';\nimport { reviveTarget } from './reviveTarget';\n\nexport const reviveAnnotation = <T extends TextAnnotation>(annotation: T, container: HTMLElement): T =>\n isRevived(annotation.target.selector)\n ? annotation\n : ({ ...annotation, target: reviveTarget(annotation.target, container) });","export const trimRangeToContainer = (\n range: Range,\n container: HTMLElement\n): Range => {\n const trimmedRange = range.cloneRange();\n\n // If the start is outside the container - set it to the start of the container\n if (!container.contains(trimmedRange.startContainer)) {\n trimmedRange.setStart(container, 0);\n }\n\n // If the end is outside the container - set it to the end of the container\n if (!container.contains(trimmedRange.endContainer)) {\n trimmedRange.setEnd(container, container.childNodes.length);\n }\n\n return trimmedRange;\n};\n","import type { TextAnnotationStore } from '../state';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport { reviveTarget } from '../utils';\n\nconst getScrollParent = (el: Element) => {\n if (el === null)\n return document.scrollingElement;\n\n const { overflowY } = window.getComputedStyle(el);\n const isScrollable = overflowY !== 'visible' && overflowY !== 'hidden';\n\n // Cf. discussion https://stackoverflow.com/questions/35939886/find-first-scrollable-parent\n if (isScrollable && el.scrollHeight > el.clientHeight)\n return el;\n else\n return getScrollParent(el.parentElement);\n};\n\nexport const scrollIntoView = (\n container: HTMLElement, store: TextAnnotationStore\n) => (annotationOrId: string | TextAnnotation) => {\n const id =\n typeof annotationOrId === 'string' ? annotationOrId : annotationOrId.id;\n\n // Executes scroll on an annotation with a valid DOM range selector\n const scroll = (target: TextAnnotationTarget) => {\n // Parent bounds and client (= visible) height\n const parentBounds = scrollParent.getBoundingClientRect();\n const parentHeight = scrollParent.clientHeight;\n const parentWidth = scrollParent.clientWidth;\n\n // Position of the annotation relative to viewport\n // Note: first selector is not necessarily top one...\n const annotationBounds = target.selector[0].range.getBoundingClientRect();\n\n // Note: getBoundingClientRect seems to return wrong height! \n // (Includes block elements?) We'll therefore use the normalized height\n // from the spatial index!\n const { width, height } = store.getAnnotationBounds(id);\n\n // Position of the annotation relative to scrollParent\n const offsetTop = annotationBounds.top - parentBounds.top;\n const offsetLeft = annotationBounds.left - parentBounds.left;\n\n const scrollTop = scrollParent.parentElement ? scrollParent.scrollTop : 0;\n const scrollLeft = scrollParent.parentElement ? scrollParent.scrollLeft : 0;\n\n // Scroll the annotation to the center of the viewport\n const top = offsetTop + scrollTop - (parentHeight - height) / 2;\n const left = offsetLeft + scrollLeft - (parentWidth - width) / 2;\n\n scrollParent.scroll({ top, left, behavior: 'smooth' });\n };\n\n // Get closest scrollable parent\n const scrollParent: Element = getScrollParent(container);\n\n if (!scrollParent) {\n console.warn(`The scroll parent is missing for the annotation: ${id}`, { container });\n return false;\n }\n\n // Get curren version of the annotation from the store\n const current = store.getAnnotation(id);\n if (!current) {\n console.warn(`The annotation is missing in the store: ${id}`);\n return false;\n }\n\n // The 1st selector is the topmost one as well\n const { range: annoRange } = current.target.selector[0];\n if (annoRange && !annoRange.collapsed) {\n scroll(current.target);\n return true;\n }\n\n // Try reviving to account for lazy rendering\n const revived = reviveTarget(current.target, container);\n const { range: revivedAnnoRange } = revived.selector[0];\n if (revivedAnnoRange && !revivedAnnoRange.collapsed) {\n scroll(revived);\n return true;\n }\n\n return false;\n};\n","import type { AnnotationState, Color, DrawingStyle } from '@annotorious/core';\nimport type { TextAnnotation } from 'src/model';\n\nexport interface HighlightStyle extends Pick<DrawingStyle, 'fill' | 'fillOpacity'> {\n\n underlineStyle?: string;\n\n underlineColor?: Color;\n\n underlineOffset?: number;\n\n underlineThickness?: number;\n \n}\n\nexport type HighlightStyleExpression = HighlightStyle \n | (<I extends TextAnnotation = TextAnnotation>(annotation: I, state: AnnotationState, zIndex?: number) => HighlightStyle | undefined);\n\nexport const DEFAULT_STYLE: HighlightStyle = { \n fill: 'rgb(0, 128, 255)', \n fillOpacity: 0.18\n};\n\nexport const DEFAULT_SELECTED_STYLE: HighlightStyle = { \n fill: 'rgb(0, 128, 255)', \n fillOpacity: 0.45 \n};\n","\nimport type { Highlight } from './Highlight';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE } from './HighlightStyle';\nimport type { HighlightStyle, HighlightStyleExpression } from './HighlightStyle';\nimport type { ViewportBounds } from './viewport';\n\nexport interface HighlightPainter {\n\n clear(): void;\n\n destroy(): void;\n\n paint(highlight: Highlight, viewportBounds: ViewportBounds): HighlightStyle;\n\n reset(): void;\n\n}\n\n/** Helper **/\nexport const paint = (\n highlight: Highlight,\n viewportBounds: ViewportBounds,\n style?: HighlightStyleExpression, \n painter?: HighlightPainter,\n zIndex?: number\n) => {\n const base: HighlightStyle = style \n ? typeof style === 'function' \n ? style(highlight.annotation, highlight.state, zIndex) || (\n highlight.state?.selected ? DEFAULT_SELECTED_STYLE : DEFAULT_STYLE\n )\n : style \n : highlight.state?.selected \n ? DEFAULT_SELECTED_STYLE \n : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n return painter ? painter.paint(highlight, viewportBounds) || base : base;\n}","import type { ViewportState } from '@annotorious/core';\nimport type { TextAnnotation } from '../model';\n\nexport interface ViewportBounds {\n\n top: number;\n\n left: number;\n\n minX: number;\n\n minY: number;\n \n maxX: number;\n \n maxY: number;\n\n}\n\nexport const getViewportBounds = (container: HTMLElement): ViewportBounds => {\n const { top, left } = container.getBoundingClientRect();\n\n const { innerWidth, innerHeight } = window;\n\n const minX = - left;\n const minY = - top;\n const maxX = innerWidth - left;\n const maxY = innerHeight - top;\n\n return { top, left, minX, minY, maxX, maxY };\n}\n\nexport const trackViewport = (viewport: ViewportState) => {\n let visible = new Set<string>();\n\n const onDraw = (annotations: TextAnnotation[]) => {\n const ids = annotations.map(a => a.id);\n\n if (visible.size !== ids.length || ids.some(id => !visible.has(id))) {\n viewport.set(ids);\n } \n\n visible = new Set(ids);\n }\n\n return onDraw;\n\n}","import type { Filter, ViewportState } from '@annotorious/core';\nimport type { TextAnnotatorState } from '../state';\nimport { debounce } from '../utils';\nimport { type ViewportBounds, getViewportBounds, trackViewport } from './viewport';\nimport type { HighlightPainter } from './HighlightPainter';\nimport type { Highlight } from './Highlight';\nimport type { HighlightStyleExpression } from './HighlightStyle';\n\nexport interface RendererImplementation {\n\n destroy(): void;\n\n redraw(\n\n highlights:Highlight[], \n\n bounds: ViewportBounds, \n \n style?: HighlightStyleExpression,\n\n painter?: HighlightPainter,\n\n lazy?: boolean\n \n ): void;\n\n setVisible(visible: boolean): void;\n\n}\n\nexport interface Renderer {\n\n destroy(): void;\n\n redraw(force?: boolean): void;\n\n setStyle(style?: HighlightStyleExpression): void;\n\n setFilter(filter?: Filter): void;\n\n setPainter(painter?: HighlightPainter): void;\n\n setVisible(visible: boolean): void;\n\n}\n\nexport const createBaseRenderer = <T extends TextAnnotatorState = TextAnnotatorState> (\n container: HTMLElement, \n state: T,\n viewport: ViewportState,\n renderer: RendererImplementation\n): Renderer => {\n const { store, selection, hover } = state;\n\n let currentStyle: HighlightStyleExpression | undefined;\n\n let currentFilter: Filter | undefined;\n\n let currentPainter: HighlightPainter;\n\n const onDraw = trackViewport(viewport);\n\n const onPointerMove = (event: PointerEvent) => {\n const {x, y} = container.getBoundingClientRect();\n\n const hit = store.getAt(event.clientX - x, event.clientY - y, false, currentFilter);\n if (hit) {\n if (hover.current !== hit.id) {\n container.classList.add('hovered');\n hover.set(hit.id);\n }\n } else {\n if (hover.current) {\n container.classList.remove('hovered');\n hover.set(null);\n }\n }\n }\n\n container.addEventListener('pointermove', onPointerMove);\n\n const redraw = (lazy: boolean = false) => {\n if (currentPainter)\n currentPainter.clear();\n\n const bounds = getViewportBounds(container); \n\n const { minX, minY, maxX, maxY } = bounds;\n \n const annotationsInView = currentFilter\n ? store.getIntersecting(minX, minY, maxX, maxY).filter(({ annotation }) => currentFilter(annotation))\n : store.getIntersecting(minX, minY, maxX, maxY);\n\n const selectedIds = selection.selected.map(({ id }) => id);\n\n const highlights: Highlight[] = annotationsInView.map(({ annotation, rects }) => {\n const selected = selectedIds.includes(annotation.id);\n const hovered = annotation.id === hover.current;\n\n return {\n annotation,\n rects,\n state: { selected, hovered }\n };\n });\n\n renderer.redraw(highlights, bounds, currentStyle, currentPainter, lazy);\n\n setTimeout(() => onDraw(annotationsInView.map(({ annotation }) => annotation)), 1);\n }\n\n const setPainter = (painter: HighlightPainter) => { \n currentPainter = painter;\n redraw();\n }\n\n const setStyle = (style?: HighlightStyleExpression) => {\n currentStyle = style;\n redraw();\n }\n\n const setFilter = (filter?: Filter) => {\n currentFilter = filter;\n redraw(false);\n } \n\n // Refresh on store change\n const onStoreChange = () => redraw();\n store.observe(onStoreChange);\n\n // Refresh on selection change\n const unsubscribeSelection = selection.subscribe(() => redraw());\n\n // Refresh on hover change\n const unsubscribeHover = hover.subscribe(() => redraw());\n\n // Refresh on scroll\n const onScroll = () => redraw(true);\n\n document.addEventListener('scroll', onScroll, { capture: true, passive: true });\n\n // Refresh on resize\n const onResize = debounce(() => {\n store.recalculatePositions();\n\n if (currentPainter)\n currentPainter.reset();\n\n redraw();\n });\n\n window.addEventListener('resize', onResize);\n\n const resizeObserver = new ResizeObserver(onResize);\n resizeObserver.observe(container);\n\n // This is an extra precaution. The position of the container\n // might shift (without resizing) due to layout changes higher-up\n // in the DOM. (This happens in Recogito for example)\n const config: MutationObserverInit = { attributes: true, childList: true, subtree: true };\n\n const mutationObserver = new MutationObserver(debounce((records: MutationRecord[]) => {\n const isInternal = records\n .every(record => record.target === container || container.contains(record.target));\n\n if (!isInternal)\n redraw(true);\n }, 150));\n\n mutationObserver.observe(document.body, config);\n\n const destroy = () => {\n container.removeEventListener('pointermove', onPointerMove);\n \n renderer.destroy();\n \n store.unobserve(onStoreChange);\n\n unsubscribeSelection();\n unsubscribeHover();\n\n document.removeEventListener('scroll', onScroll);\n\n window.removeEventListener('resize', onResize);\n resizeObserver.disconnect();\n\n mutationObserver.disconnect();\n }\n\n return {\n destroy,\n redraw,\n setStyle,\n setFilter,\n setPainter,\n setVisible: renderer.setVisible\n }\n\n}\n","import type { ViewportState } from '@annotorious/core';\nimport type { TextAnnotatorState } from '../../state';\nimport { debounce } from '../../utils';\nimport type { ViewportBounds } from '../viewport';\nimport type { HighlightStyle } from '../HighlightStyle';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';\nimport type { HighlightPainter } from '../HighlightPainter';\nimport { createBaseRenderer, type RendererImplementation } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport type { TextAnnotation } from 'src/model';\n\nimport './canvasRenderer.css';\n\nconst createCanvas = () => {\n const canvas = document.createElement('canvas');\n canvas.width = window.innerWidth;\n canvas.height = window.innerHeight;\n canvas.className = 'r6o-canvas-highlight-layer bg';\n return canvas;\n}\n\nconst resetCanvas = (canvas: HTMLCanvasElement, highres?: boolean) => {\n canvas.width = highres ? 2 * window.innerWidth : window.innerWidth;\n canvas.height = highres ? 2 * window.innerHeight : window.innerHeight;\n\n if (highres) {\n // Note that resizing the canvas resets the context\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n }\n}\n\nconst createRenderer = (container: HTMLElement): RendererImplementation => {\n\n container.classList.add('r6o-annotatable');\n\n const canvas = createCanvas();\n const ctx = canvas.getContext('2d');\n\n document.body.appendChild(canvas);\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n currentPainter?: HighlightPainter\n ) => requestAnimationFrame(() => {\n\n const { width, height } = canvas;\n\n // New render loop - clear canvases\n ctx.clearRect(-0.5, -0.5, width + 1, height + 1);\n\n if (currentPainter)\n currentPainter.clear();\n\n const { top, left } = viewportBounds;\n\n /**\n * Highlights rendering on the canvas is an order-sensitive operation.\n * The later the highlight is rendered, the higher it will be in the visual stack.\n *\n * By default, we should expect that the newer highlight\n * will be rendered over the older one\n */\n const highlightsByCreation = [...highlights].sort((highlightA, highlightB) => {\n const { annotation: { target: { created: createdA } } } = highlightA;\n const { annotation: { target: { created: createdB } } } = highlightB;\n return createdA.getTime() - createdB.getTime();\n });\n\n highlightsByCreation.forEach(h => {\n const base: HighlightStyle = currentStyle\n ? typeof currentStyle === 'function'\n ? currentStyle(h.annotation, h.state)\n : currentStyle\n : h.state?.selected\n ? DEFAULT_SELECTED_STYLE\n : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n const style = currentPainter ? currentPainter.paint(h, viewportBounds) || base : base;\n\n // Offset annotation rects by current scroll position\n const offsetRects = h.rects.map(({ x, y, width, height }) => ({\n x: x + left,\n y: y + top,\n width,\n height\n }));\n\n ctx.fillStyle = style.fill;\n ctx.globalAlpha = style.fillOpacity || 1;\n\n offsetRects.forEach(({ x, y, width, height }) =>\n ctx.fillRect(x, y, width, height)\n );\n\n if (style.underlineColor) {\n ctx.globalAlpha = 1;\n ctx.strokeStyle = style.underlineColor;\n ctx.lineWidth = style.underlineThickness ?? 1;\n\n // Place the underline below the highlighted text + an optional offset\n const underlineOffset = style.underlineOffset ?? 0;\n\n offsetRects.forEach(({ x, y, width, height }) => {\n ctx.beginPath();\n ctx.moveTo(x, y + height + underlineOffset);\n ctx.lineTo(x + width, y + height + underlineOffset);\n\n // Draw the Path\n ctx.stroke();\n });\n }\n });\n });\n\n const onResize = debounce(() => {\n resetCanvas(canvas);\n });\n\n window.addEventListener('resize', onResize);\n\n const setVisible = (visible: boolean) => {\n console.log('setVisible not implemented on Canvas renderer');\n }\n\n const destroy = () => {\n canvas.remove();\n\n window.removeEventListener('resize', onResize);\n }\n\n return {\n destroy,\n setVisible,\n redraw\n };\n\n};\n\nexport const createCanvasRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer(container));\n","import type { ViewportState } from '@annotorious/core';\nimport { colord } from 'colord';\nimport type { HighlightPainter } from '../HighlightPainter';\nimport type { TextAnnotatorState } from 'src/state';\nimport type { ViewportBounds } from '../viewport';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE } from '../HighlightStyle';\nimport type { HighlightStyle, HighlightStyleExpression } from '../HighlightStyle';\nimport { type RendererImplementation, createBaseRenderer } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport type { TextAnnotation } from 'src/model';\n\nconst toCSS = (s?: HighlightStyle) => {\n const backgroundColor = colord(s?.fill || DEFAULT_STYLE.fill)\n .alpha(s?.fillOpacity === undefined ? DEFAULT_STYLE.fillOpacity : s.fillOpacity)\n .toHex();\n\n const rules = [\n `background-color:${backgroundColor}`,\n s?.underlineThickness ? `text-decoration:underline` : undefined,\n s?.underlineColor ? `text-decoration-color:${s.underlineColor}` : undefined,\n s?.underlineOffset ? `text-underline-offset:${s.underlineOffset}px` : undefined,\n s?.underlineThickness ? `text-decoration-thickness:${s.underlineThickness}px` : undefined\n ].filter(Boolean);\n\n return rules.join(';');\n}\n\nexport const createRenderer = (): RendererImplementation => {\n const elem = document.createElement('style');\n document.getElementsByTagName('head')[0].appendChild(elem);\n\n let currentRendered = new Set<string>();\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n painter?: HighlightPainter\n ) => {\n if (painter)\n painter.clear();\n\n // Next set of rendered annotation IDs and selections\n const nextRendered = new Set(highlights.map(h => h.annotation.id));\n\n // Annotations currently in this stylesheet that no longer need rendering\n const toRemove = Array.from(currentRendered).filter(id => !nextRendered.has(id));\n\n // For simplicity, re-generate the whole stylesheet\n const updatedCSS = highlights.map(h => {\n const base = currentStyle\n ? typeof currentStyle === 'function'\n ? currentStyle(h.annotation, h.state)\n : currentStyle\n : h.state?.selected ? DEFAULT_SELECTED_STYLE : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n const style = painter ? painter.paint(h, viewportBounds) || base : base;\n\n return `::highlight(_${h.annotation.id}) { ${toCSS(style)} }`;\n });\n\n elem.innerHTML = updatedCSS.join('\\n');\n\n // After we have the styles, we need to update the Highlights.\n // Note that the (experimental) CSS Custom Highlight API is not yet\n // available in TypeScript!\n\n // @ts-ignore\n CSS.highlights.clear();\n // toRemove.forEach(id => CSS.highlights.delete(`_${id}`));\n\n // Could be improved further by (re-)setting only annotations that\n // have changes.\n highlights.forEach(({ annotation }) => {\n const ranges = annotation.target.selector.map(s => s.range);\n\n // @ts-ignore\n const highlights = new Highlight(...ranges);\n\n // @ts-ignore\n CSS.highlights.set(`_${annotation.id}`, highlights);\n });\n\n currentRendered = nextRendered;\n }\n\n const setVisible = (visible: boolean) => {\n console.log('setVisible not implemented on CSS Custom Highlights renderer');\n }\n\n const destroy = () => {\n // Clear all highlights from the Highlight Registry\n // @ts-ignore\n CSS.highlights.clear();\n\n // Remove the stylesheet\n elem.remove();\n }\n\n return {\n destroy,\n setVisible,\n redraw\n };\n\n}\n\nexport const createHighlightsRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer());\n","import type { ViewportState } from '@annotorious/core';\nimport { colord } from 'colord';\nimport { dequal } from 'dequal/lite';\nimport type { Rect, TextAnnotatorState } from '../../state';\nimport { type HighlightPainter, paint } from '../HighlightPainter';\nimport type { ViewportBounds } from '../viewport';\nimport { createBaseRenderer, type RendererImplementation } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport { DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';\nimport type { TextAnnotation } from 'src/model';\n\nimport './spansRenderer.css';\n\nconst computeZIndex = (rect: Rect, all: Highlight[]): number => {\n const intersects = (a: Rect, b: Rect): boolean => (\n a.x <= b.x + b.width && a.x + a.width >= b.x &&\n a.y <= b.y + b.height && a.y + a.height >= b.y\n )\n\n const getLength = (h: Highlight) => \n h.rects.reduce((total, rect) => total + rect.width, 0);\n\n // Any highlights that intersect this rect, sorted by total length\n const intersecting = all.filter(({ rects }) => rects.some(r => intersects(rect, r)));\n intersecting.sort((a, b) => getLength(b) - getLength(a));\n\n return intersecting.findIndex(h => h.rects.includes(rect));\n}\n\nconst createRenderer = (container: HTMLElement): RendererImplementation => {\n\n container.classList.add('r6o-annotatable');\n\n const highlightLayer = document.createElement('div');\n highlightLayer.className = 'r6o-span-highlight-layer';\n\n container.insertBefore(highlightLayer, container.firstChild);\n\n // Currently rendered highlights\n let currentRendered: Highlight[] = [];\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n painter?: HighlightPainter,\n lazy?: boolean\n ) => {\n const noChanges = dequal(currentRendered, highlights);\n\n // If there are no changes and rendering is set to lazy\n // Don't redraw the SPANs - but redraw the painter, if any!\n const shouldRedraw = !(noChanges && lazy);\n\n if (!painter && !shouldRedraw) return;\n\n if (shouldRedraw)\n highlightLayer.innerHTML = '';\n\n /**\n * Highlights rendering in the span highlight layer is an order-sensitive operation.\n * The later the highlight is rendered, the higher it will be in the visual stack.\n *\n * By default, we should expect that the newer highlight\n * will be rendered over the older one\n */\n const sorted = [...highlights].sort((highlightA, highlightB) => {\n const { annotation: { target: { created: createdA } } } = highlightA;\n const { annotation: { target: { created: createdB } } } = highlightB;\n return createdA && createdB ? createdA.getTime() - createdB.getTime() : 0;\n });\n\n sorted.forEach(highlight => {\n highlight.rects.map(rect => {\n const zIndex = computeZIndex(rect, highlights);\n const style = paint(highlight, viewportBounds, currentStyle, painter, zIndex);\n\n if (shouldRedraw) {\n const span = document.createElement('span');\n span.className = 'r6o-annotation';\n span.dataset.annotation = highlight.annotation.id;\n\n span.style.left = `${rect.x}px`;\n span.style.top = `${rect.y}px`;\n span.style.width = `${rect.width}px`;\n span.style.height = `${rect.height}px`;\n\n span.style.backgroundColor = colord(style?.fill || DEFAULT_STYLE.fill)\n .alpha(style?.fillOpacity === undefined ? DEFAULT_STYLE.fillOpacity : style.fillOpacity)\n .toHex();\n\n if (style.underlineStyle)\n span.style.borderStyle = style.underlineStyle;\n\n if (style.underlineColor)\n span.style.borderColor = style.underlineColor;\n\n if (style.underlineThickness)\n span.style.borderBottomWidth = `${style.underlineThickness}px`;\n\n if (style.underlineOffset)\n span.style.paddingBottom = `${style.underlineOffset}px`;\n\n highlightLayer.appendChild(span);\n }\n });\n });\n\n currentRendered = highlights;\n }\n\n const setVisible = (visible: boolean) => {\n if (visible)\n highlightLayer.classList.remove('hidden');\n else\n highlightLayer.classList.add('hidden');\n }\n\n const destroy = () => {\n highlightLayer.remove();\n }\n\n return {\n destroy,\n redraw,\n setVisible\n };\n\n}\n\nexport const createSpansRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer(container));\n","import { v4 as uuidv4 } from 'uuid';\nimport {\n type FormatAdapter,\n type ParseResult,\n parseW3CBodies,\n parseW3CUser,\n serializeW3CBodies\n} from '@annotorious/core';\nimport type { TextAnnotation, TextAnnotationTarget, TextSelector } from '../core';\nimport type { W3CTextAnnotation, W3CTextAnnotationTarget, W3CTextSelector } from '../w3c';\nimport { getQuoteContext } from '../../utils';\n\nexport type W3CTextFormatAdapter<I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation> = FormatAdapter<I, E>;\n\n/**\n * @param source - the IRI of the annotated content\n * @param container - the HTML container of the annotated content,\n * Required to locate the content's `range` within the DOM\n */\nexport const W3CTextFormat =<I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n source: string,\n container?: HTMLElement\n): W3CTextFormatAdapter<I, E> => ({\n parse: (serialized) => parseW3CTextAnnotation(serialized),\n serialize: (annotation) => serializeW3CTextAnnotation(annotation, source, container)\n});\n\nconst isTextSelector = (selector: Partial<TextSelector>): selector is TextSelector =>\n selector.quote !== undefined && selector.start !== undefined && selector.end !== undefined;\n\nconst parseW3CTextTargets = (annotation: W3CTextAnnotation) => {\n const {\n id: annotationId,\n creator,\n created,\n modified,\n target\n } = annotation;\n\n const w3cTargets = Array.isArray(target) ? target : [target];\n if (w3cTargets.length === 0) {\n return { error: Error(`No targets found for annotation: ${annotation.id}`) };\n }\n\n const parsed: TextAnnotationTarget = {\n creator: parseW3CUser(creator),\n created: created ? new Date(created) : undefined,\n updated: modified ? new Date(modified) : undefined,\n annotation: annotationId,\n selector: [],\n // @ts-expect-error: `styleClass` is not part of the core `TextAnnotationTarget` type\n styleClass: 'styleClass' in w3cTargets[0] ? w3cTargets[0].styleClass : undefined\n };\n\n for (const w3cTarget of w3cTargets) {\n const w3cSelectors = Array.isArray(w3cTarget.selector) ? w3cTarget.selector : [w3cTarget.selector];\n\n const selector = w3cSelectors.reduce<Partial<TextSelector>>((s, w3cSelector) => {\n switch (w3cSelector.type) {\n case 'TextQuoteSelector':\n s.quote = w3cSelector.exact;\n break;\n case 'TextPositionSelector':\n s.start = w3cSelector.start;\n s.end = w3cSelector.end;\n break;\n }\n return s;\n }, {});\n\n if (isTextSelector(selector)) {\n parsed.selector.push(\n {\n ...selector,\n id: w3cTarget.id,\n // @ts-expect-error: `scope` is not part of the core `TextSelector` type\n scope: w3cTarget.scope\n }\n );\n } else {\n const missingTypes = [\n !selector.start ? 'TextPositionSelector' : undefined,\n !selector.quote ? 'TextQuoteSelector' : undefined\n ].filter(Boolean);\n\n return { error: Error(`Missing selector types: ${missingTypes.join(' and ')} for annotation: ${annotation.id}`) };\n }\n }\n\n return { parsed };\n};\n\nexport const parseW3CTextAnnotation = <I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n annotation: E\n): ParseResult<I> => {\n const annotationId = annotation.id || uuidv4();\n\n const {\n creator,\n created,\n modified,\n body,\n ...rest\n } = annotation;\n\n const bodies = parseW3CBodies(body, annotationId);\n const target = parseW3CTextTargets(annotation);\n\n const parseResult = 'error' in target\n ? { error: target.error }\n : {\n parsed: {\n ...rest,\n id: annotationId,\n bodies,\n target: target.parsed\n }\n };\n\n return parseResult as ParseResult<I>;\n\n};\n\nexport const serializeW3CTextAnnotation = <I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n annotation: I,\n source: string,\n container?: HTMLElement\n): E => {\n const { bodies, target, ...rest } = annotation;\n\n const {\n selector,\n creator,\n created,\n updated,\n ...targetRest\n } = target;\n\n const w3cTargets = selector.map((s): W3CTextAnnotationTarget => {\n const { id, quote, start, end, range } = s;\n\n const quoteSelector: W3CTextSelector = {\n type: 'TextQuoteSelector',\n exact: quote\n }\n\n if (container) {\n const { prefix, suffix } = getQuoteContext(range, container);\n quoteSelector.prefix = prefix;\n quoteSelector.suffix = suffix;\n }\n\n const positionSelector: W3CTextSelector = {\n type: 'TextPositionSelector',\n start,\n end\n }\n\n return {\n ...targetRest,\n id,\n // @ts-expect-error: `scope` is not part of the core `TextSelector` type\n scope: 'scope' in s ? s.scope : undefined,\n source,\n selector: [quoteSelector, positionSelector]\n };\n });\n\n return {\n ...rest,\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n id: annotation.id,\n type: 'Annotation',\n body: serializeW3CBodies(annotation.bodies),\n creator,\n created: created?.toISOString(),\n modified: updated?.toISOString(),\n target: w3cTargets\n } as unknown as E;\n\n};\n","import RBush from 'rbush';\nimport type { Store } from '@annotorious/core';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport { isRevived, reviveSelector, mergeClientRects } from '../utils';\nimport type { AnnotationRects } from './TextAnnotationStore';\n\ninterface IndexedHighlightRect {\n\n minX: number;\n\n minY: number;\n\n maxX: number;\n\n maxY: number;\n\n annotation: {\n \n id: string;\n\n rects: DOMRect[];\n\n }\n\n}\n\nexport const createSpatialTree = <T extends TextAnnotation>(store: Store<T>, container: HTMLElement) => {\n\n const tree = new RBush<IndexedHighlightRect>();\n\n const index = new Map<string, IndexedHighlightRect[]>();\n\n // Helper: converts a single text annotation target to a list of hightlight rects\n const toItems = (target: TextAnnotationTarget, offset: DOMRect): IndexedHighlightRect[] => {\n const rects = target.selector.flatMap(s => {\n const revivedRange = isRevived([s]) ? s.range : reviveSelector(s, container).range;\n return Array.from(revivedRange.getClientRects());\n });\n\n const merged = mergeClientRects(rects)\n // Offset the merged client rects so that coords\n // are relative to the parent container\n .map(({ left, top, right, bottom }) => \n new DOMRect(left - offset.left, top - offset.top, right - left, bottom - top));\n\n return merged.map(rect => {\n const { x, y, width, height } = rect;\n\n return {\n minX: x,\n minY: y,\n maxX: x + width,\n maxY: y + height,\n annotation: {\n id: target.annotation,\n rects: merged\n }\n }\n });\n }\n\n const all = () => [...index.values()];\n\n const clear = () => {\n tree.clear();\n index.clear();\n }\n\n const insert = (target: TextAnnotationTarget) => {\n const rects = toItems(target, container.getBoundingClientRect());\n if (rects.length === 0) return;\n\n rects.forEach(rect => tree.insert(rect));\n index.set(target.annotation, rects);\n }\n\n const remove = (target: TextAnnotationTarget) => {\n const rects = index.get(target.annotation);\n if (rects) {\n rects.forEach(rect => tree.remove(rect));\n index.delete(target.annotation);\n }\n }\n\n const update = (target: TextAnnotationTarget) => {\n remove(target);\n insert(target);\n }\n\n const set = (targets: TextAnnotationTarget[], replace: boolean = true) => {\n if (replace)\n clear();\n\n const offset = container.getBoundingClientRect();\n\n const rectsByTarget = targets.map(target => ({ target, rects: toItems(target, offset) }));\n rectsByTarget.forEach(({ target, rects }) => {\n if (rects.length > 0)\n index.set(target.annotation, rects)\n });\n\n const allRects = rectsByTarget.flatMap(({ rects }) => rects);\n tree.load(allRects);\n }\n\n const getAt = (x: number, y: number, all = false): string[] => {\n const hits = tree.search({\n minX: x,\n minY: y,\n maxX: x,\n maxY: y\n });\n\n const area = (rect: IndexedHighlightRect) =>\n rect.annotation.rects.reduce((area, r) =>\n area + r.width * r.height, 0);\n \n // Get smallest rect\n if (hits.length > 0) {\n hits.sort((a, b) => area(a) - area(b));\n return all ? hits.map(h => h.annotation.id) : [ hits[0].annotation.id ];\n } else {\n return [];\n }\n }\n\n const getAnnotationBounds = (id: string): DOMRect => {\n const rects = getAnnotationRects(id);\n\n if (rects.length === 0)\n return undefined;\n\n let left = rects[0].left;\n let top = rects[0].top;\n let right = rects[0].right;\n let bottom = rects[0].bottom;\n\n for (let i = 1; i < rects.length; i++) {\n const rect = rects[i];\n\n left = Math.min(left, rect.left);\n top = Math.min(top, rect.top);\n right = Math.max(right, rect.right);\n bottom = Math.max(bottom, rect.bottom);\n }\n\n return new DOMRect(left, top, right - left, bottom - top);\n }\n\n const getAnnotationRects = (id: string): DOMRect[] => {\n const indexed = index.get(id);\n if (indexed) {\n // Reminder: *each* IndexedHighlightRect stores *all*\n // DOMRects for the annotation for convenience\n return indexed[0].annotation.rects;\n } else {\n return [];\n }\n }\n\n const getIntersecting = (\n minX: number, \n minY: number, \n maxX: number, \n maxY: number,\n ): AnnotationRects<T>[] => {\n // All rects in this area, regardless of annotation\n const rects = tree.search({ minX, minY, maxX, maxY });\n\n // Distinct annotation IDs\n const annotationIds = new Set(rects.map(rect => rect.annotation.id));\n\n // Resolve annotation IDs. Note that the tree could be slightly out of sync (because \n // it updates by listening to changes, just like anyone else)\n return Array.from(annotationIds).map(annotationId => ({\n annotation: store.getAnnotation(annotationId),\n rects: getAnnotationRects(annotationId)\n })).filter(t => Boolean(t.annotation));\n }\n\n const size = () => tree.all().length;\n\n const recalculate = () =>\n set(store.all().map(a => a.target), true);\n\n return {\n all,\n clear,\n getAt,\n getAnnotationBounds,\n getAnnotationRects,\n getIntersecting,\n insert,\n recalculate,\n remove,\n set,\n size,\n update\n }\n\n}\n","import type { Filter, Store, ViewportState } from '@annotorious/core';\nimport { \n createHoverState, \n createSelectionState, \n createStore, \n Origin,\n createViewportState\n} from '@annotorious/core';\nimport type { \n AnnotatorState, \n SelectionState, \n HoverState, \n} from '@annotorious/core';\n\nimport { createSpatialTree } from './spatialTree';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport type { AnnotationRects, TextAnnotationStore } from './TextAnnotationStore';\nimport { isRevived, reviveAnnotation, reviveTarget } from '../utils';\nimport type { TextAnnotatorOptions } from '../TextAnnotatorOptions';\n\nexport interface TextAnnotatorState<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends AnnotatorState<I, E> {\n\n store: TextAnnotationStore<I>;\n\n selection: SelectionState<I, E>;\n\n hover: HoverState<I>;\n\n viewport: ViewportState;\n\n}\n\nexport const createTextAnnotatorState = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n container: HTMLElement,\n opts: TextAnnotatorOptions<I, E>\n): TextAnnotatorState<I, E> => {\n\n const store: Store<I> = createStore<I>();\n\n const tree = createSpatialTree(store, container);\n\n const selection = createSelectionState<I, E>(store, opts.userSelectAction, opts.adapter);\n\n const hover = createHoverState(store);\n\n const viewport = createViewportState();\n\n // Wrap store interface to intercept annotations and revive DOM ranges, if needed\n const addAnnotation = (annotation: I, origin = Origin.LOCAL): boolean => {\n const revived = reviveAnnotation(annotation, container);\n\n const isValid = isRevived(revived.target.selector);\n if (isValid)\n store.addAnnotation(revived, origin); \n\n return isValid;\n }\n\n const bulkAddAnnotations = (\n annotations: I[], \n replace = true, \n origin = Origin.LOCAL\n ): I[] => {\n const revived = annotations.map(a => reviveAnnotation<I>(a, container));\n\n // Initial page load might take some time. Retry for more robustness.\n const couldNotRevive = revived.filter(a => !isRevived(a.target.selector));\n store.bulkAddAnnotations(revived, replace, origin);\n\n return couldNotRevive;\n }\n \n const bulkUpsertAnnotations = (\n annotations: I[], \n origin = Origin.LOCAL\n ): I[] => {\n const revived = annotations.map(a => reviveAnnotation(a, container));\n\n // Initial page load might take some time. Retry for more robustness.\n const couldNotRevive = revived.filter(a => !isRevived(a.target.selector));\n \n revived.forEach(a => {\n if (store.getAnnotation(a.id))\n store.updateAnnotation(a, origin);\n else \n store.addAnnotation(a, origin);\n })\n\n return couldNotRevive;\n }\n\n const updateTarget = (target: TextAnnotationTarget, origin = Origin.LOCAL) => {\n const revived = reviveTarget(target, container);\n store.updateTarget(revived, origin);\n }\n\n const bulkUpdateTargets = (targets: TextAnnotationTarget[], origin = Origin.LOCAL) => {\n const revived = targets.map(t => reviveTarget(t, container));\n store.bulkUpdateTargets(revived, origin);\n }\n\n function getAt(x: number, y: number, all: true, filter?: Filter): I[] | undefined;\n function getAt(x: number, y: number, all: false, filter?: Filter): I | undefined;\n function getAt(x: number, y: number, all?: boolean, filter?: Filter): I | I[] | undefined {\n const getAll = all || Boolean(filter);\n\n const annotations = tree.getAt(x, y, getAll).map(id => store.getAnnotation(id));\n\n const filtered = filter ? annotations.filter(filter) : annotations;\n\n if (filtered.length === 0)\n return undefined;\n\n return all ? filtered : filtered[0];\n }\n\n const getAnnotationBounds = (id: string): DOMRect | undefined => {\n const rects = tree.getAnnotationRects(id);\n if (rects.length === 0) return;\n return tree.getAnnotationBounds(id);\n }\n\n const getIntersecting = (\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n ): AnnotationRects<I>[] => tree.getIntersecting(minX, minY, maxX, maxY);\n\n const getAnnotationRects = (id: string): DOMRect[] => tree.getAnnotationRects(id);\n\n const recalculatePositions = () => tree.recalculate();\n\n store.observe(({ changes }) => {\n const deleted = (changes.deleted || []).filter(a => isRevived(a.target.selector));\n const created = (changes.created || []).filter(a => isRevived(a.target.selector));\n const updated = (changes.updated || []).filter(u => isRevived(u.newValue.target.selector));\n\n if (deleted?.length > 0)\n deleted.forEach(a => tree.remove(a.target));\n\n if (created.length > 0)\n tree.set(created.map(a => a.target), false);\n\n if (updated?.length > 0)\n updated.forEach(({ newValue }) => tree.update(newValue.target));\n });\n\n return {\n store: {\n ...store,\n addAnnotation,\n bulkAddAnnotations,\n bulkUpdateTargets,\n bulkUpsertAnnotations,\n getAnnotationBounds,\n getAnnotationRects,\n getIntersecting,\n getAt,\n recalculatePositions,\n updateTarget\n },\n selection,\n hover,\n viewport\n }\n\n}\n","import type { Color, PresenceProvider, PresentUser } from '@annotorious/core';\nimport type { AnnotationRects } from '../state';\nimport type { HighlightStyle, HighlightPainter } from '../highlight';\nimport type { PresencePainterOptions } from '../presence';\nimport type { ViewportBounds } from '../highlight/viewport';\n\nimport './PresencePainter.css';\n\nconst createCanvas = () => {\n const canvas = document.createElement('canvas');\n\n // Retina resolution for crisp font rendering\n canvas.width = 2 * window.innerWidth;\n canvas.height = 2 * window.innerHeight;\n canvas.className = 'r6o-presence-layer';\n\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n\n return canvas;\n}\n\nexport const createPresencePainter = (\n provider: PresenceProvider, \n opts: PresencePainterOptions = {}\n): HighlightPainter => {\n\n const canvas = createCanvas();\n\n const ctx = canvas.getContext('2d');\n\n document.body.appendChild(canvas);\n\n const trackedAnnotations = new Map<string, PresentUser>();\n\n const getAnnotationsForUser = (p: PresentUser) =>\n Array.from(trackedAnnotations.entries())\n .filter(([id, user]) => user.presenceKey === p.presenceKey)\n .map(([id, _]) => id);\n\n provider.on('selectionChange', (p: PresentUser, selection: string[] | null) => {\n // Remove this user's previous selection\n const currentIds = getAnnotationsForUser(p);\n currentIds.forEach(id => trackedAnnotations.delete(id));\n\n // Set new selection (if any)\n if (selection)\n selection.forEach(id => trackedAnnotations.set(id, p));\n }); \n\n const clear = () => {\n const { width, height } = canvas;\n ctx.clearRect(-0.5, -0.5, width + 1, height + 1);\n }\n\n const paint = (\n highlight: AnnotationRects, \n viewportBounds: ViewportBounds,\n isSelected?: boolean\n ): HighlightStyle | undefined => {\n if (opts.font)\n ctx.font = opts.font;\n\n const user = trackedAnnotations.get(highlight.annotation.id);\n if (user) {\n // Draw cursor + label to the presence canvas\n const { height } = highlight.rects[0];\n const x = highlight.rects[0].x + viewportBounds.left;\n const y = highlight.rects[0].y + viewportBounds.top;\n\n // Draw presence indicator\n ctx.fillStyle = user.appearance.color;\n ctx.fillRect(x - 2, y - 2.5, 2, height + 5);\n\n // Draw name label\n const metrics = ctx.measureText(user.appearance.label);\n const labelWidth = metrics.width + 6;\n const labelHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + 8;\n \n // Sigh... different between FF and Chrome\n const paddingBottom = metrics.fontBoundingBoxAscent ? 8 : 6.5;\n\n ctx.fillRect(x - 2, y - 2.5 - labelHeight, labelWidth, labelHeight);\n \n ctx.fillStyle = '#fff';\n ctx.fillText(user.appearance.label, x + 1, y - paddingBottom);\n\n // Return modfied style for the renderer\n return { \n fill: user.appearance.color as Color,\n fillOpacity: isSelected ? 0.45 : 0.18\n }\n }\n }\n \n const reset = () => {\n canvas.width = 2 * window.innerWidth;\n canvas.height = 2 * window.innerHeight;\n\n // Note that resizing the canvas resets the context\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n }\n\n const destroy = () => {\n canvas.remove();\n }\n\n return {\n clear,\n destroy,\n paint,\n reset\n }\n \n}\n","import { Origin } from '@annotorious/core';\nimport type { Filter, Selection, User } from '@annotorious/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport hotkeys from 'hotkeys-js';\nimport { poll } from 'poll';\nimport type { TextAnnotatorState } from './state';\nimport type { TextAnnotation, TextAnnotationTarget } from './model';\nimport type { TextAnnotatorOptions } from './TextAnnotatorOptions';\nimport {\n clonePointerEvent,\n cloneKeyboardEvent,\n debounce,\n splitAnnotatableRanges,\n rangeToSelector,\n isMac,\n isWhitespaceOrEmpty,\n trimRangeToContainer,\n isNotAnnotatable\n} from './utils';\n\nconst CLICK_TIMEOUT = 300;\n\nconst ARROW_KEYS = ['up', 'down', 'left', 'right'];\n\nconst SELECT_ALL = isMac ? '⌘+a' : 'ctrl+a';\n\nconst SELECTION_KEYS = [\n ...ARROW_KEYS.map(key => `shift+${key}`),\n SELECT_ALL\n];\n\nexport const SelectionHandler = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n options: TextAnnotatorOptions<TextAnnotation, unknown>\n) => {\n\n let currentUser: User | undefined;\n\n const { annotatingEnabled, offsetReferenceSelector, selectionMode } = options;\n\n const setUser = (user?: User) => currentUser = user;\n\n let currentFilter: Filter | undefined;\n\n const setFilter = (filter?: Filter) => currentFilter = filter;\n\n const { store, selection } = state;\n\n let currentTarget: TextAnnotationTarget | undefined;\n\n let isLeftClick: boolean | undefined;\n\n let lastDownEvent: Selection['event'] | undefined;\n\n const onSelectStart = (evt: Event) => {\n if (isLeftClick === false)\n return;\n\n /**\n * Make sure we don't listen to selection changes that were\n * not started on the container, or which are not supposed to\n * be annotatable (like a component popup).\n * Note that Chrome/iOS will sometimes return the root doc as target!\n */\n currentTarget = isNotAnnotatable(container, evt.target as Node)\n ? undefined\n : {\n annotation: uuidv4(),\n selector: [],\n creator: currentUser,\n created: new Date()\n };\n };\n\n const onSelectionChange = debounce((evt: Event) => {\n const sel = document.getSelection();\n\n /**\n * In iOS when a user clicks on a button, the `selectionchange` event is fired.\n * However, the generated selection is empty and the `anchorNode` is `null`. That\n * doesn't give us information about whether the selection is in the annotatable area\n * or whether the previously selected text was dismissed. Therefore we should bail\n * out from such a range processing.\n *\n * @see https://github.com/recogito/text-annotator-js/pull/164#issuecomment-2416961473\n */\n if (!sel?.anchorNode) {\n return;\n }\n\n /**\n * This is to handle cases where the selection is \"hijacked\" by\n * another element in a not-annotatable area. A rare case in practice.\n * But rich text editors like Quill will do it!\n */\n if (isNotAnnotatable(container, sel.anchorNode)) {\n currentTarget = undefined;\n return;\n }\n\n const timeDifference = evt.timeStamp - (lastDownEvent?.timeStamp || evt.timeStamp);\n\n /**\n * The selection start needs to be emulated only for the pointer events!\n * The keyboard ones are consistently fired on desktops\n * and the `timeDifference` will always be <10ms. between the `keydown` and `selectionchange`\n */\n if (lastDownEvent?.type === 'pointerdown') {\n if (timeDifference < 1000 && !currentTarget) {\n // Chrome/iOS does not reliably fire the 'selectstart' event!\n onSelectStart(lastDownEvent || evt);\n } else if (sel.isCollapsed && timeDifference < CLICK_TIMEOUT) {\n // Firefox doesn't fire the 'selectstart' when user clicks\n // over the text, which collapses the selection\n onSelectStart(lastDownEvent || evt);\n }\n }\n\n // The selection isn't active -> bail out from selection change processing\n if (!currentTarget) return;\n\n if (sel.isCollapsed) {\n /**\n * The selection range got collapsed during the selecting process.\n * The previously created annotation isn't relevant anymore and can be discarded\n *\n * @see https://github.com/recogito/text-annotator-js/issues/139\n */\n if (store.getAnnotation(currentTarget.annotation)) {\n selection.clear();\n store.deleteAnnotation(currentTarget.annotation);\n }\n\n return;\n }\n\n const selectionRanges =\n Array.from(Array(sel.rangeCount).keys()).map(idx => sel.getRangeAt(idx));\n\n const containedRanges =\n selectionRanges.map(r => trimRangeToContainer(r, container));\n\n // The selection should be captured only within the annotatable container\n if (containedRanges.every(r => isWhitespaceOrEmpty(r))) return;\n\n const annotatableRanges = containedRanges.flatMap(r => splitAnnotatableRanges(container, r.cloneRange()));\n\n const hasChanged =\n annotatableRanges.length !== currentTarget.selector.length ||\n annotatableRanges.some((r, i) => r.toString() !== currentTarget.selector[i]?.quote);\n\n if (!hasChanged) return;\n\n currentTarget = {\n ...currentTarget,\n selector: annotatableRanges.map(r => rangeToSelector(r, container, offsetReferenceSelector)),\n updated: new Date()\n };\n\n /**\n * During mouse selection on the desktop, the annotation won't usually exist while the selection is being edited.\n * But it'll be typical during selection via the keyboard or mobile's handlebars.\n */\n if (store.getAnnotation(currentTarget.annotation)) {\n store.updateTarget(currentTarget, Origin.LOCAL);\n } else {\n // Proper lifecycle management: clear the previous selection first...\n selection.clear();\n }\n });\n\n /**\n * Select events don't carry information about the mouse button.\n * Therefore, to prevent right-click selection, we need to listen\n * to the initial pointerdown event and remember the button\n */\n const onPointerDown = (evt: PointerEvent) => {\n if (isNotAnnotatable(container, evt.target as Node)) return;\n\n /**\n * Cloning the event to prevent it from accidentally being `undefined`\n * @see https://github.com/recogito/text-annotator-js/commit/65d13f3108c429311cf8c2523f6babbbc946013d#r144033948\n */\n lastDownEvent = clonePointerEvent(evt);\n isLeftClick = lastDownEvent.button === 0;\n };\n\n const onPointerUp = async (evt: PointerEvent) => {\n if (!isLeftClick) return;\n\n if (isNotAnnotatable(container, evt.target as Node)) {\n if (options.dismissOnClickOutside)\n selection.clear();\n\n return;\n }\n\n // Logic for selecting an existing annotation\n const clickSelect = () => {\n const { x, y } = container.getBoundingClientRect();\n\n const hovered =\n evt.target instanceof Node &&\n container.contains(evt.target) &&\n store.getAt(evt.clientX - x, evt.clientY - y, selectionMode === 'all', currentFilter);\n\n if (hovered) {\n const { selected } = selection;\n\n const currentIds = new Set(selected.map(s => s.id));\n const nextIds = Array.isArray(hovered) ? hovered.map(a => a.id) : [hovered.id];\n\n const hasChanged =\n currentIds.size !== nextIds.length ||\n !nextIds.every(id => currentIds.has(id));\n\n if (hasChanged)\n selection.userSelect(nextIds, evt);\n } else {\n selection.clear();\n }\n };\n\n const timeDifference = evt.timeStamp - lastDownEvent.timeStamp;\n if (timeDifference < CLICK_TIMEOUT) {\n await pollSelectionCollapsed();\n\n const sel = document.getSelection();\n if (sel?.isCollapsed) {\n currentTarget = undefined;\n clickSelect();\n return;\n }\n }\n\n if (currentTarget && currentTarget.selector.length > 0) {\n upsertCurrentTarget();\n selection.userSelect(currentTarget.annotation, clonePointerEvent(evt));\n }\n }\n\n /**\n * We must check the `isCollapsed` after an unspecified timeout\n * to handle the annotation dismissal after a click properly.\n *\n * Otherwise, the `isCollapsed` will return an obsolete `false` value,\n * click won't be processed, and the annotation will get falsely re-selected.\n *\n * @see https://github.com/recogito/text-annotator-js/issues/136#issue-2465915707\n * @see https://github.com/recogito/text-annotator-js/issues/136#issuecomment-2413773804\n */\n const pollSelectionCollapsed = async () => {\n const sel = document.getSelection();\n\n let stopPolling = false;\n let isCollapsed = sel?.isCollapsed;\n const shouldStopPolling = () => isCollapsed || stopPolling;\n\n const pollingDelayMs = 1;\n const stopPollingInMs = 50;\n setTimeout(() => stopPolling = true, stopPollingInMs);\n\n return poll(() => isCollapsed = sel?.isCollapsed, pollingDelayMs, shouldStopPolling);\n }\n\n const onContextMenu = (evt: PointerEvent) => {\n const sel = document.getSelection();\n\n if (sel?.isCollapsed) return;\n\n /**\n * When selecting the initial word, Chrome Android\n * fires `contextmenu`before `selectionchange`\n */\n if (!currentTarget || currentTarget.selector.length === 0) {\n onSelectionChange(evt);\n }\n/**\n * The selection couldn't be initiated - might span over a not-annotatable element.\n */\n if (!currentTarget) return;\n upsertCurrentTarget();\n\n selection.userSelect(currentTarget.annotation, clonePointerEvent(evt));\n }\n\n const onKeyup = (evt: KeyboardEvent) => {\n if (evt.key === 'Shift' && currentTarget) {\n const sel = document.getSelection();\n\n if (!sel.isCollapsed) {\n upsertCurrentTarget();\n selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt));\n }\n }\n }\n\n const onSelectAll = (evt: KeyboardEvent) => {\n\n const onSelected = () => setTimeout(() => {\n if (currentTarget?.selector.length > 0) {\n selection.clear();\n\n store.addAnnotation({\n id: currentTarget.annotation,\n bodies: [],\n target: currentTarget\n });\n\n selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt));\n }\n\n document.removeEventListener('selectionchange', onSelected);\n\n // Sigh... this needs a delay to work. But doesn't seem reliable.\n }, 100);\n\n // Listen to the change event that follows\n document.addEventListener('selectionchange', onSelected);\n\n // Start selection!\n onSelectStart(evt);\n }\n\n hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, evt => {\n if (!evt.repeat)\n lastDownEvent = cloneKeyboardEvent(evt);\n });\n\n hotkeys(SELECT_ALL, { keydown: true, keyup: false}, evt => {\n lastDownEvent = cloneKeyboardEvent(evt);\n onSelectAll(evt);\n });\n\n /**\n * Free caret movement through the text resets the annotation selection.\n *\n * It should be handled only on:\n * - the annotatable `container`, where the text is.\n * - the `body`, where the focus goes when user closes the popup,\n * or clicks the button that gets unmounted, e.g. \"Close\"\n */\n const handleArrowKeyPress = (evt: KeyboardEvent) => {\n if (\n evt.repeat ||\n evt.target !== container && evt.target !== document.body\n ) {\n return;\n }\n\n currentTarget = undefined;\n selection.clear();\n };\n\n hotkeys(ARROW_KEYS.join(','), { keydown: true, keyup: false }, handleArrowKeyPress);\n\n // Helper\n const upsertCurrentTarget = () => {\n const existingAnnotation = store.getAnnotation(currentTarget.annotation);\n if (!existingAnnotation) {\n store.addAnnotation({\n id: currentTarget.annotation,\n bodies: [],\n target: currentTarget\n });\n return;\n }\n\n const { target: { updated: existingTargetUpdated } } = existingAnnotation;\n const { updated: currentTargetUpdated } = currentTarget;\n if (\n !existingTargetUpdated ||\n !currentTargetUpdated ||\n existingTargetUpdated < currentTargetUpdated\n ) {\n store.updateTarget(currentTarget);\n }\n };\n\n container.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('pointerup', onPointerUp);\n document.addEventListener('contextmenu', onContextMenu);\n\n if (annotatingEnabled) {\n container.addEventListener('keyup', onKeyup);\n container.addEventListener('selectstart', onSelectStart);\n document.addEventListener('selectionchange', onSelectionChange);\n }\n\n const destroy = () => {\n container.removeEventListener('pointerdown', onPointerDown);\n document.removeEventListener('pointerup', onPointerUp);\n document.removeEventListener('contextmenu', onContextMenu);\n\n container.removeEventListener('keyup', onKeyup);\n container.removeEventListener('selectstart', onSelectStart);\n document.removeEventListener('selectionchange', onSelectionChange);\n\n hotkeys.unbind();\n };\n\n return {\n destroy,\n setFilter,\n setUser\n }\n\n}\n\n","import type { FormatAdapter, UserSelectActionExpression, User, Annotation } from '@annotorious/core';\nimport type { PresencePainterOptions } from './presence';\nimport type { TextAnnotation } from './model';\nimport type { HighlightStyleExpression } from './highlight';\n\nexport interface TextAnnotatorOptions<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> {\n\n adapter?: FormatAdapter<I, E> | null;\n\n annotatingEnabled?: boolean;\n\n dismissOnClickOutside?: boolean;\n\n renderer?: RendererType;\n\n offsetReferenceSelector?: string;\n\n userSelectAction?: UserSelectActionExpression<E>,\n\n presence?: PresencePainterOptions;\n\n selectionMode?: 'shortest' | 'all';\n\n style?: HighlightStyleExpression;\n\n user?: User;\n \n}\n\nexport type RendererType = 'SPANS' | 'CANVAS' | 'CSS_HIGHLIGHTS';\n\nexport const fillDefaults = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n opts: TextAnnotatorOptions<I, E>,\n defaults: TextAnnotatorOptions<I, E>\n): TextAnnotatorOptions<I, E> => {\n\n return {\n ...opts,\n annotatingEnabled: opts.annotatingEnabled ?? defaults.annotatingEnabled,\n user: opts.user || defaults.user\n };\n\n};\n","import { createAnonymousGuest, createLifecycleObserver, createBaseAnnotator, createUndoStack } from '@annotorious/core';\nimport type { Filter } from '@annotorious/core';\nimport type { Annotator, User, PresenceProvider } from '@annotorious/core';\nimport { createCanvasRenderer, createHighlightsRenderer, createSpansRenderer, type HighlightStyleExpression } from './highlight';\nimport { createPresencePainter } from './presence';\nimport { scrollIntoView } from './api';\nimport { type TextAnnotationStore, type TextAnnotatorState, createTextAnnotatorState } from './state';\nimport type { TextAnnotation } from './model';\nimport { cancelSingleClickEvents, programmaticallyFocusable } from './utils';\nimport { fillDefaults, type RendererType, type TextAnnotatorOptions } from './TextAnnotatorOptions';\nimport { SelectionHandler } from './SelectionHandler';\n\nimport './TextAnnotator.css';\n\nconst USE_DEFAULT_RENDERER: RendererType = 'SPANS';\n\nexport interface TextAnnotator<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends Annotator<I, E> {\n\n element: HTMLElement;\n\n setStyle(style: HighlightStyleExpression | undefined): void;\n\n // Returns true if successful (or false if the annotation is not currently rendered)\n scrollIntoView(annotationOrId: I | string): boolean;\n\n state: TextAnnotatorState<I, E>;\n\n}\n\nexport const createTextAnnotator = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n container: HTMLElement,\n options: TextAnnotatorOptions<I, E> = {}\n): TextAnnotator<I, E> => {\n // Prevent mobile browsers from triggering word selection on single click.\n cancelSingleClickEvents(container);\n\n // Make sure that the container is focusable and can receive both pointer and keyboard events\n programmaticallyFocusable(container);\n\n const opts = fillDefaults<I, E>(options, {\n annotatingEnabled: true,\n user: createAnonymousGuest()\n });\n\n const state: TextAnnotatorState<I, E> = createTextAnnotatorState<I, E>(container, opts);\n\n const { selection, viewport } = state;\n\n const store: TextAnnotationStore<I> = state.store;\n\n const undoStack = createUndoStack<I>(store);\n\n const lifecycle = createLifecycleObserver<I, E>(state, undoStack, opts.adapter);\n\n let currentUser: User = opts.user;\n\n // Use selected renderer, or fall back to default. If CSS_HIGHLIGHT is\n // requested, check if CSS Custom Highlights are supported, and fall\n // back to default renderer if not.\n const useRenderer: RendererType =\n opts.renderer === 'CSS_HIGHLIGHTS'\n ? Boolean(CSS.highlights) ? 'CSS_HIGHLIGHTS' : USE_DEFAULT_RENDERER\n : opts.renderer || USE_DEFAULT_RENDERER;\n\n const highlightRenderer =\n useRenderer === 'SPANS' ? createSpansRenderer(container, state, viewport) :\n useRenderer === 'CSS_HIGHLIGHTS' ? createHighlightsRenderer(container, state, viewport) :\n useRenderer === 'CANVAS' ? createCanvasRenderer(container, state, viewport) : undefined;\n\n if (!highlightRenderer)\n throw `Unknown renderer implementation: ${useRenderer}`;\n\n console.debug(`Using ${useRenderer} renderer`);\n\n if (opts.style)\n highlightRenderer.setStyle(opts.style);\n\n const selectionHandler = SelectionHandler(container, state, opts);\n selectionHandler.setUser(currentUser);\n\n /*************************/\n /* External API */\n /******++++++*************/\n\n // Most of the external API functions are covered in the base annotator\n const base = createBaseAnnotator<I, E>(state, undoStack, opts.adapter);\n\n const getUser = () => currentUser;\n\n const setFilter = (filter?: Filter<I>) => {\n highlightRenderer.setFilter(filter);\n selectionHandler.setFilter(filter);\n }\n\n const setStyle = (style: HighlightStyleExpression | undefined) =>\n highlightRenderer.setStyle(style);\n\n const setUser = (user: User) => {\n currentUser = user;\n selectionHandler.setUser(user);\n }\n\n const setPresenceProvider = (provider: PresenceProvider) => {\n if (provider) {\n highlightRenderer.setPainter(createPresencePainter(provider, opts.presence));\n provider.on('selectionChange', () => highlightRenderer.redraw());\n }\n }\n\n const setSelected = (arg?: string | string[]) => {\n if (arg) {\n selection.setSelected(arg);\n } else {\n selection.clear();\n }\n }\n\n const setVisible = (visible: boolean) =>\n highlightRenderer.setVisible(visible);\n\n const destroy = () => {\n highlightRenderer.destroy();\n selectionHandler.destroy();\n\n // Other cleanup actions\n undoStack.destroy();\n }\n\n return {\n ...base,\n destroy,\n element: container,\n getUser,\n setFilter,\n setStyle,\n setUser,\n setSelected,\n setPresenceProvider,\n setVisible,\n on: lifecycle.on,\n off: lifecycle.off,\n scrollIntoView: scrollIntoView(container, store),\n state\n }\n\n}\n"],"names":["NOT_ANNOTATABLE_CLASS","NOT_ANNOTATABLE_SELECTOR","isNotAnnotatable","container","node","_a","isRangeAnnotatable","range","ancestor","cancelSingleClickEvents","event","clonePointerEvent","cloneKeyboardEvent","isMac","programmaticallyFocusable","debounce","func","delay","timeoutId","args","iterateNotAnnotatableElements","notAnnotatableIterator","notAnnotatableNode","splitAnnotatableRanges","annotatableRanges","prevNotAnnotatable","notAnnotatable","subRange","lastRange","getRangeAnnotatableContents","contents","el","getQuoteContext","length","offsetReferenceSelector","offsetReference","rangeBefore","before","rangeAfter","after","isRevived","selector","s","whitespaceOrEmptyRegex","isWhitespaceOrEmpty","getRelation","rectA","rectB","round","num","a","b","union","left","right","top","bottom","mergeClientRects","rects","merged","next","wasMerged","relation","r","toDomRectList","index","i","rangeToSelector","quote","start","end","reviveSelector","iterator","runningOffset","n","startCounting","len","_b","reviveTarget","target","reviveAnnotation","annotation","trimRangeToContainer","trimmedRange","getScrollParent","overflowY","scrollIntoView","store","annotationOrId","id","scroll","parentBounds","scrollParent","parentHeight","parentWidth","annotationBounds","width","height","offsetTop","offsetLeft","scrollTop","scrollLeft","current","annoRange","revived","revivedAnnoRange","DEFAULT_STYLE","DEFAULT_SELECTED_STYLE","paint","highlight","viewportBounds","style","painter","zIndex","base","getViewportBounds","innerWidth","innerHeight","minX","minY","maxX","maxY","trackViewport","viewport","visible","annotations","ids","createBaseRenderer","state","renderer","selection","hover","currentStyle","currentFilter","currentPainter","onDraw","onPointerMove","x","y","hit","redraw","lazy","bounds","annotationsInView","selectedIds","highlights","selected","hovered","setPainter","setStyle","setFilter","filter","onStoreChange","unsubscribeSelection","unsubscribeHover","onScroll","onResize","resizeObserver","config","mutationObserver","records","record","createCanvas","canvas","resetCanvas","highres","createRenderer","ctx","highlightA","highlightB","createdA","createdB","h","offsetRects","underlineOffset","createCanvasRenderer","toCSS","colord","elem","currentRendered","nextRendered","updatedCSS","ranges","createHighlightsRenderer","computeZIndex","rect","all","intersects","getLength","total","intersecting","highlightLayer","shouldRedraw","dequal","span","createSpansRenderer","W3CTextFormat","source","serialized","parseW3CTextAnnotation","serializeW3CTextAnnotation","isTextSelector","parseW3CTextTargets","annotationId","creator","created","modified","w3cTargets","parsed","parseW3CUser","w3cTarget","w3cSelector","missingTypes","uuidv4","body","rest","bodies","parseW3CBodies","updated","targetRest","quoteSelector","prefix","suffix","positionSelector","serializeW3CBodies","createSpatialTree","tree","RBush","toItems","offset","revivedRange","clear","insert","remove","update","set","targets","replace","rectsByTarget","allRects","getAt","hits","area","getAnnotationBounds","getAnnotationRects","indexed","annotationIds","t","createTextAnnotatorState","opts","createStore","createSelectionState","createHoverState","createViewportState","addAnnotation","origin","Origin","isValid","bulkAddAnnotations","couldNotRevive","bulkUpsertAnnotations","updateTarget","bulkUpdateTargets","getAll","filtered","getIntersecting","recalculatePositions","changes","deleted","u","newValue","context","createPresencePainter","provider","trackedAnnotations","getAnnotationsForUser","p","user","_","isSelected","metrics","labelWidth","labelHeight","paddingBottom","CLICK_TIMEOUT","ARROW_KEYS","SELECT_ALL","SELECTION_KEYS","key","SelectionHandler","options","currentUser","annotatingEnabled","selectionMode","setUser","currentTarget","isLeftClick","lastDownEvent","onSelectStart","evt","onSelectionChange","sel","timeDifference","containedRanges","idx","onPointerDown","onPointerUp","clickSelect","currentIds","nextIds","pollSelectionCollapsed","upsertCurrentTarget","stopPolling","isCollapsed","shouldStopPolling","pollingDelayMs","poll","onContextMenu","onKeyup","onSelectAll","onSelected","hotkeys","handleArrowKeyPress","existingAnnotation","existingTargetUpdated","currentTargetUpdated","fillDefaults","defaults","USE_DEFAULT_RENDERER","createTextAnnotator","createAnonymousGuest","undoStack","createUndoStack","lifecycle","createLifecycleObserver","useRenderer","highlightRenderer","selectionHandler","createBaseAnnotator","arg"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text-annotator.umd.js","sources":["../src/utils/isNotAnnotatable.ts","../src/utils/cancelSingleClickEvents.ts","../src/utils/cloneEvents.ts","../src/utils/device.ts","../src/utils/programmaticallyFocusable.ts","../src/utils/debounce.ts","../src/utils/splitAnnotatableRanges.ts","../src/utils/getQuoteContext.ts","../src/utils/isRevived.ts","../src/utils/isWhitespaceOrEmpty.ts","../src/utils/mergeClientRects.ts","../src/utils/rangeToSelector.ts","../src/utils/reviveSelector.ts","../src/utils/reviveTarget.ts","../src/utils/reviveAnnotation.ts","../src/utils/trimRangeToContainer.ts","../src/api/scrollIntoView.ts","../src/highlight/HighlightStyle.ts","../src/highlight/HighlightPainter.ts","../src/highlight/viewport.ts","../src/highlight/baseRenderer.ts","../src/highlight/canvas/canvasRenderer.ts","../src/highlight/highlights/highlightsRenderer.ts","../src/highlight/span/spansRenderer.ts","../src/model/w3c/W3CTextFormatAdapter.ts","../src/state/spatialTree.ts","../src/state/TextAnnotatorState.ts","../src/presence/PresencePainter.ts","../src/SelectionHandler.ts","../src/TextAnnotatorOptions.ts","../src/TextAnnotator.ts"],"sourcesContent":["export const NOT_ANNOTATABLE_CLASS = 'not-annotatable';\n\nexport const NOT_ANNOTATABLE_SELECTOR = `.${NOT_ANNOTATABLE_CLASS}`;\n\nexport const isNotAnnotatable = (container: Node, node: Node): boolean => {\n if (!container.contains(node)) return true;\n\n const closestNotAnnotatable = node instanceof HTMLElement\n ? node.closest(NOT_ANNOTATABLE_SELECTOR)\n : node.parentElement?.closest(NOT_ANNOTATABLE_SELECTOR);\n return Boolean(closestNotAnnotatable);\n}\n\nexport const isRangeAnnotatable = (container: Node, range: Range): boolean => {\n const ancestor = range.commonAncestorContainer;\n return !isNotAnnotatable(container, ancestor);\n}","import { NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\n/**\n * Calls .preventDefault() on click events in annotable areas, in order\n * to prevent problematic default browser behavior. (Specifically: keep\n * Chrome Android from triggering word selection on single click.)\n */\nexport const cancelSingleClickEvents = (container: HTMLElement) =>\n container.addEventListener('click', event => {\n const targetElement = event.target as HTMLElement;\n\n const shouldPrevent =\n // Allow clicks within not-annotatable elements\n !targetElement.closest(NOT_ANNOTATABLE_SELECTOR)\n // Allow clicks on links\n && !(event.target as Element).closest('a');\n\n if (shouldPrevent)\n event.preventDefault();\n });\n","/**\n * Events need to be manually mapped into new objects:\n * 1. It preserves the `target` and `currentTarget` properties.\n * Otherwise, they will be `null` when the event is read beyond the handler.\n * 2. Spread operator can copy only own enumerable properties, not inherited ones.\n * Therefore, we need to manually copy the props we're interested in.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget\n * @see https://github.com/recogito/text-annotator-js/commit/65d13f3108c429311cf8c2523f6babbbc946013d#r144041390\n */\n\nexport const clonePointerEvent = (event: PointerEvent): PointerEvent => ({\n ...event,\n type: event.type,\n x: event.x,\n y: event.y,\n clientX: event.clientX,\n clientY: event.clientY,\n offsetX: event.offsetX,\n offsetY: event.offsetY,\n screenX: event.screenX,\n screenY: event.screenY,\n isPrimary: event.isPrimary,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n button: event.button,\n buttons: event.buttons,\n currentTarget: event.currentTarget,\n target: event.target,\n defaultPrevented: event.defaultPrevented,\n detail: event.detail,\n eventPhase: event.eventPhase,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n timeStamp: event.timeStamp\n})\n\nexport const cloneKeyboardEvent = (event: KeyboardEvent): KeyboardEvent => ({\n ...event,\n type: event.type,\n key: event.key,\n code: event.code,\n location: event.location,\n repeat: event.repeat,\n altKey: event.altKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n currentTarget: event.currentTarget,\n target: event.target,\n defaultPrevented: event.defaultPrevented,\n detail: event.detail,\n timeStamp: event.timeStamp\n})\n","export const isMac = typeof navigator !== 'undefined' &&\n // @ts-ignore\n /mac/i.test(navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform);\n","/**\n * Makes an element programmatically focusable by adding a `tabindex=\"-1\"` attribute.\n * Or does nothing if the element is already focusable 🤷🏻\n * It's required to process keyboard events on an element that is not natively focusable.\n */\nexport const programmaticallyFocusable = (container: HTMLElement) => {\n if (!container.hasAttribute('tabindex') && container.tabIndex < 0) {\n container.setAttribute('tabindex', '-1');\n }\n\n container.classList.add('no-focus-outline');\n};\n","export const debounce = <T extends (...args: any[]) => void>(func: T, delay = 10): T => {\n\tlet timeoutId: ReturnType<typeof setTimeout>;\n\n\treturn ((...args: any[]) => {\n\t\tclearTimeout(timeoutId);\n\t\ttimeoutId = setTimeout(() => func.apply(this, args), delay);\n\t}) as T;\n}\n","import { isRangeAnnotatable, NOT_ANNOTATABLE_CLASS, NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\nconst iterateNotAnnotatableElements = function*(range: Range): Generator<HTMLElement> {\n const notAnnotatableIterator = document.createNodeIterator(\n range.commonAncestorContainer,\n NodeFilter.SHOW_ELEMENT,\n (node) =>\n node instanceof HTMLElement // Only elements that can have the class applied\n && node.classList.contains(NOT_ANNOTATABLE_CLASS) // Only elements that are not annotatable\n && !node.parentElement.closest(NOT_ANNOTATABLE_SELECTOR) // Only elements that are not descendants of a not annotatable element\n && range.intersectsNode(node) // Only elements that are within the range\n ? NodeFilter.FILTER_ACCEPT\n : NodeFilter.FILTER_SKIP\n );\n\n let notAnnotatableNode: Node | null;\n\n while ((notAnnotatableNode = notAnnotatableIterator.nextNode())) {\n if (notAnnotatableNode instanceof HTMLElement) {\n yield notAnnotatableNode;\n }\n }\n}\n\n/**\n * Splits a DOM Range into one or more ranges that span annotatable content only.\n */\nexport const splitAnnotatableRanges = (container: Node, range: Range): Range[] => {\n if (!isRangeAnnotatable(container, range)) return [];\n\n const annotatableRanges: Range[] = [];\n\n let prevNotAnnotatable: HTMLElement | null = null;\n\n for (const notAnnotatable of iterateNotAnnotatableElements(range)) {\n let subRange: Range;\n\n // From the start of the range to the not annotatable element.\n // If selection starts on the non-annotatable element, a collapsed range will be created and ignored.\n if (!prevNotAnnotatable) {\n subRange = range.cloneRange();\n subRange.setEndBefore(notAnnotatable);\n } else {\n // From the previous not annotatable element to the current not annotatable element\n subRange = document.createRange();\n subRange.setStartAfter(prevNotAnnotatable);\n subRange.setEndBefore(notAnnotatable);\n }\n\n if (!subRange.collapsed)\n annotatableRanges.push(subRange);\n\n prevNotAnnotatable = notAnnotatable;\n }\n\n // From the last not annotatable element to the end of the parent range\n if (prevNotAnnotatable) {\n const lastRange = range.cloneRange();\n lastRange.setStartAfter(prevNotAnnotatable);\n if (!lastRange.collapsed) {\n annotatableRanges.push(lastRange);\n }\n }\n\n return annotatableRanges.length > 0 ? annotatableRanges : [range];\n}\n\nexport const getRangeAnnotatableContents = (range: Range): DocumentFragment => {\n const contents = range.cloneContents();\n contents.querySelectorAll(NOT_ANNOTATABLE_SELECTOR).forEach((el) => el.remove());\n return contents;\n}\n","import { getRangeAnnotatableContents } from './splitAnnotatableRanges';\n\nexport const getQuoteContext = (\n range: Range, \n container: HTMLElement, \n length = 10,\n offsetReferenceSelector?: string\n) => {\n const offsetReference: HTMLElement = offsetReferenceSelector\n ? (range.startContainer.parentElement as HTMLElement).closest(offsetReferenceSelector)!\n : container;\n\n const rangeBefore = document.createRange();\n rangeBefore.setStart(offsetReference, 0);\n rangeBefore.setEnd(range.startContainer, range.startOffset);\n\n const before = getRangeAnnotatableContents(rangeBefore).textContent;\n \n const rangeAfter = document.createRange();\n rangeAfter.setStart(range.endContainer, range.endOffset);\n\n if (offsetReference === document.body)\n rangeAfter.setEnd(offsetReference, offsetReference.childNodes.length);\n else\n rangeAfter.setEndAfter(offsetReference);\n\n const after = getRangeAnnotatableContents(rangeAfter).textContent;\n\n return {\n prefix: before.substring(before.length - length),\n suffix: after.substring(0, length)\n }\n}\n","import type { TextSelector } from '../model';\n\nexport const isRevived = (selector: TextSelector[]) =>\n selector.every(s => s.range instanceof Range && !s.range.collapsed);\n","export const whitespaceOrEmptyRegex = /^\\s*$/;\n\nexport const isWhitespaceOrEmpty = (range: Range): boolean => whitespaceOrEmptyRegex.test(range.toString())\n","// The three topological relations we need to check for\ntype Relation = \n // Inline elements, same height, directly adjacent\n 'inline-adjacent' |\n // Inline elements, A fully contains B\n 'inline-contains' |\n // Inline elements, A is fully contained inside B\n 'inline-is-contained' |\n // At least one block element, A fully contains B\n 'block-contains' |\n // At least one block element, A is fully contained in B\n 'block-is-contained';\n\n// Note that this is not a general topology test. Takes a \n// few shortcuts to test ONLY the situations we'll encounter\n// with text selections.\nconst getRelation = (rectA: DOMRect, rectB: DOMRect): Relation | undefined => {\n const round = (num: number ) => Math.round(num * 10) / 10;\n\n // Some browsers have fractional pixel differences (looking at you FF!)\n const a = {\n top: round(rectA.top),\n bottom: round(rectA.bottom),\n left: round(rectA.left),\n right: round(rectA.right)\n };\n\n const b = {\n top: round(rectB.top),\n bottom: round(rectB.bottom),\n left: round(rectB.left),\n right: round(rectB.right)\n };\n\n if (Math.abs(a.top - b.top) < 0.5 && Math.abs(a.bottom - b.bottom) < 0.5) {\n // Same height - check for containment and adjacency\n if (Math.abs(a.left - b.right) < 0.5 || Math.abs(a.right - b.left) < 0.5)\n return 'inline-adjacent';\n\n if (a.left >= b.left && a.right <= b.right)\n return 'inline-is-contained';\n\n if (a.left <= b.left && a.right >= b.right)\n return 'inline-contains';\n } else {\n // Different heights - check for containment\n if (a.top <= b.top && a.bottom >= b.bottom) {\n if (a.left <= b.left && a.right >= b.right) {\n return 'block-contains'\n }\n } else if (a.top >= b.top && a.bottom <= b.bottom) {\n if (a.left >= b.left && a.right <= b.right) {\n return 'block-is-contained';\n }\n }\n }\n}\n\nconst union = (a: DOMRect, b: DOMRect): DOMRect => {\n const left = Math.min(a.left, b.left);\n const right = Math.max(a.right, b.right);\n const top = Math.min(a.top, b.top);\n const bottom = Math.max(a.bottom, b.bottom);\n\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\nexport const mergeClientRects = (rects: DOMRect[]) => rects.reduce<DOMRect[]>((merged, rectA) => {\n // Some browser report empty rects - discard\n if (rectA.width === 0 || rectA.height === 0)\n return merged;\n\n let next = [...merged];\n\n let wasMerged = false;\n\n for (const rectB of merged) {\n const relation = getRelation(rectA, rectB);\n \n if (relation === 'inline-adjacent') {\n // A and B are adjacent - remove B and keep union\n next = next.map(r => r === rectB ? union(rectA, rectB) : r);\n wasMerged = true;\n break;\n } else if (relation === 'inline-contains') {\n // A contains B - remove B and keep A\n next = next.map(r => r === rectB ? rectA : r);\n wasMerged = true;\n break;\n } else if (relation === 'inline-is-contained') {\n // B contains A - skip A\n wasMerged = true;\n break;\n } else if (relation === 'block-contains' || relation === 'block-is-contained') {\n // Block containment - keep the element with smaller width\n if (rectA.width < rectB.width) {\n next = next.map(r => r === rectB ? rectA : r);\n }\n wasMerged = true;\n break;\n }\n }\n\n return wasMerged ? next : [ ...next, rectA ];\n}, []);\n\nexport const toDomRectList = (rects: DOMRect[]): DOMRectList => ({\n length: rects.length,\n item: (index) => rects[index],\n [Symbol.iterator]: function* (): ArrayIterator<DOMRect> {\n for (let i = 0; i < this.length; i++)\n yield this.item(i)!;\n }\n})\n\n/* Pixels that rects can be apart vertically while still\n// being considered to be on the same line.\nconst TOLERANCE = 3;\n\nexport const mergeClientRects = (rects: DOMRect[]) => {\n const lines: DOMRect[][] = [];\n\n // Sort rects from the top, to make grouping simpler\n rects.sort((a, b) => a.top - b.top);\n\n // Group rects into lines\n for (const rect of rects) {\n if (lines.length === 0 || Math.abs(rect.top - lines[lines.length - 1][0].top) > TOLERANCE) {\n // Start a new line\n lines.push([rect]);\n } else {\n lines[lines.length - 1].push(rect);\n }\n }\n\n // Merge lines\n const mergedRects = lines.map(line => {\n const top = Math.min(...line.map(r => r.top));\n const bottom = Math.max(...line.map(r => r.bottom));\n const left = Math.min(...line.map(r => r.left));\n const right = Math.max(...line.map(r => r.right));\n\n return {\n top: top,\n bottom: bottom,\n left: left,\n right: right,\n height: bottom - top,\n width: right - left\n } as DOMRect;\n }).filter(r => r.height > 0 && r.width > 0);\n\n // Checks if the given rect contains any other rects\n const containsOthers = (rect: DOMRect) => mergedRects.some(other =>\n other !== rect &&\n other.left >= rect.left &&\n other.right <= rect.right &&\n other.top >= rect.top &&\n other.bottom <= rect.bottom\n );\n\n // Remove all rects that contain other rects (block-level elements!)\n return mergedRects.filter(rect => !containsOthers(rect));\n}\n*/\n","import { getRangeAnnotatableContents } from './splitAnnotatableRanges';\nimport type { TextSelector } from '../model';\n\nexport const rangeToSelector = (\n range: Range,\n container: HTMLElement,\n offsetReferenceSelector?: string\n): TextSelector => {\n const rangeBefore = document.createRange();\n\n const offsetReference: HTMLElement = offsetReferenceSelector\n ? (range.startContainer.parentElement as HTMLElement).closest(offsetReferenceSelector)!\n : container;\n\n // A helper range from the start of the container to the start of the selection\n rangeBefore.setStart(offsetReference, 0);\n rangeBefore.setEnd(range.startContainer, range.startOffset);\n\n // A content range before content w/o not annotatable elements\n const before = getRangeAnnotatableContents(rangeBefore).textContent;\n\n const quote = range.toString();\n const start = before.length || 0;\n const end = start + quote.length;\n\n return offsetReferenceSelector\n ? { quote, start, end, range, offsetReference }\n : { quote, start, end, range };\n}\n","import type { TextSelector } from '../model';\nimport { NOT_ANNOTATABLE_SELECTOR } from './isNotAnnotatable';\n\n/**\n * Creates a new selector object with the revived DOM range from the given text annotation position\n * Only the annotatable elements are processed and counted towards the range\n *\n * @param selector annotation selector with start and end positions\n * @param container the HTML container of the annotated content\n *\n * @returns the revived selector\n */\nexport const reviveSelector = <T extends TextSelector>(selector: T, container: HTMLElement): T => {\n\n const { start, end } = selector;\n\n const offsetReference = selector.offsetReference || container;\n\n const iterator = document.createNodeIterator(container, NodeFilter.SHOW_TEXT, (node) =>\n node.parentElement?.closest(NOT_ANNOTATABLE_SELECTOR)\n ? NodeFilter.FILTER_SKIP\n : NodeFilter.FILTER_ACCEPT\n );\n\n // Position that contains the length of the preceding annotatable text nodes\n let runningOffset = 0;\n\n const range = document.createRange();\n\n let n = iterator.nextNode();\n if (n === null) console.error('Could not revive annotation target. Content missing.');\n\n // If there's no offset reference, start immediately\n let startCounting = !offsetReference;\n while (n !== null) {\n startCounting ||= (typeof offsetReference?.contains === 'function') ? offsetReference.contains(n) : false;\n\n if (startCounting) {\n const len = n.textContent?.length || 0;\n\n if (runningOffset + len > start) {\n range.setStart(n, start - runningOffset);\n break;\n }\n\n runningOffset += len;\n }\n\n n = iterator.nextNode();\n }\n\n // set range end\n while (n !== null) {\n const len = n.textContent?.length || 0;\n\n if (runningOffset + len >= end) {\n range.setEnd(n, end - runningOffset);\n break;\n }\n\n runningOffset += len;\n\n n = iterator.nextNode();\n }\n \n return {\n ...selector,\n range\n }\n\n}\n","import type { TextAnnotationTarget } from '../model';\nimport { isRevived } from './isRevived';\nimport { reviveSelector } from './reviveSelector';\n\nexport const reviveTarget = <T extends TextAnnotationTarget = TextAnnotationTarget>(target: T, container: HTMLElement): T =>\n isRevived(target.selector)\n ? target\n : ({\n ...target,\n selector: target.selector.map(s => s.range instanceof Range && !s.range.collapsed ? s : reviveSelector(s, container))\n });\n\n\n","import type { TextAnnotation } from '../model';\nimport { isRevived } from './isRevived';\nimport { reviveTarget } from './reviveTarget';\n\nexport const reviveAnnotation = <T extends TextAnnotation>(annotation: T, container: HTMLElement): T =>\n isRevived(annotation.target.selector)\n ? annotation\n : ({ ...annotation, target: reviveTarget(annotation.target, container) });","export const trimRangeToContainer = (\n range: Range,\n container: HTMLElement\n): Range => {\n const trimmedRange = range.cloneRange();\n\n // If the start is outside the container - set it to the start of the container\n if (!container.contains(trimmedRange.startContainer)) {\n trimmedRange.setStart(container, 0);\n }\n\n // If the end is outside the container - set it to the end of the container\n if (!container.contains(trimmedRange.endContainer)) {\n trimmedRange.setEnd(container, container.childNodes.length);\n }\n\n return trimmedRange;\n};\n","import type { TextAnnotationStore } from '../state';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport { reviveTarget } from '../utils';\n\nconst getScrollParent = (el: Element) => {\n if (el === null)\n return document.scrollingElement;\n\n const { overflowY } = window.getComputedStyle(el);\n const isScrollable = overflowY !== 'visible' && overflowY !== 'hidden';\n\n // Cf. discussion https://stackoverflow.com/questions/35939886/find-first-scrollable-parent\n if (isScrollable && el.scrollHeight > el.clientHeight)\n return el;\n else\n return getScrollParent(el.parentElement);\n};\n\nexport const scrollIntoView = (\n container: HTMLElement, store: TextAnnotationStore\n) => (annotationOrId: string | TextAnnotation) => {\n const id =\n typeof annotationOrId === 'string' ? annotationOrId : annotationOrId.id;\n\n // Executes scroll on an annotation with a valid DOM range selector\n const scroll = (target: TextAnnotationTarget) => {\n // Parent bounds and client (= visible) height\n const parentBounds = scrollParent.getBoundingClientRect();\n const parentHeight = scrollParent.clientHeight;\n const parentWidth = scrollParent.clientWidth;\n\n // Position of the annotation relative to viewport\n // Note: first selector is not necessarily top one...\n const annotationBounds = target.selector[0].range.getBoundingClientRect();\n\n // Note: getBoundingClientRect seems to return wrong height! \n // (Includes block elements?) We'll therefore use the normalized height\n // from the spatial index!\n const { width, height } = store.getAnnotationBounds(id);\n\n // Position of the annotation relative to scrollParent\n const offsetTop = annotationBounds.top - parentBounds.top;\n const offsetLeft = annotationBounds.left - parentBounds.left;\n\n const scrollTop = scrollParent.parentElement ? scrollParent.scrollTop : 0;\n const scrollLeft = scrollParent.parentElement ? scrollParent.scrollLeft : 0;\n\n // Scroll the annotation to the center of the viewport\n const top = offsetTop + scrollTop - (parentHeight - height) / 2;\n const left = offsetLeft + scrollLeft - (parentWidth - width) / 2;\n\n scrollParent.scroll({ top, left, behavior: 'smooth' });\n };\n\n // Get closest scrollable parent\n const scrollParent: Element = getScrollParent(container);\n\n if (!scrollParent) {\n console.warn(`The scroll parent is missing for the annotation: ${id}`, { container });\n return false;\n }\n\n // Get curren version of the annotation from the store\n const current = store.getAnnotation(id);\n if (!current) {\n console.warn(`The annotation is missing in the store: ${id}`);\n return false;\n }\n\n // The 1st selector is the topmost one as well\n const { range: annoRange } = current.target.selector[0];\n if (annoRange && !annoRange.collapsed) {\n scroll(current.target);\n return true;\n }\n\n // Try reviving to account for lazy rendering\n const revived = reviveTarget(current.target, container);\n const { range: revivedAnnoRange } = revived.selector[0];\n if (revivedAnnoRange && !revivedAnnoRange.collapsed) {\n scroll(revived);\n return true;\n }\n\n return false;\n};\n","import type { AnnotationState, Color, DrawingStyle } from '@annotorious/core';\nimport type { TextAnnotation } from 'src/model';\n\nexport interface HighlightStyle extends Pick<DrawingStyle, 'fill' | 'fillOpacity'> {\n\n underlineStyle?: string;\n\n underlineColor?: Color;\n\n underlineOffset?: number;\n\n underlineThickness?: number;\n \n}\n\nexport type HighlightStyleExpression = HighlightStyle \n | (<I extends TextAnnotation = TextAnnotation>(annotation: I, state: AnnotationState, zIndex?: number) => HighlightStyle | undefined);\n\nexport const DEFAULT_STYLE: HighlightStyle = { \n fill: 'rgb(0, 128, 255)', \n fillOpacity: 0.18\n};\n\nexport const DEFAULT_SELECTED_STYLE: HighlightStyle = { \n fill: 'rgb(0, 128, 255)', \n fillOpacity: 0.45 \n};\n","\nimport type { Highlight } from './Highlight';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE } from './HighlightStyle';\nimport type { HighlightStyle, HighlightStyleExpression } from './HighlightStyle';\nimport type { ViewportBounds } from './viewport';\n\nexport interface HighlightPainter {\n\n clear(): void;\n\n destroy(): void;\n\n paint(highlight: Highlight, viewportBounds: ViewportBounds): HighlightStyle;\n\n reset(): void;\n\n}\n\n/** Helper **/\nexport const paint = (\n highlight: Highlight,\n viewportBounds: ViewportBounds,\n style?: HighlightStyleExpression, \n painter?: HighlightPainter,\n zIndex?: number\n) => {\n const base: HighlightStyle = style \n ? typeof style === 'function' \n ? style(highlight.annotation, highlight.state, zIndex) || (\n highlight.state?.selected ? DEFAULT_SELECTED_STYLE : DEFAULT_STYLE\n )\n : style \n : highlight.state?.selected \n ? DEFAULT_SELECTED_STYLE \n : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n return painter ? painter.paint(highlight, viewportBounds) || base : base;\n}","import type { ViewportState } from '@annotorious/core';\nimport type { TextAnnotation } from '../model';\n\nexport interface ViewportBounds {\n\n top: number;\n\n left: number;\n\n minX: number;\n\n minY: number;\n \n maxX: number;\n \n maxY: number;\n\n}\n\nexport const getViewportBounds = (container: HTMLElement): ViewportBounds => {\n const { top, left } = container.getBoundingClientRect();\n\n const { innerWidth, innerHeight } = window;\n\n const minX = - left;\n const minY = - top;\n const maxX = innerWidth - left;\n const maxY = innerHeight - top;\n\n return { top, left, minX, minY, maxX, maxY };\n}\n\nexport const trackViewport = (viewport: ViewportState) => {\n let visible = new Set<string>();\n\n const onDraw = (annotations: TextAnnotation[]) => {\n const ids = annotations.map(a => a.id);\n\n if (visible.size !== ids.length || ids.some(id => !visible.has(id))) {\n viewport.set(ids);\n } \n\n visible = new Set(ids);\n }\n\n return onDraw;\n\n}","import type { Filter, ViewportState } from '@annotorious/core';\nimport type { TextAnnotatorState } from '../state';\nimport { debounce } from '../utils';\nimport { type ViewportBounds, getViewportBounds, trackViewport } from './viewport';\nimport type { HighlightPainter } from './HighlightPainter';\nimport type { Highlight } from './Highlight';\nimport type { HighlightStyleExpression } from './HighlightStyle';\n\nexport interface RendererImplementation {\n\n destroy(): void;\n\n redraw(\n\n highlights:Highlight[], \n\n bounds: ViewportBounds, \n \n style?: HighlightStyleExpression,\n\n painter?: HighlightPainter,\n\n lazy?: boolean\n \n ): void;\n\n setVisible(visible: boolean): void;\n\n}\n\nexport interface Renderer {\n\n destroy(): void;\n\n redraw(force?: boolean): void;\n\n setStyle(style?: HighlightStyleExpression): void;\n\n setFilter(filter?: Filter): void;\n\n setPainter(painter?: HighlightPainter): void;\n\n setVisible(visible: boolean): void;\n\n}\n\nexport const createBaseRenderer = <T extends TextAnnotatorState = TextAnnotatorState> (\n container: HTMLElement, \n state: T,\n viewport: ViewportState,\n renderer: RendererImplementation\n): Renderer => {\n const { store, selection, hover } = state;\n\n let currentStyle: HighlightStyleExpression | undefined;\n\n let currentFilter: Filter | undefined;\n\n let currentPainter: HighlightPainter;\n\n const onDraw = trackViewport(viewport);\n\n const onPointerMove = (event: PointerEvent) => {\n const {x, y} = container.getBoundingClientRect();\n\n const hit = store.getAt(event.clientX - x, event.clientY - y, false, currentFilter);\n if (hit) {\n if (hover.current !== hit.id) {\n container.classList.add('hovered');\n hover.set(hit.id);\n }\n } else {\n if (hover.current) {\n container.classList.remove('hovered');\n hover.set(null);\n }\n }\n }\n\n container.addEventListener('pointermove', onPointerMove);\n\n const redraw = (lazy: boolean = false) => {\n if (currentPainter)\n currentPainter.clear();\n\n const bounds = getViewportBounds(container); \n\n const { minX, minY, maxX, maxY } = bounds;\n \n const annotationsInView = currentFilter\n ? store.getIntersecting(minX, minY, maxX, maxY).filter(({ annotation }) => currentFilter(annotation))\n : store.getIntersecting(minX, minY, maxX, maxY);\n\n const selectedIds = selection.selected.map(({ id }) => id);\n\n const highlights: Highlight[] = annotationsInView.map(({ annotation, rects }) => {\n const selected = selectedIds.includes(annotation.id);\n const hovered = annotation.id === hover.current;\n\n return {\n annotation,\n rects,\n state: { selected, hovered }\n };\n });\n\n renderer.redraw(highlights, bounds, currentStyle, currentPainter, lazy);\n\n setTimeout(() => onDraw(annotationsInView.map(({ annotation }) => annotation)), 1);\n }\n\n const setPainter = (painter: HighlightPainter) => { \n currentPainter = painter;\n redraw();\n }\n\n const setStyle = (style?: HighlightStyleExpression) => {\n currentStyle = style;\n redraw();\n }\n\n const setFilter = (filter?: Filter) => {\n currentFilter = filter;\n redraw(false);\n } \n\n // Refresh on store change\n const onStoreChange = () => redraw();\n store.observe(onStoreChange);\n\n // Refresh on selection change\n const unsubscribeSelection = selection.subscribe(() => redraw());\n\n // Refresh on hover change\n const unsubscribeHover = hover.subscribe(() => redraw());\n\n // Refresh on scroll\n const onScroll = () => redraw(true);\n\n document.addEventListener('scroll', onScroll, { capture: true, passive: true });\n\n // Refresh on resize\n const onResize = debounce(() => {\n store.recalculatePositions();\n\n if (currentPainter)\n currentPainter.reset();\n\n redraw();\n });\n\n window.addEventListener('resize', onResize);\n\n const resizeObserver = new ResizeObserver(onResize);\n resizeObserver.observe(container);\n\n // This is an extra precaution. The position of the container\n // might shift (without resizing) due to layout changes higher-up\n // in the DOM. (This happens in Recogito for example)\n const config: MutationObserverInit = { attributes: true, childList: true, subtree: true };\n\n const mutationObserver = new MutationObserver(debounce((records: MutationRecord[]) => {\n const isInternal = records\n .every(record => record.target === container || container.contains(record.target));\n\n if (!isInternal)\n redraw(true);\n }, 150));\n\n mutationObserver.observe(document.body, config);\n\n const destroy = () => {\n container.removeEventListener('pointermove', onPointerMove);\n \n renderer.destroy();\n \n store.unobserve(onStoreChange);\n\n unsubscribeSelection();\n unsubscribeHover();\n\n document.removeEventListener('scroll', onScroll);\n\n window.removeEventListener('resize', onResize);\n resizeObserver.disconnect();\n\n mutationObserver.disconnect();\n }\n\n return {\n destroy,\n redraw,\n setStyle,\n setFilter,\n setPainter,\n setVisible: renderer.setVisible\n }\n\n}\n","import type { ViewportState } from '@annotorious/core';\nimport type { TextAnnotatorState } from '../../state';\nimport { debounce } from '../../utils';\nimport type { ViewportBounds } from '../viewport';\nimport type { HighlightStyle } from '../HighlightStyle';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';\nimport type { HighlightPainter } from '../HighlightPainter';\nimport { createBaseRenderer, type RendererImplementation } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport type { TextAnnotation } from 'src/model';\n\nimport './canvasRenderer.css';\n\nconst createCanvas = () => {\n const canvas = document.createElement('canvas');\n canvas.width = window.innerWidth;\n canvas.height = window.innerHeight;\n canvas.className = 'r6o-canvas-highlight-layer bg';\n return canvas;\n}\n\nconst resetCanvas = (canvas: HTMLCanvasElement, highres?: boolean) => {\n canvas.width = highres ? 2 * window.innerWidth : window.innerWidth;\n canvas.height = highres ? 2 * window.innerHeight : window.innerHeight;\n\n if (highres) {\n // Note that resizing the canvas resets the context\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n }\n}\n\nconst createRenderer = (container: HTMLElement): RendererImplementation => {\n\n container.classList.add('r6o-annotatable');\n\n const canvas = createCanvas();\n const ctx = canvas.getContext('2d');\n\n document.body.appendChild(canvas);\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n currentPainter?: HighlightPainter\n ) => requestAnimationFrame(() => {\n\n const { width, height } = canvas;\n\n // New render loop - clear canvases\n ctx.clearRect(-0.5, -0.5, width + 1, height + 1);\n\n if (currentPainter)\n currentPainter.clear();\n\n const { top, left } = viewportBounds;\n\n /**\n * Highlights rendering on the canvas is an order-sensitive operation.\n * The later the highlight is rendered, the higher it will be in the visual stack.\n *\n * By default, we should expect that the newer highlight\n * will be rendered over the older one\n */\n const highlightsByCreation = [...highlights].sort((highlightA, highlightB) => {\n const { annotation: { target: { created: createdA } } } = highlightA;\n const { annotation: { target: { created: createdB } } } = highlightB;\n return createdA.getTime() - createdB.getTime();\n });\n\n highlightsByCreation.forEach(h => {\n const base: HighlightStyle = currentStyle\n ? typeof currentStyle === 'function'\n ? currentStyle(h.annotation, h.state)\n : currentStyle\n : h.state?.selected\n ? DEFAULT_SELECTED_STYLE\n : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n const style = currentPainter ? currentPainter.paint(h, viewportBounds) || base : base;\n\n // Offset annotation rects by current scroll position\n const offsetRects = h.rects.map(({ x, y, width, height }) => ({\n x: x + left,\n y: y + top,\n width,\n height\n }));\n\n ctx.fillStyle = style.fill;\n ctx.globalAlpha = style.fillOpacity || 1;\n\n offsetRects.forEach(({ x, y, width, height }) =>\n ctx.fillRect(x, y, width, height)\n );\n\n if (style.underlineColor) {\n ctx.globalAlpha = 1;\n ctx.strokeStyle = style.underlineColor;\n ctx.lineWidth = style.underlineThickness ?? 1;\n\n // Place the underline below the highlighted text + an optional offset\n const underlineOffset = style.underlineOffset ?? 0;\n\n offsetRects.forEach(({ x, y, width, height }) => {\n ctx.beginPath();\n ctx.moveTo(x, y + height + underlineOffset);\n ctx.lineTo(x + width, y + height + underlineOffset);\n\n // Draw the Path\n ctx.stroke();\n });\n }\n });\n });\n\n const onResize = debounce(() => {\n resetCanvas(canvas);\n });\n\n window.addEventListener('resize', onResize);\n\n const setVisible = (visible: boolean) => {\n console.log('setVisible not implemented on Canvas renderer');\n }\n\n const destroy = () => {\n canvas.remove();\n\n window.removeEventListener('resize', onResize);\n }\n\n return {\n destroy,\n setVisible,\n redraw\n };\n\n};\n\nexport const createCanvasRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer(container));\n","import type { ViewportState } from '@annotorious/core';\nimport { colord } from 'colord';\nimport type { HighlightPainter } from '../HighlightPainter';\nimport type { TextAnnotatorState } from 'src/state';\nimport type { ViewportBounds } from '../viewport';\nimport { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE } from '../HighlightStyle';\nimport type { HighlightStyle, HighlightStyleExpression } from '../HighlightStyle';\nimport { type RendererImplementation, createBaseRenderer } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport type { TextAnnotation } from 'src/model';\n\nconst toCSS = (s?: HighlightStyle) => {\n const backgroundColor = colord(s?.fill || DEFAULT_STYLE.fill)\n .alpha(s?.fillOpacity === undefined ? DEFAULT_STYLE.fillOpacity : s.fillOpacity)\n .toHex();\n\n const rules = [\n `background-color:${backgroundColor}`,\n s?.underlineThickness ? `text-decoration:underline` : undefined,\n s?.underlineColor ? `text-decoration-color:${s.underlineColor}` : undefined,\n s?.underlineOffset ? `text-underline-offset:${s.underlineOffset}px` : undefined,\n s?.underlineThickness ? `text-decoration-thickness:${s.underlineThickness}px` : undefined\n ].filter(Boolean);\n\n return rules.join(';');\n}\n\nexport const createRenderer = (): RendererImplementation => {\n const elem = document.createElement('style');\n document.getElementsByTagName('head')[0].appendChild(elem);\n\n let currentRendered = new Set<string>();\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n painter?: HighlightPainter\n ) => {\n if (painter)\n painter.clear();\n\n // Next set of rendered annotation IDs and selections\n const nextRendered = new Set(highlights.map(h => h.annotation.id));\n\n // Annotations currently in this stylesheet that no longer need rendering\n const toRemove = Array.from(currentRendered).filter(id => !nextRendered.has(id));\n\n // For simplicity, re-generate the whole stylesheet\n const updatedCSS = highlights.map(h => {\n const base = currentStyle\n ? typeof currentStyle === 'function'\n ? currentStyle(h.annotation, h.state)\n : currentStyle\n : h.state?.selected ? DEFAULT_SELECTED_STYLE : DEFAULT_STYLE;\n\n // Trigger the custom painter (if any) as a side-effect\n const style = painter ? painter.paint(h, viewportBounds) || base : base;\n\n return `::highlight(_${h.annotation.id}) { ${toCSS(style)} }`;\n });\n\n elem.innerHTML = updatedCSS.join('\\n');\n\n // After we have the styles, we need to update the Highlights.\n // Note that the (experimental) CSS Custom Highlight API is not yet\n // available in TypeScript!\n\n // @ts-ignore\n CSS.highlights.clear();\n // toRemove.forEach(id => CSS.highlights.delete(`_${id}`));\n\n // Could be improved further by (re-)setting only annotations that\n // have changes.\n highlights.forEach(({ annotation }) => {\n const ranges = annotation.target.selector.map(s => s.range);\n\n // @ts-ignore\n const highlights = new Highlight(...ranges);\n\n // @ts-ignore\n CSS.highlights.set(`_${annotation.id}`, highlights);\n });\n\n currentRendered = nextRendered;\n }\n\n const setVisible = (visible: boolean) => {\n console.log('setVisible not implemented on CSS Custom Highlights renderer');\n }\n\n const destroy = () => {\n // Clear all highlights from the Highlight Registry\n // @ts-ignore\n CSS.highlights.clear();\n\n // Remove the stylesheet\n elem.remove();\n }\n\n return {\n destroy,\n setVisible,\n redraw\n };\n\n}\n\nexport const createHighlightsRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer());\n","import type { ViewportState } from '@annotorious/core';\nimport { colord } from 'colord';\nimport { dequal } from 'dequal/lite';\nimport type { Rect, TextAnnotatorState } from '../../state';\nimport { type HighlightPainter, paint } from '../HighlightPainter';\nimport type { ViewportBounds } from '../viewport';\nimport { createBaseRenderer, type RendererImplementation } from '../baseRenderer';\nimport type { Highlight } from '../Highlight';\nimport { DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';\nimport type { TextAnnotation } from 'src/model';\n\nimport './spansRenderer.css';\n\nconst computeZIndex = (rect: Rect, all: Highlight[]): number => {\n const intersects = (a: Rect, b: Rect): boolean => (\n a.x <= b.x + b.width && a.x + a.width >= b.x &&\n a.y <= b.y + b.height && a.y + a.height >= b.y\n )\n\n const getLength = (h: Highlight) => \n h.rects.reduce((total, rect) => total + rect.width, 0);\n\n // Any highlights that intersect this rect, sorted by total length\n const intersecting = all.filter(({ rects }) => rects.some(r => intersects(rect, r)));\n intersecting.sort((a, b) => getLength(b) - getLength(a));\n\n return intersecting.findIndex(h => h.rects.includes(rect));\n}\n\nconst createRenderer = (container: HTMLElement): RendererImplementation => {\n\n container.classList.add('r6o-annotatable');\n\n const highlightLayer = document.createElement('div');\n highlightLayer.className = 'r6o-span-highlight-layer';\n\n container.insertBefore(highlightLayer, container.firstChild);\n\n // Currently rendered highlights\n let currentRendered: Highlight[] = [];\n\n const redraw = (\n highlights: Highlight[],\n viewportBounds: ViewportBounds,\n currentStyle?: HighlightStyleExpression,\n painter?: HighlightPainter,\n lazy?: boolean\n ) => {\n const noChanges = dequal(currentRendered, highlights);\n\n // If there are no changes and rendering is set to lazy\n // Don't redraw the SPANs - but redraw the painter, if any!\n const shouldRedraw = !(noChanges && lazy);\n\n if (!painter && !shouldRedraw) return;\n\n if (shouldRedraw)\n highlightLayer.innerHTML = '';\n\n /**\n * Highlights rendering in the span highlight layer is an order-sensitive operation.\n * The later the highlight is rendered, the higher it will be in the visual stack.\n *\n * By default, we should expect that the newer highlight\n * will be rendered over the older one\n */\n const sorted = [...highlights].sort((highlightA, highlightB) => {\n const { annotation: { target: { created: createdA } } } = highlightA;\n const { annotation: { target: { created: createdB } } } = highlightB;\n return createdA && createdB ? createdA.getTime() - createdB.getTime() : 0;\n });\n\n sorted.forEach(highlight => {\n highlight.rects.map(rect => {\n const zIndex = computeZIndex(rect, highlights);\n const style = paint(highlight, viewportBounds, currentStyle, painter, zIndex);\n\n if (shouldRedraw) {\n const span = document.createElement('span');\n span.className = 'r6o-annotation';\n span.dataset.annotation = highlight.annotation.id;\n\n span.style.left = `${rect.x}px`;\n span.style.top = `${rect.y}px`;\n span.style.width = `${rect.width}px`;\n span.style.height = `${rect.height}px`;\n\n span.style.backgroundColor = colord(style?.fill || DEFAULT_STYLE.fill)\n .alpha(style?.fillOpacity === undefined ? DEFAULT_STYLE.fillOpacity : style.fillOpacity)\n .toHex();\n\n if (style.underlineStyle)\n span.style.borderStyle = style.underlineStyle;\n\n if (style.underlineColor)\n span.style.borderColor = style.underlineColor;\n\n if (style.underlineThickness)\n span.style.borderBottomWidth = `${style.underlineThickness}px`;\n\n if (style.underlineOffset)\n span.style.paddingBottom = `${style.underlineOffset}px`;\n\n highlightLayer.appendChild(span);\n }\n });\n });\n\n currentRendered = highlights;\n }\n\n const setVisible = (visible: boolean) => {\n if (visible)\n highlightLayer.classList.remove('hidden');\n else\n highlightLayer.classList.add('hidden');\n }\n\n const destroy = () => {\n highlightLayer.remove();\n }\n\n return {\n destroy,\n redraw,\n setVisible\n };\n\n}\n\nexport const createSpansRenderer = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n viewport: ViewportState\n) => createBaseRenderer(container, state, viewport, createRenderer(container));\n","import { v4 as uuidv4 } from 'uuid';\nimport {\n type FormatAdapter,\n type ParseResult,\n parseW3CBodies,\n parseW3CUser,\n serializeW3CBodies\n} from '@annotorious/core';\nimport type { TextAnnotation, TextAnnotationTarget, TextSelector } from '../core';\nimport type { W3CTextAnnotation, W3CTextAnnotationTarget, W3CTextSelector } from '../w3c';\nimport { getQuoteContext } from '../../utils';\n\nexport type W3CTextFormatAdapter<I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation> = FormatAdapter<I, E>;\n\n/**\n * @param source - the IRI of the annotated content\n * @param container - the HTML container of the annotated content,\n * Required to locate the content's `range` within the DOM\n */\nexport const W3CTextFormat =<I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n source: string,\n container?: HTMLElement\n): W3CTextFormatAdapter<I, E> => ({\n parse: (serialized) => parseW3CTextAnnotation(serialized),\n serialize: (annotation) => serializeW3CTextAnnotation(annotation, source, container)\n});\n\nconst isTextSelector = (selector: Partial<TextSelector>): selector is TextSelector =>\n selector.quote !== undefined && selector.start !== undefined && selector.end !== undefined;\n\nconst parseW3CTextTargets = (annotation: W3CTextAnnotation) => {\n const {\n id: annotationId,\n creator,\n created,\n modified,\n target\n } = annotation;\n\n const w3cTargets = Array.isArray(target) ? target : [target];\n if (w3cTargets.length === 0) {\n return { error: Error(`No targets found for annotation: ${annotation.id}`) };\n }\n\n const parsed: TextAnnotationTarget = {\n creator: parseW3CUser(creator),\n created: created ? new Date(created) : undefined,\n updated: modified ? new Date(modified) : undefined,\n annotation: annotationId,\n selector: [],\n // @ts-expect-error: `styleClass` is not part of the core `TextAnnotationTarget` type\n styleClass: 'styleClass' in w3cTargets[0] ? w3cTargets[0].styleClass : undefined\n };\n\n for (const w3cTarget of w3cTargets) {\n const w3cSelectors = Array.isArray(w3cTarget.selector) ? w3cTarget.selector : [w3cTarget.selector];\n\n const selector = w3cSelectors.reduce<Partial<TextSelector>>((s, w3cSelector) => {\n switch (w3cSelector.type) {\n case 'TextQuoteSelector':\n s.quote = w3cSelector.exact;\n break;\n case 'TextPositionSelector':\n s.start = w3cSelector.start;\n s.end = w3cSelector.end;\n break;\n }\n return s;\n }, {});\n\n if (isTextSelector(selector)) {\n parsed.selector.push(\n {\n ...selector,\n id: w3cTarget.id,\n // @ts-expect-error: `scope` is not part of the core `TextSelector` type\n scope: w3cTarget.scope\n }\n );\n } else {\n const missingTypes = [\n !selector.start ? 'TextPositionSelector' : undefined,\n !selector.quote ? 'TextQuoteSelector' : undefined\n ].filter(Boolean);\n\n return { error: Error(`Missing selector types: ${missingTypes.join(' and ')} for annotation: ${annotation.id}`) };\n }\n }\n\n return { parsed };\n};\n\nexport const parseW3CTextAnnotation = <I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n annotation: E\n): ParseResult<I> => {\n const annotationId = annotation.id || uuidv4();\n\n const {\n creator,\n created,\n modified,\n body,\n ...rest\n } = annotation;\n\n const bodies = parseW3CBodies(body, annotationId);\n const target = parseW3CTextTargets(annotation);\n\n const parseResult = 'error' in target\n ? { error: target.error }\n : {\n parsed: {\n ...rest,\n id: annotationId,\n bodies,\n target: target.parsed\n }\n };\n\n return parseResult as ParseResult<I>;\n\n};\n\nexport const serializeW3CTextAnnotation = <I extends TextAnnotation = TextAnnotation, E extends W3CTextAnnotation = W3CTextAnnotation>(\n annotation: I,\n source: string,\n container?: HTMLElement\n): E => {\n const { bodies, target, ...rest } = annotation;\n\n const {\n selector,\n creator,\n created,\n updated,\n ...targetRest\n } = target;\n\n const w3cTargets = selector.map((s): W3CTextAnnotationTarget => {\n const { id, quote, start, end, range } = s;\n\n const quoteSelector: W3CTextSelector = {\n type: 'TextQuoteSelector',\n exact: quote\n }\n\n if (container) {\n const { prefix, suffix } = getQuoteContext(range, container);\n quoteSelector.prefix = prefix;\n quoteSelector.suffix = suffix;\n }\n\n const positionSelector: W3CTextSelector = {\n type: 'TextPositionSelector',\n start,\n end\n }\n\n return {\n ...targetRest,\n id,\n // @ts-expect-error: `scope` is not part of the core `TextSelector` type\n scope: 'scope' in s ? s.scope : undefined,\n source,\n selector: [quoteSelector, positionSelector]\n };\n });\n\n return {\n ...rest,\n '@context': 'http://www.w3.org/ns/anno.jsonld',\n id: annotation.id,\n type: 'Annotation',\n body: serializeW3CBodies(annotation.bodies),\n creator,\n created: created?.toISOString(),\n modified: updated?.toISOString(),\n target: w3cTargets\n } as unknown as E;\n\n};\n","import RBush from 'rbush';\nimport type { Store } from '@annotorious/core';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport { isRevived, reviveSelector, mergeClientRects } from '../utils';\nimport type { AnnotationRects } from './TextAnnotationStore';\n\ninterface IndexedHighlightRect {\n\n minX: number;\n\n minY: number;\n\n maxX: number;\n\n maxY: number;\n\n annotation: {\n \n id: string;\n\n rects: DOMRect[];\n\n }\n\n}\n\nexport const createSpatialTree = <T extends TextAnnotation>(store: Store<T>, container: HTMLElement) => {\n\n const tree = new RBush<IndexedHighlightRect>();\n\n const index = new Map<string, IndexedHighlightRect[]>();\n\n // Helper: converts a single text annotation target to a list of hightlight rects\n const toItems = (target: TextAnnotationTarget, offset: DOMRect): IndexedHighlightRect[] => {\n const rects = target.selector.flatMap(s => {\n const revivedRange = isRevived([s]) ? s.range : reviveSelector(s, container).range;\n return Array.from(revivedRange.getClientRects());\n });\n\n const merged = mergeClientRects(rects)\n // Offset the merged client rects so that coords\n // are relative to the parent container\n .map(({ left, top, right, bottom }) => \n new DOMRect(left - offset.left, top - offset.top, right - left, bottom - top));\n\n return merged.map(rect => {\n const { x, y, width, height } = rect;\n\n return {\n minX: x,\n minY: y,\n maxX: x + width,\n maxY: y + height,\n annotation: {\n id: target.annotation,\n rects: merged\n }\n }\n });\n }\n\n const all = () => [...index.values()];\n\n const clear = () => {\n tree.clear();\n index.clear();\n }\n\n const insert = (target: TextAnnotationTarget) => {\n const rects = toItems(target, container.getBoundingClientRect());\n if (rects.length === 0) return;\n\n rects.forEach(rect => tree.insert(rect));\n index.set(target.annotation, rects);\n }\n\n const remove = (target: TextAnnotationTarget) => {\n const rects = index.get(target.annotation);\n if (rects) {\n rects.forEach(rect => tree.remove(rect));\n index.delete(target.annotation);\n }\n }\n\n const update = (target: TextAnnotationTarget) => {\n remove(target);\n insert(target);\n }\n\n const set = (targets: TextAnnotationTarget[], replace: boolean = true) => {\n if (replace)\n clear();\n\n const offset = container.getBoundingClientRect();\n\n const rectsByTarget = targets.map(target => ({ target, rects: toItems(target, offset) }));\n rectsByTarget.forEach(({ target, rects }) => {\n if (rects.length > 0)\n index.set(target.annotation, rects)\n });\n\n const allRects = rectsByTarget.flatMap(({ rects }) => rects);\n tree.load(allRects);\n }\n\n const getAt = (x: number, y: number, all = false): string[] => {\n const hits = tree.search({\n minX: x,\n minY: y,\n maxX: x,\n maxY: y\n });\n\n const area = (rect: IndexedHighlightRect) =>\n rect.annotation.rects.reduce((area, r) =>\n area + r.width * r.height, 0);\n \n // Get smallest rect\n if (hits.length > 0) {\n hits.sort((a, b) => area(a) - area(b));\n return all ? hits.map(h => h.annotation.id) : [ hits[0].annotation.id ];\n } else {\n return [];\n }\n }\n\n const getAnnotationBounds = (id: string): DOMRect => {\n const rects = getAnnotationRects(id);\n\n if (rects.length === 0)\n return undefined;\n\n let left = rects[0].left;\n let top = rects[0].top;\n let right = rects[0].right;\n let bottom = rects[0].bottom;\n\n for (let i = 1; i < rects.length; i++) {\n const rect = rects[i];\n\n left = Math.min(left, rect.left);\n top = Math.min(top, rect.top);\n right = Math.max(right, rect.right);\n bottom = Math.max(bottom, rect.bottom);\n }\n\n return new DOMRect(left, top, right - left, bottom - top);\n }\n\n const getAnnotationRects = (id: string): DOMRect[] => {\n const indexed = index.get(id);\n if (indexed) {\n // Reminder: *each* IndexedHighlightRect stores *all*\n // DOMRects for the annotation for convenience\n return indexed[0].annotation.rects;\n } else {\n return [];\n }\n }\n\n const getIntersecting = (\n minX: number, \n minY: number, \n maxX: number, \n maxY: number,\n ): AnnotationRects<T>[] => {\n // All rects in this area, regardless of annotation\n const rects = tree.search({ minX, minY, maxX, maxY });\n\n // Distinct annotation IDs\n const annotationIds = new Set(rects.map(rect => rect.annotation.id));\n\n // Resolve annotation IDs. Note that the tree could be slightly out of sync (because \n // it updates by listening to changes, just like anyone else)\n return Array.from(annotationIds).map(annotationId => ({\n annotation: store.getAnnotation(annotationId),\n rects: getAnnotationRects(annotationId)\n })).filter(t => Boolean(t.annotation));\n }\n\n const size = () => tree.all().length;\n\n const recalculate = () =>\n set(store.all().map(a => a.target), true);\n\n return {\n all,\n clear,\n getAt,\n getAnnotationBounds,\n getAnnotationRects,\n getIntersecting,\n insert,\n recalculate,\n remove,\n set,\n size,\n update\n }\n\n}\n","import type { Filter, Store, ViewportState } from '@annotorious/core';\nimport { \n createHoverState, \n createSelectionState, \n createStore, \n Origin,\n createViewportState\n} from '@annotorious/core';\nimport type { \n AnnotatorState, \n SelectionState, \n HoverState, \n} from '@annotorious/core';\n\nimport { createSpatialTree } from './spatialTree';\nimport type { TextAnnotation, TextAnnotationTarget } from '../model';\nimport type { AnnotationRects, TextAnnotationStore } from './TextAnnotationStore';\nimport { isRevived, reviveAnnotation, reviveTarget } from '../utils';\nimport type { TextAnnotatorOptions } from '../TextAnnotatorOptions';\n\nexport interface TextAnnotatorState<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends AnnotatorState<I, E> {\n\n store: TextAnnotationStore<I>;\n\n selection: SelectionState<I, E>;\n\n hover: HoverState<I>;\n\n viewport: ViewportState;\n\n}\n\nexport const createTextAnnotatorState = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n container: HTMLElement,\n opts: TextAnnotatorOptions<I, E>\n): TextAnnotatorState<I, E> => {\n\n const store: Store<I> = createStore<I>();\n\n const tree = createSpatialTree(store, container);\n\n const selection = createSelectionState<I, E>(store, opts.userSelectAction, opts.adapter);\n\n const hover = createHoverState(store);\n\n const viewport = createViewportState();\n\n // Wrap store interface to intercept annotations and revive DOM ranges, if needed\n const addAnnotation = (annotation: I, origin = Origin.LOCAL): boolean => {\n const revived = reviveAnnotation(annotation, container);\n\n const isValid = isRevived(revived.target.selector);\n if (isValid)\n store.addAnnotation(revived, origin); \n\n return isValid;\n }\n\n const bulkAddAnnotations = (\n annotations: I[], \n replace = true, \n origin = Origin.LOCAL\n ): I[] => {\n const revived = annotations.map(a => reviveAnnotation<I>(a, container));\n\n // Initial page load might take some time. Retry for more robustness.\n const couldNotRevive = revived.filter(a => !isRevived(a.target.selector));\n store.bulkAddAnnotations(revived, replace, origin);\n\n return couldNotRevive;\n }\n \n const bulkUpsertAnnotations = (\n annotations: I[], \n origin = Origin.LOCAL\n ): I[] => {\n const revived = annotations.map(a => reviveAnnotation(a, container));\n\n // Initial page load might take some time. Retry for more robustness.\n const couldNotRevive = revived.filter(a => !isRevived(a.target.selector));\n \n revived.forEach(a => {\n if (store.getAnnotation(a.id))\n store.updateAnnotation(a, origin);\n else \n store.addAnnotation(a, origin);\n })\n\n return couldNotRevive;\n }\n\n const updateTarget = (target: TextAnnotationTarget, origin = Origin.LOCAL) => {\n const revived = reviveTarget(target, container);\n store.updateTarget(revived, origin);\n }\n\n const bulkUpdateTargets = (targets: TextAnnotationTarget[], origin = Origin.LOCAL) => {\n const revived = targets.map(t => reviveTarget(t, container));\n store.bulkUpdateTargets(revived, origin);\n }\n\n function getAt(x: number, y: number, all: true, filter?: Filter): I[] | undefined;\n function getAt(x: number, y: number, all: false, filter?: Filter): I | undefined;\n function getAt(x: number, y: number, all?: boolean, filter?: Filter): I | I[] | undefined {\n const getAll = all || Boolean(filter);\n\n const annotations = tree.getAt(x, y, getAll).map(id => store.getAnnotation(id));\n\n const filtered = filter ? annotations.filter(filter) : annotations;\n\n if (filtered.length === 0)\n return undefined;\n\n return all ? filtered : filtered[0];\n }\n\n const getAnnotationBounds = (id: string): DOMRect | undefined => {\n const rects = tree.getAnnotationRects(id);\n if (rects.length === 0) return;\n return tree.getAnnotationBounds(id);\n }\n\n const getIntersecting = (\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n ): AnnotationRects<I>[] => tree.getIntersecting(minX, minY, maxX, maxY);\n\n const getAnnotationRects = (id: string): DOMRect[] => tree.getAnnotationRects(id);\n\n const recalculatePositions = () => tree.recalculate();\n\n store.observe(({ changes }) => {\n const deleted = (changes.deleted || []).filter(a => isRevived(a.target.selector));\n const created = (changes.created || []).filter(a => isRevived(a.target.selector));\n const updated = (changes.updated || []).filter(u => isRevived(u.newValue.target.selector));\n\n if (deleted?.length > 0)\n deleted.forEach(a => tree.remove(a.target));\n\n if (created.length > 0)\n tree.set(created.map(a => a.target), false);\n\n if (updated?.length > 0)\n updated.forEach(({ newValue }) => tree.update(newValue.target));\n });\n\n return {\n store: {\n ...store,\n addAnnotation,\n bulkAddAnnotations,\n bulkUpdateTargets,\n bulkUpsertAnnotations,\n getAnnotationBounds,\n getAnnotationRects,\n getIntersecting,\n getAt,\n recalculatePositions,\n updateTarget\n },\n selection,\n hover,\n viewport\n }\n\n}\n","import type { Color, PresenceProvider, PresentUser } from '@annotorious/core';\nimport type { AnnotationRects } from '../state';\nimport type { HighlightStyle, HighlightPainter } from '../highlight';\nimport type { PresencePainterOptions } from '../presence';\nimport type { ViewportBounds } from '../highlight/viewport';\n\nimport './PresencePainter.css';\n\nconst createCanvas = () => {\n const canvas = document.createElement('canvas');\n\n // Retina resolution for crisp font rendering\n canvas.width = 2 * window.innerWidth;\n canvas.height = 2 * window.innerHeight;\n canvas.className = 'r6o-presence-layer';\n\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n\n return canvas;\n}\n\nexport const createPresencePainter = (\n provider: PresenceProvider, \n opts: PresencePainterOptions = {}\n): HighlightPainter => {\n\n const canvas = createCanvas();\n\n const ctx = canvas.getContext('2d');\n\n document.body.appendChild(canvas);\n\n const trackedAnnotations = new Map<string, PresentUser>();\n\n const getAnnotationsForUser = (p: PresentUser) =>\n Array.from(trackedAnnotations.entries())\n .filter(([id, user]) => user.presenceKey === p.presenceKey)\n .map(([id, _]) => id);\n\n provider.on('selectionChange', (p: PresentUser, selection: string[] | null) => {\n // Remove this user's previous selection\n const currentIds = getAnnotationsForUser(p);\n currentIds.forEach(id => trackedAnnotations.delete(id));\n\n // Set new selection (if any)\n if (selection)\n selection.forEach(id => trackedAnnotations.set(id, p));\n }); \n\n const clear = () => {\n const { width, height } = canvas;\n ctx.clearRect(-0.5, -0.5, width + 1, height + 1);\n }\n\n const paint = (\n highlight: AnnotationRects, \n viewportBounds: ViewportBounds,\n isSelected?: boolean\n ): HighlightStyle | undefined => {\n if (opts.font)\n ctx.font = opts.font;\n\n const user = trackedAnnotations.get(highlight.annotation.id);\n if (user) {\n // Draw cursor + label to the presence canvas\n const { height } = highlight.rects[0];\n const x = highlight.rects[0].x + viewportBounds.left;\n const y = highlight.rects[0].y + viewportBounds.top;\n\n // Draw presence indicator\n ctx.fillStyle = user.appearance.color;\n ctx.fillRect(x - 2, y - 2.5, 2, height + 5);\n\n // Draw name label\n const metrics = ctx.measureText(user.appearance.label);\n const labelWidth = metrics.width + 6;\n const labelHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + 8;\n \n // Sigh... different between FF and Chrome\n const paddingBottom = metrics.fontBoundingBoxAscent ? 8 : 6.5;\n\n ctx.fillRect(x - 2, y - 2.5 - labelHeight, labelWidth, labelHeight);\n \n ctx.fillStyle = '#fff';\n ctx.fillText(user.appearance.label, x + 1, y - paddingBottom);\n\n // Return modfied style for the renderer\n return { \n fill: user.appearance.color as Color,\n fillOpacity: isSelected ? 0.45 : 0.18\n }\n }\n }\n \n const reset = () => {\n canvas.width = 2 * window.innerWidth;\n canvas.height = 2 * window.innerHeight;\n\n // Note that resizing the canvas resets the context\n const context = canvas.getContext('2d');\n context.scale(2, 2);\n context.translate(0.5, 0.5);\n }\n\n const destroy = () => {\n canvas.remove();\n }\n\n return {\n clear,\n destroy,\n paint,\n reset\n }\n \n}\n","import { Origin } from '@annotorious/core';\nimport type { Filter, Selection, User } from '@annotorious/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport hotkeys from 'hotkeys-js';\nimport { poll } from 'poll';\nimport type { TextAnnotatorState } from './state';\nimport type { TextAnnotation, TextAnnotationTarget } from './model';\nimport type { TextAnnotatorOptions } from './TextAnnotatorOptions';\nimport {\n clonePointerEvent,\n cloneKeyboardEvent,\n debounce,\n splitAnnotatableRanges,\n rangeToSelector,\n isMac,\n isWhitespaceOrEmpty,\n trimRangeToContainer,\n isNotAnnotatable\n} from './utils';\n\nconst CLICK_TIMEOUT = 300;\n\nconst ARROW_KEYS = ['up', 'down', 'left', 'right'];\n\nconst SELECT_ALL = isMac ? '⌘+a' : 'ctrl+a';\n\nconst SELECTION_KEYS = [\n ...ARROW_KEYS.map(key => `shift+${key}`),\n SELECT_ALL\n];\n\nexport const SelectionHandler = (\n container: HTMLElement,\n state: TextAnnotatorState<TextAnnotation, unknown>,\n options: TextAnnotatorOptions<TextAnnotation, unknown>\n) => {\n\n let currentUser: User | undefined;\n\n const {\n annotatingEnabled,\n offsetReferenceSelector,\n selectionMode,\n dismissOnNotAnnotatable = 'NEVER'\n } = options;\n\n const setUser = (user?: User) => currentUser = user;\n\n let currentFilter: Filter | undefined;\n\n const setFilter = (filter?: Filter) => currentFilter = filter;\n\n const { store, selection } = state;\n\n let currentTarget: TextAnnotationTarget | undefined;\n\n let isLeftClick: boolean | undefined;\n\n let lastDownEvent: Selection['event'] | undefined;\n\n const onSelectStart = (evt: Event) => {\n if (isLeftClick === false)\n return;\n\n /**\n * Make sure we don't listen to selection changes that were\n * not started on the container, or which are not supposed to\n * be annotatable (like a component popup).\n * Note that Chrome/iOS will sometimes return the root doc as target!\n */\n currentTarget = isNotAnnotatable(container, evt.target as Node)\n ? undefined\n : {\n annotation: uuidv4(),\n selector: [],\n creator: currentUser,\n created: new Date()\n };\n };\n\n const onSelectionChange = debounce((evt: Event) => {\n const sel = document.getSelection();\n\n /**\n * In iOS when a user clicks on a button, the `selectionchange` event is fired.\n * However, the generated selection is empty and the `anchorNode` is `null`. That\n * doesn't give us information about whether the selection is in the annotatable area\n * or whether the previously selected text was dismissed. Therefore we should bail\n * out from such a range processing.\n *\n * @see https://github.com/recogito/text-annotator-js/pull/164#issuecomment-2416961473\n */\n if (!sel?.anchorNode) {\n return;\n }\n\n /**\n * This is to handle cases where the selection is \"hijacked\" by\n * another element in a not-annotatable area. A rare case in practice.\n * But rich text editors like Quill will do it!\n */\n if (isNotAnnotatable(container, sel.anchorNode)) {\n currentTarget = undefined;\n return;\n }\n\n const timeDifference = evt.timeStamp - (lastDownEvent?.timeStamp || evt.timeStamp);\n\n /**\n * The selection start needs to be emulated only for the pointer events!\n * The keyboard ones are consistently fired on desktops\n * and the `timeDifference` will always be <10ms. between the `keydown` and `selectionchange`\n */\n if (lastDownEvent?.type === 'pointerdown') {\n if (timeDifference < 1000 && !currentTarget) {\n // Chrome/iOS does not reliably fire the 'selectstart' event!\n onSelectStart(lastDownEvent || evt);\n } else if (sel.isCollapsed && timeDifference < CLICK_TIMEOUT) {\n // Firefox doesn't fire the 'selectstart' when user clicks\n // over the text, which collapses the selection\n onSelectStart(lastDownEvent || evt);\n }\n }\n\n // The selection isn't active -> bail out from selection change processing\n if (!currentTarget) return;\n\n if (sel.isCollapsed) {\n /**\n * The selection range got collapsed during the selecting process.\n * The previously created annotation isn't relevant anymore and can be discarded\n *\n * @see https://github.com/recogito/text-annotator-js/issues/139\n */\n if (store.getAnnotation(currentTarget.annotation)) {\n selection.clear();\n store.deleteAnnotation(currentTarget.annotation);\n }\n\n return;\n }\n\n const selectionRanges =\n Array.from(Array(sel.rangeCount).keys()).map(idx => sel.getRangeAt(idx));\n\n const containedRanges =\n selectionRanges.map(r => trimRangeToContainer(r, container));\n\n // The selection should be captured only within the annotatable container\n if (containedRanges.every(r => isWhitespaceOrEmpty(r))) return;\n\n const annotatableRanges = containedRanges.flatMap(r => splitAnnotatableRanges(container, r.cloneRange()));\n\n const hasChanged =\n annotatableRanges.length !== currentTarget.selector.length ||\n annotatableRanges.some((r, i) => r.toString() !== currentTarget.selector[i]?.quote);\n\n if (!hasChanged) return;\n\n currentTarget = {\n ...currentTarget,\n selector: annotatableRanges.map(r => rangeToSelector(r, container, offsetReferenceSelector)),\n updated: new Date()\n };\n\n /**\n * During mouse selection on the desktop, the annotation won't usually exist while the selection is being edited.\n * But it'll be typical during selection via the keyboard or mobile's handlebars.\n */\n if (store.getAnnotation(currentTarget.annotation)) {\n store.updateTarget(currentTarget, Origin.LOCAL);\n } else {\n // Proper lifecycle management: clear the previous selection first...\n selection.clear();\n }\n });\n\n /**\n * Select events don't carry information about the mouse button.\n * Therefore, to prevent right-click selection, we need to listen\n * to the initial pointerdown event and remember the button\n */\n const onPointerDown = (evt: PointerEvent) => {\n if (isNotAnnotatable(container, evt.target as Node)) return;\n\n /**\n * Cloning the event to prevent it from accidentally being `undefined`\n * @see https://github.com/recogito/text-annotator-js/commit/65d13f3108c429311cf8c2523f6babbbc946013d#r144033948\n */\n lastDownEvent = clonePointerEvent(evt);\n isLeftClick = lastDownEvent.button === 0;\n };\n\n const onPointerUp = async (evt: PointerEvent) => {\n if (!isLeftClick) return;\n\n if (isNotAnnotatable(container, evt.target as Node)) {\n const shouldDismissSelection = typeof dismissOnNotAnnotatable === 'function'\n ? dismissOnNotAnnotatable(evt, container)\n : dismissOnNotAnnotatable === 'ALWAYS';\n if (shouldDismissSelection) {\n selection.clear();\n }\n return;\n }\n\n // Logic for selecting an existing annotation\n const clickSelect = () => {\n const { x, y } = container.getBoundingClientRect();\n\n const hovered =\n evt.target instanceof Node &&\n container.contains(evt.target) &&\n store.getAt(evt.clientX - x, evt.clientY - y, selectionMode === 'all', currentFilter);\n\n if (hovered) {\n const { selected } = selection;\n\n const currentIds = new Set(selected.map(s => s.id));\n const nextIds = Array.isArray(hovered) ? hovered.map(a => a.id) : [hovered.id];\n\n const hasChanged =\n currentIds.size !== nextIds.length ||\n !nextIds.every(id => currentIds.has(id));\n\n if (hasChanged)\n selection.userSelect(nextIds, evt);\n } else {\n selection.clear();\n }\n };\n\n const timeDifference = evt.timeStamp - lastDownEvent.timeStamp;\n if (timeDifference < CLICK_TIMEOUT) {\n await pollSelectionCollapsed();\n\n const sel = document.getSelection();\n if (sel?.isCollapsed) {\n currentTarget = undefined;\n clickSelect();\n return;\n }\n }\n\n if (currentTarget && currentTarget.selector.length > 0) {\n upsertCurrentTarget();\n selection.userSelect(currentTarget.annotation, clonePointerEvent(evt));\n }\n }\n\n /**\n * We must check the `isCollapsed` after an unspecified timeout\n * to handle the annotation dismissal after a click properly.\n *\n * Otherwise, the `isCollapsed` will return an obsolete `false` value,\n * click won't be processed, and the annotation will get falsely re-selected.\n *\n * @see https://github.com/recogito/text-annotator-js/issues/136#issue-2465915707\n * @see https://github.com/recogito/text-annotator-js/issues/136#issuecomment-2413773804\n */\n const pollSelectionCollapsed = async () => {\n const sel = document.getSelection();\n\n let stopPolling = false;\n let isCollapsed = sel?.isCollapsed;\n const shouldStopPolling = () => isCollapsed || stopPolling;\n\n const pollingDelayMs = 1;\n const stopPollingInMs = 50;\n setTimeout(() => stopPolling = true, stopPollingInMs);\n\n return poll(() => isCollapsed = sel?.isCollapsed, pollingDelayMs, shouldStopPolling);\n }\n\n const onContextMenu = (evt: PointerEvent) => {\n const sel = document.getSelection();\n\n if (sel?.isCollapsed) return;\n\n /**\n * When selecting the initial word, Chrome Android\n * fires `contextmenu`before `selectionchange`\n */\n if (!currentTarget || currentTarget.selector.length === 0) {\n onSelectionChange(evt);\n }\n /**\n * The selection couldn't be initiated - might span over a not-annotatable element.\n */\n if (!currentTarget) return;\n upsertCurrentTarget();\n\n selection.userSelect(currentTarget.annotation, clonePointerEvent(evt));\n }\n\n const onKeyup = (evt: KeyboardEvent) => {\n if (evt.key === 'Shift' && currentTarget) {\n const sel = document.getSelection();\n\n if (!sel.isCollapsed) {\n upsertCurrentTarget();\n selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt));\n }\n }\n }\n\n const onSelectAll = (evt: KeyboardEvent) => {\n\n const onSelected = () => setTimeout(() => {\n if (currentTarget?.selector.length > 0) {\n selection.clear();\n\n store.addAnnotation({\n id: currentTarget.annotation,\n bodies: [],\n target: currentTarget\n });\n\n selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt));\n }\n\n document.removeEventListener('selectionchange', onSelected);\n\n // Sigh... this needs a delay to work. But doesn't seem reliable.\n }, 100);\n\n // Listen to the change event that follows\n document.addEventListener('selectionchange', onSelected);\n\n // Start selection!\n onSelectStart(evt);\n }\n\n hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, evt => {\n if (!evt.repeat)\n lastDownEvent = cloneKeyboardEvent(evt);\n });\n\n hotkeys(SELECT_ALL, { keydown: true, keyup: false }, evt => {\n lastDownEvent = cloneKeyboardEvent(evt);\n onSelectAll(evt);\n });\n\n /**\n * Free caret movement through the text resets the annotation selection.\n *\n * It should be handled only on:\n * - the annotatable `container`, where the text is.\n * - the `body`, where the focus goes when user closes the popup,\n * or clicks the button that gets unmounted, e.g. \"Close\"\n */\n const handleArrowKeyPress = (evt: KeyboardEvent) => {\n if (\n evt.repeat ||\n evt.target !== container && evt.target !== document.body\n ) {\n return;\n }\n\n currentTarget = undefined;\n selection.clear();\n };\n\n hotkeys(ARROW_KEYS.join(','), { keydown: true, keyup: false }, handleArrowKeyPress);\n\n // Helper\n const upsertCurrentTarget = () => {\n const existingAnnotation = store.getAnnotation(currentTarget.annotation);\n if (!existingAnnotation) {\n store.addAnnotation({\n id: currentTarget.annotation,\n bodies: [],\n target: currentTarget\n });\n return;\n }\n\n const { target: { updated: existingTargetUpdated } } = existingAnnotation;\n const { updated: currentTargetUpdated } = currentTarget;\n if (\n !existingTargetUpdated ||\n !currentTargetUpdated ||\n existingTargetUpdated < currentTargetUpdated\n ) {\n store.updateTarget(currentTarget);\n }\n };\n\n container.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('pointerup', onPointerUp);\n document.addEventListener('contextmenu', onContextMenu);\n\n if (annotatingEnabled) {\n container.addEventListener('keyup', onKeyup);\n container.addEventListener('selectstart', onSelectStart);\n document.addEventListener('selectionchange', onSelectionChange);\n }\n\n const destroy = () => {\n container.removeEventListener('pointerdown', onPointerDown);\n document.removeEventListener('pointerup', onPointerUp);\n document.removeEventListener('contextmenu', onContextMenu);\n\n container.removeEventListener('keyup', onKeyup);\n container.removeEventListener('selectstart', onSelectStart);\n document.removeEventListener('selectionchange', onSelectionChange);\n\n hotkeys.unbind();\n };\n\n return {\n destroy,\n setFilter,\n setUser\n }\n\n}\n\n","import type { FormatAdapter, UserSelectActionExpression, User, Annotation } from '@annotorious/core';\nimport type { PresencePainterOptions } from './presence';\nimport type { TextAnnotation } from './model';\nimport type { HighlightStyleExpression } from './highlight';\n\nexport interface TextAnnotatorOptions<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> {\n\n adapter?: FormatAdapter<I, E> | null;\n\n annotatingEnabled?: boolean;\n\n /**\n * Determines whether an active selection should be dismissed\n * when a user ends their interaction (click, selection)\n * on a non-annotatable element.\n * - NEVER - don't dismiss the selection, ignore the action.\n * - ALWAYS - dismiss the selection.\n * - function - a custom matcher that takes an event and container as arguments.\n * Returns `true` if the selection should be dismissed.\n *\n * @defaut NEVER\n */\n dismissOnNotAnnotatable?: DismissOnNotAnnotatableExpression;\n\n renderer?: RendererType;\n\n offsetReferenceSelector?: string;\n\n userSelectAction?: UserSelectActionExpression<E>,\n\n presence?: PresencePainterOptions;\n\n selectionMode?: 'shortest' | 'all';\n\n style?: HighlightStyleExpression;\n\n user?: User;\n \n}\n\nexport type RendererType = 'SPANS' | 'CANVAS' | 'CSS_HIGHLIGHTS';\n\nexport type DismissOnNotAnnotatableExpression = 'NEVER'| 'ALWAYS' | ((event: Event, container: HTMLElement) => boolean)\n\nexport const fillDefaults = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n opts: TextAnnotatorOptions<I, E>,\n defaults: TextAnnotatorOptions<I, E>\n): TextAnnotatorOptions<I, E> => {\n\n return {\n ...opts,\n annotatingEnabled: opts.annotatingEnabled ?? defaults.annotatingEnabled,\n user: opts.user || defaults.user\n };\n\n};\n","import { createAnonymousGuest, createLifecycleObserver, createBaseAnnotator, createUndoStack } from '@annotorious/core';\nimport type { Filter } from '@annotorious/core';\nimport type { Annotator, User, PresenceProvider } from '@annotorious/core';\nimport { createCanvasRenderer, createHighlightsRenderer, createSpansRenderer, type HighlightStyleExpression } from './highlight';\nimport { createPresencePainter } from './presence';\nimport { scrollIntoView } from './api';\nimport { type TextAnnotationStore, type TextAnnotatorState, createTextAnnotatorState } from './state';\nimport type { TextAnnotation } from './model';\nimport { cancelSingleClickEvents, programmaticallyFocusable } from './utils';\nimport { fillDefaults, type RendererType, type TextAnnotatorOptions } from './TextAnnotatorOptions';\nimport { SelectionHandler } from './SelectionHandler';\n\nimport './TextAnnotator.css';\n\nconst USE_DEFAULT_RENDERER: RendererType = 'SPANS';\n\nexport interface TextAnnotator<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends Annotator<I, E> {\n\n element: HTMLElement;\n\n setStyle(style: HighlightStyleExpression | undefined): void;\n\n // Returns true if successful (or false if the annotation is not currently rendered)\n scrollIntoView(annotationOrId: I | string): boolean;\n\n state: TextAnnotatorState<I, E>;\n\n}\n\nexport const createTextAnnotator = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(\n container: HTMLElement,\n options: TextAnnotatorOptions<I, E> = {}\n): TextAnnotator<I, E> => {\n // Prevent mobile browsers from triggering word selection on single click.\n cancelSingleClickEvents(container);\n\n // Make sure that the container is focusable and can receive both pointer and keyboard events\n programmaticallyFocusable(container);\n\n const opts = fillDefaults<I, E>(options, {\n annotatingEnabled: true,\n user: createAnonymousGuest()\n });\n\n const state: TextAnnotatorState<I, E> = createTextAnnotatorState<I, E>(container, opts);\n\n const { selection, viewport } = state;\n\n const store: TextAnnotationStore<I> = state.store;\n\n const undoStack = createUndoStack<I>(store);\n\n const lifecycle = createLifecycleObserver<I, E>(state, undoStack, opts.adapter);\n\n let currentUser: User = opts.user;\n\n // Use selected renderer, or fall back to default. If CSS_HIGHLIGHT is\n // requested, check if CSS Custom Highlights are supported, and fall\n // back to default renderer if not.\n const useRenderer: RendererType =\n opts.renderer === 'CSS_HIGHLIGHTS'\n ? Boolean(CSS.highlights) ? 'CSS_HIGHLIGHTS' : USE_DEFAULT_RENDERER\n : opts.renderer || USE_DEFAULT_RENDERER;\n\n const highlightRenderer =\n useRenderer === 'SPANS' ? createSpansRenderer(container, state, viewport) :\n useRenderer === 'CSS_HIGHLIGHTS' ? createHighlightsRenderer(container, state, viewport) :\n useRenderer === 'CANVAS' ? createCanvasRenderer(container, state, viewport) : undefined;\n\n if (!highlightRenderer)\n throw `Unknown renderer implementation: ${useRenderer}`;\n\n console.debug(`Using ${useRenderer} renderer`);\n\n if (opts.style)\n highlightRenderer.setStyle(opts.style);\n\n const selectionHandler = SelectionHandler(container, state, opts);\n selectionHandler.setUser(currentUser);\n\n /*************************/\n /* External API */\n /******++++++*************/\n\n // Most of the external API functions are covered in the base annotator\n const base = createBaseAnnotator<I, E>(state, undoStack, opts.adapter);\n\n const getUser = () => currentUser;\n\n const setFilter = (filter?: Filter<I>) => {\n highlightRenderer.setFilter(filter);\n selectionHandler.setFilter(filter);\n }\n\n const setStyle = (style: HighlightStyleExpression | undefined) =>\n highlightRenderer.setStyle(style);\n\n const setUser = (user: User) => {\n currentUser = user;\n selectionHandler.setUser(user);\n }\n\n const setPresenceProvider = (provider: PresenceProvider) => {\n if (provider) {\n highlightRenderer.setPainter(createPresencePainter(provider, opts.presence));\n provider.on('selectionChange', () => highlightRenderer.redraw());\n }\n }\n\n const setSelected = (arg?: string | string[]) => {\n if (arg) {\n selection.setSelected(arg);\n } else {\n selection.clear();\n }\n }\n\n const setVisible = (visible: boolean) =>\n highlightRenderer.setVisible(visible);\n\n const destroy = () => {\n highlightRenderer.destroy();\n selectionHandler.destroy();\n\n // Other cleanup actions\n undoStack.destroy();\n }\n\n return {\n ...base,\n destroy,\n element: container,\n getUser,\n setFilter,\n setStyle,\n setUser,\n setSelected,\n setPresenceProvider,\n setVisible,\n on: lifecycle.on,\n off: lifecycle.off,\n scrollIntoView: scrollIntoView(container, store),\n state\n }\n\n}\n"],"names":["NOT_ANNOTATABLE_CLASS","NOT_ANNOTATABLE_SELECTOR","isNotAnnotatable","container","node","_a","isRangeAnnotatable","range","ancestor","cancelSingleClickEvents","event","clonePointerEvent","cloneKeyboardEvent","isMac","programmaticallyFocusable","debounce","func","delay","timeoutId","args","iterateNotAnnotatableElements","notAnnotatableIterator","notAnnotatableNode","splitAnnotatableRanges","annotatableRanges","prevNotAnnotatable","notAnnotatable","subRange","lastRange","getRangeAnnotatableContents","contents","el","getQuoteContext","length","offsetReferenceSelector","offsetReference","rangeBefore","before","rangeAfter","after","isRevived","selector","s","whitespaceOrEmptyRegex","isWhitespaceOrEmpty","getRelation","rectA","rectB","round","num","a","b","union","left","right","top","bottom","mergeClientRects","rects","merged","next","wasMerged","relation","r","toDomRectList","index","i","rangeToSelector","quote","start","end","reviveSelector","iterator","runningOffset","n","startCounting","len","_b","reviveTarget","target","reviveAnnotation","annotation","trimRangeToContainer","trimmedRange","getScrollParent","overflowY","scrollIntoView","store","annotationOrId","id","scroll","parentBounds","scrollParent","parentHeight","parentWidth","annotationBounds","width","height","offsetTop","offsetLeft","scrollTop","scrollLeft","current","annoRange","revived","revivedAnnoRange","DEFAULT_STYLE","DEFAULT_SELECTED_STYLE","paint","highlight","viewportBounds","style","painter","zIndex","base","getViewportBounds","innerWidth","innerHeight","minX","minY","maxX","maxY","trackViewport","viewport","visible","annotations","ids","createBaseRenderer","state","renderer","selection","hover","currentStyle","currentFilter","currentPainter","onDraw","onPointerMove","x","y","hit","redraw","lazy","bounds","annotationsInView","selectedIds","highlights","selected","hovered","setPainter","setStyle","setFilter","filter","onStoreChange","unsubscribeSelection","unsubscribeHover","onScroll","onResize","resizeObserver","config","mutationObserver","records","record","createCanvas","canvas","resetCanvas","highres","createRenderer","ctx","highlightA","highlightB","createdA","createdB","h","offsetRects","underlineOffset","createCanvasRenderer","toCSS","colord","elem","currentRendered","nextRendered","updatedCSS","ranges","createHighlightsRenderer","computeZIndex","rect","all","intersects","getLength","total","intersecting","highlightLayer","shouldRedraw","dequal","span","createSpansRenderer","W3CTextFormat","source","serialized","parseW3CTextAnnotation","serializeW3CTextAnnotation","isTextSelector","parseW3CTextTargets","annotationId","creator","created","modified","w3cTargets","parsed","parseW3CUser","w3cTarget","w3cSelector","missingTypes","uuidv4","body","rest","bodies","parseW3CBodies","updated","targetRest","quoteSelector","prefix","suffix","positionSelector","serializeW3CBodies","createSpatialTree","tree","RBush","toItems","offset","revivedRange","clear","insert","remove","update","set","targets","replace","rectsByTarget","allRects","getAt","hits","area","getAnnotationBounds","getAnnotationRects","indexed","annotationIds","t","createTextAnnotatorState","opts","createStore","createSelectionState","createHoverState","createViewportState","addAnnotation","origin","Origin","isValid","bulkAddAnnotations","couldNotRevive","bulkUpsertAnnotations","updateTarget","bulkUpdateTargets","getAll","filtered","getIntersecting","recalculatePositions","changes","deleted","u","newValue","context","createPresencePainter","provider","trackedAnnotations","getAnnotationsForUser","p","user","_","isSelected","metrics","labelWidth","labelHeight","paddingBottom","CLICK_TIMEOUT","ARROW_KEYS","SELECT_ALL","SELECTION_KEYS","key","SelectionHandler","options","currentUser","annotatingEnabled","selectionMode","dismissOnNotAnnotatable","setUser","currentTarget","isLeftClick","lastDownEvent","onSelectStart","evt","onSelectionChange","sel","timeDifference","containedRanges","idx","onPointerDown","onPointerUp","clickSelect","currentIds","nextIds","pollSelectionCollapsed","upsertCurrentTarget","stopPolling","isCollapsed","shouldStopPolling","pollingDelayMs","poll","onContextMenu","onKeyup","onSelectAll","onSelected","hotkeys","handleArrowKeyPress","existingAnnotation","existingTargetUpdated","currentTargetUpdated","fillDefaults","defaults","USE_DEFAULT_RENDERER","createTextAnnotator","createAnonymousGuest","undoStack","createUndoStack","lifecycle","createLifecycleObserver","useRenderer","highlightRenderer","selectionHandler","createBaseAnnotator","arg"],"mappings":"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"}
|