pdf-search-highlight 0.2.2 → 0.3.1
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 +124 -15
- package/dist/{PDFSearchViewer-rNp5NirR.d.cts → PDFSearchViewer-DkU4bVBD.d.cts} +54 -27
- package/dist/{PDFSearchViewer-rNp5NirR.d.ts → PDFSearchViewer-DkU4bVBD.d.ts} +54 -27
- package/dist/{chunk-AA4UECNB.js → chunk-4NJWRYPR.js} +172 -9
- package/dist/chunk-4NJWRYPR.js.map +1 -0
- package/dist/{chunk-Y5LFTIMY.cjs → chunk-Z2S4WPR7.cjs} +178 -15
- package/dist/chunk-Z2S4WPR7.cjs.map +1 -0
- package/dist/core/index.cjs +4 -2
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +28 -4
- package/dist/core/index.d.ts +28 -4
- package/dist/core/index.js +3 -1
- package/dist/pdf-search-highlight.css +27 -1
- package/dist/react/index.cjs +36 -24
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +16 -4
- package/dist/react/index.d.ts +16 -4
- package/dist/react/index.js +18 -6
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-AA4UECNB.js.map +0 -1
- package/dist/chunk-Y5LFTIMY.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pdf-search-highlight
|
|
2
2
|
|
|
3
|
-
PDF viewer with text search and highlight. Render PDF, search text with flexible whitespace matching or fuzzy (approximate) matching, and navigate between highlighted results. Zoom in/out and download PDF files.
|
|
3
|
+
PDF viewer with text search and highlight. Render PDF, search text with flexible whitespace matching or fuzzy (approximate) matching, and navigate between highlighted results. Supports multi-context search with different highlight colors. Zoom in/out and download PDF files.
|
|
4
4
|
|
|
5
5
|
Built on [pdf.js](https://mozilla.github.io/pdf.js/). Works with Vanilla JS and React.
|
|
6
6
|
|
|
@@ -15,6 +15,7 @@ npm install pdf-search-highlight pdfjs-dist
|
|
|
15
15
|
- Render PDF pages (canvas + text layer)
|
|
16
16
|
- Search with flexible whitespace matching — handles inconsistent PDF text splitting
|
|
17
17
|
- Fuzzy (approximate) search — find text even with typos or OCR errors
|
|
18
|
+
- **Multi-context search** — search multiple queries simultaneously, each highlighted with a different color
|
|
18
19
|
- Cross-span highlight using `<mark>` elements
|
|
19
20
|
- Navigate between matches (next/prev, auto-scroll)
|
|
20
21
|
- Zoom in/out with configurable scale
|
|
@@ -52,6 +53,19 @@ search.next();
|
|
|
52
53
|
search.prev();
|
|
53
54
|
search.clear();
|
|
54
55
|
|
|
56
|
+
// Multi-context search — each query gets a different highlight color
|
|
57
|
+
search.searchMultiple([
|
|
58
|
+
{ query: 'contract' },
|
|
59
|
+
{ query: 'payment' },
|
|
60
|
+
{ query: 'deadline' },
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
// With per-context options
|
|
64
|
+
search.searchMultiple([
|
|
65
|
+
{ query: 'contract' },
|
|
66
|
+
{ query: 'payement', options: { fuzzy: true, fuzzyThreshold: 0.7 } },
|
|
67
|
+
]);
|
|
68
|
+
|
|
55
69
|
// Zoom
|
|
56
70
|
renderer.setScale(1.5);
|
|
57
71
|
const newPages = await renderer.renderAllPages();
|
|
@@ -76,6 +90,14 @@ await viewer.loadPDF(file);
|
|
|
76
90
|
viewer.search('query');
|
|
77
91
|
viewer.nextMatch();
|
|
78
92
|
|
|
93
|
+
// Multi-context search
|
|
94
|
+
viewer.searchMultiple([
|
|
95
|
+
{ query: 'contract' },
|
|
96
|
+
{ query: 'payment' },
|
|
97
|
+
{ query: 'deadline' },
|
|
98
|
+
]);
|
|
99
|
+
viewer.nextMatch(); // navigates through ALL matches in document order
|
|
100
|
+
|
|
79
101
|
// Zoom
|
|
80
102
|
await viewer.zoomIn();
|
|
81
103
|
await viewer.zoomOut();
|
|
@@ -87,6 +109,9 @@ await viewer.download('document.pdf');
|
|
|
87
109
|
// Events
|
|
88
110
|
viewer.on('load', ({ pageCount }) => console.log('Pages:', pageCount));
|
|
89
111
|
viewer.on('search', ({ query, total }) => console.log('Found:', total));
|
|
112
|
+
viewer.on('searchmultiple', ({ contexts, total, totalsPerContext }) => {
|
|
113
|
+
console.log('Multi-search:', total, 'total matches');
|
|
114
|
+
});
|
|
90
115
|
viewer.on('matchchange', ({ current, total }) => console.log(`${current + 1}/${total}`));
|
|
91
116
|
viewer.on('zoom', ({ scale }) => console.log('Scale:', scale));
|
|
92
117
|
viewer.on('error', ({ error, context }) => console.error(context, error));
|
|
@@ -101,16 +126,25 @@ import 'pdf-search-highlight/styles.css';
|
|
|
101
126
|
function App() {
|
|
102
127
|
const { containerRef, pages, loadPDF, zoomIn, zoomOut, download, scale } =
|
|
103
128
|
usePDFRenderer(pdfjsLib);
|
|
104
|
-
const { search, next, prev, current, total } =
|
|
129
|
+
const { search, searchMultiple, next, prev, current, total } =
|
|
130
|
+
useSearchController(pages);
|
|
105
131
|
|
|
106
132
|
return (
|
|
107
133
|
<>
|
|
108
|
-
{/*
|
|
134
|
+
{/* Single search */}
|
|
109
135
|
<input onChange={e => search(e.target.value)} />
|
|
110
136
|
<span>{total > 0 ? `${current + 1}/${total}` : ''}</span>
|
|
111
137
|
<button onClick={prev}>Prev</button>
|
|
112
138
|
<button onClick={next}>Next</button>
|
|
113
139
|
|
|
140
|
+
{/* Multi-context search */}
|
|
141
|
+
<button onClick={() => searchMultiple([
|
|
142
|
+
{ query: 'contract' },
|
|
143
|
+
{ query: 'payment' },
|
|
144
|
+
])}>
|
|
145
|
+
Search Multiple
|
|
146
|
+
</button>
|
|
147
|
+
|
|
114
148
|
{/* Zoom & download */}
|
|
115
149
|
<button onClick={zoomOut}>-</button>
|
|
116
150
|
<button onClick={zoomIn}>+</button>
|
|
@@ -139,8 +173,11 @@ function App() {
|
|
|
139
173
|
pdfjsLib={pdfjsLib}
|
|
140
174
|
source={file}
|
|
141
175
|
searchQuery={query}
|
|
176
|
+
// OR multi-context search:
|
|
177
|
+
// searchContexts={[{ query: 'contract' }, { query: 'payment' }]}
|
|
142
178
|
onLoad={({ pageCount }) => console.log('Pages:', pageCount)}
|
|
143
179
|
onSearch={({ query, total }) => console.log('Found:', total)}
|
|
180
|
+
onSearchMultiple={({ contexts, total }) => console.log('Multi:', total)}
|
|
144
181
|
onMatchChange={({ current, total }) => console.log(`${current + 1}/${total}`)}
|
|
145
182
|
onZoom={({ scale }) => console.log('Scale:', scale)}
|
|
146
183
|
style={{ height: '80vh', overflow: 'auto' }}
|
|
@@ -149,6 +186,7 @@ function App() {
|
|
|
149
186
|
|
|
150
187
|
// Imperative access via ref
|
|
151
188
|
// ref.current.nextMatch()
|
|
189
|
+
// ref.current.searchMultiple([{ query: 'a' }, { query: 'b' }])
|
|
152
190
|
// ref.current.zoomIn()
|
|
153
191
|
// ref.current.download('doc.pdf')
|
|
154
192
|
}
|
|
@@ -161,18 +199,20 @@ function App() {
|
|
|
161
199
|
| Export | Description |
|
|
162
200
|
|---|---|
|
|
163
201
|
| `PDFRenderer` | Renders PDF pages into a container (canvas + text layer) |
|
|
164
|
-
| `SearchController` | Headless search + highlight controller |
|
|
165
|
-
| `PDFSearchViewer` | All-in-one: render + search + highlight + zoom + download |
|
|
202
|
+
| `SearchController` | Headless search + highlight controller. `search()` for single query, `searchMultiple()` for multi-context |
|
|
203
|
+
| `PDFSearchViewer` | All-in-one: render + search + highlight + zoom + download. `search()` + `searchMultiple()` |
|
|
166
204
|
| `searchPage` | Low-level: search spans with flexible regex |
|
|
167
205
|
| `HighlightManager` | Low-level: apply/clear highlights on spans |
|
|
206
|
+
| `SearchContext` | Type: `{ query: string; options?: SearchOptions }` — used with `searchMultiple()` |
|
|
168
207
|
|
|
169
208
|
### React (`pdf-search-highlight/react`)
|
|
170
209
|
|
|
171
210
|
| Export | Description |
|
|
172
211
|
|---|---|
|
|
173
212
|
| `usePDFRenderer(pdfjsLib, options?)` | Hook: render PDF, returns `{ containerRef, pages, loadPDF, scale, setScale, zoomIn, zoomOut, download, ... }` |
|
|
174
|
-
| `useSearchController(pages, options?)` | Hook: search + highlight, returns `{ search, next, prev, goTo, clear, current, total }` |
|
|
175
|
-
| `PDFSearchViewer` | All-in-one component
|
|
213
|
+
| `useSearchController(pages, options?)` | Hook: search + highlight, returns `{ search, searchMultiple, next, prev, goTo, clear, current, total }` |
|
|
214
|
+
| `PDFSearchViewer` | All-in-one component. Props: `searchQuery` (single) or `searchContexts` (multi). Ref handle: `nextMatch`, `prevMatch`, `searchMultiple`, `clearSearch`, ... |
|
|
215
|
+
| `SearchContext` | Type re-exported from core |
|
|
176
216
|
|
|
177
217
|
### PDFRenderer
|
|
178
218
|
|
|
@@ -200,17 +240,28 @@ const search = new SearchController({
|
|
|
200
240
|
});
|
|
201
241
|
|
|
202
242
|
search.setPages(pages);
|
|
243
|
+
|
|
244
|
+
// Single search
|
|
203
245
|
search.search('query', { caseSensitive: false, flexibleWhitespace: true });
|
|
204
246
|
search.search('query', { fuzzy: true, fuzzyThreshold: 0.6 });
|
|
247
|
+
|
|
248
|
+
// Multi-context search
|
|
249
|
+
search.searchMultiple([
|
|
250
|
+
{ query: 'contract' },
|
|
251
|
+
{ query: 'payment' },
|
|
252
|
+
{ query: 'deadline', options: { fuzzy: true } },
|
|
253
|
+
]);
|
|
254
|
+
|
|
205
255
|
search.next();
|
|
206
256
|
search.prev();
|
|
207
257
|
search.goTo(5);
|
|
208
258
|
search.clear();
|
|
209
259
|
search.onChange = ({ current, total, query }) => {};
|
|
210
260
|
|
|
211
|
-
search.current
|
|
212
|
-
search.total
|
|
213
|
-
search.query
|
|
261
|
+
search.current // current match index
|
|
262
|
+
search.total // total matches
|
|
263
|
+
search.query // last single query
|
|
264
|
+
search.contexts // last multi-context queries
|
|
214
265
|
```
|
|
215
266
|
|
|
216
267
|
### PDFSearchViewer (Core)
|
|
@@ -219,10 +270,21 @@ search.query // last query
|
|
|
219
270
|
const viewer = new PDFSearchViewer(container, pdfjsLib, options);
|
|
220
271
|
|
|
221
272
|
await viewer.loadPDF(source);
|
|
273
|
+
|
|
274
|
+
// Single search
|
|
222
275
|
viewer.search('query', { caseSensitive: true });
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
viewer.
|
|
276
|
+
|
|
277
|
+
// Multi-context search — each context highlighted with a different color
|
|
278
|
+
viewer.searchMultiple([
|
|
279
|
+
{ query: 'contract' },
|
|
280
|
+
{ query: 'payment' },
|
|
281
|
+
{ query: 'deadline', options: { fuzzy: true } },
|
|
282
|
+
]);
|
|
283
|
+
|
|
284
|
+
// Navigation — works for both single and multi-context
|
|
285
|
+
viewer.nextMatch(); // Next match (all contexts, document order)
|
|
286
|
+
viewer.prevMatch(); // Previous match
|
|
287
|
+
viewer.clearSearch(); // Clear all highlights
|
|
226
288
|
|
|
227
289
|
await viewer.zoomIn(); // Zoom in by 0.25
|
|
228
290
|
await viewer.zoomOut(); // Zoom out by 0.25
|
|
@@ -233,6 +295,7 @@ await viewer.download('file.pdf'); // Download PDF
|
|
|
233
295
|
|
|
234
296
|
viewer.on('load', (data) => {}); // { pageCount }
|
|
235
297
|
viewer.on('search', (data) => {}); // { query, total }
|
|
298
|
+
viewer.on('searchmultiple', (data) => {}); // { contexts, total, totalsPerContext }
|
|
236
299
|
viewer.on('matchchange', (data) => {}); // { current, total }
|
|
237
300
|
viewer.on('zoom', (data) => {}); // { scale }
|
|
238
301
|
viewer.on('error', (data) => {}); // { error, context }
|
|
@@ -256,8 +319,42 @@ interface SearchOptions {
|
|
|
256
319
|
fuzzy?: boolean; // Default: false — enable approximate matching
|
|
257
320
|
fuzzyThreshold?: number; // Default: 0.6 — similarity 0.0–1.0
|
|
258
321
|
}
|
|
322
|
+
|
|
323
|
+
interface SearchContext {
|
|
324
|
+
query: string; // The search query
|
|
325
|
+
options?: SearchOptions; // Optional per-context overrides
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Multi-Context Search
|
|
330
|
+
|
|
331
|
+
Search for multiple terms simultaneously, each highlighted with a different color:
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
// Each context gets an auto-assigned color (highlight-0 through highlight-7, cycles)
|
|
335
|
+
search.searchMultiple([
|
|
336
|
+
{ query: 'contract' }, // Yellow
|
|
337
|
+
{ query: 'payment' }, // Cyan
|
|
338
|
+
{ query: 'deadline' }, // Green
|
|
339
|
+
{ query: 'penalty' }, // Orange
|
|
340
|
+
]);
|
|
341
|
+
|
|
342
|
+
// Per-context options override shared options
|
|
343
|
+
search.searchMultiple(
|
|
344
|
+
[
|
|
345
|
+
{ query: 'contract' },
|
|
346
|
+
{ query: 'payement', options: { fuzzy: true, fuzzyThreshold: 0.7 } },
|
|
347
|
+
],
|
|
348
|
+
{ caseSensitive: false } // shared options
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
// Navigate through ALL matches in document order
|
|
352
|
+
search.next(); // goes to next match regardless of which context
|
|
353
|
+
search.prev(); // goes to previous match
|
|
259
354
|
```
|
|
260
355
|
|
|
356
|
+
8 colors are provided by default (CSS classes `highlight-0` through `highlight-7`). Colors cycle for more than 8 contexts.
|
|
357
|
+
|
|
261
358
|
### Custom CSS
|
|
262
359
|
|
|
263
360
|
Override any class name:
|
|
@@ -279,12 +376,23 @@ const renderer = new PDFRenderer(container, {
|
|
|
279
376
|
Default styles:
|
|
280
377
|
|
|
281
378
|
```css
|
|
379
|
+
/* Single search */
|
|
282
380
|
.highlight {
|
|
283
381
|
background: rgba(255, 230, 0, 0.45) !important;
|
|
284
382
|
}
|
|
285
383
|
.highlight.active {
|
|
286
384
|
background: rgba(233, 69, 96, 0.55) !important;
|
|
287
385
|
}
|
|
386
|
+
|
|
387
|
+
/* Multi-context search (8 colors) */
|
|
388
|
+
.highlight-0 { /* Yellow */ }
|
|
389
|
+
.highlight-1 { /* Cyan */ }
|
|
390
|
+
.highlight-2 { /* Green */ }
|
|
391
|
+
.highlight-3 { /* Orange */ }
|
|
392
|
+
.highlight-4 { /* Purple */ }
|
|
393
|
+
.highlight-5 { /* Pink */ }
|
|
394
|
+
.highlight-6 { /* Blue */ }
|
|
395
|
+
.highlight-7 { /* Lime */ }
|
|
288
396
|
```
|
|
289
397
|
|
|
290
398
|
## How it works
|
|
@@ -294,8 +402,9 @@ Default styles:
|
|
|
294
402
|
3. **Flexible whitespace**: Query `"and expensive"` becomes regex `a\s*n\s*d\s*e\s*x\s*p\s*e\s*n\s*s\s*i\s*v\s*e` — matches regardless of whitespace differences in PDF text
|
|
295
403
|
4. **Fuzzy search**: Semi-global Levenshtein alignment finds substrings within edit distance ≤ `queryLength × (1 - threshold)` — handles typos, OCR errors, and garbled text extraction
|
|
296
404
|
5. **Highlight**: Regex/fuzzy matches on concatenated text → charMap maps back to spans → split span DOM into text nodes + `<mark>` elements
|
|
297
|
-
6. **
|
|
298
|
-
7. **
|
|
405
|
+
6. **Multi-context**: Each context runs independently, matches are sorted by document position, and each context's `<mark>` elements receive a distinct CSS class (`highlight-0`, `highlight-1`, ...)
|
|
406
|
+
7. **Navigate**: Prev/next with wrap-around, auto-scroll to active match — in multi-context mode, navigation cycles through all matches across all contexts
|
|
407
|
+
8. **Zoom**: Re-renders all pages at new scale, search highlights are automatically re-applied
|
|
299
408
|
|
|
300
409
|
## License
|
|
301
410
|
|
|
@@ -36,6 +36,8 @@ interface PDFSearchViewerOptions {
|
|
|
36
36
|
workerSrc?: string;
|
|
37
37
|
/** Gap in pixels between rendered pages. Defaults to 20. */
|
|
38
38
|
pageGap?: number;
|
|
39
|
+
/** Auto-scroll to active match on search/next/prev. Defaults to true. */
|
|
40
|
+
autoScroll?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Custom CSS class names for viewer elements.
|
|
41
43
|
* Override any or all to apply your own styles.
|
|
@@ -70,32 +72,6 @@ interface SearchOptions {
|
|
|
70
72
|
fuzzyThreshold?: number;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
type PDFSearchViewerEventMap = {
|
|
74
|
-
/** Fired when PDF finishes loading. */
|
|
75
|
-
load: {
|
|
76
|
-
pageCount: number;
|
|
77
|
-
};
|
|
78
|
-
/** Fired when a search completes. */
|
|
79
|
-
search: {
|
|
80
|
-
query: string;
|
|
81
|
-
total: number;
|
|
82
|
-
};
|
|
83
|
-
/** Fired when active match changes (via next/prev). */
|
|
84
|
-
matchchange: {
|
|
85
|
-
current: number;
|
|
86
|
-
total: number;
|
|
87
|
-
};
|
|
88
|
-
/** Fired when zoom/scale changes. */
|
|
89
|
-
zoom: {
|
|
90
|
-
scale: number;
|
|
91
|
-
};
|
|
92
|
-
/** Fired on error. */
|
|
93
|
-
error: {
|
|
94
|
-
error: Error;
|
|
95
|
-
context: string;
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
|
|
99
75
|
/**
|
|
100
76
|
* A single search match, potentially spanning multiple spans.
|
|
101
77
|
* Each match contains an array of <mark> elements that highlight
|
|
@@ -125,6 +101,48 @@ interface PageData {
|
|
|
125
101
|
/** All text spans on this page. */
|
|
126
102
|
spans: SpanData[];
|
|
127
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* A single search context for multi-context search.
|
|
106
|
+
* Each context represents a separate query highlighted with a distinct color.
|
|
107
|
+
*/
|
|
108
|
+
interface SearchContext {
|
|
109
|
+
/** The query string to search for. */
|
|
110
|
+
query: string;
|
|
111
|
+
/** Optional per-context search options (overrides shared options). */
|
|
112
|
+
options?: SearchOptions;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
type PDFSearchViewerEventMap = {
|
|
116
|
+
/** Fired when PDF finishes loading. */
|
|
117
|
+
load: {
|
|
118
|
+
pageCount: number;
|
|
119
|
+
};
|
|
120
|
+
/** Fired when a search completes. */
|
|
121
|
+
search: {
|
|
122
|
+
query: string;
|
|
123
|
+
total: number;
|
|
124
|
+
};
|
|
125
|
+
/** Fired when a multi-context search completes. */
|
|
126
|
+
searchmultiple: {
|
|
127
|
+
contexts: SearchContext[];
|
|
128
|
+
total: number;
|
|
129
|
+
totalsPerContext: number[];
|
|
130
|
+
};
|
|
131
|
+
/** Fired when active match changes (via next/prev). */
|
|
132
|
+
matchchange: {
|
|
133
|
+
current: number;
|
|
134
|
+
total: number;
|
|
135
|
+
};
|
|
136
|
+
/** Fired when zoom/scale changes. */
|
|
137
|
+
zoom: {
|
|
138
|
+
scale: number;
|
|
139
|
+
};
|
|
140
|
+
/** Fired on error. */
|
|
141
|
+
error: {
|
|
142
|
+
error: Error;
|
|
143
|
+
context: string;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
128
146
|
|
|
129
147
|
type PDFSource = File | ArrayBuffer | Uint8Array | string;
|
|
130
148
|
/**
|
|
@@ -153,6 +171,8 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
153
171
|
private pageData;
|
|
154
172
|
private lastQuery;
|
|
155
173
|
private lastSearchOptions;
|
|
174
|
+
private lastContexts;
|
|
175
|
+
private lastIsMultiContext;
|
|
156
176
|
private destroyed;
|
|
157
177
|
constructor(container: HTMLElement, pdfjsLib: any, options?: PDFSearchViewerOptions);
|
|
158
178
|
/**
|
|
@@ -164,6 +184,13 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
164
184
|
* Clears previous highlights and creates new ones.
|
|
165
185
|
*/
|
|
166
186
|
search(query: string, options?: SearchOptions): number;
|
|
187
|
+
/**
|
|
188
|
+
* Search for multiple query contexts across all pages.
|
|
189
|
+
* Each context is highlighted with a different color (highlight-0, highlight-1, ...).
|
|
190
|
+
* Navigation (nextMatch/prevMatch) cycles through ALL matches in document order.
|
|
191
|
+
* Returns total number of matches across all contexts.
|
|
192
|
+
*/
|
|
193
|
+
searchMultiple(contexts: SearchContext[], sharedOptions?: SearchOptions): number;
|
|
167
194
|
/**
|
|
168
195
|
* Navigate to next match (wraps around).
|
|
169
196
|
*/
|
|
@@ -206,4 +233,4 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
206
233
|
destroy(): void;
|
|
207
234
|
}
|
|
208
235
|
|
|
209
|
-
export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type
|
|
236
|
+
export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type SearchContext as a, type PDFSearchViewerOptions as b, type SpanData as c, type SearchMatch as d, PDFSearchViewer as e, type PDFSearchViewerEventMap as f, type PDFSource as g };
|
|
@@ -36,6 +36,8 @@ interface PDFSearchViewerOptions {
|
|
|
36
36
|
workerSrc?: string;
|
|
37
37
|
/** Gap in pixels between rendered pages. Defaults to 20. */
|
|
38
38
|
pageGap?: number;
|
|
39
|
+
/** Auto-scroll to active match on search/next/prev. Defaults to true. */
|
|
40
|
+
autoScroll?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Custom CSS class names for viewer elements.
|
|
41
43
|
* Override any or all to apply your own styles.
|
|
@@ -70,32 +72,6 @@ interface SearchOptions {
|
|
|
70
72
|
fuzzyThreshold?: number;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
type PDFSearchViewerEventMap = {
|
|
74
|
-
/** Fired when PDF finishes loading. */
|
|
75
|
-
load: {
|
|
76
|
-
pageCount: number;
|
|
77
|
-
};
|
|
78
|
-
/** Fired when a search completes. */
|
|
79
|
-
search: {
|
|
80
|
-
query: string;
|
|
81
|
-
total: number;
|
|
82
|
-
};
|
|
83
|
-
/** Fired when active match changes (via next/prev). */
|
|
84
|
-
matchchange: {
|
|
85
|
-
current: number;
|
|
86
|
-
total: number;
|
|
87
|
-
};
|
|
88
|
-
/** Fired when zoom/scale changes. */
|
|
89
|
-
zoom: {
|
|
90
|
-
scale: number;
|
|
91
|
-
};
|
|
92
|
-
/** Fired on error. */
|
|
93
|
-
error: {
|
|
94
|
-
error: Error;
|
|
95
|
-
context: string;
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
|
|
99
75
|
/**
|
|
100
76
|
* A single search match, potentially spanning multiple spans.
|
|
101
77
|
* Each match contains an array of <mark> elements that highlight
|
|
@@ -125,6 +101,48 @@ interface PageData {
|
|
|
125
101
|
/** All text spans on this page. */
|
|
126
102
|
spans: SpanData[];
|
|
127
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* A single search context for multi-context search.
|
|
106
|
+
* Each context represents a separate query highlighted with a distinct color.
|
|
107
|
+
*/
|
|
108
|
+
interface SearchContext {
|
|
109
|
+
/** The query string to search for. */
|
|
110
|
+
query: string;
|
|
111
|
+
/** Optional per-context search options (overrides shared options). */
|
|
112
|
+
options?: SearchOptions;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
type PDFSearchViewerEventMap = {
|
|
116
|
+
/** Fired when PDF finishes loading. */
|
|
117
|
+
load: {
|
|
118
|
+
pageCount: number;
|
|
119
|
+
};
|
|
120
|
+
/** Fired when a search completes. */
|
|
121
|
+
search: {
|
|
122
|
+
query: string;
|
|
123
|
+
total: number;
|
|
124
|
+
};
|
|
125
|
+
/** Fired when a multi-context search completes. */
|
|
126
|
+
searchmultiple: {
|
|
127
|
+
contexts: SearchContext[];
|
|
128
|
+
total: number;
|
|
129
|
+
totalsPerContext: number[];
|
|
130
|
+
};
|
|
131
|
+
/** Fired when active match changes (via next/prev). */
|
|
132
|
+
matchchange: {
|
|
133
|
+
current: number;
|
|
134
|
+
total: number;
|
|
135
|
+
};
|
|
136
|
+
/** Fired when zoom/scale changes. */
|
|
137
|
+
zoom: {
|
|
138
|
+
scale: number;
|
|
139
|
+
};
|
|
140
|
+
/** Fired on error. */
|
|
141
|
+
error: {
|
|
142
|
+
error: Error;
|
|
143
|
+
context: string;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
128
146
|
|
|
129
147
|
type PDFSource = File | ArrayBuffer | Uint8Array | string;
|
|
130
148
|
/**
|
|
@@ -153,6 +171,8 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
153
171
|
private pageData;
|
|
154
172
|
private lastQuery;
|
|
155
173
|
private lastSearchOptions;
|
|
174
|
+
private lastContexts;
|
|
175
|
+
private lastIsMultiContext;
|
|
156
176
|
private destroyed;
|
|
157
177
|
constructor(container: HTMLElement, pdfjsLib: any, options?: PDFSearchViewerOptions);
|
|
158
178
|
/**
|
|
@@ -164,6 +184,13 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
164
184
|
* Clears previous highlights and creates new ones.
|
|
165
185
|
*/
|
|
166
186
|
search(query: string, options?: SearchOptions): number;
|
|
187
|
+
/**
|
|
188
|
+
* Search for multiple query contexts across all pages.
|
|
189
|
+
* Each context is highlighted with a different color (highlight-0, highlight-1, ...).
|
|
190
|
+
* Navigation (nextMatch/prevMatch) cycles through ALL matches in document order.
|
|
191
|
+
* Returns total number of matches across all contexts.
|
|
192
|
+
*/
|
|
193
|
+
searchMultiple(contexts: SearchContext[], sharedOptions?: SearchOptions): number;
|
|
167
194
|
/**
|
|
168
195
|
* Navigate to next match (wraps around).
|
|
169
196
|
*/
|
|
@@ -206,4 +233,4 @@ declare class PDFSearchViewer extends EventEmitter<PDFSearchViewerEventMap> {
|
|
|
206
233
|
destroy(): void;
|
|
207
234
|
}
|
|
208
235
|
|
|
209
|
-
export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type
|
|
236
|
+
export { type ClassNames as C, EventEmitter as E, type PageData as P, type SearchOptions as S, type SearchContext as a, type PDFSearchViewerOptions as b, type SpanData as c, type SearchMatch as d, PDFSearchViewer as e, type PDFSearchViewerEventMap as f, type PDFSource as g };
|