web-annotation-renderer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +21 -0
  3. package/README.md +156 -0
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.js +32 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index10.cjs +2 -0
  9. package/dist/index10.cjs.map +1 -0
  10. package/dist/index10.js +23 -0
  11. package/dist/index10.js.map +1 -0
  12. package/dist/index11.cjs +2 -0
  13. package/dist/index11.cjs.map +1 -0
  14. package/dist/index11.js +23 -0
  15. package/dist/index11.js.map +1 -0
  16. package/dist/index12.cjs +2 -0
  17. package/dist/index12.cjs.map +1 -0
  18. package/dist/index12.js +203 -0
  19. package/dist/index12.js.map +1 -0
  20. package/dist/index13.cjs +2 -0
  21. package/dist/index13.cjs.map +1 -0
  22. package/dist/index13.js +18 -0
  23. package/dist/index13.js.map +1 -0
  24. package/dist/index14.cjs +2 -0
  25. package/dist/index14.cjs.map +1 -0
  26. package/dist/index14.js +116 -0
  27. package/dist/index14.js.map +1 -0
  28. package/dist/index15.cjs +2 -0
  29. package/dist/index15.cjs.map +1 -0
  30. package/dist/index15.js +35 -0
  31. package/dist/index15.js.map +1 -0
  32. package/dist/index2.cjs +2 -0
  33. package/dist/index2.cjs.map +1 -0
  34. package/dist/index2.js +182 -0
  35. package/dist/index2.js.map +1 -0
  36. package/dist/index3.cjs +2 -0
  37. package/dist/index3.cjs.map +1 -0
  38. package/dist/index3.js +121 -0
  39. package/dist/index3.js.map +1 -0
  40. package/dist/index4.cjs +2 -0
  41. package/dist/index4.cjs.map +1 -0
  42. package/dist/index4.js +104 -0
  43. package/dist/index4.js.map +1 -0
  44. package/dist/index5.cjs +2 -0
  45. package/dist/index5.cjs.map +1 -0
  46. package/dist/index5.js +105 -0
  47. package/dist/index5.js.map +1 -0
  48. package/dist/index6.cjs +2 -0
  49. package/dist/index6.cjs.map +1 -0
  50. package/dist/index6.js +119 -0
  51. package/dist/index6.js.map +1 -0
  52. package/dist/index7.cjs +2 -0
  53. package/dist/index7.cjs.map +1 -0
  54. package/dist/index7.js +100 -0
  55. package/dist/index7.js.map +1 -0
  56. package/dist/index8.cjs +2 -0
  57. package/dist/index8.cjs.map +1 -0
  58. package/dist/index8.js +109 -0
  59. package/dist/index8.js.map +1 -0
  60. package/dist/index9.cjs +2 -0
  61. package/dist/index9.cjs.map +1 -0
  62. package/dist/index9.js +112 -0
  63. package/dist/index9.js.map +1 -0
  64. package/package.json +84 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-10-25
9
+
10
+ ### Added
11
+
12
+ - Initial release of @ai-annotator/renderer
13
+ - Framework-agnostic core rendering engine
14
+ - PDF rendering with pdf.js integration
15
+ - Timeline synchronization system
16
+ - React adapter component (AnnotPdf)
17
+ - Support for highlight annotations with progressive reveal
18
+ - Support for text box annotations with word-by-word reveal
19
+ - Support for ink/drawing annotations with progressive strokes
20
+ - Coordinate utilities for normalized positioning
21
+ - Viewport utilities for responsive rendering
22
+ - Type validators for annotation data
23
+ - Complete API documentation
24
+ - Working examples (vanilla JS, React basic, React audio sync)
25
+
26
+ ### Features
27
+
28
+ - Automatic worker configuration (zero config for consumers)
29
+ - Tree-shakeable exports
30
+ - Source maps for debugging
31
+ - TypeScript-friendly JSDoc annotations
32
+ - Comprehensive error handling
33
+
34
+ [0.1.0]: https://github.com/jhl72e/pdfAutoAnnotator/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 [jhl72e]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @ai-annotator/renderer
2
+
3
+ [![npm version](https://badge.fury.io/js/@ai-annotator%2Frenderer.svg)](https://www.npmjs.com/package/@ai-annotator/renderer)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A framework-agnostic PDF annotation renderer with timeline synchronization for educational content, interactive presentations, and annotated documents.
7
+
8
+ This library renders structured annotation data (highlights, text boxes, drawings) on top of PDF documents, synchronized with audio or video timelines. Built on pdf.js with a clean, modern API.
9
+
10
+ ## Features
11
+
12
+ - 📄 **PDF Rendering** - Built on pdf.js for reliable PDF display
13
+ - ⏱️ **Timeline Synchronization** - Sync annotations with audio/video playback
14
+ - 🎨 **Multiple Annotation Types** - Highlights, text boxes, and ink drawings
15
+ - ⚛️ **Framework Agnostic** - Core engine works with any framework
16
+ - ⚛️ **React Adapter** - Ready-to-use React component included
17
+ - 🎯 **Progressive Animations** - Smooth reveal animations based on timeline
18
+ - 📦 **Simple Setup** - One-line worker configuration
19
+ - 🌲 **Tree-shakeable** - Import only what you need
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @ai-annotator/renderer
25
+ ```
26
+
27
+ **Requirements:**
28
+
29
+ - Node.js >= 18
30
+ - React 18 or 19 (only if using React adapter)
31
+
32
+ ## Worker Configuration
33
+
34
+ **Important:** Before using the library, configure the PDF.js worker in your application:
35
+
36
+ ```javascript
37
+ import * as pdfjsLib from "pdfjs-dist";
38
+
39
+ pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
40
+ "pdfjs-dist/build/pdf.worker.min.mjs",
41
+ import.meta.url
42
+ ).toString();
43
+ ```
44
+
45
+ This must be done once at application startup, before using any PDF functionality.
46
+
47
+ ## Quick Start - Vanilla JavaScript
48
+
49
+ ```javascript
50
+ import { AnnotationRenderer } from "@ai-annotator/renderer";
51
+ import * as pdfjsLib from "pdfjs-dist";
52
+
53
+ // Configure PDF.js worker (call once at app startup)
54
+ pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
55
+ "pdfjs-dist/build/pdf.worker.min.mjs",
56
+ import.meta.url
57
+ ).toString();
58
+
59
+ // Create renderer instance
60
+ const renderer = new AnnotationRenderer({
61
+ container: document.getElementById("annotation-container"),
62
+ canvasElement: document.getElementById("pdf-canvas"),
63
+ });
64
+
65
+ // Load PDF
66
+ await renderer.loadPDF("/path/to/document.pdf");
67
+
68
+ // Set annotations
69
+ renderer.setAnnotations([
70
+ {
71
+ id: "1",
72
+ type: "highlight",
73
+ page: 1,
74
+ start: 0,
75
+ end: 5,
76
+ quads: [{ x: 0.1, y: 0.2, w: 0.3, h: 0.05 }],
77
+ style: { color: "rgba(255, 255, 0, 0.3)" },
78
+ },
79
+ ]);
80
+
81
+ // Update timeline position
82
+ renderer.updateTimeline(2.5); // seconds
83
+ ```
84
+
85
+ ## Quick Start - React
86
+
87
+ ```javascript
88
+ import { AnnotPdf } from "@ai-annotator/renderer";
89
+ import * as pdfjsLib from "pdfjs-dist";
90
+
91
+ // Configure PDF.js worker (call once at app startup)
92
+ pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
93
+ "pdfjs-dist/build/pdf.worker.min.mjs",
94
+ import.meta.url
95
+ ).toString();
96
+
97
+ function App() {
98
+ const [currentTime, setCurrentTime] = useState(0);
99
+
100
+ const annotations = [
101
+ {
102
+ id: "1",
103
+ type: "highlight",
104
+ page: 1,
105
+ start: 0,
106
+ end: 5,
107
+ quads: [{ x: 0.1, y: 0.2, w: 0.3, h: 0.05 }],
108
+ style: { color: "rgba(255, 255, 0, 0.3)" },
109
+ },
110
+ ];
111
+
112
+ return (
113
+ <AnnotPdf
114
+ pdfUrl="/path/to/document.pdf"
115
+ annotations={annotations}
116
+ currentTime={currentTime}
117
+ page={1}
118
+ scale={1.0}
119
+ width={800}
120
+ height={600}
121
+ />
122
+ );
123
+ }
124
+ ```
125
+
126
+ ## Documentation
127
+
128
+ - [Full API Reference](https://github.com/jhl72e/pdfAutoAnnotator/blob/main/docs/API.md)
129
+ - [Annotation Data Format](https://github.com/jhl72e/pdfAutoAnnotator/blob/main/docs/ANNOTATION_FORMAT.md)
130
+ - [Examples](https://github.com/jhl72e/pdfAutoAnnotator/tree/main/examples)
131
+
132
+ ## Browser Compatibility
133
+
134
+ Works in all modern browsers:
135
+
136
+ - Chrome/Edge (latest)
137
+ - Firefox (latest)
138
+ - Safari (latest)
139
+
140
+ Requires:
141
+
142
+ - ES6+ support
143
+ - Canvas API
144
+ - Web Workers
145
+
146
+ ## Examples
147
+
148
+ Check out the [examples directory](https://github.com/jhl72e/pdfAutoAnnotator/tree/main/examples) for complete working examples:
149
+
150
+ - Vanilla JavaScript
151
+ - React with timeline sync
152
+ - React with audio integration
153
+
154
+ ## License
155
+
156
+ MIT © [jhl72e]
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index2.cjs"),r=require("./index3.cjs"),n=require("./index4.cjs"),t=require("./index5.cjs"),i=require("./index6.cjs"),a=require("./index7.cjs"),o=require("./index8.cjs"),s=require("./index9.cjs"),c=require("./index10.cjs"),d=require("./index11.cjs"),l=require("./index12.cjs"),u=require("./index13.cjs"),y=require("./index14.cjs"),q="0.1.0",L="web-annotation-renderer";exports.AnnotationRenderer=e.AnnotationRenderer;exports.PDFRenderer=r.PDFRenderer;exports.LayerManager=n.LayerManager;exports.TimelineSync=t.TimelineSync;exports.BaseLayer=i.default;exports.HighlightLayer=a.default;exports.TextLayer=o.default;exports.DrawingLayer=s.default;exports.coordinateUtils=c;exports.viewportUtils=d;exports.normalizeAnnotationArray=l.normalizeAnnotationArray;exports.TypeValidators=u;exports.AnnotPdf=y.default;exports.LIB_NAME=L;exports.VERSION=q;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/index.js"],"sourcesContent":["/**\n * @ai-annotator/renderer - Public API\n *\n * Single entry point for the Dynamic PDF Annotation Renderer library.\n * Exports all core subsystems, layers, utilities, and types.\n *\n * @module @ai-annotator/renderer\n */\n\n// ============================================================================\n// Core Rendering Engine\n// ============================================================================\n\n// Import statements\nimport { AnnotationRenderer } from './core/AnnotationRenderer.js';\nimport { PDFRenderer } from './core/PDFRenderer.js';\nimport { LayerManager } from './core/LayerManager.js';\nimport { TimelineSync } from './core/TimelineSync.js';\n\n// Export statements\nexport { AnnotationRenderer };\nexport { PDFRenderer };\nexport { LayerManager };\nexport { TimelineSync };\n\n// ============================================================================\n// Annotation Layers\n// ============================================================================\n\n// Framework-agnostic layer classes\n// BaseLayer: Abstract base class for creating custom layers\n// HighlightLayer, TextLayer, DrawingLayer: Built-in layer implementations\n\nimport BaseLayer from './layers/BaseLayer.js';\nimport HighlightLayer from './layers/HighlightLayer.js';\nimport TextLayer from './layers/TextLayer.js';\nimport DrawingLayer from './layers/DrawingLayer.js';\n\nexport { BaseLayer };\nexport { HighlightLayer };\nexport { TextLayer };\nexport { DrawingLayer };\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nimport * as coordinateUtils from './utils/coordinateUtils.js';\nimport * as viewportUtils from './utils/viewportUtils.js';\n\nexport { coordinateUtils };\nexport { viewportUtils };\n\n// Future: colorUtils, validators\n// import * as colorUtils from './utils/colorUtils.js';\n// export { colorUtils };\n\n// ============================================================================\n// Type Definitions & Validators\n// ============================================================================\n\n// Type definitions in src/types/annotations.js\n\n/**\n * Type Validators - Optional data normalization\n *\n * Import separately to use defensive normalization for annotation data.\n * These validators are standalone utilities that do not modify the core system.\n */\nexport { normalizeAnnotationArray } from './types/validators.js';\n\n// Namespace export for all validator utilities\nexport * as TypeValidators from './types/index.js';\n\n// ============================================================================\n// Framework Adapters\n// ============================================================================\n// Declarative framework-specific wrappers for AnnotationRenderer\n// These provide idiomatic APIs for React, Vue, and other frameworks\n\n/**\n * React adapter component for declarative PDF annotation rendering\n * @see {@link AnnotPdf}\n */\nexport { AnnotPdf } from './adapters/index.js';\n\n// Future framework adapters will be exported here:\n// export { VuePdfViewer } from './adapters/index.js';\n// export { SveltePdfViewer } from './adapters/index.js';\n\n// ============================================================================\n// Package Metadata\n// ============================================================================\n\n/**\n * Library version\n * @constant {string}\n */\nexport const VERSION = '0.1.0';\n\n/**\n * Library name\n * @constant {string}\n */\nexport const LIB_NAME = 'web-annotation-renderer';\n"],"names":["VERSION","LIB_NAME"],"mappings":"6aAkGaA,EAAU,QAMVC,EAAW"}
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ import { AnnotationRenderer as p } from "./index2.js";
2
+ import { PDFRenderer as m } from "./index3.js";
3
+ import { LayerManager as s } from "./index4.js";
4
+ import { TimelineSync as l } from "./index5.js";
5
+ import { default as L } from "./index6.js";
6
+ import { default as A } from "./index7.js";
7
+ import { default as g } from "./index8.js";
8
+ import { default as R } from "./index9.js";
9
+ import * as r from "./index10.js";
10
+ import * as e from "./index11.js";
11
+ import { normalizeAnnotationArray as h } from "./index12.js";
12
+ import * as o from "./index13.js";
13
+ import { default as D } from "./index14.js";
14
+ const t = "0.1.0", a = "web-annotation-renderer";
15
+ export {
16
+ D as AnnotPdf,
17
+ p as AnnotationRenderer,
18
+ L as BaseLayer,
19
+ R as DrawingLayer,
20
+ A as HighlightLayer,
21
+ a as LIB_NAME,
22
+ s as LayerManager,
23
+ m as PDFRenderer,
24
+ g as TextLayer,
25
+ l as TimelineSync,
26
+ o as TypeValidators,
27
+ t as VERSION,
28
+ r as coordinateUtils,
29
+ h as normalizeAnnotationArray,
30
+ e as viewportUtils
31
+ };
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["/**\n * @ai-annotator/renderer - Public API\n *\n * Single entry point for the Dynamic PDF Annotation Renderer library.\n * Exports all core subsystems, layers, utilities, and types.\n *\n * @module @ai-annotator/renderer\n */\n\n// ============================================================================\n// Core Rendering Engine\n// ============================================================================\n\n// Import statements\nimport { AnnotationRenderer } from './core/AnnotationRenderer.js';\nimport { PDFRenderer } from './core/PDFRenderer.js';\nimport { LayerManager } from './core/LayerManager.js';\nimport { TimelineSync } from './core/TimelineSync.js';\n\n// Export statements\nexport { AnnotationRenderer };\nexport { PDFRenderer };\nexport { LayerManager };\nexport { TimelineSync };\n\n// ============================================================================\n// Annotation Layers\n// ============================================================================\n\n// Framework-agnostic layer classes\n// BaseLayer: Abstract base class for creating custom layers\n// HighlightLayer, TextLayer, DrawingLayer: Built-in layer implementations\n\nimport BaseLayer from './layers/BaseLayer.js';\nimport HighlightLayer from './layers/HighlightLayer.js';\nimport TextLayer from './layers/TextLayer.js';\nimport DrawingLayer from './layers/DrawingLayer.js';\n\nexport { BaseLayer };\nexport { HighlightLayer };\nexport { TextLayer };\nexport { DrawingLayer };\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nimport * as coordinateUtils from './utils/coordinateUtils.js';\nimport * as viewportUtils from './utils/viewportUtils.js';\n\nexport { coordinateUtils };\nexport { viewportUtils };\n\n// Future: colorUtils, validators\n// import * as colorUtils from './utils/colorUtils.js';\n// export { colorUtils };\n\n// ============================================================================\n// Type Definitions & Validators\n// ============================================================================\n\n// Type definitions in src/types/annotations.js\n\n/**\n * Type Validators - Optional data normalization\n *\n * Import separately to use defensive normalization for annotation data.\n * These validators are standalone utilities that do not modify the core system.\n */\nexport { normalizeAnnotationArray } from './types/validators.js';\n\n// Namespace export for all validator utilities\nexport * as TypeValidators from './types/index.js';\n\n// ============================================================================\n// Framework Adapters\n// ============================================================================\n// Declarative framework-specific wrappers for AnnotationRenderer\n// These provide idiomatic APIs for React, Vue, and other frameworks\n\n/**\n * React adapter component for declarative PDF annotation rendering\n * @see {@link AnnotPdf}\n */\nexport { AnnotPdf } from './adapters/index.js';\n\n// Future framework adapters will be exported here:\n// export { VuePdfViewer } from './adapters/index.js';\n// export { SveltePdfViewer } from './adapters/index.js';\n\n// ============================================================================\n// Package Metadata\n// ============================================================================\n\n/**\n * Library version\n * @constant {string}\n */\nexport const VERSION = '0.1.0';\n\n/**\n * Library name\n * @constant {string}\n */\nexport const LIB_NAME = 'web-annotation-renderer';\n"],"names":["VERSION","LIB_NAME"],"mappings":";;;;;;;;;;;;;AAkGY,MAACA,IAAU,SAMVC,IAAW;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=(t,h)=>({left:t.x*h.width,top:t.y*h.height,width:(t.w??0)*h.width,height:(t.h??0)*h.height}),i=(t,h)=>({left:t.x*h.width,top:t.y*h.height,width:(t.w??0)*h.width,height:(t.h??0)*h.height});function o(t,h){return{x:t.x*h.width,y:t.y*h.height}}exports.NormSizeToPixel=i;exports.pointNormToAbs=o;exports.rectNormToAbs=e;
2
+ //# sourceMappingURL=index10.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index10.cjs","sources":["../src/utils/coordinateUtils.js"],"sourcesContent":["/**\n * Coordinate Utility Functions\n *\n * This module provides utility functions for coordinate transformations\n * between normalized (0-1) coordinates and absolute pixel coordinates.\n * Used by annotation layers to position elements on the PDF canvas.\n */\n\n/**\n * Convert normalized rectangle to absolute pixel coordinates\n *\n * Transforms a rectangle with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number, w: number, h: number}} rect - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n *\n * @example\n * const rect = { x: 0.1, y: 0.2, w: 0.5, h: 0.3 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = rectNormToAbs(rect, viewport);\n * // Returns: { left: 100, top: 280, width: 500, height: 420 }\n */\nexport const rectNormToAbs = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized size to pixel dimensions (Legacy)\n *\n * @deprecated Use rectNormToAbs instead. This function is kept for backward compatibility.\n *\n * Transforms normalized rectangle coordinates to absolute pixel coordinates.\n * This is an alias for rectNormToAbs maintained for backward compatibility.\n *\n * @param {{x: number, y: number, w: number, h: number}} r - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} vp - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n */\nexport const NormSizeToPixel = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized point to absolute pixel coordinates\n *\n * Transforms a point with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number}} point - Normalized point (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{x: number, y: number}} Absolute coordinates in pixels\n *\n * @example\n * const point = { x: 0.5, y: 0.5 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = pointNormToAbs(point, viewport);\n * // Returns: { x: 500, y: 700 }\n */\nexport function pointNormToAbs(point, viewport) {\n return {\n x: point.x * viewport.width,\n y: point.y * viewport.height\n };\n}\n"],"names":["rectNormToAbs","r","vp","NormSizeToPixel","pointNormToAbs","point","viewport"],"mappings":"gFAwBY,MAACA,EAAgB,CAACC,EAAGC,KAAQ,CACvC,KAAMD,EAAE,EAAIC,EAAG,MACf,IAAKD,EAAE,EAAIC,EAAG,OACd,OAAQD,EAAE,GAAK,GAAKC,EAAG,MACvB,QAASD,EAAE,GAAK,GAAKC,EAAG,MAC1B,GAcaC,EAAkB,CAACF,EAAGC,KAAQ,CACzC,KAAMD,EAAE,EAAIC,EAAG,MACf,IAAKD,EAAE,EAAIC,EAAG,OACd,OAAQD,EAAE,GAAK,GAAKC,EAAG,MACvB,QAASD,EAAE,GAAK,GAAKC,EAAG,MAC1B,GAkBO,SAASE,EAAeC,EAAOC,EAAU,CAC9C,MAAO,CACL,EAAGD,EAAM,EAAIC,EAAS,MACtB,EAAGD,EAAM,EAAIC,EAAS,MAC1B,CACA"}
@@ -0,0 +1,23 @@
1
+ const i = (h, t) => ({
2
+ left: h.x * t.width,
3
+ top: h.y * t.height,
4
+ width: (h.w ?? 0) * t.width,
5
+ height: (h.h ?? 0) * t.height
6
+ }), e = (h, t) => ({
7
+ left: h.x * t.width,
8
+ top: h.y * t.height,
9
+ width: (h.w ?? 0) * t.width,
10
+ height: (h.h ?? 0) * t.height
11
+ });
12
+ function o(h, t) {
13
+ return {
14
+ x: h.x * t.width,
15
+ y: h.y * t.height
16
+ };
17
+ }
18
+ export {
19
+ e as NormSizeToPixel,
20
+ o as pointNormToAbs,
21
+ i as rectNormToAbs
22
+ };
23
+ //# sourceMappingURL=index10.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index10.js","sources":["../src/utils/coordinateUtils.js"],"sourcesContent":["/**\n * Coordinate Utility Functions\n *\n * This module provides utility functions for coordinate transformations\n * between normalized (0-1) coordinates and absolute pixel coordinates.\n * Used by annotation layers to position elements on the PDF canvas.\n */\n\n/**\n * Convert normalized rectangle to absolute pixel coordinates\n *\n * Transforms a rectangle with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number, w: number, h: number}} rect - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n *\n * @example\n * const rect = { x: 0.1, y: 0.2, w: 0.5, h: 0.3 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = rectNormToAbs(rect, viewport);\n * // Returns: { left: 100, top: 280, width: 500, height: 420 }\n */\nexport const rectNormToAbs = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized size to pixel dimensions (Legacy)\n *\n * @deprecated Use rectNormToAbs instead. This function is kept for backward compatibility.\n *\n * Transforms normalized rectangle coordinates to absolute pixel coordinates.\n * This is an alias for rectNormToAbs maintained for backward compatibility.\n *\n * @param {{x: number, y: number, w: number, h: number}} r - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} vp - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n */\nexport const NormSizeToPixel = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized point to absolute pixel coordinates\n *\n * Transforms a point with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number}} point - Normalized point (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{x: number, y: number}} Absolute coordinates in pixels\n *\n * @example\n * const point = { x: 0.5, y: 0.5 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = pointNormToAbs(point, viewport);\n * // Returns: { x: 500, y: 700 }\n */\nexport function pointNormToAbs(point, viewport) {\n return {\n x: point.x * viewport.width,\n y: point.y * viewport.height\n };\n}\n"],"names":["rectNormToAbs","r","vp","NormSizeToPixel","pointNormToAbs","point","viewport"],"mappings":"AAwBY,MAACA,IAAgB,CAACC,GAAGC,OAAQ;AAAA,EACvC,MAAMD,EAAE,IAAIC,EAAG;AAAA,EACf,KAAKD,EAAE,IAAIC,EAAG;AAAA,EACd,QAAQD,EAAE,KAAK,KAAKC,EAAG;AAAA,EACvB,SAASD,EAAE,KAAK,KAAKC,EAAG;AAC1B,IAcaC,IAAkB,CAACF,GAAGC,OAAQ;AAAA,EACzC,MAAMD,EAAE,IAAIC,EAAG;AAAA,EACf,KAAKD,EAAE,IAAIC,EAAG;AAAA,EACd,QAAQD,EAAE,KAAK,KAAKC,EAAG;AAAA,EACvB,SAASD,EAAE,KAAK,KAAKC,EAAG;AAC1B;AAkBO,SAASE,EAAeC,GAAOC,GAAU;AAC9C,SAAO;AAAA,IACL,GAAGD,EAAM,IAAIC,EAAS;AAAA,IACtB,GAAGD,EAAM,IAAIC,EAAS;AAAA,EAC1B;AACA;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function n(e,t){if(!e)throw new Error("Page object is required");return e.getViewport({scale:t})}function r(e){return e?{width:e.width,height:e.height}:{width:0,height:0}}function o(e,t,i){return{width:e*i,height:t*i}}exports.calculateScaledDimensions=o;exports.calculateViewport=n;exports.getViewportDimensions=r;
2
+ //# sourceMappingURL=index11.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index11.cjs","sources":["../src/utils/viewportUtils.js"],"sourcesContent":["/**\n * Viewport Utility Functions\n *\n * This module provides utility functions for PDF viewport calculations\n * and transformations. These functions are used by the PDF viewer to\n * calculate viewport dimensions and manage scaling.\n */\n\n/**\n * Calculate viewport from PDF page\n *\n * Creates a viewport object from a PDF.js page with the specified scale.\n * The viewport contains dimensions and transformation matrix for rendering.\n *\n * @param {Object} page - PDF.js page object\n * @param {number} scale - Scale factor for rendering\n * @returns {Object} Viewport object with width, height, and transform matrix\n *\n * @example\n * const viewport = calculateViewport(pdfPage, 1.5);\n * // Returns: { width: 1200, height: 1600, scale: 1.5, ... }\n */\nexport function calculateViewport(page, scale) {\n if (!page) {\n throw new Error('Page object is required');\n }\n\n return page.getViewport({ scale });\n}\n\n/**\n * Get viewport dimensions\n *\n * Extracts width and height from a viewport object.\n * Useful for coordinate transformations and layout calculations.\n *\n * @param {Object} viewport - Viewport object from PDF.js\n * @returns {{width: number, height: number}} Dimensions object\n *\n * @example\n * const { width, height } = getViewportDimensions(viewport);\n * // Returns: { width: 1200, height: 1600 }\n */\nexport function getViewportDimensions(viewport) {\n if (!viewport) {\n return { width: 0, height: 0 };\n }\n\n return {\n width: viewport.width,\n height: viewport.height\n };\n}\n\n/**\n * Calculate scaled dimensions\n *\n * Calculates dimensions for a given scale factor.\n * Used when zoom level changes to determine new canvas size.\n *\n * @param {number} baseWidth - Original width\n * @param {number} baseHeight - Original height\n * @param {number} scale - Scale factor\n * @returns {{width: number, height: number}} Scaled dimensions\n *\n * @example\n * const scaled = calculateScaledDimensions(800, 1000, 1.5);\n * // Returns: { width: 1200, height: 1500 }\n */\nexport function calculateScaledDimensions(baseWidth, baseHeight, scale) {\n return {\n width: baseWidth * scale,\n height: baseHeight * scale\n };\n}\n"],"names":["calculateViewport","page","scale","getViewportDimensions","viewport","calculateScaledDimensions","baseWidth","baseHeight"],"mappings":"gFAsBO,SAASA,EAAkBC,EAAMC,EAAO,CAC7C,GAAI,CAACD,EACH,MAAM,IAAI,MAAM,yBAAyB,EAG3C,OAAOA,EAAK,YAAY,CAAE,MAAAC,EAAO,CACnC,CAeO,SAASC,EAAsBC,EAAU,CAC9C,OAAKA,EAIE,CACL,MAAOA,EAAS,MAChB,OAAQA,EAAS,MACrB,EANW,CAAE,MAAO,EAAG,OAAQ,CAAC,CAOhC,CAiBO,SAASC,EAA0BC,EAAWC,EAAYL,EAAO,CACtE,MAAO,CACL,MAAOI,EAAYJ,EACnB,OAAQK,EAAaL,CACzB,CACA"}
@@ -0,0 +1,23 @@
1
+ function r(t, e) {
2
+ if (!t)
3
+ throw new Error("Page object is required");
4
+ return t.getViewport({ scale: e });
5
+ }
6
+ function n(t) {
7
+ return t ? {
8
+ width: t.width,
9
+ height: t.height
10
+ } : { width: 0, height: 0 };
11
+ }
12
+ function h(t, e, i) {
13
+ return {
14
+ width: t * i,
15
+ height: e * i
16
+ };
17
+ }
18
+ export {
19
+ h as calculateScaledDimensions,
20
+ r as calculateViewport,
21
+ n as getViewportDimensions
22
+ };
23
+ //# sourceMappingURL=index11.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index11.js","sources":["../src/utils/viewportUtils.js"],"sourcesContent":["/**\n * Viewport Utility Functions\n *\n * This module provides utility functions for PDF viewport calculations\n * and transformations. These functions are used by the PDF viewer to\n * calculate viewport dimensions and manage scaling.\n */\n\n/**\n * Calculate viewport from PDF page\n *\n * Creates a viewport object from a PDF.js page with the specified scale.\n * The viewport contains dimensions and transformation matrix for rendering.\n *\n * @param {Object} page - PDF.js page object\n * @param {number} scale - Scale factor for rendering\n * @returns {Object} Viewport object with width, height, and transform matrix\n *\n * @example\n * const viewport = calculateViewport(pdfPage, 1.5);\n * // Returns: { width: 1200, height: 1600, scale: 1.5, ... }\n */\nexport function calculateViewport(page, scale) {\n if (!page) {\n throw new Error('Page object is required');\n }\n\n return page.getViewport({ scale });\n}\n\n/**\n * Get viewport dimensions\n *\n * Extracts width and height from a viewport object.\n * Useful for coordinate transformations and layout calculations.\n *\n * @param {Object} viewport - Viewport object from PDF.js\n * @returns {{width: number, height: number}} Dimensions object\n *\n * @example\n * const { width, height } = getViewportDimensions(viewport);\n * // Returns: { width: 1200, height: 1600 }\n */\nexport function getViewportDimensions(viewport) {\n if (!viewport) {\n return { width: 0, height: 0 };\n }\n\n return {\n width: viewport.width,\n height: viewport.height\n };\n}\n\n/**\n * Calculate scaled dimensions\n *\n * Calculates dimensions for a given scale factor.\n * Used when zoom level changes to determine new canvas size.\n *\n * @param {number} baseWidth - Original width\n * @param {number} baseHeight - Original height\n * @param {number} scale - Scale factor\n * @returns {{width: number, height: number}} Scaled dimensions\n *\n * @example\n * const scaled = calculateScaledDimensions(800, 1000, 1.5);\n * // Returns: { width: 1200, height: 1500 }\n */\nexport function calculateScaledDimensions(baseWidth, baseHeight, scale) {\n return {\n width: baseWidth * scale,\n height: baseHeight * scale\n };\n}\n"],"names":["calculateViewport","page","scale","getViewportDimensions","viewport","calculateScaledDimensions","baseWidth","baseHeight"],"mappings":"AAsBO,SAASA,EAAkBC,GAAMC,GAAO;AAC7C,MAAI,CAACD;AACH,UAAM,IAAI,MAAM,yBAAyB;AAG3C,SAAOA,EAAK,YAAY,EAAE,OAAAC,GAAO;AACnC;AAeO,SAASC,EAAsBC,GAAU;AAC9C,SAAKA,IAIE;AAAA,IACL,OAAOA,EAAS;AAAA,IAChB,QAAQA,EAAS;AAAA,EACrB,IANW,EAAE,OAAO,GAAG,QAAQ,EAAC;AAOhC;AAiBO,SAASC,EAA0BC,GAAWC,GAAYL,GAAO;AACtE,SAAO;AAAA,IACL,OAAOI,IAAYJ;AAAA,IACnB,QAAQK,IAAaL;AAAA,EACzB;AACA;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("./index15.cjs");function a(t,n,o,s,e){let i=t;return typeof t=="string"&&(i=parseFloat(t)),typeof i!="number"||isNaN(i)?(e.push(`[${o}]: Field "${s}" invalid value "${t}", using default ${n}`),n):i<0?(e.push(`[${o}]: Field "${s}" value ${i} below range [0,1], clamping to 0`),0):i>1?(e.push(`[${o}]: Field "${s}" value ${i} exceeds range [0,1], clamping to 1`),1):i}function d(t,n,o,s){if(typeof t!="string"||t.trim().length===0)return s.push(`[${o}]: Invalid color format "${t}", using default ${n}`),n;const e=t.trim(),i=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/,r=/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+\s*)?\)$/,u=["red","blue","green","yellow","black","white","gray","grey","orange","purple","pink","brown","transparent"],h=i.test(e),$=r.test(e),A=u.includes(e.toLowerCase());return h||$||A?e:(s.push(`[${o}]: Invalid color format "${t}", using default ${n}`),n)}function f(t,n,o,s,e){let i=t;return typeof t=="string"&&(i=parseFloat(t)),typeof i!="number"||isNaN(i)||i<=0?(e.push(`[${o}]: Field "${s}" invalid value "${t}", using default ${n}`),n):i}function c(t,n,o){const s={};if(typeof t.id!="string"||t.id.trim().length===0){const e=Date.now(),i=Math.random().toString(36).substr(2,9);s.id=`anno-${e}-${i}`,o.push(`[${s.id}]: Auto-generated ID (original was missing or invalid)`)}else s.id=t.id.trim();return s.type=t.type,typeof t.page!="number"||t.page<1?(n.push(`[${s.id}]: Field "page" invalid value "${t.page}", using default ${l.BASE_DEFAULTS.page}`),s.page=l.BASE_DEFAULTS.page):s.page=Math.floor(t.page),typeof t.start!="number"||t.start<0?(n.push(`[${s.id}]: Field "start" invalid value "${t.start}", using default ${l.BASE_DEFAULTS.start}`),s.start=l.BASE_DEFAULTS.start):s.start=t.start,typeof t.end!="number"||t.end<0?(n.push(`[${s.id}]: Field "end" invalid value "${t.end}", using start value ${s.start}`),s.end=s.start):t.end<s.start?(n.push(`[${s.id}]: Field "end" (${t.end}) less than start (${s.start}), clamping to start`),s.end=s.start):s.end=t.end,s}function T(t,n,o){return!t||typeof t!="object"?(o.push(`[${n}]: Invalid quad object, using default`),{x:.1,y:.1,w:.8,h:.05}):{x:a(t.x,.1,n,"quad.x",o),y:a(t.y,.1,n,"quad.y",o),w:a(t.w,.8,n,"quad.w",o),h:a(t.h,.05,n,"quad.h",o)}}function p(t,n,o,s){const e={...t};n.mode!=="quads"?(o.push(`[${t.id}]: Field "mode" invalid value "${n.mode}", using default "${l.HIGHLIGHT_DEFAULTS.mode}"`),e.mode=l.HIGHLIGHT_DEFAULTS.mode):e.mode=n.mode,!Array.isArray(n.quads)||n.quads.length===0?(o.push(`[${t.id}]: Field "quads" missing or empty, using default`),e.quads=l.HIGHLIGHT_DEFAULTS.quads):e.quads=n.quads.map((r,u)=>T(r,t.id,o));const i=l.HIGHLIGHT_DEFAULTS.style.color;return!n.style||typeof n.style!="object"?(o.push(`[${t.id}]: Field "style" missing or invalid, using default`),e.style={color:i}):e.style={color:d(n.style.color,i,t.id,o)},e}function m(t,n,o,s){const e={...t};typeof n.content!="string"||n.content.trim().length===0?(o.push(`[${t.id}]: Field "content" missing or empty, using default "${l.TEXT_DEFAULTS.content}"`),e.content=l.TEXT_DEFAULTS.content):e.content=n.content,e.x=a(n.x,l.TEXT_DEFAULTS.x,t.id,"x",o),e.y=a(n.y,l.TEXT_DEFAULTS.y,t.id,"y",o),e.w=a(n.w,l.TEXT_DEFAULTS.w,t.id,"w",o),e.h=a(n.h,l.TEXT_DEFAULTS.h,t.id,"h",o);const i=l.TEXT_DEFAULTS.style.bg,r=l.TEXT_DEFAULTS.style.color;return!n.style||typeof n.style!="object"?(o.push(`[${t.id}]: Field "style" missing or invalid, using defaults`),e.style={bg:i,color:r}):e.style={bg:d(n.style.bg,i,t.id,o),color:d(n.style.color,r,t.id,o)},e}function F(t,n,o){return!t||typeof t!="object"?(o.push(`[${n}]: Invalid point object, using default`),{t:0,x:.1,y:.1}):{t:a(t.t,0,n,"point.t",o),x:a(t.x,.1,n,"point.x",o),y:a(t.y,.1,n,"point.y",o)}}function E(t,n,o){if(!t||typeof t!="object")return o.push(`[${n}]: Invalid stroke object, using default`),l.INK_DEFAULTS.strokes[0];const s={color:d(t.color,l.INK_DEFAULTS.strokes[0].color,n,o),size:f(t.size,l.INK_DEFAULTS.strokes[0].size,n,"stroke.size",o)};return!Array.isArray(t.points)||t.points.length===0?(o.push(`[${n}]: Stroke missing points array, using default`),s.points=l.INK_DEFAULTS.strokes[0].points):s.points=t.points.map(e=>F(e,n,o)),s}function g(t,n,o,s){const e={...t};return!Array.isArray(n.strokes)||n.strokes.length===0?(o.push(`[${t.id}]: Field "strokes" missing or empty, using default`),e.strokes=l.INK_DEFAULTS.strokes):e.strokes=n.strokes.map(i=>E(i,t.id,o)),e}function y(t,n){const o=[],s=[];if(!t||typeof t!="object")return{annotation:null,warnings:[],info:[],critical:`Annotation at index ${n}: Not a valid object`};if(typeof t.type!="string"||t.type.trim().length===0)return{annotation:null,warnings:[],info:[],critical:`Annotation at index ${n}: Missing or invalid type field`};const e=t.type.trim(),i=c(t,o,s);let r;if(e==="highlight")r=p(i,t,o);else if(e==="text")r=m(i,t,o);else if(e==="ink")r=g(i,t,o);else return{annotation:null,warnings:[],info:[],critical:`Annotation at index ${n}: Unsupported type "${e}"`};return{annotation:r,warnings:o,info:s,critical:null}}function z(t,n={}){n.skipInvalid;const o=n.warnInConsole!==!1,s=n.onWarning||null,e={normalized:[],warnings:[],info:[],skipped:[]};if(!Array.isArray(t)){const i="normalizeAnnotationArray: Input is not an array, returning empty result";return e.warnings.push(i),o&&console.warn(`[Annotation Normalizer] ${i}`),e}return t.forEach((i,r)=>{if(i==null){e.skipped.push({index:r,annotation:i,reason:"Annotation is null or undefined"});return}const u=y(i,r);if(u.critical){e.skipped.push({index:r,annotation:i,reason:u.critical}),o&&console.error(`[Annotation Normalizer] ${u.critical}`);return}e.normalized.push(u.annotation),e.warnings.push(...u.warnings),e.info.push(...u.info)}),o&&(e.warnings.length>0||e.info.length>0||e.skipped.length>0)&&(console.group("[Annotation Normalizer] Validation Summary"),e.normalized.length>0&&console.info(`✓ Normalized ${e.normalized.length} annotation(s)`),e.skipped.length>0&&(console.error(`✗ Skipped ${e.skipped.length} annotation(s)`),e.skipped.forEach(i=>{console.error(` Index ${i.index}: ${i.reason}`)})),e.warnings.length>0&&(console.warn(`⚠ ${e.warnings.length} warning(s):`),e.warnings.forEach(i=>console.warn(` ${i}`))),e.info.length>0&&(console.info(`ℹ ${e.info.length} info message(s):`),e.info.forEach(i=>console.info(` ${i}`))),console.groupEnd()),s&&typeof s=="function"&&s(e),e}exports.normalizeAnnotation=y;exports.normalizeAnnotationArray=z;exports.normalizeBaseFields=c;exports.normalizeColor=d;exports.normalizeCoordinate=a;exports.normalizeHighlight=p;exports.normalizeInk=g;exports.normalizePositiveNumber=f;exports.normalizeText=m;
2
+ //# sourceMappingURL=index12.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index12.cjs","sources":["../src/types/validators.js"],"sourcesContent":["/**\n * Annotation Data Normalization Utilities\n *\n * This module provides defensive normalization functions that validate and fix\n * annotation data. Invalid values are replaced with safe defaults and warnings\n * are collected for user feedback.\n *\n * @module types/validators\n */\n\nimport {\n BASE_DEFAULTS,\n HIGHLIGHT_DEFAULTS,\n TEXT_DEFAULTS,\n INK_DEFAULTS\n} from './defaults.js';\n\n// ============================================================================\n// FIELD-LEVEL NORMALIZERS\n// ============================================================================\n\n/**\n * Normalize coordinate value to 0-1 range\n *\n * Validates that a value is a number in the 0-1 range. Out-of-range values\n * are clamped. Invalid values use the provided default.\n *\n * @param {*} value - Value to normalize\n * @param {number} defaultValue - Fallback value if invalid\n * @param {string} id - Annotation ID for warning messages\n * @param {string} fieldName - Field name for warning messages\n * @param {Array<string>} warnings - Array to collect warning messages\n * @returns {number} Normalized coordinate value in range [0, 1]\n *\n * @example\n * normalizeCoordinate(0.5, 0.1, 'txt-1', 'x', warnings) // Returns: 0.5\n * normalizeCoordinate(5, 0.1, 'txt-1', 'x', warnings) // Returns: 1, adds warning\n * normalizeCoordinate('abc', 0.1, 'txt-1', 'x', warnings) // Returns: 0.1, adds warning\n */\nexport function normalizeCoordinate(value, defaultValue, id, fieldName, warnings) {\n // Type coercion: parse string to number if needed\n let numValue = value;\n if (typeof value === 'string') {\n numValue = parseFloat(value);\n if (!isNaN(numValue) && numValue === value) {\n // Successfully parsed - no warning needed\n }\n }\n\n // Validate is valid number\n if (typeof numValue !== 'number' || isNaN(numValue)) {\n warnings.push(\n `[${id}]: Field \"${fieldName}\" invalid value \"${value}\", using default ${defaultValue}`\n );\n return defaultValue;\n }\n\n // Range check: clamp to [0, 1]\n if (numValue < 0) {\n warnings.push(\n `[${id}]: Field \"${fieldName}\" value ${numValue} below range [0,1], clamping to 0`\n );\n return 0;\n }\n\n if (numValue > 1) {\n warnings.push(\n `[${id}]: Field \"${fieldName}\" value ${numValue} exceeds range [0,1], clamping to 1`\n );\n return 1;\n }\n\n // Valid value\n return numValue;\n}\n\n/**\n * Normalize color string\n *\n * Validates that a value is a valid color string. Supports hex, rgb/rgba,\n * and named colors. Invalid colors use the provided default.\n *\n * @param {*} value - Color value to normalize\n * @param {string} defaultValue - Fallback color if invalid\n * @param {string} id - Annotation ID for warning messages\n * @param {Array<string>} warnings - Array to collect warning messages\n * @returns {string} Valid color string\n *\n * @example\n * normalizeColor('#fff', '#000', 'txt-1', warnings) // Returns: '#fff'\n * normalizeColor('rgba(255,0,0,0.5)', '#000', 'txt-1', warnings) // Returns: 'rgba(255,0,0,0.5)'\n * normalizeColor('notacolor', '#000', 'txt-1', warnings) // Returns: '#000', adds warning\n */\nexport function normalizeColor(value, defaultValue, id, warnings) {\n // Type check: must be non-empty string\n if (typeof value !== 'string' || value.trim().length === 0) {\n warnings.push(\n `[${id}]: Invalid color format \"${value}\", using default ${defaultValue}`\n );\n return defaultValue;\n }\n\n const trimmed = value.trim();\n\n // Regex patterns for color validation (cached at module level)\n const hexPattern = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;\n const rgbPattern = /^rgba?\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*(,\\s*[\\d.]+\\s*)?\\)$/;\n\n // Named colors (basic set)\n const namedColors = [\n 'red', 'blue', 'green', 'yellow', 'black', 'white', 'gray',\n 'grey', 'orange', 'purple', 'pink', 'brown', 'transparent'\n ];\n\n // Validate format\n const isHex = hexPattern.test(trimmed);\n const isRgb = rgbPattern.test(trimmed);\n const isNamed = namedColors.includes(trimmed.toLowerCase());\n\n if (isHex || isRgb || isNamed) {\n return trimmed;\n }\n\n // Invalid format\n warnings.push(\n `[${id}]: Invalid color format \"${value}\", using default ${defaultValue}`\n );\n return defaultValue;\n}\n\n/**\n * Normalize positive number\n *\n * Validates that a value is a positive number. Invalid values use the\n * provided default.\n *\n * @param {*} value - Value to normalize\n * @param {number} defaultValue - Fallback value if invalid\n * @param {string} id - Annotation ID for warning messages\n * @param {string} fieldName - Field name for warning messages\n * @param {Array<string>} warnings - Array to collect warning messages\n * @returns {number} Positive number\n *\n * @example\n * normalizePositiveNumber(5, 3, 'ink-1', 'size', warnings) // Returns: 5\n * normalizePositiveNumber(-1, 3, 'ink-1', 'size', warnings) // Returns: 3, adds warning\n * normalizePositiveNumber('abc', 3, 'ink-1', 'size', warnings) // Returns: 3, adds warning\n */\nexport function normalizePositiveNumber(value, defaultValue, id, fieldName, warnings) {\n // Type coercion: parse string to number if needed\n let numValue = value;\n if (typeof value === 'string') {\n numValue = parseFloat(value);\n }\n\n // Validate is valid number and positive\n if (typeof numValue !== 'number' || isNaN(numValue) || numValue <= 0) {\n warnings.push(\n `[${id}]: Field \"${fieldName}\" invalid value \"${value}\", using default ${defaultValue}`\n );\n return defaultValue;\n }\n\n return numValue;\n}\n\n// ============================================================================\n// BASE FIELDS NORMALIZER\n// ============================================================================\n\n/**\n * Normalize common base annotation fields\n *\n * Validates and normalizes fields common to all annotation types: id, type,\n * page, start, and end. Auto-generates ID if missing. Applies safe defaults\n * for invalid values.\n *\n * @param {Object} raw - Raw annotation object\n * @param {Array<string>} warnings - Array to collect warning messages\n * @param {Array<string>} info - Array to collect info messages\n * @returns {Object} Object with normalized base fields\n *\n * @example\n * normalizeBaseFields({ type: 'text', page: 2 }, warnings, info)\n * // Returns: { id: 'anno-1234...', type: 'text', page: 2, start: 0, end: 0 }\n */\nexport function normalizeBaseFields(raw, warnings, info) {\n const base = {};\n\n // ===== ID Field =====\n // Check: non-empty string\n // Invalid: auto-generate unique ID\n if (typeof raw.id !== 'string' || raw.id.trim().length === 0) {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substr(2, 9);\n base.id = `anno-${timestamp}-${random}`;\n info.push(`[${base.id}]: Auto-generated ID (original was missing or invalid)`);\n } else {\n base.id = raw.id.trim();\n }\n\n // ===== Type Field =====\n // Pass through as-is (validated in parent function)\n base.type = raw.type;\n\n // ===== Page Field =====\n // Check: positive integer\n // Invalid: default to 1\n if (typeof raw.page !== 'number' || raw.page < 1) {\n warnings.push(\n `[${base.id}]: Field \"page\" invalid value \"${raw.page}\", using default ${BASE_DEFAULTS.page}`\n );\n base.page = BASE_DEFAULTS.page;\n } else {\n // Floor to ensure integer\n base.page = Math.floor(raw.page);\n }\n\n // ===== Start Field =====\n // Check: non-negative number\n // Invalid: default to 0\n if (typeof raw.start !== 'number' || raw.start < 0) {\n warnings.push(\n `[${base.id}]: Field \"start\" invalid value \"${raw.start}\", using default ${BASE_DEFAULTS.start}`\n );\n base.start = BASE_DEFAULTS.start;\n } else {\n base.start = raw.start;\n }\n\n // ===== End Field =====\n // Check: non-negative number >= start\n // Invalid: clamp to start value\n if (typeof raw.end !== 'number' || raw.end < 0) {\n warnings.push(\n `[${base.id}]: Field \"end\" invalid value \"${raw.end}\", using start value ${base.start}`\n );\n base.end = base.start;\n } else if (raw.end < base.start) {\n warnings.push(\n `[${base.id}]: Field \"end\" (${raw.end}) less than start (${base.start}), clamping to start`\n );\n base.end = base.start;\n } else {\n base.end = raw.end;\n }\n\n return base;\n}\n\n// ============================================================================\n// TYPE-SPECIFIC NORMALIZERS\n// ============================================================================\n\n/**\n * Normalize a single quad (rectangular region)\n *\n * @private\n * @param {Object} quad - Quad object with x, y, w, h\n * @param {string} id - Annotation ID\n * @param {Array<string>} warnings - Warnings array\n * @returns {Object} Normalized quad\n */\nfunction normalizeQuad(quad, id, warnings) {\n if (!quad || typeof quad !== 'object') {\n warnings.push(`[${id}]: Invalid quad object, using default`);\n return { x: 0.1, y: 0.1, w: 0.8, h: 0.05 };\n }\n\n return {\n x: normalizeCoordinate(quad.x, 0.1, id, 'quad.x', warnings),\n y: normalizeCoordinate(quad.y, 0.1, id, 'quad.y', warnings),\n w: normalizeCoordinate(quad.w, 0.8, id, 'quad.w', warnings),\n h: normalizeCoordinate(quad.h, 0.05, id, 'quad.h', warnings)\n };\n}\n\n/**\n * Normalize highlight annotation\n *\n * Validates and normalizes highlight-specific fields: mode, quads array,\n * and style.color. Applies defaults for invalid fields.\n *\n * @param {Object} base - Object with normalized base fields\n * @param {Object} raw - Raw annotation object\n * @param {Array<string>} warnings - Warnings array\n * @param {Array<string>} info - Info array\n * @returns {Object} Fully normalized highlight annotation\n *\n * @example\n * normalizeHighlight(base, raw, warnings, info)\n * // Returns: { ...base, mode: 'quads', quads: [...], style: {...} }\n */\nexport function normalizeHighlight(base, raw, warnings, info) {\n const annotation = { ...base };\n\n // ===== Mode Field =====\n // Check: value equals \"quads\"\n // Invalid: default to \"quads\"\n if (raw.mode !== 'quads') {\n warnings.push(\n `[${base.id}]: Field \"mode\" invalid value \"${raw.mode}\", using default \"${HIGHLIGHT_DEFAULTS.mode}\"`\n );\n annotation.mode = HIGHLIGHT_DEFAULTS.mode;\n } else {\n annotation.mode = raw.mode;\n }\n\n // ===== Quads Array =====\n // Check: non-empty array\n // Invalid: use default quads\n if (!Array.isArray(raw.quads) || raw.quads.length === 0) {\n warnings.push(\n `[${base.id}]: Field \"quads\" missing or empty, using default`\n );\n annotation.quads = HIGHLIGHT_DEFAULTS.quads;\n } else {\n // Normalize each quad\n annotation.quads = raw.quads.map((quad, idx) => normalizeQuad(quad, base.id, warnings));\n }\n\n // ===== Style Object =====\n // Check: object with color property\n const defaultColor = HIGHLIGHT_DEFAULTS.style.color;\n if (!raw.style || typeof raw.style !== 'object') {\n warnings.push(\n `[${base.id}]: Field \"style\" missing or invalid, using default`\n );\n annotation.style = { color: defaultColor };\n } else {\n annotation.style = {\n color: normalizeColor(raw.style.color, defaultColor, base.id, warnings)\n };\n }\n\n return annotation;\n}\n\n/**\n * Normalize text annotation\n *\n * Validates and normalizes text-specific fields: content, position (x, y),\n * dimensions (w, h), and style (bg, color). Applies defaults for invalid fields.\n *\n * @param {Object} base - Object with normalized base fields\n * @param {Object} raw - Raw annotation object\n * @param {Array<string>} warnings - Warnings array\n * @param {Array<string>} info - Info array\n * @returns {Object} Fully normalized text annotation\n *\n * @example\n * normalizeText(base, raw, warnings, info)\n * // Returns: { ...base, content: '...', x: 0.1, y: 0.1, w: 0.3, h: 0.1, style: {...} }\n */\nexport function normalizeText(base, raw, warnings, info) {\n const annotation = { ...base };\n\n // ===== Content Field =====\n // Check: non-empty string\n // Invalid: default to placeholder\n if (typeof raw.content !== 'string' || raw.content.trim().length === 0) {\n warnings.push(\n `[${base.id}]: Field \"content\" missing or empty, using default \"${TEXT_DEFAULTS.content}\"`\n );\n annotation.content = TEXT_DEFAULTS.content;\n } else {\n annotation.content = raw.content;\n }\n\n // ===== Position Fields (x, y) =====\n annotation.x = normalizeCoordinate(raw.x, TEXT_DEFAULTS.x, base.id, 'x', warnings);\n annotation.y = normalizeCoordinate(raw.y, TEXT_DEFAULTS.y, base.id, 'y', warnings);\n\n // ===== Dimension Fields (w, h) =====\n annotation.w = normalizeCoordinate(raw.w, TEXT_DEFAULTS.w, base.id, 'w', warnings);\n annotation.h = normalizeCoordinate(raw.h, TEXT_DEFAULTS.h, base.id, 'h', warnings);\n\n // ===== Style Object =====\n const defaultBg = TEXT_DEFAULTS.style.bg;\n const defaultColor = TEXT_DEFAULTS.style.color;\n\n if (!raw.style || typeof raw.style !== 'object') {\n warnings.push(\n `[${base.id}]: Field \"style\" missing or invalid, using defaults`\n );\n annotation.style = {\n bg: defaultBg,\n color: defaultColor\n };\n } else {\n annotation.style = {\n bg: normalizeColor(raw.style.bg, defaultBg, base.id, warnings),\n color: normalizeColor(raw.style.color, defaultColor, base.id, warnings)\n };\n }\n\n return annotation;\n}\n\n/**\n * Normalize a single ink point\n *\n * @private\n * @param {Object} point - Point object with t, x, y\n * @param {string} id - Annotation ID\n * @param {Array<string>} warnings - Warnings array\n * @returns {Object} Normalized point\n */\nfunction normalizePoint(point, id, warnings) {\n if (!point || typeof point !== 'object') {\n warnings.push(`[${id}]: Invalid point object, using default`);\n return { t: 0, x: 0.1, y: 0.1 };\n }\n\n return {\n t: normalizeCoordinate(point.t, 0, id, 'point.t', warnings),\n x: normalizeCoordinate(point.x, 0.1, id, 'point.x', warnings),\n y: normalizeCoordinate(point.y, 0.1, id, 'point.y', warnings)\n };\n}\n\n/**\n * Normalize a single ink stroke\n *\n * @private\n * @param {Object} stroke - Stroke object with color, size, points\n * @param {string} id - Annotation ID\n * @param {Array<string>} warnings - Warnings array\n * @returns {Object} Normalized stroke\n */\nfunction normalizeStroke(stroke, id, warnings) {\n if (!stroke || typeof stroke !== 'object') {\n warnings.push(`[${id}]: Invalid stroke object, using default`);\n return INK_DEFAULTS.strokes[0];\n }\n\n const normalized = {\n color: normalizeColor(stroke.color, INK_DEFAULTS.strokes[0].color, id, warnings),\n size: normalizePositiveNumber(stroke.size, INK_DEFAULTS.strokes[0].size, id, 'stroke.size', warnings)\n };\n\n // ===== Points Array =====\n if (!Array.isArray(stroke.points) || stroke.points.length === 0) {\n warnings.push(`[${id}]: Stroke missing points array, using default`);\n normalized.points = INK_DEFAULTS.strokes[0].points;\n } else {\n normalized.points = stroke.points.map(point => normalizePoint(point, id, warnings));\n }\n\n return normalized;\n}\n\n/**\n * Normalize ink annotation\n *\n * Validates and normalizes ink-specific fields: strokes array with color,\n * size, and points. Applies defaults for invalid fields.\n *\n * @param {Object} base - Object with normalized base fields\n * @param {Object} raw - Raw annotation object\n * @param {Array<string>} warnings - Warnings array\n * @param {Array<string>} info - Info array\n * @returns {Object} Fully normalized ink annotation\n *\n * @example\n * normalizeInk(base, raw, warnings, info)\n * // Returns: { ...base, strokes: [{ color: '...', size: 3, points: [...] }] }\n */\nexport function normalizeInk(base, raw, warnings, info) {\n const annotation = { ...base };\n\n // ===== Strokes Array =====\n // Check: non-empty array\n // Invalid: use default single stroke\n if (!Array.isArray(raw.strokes) || raw.strokes.length === 0) {\n warnings.push(\n `[${base.id}]: Field \"strokes\" missing or empty, using default`\n );\n annotation.strokes = INK_DEFAULTS.strokes;\n } else {\n // Normalize each stroke\n annotation.strokes = raw.strokes.map(stroke => normalizeStroke(stroke, base.id, warnings));\n }\n\n return annotation;\n}\n\n// ============================================================================\n// ORCHESTRATION - SINGLE ANNOTATION & ARRAY\n// ============================================================================\n\n/**\n * Normalize a single annotation\n *\n * Routes annotation to appropriate type-specific normalizer based on type field.\n * Handles critical validation errors (missing/invalid type).\n *\n * @param {Object} raw - Raw annotation object\n * @param {number} index - Position in original array (for error context)\n * @returns {Object} Result object with annotation, warnings, info, and critical error\n * @returns {Object|null} return.annotation - Normalized annotation or null if critical error\n * @returns {Array<string>} return.warnings - Warning messages\n * @returns {Array<string>} return.info - Info messages\n * @returns {string|null} return.critical - Critical error message or null\n *\n * @example\n * normalizeAnnotation({ type: 'text', content: 'Hello' }, 0)\n * // Returns: { annotation: {...}, warnings: [], info: [], critical: null }\n */\nexport function normalizeAnnotation(raw, index) {\n const warnings = [];\n const info = [];\n\n // Validate input is object\n if (!raw || typeof raw !== 'object') {\n return {\n annotation: null,\n warnings: [],\n info: [],\n critical: `Annotation at index ${index}: Not a valid object`\n };\n }\n\n // Check type field (critical - cannot route without type)\n if (typeof raw.type !== 'string' || raw.type.trim().length === 0) {\n return {\n annotation: null,\n warnings: [],\n info: [],\n critical: `Annotation at index ${index}: Missing or invalid type field`\n };\n }\n\n const type = raw.type.trim();\n\n // Normalize base fields first\n const base = normalizeBaseFields(raw, warnings, info);\n\n // Route to type-specific normalizer\n let annotation;\n\n if (type === 'highlight') {\n annotation = normalizeHighlight(base, raw, warnings, info);\n } else if (type === 'text') {\n annotation = normalizeText(base, raw, warnings, info);\n } else if (type === 'ink') {\n annotation = normalizeInk(base, raw, warnings, info);\n } else {\n return {\n annotation: null,\n warnings: [],\n info: [],\n critical: `Annotation at index ${index}: Unsupported type \"${type}\"`\n };\n }\n\n return {\n annotation,\n warnings,\n info,\n critical: null\n };\n}\n\n/**\n * Normalize array of annotations\n *\n * MAIN ENTRY POINT for annotation normalization. Processes each annotation,\n * collects warnings, and returns normalized data ready for rendering.\n *\n * @param {Array} rawAnnotations - Array of raw annotation objects\n * @param {Object} [options] - Configuration options\n * @param {boolean} [options.skipInvalid=true] - Skip critically invalid annotations\n * @param {boolean} [options.warnInConsole=true] - Log warnings to console\n * @param {Function} [options.onWarning] - Custom warning callback\n * @returns {Object} ValidationResult with normalized annotations and messages\n * @returns {Array} return.normalized - Successfully normalized annotations\n * @returns {Array<string>} return.warnings - Warning messages\n * @returns {Array<string>} return.info - Informational messages\n * @returns {Array<Object>} return.skipped - Skipped annotations with reasons\n *\n * @example\n * const result = normalizeAnnotationArray(rawAnnotations, {\n * skipInvalid: true,\n * warnInConsole: true\n * });\n *\n * renderer.setAnnotations(result.normalized);\n */\nexport function normalizeAnnotationArray(rawAnnotations, options = {}) {\n // Default options\n const skipInvalid = options.skipInvalid !== false; // Default: true\n const warnInConsole = options.warnInConsole !== false; // Default: true\n const onWarning = options.onWarning || null;\n\n // Initialize result structure\n const result = {\n normalized: [],\n warnings: [],\n info: [],\n skipped: []\n };\n\n // Validate input is array\n if (!Array.isArray(rawAnnotations)) {\n const warning = 'normalizeAnnotationArray: Input is not an array, returning empty result';\n result.warnings.push(warning);\n\n if (warnInConsole) {\n console.warn(`[Annotation Normalizer] ${warning}`);\n }\n\n return result;\n }\n\n // Process each annotation\n rawAnnotations.forEach((raw, index) => {\n // Skip null/undefined\n if (raw == null) {\n result.skipped.push({\n index,\n annotation: raw,\n reason: 'Annotation is null or undefined'\n });\n return;\n }\n\n // Normalize annotation\n const normalized = normalizeAnnotation(raw, index);\n\n // Check for critical error\n if (normalized.critical) {\n result.skipped.push({\n index,\n annotation: raw,\n reason: normalized.critical\n });\n\n if (warnInConsole) {\n console.error(`[Annotation Normalizer] ${normalized.critical}`);\n }\n\n return;\n }\n\n // Add to normalized array\n result.normalized.push(normalized.annotation);\n\n // Collect warnings and info\n result.warnings.push(...normalized.warnings);\n result.info.push(...normalized.info);\n });\n\n // Console output\n if (warnInConsole) {\n if (result.warnings.length > 0 || result.info.length > 0 || result.skipped.length > 0) {\n console.group('[Annotation Normalizer] Validation Summary');\n\n if (result.normalized.length > 0) {\n console.info(`✓ Normalized ${result.normalized.length} annotation(s)`);\n }\n\n if (result.skipped.length > 0) {\n console.error(`✗ Skipped ${result.skipped.length} annotation(s)`);\n result.skipped.forEach(s => {\n console.error(` Index ${s.index}: ${s.reason}`);\n });\n }\n\n if (result.warnings.length > 0) {\n console.warn(`⚠ ${result.warnings.length} warning(s):`);\n result.warnings.forEach(w => console.warn(` ${w}`));\n }\n\n if (result.info.length > 0) {\n console.info(`ℹ ${result.info.length} info message(s):`);\n result.info.forEach(i => console.info(` ${i}`));\n }\n\n console.groupEnd();\n }\n }\n\n // Call custom warning handler\n if (onWarning && typeof onWarning === 'function') {\n onWarning(result);\n }\n\n return result;\n}\n"],"names":["normalizeCoordinate","value","defaultValue","id","fieldName","warnings","numValue","normalizeColor","trimmed","hexPattern","rgbPattern","namedColors","isHex","isRgb","isNamed","normalizePositiveNumber","normalizeBaseFields","raw","info","base","timestamp","random","BASE_DEFAULTS","normalizeQuad","quad","normalizeHighlight","annotation","HIGHLIGHT_DEFAULTS","idx","defaultColor","normalizeText","TEXT_DEFAULTS","defaultBg","normalizePoint","point","normalizeStroke","stroke","INK_DEFAULTS","normalized","normalizeInk","normalizeAnnotation","index","type","normalizeAnnotationArray","rawAnnotations","options","warnInConsole","onWarning","result","warning","s","w"],"mappings":"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"}