Skip to content

Commit

Permalink
Merge pull request #3 from Jaewoook/embed-wasm
Browse files Browse the repository at this point in the history
Embed wasm binary in single js file
  • Loading branch information
Jaewoook authored Jan 19, 2024
2 parents 668a378 + a13343f commit c1356e8
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 138 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PDFium.js Changelog

## v0.2.0 (2024-01-19)

- Upgrade pdfium WebAssembly binary version to 6183
- Embed wasm binary in loader file
- Fix library to work in Next.js (client component required)
- Remove `wasmPath` parameter from library options
- Update FPDF property `asm` to `wasmExports` ([check emscripten changelog](https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md#3144---072523))
- Update rollup build configuration
- Remove unused dependency

## v0.1.0 (2023-07-13)

- Initial version of PDFium.js
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,15 @@ yarn add pdfium.js
npm install --save pdfium.js
```

### WebAssembly Preparation

> [!IMPORTANT]
> This step is required to use this library. Make sure to copy the bundled `pdfium.wasm` file to your static assets directory before using it.
```bash
cp ./node_modules/pdfium.js/dist/pdfium.wasm <YOUR_STATIC_ASSETS_DIRECTORY>
```

or you can manually download the pdfium.wasm file [here](https://github.com/Jaewoook/pdfium.js/raw/main/src/libs/pdfium.wasm).

## Usage

> [!NOTE]
> When you call `PDFium()`, this library will load and instantiate PDFium binary in browser environment. If your project is using SSR, such as Next.js, it should not be loaded in server-side environment. `"use client";` directive might be required.
```ts
import { PDFium } from "pdfium.js";

PDFium({ wasmPath: "/" }).then((PDFiumModule) => {
PDFium().then((PDFiumModule) => {
// library initialization
PDFiumModule._FPDF_InitLibrary();

Expand All @@ -74,10 +66,10 @@ PDFium().then((PDFiumModule) => {
const bytes = 1024;

// allocate 1024 bytes in memory
const memoryAddress = PDFiumModule.asm.malloc(bytes);
const memoryAddress = PDFiumModule.wasmExports.malloc(bytes);

// free memory
PDFiumModule.asm.free(memoryAddress);
PDFiumModule.wasmExports.free(memoryAddress);
});
```

Expand All @@ -88,6 +80,7 @@ This library doesn't provide full PDFium API yet. Check full version of defined
You can also find original API specification [here](https://pdfium.googlesource.com/pdfium/+/main/public/).

### Supported API List

- _FPDF_InitLibrary
- _FPDF_InitLibraryWithConfig
- _FPDF_DestroyLibrary
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pdfium.js",
"version": "0.1.0-rc.1",
"version": "0.2.0-rc.1",
"description": "A PDFium wrapper library for browser-side JavaScript",
"main": "./dist/cjs/index.js",
"types": "./dist/esm/index.d.ts",
Expand Down Expand Up @@ -31,7 +31,7 @@
"webassembly"
],
"author": {
"name" :"Jaewook Ahn",
"name": "Jaewook Ahn",
"email": "[email protected]",
"url": "https://jaewook.me"
},
Expand All @@ -40,7 +40,8 @@
"type-check": "tsc",
"build": "rimraf dist && rollup -c",
"lint": "eslint . --ext ts,js",
"commitlint": "commitlint --edit"
"commitlint": "commitlint --edit",
"prepare": "husky install"
},
"devDependencies": {
"@commitlint/cli": "^17.6.6",
Expand All @@ -56,7 +57,6 @@
"prettier": "2.8.8",
"rimraf": "^5.0.1",
"rollup": "^3.26.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-dts": "^5.3.0",
"rollup-plugin-esbuild": "^5.0.0",
"typescript": "^5.1.6"
Expand Down
2 changes: 1 addition & 1 deletion pdfium-version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"pdfium": "5782"
"pdfium": "6183"
}
5 changes: 1 addition & 4 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// @ts-check
import copy from "rollup-plugin-copy";
import dts from "rollup-plugin-dts";
import esbuild from "rollup-plugin-esbuild";
import packageJson from "./package.json" assert { type: "json" };

const wasmPath = "src/libs/pdfium.wasm";
const entryFile = "src/index.ts";
const distDir = "dist";

/** @type {import("rollup").RollupOptions[]} */
const config = [
Expand All @@ -23,7 +20,7 @@ const config = [
format: "es",
},
],
plugins: [esbuild(), copy({ targets: [{ src: wasmPath, dest: distDir }] })],
plugins: [esbuild()],
},
{
input: entryFile,
Expand Down
2 changes: 1 addition & 1 deletion src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface FPDF extends ModuleOptions {
HEAPU32: Uint32Array;
HEAPF32: Float32Array;
HEAPF64: Float64Array;
asm: {
wasmExports: {
[key: string]: any;
malloc: (size: number) => number;
free: (address: number) => number;
Expand Down
36 changes: 14 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import PDFiumModule from "./libs/pdfium";
import createPDFiumModule from "./libs/pdfium";
import type { FPDF } from "./global";

window.PDFiumModule = PDFiumModule;

/**
* Emscripten module options type definition
*/
interface ModuleOptions {
[key: string]: unknown;
printErr: (message: string) => void;
onAbort: () => void;
locateFile: (path: string, prefix: string) => string;
}

interface LibraryInitOptions {
wasmPath?: string;
interface LibraryOptions {
onError?: () => void;
debug?: boolean;
}

const generateModuleWithOptions = (options: LibraryInitOptions): ModuleOptions => {
const generateModule = (options: LibraryOptions): ModuleOptions => {
return {
printErr: (err: string) => {
console.error("[PDFium Error]", err);
Expand All @@ -28,29 +24,25 @@ const generateModuleWithOptions = (options: LibraryInitOptions): ModuleOptions =
console.error("Failed to load PDFium module.");
options.onError?.();
},
locateFile: (path, prefix) => {
return options.wasmPath + prefix + path;
},
};
};

/**
* Initialize PDFium with options.
* Create PDFium wasm module with options.
*
* `wasmPath` is required to load `.wasm` file as static asset.
* `onWasmLoaded` is optional callback function that called when wasm load finished.
* @param options library initialize options
* @param options module creation options
*/
const initPDFium = (options: LibraryInitOptions) => {
const { onError, wasmPath = "/", debug = false } = options;
const createPDFium = (options: LibraryOptions) => {
const { onError, debug = false } = options;

return new Promise<FPDF>((resolve, reject) => {
if (debug) {
console.log("[PDFium debug] initPDFium", options);
console.log("[PDFium debug] createPDFium", options);
}

const Module = generateModuleWithOptions({ onError, wasmPath, debug });
const Module = generateModule({ onError, debug });

PDFiumModule(Module)
createPDFiumModule(Module)
.then((FPDFModule) => {
// register PDFium module to window
window.FPDF = FPDFModule;
Expand All @@ -60,14 +52,14 @@ const initPDFium = (options: LibraryInitOptions) => {
});
};

const PDFium = (options: LibraryInitOptions = {}) => {
const PDFium = (options: LibraryOptions = {}) => {
if (window.FPDF) {
return Promise.resolve(window.FPDF);
}

return initPDFium(options);
return createPDFium(options);
};

export * from "./constants";
export { initPDFium, PDFium };
export { createPDFium, FPDF, PDFium };
export default PDFium;
4 changes: 2 additions & 2 deletions src/libs/pdfium.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
declare var PDFiumModule: (Module?: object) => Promise<FPDF>;
declare var createPDFiumModule: (Module?: object) => Promise<FPDF>;

export default PDFiumModule;
export default createPDFiumModule;
19 changes: 8 additions & 11 deletions src/libs/pdfium.js

Large diffs are not rendered by default.

Binary file removed src/libs/pdfium.wasm
Binary file not shown.
82 changes: 3 additions & 79 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -447,31 +447,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==

"@types/fs-extra@^8.0.1":
version "8.1.2"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f"
integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==
dependencies:
"@types/node" "*"

"@types/glob@^7.1.1":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
dependencies:
"@types/minimatch" "*"
"@types/node" "*"

"@types/json-schema@^7.0.9":
version "7.0.12"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==

"@types/minimatch@*":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==

"@types/minimist@^1.2.0":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
Expand Down Expand Up @@ -769,11 +749,6 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==

colorette@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==

compare-func@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
Expand Down Expand Up @@ -1117,7 +1092,7 @@ fast-diff@^1.1.2:
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==

fast-glob@^3.0.3, fast-glob@^3.2.9:
fast-glob@^3.2.9:
version "3.3.0"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0"
integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==
Expand Down Expand Up @@ -1205,15 +1180,6 @@ fs-extra@^11.0.0:
jsonfile "^6.0.1"
universalify "^2.0.0"

fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"

fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
Expand Down Expand Up @@ -1301,20 +1267,6 @@ globals@^13.19.0:
dependencies:
type-fest "^0.20.2"

[email protected]:
version "10.0.1"
resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22"
integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==
dependencies:
"@types/glob" "^7.1.1"
array-union "^2.1.0"
dir-glob "^3.0.1"
fast-glob "^3.0.3"
glob "^7.1.3"
ignore "^5.1.1"
merge2 "^1.2.3"
slash "^3.0.0"

globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
Expand Down Expand Up @@ -1381,7 +1333,7 @@ husky@^8.0.3:
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==

ignore@^5.1.1, ignore@^5.2.0:
ignore@^5.2.0:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
Expand Down Expand Up @@ -1471,11 +1423,6 @@ is-plain-obj@^1.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==

is-plain-object@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b"
integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==

is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
Expand Down Expand Up @@ -1544,13 +1491,6 @@ jsonc-parser@^3.2.0:
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==

jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
optionalDependencies:
graceful-fs "^4.1.6"

jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
Expand Down Expand Up @@ -1708,7 +1648,7 @@ merge-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==

merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1:
merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
Expand Down Expand Up @@ -2048,17 +1988,6 @@ rimraf@^5.0.1:
dependencies:
glob "^10.2.5"

rollup-plugin-copy@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz#f1228a3ffb66ffad8606e2f3fb7ff23141ed3286"
integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==
dependencies:
"@types/fs-extra" "^8.0.1"
colorette "^1.1.0"
fs-extra "^8.1.0"
globby "10.0.1"
is-plain-object "^3.0.0"

rollup-plugin-dts@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.0.tgz#80a95988002f188e376f6db3b7e2f53679168957"
Expand Down Expand Up @@ -2349,11 +2278,6 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==

universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==

universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
Expand Down

0 comments on commit c1356e8

Please sign in to comment.