Skip to content

Commit c7c9016

Browse files
committed
search function
1 parent efca86b commit c7c9016

7 files changed

Lines changed: 218 additions & 49 deletions

File tree

package-lock.json

Lines changed: 37 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lemniscate",
3-
"version": "0.1.0",
3+
"version": "0.2.0",
44
"license": "MIT",
55
"scripts": {
66
"dev": "vite dev",
@@ -35,6 +35,7 @@
3535
"@embedpdf/plugin-print": "^2.6.2",
3636
"@embedpdf/plugin-render": "^2.6.2",
3737
"@embedpdf/plugin-scroll": "^2.6.2",
38+
"@embedpdf/plugin-search": "^2.6.2",
3839
"@embedpdf/plugin-spread": "^2.6.2",
3940
"@embedpdf/plugin-tiling": "^2.6.2",
4041
"@embedpdf/plugin-viewport": "^2.6.2",
@@ -43,15 +44,15 @@
4344
"@sveltejs/package": "^2.5.7",
4445
"@sveltejs/vite-plugin-svelte": "^6.2.4",
4546
"@types/file-saver": "^2.0.7",
46-
"@types/node": "^25.3.0",
47-
"carbon-components-svelte": "^0.101.0",
47+
"@types/node": "^25.3.1",
48+
"carbon-components-svelte": "^0.101.3",
4849
"carbon-icons-svelte": "^13.8.0",
4950
"cm6-theme-basic-dark": "^0.2.0",
5051
"cm6-theme-basic-light": "^0.2.0",
5152
"file-saver": "^2.0.5",
5253
"pandoc-wasm": "^1.0.1",
5354
"publint": "^0.3.17",
54-
"svelte": "^5.53.0",
55+
"svelte": "^5.53.5",
5556
"svelte-check": "^4.4.3",
5657
"svelte-codemirror-editor": "^2.1.0",
5758
"svelte-idle": "^3.0.1",

src/lib/PDFPluginLoader.svelte

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@
22
import {
33
useActiveDocument,
44
useDocumentManagerCapability
5-
} from "@embedpdf/plugin-document-manager/svelte";
6-
import { useExport } from "@embedpdf/plugin-export/svelte";
7-
import { useFullscreen } from "@embedpdf/plugin-fullscreen/svelte";
8-
import { usePrint } from "@embedpdf/plugin-print/svelte";
9-
import { useSpread } from "@embedpdf/plugin-spread/svelte";
10-
import { useZoom } from "@embedpdf/plugin-zoom/svelte";
5+
} from '@embedpdf/plugin-document-manager/svelte';
6+
import { useExport } from '@embedpdf/plugin-export/svelte';
7+
import { useFullscreen } from '@embedpdf/plugin-fullscreen/svelte';
8+
import { usePrint } from '@embedpdf/plugin-print/svelte';
9+
import { useScrollCapability } from '@embedpdf/plugin-scroll/svelte';
10+
import { useSearch } from '@embedpdf/plugin-search/svelte';
11+
import { useSpread } from '@embedpdf/plugin-spread/svelte';
12+
import { useZoom } from '@embedpdf/plugin-zoom/svelte';
1113
1214
import type {
1315
ActiveDocument,
1416
DocumentManager,
1517
Fullscreen,
18+
ScrollManager,
1619
UseExportReturn,
1720
UsePrintReturn,
21+
UseSearchReturn,
1822
UseSpreadReturn,
1923
UseZoomReturn
2024
} from './types';
@@ -25,6 +29,8 @@
2529
exportApi = $bindable(),
2630
fullscreen = $bindable(),
2731
print = $bindable(),
32+
scrollManager = $bindable(),
33+
search = $bindable(),
2834
spread = $bindable(),
2935
zoom = $bindable(),
3036
documentId
@@ -34,6 +40,8 @@
3440
exportApi: UseExportReturn | undefined,
3541
fullscreen: Fullscreen | undefined,
3642
print: UsePrintReturn | undefined,
43+
scrollManager: ScrollManager | undefined,
44+
search: UseSearchReturn | undefined,
3745
spread: UseSpreadReturn | undefined,
3846
zoom: UseZoomReturn | undefined,
3947
documentId: string
@@ -46,6 +54,8 @@
4654
print = usePrint(() => documentId);
4755
zoom = useZoom(() => documentId);
4856
spread = useSpread(() => documentId);
57+
search = useSearch(() => documentId);
58+
scrollManager = useScrollCapability();
4959
</script>
5060

5161
<span></span>

src/lib/PDFViewer.svelte

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@
3636
TilingLayer,
3737
TilingPluginPackage
3838
} from '@embedpdf/plugin-tiling/svelte';
39+
import {
40+
SearchLayer,
41+
SearchPluginPackage
42+
} from '@embedpdf/plugin-search/svelte';
3943
4044
import { SettingsStore } from './stores.ts';
4145
import PDFPluginLoader from './PDFPluginLoader.svelte';
4246
import type {
4347
ActiveDocument,
4448
DocumentManager,
4549
Fullscreen,
50+
ScrollManager,
4651
UseExportReturn,
4752
UsePrintReturn,
53+
UseSearchReturn,
4854
UseSpreadReturn,
4955
UseZoomReturn
5056
} from './types';
@@ -72,7 +78,8 @@
7278
tileSize: 768,
7379
overlapPx: 5,
7480
extraRings: 0
75-
})
81+
}),
82+
createPluginRegistration(SearchPluginPackage)
7683
];
7784
7885
let docManager: DocumentManager | undefined = $state(undefined);
@@ -82,6 +89,8 @@
8289
let spread: UseSpreadReturn | undefined = $state(undefined);
8390
let zoom: UseZoomReturn | undefined = $state(undefined);
8491
let fullscreen: Fullscreen | undefined = $state(undefined);
92+
let search: UseSearchReturn | undefined = $state(undefined);
93+
let scrollManager: ScrollManager | undefined = $state(undefined);
8594
8695
let isPrinting = $state(false);
8796
@@ -117,27 +126,61 @@
117126
export function fullscreenPdf(): void {
118127
fullscreen!.provides?.toggleFullscreen(`#${activeDocument?.activeDocumentId}`)
119128
}
129+
130+
export function searchPdf(query: string): void {
131+
if (!search) return;
132+
query === '' ? search.provides?.stopSearch() : search.provides?.searchAllPages(query);
133+
}
134+
135+
export function changeSearchResult(dir: 'prev' | 'next'): void {
136+
dir === 'prev' ? search!.provides?.previousResult() : search!.provides?.nextResult();
137+
}
138+
139+
function scrollToItem(index: number): void {
140+
const item = search!.state.results[index];
141+
if (!item) return;
142+
const minCoordinates = item.rects.reduce(
143+
(min, rect) => ({
144+
x: Math.min(min.x, rect.origin.x),
145+
y: Math.min(min.y, rect.origin.y),
146+
}),
147+
{ x: Infinity, y: Infinity },
148+
);
149+
scrollManager!.provides?.scrollToPage({
150+
pageNumber: item.pageIndex + 1,
151+
pageCoordinates: minCoordinates,
152+
alignX: 50,
153+
alignY: 50
154+
});
155+
}
156+
157+
$effect(() => {
158+
if (search &&
159+
typeof search.state.activeResultIndex === 'number' &&
160+
!search.state.loading &&
161+
search.state.results.length > 0)
162+
scrollToItem(search.state.activeResultIndex);
163+
});
120164
</script>
121165

122166
{#if pdfEngine.isLoading || !pdfEngine.engine}
123167
<div class='loading-pane'>
124168
Loading PDF Engine...
125169
</div>
126170
{:else}
127-
<div style='height: 80vh;'>
171+
<div class='pdf-wrapper'>
128172
<EmbedPDF engine={pdfEngine.engine} {plugins}>
129173
{#snippet children({ activeDocumentId })}
130174
{#if activeDocumentId}
131175
{@const documentId = activeDocumentId}
132176
<DocumentContent {documentId}>
133177
{#snippet children(documentContent)}
134178
{#if documentContent.isLoaded}
135-
<div
136-
style:width='100%'
137-
style:height='100%'
138-
style:position='relative'
139-
>
140-
<Viewport {documentId} style={$SettingsStore.theme === 'dark' ? 'background-color:#2E3235' : 'background-color:#FFFFFF'}>
179+
<div class='viewport-wrapper'>
180+
<Viewport
181+
{documentId}
182+
style={$SettingsStore.theme === 'dark' ? 'background-color:#2E3235' : 'background-color:#FFFFFF'}
183+
>
141184
<Scroller {documentId}>
142185
{#snippet renderPage(page: RenderPageProps)}
143186
<RenderLayer
@@ -149,6 +192,10 @@
149192
{documentId}
150193
pageIndex={page.pageIndex}
151194
/>
195+
<SearchLayer
196+
{documentId}
197+
pageIndex={page.pageIndex}
198+
/>
152199
{/snippet}
153200
</Scroller>
154201
<PDFPluginLoader
@@ -157,6 +204,8 @@
157204
bind:exportApi
158205
bind:fullscreen
159206
bind:print
207+
bind:scrollManager
208+
bind:search
160209
bind:spread
161210
bind:zoom
162211
{documentId}

0 commit comments

Comments
 (0)