Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Supported in all [major browsers](https://caniuse.com/custom-elementsv1), and wo

## Features

- Standalone web component with no runtime dependencies
- Standalone isolated web component with no runtime dependencies
- Drop-in, iframe-based PDF.js default viewer for any web app
- Works with same-origin and cross-origin PDF documents
- Configure via attributes and URL parameters (page, zoom, search, pagemode, locale)
Expand Down Expand Up @@ -86,8 +86,9 @@ The element is block-level and needs an explicit height.
| `zoom` | Zoom level (for example `auto`, `page-width`, `200%`). | `''` |
| `pagemode` | Sidebar mode: `thumbs`, `bookmarks`, `attachments`, `layers`, `none`. | `none` |
| `locale` | Viewer UI locale (for example `en-US`, `de`, `uk`). [Available locales](https://github.com/mozilla/pdf.js/tree/master/l10n) | `''` |
| `locale-src-template` | Locale file URL template. Must contain `{locale}` placeholder. Used together with `locale`. | `https://cdn.jsdelivr.net/gh/mozilla-l10n/firefox-l10n@main/{locale}/toolkit/toolkit/pdfviewer/viewer.ftl` |
| `viewer-css-theme` | Viewer theme: `AUTOMATIC`, `LIGHT`, `DARK`. | `AUTOMATIC` |
| `worker-src` | PDF.js worker URL override. | `https://cdn.jsdelivr.net/npm/pdfjs-dist@5.4.624/build/pdf.worker.min.mjs` |
| `worker-src` | PDF.js worker URL override. | `<package-url>/pdf.worker.min.mjs` |

Play with attributes on [API docs page](https://alekswebnet.github.io/pdfjs-viewer-element/#api).

Expand All @@ -101,6 +102,41 @@ Most attributes can be updated dynamically:
- `worker-src` updates viewer options for subsequent document loads.
- `locale` rebuilds the viewer so localization resources can be applied.

## Worker source

By default, the component resolves `worker-src` to the worker shipped with this package (`pdf.worker.min.mjs` in `dist`).

Set `worker-src` only if you want to serve the worker from a custom location (for example your own CDN or static assets path).

- The URL must point to a valid PDF.js module worker file.
- The worker version should match the bundled PDF.js version.

```html
<pdfjs-viewer-element
src="/file.pdf"
worker-src="https://cdn.jsdelivr.net/npm/pdfjs-dist@5.5.207/build/pdf.worker.min.mjs">
</pdfjs-viewer-element>
```

## Locale source template

Use `locale-src-template` when you need to load localization files from a custom host.

- The template must include `{locale}`.
- `{locale}` is replaced by the `locale` attribute value (for example `de`, `uk`, `en-US`).
- If `locale` is not set, no locale file is loaded.
- Changes to `locale-src-template` are applied when the viewer is (re)initialized, for example after setting/changing `locale`.

Example:

```html
<pdfjs-viewer-element
src="/file.pdf"
locale="de"
locale-src-template="https://cdn.example.com/pdfjs-locales/{locale}/viewer.ftl">
</pdfjs-viewer-element>
```

## Viewer CSS theme

Use `viewer-css-theme` attribute to set light or dark theme manually:
Expand Down Expand Up @@ -213,7 +249,7 @@ You can also react to source changes dynamically:

```javascript
const viewerElement = document.querySelector('pdfjs-viewer-element')
viewer.setAttribute('src', '/another-file.pdf')
viewerElement.setAttribute('src', '/another-file.pdf')
```

## Accessibility
Expand Down
23 changes: 23 additions & 0 deletions demo/custom-worker-src.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>pdfjs-viewer-element | Custom Worker Src Demo</title>
<script type="module" src="../dist/pdfjs-viewer-element.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>

<body>
<pdfjs-viewer-element
src="/public/sample-pdf-with-images.pdf"
worker-src="https://cdn.jsdelivr.net/npm/pdfjs-dist@v5.5.207/build/pdf.worker.min.mjs"
style="height: 100dvh">
</pdfjs-viewer-element>
</body>
</html>
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pdfjs-viewer-element",
"version": "3.1.1",
"version": "3.1.2",
"license": "MIT",
"author": {
"name": "Oleksandr Shevchuk",
Expand Down Expand Up @@ -37,7 +37,7 @@
],
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build": "tsc && vite build && node scripts/copy-worker.mjs",
"test": "vitest",
"coverage": "vitest run --coverage"
},
Expand All @@ -47,6 +47,7 @@
"@vitest/browser": "^4.0.18",
"@vitest/browser-webdriverio": "^4.0.18",
"jsdom": "^28.1.0",
"terser": "^5.39.0",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vitest": "^4.0.18",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions scripts/copy-worker.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { resolve } from 'node:path'
import { minify } from 'terser'

const rootDir = resolve(import.meta.dirname, '..')
const sourceFile = resolve(rootDir, 'src', 'build', 'pdf.worker.mjs')
const distDir = resolve(rootDir, 'dist')
const targetFile = resolve(distDir, 'pdf.worker.min.mjs')

await mkdir(distDir, { recursive: true })

const workerCode = await readFile(sourceFile, 'utf8')
const result = await minify(workerCode, {
module: true,
compress: true,
mangle: true,
format: {
comments: false
}
})

if (!result.code) {
throw new Error('Worker minification failed: empty output')
}

await writeFile(targetFile, result.code, 'utf8')
20 changes: 17 additions & 3 deletions src/pdfjs-viewer-element.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const PDFJS_VERSION = '5.5.207'
const DEFAULT_WORKER_SRC = import.meta.env.DEV
? new URL('./build/pdf.worker.mjs', import.meta.url).href
: new URL('./pdf.worker.min.mjs', import.meta.url).href

const DEFAULTS = {
src: '',
Expand All @@ -10,7 +12,8 @@ const DEFAULTS = {
pagemode: 'none',
locale: '',
viewerCssTheme: 'AUTOMATIC',
workerSrc: `https://cdn.jsdelivr.net/npm/pdfjs-dist@${PDFJS_VERSION}/build/pdf.worker.min.mjs`
workerSrc: DEFAULT_WORKER_SRC,
localeSrcTemplate: 'https://cdn.jsdelivr.net/gh/mozilla-l10n/firefox-l10n@main/{locale}/toolkit/toolkit/pdfviewer/viewer.ftl'
} as const

export const ViewerCssTheme = { AUTOMATIC: 0, LIGHT: 1, DARK: 2 } as const
Expand Down Expand Up @@ -38,6 +41,13 @@ export class PdfjsViewerElement extends HTMLElement {
]
}

private formatTemplate(template: string, params: Record<string, any>) {
return template.replace(/\{(\w+)\}/g, (_, key) => {
if (!(key in params)) throw new Error(`Missing param: ${key}`);
return String(params[key]);
});
}

private getFullPath(path: string) {
return path.startsWith('/') ? `${window.location.origin}${path}` : path
}
Expand Down Expand Up @@ -120,8 +130,12 @@ export class PdfjsViewerElement extends HTMLElement {
this.cleanupLocaleResource()
return
}
const localeUrl = this.formatTemplate(
this.getAttribute('locale-src-template') || DEFAULTS.localeSrcTemplate,
{ locale }
)
const localeObject = {
[String(locale)]: `https://raw.githubusercontent.com/mozilla-l10n/firefox-l10n/main/${locale}/toolkit/toolkit/pdfviewer/viewer.ftl`
[String(locale)]: localeUrl
}
const localeLink = doc.createElement('link')
localeLink.rel = 'resource'
Expand Down
1 change: 1 addition & 0 deletions types/pdfjs-viewer-element.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export declare class PdfjsViewerElement extends HTMLElement {
private localeResourceLink?;
private viewerStyles;
static get observedAttributes(): string[];
private formatTemplate;
private getFullPath;
private getCssThemeOption;
private applyIframeHash;
Expand Down
1 change: 0 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export default defineConfig({
output: {
plugins: [
terser({
'sourceMap': false,
compress: true,
mangle: false,
format: { comments: false }
Expand Down