Skip to content

Commit

Permalink
Merge pull request #5 from Jaewoook/docs/api-usage
Browse files Browse the repository at this point in the history
Add example project implementation
  • Loading branch information
Jaewoook authored Dec 22, 2024
2 parents b592593 + 5e6d0c5 commit b95ff0f
Show file tree
Hide file tree
Showing 17 changed files with 1,519 additions and 878 deletions.
6 changes: 5 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ module.exports = {
es2021: true,
node: true,
},
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
],
overrides: [
{
env: {
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "CI"
name: "PDFium.js:CI"

on:
push:
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/ci_example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: "Example:CI"

on:
push:
pull_request:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache-dependency-path: "example/yarn.lock"
node-version-file: ".tool-versions"
- run: cd example
- run: yarn install --frozen-lockfile
- run: yarn build
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache-dependency-path: "example/yarn.lock"
node-version-file: ".tool-versions"
- run: cd example
- run: yarn install --frozen-lockfile
- run: yarn lint
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"printWidth": 120,
"printWidth": 100,
"singleQuote": false,
"trailingComma": "es5",
"semi": true
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodejs 18.15.0
nodejs 20.17.0
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ yarn add pdfium.js
npm install --save pdfium.js
```

## Example project

Check out this example project. The implemantion of renderer may helpful to achieve what you do.

![example project](./images/example_project.png)

## Usage

> [!NOTE]
Expand All @@ -48,7 +54,7 @@ PDFium().then((PDFiumModule) => {
// memory allocation
const byteArray: Uint8Array = <FILE BINARY DATA>;
const fileSize = byteArray.length;
const binaryAddress = PDFiumModule.asm.malloc(fileSize);
const binaryAddress = PDFiumModule.wasmExports.malloc(fileSize);
PDFiumModule.HEAPU8.set(byteArray, binaryAddress);

// document loading
Expand Down
14 changes: 14 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# PDFium.js Example Project

This is an example project that utilizes `PDFium.js`. This project is built using Vite.
By defaukt, this project downloads and installs the latest `PDFium.js` from npm,
but you can change the version if you need.

## How to run

You can simply run the following commands to run this project.

```sh
yarn install
yarn dev
```
15 changes: 8 additions & 7 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,22 @@
"preview": "vite preview"
},
"dependencies": {
"pdfium.js": "^0.1.0-rc.1",
"axios": "^1.7.7",
"pdfium.js": "^0.2.1-rc.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-toastify": "^10.0.5"
},
"devDependencies": {
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@typescript-eslint/eslint-plugin": "^8.6.0",
"@typescript-eslint/parser": "^8.6.0",
"@vitejs/plugin-react": "^4.0.1",
"eslint": "^8.44.0",
"eslint": "^9.11.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.1",
"rollup": "^3.26.2",
"typescript": "^5.0.2",
"vite": "^4.4.0"
"vite": "^5.4.7"
}
}
Binary file added example/public/PDF32000_2008.pdf
Binary file not shown.
Binary file removed example/public/pdfium.wasm
Binary file not shown.
51 changes: 47 additions & 4 deletions example/src/App.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,49 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
width: 100vw;
margin: 0;
padding: 0;
}

header {
width: 100%;
display: flex;
padding: 1.25em 0.5em;
}

p {
margin: 0;
}

header > h1 {
font-size: 2em;
margin: 0;
}

#content {
display: flex;
}

aside {
padding: 1em 0.5em;
}

asdie button {
margin: 0.5em;
}

main {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
}

div.api-container {
display: flex;
flex-direction: column;
margin-top: 0.75em;
}

canvas {
background: #e0e0e0;
}
127 changes: 109 additions & 18 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,125 @@
import { useEffect } from "react";
import axios from "axios";
import { useCallback, useRef, useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import { PDFium } from "pdfium.js";
import { PDFRenderer } from "./pdf-renderer";

import "react-toastify/ReactToastify.min.css";
import "./App.css";

const App = () => {
const [isReady, setReady] = useState(false);
const [initialized, setInitialized] = useState(false);
const [documentLoaded, setDocumentLoaded] = useState(false);
const [targetPageIndex, setTargetPageIndex] = useState(0);
const [totalPageCount, setTotalPageCount] = useState(0);

const pdfRenderSurfaceRef = useRef<HTMLCanvasElement>(null);
const pdfRenderer = useRef<PDFRenderer>();

const handlePDFiumError = () => {
toast("[PDFium Native] An error occurred!", { type: "error", autoClose: false });
console.log("[PDFium] An error occurred!");
};

useEffect(() => {
PDFium({ wasmPath: "/", onError: handlePDFiumError })
.then((PDFiumModule) => {
console.log("PDFium WebAssembly loaded", PDFiumModule);
})
.catch((err) => {
console.log("ERROR");
console.error(err);
});

PDFium()
.then((module) => {
console.log(module.HEAP16);
})
.catch((err) => console.error(err));
const loadPDFium = async () => {
if (isReady) {
toast("PDFium.js already loaded", { type: "info" });
return;
}

try {
const PDFiumModule = await PDFium({ onError: handlePDFiumError });
setReady(true);
toast("PDFium.js loaded", { type: "success" });
console.log("PDFium WebAssembly loaded", PDFiumModule);
} catch (err) {
toast(JSON.stringify(err), { type: "error", autoClose: false });
console.error(err);
}
};

const initPDFium = useCallback(() => {
window.FPDF?._FPDF_InitLibrary();
setInitialized(true);
}, [initialized]);

const destroyPDFium = useCallback(() => {
window.FPDF?._FPDF_DestroyLibrary();
setInitialized(false);
}, [initialized]);

const loadDocumentBinary = useCallback(async () => {
if (pdfRenderer.current) {
toast("Document already loaded!", { type: "error" });
return;
}

const binaryRes = await axios.get<ArrayBuffer>("/PDF32000_2008.pdf", {
responseType: "arraybuffer",
});
const binary = new Uint8Array(binaryRes.data);
pdfRenderer.current = new PDFRenderer(binary);
pdfRenderer.current.openDocument();
setDocumentLoaded(true);
setTotalPageCount(pdfRenderer.current.getPageCount());
}, []);

const renderDocument = useCallback(async () => {
if (!pdfRenderer.current) {
toast("PDF document not loaded", { type: "error" });
return;
}

if (!pdfRenderer.current.openPage(targetPageIndex)) {
toast("Failed to open target page in PDF document", { type: "error" });
return;
}

pdfRenderer.current.render(pdfRenderSurfaceRef.current, targetPageIndex, 1.0);
}, [targetPageIndex]);

return (
<>
<h1>PDFium.js Example</h1>
<header>
<h1>PDFium.js Example</h1>
</header>
<div id="content">
<aside>
<p>PDFium.js loaded: {isReady ? "Yes" : "No"}</p>
<p>WASM Library Initialized: {initialized ? "Yes" : "No"}</p>
<p>PDF binary loaded: {documentLoaded ? "Yes" : "no"}</p>
<hr />
<p>Number of pages: {totalPageCount}</p>
<div className="api-container">
<button onClick={loadPDFium}>Load PDFium.js</button>
<br />
<button disabled={!isReady || initialized} onClick={initPDFium}>
Init PDFium Native Library
</button>
<button disabled={!isReady || !initialized} onClick={destroyPDFium}>
Destroy PDFium Native Library
</button>
<br />
<button disabled={!isReady || documentLoaded} onClick={loadDocumentBinary}>Load document</button>
<br />
<label>
Target page index:{" "}
<input
type="number"
value={targetPageIndex}
onChange={(e) => setTargetPageIndex(Number(e.target.value))}
/>
</label>
<button disabled={!documentLoaded} onClick={renderDocument}>Render sample document</button>
</div>
</aside>
<main className="pdf-container">
<canvas id="pdf-canvas" ref={pdfRenderSurfaceRef} width={500} />
</main>
</div>

<p>You can test PDFium module in this page.</p>
<ToastContainer position="bottom-right" theme="dark" newestOnTop />
</>
);
};
Expand Down
2 changes: 1 addition & 1 deletion example/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
body {
margin: 0;
display: flex;
place-items: center;
justify-content: center;
min-width: 320px;
min-height: 100vh;
}
Expand Down
Loading

0 comments on commit b95ff0f

Please sign in to comment.