Compare commits

...
Author SHA1 Message Date
Abimael Martell 7210bebaad refactor(bindings): organize language packages 2026-07-17 16:55:09 -07:00
37 changed files with 691 additions and 1570 deletions
+63 -8
View File
@@ -42,9 +42,6 @@ jobs:
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check WASM formatting
run: cargo fmt --manifest-path wasm/Cargo.toml -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
@@ -99,21 +96,79 @@ jobs:
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
workspaces: |
wasm -> target
key: wasm
- name: Check WebAssembly bindings
run: cargo check --manifest-path wasm/Cargo.toml --target wasm32-unknown-unknown
run: cargo check --package pdf-inspector-wasm --target wasm32-unknown-unknown
- name: Check root package for WebAssembly
run: cargo check --target wasm32-unknown-unknown
- name: Lint WebAssembly bindings
run: cargo clippy --manifest-path wasm/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
run: cargo clippy --package pdf-inspector-wasm --target wasm32-unknown-unknown -- -D warnings
- name: Install wasm-pack
run: cargo install wasm-pack --version 0.15.0 --locked
- name: Test WebAssembly package
run: wasm-pack test --node --release wasm
run: wasm-pack test --node --release bindings/wasm
node:
name: Node.js binding
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
key: node
- name: Install dependencies
working-directory: bindings/node
run: bun install --frozen-lockfile
- name: Build binding
working-directory: bindings/node
run: bunx napi build --platform --release
- name: Run binding tests
working-directory: bindings/node
run: node test.mjs
python:
name: Python binding
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
key: python
- name: Install build and test tools
run: python -m pip install maturin pytest
- name: Build wheel
run: maturin build --manifest-path bindings/python/Cargo.toml --release --out dist
- name: Install wheel
run: python -m pip install dist/*.whl
- name: Run binding tests
run: python -m pytest bindings/python/tests
+11 -8
View File
@@ -3,7 +3,7 @@ name: Publish Python package
on:
push:
branches: [main]
paths: ['pyproject.toml']
paths: ['bindings/python/pyproject.toml']
# Manual fallback: re-publish the current version without a version bump
# (e.g. first run after PyPI trusted publishing is configured).
workflow_dispatch:
@@ -31,7 +31,7 @@ jobs:
- name: Check if version changed
id: check
run: |
NEW_VERSION=$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')
NEW_VERSION=$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("bindings/python/pyproject.toml").read_text())["project"]["version"])')
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
@@ -45,10 +45,13 @@ jobs:
exit 0
fi
# .get(): the parent commit may predate the static version field
# (pyproject.toml used dynamic = ["version"]) — treat that as a change
# so the very first merge of this workflow publishes.
OLD_VERSION=$(git show HEAD~1:pyproject.toml | python3 -c 'import sys, tomllib; print(tomllib.loads(sys.stdin.read())["project"].get("version", ""))')
if git cat-file -e HEAD~1:bindings/python/pyproject.toml 2>/dev/null; then
OLD_MANIFEST=bindings/python/pyproject.toml
else
# Migration fallback for the commit that moved the Python package.
OLD_MANIFEST=pyproject.toml
fi
OLD_VERSION=$(git show "HEAD~1:$OLD_MANIFEST" | python3 -c 'import sys, tomllib; print(tomllib.loads(sys.stdin.read())["project"].get("version", ""))')
echo "old=$OLD_VERSION new=$NEW_VERSION"
if [ "$NEW_VERSION" = "$OLD_VERSION" ]; then
@@ -108,7 +111,7 @@ jobs:
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist
args: --manifest-path bindings/python/Cargo.toml --release --out dist
manylinux: auto
- name: Upload wheel
@@ -130,7 +133,7 @@ jobs:
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
args: --manifest-path bindings/python/Cargo.toml --out dist
- name: Upload sdist
uses: actions/upload-artifact@v4
+15 -11
View File
@@ -3,7 +3,7 @@ name: Publish WebAssembly package
on:
push:
branches: [main]
paths: ['wasm/Cargo.toml']
paths: ['bindings/wasm/Cargo.toml']
workflow_dispatch:
permissions:
@@ -31,21 +31,25 @@ jobs:
- name: Check package version
id: check
run: |
NEW_VERSION=$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("wasm/Cargo.toml").read_text())["package"]["version"])')
NEW_VERSION=$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("bindings/wasm/Cargo.toml").read_text())["package"]["version"])')
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
elif git cat-file -e HEAD~1:wasm/Cargo.toml 2>/dev/null; then
OLD_VERSION=$(git show HEAD~1:wasm/Cargo.toml | python3 -c 'import sys, tomllib; print(tomllib.loads(sys.stdin.read())["package"]["version"])')
else
if git cat-file -e HEAD~1:bindings/wasm/Cargo.toml 2>/dev/null; then
OLD_MANIFEST=bindings/wasm/Cargo.toml
else
# Migration fallback for the commit that moved wasm/.
OLD_MANIFEST=wasm/Cargo.toml
fi
OLD_VERSION=$(git show "HEAD~1:$OLD_MANIFEST" | python3 -c 'import sys, tomllib; print(tomllib.loads(sys.stdin.read())["package"]["version"])')
if [ "$NEW_VERSION" = "$OLD_VERSION" ]; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "published=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
if ! npm view "@firecrawl/pdf-inspector-wasm" name >/dev/null 2>&1; then
@@ -87,25 +91,25 @@ jobs:
run: cargo install wasm-pack --version 0.15.0 --locked
- name: Build browser package
run: wasm-pack build wasm --target web --scope firecrawl --out-dir pkg --release
run: wasm-pack build bindings/wasm --target web --scope firecrawl --out-dir pkg --profile wasm-release --no-opt
- name: Prepare package metadata
run: |
node -e '
const fs = require("fs")
const path = "wasm/pkg/package.json"
const path = "bindings/wasm/pkg/package.json"
const pkg = JSON.parse(fs.readFileSync(path, "utf8"))
pkg.name = "@firecrawl/pdf-inspector-wasm"
pkg.description = "Browser WebAssembly bindings for the pdf-inspector Rust PDF parser"
pkg.keywords = ["pdf", "pdf-parser", "webassembly", "wasm", "markdown", "rust", "firecrawl"]
pkg.repository = { type: "git", url: "https://github.com/firecrawl/pdf-inspector" }
pkg.homepage = "https://github.com/firecrawl/pdf-inspector/tree/main/wasm"
pkg.homepage = "https://github.com/firecrawl/pdf-inspector/tree/main/bindings/wasm"
pkg.publishConfig = { access: "public" }
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n")
'
- name: Inspect package contents
run: npm pack --dry-run ./wasm/pkg
run: npm pack --dry-run ./bindings/wasm/pkg
- name: Publish package
run: npm publish ./wasm/pkg --provenance --access public
run: npm publish ./bindings/wasm/pkg --provenance --access public
+19 -13
View File
@@ -3,7 +3,7 @@ name: Publish npm package
on:
push:
branches: [main]
paths: ['napi/package.json']
paths: ['bindings/node/package.json']
# Manual fallback: retry a publish that failed partway (per-package
# already-published checks make re-runs idempotent).
workflow_dispatch:
@@ -31,7 +31,7 @@ jobs:
- name: Check if version changed
id: check
run: |
NEW_VERSION=$(node -p "require('./napi/package.json').version")
NEW_VERSION=$(node -p "require('./bindings/node/package.json').version")
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
@@ -43,7 +43,13 @@ jobs:
exit 0
fi
OLD_VERSION=$(git show HEAD~1:napi/package.json | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version")
if git cat-file -e HEAD~1:bindings/node/package.json 2>/dev/null; then
OLD_MANIFEST=bindings/node/package.json
else
# Migration fallback for the commit that moved napi/.
OLD_MANIFEST=napi/package.json
fi
OLD_VERSION=$(git show "HEAD~1:$OLD_MANIFEST" | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version")
echo "old=$OLD_VERSION new=$NEW_VERSION"
if [ "$NEW_VERSION" != "$OLD_VERSION" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
@@ -82,24 +88,24 @@ jobs:
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
napi/target/
target/
key: ${{ runner.os }}-cargo-napi-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-napi-
- name: Install dependencies
working-directory: napi
run: bun install
working-directory: bindings/node
run: bun install --frozen-lockfile
- name: Build native addon
working-directory: napi
working-directory: bindings/node
run: bunx napi build --platform --release
- name: Upload native binary
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.target }}
path: napi/*.node
path: bindings/node/*.node
if-no-files-found: error
- name: Upload generated JS bindings
@@ -108,8 +114,8 @@ jobs:
with:
name: js-bindings
path: |
napi/index.js
napi/index.d.ts
bindings/node/index.js
bindings/node/index.d.ts
if-no-files-found: error
publish:
@@ -130,10 +136,10 @@ jobs:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: napi/artifacts
path: bindings/node/artifacts
- name: Publish platform packages
working-directory: napi
working-directory: bindings/node
run: |
VERSION="${{ needs.check-version.outputs.version }}"
@@ -183,7 +189,7 @@ jobs:
done
- name: Publish main package
working-directory: napi
working-directory: bindings/node
run: |
VERSION="${{ needs.check-version.outputs.version }}"
+7 -8
View File
@@ -1,13 +1,12 @@
# Rust build artifacts
/target/
/wasm/target/
/wasm/pkg/
/bindings/*/target/
/bindings/wasm/pkg/
debug/
*.pdb
# Cargo lock (optional for libraries)
Cargo.lock
!/wasm/Cargo.lock
# The workspace lock keeps binding builds reproducible.
!/Cargo.lock
# IDE
.idea/
@@ -27,9 +26,9 @@ Thumbs.db
# Build cache
**/*.rs.bk
# NAPI generated (regenerated by `napi prepublish` during CI)
napi/index.js
napi/index.d.ts
# Node generated files (regenerated by `napi prepublish` during CI)
bindings/node/index.js
bindings/node/index.d.ts
# Local samples and scripts
samples/
+4
View File
@@ -45,6 +45,10 @@ src/
classify.rs line classification (header, list, code, caption)
preprocess.rs drop cap merging, heading line merging
postprocess.rs dot leaders, hyphenation, page numbers, URL formatting
bindings/
node/ npm package, bundled CLI, and napi-rs adapter
python/ PyPI package, type stubs, tests, and PyO3 adapter
wasm/ browser npm package and wasm-bindgen adapter
```
## Key design decisions
+4
View File
@@ -45,6 +45,10 @@ src/
classify.rs line classification (header, list, code, caption)
preprocess.rs drop cap merging, heading line merging
postprocess.rs dot leaders, hyphenation, page numbers, URL formatting
bindings/
node/ npm package, bundled CLI, and napi-rs adapter
python/ PyPI package, type stubs, tests, and PyO3 adapter
wasm/ browser npm package and wasm-bindgen adapter
```
## Key design decisions
+436 -126
View File
@@ -94,16 +94,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "autocfg"
version = "1.5.0"
name = "async-trait"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "bitflags"
version = "2.11.0"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
[[package]]
name = "block-buffer"
@@ -125,9 +136,15 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.20.2"
version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cbc"
@@ -140,9 +157,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.58"
version = "1.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -167,9 +184,9 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.44"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"num-traits",
@@ -192,6 +209,16 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]]
name = "convert_case"
version = "0.11.0"
@@ -271,28 +298,15 @@ dependencies = [
[[package]]
name = "ctor"
version = "0.8.0"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98"
dependencies = [
"ctor-proc-macro",
"dtor",
]
[[package]]
name = "ctor-proc-macro"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1"
checksum = "a394189d59f9befacce833f337f7b1eca5e9a91221bcdd4d28e0114d96e597b3"
[[package]]
name = "deranged"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
@@ -304,21 +318,6 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "dtor"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4"
dependencies = [
"dtor-proc-macro",
]
[[package]]
name = "dtor-proc-macro"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
[[package]]
name = "ecb"
version = "0.1.2"
@@ -330,9 +329,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.15.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]]
name = "encoding_rs"
@@ -372,6 +371,22 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
@@ -499,11 +514,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi",
"rand_core",
"wasip2",
"wasip3",
"wasm-bindgen",
]
[[package]]
@@ -517,9 +534,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.16.1"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -558,17 +575,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "indexmap"
version = "2.13.0"
name = "include_dir"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd"
dependencies = [
"include_dir_macros",
]
[[package]]
name = "include_dir_macros"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "indexmap"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.16.1",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
name = "indoc"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
dependencies = [
"rustversion",
]
[[package]]
name = "inout"
version = "0.1.4"
@@ -593,9 +638,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "jiff"
version = "0.2.23"
version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359"
checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
@@ -603,14 +648,14 @@ dependencies = [
"portable-atomic",
"portable-atomic-util",
"serde_core",
"windows-sys",
"windows-link",
]
[[package]]
name = "jiff-static"
version = "0.2.23"
version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4"
checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47"
dependencies = [
"proc-macro2",
"quote",
@@ -634,11 +679,12 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.94"
version = "0.3.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
dependencies = [
"once_cell",
"cfg-if",
"futures-util",
"wasm-bindgen",
]
@@ -650,9 +696,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
version = "0.2.184"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libloading"
@@ -665,10 +711,22 @@ dependencies = [
]
[[package]]
name = "log"
version = "0.4.29"
name = "libm"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "log"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
[[package]]
name = "lopdf"
@@ -713,9 +771,28 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.8.0"
version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]]
name = "minicov"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d"
dependencies = [
"cc",
"walkdir",
]
[[package]]
name = "miniz_oxide"
@@ -729,9 +806,9 @@ dependencies = [
[[package]]
name = "napi"
version = "3.8.4"
version = "3.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb7848c221fb7bb789e02f01875287ebb1e078b92a6566a34de01ef8806e7c2b"
checksum = "6826e5ddc15589b2d68c8ad5321c18e85d40488e93e32962f362e572669bccf6"
dependencies = [
"bitflags",
"ctor",
@@ -746,15 +823,15 @@ dependencies = [
[[package]]
name = "napi-build"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d376940fd5b723c6893cd1ee3f33abbfd86acb1cd1ec079f3ab04a2a3bc4d3b1"
checksum = "c9c366d2c8c60b86fa632df75f745509b52f9128f91a6bad4c796e44abb505e1"
[[package]]
name = "napi-derive"
version = "3.5.3"
version = "3.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60867ff9a6f76e82350e0c3420cb0736f5866091b61d7d8a024baa54b0ec17dd"
checksum = "b0fe526e81c105d3640516fcde83909dd1afe757c0d7a15af58830b5bc0fb9a1"
dependencies = [
"convert_case",
"ctor",
@@ -766,9 +843,9 @@ dependencies = [
[[package]]
name = "napi-derive-backend"
version = "5.0.2"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0864cf6a82e2cfb69067374b64c9253d7e910e5b34db833ed7495dda56ccb18"
checksum = "514281397bcddd9ea9a876c7a21a57bff2374237a000ca9a64ea0211ec1993e2"
dependencies = [
"convert_case",
"proc-macro2",
@@ -779,9 +856,9 @@ dependencies = [
[[package]]
name = "napi-sys"
version = "3.2.1"
version = "3.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb602b84d7c1edae45e50bbf1374696548f36ae179dfa667f577e384bb90c2b"
checksum = "73e43cf2eb0bd1bf95a43c07c076ebd2da5d1e015a71c3d201faeffffcc0ecac"
dependencies = [
"libloading",
]
@@ -802,10 +879,19 @@ dependencies = [
]
[[package]]
name = "num-conv"
version = "0.2.1"
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys",
]
[[package]]
name = "num-conv"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-traits"
@@ -814,6 +900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
@@ -828,23 +915,31 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "pdf-inspector"
version = "0.1.6"
dependencies = [
"env_logger",
"include_dir",
"log",
"lopdf",
"once_cell",
"rayon",
"regex",
"tempfile",
"thiserror",
"ttf-parser",
"unicode-normalization",
]
[[package]]
name = "pdf-inspector-napi"
name = "pdf-inspector-node"
version = "0.2.2"
dependencies = [
"napi",
@@ -853,6 +948,27 @@ dependencies = [
"pdf-inspector",
]
[[package]]
name = "pdf-inspector-python"
version = "0.2.5"
dependencies = [
"pdf-inspector",
"pyo3",
]
[[package]]
name = "pdf-inspector-wasm"
version = "0.1.2"
dependencies = [
"console_error_panic_hook",
"js-sys",
"pdf-inspector",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]]
name = "pin-project-lite"
version = "0.2.17"
@@ -867,9 +983,9 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
[[package]]
name = "portable-atomic-util"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3"
checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
dependencies = [
"portable-atomic",
]
@@ -899,6 +1015,68 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "pyo3"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a"
dependencies = [
"indoc",
"libc",
"memoffset",
"once_cell",
"portable-atomic",
"pyo3-build-config",
"pyo3-ffi",
"pyo3-macros",
"unindent",
]
[[package]]
name = "pyo3-build-config"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598"
dependencies = [
"once_cell",
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c"
dependencies = [
"libc",
"pyo3-build-config",
]
[[package]]
name = "pyo3-macros"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
"quote",
"syn",
]
[[package]]
name = "pyo3-macros-backend"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc"
dependencies = [
"heck",
"proc-macro2",
"pyo3-build-config",
"quote",
"syn",
]
[[package]]
name = "quote"
version = "1.0.45"
@@ -916,9 +1094,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
"getrandom",
@@ -927,9 +1105,9 @@ dependencies = [
[[package]]
name = "rand_core"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rangemap"
@@ -939,9 +1117,9 @@ checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
[[package]]
name = "rayon"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
@@ -959,9 +1137,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.12.3"
version = "1.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
dependencies = [
"aho-corasick",
"memchr",
@@ -982,15 +1160,28 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.10"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "rustc-hash"
version = "2.1.2"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
[[package]]
name = "rustix"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
@@ -999,10 +1190,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "semver"
version = "1.0.27"
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
@@ -1011,6 +1211,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
@@ -1035,9 +1247,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.149"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
@@ -1059,9 +1271,9 @@ dependencies = [
[[package]]
name = "shlex"
version = "1.3.0"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "simd-adler32"
@@ -1088,15 +1300,34 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "target-lexicon"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
[[package]]
name = "tempfile"
version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom",
"once_cell",
"rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
version = "2.0.18"
@@ -1119,12 +1350,11 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.47"
version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde_core",
@@ -1134,15 +1364,15 @@ dependencies = [
[[package]]
name = "time-core"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
version = "0.2.27"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d"
dependencies = [
"num-conv",
"time-core",
@@ -1171,9 +1401,9 @@ checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
name = "typenum"
version = "1.19.0"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
name = "unicode-bidi"
@@ -1204,9 +1434,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
[[package]]
name = "unicode-segmentation"
version = "1.13.2"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "unicode-xid"
@@ -1214,6 +1444,12 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "unindent"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
[[package]]
name = "utf8parse"
version = "0.2.2"
@@ -1227,12 +1463,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"wit-bindgen",
"same-file",
"winapi-util",
]
[[package]]
name = "wasip2"
version = "1.0.4+wasi-0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
dependencies = [
"wit-bindgen 0.57.1",
]
[[package]]
@@ -1241,14 +1487,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen",
"wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.117"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
dependencies = [
"cfg-if",
"once_cell",
@@ -1258,10 +1504,20 @@ dependencies = [
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.117"
name = "wasm-bindgen-futures"
version = "0.4.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1269,9 +1525,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.117"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1282,13 +1538,52 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.117"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-bindgen-test"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16931d57bcdd6a0dcc11254bdd1388827690c1b6807f0d2836f59a4f9eb30ac"
dependencies = [
"async-trait",
"cast",
"js-sys",
"libm",
"minicov",
"nu-ansi-term",
"num-traits",
"oorandom",
"serde",
"serde_json",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
"wasm-bindgen-test-shared",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fccaddcb2cd722baa7453b4c3d2cb2a3071597bb91f7a4373e8775bdb151778c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "wasm-bindgen-test-shared"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3746ad029217960123cf2ebf939dda51eb931ba9f8f09c117e39c820b96aa794"
[[package]]
name = "wasm-encoder"
version = "0.244.0"
@@ -1329,6 +1624,15 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-core"
version = "0.62.2"
@@ -1406,6 +1710,12 @@ dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
+17 -11
View File
@@ -16,19 +16,12 @@ include = [
"/external/bcmaps/**",
"/docs/rust-api.md",
"/LICENSE",
# maturin derives the sdist file list from this allowlist; the stub must
# ship so wheels built from the sdist keep their type hints.
"/pdf_inspector.pyi",
]
[lib]
name = "pdf_inspector"
crate-type = ["lib", "cdylib"]
[dependencies]
# Python bindings
pyo3 = { version = "0.25", features = ["extension-module", "abi3-py38"], optional = true }
# Error handling
thiserror = "2.0"
@@ -59,10 +52,6 @@ include_dir = "0.7"
[dev-dependencies]
tempfile = "3.3"
[features]
default = []
python = ["pyo3"]
[[bin]]
name = "pdf2md"
path = "src/bin/pdf2md.rs"
@@ -74,3 +63,20 @@ path = "src/bin/detect_pdf.rs"
[[bin]]
name = "dump_ops"
path = "src/bin/dump_ops.rs"
[workspace]
members = ["bindings/node", "bindings/python", "bindings/wasm"]
default-members = ["."]
resolver = "2"
# Native packages benefit from LTO. Browser builds use a size-focused custom
# profile selected by the wasm-pack release command.
[profile.release]
lto = true
strip = "debuginfo"
[profile.wasm-release]
inherits = "release"
codegen-units = 1
opt-level = "s"
strip = true
+10 -9
View File
@@ -5,7 +5,7 @@
[![PyPI](https://img.shields.io/pypi/v/pdf-inspector.svg)](https://pypi.org/project/pdf-inspector/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
Fast Rust library for PDF classification and text extraction. Detects whether a PDF is text-based or scanned, extracts text with position awareness, and converts to clean Markdown — all without OCR. Includes bindings for [Python](docs/python.md), [Node.js](napi/README.md), and [browser WebAssembly](wasm/README.md).
Fast Rust library for PDF classification and text extraction. Detects whether a PDF is text-based or scanned, extracts text with position awareness, and converts to clean Markdown — all without OCR. Includes bindings for [Python](bindings/python/README.md), [Node.js](bindings/node/README.md), and [browser WebAssembly](bindings/wasm/README.md).
Built by [Firecrawl](https://firecrawl.dev) to handle text-based PDFs locally in under 200ms, skipping expensive OCR services for the ~54% of PDFs that don't need them.
@@ -47,8 +47,7 @@ Use the [paired benchmark harness](docs/benchmarking.md) to compare two local bu
### Python
```bash
pip install maturin
maturin develop --release
pip install pdf-inspector
```
```python
@@ -59,7 +58,7 @@ print(result.pdf_type) # "text_based", "scanned", "image_based", "mixed"
print(result.markdown) # Markdown string or None
```
> Full API reference: [docs/python.md](docs/python.md)
> Full API reference: [bindings/python/README.md](bindings/python/README.md)
### Node.js
@@ -76,7 +75,7 @@ console.log(result.pdfType); // "TextBased", "Scanned", "ImageBased", "Mixed"
console.log(result.markdown); // Markdown string or null
```
> Full API reference: [napi/README.md](napi/README.md)
> Full API reference: [bindings/node/README.md](bindings/node/README.md)
### Browser WebAssembly
@@ -96,7 +95,7 @@ console.log(result.pdfType);
console.log(result.markdown);
```
> Full API reference: [wasm/README.md](wasm/README.md)
> Full API reference: [bindings/wasm/README.md](bindings/wasm/README.md)
### Rust
@@ -197,7 +196,6 @@ The document is loaded **once** via `load_document_from_path` / `load_document_f
```
src/
lib.rs — Public API, PdfOptions builder, convenience functions
python.rs — PyO3 Python bindings
types.rs — Shared types: TextItem, TextLine, PdfRect, ItemType
text_utils.rs — Character/text helpers (CJK, RTL, ligatures, bold/italic)
process_mode.rs — ProcessMode enum (DetectOnly, Analyze, Full)
@@ -208,8 +206,11 @@ src/
tables/ — Table detection and formatting
markdown/ — Markdown conversion and structure detection
bin/ — CLI tools (pdf2md, detect_pdf)
napi/ — Node.js/Bun bindings (napi-rs)
wasm/ Browser bindings (wasm-bindgen)
bindings/
node/Node.js/Bun package and CLI (napi-rs)
python/ — Python package (PyO3 + maturin)
wasm/ — Browser package (wasm-bindgen)
tests/fixtures/ — Shared PDFs used across core and binding tests
```
## How classification works
+13
View File
@@ -0,0 +1,13 @@
# Language bindings
The Rust crate at the repository root owns PDF parsing, extraction, and Markdown conversion. Each directory here is a thin package adapter that translates the core API into the conventions of its runtime.
| Binding | Public package | Implementation |
|---|---|---|
| [Node.js](node/README.md) | `@firecrawl/pdf-inspector` | napi-rs |
| [Python](python/README.md) | `pdf-inspector` | PyO3 + maturin |
| [Browser WebAssembly](wasm/README.md) | `@firecrawl/pdf-inspector-wasm` | wasm-bindgen |
The public package names and APIs are independent from these repository paths. Binding-specific metadata, tests, examples, and release inputs live with their adapter; shared PDF fixtures remain in [`tests/fixtures`](../tests/fixtures).
Versions remain independent for now. A later release-policy change can align them without mixing that change into the structural reorganization.
+3
View File
@@ -0,0 +1,3 @@
target/
node_modules/
*.node
+3 -6
View File
@@ -1,19 +1,16 @@
[package]
name = "pdf-inspector-napi"
name = "pdf-inspector-node"
version = "0.2.2"
edition = "2021"
publish = false
[lib]
crate-type = ["cdylib"]
[dependencies]
pdf-inspector = { path = ".." }
pdf-inspector = { path = "../.." }
napi = { version = "3.0.0", features = ["serde-json"] }
napi-derive = "3.0.0"
[build-dependencies]
napi-build = "2"
[profile.release]
lto = true
strip = "debuginfo"
+9 -3
View File
@@ -8,9 +8,9 @@
"@napi-rs/cli": "^3.4.1",
},
"optionalDependencies": {
"@firecrawl/pdf-inspector-darwin-arm64": "1.11.0",
"@firecrawl/pdf-inspector-linux-x64-gnu": "1.11.0",
"@firecrawl/pdf-inspector-win32-x64-msvc": "1.11.0",
"@firecrawl/pdf-inspector-darwin-arm64": "1.11.1",
"@firecrawl/pdf-inspector-linux-x64-gnu": "1.11.1",
"@firecrawl/pdf-inspector-win32-x64-msvc": "1.11.1",
},
},
},
@@ -21,6 +21,12 @@
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
"@firecrawl/pdf-inspector-darwin-arm64": ["@firecrawl/pdf-inspector-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MYworvuQ84dRxMhVmhSuSP8gVdrxqKfnTC+spGc+OIEaJGHNuzgBUzgi9O7p3wSP/hkK9QdCDEbl6wdBO9a4rA=="],
"@firecrawl/pdf-inspector-linux-x64-gnu": ["@firecrawl/pdf-inspector-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Vyp7EpmplnWFsyi7YGK1yKE97PIrueIpo7jJx9zfU5wVAjSQuBRwykYbSUywsS3GPEbfgFlMDAW0Cls4lbtPqw=="],
"@firecrawl/pdf-inspector-win32-x64-msvc": ["@firecrawl/pdf-inspector-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-B3hpMRHlJFaOdZaWiG0wyGcfVkf3AQh232tRd0kN4EpAIyo/sEU6+cbEarH1Z+ypd7QRNlO6fcnSYHelZaqS0A=="],
"@inquirer/ansi": ["@inquirer/ansi@2.0.4", "", {}, "sha512-DpcZrQObd7S0R/U3bFdkcT5ebRwbTTC4D3tCc1vsJizmgPLxNJBo+AAFmrZwe8zk30P2QzgzGWZ3Q9uJwWuhIg=="],
"@inquirer/checkbox": ["@inquirer/checkbox@5.1.2", "", { "dependencies": { "@inquirer/ansi": "^2.0.4", "@inquirer/core": "^11.1.7", "@inquirer/figures": "^2.0.4", "@inquirer/type": "^4.0.4" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-PubpMPO2nJgMufkoB3P2wwxNXEMUXnBIKi/ACzDUYfaoPuM7gSTmuxJeMscoLVEsR4qqrCMf5p0SiYGWnVJ8kw=="],
+1 -3
View File
@@ -153,9 +153,7 @@ fn to_napi_result(r: pdf_inspector::PdfProcessResult) -> PdfResult {
}
}
fn to_napi_page_ocr_reasons(
reasons: Vec<pdf_inspector::PageOcrReasons>,
) -> Vec<PageOcrReasons> {
fn to_napi_page_ocr_reasons(reasons: Vec<pdf_inspector::PageOcrReasons>) -> Vec<PageOcrReasons> {
reasons
.into_iter()
.map(|reason| PageOcrReasons {
+1 -1
View File
@@ -11,7 +11,7 @@ import {
extractPagesMarkdown,
} from './index.js';
const fixture = readFileSync('../tests/fixtures/thermo-freon12.pdf');
const fixture = readFileSync('../../tests/fixtures/thermo-freon12.pdf');
// --- processPdf ---
console.log('Testing processPdf...');
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "pdf-inspector-python"
version = "0.2.5"
edition = "2021"
authors = ["Firecrawl Team"]
description = "Python bindings for pdf-inspector"
license = "MIT"
repository = "https://github.com/firecrawl/pdf-inspector"
readme = "README.md"
publish = false
[lib]
name = "pdf_inspector"
crate-type = ["cdylib"]
[dependencies]
pdf-inspector = { path = "../.." }
pyo3 = { version = "0.25", features = ["extension-module", "abi3-py38"] }
@@ -36,6 +36,7 @@ Prebuilt wheels cover CPython ≥3.8 on Linux (x86_64, aarch64), macOS (Intel, A
```bash
pip install maturin
cd bindings/python
maturin develop --release
```
@@ -5,10 +5,10 @@ build-backend = "maturin"
[project]
name = "pdf-inspector"
# Bump this to publish to PyPI — CI publishes automatically when the version
# changes on main (same flow as napi/package.json for npm).
# changes on main (same flow as bindings/node/package.json for npm).
version = "0.2.5"
description = "Fast PDF inspection, classification, and text extraction with smart scanned vs text-based detection"
readme = "docs/python.md"
readme = "README.md"
license = { text = "MIT" }
requires-python = ">=3.8"
classifiers = [
@@ -23,7 +23,8 @@ classifiers = [
[project.urls]
Homepage = "https://github.com/firecrawl/pdf-inspector"
Repository = "https://github.com/firecrawl/pdf-inspector"
Documentation = "https://github.com/firecrawl/pdf-inspector/blob/main/docs/python.md"
Documentation = "https://github.com/firecrawl/pdf-inspector/blob/main/bindings/python/README.md"
[tool.maturin]
features = ["python"]
bindings = "pyo3"
module-name = "pdf_inspector"
+25 -24
View File
@@ -4,8 +4,9 @@ use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use std::collections::HashSet;
use crate::detector::PdfType;
use crate::types::ItemType;
use ::pdf_inspector as core;
use core::detector::PdfType;
use core::types::ItemType;
// ---------------------------------------------------------------------------
// Result wrapper
@@ -299,7 +300,7 @@ fn pdf_type_str(t: PdfType) -> String {
}
}
fn to_py_result(r: crate::PdfProcessResult) -> PyPdfResult {
fn to_py_result(r: core::PdfProcessResult) -> PyPdfResult {
PyPdfResult {
pdf_type: pdf_type_str(r.pdf_type),
markdown: r.markdown,
@@ -316,7 +317,7 @@ fn to_py_result(r: crate::PdfProcessResult) -> PyPdfResult {
}
}
fn to_py_page_ocr_reasons(reasons: Vec<crate::PageOcrReasons>) -> Vec<PyPageOcrReasons> {
fn to_py_page_ocr_reasons(reasons: Vec<core::PageOcrReasons>) -> Vec<PyPageOcrReasons> {
reasons
.into_iter()
.map(|reason| PyPageOcrReasons {
@@ -326,7 +327,7 @@ fn to_py_page_ocr_reasons(reasons: Vec<crate::PageOcrReasons>) -> Vec<PyPageOcrR
.collect()
}
fn to_py_err(e: crate::PdfError) -> PyErr {
fn to_py_err(e: core::PdfError) -> PyErr {
PyValueError::new_err(e.to_string())
}
@@ -339,7 +340,7 @@ fn item_type_str(t: &ItemType) -> String {
}
}
fn convert_text_items(items: Vec<crate::TextItem>) -> Vec<PyTextItem> {
fn convert_text_items(items: Vec<core::TextItem>) -> Vec<PyTextItem> {
items
.into_iter()
.map(|item| PyTextItem {
@@ -392,7 +393,7 @@ fn parse_page_regions(
.collect()
}
fn to_py_pages_result(r: crate::PagesExtractionResult) -> PyPagesExtractionResult {
fn to_py_pages_result(r: core::PagesExtractionResult) -> PyPagesExtractionResult {
PyPagesExtractionResult {
pages: r
.pages
@@ -412,7 +413,7 @@ fn to_py_pages_result(r: crate::PagesExtractionResult) -> PyPagesExtractionResul
}
}
fn convert_region_results(results: Vec<crate::PageRegionResult>) -> Vec<PyPageRegionTexts> {
fn convert_region_results(results: Vec<core::PageRegionResult>) -> Vec<PyPageRegionTexts> {
results
.into_iter()
.map(|page_result| PyPageRegionTexts {
@@ -438,11 +439,11 @@ fn convert_region_results(results: Vec<crate::PageRegionResult>) -> Vec<PyPageRe
#[pyfunction]
#[pyo3(signature = (path, pages=None))]
fn process_pdf(path: &str, pages: Option<Vec<u32>>) -> PyResult<PyPdfResult> {
let mut opts = crate::PdfOptions::new();
let mut opts = core::PdfOptions::new();
if let Some(p) = pages {
opts = opts.pages(p);
}
let result = crate::process_pdf_with_options(path, opts).map_err(to_py_err)?;
let result = core::process_pdf_with_options(path, opts).map_err(to_py_err)?;
Ok(to_py_result(result))
}
@@ -450,25 +451,25 @@ fn process_pdf(path: &str, pages: Option<Vec<u32>>) -> PyResult<PyPdfResult> {
#[pyfunction]
#[pyo3(signature = (data, pages=None))]
fn process_pdf_bytes(data: &[u8], pages: Option<Vec<u32>>) -> PyResult<PyPdfResult> {
let mut opts = crate::PdfOptions::new();
let mut opts = core::PdfOptions::new();
if let Some(p) = pages {
opts = opts.pages(p);
}
let result = crate::process_pdf_mem_with_options(data, opts).map_err(to_py_err)?;
let result = core::process_pdf_mem_with_options(data, opts).map_err(to_py_err)?;
Ok(to_py_result(result))
}
/// Fast detection only — no text extraction or markdown.
#[pyfunction]
fn detect_pdf(path: &str) -> PyResult<PyPdfResult> {
let result = crate::detect_pdf(path).map_err(to_py_err)?;
let result = core::detect_pdf(path).map_err(to_py_err)?;
Ok(to_py_result(result))
}
/// Fast detection from bytes — no text extraction or markdown.
#[pyfunction]
fn detect_pdf_bytes(data: &[u8]) -> PyResult<PyPdfResult> {
let result = crate::detect_pdf_mem(data).map_err(to_py_err)?;
let result = core::detect_pdf_mem(data).map_err(to_py_err)?;
Ok(to_py_result(result))
}
@@ -485,7 +486,7 @@ fn classify_pdf(path: &str) -> PyResult<PyPdfClassification> {
/// Pages in pages_needing_ocr are 0-indexed.
#[pyfunction]
fn classify_pdf_bytes(data: &[u8]) -> PyResult<PyPdfClassification> {
let result = crate::classify_pdf_mem(data).map_err(to_py_err)?;
let result = core::classify_pdf_mem(data).map_err(to_py_err)?;
Ok(PyPdfClassification {
pdf_type: pdf_type_str(result.pdf_type),
page_count: result.page_count,
@@ -497,13 +498,13 @@ fn classify_pdf_bytes(data: &[u8]) -> PyResult<PyPdfClassification> {
/// Extract plain text from a PDF file.
#[pyfunction]
fn extract_text(path: &str) -> PyResult<String> {
crate::extract_text(path).map_err(to_py_err)
core::extract_text(path).map_err(to_py_err)
}
/// Extract plain text from PDF bytes.
#[pyfunction]
fn extract_text_bytes(data: &[u8]) -> PyResult<String> {
crate::extractor::extract_text_mem(data).map_err(to_py_err)
core::extractor::extract_text_mem(data).map_err(to_py_err)
}
/// Extract text with position information from a file.
@@ -513,9 +514,9 @@ fn extract_text_with_positions(path: &str, pages: Option<Vec<u32>>) -> PyResult<
let items = match pages {
Some(p) => {
let page_set: HashSet<u32> = p.into_iter().collect();
crate::extract_text_with_positions_pages(path, Some(&page_set)).map_err(to_py_err)?
core::extract_text_with_positions_pages(path, Some(&page_set)).map_err(to_py_err)?
}
None => crate::extract_text_with_positions(path).map_err(to_py_err)?,
None => core::extract_text_with_positions(path).map_err(to_py_err)?,
};
Ok(convert_text_items(items))
}
@@ -530,10 +531,10 @@ fn extract_text_with_positions_bytes(
let items = match pages {
Some(p) => {
let page_set: HashSet<u32> = p.into_iter().collect();
crate::extractor::extract_text_with_positions_mem_pages(data, Some(&page_set))
core::extractor::extract_text_with_positions_mem_pages(data, Some(&page_set))
.map_err(to_py_err)?
}
None => crate::extractor::extract_text_with_positions_mem(data).map_err(to_py_err)?,
None => core::extractor::extract_text_with_positions_mem(data).map_err(to_py_err)?,
};
Ok(convert_text_items(items))
}
@@ -571,7 +572,7 @@ fn extract_text_in_regions_bytes(
page_regions: Vec<(u32, Vec<Vec<f64>>)>,
) -> PyResult<Vec<PyPageRegionTexts>> {
let regions = parse_page_regions(page_regions)?;
let results = crate::extract_text_in_regions_mem(data, &regions).map_err(to_py_err)?;
let results = core::extract_text_in_regions_mem(data, &regions).map_err(to_py_err)?;
Ok(convert_region_results(results))
}
@@ -596,7 +597,7 @@ fn extract_pages_markdown(
path: &str,
pages: Option<Vec<u32>>,
) -> PyResult<PyPagesExtractionResult> {
let result = crate::extract_pages_markdown(path, pages.as_deref()).map_err(to_py_err)?;
let result = core::extract_pages_markdown(path, pages.as_deref()).map_err(to_py_err)?;
Ok(to_py_pages_result(result))
}
@@ -609,7 +610,7 @@ fn extract_pages_markdown_bytes(
data: &[u8],
pages: Option<Vec<u32>>,
) -> PyResult<PyPagesExtractionResult> {
let result = crate::extract_pages_markdown_mem(data, pages.as_deref()).map_err(to_py_err)?;
let result = core::extract_pages_markdown_mem(data, pages.as_deref()).map_err(to_py_err)?;
Ok(to_py_pages_result(result))
}
@@ -1,14 +1,16 @@
"""Tests for the pdf_inspector Python bindings."""
import os
from pathlib import Path
import pytest
import pdf_inspector
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
FIXTURES_DIR = Path(__file__).resolve().parents[3] / "tests" / "fixtures"
def fixture_path(name: str) -> str:
return os.path.join(FIXTURES_DIR, name)
return str(FIXTURES_DIR / name)
def fixture_bytes(name: str) -> bytes:
@@ -389,7 +391,11 @@ class TestMultipleFixtures:
@pytest.mark.parametrize(
"filename",
[f for f in os.listdir(FIXTURES_DIR) if f.endswith(".pdf")],
[
f
for f in os.listdir(FIXTURES_DIR)
if f.endswith(".pdf") and f != "encrypted-secret123.pdf"
],
)
def test_process_all_fixtures(self, filename):
result = pdf_inspector.process_pdf(fixture_path(filename))
@@ -401,3 +407,7 @@ class TestMultipleFixtures:
)
assert result.page_count > 0
assert result.confidence >= 0.0
def test_password_protected_fixture_reports_error(self):
with pytest.raises(ValueError, match="encrypted"):
pdf_inspector.process_pdf(fixture_path("encrypted-secret123.pdf"))
+1 -7
View File
@@ -16,7 +16,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
console_error_panic_hook = "0.1"
js-sys = "0.3"
pdf-inspector = { path = ".." }
pdf-inspector = { path = "../.." }
serde = { version = "1", features = ["derive"] }
serde-wasm-bindgen = "0.6"
wasm-bindgen = "0.2"
@@ -24,12 +24,6 @@ wasm-bindgen = "0.2"
[dev-dependencies]
wasm-bindgen-test = "0.3"
[profile.release]
codegen-units = 1
lto = true
opt-level = "s"
strip = true
[package.metadata.wasm-pack.profile.release]
# Rust 1.95 emits bulk-memory instructions that the binaryen bundled with
# wasm-pack 0.15.0 does not yet validate. rustc still performs the release,
+1 -1
View File
@@ -52,7 +52,7 @@ The package also exports:
```bash
cargo install wasm-pack --version 0.15.0 --locked
wasm-pack build wasm --target web --scope firecrawl --release
wasm-pack build bindings/wasm --target web --scope firecrawl --profile wasm-release --no-opt
```
## License
+2 -2
View File
@@ -292,8 +292,8 @@ mod tests {
use js_sys::Reflect;
use wasm_bindgen_test::*;
const TEXT_PDF: &[u8] = include_bytes!("../../tests/fixtures/thermo-freon12.pdf");
const ENCRYPTED_PDF: &[u8] = include_bytes!("../../tests/fixtures/encrypted-secret123.pdf");
const TEXT_PDF: &[u8] = include_bytes!("../../../tests/fixtures/thermo-freon12.pdf");
const ENCRYPTED_PDF: &[u8] = include_bytes!("../../../tests/fixtures/encrypted-secret123.pdf");
fn synthetic_korea1_pdf() -> Vec<u8> {
let mut pdf = b"%PDF-1.4\n".to_vec();
+5 -5
View File
@@ -22,17 +22,17 @@ If `Cargo.toml` changes without a package version bump, the workflow exits witho
## Browser WebAssembly package
The browser package is published as `@firecrawl/pdf-inspector-wasm`. Its version lives in `wasm/Cargo.toml`, and `.github/workflows/publish-wasm.yml` builds the `web` target with `wasm-pack` before publishing the generated package.
The browser package is published as `@firecrawl/pdf-inspector-wasm`. Its version lives in `bindings/wasm/Cargo.toml`, and `.github/workflows/publish-wasm.yml` builds the `web` target with `wasm-pack` before publishing the generated package.
The npm package must exist before a trusted publisher can be configured. For the first release only:
1. Build with `wasm-pack build wasm --target web --scope firecrawl --out-dir pkg --release`.
2. Inspect with `npm pack --dry-run ./wasm/pkg`.
3. Publish with `npm publish ./wasm/pkg --access public` from an authorized maintainer session.
1. Build with `wasm-pack build bindings/wasm --target web --scope firecrawl --out-dir pkg --profile wasm-release --no-opt`.
2. Inspect with `npm pack --dry-run ./bindings/wasm/pkg`.
3. Publish with `npm publish ./bindings/wasm/pkg --access public` from an authorized maintainer session.
4. In the package settings on npm, configure the GitHub Actions trusted publisher:
- Organization: `firecrawl`
- Repository: `pdf-inspector`
- Workflow: `publish-wasm.yml`
- Allowed action: `npm publish`
After that one-time bootstrap, bumping the version in `wasm/Cargo.toml` and merging it to `main` publishes through OIDC. Until the package exists, the workflow exits cleanly without attempting an unauthenticated first publish. See npm's [trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/) for the registry-side setup.
After that one-time bootstrap, bumping the version in `bindings/wasm/Cargo.toml` and merging it to `main` publishes through OIDC. Until the package exists, the workflow exits cleanly without attempting an unauthenticated first publish. See npm's [trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/) for the registry-side setup.
-6
View File
@@ -1,6 +0,0 @@
target/
node_modules/
*.node
# Override root .gitignore — lock file needed for reproducible napi builds
!Cargo.lock
+4 -4
View File
@@ -802,7 +802,7 @@
<p>Emit headings, lists, tables, links, code, emphasis, captions, page markers, and token-efficient cleanup.</p>
</article>
<article class="capability">
<div class="cap-id"><span>06</span><span>napi/</span></div>
<div class="cap-id"><span>06</span><span>bindings/</span></div>
<h3>Packaged for your stack</h3>
<p>Install from npm, PyPI, or crates.io. The npm package also includes TypeScript definitions and the bundled pdf-inspector CLI.</p>
</article>
@@ -915,7 +915,7 @@
console.<span class="fn">log</span>(result.pdfType);
console.<span class="fn">log</span>(result.markdown);
<span class="cm">// </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/napi/README.md">Full Node.js API reference ↗</a></pre></div>
<span class="cm">// </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/bindings/node/README.md">Full Node.js API reference ↗</a></pre></div>
<div class="code-panel" id="panel-cli" role="tabpanel"><pre><span class="cm"># run directly from npm</span>
npx <span class="fn">@firecrawl/pdf-inspector</span> document.pdf
@@ -929,7 +929,7 @@ npm install -g <span class="fn">@firecrawl/pdf-inspector</span>
<span class="cm"># classification only</span>
<span class="fn">pdf-inspector</span> detect document.pdf --json
<span class="cm"># </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/napi/README.md">Node.js and CLI reference ↗</a></pre></div>
<span class="cm"># </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/bindings/node/README.md">Node.js and CLI reference ↗</a></pre></div>
<div class="code-panel" id="panel-python" role="tabpanel"><pre><span class="cm"># pip install pdf-inspector</span>
<span class="kw">import</span> pdf_inspector
@@ -939,7 +939,7 @@ result = pdf_inspector.<span class="fn">process_pdf</span>(<span class="str">"do
<span class="fn">print</span>(result.markdown)
<span class="fn">print</span>(result.pages_needing_ocr)
<span class="cm"># </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/docs/python.md">Full Python API reference ↗</a></pre></div>
<span class="cm"># </span><a href="https://github.com/firecrawl/pdf-inspector/blob/main/bindings/python/README.md">Full Python API reference ↗</a></pre></div>
<div class="code-panel" id="panel-rust" role="tabpanel"><pre><span class="cm">// cargo add pdf-inspector</span>
<span class="kw">use</span> pdf_inspector::process_pdf;
-3
View File
@@ -28,9 +28,6 @@
//! ).unwrap();
//! ```
#[cfg(feature = "python")]
pub mod python;
pub mod adobe_korea1;
pub mod detector;
pub mod extractor;
-1304
View File
File diff suppressed because it is too large Load Diff