pdf-search-highlight 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.
@@ -0,0 +1,184 @@
1
+ type Listener<T> = (data: T) => void;
2
+ declare class EventEmitter<EventMap extends {
3
+ [key: string]: unknown;
4
+ }> {
5
+ private listeners;
6
+ on<K extends keyof EventMap>(event: K, listener: Listener<EventMap[K]>): this;
7
+ off<K extends keyof EventMap>(event: K, listener: Listener<EventMap[K]>): this;
8
+ protected emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
9
+ removeAllListeners(): void;
10
+ }
11
+
12
+ /**
13
+ * Custom CSS class names for each part of the viewer.
14
+ * All are optional — defaults are applied if omitted.
15
+ */
16
+ interface ClassNames {
17
+ /** Root container. Default: 'psh-container' */
18
+ container?: string;
19
+ /** Each page wrapper. Default: 'psh-page' */
20
+ page?: string;
21
+ /** Canvas element. Default: 'psh-canvas' */
22
+ canvas?: string;
23
+ /** Text layer overlay. Default: 'psh-text-layer' */
24
+ textLayer?: string;
25
+ /** Page label (e.g. "Page 1 / 5"). Default: 'psh-page-label' */
26
+ pageLabel?: string;
27
+ /** Highlight <mark>. Default: 'highlight' */
28
+ highlight?: string;
29
+ /** Active highlight modifier. Default: 'active' */
30
+ activeHighlight?: string;
31
+ }
32
+ interface PDFSearchViewerOptions {
33
+ /** Scale factor. 'auto' = fit container width. Defaults to 'auto'. */
34
+ scale?: number | 'auto';
35
+ /** Path or URL to pdf.js worker script. */
36
+ workerSrc?: string;
37
+ /** Gap in pixels between rendered pages. Defaults to 20. */
38
+ pageGap?: number;
39
+ /**
40
+ * Custom CSS class names for viewer elements.
41
+ * Override any or all to apply your own styles.
42
+ *
43
+ * ```js
44
+ * classNames: {
45
+ * page: 'my-page',
46
+ * highlight: 'my-highlight',
47
+ * activeHighlight: 'my-active',
48
+ * }
49
+ * ```
50
+ */
51
+ classNames?: ClassNames;
52
+ }
53
+ interface SearchOptions {
54
+ /** Case-sensitive matching. Defaults to false. */
55
+ caseSensitive?: boolean;
56
+ /**
57
+ * Flexible whitespace matching: insert \s* between every character.
58
+ * Handles PDF text split inconsistencies. Defaults to true.
59
+ * Only applies for queries < 200 chars (performance).
60
+ */
61
+ flexibleWhitespace?: boolean;
62
+ }
63
+
64
+ type PDFSearchViewerEventMap = {
65
+ /** Fired when PDF finishes loading. */
66
+ load: {
67
+ pageCount: number;
68
+ };
69
+ /** Fired when a search completes. */
70
+ search: {
71
+ query: string;
72
+ total: number;
73
+ };
74
+ /** Fired when active match changes (via next/prev). */
75
+ matchchange: {
76
+ current: number;
77
+ total: number;
78
+ };
79
+ /** Fired on error. */
80
+ error: {
81
+ error: Error;
82
+ context: string;
83
+ };
84
+ };
85
+
86
+ /**
87
+ * A single search match, potentially spanning multiple spans.
88
+ * Each match contains an array of <mark> elements that highlight
89
+ * the matched text across one or more text layer spans.
90
+ */
91
+ interface SearchMatch {
92
+ /** The <mark> elements for this match (may span multiple spans). */
93
+ marks: HTMLElement[];
94
+ }
95
+ /**
96
+ * Internal span data for a rendered page.
97
+ */
98
+ interface SpanData {
99
+ /** The DOM element in the text layer. */
100
+ el: HTMLElement;
101
+ /** Original text content. */
102
+ text: string;
103
+ /** Whether this span has end-of-line. */
104
+ hasEOL: boolean;
105
+ }
106
+ /**
107
+ * Internal page data after rendering.
108
+ */
109
+ interface PageData {
110
+ /** Page wrapper container element. */
111
+ container: HTMLElement;
112
+ /** All text spans on this page. */
113
+ spans: SpanData[];
114
+ }
115
+
116
+ type PDFSource = File | ArrayBuffer | Uint8Array | string;
117
+ /**
118
+ * Main PDF viewer with search and highlight functionality.
119
+ *
120
+ * Usage:
121
+ * ```js
122
+ * import * as pdfjsLib from 'pdfjs-dist';
123
+ * import { PDFSearchViewer } from 'pdf-search-highlight';
124
+ *
125
+ * const viewer = new PDFSearchViewer(container, pdfjsLib, {
126
+ * classNames: {
127
+ * page: 'my-page',
128
+ * highlight: 'my-highlight',
129
+ * activeHighlight: 'my-active',
130
+ * }
131
+ * });
132
+ * await viewer.loadPDF(file);
133
+ * viewer.search('hello');
134
+ * viewer.nextMatch();
135
+ * ```
136
+ */
137
+ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
138
+ private renderer;
139
+ private highlightManager;
140
+ private pageData;
141
+ private lastQuery;
142
+ private lastSearchOptions;
143
+ private destroyed;
144
+ constructor(container: HTMLElement, pdfjsLib: any, options?: PDFSearchViewerOptions);
145
+ /**
146
+ * Load and render a PDF document.
147
+ */
148
+ loadPDF(source: PDFSource): Promise<void>;
149
+ /**
150
+ * Search for text across all pages.
151
+ * Clears previous highlights and creates new ones.
152
+ */
153
+ search(query: string, options?: SearchOptions): number;
154
+ /**
155
+ * Navigate to next match (wraps around).
156
+ */
157
+ nextMatch(): number;
158
+ /**
159
+ * Navigate to previous match (wraps around).
160
+ */
161
+ prevMatch(): number;
162
+ /**
163
+ * Clear all search highlights.
164
+ */
165
+ clearSearch(): void;
166
+ /**
167
+ * Get total number of pages.
168
+ */
169
+ getPageCount(): number;
170
+ /**
171
+ * Get current active match index (0-based). -1 if none.
172
+ */
173
+ getCurrentMatchIndex(): number;
174
+ /**
175
+ * Get total number of matches.
176
+ */
177
+ getMatchCount(): number;
178
+ /**
179
+ * Destroy the viewer, release all resources.
180
+ */
181
+ destroy(): void;
182
+ }
183
+
184
+ export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type PDFSearchViewerOptions as a, type SpanData as b, type SearchMatch as c, PDFSearchViewer as d, type PDFSearchViewerEventMap as e, type PDFSource as f };
@@ -0,0 +1,184 @@
1
+ type Listener<T> = (data: T) => void;
2
+ declare class EventEmitter<EventMap extends {
3
+ [key: string]: unknown;
4
+ }> {
5
+ private listeners;
6
+ on<K extends keyof EventMap>(event: K, listener: Listener<EventMap[K]>): this;
7
+ off<K extends keyof EventMap>(event: K, listener: Listener<EventMap[K]>): this;
8
+ protected emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
9
+ removeAllListeners(): void;
10
+ }
11
+
12
+ /**
13
+ * Custom CSS class names for each part of the viewer.
14
+ * All are optional — defaults are applied if omitted.
15
+ */
16
+ interface ClassNames {
17
+ /** Root container. Default: 'psh-container' */
18
+ container?: string;
19
+ /** Each page wrapper. Default: 'psh-page' */
20
+ page?: string;
21
+ /** Canvas element. Default: 'psh-canvas' */
22
+ canvas?: string;
23
+ /** Text layer overlay. Default: 'psh-text-layer' */
24
+ textLayer?: string;
25
+ /** Page label (e.g. "Page 1 / 5"). Default: 'psh-page-label' */
26
+ pageLabel?: string;
27
+ /** Highlight <mark>. Default: 'highlight' */
28
+ highlight?: string;
29
+ /** Active highlight modifier. Default: 'active' */
30
+ activeHighlight?: string;
31
+ }
32
+ interface PDFSearchViewerOptions {
33
+ /** Scale factor. 'auto' = fit container width. Defaults to 'auto'. */
34
+ scale?: number | 'auto';
35
+ /** Path or URL to pdf.js worker script. */
36
+ workerSrc?: string;
37
+ /** Gap in pixels between rendered pages. Defaults to 20. */
38
+ pageGap?: number;
39
+ /**
40
+ * Custom CSS class names for viewer elements.
41
+ * Override any or all to apply your own styles.
42
+ *
43
+ * ```js
44
+ * classNames: {
45
+ * page: 'my-page',
46
+ * highlight: 'my-highlight',
47
+ * activeHighlight: 'my-active',
48
+ * }
49
+ * ```
50
+ */
51
+ classNames?: ClassNames;
52
+ }
53
+ interface SearchOptions {
54
+ /** Case-sensitive matching. Defaults to false. */
55
+ caseSensitive?: boolean;
56
+ /**
57
+ * Flexible whitespace matching: insert \s* between every character.
58
+ * Handles PDF text split inconsistencies. Defaults to true.
59
+ * Only applies for queries < 200 chars (performance).
60
+ */
61
+ flexibleWhitespace?: boolean;
62
+ }
63
+
64
+ type PDFSearchViewerEventMap = {
65
+ /** Fired when PDF finishes loading. */
66
+ load: {
67
+ pageCount: number;
68
+ };
69
+ /** Fired when a search completes. */
70
+ search: {
71
+ query: string;
72
+ total: number;
73
+ };
74
+ /** Fired when active match changes (via next/prev). */
75
+ matchchange: {
76
+ current: number;
77
+ total: number;
78
+ };
79
+ /** Fired on error. */
80
+ error: {
81
+ error: Error;
82
+ context: string;
83
+ };
84
+ };
85
+
86
+ /**
87
+ * A single search match, potentially spanning multiple spans.
88
+ * Each match contains an array of <mark> elements that highlight
89
+ * the matched text across one or more text layer spans.
90
+ */
91
+ interface SearchMatch {
92
+ /** The <mark> elements for this match (may span multiple spans). */
93
+ marks: HTMLElement[];
94
+ }
95
+ /**
96
+ * Internal span data for a rendered page.
97
+ */
98
+ interface SpanData {
99
+ /** The DOM element in the text layer. */
100
+ el: HTMLElement;
101
+ /** Original text content. */
102
+ text: string;
103
+ /** Whether this span has end-of-line. */
104
+ hasEOL: boolean;
105
+ }
106
+ /**
107
+ * Internal page data after rendering.
108
+ */
109
+ interface PageData {
110
+ /** Page wrapper container element. */
111
+ container: HTMLElement;
112
+ /** All text spans on this page. */
113
+ spans: SpanData[];
114
+ }
115
+
116
+ type PDFSource = File | ArrayBuffer | Uint8Array | string;
117
+ /**
118
+ * Main PDF viewer with search and highlight functionality.
119
+ *
120
+ * Usage:
121
+ * ```js
122
+ * import * as pdfjsLib from 'pdfjs-dist';
123
+ * import { PDFSearchViewer } from 'pdf-search-highlight';
124
+ *
125
+ * const viewer = new PDFSearchViewer(container, pdfjsLib, {
126
+ * classNames: {
127
+ * page: 'my-page',
128
+ * highlight: 'my-highlight',
129
+ * activeHighlight: 'my-active',
130
+ * }
131
+ * });
132
+ * await viewer.loadPDF(file);
133
+ * viewer.search('hello');
134
+ * viewer.nextMatch();
135
+ * ```
136
+ */
137
+ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
138
+ private renderer;
139
+ private highlightManager;
140
+ private pageData;
141
+ private lastQuery;
142
+ private lastSearchOptions;
143
+ private destroyed;
144
+ constructor(container: HTMLElement, pdfjsLib: any, options?: PDFSearchViewerOptions);
145
+ /**
146
+ * Load and render a PDF document.
147
+ */
148
+ loadPDF(source: PDFSource): Promise<void>;
149
+ /**
150
+ * Search for text across all pages.
151
+ * Clears previous highlights and creates new ones.
152
+ */
153
+ search(query: string, options?: SearchOptions): number;
154
+ /**
155
+ * Navigate to next match (wraps around).
156
+ */
157
+ nextMatch(): number;
158
+ /**
159
+ * Navigate to previous match (wraps around).
160
+ */
161
+ prevMatch(): number;
162
+ /**
163
+ * Clear all search highlights.
164
+ */
165
+ clearSearch(): void;
166
+ /**
167
+ * Get total number of pages.
168
+ */
169
+ getPageCount(): number;
170
+ /**
171
+ * Get current active match index (0-based). -1 if none.
172
+ */
173
+ getCurrentMatchIndex(): number;
174
+ /**
175
+ * Get total number of matches.
176
+ */
177
+ getMatchCount(): number;
178
+ /**
179
+ * Destroy the viewer, release all resources.
180
+ */
181
+ destroy(): void;
182
+ }
183
+
184
+ export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type PDFSearchViewerOptions as a, type SpanData as b, type SearchMatch as c, PDFSearchViewer as d, type PDFSearchViewerEventMap as e, type PDFSource as f };