@rightkit/document-core 0.1.2 → 0.2.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 (126) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +31 -7
  3. package/dist/app/chrome.js +1 -1
  4. package/dist/app/documentPrinting.d.ts +0 -6
  5. package/dist/app/documentPrinting.js +0 -18
  6. package/dist/app/shell/nativeMenu.d.ts +3 -2
  7. package/dist/app/shell/nativeMenu.js +8 -5
  8. package/dist/documents/perfEventCounters.d.ts +0 -8
  9. package/dist/documents/perfEventCounters.js +2 -1
  10. package/dist/documents/preview/previewFrame.d.ts +2 -1
  11. package/dist/documents/preview/previewFrame.js +9 -7
  12. package/dist/documents/searchUtils.js +1 -1
  13. package/dist/host.d.ts +36 -0
  14. package/dist/host.js +54 -0
  15. package/dist/index.d.ts +1 -46
  16. package/dist/index.js +1 -46
  17. package/dist/settings/themes.js +1 -1
  18. package/dist/state/bridgeEvents.d.ts +1 -1
  19. package/dist/state/bridgeEvents.js +7 -4
  20. package/dist/state/recentUrls.js +4 -3
  21. package/dist/state/tauriBridge.d.ts +3 -47
  22. package/dist/state/tauriBridge.js +6 -162
  23. package/dist/styles.css +2 -2
  24. package/package.json +16 -87
  25. package/dist/app/shortcutChords.d.ts +0 -6
  26. package/dist/app/shortcutChords.js +0 -14
  27. package/dist/app/useCloseFindOnSurfaceChange.d.ts +0 -14
  28. package/dist/app/useCloseFindOnSurfaceChange.js +0 -23
  29. package/dist/app/useEditText.d.ts +0 -6
  30. package/dist/app/useEditText.js +0 -10
  31. package/dist/appName.d.ts +0 -2
  32. package/dist/appName.js +0 -8
  33. package/dist/documents/FullscreenIcon.d.ts +0 -4
  34. package/dist/documents/FullscreenIcon.js +0 -7
  35. package/dist/documents/mdx/mdxRuntimeScript.d.ts +0 -2
  36. package/dist/documents/mdx/mdxRuntimeScript.js +0 -3
  37. package/dist/documents/mdx/mdxRuntimeScript.txt +0 -584
  38. package/dist/documents/pdf/MacPdfReadPane.d.ts +0 -23
  39. package/dist/documents/pdf/MacPdfReadPane.js +0 -708
  40. package/dist/documents/pdf/NativePdfDocument.d.ts +0 -9
  41. package/dist/documents/pdf/NativePdfDocument.js +0 -41
  42. package/dist/documents/pdf/PdfInlineTextEditor.d.ts +0 -53
  43. package/dist/documents/pdf/PdfInlineTextEditor.js +0 -225
  44. package/dist/documents/pdf/PdfOcrLayer.d.ts +0 -4
  45. package/dist/documents/pdf/PdfOcrLayer.js +0 -30
  46. package/dist/documents/pdf/PdfOutline.d.ts +0 -6
  47. package/dist/documents/pdf/PdfOutline.js +0 -12
  48. package/dist/documents/pdf/PdfPasswordPrompt.d.ts +0 -5
  49. package/dist/documents/pdf/PdfPasswordPrompt.js +0 -24
  50. package/dist/documents/pdf/PdfThumbnails.d.ts +0 -8
  51. package/dist/documents/pdf/PdfThumbnails.js +0 -201
  52. package/dist/documents/pdf/PdfToolbar.d.ts +0 -47
  53. package/dist/documents/pdf/PdfToolbar.js +0 -76
  54. package/dist/documents/pdf/PdfViewer.d.ts +0 -36
  55. package/dist/documents/pdf/PdfViewer.js +0 -1522
  56. package/dist/documents/pdf/PdfViewerBody.d.ts +0 -22
  57. package/dist/documents/pdf/PdfViewerBody.js +0 -42
  58. package/dist/documents/pdf/macPdfNativeBridge.d.ts +0 -118
  59. package/dist/documents/pdf/macPdfNativeBridge.js +0 -134
  60. package/dist/documents/pdf/nearestVisiblePdfPage.d.ts +0 -2
  61. package/dist/documents/pdf/nearestVisiblePdfPage.js +0 -22
  62. package/dist/documents/pdf/pdfBench.d.ts +0 -88
  63. package/dist/documents/pdf/pdfBench.js +0 -535
  64. package/dist/documents/pdf/pdfBenchAutopilot.d.ts +0 -48
  65. package/dist/documents/pdf/pdfBenchAutopilot.js +0 -154
  66. package/dist/documents/pdf/pdfBenchTransport.d.ts +0 -21
  67. package/dist/documents/pdf/pdfBenchTransport.js +0 -233
  68. package/dist/documents/pdf/pdfEditModel.d.ts +0 -294
  69. package/dist/documents/pdf/pdfEditModel.js +0 -105
  70. package/dist/documents/pdf/pdfEditor.d.ts +0 -100
  71. package/dist/documents/pdf/pdfEditor.js +0 -68
  72. package/dist/documents/pdf/pdfOcr.d.ts +0 -36
  73. package/dist/documents/pdf/pdfOcr.js +0 -88
  74. package/dist/documents/pdf/pdfOcrEdit.d.ts +0 -32
  75. package/dist/documents/pdf/pdfOcrEdit.js +0 -138
  76. package/dist/documents/pdf/pdfPrinting.d.ts +0 -28
  77. package/dist/documents/pdf/pdfPrinting.js +0 -110
  78. package/dist/documents/pdf/pdfSave.d.ts +0 -87
  79. package/dist/documents/pdf/pdfSave.js +0 -250
  80. package/dist/documents/pdf/pdfShared.d.ts +0 -16
  81. package/dist/documents/pdf/pdfShared.js +0 -20
  82. package/dist/documents/pdf/pdfToMarkdown.d.ts +0 -11
  83. package/dist/documents/pdf/pdfToMarkdown.js +0 -67
  84. package/dist/documents/pdf/pdfjsLibGlobal.d.ts +0 -1
  85. package/dist/documents/pdf/pdfjsLibGlobal.js +0 -12
  86. package/dist/documents/pdf/toolbarIcons.d.ts +0 -18
  87. package/dist/documents/pdf/toolbarIcons.js +0 -31
  88. package/dist/documents/pdf/usePdfDocumentLoader.d.ts +0 -40
  89. package/dist/documents/pdf/usePdfDocumentLoader.js +0 -243
  90. package/dist/documents/pdf/usePdfEditSession.d.ts +0 -88
  91. package/dist/documents/pdf/usePdfEditSession.js +0 -341
  92. package/dist/documents/pdf/usePdfEditor.d.ts +0 -59
  93. package/dist/documents/pdf/usePdfEditor.js +0 -317
  94. package/dist/documents/pdf/usePdfFit.d.ts +0 -19
  95. package/dist/documents/pdf/usePdfFit.js +0 -55
  96. package/dist/documents/pdf/usePdfOcr.d.ts +0 -38
  97. package/dist/documents/pdf/usePdfOcr.js +0 -337
  98. package/dist/documents/pdf/usePdfPreviewRecompose.d.ts +0 -28
  99. package/dist/documents/pdf/usePdfPreviewRecompose.js +0 -256
  100. package/dist/documents/pdf/usePdfSavePlan.d.ts +0 -61
  101. package/dist/documents/pdf/usePdfSavePlan.js +0 -287
  102. package/dist/documents/pdf/usePdfSearch.d.ts +0 -31
  103. package/dist/documents/pdf/usePdfSearch.js +0 -367
  104. package/dist/documents/pdf/usePdfViewControls.d.ts +0 -72
  105. package/dist/documents/pdf/usePdfViewControls.js +0 -152
  106. package/dist/documents/scopedSelectAll.d.ts +0 -5
  107. package/dist/documents/scopedSelectAll.js +0 -77
  108. package/dist/documents/txt/cmScroll.d.ts +0 -11
  109. package/dist/documents/txt/cmScroll.js +0 -52
  110. package/dist/documents/useMirroredEditText.d.ts +0 -15
  111. package/dist/documents/useMirroredEditText.js +0 -29
  112. package/dist/documents/useSplitResize.d.ts +0 -7
  113. package/dist/documents/useSplitResize.js +0 -37
  114. package/dist/settings/rk-settings.css +0 -38
  115. package/dist/settings/sections/EditorSection.d.ts +0 -1
  116. package/dist/settings/sections/EditorSection.js +0 -18
  117. package/dist/settings/sections/FileAssociationsSection.d.ts +0 -1
  118. package/dist/settings/sections/FileAssociationsSection.js +0 -5
  119. package/dist/settings/sections/MacFileAssociationsBlock.d.ts +0 -33
  120. package/dist/settings/sections/MacFileAssociationsBlock.js +0 -151
  121. package/dist/settings/sections/ThemeSection.d.ts +0 -1
  122. package/dist/settings/sections/ThemeSection.js +0 -31
  123. package/dist/settings/sections/TypographySection.d.ts +0 -1
  124. package/dist/settings/sections/TypographySection.js +0 -19
  125. package/dist/settings/sections/onOff.d.ts +0 -11
  126. package/dist/settings/sections/onOff.js +0 -8
@@ -1,250 +0,0 @@
1
- /**
2
- * PDF save orchestration (`docs/PDF-EDITOR-NOW.md` §9.4, §10).
3
- *
4
- * Two independent flows live here, both built against the *injected-bridge* function types frozen
5
- * in `pdfEditModel.ts` (§10.3's "Frozen cross-lane seams" — the real `tauriBridge.ts` Tauri-backed
6
- * implementations land later at Dispatch D2, so every backend call here is a parameter, never an
7
- * import):
8
- *
9
- * 1. `recomposePdfPreview` (§9.4) — calls an injected `ComposePdfPreview`-shaped function to get
10
- * memory-only candidate bytes for the current source-command history, so the on-page display of
11
- * committed-but-unsaved edits always renders from the same composer Save itself will use.
12
- *
13
- * 2. `createPdfSavePlan` (§10.1/§10.2/§10.3) — the two-phase Save protocol: prepare (Rust composes
14
- * + structurally validates a candidate and returns it plus a short-lived token), isolated
15
- * pdf.js render-verify (catch corruption client-side before committing), then commit (Rust
16
- * atomically replaces bytes). Returns a `PdfSavePlan` (§10.3's exact shape) rather than bare
17
- * bytes, so the generic document saver only updates recents/fingerprints/checkpoints after a
18
- * real commit succeeds.
19
- *
20
- * `verifyPdfCandidate` (§10.2) loads candidate bytes into a FRESH, isolated pdf.js document — never
21
- * the active on-screen `PDFDocumentProxy` — and renders affected pages to an offscreen canvas before
22
- * extracting text for the expected-text checks. This mirrors `pdfPrinting.ts`'s isolated-document
23
- * pattern (pdf.js caches page proxies per document; reusing the live viewer's document risks a
24
- * second concurrent `render()` against a `PDFPageProxy` it may already be rendering — a hang, not an
25
- * error). Every await is time-bounded so a stuck pdf.js worker surfaces as a rejected promise
26
- * (`VerificationFailed`) instead of silence.
27
- */
28
- import * as pdfjs from "pdfjs-dist";
29
- import { pdfDocumentInit, pdfWasmUrl } from "@rightkit/pdf-ui";
30
- import { withTimeout } from "./pdfShared.js";
31
- import { logEvent } from "../../state/diagnostics.js";
32
- // ---------------------------------------------------------------------------------------------
33
- // §9.4 in-memory preview composition
34
- // ---------------------------------------------------------------------------------------------
35
- /** Compose final replacements against original bytes without deleting undo history. A failed
36
- * preview leaves its original locator visible; correcting it supersedes earlier replacements
37
- * of exactly those bytes, rather than retrying an invalid intermediate edit first. */
38
- function effectiveSourceCommands(commands) {
39
- const seen = new Set();
40
- const effective = [];
41
- for (const command of [...commands].reverse()) {
42
- if (command.kind === "replaceSourceText") {
43
- const { documentSha256, page, islandDigest, spans } = command.locator;
44
- const key = JSON.stringify([
45
- documentSha256,
46
- page,
47
- islandDigest,
48
- spans.map((span) => [
49
- span.streamRef,
50
- span.contentsIndex,
51
- span.operatorIndex,
52
- span.operandIndex,
53
- span.glyphStart,
54
- span.glyphEnd,
55
- span.expectedText,
56
- span.expectedDigest,
57
- ]),
58
- ]);
59
- if (seen.has(key))
60
- continue;
61
- seen.add(key);
62
- }
63
- effective.push(command);
64
- }
65
- return effective.reverse();
66
- }
67
- /** Recompose the memory-only preview candidate for the given source-command history (§9.4). No
68
- * token, no retained candidate, no write — callers re-render affected pages from the returned
69
- * bytes inside their existing page slots. Thin by design: the composer decides validity; this
70
- * function only shapes the request and forwards the injected call. */
71
- export async function recomposePdfPreview(deps, sourcePath, expectedSourceSha256, sourceCommands) {
72
- const request = {
73
- sourcePath,
74
- expectedSourceSha256,
75
- sourceCommands: effectiveSourceCommands(sourceCommands),
76
- };
77
- return deps.composePdfPreview(request);
78
- }
79
- // ---------------------------------------------------------------------------------------------
80
- // §10.2 isolated pdf.js render-verify
81
- // ---------------------------------------------------------------------------------------------
82
- /** Thrown by `verifyPdfCandidate` on any renderability/content failure. Callers map this to
83
- * `PdfEditError` code `"verification_failed"` (§11) rather than letting a raw pdf.js error surface,
84
- * since §11 requires logs to carry "code/page/strategy but no document text" — this type carries a
85
- * `page` when the failure is page-scoped and never embeds extracted document text in its message. */
86
- export class PdfCandidateVerificationError extends Error {
87
- page;
88
- constructor(message, page = null) {
89
- super(message);
90
- this.name = "PdfCandidateVerificationError";
91
- this.page = page;
92
- }
93
- }
94
- const RENDER_TIMEOUT_MS = 20_000;
95
- /** WKWebView's ReadableStream lacks async iteration, which makes pdf.js `getTextContent()` throw.
96
- * Read its public stream with a reader instead; this works in WKWebView & standards browsers. */
97
- async function extractPageText(page) {
98
- const reader = page.streamTextContent().getReader();
99
- let extracted = "";
100
- try {
101
- while (true) {
102
- const chunk = await withTimeout(reader.read(), RENDER_TIMEOUT_MS, "pdf.js text stream timed out");
103
- if (chunk.done)
104
- break;
105
- extracted += chunk.value.items.map((item) => item.str ?? "").join("");
106
- }
107
- return extracted;
108
- }
109
- finally {
110
- reader.releaseLock();
111
- }
112
- }
113
- /** Render every page in `pages` from a FRESH, isolated pdf.js document built from `bytes` (never the
114
- * active on-screen document — see module doc), waiting for each render to fully settle, then check
115
- * that every `expectedText` entry's text is present somewhere in that page's extracted text.
116
- * Resolves on success; rejects with `PdfCandidateVerificationError` on any load/render/text-check
117
- * failure. Always disposes the isolated document via `doc.destroy()`, success or failure, so a
118
- * failed verification never leaks a pdf.js worker/document. */
119
- export async function verifyPdfCandidate({ bytes, pages, expectedText, }) {
120
- const data = bytes.slice();
121
- const loadingTask = pdfjs.getDocument(pdfDocumentInit(data, { wasmUrl: pdfWasmUrl() }));
122
- let doc;
123
- try {
124
- doc = await withTimeout(loadingTask.promise, RENDER_TIMEOUT_MS, "pdf.js getDocument timed out");
125
- }
126
- catch (e) {
127
- throw new PdfCandidateVerificationError(e instanceof Error ? e.message : "candidate could not be opened");
128
- }
129
- try {
130
- const expectedByPage = new Map();
131
- for (const check of expectedText) {
132
- const list = expectedByPage.get(check.page);
133
- if (list)
134
- list.push(check);
135
- else
136
- expectedByPage.set(check.page, [check]);
137
- }
138
- for (const pageNumber of pages) {
139
- let page;
140
- try {
141
- page = await withTimeout(doc.getPage(pageNumber), RENDER_TIMEOUT_MS, `pdf.js getPage(${pageNumber}) timed out`);
142
- }
143
- catch (e) {
144
- throw new PdfCandidateVerificationError(e instanceof Error ? e.message : "candidate page could not be opened", pageNumber);
145
- }
146
- const viewport = page.getViewport({ scale: 1 });
147
- const canvas = document.createElement("canvas");
148
- canvas.width = Math.max(1, Math.ceil(viewport.width));
149
- canvas.height = Math.max(1, Math.ceil(viewport.height));
150
- const ctx = canvas.getContext("2d");
151
- if (!ctx) {
152
- throw new PdfCandidateVerificationError("candidate render context unavailable", pageNumber);
153
- }
154
- try {
155
- await withTimeout(page.render({ canvas, canvasContext: ctx, viewport }).promise, RENDER_TIMEOUT_MS, `pdf.js render(page ${pageNumber}) timed out`);
156
- }
157
- catch (e) {
158
- throw new PdfCandidateVerificationError(e instanceof Error ? e.message : "candidate page failed to render", pageNumber);
159
- }
160
- const checks = expectedByPage.get(pageNumber);
161
- if (checks && checks.length > 0) {
162
- let extracted;
163
- try {
164
- extracted = await extractPageText(page);
165
- }
166
- catch (e) {
167
- throw new PdfCandidateVerificationError(e instanceof Error ? e.message : "candidate text could not be extracted", pageNumber);
168
- }
169
- for (const check of checks) {
170
- if (!extracted.includes(check.expectedText)) {
171
- throw new PdfCandidateVerificationError(`expected text missing after candidate render (island ${check.islandId})`, pageNumber);
172
- }
173
- }
174
- }
175
- }
176
- }
177
- finally {
178
- // `PDFDocumentProxy` has no `destroy()` of its own in this pdfjs-dist version — disposal goes
179
- // through the `PDFDocumentLoadingTask` that produced it (same pattern as `pdfPrinting.ts`/
180
- // `pdfBenchTransport.ts`).
181
- await loadingTask.destroy();
182
- }
183
- }
184
- /** Builds `PreparePdfSaveRequest` from `PdfSaveInput` — kept as a named step so both the happy path
185
- * and tests can assert on the exact shape sent to `preparePdfSave` without duplicating field
186
- * wiring. */
187
- function toPrepareRequest(input) {
188
- return {
189
- sourcePath: input.sourcePath,
190
- expectedSourceSha256: input.expectedSourceSha256,
191
- annotationPdfBytes: input.annotationPdfBytes,
192
- sourceCommands: effectiveSourceCommands(input.sourceCommands),
193
- };
194
- }
195
- /**
196
- * Runs §10.1 prepare against the injected `preparePdfSave`, then §10.2 isolated pdf.js
197
- * render-verify against the returned candidate. Returns a `PdfSavePlan` (§10.3's exact shape) only
198
- * once both steps succeed — `commit` is the only thing that talks to `commitPdfSave`, and it does so
199
- * lazily so a caller that decides not to commit (e.g. user cancels a Save As target picker between
200
- * prepare and commit) never invalidates the token by calling it.
201
- *
202
- * Token lifecycle (§10.3): the token this returns is single-use, expires after five minutes, and is
203
- * invalidated by any source revision in between — this module does not retry or re-prepare on a
204
- * stale-token rejection from `commit_pdf_save`; it surfaces the typed `PdfEditError` (expected code
205
- * `"write_conflict"` or `"stale_source"` per §11) to the caller, which owns the "start over" UX.
206
- * `didCommit` intentionally does nothing beyond what `commitPdfSave` already returned — §10.3 gives
207
- * the generic document saver, not this module, ownership of when recents/fingerprints/checkpoints
208
- * update, so this hook exists only as the seam that saver calls after using `result`.
209
- */
210
- export async function prepareAndVerifyPdfSave(deps, input) {
211
- let prepared;
212
- try {
213
- prepared = await deps.preparePdfSave(toPrepareRequest(input));
214
- logEvent("pdf-save:prepare:done");
215
- }
216
- catch (error) {
217
- logEvent("pdf-save:prepare:error");
218
- throw error;
219
- }
220
- const verify = deps.verifyCandidate ?? verifyPdfCandidate;
221
- try {
222
- await verify({
223
- bytes: prepared.candidateBytes,
224
- pages: prepared.affectedPages,
225
- expectedText: prepared.expectedText,
226
- });
227
- logEvent("pdf-save:verify:done");
228
- }
229
- catch (error) {
230
- logEvent("pdf-save:verify:error");
231
- throw error;
232
- }
233
- let committed = false;
234
- return {
235
- async commit(targetPath) {
236
- if (committed) {
237
- throw new PdfCandidateVerificationError("save token already used — prepare a new candidate before committing again");
238
- }
239
- committed = true;
240
- // Any rejection (typed `PdfEditError` per §11, e.g. "write_conflict"/"stale_source", or
241
- // otherwise) is surfaced as-is — this module does not retry or reinterpret it (see doc
242
- // comment above); the caller owns the "start over" UX.
243
- return deps.commitPdfSave(prepared.token, targetPath);
244
- },
245
- async didCommit(_result) {
246
- // Intentionally a no-op seam (see doc comment above): the generic document saver
247
- // (`useDocumentSaver.ts`) is the sole owner of post-commit bookkeeping.
248
- },
249
- };
250
- }
@@ -1,16 +0,0 @@
1
- export { boundedCanvasDpr, clampScale, viewportRotation, withTimeout, ZOOM_MAX, ZOOM_MIN, type OutlineNode, type Size, } from "@rightkit/pdf-ui";
2
- export declare const MARK_BG = "rgba(196,106,61,.40)";
3
- export declare const MARK_ACTIVE_BG = "rgba(240,160,96,.65)";
4
- export declare const THUMB_W = 130;
5
- export interface Match {
6
- page: number;
7
- occ: number;
8
- }
9
- /** Wrap every occurrence of `q` (honoring match-case / whole-word) inside a rendered text-layer
10
- * span with <mark>, using the package's span highlighter with the host app non-active copper
11
- * background. The active match is not drawn here: usePdfSearch emphasises it by page-wide
12
- * occurrence index. */
13
- export declare function highlightSpan(span: HTMLElement, q: string, options?: {
14
- matchCase?: boolean;
15
- wholeWord?: boolean;
16
- }): void;
@@ -1,20 +0,0 @@
1
- // Shared PDF viewer primitives: @rightkit/pdf-ui's zoom/DPR/rotation/timeout helpers plus
2
- // the host app brand find-highlight colors, text-layer highlighter, and thumbnail width.
3
- import { highlightSpan as highlightSpanWithMarks } from "@rightkit/pdf-ui";
4
- export { boundedCanvasDpr, clampScale, viewportRotation, withTimeout, ZOOM_MAX, ZOOM_MIN, } from "@rightkit/pdf-ui";
5
- // Both highlight backgrounds are translucent so the canvas-rendered glyph shows through — the
6
- // text layer is only an invisible selection overlay, so we never repaint its (transparent) text.
7
- export const MARK_BG = "rgba(196,106,61,.40)"; // copper @ 40% — non-active matches
8
- export const MARK_ACTIVE_BG = "rgba(240,160,96,.65)"; // brighter copper @ 65% — active match
9
- export const THUMB_W = 130; // CSS px width of a thumbnail canvas
10
- /** Wrap every occurrence of `q` (honoring match-case / whole-word) inside a rendered text-layer
11
- * span with <mark>, using the package's span highlighter with the host app non-active copper
12
- * background. The active match is not drawn here: usePdfSearch emphasises it by page-wide
13
- * occurrence index. */
14
- export function highlightSpan(span, q, options) {
15
- highlightSpanWithMarks(span, q, {
16
- matchCase: options?.matchCase,
17
- wholeWord: options?.wholeWord,
18
- markBg: MARK_BG,
19
- });
20
- }
@@ -1,11 +0,0 @@
1
- interface Item {
2
- str: string;
3
- hasEOL?: boolean;
4
- height?: number;
5
- transform?: number[];
6
- }
7
- /** One page's text as paragraphs: lines join on EOL/baseline change; a vertical gap over 1.6 line
8
- * heights starts a new paragraph. Plain paragraphs only (no font-size heading inference). */
9
- export declare function pageItemsToParagraphs(items: Item[]): string[];
10
- export declare function pdfUrlToMarkdown(url: string): Promise<string>;
11
- export {};
@@ -1,67 +0,0 @@
1
- import * as pdfjs from "pdfjs-dist";
2
- /** One page's text as paragraphs: lines join on EOL/baseline change; a vertical gap over 1.6 line
3
- * heights starts a new paragraph. Plain paragraphs only (no font-size heading inference). */
4
- export function pageItemsToParagraphs(items) {
5
- const paras = [];
6
- let line = "";
7
- let cur = "";
8
- let lastY = null;
9
- let lastH = 0;
10
- const flushLine = () => {
11
- const t = line.replace(/\s+/g, " ").trim();
12
- if (t)
13
- cur += (cur ? " " : "") + t;
14
- line = "";
15
- };
16
- const flushPara = () => {
17
- flushLine();
18
- if (cur)
19
- paras.push(cur);
20
- cur = "";
21
- };
22
- for (const it of items) {
23
- const y = it.transform?.[5] ?? null;
24
- const h = it.height || lastH || 10;
25
- if (y !== null && lastY !== null && Math.abs(y - lastY) > h * 0.5) {
26
- const gap = Math.abs(y - lastY);
27
- flushLine();
28
- if (gap > h * 1.6)
29
- flushPara();
30
- }
31
- if (y !== null)
32
- lastY = y;
33
- lastH = h;
34
- line += it.str;
35
- if (it.hasEOL)
36
- flushLine();
37
- }
38
- flushPara();
39
- return paras;
40
- }
41
- export async function pdfUrlToMarkdown(url) {
42
- const task = pdfjs.getDocument({ url });
43
- const doc = await task.promise;
44
- try {
45
- const pages = [];
46
- for (let n = 1; n <= doc.numPages; n++) {
47
- const page = await doc.getPage(n);
48
- const reader = page.streamTextContent().getReader();
49
- const items = [];
50
- for (;;) {
51
- const { done, value } = await reader.read();
52
- if (done)
53
- break;
54
- for (const i of value.items)
55
- if ("str" in i)
56
- items.push(i);
57
- }
58
- const paras = pageItemsToParagraphs(items);
59
- if (paras.length)
60
- pages.push(paras.join("\n\n"));
61
- }
62
- return `${pages.join("\n\n")}\n`;
63
- }
64
- finally {
65
- void task.destroy();
66
- }
67
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,12 +0,0 @@
1
- // pdf.js publishes `AnnotationEditorUIManager`'s two viewer-component dependencies (EventBus,
2
- // GenericL10n) only from "pdfjs-dist/web/pdf_viewer.mjs" — and that module's own top-level code
3
- // destructures `globalThis.pdfjsLib` (Mozilla's own viewer bootstrap sets this global before
4
- // loading it as a second <script>; a pure-ESM consumer has no such bootstrap). Importing
5
- // pdf_viewer.mjs without this throws at *module load*, not at use — "Cannot destructure property
6
- // 'AbortException' of 'globalThis.pdfjsLib' as it is undefined."
7
- //
8
- // Import this module (for its side effect only, before any "pdfjs-dist/web/pdf_viewer.mjs"
9
- // import) to wire that global. ES module evaluation is depth-first in source order, so as long as
10
- // this import line comes first, the global is set before pdf_viewer.mjs's body runs.
11
- import * as pdfjs from "pdfjs-dist";
12
- globalThis.pdfjsLib = pdfjs;
@@ -1,18 +0,0 @@
1
- /** Page thumbnails panel toggle. */
2
- export declare const IconThumbnails: () => import("react").JSX.Element;
3
- /** Outline (bookmarks) panel toggle. */
4
- export declare const IconOutline: () => import("react").JSX.Element;
5
- /** Fit to width. */
6
- export declare const IconFitWidth: () => import("react").JSX.Element;
7
- /** Fit full page. */
8
- export declare const IconFitPage: () => import("react").JSX.Element;
9
- /** Toggle existing-text edit mode (edits source text runs, not overlaid annotations). */
10
- export declare const IconEditText: () => import("react").JSX.Element;
11
- /** Add-text annotation tool. */
12
- export declare const IconAnnotateText: () => import("react").JSX.Element;
13
- /** Ink/draw annotation tool. */
14
- export declare const IconDraw: () => import("react").JSX.Element;
15
- /** Highlight annotation tool. */
16
- export declare const IconHighlight: () => import("react").JSX.Element;
17
- /** Image stamp annotation tool. */
18
- export declare const IconImage: () => import("react").JSX.Element;
@@ -1,31 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- // PDF toolbar icons — Phosphor, matching the existing zoom/rotate icons in PdfToolbar.tsx
3
- // (14px, regular weight, aria-hidden — the accessible name lives on the wrapping button's
4
- // aria-label/title) and the DOCX toolbar's icon-based convention (src/documents/docx/toolbarIcons.tsx).
5
- import { SquaresFour } from "@phosphor-icons/react/dist/icons/SquaresFour";
6
- import { TreeStructure } from "@phosphor-icons/react/dist/icons/TreeStructure";
7
- import { ArrowsOutLineHorizontal } from "@phosphor-icons/react/dist/icons/ArrowsOutLineHorizontal";
8
- import { CornersOut } from "@phosphor-icons/react/dist/icons/CornersOut";
9
- import { TextT } from "@phosphor-icons/react/dist/icons/TextT";
10
- import { TextAa } from "@phosphor-icons/react/dist/icons/TextAa";
11
- import { Scribble } from "@phosphor-icons/react/dist/icons/Scribble";
12
- import { Highlighter } from "@phosphor-icons/react/dist/icons/Highlighter";
13
- import { ImageSquare } from "@phosphor-icons/react/dist/icons/ImageSquare";
14
- /** Page thumbnails panel toggle. */
15
- export const IconThumbnails = () => _jsx(SquaresFour, { size: 14, weight: "regular", "aria-hidden": true });
16
- /** Outline (bookmarks) panel toggle. */
17
- export const IconOutline = () => _jsx(TreeStructure, { size: 14, weight: "regular", "aria-hidden": true });
18
- /** Fit to width. */
19
- export const IconFitWidth = () => (_jsx(ArrowsOutLineHorizontal, { size: 14, weight: "regular", "aria-hidden": true }));
20
- /** Fit full page. */
21
- export const IconFitPage = () => _jsx(CornersOut, { size: 14, weight: "regular", "aria-hidden": true });
22
- /** Toggle existing-text edit mode (edits source text runs, not overlaid annotations). */
23
- export const IconEditText = () => _jsx(TextT, { size: 14, weight: "regular", "aria-hidden": true });
24
- /** Add-text annotation tool. */
25
- export const IconAnnotateText = () => _jsx(TextAa, { size: 14, weight: "regular", "aria-hidden": true });
26
- /** Ink/draw annotation tool. */
27
- export const IconDraw = () => _jsx(Scribble, { size: 14, weight: "regular", "aria-hidden": true });
28
- /** Highlight annotation tool. */
29
- export const IconHighlight = () => _jsx(Highlighter, { size: 14, weight: "regular", "aria-hidden": true });
30
- /** Image stamp annotation tool. */
31
- export const IconImage = () => _jsx(ImageSquare, { size: 14, weight: "regular", "aria-hidden": true });
@@ -1,40 +0,0 @@
1
- import { type Dispatch, type MutableRefObject, type SetStateAction } from "react";
2
- import * as pdfjs from "pdfjs-dist";
3
- import type { PDFDocumentProxy } from "pdfjs-dist";
4
- import type { ViewMeta } from "../types.js";
5
- import type { OutlineNode, Size } from "./pdfShared.js";
6
- /** Benchmark-only password injection; production & manual unlocks always use the prompt. */
7
- export declare function getPdfBenchPassword(): string | null;
8
- interface UsePdfDocumentLoaderArgs {
9
- documentPath: string;
10
- url?: string;
11
- initialView?: ViewMeta;
12
- pdfRef: MutableRefObject<PDFDocumentProxy | null>;
13
- renderedRef: MutableRefObject<Map<number, () => void>>;
14
- slotRefs: MutableRefObject<Map<number, HTMLDivElement>>;
15
- visibleRef: MutableRefObject<Set<number>>;
16
- restoredRef: MutableRefObject<boolean>;
17
- reportReadyRef: MutableRefObject<boolean>;
18
- setCurrent: Dispatch<SetStateAction<number>>;
19
- setScale: Dispatch<SetStateAction<number>>;
20
- setRotation: Dispatch<SetStateAction<number>>;
21
- setFitMode: Dispatch<SetStateAction<"width" | "page" | null>>;
22
- }
23
- export declare function usePdfDocumentLoader({ documentPath, url, initialView, pdfRef, renderedRef, slotRefs, visibleRef, restoredRef, reportReadyRef, setCurrent, setScale, setRotation, setFitMode, }: UsePdfDocumentLoaderArgs): {
24
- pdfDoc: import("pdfjs-dist/types/src/display/api.js").PDFDocumentProxy | null;
25
- numPages: number;
26
- base: Size | null;
27
- pageSizes: Map<number, Size>;
28
- setPageSizes: Dispatch<SetStateAction<Map<number, Size>>>;
29
- error: string | null;
30
- renderErrors: Map<number, string>;
31
- setRenderErrors: Dispatch<SetStateAction<Map<number, string>>>;
32
- pwPrompt: {
33
- retry: boolean;
34
- onSubmit: (pw: string) => void;
35
- onCancel: () => void;
36
- } | null;
37
- outline: OutlineNode[] | null;
38
- replaceDocument: (doc: PDFDocumentProxy, task: ReturnType<typeof pdfjs.getDocument>) => void;
39
- };
40
- export {};