Skip to content
PDF-magicPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

PDF Viewer

A Chrome Manifest V3 extension that replaces the normal PDF tab with a local PDF.js viewer and makes the current page shareable.

Features

  • On Chrome 151+, registers as the PDF MIME handler so the original https://…pdf URL stays in the address bar while the extension renders the document.
  • Uses Chrome's already-received PDF stream instead of re-requesting the document URL.
  • Uses the ✨ sparkle favicon for local file:// PDFs, while leaving the Luna favicon on web PDFs.
  • Displays a PDF's embedded Title metadata in the browser tab (PDF Info first, then XMP dc:title), falling back to its filename when no title is available.
  • Falls back to the older extension-page redirect flow on Chrome versions that do not expose the MIME handler API.
  • Renders PDFs locally with bundled PDF.js assets; no remotely hosted executable code is used.
  • Supports dark and light viewing modes, remembers the selected theme, and shows Celestia in dark mode and Luna in light mode.
  • Tracks the page currently centered in the viewport.
  • Copies the original document URL as #page=<current page> silently when the mark is clicked.
  • Honors an existing #page=N fragment when opening a document.
  • Places Download beside the page-link icon and keeps rotate left/right and print in the More tools menu.
  • Keeps the More tools menu open across repeated rotate actions.
  • Offers a default-on More PDF tools → Join tagged paragraph lines on copy setting. This uses PDF.js's exposed structure-tree paragraph tags and MCIDs to join soft printed line breaks and respect tagged block reading order in the clipboard; turning it off restores the original line breaks. Plain text copy works without enabling Markdown. PDFs lacking reliable tags retain their native copy behavior. Note: PDF.js does not currently expose /ActualText values stored only in content-stream BDC properties, so this reflows tagged text rather than reading that replacement string verbatim.
  • Offers an opt-in More PDF tools → Copy selection as Markdown setting. When enabled, normal Copy on selected PDF text writes Markdown to the clipboard: detected italics use _underscores_, bold uses **asterisks**, and line/page boundaries are retained. The preference persists across PDFs; copying outside PDF text stays unchanged. Font identification is best-effort (not all PDFs disclose readable font metadata), and image-only scans need OCR text before they can be copied.
  • Prepares compressed previews of every page in the background for fast scrolling, while keeping sharp rendering and selectable text near the current page.
  • Shows a PDF Enhancer button in the top-left section slot when a document has no section navigator; enhanced local copies retain the original web reference URL for link copying and ChatGPT summaries.

Load directly in Chrome

Install dependencies once:

npm install

Then:

  1. Open chrome://extensions.
  2. Enable Developer mode.
  3. Click Load unpacked.
  4. Select the repository root — the folder containing manifest.json.

The root manifest points directly at the source files and local node_modules, so a separate build step is not required for normal local development.

PDF enhancer integration

The viewer can hand the current PDF to the local PDF-magic/enhancer workflow: https://github.com/PDF-magic/enhancer. The enhancer button occupies the top-left section-control slot only when the PDF has no section navigator.

Chrome and Brave cannot run Git or install native-messaging hosts by themselves. If Enhance cannot find the native host, the viewer opens a setup dialog instead of copying a terminal command.

Enter the GitHub URL of an existing enhancer fork, or keep https://github.com/PDF-magic/enhancer for upstream. Optionally enter a local checkout folder. Click Clone · Download installer to download a ZIP with a user-runnable setup script. On macOS, extract it and open Install PDF Magic.command (review the script before running). On Linux, extract it and run bash "Install PDF Magic.sh" locally. The user must explicitly run the installer; the extension never executes local shell commands silently or claims a download is an installation.

The installer clones the selected GitHub repository (or reuses a matching checkout in the selected folder), then registers the native messaging helper for the current Chrome/Brave extension ID. If you already have a local checkout, provide its folder in the dialog. Changing an existing managed checkout to a different remote requires choosing a new checkout folder: setup will not silently bind to an unrelated Git remote.

You can also run the installer manually:

./native/install-host.sh CHROME_EXTENSION_ID --repo https://github.com/YOUR-ACCOUNT/enhancer.git --directory "/absolute/path/to/enhancer"

To automatically create or reuse a personal fork using an authenticated GitHub CLI session, run:

./native/install-host.sh CHROME_EXTENSION_ID --fork-if-available

The installer first reuses a sibling ../enhancer checkout when one exists. Otherwise it creates a managed checkout under ~/Library/Application Support/PDF Magic/Enhancer on macOS or ~/.local/share/pdf-magic/enhancer on Linux. It registers the native bridge under ~/.config/pdf-magic/native for both Chrome and Brave. When setup runs from a viewer checkout, this stable launcher loads that checkout's current helper on every enhancement, so helper updates take effect automatically on the next request without reinstalling or reloading the extension. Running jobs finish with the version they started with. If the checkout is moved or unavailable, the launcher uses its installed fallback; rerun setup from the new location to relink it. Download-only setup installs a standalone copy and must be rerun to update it.

After setup completes, click Enhance again. The host locates Homebrew tools even when the browser is launched from Finder and keeps OCR logs separate from native-messaging responses.

For web PDFs, the viewer sends the already-loaded document to the host in acknowledged chunks. Enhancement does not make another HTTP download, so it can use PDFs that the browser loaded from sites that reject standalone requests. Local PDFs are read directly from disk. Both enhancement modes use --force-ocr --ai-review to re-read every page and review recognized text against page images with the local AI models, including when the PDF already contains text. This rasterizes pages in the enhanced copy and takes longer than preserving existing text. The source remains unchanged. The tagger builds heading structure and section bookmarks from the reviewed text. Cached results from the previous pipeline are regenerated on the next enhancement.

Enhanced web copies are saved under ~/Library/Application Support/PDF Magic/Enhanced on macOS or ~/.local/share/pdf-magic/enhanced on Linux. This lets browser-launched helpers finish tagging without needing to replace files in the protected Downloads folder. Enhanced local copies are saved beside their source PDF.

Enhancement requests are deduplicated by the PDF's SHA-256 content hash, including requests from separate tabs and different URLs or filenames. Duplicate requests share the running job's progress and result. Completed results are reused only while their output hash still matches; submitting an unchanged enhanced PDF also reuses that result. Changed or missing outputs are regenerated, and failed or interrupted jobs can be retried. Job records are stored in .jobs under the enhanced web-copy directory. Jobs already started by an older native host continue independently.

Different PDFs are queued behind one shared enhancement slot before the OCR pipeline starts. This keeps separate browser tabs from launching multiple memory-intensive OCR or local-model workloads at the same time, while duplicate requests for the same PDF still follow the existing shared job. A waiting tab reports that its enhancement is queued and begins automatically when the active enhancement releases the slot.

The host runs ocr-scanned-pdf.sh, uses the OCR tagging report to name the new local *-enhanced-ocr.pdf copy from the document's recognized title when a credible title is available, and falls back to the source URL filename otherwise. It also stamps the original reference URL into the PDF's XMP metadata as a pdfmagic:href tag. The current tab is replaced with the enhanced local copy. Copy File URL, Copy Page Link, and Summarize with ChatGPT then use the preserved reference URL instead of the local file:// path. Older enhanced copies with PDFMagicSourceURL document-info metadata remain supported.

Recognized H1–H6 headings are also written as nested PDF bookmarks with page destinations. The enhanced copy shows the § section navigator in place of Enhance when it contains these sections.

Enhanced copies use a detected signature or large letterhead name for Creator and Author. When no name is recognized, the enhancer uses existing author metadata, then the local account's full name or username. Producer is PDF Magic Enhancer. The metadata panel's Href link points to the preserved original document URL. Name detection uses searchable text and remains heuristic.

Enable Allow access to file URLs for the unpacked extension in Chrome or Brave so the enhanced local PDF reopens in this viewer.

Build a standalone extension folder

npm run build

The standalone unpacked extension is written to dist/. You can also select dist/ with Load unpacked if you want the packaged build instead of the source tree.

Source layout

  • src/background.js: extension background worker.
  • src/viewer.html: viewer entry point; src/loading-preview.html: loading-state preview.
  • src/viewer/: PDF rendering, settings, networking, and viewer styles.
  • src/viewer/navigation/, search/, selection/, sharing/, and theme/: viewer features with their scripts and styles together.
  • src/content/: scripts injected into SEC and ChatGPT pages.
  • src/assets/: shared images and icons.

The build preserves the source directory structure in dist/, bundles the viewer and QR modules, and adds the PDF.js runtime assets.

Usage

Open a PDF normally. On Chrome 151+, the extension renders the intercepted PDF stream in place while Chrome keeps the original document URL visible in the address bar. Scroll to a page and click the page-link icon to copy a link such as:

https://example.com/document.pdf#page=42

On older Chrome versions, the extension retains the previous chrome-extension://…?url=… redirect as a compatibility fallback.

The toolbar also supports previous/next page navigation, direct page entry, theme switching, page-link copying, download, and a compact More tools menu for rotate and print.

The normal page-number field uses physical PDF pages (e.g. 181). Append an asterisk to jump to a printed page number instead (e.g. 181*), using embedded page labels or verified numbers in page margins. This shortcut works without enabling any extra controls. To display a separate Printed № search field, opt in with More PDF tools → Show printed-page search. The extra field is off by default and the preference persists across documents. Unknown printed labels are reported rather than silently treated as physical pages.

Page previews load progressively without delaying the first readable pages. The viewer keeps compressed WebP previews rather than full-size canvases for distant pages, and attaches previews only within eight pages of the current page. Preview resolution adapts to the document's page count to help the complete set fit in memory. Sharp canvases, text selection, and links render within three pages after scrolling settles. The compressed preview cache has a 128 MiB limit; documents that exceed it retain recently used previews and regenerate missing ones as needed. Printing still prepares sharp versions of all pages.

ChatGPT PDF attachment handoff

Clicking Summarize with ChatGPT now passes the already-loaded PDF bytes as an attachment, including for local file:// and authenticated PDFs. The service worker relays acknowledged chunks in memory; it does not save PDF bytes to extension storage. ChatGPT's upload UI can change: if the attachment is not confirmed, the extension leaves an unsent draft asking for manual attachment rather than submitting a URL-only summary. Full local filesystem paths are not copied into the prompt.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages