@epam/pdf-highlighter-kit 0.0.9 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/PDFHighlightViewer.d.ts +15 -5
- package/dist/PDFHighlightViewer.d.ts.map +1 -1
- package/dist/PDFHighlightViewer.js +75 -40
- package/dist/PDFHighlightViewer.js.map +1 -1
- package/dist/api.d.ts +5 -5
- package/dist/api.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/pdf-engine.d.ts +2 -2
- package/dist/core/pdf-engine.d.ts.map +1 -1
- package/dist/core/pdf-engine.js +2 -8
- package/dist/core/pdf-engine.js.map +1 -1
- package/dist/core/performance-optimizer.d.ts +10 -10
- package/dist/core/performance-optimizer.d.ts.map +1 -1
- package/dist/core/performance-optimizer.js +2 -1
- package/dist/core/performance-optimizer.js.map +1 -1
- package/dist/core/viewport-manager.d.ts +18 -7
- package/dist/core/viewport-manager.d.ts.map +1 -1
- package/dist/core/viewport-manager.js +84 -35
- package/dist/core/viewport-manager.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +18 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/label-style.d.ts.map +1 -1
- package/dist/utils/label-style.js +3 -2
- package/dist/utils/label-style.js.map +1 -1
- package/dist/utils/pdf-utils.d.ts +3 -2
- package/dist/utils/pdf-utils.d.ts.map +1 -1
- package/dist/utils/pdf-utils.js +2 -2
- package/dist/utils/pdf-utils.js.map +1 -1
- package/dist/utils/worker-loader-simple.d.ts.map +1 -1
- package/dist/utils/worker-loader-simple.js +4 -1
- package/dist/utils/worker-loader-simple.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -201,9 +201,14 @@ export interface ViewerOptions {
|
|
|
201
201
|
|
|
202
202
|
// Page dimensions for which bbox coordinates were calculated
|
|
203
203
|
bboxSourceDimensions?: BBoxDimensions;
|
|
204
|
+
|
|
205
|
+
// Only show these document page numbers (1-based). If empty or omitted, all pages are shown.
|
|
206
|
+
selectedPages?: number[];
|
|
204
207
|
}
|
|
205
208
|
```
|
|
206
209
|
|
|
210
|
+
**Displaying only selected pages:** Use `selectedPages` to show a subset of the document (e.g. `[1, 3, 5]` or `[2, 4, 6, 8]`). The full PDF is still loaded; only the listed pages get DOM containers and participate in scrolling and rendering. Page numbers in the API (e.g. `setPage`, events, highlights) remain physical document page numbers. You can pass `selectedPages` in `init` options or per load via `loadPDF(source, { selectedPages })`; the latter overrides the init value for that load. `getTotalPages()` returns the length of the displayed list when `selectedPages` is set.
|
|
211
|
+
|
|
207
212
|
## API Reference
|
|
208
213
|
|
|
209
214
|
### Main Methods
|
|
@@ -212,9 +217,18 @@ export interface ViewerOptions {
|
|
|
212
217
|
|
|
213
218
|
Initialize the viewer with a container element and optional configuration.
|
|
214
219
|
|
|
215
|
-
#### `loadPDF(source: string | ArrayBuffer | Blob): Promise<void>`
|
|
220
|
+
#### `loadPDF(source: string | ArrayBuffer | Blob, options?: LoadPDFOptions): Promise<void>`
|
|
221
|
+
|
|
222
|
+
Load a PDF document from URL or ArrayBuffer. Optional second argument:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
interface LoadPDFOptions {
|
|
226
|
+
/** Only show these document page numbers (1-based). If empty or omitted, all pages are shown. */
|
|
227
|
+
selectedPages?: number[];
|
|
228
|
+
}
|
|
229
|
+
```
|
|
216
230
|
|
|
217
|
-
|
|
231
|
+
Example: `await viewer.loadPDF(url, { selectedPages: [1, 3, 5] });` shows only pages 1, 3, and 5. When `options.selectedPages` is provided, it overrides `ViewerOptions.selectedPages` for this load.
|
|
218
232
|
|
|
219
233
|
#### `loadHighlights(highlights: InputHighlightData[]): void`
|
|
220
234
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PDFHighlightViewer as IPDFHighlightViewer } from './api';
|
|
2
|
-
import { ViewerOptions, TextRange, SelectionWithMetadata, PerformanceMetrics, HighlightAnalytics, AccessibilityFeatures, InteractionMode, InputHighlightData, HighlightStyle, HighlightLabelStyle, ZoomValue, ThumbnailOptions } from './types';
|
|
2
|
+
import { PDFSource, ViewerOptions, LoadPDFOptions, TextRange, SelectionWithMetadata, PerformanceMetrics, HighlightAnalytics, AccessibilityFeatures, InteractionMode, InputHighlightData, HighlightStyle, HighlightLabelStyle, ZoomValue, ThumbnailOptions } from './types';
|
|
3
3
|
type EventCallback = (data?: unknown) => void;
|
|
4
4
|
export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
5
5
|
private pdfEngine;
|
|
@@ -15,6 +15,10 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
15
15
|
private currentPage;
|
|
16
16
|
private currentScale;
|
|
17
17
|
private totalPages;
|
|
18
|
+
/** Actual number of pages in the loaded PDF (1..documentNumPages). */
|
|
19
|
+
private documentNumPages;
|
|
20
|
+
/** When set, only these physical page numbers are shown; null = all pages. */
|
|
21
|
+
private selectedPages;
|
|
18
22
|
private selectedTermId;
|
|
19
23
|
private isInitialized;
|
|
20
24
|
private navIndex;
|
|
@@ -58,9 +62,15 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
58
62
|
* Handle keyboard navigation
|
|
59
63
|
*/
|
|
60
64
|
private handleKeyboardNavigation;
|
|
61
|
-
loadPDF(source:
|
|
65
|
+
loadPDF(source: PDFSource, options?: LoadPDFOptions): Promise<void>;
|
|
62
66
|
/**
|
|
63
|
-
*
|
|
67
|
+
* Normalize selectedPages: filter to 1..numPages, dedupe, sort. Empty result => null (show all).
|
|
68
|
+
*/
|
|
69
|
+
private normalizeSelectedPages;
|
|
70
|
+
/** List of physical page numbers to display (either selectedPages or 1..documentNumPages). */
|
|
71
|
+
private getDisplayedPageList;
|
|
72
|
+
/**
|
|
73
|
+
* Create DOM containers for displayed pages only (selectedPages or all)
|
|
64
74
|
*/
|
|
65
75
|
private createPageContainers;
|
|
66
76
|
/**
|
|
@@ -125,7 +135,7 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
125
135
|
getSelection: () => string;
|
|
126
136
|
getSelectionWithContext: () => SelectionWithMetadata | null;
|
|
127
137
|
clearSelection: () => void;
|
|
128
|
-
selectText: (
|
|
138
|
+
selectText: (_range: TextRange) => void;
|
|
129
139
|
copySelection: (format?: "plain" | "formatted" | "citation") => void;
|
|
130
140
|
createHighlightFromSelection: (style?: HighlightStyle) => InputHighlightData | null;
|
|
131
141
|
};
|
|
@@ -188,7 +198,7 @@ export declare class PDFHighlightViewer implements IPDFHighlightViewer {
|
|
|
188
198
|
private toPageCoordinateDimensions;
|
|
189
199
|
private normalizeBBoxForPage;
|
|
190
200
|
/**
|
|
191
|
-
* Build spatial indices for
|
|
201
|
+
* Build spatial indices for displayed pages only
|
|
192
202
|
*/
|
|
193
203
|
private buildAllSpatialIndices;
|
|
194
204
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PDFHighlightViewer.d.ts","sourceRoot":"","sources":["../src/PDFHighlightViewer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,IAAI,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EACL,aAAa,
|
|
1
|
+
{"version":3,"file":"PDFHighlightViewer.d.ts","sourceRoot":"","sources":["../src/PDFHighlightViewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,10 @@ export class PDFHighlightViewer {
|
|
|
23
23
|
this.currentPage = 1;
|
|
24
24
|
this.currentScale = 1.5;
|
|
25
25
|
this.totalPages = 0;
|
|
26
|
+
/** Actual number of pages in the loaded PDF (1..documentNumPages). */
|
|
27
|
+
this.documentNumPages = 0;
|
|
28
|
+
/** When set, only these physical page numbers are shown; null = all pages. */
|
|
29
|
+
this.selectedPages = null;
|
|
26
30
|
this.selectedTermId = null;
|
|
27
31
|
this.isInitialized = false;
|
|
28
32
|
this.navIndex = -1;
|
|
@@ -56,9 +60,8 @@ export class PDFHighlightViewer {
|
|
|
56
60
|
clearSelection: () => {
|
|
57
61
|
this.interactionHandler.clearSelection();
|
|
58
62
|
},
|
|
59
|
-
selectText: (
|
|
63
|
+
selectText: (_range) => {
|
|
60
64
|
// TODO: Implement programmatic text selection
|
|
61
|
-
console.log('selectText not yet implemented:', range);
|
|
62
65
|
},
|
|
63
66
|
copySelection: (format = 'plain') => {
|
|
64
67
|
const selection = this.textSelection.getSelection();
|
|
@@ -441,23 +444,30 @@ export class PDFHighlightViewer {
|
|
|
441
444
|
* Handle keyboard navigation
|
|
442
445
|
*/
|
|
443
446
|
handleKeyboardNavigation(event) {
|
|
447
|
+
const displayed = this.getDisplayedPageList();
|
|
448
|
+
if (displayed.length === 0)
|
|
449
|
+
return;
|
|
450
|
+
const currentIdx = displayed.indexOf(this.currentPage);
|
|
451
|
+
const idx = currentIdx >= 0 ? currentIdx : 0;
|
|
444
452
|
switch (event.key) {
|
|
445
453
|
case 'PageDown':
|
|
446
454
|
case 'ArrowDown':
|
|
447
|
-
|
|
455
|
+
if (idx < displayed.length - 1)
|
|
456
|
+
this.setPage(displayed[idx + 1]);
|
|
448
457
|
event.preventDefault();
|
|
449
458
|
break;
|
|
450
459
|
case 'PageUp':
|
|
451
460
|
case 'ArrowUp':
|
|
452
|
-
|
|
461
|
+
if (idx > 0)
|
|
462
|
+
this.setPage(displayed[idx - 1]);
|
|
453
463
|
event.preventDefault();
|
|
454
464
|
break;
|
|
455
465
|
case 'Home':
|
|
456
|
-
this.setPage(
|
|
466
|
+
this.setPage(displayed[0]);
|
|
457
467
|
event.preventDefault();
|
|
458
468
|
break;
|
|
459
469
|
case 'End':
|
|
460
|
-
this.setPage(
|
|
470
|
+
this.setPage(displayed[displayed.length - 1]);
|
|
461
471
|
event.preventDefault();
|
|
462
472
|
break;
|
|
463
473
|
case '+':
|
|
@@ -474,20 +484,23 @@ export class PDFHighlightViewer {
|
|
|
474
484
|
// =============================================================================
|
|
475
485
|
// PDF Management
|
|
476
486
|
// =============================================================================
|
|
477
|
-
async loadPDF(source) {
|
|
487
|
+
async loadPDF(source, options) {
|
|
478
488
|
if (!this.isInitialized) {
|
|
479
489
|
throw new Error('Viewer must be initialized before loading PDF');
|
|
480
490
|
}
|
|
481
491
|
try {
|
|
482
|
-
// Load document with PDF engine
|
|
483
492
|
await this.pdfEngine.loadDocument(source);
|
|
484
493
|
const docInfo = this.pdfEngine.getDocumentInfo();
|
|
485
|
-
this.
|
|
486
|
-
|
|
494
|
+
this.documentNumPages = docInfo.numPages;
|
|
495
|
+
const rawSelected = options?.selectedPages ?? this.options.selectedPages;
|
|
496
|
+
const selectedPages = this.normalizeSelectedPages(rawSelected, this.documentNumPages);
|
|
497
|
+
this.selectedPages = selectedPages;
|
|
498
|
+
this.totalPages = selectedPages !== null ? selectedPages.length : this.documentNumPages;
|
|
499
|
+
this.viewportManager.setSelectedPages(selectedPages);
|
|
487
500
|
this.viewportManager.setTotalPages(this.totalPages);
|
|
488
|
-
// Create page containers
|
|
489
501
|
await this.createPageContainers();
|
|
490
|
-
|
|
502
|
+
const displayed = this.getDisplayedPageList();
|
|
503
|
+
this.currentPage = displayed.length > 0 ? displayed[0] : 1;
|
|
491
504
|
await this.loadInitialPages();
|
|
492
505
|
if (this.options.enableVirtualScrolling === false) {
|
|
493
506
|
await this.renderAllPagesBatched(2);
|
|
@@ -500,17 +513,45 @@ export class PDFHighlightViewer {
|
|
|
500
513
|
}
|
|
501
514
|
}
|
|
502
515
|
/**
|
|
503
|
-
*
|
|
516
|
+
* Normalize selectedPages: filter to 1..numPages, dedupe, sort. Empty result => null (show all).
|
|
517
|
+
*/
|
|
518
|
+
normalizeSelectedPages(raw, numPages) {
|
|
519
|
+
if (!raw || raw.length === 0)
|
|
520
|
+
return null;
|
|
521
|
+
const set = new Set();
|
|
522
|
+
for (const p of raw) {
|
|
523
|
+
if (Number.isInteger(p) && p >= 1 && p <= numPages)
|
|
524
|
+
set.add(p);
|
|
525
|
+
}
|
|
526
|
+
if (set.size === 0)
|
|
527
|
+
return null;
|
|
528
|
+
return Array.from(set).sort((a, b) => a - b);
|
|
529
|
+
}
|
|
530
|
+
/** List of physical page numbers to display (either selectedPages or 1..documentNumPages). */
|
|
531
|
+
getDisplayedPageList() {
|
|
532
|
+
if (this.selectedPages !== null && this.selectedPages.length > 0) {
|
|
533
|
+
return this.selectedPages;
|
|
534
|
+
}
|
|
535
|
+
const list = [];
|
|
536
|
+
for (let i = 1; i <= this.documentNumPages; i++) {
|
|
537
|
+
list.push(i);
|
|
538
|
+
}
|
|
539
|
+
return list;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Create DOM containers for displayed pages only (selectedPages or all)
|
|
504
543
|
*/
|
|
505
544
|
async createPageContainers() {
|
|
506
545
|
if (!this.pdfContainer)
|
|
507
546
|
return;
|
|
508
|
-
// Clear existing containers
|
|
509
547
|
this.pdfContainer.innerHTML = '';
|
|
510
548
|
this.pageContainers.clear();
|
|
511
|
-
const
|
|
549
|
+
const displayed = this.getDisplayedPageList();
|
|
550
|
+
if (displayed.length === 0)
|
|
551
|
+
return;
|
|
552
|
+
const firstPageDimensions = await this.getPageDimensions(displayed[0]);
|
|
512
553
|
const avgPageHeight = firstPageDimensions.height;
|
|
513
|
-
for (
|
|
554
|
+
for (const pageNumber of displayed) {
|
|
514
555
|
const pageContainer = document.createElement('div');
|
|
515
556
|
pageContainer.className = 'pdf-page-container';
|
|
516
557
|
pageContainer.setAttribute('data-page-number', pageNumber.toString());
|
|
@@ -522,7 +563,6 @@ export class PDFHighlightViewer {
|
|
|
522
563
|
this.pdfContainer.appendChild(pageContainer);
|
|
523
564
|
this.pageContainers.set(pageNumber, pageContainer);
|
|
524
565
|
}
|
|
525
|
-
// Update viewport manager with real page dimensions
|
|
526
566
|
this.viewportManager.updateDimensions(this.container?.clientHeight || 600, avgPageHeight);
|
|
527
567
|
}
|
|
528
568
|
/**
|
|
@@ -531,19 +571,19 @@ export class PDFHighlightViewer {
|
|
|
531
571
|
async loadInitialPages() {
|
|
532
572
|
if (!this.container)
|
|
533
573
|
return;
|
|
534
|
-
// Get what should be visible at the top
|
|
535
574
|
const visiblePages = this.viewportManager.getVisiblePages(0, this.container.clientHeight);
|
|
536
|
-
|
|
575
|
+
const firstPage = this.getDisplayedPageList()[0];
|
|
576
|
+
if (firstPage === undefined)
|
|
577
|
+
return;
|
|
537
578
|
try {
|
|
538
|
-
await this.renderPage(
|
|
579
|
+
await this.renderPage(firstPage);
|
|
539
580
|
}
|
|
540
581
|
catch (error) {
|
|
541
582
|
console.error('Failed to load initial page:', error);
|
|
542
583
|
}
|
|
543
|
-
// Load other visible pages with small delay
|
|
544
584
|
setTimeout(() => {
|
|
545
585
|
visiblePages
|
|
546
|
-
.filter((page) => page
|
|
586
|
+
.filter((page) => page !== firstPage)
|
|
547
587
|
.forEach((pageNumber) => {
|
|
548
588
|
this.renderPage(pageNumber).catch((error) => {
|
|
549
589
|
console.error(`Failed to load initial page ${pageNumber}:`, error);
|
|
@@ -552,13 +592,15 @@ export class PDFHighlightViewer {
|
|
|
552
592
|
}, 100);
|
|
553
593
|
}
|
|
554
594
|
async renderAllPagesBatched(batchSize = 2) {
|
|
555
|
-
|
|
595
|
+
const displayed = this.getDisplayedPageList();
|
|
596
|
+
for (let i = 0; i < displayed.length; i += batchSize) {
|
|
556
597
|
const batch = [];
|
|
557
|
-
for (let j = i; j < i + batchSize && j
|
|
558
|
-
const
|
|
598
|
+
for (let j = i; j < i + batchSize && j < displayed.length; j++) {
|
|
599
|
+
const pageNumber = displayed[j];
|
|
600
|
+
const pageContainer = this.pageContainers.get(pageNumber);
|
|
559
601
|
if (pageContainer && !pageContainer.classList.contains('rendered')) {
|
|
560
|
-
batch.push(this.renderPage(
|
|
561
|
-
console.
|
|
602
|
+
batch.push(this.renderPage(pageNumber).catch((error) => {
|
|
603
|
+
console.error(`Failed to render page ${pageNumber}:`, error);
|
|
562
604
|
}));
|
|
563
605
|
}
|
|
564
606
|
}
|
|
@@ -575,10 +617,8 @@ export class PDFHighlightViewer {
|
|
|
575
617
|
return;
|
|
576
618
|
// Check if already rendered
|
|
577
619
|
if (pageContainer.classList.contains('rendered')) {
|
|
578
|
-
console.log(`Page ${pageNumber}: skipping, already has 'rendered' class`);
|
|
579
620
|
return;
|
|
580
621
|
}
|
|
581
|
-
console.log(`Page ${pageNumber}: rendering at scale ${this.currentScale}`);
|
|
582
622
|
try {
|
|
583
623
|
// Add loading state
|
|
584
624
|
pageContainer.classList.add('loading');
|
|
@@ -615,7 +655,8 @@ export class PDFHighlightViewer {
|
|
|
615
655
|
});
|
|
616
656
|
}
|
|
617
657
|
setPage(pageNumber) {
|
|
618
|
-
|
|
658
|
+
const displayed = this.getDisplayedPageList();
|
|
659
|
+
if (!displayed.includes(pageNumber))
|
|
619
660
|
return;
|
|
620
661
|
if (this.container) {
|
|
621
662
|
this.container.scrollTop = this.getPageScrollTop(pageNumber);
|
|
@@ -882,7 +923,6 @@ export class PDFHighlightViewer {
|
|
|
882
923
|
if (!this.container)
|
|
883
924
|
return;
|
|
884
925
|
const pageToKeep = this.currentPage;
|
|
885
|
-
console.log('Zoom changed to:', this.currentScale);
|
|
886
926
|
// Clear ALL cached data for the new scale
|
|
887
927
|
this.pdfEngine.clearAllPageCache();
|
|
888
928
|
this.pageDimensions.clear(); // Clear dimension cache
|
|
@@ -916,7 +956,6 @@ export class PDFHighlightViewer {
|
|
|
916
956
|
// Recompute visible pages after scroll restore for correct rendering
|
|
917
957
|
const scrollTopAfterRestore = this.container.scrollTop;
|
|
918
958
|
const visiblePagesAfterRestore = this.viewportManager.getVisiblePages(scrollTopAfterRestore, containerHeight);
|
|
919
|
-
console.log('Re-rendering visible pages at new scale:', visiblePagesAfterRestore);
|
|
920
959
|
// Render visible pages immediately
|
|
921
960
|
for (const pageNumber of visiblePagesAfterRestore) {
|
|
922
961
|
try {
|
|
@@ -1074,11 +1113,9 @@ export class PDFHighlightViewer {
|
|
|
1074
1113
|
}
|
|
1075
1114
|
enableProfiling() {
|
|
1076
1115
|
// TODO: Enable detailed performance profiling
|
|
1077
|
-
console.log('Profiling enabled');
|
|
1078
1116
|
}
|
|
1079
1117
|
disableProfiling() {
|
|
1080
1118
|
// TODO: Disable detailed performance profiling
|
|
1081
|
-
console.log('Profiling disabled');
|
|
1082
1119
|
}
|
|
1083
1120
|
// =============================================================================
|
|
1084
1121
|
// Event Management
|
|
@@ -1507,10 +1544,10 @@ export class PDFHighlightViewer {
|
|
|
1507
1544
|
};
|
|
1508
1545
|
}
|
|
1509
1546
|
/**
|
|
1510
|
-
* Build spatial indices for
|
|
1547
|
+
* Build spatial indices for displayed pages only
|
|
1511
1548
|
*/
|
|
1512
1549
|
buildAllSpatialIndices() {
|
|
1513
|
-
for (
|
|
1550
|
+
for (const pageNumber of this.getDisplayedPageList()) {
|
|
1514
1551
|
this.buildSpatialIndexForPage(pageNumber);
|
|
1515
1552
|
}
|
|
1516
1553
|
}
|
|
@@ -1741,8 +1778,6 @@ export class PDFHighlightViewer {
|
|
|
1741
1778
|
textLayer.appendChild(textSpan);
|
|
1742
1779
|
});
|
|
1743
1780
|
pageContainer.appendChild(textLayer);
|
|
1744
|
-
console.log(`Text layer added to page ${pageNumber} with ${textContent.items.length} text items`);
|
|
1745
|
-
console.log('Text span style applied:', textLayer.children[0]?.getAttribute('style'));
|
|
1746
1781
|
}
|
|
1747
1782
|
catch (error) {
|
|
1748
1783
|
console.error(`Failed to add text layer to page ${pageNumber}:`, error);
|
|
@@ -1758,8 +1793,8 @@ export class PDFHighlightViewer {
|
|
|
1758
1793
|
const targetHeight = (coord.y2 - coord.y1) * scale;
|
|
1759
1794
|
const existingHighlights = highlightLayer.children;
|
|
1760
1795
|
let overlappingCount = 0;
|
|
1761
|
-
for (
|
|
1762
|
-
const existing =
|
|
1796
|
+
for (const existingHighlight of existingHighlights) {
|
|
1797
|
+
const existing = existingHighlight;
|
|
1763
1798
|
const existingLeft = parseFloat(existing.style.left);
|
|
1764
1799
|
const existingTop = parseFloat(existing.style.top);
|
|
1765
1800
|
const existingWidth = parseFloat(existing.style.width);
|