Merge main into add-farsi-translation

This commit is contained in:
alam00000 committed 2026-10-22 12:47:54 +05:30
commit 538e940525
365 files changed
+37167 -45078

No files matched your search

+14 -16
View File
@@ -45,7 +45,7 @@ jobs:
run: npm run package
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: |
dist-${{ steps.version.outputs.version }}.zip
@@ -77,10 +77,10 @@ jobs:
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -103,7 +103,7 @@ jobs:
- name: Build and push amd64 ${{ matrix.mode.name }} (release)
if: steps.version.outputs.is_release == 'true'
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
push: true
build-args: |
@@ -111,12 +111,11 @@ jobs:
tags: |
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64
platforms: linux/amd64
cache-from: type=gha,scope=amd64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }}
no-cache: true
- name: Build and push amd64 ${{ matrix.mode.name }} (edge)
if: steps.version.outputs.is_release == 'false'
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
push: true
build-args: |
@@ -146,10 +145,10 @@ jobs:
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -172,7 +171,7 @@ jobs:
- name: Build and push arm64 ${{ matrix.mode.name }} (release)
if: steps.version.outputs.is_release == 'true'
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
push: true
build-args: |
@@ -180,12 +179,11 @@ jobs:
tags: |
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
platforms: linux/arm64
cache-from: type=gha,scope=arm64-${{ matrix.mode.name }}
cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }}
no-cache: true
- name: Build and push arm64 ${{ matrix.mode.name }} (edge)
if: steps.version.outputs.is_release == 'false'
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
push: true
build-args: |
@@ -211,7 +209,7 @@ jobs:
suffix: "-simple"
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -275,14 +273,14 @@ jobs:
suffix: "-simple"
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
+2 -4
View File
@@ -11,7 +11,6 @@ permissions:
actions: write
contents: write
pull-requests: write
statuses: write
jobs:
cla-check:
@@ -28,16 +27,15 @@ jobs:
)
steps:
- name: "CLA Assistant"
uses: contributor-assistant/github-action@v2.6.1
uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT_TOKEN }}
with:
path-to-signatures: 'signatures/cla.json'
path-to-document: 'https://github.com/${{ github.repository }}/blob/main/ICLA.md'
# Branch to store signatures
branch: 'main'
branch: 'cla-signatures'
# Allowlist for bot accounts (won't need to sign CLA)
allowlist: 'bot*,*[bot],dependabot*,renovate*,github-actions*'
+20 -2
View File
@@ -1,12 +1,30 @@
name: Update Sponsors
on:
workflow_dispatch:
schedule:
- cron: '0 6 * * 1'
permissions:
contents: read
jobs:
update:
runs-on: ubuntu-latest
if: github.repository == 'alam00000/bentopdf'
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: JamesIves/github-sponsors-readme-action@v1
- uses: JamesIves/github-sponsors-readme-action@02650b8cd445fc16dfef73195f9c406dce041623 # v1.6.1
with:
token: ${{ secrets.SPONSORS_TOKEN }}
file: 'README.md'
file: 'README.md'
active-only: false
- uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
commit-message: 'docs: update sponsors'
title: 'docs: update sponsors'
body: Updates the sponsors list in the README from GitHub Sponsors.
branch: chore/update-sponsors
delete-branch: true
+8 -8
View File
@@ -28,10 +28,10 @@ jobs:
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Build image for scanning
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
context: .
file: ${{ matrix.image.file }}
@@ -41,7 +41,7 @@ jobs:
no-cache: true
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ matrix.image.name }}:scan
format: sarif
@@ -51,7 +51,7 @@ jobs:
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v4
if: always()
if: always() && hashFiles('trivy-*.sarif') != ''
with:
sarif_file: trivy-${{ matrix.image.name }}.sarif
category: trivy-${{ matrix.image.name }}
@@ -63,7 +63,7 @@ jobs:
uses: actions/checkout@v4
- name: Scan npm dependencies with Trivy
uses: aquasecurity/trivy-action@master
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
scan-type: fs
scan-ref: .
@@ -74,7 +74,7 @@ jobs:
- name: Upload dependency scan results
uses: github/codeql-action/upload-sarif@v4
if: always()
if: always() && hashFiles('trivy-deps.sarif') != ''
with:
sarif_file: trivy-deps.sarif
category: trivy-dependencies
@@ -86,7 +86,7 @@ jobs:
uses: actions/checkout@v4
- name: Scan Dockerfiles for misconfigurations
uses: aquasecurity/trivy-action@master
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
scan-type: config
scan-ref: .
@@ -96,7 +96,7 @@ jobs:
- name: Upload config scan results
uses: github/codeql-action/upload-sarif@v4
if: always()
if: always() && hashFiles('trivy-config.sarif') != ''
with:
sarif_file: trivy-config.sarif
category: trivy-config
+90 -18
View File
@@ -6,8 +6,7 @@ on:
- cron: '17 4 * * *'
permissions:
contents: write
pull-requests: write
contents: read
concurrency:
group: update-engine
@@ -18,12 +17,19 @@ env:
HUSKY: 0
jobs:
update:
build:
runs-on: ubuntu-latest
if: github.repository == 'alam00000/bentopdf'
permissions:
contents: read
outputs:
run: ${{ steps.gate.outputs.run }}
version: ${{ steps.gate.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Read current upstream marker
id: current
@@ -40,13 +46,21 @@ jobs:
- name: Should update?
id: gate
env:
CURRENT: ${{ steps.current.outputs.version }}
UPSTREAM: ${{ steps.upstream.outputs.version }}
run: |
if [ "${{ steps.upstream.outputs.version }}" = "${{ steps.current.outputs.version }}" ]; then
if ! [[ "$UPSTREAM" =~ ^[0-9a-f]{12}$ ]]; then
echo "::error::Unexpected fork HEAD: $UPSTREAM"
exit 1
fi
echo "version=$UPSTREAM" >> "$GITHUB_OUTPUT"
if [ "$UPSTREAM" = "$CURRENT" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
echo "Already on ${{ steps.current.outputs.version }}."
echo "Already on $CURRENT."
else
echo "run=true" >> "$GITHUB_OUTPUT"
echo "Updating ${{ steps.current.outputs.version }} -> ${{ steps.upstream.outputs.version }}"
echo "Updating $CURRENT -> $UPSTREAM"
fi
- name: Setup Node
@@ -73,9 +87,10 @@ jobs:
- name: Pack the engine
if: steps.gate.outputs.run == 'true'
id: engine
env:
SHA: ${{ steps.gate.outputs.version }}
run: |
set -euo pipefail
SHA=${{ steps.upstream.outputs.version }}
VENDOR=./_fork/packages/pdfium/src/vendor
STAGE=$(mktemp -d)/package
mkdir -p "$STAGE"
@@ -107,9 +122,10 @@ jobs:
- name: Pack the viewer without a second engine
if: steps.gate.outputs.run == 'true'
id: viewer
env:
SHA: ${{ steps.gate.outputs.version }}
run: |
set -euo pipefail
SHA=${{ steps.upstream.outputs.version }}
WORK=$(mktemp -d)
(cd ./_fork && npm pack ./viewers/snippet --pack-destination "$WORK" >/dev/null)
TMP=$(mktemp -d)
@@ -137,14 +153,17 @@ jobs:
- name: Point dependencies at the new tarballs
if: steps.gate.outputs.run == 'true'
env:
ENGINE_TARBALL: ${{ steps.engine.outputs.tarball }}
VIEWER_TARBALL: ${{ steps.viewer.outputs.tarball }}
run: |
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg.dependencies['bentopdf-pdfium'] = 'file:' + process.argv[1];
pkg.dependencies['bentopdf-viewer'] = 'file:' + process.argv[2];
pkg.dependencies['bentopdf-pdfium'] = 'file:' + process.env.ENGINE_TARBALL;
pkg.dependencies['bentopdf-viewer'] = 'file:' + process.env.VIEWER_TARBALL;
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
" "${{ steps.engine.outputs.tarball }}" "${{ steps.viewer.outputs.tarball }}"
"
- name: Cleanup upstream clone
if: steps.gate.outputs.run == 'true'
@@ -174,19 +193,66 @@ jobs:
- name: Write upstream marker
if: steps.gate.outputs.run == 'true'
env:
SHA: ${{ steps.gate.outputs.version }}
run: |
echo "${{ steps.upstream.outputs.version }}" > vendor/bentopdf-viewer/.upstream-version
echo "${{ steps.upstream.outputs.version }}" > vendor/bentopdf-pdfium/.upstream-version
echo "$SHA" > vendor/bentopdf-viewer/.upstream-version
echo "$SHA" > vendor/bentopdf-pdfium/.upstream-version
- name: Upload update
if: steps.gate.outputs.run == 'true'
uses: actions/upload-artifact@v4
with:
name: engine-update
include-hidden-files: true
retention-days: 1
path: |
package.json
package-lock.json
vendor/bentopdf-pdfium/
vendor/bentopdf-viewer/
pull-request:
runs-on: ubuntu-latest
needs: build
if: needs.build.outputs.run == 'true'
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Download update
uses: actions/download-artifact@v4
with:
name: engine-update
path: ${{ runner.temp }}/engine-update
- name: Apply update
id: apply
env:
UPDATE: ${{ runner.temp }}/engine-update
run: |
set -euo pipefail
rm -rf vendor/bentopdf-pdfium vendor/bentopdf-viewer
mkdir -p vendor
cp -R "$UPDATE/vendor/bentopdf-pdfium" "$UPDATE/vendor/bentopdf-viewer" vendor/
cp "$UPDATE/package.json" "$UPDATE/package-lock.json" .
{
echo 'checksums<<EOF'
sha256sum vendor/bentopdf-pdfium/*.tgz vendor/bentopdf-viewer/*.tgz
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Create Pull Request
if: steps.gate.outputs.run == 'true'
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
commit-message: 'build(deps): bump PDF engine and viewer to ${{ steps.upstream.outputs.version }}'
title: 'build(deps): bump PDF engine and viewer to ${{ steps.upstream.outputs.version }}'
commit-message: 'build(deps): bump PDF engine and viewer to ${{ needs.build.outputs.version }}'
title: 'build(deps): bump PDF engine and viewer to ${{ needs.build.outputs.version }}'
body: |
Both vendored packages built from one clone of the viewer fork at
`${{ steps.upstream.outputs.version }}`, so the text editor and the
`${{ needs.build.outputs.version }}`, so the text editor and the
PDF editor run the same engine.
- `bentopdf-pdfium` — the engine wasm, packed from the fork's published `src/vendor`
@@ -194,5 +260,11 @@ jobs:
The viewer loads the shared engine through `EmbedPDF.init({ wasmUrl })`.
CI verified a single wasm on disk, typecheck, and the test suite.
Built in a read-only job. Tarball checksums:
```
${{ steps.apply.outputs.checksums }}
```
branch: chore/update-pdf-engine
delete-branch: true
+7
View File
@@ -54,3 +54,10 @@ test
# Sibling checkouts of the engine/viewer forks
bentopdf-pdfium-viewer/
bentopdf-pymupdf-wasm/
/blog/*.html
!/blog/author-alam.html
/src/partials/tool-links-static.html
/security-headers-docs.conf
/dist-*.zip
/docs/.vitepress/cache/
+4 -4
View File
@@ -12,7 +12,7 @@ Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Embedder-Policy "require-corp"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-eval' blob: https://cdn.jsdelivr.net; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' blob: https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-src 'self' blob:; frame-ancestors 'self'; form-action 'self'"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-eval' blob: https://cdn.jsdelivr.net/npm/@bentopdf/pymupdf-wasm@0.11.16/ https://cdn.jsdelivr.net/npm/@bentopdf/gs-wasm@0.1.1/assets/ https://cdn.jsdelivr.net/npm/coherentpdf@2.5.5/dist/ https://cdn.jsdelivr.net/npm/tesseract.js@v7.0.0/dist/ https://cdn.jsdelivr.net/npm/tesseract.js-core@v7.0.0/; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' blob: https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-src 'self' blob:; frame-ancestors 'self'; form-action 'self'"
</IfModule>
# Block source maps from being served
@@ -99,7 +99,7 @@ RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove trailing slash (except for language root directories)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/$
RewriteCond %{REQUEST_URI} !^/(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/$
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
@@ -117,11 +117,11 @@ RewriteRule ^en/(.+)$ /$1 [R=301,L]
# Language prefix root (e.g., /de/ -> /de/index.html)
RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/?$ /$1/index.html [L]
RewriteRule ^(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/?$ /$1/index.html [L]
# Language prefix with path (e.g., /de/merge-pdf -> /de/merge-pdf.html)
RewriteCond %{DOCUMENT_ROOT}/$1/$2.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/([^/]+)/?$ /$1/$2.html [L]
RewriteRule ^(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/([^/]+)/?$ /$1/$2.html [L]
# ============================================
# 5.5. DOCS ROUTING (VitePress)
+5
View File
@@ -1,2 +1,7 @@
# Handlebars partials with template syntax inside HTML attributes
src/partials/footer.html
blog/posts/
public/pdfjs-viewer/
public/pdfjs-annotation-viewer/
+1 -1
View File
@@ -3,7 +3,7 @@
ARG BASE_URL=
# Build stage
FROM public.ecr.aws/docker/library/node:20-alpine AS builder
FROM mirror.gcr.io/library/node:26-alpine AS builder
WORKDIR /app
COPY package*.json ./
COPY vendor ./vendor
+1 -1
View File
@@ -5,7 +5,7 @@
ARG BASE_URL=
# Build stage (identical to main Dockerfile)
FROM public.ecr.aws/docker/library/node:20-alpine AS builder
FROM mirror.gcr.io/library/node:26-alpine AS builder
WORKDIR /app
COPY package*.json ./
COPY vendor ./vendor
+18 -8
View File
@@ -1,8 +1,13 @@
<p align="center"><img src="public/images/favicon-no-bg.svg" width="80"></p>
<h1 align="center">BentoPDF</h1>
<p align="center"><sub>Supported by</sub></p>
<p align="center">
<a href="https://vercel.com/open-source-program">
<img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge-2026.svg" height="30" />
</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://www.digitalocean.com/?refcode=d93c189ef6d0&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge">
<img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%203.svg" alt="DigitalOcean Referral Badge">
<img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%203.svg" alt="DigitalOcean Referral Badge" height="44">
</a>
</p>
@@ -29,6 +34,7 @@
- [Convert to PDF](#convert-to-pdf)
- [Convert from PDF](#convert-from-pdf)
- [Secure & Optimize PDFs](#secure--optimize-pdfs)
- [Other Products](#-other-products)
- [Translations](#-translations)
- [Getting Started](#-getting-started)
- [Prerequisites](#prerequisites)
@@ -124,8 +130,7 @@ We're incredibly grateful to all our sponsors and supporters who help keep Bento
[![Sponsor me on GitHub](https://img.shields.io/badge/Become%20a%20Sponsor-%E2%9D%A4-ff69b4?style=for-the-badge)](https://github.com/sponsors/alam00000)
[![Buy me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?style=for-the-badge&logo=kofi)](https://ko-fi.com/alio01)
<!-- sponsors -->
<!-- sponsors -->
<!-- sponsors --><a href="https://github.com/gaedeke"><img src="https:&#x2F;&#x2F;github.com&#x2F;gaedeke.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/stiflerbox"><img src="https:&#x2F;&#x2F;github.com&#x2F;stiflerbox.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/shollyethan"><img src="https:&#x2F;&#x2F;github.com&#x2F;shollyethan.png" width="60px" alt="User avatar: Ethan Sholly" /></a><a href="https://github.com/KnudH"><img src="https:&#x2F;&#x2F;github.com&#x2F;KnudH.png" width="60px" alt="User avatar: Knud Hollander" /></a><a href="https://github.com/mohannadhussain"><img src="https:&#x2F;&#x2F;github.com&#x2F;mohannadhussain.png" width="60px" alt="User avatar: Mohannad Hussain" /></a><a href="https://github.com/chaoscastle"><img src="https:&#x2F;&#x2F;github.com&#x2F;chaoscastle.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/RobertGonzales1"><img src="https:&#x2F;&#x2F;github.com&#x2F;RobertGonzales1.png" width="60px" alt="User avatar: Robert Gonzales" /></a><a href="https://github.com/michivonah"><img src="https:&#x2F;&#x2F;github.com&#x2F;michivonah.png" width="60px" alt="User avatar: Michi" /></a><a href="https://github.com/bmikaili"><img src="https:&#x2F;&#x2F;github.com&#x2F;bmikaili.png" width="60px" alt="User avatar: Berzan" /></a><a href="https://github.com/Thanyanit-J"><img src="https:&#x2F;&#x2F;github.com&#x2F;Thanyanit-J.png" width="60px" alt="User avatar: Thanyanit Jongjitragan" /></a><a href="https://github.com/AceofSpades5757"><img src="https:&#x2F;&#x2F;github.com&#x2F;AceofSpades5757.png" width="60px" alt="User avatar: Kyle L. Davis" /></a><a href="https://github.com/Jacco011"><img src="https:&#x2F;&#x2F;github.com&#x2F;Jacco011.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/Pallandos"><img src="https:&#x2F;&#x2F;github.com&#x2F;Pallandos.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/haritvsmurali"><img src="https:&#x2F;&#x2F;github.com&#x2F;haritvsmurali.png" width="60px" alt="User avatar: Hari Haran" /></a><a href="https://github.com/mrtoadie"><img src="https:&#x2F;&#x2F;github.com&#x2F;mrtoadie.png" width="60px" alt="User avatar: Toadie" /></a><a href="https://github.com/sam12dr21"><img src="https:&#x2F;&#x2F;github.com&#x2F;sam12dr21.png" width="60px" alt="User avatar: " /></a><!-- sponsors -->
---
@@ -175,6 +180,7 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs.
| Tool Name | Description |
| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **PDF Editor** | Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs. |
| **Edit PDF Text** | Edit existing text directly in your PDF. Reuses the document's embedded fonts and keeps the rest of the page untouched. |
| **Create Fillable Forms** | Create professional fillable PDF forms with text fields, checkboxes, dropdowns, radio buttons, signatures, and more. Fully compliant with PDF standards for compatibility with all PDF viewers. |
| **PDF Form Filler** | Fill in forms directly in the browser. Also supports XFA forms. |
| **Add Page Numbers** | Easily add page numbers with customizable formatting. |
@@ -1219,16 +1225,20 @@ BentoPDF was originally built using **HTML**, **CSS**, and **vanilla JavaScript*
---
## 📦 Other Products
| Product | Description | Links |
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------- |
| **Kura** | PDF standards and preflight engine. Converts to every PDF/A level, PDF/UA, PDF/X, PDF/E and PDF/VT, and can perform preflight checks. | [Website](https://kura.bentopdf.com) · [GitHub](https://github.com/alam00000/bentopdf-kura) |
| **Hyper Compress** | The best open source PDF compression engine. | [Website](https://hyper.bentopdf.com) · [GitHub](https://github.com/alam00000/bentopdf-hyper-compress) |
---
## 🗺️ Roadmap
### Planned Features:
- **HTML to PDF**: Convert HTML files or web pages into PDF documents.
- **Markdown to PDF**: Enhanced support for converting `.md` files to PDF.
- **Convert to PDF/A**: Convert PDFs to the PDF/A archival format.
- **Edit PDF Content**: Directly edit text and other content within your PDF.
- **PDF to Office**: Converts PDF files into editable Word, Excel, and PowerPoint formats.
- **Office to PDF**: Converts Word, Excel, and PowerPoint documents into optimized PDFs.
Contributions and discussions on the roadmap are welcome! Join the conversation via [Discord](https://discord.gg/Bgq3Ay3f2w).
+11
View File
@@ -62,6 +62,17 @@ When the build completes, you can find the website at `https://[your-github-user
If/when you merge changes from the source BentoPDF repository, the build and deploy action will automatically be kicked off and the new version will be automatically deployed to GitHub Pages.
> **Note:** GitHub Pages cannot set custom response headers, so a GitHub Pages deployment is served without BentoPDF's Content-Security-Policy and other security headers. If you need them, use one of the other hosts below or put a proxy or CDN that can add headers in front of your Pages site.
## Security headers
BentoPDF ships a Content-Security-Policy and other security headers for each static host:
- **Netlify and Cloudflare Pages** read `_headers` from the deployed folder. `npm run build` writes `dist/_headers` with `scripts/generate-security-headers.mjs`, so any `VITE_WASM_*`, `VITE_TESSERACT_*`, `VITE_CORS_PROXY_URL` or `VITE_OCR_FONT_BASE_URL` values you set at build time are allowed by the policy. If you add your own `public/_headers`, the build ships yours instead. The release `dist-{version}.zip` already contains it.
- **Vercel** uses the `headers` block in `vercel.json`. It holds the default policy, so if you point the `VITE_*` URLs at your own servers, update the Content-Security-Policy there to match the `dist/_headers` your build produces.
- **`npx serve`** reads `serve.json` from the folder it serves. To use the repository's `serve.json` with the build output, run `npx serve dist -c ../serve.json`.
- **GitHub Pages** cannot set headers (see the note above).
## SEO and search engine indexing
By default, every self-hosted BentoPDF build emits canonical URLs and an
+253 -192
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Primary Meta Tags -->
<title>About BentoPDF - Privacy-First Free PDF Tools | Our Mission</title>
<title>About BentoPDF - Privacy-First Free PDF Tools | Our Story</title>
<meta
name="description"
content="Learn about BentoPDF - 100% free, privacy-first PDF toolkit. All tools run in your browser, no uploads, no signup. Fast, secure, and forever free."
@@ -51,6 +51,7 @@
<meta name="twitter:site" content="@BentoPDF" />
<link href="/src/css/styles.css" rel="stylesheet" />
<link href="/src/css/landing.css" rel="stylesheet" />
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest" />
@@ -77,220 +78,267 @@
<link rel="icon" href="/favicon.ico" sizes="32x32" />
</head>
<body class="antialiased bg-gray-900 text-gray-300">
<body class="lp antialiased">
{{> navbar }}
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
<section id="about-hero" class="text-center py-16 md:py-24">
<h1 class="text-3xl md:text-6xl font-bold text-white mb-4">
<span data-i18n="about.hero.title"
>We believe PDF tools should be</span
>
<span class="marker-slanted" data-i18n="about.hero.subtitle"
>fast, private, and free.</span
>
</h1>
<p
class="text-lg md:text-xl text-gray-400"
data-i18n="about.hero.noCompromises"
>
No compromises.
</p>
</section>
<div class="section-divider"></div>
<section id="mission-section" class="py-16 max-w-4xl mx-auto">
<div class="text-center">
<i
data-lucide="rocket"
class="w-16 h-16 text-indigo-400 mx-auto mb-6"
></i>
<h2
class="text-3xl md:text-4xl font-bold text-white mb-4"
data-i18n="about.mission.title"
>
Our Mission
</h2>
<p
class="text-lg text-gray-400 leading-relaxed"
data-i18n="about.mission.description"
>
To provide the most comprehensive PDF toolbox that respects your
privacy and never asks for payment. We believe essential document
tools should be accessible to everyone, everywhere, without
barriers.
</p>
</div>
</section>
<div
class="bg-gray-800 rounded-xl p-8 md:p-12 my-16 border border-gray-700"
>
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
<div class="text-center md:text-left">
<span
class="text-indigo-400 font-bold uppercase"
data-i18n="about.philosophy.label"
>Our Core Philosophy</span
<div id="app">
<section id="story-section" class="lp-sec lp-sec--first">
<div class="lp-frame">
<div class="lp-story">
<div class="lp-story-head">
<h1 class="lp-h2">
<span class="line">Hi, I'm Alam.</span>
<span class="line dim">I build BentoPDF.</span>
</h1>
<div class="lp-story-by">
<img
class="lp-avatar"
src="/images/author-alam.jpg"
alt="Alam"
width="44"
height="44"
/>
<a
href="https://github.com/alam00000"
target="_blank"
rel="me noopener noreferrer"
>GitHub</a
>
<a
href="https://www.linkedin.com/in/abdullah-alam01/"
target="_blank"
rel="me noopener noreferrer"
>LinkedIn</a
>
<a
href="https://x.com/alamdraws"
target="_blank"
rel="me noopener noreferrer"
>X</a
>
</div>
</div>
<div class="lp-story-body">
<p>
BentoPDF started off as just a simple internal tool I used for
quickly merging and splitting PDFs.
</p>
<p>
At some point, I decided to
<a
href="https://www.reddit.com/r/webdev/comments/1nr937y/i_made_bentopdf_a_privacy_first_pdf_toolkit_that/"
target="_blank"
rel="noopener noreferrer"
>share it on Reddit</a
>. Someone in the comments
<a
href="https://www.reddit.com/r/webdev/comments/1nr937y/comment/ngdeqby/"
target="_blank"
rel="noopener noreferrer"
>asked if it was open source</a
>. I thought, “Why not?” So a couple of weeks later, I
<a
href="https://github.com/alam00000/bentopdf"
target="_blank"
rel="noopener noreferrer"
>put the code on GitHub</a
>.
</p>
<p>
I posted it on
<a
href="https://www.reddit.com/r/selfhosted/comments/1o5borw/bentopdf_is_a_self_hostable_pdf_toolkit/"
target="_blank"
rel="noopener noreferrer"
>r/selfhosted</a
>
the next day, and that's when things really started to take off.
</p>
<p>
I honestly never thought BentoPDF would grow into what it is
today. It started as a little tool I made for myself, and
somehow it turned into a much bigger project used by people all
over the world.
</p>
</div>
</div>
<div class="lp-grid lp-grid--4 lp-cross">
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
<b>15K+</b><span>GitHub stars</span>
</div>
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
<b>10M+</b><span>Downloads</span>
</div>
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
<b>1.3K+</b><span>Forks</span>
</div>
<a
href="https://github.com/alam00000/bentopdf/graphs/contributors"
target="_blank"
rel="noopener noreferrer"
class="lp-cell lp-stat lp-cell--raised lp-reveal lp-stat-link"
>
<h2
class="text-3xl md:text-4xl font-bold text-white mt-2 mb-4"
data-i18n="about.philosophy.title"
>
Privacy First. Always.
</h2>
<p
class="text-gray-400 leading-relaxed"
data-i18n="about.philosophy.description"
>
In an era where data is a commodity, we take a different approach.
All processing for BentoPDF tools happens locally in your browser.
This means your files never touch our servers, we never see your
documents, and we don't track what you do. Your documents remain
completely and unequivocally private. It's not just a feature;
it's our foundation.
<b>60+</b
><span>Contributors <i data-lucide="arrow-up-right"></i></span>
</a>
</div>
<div class="lp-story-outro">
<p>
I don't build BentoPDF alone anymore. More than 60 people have
contributed code, translations and fixes, and thousands more have
starred it, shared it, reported bugs and asked for features. Thank
you.
</p>
<p>Enough about me. Here's more about BentoPDF.</p>
</div>
<div class="flex justify-center">
<div class="relative w-48 h-48">
<div
class="absolute inset-0 bg-indigo-500 rounded-full opacity-20 animate-pulse"
></div>
<div
class="absolute inset-4 bg-indigo-500 rounded-full opacity-30 animate-pulse delay-500"
></div>
<i
data-lucide="shield-check"
class="w-48 h-48 text-indigo-400"
></i>
</div>
</section>
<section id="mission-section" class="lp-sec lp-band">
<div class="lp-frame">
<figure class="lp-manifesto lp-reveal">
<h2 class="lp-h2">
<span class="line" data-i18n="about.mission.title">Our</span>
<span class="line dim" data-i18n="about.mission.titleDim"
>Mission</span
>
</h2>
<blockquote
class="lp-manifesto-text"
data-i18n="about.mission.description"
>
To provide the most comprehensive PDF toolbox that respects your
privacy and never asks for payment. We believe essential document
tools should be accessible to everyone, everywhere, without
barriers.
</blockquote>
</figure>
</div>
</section>
<section id="philosophy-section" class="lp-sec">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line" data-i18n="about.hero.title"
>PDF tools should be</span
>
<span class="line dim" data-i18n="about.hero.subtitle"
>fast, private, and free.</span
>
</h2>
<p class="lp-head-p" data-i18n="about.hero.noCompromises">
No compromises.
</p>
<p class="lp-head-p" data-i18n="about.philosophy.description">
Every BentoPDF tool runs locally in your browser. Your files are
never uploaded, nobody else sees your documents, and nothing
tracks what you do.
</p>
</div>
</div>
<div class="lp-grid lp-grid--3 lp-cross">
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
<b>0</b
><span data-i18n="features.noUploads.title">No Uploads</span>
</div>
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
<b>0</b><span data-i18n="hero.noSignups">No Signups</span>
</div>
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
<b>$0</b
><span data-i18n="features.foreverFree.title">Forever Free</span>
</div>
</div>
</div>
</div>
</section>
<section id="why-Bentopdf" class="py-16">
<h2 class="text-3xl md:text-4xl font-bold text-center text-white mb-12">
<span data-i18n="about.whyBentopdf.title">Why</span>
<span class="marker-slanted">BentoPDF?</span>
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
<i
data-lucide="zap"
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
></i>
<section id="why-bentopdf" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h3
class="text-xl font-bold text-white"
data-i18n="about.whyBentopdf.speed.title"
>
Built for Speed
</h3>
<p
class="text-gray-400 mt-2"
data-i18n="about.whyBentopdf.speed.description"
>
No waiting for uploads or downloads to a server. By processing
files directly in your browser using modern web technologies
like WebAssembly, we offer unparalleled speed for all our tools.
</p>
<h2 class="lp-h2">
<span class="line" data-i18n="about.whyBentopdf.title"
>Why</span
>
<span class="line dim">BentoPDF?</span>
</h2>
</div>
</div>
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
<i
data-lucide="badge-dollar-sign"
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
></i>
<div>
<h3
class="text-xl font-bold text-white"
data-i18n="about.whyBentopdf.free.title"
>
Completely Free
</h3>
<p
class="text-gray-400 mt-2"
data-i18n="about.whyBentopdf.free.description"
>
No trials, no subscriptions, no hidden fees, and no "premium"
features held hostage. We believe powerful PDF tools should be a
public utility, not a profit center.
<div class="lp-grid lp-grid--2 lp-cross">
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="zap"></i></span>
<h3 data-i18n="about.whyBentopdf.speed.title">Built for Speed</h3>
<p data-i18n="about.whyBentopdf.speed.description">
There's no upload or download step. Files are processed right in
your browser using WebAssembly, so you're never waiting on a
server.
</p>
</div>
</div>
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
<i
data-lucide="user-plus"
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
></i>
<div>
<h3
class="text-xl font-bold text-white"
data-i18n="about.whyBentopdf.noAccount.title"
>
<div class="lp-cell lp-reveal">
<span class="lp-tile"
><i data-lucide="badge-dollar-sign"></i
></span>
<h3 data-i18n="about.whyBentopdf.free.title">Free to Use</h3>
<p data-i18n="about.whyBentopdf.free.description">
Every tool is free, with no trials, no subscriptions and no
watermarks. Development is funded by commercial licenses.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="user-plus"></i></span>
<h3 data-i18n="about.whyBentopdf.noAccount.title">
No Account Required
</h3>
<p
class="text-gray-400 mt-2"
data-i18n="about.whyBentopdf.noAccount.description"
>
Start using any tool immediately. We don't need your email, a
password, or any personal information. Your workflow should be
frictionless and anonymous.
<p data-i18n="about.whyBentopdf.noAccount.description">
Open any tool and start right away. No email, no password, no
personal information.
</p>
</div>
</div>
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
<i
data-lucide="code-2"
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
></i>
<div>
<h3
class="text-xl font-bold text-white"
data-i18n="about.whyBentopdf.openSource.title"
>
Open Source Spirit
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="code-2"></i></span>
<h3 data-i18n="about.whyBentopdf.openSource.title">
Open Source
</h3>
<p
class="text-gray-400 mt-2"
data-i18n="about.whyBentopdf.openSource.description"
>
Built with transparency in mind. We leverage incredible
open-source libraries like PDF-lib and PDF.js, and believe in
the community-driven effort to make powerful tools accessible to
everyone.
<p data-i18n="about.whyBentopdf.openSource.description">
The code is public on GitHub under AGPL-3.0, so you can check
exactly how your files are handled. It builds on open-source
projects like PDF.js, pdf-lib, qpdf and LibreOffice.
</p>
</div>
</div>
</div>
</section>
<div class="section-divider"></div>
<section id="cta-section" class="text-center py-16">
<h2
class="text-3xl font-bold text-white mb-4"
data-i18n="about.cta.title"
>
Ready to get started?
</h2>
<p
class="text-lg text-gray-400 mb-8 max-w-2xl mx-auto"
data-i18n="about.cta.description"
>
Join thousands of users who trust BentoPDF for their daily document
needs. Experience the difference that privacy and performance can
make.
</p>
<a
href="index.html#tools-header"
class="inline-block px-8 py-3 rounded-full bg-gradient-to-b from-indigo-500 to-indigo-600 text-white font-semibold focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900 focus:ring-indigo-400 hover:shadow-xl hover:shadow-indigo-500/30 transition-all duration-200 transform hover:-translate-y-1"
data-i18n="about.cta.button"
>
Explore All Tools
</a>
<section id="cta-section" class="lp-sec">
<div class="lp-frame">
<div class="lp-cta">
<h2 class="lp-h2" data-i18n="about.cta.title">
Ready to get started?
</h2>
<p data-i18n="about.cta.description">
Join thousands of users who trust BentoPDF for their daily
document needs. Experience the difference that privacy and
performance can make.
</p>
<div class="lp-cta-actions">
<span class="lp-brackets">
<a
href="index.html#tools-header"
class="lp-btn lp-btn--primary"
>
<span data-i18n="about.cta.button">Explore All Tools</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
<a href="https://bentopdf.com/docs/" class="lp-btn lp-btn--ghost">
<i data-lucide="book-open"></i>
<span data-i18n="nav.docs">Docs</span>
</a>
</div>
</div>
</div>
</section>
</div>
@@ -299,6 +347,7 @@
<script type="module" src="src/js/utils/lucide-init.ts"></script>
<script type="module" src="src/js/main.ts"></script>
<script type="module" src="src/js/mobileMenu.ts"></script>
<script type="module" src="src/js/landing.ts"></script>
<!-- JSON-LD Schema -->
<script type="application/ld+json">
@@ -306,8 +355,20 @@
"@context": "https://schema.org",
"@type": "AboutPage",
"name": "About BentoPDF",
"description": "Learn about BentoPDF's mission to provide free, privacy-first PDF tools",
"url": "https://www.bentopdf.com/about"
"description": "How BentoPDF started, told by its creator Alam",
"url": "https://www.bentopdf.com/about",
"mainEntity": {
"@type": "Person",
"name": "Alam",
"url": "https://www.bentopdf.com/blog/author-alam",
"image": "https://www.bentopdf.com/images/author-alam.jpg",
"jobTitle": "Creator and maintainer of BentoPDF",
"sameAs": [
"https://github.com/alam00000",
"https://www.linkedin.com/in/abdullah-alam01/",
"https://x.com/alamdraws"
]
}
}
</script>
</body>
+149
View File
@@ -0,0 +1,149 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Alam, Creator of BentoPDF</title>
<meta
name="description"
content="Alam builds BentoPDF, the open-source, privacy-first PDF toolkit that runs entirely in your browser. Every post on this blog is written by him."
/>
<meta name="robots" content="index, follow" />
<link rel="canonical" href="https://www.bentopdf.com/blog/author-alam" />
<meta property="og:type" content="profile" />
<meta
property="og:url"
content="https://www.bentopdf.com/blog/author-alam"
/>
<meta property="og:title" content="Alam, Creator of BentoPDF" />
<meta
property="og:description"
content="The maintainer behind BentoPDF and the author of every post on this blog."
/>
<meta
property="og:image"
content="https://www.bentopdf.com/images/author-alam.jpg"
/>
<meta property="og:site_name" content="BentoPDF" />
<meta name="twitter:card" content="summary" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
<link rel="icon" href="/favicon.ico" sizes="32x32" />
<link href="/src/css/styles.css" rel="stylesheet" />
</head>
<body class="antialiased bg-gray-900">
{{> navbar }}
<section class="max-w-3xl mx-auto px-4 py-12">
<div class="flex items-center gap-5 mb-8">
<img
src="/images/author-alam.jpg"
alt="Alam"
width="80"
height="80"
class="rounded-full"
/>
<div>
<h1 class="text-3xl font-bold text-white">Alam</h1>
<p class="text-gray-400">Creator and maintainer of BentoPDF</p>
</div>
</div>
<p class="text-gray-300 leading-relaxed mb-5">
I’m Alam, and I build
<a href="/" class="text-indigo-300 hover:text-indigo-400">BentoPDF</a>,
a free, open-source PDF toolkit with 100+ tools that run entirely in
your browser.
</p>
<p class="text-gray-300 leading-relaxed mb-5">
There’s no uploading your files to a server, no account to create, and
no tracking. Your documents stay on your device. The
<a
href="https://github.com/alam00000/bentopdf"
rel="noopener"
class="text-indigo-300 hover:text-indigo-400"
>source code</a
>
is public, so you can see how it works yourself. BentoPDF is
AGPL-licensed and self-hostable.
</p>
<p class="text-gray-300 leading-relaxed mb-5">
I write every post on this blog myself. I’ll write about PDFs, how they
work, things I learn while building BentoPDF, and occasionally things
that go wrong.
</p>
<p class="text-gray-300 leading-relaxed mb-5">
When I compare BentoPDF with another PDF tool, I’ll link to its
documentation so you can check what I’m saying. If there’s something
BentoPDF doesn’t do well, I’ll say that too.
</p>
<p class="text-gray-300 leading-relaxed mb-5">
And if I get something wrong, please
<a
href="https://github.com/alam00000/bentopdf/issues"
rel="noopener"
class="text-indigo-300 hover:text-indigo-400"
>open an issue</a
>. I’ll fix it and add a note to the post.
</p>
<p class="text-gray-300 leading-relaxed mb-5">
You can find me on
<a
href="https://github.com/alam00000"
rel="me noopener"
class="text-indigo-300 hover:text-indigo-400"
>GitHub</a
>,
<a
href="https://www.linkedin.com/in/abdullah-alam01/"
rel="me noopener"
class="text-indigo-300 hover:text-indigo-400"
>LinkedIn</a
>
and
<a
href="https://x.com/alamdraws"
rel="me noopener"
class="text-indigo-300 hover:text-indigo-400"
>X</a
>.
</p>
<p class="text-gray-300 leading-relaxed">
<a
href="/blog"
class="inline-flex items-center gap-2 text-indigo-300 hover:text-indigo-400 font-semibold"
>Read the blog <i class="ph ph-arrow-right" aria-hidden="true"></i
></a>
</p>
</section>
{{> footer }}
<script type="module" src="/src/js/utils/lucide-init.ts"></script>
<script type="module">
import '@phosphor-icons/web/regular';
</script>
<script type="module" src="/src/js/mobileMenu.ts"></script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfilePage",
"mainEntity": {
"@type": "Person",
"name": "Alam",
"url": "https://www.bentopdf.com/blog/author-alam",
"image": "https://www.bentopdf.com/images/author-alam.jpg",
"jobTitle": "Creator and maintainer of BentoPDF",
"sameAs": [
"https://github.com/alam00000",
"https://www.linkedin.com/in/abdullah-alam01/",
"https://x.com/alamdraws"
]
}
}
</script>
</body>
</html>
+134
View File
@@ -0,0 +1,134 @@
---
{
"title": "How to Edit a PDF Without Uploading It Anywhere | BentoPDF Blog",
"h1": "How to edit a PDF without uploading it anywhere",
"ogTitle": "How to Edit a PDF Without Uploading It Anywhere",
"breadcrumb": "Edit a PDF without uploading",
"description": "Edit PDF text, fill forms, redact, and sign in your browser while the file stays on your device. Step by step, with the right tool for each job.",
"card": "Rewrite text, fill forms, redact properly, and sign, locally on your device.",
"date": "2026-09-03",
"cta": {
"heading": "Edit your PDF now",
"text": "Free, no signup. Your file stays on your device.",
"href": "/edit-pdf",
"label": "Open the PDF editor"
}
}
---
You can edit a PDF in your browser without uploading the file to a server.
Open [BentoPDF's PDF editor](/edit-pdf), pick your file, make your changes, and download the result. The PDF stays on your device. There's no account and no watermark.
But “edit a PDF” can mean a few different things. You might want to change existing text, fill out a form, add a signature, redact something, or just highlight a paragraph. The right tool depends on what you're trying to do.
## Why edit a PDF without uploading it?
Think about the PDFs you normally edit.
Contracts. Bank statements. Tax documents. Forms with your address or ID number.
Those aren't necessarily files you want to upload to a random “free PDF editor.”
With an on-device PDF editor, the file stays on your computer while you're working on it.
You can even check this yourself. Open your browser's developer tools, go to the Network tab, and watch what happens while you edit. The PDF itself doesn't need to be sent to a server.
## How to edit the actual text in a PDF
If you want to change words that are already in the PDF, use [Edit PDF Text](/edit-pdf-text).
1. Open the tool.
2. Drop in your PDF.
3. Click on the text you want to change.
4. Type your changes.
5. Download the edited PDF.
BentoPDF loads the PDF in your browser and does the editing on your device.
This is one of the harder things to do with PDFs because PDF text doesn't work quite like text in a Word document. The PDF is mostly concerned with putting things at particular positions on a page, so changing a sentence can mean figuring out how the surrounding text should move.
It works well for ordinary documents, but PDFs with unusual embedded fonts or very complicated layouts can be trickier. I'd always open the downloaded PDF and check it.
## How to annotate a PDF
If you don't need to change the existing text, annotating a PDF is much simpler.
The [PDF editor](/edit-pdf) lets you add highlights, comments, shapes, stamps, text boxes, and images.
Open the PDF, add your annotations, and download the result.
Again, the editing happens in your browser rather than on a remote server.
## How to fill out a PDF form
There are two common kinds of PDF forms.
If the PDF has actual form fields, open it in [PDF Form Filler](/form-filler) and type into the fields. It handles standard AcroForm fields, and also XFA forms, which are the legacy XML-based format. XFA is worth calling out because Chrome and most other viewers show those files as blank pages, which is why some government forms tell you to open them in Adobe Reader. Firefox and BentoPDF's form filler render them properly.
If it's a scanned or flattened form, there aren't any fields to click. In that case, you can put text boxes over the blank spaces in the [PDF editor](/edit-pdf) and type into them. If you'd rather have real fields, [Create PDF Form](/form-creator) can add them to the document first.
This is especially useful for government and HR forms, which often contain personal information I'd rather not upload somewhere just to fill in a few boxes.
If the PDF is a scan and you actually need to edit the scanned text itself, you'll need OCR first. [BentoPDF's OCR tool](/ocr-pdf) can recognize the text in the document while keeping the processing on your device.
## How to redact a PDF properly
This one is important because putting a black box over text isn't necessarily redaction.
If you draw a rectangle over a name, the original name may still exist underneath it. It might still be selectable, searchable, or extractable.
Proper redaction removes the underlying content.
The [PDF editor](/edit-pdf) has redaction tools that permanently remove the underlying content rather than drawing over it. For documents where you also want to strip metadata or other hidden content, [Sanitize PDF](/sanitize-pdf) can help with that.
There's also a privacy reason to do redaction locally: if you upload the original, unredacted PDF to a redaction service, that service has already received the information you're trying to hide.
## How to sign a PDF without uploading it
[Sign PDF](/sign-pdf) lets you add a drawn, typed, or image signature to a PDF. Place it on the page, resize it, and optionally flatten it so it becomes part of the page instead of an annotation someone can drag away later.
The signature is added on your device, so you don't need to upload the document to a signing service just to place a signature on it.
One thing to keep in mind: adding a signature image to a PDF is not the same thing as applying a cryptographic digital signature. If the recipient needs a signature that can actually be verified, use [Digital Signature](/digital-sign-pdf) instead. It signs the document with an X.509 certificate (PKCS#12 .pfx and .p12, or PEM), which proves who signed it and shows whether anything changed afterwards. You can also add a visible signature block on top of that. The certificate password and private key stay in your browser, same as the PDF.
## Can you edit a PDF offline?
Yes.
There's an easy way to test it: load the editor, turn off Wi-Fi, and edit a PDF.
The PDF processing code runs in your browser using WebAssembly. Once the application has loaded, the actual PDF processing doesn't need a server.
This is also something you can inspect yourself in your browser's developer tools. The website is how you get the software; it doesn't have to be where your PDF gets processed.
If you want to run the whole thing yourself, BentoPDF is [open source and self-hostable](https://github.com/alam00000/bentopdf). You can run your own instance instead of relying on ours.
## What about scanned PDFs?
A scanned PDF is basically a collection of images.
If you want to change the words in it, an ordinary PDF text editor can't simply edit them because there isn't any text there yet.
You'll need OCR (optical character recognition) to turn the pixels into text.
You can either OCR the PDF first and then edit the resulting text, or, if you're just filling out a scanned form, put text boxes on top of the existing page.
## Is there a file size limit?
There isn't an imposed file-size limit.
The practical limit is your device's available memory. Normal PDFs are usually fine, but a thousand-page scanned archive is a very different workload from a five-page contract.
For very large PDFs, a desktop application may be a better choice.
## Will editing a digitally signed PDF break the signature?
Yes.
Changing a digitally signed PDF will invalidate its existing signature. This isn't specific to BentoPDF; it's a consequence of changing a document that has already been signed.
So the usual order is:
**Edit first. Sign last.**
If you need to make changes to a signed document, make sure you understand the signature requirements before doing so.
+2 -2
View File
@@ -7,10 +7,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.7
version: 1.0.9
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: '2.8.8'
appVersion: '2.8.10'
+6
View File
@@ -65,6 +65,9 @@ spec:
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
{{- end }}
volumes:
- name: nginx-tmp
emptyDir: {}
@@ -72,3 +75,6 @@ spec:
emptyDir: {}
- name: nginx-run
emptyDir: {}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 8 }}
{{- end }}
+4
View File
@@ -88,3 +88,7 @@ readinessProbe:
httpGet:
path: /
port: http
extraVolumes: []
extraVolumeMounts: []
+1 -1
View File
@@ -83,7 +83,7 @@ npx wrangler deploy -c wasm-wrangler.toml
## Security Features
- **Origin validation**: Only allows requests from configured origins
- **Rate limiting**: 100 requests/minute per IP (requires KV namespace)
- **Rate limiting**: 100 requests/minute per IP, per /64 for IPv6 (requires KV namespace; fails open on KV errors)
- **File type restrictions**: Only WASM-related files (.js, .wasm, .data, etc.)
- **Size limits**: Max 100MB per file
- **Caching**: Reduces origin requests and improves performance
+166 -76
View File
@@ -81,53 +81,134 @@ function isAllowedOrigin(origin) {
return ALLOWED_ORIGINS.includes(origin);
}
function parseIPv4(address) {
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(address);
if (!match) return null;
const octets = match.slice(1).map(Number);
if (octets.some((octet) => octet > 255)) return null;
return octets.reduce((value, octet) => value * 256 + octet, 0);
}
function parseIPv6(address) {
let text = address.toLowerCase();
const embedded = /^(.*:)(\d+\.\d+\.\d+\.\d+)$/.exec(text);
if (embedded) {
const ipv4 = parseIPv4(embedded[2]);
if (ipv4 === null) return null;
text = `${embedded[1]}${Math.floor(ipv4 / 65536).toString(16)}:${(ipv4 % 65536).toString(16)}`;
}
const sections = text.split('::');
if (sections.length > 2) return null;
const head = sections[0] ? sections[0].split(':') : [];
const tail =
sections.length === 2 && sections[1] ? sections[1].split(':') : [];
const missing = 8 - head.length - tail.length;
if (sections.length === 1 ? missing !== 0 : missing < 1) return null;
const groups = [...head, ...Array(missing).fill('0'), ...tail];
if (!groups.every((group) => /^[0-9a-f]{1,4}$/.test(group))) return null;
return groups.map((group) => parseInt(group, 16));
}
const BLOCKED_IPV4_RANGES = [
'0.0.0.0/8',
'10.0.0.0/8',
'100.64.0.0/10',
'127.0.0.0/8',
'169.254.0.0/16',
'172.16.0.0/12',
'192.0.0.0/24',
'192.0.2.0/24',
'192.168.0.0/16',
'198.18.0.0/15',
'198.51.100.0/24',
'203.0.113.0/24',
'224.0.0.0/4',
'240.0.0.0/4',
].map((cidr) => {
const [address, prefixLength] = cidr.split('/');
return { base: parseIPv4(address), size: 2 ** (32 - Number(prefixLength)) };
});
const BLOCKED_IPV6_RANGES = [
'::/128',
'::1/128',
'::/96',
'::ffff:0:0/96',
'64:ff9b::/96',
'64:ff9b:1::/48',
'100::/64',
'2001::/32',
'2001:db8::/32',
'2002::/16',
'fc00::/7',
'fe80::/10',
'fec0::/10',
'ff00::/8',
].map((cidr) => {
const [address, prefixLength] = cidr.split('/');
return { groups: parseIPv6(address), prefixLength: Number(prefixLength) };
});
function isBlockedIPv4(value) {
return BLOCKED_IPV4_RANGES.some(
({ base, size }) => value >= base && value < base + size
);
}
function isBlockedIPv6(groups) {
return BLOCKED_IPV6_RANGES.some((range) =>
range.groups.every((group, index) => {
const bitsInGroup = Math.min(
16,
Math.max(0, range.prefixLength - index * 16)
);
const groupMask = (0xffff << (16 - bitsInGroup)) & 0xffff;
return (groups[index] & groupMask) === (group & groupMask);
})
);
}
function isBlockedIp(address) {
const ipv4 = parseIPv4(address);
if (ipv4 !== null) return isBlockedIPv4(ipv4);
const ipv6Groups = parseIPv6(address);
if (ipv6Groups !== null) return isBlockedIPv6(ipv6Groups);
return true;
}
function isIpLiteral(host) {
return /^[\d.]+$/.test(host) || host.includes(':');
}
function getRateLimitKey(ip) {
const ipv6Groups = ip.includes(':') ? parseIPv6(ip) : null;
if (!ipv6Groups) return ip;
return `${ipv6Groups
.slice(0, 4)
.map((group) => group.toString(16))
.join(':')}::/64`;
}
function isPrivateOrReservedHost(hostname) {
if (
/^10\./.test(hostname) ||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname) ||
/^192\.168\./.test(hostname) ||
/^169\.254\./.test(hostname) || // link-local (cloud metadata)
/^100\.(6[4-9]|[7-9]\d|1[0-1]\d|12[0-7])\./.test(hostname) || // CGNAT
/^127\./.test(hostname) ||
/^0\./.test(hostname)
) {
const host = hostname
.toLowerCase()
.replace(/^\[|\]$/g, '')
.replace(/\.$/, '');
if (['localhost', 'localhost.localdomain'].includes(host)) {
return true;
}
if (/^\d+$/.test(hostname)) {
return true;
}
const lower = hostname.toLowerCase().replace(/^\[|\]$/g, '');
if (
lower === '::1' ||
lower.startsWith('::ffff:') ||
lower.startsWith('fe80') ||
lower.startsWith('fc') ||
lower.startsWith('fd') ||
lower.startsWith('ff')
) {
return true;
}
const blockedNames = [
'localhost',
'localhost.localdomain',
'0.0.0.0',
'[::1]',
];
if (blockedNames.includes(hostname.toLowerCase())) {
return true;
}
return false;
return isIpLiteral(host) && isBlockedIp(host);
}
async function hostnameResolvesToPrivate(hostname) {
const clean = hostname.replace(/^\[|\]$/g, '');
if (/^\d+\.\d+\.\d+\.\d+$/.test(clean) || clean.includes(':')) {
return isPrivateOrReservedHost(clean);
}
const clean = hostname
.toLowerCase()
.replace(/^\[|\]$/g, '')
.replace(/\.$/, '');
if (isPrivateOrReservedHost(clean)) return true;
if (isIpLiteral(clean)) return false;
const ips = [];
for (const type of ['A', 'AAAA']) {
try {
@@ -138,14 +219,16 @@ async function hostnameResolvesToPrivate(hostname) {
if (!res.ok) return true;
const data = await res.json();
for (const ans of data.Answer || []) {
if (ans && ans.data) ips.push(String(ans.data).replace(/\.$/, ''));
if (ans && (ans.type === 1 || ans.type === 28) && ans.data) {
ips.push(String(ans.data));
}
}
} catch {
return true;
}
}
if (ips.length === 0) return true;
return ips.some((ip) => isPrivateOrReservedHost(ip));
return ips.some((ip) => isBlockedIp(ip));
}
function isValidCertificateUrl(urlString) {
@@ -372,49 +455,56 @@ export default {
}
const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
const rateLimitKey = `ratelimit:${clientIP}`;
const rateLimitKey = `ratelimit:${getRateLimitKey(clientIP)}`;
const now = Date.now();
if (env.RATE_LIMIT_KV) {
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
type: 'json',
});
const requests = rateLimitData?.requests || [];
try {
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
type: 'json',
});
const requests = rateLimitData?.requests || [];
const recentRequests = requests.filter(
(t) => now - t < RATE_LIMIT_WINDOW_MS
);
const recentRequests = requests.filter(
(t) => now - t < RATE_LIMIT_WINDOW_MS
);
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
return new Response(
JSON.stringify({
error: 'Rate limit exceeded',
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute. Please try again later.`,
retryAfter: Math.ceil(
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
),
}),
{
status: 429,
headers: {
...corsHeaders(origin),
'Content-Type': 'application/json',
'Retry-After': Math.ceil(
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
return new Response(
JSON.stringify({
error: 'Rate limit exceeded',
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute. Please try again later.`,
retryAfter: Math.ceil(
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
).toString(),
},
),
}),
{
status: 429,
headers: {
...corsHeaders(origin),
'Content-Type': 'application/json',
'Retry-After': Math.ceil(
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
).toString(),
},
}
);
}
recentRequests.push(now);
await env.RATE_LIMIT_KV.put(
rateLimitKey,
JSON.stringify({ requests: recentRequests }),
{
expirationTtl: 120,
}
);
} catch (error) {
console.error(
'[CORS Proxy] Rate limit KV error, allowing request:',
error
);
}
recentRequests.push(now);
await env.RATE_LIMIT_KV.put(
rateLimitKey,
JSON.stringify({ requests: recentRequests }),
{
expirationTtl: 120,
}
);
} else {
console.warn(
'[CORS Proxy] RATE_LIMIT_KV not configured — rate limiting is disabled'
+97 -36
View File
@@ -39,9 +39,38 @@ const ALLOWED_EXTENSIONS = [
'.mem',
'.asm.js',
'.worker.js',
'.html',
'.whl',
];
const SAFE_SUBPATH = /^\/[A-Za-z0-9._/-]*$/;
function isSafeSubpath(subpath) {
return (
SAFE_SUBPATH.test(subpath) &&
!subpath.split('/').some((segment) => segment === '.' || segment === '..')
);
}
function getRateLimitKey(ip) {
if (!ip.includes(':') || ip.includes('.')) return ip;
const sections = ip.toLowerCase().split('::');
if (sections.length > 2) return ip;
const leadingGroups = sections[0] ? sections[0].split(':') : [];
const trailingGroups = sections[1] ? sections[1].split(':') : [];
const missing = 8 - leadingGroups.length - trailingGroups.length;
if (sections.length === 1 ? missing !== 0 : missing < 1) return ip;
const groups = [
...leadingGroups,
...Array(missing).fill('0'),
...trailingGroups,
];
if (!groups.every((group) => /^[0-9a-f]{1,4}$/.test(group))) return ip;
return `${groups
.slice(0, 4)
.map((group) => parseInt(group, 16).toString(16))
.join(':')}::/64`;
}
function isAllowedOrigin(origin) {
if (!origin) return true; // Allow no-origin requests (e.g., direct browser navigation)
return ALLOWED_ORIGINS.some((allowed) =>
@@ -66,6 +95,7 @@ function corsHeaders(origin) {
'Access-Control-Expose-Headers':
'Content-Length, Content-Range, Content-Type',
'Access-Control-Max-Age': '86400',
'X-Content-Type-Options': 'nosniff',
};
}
@@ -89,7 +119,6 @@ function getContentType(pathname) {
'.so': 'application/octet-stream',
'.zip': 'application/zip',
'.mem': 'application/octet-stream',
'.html': 'text/html',
};
return contentTypes[ext] || 'application/octet-stream';
}
@@ -115,7 +144,34 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
? sourceBaseUrl.slice(0, -1)
: sourceBaseUrl;
const normalizedPath = subpath.startsWith('/') ? subpath : `/${subpath}`;
const targetUrl = `${normalizedBase}${normalizedPath}`;
let targetUrl = null;
if (isSafeSubpath(normalizedPath)) {
try {
const candidate = new URL(`${normalizedBase}${normalizedPath}`).href;
if (candidate.startsWith(new URL(`${normalizedBase}/`).href)) {
targetUrl = candidate;
}
} catch {
targetUrl = null;
}
}
if (!targetUrl) {
return new Response(
JSON.stringify({
error: 'Invalid path',
message: 'The requested path is not allowed.',
}),
{
status: 400,
headers: {
...corsHeaders(origin),
'Content-Type': 'application/json',
},
}
);
}
if (!isAllowedFile(normalizedPath)) {
return new Response(
@@ -151,8 +207,6 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
JSON.stringify({
error: 'Failed to fetch resource',
status: response.status,
statusText: response.statusText,
targetUrl: targetUrl,
}),
{
status: response.status,
@@ -204,14 +258,14 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
'Content-Type': getContentType(normalizedPath),
'Content-Length': bodyData.byteLength.toString(),
'Cache-Control': `public, max-age=${CACHE_TTL_SECONDS}`,
'X-Proxied-From': new URL(targetUrl).hostname,
},
});
} catch (error) {
console.error('[WASM Proxy] Fetch error:', error);
return new Response(
JSON.stringify({
error: 'Proxy error',
message: error.message,
message: 'Failed to fetch the requested resource',
}),
{
status: 500,
@@ -260,42 +314,49 @@ export default {
if (env.RATE_LIMIT_KV) {
const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
const rateLimitKey = `wasm-ratelimit:${clientIP}`;
const rateLimitKey = `wasm-ratelimit:${getRateLimitKey(clientIP)}`;
const now = Date.now();
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
type: 'json',
});
const requests = rateLimitData?.requests || [];
const recentRequests = requests.filter(
(t) => now - t < RATE_LIMIT_WINDOW_MS
);
try {
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
type: 'json',
});
const requests = rateLimitData?.requests || [];
const recentRequests = requests.filter(
(t) => now - t < RATE_LIMIT_WINDOW_MS
);
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
return new Response(
JSON.stringify({
error: 'Rate limit exceeded',
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute.`,
}),
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
return new Response(
JSON.stringify({
error: 'Rate limit exceeded',
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute.`,
}),
{
status: 429,
headers: {
...corsHeaders(origin),
'Content-Type': 'application/json',
'Retry-After': '60',
},
}
);
}
recentRequests.push(now);
await env.RATE_LIMIT_KV.put(
rateLimitKey,
JSON.stringify({ requests: recentRequests }),
{
status: 429,
headers: {
...corsHeaders(origin),
'Content-Type': 'application/json',
'Retry-After': '60',
},
expirationTtl: 120,
}
);
} catch (error) {
console.error(
'[WASM Proxy] Rate limit KV error, allowing request:',
error
);
}
recentRequests.push(now);
await env.RATE_LIMIT_KV.put(
rateLimitKey,
JSON.stringify({ requests: recentRequests }),
{
expirationTtl: 120,
}
);
}
if (pathname.startsWith('/pymupdf/')) {
+70 -28
View File
@@ -49,6 +49,7 @@
<meta name="twitter:site" content="@BentoPDF" />
<link href="/src/css/styles.css" rel="stylesheet" />
<link href="/src/css/landing.css" rel="stylesheet" />
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest" />
@@ -75,38 +76,78 @@
<link rel="icon" href="/favicon.ico" sizes="32x32" />
</head>
<body class="antialiased bg-gray-900 text-gray-300">
<body class="lp antialiased">
{{> navbar }}
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
<section id="contact-hero" class="text-center py-16 md:py-24">
<h1
class="text-4xl md:text-5xl font-bold text-white mb-4"
data-i18n="contact.title"
>
Get in Touch
</h1>
<p
class="text-lg md:text-xl text-gray-400 max-w-3xl mx-auto"
data-i18n="contact.subtitle"
>
We'd love to hear from you. Whether you have a question, feedback, or
a feature request, please don't hesitate to reach out.
</p>
<div id="app">
<section id="contact-hero" class="lp-sec lp-sec--first">
<div class="lp-frame">
<div class="lp-cta">
<div>
<h1 class="lp-h2">
<span class="line" data-i18n="contact.title">Get in Touch</span>
</h1>
<p class="lp-head-p" data-i18n="contact.subtitle">
We'd love to hear from you. Whether you have a question,
feedback, or a feature request, please don't hesitate to reach
out.
</p>
</div>
</div>
</div>
</section>
<div class="max-w-2xl mx-auto text-center py-8">
<p class="text-lg text-gray-400">
<span data-i18n="contact.email"
>You can reach us directly by email at:</span
>
<a
href="mailto:contact@bentopdf.com"
class="text-indigo-400 underline hover:text-indigo-300"
>contact@bentopdf.com</a
>
</p>
</div>
<section id="contact-channels" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-grid lp-grid--2 lp-cross">
<a class="lp-cell lp-reveal" href="mailto:contact@bentopdf.com">
<span class="lp-tile"><i data-lucide="mail"></i></span>
<h3 data-i18n="contact.emailTitle">Email</h3>
<p data-i18n="contact.email">
You can reach us directly by email at:
</p>
<b>contact@bentopdf.com</b>
</a>
<a
class="lp-cell lp-reveal"
href="https://github.com/alam00000/bentopdf/issues"
target="_blank"
rel="noopener noreferrer"
>
<span class="lp-tile"><i data-lucide="github"></i></span>
<h3>GitHub</h3>
<p data-i18n="contact.githubText">
Report a bug, request a feature, or read the source.
</p>
<b>github.com/alam00000/bentopdf</b>
</a>
<a
class="lp-cell lp-reveal"
href="https://discord.gg/Bgq3Ay3f2w"
target="_blank"
rel="noopener noreferrer"
>
<span class="lp-tile"><i data-lucide="message-circle"></i></span>
<h3>Discord</h3>
<p data-i18n="contact.discordText">
Join the community to chat with us and other users.
</p>
<b>discord.gg/Bgq3Ay3f2w</b>
</a>
<a class="lp-cell lp-reveal" href="faq.html">
<span class="lp-tile"><i data-lucide="help-circle"></i></span>
<h3 data-i18n="footer.faqLink">FAQ</h3>
<p data-i18n="contact.faqText">
Find quick answers to the questions we get most often.
</p>
<b data-i18n="contact.faqLink">Read the FAQ</b>
</a>
</div>
</div>
</section>
</div>
{{> footer }}
@@ -114,6 +155,7 @@
<script type="module" src="src/js/utils/lucide-init.ts"></script>
<script type="module" src="src/js/main.ts"></script>
<script type="module" src="src/js/mobileMenu.ts"></script>
<script type="module" src="src/js/landing.ts"></script>
<!-- JSON-LD Schema -->
<script type="application/ld+json">
{
-283
View File
@@ -1,283 +0,0 @@
import { useMediaQuery } from './chunk-BRNHR3LR.js';
import { computed, ref, shallowRef, watch } from './chunk-H6MPEGKE.js';
// node_modules/vitepress/dist/client/theme-default/index.js
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/fonts.css';
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/vars.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/base.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/icons.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/utils.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css';
import '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css';
import VPBadge from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue';
import Layout from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/Layout.vue';
import { default as default2 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue';
import { default as default3 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue';
import { default as default4 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue';
import { default as default5 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue';
import { default as default6 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue';
import { default as default7 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue';
import { default as default8 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue';
import { default as default9 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue';
import { default as default10 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue';
import { default as default11 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue';
import { default as default12 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue';
import { default as default13 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue';
import { default as default14 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue';
import { default as default15 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue';
import { default as default16 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue';
import { default as default17 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue';
import { default as default18 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue';
import { default as default19 } from '/Users/abdullahtapadar/Desktop/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue';
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
import { onContentUpdated } from 'vitepress';
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
import { getScrollOffset } from 'vitepress';
// node_modules/vitepress/dist/client/theme-default/support/utils.js
import { withBase } from 'vitepress';
// node_modules/vitepress/dist/client/theme-default/composables/data.js
import { useData as useData$ } from 'vitepress';
var useData = useData$;
// node_modules/vitepress/dist/client/theme-default/support/utils.js
function ensureStartingSlash(path) {
return path.startsWith('/') ? path : `/${path}`;
}
// node_modules/vitepress/dist/client/theme-default/support/sidebar.js
function getSidebar(_sidebar, path) {
if (Array.isArray(_sidebar)) return addBase(_sidebar);
if (_sidebar == null) return [];
path = ensureStartingSlash(path);
const dir = Object.keys(_sidebar)
.sort((a, b) => {
return b.split('/').length - a.split('/').length;
})
.find((dir2) => {
return path.startsWith(ensureStartingSlash(dir2));
});
const sidebar = dir ? _sidebar[dir] : [];
return Array.isArray(sidebar)
? addBase(sidebar)
: addBase(sidebar.items, sidebar.base);
}
function getSidebarGroups(sidebar) {
const groups = [];
let lastGroupIndex = 0;
for (const index in sidebar) {
const item = sidebar[index];
if (item.items) {
lastGroupIndex = groups.push(item);
continue;
}
if (!groups[lastGroupIndex]) {
groups.push({ items: [] });
}
groups[lastGroupIndex].items.push(item);
}
return groups;
}
function addBase(items, _base) {
return [...items].map((_item) => {
const item = { ..._item };
const base = item.base || _base;
if (base && item.link) item.link = base + item.link;
if (item.items) item.items = addBase(item.items, base);
return item;
});
}
// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js
function useSidebar() {
const { frontmatter, page, theme: theme2 } = useData();
const is960 = useMediaQuery('(min-width: 960px)');
const isOpen = ref(false);
const _sidebar = computed(() => {
const sidebarConfig = theme2.value.sidebar;
const relativePath = page.value.relativePath;
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];
});
const sidebar = ref(_sidebar.value);
watch(_sidebar, (next, prev) => {
if (JSON.stringify(next) !== JSON.stringify(prev))
sidebar.value = _sidebar.value;
});
const hasSidebar = computed(() => {
return (
frontmatter.value.sidebar !== false &&
sidebar.value.length > 0 &&
frontmatter.value.layout !== 'home'
);
});
const leftAside = computed(() => {
if (hasAside)
return frontmatter.value.aside == null
? theme2.value.aside === 'left'
: frontmatter.value.aside === 'left';
return false;
});
const hasAside = computed(() => {
if (frontmatter.value.layout === 'home') return false;
if (frontmatter.value.aside != null) return !!frontmatter.value.aside;
return theme2.value.aside !== false;
});
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);
const sidebarGroups = computed(() => {
return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];
});
function open() {
isOpen.value = true;
}
function close() {
isOpen.value = false;
}
function toggle() {
isOpen.value ? close() : open();
}
return {
isOpen,
sidebar,
sidebarGroups,
hasSidebar,
hasAside,
leftAside,
isSidebarEnabled,
open,
close,
toggle,
};
}
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/;
var resolvedHeaders = [];
function getHeaders(range) {
const headers = [
...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'),
]
.filter((el) => el.id && el.hasChildNodes())
.map((el) => {
const level = Number(el.tagName[1]);
return {
element: el,
title: serializeHeader(el),
link: '#' + el.id,
level,
};
});
return resolveHeaders(headers, range);
}
function serializeHeader(h) {
let ret = '';
for (const node of h.childNodes) {
if (node.nodeType === 1) {
if (ignoreRE.test(node.className)) continue;
ret += node.textContent;
} else if (node.nodeType === 3) {
ret += node.textContent;
}
}
return ret.trim();
}
function resolveHeaders(headers, range) {
if (range === false) {
return [];
}
const levelsRange =
(typeof range === 'object' && !Array.isArray(range)
? range.level
: range) || 2;
const [high, low] =
typeof levelsRange === 'number'
? [levelsRange, levelsRange]
: levelsRange === 'deep'
? [2, 6]
: levelsRange;
return buildTree(headers, high, low);
}
function buildTree(data, min, max) {
resolvedHeaders.length = 0;
const result = [];
const stack = [];
data.forEach((item) => {
const node = { ...item, children: [] };
let parent = stack[stack.length - 1];
while (parent && parent.level >= node.level) {
stack.pop();
parent = stack[stack.length - 1];
}
if (
node.element.classList.contains('ignore-header') ||
(parent && 'shouldIgnore' in parent)
) {
stack.push({ level: node.level, shouldIgnore: true });
return;
}
if (node.level > max || node.level < min) return;
resolvedHeaders.push({ element: node.element, link: node.link });
if (parent) parent.children.push(node);
else result.push(node);
stack.push(node);
});
return result;
}
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
function useLocalNav() {
const { theme: theme2, frontmatter } = useData();
const headers = shallowRef([]);
const hasLocalNav = computed(() => {
return headers.value.length > 0;
});
onContentUpdated(() => {
headers.value = getHeaders(
frontmatter.value.outline ?? theme2.value.outline
);
});
return {
headers,
hasLocalNav,
};
}
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
var theme = {
Layout,
enhanceApp: ({ app }) => {
app.component('Badge', VPBadge);
},
};
var without_fonts_default = theme;
export {
default2 as VPBadge,
default3 as VPButton,
default4 as VPDocAsideSponsors,
default5 as VPFeatures,
default6 as VPHomeContent,
default7 as VPHomeFeatures,
default8 as VPHomeHero,
default9 as VPHomeSponsors,
default10 as VPImage,
default11 as VPLink,
default12 as VPNavBarSearch,
default13 as VPSocialLink,
default14 as VPSocialLinks,
default15 as VPSponsors,
default16 as VPTeamMembers,
default17 as VPTeamPage,
default18 as VPTeamPageSection,
default19 as VPTeamPageTitle,
without_fonts_default as default,
useLocalNav,
useSidebar,
};
//# sourceMappingURL=@theme_index.js.map
-7
View File
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/vitepress/dist/client/theme-default/index.js", "../../../../node_modules/vitepress/dist/client/theme-default/without-fonts.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/local-nav.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/outline.js", "../../../../node_modules/vitepress/dist/client/theme-default/support/utils.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/data.js", "../../../../node_modules/vitepress/dist/client/theme-default/support/sidebar.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/sidebar.js"],
"sourcesContent": ["import './styles/fonts.css';\nexport * from './without-fonts';\nexport { default as default } from './without-fonts';\n", "import './styles/vars.css';\nimport './styles/base.css';\nimport './styles/icons.css';\nimport './styles/utils.css';\nimport './styles/components/custom-block.css';\nimport './styles/components/vp-code.css';\nimport './styles/components/vp-code-group.css';\nimport './styles/components/vp-doc.css';\nimport './styles/components/vp-sponsor.css';\nimport VPBadge from './components/VPBadge.vue';\nimport Layout from './Layout.vue';\nexport { default as VPBadge } from './components/VPBadge.vue';\nexport { default as VPButton } from './components/VPButton.vue';\nexport { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue';\nexport { default as VPFeatures } from './components/VPFeatures.vue';\nexport { default as VPHomeContent } from './components/VPHomeContent.vue';\nexport { default as VPHomeFeatures } from './components/VPHomeFeatures.vue';\nexport { default as VPHomeHero } from './components/VPHomeHero.vue';\nexport { default as VPHomeSponsors } from './components/VPHomeSponsors.vue';\nexport { default as VPImage } from './components/VPImage.vue';\nexport { default as VPLink } from './components/VPLink.vue';\nexport { default as VPNavBarSearch } from './components/VPNavBarSearch.vue';\nexport { default as VPSocialLink } from './components/VPSocialLink.vue';\nexport { default as VPSocialLinks } from './components/VPSocialLinks.vue';\nexport { default as VPSponsors } from './components/VPSponsors.vue';\nexport { default as VPTeamMembers } from './components/VPTeamMembers.vue';\nexport { default as VPTeamPage } from './components/VPTeamPage.vue';\nexport { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';\nexport { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';\nexport { useLocalNav } from './composables/local-nav';\nexport { useSidebar } from './composables/sidebar';\nconst theme = {\n Layout,\n enhanceApp: ({ app }) => {\n app.component('Badge', VPBadge);\n }\n};\nexport default theme;\n", "import { onContentUpdated } from 'vitepress';\nimport { computed, shallowRef } from 'vue';\nimport { getHeaders } from '../composables/outline';\nimport { useData } from './data';\nexport function useLocalNav() {\n const { theme, frontmatter } = useData();\n const headers = shallowRef([]);\n const hasLocalNav = computed(() => {\n return headers.value.length > 0;\n });\n onContentUpdated(() => {\n headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline);\n });\n return {\n headers,\n hasLocalNav\n };\n}\n", "import { getScrollOffset } from 'vitepress';\nimport { onMounted, onUnmounted, onUpdated } from 'vue';\nimport { throttleAndDebounce } from '../support/utils';\nimport { useAside } from './aside';\nconst ignoreRE = /\\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\\b/;\n// cached list of anchor elements from resolveHeaders\nconst resolvedHeaders = [];\nexport function resolveTitle(theme) {\n return ((typeof theme.outline === 'object' &&\n !Array.isArray(theme.outline) &&\n theme.outline.label) ||\n theme.outlineTitle ||\n 'On this page');\n}\nexport function getHeaders(range) {\n const headers = [\n ...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)')\n ]\n .filter((el) => el.id && el.hasChildNodes())\n .map((el) => {\n const level = Number(el.tagName[1]);\n return {\n element: el,\n title: serializeHeader(el),\n link: '#' + el.id,\n level\n };\n });\n return resolveHeaders(headers, range);\n}\nfunction serializeHeader(h) {\n let ret = '';\n for (const node of h.childNodes) {\n if (node.nodeType === 1) {\n if (ignoreRE.test(node.className))\n continue;\n ret += node.textContent;\n }\n else if (node.nodeType === 3) {\n ret += node.textContent;\n }\n }\n return ret.trim();\n}\nexport function resolveHeaders(headers, range) {\n if (range === false) {\n return [];\n }\n const levelsRange = (typeof range === 'object' && !Array.isArray(range)\n ? range.level\n : range) || 2;\n const [high, low] = typeof levelsRange === 'number'\n ? [levelsRange, levelsRange]\n : levelsRange === 'deep'\n ? [2, 6]\n : levelsRange;\n return buildTree(headers, high, low);\n}\nexport function useActiveAnchor(container, marker) {\n const { isAsideEnabled } = useAside();\n const onScroll = throttleAndDebounce(setActiveLink, 100);\n let prevActiveLink = null;\n onMounted(() => {\n requestAnimationFrame(setActiveLink);\n window.addEventListener('scroll', onScroll);\n });\n onUpdated(() => {\n // sidebar update means Line truncated
"mappings": "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",
"names": ["default", "dir", "theme", "theme"]
}
-58
View File
@@ -1,58 +0,0 @@
{
"hash": "cbe76ac1",
"configHash": "fcacb6fc",
"lockfileHash": "25b6b516",
"browserHash": "e3bcae4a",
"optimized": {
"vue": {
"src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "d430f9d5",
"needsInterop": false
},
"vitepress > @vue/devtools-api": {
"src": "../../../../node_modules/@vue/devtools-api/dist/index.js",
"file": "vitepress___@vue_devtools-api.js",
"fileHash": "cdc3240f",
"needsInterop": false
},
"vitepress > @vueuse/core": {
"src": "../../../../node_modules/@vueuse/core/index.mjs",
"file": "vitepress___@vueuse_core.js",
"fileHash": "9c54fae4",
"needsInterop": false
},
"vitepress > @vueuse/integrations/useFocusTrap": {
"src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs",
"file": "vitepress___@vueuse_integrations_useFocusTrap.js",
"fileHash": "dcb2d016",
"needsInterop": false
},
"vitepress > mark.js/src/vanilla.js": {
"src": "../../../../node_modules/mark.js/src/vanilla.js",
"file": "vitepress___mark__js_src_vanilla__js.js",
"fileHash": "89ac005f",
"needsInterop": false
},
"vitepress > minisearch": {
"src": "../../../../node_modules/minisearch/dist/es/index.js",
"file": "vitepress___minisearch.js",
"fileHash": "dcc8fa95",
"needsInterop": false
},
"@theme/index": {
"src": "../../../../node_modules/vitepress/dist/client/theme-default/index.js",
"file": "@theme_index.js",
"fileHash": "12a406fc",
"needsInterop": false
}
},
"chunks": {
"chunk-BRNHR3LR": {
"file": "chunk-BRNHR3LR.js"
},
"chunk-H6MPEGKE": {
"file": "chunk-H6MPEGKE.js"
}
}
}
File diff suppressed because it is too large. Load diff
-7
View File
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/@vueuse/shared/index.mjs", "../../../../node_modules/@vueuse/core/index.mjs"],
"sourcesContent": ["import { shallowRef, watchEffect, readonly, watch, customRef, getCurrentScope, onScopeDispose, effectScope, getCurrentInstance, hasInjectionContext, inject, provide, ref, isRef, unref, toValue as toValue$1, computed, reactive, toRefs as toRefs$1, toRef as toRef$1, onBeforeMount, nextTick, onBeforeUnmount, onMounted, onUnmounted, isReactive } from 'vue';\n\nfunction computedEager(fn, options) {\n var _a;\n const result = shallowRef();\n watchEffect(() => {\n result.value = fn();\n }, {\n ...options,\n flush: (_a = options == null ? void 0 : options.flush) != null ? _a : \"sync\"\n });\n return readonly(result);\n}\n\nfunction computedWithControl(source, fn) {\n let v = void 0;\n let track;\n let trigger;\n const dirty = shallowRef(true);\n const update = () => {\n dirty.value = true;\n trigger();\n };\n watch(source, update, { flush: \"sync\" });\n const get = typeof fn === \"function\" ? fn : fn.get;\n const set = typeof fn === \"function\" ? void 0 : fn.set;\n const result = customRef((_track, _trigger) => {\n track = _track;\n trigger = _trigger;\n return {\n get() {\n if (dirty.value) {\n v = get(v);\n dirty.value = false;\n }\n track();\n return v;\n },\n set(v2) {\n set == null ? void 0 : set(v2);\n }\n };\n });\n if (Object.isExtensible(result))\n result.trigger = update;\n return result;\n}\n\nfunction tryOnScopeDispose(fn) {\n if (getCurrentScope()) {\n onScopeDispose(fn);\n return true;\n }\n return false;\n}\n\nfunction createEventHook() {\n const fns = /* @__PURE__ */ new Set();\n const off = (fn) => {\n fns.delete(fn);\n };\n const clear = () => {\n fns.clear();\n };\n const on = (fn) => {\n fns.add(fn);\n const offFn = () => off(fn);\n tryOnScopeDispose(offFn);\n return {\n off: offFn\n };\n };\n const trigger = (...args) => {\n return Promise.all(Array.from(fns).map((fn) => fn(...args)));\n };\n return {\n on,\n off,\n trigger,\n clear\n };\n}\n\nfunction createGlobalState(stateFactory) {\n let initialized = false;\n let state;\n const scope = effectScope(true);\n return (...args) => {\n if (!initialized) {\n state = scope.run(() => stateFactory(...args));\n initialized = true;\n }\n return state;\n };\n}\n\nconst localProvidedStateMap = /* @__PURE__ */ new WeakMap();\n\nconst injectLocal = (...args) => {\n var _a;\n const key = args[0];\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null && !hasInjectionContext())\n throw new Error(\"injectLocal must be called in setup\");\n if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance))\n return localProvidedStateMap.get(instance)[key];\n return inject(...args);\n};\n\nconst provideLocal = (key, value) => {\n var _a;\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null)\n throw new Error(\"provideLocal must be called in setup\");\n if (!localProvidedStateMap.has(instance))\n localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null));\n const localProvidedState = localProvidedStateMap.get(instance);\n localProvidedState[key] = value;\n provide(key, value);\n};\n\nfunction createInjectionState(composable, options) {\n const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || \"InjectionState\");\n const defaultValue = options == null ? void 0 : options.defaultValue;\n const useProvidingState = (...args) => {\n const state = composable(...args);\n provideLocal(key, state);\n return state;\n };\n const useInjectedState = () => injectLocal(key, defaultValue);\n return [useProvidingState, useInjectedState];\n}\n\nfunction createRef(value, deep) {\n if (deep === true) {\n return ref(value);\n } else {\n return shallowRef(value);\n }\n}\n\nfunction createSharedComposable(composable) {\n let subscribers = 0;\n let state;\n let scope;\n const dispose = () => {\n subscribers -= 1;\n if (scope && subscribers <= 0) {\n scope.stop();\n state = void 0;\n scope = void 0;\n }\n };\n return (...args) => {\n subscribers += 1;\n if (!scope) {\n scope = effectScope(true);\n state = scope.run(() => composable(...args));\n }\n tryOnScopeDispose(dispose);\n return state;\n };\n}\n\nfunction extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) {\n for (const [key, value] of Object.entries(extend)) {\n if (key === \"value\")\n continue;\n if (isRef(value) && unwrap) {\n Object.defineProperty(ref, key, {\n get() {\n return value.value;\n },\n set(v) {\n value.value = v;\n },\n enumerable\n });\n } else {\n Object.defineProperty(ref, key, { value, enumerable });\n }\n }Line truncated
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,cAAc,IAAI,SAAS;AAClC,MAAI;AACJ,QAAM,SAAS,WAAW;AAC1B,cAAY,MAAM;AAChB,WAAO,QAAQ,GAAG;AAAA,EACpB,GAAG;AAAA,IACD,GAAG;AAAA,IACH,QAAQ,KAAK,WAAW,OAAO,SAAS,QAAQ,UAAU,OAAO,KAAK;AAAA,EACxE,CAAC;AACD,SAAO,SAAS,MAAM;AACxB;AAEA,SAAS,oBAAoB,QAAQ,IAAI;AACvC,MAAI,IAAI;AACR,MAAI;AACJ,MAAI;AACJ,QAAM,QAAQ,WAAW,IAAI;AAC7B,QAAM,SAAS,MAAM;AACnB,UAAM,QAAQ;AACd,YAAQ;AAAA,EACV;AACA,QAAM,QAAQ,QAAQ,EAAE,OAAO,OAAO,CAAC;AACvC,QAAMA,OAAM,OAAO,OAAO,aAAa,KAAK,GAAG;AAC/C,QAAMC,OAAM,OAAO,OAAO,aAAa,SAAS,GAAG;AACnD,QAAM,SAAS,UAAU,CAAC,QAAQ,aAAa;AAC7C,YAAQ;AACR,cAAU;AACV,WAAO;AAAA,MACL,MAAM;AACJ,YAAI,MAAM,OAAO;AACf,cAAID,KAAI,CAAC;AACT,gBAAM,QAAQ;AAAA,QAChB;AACA,cAAM;AACN,eAAO;AAAA,MACT;AAAA,MACA,IAAI,IAAI;AACN,QAAAC,QAAO,OAAO,SAASA,KAAI,EAAE;AAAA,MAC/B;AAAA,IACF;AAAA,EACF,CAAC;AACD,MAAI,OAAO,aAAa,MAAM;AAC5B,WAAO,UAAU;AACnB,SAAO;AACT;AAEA,SAAS,kBAAkB,IAAI;AAC7B,MAAI,gBAAgB,GAAG;AACrB,mBAAe,EAAE;AACjB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB;AACzB,QAAM,MAAsB,oBAAI,IAAI;AACpC,QAAM,MAAM,CAAC,OAAO;AAClB,QAAI,OAAO,EAAE;AAAA,EACf;AACA,QAAM,QAAQ,MAAM;AAClB,QAAI,MAAM;AAAA,EACZ;AACA,QAAM,KAAK,CAAC,OAAO;AACjB,QAAI,IAAI,EAAE;AACV,UAAM,QAAQ,MAAM,IAAI,EAAE;AAC1B,sBAAkB,KAAK;AACvB,WAAO;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAM,UAAU,IAAI,SAAS;AAC3B,WAAO,QAAQ,IAAI,MAAM,KAAK,GAAG,EAAE,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,CAAC;AAAA,EAC7D;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,cAAc;AACvC,MAAI,cAAc;AAClB,MAAI;AACJ,QAAM,QAAQ,YAAY,IAAI;AAC9B,SAAO,IAAI,SAAS;AAClB,QAAI,CAAC,aAAa;AAChB,cAAQ,MAAM,IAAI,MAAM,aAAa,GAAG,IAAI,CAAC;AAC7C,oBAAc;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AACF;AAEA,IAAM,wBAAwC,oBAAI,QAAQ;AAE1D,IAAM,cAAc,IAAI,SAAS;AAC/B,MAAI;AACJ,QAAM,MAAM,KAAK,CAAC;AAClB,QAAM,YAAY,KAAK,mBAAmB,MAAM,OAAO,SAAS,GAAG;AACnE,MAAI,YAAY,QAAQ,CAAC,oBAAoB;AAC3C,UAAM,IAAI,MAAM,qCAAqC;AACvD,MAAI,YAAY,sBAAsB,IAAI,QAAQ,KAAK,OAAO,sBAAsB,IAAI,QAAQ;AAC9F,WAAO,sBAAsB,IAAI,QAAQ,EAAE,GAAG;AAChD,SAAO,OAAO,GAAG,IAAI;AACvB;AAEA,IAAM,eAAe,CAAC,KAAK,UAAU;AACnC,MAAI;AACJ,QAAM,YAAY,KAAK,mBAAmB,MAAM,OAAO,SAAS,GAAG;AACnE,MAAI,YAAY;AACd,UAAM,IAAI,MAAM,sCAAsC;AACxD,MAAI,CAAC,sBAAsB,IAAI,QAAQ;AACrC,0BAAsB,IAAI,UAA0B,uBAAO,OAAO,IAAI,CAAC;AACzE,QAAM,qBAAqB,sBAAsB,IAAI,QAAQ;AAC7D,qBAAmB,GAAG,IAAI;AAC1B,UAAQ,KAAK,KAAK;AACpB;AAEA,SAAS,qBAAqB,YAAY,SAAS;AACjD,QAAM,OAAO,WAAW,OAAO,SAAS,QAAQ,iBAAiB,OAAO,WAAW,QAAQ,gBAAgB;AAC3G,QAAM,eAAe,WAAW,OAAO,SAAS,QAAQ;AACxD,QAAM,oBAAoB,IAAI,SAAS;AACrC,UAAM,QAAQ,WAAW,GAAG,IAAI;AAChC,iBAAa,KAAK,KAAK;AACvB,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,MAAM,YAAY,KAAK,YAAY;AAC5D,SAAO,CAAC,mBAAmB,gBAAgB;AAC7C;AAEA,SAAS,UAAU,OAAO,MAAM;AAC9B,MAAI,SAAS,MAAM;AACjB,WAAO,IAAI,KAAK;AAAA,EAClB,OAAO;AACL,WAAO,WAAW,KAAK;AAAA,EACzB;AACF;AAEA,SAAS,uBAAuB,YAAY;AAC1C,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,MAAM;AACpB,mBAAe;AACf,QAAI,SAAS,eAAe,GAAG;AAC7B,YAAM,KAAK;AACX,cAAQ;AACR,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO,IAAI,SAAS;AAClB,mBAAe;AACf,QAAI,CAAC,OAAO;AACV,cAAQ,YAAY,IAAI;AACxB,cAAQ,MAAM,IAAI,MAAM,WAAW,GAAG,IAAI,CAAC;AAAA,IAC7C;AACA,sBAAkB,OAAO;AACzB,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAUC,MAAK,QAAQ,EAAE,aAAa,OAAO,SAAS,KAAK,IAAI,CAAC,GAAG;AAC1E,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ;AACV;AACF,QAAI,MAAM,KAAK,KAAK,QAAQ;AAC1B,aAAO,eAAeA,MAAK,KAAK;AAAA,QAC9B,MAAM;AACJ,iBAAO,MAAM;AAAA,QACf;AAAA,QACA,IAAI,GAAG;AACL,gBAAM,QAAQ;AAAA,QAChB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,aAAO,eAAeA,MAAK,KAAK,EAAE,OAAO,WAAW,CAAC;AAAA,IACvD;AAAA,EACF;AACA,SAAOA;AACT;AAEA,SAAS,IAAI,KAAK,KAAK;AACrB,MAAI,OAAO;AACT,WAAO,MAAM,GAAG;AAClB,SAAO,MAAM,GAAG,EAAE,GAAG;AACvB;AAEA,SAAS,UAAU,GAAG;AACpB,SAAO,MAAM,CAAC,KAAK;AACrB;AAEA,SAAS,mBAAmB,KAAK,KAAK;AACpC,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,QAAQ,EAAE,GAAG,IAAI;AACvB,WAAO,eAAe,OAAO,OAAO,UAAU;AAAA,MAC5C,YAAY;AAAA,MACZ,QAAQ;AACN,YAAI,QAAQ;AACZ,eAAO;AAAA,UACL,MAAM,OAAO;AAAA,YACX,OAAO,IAAI,OAAO;AAAA,YAClB,MAAM,QAAQ,IAAI;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,OAAO;AACL,WAAO,OAAO,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG;AAAA,EACpC;AACF;AAEA,SAAS,SAAS,IAAI,SAAS;AAC7B,QAAM,WAAW,WAAW,OAAO,SAAS,QAAQ,oBAAoB,QAAQ,QAAQ;AACxF,SAAO,YAAY,MAAM;AACvB,WAAO,SAAS,MAAM,GAAG,MAAM,MAAM,KAAK,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;AAAA,EACnE;AACF;AAEA,SAAS,eAAe,KAAK,gBAAgB,CAAC,GAAG;AAC/C,MAAIC,QAAO,CAAC;AACZ,MAAI;AACJ,MAAI,MAAM,QAAQ,aAAa,GAAG;AAChC,IAAAA,QAAO;AAAA,EACT,OAAO;AACL,cAAU;AACV,UAAM,EAAE,uBAAuB,KAAK,IAAI;AACxC,IAAAA,MAAK,KAAK,GAAG,OAAO,KAAK,GAAG,CAAC;AAC7B,QAAI;AACF,MAAAA,MAAK,KAAK,GAAG,OAAO,oBAAoB,GAAG,CAAC;AAAA,EAChD;AACA,SAAO,OAAO;AAAA,IACZA,MAAK,IAAI,CAAC,QAAQ;AAChB,YAAM,QAAQ,IAAI,GAAG;AACrB,aAAO;AAAA,QACL;AAAA,QACA,OAAO,UAAU,aAAa,SAAS,MAAM,KAAK,GAAG,GAAG,OAAO,IAAI;AAAA,MACrE;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,WAAW,WAAW;AAC7B,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO,SAAS,SAAS;AAC3B,QAAM,QAAQ,IAAI,MAAM,CAAC,GAAG;AAAA,IAC1B,IAAI,GAAG,GAAG,UAAU;AAClB,aAAO,MAAM,QAAQ,IAAI,UAAU,OAAO,GAAG,QAAQ,CAAC;AAAA,IACxD;AAAA,IACA,IAAI,GAAG,GAAG,OAAO;AACf,UAAI,MAAM,UAAU,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK;AAC3C,kBAAU,MAAM,CAAC,EAAE,QAAQ;AAAA;AAE3B,kBAAU,MAAM,CAAC,IAAI;ALine truncated
"names": ["get", "set", "ref", "keys", "invoke", "toRef", "toRefs", "toValue", "window", "document", "timestamp", "navigator", "events", "getValue", "ref", "defaults", "toRef", "set", "onUpdated", "preventDefault", "toRefs", "now", "keys", "get", "isReadonly"]
}
File diff suppressed because it is too large. Load diff
-7
View File
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/@vue/shared/dist/shared.esm-bundler.js", "../../../../node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js", "../../../../node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js", "../../../../node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js", "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js"],
"sourcesContent": ["/**\n* @vue/shared v3.5.29\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\n// @__NO_SIDE_EFFECTS__\nfunction makeMap(str) {\n const map = /* @__PURE__ */ Object.create(null);\n for (const key of str.split(\",\")) map[key] = 1;\n return (val) => val in map;\n}\n\nconst EMPTY_OBJ = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze({}) : {};\nconst EMPTY_ARR = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze([]) : [];\nconst NOOP = () => {\n};\nconst NO = () => false;\nconst isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter\n(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);\nconst isModelListener = (key) => key.startsWith(\"onUpdate:\");\nconst extend = Object.assign;\nconst remove = (arr, el) => {\n const i = arr.indexOf(el);\n if (i > -1) {\n arr.splice(i, 1);\n }\n};\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst hasOwn = (val, key) => hasOwnProperty.call(val, key);\nconst isArray = Array.isArray;\nconst isMap = (val) => toTypeString(val) === \"[object Map]\";\nconst isSet = (val) => toTypeString(val) === \"[object Set]\";\nconst isDate = (val) => toTypeString(val) === \"[object Date]\";\nconst isRegExp = (val) => toTypeString(val) === \"[object RegExp]\";\nconst isFunction = (val) => typeof val === \"function\";\nconst isString = (val) => typeof val === \"string\";\nconst isSymbol = (val) => typeof val === \"symbol\";\nconst isObject = (val) => val !== null && typeof val === \"object\";\nconst isPromise = (val) => {\n return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);\n};\nconst objectToString = Object.prototype.toString;\nconst toTypeString = (value) => objectToString.call(value);\nconst toRawType = (value) => {\n return toTypeString(value).slice(8, -1);\n};\nconst isPlainObject = (val) => toTypeString(val) === \"[object Object]\";\nconst isIntegerKey = (key) => isString(key) && key !== \"NaN\" && key[0] !== \"-\" && \"\" + parseInt(key, 10) === key;\nconst isReservedProp = /* @__PURE__ */ makeMap(\n // the leading comma is intentional so empty string \"\" is also included\n \",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"\n);\nconst isBuiltInDirective = /* @__PURE__ */ makeMap(\n \"bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo\"\n);\nconst cacheStringFunction = (fn) => {\n const cache = /* @__PURE__ */ Object.create(null);\n return ((str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n });\n};\nconst camelizeRE = /-\\w/g;\nconst camelize = cacheStringFunction(\n (str) => {\n return str.replace(camelizeRE, (c) => c.slice(1).toUpperCase());\n }\n);\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction(\n (str) => str.replace(hyphenateRE, \"-$1\").toLowerCase()\n);\nconst capitalize = cacheStringFunction((str) => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n});\nconst toHandlerKey = cacheStringFunction(\n (str) => {\n const s = str ? `on${capitalize(str)}` : ``;\n return s;\n }\n);\nconst hasChanged = (value, oldValue) => !Object.is(value, oldValue);\nconst invokeArrayFns = (fns, ...arg) => {\n for (let i = 0; i < fns.length; i++) {\n fns[i](...arg);\n }\n};\nconst def = (obj, key, value, writable = false) => {\n Object.defineProperty(obj, key, {\n configurable: true,\n enumerable: false,\n writable,\n value\n });\n};\nconst looseToNumber = (val) => {\n const n = parseFloat(val);\n return isNaN(n) ? val : n;\n};\nconst toNumber = (val) => {\n const n = isString(val) ? Number(val) : NaN;\n return isNaN(n) ? val : n;\n};\nlet _globalThis;\nconst getGlobalThis = () => {\n return _globalThis || (_globalThis = typeof globalThis !== \"undefined\" ? globalThis : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : {});\n};\nconst identRE = /^[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*$/;\nfunction genPropsAccessExp(name) {\n return identRE.test(name) ? `__props.${name}` : `__props[${JSON.stringify(name)}]`;\n}\nfunction genCacheKey(source, options) {\n return source + JSON.stringify(\n options,\n (_, val) => typeof val === \"function\" ? val.toString() : val\n );\n}\n\nconst PatchFlags = {\n \"TEXT\": 1,\n \"1\": \"TEXT\",\n \"CLASS\": 2,\n \"2\": \"CLASS\",\n \"STYLE\": 4,\n \"4\": \"STYLE\",\n \"PROPS\": 8,\n \"8\": \"PROPS\",\n \"FULL_PROPS\": 16,\n \"16\": \"FULL_PROPS\",\n \"NEED_HYDRATION\": 32,\n \"32\": \"NEED_HYDRATION\",\n \"STABLE_FRAGMENT\": 64,\n \"64\": \"STABLE_FRAGMENT\",\n \"KEYED_FRAGMENT\": 128,\n \"128\": \"KEYED_FRAGMENT\",\n \"UNKEYED_FRAGMENT\": 256,\n \"256\": \"UNKEYED_FRAGMENT\",\n \"NEED_PATCH\": 512,\n \"512\": \"NEED_PATCH\",\n \"DYNAMIC_SLOTS\": 1024,\n \"1024\": \"DYNAMLine truncated
"mappings": "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 truncated
"names": ["map", "computed", "computed", "self", "hasOwnProperty", "isRef", "readonly", "effect", "isRef", "isRef", "p", "version", "effect", "watch", "callHook", "remove", "ref", "ref2", "patchProp", "hydrate", "hasWarned", "resolve", "render", "computed", "h", "createApp", "track", "trigger", "isModelListener", "emit", "render2", "remove2", "warn", "warn", "callHook", "resolve", "watch", "isBoolean", "def", "enterCbKey", "compile", "warn"]
}
-3
View File
@@ -1,3 +0,0 @@
{
"type": "module"
}
File diff suppressed because it is too large. Load diff
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/@vue/devtools-shared/dist/index.js", "../../../../node_modules/perfect-debounce/dist/index.mjs", "../../../../node_modules/hookable/dist/index.mjs", "../../../../node_modules/birpc/dist/index.mjs", "../../../../node_modules/@vue/devtools-kit/dist/index.js"],
"sourcesContent": ["var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __esm = (fn, res) => function __init() {\n return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;\n};\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target2, \"default\", { value: mod, enumerable: true }) : target2,\n mod\n));\n\n// ../../node_modules/.pnpm/tsup@8.4.0_@microsoft+api-extractor@7.51.1_@types+node@22.13.14__jiti@2.4.2_postcss@8.5_96eb05a9d65343021e53791dd83f3773/node_modules/tsup/assets/esm_shims.js\nvar init_esm_shims = __esm({\n \"../../node_modules/.pnpm/tsup@8.4.0_@microsoft+api-extractor@7.51.1_@types+node@22.13.14__jiti@2.4.2_postcss@8.5_96eb05a9d65343021e53791dd83f3773/node_modules/tsup/assets/esm_shims.js\"() {\n \"use strict\";\n }\n});\n\n// ../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js\nvar require_rfdc = __commonJS({\n \"../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js\"(exports, module) {\n \"use strict\";\n init_esm_shims();\n module.exports = rfdc2;\n function copyBuffer(cur) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur);\n }\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length);\n }\n function rfdc2(opts) {\n opts = opts || {};\n if (opts.circles) return rfdcCircles(opts);\n const constructorHandlers = /* @__PURE__ */ new Map();\n constructorHandlers.set(Date, (o) => new Date(o));\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)));\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)));\n if (opts.constructorHandlers) {\n for (const handler2 of opts.constructorHandlers) {\n constructorHandlers.set(handler2[0], handler2[1]);\n }\n }\n let handler = null;\n return opts.proto ? cloneProto : clone;\n function cloneArray(a, fn) {\n const keys = Object.keys(a);\n const a2 = new Array(keys.length);\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i];\n const cur = a[k];\n if (typeof cur !== \"object\" || cur === null) {\n a2[k] = cur;\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn);\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur);\n } else {\n a2[k] = fn(cur);\n }\n }\n return a2;\n }\n function clone(o) {\n if (typeof o !== \"object\" || o === null) return o;\n if (Array.isArray(o)) return cloneArray(o, clone);\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone);\n }\n const o2 = {};\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue;\n const cur = o[k];\n if (typeof cur !== \"object\" || cur === null) {\n o2[k] = cur;\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone);\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur);\n } else {\n o2[k] = clone(cur);\n }\n }\n return o2;\n }\n function cloneProto(o) {\n if (typeof o !== \"object\" || o === null) return o;\n if (Array.isArray(o)) return cloneArray(o, cloneProto);\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto);\n }\n const o2 = {};\n for (const k in o) {\n const cur = o[k];\n if (tLine truncated
"mappings": "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 truncated
"names": ["hooks", "hooks", "hook", "hook", "hooks", "clearTimeout", "setTimeout", "__create", "__defProp", "__getOwnPropDesc", "__getOwnPropNames", "__getProtoOf", "__hasOwnProp", "__esm", "__commonJS", "__copyProps", "__toESM", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a2", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "__toESM", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a22", "init_esm_shims", "init_esm_shims"]
}
-583
View File
@@ -1,583 +0,0 @@
import {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever,
} from './chunk-BRNHR3LR.js';
import './chunk-H6MPEGKE.js';
export {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
computedAsync as asyncComputed,
refAutoReset as autoResetRef,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
computedWithControl as controlledComputed,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
reactify as createReactiveFn,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
refDebounced as debouncedRef,
watchDebounced as debouncedWatch,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
computedEager as eagerComputed,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
watchIgnorable as ignorableWatch,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
watchPausable as pausableWatch,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
refThrottled as throttledRef,
watchThrottled as throttledWatch,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
refDebounced as useDebounce,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
refThrottled as useThrottle,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever,
};
//# sourceMappingURL=vitepress___@vueuse_core.js.map
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large. Load diff
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/tabbable/src/index.js", "../../../../node_modules/focus-trap/index.js", "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs"],
"sourcesContent": ["// NOTE: separate `:not()` selectors has broader browser support than the newer\n// `:not([inert], [inert] *)` (Feb 2023)\nconst candidateSelectors = [\n 'input:not([inert]):not([inert] *)',\n 'select:not([inert]):not([inert] *)',\n 'textarea:not([inert]):not([inert] *)',\n 'a[href]:not([inert]):not([inert] *)',\n 'button:not([inert]):not([inert] *)',\n '[tabindex]:not(slot):not([inert]):not([inert] *)',\n 'audio[controls]:not([inert]):not([inert] *)',\n 'video[controls]:not([inert]):not([inert] *)',\n '[contenteditable]:not([contenteditable=\"false\"]):not([inert]):not([inert] *)',\n 'details>summary:first-of-type:not([inert]):not([inert] *)',\n 'details:not([inert]):not([inert] *)',\n];\nconst candidateSelector = /* #__PURE__ */ candidateSelectors.join(',');\n\nconst NoElement = typeof Element === 'undefined';\n\nconst matches = NoElement\n ? function () {}\n : Element.prototype.matches ||\n Element.prototype.msMatchesSelector ||\n Element.prototype.webkitMatchesSelector;\n\nconst getRootNode =\n !NoElement && Element.prototype.getRootNode\n ? (element) => element?.getRootNode?.()\n : (element) => element?.ownerDocument;\n\n/**\n * Determines if a node is inert or in an inert ancestor.\n * @param {Node} [node]\n * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to\n * see if any of them are inert. If false, only `node` itself is considered.\n * @returns {boolean} True if inert itself or by way of being in an inert ancestor.\n * False if `node` is falsy.\n */\nconst isInert = function (node, lookUp = true) {\n // CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert`\n // JS API property; we have to check the attribute, which can either be empty or 'true';\n // if it's `null` (not specified) or 'false', it's an active element\n const inertAtt = node?.getAttribute?.('inert');\n const inert = inertAtt === '' || inertAtt === 'true';\n\n // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`\n // if it weren't for `matches()` not being a function on shadow roots; the following\n // code works for any kind of node\n const result =\n inert ||\n (lookUp &&\n node &&\n // closest does not exist on shadow roots, so we fall back to a manual\n // lookup upward, in case it is not defined.\n (typeof node.closest === 'function'\n ? node.closest('[inert]')\n : isInert(node.parentNode)));\n\n return result;\n};\n\n/**\n * Determines if a node's content is editable.\n * @param {Element} [node]\n * @returns True if it's content-editable; false if it's not or `node` is falsy.\n */\nconst isContentEditable = function (node) {\n // CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have\n // to use the attribute directly to check for this, which can either be empty or 'true';\n // if it's `null` (not specified) or 'false', it's a non-editable element\n const attValue = node?.getAttribute?.('contenteditable');\n return attValue === '' || attValue === 'true';\n};\n\n/**\n * @param {Element} el container to check in\n * @param {boolean} includeContainer add container to check\n * @param {(node: Element) => boolean} filter filter candidates\n * @returns {Element[]}\n */\nconst getCandidates = function (el, includeContainer, filter) {\n // even if `includeContainer=false`, we still have to check it for inertness because\n // if it's inert (either by itself or via its parent), then all its children are inert\n if (isInert(el)) {\n return [];\n }\n\n let candidates = Array.prototype.slice.apply(\n el.querySelectorAll(candidateSelector)\n );\n if (includeContainer && matches.call(el, candidateSelector)) {\n candidates.unshift(el);\n }\n candidates = candidates.filter(filter);\n return candidates;\n};\n\n/**\n * @callback GetShadowRoot\n * @param {Element} element to check for shadow root\n * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.\n */\n\n/**\n * @callback ShadowRootFilter\n * @param {Element} shadowHostNode the element which contains shadow content\n * @returns {boolean} true if a shadow root could potentially contain valid candidates.\n */\n\n/**\n * @typedef {Object} CandidateScope\n * @property {Element} scopeParent contains inner candidates\n * @property {Element[]} candidates list of candidates found in the scope parent\n */\n\n/**\n * @typedef {Object} IterativeOptions\n * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;\n * if a function, implies shadow support is enabled and either returns the shadow root of an element\n * or a boolean stating if it has an undisclosed shadow root\n * @property {(node: Element) => boolean} filter filter candidates\n * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned lLine truncated
"mappings": "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 truncated
"names": ["candidateSelectors", "candidateSelector", "join", "NoElement", "Element", "matches", "prototype", "msMatchesSelector", "webkitMatchesSelector", "getRootNode", "element", "_element$getRootNode", "call", "ownerDocument", "isInert", "node", "lookUp", "_node$getAttribute", "inertAtt", "getAttribute", "inert", "result", "closest", "parentNode", "isContentEditable", "_node$getAttribute2", "attValue", "getCandidates", "el", "includeContainer", "filter", "candidates", "Array", "slice", "apply", "querySelectorAll", "unshift", "getCandidatesIteratively", "elements", "options", "elementsToCheck", "from", "length", "shift", "tagName", "assigned", "assignedElements", "content", "children", "nestedCandidates", "flatten", "push", "scopeParent", "validCandidate", "includes", "shadowRoot", "getShadowRoot", "validShadowRoot", "shadowRootFilter", "hasTabIndex", "isNaN", "parseInt", "getTabIndex", "Error", "tabIndex", "test", "getSortOrderTabIndex", "isScope", "sortOrderedTabbables", "a", "b", "documentOrder", "isInput", "isHiddenInput", "type", "isDetailsWithSummary", "r", "some", "child", "getCheckedRadio", "nodes", "form", "i", "checked", "isTabbableRadio", "name", "radioScope", "queryRadios", "radioSet", "window", "CSS", "escape", "err", "console", "error", "message", "isRadio", "isNonTabbableRadio", "isNodeAttached", "_nodeRoot", "nodeRoot", "nodeRootHost", "host", "attached", "_nodeRootHost", "_nodeRootHost$ownerDo", "_node$ownerDocument", "contains", "_nodeRoot2", "_nodeRootHost2", "_nodeRootHost2$ownerD", "isZeroArea", "_node$getBoundingClie", "getBoundingClientRect", "width", "height", "isHidden", "_ref", "displayCheck", "visible", "checkVisibility", "checkOpacity", "opacityProperty", "contentVisibilityAuto", "visibilityProperty", "checkVisibilityCSS", "getComputedStyle", "visibility", "isDirectSummary", "nodeUnderDetails", "parentElement", "originalNode", "rootNode", "assignedSlot", "getClientRects", "isDisabledFromFieldset", "disabled", "item", "isNodeMatchingSelectorFocusable", "isNodeMatchingSelectorTabbable", "isShadowRootTabbable", "shadowHostNode", "sortByOrder", "regularTabbables", "orderedTabbables", "forEach", "candidateTabindex", "sort", "reduce", "acc", "sortable", "concat", "tabbable", "container", "bind", "focusable", "isTabbable", "focusableCandidateSelector", "isFocusable", "activeFocusTraps", "getActiveTrap", "trapStack", "length", "activateTrap", "trap", "activeTrap", "pauseTrap", "trapIndex", "indexOf", "push", "splice", "deactivateTrap", "unpauseTrap", "_setPausedState", "_isManuallyPaused", "isSelectableInput", "node", "tagName", "toLowerCase", "select", "isEscapeEvent", "e", "key", "keyCode", "isTabEvent", "isKeyForward", "shiftKey", "isKeyBackward", "delay", "fn", "setTimeout", "valueOrHandler", "value", "_len", "arguments", "params", "Array", "_key", "apply", "getActualTarget", "event", "target", "shadowRoot", "composedPath", "internalTrapStack", "createFocusTrap", "elements", "userOptions", "doc", "document", "config", "_objectSpread", "returnFocusOnDeactivate", "escapeDeactivates", "delayInitialFocus", "isolateSubtrees", "state", "containers", "containerGroups", "tabbableGroups", "adjacentElements", "Set", "alreadyInert", "nodeFocusedBeforeActivation", "mostRecentlyFocusedNode", "active", "paused", "manuallyPaused", "delayInitialFocusTimer", "undefined", "recentNavEvent", "getOption", "configOverrideOptions", "optionName", "configOptionName", "findContainerIndex", "element", "findIndex", "_ref", "container", "tabbableNodes", "contains", "includes", "find", "getNodeForOption", "_ref2", "_ref2$hasFallback", "hasFallback", "_ref2$params", "optionValue", "_toConsumableArray", "Error", "concat", "querySelector", "err", "message", "getInitialFocusNode", "isFocusable", "tabbableOptions", "activeElement", "firstTabbableGroup", "firstTabbableNode", "updateTabbableNodes", "map", "tabbable", "focusableNodes", "focusable", "lastTabbableNode", "firstDomTabbableNode", "isTabbable", "lastDomTabbableNode", "slice", "reverse", "posTabIndexesFound", "getTabIndex", "nextTabbableNode", "forward", "nodeIdx", "el", "filter", "group", "g", "getActiveElement", "tryFocus", "focus", "preventScroll", "getReturnFocusNode", "previousActiveElement", "findNextNavNode", "_ref3", "_ref3$isBackward", "isBackward", "destinationNode", "containerIndex", "containerGroup", "startOfGroupIndex", "_ref4", "destinationGroupIndex", "destinationGroup", "lastOfGroupIndex", "_ref5", "checkPointerDown", "clickOutsideDeactivates", "deactivate", "returnFocus", "allowOutsideClick", "preventDefault", "checkFocusIn", "targetContained", "Document", "stopImmediatePropagation", "nextNode", "navAcrossContainers", "mruContainerIdx", "mruTabIdx", "some", "n", "checkKeyNav", "checkTabKey", "checkEscapeKey", "checkClick", "addListeners", "addEventListener", "capture", "passive", "collectAdjacentElements", "_setSubtreeIsolation", "clear", "containerAncestors", "_iterator", "_createForOfIteratorHelper", "_step", "s", "done", "add", "insideSLine truncated
}
File diff suppressed because it is too large. Load diff
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/mark.js/src/lib/domiterator.js", "../../../../node_modules/mark.js/src/lib/mark.js", "../../../../node_modules/mark.js/src/vanilla.js"],
"sourcesContent": ["/**\n * A NodeIterator with iframes support and a method to check if an element is\n * matching a specified selector\n * @example\n * const iterator = new DOMIterator(\n * document.querySelector(\"#context\"), true\n * );\n * iterator.forEachNode(NodeFilter.SHOW_TEXT, node => {\n * console.log(node);\n * }, node => {\n * if(DOMIterator.matches(node.parentNode, \".ignore\")){\n * return NodeFilter.FILTER_REJECT;\n * } else {\n * return NodeFilter.FILTER_ACCEPT;\n * }\n * }, () => {\n * console.log(\"DONE\");\n * });\n * @todo Outsource into separate repository\n */\nexport default class DOMIterator {\n\n /**\n * @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM\n * element, an array of DOM elements, a NodeList or a selector\n * @param {boolean} [iframes=true] - A boolean indicating if iframes should\n * be handled\n * @param {string[]} [exclude=[]] - An array containing exclusion selectors\n * for iframes\n * @param {number} [iframesTimeout=5000] - A number indicating the ms to\n * wait before an iframe should be skipped, in case the load event isn't\n * fired. This also applies if the user is offline and the resource of the\n * iframe is online (either by the browsers \"offline\" mode or because\n * there's no internet connection)\n */\n constructor(ctx, iframes = true, exclude = [], iframesTimeout = 5000) {\n /**\n * The context of the instance. Either a DOM element, an array of DOM\n * elements, a NodeList or a selector\n * @type {HTMLElement|HTMLElement[]|NodeList|string}\n * @access protected\n */\n this.ctx = ctx;\n /**\n * Boolean indicating if iframe support is enabled\n * @type {boolean}\n * @access protected\n */\n this.iframes = iframes;\n /**\n * An array containing exclusion selectors for iframes\n * @type {string[]}\n */\n this.exclude = exclude;\n /**\n * The maximum ms to wait for a load event before skipping an iframe\n * @type {number}\n */\n this.iframesTimeout = iframesTimeout;\n }\n\n /**\n * Checks if the specified DOM element matches the selector\n * @param {HTMLElement} element - The DOM element\n * @param {string|string[]} selector - The selector or an array with\n * selectors\n * @return {boolean}\n * @access public\n */\n static matches(element, selector) {\n const selectors = typeof selector === 'string' ? [selector] : selector,\n fn = (\n element.matches ||\n element.matchesSelector ||\n element.msMatchesSelector ||\n element.mozMatchesSelector ||\n element.oMatchesSelector ||\n element.webkitMatchesSelector\n );\n if (fn) {\n let match = false;\n selectors.every(sel => {\n if (fn.call(element, sel)) {\n match = true;\n return false;\n }\n return true;\n });\n return match;\n } else { // may be false e.g. when el is a textNode\n return false;\n }\n }\n\n /**\n * Returns all contexts filtered by duplicates (even nested)\n * @return {HTMLElement[]} - An array containing DOM contexts\n * @access protected\n */\n getContexts() {\n let ctx,\n filteredCtx = [];\n if (typeof this.ctx === 'undefined' || !this.ctx) { // e.g. null\n ctx = [];\n } else if (NodeList.prototype.isPrototypeOf(this.ctx)) {\n ctx = Array.prototype.slice.call(this.ctx);\n } else if (Array.isArray(this.ctx)) {\n ctx = this.ctx;\n } else if (typeof this.ctx === 'string') {\n ctx = Array.prototype.slice.call(\n document.querySelectorAll(this.ctx)\n );\n } else { // e.g. HTMLElement or element inside iframe\n ctx = [this.ctx];\n }\n // filter duplicate text nodes\n ctx.forEach(ctx => {\n const isDescendant = filteredCtx.filter(contexts => {\n return contexts.contains(ctx);\n }).length > 0;\n if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) {\n filteredCtx.push(ctx);\n }\n });\n return filteredCtx;\n }\n\n /**\n * @callback DOMIterator~getIframeContentsSuccessCallback\n * @param {HTMLDocument} contents - The contentDocument of the iframe\n */\n /**\n * Calls the success callback function with the iframe document. If it can't\n * be accessed it calls the error callback function\n * @param {HTMLElement} ifr - The iframe DOM element\n * @param {DOMIterator~getIframeContentsSuccessCallback} successFn\n * @param {function} [errorFn]\n * @access protected\n */\n getIframeContents(ifr, successFn, errorFn = () => {}) {\n let doc;\n try {\n const ifrWin = ifr.contentWindow;\n doc = ifrWin.document;\n if (!ifrWin || !doc) { // no permission = null. Undefined in Phantom\n throw new Error('iframe inaccessible');\n }\n } catch (e) {\n errorFn();\n }\n if (doc) {\n successFn(doc);\n }\n }\n\n /Line truncated
"mappings": "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 truncated
"names": ["ctx", "ifr", "node", "dct", "Mark"]
}
File diff suppressed because it is too large. Load diff
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../../node_modules/minisearch/src/SearchableMap/TreeIterator.ts", "../../../../node_modules/minisearch/src/SearchableMap/fuzzySearch.ts", "../../../../node_modules/minisearch/src/SearchableMap/SearchableMap.ts", "../../../../node_modules/minisearch/src/MiniSearch.ts"],
"sourcesContent": ["import type { RadixTree, Entry, LeafType } from './types'\n\n/** @ignore */\nconst ENTRIES = 'ENTRIES'\n\n/** @ignore */\nconst KEYS = 'KEYS'\n\n/** @ignore */\nconst VALUES = 'VALUES'\n\n/** @ignore */\nconst LEAF = '' as LeafType\n\ninterface Iterators<T> {\n ENTRIES: Entry<T>\n KEYS: string\n VALUES: T\n}\n\ntype Kind<T> = keyof Iterators<T>\ntype Result<T, K extends keyof Iterators<T>> = Iterators<T>[K]\n\ntype IteratorPath<T> = {\n node: RadixTree<T>,\n keys: string[]\n}[]\n\nexport type IterableSet<T> = {\n _tree: RadixTree<T>,\n _prefix: string\n}\n\n/**\n * @private\n */\nclass TreeIterator<T, K extends Kind<T>> implements Iterator<Result<T, K>> {\n set: IterableSet<T>\n _type: K\n _path: IteratorPath<T>\n\n constructor (set: IterableSet<T>, type: K) {\n const node = set._tree\n const keys = Array.from(node.keys())\n this.set = set\n this._type = type\n this._path = keys.length > 0 ? [{ node, keys }] : []\n }\n\n next (): IteratorResult<Result<T, K>> {\n const value = this.dive()\n this.backtrack()\n return value\n }\n\n dive (): IteratorResult<Result<T, K>> {\n if (this._path.length === 0) { return { done: true, value: undefined } }\n const { node, keys } = last(this._path)!\n if (last(keys) === LEAF) { return { done: false, value: this.result() } }\n\n const child = node.get(last(keys)!)!\n this._path.push({ node: child, keys: Array.from(child.keys()) })\n return this.dive()\n }\n\n backtrack (): void {\n if (this._path.length === 0) { return }\n const keys = last(this._path)!.keys\n keys.pop()\n if (keys.length > 0) { return }\n this._path.pop()\n this.backtrack()\n }\n\n key (): string {\n return this.set._prefix + this._path\n .map(({ keys }) => last(keys))\n .filter(key => key !== LEAF)\n .join('')\n }\n\n value (): T {\n return last(this._path)!.node.get(LEAF)!\n }\n\n result (): Result<T, K> {\n switch (this._type) {\n case VALUES: return this.value() as Result<T, K>\n case KEYS: return this.key() as Result<T, K>\n default: return [this.key(), this.value()] as Result<T, K>\n }\n }\n\n [Symbol.iterator] () {\n return this\n }\n}\n\nconst last = <T>(array: T[]): T | undefined => {\n return array[array.length - 1]\n}\n\nexport { TreeIterator, ENTRIES, KEYS, VALUES, LEAF }\n", "/* eslint-disable no-labels */\nimport { LEAF } from './TreeIterator'\nimport type { RadixTree } from './types'\n\nexport type FuzzyResult<T> = [T, number]\n\nexport type FuzzyResults<T> = Map<string, FuzzyResult<T>>\n\n/**\n * @ignore\n */\nexport const fuzzySearch = <T = any>(node: RadixTree<T>, query: string, maxDistance: number): FuzzyResults<T> => {\n const results: FuzzyResults<T> = new Map()\n if (query === undefined) return results\n\n // Number of columns in the Levenshtein matrix.\n const n = query.length + 1\n\n // Matching terms can never be longer than N + maxDistance.\n const m = n + maxDistance\n\n // Fill first matrix row and column with numbers: 0 1 2 3 ...\n const matrix = new Uint8Array(m * n).fill(maxDistance + 1)\n for (let j = 0; j < n; ++j) matrix[j] = j\n for (let i = 1; i < m; ++i) matrix[i * n] = i\n\n recurse(\n node,\n query,\n maxDistance,\n results,\n matrix,\n 1,\n n,\n ''\n )\n\n return results\n}\n\n// Modified version of http://stevehanov.ca/blog/?id=114\n\n// This builds a Levenshtein matrix for a given query and continuously updates\n// it for nodes in the radix tree that fall within the given maximum edit\n// distance. Keeping the same matrix around is beneficial especially for larger\n// edit distances.\n//\n// k a t e <-- query\n// 0 1 2 3 4\n// c 1 1 2 3 4\n// a 2 2 1 2 3\n// t 3 3 2 1 [2] <-- edit distance\n// ^\n// ^ term in radix tree, rows are added and removed as needed\n\nconst recurse = <T = any>(\n node: RadixTree<T>,\n query: string,\n maxDistance: number,\n results: FuzzyResults<T>,\n matrix: Uint8Array,\n m: number,\n n: number,\n prefix: string\n): void => {\n const offset = m * n\n\n key: for (const key of node.keys()) {\n if (key === LEAF) {\n // We've reached a leaf node. Check if the edit distance acceptable and\n // store the result if it is.\n const distance = matrix[offset - 1]\n if (distance <= maxDistance) {\n results.set(prefix, [node.get(key)!, distance])\n }\n } else {\n // Iterate over all characters in the key. Update the Levenshtein matrix\n // and check if the minimum distance in the last row is still within the\n // maximum edit distance. If it is, we can recurse over all child nodes.\n let i = m\n for (let pos = 0; pos < key.length; ++pos, ++i) {\n const char = key[pos]\n const thisRowOffset = n * i\n const prevRowOffset = thisRowOffset - n\n\n // Set the first column based on the previous row, Line truncated
"mappings": "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 truncated
"names": ["last", "node", "child", "key", "chunk", "promise", "conditions", "options", "results", "query", "boosts", "data"]
}
-347
View File
@@ -1,347 +0,0 @@
import {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBaseVNode,
createBlock,
createCommentVNode,
createElementBlock,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
nodeOps,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
patchProp,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId,
} from './chunk-H6MPEGKE.js';
export {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBlock,
createCommentVNode,
createElementBlock,
createBaseVNode as createElementVNode,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
nodeOps,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
patchProp,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId,
};
//# sourceMappingURL=vue.js.map
-7
View File
@@ -1,7 +0,0 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+4 -3
View File
@@ -7,6 +7,7 @@ export default defineConfig({
description: "Documentation for BentoPDF - The free, open-source, privacy-first PDF toolkit",
base: '/docs/',
cleanUrls: true,
metaChunk: true,
transformPageData(pageData) {
const relPath = pageData.relativePath.replace(/\.md$/, '')
@@ -115,7 +116,7 @@ export default defineConfig({
{ text: 'PDF to Excel', link: '/tools/pdf-to-excel' },
{ text: 'PDF to Greyscale', link: '/tools/pdf-to-greyscale' },
{ text: 'PDF to JSON', link: '/tools/pdf-to-json' },
{ text: 'PDF to Word', link: '/tools/pdf-to-docx' },
{ text: 'PDF to Word', link: '/tools/pdf-to-word' },
{ text: 'Extract Images', link: '/tools/extract-images' },
{ text: 'PDF to Markdown', link: '/tools/pdf-to-markdown' },
{ text: 'Prepare PDF for AI', link: '/tools/prepare-pdf-for-ai' },
@@ -176,9 +177,9 @@ export default defineConfig({
text: 'Secure PDF',
collapsed: true,
items: [
{ text: 'Encrypt PDF', link: '/tools/encrypt-pdf' },
{ text: 'Protect PDF', link: '/tools/protect-pdf' },
{ text: 'Sanitize PDF', link: '/tools/sanitize-pdf' },
{ text: 'Decrypt PDF', link: '/tools/decrypt-pdf' },
{ text: 'Unlock PDF', link: '/tools/unlock-pdf' },
{ text: 'Flatten PDF', link: '/tools/flatten-pdf' },
{ text: 'Remove Metadata', link: '/tools/remove-metadata' },
{ text: 'Change Permissions', link: '/tools/change-permissions' },
+1 -1
View File
@@ -123,7 +123,7 @@ The included Cloudflare Worker has several security measures:
| **Private IP Blocking** | Blocks IPv4/IPv6 private ranges, link-local, loopback, decimal IPs, and cloud metadata |
| **Content-Type Safety** | Only returns safe certificate MIME types, blocks upstream content-type injection |
| **File Size Limit** | Streams response with 10MB limit, aborts mid-download if exceeded |
| **Rate Limiting** | 60 requests per IP per minute (requires KV) |
| **Rate Limiting** | 60 requests per minute per IP or IPv6 /64 (requires KV, fails open on KV errors) |
| **HMAC Signatures** | Optional client-side signing (deters casual abuse) |
### DNS rebinding (self-hosting off Cloudflare)
+4 -3
View File
@@ -126,10 +126,11 @@ The nginx image ships with an enforcing `Content-Security-Policy` header. The CS
As a result:
- If you override `VITE_CORS_PROXY_URL` or `VITE_WASM_*_URL` at build time, the CSP permits those origins automatically — no extra config needed.
- If you configure custom WASM URLs at _runtime_ via the in-app Advanced Settings page, those origins are **not** in the CSP and the browser will block fetches to them. Runtime configuration is intended for experimentation; for permanent custom URLs set the matching `VITE_*` build arg.
- Air-gapped deployments that override all three `VITE_WASM_*_URL` values also get the public `cdn.jsdelivr.net` removed from CSP (each default is replaced, not appended). Similarly, setting `VITE_CORS_PROXY_URL` replaces the public `bentopdf-cors-proxy.bentopdf.workers.dev` default.
- For URLs on `cdn.jsdelivr.net`, `script-src` allows only the exact versioned package folder, for example `https://cdn.jsdelivr.net/npm/@bentopdf/pymupdf-wasm@0.11.16/`, not the whole CDN. jsDelivr serves any public npm package or GitHub repository, so allowing the whole host would let any of them run on your instance. URLs on any other host are allowed by origin.
- If you configure custom WASM URLs at _runtime_ via the in-app Advanced Settings page, those origins are **not** in the CSP and the browser will block fetches to them. This also applies to a different version of the same package on `cdn.jsdelivr.net`, because only the version set at build time is allowed. Runtime configuration is intended for experimentation; for permanent custom URLs set the matching `VITE_*` build arg.
- Air-gapped deployments that override all three `VITE_WASM_*_URL` values also get those `cdn.jsdelivr.net` package folders removed from CSP (each default is replaced, not appended). The Tesseract OCR defaults on `cdn.jsdelivr.net` stay in the policy until you also set the three `VITE_TESSERACT_*` values. Similarly, setting `VITE_CORS_PROXY_URL` replaces the public `bentopdf-cors-proxy.bentopdf.workers.dev` default.
The CSP includes `'unsafe-eval'` in `script-src` because the LibreOffice WASM runtime (used by Word/Excel/PowerPoint conversion tools) compiles internal dispatch code via `new Function()`. Removing it would break all LibreOffice-backed tools. If you build in `SIMPLE_MODE` (without LibreOffice), you can manually edit the generated `security-headers.conf` to drop `'unsafe-eval'` for a stricter policy.
The CSP includes `'unsafe-eval'` in `script-src` because the LibreOffice WASM runtime (used by Word/Excel/PowerPoint conversion tools) and the wasm-vips image library (used by PDF to TIFF) compile internal dispatch code via `new Function()`. Removing it would break those tools. If you build in `SIMPLE_MODE` (without LibreOffice) and do not need PDF to TIFF, you can manually edit the generated `security-headers.conf` to drop `'unsafe-eval'` for a stricter policy.
For OCR, leave the `VITE_TESSERACT_*` variables empty to use the default online assets, or set all three together for self-hosted/offline OCR. Partial OCR overrides are rejected because the worker, core runtime, and traineddata directory must match. For fully offline searchable PDF output, also set `VITE_OCR_FONT_BASE_URL` so the OCR text-layer fonts are loaded from your internal server instead of the public Noto font URLs.
+2 -2
View File
@@ -56,6 +56,6 @@ If you set only an owner password (no user password), anyone can open the file b
## Related Tools
- [Encrypt PDF](./encrypt-pdf) -- simple password protection without granular permissions
- [Decrypt PDF](./decrypt-pdf) -- remove encryption entirely
- [Encrypt PDF](./protect-pdf) -- simple password protection without granular permissions
- [Decrypt PDF](./unlock-pdf) -- remove encryption entirely
- [Remove Restrictions](./remove-restrictions) -- strip all restrictions when you have the owner password
+41 -37
View File
@@ -1,69 +1,73 @@
---
title: Compress PDF
description: Reduce PDF file size by up to 90% with smart compression algorithms. Supports batch processing and custom quality settings.
description: Reduce PDF file size by up to 90% with the Hyper Compress engine. Supports target file sizes, batch processing, and custom quality settings.
---
# Compress PDF
Shrink your PDF files without destroying them. BentoPDF offers two distinct compression algorithms -- one for text-heavy documents, another for photo-heavy scans -- so you get meaningful size reduction regardless of what your PDF contains.
Shrink your PDF files without destroying them. Compress PDF is powered by [Hyper Compress](https://www.bentopdf.com/hyper-compress), BentoPDF's own compression engine. It recompresses images, subsets and merges fonts, and strips dead weight such as embedded thumbnails and private application data. The PDF stays fully functional: text remains selectable, links and form fields keep working.
Hyper Compress is compiled to WebAssembly and ships with BentoPDF, so compression works offline and in air-gapped deployments with no extra setup.
## How It Works
1. Upload one or more PDFs by clicking the drop zone or dragging files in.
2. Select a **Compression Algorithm** -- Condense or Photon.
3. Pick a **Compression Level** from Light to Extreme.
4. Optionally toggle **Convert to Grayscale** or expand **Custom Settings** for fine-grained control.
5. Click **Compress PDF**. For multiple files, you get a single ZIP download.
2. Pick a **Compression Level**: Low, Medium, High, or Lossless.
3. Optionally enter a **Target File Size**, or expand **Custom Settings** for fine-grained control, including **Convert to grayscale**.
4. Click **Compress PDF**. For multiple files, you get a single ZIP download.
## Compression Algorithms
## Special Documents
### Condense (Recommended)
The default algorithm. It removes dead weight from the PDF structure, recompresses images at a target DPI, subsets fonts to strip unused glyphs, and removes embedded thumbnails. The PDF stays fully functional -- text remains selectable, links keep working.
Condense requires the PyMuPDF WASM engine.
### Photon (For Photo-Heavy PDFs)
Photon renders each page to a JPEG image and reassembles them into a new PDF. This works well for scanned documents or image-heavy files where Condense cannot squeeze much out. The trade-off is that text becomes non-selectable and hyperlinks stop working.
- **Digitally signed PDFs** are returned unchanged, because any change would invalidate the signature. Turn on **Override content protection** under Custom Settings to remove the signatures and compress them; the visible signature stays on the page, but the file is no longer signed.
- **PDF/A files** lose their PDF/A label after compression, so the file never claims a conformance it no longer meets. Turn on **Preserve PDF/A** under Custom Settings to keep the file conformant instead.
- **Password-protected PDFs** get a password field on their file card. Enter the password there and Hyper Compress opens the file itself, no separate unlock step. With two or more locked files, one shared field unlocks every file that uses the same password. The compressed copy has no password; use [Protect PDF](./protect-pdf) to add one again.
- **Scans with no text layer** can shrink further with **Rasterize pages** under Custom Settings, which replaces each page with one optimized image. It is skipped for any document that has selectable text, including OCR'd scans, unless **Override content protection** is on. Then text pages become images too, so text stops being selectable and links stop working.
## Compression Levels
| Level | Image Quality | DPI Target | Best For |
| -------------- | ------------- | ---------- | ------------------------------ |
| **Light** | 90% | 150 | Preserving visual quality |
| **Balanced** | 75% | 96 | Everyday documents |
| **Aggressive** | 50% | 72 | Email attachments, web uploads |
| **Extreme** | 30% | 60 | Maximum size reduction |
| Level | Image Quality | Max Resolution | Best For |
| ------------ | ---------------- | -------------- | ------------------------------ |
| **Low** | 80 | 200 DPI | Preserving visual quality |
| **Medium** | 50 | 150 DPI | Everyday documents |
| **High** | 20 | 72 DPI | Email attachments, web uploads |
| **Lossless** | Images untouched | Unchanged | Archival copies |
High also unembeds the 14 standard PDF fonts, plus look-alikes such as Arial when that is safe.
## Target File Size
Enter a size in KB or MB and Hyper Compress searches for the best image quality that still fits, starting from the level you picked. If the document cannot get that small, you get the smallest version it can make and a message saying so. The dedicated pages such as [Compress PDF to 1MB](https://www.bentopdf.com/compress-pdf-to-1mb) open with the target already filled in.
## Custom Settings
Expand the Custom Settings panel to override preset values:
Expand the Custom Settings panel to adjust Hyper Compress directly. Choosing a compression level resets these to that level's values, and editing any of them switches the level to Custom.
- **Output Quality** (1-100%) -- JPEG quality for recompressed images
- **Resize Images To** (DPI) -- target resolution for downsampled images
- **Only Process Above** (DPI) -- images below this threshold are left untouched
- **Remove metadata** -- strips document info fields
- **Subset fonts** -- removes unused glyphs from embedded fonts
- **Remove embedded thumbnails** -- drops preview images stored inside the PDF
- **Override content protection**: by default Hyper Compress leaves signed PDFs untouched and won't rasterize pages that have text. Turning this on bypasses both. It stays on when you change the level.
- **Images**: image quality, maximum resolution, forced resampling, color reduction, clipping invisible image areas, removing alternate images, simplifying color profiles, JPEG 2000, and lossless mode
- **Fonts**: subsetting, merging duplicates, and unembedding standard fonts and their look-alikes
- **Content**: flattening annotations, form fields, or links
- **Cleanup**: removing thumbnails, application data, article threads, web capture information, the structure tree, or output intents
- **Rasterize**: replacing pages with images, for image-only scans; skipped when the document has selectable text
- **Output**: Preserve PDF/A, and Brotli compression for PDF 2.0 readers that support it
## Use Cases
- Bringing a 50 MB report under an email attachment limit
- Getting a scan under a portal's strict upload limit with a target file size
- Optimizing marketing PDFs for faster website downloads
- Archiving large document sets where storage costs matter
- Preparing scanned contracts for a document management system
- Reducing mobile data usage when sharing PDFs over messaging apps
## Tips
- Start with Balanced. If the result is still too large, step up to Aggressive before trying Extreme.
- Use Photon only when Condense produces minimal savings -- it permanently removes text selection.
- The grayscale toggle alone can cut file size substantially for color-heavy documents.
- Start with Medium. If the result is still too large, set a target file size or step up to High.
- For a scan with no text layer, turn on Rasterize pages under Custom Settings.
- Convert to grayscale, under Custom Settings, can cut file size for color-heavy documents.
## Related Tools
- [Linearize PDF](./linearize-pdf) -- optimize the compressed PDF for fast web viewing
- [Rasterize PDF](./rasterize-pdf) -- convert pages to images at a specific DPI
- [Repair PDF](./repair-pdf) -- fix a PDF that broke during compression elsewhere
- [Remove Metadata](./remove-metadata) -- strip hidden data for privacy
- [Linearize PDF](./linearize-pdf): optimize the compressed PDF for fast web viewing
- [Rasterize PDF](./rasterize-pdf): convert pages to images at a specific DPI, including pages with text
- [Repair PDF](./repair-pdf): fix a PDF that broke during compression elsewhere
- [Remove Metadata](./remove-metadata): strip hidden data for privacy
+1 -1
View File
@@ -61,5 +61,5 @@ Signing may require an internet connection. The signing library fetches the cert
- [Validate Signature](./validate-signature-pdf) -- verify digital signatures in signed PDFs
- [Flatten PDF](./flatten-pdf) -- flatten forms before signing to prevent modifications
- [Encrypt PDF](./encrypt-pdf) -- add password protection on top of the digital signature
- [Encrypt PDF](./protect-pdf) -- add password protection on top of the digital signature
- [Remove Metadata](./remove-metadata) -- strip metadata before signing
+2 -1
View File
@@ -18,7 +18,7 @@ BentoPDF's PDF Editor lets you annotate, highlight, redact, comment, add shapes
- Full annotation toolbar with highlighting, underlining, strikethrough, and freehand drawing
- Text insertion and commenting
- Redaction tools for permanently removing sensitive content
- Redaction tools that permanently remove marked content once you apply the redaction. If any marks haven't been applied when you click **Download Edited PDF**, the editor offers to apply them first.
- Shape tools for rectangles, circles, lines, and arrows
- Image insertion onto PDF pages
- Built-in text search across the document
@@ -37,6 +37,7 @@ BentoPDF's PDF Editor lets you annotate, highlight, redact, comment, add shapes
- You can open multiple PDFs at once and switch between them using the tab bar at the top of the editor.
- The editor preserves the original PDF structure, so fonts, layouts, and form fields remain intact.
- Marking text or an area for redaction doesn't remove anything until the redaction is applied. When you redact selected text, copies of it in the file's properties, bookmarks, comments, and attachments are also removed from the download, unless the file is encrypted.
- For bulk watermarking or page numbering, use the dedicated tools instead for more control over formatting.
## Related Tools
+1 -1
View File
@@ -48,4 +48,4 @@ The tool uses pdf-lib to flatten form fields (via `form.flatten()`) and a dedica
- [Sanitize PDF](./sanitize-pdf) -- flatten forms plus remove metadata, scripts, and more
- [Rasterize PDF](./rasterize-pdf) -- convert to image-based PDF for maximum flattening
- [Font to Outline](./font-to-outline) -- flatten fonts to vector paths
- [Encrypt PDF](./encrypt-pdf) -- lock the flattened PDF with a password
- [Encrypt PDF](./protect-pdf) -- lock the flattened PDF with a password
+3 -3
View File
@@ -95,7 +95,7 @@ Extract content from PDFs into images, documents, and data formats.
- [**PDF to Excel**](./pdf-to-excel) — Extract tables from PDF and convert to Excel (XLSX).
- [**PDF to Greyscale**](./pdf-to-greyscale) — Convert all colors to black and white.
- [**PDF to JSON**](./pdf-to-json) — Convert PDF files to JSON format.
- [**PDF to Word**](./pdf-to-docx) — Convert PDF files to editable Word documents.
- [**PDF to Word**](./pdf-to-word) — Convert PDF files to editable Word documents.
- [**Extract Images**](./extract-images) — Extract all embedded images from your PDF files.
- [**PDF to Markdown**](./pdf-to-markdown) — Convert PDF text and tables to Markdown format.
- [**Prepare PDF for AI**](./prepare-pdf-for-ai) — Extract PDF content as LlamaIndex JSON for RAG/LLM pipelines.
@@ -171,9 +171,9 @@ Protect, encrypt, and control access to your PDF documents.
<div class="tool-grid">
- [**Encrypt PDF**](./encrypt-pdf) — Lock your PDF by adding a password.
- [**Encrypt PDF**](./protect-pdf) — Lock your PDF by adding a password.
- [**Sanitize PDF**](./sanitize-pdf) — Remove metadata, annotations, scripts, and more.
- [**Decrypt PDF**](./decrypt-pdf) — Unlock PDF by removing password protection.
- [**Decrypt PDF**](./unlock-pdf) — Unlock PDF by removing password protection.
- [**Flatten PDF**](./flatten-pdf) — Make form fields and annotations non-editable.
- [**Remove Metadata**](./remove-metadata) — Strip hidden data from your PDF.
- [**Change Permissions**](./change-permissions) — Set or change user permissions on a PDF.
+1 -1
View File
@@ -39,5 +39,5 @@ Converts PDF files to Markdown (`.md`) format, preserving headings, paragraphs,
## Related Tools
- [PDF to Text](./pdf-to-text)
- [PDF to Word](./pdf-to-docx)
- [PDF to Word](./pdf-to-word)
- [Prepare PDF for AI](./prepare-pdf-for-ai)
+1 -1
View File
@@ -40,4 +40,4 @@ This tool has no configurable options. All text content is extracted from every
- [PDF to Markdown](./pdf-to-markdown)
- [Prepare PDF for AI](./prepare-pdf-for-ai)
- [PDF to Word](./pdf-to-docx)
- [PDF to Word](./pdf-to-word)
File renamed without changes.
@@ -58,7 +58,7 @@ AES-256 is computationally infeasible to brute-force with current technology. Th
## Related Tools
- [Decrypt PDF](./decrypt-pdf) -- remove encryption when you know the password
- [Decrypt PDF](./unlock-pdf) -- remove encryption when you know the password
- [Change Permissions](./change-permissions) -- modify specific usage restrictions
- [Remove Restrictions](./remove-restrictions) -- strip all security from a PDF
- [Sanitize PDF](./sanitize-pdf) -- remove hidden content before encrypting
+1 -1
View File
@@ -46,5 +46,5 @@ No options to configure. The tool is thorough by design: it clears everything.
## Related Tools
- [Sanitize PDF](./sanitize-pdf) -- remove metadata plus scripts, attachments, and more
- [Encrypt PDF](./encrypt-pdf) -- protect the cleaned PDF with a password
- [Encrypt PDF](./protect-pdf) -- protect the cleaned PDF with a password
- [Compress PDF](./compress-pdf) -- removing metadata can slightly reduce file size; compress for more savings
+2 -2
View File
@@ -40,6 +40,6 @@ The tool uses QPDF's `--decrypt` and `--remove-restrictions` flags to produce a
## Related Tools
- [Decrypt PDF](./decrypt-pdf) -- unlock a PDF when you know the user password
- [Encrypt PDF](./encrypt-pdf) -- re-apply encryption with new settings
- [Decrypt PDF](./unlock-pdf) -- unlock a PDF when you know the user password
- [Encrypt PDF](./protect-pdf) -- re-apply encryption with new settings
- [Change Permissions](./change-permissions) -- selectively modify which actions are allowed
+1 -1
View File
@@ -49,5 +49,5 @@ All options are enabled by default. Uncheck any you want to preserve.
- [Remove Metadata](./remove-metadata) -- strip only metadata without touching other content
- [Flatten PDF](./flatten-pdf) -- flatten forms and annotations specifically
- [Encrypt PDF](./encrypt-pdf) -- add password protection after sanitizing
- [Encrypt PDF](./protect-pdf) -- add password protection after sanitizing
- [Rasterize PDF](./rasterize-pdf) -- the nuclear option: convert to images to eliminate all hidden content
@@ -41,6 +41,6 @@ If you have the password to an encrypted PDF, this tool removes the encryption e
## Related Tools
- [Encrypt PDF](./encrypt-pdf) -- re-apply encryption with a new password
- [Encrypt PDF](./protect-pdf) -- re-apply encryption with a new password
- [Remove Restrictions](./remove-restrictions) -- remove usage restrictions without full decryption
- [Change Permissions](./change-permissions) -- modify specific permissions on an encrypted PDF
+56 -85
View File
@@ -49,6 +49,7 @@
<meta name="twitter:site" content="@BentoPDF" />
<link href="/src/css/styles.css" rel="stylesheet" />
<link href="/src/css/landing.css" rel="stylesheet" />
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest" />
@@ -75,10 +76,13 @@
<link rel="icon" href="/favicon.ico" sizes="32x32" />
</head>
<body class="antialiased bg-gray-900 text-gray-300">
<body class="lp antialiased bg-gray-900 text-gray-300">
{{> navbar }}
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
<div
id="app"
class="min-h-screen container mx-auto px-4 pt-4 md:px-8 md:pt-8"
>
<section id="faq-hero" class="text-center py-16 md:py-24">
<h1 class="text-4xl md:text-5xl font-bold text-white mb-4">
Frequently Asked Questions
@@ -89,42 +93,32 @@
</p>
</section>
<div class="max-w-4xl mx-auto space-y-4">
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<div class="faq-list">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Are my files safe and private?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
<strong>Absolutely.</strong> This is the most important feature of
BentoPDF. All processing happens 100% locally in your web browser.
Your files are never uploaded to any server, which means we—or
anyone else—can never see them. Your privacy is guaranteed.
Your files are never uploaded to any server, which means we, or
anyone else, can never see them. Your privacy is guaranteed.
</p>
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Is BentoPDF really free? What's the catch?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
Yes, it's completely free, and there's no catch. There are no
hidden fees, no subscription plans, no usage limits, and no
@@ -134,19 +128,14 @@
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Do I need an internet connection to use the tools?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
After you load the website for the first time, most tools will
work completely offline! Because all the processing libraries are
@@ -158,19 +147,14 @@
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Are there any file size or usage limitations?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
No, we do not impose any artificial limits on file size, the
number of files, or how many times you can use a tool. The only
@@ -181,19 +165,14 @@
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Why did my PDF fail to process?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>Failures are rare but can happen for a few reasons:</p>
<ul class="list-disc list-inside mt-2 space-y-1">
<li>
@@ -212,19 +191,14 @@
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
Do you track my activity on BentoPDF?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
No. BentoPDF does not track you at all. We do not use cookies,
analytics, or any tracking scripts, not even on the live website
@@ -234,19 +208,14 @@
</div>
</details>
<details
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
>
<summary class="flex items-center justify-between cursor-pointer">
<details class="faq-d">
<summary class="faq-d-q">
<h3 class="font-semibold text-white text-lg">
What technology does BentoPDF use?
</h3>
<i
data-lucide="plus"
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
></i>
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<div class="mt-4 text-gray-400">
<div class="faq-d-a">
<p>
BentoPDF is built on the power of modern web technologies. We
primarily use JavaScript libraries like
@@ -259,22 +228,24 @@
</details>
</div>
<div class="section-divider mt-16"></div>
<section id="contact-section" class="text-center py-16">
<h2 class="text-3xl font-bold text-white mb-4">
Still have questions?
</h2>
<p class="text-lg text-gray-400 mb-8 max-w-2xl mx-auto">
If you can't find the answer you're looking for, feel free to reach
out to our support team. We're always Bento to help.
</p>
<a
href="contact.html"
class="inline-block px-8 py-3 rounded-full bg-gray-700 text-white font-semibold focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900 focus:ring-indigo-400 hover:bg-gray-600 transition-colors duration-200"
>
Contact Us
</a>
<section id="contact-section" class="lp-sec">
<div class="lp-frame">
<div class="lp-cta">
<h2 class="lp-h2">Still have questions?</h2>
<p>
If you can't find the answer you're looking for, feel free to
reach out. We're always happy to help.
</p>
<div class="lp-cta-actions">
<span class="lp-brackets">
<a href="contact.html" class="lp-btn lp-btn--primary">
<span data-i18n="footer.contactUs">Contact Us</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
</div>
</div>
</div>
</section>
</div>
@@ -293,7 +264,7 @@
"name": "Are my files safe and private?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Absolutely. This is the most important feature of BentoPDF. All processing happens 100% locally in your web browser. Your files are never uploaded to any server, which means we—or anyone else—can never see them. Your privacy is guaranteed."
"text": "Absolutely. This is the most important feature of BentoPDF. All processing happens 100% locally in your web browser. Your files are never uploaded to any server, which means we, or anyone else, can never see them. Your privacy is guaranteed."
}
},
{
+692
View File
@@ -0,0 +1,692 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Primary Meta Tags -->
<title>Hyper Compress - PDF Compression Engine | BentoPDF</title>
<meta
name="description"
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
/>
<meta name="author" content="BentoPDF" />
<meta name="robots" content="index, follow" />
<!-- Canonical URL -->
<link rel="canonical" href="https://www.bentopdf.com/hyper-compress" />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.bentopdf.com/hyper-compress" />
<meta
property="og:title"
content="Hyper Compress - PDF Compression Engine | BentoPDF"
/>
<meta
property="og:description"
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
/>
<meta
property="og:image"
content="https://www.bentopdf.com/images/og-tools.png"
/>
<meta property="og:site_name" content="BentoPDF" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content="Hyper Compress - PDF Compression Engine | BentoPDF"
/>
<meta
name="twitter:description"
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
/>
<meta
name="twitter:image"
content="https://www.bentopdf.com/images/og-tools.png"
/>
<meta name="twitter:site" content="@BentoPDF" />
<link href="/src/css/styles.css" rel="stylesheet" />
<link href="/src/css/landing.css" rel="stylesheet" />
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest" />
<!-- Favicons -->
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/images/favicon-192x192.png"
/>
<link
rel="icon"
type="image/png"
sizes="512x512"
href="/images/favicon-512x512.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/images/apple-touch-icon.png"
/>
<link rel="icon" href="/favicon.ico" sizes="32x32" />
</head>
<body class="lp antialiased">
{{> navbar }}
<div id="app">
<section id="hyper-compress-hero" class="lp-sec lp-sec--first">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h1 class="lp-h1">
<span class="line">Meet</span>
<span class="line dim">Hyper Compress</span>
</h1>
<p class="lp-head-p">
The best open source PDF compression engine. It never returns a
file larger than the original, offers a true lossless mode, and
posted the lowest corruption rate of every engine we
benchmarked.
</p>
<p class="lp-head-p">
Ships as a CLI, Node SDK, C library, self-hosted service and
WebAssembly build.
</p>
<div class="lp-actions">
<span class="lp-brackets">
<a href="#pricing" class="lp-btn lp-btn--primary">
<span>See pricing</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
<a
href="https://hyper.bentopdf.com"
target="_blank"
rel="noopener"
class="lp-btn lp-btn--ghost"
>
<i data-lucide="external-link"></i>
<span>Visit website</span>
</a>
<a
href="https://github.com/alam00000/bentopdf-hyper-compress"
target="_blank"
rel="noopener"
class="lp-btn lp-btn--ghost"
>
<i data-lucide="github"></i>
<span>View on GitHub</span>
</a>
</div>
</div>
</div>
<div class="lp-grid lp-grid--4">
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
<b>64.8%</b><span>median reduction, strongest preset</span>
</div>
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
<b>22.4%</b><span>median reduction, lossless</span>
</div>
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
<b>0.39%</b><span>corruption rate, lowest tested</span>
</div>
<div class="lp-cell lp-stat lp-cell--raised lp-reveal">
<b>2,104</b><span>real-world PDFs benchmarked</span>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-pad--tight">
<div class="lp-note lp-reveal">
<i data-lucide="badge-check"></i>
<p>
<strong
>Open source, self-hosting and internal use stay free.</strong
>
Hyper Compress is licensed under the AGPL-3.0. If your project
is AGPL-compatible, or you run Hyper Compress as-is for
yourself, you never need a commercial license. Commercial
licenses are only for shipping Hyper Compress inside
closed-source software.
</p>
</div>
</div>
</div>
</section>
<section id="pricing" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Commercial</span>
<span class="line dim">Licenses</span>
</h2>
<p class="lp-head-p">
Per product, billed annually. Every tier includes all updates
and new releases while active.
</p>
</div>
</div>
<div class="lp-grid lp-grid--4">
<div class="lp-cell lp-tier lp-reveal">
<h3>Solo</h3>
<p class="lp-tier-for">
One developer, under $100k annual revenue
</p>
<div class="lp-tier-price"><b>$99</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_38OODBtvzFt24gT3W2ibWPZmm5HVMdUuWOjBt3ImRJA"
class="lp-btn lp-btn--ghost lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Solo</a
>
</div>
<div class="lp-cell lp-tier lp-cell--accent lp-reveal">
<h3>Indie</h3>
<p class="lp-tier-for">Companies under $1M annual revenue</p>
<div class="lp-tier-price"><b>$199</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>Unlimited developers</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_SWybHH8hi4Yufhn6seVrlJnlXZfymvLQgCadU3pWjT9"
class="lp-btn lp-btn--primary lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Indie</a
>
</div>
<div class="lp-cell lp-tier lp-reveal">
<h3>Business</h3>
<p class="lp-tier-for">Companies at $1M annual revenue or more</p>
<div class="lp-tier-price"><b>$499</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>Unlimited developers</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Priority email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_k2hYaoG49OZyB3WbAkmVyB55MRHqYQqex1bja0z7DfY"
class="lp-btn lp-btn--ghost lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Business</a
>
</div>
<div class="lp-cell lp-tier lp-reveal">
<h3>OEM</h3>
<p class="lp-tier-for">
Redistribution, reselling as an SDK, or offering Hyper Compress
as a service
</p>
<div class="lp-tier-price">
<span class="lp-tier-from">from</span><b>$1,999</b
><span>/ year</span>
</div>
<ul>
<li><i data-lucide="check"></i>Redistribution rights</li>
<li><i data-lucide="check"></i>Terms shaped to your product</li>
<li><i data-lucide="check"></i>Priority support</li>
</ul>
<a
href="mailto:contact@bentopdf.com?subject=Hyper%20Compress%20commercial%20license%20OEM"
class="lp-btn lp-btn--ghost lp-btn--sm"
>Contact us</a
>
</div>
</div>
</div>
</section>
<section id="license-details" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Commercial license</span>
<span class="line dim">details</span>
</h2>
</div>
</div>
<div class="lp-pad">
<div class="grid grid-cols-1 gap-6">
<div class="lp-panel">
<h3
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
>
<i data-lucide="package" class="w-6 h-6 text-indigo-400"></i>
Delivery &amp; licensing model
</h3>
<ul class="space-y-3 text-gray-400">
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
><strong class="text-white"
>No license key is required or provided.</strong
>
Hyper Compress intentionally does not use license keys, to
streamline deployment and reduce operational
friction.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Upon purchase you receive a ZIP archive containing the
complete Hyper Compress source code.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Because Hyper Compress is open source, every release and
every update can always be downloaded from our
<a
href="https://github.com/alam00000/bentopdf-hyper-compress/releases"
target="_blank"
rel="noopener noreferrer"
class="text-indigo-400 hover:underline"
>GitHub releases page</a
>.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>The source code provided is identical to the code
published in our public open-source repository.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="x-circle"
class="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5"
></i>
<span
><strong class="text-white">No refunds.</strong> Under no
circumstances shall a refund be made after purchase.</span
>
</li>
</ul>
<p class="mt-4 text-gray-300">
<strong class="text-white">GitHub repository:</strong>
<a
href="https://github.com/alam00000/bentopdf-hyper-compress"
target="_blank"
rel="noopener noreferrer"
class="text-indigo-400 hover:underline"
>github.com/alam00000/bentopdf-hyper-compress</a
>
</p>
</div>
<div class="lp-panel">
<h3
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
>
<i
data-lucide="file-text"
class="w-6 h-6 text-indigo-400"
></i>
Invoicing
</h3>
<ul class="space-y-3 text-gray-400">
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>We use <strong class="text-white">Polar</strong> for
payments, which
<strong class="text-white"
>automatically sends invoices</strong
>
via email after purchase.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Polar handles
<strong class="text-white">VAT invoices</strong> for
businesses in applicable regions.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="info"
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
></i>
<span
>For VAT invoices, select
<strong class="text-white"
>"I'm purchasing as a business"</strong
>
during checkout and enter your billing address and Tax/VAT
number.</span
>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section id="compare" class="lp-sec">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">What each tier</span>
<span class="line dim">covers</span>
</h2>
<p class="lp-head-p">
Every tier lets you ship Hyper Compress inside one closed-source
product. The tiers differ by who you are, how many developers
you have, and whether Hyper Compress is passed on to anyone
else.
</p>
</div>
</div>
<div class="lp-pad--tight lp-reveal">
<div class="overflow-x-auto">
<table class="lp-table lp-compare">
<thead>
<tr>
<th></th>
<th>Solo</th>
<th>Indie</th>
<th>Business</th>
<th>OEM</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Who it's for</th>
<td>One developer, under $100k annual revenue</td>
<td>Companies under $1M annual revenue</td>
<td>Companies at $1M annual revenue or more</td>
<td>
Anyone redistributing, reselling or hosting the engine
</td>
</tr>
<tr>
<th scope="row">Annual price</th>
<td>$99</td>
<td>$199</td>
<td>$499</td>
<td>from $1,999</td>
</tr>
<tr>
<th scope="row">Developers covered</th>
<td>One developer</td>
<td>Unlimited</td>
<td>Unlimited</td>
<td>Discussed with you</td>
</tr>
<tr>
<th scope="row">Closed-source products covered</th>
<td>One</td>
<td>One</td>
<td>One</td>
<td>Terms shaped to your product</td>
</tr>
<tr>
<th scope="row">Updates while active</th>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">Support</th>
<td>Email</td>
<td>Email</td>
<td>Priority email</td>
<td>Priority</td>
</tr>
<tr>
<th scope="row">
Redistribute inside someone else's product
</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">Resell as an SDK</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">
Offer Hyper Compress as a hosted service
</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
</tbody>
</table>
</div>
<p class="lp-table-note">
Redistribution, reselling and hosting are what separate OEM from
the rest. If Hyper Compress only ships inside your own
closed-source product, the choice between Solo, Indie and Business
is purely a question of your size.
</p>
</div>
</div>
</section>
<section class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">License</span>
<span class="line dim">Terms</span>
</h2>
</div>
</div>
<div class="lp-grid lp-grid--2">
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="package"></i></span>
<h3>Per product</h3>
<p>
A license covers one shipped product. A second product needs a
second license, or ask about covering your whole catalogue at
OEM.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="refresh-cw"></i></span>
<h3>Updates included</h3>
<p>
Every release published while your license is active is yours.
If you let it lapse, you keep a perpetual right to the last
version you received.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="unlock"></i></span>
<h3>No AGPL obligations</h3>
<p>
The commercial license replaces the AGPL for your product. You
ship closed source, with no requirement to publish your changes
or your application.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="shield-check"></i></span>
<h3>Clean provenance</h3>
<p>
Hyper Compress is written and owned by BentoPDF, and every
third-party component it bundles, including PDFium, qpdf, jpegli
and Leptonica, is permissively licensed. No copyleft surprises
in your supply chain.
</p>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Frequently Asked</span>
<span class="line dim">Questions</span>
</h2>
</div>
</div>
<div class="lp-faq-wrap">
<div id="faq-accordion" class="lp-faq lp-reveal">
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span>Do I need a commercial license?</span>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
Only if you ship Hyper Compress inside closed-source
software. Open-source projects under an AGPL-compatible
license, self-hosting, and internal use are all free under
the AGPL-3.0.
</p>
</div>
</div>
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span
>Does the BentoPDF commercial license cover Hyper
Compress?</span
>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
No. Hyper Compress is a separate project with its own
license. The BentoPDF app license does not grant any rights
to Hyper Compress, and a Hyper Compress license does not
cover BentoPDF.
</p>
</div>
</div>
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span>What happens if my company outgrows its tier?</span>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
You move up to the matching tier at your next renewal.
Nothing retroactive. Growing past a threshold mid-term never
invalidates your current license.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-cta">
<h2 class="lp-h2">Not sure which tier fits?</h2>
<p>
Tell us what you're building and we'll tell you what it costs. No
calls required.
</p>
<div class="lp-cta-actions">
<span class="lp-brackets">
<a
href="mailto:contact@bentopdf.com?subject=Hyper%20Compress%20commercial%20license%20pricing"
class="lp-btn lp-btn--primary"
>
<span>contact@bentopdf.com</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
</div>
</div>
</div>
</section>
</div>
{{> footer }}
<script type="module" src="src/js/utils/lucide-init.ts"></script>
<script type="module" src="src/js/main.ts"></script>
<script type="module" src="src/js/mobileMenu.ts"></script>
<script type="module" src="src/js/landing.ts"></script>
<!-- JSON-LD Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Hyper Compress - PDF Compression Engine | BentoPDF",
"url": "https://www.bentopdf.com/hyper-compress"
}
</script>
</body>
</html>
+443 -544
View File
File diff suppressed because it is too large. Load diff
+683
View File
@@ -0,0 +1,683 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Primary Meta Tags -->
<title>Kura - PDF/A, PDF/UA &amp; PDF/X Conversion Engine | BentoPDF</title>
<meta
name="description"
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
/>
<meta name="author" content="BentoPDF" />
<meta name="robots" content="index, follow" />
<!-- Canonical URL -->
<link rel="canonical" href="https://www.bentopdf.com/kura" />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.bentopdf.com/kura" />
<meta
property="og:title"
content="Kura - PDF/A, PDF/UA &amp; PDF/X Conversion Engine | BentoPDF"
/>
<meta
property="og:description"
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
/>
<meta
property="og:image"
content="https://www.bentopdf.com/images/og-tools.png"
/>
<meta property="og:site_name" content="BentoPDF" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content="Kura - PDF/A, PDF/UA &amp; PDF/X Conversion Engine | BentoPDF"
/>
<meta
name="twitter:description"
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
/>
<meta
name="twitter:image"
content="https://www.bentopdf.com/images/og-tools.png"
/>
<meta name="twitter:site" content="@BentoPDF" />
<link href="/src/css/styles.css" rel="stylesheet" />
<link href="/src/css/landing.css" rel="stylesheet" />
<!-- Web App Manifest -->
<link rel="manifest" href="/site.webmanifest" />
<!-- Favicons -->
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
<link
rel="icon"
type="image/png"
sizes="192x192"
href="/images/favicon-192x192.png"
/>
<link
rel="icon"
type="image/png"
sizes="512x512"
href="/images/favicon-512x512.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/images/apple-touch-icon.png"
/>
<link rel="icon" href="/favicon.ico" sizes="32x32" />
</head>
<body class="lp antialiased">
{{> navbar }}
<div id="app">
<section id="kura-hero" class="lp-sec lp-sec--first">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h1 class="lp-h1">
<span class="line">Meet</span>
<span class="line dim">Kura</span>
</h1>
<p class="lp-head-p">
The PDF standards and preflight engine. Convert any PDF to every
PDF/A level, PDF/UA, PDF/X, PDF/E and PDF/VT, then preflight the
result against 396 bundled profiles to confirm it conforms.
</p>
<p class="lp-head-p">
Ships as a CLI, npm package, browser WebAssembly build, Docker
image and C library.
</p>
<div class="lp-actions">
<span class="lp-brackets">
<a href="#pricing" class="lp-btn lp-btn--primary">
<span>See pricing</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
<a
href="https://kura.bentopdf.com"
target="_blank"
rel="noopener"
class="lp-btn lp-btn--ghost"
>
<i data-lucide="external-link"></i>
<span>Visit website</span>
</a>
<a
href="https://github.com/alam00000/bentopdf-kura"
target="_blank"
rel="noopener"
class="lp-btn lp-btn--ghost"
>
<i data-lucide="github"></i>
<span>View on GitHub</span>
</a>
</div>
</div>
</div>
<div class="lp-grid lp-grid--4">
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
<b>25</b><span>conformance targets</span>
</div>
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
<b>396</b><span>bundled preflight profiles</span>
</div>
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
<b>0</b><span>false findings in conformance testing</span>
</div>
<div class="lp-cell lp-stat lp-cell--raised lp-reveal">
<b>5</b><span>form factors, one engine</span>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-pad--tight">
<div class="lp-note lp-reveal">
<i data-lucide="badge-check"></i>
<p>
<strong
>Open source, self-hosting and internal use stay free.</strong
>
Kura is licensed under the AGPL-3.0. If your project is
AGPL-compatible, or you run Kura as-is for yourself, you never
need a commercial license. Commercial licenses are only for
shipping Kura inside closed-source software.
</p>
</div>
</div>
</div>
</section>
<section id="pricing" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Commercial</span>
<span class="line dim">Licenses</span>
</h2>
<p class="lp-head-p">
Per product, billed annually. Every tier includes all updates
and new releases while active.
</p>
</div>
</div>
<div class="lp-grid lp-grid--4">
<div class="lp-cell lp-tier lp-reveal">
<h3>Solo</h3>
<p class="lp-tier-for">
One developer, under $100k annual revenue
</p>
<div class="lp-tier-price"><b>$99</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_NLuLBtXkHXyelWdxPy6zarYyNJqMd4NF1PWJI2sEeZa"
class="lp-btn lp-btn--ghost lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Solo</a
>
</div>
<div class="lp-cell lp-tier lp-cell--accent lp-reveal">
<h3>Indie</h3>
<p class="lp-tier-for">Companies under $1M annual revenue</p>
<div class="lp-tier-price"><b>$199</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>Unlimited developers</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_MMPcXzyyNvVfX3Fuvac1eGgG7pTgDiIDB2RCs4HUbxx"
class="lp-btn lp-btn--primary lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Indie</a
>
</div>
<div class="lp-cell lp-tier lp-reveal">
<h3>Business</h3>
<p class="lp-tier-for">Companies at $1M annual revenue or more</p>
<div class="lp-tier-price"><b>$499</b><span>/ year</span></div>
<ul>
<li><i data-lucide="check"></i>One closed-source product</li>
<li><i data-lucide="check"></i>Unlimited developers</li>
<li><i data-lucide="check"></i>All updates while active</li>
<li><i data-lucide="check"></i>Priority email support</li>
</ul>
<a
href="https://buy.polar.sh/polar_cl_r4HLyDK1rda9cERr31Jbg99m3GEVDC2K4ooFo4FtoFb"
class="lp-btn lp-btn--ghost lp-btn--sm"
target="_blank"
rel="noopener noreferrer"
>Get Business</a
>
</div>
<div class="lp-cell lp-tier lp-reveal">
<h3>OEM</h3>
<p class="lp-tier-for">
Redistribution, reselling as an SDK, or offering Kura as a
service
</p>
<div class="lp-tier-price">
<span class="lp-tier-from">from</span><b>$1,999</b
><span>/ year</span>
</div>
<ul>
<li><i data-lucide="check"></i>Redistribution rights</li>
<li><i data-lucide="check"></i>Terms shaped to your product</li>
<li><i data-lucide="check"></i>Priority support</li>
</ul>
<a
href="mailto:contact@bentopdf.com?subject=Kura%20commercial%20license%20OEM"
class="lp-btn lp-btn--ghost lp-btn--sm"
>Contact us</a
>
</div>
</div>
</div>
</section>
<section id="license-details" class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Commercial license</span>
<span class="line dim">details</span>
</h2>
</div>
</div>
<div class="lp-pad">
<div class="grid grid-cols-1 gap-6">
<div class="lp-panel">
<h3
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
>
<i data-lucide="package" class="w-6 h-6 text-indigo-400"></i>
Delivery &amp; licensing model
</h3>
<ul class="space-y-3 text-gray-400">
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
><strong class="text-white"
>No license key is required or provided.</strong
>
Kura intentionally does not use license keys, to
streamline deployment and reduce operational
friction.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Upon purchase you receive a ZIP archive containing the
complete Kura source code.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Because Kura is open source, every release and every
update can always be downloaded from our
<a
href="https://github.com/alam00000/bentopdf-kura/releases"
target="_blank"
rel="noopener noreferrer"
class="text-indigo-400 hover:underline"
>GitHub releases page</a
>.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>The source code provided is identical to the code
published in our public open-source repository.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="x-circle"
class="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5"
></i>
<span
><strong class="text-white">No refunds.</strong> Under no
circumstances shall a refund be made after purchase.</span
>
</li>
</ul>
<p class="mt-4 text-gray-300">
<strong class="text-white">GitHub repository:</strong>
<a
href="https://github.com/alam00000/bentopdf-kura"
target="_blank"
rel="noopener noreferrer"
class="text-indigo-400 hover:underline"
>github.com/alam00000/bentopdf-kura</a
>
</p>
</div>
<div class="lp-panel">
<h3
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
>
<i
data-lucide="file-text"
class="w-6 h-6 text-indigo-400"
></i>
Invoicing
</h3>
<ul class="space-y-3 text-gray-400">
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>We use <strong class="text-white">Polar</strong> for
payments, which
<strong class="text-white"
>automatically sends invoices</strong
>
via email after purchase.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="check-circle"
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
></i>
<span
>Polar handles
<strong class="text-white">VAT invoices</strong> for
businesses in applicable regions.</span
>
</li>
<li class="flex items-start gap-3">
<i
data-lucide="info"
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
></i>
<span
>For VAT invoices, select
<strong class="text-white"
>"I'm purchasing as a business"</strong
>
during checkout and enter your billing address and Tax/VAT
number.</span
>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section id="compare" class="lp-sec">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">What each tier</span>
<span class="line dim">covers</span>
</h2>
<p class="lp-head-p">
Every tier lets you ship Kura inside one closed-source product.
The tiers differ by who you are, how many developers you have,
and whether Kura is passed on to anyone else.
</p>
</div>
</div>
<div class="lp-pad--tight lp-reveal">
<div class="overflow-x-auto">
<table class="lp-table lp-compare">
<thead>
<tr>
<th></th>
<th>Solo</th>
<th>Indie</th>
<th>Business</th>
<th>OEM</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Who it's for</th>
<td>One developer, under $100k annual revenue</td>
<td>Companies under $1M annual revenue</td>
<td>Companies at $1M annual revenue or more</td>
<td>
Anyone redistributing, reselling or hosting the engine
</td>
</tr>
<tr>
<th scope="row">Annual price</th>
<td>$99</td>
<td>$199</td>
<td>$499</td>
<td>from $1,999</td>
</tr>
<tr>
<th scope="row">Developers covered</th>
<td>One developer</td>
<td>Unlimited</td>
<td>Unlimited</td>
<td>Discussed with you</td>
</tr>
<tr>
<th scope="row">Closed-source products covered</th>
<td>One</td>
<td>One</td>
<td>One</td>
<td>Terms shaped to your product</td>
</tr>
<tr>
<th scope="row">Updates while active</th>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">Support</th>
<td>Email</td>
<td>Email</td>
<td>Priority email</td>
<td>Priority</td>
</tr>
<tr>
<th scope="row">
Redistribute inside someone else's product
</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">Resell as an SDK</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
<tr>
<th scope="row">Offer Kura as a hosted service</th>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-no"><i data-lucide="x"></i></td>
<td class="lp-yes"><i data-lucide="check"></i></td>
</tr>
</tbody>
</table>
</div>
<p class="lp-table-note">
Redistribution, reselling and hosting are what separate OEM from
the rest. If Kura only ships inside your own closed-source
product, the choice between Solo, Indie and Business is purely a
question of your size.
</p>
</div>
</div>
</section>
<section class="lp-sec lp-band">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">License</span>
<span class="line dim">Terms</span>
</h2>
</div>
</div>
<div class="lp-grid lp-grid--2">
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="package"></i></span>
<h3>Per product</h3>
<p>
A license covers one shipped product. A second product needs a
second license, or ask about covering your whole catalogue at
OEM.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="refresh-cw"></i></span>
<h3>Updates included</h3>
<p>
Every release published while your license is active is yours.
If you let it lapse, you keep a perpetual right to the last
version you received.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="unlock"></i></span>
<h3>No AGPL obligations</h3>
<p>
The commercial license replaces the AGPL for your product. You
ship closed source, with no requirement to publish your changes
or your application.
</p>
</div>
<div class="lp-cell lp-reveal">
<span class="lp-tile"><i data-lucide="shield-check"></i></span>
<h3>Clean provenance</h3>
<p>
Kura is written and owned by BentoPDF, and every third-party
component it links, including qpdf, PDFium and FreeType, is
permissively licensed. No copyleft surprises in your supply
chain.
</p>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-head lp-head--center">
<div>
<h2 class="lp-h2">
<span class="line">Frequently Asked</span>
<span class="line dim">Questions</span>
</h2>
</div>
</div>
<div class="lp-faq-wrap">
<div id="faq-accordion" class="lp-faq lp-reveal">
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span>Do I need a commercial license?</span>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
Only if you ship Kura inside closed-source software.
Open-source projects under an AGPL-compatible license,
self-hosting, and internal use are all free under the
AGPL-3.0.
</p>
</div>
</div>
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span>Does the BentoPDF commercial license cover Kura?</span>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
No. Kura is a separate project with its own license. The
BentoPDF app license does not grant any rights to Kura, and
a Kura license does not cover BentoPDF.
</p>
</div>
</div>
<div class="faq-item">
<button
class="faq-question w-full flex justify-between items-center text-left"
type="button"
>
<span>What happens if my company outgrows its tier?</span>
<i data-lucide="plus" class="faq-icon"></i>
</button>
<div
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
>
<p>
You move up to the matching tier at your next renewal.
Nothing retroactive. Growing past a threshold mid-term never
invalidates your current license.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="lp-sec">
<div class="lp-frame">
<div class="lp-cta">
<h2 class="lp-h2">Not sure which tier fits?</h2>
<p>
Tell us what you're building and we'll tell you what it costs. No
calls required.
</p>
<div class="lp-cta-actions">
<span class="lp-brackets">
<a
href="mailto:contact@bentopdf.com?subject=Kura%20commercial%20license%20pricing"
class="lp-btn lp-btn--primary"
>
<span>contact@bentopdf.com</span>
<i data-lucide="arrow-right"></i>
</a>
</span>
</div>
</div>
</div>
</section>
</div>
{{> footer }}
<script type="module" src="src/js/utils/lucide-init.ts"></script>
<script type="module" src="src/js/main.ts"></script>
<script type="module" src="src/js/mobileMenu.ts"></script>
<script type="module" src="src/js/landing.ts"></script>
<!-- JSON-LD Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Kura - PDF/A, PDF/UA &amp; PDF/X Conversion Engine | BentoPDF",
"url": "https://www.bentopdf.com/kura"
}
</script>
</body>
</html>
+1133 -1081
View File
File diff suppressed because it is too large. Load diff
+49 -3
View File
@@ -43,6 +43,21 @@ http {
return 301 /uk$1;
}
if ($request_uri ~ ^/en/?(\?.*)?$) {
return 301 /$1;
}
if ($request_uri ~ ^/en/([A-Za-z0-9].*)$) {
return 301 /$1;
}
if ($request_uri ~ ^(/(?:ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/src/pages/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
return 301 $1/$2$3;
}
if ($request_uri ~ ^(/(?:ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/change-text-color(?:\.html)?/?(\?.*)?$) {
return 301 $1/text-color$2;
}
if ($request_uri ~ ^/tools/$) {
return 301 /tools;
}
@@ -68,18 +83,45 @@ http {
return 301 /docs/$1$2;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja))?/index\.html(\?.*)?$) {
if ($request_uri ~ ^/docs/tools/pdf-to-docx/?(\?.*)?$) {
return 301 /docs/tools/pdf-to-word$1;
}
if ($request_uri ~ ^/docs/tools/decrypt-pdf/?(\?.*)?$) {
return 301 /docs/tools/unlock-pdf$1;
}
if ($request_uri ~ ^/docs/tools/encrypt-pdf/?(\?.*)?$) {
return 301 /docs/tools/protect-pdf$1;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/index\.html(\?.*)?$) {
return 301 $1/$2;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja))?/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/pdf-to-docx(?:\.html)?/?(\?.*)?$) {
return 301 $1/pdf-to-word$2;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/decrypt-pdf(?:\.html)?/?(\?.*)?$) {
return 301 $1/unlock-pdf$2;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/encrypt-pdf(?:\.html)?/?(\?.*)?$) {
return 301 $1/protect-pdf$2;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))?/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
return 301 $1/$2$3;
}
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca))/([a-z0-9][a-z0-9-]*)/(\?.*)?$) {
return 301 $1/$2$3;
}
if ($request_uri ~ ^/((?!(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca|docs|blog)/)[a-z0-9][a-z0-9-]*)/(\?.*)?$) {
return 301 /$1$2;
}
location ~ /src/pages/ {
return 404;
}
location ~ ^/(en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja)(/.*)?$ {
location ~ ^/(en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|ca)(/.*)?$ {
try_files $uri $uri/ $uri.html =404;
expires 5m;
}
@@ -106,6 +148,10 @@ http {
expires 1y;
}
location ~ ^/((sw\.js|coherentpdf\.browser\.min\.js|qpdf\.wasm)$|(workers|pdfjs-viewer|pdfjs-annotation-viewer)/) {
expires epoch;
}
location ~* \.(wasm|wasm\.gz|data|data\.gz)$ {
expires 1y;
}
+72 -69
View File
@@ -1,12 +1,12 @@
{
"name": "bento-pdf",
"version": "2.8.7",
"version": "2.8.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bento-pdf",
"version": "2.8.7",
"version": "2.8.10",
"license": "AGPL-3.0-only",
"dependencies": {
"@fontsource/cedarville-cursive": "^5.2.7",
@@ -27,26 +27,27 @@
"@types/node-forge": "^1.3.14",
"@types/papaparse": "^5.5.2",
"archiver": "^7.0.1",
"bentopdf-pdfium": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-8ff5002c6cd5.tgz",
"bentopdf-viewer": "file:vendor/bentopdf-viewer/bentopdf-viewer-8ff5002c6cd5.tgz",
"bentopdf-pdfium": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-051abe5b72a9.tgz",
"bentopdf-viewer": "file:vendor/bentopdf-viewer/bentopdf-viewer-051abe5b72a9.tgz",
"blob-stream": "^0.1.3",
"bwip-js": "^4.8.0",
"cropperjs": "^1.6.2",
"diff": "^8.0.3",
"dompurify": "^3.4.12",
"dompurify": "^3.4.17",
"fast-xml-parser": "^5.7.1",
"heic2any": "^0.0.4",
"highlight.js": "^11.11.1",
"html2canvas": "^1.4.1",
"hyper-compress-wasm": "file:vendor/hyper-compress-wasm/hyper-compress-wasm-1.0.3.tgz",
"i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1",
"i18next-http-backend": "^3.0.6",
"i18next-http-backend": "^4.0.2",
"jspdf": "^4.2.1",
"jspdf-autotable": "^5.0.2",
"jszip": "^3.10.1",
"lit": "^3.3.2",
"lucide": "^0.575.0",
"markdown-it": "^14.2.0",
"markdown-it": "^14.3.3",
"markdown-it-abbr": "^2.0.0",
"markdown-it-anchor": "^9.2.0",
"markdown-it-deflist": "^3.0.0",
@@ -102,6 +103,7 @@
"husky": "^9.1.7",
"jsdom": "^28.1.0",
"lint-staged": "^16.3.1",
"marked": "^16.4.2",
"prettier": "^3.8.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.56.1",
@@ -4271,15 +4273,15 @@
"license": "MIT"
},
"node_modules/bentopdf-pdfium": {
"version": "0.0.0-8ff5002c6cd5",
"resolved": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-8ff5002c6cd5.tgz",
"integrity": "sha512-bVDsJNwtan8snh2cibjvRNIjuM1UBvfKNd6OEn9RNYTZddH0JF4ekQBVSMbY9aVBNbNGCIwKPeaAFbrF8Jzvhw==",
"version": "0.0.0-051abe5b72a9",
"resolved": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-051abe5b72a9.tgz",
"integrity": "sha512-ctM0Y6MEVa2UQO8+uD7/GYzl7GWyrEJJxzUJURHJttJKzxn02DtNpyEWgcLREXnfaFIo7UJ4j5sFmioVGi/WpQ==",
"license": "AGPL-3.0"
},
"node_modules/bentopdf-viewer": {
"version": "2.9.1",
"resolved": "file:vendor/bentopdf-viewer/bentopdf-viewer-8ff5002c6cd5.tgz",
"integrity": "sha512-ucbsz9WeAf2Y8VIsR32dNl/NSgidMi85UFUKgWvUE4i93c4ds0P3u4imfg/T641iWAahbK75agNDfhuuzp2AFQ==",
"resolved": "file:vendor/bentopdf-viewer/bentopdf-viewer-051abe5b72a9.tgz",
"integrity": "sha512-A+utjVLgFdE/MA2mlPLimi7jXdhMXex6RozdcJbt0YgNj4tt1W3ihk9QYbVi3dUHm2zfwGPntE+CSn1d8OGoZw==",
"license": "MIT",
"dependencies": {
"preact": "^10.17.0",
@@ -4346,9 +4348,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5063,15 +5065,6 @@
"integrity": "sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==",
"license": "MIT"
},
"node_modules/cross-fetch": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz",
"integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.7.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -5869,9 +5862,9 @@
}
},
"node_modules/dompurify": {
"version": "3.4.12",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz",
"integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==",
"version": "3.4.17",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.17.tgz",
"integrity": "sha512-B/pSlYVHQ58kqISD/yDjuJ1yfzI34m1gF4lAod2bwSRhiN4K5Cl3H8Af7hqB2PmTL911tdEudnnXn5FnhRoz0w==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
@@ -6392,9 +6385,9 @@
}
},
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
"integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
"license": "MIT"
},
"node_modules/file-entry-cache": {
@@ -6681,9 +6674,9 @@
"license": "MIT"
},
"node_modules/glob/node_modules/brace-expansion": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
"integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -6743,13 +6736,13 @@
"license": "MIT"
},
"node_modules/handlebars": {
"version": "4.7.9",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
"integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
"version": "4.7.10",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz",
"integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5",
"minimist": "^1.2.8",
"neo-async": "^2.6.2",
"source-map": "^0.6.1",
"wordwrap": "^1.0.0"
@@ -7021,6 +7014,15 @@
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/hyper-compress-wasm": {
"version": "1.0.3",
"resolved": "file:vendor/hyper-compress-wasm/hyper-compress-wasm-1.0.3.tgz",
"integrity": "sha512-utOyNU/cTtMlCe+ik1ggYcuvINy8K4nDBHMA7VVeKTQlM0tWMJVWvY93R345sNOa49tr3nEeCDgGoNpp43ZQUQ==",
"license": "AGPL-3.0-only",
"engines": {
"node": ">=22"
}
},
"node_modules/i18next": {
"version": "25.10.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.2.tgz",
@@ -7062,12 +7064,12 @@
}
},
"node_modules/i18next-http-backend": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.6.tgz",
"integrity": "sha512-mBOqy8993jtqAoj6XaI1XeC/8/9v6EPS+681ziegrPvTB0DoaCY7PpTS0SpY56qLMoS4OI1TZEM2Zf59zNh05w==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-4.0.2.tgz",
"integrity": "sha512-oay62dIB2kL7+WHzoUXBjWfL3+mwijD3pQkQkIEaRLhy6kjXxUhrRenV0gInwlCASAaJaDy94+XvYizK+cAGdA==",
"license": "MIT",
"dependencies": {
"cross-fetch": "4.1.0"
"engines": {
"node": ">=18"
}
},
"node_modules/iconv-lite": {
@@ -8343,9 +8345,9 @@
"license": "MIT"
},
"node_modules/markdown-it": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
"integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
"version": "14.3.3",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.3.tgz",
"integrity": "sha512-L//tDAkjTjJCU6pBUSBTgs3Kg4InVaZuUZog/b6V12UKhcDQ7S78877ibbCanRExwPuYP1CZD7Gd2dxSy1GXRg==",
"funding": [
{
"type": "github",
@@ -8359,8 +8361,8 @@
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.1",
"entities": "^4.5.0",
"linkify-it": "^5.0.2",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
@@ -9601,13 +9603,14 @@
}
},
"node_modules/qs": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"version": "6.16.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.16.1.tgz",
"integrity": "sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
"es-define-property": "^1.0.1",
"side-channel": "^1.1.1"
},
"engines": {
"node": ">=0.6"
@@ -9695,9 +9698,9 @@
"license": "MIT"
},
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
"integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -10264,15 +10267,15 @@
}
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
"integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"object-inspect": "^1.13.4",
"side-channel-list": "^1.0.1",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
@@ -10284,14 +10287,14 @@
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
"object-inspect": "^1.13.4"
},
"engines": {
"node": ">= 0.4"
@@ -10419,9 +10422,9 @@
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
"integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -11176,9 +11179,9 @@
}
},
"node_modules/undici": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
"integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
"version": "7.30.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz",
"integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==",
"dev": true,
"license": "MIT",
"engines": {
+10 -7
View File
@@ -1,12 +1,13 @@
{
"name": "bento-pdf",
"private": true,
"version": "2.8.8",
"version": "2.8.10",
"license": "AGPL-3.0-only",
"type": "module",
"scripts": {
"predev": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs",
"dev": "vite",
"build": "tsc && vite build && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/seo-audit.mjs",
"build": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs && tsc && vite build && node scripts/enhance-seo-pages.mjs && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/seo-audit.mjs",
"seo-audit": "node scripts/seo-audit.mjs",
"build:with-docs": "npm run build && npm run docs:build && node scripts/include-docs-in-dist.js",
"build:gzip": "COMPRESSION_MODE=g npm run build",
@@ -60,6 +61,7 @@
"husky": "^9.1.7",
"jsdom": "^28.1.0",
"lint-staged": "^16.3.1",
"marked": "^16.4.2",
"prettier": "^3.8.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.56.1",
@@ -90,26 +92,27 @@
"@types/node-forge": "^1.3.14",
"@types/papaparse": "^5.5.2",
"archiver": "^7.0.1",
"bentopdf-pdfium": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-8ff5002c6cd5.tgz",
"bentopdf-viewer": "file:vendor/bentopdf-viewer/bentopdf-viewer-8ff5002c6cd5.tgz",
"bentopdf-pdfium": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-051abe5b72a9.tgz",
"bentopdf-viewer": "file:vendor/bentopdf-viewer/bentopdf-viewer-051abe5b72a9.tgz",
"blob-stream": "^0.1.3",
"bwip-js": "^4.8.0",
"cropperjs": "^1.6.2",
"diff": "^8.0.3",
"dompurify": "^3.4.12",
"dompurify": "^3.4.17",
"fast-xml-parser": "^5.7.1",
"heic2any": "^0.0.4",
"highlight.js": "^11.11.1",
"html2canvas": "^1.4.1",
"hyper-compress-wasm": "file:vendor/hyper-compress-wasm/hyper-compress-wasm-1.0.3.tgz",
"i18next": "^25.8.13",
"i18next-browser-languagedetector": "^8.2.1",
"i18next-http-backend": "^3.0.6",
"i18next-http-backend": "^4.0.2",
"jspdf": "^4.2.1",
"jspdf-autotable": "^5.0.2",
"jszip": "^3.10.1",
"lit": "^3.3.2",
"lucide": "^0.575.0",
"markdown-it": "^14.2.0",
"markdown-it": "^14.3.3",
"markdown-it-abbr": "^2.0.0",
"markdown-it-anchor": "^9.2.0",
"markdown-it-deflist": "^3.0.0",
+132 -44
View File
@@ -193,7 +193,7 @@
<h3 class="font-semibold text-white">JSON to PDF</h3>
<p class="text-gray-400 text-sm">Data to PDF</p>
</a>
<a href="/pdf-to-docx" class="tool-card">
<a href="/pdf-to-word" class="tool-card">
<i
class="ph ph-microsoft-word-logo text-4xl text-indigo-400 mb-2"
></i>
@@ -422,59 +422,147 @@
Frequently Asked Questions
</h2>
<div class="space-y-4">
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are these pdf converter tools really free?
<i class="ph ph-caret-down text-xl"></i>
<div class="faq-list">
<details class="faq-d">
<summary class="faq-d-q">
Which file formats can I convert to PDF?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Yes! All BentoPDF pdf converter tools are 100% free with no hidden
fees, no premium tiers, and no subscription required. Use
unlimited tools, unlimited times.
<p class="faq-d-a">
Word, Excel, and PowerPoint files (including the older DOC, XLS,
and PPT formats), OpenDocument text, spreadsheets, presentations,
and drawings, RTF, plain text, Markdown, CSV, XML, ebooks in EPUB,
MOBI, FB2, and CBZ, XPS, Publisher, Visio, WordPerfect, Microsoft
Works, Apple Pages, and images in JPG, PNG, HEIC, WebP, TIFF, BMP,
SVG, and PSD. If you have a folder of mixed image types,
<a
href="/image-to-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Images to PDF</a
>
accepts them all in one batch and puts each image on its own page.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are my files private and secure?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
What can I convert a PDF into?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Absolutely! All processing happens entirely in your browser. Your
files never leave your device, are never uploaded to servers.
Complete privacy guaranteed.
<p class="faq-d-a">
Word (DOCX), Excel (XLSX), CSV, plain text, Markdown, SVG, and
page images in JPG, PNG, WebP, TIFF, or BMP, with multi-page PDFs
delivered as a ZIP holding one image per page. For long-term
archiving,
<a
href="/pdf-to-pdfa"
class="text-indigo-300 hover:text-indigo-400"
>PDF to PDF/A</a
>
outputs PDF/A-1b, 2b, or 3b, and a separate tool turns a color PDF
into a grayscale one.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Is there a file size limit?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
Does PDF to Word keep the layout?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No file size limits! Process files of any size. Browser-based
processing means no artificial limitations.
<p class="faq-d-a">
<a
href="/pdf-to-word"
class="text-indigo-300 hover:text-indigo-400"
>PDF to Word</a
>
rebuilds the document with its text, basic formatting, and general
layout, and it can convert a batch of files in one run. Pages with
multiple columns, embedded forms, or heavy graphics may not come
across perfectly, so expect to tidy those up in your word
processor.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Do I need to install software?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
Why is my converted Word or text file empty?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No installation required! All tools are web-based and work
directly in your browser. Just open the page and start using -
works on any device.
<p class="faq-d-a">
The PDF is almost certainly a scan, which stores each page as a
picture with no text layer, so PDF to Word, PDF to Text, and the
table converters have nothing to pull out. Run the file through
<a href="/ocr-pdf" class="text-indigo-300 hover:text-indigo-400"
>OCR PDF</a
>
first to add a searchable text layer, then convert the result.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Can I get tables out of a PDF into Excel?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/pdf-to-excel"
class="text-indigo-300 hover:text-indigo-400"
>PDF to Excel</a
>
scans every page for tables and writes each one to its own
worksheet, named after the page it came from. If it reports that
no tables were found, the PDF lays the data out as loose text
rather than a real table structure; PDF to CSV and Extract Tables
rely on the same detection, so try PDF to Text to grab the raw
content instead.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Do I need Microsoft Office installed to convert Word, Excel, or
PowerPoint files?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
No. Those files, along with Publisher, Visio, RTF, and
WordPerfect, are converted by a LibreOffice engine that runs
inside your browser, so there's nothing to install;
<a
href="/word-to-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Word to PDF</a
>, for example, also takes DOC, ODT, and RTF directly. The engine
downloads once per session, which makes the first conversion take
a few seconds longer than the ones after it.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Will converting a PDF to JPG or PNG lose quality?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
Pages are rendered at twice their native size, so a letter-size
page becomes an image of roughly 1,224 by 1,584 pixels.
<a
href="/pdf-to-jpg"
class="text-indigo-300 hover:text-indigo-400"
>PDF to JPG</a
>
is lossy with a quality slider that defaults to 90%, which keeps a
good balance between sharpness and file size; PDF to PNG and PDF
to TIFF are lossless, and PNG adds a scale control from 1x to 3x
for print-quality output.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Are my files uploaded to a server during conversion?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
No. Every converter on this page, including the Office, ebook, and
image converters, runs as WebAssembly inside your browser tab, so
the file is read from your device and the result is written
straight back to it. There's no upload queue, no server copy, and
nothing to delete afterward.
</p>
</details>
</div>
+131 -46
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Primary Meta Tags -->
<title>PDF Editor - Free Online PDF Editor Tools | BentoPDF</title>
<title>PDF Editing Tools - All Free Online PDF Editors | BentoPDF</title>
<meta
name="description"
content="Edit, modify, and enhance your PDFs with 25+ free online tools. Compress, rotate, crop, add watermarks, page numbers, and more. Privacy-first PDF editing in your browser."
@@ -25,7 +25,7 @@
<meta property="og:url" content="https://www.bentopdf.com/pdf-editor" />
<meta
property="og:title"
content="PDF Editor - Free Online PDF Editor Tools | BentoPDF"
content="PDF Editing Tools - All Free Online PDF Editors | BentoPDF"
/>
<meta
property="og:description"
@@ -41,7 +41,10 @@
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="PDF Editor - Free Online Tools" />
<meta
name="twitter:title"
content="PDF Editing Tools - All Free Online PDF Editors | BentoPDF"
/>
<meta
name="twitter:description"
content="Edit, modify, and enhance your PDFs with 25+ free online tools. Compress, rotate, crop, add watermarks, page numbers, and more. Privacy-first PDF editing in your browser."
@@ -296,59 +299,141 @@
Frequently Asked Questions
</h2>
<div class="space-y-4">
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are these pdf editor tools really free?
<i class="ph ph-caret-down text-xl"></i>
<div class="faq-list">
<details class="faq-d">
<summary class="faq-d-q">
Can I change the existing text in a PDF?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Yes! All BentoPDF pdf editor tools are 100% free with no hidden
fees, no premium tiers, and no subscription required. Use
unlimited tools, unlimited times.
<p class="faq-d-a">
<a
href="/edit-pdf-text"
class="text-indigo-300 hover:text-indigo-400"
>Edit PDF Text</a
>
lets you click any paragraph and rewrite it in place, with the
surrounding text reflowing as you type and controls for fonts and
styling. For adding new text boxes, comments, highlights, shapes,
or images on top of the page, use the general Edit PDF tool
instead.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are my files private and secure?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
What can I do in the Edit PDF tool?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Absolutely! All processing happens entirely in your browser. Your
files never leave your device, are never uploaded to servers.
Complete privacy guaranteed.
<p class="faq-d-a">
The
<a href="/edit-pdf" class="text-indigo-300 hover:text-indigo-400"
>Edit PDF</a
>
toolbar covers highlighting, underlining, strikethrough, freehand
drawing, text and comments, shapes and images, permanent
redaction, and full-text search. It keeps the original PDF
structure, so fonts, layouts, and form fields stay intact, and you
can keep up to 10 documents open in tabs and switch between them.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Is there a file size limit?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
How do I make a PDF smaller?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No file size limits! Process files of any size. Browser-based
processing means no artificial limitations.
<p class="faq-d-a">
<a
href="/compress-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Compress PDF</a
>
strips unused structure, downsamples images, and subsets fonts
while keeping text selectable and links working. Start with the
Medium level, or enter a target file size, and only step up to
High if the file is still too large.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Do I need to install software?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
Which editing tools keep my text selectable?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No installation required! All tools are web-based and work
directly in your browser. Just open the page and start using -
works on any device.
<p class="faq-d-a">
Page-level tools such as Rotate, Organize, Delete Pages,
Background Color, and Remove Annotations work on the PDF structure
and leave text searchable. Invert Colors, Change Text Color, and
PDF to Greyscale re-render every page as an image, so text in
their output can no longer be selected or searched. If you need
searchable text after one of those, run the result through
<a href="/ocr-pdf" class="text-indigo-300 hover:text-indigo-400"
>OCR PDF</a
>.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Can I add page numbers or a header and footer?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/page-numbers"
class="text-indigo-300 hover:text-indigo-400"
>Page Numbers</a
>
puts a number in any of six positions on every page, in plain or
"page X of Y" style, with your choice of font size and color.
Header and Footer adds text to six slots per page (left, center,
and right at top and bottom), understands {page} and {total}
placeholders so a footer like "Page {page} of {total}" fills in
correctly on each page, and can be limited to a page range.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Can I put a watermark on every page?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/add-watermark"
class="text-indigo-300 hover:text-indigo-400"
>Add Watermark</a
>
stamps text or an image onto your pages, and you position it by
dragging on a live preview, then set opacity, rotation, and size.
A tiled mode repeats the mark across the whole page so it's much
harder to crop out, and you can apply one watermark to all pages,
restrict it to a page range, or set a different watermark on each
page.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Can I rotate a single page, or fix a slightly tilted scan?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/rotate-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Rotate PDF</a
>
shows a thumbnail of every page with its own left and right
buttons for 90-degree turns, plus a bulk control for the whole
document. For a scan that's off by a few degrees, Rotate by Custom
Degrees accepts any angle, per page or for all pages at once.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Does editing a PDF here upload it anywhere?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
No. The editor and every other tool on this page run as
WebAssembly inside your browser, so the file is opened, changed,
and saved on your own device without a server in between. Nothing
is stored, so there's no copy to delete when you're done.
</p>
</details>
</div>
+129 -43
View File
@@ -251,59 +251,145 @@
Frequently Asked Questions
</h2>
<div class="space-y-4">
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are these pdf merge & split tools really free?
<i class="ph ph-caret-down text-xl"></i>
<div class="faq-list">
<details class="faq-d">
<summary class="faq-d-q">
How do I combine several PDFs into one file?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Yes! All BentoPDF pdf merge & split tools are 100% free with no
hidden fees, no premium tiers, and no subscription required. Use
unlimited tools, unlimited times.
<p class="faq-d-a">
Add two or more files to
<a href="/merge-pdf" class="text-indigo-300 hover:text-indigo-400"
>Merge PDF</a
>
and drag them into the order you want. File Mode joins whole
documents, with an optional page range per file such as 1-3, 5,
while Page Mode lays out every page as a thumbnail so you can
build the exact sequence. There's no cap on file count or total
pages, and pages are copied without re-encoding, so quality
doesn't change.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are my files private and secure?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
What are the different ways to split a PDF?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Absolutely! All processing happens entirely in your browser. Your
files never leave your device, are never uploaded to servers.
Complete privacy guaranteed.
<p class="faq-d-a">
<a href="/split-pdf" class="text-indigo-300 hover:text-indigo-400"
>Split PDF</a
>
has six modes: page ranges, visual selection from thumbnails, even
or odd pages only, one file per page, splitting at bookmark
boundaries with a choice of bookmark level, and fixed chunks of
every N pages. A single range downloads as one PDF, while multiple
ranges or per-page output arrive as a ZIP. Bookmark mode needs a
PDF that actually contains bookmarks.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Is there a file size limit?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
What's the difference between Split, Extract Pages, and Delete
Pages?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No file size limits! Process files of any size. Browser-based
processing means no artificial limitations.
<p class="faq-d-a">
<a
href="/extract-pages"
class="text-indigo-300 hover:text-indigo-400"
>Extract Pages</a
>
keeps only the pages you list and saves them as a new file, Delete
Pages removes the pages you list and keeps everything else, and
Split breaks one document into several files. Extract and Delete
are inverses of each other, so pick whichever needs the shorter
list of page numbers.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Do I need to install software?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
Can I reorder pages or duplicate a page?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No installation required! All tools are web-based and work
directly in your browser. Just open the page and start using -
works on any device.
<p class="faq-d-a">
<a
href="/organize-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Organize PDF</a
>
shows every page as a draggable thumbnail with a duplicate and a
delete button on each one. You can also type a complete page order
such as 3, 1, 2, 4 to rearrange everything in one step, and
Reverse Pages flips an entire document, or a batch of them, in one
click.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
My scanner put all the front pages first and all the backs after.
How do I fix the order?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/duplex-collate"
class="text-indigo-300 hover:text-indigo-400"
>Duplex Collate</a
>
handles exactly that: it interleaves the two blocks into front 1,
back 1, front 2, back 2 order, with an option to reverse the back
block for stacks that were flipped before the second pass. If the
fronts and backs are in two separate files, Alternate Merge
interleaves pages from multiple PDFs the same way.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
How do I print a PDF as a folded booklet?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/pdf-booklet"
class="text-indigo-300 hover:text-indigo-400"
>PDF Booklet</a
>
reorders the pages into saddle-stitch imposition and shows a
preview of each sheet before you download. Print the result
double-sided with "flip on short edge", fold the stack in half,
and staple at the spine; if the page count isn't a multiple of
four, blank pages are added automatically to fill the last sheet.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Can I see what changed between two versions of a PDF?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/compare-pdfs"
class="text-indigo-300 hover:text-indigo-400"
>Compare PDFs</a
>
pairs up the pages of two documents and highlights differences in
text, images, annotations, headers and footers, and formatting, in
either a side-by-side or an overlay view. Filters let you hide the
change types you don't care about, OCR can be switched on for
scanned documents, and the comparison can be exported as a PDF
report.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Are my files uploaded when I merge or split them?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
No. Merging, splitting, and reordering run as WebAssembly inside
your browser, so the files are read from your disk and the result
is written back to it without passing through a server. That holds
for large scans and multi-file batches too.
</p>
</details>
</div>
+143 -45
View File
@@ -111,12 +111,12 @@
<div
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4"
>
<a href="/encrypt-pdf" class="tool-card">
<a href="/protect-pdf" class="tool-card">
<i class="ph ph-lock text-4xl text-indigo-400 mb-2"></i>
<h3 class="font-semibold text-white">Encrypt PDF</h3>
<p class="text-gray-400 text-sm">Add password</p>
</a>
<a href="/decrypt-pdf" class="tool-card">
<a href="/unlock-pdf" class="tool-card">
<i class="ph ph-lock-open text-4xl text-indigo-400 mb-2"></i>
<h3 class="font-semibold text-white">Decrypt PDF</h3>
<p class="text-gray-400 text-sm">Remove password</p>
@@ -226,59 +226,157 @@
Frequently Asked Questions
</h2>
<div class="space-y-4">
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are these PDF security tools really free?
<i class="ph ph-caret-down text-xl"></i>
<div class="faq-list">
<details class="faq-d">
<summary class="faq-d-q">
What's the difference between protecting a PDF with a password and
restricting its permissions?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Yes! All BentoPDF PDF security tools are 100% free with no hidden
fees, no premium tiers, and no subscription required. Use
unlimited tools, unlimited times.
<p class="faq-d-a">
A user password, set with
<a
href="/protect-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Protect PDF</a
>, is required to open the file at all. Permissions are flags
stored inside the encryption that control what a reader can do
after opening, such as printing, copying, editing, annotating, or
filling forms, and they only take effect when an owner password is
set. Change Permissions lets you allow or deny each action
individually, while Protect PDF applies the strictest set as soon
as you add an owner password.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Are my files private and secure?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
How strong is the password protection?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
Absolutely! All processing happens entirely in your browser. Your
files never leave your device and are never uploaded to servers.
Complete privacy is guaranteed.
<p class="faq-d-a">
Protect PDF and Change Permissions use 256-bit AES encryption, the
PDF 2.0 standard, applied by QPDF running in your browser. The
encryption itself isn't practical to brute-force, so the weak
point is the password: use a long passphrase and send it through a
different channel than the file. Permission flags are a separate
matter, since they rely on the reader honoring them and some
third-party tools ignore them.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Is there a file size limit?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
Can I remove a password from a PDF if I don't know it?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No file size limits! Process files of any size. Browser-based
processing means no artificial limitations.
<p class="faq-d-a">
No.
<a
href="/unlock-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Unlock PDF</a
>
needs the password and then saves a copy with no encryption or
restrictions left, and none of the tools crack or brute-force
passwords. For a file that opens fine but blocks printing or
copying, use Remove Restrictions instead, which asks for the owner
password if the file has one.
</p>
</details>
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
<summary
class="cursor-pointer font-semibold text-white flex items-center justify-between"
>
Do I need to install software?
<i data-lucide="chevron-down" class="w-5 h-5"></i>
<details class="faq-d">
<summary class="faq-d-q">
What's the difference between Sign PDF and a digital signature?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="mt-3 text-gray-400">
No installation required! All tools are web-based and work
directly in your browser. Just open the page and start using -
works on any device.
<p class="faq-d-a">
Sign PDF places a drawn, typed, or uploaded signature image on the
page, with an option to flatten it so nobody can move or delete it
later.
<a
href="/digital-sign-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Digital Signature</a
>
applies a cryptographic signature with your own X.509 certificate
(.pfx, .p12, or .pem), which proves who signed and that the file
hasn't changed since, and Validate Signature checks signatures
already in a file. Certificate signing may need an internet
connection to fetch the certificate chain, and self-signed
certificates will show warnings in Adobe Reader.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
How do I redact text so it's actually gone?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
Use the redaction tool in the
<a href="/edit-pdf" class="text-indigo-300 hover:text-indigo-400"
>PDF Editor</a
>. Marking text or an area only flags it. Once you apply the
redaction, the marked content is permanently removed from the page
instead of just being covered with a box, and if you download with
marks that haven't been applied yet, the editor offers to apply
them first. When you redact selected text, copies of it in the
file's properties, bookmarks, comments, and attachments are
removed on download too, unless the file is encrypted. Area
redactions have no text to search for, so if the file's
properties, comments, or attachments could reveal the same
information, run Remove Metadata or Sanitize PDF on the result as
well.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
What's the difference between Remove Metadata and Sanitize PDF?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/remove-metadata"
class="text-indigo-300 hover:text-indigo-400"
>Remove Metadata</a
>
strips only the document properties: title, author, dates,
producer, XMP data, document IDs, and application-specific data,
and it leaves pages, forms, links, and bookmarks untouched.
Sanitize PDF goes further and can also flatten forms and delete
annotations, embedded JavaScript, attachments, layers, links, and
structure tags, with each item selectable. Both are irreversible,
so keep your original file.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
What does flattening a PDF do, and when should I use it?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
<a
href="/flatten-pdf"
class="text-indigo-300 hover:text-indigo-400"
>Flatten PDF</a
>
burns form fields and annotations (comments, highlights, stamps,
sticky notes, signature fields) into the page content, so they
look the same but can no longer be edited, moved, or removed. Use
it after a form is filled in or a signature is placed and before
you send the file, because there's no way to unflatten. Text stays
selectable and searchable, and bookmarks are kept.
</p>
</details>
<details class="faq-d">
<summary class="faq-d-q">
Are my passwords, certificates, or files sent to a server?
<i data-lucide="plus" class="faq-d-icon"></i>
</summary>
<p class="faq-d-a">
No. Encrypting, unlocking, sanitizing, and signing all run as
WebAssembly in your browser, so the document, the password you
type, and your certificate's private key stay on your device. The
one network exception is Digital Signature, which may contact your
certificate authority's servers to fetch the certificate chain;
the document itself is still never sent.
</p>
</details>
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 128 KiB

+8 -5
View File
@@ -212,7 +212,7 @@
},
"browserBased": {
"question": "كيف تحافظ المعالجة عبر المتصفح على أمانك؟",
"answer": "بالعمل بالكامل داخل متصفحك، يضمن BentoPDF أن ملفاتك لا تغادر جهازك أبدًا. هذا يلغي مخاطر اختراق الخوادم أو تسريب البيانات أو الوصول غير المصرح به. ملفاتك تبقى ملكك — دائمًا."
"answer": "بالعمل بالكامل داخل متصفحك، يضمن BentoPDF أن ملفاتك لا تغادر جهازك أبدًا. هذا يلغي مخاطر اختراق الخوادم أو تسريب البيانات أو الوصول غير المصرح به. ملفاتك تبقى ملكك، دائمًا."
},
"analytics": {
"question": "هل تستخدمون ملفات تعريف الارتباط أو التحليلات لتتبعي؟",
@@ -222,7 +222,7 @@
"testimonials": {
"title": "ماذا يقول",
"users": "مستخدمونا",
"say": ""
"say": " "
},
"support": {
"title": "أعجبك عملنا؟",
@@ -239,7 +239,9 @@
"legal": "قانوني",
"termsAndConditions": "الشروط والأحكام",
"privacyPolicy": "سياسة الخصوصية",
"followUs": "تابعنا"
"followUs": "تابعنا",
"privacyShort": "الخصوصية",
"termsShort": "الشروط"
},
"merge": {
"title": "دمج ملفات PDF",
@@ -287,12 +289,13 @@
},
"mission": {
"title": "مهمتنا",
"titleDim": " ",
"description": "تقديم أشمل مجموعة أدوات PDF تحترم خصوصيتك ولا تطلب أي مقابل. نؤمن بأن أدوات المستندات الأساسية يجب أن تكون متاحة للجميع، في كل مكان، بدون عوائق."
},
"philosophy": {
"label": "فلسفتنا الأساسية",
"title": "الخصوصية أولاً. دائمًا.",
"description": "في عصر أصبحت فيه البيانات سلعة، نتبع نهجًا مختلفًا. تتم جميع معالجة أدوات Bentopdf محليًا في متصفحك. هذا يعني أن ملفاتك لا تلمس خوادمنا أبدًا، ولا نرى مستنداتك، ولا نتتبع ما تفعله. مستنداتك تبقى خاصة تمامًا وبشكل قاطع. إنها ليست مجرد ميزة؛ إنها أساسنا."
"description": "في عصر أصبحت فيه البيانات سلعة، نتبع نهجًا مختلفًا. تتم جميع معالجة أدوات BentoPDF محليًا في متصفحك. هذا يعني أن ملفاتك لا تلمس خوادمنا أبدًا، ولا نرى مستنداتك، ولا نتتبع ما تفعله. مستنداتك تبقى خاصة تمامًا وبشكل قاطع. إنها ليست مجرد ميزة؛ إنها أساسنا."
},
"whyBentopdf": {
"title": "لماذا",
@@ -315,7 +318,7 @@
},
"cta": {
"title": "مستعد للبدء؟",
"description": "انضم إلى آلاف المستخدمين الذين يثقون بـ Bentopdf لاحتياجات مستنداتهم اليومية. اختبر الفرق الذي يمكن أن تحدثه الخصوصية والأداء.",
"description": "انضم إلى آلاف المستخدمين الذين يثقون بـ BentoPDF لاحتياجات مستنداتهم اليومية. اختبر الفرق الذي يمكن أن تحدثه الخصوصية والأداء.",
"button": "استكشف جميع الأدوات"
}
},
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "ضغط PDF",
"subtitle": "تقليل حجم ملف PDF الخاص بك.",
"algorithmLabel": "خوارزمية الضغط",
"condense": "تكثيف (موصى به)",
"photon": "فوتون (لملفات PDF كثيرة الصور)",
"condenseInfo": "يستخدم التكثيف ضغطًا متقدمًا: يزيل البيانات الزائدة، يحسّن الصور، يقلّص الخطوط. الأفضل لمعظم ملفات PDF.",
"photonInfo": "يحول فوتون الصفحات إلى صور. استخدمه لملفات PDF كثيرة الصور/الممسوحة ضوئيًا.",
"photonWarning": "تحذير: سيصبح النص غير قابل للتحديد وستتوقف الروابط عن العمل.",
"levelLabel": "مستوى الضغط",
"light": "خفيف (الحفاظ على الجودة)",
"balanced": "متوازن (موصى به)",
"aggressive": "عدواني (ملفات أصغر)",
"extreme": "أقصى (ضغط أقصى)",
"grayscale": "تحويل إلى تدرج الرمادي",
"grayscaleHint": "يقلل حجم الملف بإزالة معلومات الألوان",
"customSettings": "إعدادات مخصصة",
"customSettingsHint": "ضبط دقيق لمعلمات الضغط:",
"outputQuality": "جودة المخرجات",
"resizeImagesTo": "تغيير حجم الصور إلى",
"onlyProcessAbove": "معالجة فقط أعلى من",
"removeMetadata": "إزالة البيانات الوصفية",
"subsetFonts": "تقليص الخطوط (إزالة الحروف غير المستخدمة)",
"removeThumbnails": "إزالة الصور المصغرة المضمنة",
"compressButton": "ضغط PDF"
"subtitle": "تقليل حجم ملف PDF الخاص بك."
},
"pdfEditor": {
"name": "محرر PDF",
@@ -60,6 +38,8 @@
"subtitle": "انقر على أي فقرة وحرّرها في مكانها مع إعادة تدفق فوري للنص والخطوط والأنماط.",
"saved": "تم حفظ ملف PDF بنجاح! ({{size}} كيلوبايت)",
"failedToLoad": "تعذّر تحميل محرّر نصوص PDF.",
"loadingFonts": "جارٍ تحميل الخطوط...",
"fontsUnavailable": "تعذّر تنزيل خط مطلوب لبعض الأحرف. تحقّق من اتصالك وحاول مرة أخرى، وإلا فقد لا تظهر هذه الأحرف بشكل صحيح في ملف PDF المحفوظ.",
"howToUpload": "رفع ملف PDF",
"howToClick": "انقر على فقرة",
"howToRestyle": "غيّر تنسيق أي شيء",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "نعم! فعّل خيار \"التكرار\" وستتكرر صفحات التراكب على جميع صفحات الملف الأساسي. العلامة المائية ذات الصفحة الواحدة ستُطبق على كل صفحة.",
"faqPrivacyQuestion": "هل ملفاتي خاصة وآمنة؟",
"faqPrivacyAnswer": "بالتأكيد! تتم جميع المعالجة في متصفحك. لا تغادر ملفاتك جهازك أبداً، مما يضمن خصوصية كاملة."
},
"unlockPdf": {
"name": "فك تشفير PDF",
"subtitle": "فتح PDF بإزالة حماية كلمة المرور."
},
"protectPdf": {
"name": "تشفير PDF",
"subtitle": "قفل PDF بإضافة كلمة مرور."
}
}
+18 -15
View File
@@ -5,7 +5,7 @@
"contact": "Кантакты",
"licensing": "Ліцэнзія",
"allTools": "Усе інструменты",
"docs": "Docs",
"docs": "Дакументацыя",
"openMainMenu": "Адкрыць галоўнае меню",
"language": "Мова",
"searchLanguage": "Пошук мовы…",
@@ -59,7 +59,7 @@
"title": "Пачніце працу з",
"toolsLabel": "інструментамі",
"subtitle": "Націсніце на інструмент, каб адкрыць запампоўшчык",
"searchPlaceholder": "Пошук (напр., \"выдаліць\", \"сціснуць\"...)",
"searchPlaceholder": "Пошук (напр., «выдаліць», «сціснуць»...)",
"backToTools": "Назад да інструментаў",
"firstLoadNotice": "Першае адкрыццё займае крыху часу, пакуль загружаецца рухавік канвертацыі. Потым усё будзе адкрывацца імгненна."
},
@@ -100,11 +100,11 @@
},
"howItWorks": {
"title": "Як гэта працуе",
"step1Title": "Загрузіць файл",
"step1Title": "Запампуйце файл",
"step1": "Націсніце або перацягніце файл, каб пачаць",
"step2Title": "Апрацоўка",
"step2Title": "Апрацуйце",
"step2": "Націсніце кнопку апрацоўкі",
"step3Title": "Спампаваць",
"step3Title": "Спампуйце",
"step3": "Імгненна захавайце апрацаваны файл"
},
"relatedTools": {
@@ -175,7 +175,7 @@
},
"ccpa": {
"title": "Адпаведнасць CCPA",
"description": "Дае жыхарам Каліфорніі правы ведаць, як збіраецца, выкарыстоўваецца і перадаецца іх персанальная інфармацыя."
"description": "Дае жыхарам Каліфорніі правы адносна таго, як збіраецца, выкарыстоўваецца і перадаецца іх персанальная інфармацыя."
},
"hipaa": {
"title": "Адпаведнасць HIPAA",
@@ -211,7 +211,7 @@
"answer": "Звычайна інструменты PDF запампоўваюць вашы файлы на сервер для апрацоўкі. BentoPDF ніколі так не робіць. Мы выкарыстоўваем бяспечныя сучасныя вэб-тэхналогіі, каб апрацоўваць вашы файлы непасрэдна ў браўзеры. Гэта азначае большую хуткасць, лепшую прыватнасць і поўны спакой."
},
"browserBased": {
"question": "Чаму апрацоўка ў браўзеры - гэта бяспечна?",
"question": "Чаму апрацоўка ў браўзеры — гэта бяспечна?",
"answer": "Працуючы цалкам у браўзеры, BentoPDF гарантуе, што вашы файлы ніколі не пакінуць вашу прыладу. Гэта ліквідуе рызыкі ўзлому сервераў, уцечак даных або несанкцыянаванага доступу. Вашы файлы застаюцца вашымі — заўсёды."
},
"analytics": {
@@ -239,7 +239,9 @@
"legal": "Прававая інфармацыя",
"termsAndConditions": "Умовы выкарыстання",
"privacyPolicy": "Палітыка прыватнасці",
"followUs": "Сачыце за намі"
"followUs": "Сачыце за намі",
"privacyShort": "Прыватнасць",
"termsShort": "Умовы"
},
"merge": {
"title": "Аб'яднаць PDF",
@@ -286,7 +288,8 @@
"noCompromises": "Без кампрамісаў."
},
"mission": {
"title": "Наша місія",
"title": "Наша",
"titleDim": "місія",
"description": "Даць найбольш поўны набор інструментаў PDF, які шануе вашу прыватнасць і ніколі не патрабуе аплаты. Мы лічым, што неабходныя інструменты для дакументаў павінны быць даступнымі ўсім, паўсюль, без бар'ераў."
},
"philosophy": {
@@ -302,7 +305,7 @@
},
"free": {
"title": "Цалкам бясплатна",
"description": "Без пробных версій, падпісак, схаваных плацяжоў і без \"прэміум\" функцый. Мы верым, што магутныя інструменты PDF павінны быць грамадскай карысцю, а не цэнтрам прыбытку."
"description": "Без пробных версій, падпісак, схаваных плацяжоў і без «прэміум» функцый. Мы верым, што магутныя інструменты PDF павінны быць грамадскай карысцю, а не цэнтрам прыбытку."
},
"noAccount": {
"title": "Не патрэбны ўліковы запіс",
@@ -350,12 +353,12 @@
"download": "Спампаваць:",
"downloadSelected": "Спампаваць выбранае",
"exportPdf": "Экспартаваць PDF",
"uploadPdfFiles": "Выбраць PDF або выявы",
"dragAndDrop": "Перацягніце PDF або выявы сюды або націсніце, каб выбраць",
"uploadPdfFiles": "Выбраць PDF або відарысы",
"dragAndDrop": "Перацягніце PDF або відарысы сюды або націсніце, каб выбраць",
"selectFiles": "Выбраць файлы",
"dropToAdd": "Адпусціце PDF або выявы для дабаўлення",
"convertingImages": "Канвертацыя выяў у PDF...",
"failedToConvertImages": "Не ўдалося канвертаваць выявы ў PDF.",
"dropToAdd": "Адпусціце PDF або відарысы, каб дадаць",
"convertingImages": "Канвертаванне відарысаў у PDF...",
"failedToConvertImages": "Не ўдалося канвертаваць відарысы ў PDF.",
"renderingPages": "Апрацоўка старонак...",
"actions": {
"duplicatePage": "Дубляваць гэту старонку",
+259 -270
View File
@@ -19,7 +19,8 @@
"name": "Аб'яднаць PDF",
"subtitle": "Аб'яднаць некалькі PDF у адзін файл. Закладкі захоўваюцца.",
"retainPageLabels": "Захоўваць арыгінальныя пазнакі старонак з кожнага файла",
"retainPageLabelsHint": "Выключана (па змаўчанні): аб’яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
"retainPageLabelsHint": "Выключана (прадвызначана): аб'яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы).",
"removeDuplicateFonts": "Выдаліць дублікаты шрыфтоў"
},
"splitPdf": {
"name": "Падзяліць PDF",
@@ -27,29 +28,7 @@
},
"compressPdf": {
"name": "Сціснуць PDF",
"subtitle": "Зменшыць памер файла PDF.",
"algorithmLabel": "Алгарытм сціскання",
"condense": "Condense (Рэкамендуецца)",
"photon": "Photon (Для PDF з вялікай колькасцю фота)",
"condenseInfo": "Condense выкарыстоўвае прасунутае сцісканне: выдаляе лішняе, аптымізуе відарысы, паднаборы шрыфтоў. Найлепш пасуе для большасці PDF.",
"photonInfo": "Photon ператварае старонкі ў відарысы. Для PDF з вялікай колькасцю фота або сканіраваных PDF.",
"photonWarning": "Папярэджанне: стане немагчыма вылучыць тэкст, і перастануць працаваць спасылкі.",
"levelLabel": "Узровень сціскання",
"light": "Лёгкі (Захаванне якасці)",
"balanced": "Збалансаваны (Рэкамендуецца)",
"aggressive": "Агрэсіўны (Меншыя файлы)",
"extreme": "Экстрэмальны (Максімальнае сцісканне)",
"grayscale": "Канвертаваць у градацыі шэрага",
"grayscaleHint": "Памяншае памер файла, выдаляючы інфармацыю пра колер",
"customSettings": "Карыстальніцкія налады",
"customSettingsHint": "Дакладная настройка параметраў сціскання:",
"outputQuality": "Якасць вываду",
"resizeImagesTo": "Змяніць памер відарысаў да",
"onlyProcessAbove": "Апрацоўваць толькі большыя за",
"removeMetadata": "Выдаліць метаданыя",
"subsetFonts": "Паднабор шрыфтоў (выдаліць сімвалы, якія не выкарыстоўваюцца)",
"removeThumbnails": "Выдаліць убудаваныя мініяцюры",
"compressButton": "Сціснуць PDF"
"subtitle": "Зменшыць памер файла PDF."
},
"pdfEditor": {
"name": "Рэдактар PDF",
@@ -57,24 +36,26 @@
},
"editPdfText": {
"name": "Рэдагаваць тэкст PDF",
"subtitle": "Націсніце на любы абзац і рэдагуйце яго на месцы з імгненнай перакампаноўкай тэксту, шрыфтамі і стылямі.",
"subtitle": "Рэдагаваць любы абзац на месцы — з імгненнай перакампаноўкай тэксту, шрыфтамі і стылямі.",
"saved": "PDF паспяхова захаваны! ({{size}} КБ)",
"failedToLoad": "Не ўдалося загрузіць рэдактар тэксту PDF.",
"howToUpload": "Загрузіць PDF",
"loadingFonts": "Загрузка шрыфтоў...",
"fontsUnavailable": "Не ўдалося спампаваць шрыфт, патрэбны для некаторых сімвалаў. Праверце злучэнне і паспрабуйце яшчэ раз, інакш гэтыя сімвалы могуць адлюстроўвацца няправільна ў захаваным PDF.",
"howToUpload": "Запампуйце PDF",
"howToClick": "Націсніце на абзац",
"howToRestyle": "Змяніце стыль",
"relatedPdfEditor": "Каментуйце і разметьце PDF",
"relatedSignPdf": "Намалюйце, увядзіце або загрузіце подпіс",
"relatedWatermark": "Нанясіце тэкст або выявы",
"relatedStamps": "Размяшчайце штампы на старонках",
"relatedCompress": "Паменшыце памер файла",
"relatedPdfEditor": "Анатаваць і размячаць PDF",
"relatedSignPdf": "Намаляваць, увесці або запампаваць подпіс",
"relatedWatermark": "Нанесці тэкст або відарысы",
"relatedStamps": "Размясціць штампы на старонках",
"relatedCompress": "Паменшыць памер файла",
"relatedOrganizeName": "Упарадкаваць PDF",
"relatedOrganize": "Мяняйце парадак і кіруйце старонкамі",
"relatedOrganize": "Змяніць парадак і кіраваць старонкамі",
"open": "Адкрыць",
"export": "Экспарт",
"filterAll": "Усе",
"filterText": "Тэкст",
"filterImages": "Выявы",
"filterImages": "Відарысы",
"filterShapes": "Фігуры",
"addText": "Дадаць тэкст",
"langAuto": "Аўта",
@@ -83,7 +64,7 @@
"next": "Далей",
"replace": "Замяніць",
"replaceAll": "Замяніць усё",
"emptyState": "Адкрыйце PDF, каб рэдагаваць тэкст, выявы і фігуры.",
"emptyState": "Адкрыйце PDF, каб рэдагаваць тэкст, відарысы і фігуры.",
"choosePdf": "Выберыце PDF…",
"font": "Шрыфт",
"systemFonts": "Сістэмныя шрыфты",
@@ -96,32 +77,32 @@
"direction": "Напрамак",
"dirAuto": "Аўта",
"pathStroke": "Абвядзенне контуру",
"tipBackToUpload": "Назад да загрузкі",
"tipBackToUpload": "Назад да запампоўкі",
"tipOpenAnotherPdf": "Адкрыць іншы PDF",
"tipExportS": "Экспарт (⌘S)",
"tipUndoZ": "Адмяніць (⌘Z)",
"tipRedoZ": "Паўтарыць (⇧⌘Z)",
"tipUndoZ": "Адрабіць (⌘Z)",
"tipRedoZ": "Узнавіць (⇧⌘Z)",
"tipFileDetails": "Звесткі пра файл",
"tipEditExistingContent": "Рэдагаваць наяўнае змесціва",
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "На што дзейнічае інструмент рэдагавання — звузьце вобласць на насычаных старонках",
"tipClickThePageToAddATextBox": "Націсніце на старонку, каб дадаць тэкставае поле",
"tipSpellCheckLanguage": "Мова праверкі правапісу",
"tipFindAndReplace": "Знайсці і замяніць",
"tipAddAnImage": "Дадаць выяву",
"tipCopyThisPageSTextInReadingOrder": "Скапіяваць тэкст старонкі ў парадку чытання",
"tipAddAnImage": "Дадаць відарыс",
"tipCopyThisPageSTextInReadingOrder": "Скапіраваць тэкст старонкі ў парадку чытання",
"tipCheckTheSpellingOfThisPage": "Праверыць правапіс на гэтай старонцы",
"tipShowOrHideTheFormatPanel": "Паказаць або схаваць панэль фарматавання",
"phReplaceWith": "Замяніць на",
"tipAddToYourDictionary": "Дадаць у слоўнік",
"tipClose": "Закрыць",
"phFind": "Знайсці",
"tipPreviousMatch": "Папярэдні супадзенне",
"tipPreviousMatch": "Папярэдняе супадзенне",
"tipNextMatch": "Наступнае супадзенне",
"tipRotateLeft90": "Павярнуць на 90° улева",
"tipRotateRight90": "Павярнуць на 90° управа",
"tipFlipHorizontal": "Адлюстраваць гарызантальна",
"tipFlipVertical": "Адлюстраваць вертыкальна",
"tipReplaceThisImageKeepingItsPlacement": "Замяніць выяву, захаваўшы размяшчэнне",
"tipReplaceThisImageKeepingItsPlacement": "Замяніць відарыс, захаваўшы размяшчэнне",
"tipAlternateTextForAccessibilityTaggedPdfs": "Альтэрнатыўны тэкст для даступнасці (тэгаваныя PDF)",
"tipBringToFront": "На пярэдні план",
"tipSendToBack": "На задні план",
@@ -160,7 +141,7 @@
"tipRightToLeft": "Справа налева",
"tipStrokeColor": "Колер абвядзення",
"tipStrokeWidth": "Таўшчыня абвядзення",
"tipZoomPresets": "Прадусталёўкі маштабу",
"tipZoomPresets": "Перадвызначаныя налады маштабу",
"tipZoomOut": "Паменшыць",
"tipZoomIn": "Павялічыць",
"tipFitPage": "Па памеры старонкі",
@@ -199,12 +180,12 @@
"editBookmarks": {
"name": "Рэдагаваць закладкі",
"subtitle": "Дадаць, рэдагаваць, імпартаваць, выдаліць і выняць закладкі PDF.",
"autoExtractExisting": "Аўтаматычна выманне існуючых закладак",
"autoExtractExisting": "Аўтаматычнае выманне наяўных закладак",
"importSectionTitle": "Або імпартаваць закладкі",
"csvFormat": "Фармат CSV: загаловак,старонка,узровень",
"jsonFormat": "Фармат JSON",
"uploadCsvAction": "Націсніце, каб загрузіць CSV",
"uploadJsonAction": "Націсніце, каб загрузіць JSON",
"uploadCsvAction": "Націсніце, каб запампаваць CSV",
"uploadJsonAction": "Націсніце, каб запампаваць JSON",
"orDragHere": "або перацягніце сюды"
},
"tableOfContents": {
@@ -213,15 +194,15 @@
"titleLabel": "Загаловак зместу",
"fontSize": "Памер шрыфта",
"fontFamily": "Сямейства шрыфтоў",
"addBookmark": "Додати закладку для сторінки змісту",
"addBookmark": "Дадаць закладку для старонкі зместу",
"generateButton": "Стварыць змест",
"selectPdfFirst": "Спачатку выберыце PDF-файл.",
"statusReadingFileMainThread": "Читання файлу (головний потік)...",
"statusReadingFileMainThread": "Чытанне файла (галоўны паток)...",
"statusGenerating": "Стварэнне зместу...",
"errorReadingFileWithMessage": "Помилка читання файлу: {{message}}",
"errorReadingFileWithMessage": "Памылка чытання файла: {{message}}",
"successGeneratedDownloadStarted": "Змест паспяхова створаны! Спампоўванне распачалося.",
"workerErrorWithMessage": "Помилка: {{message}}",
"workerErrorOccurred": "Адбылася памылка працаўніка. Падрабязнасці ў кансолі."
"workerErrorWithMessage": "Памылка: {{message}}",
"workerErrorOccurred": "Адбылася памылка апрацоўшчыка. Падрабязнасці ў кансолі."
},
"pageNumbers": {
"name": "Нумары старонак",
@@ -238,18 +219,18 @@
"howLabelsWorkStep4": "Уключыце працяг нумарацыі, калі адно правіла выкарыстоўвае разарваны дыяпазон, напрыклад 1-9,30-40 або няцотныя старонкі.",
"labelRulesTitle": "Правілы пазнак",
"addRule": "Дадаць правіла",
"removeExistingLabels": "Выдаліць існуючыя пазнакі старонак перад прымяненнем гэтых правіл",
"removeExistingLabels": "Выдаліць наяўныя пазнакі старонак перад прымяненнем гэтых правіл",
"cpdfNote": "Гэты інструмент выкарыстоўвае CoherentPDF у вашым браўзеры. Калі CoherentPDF не наладжаны, вам будзе прапанавана наладзіць яго ў наладах WASM.",
"processButton": "Дадаць пазнакі старонак",
"howItWorksUploadTitle": "Запампаваць файл",
"howItWorksUploadDescription": "Выберыце PDF, які хочаце перапазначыць.",
"howItWorksDefineTitle": "Вызначыць правілы",
"howItWorksUploadTitle": "Запампуйце файл",
"howItWorksUploadDescription": "Выберыце PDF, у якім хочаце змяніць пазнакі.",
"howItWorksDefineTitle": "Вызначце правілы",
"howItWorksDefineDescription": "Наладзьце адно або некалькі правіл пазнак старонак з дыяпазонамі, стылямі, прэфіксамі і пачатковымі значэннямі.",
"howItWorksDownloadTitle": "Спампаваць",
"howItWorksDownloadTitle": "Спампуйце",
"howItWorksDownloadDescription": "Захавайце абноўлены PDF з новымі пазнакамі старонак.",
"relatedToolsTitle": "Звязаныя інструменты PDF",
"faqWhatIsQuestion": "Што такое пазнака старонкі?",
"faqWhatIsAnswer": "Пазнака старонкі - гэта нумарацыя, якую чытальнікі PDF паказваюць у мініяцюрах, навігацыі па старонках і дыялогах друку. Яна не друкуе новы тэкст на самой старонцы.",
"faqWhatIsAnswer": "Пазнака старонкі — гэта нумарацыя, якую чытальнікі PDF паказваюць у мініяцюрах, навігацыі па старонках і дыялогах друку. Яна не друкуе новы тэкст на самой старонцы.",
"faqMixQuestion": "Ці можна спалучаць рымскія і звычайныя лічбы?",
"faqMixAnswer": "Так. Дадайце некалькі правіл, напрыклад 1-4 з LowercaseRoman і 5-20 з DecimalArabic.",
"faqPrivacyQuestion": "Ці застаюцца мае файлы прыватнымі?",
@@ -301,12 +282,12 @@
},
"invertColors": {
"name": "Інвертаваць колеры",
"subtitle": "Стварыць версію PDF у \"цёмнай тэме\"."
"subtitle": "Стварыць версію PDF у «цёмнай тэме»."
},
"scannerEffect": {
"name": "Эфект сканера",
"subtitle": "Зрабіць PDF падобным да адсканаванага дакумента.",
"scanSettings": "Налады сканіравання",
"scanSettings": "Налады сканавання",
"colorspace": "Каляровая прастора",
"gray": "Градацыі шэрага",
"border": "Рамка",
@@ -331,7 +312,7 @@
"temperature": "Тэмпература",
"tint": "Адценне",
"gamma": "Гама",
"sepia": "Сэпія",
"sepia": "Сепія",
"processButton": "Ужыць рэгуліроўкі колеру"
},
"backgroundColor": {
@@ -348,7 +329,7 @@
"usernameLabel": "Імя для штампа",
"usernamePlaceholder": "Увядзіце сваё імя (для штампаў)",
"usernameHint": "Гэта імя з'явіцца на створаных вамі штампах.",
"saveButton": "Захаваць PDF з пячаткай"
"saveButton": "Захаваць PDF са штампамі"
},
"removeAnnotations": {
"name": "Выдаліць анатацыі",
@@ -357,9 +338,9 @@
"pdfFormFiller": {
"name": "Запоўніць форму PDF",
"subtitle": "Запоўніць форму непасрэдна ў браўзеры. Таксама падтрымліваюцца формы XFA.",
"uploadHint": "Завантажте PDF з полями форми. Заповніть їх безпосередньо у переглядачі нижче, потім натисніть кнопку, щоб зберегти та завантажити заповнену форму. Також підтримуються форми XFA.",
"uploadHint": "Запампуйце PDF з палямі формы. Запоўніце іх непасрэдна ў праглядальніку ніжэй, а затым націсніце кнопку, каб захаваць і спампаваць запоўненую форму. Таксама падтрымліваюцца формы XFA.",
"xfaNoteTitle": "Заўвага па формах XFA:",
"xfaNoteDescription": "XFA (XML Forms Architecture) — застарілий формат, який підтримується лише певними PDF-переглядачами, такими як BentoPDF та Firefox. Якщо ви відкриваєте XFA PDF в іншому ПЗ і бачите порожні сторінки або відсутність полів форми, це означає, що цей переглядач не підтримує XFA. Щоб правильно переглядати та заповнювати форми XFA, використовуйте Firefox або заповнювач форм BentoPDF."
"xfaNoteDescription": "XFA (XML Forms Architecture) — састарэлы фармат, што падтрымліваецца толькі некаторымі праглядальнікамі PDF, напрыклад BentoPDF і Firefox. Калі адкрыць PDF XFA ў іншай праграме і ўбачыць пустыя старонкі або адсутнасць палёў формы, гэта азначае, што праглядальнік не падтрымлівае XFA. Для правільнага прагляду і запаўнення XFA выкарыстоўвайце Firefox або праграму запаўнення формаў BentoPDF."
},
"createPdfForm": {
"name": "Стварыць форму PDF",
@@ -403,33 +384,33 @@
"textToPdf": {
"name": "Тэкст у PDF",
"subtitle": "Канвертаваць звычайны тэкставы файл у PDF.",
"uploadFiles": "Загрузіць файлы",
"uploadFiles": "Запампаваць файлы",
"typeText": "Увесці тэкст",
"acceptedFormats": "Текстові файли (.txt)",
"acceptedFormats": "Тэкставыя файлы (.txt)",
"fontFamily": "Сямейства шрыфтоў",
"fontSize": "Памер шрыфта",
"textColor": "Колер тэксту",
"pageSize": "Памер старонкі",
"rtlAutoDetectNote": "Мови RTL (арабська, урду, перська тощо) автоматично визначаються, і напрямок тексту регулюється.",
"rtlAutoDetectNote": "Мовы з напрамкам справа налева (арабская, урду, персідская і інш.) вызначаюцца аўтаматычна, і кірунак тэксту карэктуецца.",
"createButton": "Стварыць PDF"
},
"jsonToPdf": {
"name": "JSON у PDF",
"subtitle": "Канвертаваць файлы JSON у фармат PDF.",
"noteLabel": "Примітка:",
"noteText": "Підтримуються лише JSON-файли, створені інструментом PDF→JSON. Стандартні JSON-файли від інших інструментів не працюють.",
"acceptedFormats": "Кілька JSON-файлів",
"noteLabel": "Нататка:",
"noteText": "Падтрымліваюцца толькі файлы JSON, створаныя інструментам канвертавання PDF у JSON. Стандартныя файлы JSON з іншых інструментаў не будуць працаваць.",
"acceptedFormats": "Некалькі файлаў JSON",
"status": {
"selectAtLeastOne": "Виберіть принаймні 1 JSON-файл",
"selectedReady": "Вибрано {{count}} файл(ів). Готово до конвертації!",
"readingFiles": "Читання файлів (головний потік)...",
"converting": "Конвертація JSON-файлів у PDF...",
"readError": "Помилка читання файлів: {{message}}",
"creatingZip": "Створення ZIP-файлу...",
"success": "JSON-файли успішно конвертовано в PDF! Завантаження ZIP розпочато.",
"zipError": "Помилка створення ZIP: {{message}}",
"workerError": "Помилка Worker: {{message}}",
"getStarted": "Виберіть JSON-файли, щоб почати"
"selectAtLeastOne": "Выберыце хаця б 1 файл JSON",
"selectedReady": "Выбрана файлаў: {{count}}. Гатова да канвертавання!",
"readingFiles": "Чытанне файлаў (галоўны паток)...",
"converting": "Пераўтварэнне файлаў JSON у PDF...",
"readError": "Памылка чытання файлаў: {{message}}",
"creatingZip": "Стварэнне ZIP-файла...",
"success": "Файлы JSON паспяхова пераўтвораны ў PDF! Пачалося спампоўванне ZIP.",
"zipError": "Памылка стварэння ZIP: {{message}}",
"workerError": "Памылка апрацоўшчыка: {{message}}",
"getStarted": "Выберыце файлы JSON, каб пачаць"
}
},
"pdfToJpg": {
@@ -515,7 +496,8 @@
"noFile": "Няма файла",
"noFileExplanation": "Спачатку запампуйце файл PDF.",
"conversionSuccess": "PDF паспяхова канвертаваны ў TIFFs!",
"conversionError": "Не ўдалося канвертаваць PDF у TIFF. Файл можа быць пашкоджаны."
"conversionError": "Не ўдалося канвертаваць PDF у TIFF. Файл можа быць пашкоджаны.",
"conversionOutOfMemory": "У браўзеры скончылася памяць падчас канвертавання. Паспрабуйце знізіць DPI або адключыць параметр шматстаронкавага TIFF, каб канвертаваць старонкі па адной."
}
},
"pdfToCbz": {
@@ -555,19 +537,19 @@
"pdfToJson": {
"name": "PDF у JSON",
"subtitle": "Канвертаваць файлы PDF у фармат JSON.",
"convertButton": "Конвертувати у JSON",
"convertButton": "Пераўтварыць у JSON",
"status": {
"selectAtLeastOne": "Виберіть принаймні 1 PDF-файл",
"selectedReady": "Вибрано {{count}} файл(ів). Готово до конвертації!",
"checkingEncrypted": "Перевірка зашифрованих PDF...",
"readingFiles": "Читання файлів (головний потік)...",
"converting": "Конвертація PDF у JSON...",
"readError": "Помилка читання файлів: {{message}}",
"creatingZip": "Створення ZIP-файлу...",
"success": "PDF успішно конвертовано у JSON! Завантаження ZIP розпочато.",
"zipError": "Помилка створення ZIP: {{message}}",
"workerError": "Помилка Worker: {{message}}",
"getStarted": "Виберіть PDF-файли, щоб почати"
"selectAtLeastOne": "Выберыце хаця б 1 файл PDF",
"selectedReady": "Выбрана файлаў: {{count}}. Гатова да канвертавання!",
"checkingEncrypted": "Праверка зашыфраваных PDF...",
"readingFiles": "Чытанне файлаў (галоўны паток)...",
"converting": "Пераўтварэнне PDF у JSON...",
"readError": "Памылка чытання файлаў: {{message}}",
"creatingZip": "Стварэнне ZIP-файла...",
"success": "PDF паспяхова пераўтвораны ў JSON! Пачалося спампоўванне ZIP.",
"zipError": "Памылка стварэння ZIP: {{message}}",
"workerError": "Памылка апрацоўшчыка: {{message}}",
"getStarted": "Выберыце файлы PDF, каб пачаць"
}
},
"ocrPdf": {
@@ -577,62 +559,62 @@
"searchLanguagesPlaceholder": "Пошук моў...",
"selectedLabel": "Выбрана:",
"none": "Няма",
"advancedSettingsSummary": "Додаткові налаштування (рекомендовано для покращення точності)",
"advancedSettingsSummary": "Пашыраныя налады (рэкамендуецца для павышэння дакладнасці)",
"resolutionLabel": "Раздзяляльная здольнасць",
"resolutionStandard": "Стандартная (192 DPI)",
"resolutionHigh": "Высокая (288 DPI)",
"resolutionUltra": "Ультра (384 DPI)",
"binarizeLabel": "Бінаризувати зображення (покращити контраст для чистих сканів)",
"embedFullFontsLabel": "Вбудувати повні шрифти (більший файл, краща сумісність)",
"whitelistPresetLabel": "Передустановка білого списку символів",
"whitelistNone": "Немає (усі символи)",
"whitelistAlphanumeric": "Літери та цифри + базова пунктуація",
"whitelistNumbersCurrency": "Числа + Символи валют",
"whitelistLettersOnly": "Лише літери (A-Z, a-z)",
"whitelistNumbersOnly": "Лише числа (0-9)",
"whitelistInvoice": "Рахунок/Чек (числа, $, ., -, /)",
"whitelistForms": "Форми (літери та цифри + загальні символи)",
"whitelistCustom": "Користувацький...",
"whitelistHelp": "Будуть розпізнані лише ці символи. Залиште порожнім для всіх символів.",
"whitelistInputLabel": "Білий список символів (необов'язково)",
"binarizeLabel": "Бінарызаваць відарыс (павысіць кантраст для чыстых сканаў)",
"embedFullFontsLabel": "Убудаваць поўныя шрыфты (большы файл, лепшая сумяшчальнасць)",
"whitelistPresetLabel": "Перадвызначаная налада спісу дазволеных сімвалаў",
"whitelistNone": "Няма (усе сімвалы)",
"whitelistAlphanumeric": "Лічбавыя і літарныя сімвалы + асноўныя знакі прыпынку",
"whitelistNumbersCurrency": "Лічбы + сімвалы валют",
"whitelistLettersOnly": "Толькі літары (A-Z, a-z)",
"whitelistNumbersOnly": "Толькі лічбы (0-9)",
"whitelistInvoice": "Рахунак/квітанцыя (лічбы, $, ., -, /)",
"whitelistForms": "Формы (літары і лічбы + агульнаўжывальныя сімвалы)",
"whitelistCustom": "Уласны…",
"whitelistHelp": "Распазнаюцца толькі гэтыя сімвалы. Пакіньце поле пустым, каб дазволіць усе сімвалы.",
"whitelistInputLabel": "Спіс дазволеных сімвалаў (неабавязкова)",
"whitelistInputPlaceholder": "напр., abcdefghijklmnopqrstuvwxyz0123456789$.,",
"startButton": "Запусціць OCR",
"progressInitializing": "Ініцыялізацыя...",
"resultsTitle": "OCR завершаны",
"resultsDescription": "Ваш PDF з пошуком готовий. Ви також можете скопіювати або завантажити витягнутий текст нижче.",
"copyToClipboard": "Капіяваць у буфер абмену",
"resultsDescription": "PDF з магчымасцю пошуку гатовы. Ніжэй можна скапіраваць або спампаваць выняты тэкст.",
"copyToClipboard": "Капіраваць у буфер абмену",
"downloadTxt": "Спампаваць як .txt",
"downloadSearchablePdf": "Спампаваць пошукавы PDF",
"statusPrefix": "Статус: {{status}}",
"availabilityInvalidConfig": "Цей реліз не надає дійсних мов OCR. Перебудуйте його з VITE_TESSERACT_AVAILABLE_LANGUAGES, встановленим на дійсні коди Tesseract.",
"availabilityBundles": "Цей реліз містить OCR для: {{languages}}.",
"availabilityInvalidConfig": "Гэта разгортванне не прапануе ніводнай дапушчальнай мовы OCR. Перазбярыце яго, задаўшы VITE_TESSERACT_AVAILABLE_LANGUAGES дапушчальнымі кодамі Tesseract.",
"availabilityBundles": "Гэта разгортванне ўключае OCR для: {{languages}}.",
"noLanguagesAvailable": "У гэтым выпуску няма даступных моў OCR.",
"noLanguagesTitle": "Мовы не выбраны",
"noLanguagesMessage": "Выберыце прынамсі адну мову для OCR.",
"noFileTitle": "Няма файла",
"noFileMessage": "Спачатку загрузіце PDF-файл.",
"noFileMessage": "Спачатку запампуйце PDF-файл.",
"languageUnavailableTitle": "Мова OCR недаступная",
"ocrErrorTitle": "Памылка OCR",
"ocrErrorMessage": "Падчас працэсу OCR адбылася памылка. Магчыма, працаўнік не загрузіўся. Паспрабуйце яшчэ раз.",
"ocrErrorMessage": "Падчас працэсу OCR адбылася памылка. Магчыма, апрацоўшчык не загрузіўся. Паспрабуйце яшчэ раз.",
"howItWorksTitle": "Як гэта працуе:",
"extractTextLabel": "Витягти текст:",
"extractTextDescription": "Використовує Tesseract OCR для розпізнавання тексту на сканованих зображеннях або PDF.",
"searchableOutputLabel": "Вивід з можливістю пошуку:",
"searchableOutputDescription": "Створює новий PDF з невидимим текстовим шаром, роблячи ваш документ повністю придатним для пошуку, зберігаючи оригінальний вигляд.",
"characterFilteringLabel": "Фільтрація символів:",
"characterFilteringDescription": "Використовуйте білі списки для фільтрації небажаних символів і покращення точності для конкретних типів документів (рахунки, форми тощо).",
"multiLanguageSupportLabel": "Багатомовна підтримка:",
"multiLanguageSupportDescription": "Виберіть кілька мов для документів зі змішаним мовним вмістом."
"extractTextLabel": "Выняць тэкст:",
"extractTextDescription": "Выкарыстоўвае OCR Tesseract для распазнавання тэксту са сканаваных відарысаў або PDF.",
"searchableOutputLabel": "Вынік з магчымасцю пошуку:",
"searchableOutputDescription": "Стварае новы PDF з нябачным тэкставым слоем, робячы дакумент цалкам даступным для пошуку і захоўваючы яго першапачатковы выгляд.",
"characterFilteringLabel": "Фільтраванне сімвалаў:",
"characterFilteringDescription": "Дазваляе адфільтроўваць непатрэбныя сімвалы праз спісы дазволеных і павышае дакладнасць для пэўных тыпаў дакументаў (рахункаў, формаў і інш.).",
"multiLanguageSupportLabel": "Падтрымка некалькіх моў:",
"multiLanguageSupportDescription": "Дазваляе выбраць некалькі моў для дакументаў з тэкстам на розных мовах."
},
"alternateMerge": {
"name": "Чаргаваць і змяшаць старонкі",
"subtitle": "Аб'яднаць PDF, чаргуючы старонкі з асобных PDF. Закладкі захоўваюцца.",
"retainPageLabels": "Захоўваць арыгінальныя пазнакі старонак з кожнага файла",
"retainPageLabelsHint": "Выключана (па змаўчанні): аб’яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
"retainPageLabelsHint": "Выключана (прадвызначана): аб'яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
},
"duplexCollate": {
"name": "Сартаванне двухбаковага сканавання",
"subtitle": "Упарадкоўвае PDF, адсканаваны двума блокамі (спачатку ўсе пярэднія бакі, потым усе адваротныя), у правільны парадак пярэдні/адваротны.",
"subtitle": "Упарадкаваць PDF, адсканаваны двума блокамі (спачатку ўсе пярэднія бакі, потым усе адваротныя), у правільны парадак пярэдні/адваротны.",
"totalPagesLabel": "Усяго старонак:",
"splitAfterPageLabel": "Падзяліць пасля старонкі",
"splitAfterPagePlaceholder": "напр. 50",
@@ -644,7 +626,7 @@
"pagesPerDocumentLabel": "Старонак у зыходным дакуменце",
"groupedHelp": "Калі ўключана, вынікам будзе ZIP-архіў з асобным PDF для кожнага згрупаванага дакумента.",
"collateButton": "Сабраць PDF",
"invalidFileTitle": "Няправільны файл",
"invalidFileTitle": "Памылковы файл",
"invalidFileMessage": "Выберыце файл PDF.",
"loadingPdf": "Загрузка PDF...",
"loadErrorMessage": "Не ўдалося загрузіць файл PDF.",
@@ -653,18 +635,18 @@
"previewSummary": "Блок пярэдніх бакоў: {{frontCount}} стар., блок адваротных: {{backCount}} стар. Вынік: {{outputCount}} стар. у парадку пярэдні/адваротны.",
"previewMismatchWarning": "Даўжыня блокаў пярэдніх і адваротных бакоў адрозніваецца ({{frontCount}} пярэдніх супраць {{backCount}} адваротных). Лішнія старонкі ({{extraCount}}) з даўжэйшага блока будуць дададзены без пары ў канец.",
"missingFileTitle": "Файл не выбраны",
"missingFileMessage": "Перад апрацоўкай загрузіце PDF прынамсі з 2 старонкамі.",
"invalidSplitTitle": "Няправільны пункт падзелу",
"missingFileMessage": "Перад апрацоўкай запампуйце PDF прынамсі з 2 старонкамі.",
"invalidSplitTitle": "Памылковы пункт падзелу",
"invalidSplitMessage": "Пункт падзелу павінен быць паміж старонкай 1 і старонкай {{maxSplit}}.",
"unevenConfirmTitle": "Няроўныя блокі",
"unevenConfirmMessage": "У блоку пярэдніх бакоў {{frontCount}} стар., у блоку адваротных — {{backCount}} стар.\nЗвычайна гэта азначае, што старонка адсканавана двойчы або яе не хапае.\n\nСтаронкі без пары ({{extraCount}}) будуць дададзены ў канец.\n\nУсё роўна працягнуць?",
"invalidGroupTitle": "Няправільны памер групы",
"invalidGroupTitle": "Памылковы памер групы",
"invalidGroupMessage": "Увядзіце правільную колькасць старонак у зыходным дакуменце.",
"collatingLoader": "Збор двухбаковага сканавання...",
"successMessage": "Сабраны PDF паспяхова створаны.",
"successGroupedMessage": "Збор завершаны. Створана файлаў: {{fileCount}}.",
"processErrorMessage": "Не ўдалося сабраць PDF.",
"howItWorksStep1Title": "Загрузіце скан",
"howItWorksStep1Title": "Запампуйце скан",
"howItWorksStep1": "Перацягніце адзін PDF, у якім спачатку ідуць усе пярэднія бакі, а потым усе адваротныя.",
"howItWorksStep2Title": "Задайце пункт падзелу",
"howItWorksStep2": "Пазначце, дзе заканчваецца блок пярэдніх бакоў, і выберыце, ці трэба перавярнуць блок адваротных.",
@@ -673,7 +655,7 @@
"faqOddPagesQuestion": "Што рабіць, калі ў скане няцотная колькасць старонак?",
"faqOddPagesAnswer": "Двухбаковае сканаванне павінна мець цотную колькасць старонак. Калі гэта не так, старонка, хутчэй за ўсё, адсканавана двойчы або прапушчана. Інструмент папярэдзіць вас перад апрацоўкай, а старонкі без пары будуць дададзены ў канец, каб нічога не згубілася.",
"faqBackOrderQuestion": "Навошта пакідаць блок адваротных бакоў без змен?",
"faqBackOrderAnswer": "Гэта залежыць ад таго, як стос падавалі на другім праходзе. Калі перавярнуць увесь стос, адваротныя бакі ідуць у адваротным парадку — гэта варыянт па змаўчанні. Калі сканер выдаў іх у тым самым парадку, што і пярэднія бакі, выберыце пакінуць блок без змен."
"faqBackOrderAnswer": "Гэта залежыць ад таго, як стос падавалі на другім праходзе. Калі перавярнуць увесь стос, адваротныя бакі ідуць у адваротным парадку — гэта прадвызначаны варыянт. Калі сканер выдаў іх у тым самым парадку, што і пярэднія бакі, выберыце пакінуць блок без змен."
},
"addAttachments": {
"name": "Дадаць далучэнні",
@@ -865,14 +847,14 @@
"btnSettings": "Налады",
"btnExportPdf": "Экспартаваць PDF",
"settingsTitle": "Налады Markdown",
"settingsPreset": "Набор налад",
"settingsPreset": "Перадвызначаная налада",
"presetDefault": "Прадвызначаны (як GFM)",
"presetCommonmark": "CommonMark (строгі)",
"presetZero": "Мінімальны (без функцый)",
"settingsOptions": "Параметры Markdown",
"optAllowHtml": "Дазволіць HTML-тэгі",
"optBreaks": "Пераўтвараць пераносы радкоў у <br>",
"optLinkify": "Аўтаматычна пераўтвараць URL-адрасы ў спасылкі",
"optLinkify": "Аўтаматычна канвертаваць URL-адрасы ў спасылкі",
"optTypographer": "Тыпограф (разумныя двукоссі і інш.)"
},
"pdfBooklet": {
@@ -1001,9 +983,8 @@
"name": "PDF у тэкст",
"subtitle": "Выняць тэкст з файлаў PDF і захаваць як тэкставы файл (.txt). Падтрымлівае некалькі файлаў.",
"noteLabel": "Заўвага:",
"noteText": "Цей інструмент працює ТІЛЬКИ з PDF, створеними цифровим способом. Для сканованих документів або PDF на основі зображень використовуйте натомість наш інструмент OCR PDF.",
"convertButton": "Выняць тэкст",
"note": "Гэты інструмент працуе ТОЛЬКІ з PDF, створанымі лічбавым спосабам. Для сканіраваных дакументаў або PDF на аснове відарысаў выкарыстоўвайце інструмент OCR PDF."
"noteText": "Гэты інструмент працуе ТОЛЬКІ з PDF, створанымі лічбавым спосабам. Для сканаваных дакументаў або PDF на аснове відарысаў выкарыстоўвайце наш інструмент OCR PDF.",
"convertButton": "Выняць тэкст"
},
"digitalSignPdf": {
"name": "Лічбавы подпіс PDF",
@@ -1012,7 +993,7 @@
"certificateSection": "Сертыфікат",
"uploadCert": "Запампаваць сертыфікат (.pfx, .p12, .pem)",
"certPassword": "Пароль сертыфіката",
"privateKeyPassword": "Пароль приватного ключа",
"privateKeyPassword": "Пароль прыватнага ключа",
"certPasswordPlaceholder": "Увядзіце пароль сертыфіката",
"certInfo": "Інфармацыя пра сертыфікат",
"certSubject": "Суб'ект",
@@ -1025,71 +1006,71 @@
"locationPlaceholder": "напрыклад, Мінск, Беларусь",
"contactInfo": "Кантактная інфармацыя",
"contactPlaceholder": "напрыклад, email@example.com",
"visibleSignature": "Видимий підпис",
"visibleSignatureDescription": "Якщо увімкнено, у PDF з'являється видиме поле підпису. Можна завантажити зображення/логотип або додати текст. Якщо не вказано жодного, ім'я підписанта автоматично відображається з сертифіката.",
"signatureImage": "Зображення/логотип підпису (необов'язково)",
"uploadSignatureImage": "Завантажити зображення (PNG, JPG, WebP)",
"signaturePreviewAlt": "Попередній перегляд підпису",
"remove": "Видалити",
"page": "Сторінка",
"firstPage": "Перша сторінка",
"lastPage": "Остання сторінка",
"allPages": "Усі сторінки",
"customPage": "Користувацька сторінка #",
"pageNumber": "Сторінка #",
"xPosition": "Позиція X (зліва)",
"yPosition": "Позиція Y (зверху)",
"width": "Ширина",
"height": "Висота",
"addTextOverlay": "Додати текстове накладання",
"text": "Текст",
"textPlaceholder": "напр., Підписано в цифровій формі Іваном Петренком",
"textColor": "Колір тексту",
"fontSize": "Розмір шрифту",
"invalidImageTitle": "Недійсне зображення",
"invalidImageMessage": "Виберіть зображення PNG, JPG або WebP.",
"invalidFileTitle": "Недійсний файл",
"invalidFileMessage": "Виберіть PDF-файл.",
"invalidCertificateTitle": "Недійсний сертифікат",
"invalidCertificateMessage": "Виберіть файл сертифіката .pfx, .p12 або .pem.",
"certificateLoaded": "Сертифікат завантажено",
"certificateUnlocked": "Сертифікат розблоковано",
"failedParsePem": "Не вдалося проаналізувати файл PEM",
"enterPasswordToUnlock": "Введіть пароль для розблокування",
"invalidPasswordOrCertificate": "Невірний пароль або сертифікат",
"incorrectPassword": "Невірний пароль",
"failedParseCertificate": "Не вдалося проаналізувати сертифікат",
"missingDataTitle": "Відсутні дані",
"missingDataMessage": "Завантажте і PDF, і дійсний сертифікат.",
"applyingSignature": "Застосування цифрового підпису...",
"signingFailedTitle": "Помилка підписання",
"chainFetchFailed": "Не вдалося отримати ланцюг сертифікатів. Можливо, проблема з мережею або проксі сертифікатів недоступний. Перевірте підключення до Інтернету та повторіть спробу. Якщо проблема не зникає, зверніться до підтримки.",
"failedToSignPdf": "Не вдалося підписати PDF: {{message}}",
"defaultSignatureText": "Підписано в цифровій формі {{signer}}\n{{date}}",
"pageCount": "{{count}} стор.",
"howToStep1Title": "Завантажити PDF",
"howToStep1Text": "Виберіть PDF-документ, який хочете підписати",
"howToStep2Title": "Завантажити сертифікат",
"howToStep2Text": "Надайте файл сертифіката .pfx або .p12 і пароль",
"howToStep3Title": "Підписати та завантажити",
"howToStep3Text": "Застосуйте цифровий підпис і завантажте підписаний PDF",
"relatedEncryptDesc": "Захистити PDF паролем",
"relatedDecryptDesc": "Видалити пароль PDF",
"relatedFlattenDesc": "Зробити анотації постійними",
"relatedSanitizeDesc": "Видалити приховані дані",
"relatedPermissionsDesc": "Встановити дозволи PDF",
"faqWhatIsQuestion": "Що таке цифровий підпис?",
"faqWhatIsAnswer": "Цифровий підпис — це криптографічний механізм, який перевіряє автентичність і цілісність документа. На відміну від намальованого підпису, він використовує криптографію відкритого ключа (сертифікати X.509) для підтвердження особи підписанта.",
"faqFormatsQuestion": "Які формати сертифікатів підтримуються?",
"faqFormatsAnswer": "Ми підтримуємо сертифікати у форматі PKCS#12 (.pfx, .p12), які містять і ваш сертифікат, і приватний ключ в одному зашифрованому файлі. Зазвичай вони видаються центрами сертифікації.",
"faqPrivateKeyQuestion": "Чи безпечний мій приватний ключ?",
"faqPrivateKeyAnswer": "Так! Уся обробка відбувається повністю у вашому браузері. Ваш сертифікат, приватний ключ і файли PDF ніколи не залишають ваш пристрій і не завантажуються на жоден сервер.",
"faqValidReadersQuestion": "Чи буде підпис дійсним у переглядачах PDF?",
"faqValidReadersAnswer": "Так, інструмент створює стандартні відокремлені підписи PKCS#7, які розпізнаються всіма основними програмами для перегляду PDF. Для повної перевірки використовуйте сертифікат від довіреного центру сертифікації.",
"visibleSignature": "Бачны подпіс",
"visibleSignatureDescription": "Калі ўключана, у PDF з'яўляецца бачнае поле подпісу. Можна запампаваць відарыс або лагатып альбо дадаць тэкст. Калі нічога не дадзена, аўтаматычна будзе паказана імя падпісанта з сертыфіката.",
"signatureImage": "Відарыс або лагатып подпісу (неабавязкова)",
"uploadSignatureImage": "Запампаваць відарыс (PNG, JPG, WebP)",
"signaturePreviewAlt": "Папярэдні прагляд подпісу",
"remove": "Выдаліць",
"page": "Старонка",
"firstPage": "Першая старонка",
"lastPage": "Апошняя старонка",
"allPages": "Усе старонкі",
"customPage": "Уласная старонка №",
"pageNumber": "Старонка №",
"xPosition": "Пазіцыя X (злева)",
"yPosition": "Пазіцыя Y (зверху)",
"width": "Шырыня",
"height": "Вышыня",
"addTextOverlay": "Дадаць накладзены тэкст",
"text": "Тэкст",
"textPlaceholder": "Напрыклад, падпісана лічбавым подпісам Джона Доу",
"textColor": "Колер тэксту",
"fontSize": "Памер шрыфта",
"invalidImageTitle": "Памылковы відарыс",
"invalidImageMessage": "Выберыце відарыс PNG, JPG або WebP.",
"invalidFileTitle": "Памылковы файл",
"invalidFileMessage": "Выберыце файл PDF.",
"invalidCertificateTitle": "Памылковы сертыфікат",
"invalidCertificateMessage": "Выберыце файл сертыфіката .pfx, .p12 або .pem.",
"certificateLoaded": "Сертыфікат загружаны",
"certificateUnlocked": "Сертыфікат разблакаваны",
"failedParsePem": "Не ўдалося разабраць файл PEM",
"enterPasswordToUnlock": "Увядзіце пароль, каб разблакаваць",
"invalidPasswordOrCertificate": "Памылковы пароль або сертыфікат",
"incorrectPassword": "Няправільны пароль",
"failedParseCertificate": "Не ўдалося разабраць сертыфікат",
"missingDataTitle": "Адсутнасць даных",
"missingDataMessage": "Дадайце PDF і сапраўдны сертыфікат.",
"applyingSignature": "Накладанне лічбавага подпісу...",
"signingFailedTitle": "Не ўдалося падпісаць",
"chainFetchFailed": "Не ўдалося атрымаць ланцужок сертыфікатаў. Гэта можа быць выклікана праблемамі з сеткай або недаступнасцю проксі-сервера сертыфікатаў. Праверце падлучэнне да інтэрнэту і паспрабуйце яшчэ раз. Калі праблема захоўваецца, звярніцеся ў службу падтрымкі.",
"failedToSignPdf": "Не ўдалося падпісаць PDF: {{message}}",
"defaultSignatureText": "Падпісана лічбавым подпісам {{signer}}\n{{date}}",
"pageCount": "{{count}} стар.",
"howToStep1Title": "Запампуйце PDF",
"howToStep1Text": "Выберыце дакумент PDF, які хочаце падпісаць",
"howToStep2Title": "Запампуйце сертыфікат",
"howToStep2Text": "Дадайце файл сертыфіката .pfx або .p12 і пароль",
"howToStep3Title": "Падпішыце і спампуйце",
"howToStep3Text": "Накладзіце лічбавы подпіс і спампуйце падпісаны PDF",
"relatedEncryptDesc": "Абараніць PDF паролем",
"relatedDecryptDesc": "Выдаліць пароль PDF",
"relatedFlattenDesc": "Зрабіць анатацыі сталымі",
"relatedSanitizeDesc": "Выдаліць схаваныя даныя",
"relatedPermissionsDesc": "Задаць дазволы PDF",
"faqWhatIsQuestion": "Што такое лічбавы подпіс?",
"faqWhatIsAnswer": "Лічбавы подпіс — гэта крыптаграфічны механізм, які правярае сапраўднасць і цэласнасць дакумента. У адрозненне ад намаляванага подпісу, ён выкарыстоўвае крыптаграфію з адкрытым ключом (сертыфікаты X.509), каб пацвердзіць асобу падпісанта.",
"faqFormatsQuestion": "Якія фарматы сертыфікатаў падтрымліваюцца?",
"faqFormatsAnswer": "Падтрымліваюцца сертыфікаты фармату PKCS#12 (.pfx, .p12), якія змяшчаюць сертыфікат і закрыты ключ карыстальніка ў адным зашыфраваным файле. Такія сертыфікаты звычайна выдаюцца цэнтрамі сертыфікацыі.",
"faqPrivateKeyQuestion": "Ці ў бяспецы мой закрыты ключ?",
"faqPrivateKeyAnswer": "Так! Уся апрацоўка адбываецца непасрэдна ў браўзеры. Сертыфікат, закрыты ключ і файлы PDF ніколі не пакідаюць прыладу карыстальніка і не запампоўваюцца на сервер.",
"faqValidReadersQuestion": "Ці будзе подпіс сапраўдным у праглядальніках PDF?",
"faqValidReadersAnswer": "Так, інструмент стварае стандартныя адасобленыя подпісы PKCS#7, якія распазнаюцца ўсімі асноўнымі праглядальнікамі PDF. Для поўнай праверкі выкарыстоўвайце сертыфікат ад даверанага цэнтра сертыфікацыі.",
"applySignature": "Ужыць лічбавы подпіс",
"successMessage": "PDF паспяхова падпісаны! Подпіс можна праверыць у любым PDF-чытальніку.",
"internetRequiredTitle": "Потрібне інтернет-з'єднання",
"internetRequiredDescription": "Для перевірки підпису може знадобитися отримати інформацію про ланцюг сертифікатів із сервера видавця сертифіката."
"internetRequiredTitle": "Патрабуецца падлучэнне да інтэрнэту",
"internetRequiredDescription": "Для падпісання можа спатрэбіцца атрымаць звесткі пра ланцужок сертыфікатаў з сервера выдаўца сертыфіката, каб праверыць подпіс."
},
"validateSignaturePdf": {
"name": "Праверыць подпіс PDF",
@@ -1113,11 +1094,11 @@
},
"fontToOutline": {
"name": "Шрыфт у контуры",
"subtitle": "Ператварыць усе шрыфты ў вектарныя контуры для стабільнага адлюстравання на ўсіх прыладах."
"subtitle": "Канвертаваць усе шрыфты ў вектарныя контуры для стабільнага адлюстравання на ўсіх прыладах."
},
"deskewPdf": {
"name": "Выпрастаць PDF",
"subtitle": "Аўтаматычна выраўняць нахіленыя адсканіраваныя старонкі з дапамогай OpenCV."
"subtitle": "Аўтаматычна выраўняць нахіленыя адсканаваныя старонкі з дапамогай OpenCV."
},
"pdfToWord": {
"name": "PDF у Word",
@@ -1167,22 +1148,22 @@
"cancel": "Скасаваць",
"loadTemplate": "Загрузіць шаблон",
"noTemplates": "Пакуль няма захаваных шаблонаў.",
"ok": "OK",
"ok": "ОК",
"workflowCompleted": "Рабочы працэс завершаны",
"errorDuringExecution": "Памылка падчас выканання",
"addNodeError": "Дадайце хаця б адзін вузел для запуску рабочага працэсу.",
"needInputOutput": "Для працы рабочага працэсу патрэбен хаця б адзін вузел уводу і адзін вузел вываду.",
"needInputOutput": "Для працы рабочага працэсу патрэбны хаця б адзін вузел уводу і адзін вузел вываду.",
"enterName": "Увядзіце назву.",
"templateExists": "Шаблон з такой назвай ужо існуе.",
"templateSaved": "Шаблон \"{{name}}\" захаваны.",
"templateLoaded": "Шаблон \"{{name}}\" загружаны.",
"templateSaved": "Шаблон «{{name}}» захаваны.",
"templateLoaded": "Шаблон «{{name}}» загружаны.",
"failedLoadTemplate": "Не ўдалося загрузіць шаблон.",
"noSettings": "Няма налад для гэтага вузла.",
"advancedSettings": "Пашыраныя налады",
"specialNodes": {
"pdfInput": {
"name": "Увод PDF",
"description": "Загрузіце адзін ці некалькі файлаў PDF"
"description": "Запампуйце адзін ці некалькі файлаў PDF"
},
"download": {
"name": "Спампаваць",
@@ -1195,96 +1176,96 @@
"expectedPdfInput": "Чакаўся ўвод PDF",
"failedToRenderPage": "Не атрымалася адлюстраваць старонку {{page}}",
"failedToGetCanvasContext": "Не атрымалася атрымаць кантэкст палатна для старонкі {{page}}",
"failedToRenderPageToImage": "Не атрымалася адлюстраваць старонку {{page}} як выяву",
"failedToRenderPageToImage": "Не атрымалася адлюстраваць старонку {{page}} як відарыс",
"noPagesProcessed": "Ніводнай старонкі не апрацавана",
"cpdfNotConfigured": "CoherentPDF не настроены. Настройце яго ў пашыраных параметрах.",
"workerError": "Памылка воркера: {{message}}",
"alternateMergeWorkerError": "Памылка воркера паслядоўнага зліцця: {{message}}",
"noPdfFilesUploaded": "У вузел PDF Input не загружаны PDF-файлы",
"failedToLoadFile": "Не атрымалася загрузіць \"{{file}}\" — файл можа быць пашкоджаны",
"noImagesUploaded": "У вузел Image Input не загружаны выявы",
"noWordDocsUploaded": "У вузел Word Input не загружаны дакументы",
"noExcelUploaded": "У вузел Excel Input не загружаны табліцы",
"noPowerPointUploaded": "У вузел PowerPoint Input не загружаны прэзентацыі",
"noCbzUploaded": "У вузел CBZ Input не загружаны архівы коміксаў",
"noEmailUploaded": "У вузел Email Input не загружаны файлы пошты",
"noEpubUploaded": "У вузел EPUB Input не загружаны файлы EPUB",
"noFb2Uploaded": "У вузел FB2 Input не загружаны файлы FB2",
"noJsonUploaded": "У вузел JSON Input не загружаны файлы JSON",
"noMarkdownUploaded": "У вузел Markdown Input не загружаны файлы Markdown",
"noMobiUploaded": "У вузел MOBI Input не загружаны файлы MOBI",
"noOdgUploaded": "У вузел ODG Input не загружаны файлы ODG",
"noPagesUploaded": "У вузел Pages Input не загружаны файлы Pages",
"noPubUploaded": "У вузел PUB Input не загружаны файлы PUB",
"noSvgUploaded": "У вузел SVG Input не загружаны файлы SVG",
"noTextUploaded": "У вузел Text Input не загружаны тэкставыя файлы",
"noVsdUploaded": "У вузел VSD Input не загружаны файлы Visio",
"noWpdUploaded": "У вузел WPD Input не загружаны файлы WPD",
"noWpsUploaded": "У вузел WPS Input не загружаны файлы WPS",
"noXmlUploaded": "У вузел XML Input не загружаны файлы XML",
"noXpsUploaded": "У вузел XPS Input не загружаны файлы XPS",
"cpdfNotConfigured": "CoherentPDF не сканфігураваны. Сканфігуруйце яго ў пашыраных наладах.",
"workerError": "Памылка апрацоўшчыка: {{message}}",
"alternateMergeWorkerError": "Памылка апрацоўшчыка паслядоўнага зліцця: {{message}}",
"noPdfFilesUploaded": "У вузел «Увод PDF» не запампаваны PDF-файлы",
"failedToLoadFile": "Не атрымалася загрузіць «{{file}}» — файл можа быць пашкоджаны",
"noImagesUploaded": "У вузел уводу відарысаў не запампаваны відарысы",
"noWordDocsUploaded": "У вузел уводу Word не запампаваны дакументы",
"noExcelUploaded": "У вузел уводу Excel не запампаваны табліцы",
"noPowerPointUploaded": "У вузел уводу PowerPoint не запампаваны прэзентацыі",
"noCbzUploaded": "У вузел уводу CBZ не запампаваны архівы коміксаў",
"noEmailUploaded": "У вузел уводу Email не запампаваны файлы пошты",
"noEpubUploaded": "У вузел уводу EPUB не запампаваны файлы EPUB",
"noFb2Uploaded": "У вузел уводу FB2 не запампаваны файлы FB2",
"noJsonUploaded": "У вузел уводу JSON не запампаваны файлы JSON",
"noMarkdownUploaded": "У вузел уводу Markdown не запампаваны файлы Markdown",
"noMobiUploaded": "У вузел уводу MOBI не запампаваны файлы MOBI",
"noOdgUploaded": "У вузел уводу ODG не запампаваны файлы ODG",
"noPagesUploaded": "У вузел уводу Pages не запампаваны файлы Pages",
"noPubUploaded": "У вузел уводу PUB не запампаваны файлы PUB",
"noSvgUploaded": "У вузел уводу SVG не запампаваны файлы SVG",
"noTextUploaded": "У вузел уводу тэксту не запампаваны тэкставыя файлы",
"noVsdUploaded": "У вузел уводу VSD не запампаваны файлы Visio",
"noWpdUploaded": "У вузел уводу WPD не запампаваны файлы WPD",
"noWpsUploaded": "У вузел уводу WPS не запампаваны файлы WPS",
"noXmlUploaded": "У вузел уводу XML не запампаваны файлы XML",
"noXpsUploaded": "У вузел уводу XPS не запампаваны файлы XPS",
"alternateMergeNeedsTwo": "Паслядоўнаму зліццю патрэбна як мінімум два PDF, падключаныя да ўваходу",
"cropMarginsExceed": "Палі абрэзкі перавышаюць памеры старонкі. Паменшыце значэнні.",
"digitalSignNoCertificate": "У вузле лічбавага подпісу не загружаны сертыфікат",
"encryptUserPasswordRequired": "Для шыфравання патрэбны карыстальніцкі пароль",
"extractImagesNoneFound": "У падключаных PDF не знойдзена выяў",
"invertColorsFailedReadImage": "Не атрымалася прачытаць даныя выявы",
"extractImagesNoneFound": "У падключаных PDF не знойдзена відарысаў",
"invertColorsFailedReadImage": "Не атрымалася прачытаць даныя відарыса",
"overlayRequiresPdf": "Вузел накладання патрабуе ўвод PDF для накладання.",
"pdfToCsvNoTables": "У PDF не знойдзена табліц",
"pdfToXlsxNoTables": "У {{file}} не знойдзена табліц",
"posterizeFailedTileCanvas": "Не атрымалася атрымаць кантэкст палатна пліткі",
"redactNoText": "Рэдагаванне: не вызначаны тэкст для рэдагавання",
"redactNoText": "Зацямненне: не вызначаны тэкст для зацямнення",
"removeBlankPagesAllBlank": "Усе старонкі пустыя",
"svgFailedToConvert": "Не атрымалася канвертаваць SVG",
"svgFailedToLoad": "Не атрымалася загрузіць SVG",
"timestampFailed": "Не атрымалася паставіць метку часу праз TSA {{tsa}}: {{message}}",
"noOutputNodes": "Не знойдзена вузлоў вываду. Дадайце вузел Download, каб завяршыць ваш працоўны працэс.",
"circularDependency": "У працоўным працэсе выяўлена кругавая залежнасць. Выдаліце ўсе цыклы паміж вузламі.",
"encryptOrdering": "Вузел шыфравання падае даныя ў \"{{target}}\", што можа збой на зашыфраваных даных. Перамясціце шыфраванне непасрэдна перад вузлом вываду.",
"invalidWorkflowFile": "Несапраўдны файл працоўнага працэсу: адсутнічае масіў вузлоў або злучэнняў.",
"storageQuotaExceeded": "Не атрымалася захаваць працоўны працэс: перавышана квота сховішча. Паспрабуйце выдаліць старыя шаблоны.",
"failedToImport": "Не атрымалася імпартаваць працоўны працэс: {{message}}"
"timestampFailed": "Не атрымалася паставіць пазнаку часу праз TSA {{tsa}}: {{message}}",
"noOutputNodes": "Не знойдзена вузлоў вываду. Дадайце вузел «Спампаваць», каб завяршыць ваш рабочы працэс.",
"circularDependency": "У рабочым працэсе выяўлена кругавая залежнасць. Выдаліце ўсе цыклы паміж вузламі.",
"encryptOrdering": "Вузел шыфравання падае даныя ў «{{target}}», што можа даць збой на зашыфраваных даных. Перамясціце шыфраванне непасрэдна перад вузлом вываду.",
"invalidWorkflowFile": "Памылковы файл рабочага працэсу: адсутнічае масіў вузлоў або злучэнняў.",
"storageQuotaExceeded": "Не атрымалася захаваць рабочы працэс: перавышана квота сховішча. Паспрабуйце выдаліць старыя шаблоны.",
"failedToImport": "Не атрымалася імпартаваць рабочы працэс: {{message}}"
}
},
"wasmSettings": {
"title": "Налады пашыраных функцый",
"description": "Налаштуйте зовнішні модулі обробки для увімкнення розширених функцій PDF. Ці модулі необов'язкові і ліцензуються окремо.",
"description": "Сканфігуруйце знешнія модулі апрацоўкі для ўключэння пашыраных магчымасцей PDF. Гэтыя модулі неабавязковыя і ліцэнзуюцца асобна.",
"status": {
"testing": "Перевірка...",
"customOverride": "Користувацьке перевизначення",
"preConfigured": "Попередньо налаштовано",
"notConfigured": "Не налаштовано"
"testing": "Праверка…",
"customOverride": "Уласная замена",
"preConfigured": "Папярэдне сканфігураваны",
"notConfigured": "Не сканфігураваны"
},
"preconfiguredTitle": "Попередньо налаштовано і готово до використання.",
"preconfiguredDescription": "Розширені модулі обробки автоматично завантажуються з CDN. Ви можете перевизначити URL нижче, якщо потрібно використовувати власне джерело (наприклад, для air-gapped або самостійно розміщених розгортань).",
"usingDefault": "Використовується за замовчуванням: {{url}}",
"pymupdfSubtitle": "Рушій обробки документів",
"pymupdfFeatures": "Вмикає: PDF у текст, Markdown, SVG, DOCX, Excel • Витягти зображення/таблиці • Конвертацію формату",
"preconfiguredTitle": "Папярэдне сканфігураваны і гатовы да выкарыстання",
"preconfiguredDescription": "Пашыраныя модулі апрацоўкі аўтаматычна загружаюцца з CDN. Вы можаце перавызначыць URL ніжэй, калі вам трэба выкарыстоўваць уласную крыніцу (напрыклад, для разгортванняў у ізаляваным асяроддзі або з уласным хостынгам).",
"usingDefault": "Выкарыстоўваецца прадвызначанае значэнне: {{url}}",
"pymupdfSubtitle": "Рухавік апрацоўкі дакументаў",
"pymupdfFeatures": "Уключае: канвертаванне PDF у тэкст, Markdown, SVG, DOCX, Excel • выманне відарысаў і табліц • канвертаванне фарматаў",
"testButton": "Праверыць",
"recommendedLabel": "Рекомендовано:",
"copyTitle": "Копіювати в буфер обміну",
"ghostscriptSubtitle": "Рушій конвертації PDF/A",
"ghostscriptFeatures": "Вмикає: Конвертацію PDF/A-1b, PDF/A-2b, PDF/A-3b • Шрифт у контур",
"cpdfSubtitle": "Рушій закладок і метаданих",
"cpdfFeatures": "Вмикає: Розділити за закладками • Редагувати закладки • Метадані PDF",
"recommendedLabel": "Рэкамендавана:",
"copyTitle": "Капіраваць у буфер абмену",
"ghostscriptSubtitle": "Рухавік канвертавання PDF/A",
"ghostscriptFeatures": "Уключае: канвертаванне ў PDF/A-1b, PDF/A-2b, PDF/A-3b • канвертаванне шрыфтоў у контуры",
"cpdfSubtitle": "Рухавік закладак і метаданых",
"cpdfFeatures": "Уключае: раздзяленне паводле закладак • рэдагаванне закладак • метаданыя PDF",
"saveConfiguration": "Захаваць канфігурацыю",
"savingConfiguration": "Збереження конфігурації...",
"savingConfiguration": "Захаванне канфігурацыі...",
"savedTitle": "Захавана",
"savedMessage": "Канфігурацыя паспяхова захавана!",
"errorTitle": "Памылка",
"failedSave": "Не вдалося зберегти конфігурацію: {{message}}",
"emptyUrlTitle": "Порожній URL",
"emptyUrlMessage": "Введіть URL для перевірки.",
"testSuccessTitle": "Успіх",
"connectionSuccess": "Підключення до {{package}} успішне!",
"connectionFailedTitle": "Збій підключення",
"connectionFailedMessage": "Не вдалося підключитися до URL.",
"failedSave": "Не ўдалося захаваць канфігурацыю: {{message}}",
"emptyUrlTitle": "Пусты URL",
"emptyUrlMessage": "Увядзіце URL для праверкі.",
"testSuccessTitle": "Поспех",
"connectionSuccess": "Злучэнне з {{package}} паспяховае!",
"connectionFailedTitle": "Не ўдалося ўсталяваць злучэнне",
"connectionFailedMessage": "Не ўдалося злучыцца з URL.",
"resetDefaults": "Скінуць да стандартных",
"resetTitle": "Скід",
"resetWithDefaults": "Користувацькі перевизначення очищено. Активні попередньо налаштовані значення за замовчуванням.",
"resetNoDefaults": "Усі конфігурації та кешовані модулі очищено.",
"licenseTitle": "Повідомлення про ліцензію:",
"licenseDescription": "Зовнішні модулі (PyMuPDF, Ghostscript, CoherentPDF) ліцензовані під AGPL-3.0 або подібними copyleft-ліцензіями. Налаштовуючи та використовуючи ці модулі, ви погоджуєтеся з їхніми відповідними умовами ліцензії. BentoPDF сумісний з будь-якою реалізацією Ghostscript WASM і PyMuPDF WASM, що дотримується очікуваного інтерфейсу."
"resetWithDefaults": "Уласныя перавызначэнні ачышчаныя. Актываваныя прадвызначаныя значэнні канфігурацыі.",
"resetNoDefaults": "Усе канфігурацыі і кэшаваныя модулі ачышчаныя.",
"licenseTitle": "Звесткі пра ліцэнзію:",
"licenseDescription": "Знешнія модулі (PyMuPDF, Ghostscript, CoherentPDF) распаўсюджваюцца паводле AGPL-3.0 або падобных ліцэнзій з копілефтам. Канфігуруючы і выкарыстоўваючы гэтыя модулі, вы згаджаецеся з умовамі адпаведных ліцэнзій. BentoPDF сумяшчальны з любой рэалізацыяй Ghostscript WASM і PyMuPDF WASM, якая адпавядае чаканаму інтэрфейсу."
},
"pdfOverlay": {
"name": "Накладанне PDF",
@@ -1297,7 +1278,7 @@
"overlayOption": "Накладанне (зверху старонак)",
"underlayOption": "Падкладанне (за старонкамі)",
"pageRangeLabel": "Прымяніць да старонак (неабавязкова)",
"pageRangeHint": "Выкарыстоўвайце \"z\" для апошняй старонкі. Пакіньце пустым, каб прымяніць да ўсіх старонак.",
"pageRangeHint": "Выкарыстоўвайце «z» для апошняй старонкі. Пакіньце пустым, каб прымяніць да ўсіх старонак.",
"repeatLabel": "Паўтараць накладанне/падкладанне, калі базавы PDF даўжэйшы",
"processButton": "Прымяніць накладанне / падкладанне",
"howItWorksUploadTitle": "Запампуйце два PDF",
@@ -1309,8 +1290,16 @@
"faqDifferenceQuestion": "У чым розніца паміж накладаннем і падкладаннем?",
"faqDifferenceAnswer": "Накладанне размяшчае старонкі зверху базавага PDF (як вадзяны знак). Падкладанне размяшчае старонкі за базавым PDF (як фірмовы бланк або фон).",
"faqSinglePageQuestion": "Ці магу я выкарыстоўваць аднастаронкавы PDF як накладанне для ўсіх старонак?",
"faqSinglePageAnswer": "Так! Уключыце опцыю \"Паўтараць\" і старонкі накладання будуць паўтарацца на ўсіх старонках базавага файла. Аднастаронкавы вадзяны знак будзе прымяняцца да кожнай старонкі.",
"faqSinglePageAnswer": "Так! Уключыце опцыю «Паўтараць» і старонкі накладання будуць паўтарацца на ўсіх старонках базавага файла. Аднастаронкавы вадзяны знак будзе прымяняцца да кожнай старонкі.",
"faqPrivacyQuestion": "Ці з'яўляюцца мае файлы прыватнымі і бяспечнымі?",
"faqPrivacyAnswer": "Безумоўна! Уся апрацоўка адбываецца ў вашым браўзеры. Вашы файлы ніколі не пакідаюць вашу прыладу, забяспечваючы поўную прыватнасць."
},
"unlockPdf": {
"name": "Расшыфраваць PDF",
"subtitle": "Разблакіраваць PDF, выдаліўшы пароль."
},
"protectPdf": {
"name": "Зашыфраваць PDF",
"subtitle": "Заблакіраваць PDF, дадаўшы пароль."
}
}
+390
View File
@@ -0,0 +1,390 @@
{
"nav": {
"home": "Inici",
"about": "Quant a",
"contact": "Contacte",
"licensing": "Llicències",
"allTools": "Totes les eines",
"docs": "Documentació",
"openMainMenu": "Obre el menú principal",
"language": "Idioma",
"searchLanguage": "Cerca un idioma…",
"noLanguagesFound": "No s'ha trobat cap idioma"
},
"donation": {
"message": "T'agrada BentoPDF? Ajuda'ns a mantenir-lo gratuït i de codi obert!",
"button": "Fes una donació"
},
"hero": {
"title": "El",
"pdfToolkit": "conjunt d'eines PDF",
"builtForPrivacy": "pensat per protegir la privadesa",
"noSignups": "Sense registre",
"unlimitedUse": "Ús il·limitat",
"worksOffline": "Funciona sense connexió",
"startUsing": "Comença a utilitzar-lo"
},
"usedBy": {
"title": "Utilitzat per empreses i persones que treballen a"
},
"features": {
"title": "Per què triar",
"bentoPdf": "BentoPDF?",
"noSignup": {
"title": "Sense registre",
"description": "Comença immediatament, sense comptes ni correus electrònics."
},
"noUploads": {
"title": "Sense càrregues de fitxers",
"description": "100 % al navegador: els fitxers no surten mai del dispositiu."
},
"foreverFree": {
"title": "Gratuït per sempre",
"description": "Totes les eines, sense períodes de prova ni pagaments."
},
"noLimits": {
"title": "Sense límits",
"description": "Utilitza'l tant com vulguis, sense límits ocults."
},
"batchProcessing": {
"title": "Processament per lots",
"description": "Processa tants PDF com vulguis alhora."
},
"lightningFast": {
"title": "Extremadament ràpid",
"description": "Processa PDF a l'instant, sense esperes ni retards."
}
},
"tools": {
"title": "Comença amb les",
"toolsLabel": "Eines",
"subtitle": "Fes clic en una eina per obrir el selector de fitxers",
"searchPlaceholder": "Cerca una eina (p. ex., «dividir», «organitzar»...)",
"backToTools": "Torna a les eines",
"firstLoadNotice": "La primera càrrega pot trigar una mica mentre es descarrega el motor de conversió. Les següents seran instantànies."
},
"upload": {
"clickToSelect": "Fes clic per seleccionar un fitxer",
"orDragAndDrop": "o arrossega'l i deixa'l anar",
"pdfOrImages": "PDF o imatges",
"filesNeverLeave": "Els teus fitxers no surten mai del dispositiu.",
"addMore": "Afegeix més fitxers",
"clearAll": "Neteja-ho tot",
"clearFiles": "Elimina els fitxers",
"hints": {
"singlePdf": "Un únic fitxer PDF",
"pdfFile": "Fitxer PDF",
"multiplePdfs2": "Diversos fitxers PDF (com a mínim 2)",
"bmpImages": "Imatges BMP",
"oneOrMorePdfs": "Un o més fitxers PDF",
"pdfDocuments": "Documents PDF",
"oneOrMoreCsv": "Un o més fitxers CSV",
"multiplePdfsSupported": "S'admeten diversos fitxers PDF",
"singleOrMultiplePdfs": "S'admeten un o diversos fitxers PDF",
"singlePdfFile": "Un únic fitxer PDF",
"pdfWithForms": "Fitxer PDF amb camps de formulari",
"heicImages": "Imatges HEIC/HEIF",
"jpgImages": "Imatges JPG, JPEG, JP2 i JPX",
"pdfsOrImages": "PDF o imatges",
"oneOrMoreOdt": "Un o més fitxers ODT",
"singlePdfOnly": "Només un fitxer PDF",
"pdfFiles": "Fitxers PDF",
"multiplePdfs": "Diversos fitxers PDF",
"pngImages": "Imatges PNG",
"pdfFilesOneOrMore": "Fitxers PDF (un o més)",
"oneOrMoreRtf": "Un o més fitxers RTF",
"svgGraphics": "Gràfics SVG",
"tiffImages": "Imatges TIFF",
"webpImages": "Imatges WebP"
}
},
"howItWorks": {
"title": "Com funciona",
"step1Title": "Puja el fitxer",
"step1": "Fes clic o arrossega i deixa anar el fitxer per començar",
"step2Title": "Processa",
"step2": "Fes clic al botó de processament per començar",
"step3Title": "Descarrega",
"step3": "Desa el fitxer processat a l'instant"
},
"relatedTools": {
"title": "Eines PDF relacionades"
},
"loader": {
"processing": "S'està processant..."
},
"alert": {
"title": "Avís",
"ok": "D'acord"
},
"preview": {
"title": "Previsualització del document",
"downloadAsPdf": "Descarrega com a PDF",
"close": "Tanca"
},
"settings": {
"title": "Configuració",
"shortcuts": "Dreceres de teclat",
"preferences": "Preferències",
"displayPreferences": "Preferències de visualització",
"searchShortcuts": "Cerca dreceres...",
"shortcutsInfo": "Mantén premudes les tecles per definir una drecera. Els canvis es desen automàticament.",
"shortcutsWarning": "⚠️ Evita les dreceres habituals del navegador (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N, etc.), perquè poden no funcionar correctament.",
"import": "Importa",
"export": "Exporta",
"resetToDefaults": "Restableix els valors predeterminats",
"fullWidthMode": "Mode d'amplada completa",
"fullWidthDescription": "Utilitza tota l'amplada de la pantalla per a totes les eines en lloc d'un contenidor centrat",
"compactMode": "Mode compacte",
"compactModeDescription": "Mostra les eines en una llista compacta en lloc de targetes",
"advancedSettings": "Configuració avançada",
"advancedSettingsDescription": "Configura els mòduls de processament externs (PyMuPDF, Ghostscript, CoherentPDF)",
"settingsAutoSaved": "La configuració es desa automàticament",
"clickToSet": "Fes clic per definir-la",
"pressKeys": "Prem les tecles...",
"warnings": {
"alreadyInUse": "La drecera ja s'utilitza",
"assignedTo": "ja està assignada a:",
"chooseDifferent": "Tria una altra drecera.",
"reserved": "Avís de drecera reservada",
"commonlyUsed": "s'utilitza habitualment per a:",
"unreliable": "Aquesta drecera pot no funcionar correctament o pot entrar en conflicte amb el navegador o el sistema.",
"useAnyway": "La vols utilitzar igualment?",
"resetTitle": "Restableix les dreceres",
"resetMessage": "Segur que vols restablir totes les dreceres als valors predeterminats?<br><br>Aquesta acció no es pot desfer.",
"importSuccessTitle": "Importació correcta",
"importSuccessMessage": "Les dreceres s'han importat correctament!",
"importFailTitle": "Error d'importació",
"importFailMessage": "No s'han pogut importar les dreceres. El format del fitxer no és vàlid."
}
},
"warning": {
"title": "Advertiment",
"cancel": "Cancel·la",
"proceed": "Continua"
},
"compliance": {
"title": "Les dades no surten mai del dispositiu",
"weKeep": "Mantenim",
"yourInfoSafe": "la teva informació segura",
"byFollowingStandards": "seguint les normes internacionals de seguretat.",
"processingLocal": "Tot el processament es fa localment al teu dispositiu.",
"gdpr": {
"title": "Compliment del RGPD",
"description": "Protegeix les dades personals i la privadesa de les persones a la Unió Europea."
},
"ccpa": {
"title": "Compliment de la CCPA",
"description": "Reconeix drets als residents de Califòrnia sobre la recopilació, l'ús i la compartició de la seva informació personal."
},
"hipaa": {
"title": "Compliment de la HIPAA",
"description": "Estableix garanties per tractar informació sanitària sensible al sistema sanitari dels Estats Units."
}
},
"faq": {
"title": "Preguntes",
"questions": "freqüents",
"sectionTitle": "Preguntes freqüents",
"isFree": {
"question": "BentoPDF és realment gratuït?",
"answer": "Sí, del tot. Totes les eines de BentoPDF són 100 % gratuïtes, sense límits de fitxers, registres ni marques d'aigua. Creiem que tothom hauria de tenir accés a eines PDF senzilles i potents sense haver de pagar."
},
"areFilesSecure": {
"question": "Els meus fitxers són segurs? On es processen?",
"answer": "Els teus fitxers es mantenen tan segurs com és possible perquè no surten mai de l'ordinador. Tot el processament es fa directament al navegador web (al dispositiu). No enviem mai els fitxers a cap servidor, de manera que mantens la privadesa i el control dels documents."
},
"platforms": {
"question": "Funciona a Mac, Windows i dispositius mòbils?",
"answer": "Sí! Com que BentoPDF funciona íntegrament al navegador, és compatible amb qualsevol sistema operatiu que tingui un navegador modern, com ara Windows, macOS, Linux, iOS i Android."
},
"gdprCompliant": {
"question": "BentoPDF compleix el RGPD?",
"answer": "Sí. BentoPDF compleix plenament el RGPD. Com que els fitxers es processen localment al navegador i mai no els recopilem ni els transmetem a cap servidor, no tenim accés a les teves dades. Això garanteix que sempre mantens el control dels documents."
},
"dataStorage": {
"question": "Emmagatzemeu o feu seguiment dels meus fitxers?",
"answer": "No. Mai no desem, seguim ni registrem els teus fitxers. Tot el que fas a BentoPDF té lloc a la memòria del navegador i desapareix quan tanques la pàgina. No hi ha càrregues de fitxers, historials ni servidors implicats."
},
"different": {
"question": "Què diferencia BentoPDF d'altres eines PDF?",
"answer": "La majoria d'eines PDF envien els fitxers a un servidor per processar-los. BentoPDF no ho fa mai. Utilitzem tecnologia web moderna i segura per processar els fitxers directament al navegador. Això permet més rapidesa, més privadesa i més tranquil·litat."
},
"browserBased": {
"question": "Com protegeix les meves dades el processament al navegador?",
"answer": "Com que funciona íntegrament al navegador, BentoPDF garanteix que els fitxers no surten mai del dispositiu. Això elimina els riscos de pirateig de servidors, filtracions de dades o accessos no autoritzats. Els teus fitxers sempre són teus."
},
"analytics": {
"question": "Utilitzeu galetes o eines d'analítica per fer-me seguiment?",
"answer": "No. BentoPDF no et fa cap seguiment. No utilitzem galetes, analítica ni scripts de seguiment, ni tan sols al web públic bentopdf.com. No sabem mai qui ets ni què fas amb les eines."
}
},
"testimonials": {
"title": "Què diuen els nostres",
"users": "usuaris",
"say": "sobre nosaltres"
},
"support": {
"title": "T'agrada la meva feina?",
"description": "BentoPDF és un projecte fet amb passió per oferir a tothom un conjunt d'eines PDF gratuït, privat i potent. Si et resulta útil, planteja't donar suport al seu desenvolupament. Cada cafè ajuda!",
"buyMeCoffee": "Convida'm a un cafè"
},
"footer": {
"copyright": "© 2026 BentoPDF. Tots els drets reservats.",
"version": "Versió",
"company": "Empresa",
"aboutUs": "Sobre nosaltres",
"faqLink": "Preguntes freqüents",
"contactUs": "Contacta amb nosaltres",
"legal": "Informació legal",
"termsAndConditions": "Termes i condicions",
"privacyPolicy": "Política de privadesa",
"followUs": "Segueix-nos",
"privacyShort": "Privadesa",
"termsShort": "Condicions"
},
"merge": {
"title": "Fusiona PDF",
"description": "Combina fitxers sencers o selecciona pàgines concretes per fusionar-les en un document nou.",
"fileMode": "Mode de fitxers",
"pageMode": "Mode de pàgines",
"howItWorks": "Com funciona:",
"fileModeInstructions": [
"Fes clic a la icona i arrossega-la per canviar l'ordre dels fitxers.",
"Al camp «Pàgines» de cada fitxer, pots indicar intervals (p. ex., «1-3, 5») per fusionar només aquestes pàgines.",
"Deixa el camp «Pàgines» buit per incloure totes les pàgines del fitxer."
],
"pageModeInstructions": [
"A continuació es mostren totes les pàgines dels PDF que has pujat.",
"Arrossega i deixa anar les miniatures de cada pàgina per establir l'ordre exacte del fitxer nou."
],
"mergePdfs": "Fusiona PDF"
},
"common": {
"page": "Pàgina",
"pages": "Pàgines",
"of": "de",
"download": "Descarrega",
"cancel": "Cancel·la",
"save": "Desa",
"delete": "Suprimeix",
"edit": "Edita",
"add": "Afegeix",
"remove": "Elimina",
"loading": "S'està carregant...",
"loadingPageCount": "S'estan carregant les pàgines...",
"error": "Error",
"success": "Correcte",
"file": "Fitxer",
"files": "Fitxers",
"close": "Tanca",
"convert": "Converteix",
"unknownError": "Error desconegut"
},
"about": {
"hero": {
"title": "Les eines PDF han de ser",
"subtitle": "ràpides, privades i gratuïtes.",
"noCompromises": "Sense concessions."
},
"mission": {
"title": "La nostra",
"titleDim": "missió",
"description": "Oferir el conjunt d'eines PDF més complet, respectuós amb la privadesa i que no exigeixi cap pagament. Creiem que les eines essencials per treballar amb documents han de ser accessibles per a tothom, arreu i sense barreres."
},
"philosophy": {
"label": "La nostra filosofia fonamental",
"title": "La privadesa, primer. Sempre.",
"description": "Totes les eines de BentoPDF funcionen localment al navegador. Els fitxers no es pugen mai a cap servidor, ningú més no veu els documents i no es fa seguiment de la teva activitat."
},
"whyBentopdf": {
"title": "Per què",
"speed": {
"title": "Pensat per ser ràpid",
"description": "No cal pujar ni descarregar fitxers al servidor. Els fitxers es processen al navegador mitjançant WebAssembly, sense haver d'esperar cap servidor."
},
"free": {
"title": "Ús gratuït",
"description": "Totes les eines són gratuïtes, sense proves, subscripcions ni marques d'aigua. El desenvolupament es finança amb llicències comercials."
},
"noAccount": {
"title": "Sense compte",
"description": "Obre qualsevol eina i comença de seguida. Sense correu electrònic, contrasenya ni dades personals."
},
"openSource": {
"title": "Codi obert",
"description": "El codi és públic a GitHub amb llicència AGPL-3.0, perquè puguis comprovar com es tracten els fitxers. Es basa en projectes de codi obert com PDF.js, pdf-lib, qpdf i LibreOffice."
}
},
"cta": {
"title": "Ja ho tens tot a punt per començar?",
"description": "Uneix-te als milers d'usuaris que confien en BentoPDF per treballar amb documents cada dia. Descobreix com la privadesa i el rendiment marquen la diferència.",
"button": "Explora totes les eines"
}
},
"contact": {
"title": "Contacta amb nosaltres",
"subtitle": "Ens agradarà saber de tu. Si tens una pregunta, un comentari o una proposta de funcionalitat, no dubtis a escriure'ns.",
"email": "Pots contactar directament amb nosaltres per correu electrònic a:"
},
"licensing": {
"title": "Llicències per a",
"subtitle": "Tria la llicència que s'adapti a les teves necessitats."
},
"multiTool": {
"uploadPdfs": "Puja fitxers PDF",
"upload": "Puja",
"addBlankPage": "Afegeix una pàgina en blanc",
"edit": "Edita:",
"undo": "Desfés",
"redo": "Refés",
"reset": "Restableix",
"selection": "Selecció:",
"selectAll": "Selecciona-ho tot",
"deselectAll": "Desselecciona-ho tot",
"rotate": "Gira:",
"rotateLeft": "Esquerra",
"rotateRight": "Dreta",
"transform": "Transforma:",
"duplicate": "Duplica",
"split": "Divideix",
"clear": "Neteja:",
"delete": "Suprimeix",
"download": "Descarrega:",
"downloadSelected": "Descarrega la selecció",
"exportPdf": "Exporta el PDF",
"uploadPdfFiles": "Selecciona fitxers PDF o d'imatge",
"dragAndDrop": "Arrossega i deixa anar aquí fitxers PDF o imatges, o fes clic per seleccionar-los",
"selectFiles": "Selecciona fitxers",
"dropToAdd": "Deixa anar fitxers PDF o d'imatge per afegir-los",
"convertingImages": "S'estan convertint les imatges a PDF...",
"failedToConvertImages": "No s'han pogut convertir les imatges a PDF.",
"renderingPages": "S'estan representant les pàgines...",
"actions": {
"duplicatePage": "Duplica aquesta pàgina",
"deletePage": "Suprimeix aquesta pàgina",
"insertPdf": "Insereix un PDF després d'aquesta pàgina",
"toggleSplit": "Activa o desactiva la divisió després d'aquesta pàgina"
},
"pleaseWait": "Espera, si us plau",
"pagesRendering": "Encara s'estan representant les pàgines. Espera, si us plau...",
"noPagesSelected": "No hi ha pàgines seleccionades",
"selectOnePage": "Selecciona com a mínim una pàgina per descarregar-la.",
"noPages": "No hi ha pàgines",
"noPagesToExport": "No hi ha pàgines per exportar.",
"renderingTitle": "S'estan generant les previsualitzacions de les pàgines",
"errorRendering": "No s'han pogut generar les miniatures de les pàgines",
"error": "Error",
"failedToLoad": "No s'ha pogut carregar"
},
"simpleMode": {
"title": "Eines PDF",
"subtitle": "Selecciona una eina per començar"
},
"disabledTool": {
"title": "Eina no disponible",
"heading": "Aquesta eina s'ha desactivat",
"message": "Aquesta eina no està disponible en aquesta instal·lació. Contacta amb l'administrador per obtenir més informació.",
"backHome": "Torna a l'inici"
}
}
File diff suppressed because it is too large. Load diff
+5 -2
View File
@@ -239,7 +239,9 @@
"legal": "Juridisk",
"termsAndConditions": "Terms and Conditions",
"privacyPolicy": "Privacy Policy",
"followUs": "Følg os"
"followUs": "Følg os",
"privacyShort": "Privatliv",
"termsShort": "Vilkår"
},
"merge": {
"title": "Flet PDF'er",
@@ -286,7 +288,8 @@
"noCompromises": "Ingen kompromiser."
},
"mission": {
"title": "Vores mission",
"title": "Vores",
"titleDim": "mission",
"description": "At give den mest komplette PDF-værktøjskasse uden betaling og med fuldt fokus på privatliv."
},
"philosophy": {
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "Komprimér PDF",
"subtitle": "Reducer filstørrelsen på din PDF.",
"algorithmLabel": "Komprimeringsalgoritme",
"condense": "Kondenser (anbefalet)",
"photon": "Photon (til billedtunge PDF’er)",
"condenseInfo": "Kondenser bruger avanceret komprimering: fjerner overflødigt indhold, optimerer billeder, udvælger skrifttyper. Bedst til de fleste PDF’er.",
"photonInfo": "Photon konverterer sider til billeder. Bruges til billedtunge eller scannede PDF’er.",
"photonWarning": "Advarsel: Tekst bliver ikke valgbar, og links holder op med at virke.",
"levelLabel": "Komprimeringsniveau",
"light": "Let (bevar kvalitet)",
"balanced": "Balanceret (anbefalet)",
"aggressive": "Aggressiv (mindre filer)",
"extreme": "Ekstrem (maksimal komprimering)",
"grayscale": "Konverter til gråtoner",
"grayscaleHint": "Reducerer filstørrelsen ved at fjerne farveinformation",
"customSettings": "Brugerdefinerede indstillinger",
"customSettingsHint": "Finjustér komprimeringsparametre:",
"outputQuality": "Outputkvalitet",
"resizeImagesTo": "Skalér billeder til",
"onlyProcessAbove": "Behandl kun over",
"removeMetadata": "Fjern metadata",
"subsetFonts": "Delvis skrifttypeindlæsning (fjern ubrugte tegn)",
"removeThumbnails": "Fjern indlejrede miniaturer",
"compressButton": "Komprimér PDF"
"subtitle": "Reducer filstørrelsen på din PDF."
},
"pdfEditor": {
"name": "PDF-editor",
@@ -60,6 +38,8 @@
"subtitle": "Klik på et hvilket som helst afsnit, og redigér det direkte med live-ombrydning, skrifttyper og formatering.",
"saved": "PDF blev gemt! ({{size}} KB)",
"failedToLoad": "PDF-teksteditoren kunne ikke indlæses.",
"loadingFonts": "Indlæser skrifttyper...",
"fontsUnavailable": "En skrifttype, der er nødvendig for nogle tegn, kunne ikke downloades. Tjek din forbindelse, og prøv igen, ellers vises disse tegn muligvis ikke korrekt i den gemte PDF.",
"howToUpload": "Upload PDF",
"howToClick": "Klik på et afsnit",
"howToRestyle": "Giv alt ny stil",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "Ja! Aktivér \"Gentag\"-indstillingen, og dine overlejringssider vil gentage sig på alle basis-sider. Et enkeltsidigt vandmærke vil blive anvendt på hver side.",
"faqPrivacyQuestion": "Er mine filer private og sikre?",
"faqPrivacyAnswer": "Absolut! Al behandling sker i din browser. Dine filer forlader aldrig din enhed, hvilket sikrer fuldstændig privatliv."
},
"unlockPdf": {
"name": "Dekryptér PDF",
"subtitle": "Fjern adgangskodebeskyttelse."
},
"protectPdf": {
"name": "Kryptér PDF",
"subtitle": "Lås din PDF med en adgangskode."
}
}
+5 -2
View File
@@ -239,7 +239,9 @@
"legal": "Rechtliches",
"termsAndConditions": "Nutzungsbedingungen",
"privacyPolicy": "Datenschutzrichtlinie",
"followUs": "Folge uns"
"followUs": "Folge uns",
"privacyShort": "Datenschutz",
"termsShort": "AGB"
},
"merge": {
"title": "PDFs zusammenführen",
@@ -286,7 +288,8 @@
"noCompromises": "Ohne Kompromisse."
},
"mission": {
"title": "Unsere Mission",
"title": "Unsere",
"titleDim": "Mission",
"description": "Die umfassendste PDF-Toolbox bereitzustellen, die deine Privatsphäre respektiert und niemals Geld kostet. Wir glauben, dass wichtige Dokumentenwerkzeuge für jede*n, überall und ohne Barrieren zugänglich sein sollten."
},
"philosophy": {
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "PDF komprimieren",
"subtitle": "Die Dateigröße Ihrer PDF reduzieren.",
"algorithmLabel": "Komprimierungsalgorithmus",
"condense": "Condense (Empfohlen)",
"photon": "Photon (Für bildlastige PDFs)",
"condenseInfo": "Condense nutzt fortschrittliche Komprimierung: entfernt unnötige Daten, optimiert Bilder, reduziert Schriftarten. Optimal für die meisten PDFs.",
"photonInfo": "Photon wandelt Seiten in Bilder um. Für bildlastige/gescannte PDFs.",
"photonWarning": "Warnung: Text wird nicht mehr auswählbar und Links funktionieren nicht mehr.",
"levelLabel": "Komprimierungsstufe",
"light": "Leicht (Qualität erhalten)",
"balanced": "Ausgewogen (Empfohlen)",
"aggressive": "Aggressiv (Kleinere Dateien)",
"extreme": "Extrem (Maximale Komprimierung)",
"grayscale": "In Graustufen umwandeln",
"grayscaleHint": "Reduziert Dateigröße durch Entfernen von Farbinformationen",
"customSettings": "Erweiterte Einstellungen",
"customSettingsHint": "Komprimierungsparameter anpassen:",
"outputQuality": "Ausgabequalität",
"resizeImagesTo": "Bilder anpassen auf",
"onlyProcessAbove": "Nur verarbeiten über",
"removeMetadata": "Metadaten entfernen",
"subsetFonts": "Schriftarten optimieren (ungenutzte Zeichen entfernen)",
"removeThumbnails": "Eingebettete Miniaturansichten entfernen",
"compressButton": "PDF komprimieren"
"subtitle": "Die Dateigröße Ihrer PDF reduzieren."
},
"pdfEditor": {
"name": "PDF-Editor",
@@ -60,6 +38,8 @@
"subtitle": "Auf einen beliebigen Absatz klicken und ihn direkt bearbeiten – mit Live-Umbruch, Schriftarten und Formatierung.",
"saved": "PDF erfolgreich gespeichert! ({{size}} KB)",
"failedToLoad": "Der PDF-Texteditor konnte nicht geladen werden.",
"loadingFonts": "Schriftarten werden geladen...",
"fontsUnavailable": "Eine für einige Zeichen benötigte Schriftart konnte nicht heruntergeladen werden. Prüfen Sie Ihre Verbindung und versuchen Sie es erneut, sonst werden diese Zeichen im gespeicherten PDF möglicherweise nicht korrekt angezeigt.",
"howToUpload": "PDF hochladen",
"howToClick": "Absatz anklicken",
"howToRestyle": "Alles umgestalten",
@@ -1311,5 +1291,13 @@
"faqSinglePageAnswer": "Ja! Aktivieren Sie die Option \"Wiederholen\" und Ihre Überlagerungsseiten werden auf allen Basisseiten wiederholt. Ein einseitiges Wasserzeichen wird auf jeder Seite angewendet.",
"faqPrivacyQuestion": "Sind meine Dateien privat und sicher?",
"faqPrivacyAnswer": "Absolut! Die gesamte Verarbeitung findet in Ihrem Browser statt. Ihre Dateien verlassen niemals Ihr Gerät, was vollständige Privatsphäre gewährleistet."
},
"unlockPdf": {
"name": "PDF entschlüsseln",
"subtitle": "PDF durch Entfernen des Passwortschutzes entsperren."
},
"protectPdf": {
"name": "PDF verschlüsseln",
"subtitle": "Ihre PDF durch Hinzufügen eines Passworts sperren."
}
}
+15 -12
View File
@@ -212,7 +212,7 @@
},
"browserBased": {
"question": "How does browser-based processing keep me safe?",
"answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours—always."
"answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours, always."
},
"analytics": {
"question": "Do you use cookies or analytics to track me?",
@@ -239,7 +239,9 @@
"legal": "Legal",
"termsAndConditions": "Terms and Conditions",
"privacyPolicy": "Privacy Policy",
"followUs": "Follow Us"
"followUs": "Follow Us",
"privacyShort": "Privacy",
"termsShort": "Terms"
},
"merge": {
"title": "Merge PDFs",
@@ -281,41 +283,42 @@
},
"about": {
"hero": {
"title": "We believe PDF tools should be",
"title": "PDF tools should be",
"subtitle": "fast, private, and free.",
"noCompromises": "No compromises."
},
"mission": {
"title": "Our Mission",
"title": "Our",
"titleDim": "Mission",
"description": "To provide the most comprehensive PDF toolbox that respects your privacy and never asks for payment. We believe essential document tools should be accessible to everyone, everywhere, without barriers."
},
"philosophy": {
"label": "Our Core Philosophy",
"title": "Privacy First. Always.",
"description": "In an era where data is a commodity, we take a different approach. All processing for Bentopdf tools happens locally in your browser. This means your files never touch our servers, we never see your documents, and we don't track what you do. Your documents remain completely and unequivocally private. It's not just a feature; it's our foundation."
"description": "Every BentoPDF tool runs locally in your browser. Your files are never uploaded, nobody else sees your documents, and nothing tracks what you do."
},
"whyBentopdf": {
"title": "Why",
"speed": {
"title": "Built for Speed",
"description": "No waiting for uploads or downloads to a server. By processing files directly in your browser using modern web technologies like WebAssembly, we offer unparalleled speed for all our tools."
"description": "There's no upload or download step. Files are processed right in your browser using WebAssembly, so you're never waiting on a server."
},
"free": {
"title": "Completely Free",
"description": "No trials, no subscriptions, no hidden fees, and no \"premium\" features held hostage. We believe powerful PDF tools should be a public utility, not a profit center."
"title": "Free to Use",
"description": "Every tool is free, with no trials, no subscriptions and no watermarks. Development is funded by commercial licenses."
},
"noAccount": {
"title": "No Account Required",
"description": "Start using any tool immediately. We don't need your email, a password, or any personal information. Your workflow should be frictionless and anonymous."
"description": "Open any tool and start right away. No email, no password, no personal information."
},
"openSource": {
"title": "Open Source Spirit",
"description": "Built with transparency in mind. We leverage incredible open-source libraries like PDF-lib and PDF.js, and believe in the community-driven effort to make powerful tools accessible to everyone."
"title": "Open Source",
"description": "The code is public on GitHub under AGPL-3.0, so you can check exactly how your files are handled. It builds on open-source projects like PDF.js, pdf-lib, qpdf and LibreOffice."
}
},
"cta": {
"title": "Ready to get started?",
"description": "Join thousands of users who trust Bentopdf for their daily document needs. Experience the difference that privacy and performance can make.",
"description": "Join thousands of users who trust BentoPDF for their daily document needs. Experience the difference that privacy and performance can make.",
"button": "Explore All Tools"
}
},
+26 -24
View File
@@ -20,7 +20,21 @@
"subtitle": "Combine multiple PDFs into one file. Preserves Bookmarks.",
"retainPageLabels": "Keep original page labels from each file",
"retainPageLabelsHint": "Off (default): the merged PDF uses natural page numbering 1–N. On: each file's original page labels are preserved (may produce duplicate labels).",
"removeDuplicateFonts": "Remove duplicate fonts"
"removeDuplicateFonts": "Remove duplicate fonts",
"alert": {
"thumbnailError": "Failed to render page thumbnails",
"noSelection": "No files or pages selected to merge.",
"mergeSuccess": "PDFs merged successfully!",
"mergeFailed": "Failed to merge PDFs.",
"mergeError": "Failed to merge PDFs. Please check that all files are valid and not password-protected.",
"workerError": "An unexpected error occurred in the merge worker.",
"loadError": "Failed to load one or more PDF files"
},
"loader": {
"renderingPreviews": "Rendering page previews...",
"merging": "Merging PDFs...",
"loadingDocuments": "Loading PDF documents..."
}
},
"splitPdf": {
"name": "Split PDF",
@@ -28,29 +42,7 @@
},
"compressPdf": {
"name": "Compress PDF",
"subtitle": "Reduce the file size of your PDF.",
"algorithmLabel": "Compression Algorithm",
"condense": "Condense (Recommended)",
"photon": "Photon (For Photo-Heavy PDFs)",
"condenseInfo": "Condense uses advanced compression: removes dead-weight, optimizes images, subsets fonts. Best for most PDFs.",
"photonInfo": "Photon converts pages to images. Use for photo-heavy/scanned PDFs.",
"photonWarning": "Warning: Text will become non-selectable and links will stop working.",
"levelLabel": "Compression Level",
"light": "Light (Preserve Quality)",
"balanced": "Balanced (Recommended)",
"aggressive": "Aggressive (Smaller Files)",
"extreme": "Extreme (Maximum Compression)",
"grayscale": "Convert to Grayscale",
"grayscaleHint": "Reduces file size by removing color information",
"customSettings": "Custom Settings",
"customSettingsHint": "Fine-tune compression parameters:",
"outputQuality": "Output Quality",
"resizeImagesTo": "Resize Images To",
"onlyProcessAbove": "Only Process Above",
"removeMetadata": "Remove metadata",
"subsetFonts": "Subset fonts (remove unused glyphs)",
"removeThumbnails": "Remove embedded thumbnails",
"compressButton": "Compress PDF"
"subtitle": "Reduce the file size of your PDF."
},
"pdfEditor": {
"name": "PDF Editor",
@@ -61,6 +53,8 @@
"subtitle": "Click any paragraph and edit it in place with live reflow, fonts, and styling.",
"saved": "PDF saved successfully! ({{size}} KB)",
"failedToLoad": "Failed to load the PDF Text Editor.",
"loadingFonts": "Loading fonts...",
"fontsUnavailable": "A font needed for some characters could not be downloaded. Check your connection and try again, or those characters may not appear correctly in the saved PDF.",
"howToUpload": "Upload PDF",
"howToClick": "Click a Paragraph",
"howToRestyle": "Restyle Anything",
@@ -1313,5 +1307,13 @@
"faqSinglePageAnswer": "Yes! Enable the \"Loop\" option and your overlay PDF pages will repeat across all base pages. A single-page watermark will apply to every page.",
"faqPrivacyQuestion": "Are my files private and secure?",
"faqPrivacyAnswer": "Absolutely! All processing happens in your browser. Your files never leave your device, ensuring complete privacy."
},
"unlockPdf": {
"name": "Unlock PDF",
"subtitle": "Remove the password from a PDF so it opens freely. Requires the current password."
},
"protectPdf": {
"name": "Protect PDF",
"subtitle": "Password protect a PDF with strong AES encryption."
}
}
+7 -4
View File
@@ -239,7 +239,9 @@
"legal": "Legal",
"termsAndConditions": "Términos y Condiciones",
"privacyPolicy": "Política de Privacidad",
"followUs": "Síguenos"
"followUs": "Síguenos",
"privacyShort": "Privacidad",
"termsShort": "Términos"
},
"merge": {
"title": "Fusionar PDFs",
@@ -286,13 +288,14 @@
"noCompromises": "Sin compromisos."
},
"mission": {
"title": "Nuestra Misión",
"title": "Nuestra",
"titleDim": "Misión",
"description": "Proporcionar la caja de herramientas PDF más completa que respete tu privacidad y nunca pida pago. Creemos que las herramientas de documentos esenciales deben ser accesibles para todos, en todas partes, sin barreras."
},
"philosophy": {
"label": "Nuestra Filosofía Central",
"title": "Privacidad Primero. Siempre.",
"description": "En una era donde los datos son una mercancía, adoptamos un enfoque diferente. Todo el procesamiento de las herramientas de Bentopdf ocurre localmente en tu navegador. Esto significa que tus archivos nunca tocan nuestros servidores, nunca vemos tus documentos y no rastreamos lo que haces. Tus documentos permanecen completa e inequívocamente privados. No es solo una característica; es nuestra base."
"description": "En una era donde los datos son una mercancía, adoptamos un enfoque diferente. Todo el procesamiento de las herramientas de BentoPDF ocurre localmente en tu navegador. Esto significa que tus archivos nunca tocan nuestros servidores, nunca vemos tus documentos y no rastreamos lo que haces. Tus documentos permanecen completa e inequívocamente privados. No es solo una característica; es nuestra base."
},
"whyBentopdf": {
"title": "Por qué",
@@ -315,7 +318,7 @@
},
"cta": {
"title": "¿Listo para comenzar?",
"description": "Únete a miles de usuarios que confían en Bentopdf para sus necesidades diarias de documentos. Experimenta la diferencia que la privacidad y el rendimiento pueden hacer.",
"description": "Únete a miles de usuarios que confían en BentoPDF para sus necesidades diarias de documentos. Experimenta la diferencia que la privacidad y el rendimiento pueden hacer.",
"button": "Explorar Todas las Herramientas"
}
},
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "Comprimir PDF",
"subtitle": "Reduce el tamaño de archivo de tu PDF.",
"algorithmLabel": "Algoritmo de Compresión",
"condense": "Condensar (Recomendado)",
"photon": "Photon (Para PDFs con Muchas Fotos)",
"condenseInfo": "Condensar usa compresión avanzada: elimina peso muerto, optimiza imágenes, reduce fuentes. Mejor para la mayoría de PDFs.",
"photonInfo": "Photon convierte páginas en imágenes. Úsalo para PDFs con muchas fotos/escaneados.",
"photonWarning": "Advertencia: El texto dejará de ser seleccionable y los enlaces dejarán de funcionar.",
"levelLabel": "Nivel de Compresión",
"light": "Ligero (Preservar Calidad)",
"balanced": "Equilibrado (Recomendado)",
"aggressive": "Agresivo (Archivos Más Pequeños)",
"extreme": "Extremo (Compresión Máxima)",
"grayscale": "Convertir a Escala de Grises",
"grayscaleHint": "Reduce el tamaño del archivo eliminando información de color",
"customSettings": "Configuración Personalizada",
"customSettingsHint": "Ajusta los parámetros de compresión:",
"outputQuality": "Calidad de Salida",
"resizeImagesTo": "Redimensionar Imágenes a",
"onlyProcessAbove": "Solo Procesar Arriba de",
"removeMetadata": "Eliminar metadatos",
"subsetFonts": "Reducir fuentes (eliminar glifos no usados)",
"removeThumbnails": "Eliminar miniaturas incrustadas",
"compressButton": "Comprimir PDF"
"subtitle": "Reduce el tamaño de archivo de tu PDF."
},
"pdfEditor": {
"name": "Editor PDF",
@@ -60,6 +38,8 @@
"subtitle": "Haz clic en cualquier párrafo y edítalo directamente con reajuste de texto en vivo, fuentes y estilos.",
"saved": "¡PDF guardado correctamente! ({{size}} KB)",
"failedToLoad": "No se pudo cargar el editor de texto PDF.",
"loadingFonts": "Cargando fuentes...",
"fontsUnavailable": "No se pudo descargar una fuente necesaria para algunos caracteres. Comprueba tu conexión e inténtalo de nuevo; de lo contrario, es posible que esos caracteres no se vean correctamente en el PDF guardado.",
"howToUpload": "Subir PDF",
"howToClick": "Haz clic en un párrafo",
"howToRestyle": "Cambia el estilo de todo",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "¡Sí! Active la opción \"Repetir\" y las páginas de superposición se repetirán en todas las páginas base. Una marca de agua de una página se aplicará a cada página.",
"faqPrivacyQuestion": "¿Mis archivos son privados y seguros?",
"faqPrivacyAnswer": "¡Por supuesto! Todo el procesamiento ocurre en su navegador. Sus archivos nunca abandonan su dispositivo, garantizando total privacidad."
},
"unlockPdf": {
"name": "Descifrar PDF",
"subtitle": "Desbloquea PDF eliminando la protección por contraseña."
},
"protectPdf": {
"name": "Cifrar PDF",
"subtitle": "Bloquea tu PDF agregando una contraseña."
}
}
+6 -3
View File
@@ -222,7 +222,7 @@
"testimonials": {
"title": "Ce que disent",
"users": "nos utilisateurs",
"say": ""
"say": " "
},
"support": {
"title": "Vous aimez ce projet ?",
@@ -239,7 +239,9 @@
"legal": "Mentions légales",
"termsAndConditions": "Conditions générales",
"privacyPolicy": "Politique de confidentialité",
"followUs": "Nous suivre"
"followUs": "Nous suivre",
"privacyShort": "Confidentialité",
"termsShort": "Conditions"
},
"merge": {
"title": "Fusionner des PDF",
@@ -286,7 +288,8 @@
"noCompromises": "Sans compromis."
},
"mission": {
"title": "Notre mission",
"title": "Notre",
"titleDim": "mission",
"description": "Proposer la palette d’outils PDF la plus complète, tout en respectant votre vie privée et sans jamais demander de paiement. Les outils essentiels doivent être accessibles à tous, partout, sans barrières."
},
"philosophy": {
+27 -24
View File
@@ -19,7 +19,22 @@
"name": "Fusionner des PDF",
"subtitle": "Assembler plusieurs PDF en un seul fichier, tout en conservant les signets.",
"retainPageLabels": "Conserver les étiquettes de page d'origine de chaque fichier",
"retainPageLabelsHint": "Désactivé (par défaut) : le PDF fusionné utilise une numérotation naturelle 1–N. Activé : les étiquettes de page d'origine de chaque fichier sont conservées (peut produire des étiquettes en double)."
"retainPageLabelsHint": "Désactivé (par défaut) : le PDF fusionné utilise une numérotation naturelle 1–N. Activé : les étiquettes de page d'origine de chaque fichier sont conservées (peut produire des étiquettes en double).",
"removeDuplicateFonts": "Supprimer les polices en double",
"alert": {
"thumbnailError": "Échec du rendu des aperçus de pages",
"noSelection": "Aucun fichier ni page sélectionné pour la fusion.",
"mergeSuccess": "PDF fusionnés avec succès !",
"mergeFailed": "Échec de la fusion des PDF.",
"mergeError": "Échec de la fusion des PDF. Veuillez vérifier que tous les fichiers sont valides et non protégés par mot de passe.",
"workerError": "Une erreur inattendue s'est produite dans le worker de fusion.",
"loadError": "Impossible de charger un ou plusieurs fichiers PDF"
},
"loader": {
"renderingPreviews": "Génération des aperçus de pages…",
"merging": "Fusion des PDF…",
"loadingDocuments": "Chargement des documents PDF…"
}
},
"splitPdf": {
"name": "Scinder un PDF",
@@ -27,29 +42,7 @@
},
"compressPdf": {
"name": "Compresser un PDF",
"subtitle": "Réduire la taille du fichier PDF.",
"algorithmLabel": "Algorithme de compression",
"condense": "Condensé (recommandé)",
"photon": "Photon (pour les PDF riches en photos)",
"condenseInfo": "Condensé utilise une compression avancée : suppression du superflu, optimisation des images, sous-ensemble des polices. Idéal pour la plupart des PDF.",
"photonInfo": "Photon convertit les pages en images. À utiliser pour les PDF contenant beaucoup de photos ou scannés.",
"photonWarning": "Attention : le texte ne sera plus sélectionnable et les liens ne fonctionneront plus.",
"levelLabel": "Niveau de compression",
"light": "Léger (préserver la qualité)",
"balanced": "Équilibré (recommandé)",
"aggressive": "Agressif (fichiers plus petits)",
"extreme": "Extrême (compression maximale)",
"grayscale": "Convertir en niveaux de gris",
"grayscaleHint": "Réduit la taille du fichier en supprimant les informations de couleur",
"customSettings": "Paramètres personnalisés",
"customSettingsHint": "Affiner les paramètres de compression :",
"outputQuality": "Qualité de sortie",
"resizeImagesTo": "Redimensionner les images à",
"onlyProcessAbove": "Traiter uniquement au-dessus de",
"removeMetadata": "Supprimer les métadonnées",
"subsetFonts": "Sous-ensemble des polices (supprimer les glyphes inutilisés)",
"removeThumbnails": "Supprimer les vignettes intégrées",
"compressButton": "Compresser le PDF"
"subtitle": "Réduire la taille du fichier PDF."
},
"pdfEditor": {
"name": "Éditeur PDF",
@@ -60,6 +53,8 @@
"subtitle": "Cliquer sur un paragraphe et le modifier directement, avec remise en page instantanée, polices et styles.",
"saved": "PDF enregistré avec succès ! ({{size}} Ko)",
"failedToLoad": "Impossible de charger l'éditeur de texte PDF.",
"loadingFonts": "Chargement des polices...",
"fontsUnavailable": "Impossible de télécharger une police nécessaire à certains caractères. Vérifiez votre connexion et réessayez, sinon ces caractères risquent de ne pas s'afficher correctement dans le PDF enregistré.",
"howToUpload": "Importer un PDF",
"howToClick": "Cliquer sur un paragraphe",
"howToRestyle": "Tout restyler",
@@ -1312,5 +1307,13 @@
"faqSinglePageAnswer": "Oui ! Activez l'option \"Répéter\" et vos pages de superposition se répéteront sur toutes les pages de base. Un filigrane d'une seule page s'appliquera à chaque page.",
"faqPrivacyQuestion": "Mes fichiers sont-ils privés et sécurisés ?",
"faqPrivacyAnswer": "Absolument ! Tout le traitement se fait dans votre navigateur. Vos fichiers ne quittent jamais votre appareil, garantissant une confidentialité totale."
},
"unlockPdf": {
"name": "Déverrouiller un PDF",
"subtitle": "Supprimer la protection par mot de passe."
},
"protectPdf": {
"name": "Chiffrer un PDF",
"subtitle": "Protéger le PDF en ajoutant un mot de passe."
}
}
+8 -5
View File
@@ -212,7 +212,7 @@
},
"browserBased": {
"question": "Bagaimana pemrosesan berbasis browser menjaga keamanan saya?",
"answer": "Dengan berjalan sepenuhnya di dalam browser Anda, BentoPDF memastikan file Anda tidak pernah meninggalkan perangkat Anda. Ini menghilangkan risiko peretasan server, pelanggaran data, atau akses tidak sah. File Anda tetap milik Anda—selalu."
"answer": "Dengan berjalan sepenuhnya di dalam browser Anda, BentoPDF memastikan file Anda tidak pernah meninggalkan perangkat Anda. Ini menghilangkan risiko peretasan server, pelanggaran data, atau akses tidak sah. File Anda tetap milik Anda, selalu."
},
"analytics": {
"question": "Apakah Anda menggunakan cookie atau analitik untuk melacak saya?",
@@ -239,7 +239,9 @@
"legal": "Hukum",
"termsAndConditions": "Syarat dan Ketentuan",
"privacyPolicy": "Kebijakan Privasi",
"followUs": "Ikuti Kami"
"followUs": "Ikuti Kami",
"privacyShort": "Privasi",
"termsShort": "Ketentuan"
},
"merge": {
"title": "Gabung PDF",
@@ -286,13 +288,14 @@
"noCompromises": "Tidak ada kompromi."
},
"mission": {
"title": "Misi Kami",
"title": "Misi",
"titleDim": "Kami",
"description": "Untuk menyediakan toolbox PDF paling komprehensif yang menghormati privasi Anda dan tidak pernah meminta pembayaran. Kami percaya alat dokumen penting harus dapat diakses oleh semua orang, di mana saja, tanpa hambatan."
},
"philosophy": {
"label": "Filosofi Inti Kami",
"title": "Privasi Yang Utama. Selalu.",
"description": "Di era di mana data adalah komoditas, kami mengambil pendekatan berbeda. Semua pemrosesan untuk alat Bentopdf terjadi secara lokal di browser Anda. Ini berarti file Anda tidak pernah menyentuh server kami, kami tidak pernah melihat dokumen Anda, dan kami tidak melacak apa yang Anda lakukan. Dokumen Anda tetap utuh dan privat secara tegas. Ini bukan hanya fitur; ini adalah fondasi kami."
"description": "Di era di mana data adalah komoditas, kami mengambil pendekatan berbeda. Semua pemrosesan untuk alat BentoPDF terjadi secara lokal di browser Anda. Ini berarti file Anda tidak pernah menyentuh server kami, kami tidak pernah melihat dokumen Anda, dan kami tidak melacak apa yang Anda lakukan. Dokumen Anda tetap utuh dan privat secara tegas. Ini bukan hanya fitur; ini adalah fondasi kami."
},
"whyBentopdf": {
"title": "Mengapa",
@@ -315,7 +318,7 @@
},
"cta": {
"title": "Siap untuk memulai?",
"description": "Bergabunglah dengan ribuan pengguna yang percaya Bentopdf untuk kebutuhan dokumen harian mereka. Rasakan bedanya privasi dan performa yang ditawarkan.",
"description": "Bergabunglah dengan ribuan pengguna yang percaya BentoPDF untuk kebutuhan dokumen harian mereka. Rasakan bedanya privasi dan performa yang ditawarkan.",
"button": "Jelajahi Semua Alat"
}
},
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "Kompres PDF",
"subtitle": "Kurangi ukuran file PDF Anda.",
"algorithmLabel": "Algoritma Kompresi",
"condense": "Kondensasi (Direkomendasikan)",
"photon": "Photon (Untuk PDF yang penuh Foto)",
"condenseInfo": "Kondensasi menggunakan kompresi lanjutan: menghapus bobot mati, mengoptimalkan gambar, subset font. Terbaik untuk sebagian besar PDF.",
"photonInfo": "Photon mengkonversi halaman ke gambar. Gunakan untuk PDF penuh foto/terpindai.",
"photonWarning": "Peringatan: Teks akan menjadi tidak dapat dipilih dan tautan akan berhenti berfungsi.",
"levelLabel": "Tingkat Kompresi",
"light": "Ringan (Pertahankan Kualitas)",
"balanced": "Seimbang (Direkomendasikan)",
"aggressive": "Agresif (File Lebih Kecil)",
"extreme": "Ekstrem (Kompresi Maksimum)",
"grayscale": "Konversi ke Grayscale",
"grayscaleHint": "Mengurangi ukuran file dengan menghapus informasi warna",
"customSettings": "Pengaturan Kustom",
"customSettingsHint": "Sesuaikan parameter kompresi:",
"outputQuality": "Kualitas Output",
"resizeImagesTo": "Ubah Ukuran Gambar Ke",
"onlyProcessAbove": "Hanya Proses Di Atas",
"removeMetadata": "Hapus metadata",
"subsetFonts": "Subset font (hapus glyph yang tidak digunakan)",
"removeThumbnails": "Hapus thumbnail tersemat",
"compressButton": "Kompres PDF"
"subtitle": "Kurangi ukuran file PDF Anda."
},
"pdfEditor": {
"name": "Editor PDF",
@@ -60,6 +38,8 @@
"subtitle": "Klik paragraf mana pun dan edit langsung di tempat dengan penyusunan ulang teks secara langsung, font, dan gaya.",
"saved": "PDF berhasil disimpan! ({{size}} KB)",
"failedToLoad": "Gagal memuat Editor Teks PDF.",
"loadingFonts": "Memuat font...",
"fontsUnavailable": "Font yang diperlukan untuk beberapa karakter tidak dapat diunduh. Periksa koneksi Anda dan coba lagi, atau karakter tersebut mungkin tidak tampil dengan benar di PDF yang disimpan.",
"howToUpload": "Unggah PDF",
"howToClick": "Klik sebuah paragraf",
"howToRestyle": "Ubah gaya apa pun",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "Ya! Aktifkan opsi \"Ulangi\" dan halaman overlay Anda akan berulang di semua halaman dasar. Watermark satu halaman akan diterapkan ke setiap halaman.",
"faqPrivacyQuestion": "Apakah file saya pribadi dan aman?",
"faqPrivacyAnswer": "Tentu saja! Semua pemrosesan terjadi di browser Anda. File Anda tidak pernah meninggalkan perangkat Anda, memastikan privasi penuh."
},
"unlockPdf": {
"name": "Dekripsi PDF",
"subtitle": "Buka kunci PDF dengan menghapus perlindungan kata sandi."
},
"protectPdf": {
"name": "Enkripsi PDF",
"subtitle": "Kunci PDF Anda dengan menambahkan kata sandi."
}
}
+5 -2
View File
@@ -239,7 +239,9 @@
"legal": "Legale",
"termsAndConditions": "Termini e condizioni",
"privacyPolicy": "Informativa sulla privacy",
"followUs": "Seguici"
"followUs": "Seguici",
"privacyShort": "Privacy",
"termsShort": "Termini"
},
"merge": {
"title": "Unisci PDF",
@@ -286,7 +288,8 @@
"noCompromises": "Nessun compromesso."
},
"mission": {
"title": "La nostra missione",
"title": "La nostra",
"titleDim": "missione",
"description": "Fornire la cassetta degli attrezzi per PDF più completa che rispetti la tua privacy e non richieda mai pagamenti. Crediamo che gli strumenti essenziali per i documenti debbano essere accessibili a tutti, ovunque, senza barriere."
},
"philosophy": {
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "Comprimi PDF",
"subtitle": "Riduci le dimensioni del tuo PDF.",
"algorithmLabel": "Algoritmo di compressione",
"condense": "Condensa (Consigliato)",
"photon": "Photon (Per PDF con molte foto)",
"condenseInfo": "Condensa usa la compressione avanzata: rimuove peso inutile, ottimizza le immagini, riduce i font. Migliore per la maggior parte dei PDF.",
"photonInfo": "Photon converte le pagine in immagini. Usalo per PDF con molte foto o scannerizzati.",
"photonWarning": "Attenzione: il testo non sarà selezionabile e i link smetteranno di funzionare.",
"levelLabel": "Livello di compressione",
"light": "Leggero (Preserva qualità)",
"balanced": "Bilanciato (Consigliato)",
"aggressive": "Aggressivo (File più piccoli)",
"extreme": "Estremo (Compressione massima)",
"grayscale": "Converti in scala di grigi",
"grayscaleHint": "Riduce le dimensioni rimuovendo le informazioni di colore",
"customSettings": "Impostazioni personalizzate",
"customSettingsHint": "Affina i parametri di compressione:",
"outputQuality": "Qualità di output",
"resizeImagesTo": "Ridimensiona le immagini a",
"onlyProcessAbove": "Elabora solo sopra",
"removeMetadata": "Rimuovi metadati",
"subsetFonts": "Riduci i font (rimuovi glifi non usati)",
"removeThumbnails": "Rimuovi miniature incorporate",
"compressButton": "Comprimi PDF"
"subtitle": "Riduci le dimensioni del tuo PDF."
},
"pdfEditor": {
"name": "Editor PDF",
@@ -60,6 +38,8 @@
"subtitle": "Clicca su un paragrafo qualsiasi e modificalo direttamente con ricomposizione del testo in tempo reale, caratteri e stili.",
"saved": "PDF salvato correttamente! ({{size}} KB)",
"failedToLoad": "Impossibile caricare l'editor di testo PDF.",
"loadingFonts": "Caricamento dei font...",
"fontsUnavailable": "Impossibile scaricare un font necessario per alcuni caratteri. Controlla la connessione e riprova, altrimenti questi caratteri potrebbero non essere visualizzati correttamente nel PDF salvato.",
"howToUpload": "Carica PDF",
"howToClick": "Fai clic su un paragrafo",
"howToRestyle": "Ridefinisci lo stile",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "Sì! Attiva l'opzione \"Ripeti\" e le pagine di sovrapposizione si ripeteranno su tutte le pagine base. Una filigrana di una pagina verrà applicata a ogni pagina.",
"faqPrivacyQuestion": "I miei file sono privati e sicuri?",
"faqPrivacyAnswer": "Assolutamente! Tutta l'elaborazione avviene nel tuo browser. I tuoi file non lasciano mai il tuo dispositivo, garantendo la massima privacy."
},
"unlockPdf": {
"name": "Decrittografa PDF",
"subtitle": "Sblocca il PDF rimuovendo la protezione tramite password."
},
"protectPdf": {
"name": "Cripta PDF",
"subtitle": "Proteggi il tuo PDF aggiungendo una password."
}
}
+4 -1
View File
@@ -239,7 +239,9 @@
"legal": "法的情報",
"termsAndConditions": "利用規約",
"privacyPolicy": "プライバシーポリシー",
"followUs": "フォローする"
"followUs": "フォローする",
"privacyShort": "プライバシー",
"termsShort": "利用規約"
},
"merge": {
"title": "PDFの結合",
@@ -287,6 +289,7 @@
},
"mission": {
"title": "私たちの使命",
"titleDim": " ",
"description": "あなたのプライバシーを尊重し、決して支払いを要求しない、最も包括的なPDFツールボックスを提供すること。私たちは必須のドキュメントツールは誰でも、どこでも、障壁なくアクセスできるべきだと考えています。"
},
"philosophy": {
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "PDFの圧縮",
"subtitle": "PDFのファイルサイズを小さくします。",
"algorithmLabel": "圧縮アルゴリズム",
"condense": "コンデンス(推奨)",
"photon": "フォトン(写真を多く含むPDF用)",
"condenseInfo": "コンデンスは高度な圧縮技術を採用しています: 不要なデータを削除、画像を最適化しフォントをサブセット化します。ほとんどのPDFに最適です。",
"photonInfo": "フォトンはページを画像に変換します。写真が多いPDFやスキャンしたPDFにおすすめです。",
"photonWarning": "警告: テキストは選択できなくなり、リンクは機能しなくなります。",
"levelLabel": "圧縮レベル",
"light": "ライト(品質維持)",
"balanced": "バランス(推奨)",
"aggressive": "アグレッシブ(ファイルをより小さく)",
"extreme": "エクストリーム(最大圧縮)",
"grayscale": "グレースケールに変換",
"grayscaleHint": "カラー情報を削除してファイルサイズを削減します。",
"customSettings": "カスタム設定",
"customSettingsHint": "圧縮パラメータの微調整:",
"outputQuality": "出力品質",
"resizeImagesTo": "画像のリサイズ",
"onlyProcessAbove": "上記の処理のみ",
"removeMetadata": "メタデータを削除する",
"subsetFonts": "サブセットフォント (未使用のグリフの削除)",
"removeThumbnails": "埋め込みサムネイルを削除する",
"compressButton": "PDFを圧縮"
"subtitle": "PDFのファイルサイズを小さくします。"
},
"pdfEditor": {
"name": "PDFエディター",
@@ -60,6 +38,8 @@
"subtitle": "段落をクリックしてその場で編集。テキストは自動で再配置され、フォントやスタイルも変更できます。",
"saved": "PDF を保存しました!({{size}} KB)",
"failedToLoad": "PDF テキストエディタを読み込めませんでした。",
"loadingFonts": "フォントを読み込み中...",
"fontsUnavailable": "一部の文字に必要なフォントをダウンロードできませんでした。接続を確認してもう一度お試しください。このままでは、保存した PDF でそれらの文字が正しく表示されない可能性があります。",
"howToUpload": "PDF をアップロード",
"howToClick": "段落をクリック",
"howToRestyle": "自由にスタイル変更",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "はい! 「ループ」オプションを有効にすると、オーバーレイPDFページがすべてのベース ページにわたって繰り返されます。単一ページのウォーターマークはすべてのページに適用されます。",
"faqPrivacyQuestion": "私のファイルは非公開で安全ですか?",
"faqPrivacyAnswer": "絶対に!すべての処理はブラウザ内で行われます。ファイルがデバイスの外に出ることはなく、完全なプライバシーが確保されます。"
},
"unlockPdf": {
"name": "PDFの復号化",
"subtitle": "パスワード保護を解除してPDFのロックを解除します。"
},
"protectPdf": {
"name": "PDFの暗号化",
"subtitle": "パスワードを追加してPDFをロックします。"
}
}
+6 -3
View File
@@ -222,7 +222,7 @@
"testimonials": {
"title": "사용자",
"users": "후기",
"say": ""
"say": " "
},
"support": {
"title": "도움이 되셨나요?",
@@ -239,7 +239,9 @@
"legal": "법적 고지",
"termsAndConditions": "이용약관",
"privacyPolicy": "개인정보처리방침",
"followUs": "팔로우"
"followUs": "팔로우",
"privacyShort": "개인정보",
"termsShort": "이용약관"
},
"merge": {
"title": "PDF 병합",
@@ -286,7 +288,8 @@
"noCompromises": "타협 없이."
},
"mission": {
"title": "우리의 목표",
"title": "우리의",
"titleDim": "목표",
"description": "프라이버시를 지키면서도 비용 부담 없는, 가장 완벽한 PDF 도구를 만드는 것입니다. 꼭 필요한 문서 도구는 누구나, 어디서든 자유롭게 쓸 수 있어야 합니다."
},
"philosophy": {
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "PDF 압축",
"subtitle": "PDF 파일 크기를 줄입니다.",
"algorithmLabel": "압축 알고리즘",
"condense": "Condense (권장)",
"photon": "Photon (사진이 많은 PDF용)",
"condenseInfo": "Condense는 불필요한 데이터 제거, 이미지 최적화, 폰트 서브셋 등 고급 압축을 적용합니다. 대부분의 PDF에 적합합니다.",
"photonInfo": "Photon은 페이지를 이미지로 변환합니다. 사진이 많거나 스캔된 PDF에 적합합니다.",
"photonWarning": "주의: 텍스트 선택이 불가능해지고 링크가 작동하지 않게 됩니다.",
"levelLabel": "압축 수준",
"light": "낮음 (품질 유지)",
"balanced": "보통 (권장)",
"aggressive": "높음 (파일 크기 우선)",
"extreme": "최대 (최고 압축률)",
"grayscale": "흑백으로 변환",
"grayscaleHint": "색상 정보를 제거하여 파일 크기를 줄입니다",
"customSettings": "사용자 설정",
"customSettingsHint": "압축 세부 설정을 조정합니다:",
"outputQuality": "출력 품질",
"resizeImagesTo": "이미지 크기 조정",
"onlyProcessAbove": "이 크기 이상만 처리",
"removeMetadata": "메타데이터 제거",
"subsetFonts": "폰트 서브셋 (미사용 글자 제거)",
"removeThumbnails": "내장 미리보기 이미지 제거",
"compressButton": "PDF 압축하기"
"subtitle": "PDF 파일 크기를 줄입니다."
},
"pdfEditor": {
"name": "PDF 편집기",
@@ -60,6 +38,8 @@
"subtitle": "아무 단락이나 클릭해 실시간 리플로우, 글꼴, 스타일과 함께 바로 편집하세요.",
"saved": "PDF를 저장했습니다! ({{size}} KB)",
"failedToLoad": "PDF 텍스트 편집기를 불러오지 못했습니다.",
"loadingFonts": "글꼴을 불러오는 중...",
"fontsUnavailable": "일부 문자에 필요한 글꼴을 다운로드하지 못했습니다. 연결을 확인하고 다시 시도하세요. 그렇지 않으면 저장된 PDF에서 해당 문자가 올바르게 표시되지 않을 수 있습니다.",
"howToUpload": "PDF 업로드",
"howToClick": "문단 클릭",
"howToRestyle": "무엇이든 스타일 변경",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "네! \"반복\" 옵션을 활성화하면 오버레이 페이지가 모든 기본 페이지에 반복됩니다. 단일 페이지 워터마크가 모든 페이지에 적용됩니다.",
"faqPrivacyQuestion": "내 파일은 비공개이고 안전한가요?",
"faqPrivacyAnswer": "물론입니다! 모든 처리는 브라우저에서 이루어집니다. 파일이 기기를 떠나지 않아 완전한 개인정보 보호가 보장됩니다."
},
"unlockPdf": {
"name": "PDF 복호화",
"subtitle": "비밀번호를 제거하여 PDF 잠금을 해제합니다."
},
"protectPdf": {
"name": "PDF 암호화",
"subtitle": "비밀번호를 설정하여 PDF를 보호합니다."
}
}
+7 -4
View File
@@ -1,6 +1,6 @@
{
"nav": {
"home": "Thuis",
"home": "Startpagina",
"about": "Over",
"contact": "Contact",
"licensing": "Licentie",
@@ -239,7 +239,9 @@
"legal": "Juridisch",
"termsAndConditions": "Algemene voorwaarden",
"privacyPolicy": "Privacybeleid",
"followUs": "Volgen"
"followUs": "Volgen",
"privacyShort": "Privacy",
"termsShort": "Voorwaarden"
},
"merge": {
"title": "PDF's samenvoegen",
@@ -286,7 +288,8 @@
"noCompromises": "Geen compromissen."
},
"mission": {
"title": "Onze missie",
"title": "Onze",
"titleDim": "missie",
"description": "Ons doel is om de meest complete PDF-toolbox te bieden die je privacy respecteert en nooit om betaling vraagt. Wij geloven dat essentiële documententools voor iedereen, overal en zonder obstakels toegankelijk moeten zijn."
},
"philosophy": {
@@ -382,6 +385,6 @@
"title": "Tool niet beschikbaar",
"heading": "Deze tool is uitgeschakeld",
"message": "Deze tool is niet beschikbaar in deze implementatie. Neem contact op met de beheerder voor meer informatie.",
"backHome": "Terug naar Thuis"
"backHome": "Terug naar Startpagina"
}
}
+11 -23
View File
@@ -27,29 +27,7 @@
},
"compressPdf": {
"name": "PDF Comprimeren",
"subtitle": "De bestandsgrootte van een PDF verkleinen.",
"algorithmLabel": "Compressie-algoritme",
"condense": "Condense (Aanbevolen)",
"photon": "Photon (Voor PDF's met veel foto's)",
"condenseInfo": "Condense gebruikt geavanceerde compressie: verwijdert overbodige onderdelen, optimaliseert afbeeldingen en kiest alleen de benodigde letters uit fonts. Ideaal voor de meeste PDF's.",
"photonInfo": "Photon zet pagina's om in afbeeldingen. Handig voor PDF's met veel foto's of gescande documenten.",
"photonWarning": "Let op: De tekst kan dan niet meer geselecteerd worden en links werken niet meer.",
"levelLabel": "Compressieniveau",
"light": "Licht (Kwaliteit behouden)",
"balanced": "Gebalanceerd (Aanbevolen)",
"aggressive": "Agressief (Kleinere bestanden)",
"extreme": "Extreem (Maximale compressie)",
"grayscale": "Converteren naar grijswaarden",
"grayscaleHint": "Vermindert de bestandsgrootte door kleurinformatie te verwijderen",
"customSettings": "Aangepaste instellingen",
"customSettingsHint": "Compressie-instellingen verfijnen:",
"outputQuality": "Uitvoerkwaliteit",
"resizeImagesTo": "Formaat van afbeeldingen aanpassen naar",
"onlyProcessAbove": "Alleen verwerken boven",
"removeMetadata": "Metagegevens wissen",
"subsetFonts": "Subset-lettertypen (ongebruikte tekens verwijderen)",
"removeThumbnails": "Ingesloten miniaturen verwijderen",
"compressButton": "PDF Comprimeren"
"subtitle": "De bestandsgrootte van een PDF verkleinen."
},
"pdfEditor": {
"name": "PDF Bewerken",
@@ -60,6 +38,8 @@
"subtitle": "Klik op een alinea en bewerk deze direct, met live tekstomloop, lettertypen en opmaak.",
"saved": "PDF is opgeslagen! ({{size}} KB)",
"failedToLoad": "Kan de PDF-teksteditor niet laden.",
"loadingFonts": "Lettertypen laden…",
"fontsUnavailable": "Een lettertype dat nodig is voor sommige tekens kon niet worden gedownload. Controleer de verbinding en probeer het opnieuw, anders worden deze tekens mogelijk niet correct weergegeven in de opgeslagen PDF.",
"howToUpload": "PDF uploaden",
"howToClick": "Klik op een alinea",
"howToRestyle": "Alles opnieuw vormgeven",
@@ -1312,5 +1292,13 @@
"faqSinglePageAnswer": "Ja! Schakel de optie \"Herhalen\" in en de overlay-pagina's worden herhaald over alle basispagina's. Een watermerk van één pagina wordt op elke pagina toegepast.",
"faqPrivacyQuestion": "Zijn mijn bestanden privé en veilig?",
"faqPrivacyAnswer": "Absoluut! Alle verwerking vindt plaats in jouw browser. Jouw bestanden verlaten nooit jouw apparaat, wat volledige privacy garandeert."
},
"unlockPdf": {
"name": "PDF Ontgrendelen",
"subtitle": "Een PDF ontgrendelen door het verwijderen van de wachtwoordbeveiliging."
},
"protectPdf": {
"name": "PDF Versleutelen",
"subtitle": "Een PDF vergrendelen door toevoeging van een toegangswachtwoord."
}
}
+387
View File
@@ -0,0 +1,387 @@
{
"nav": {
"home": "Strona główna",
"about": "O nas",
"contact": "Kontakt",
"licensing": "Licencjonowanie",
"allTools": "Wszystkie narzędzia",
"docs": "Dokumentacja",
"openMainMenu": "Otwórz menu główne",
"language": "Język",
"searchLanguage": "Szukaj języka…",
"noLanguagesFound": "Nie znaleziono języków"
},
"donation": {
"message": "Uwielbiasz BentoPDF? Pomóż nam utrzymać go jako darmowe i otwarte oprogramowanie!",
"button": "Wesprzyj"
},
"hero": {
"title": "Twój",
"pdfToolkit": "zestaw narzędzi PDF",
"builtForPrivacy": "stworzony z myślą o prywatności",
"noSignups": "Brak rejestracji",
"unlimitedUse": "Nielimitowane korzystanie",
"worksOffline": "Działa offline",
"startUsing": "Zacznij używać teraz"
},
"usedBy": {
"title": "Używane przez firmy i osoby pracujące w"
},
"features": {
"title": "Dlaczego warto wybrać",
"bentoPdf": "BentoPDF?",
"noSignup": {
"title": "Bez rejestracji",
"description": "Zacznij od razu, bez kont i e-maili."
},
"noUploads": {
"title": "Bez wysyłania na serwer",
"description": "W 100% po stronie klienta, Twoje pliki nigdy nie opuszczają urządzenia."
},
"foreverFree": {
"title": "Zawsze darmowe",
"description": "Wszystkie narzędzia, bez okresów próbnych i ukrytych opłat."
},
"noLimits": {
"title": "Bez limitów",
"description": "Używaj bez ograniczeń, brak ukrytych limitów."
},
"batchProcessing": {
"title": "Przetwarzanie wsadowe",
"description": "Obsługuj nieograniczoną liczbę plików PDF za jednym razem."
},
"lightningFast": {
"title": "Błyskawicznie",
"description": "Przetwarzaj pliki PDF natychmiast, bez czekania i opóźnień."
}
},
"tools": {
"title": "Rozpocznij z",
"toolsLabel": "Narzędzia",
"subtitle": "Kliknij narzędzie, aby otworzyć przesyłanie plików",
"searchPlaceholder": "Szukaj narzędzia (np. 'podziel', 'organizuj'...)",
"backToTools": "Wróć do narzędzi",
"firstLoadNotice": "Pierwsze wczytywanie potrwa chwilę, ponieważ pobieramy nasz silnik konwersji. Potem wszystkie ładowania będą natychmiastowe."
},
"upload": {
"clickToSelect": "Kliknij, aby wybrać plik",
"orDragAndDrop": "lub przeciągnij i upuść",
"pdfOrImages": "Pliki PDF lub obrazy",
"filesNeverLeave": "Twoje pliki nigdy nie opuszczają Twojego urządzenia.",
"addMore": "Dodaj więcej plików",
"clearAll": "Wyczyść wszystko",
"clearFiles": "Wyczyść pliki",
"hints": {
"singlePdf": "Pojedynczy plik PDF",
"pdfFile": "Plik PDF",
"multiplePdfs2": "Wiele plików PDF (co najmniej 2)",
"bmpImages": "Obrazy BMP",
"oneOrMorePdfs": "Jeden lub więcej plików PDF",
"pdfDocuments": "Dokumenty PDF",
"oneOrMoreCsv": "Jeden lub więcej plików CSV",
"multiplePdfsSupported": "Obsługiwane wiele plików PDF",
"singleOrMultiplePdfs": "Obsługiwane pojedyncze lub wielokrotne pliki PDF",
"singlePdfFile": "Pojedynczy plik PDF",
"pdfWithForms": "Plik PDF z polami formularza",
"heicImages": "Obrazy HEIC/HEIF",
"jpgImages": "Obrazy JPG, JPEG, JP2, JPX",
"pdfsOrImages": "Pliki PDF lub obrazy",
"oneOrMoreOdt": "Jeden lub więcej plików ODT",
"singlePdfOnly": "Tylko pojedynczy plik PDF",
"pdfFiles": "Pliki PDF",
"multiplePdfs": "Wiele plików PDF",
"pngImages": "Obrazy PNG",
"pdfFilesOneOrMore": "Pliki PDF (jeden lub więcej)",
"oneOrMoreRtf": "Jeden lub więcej plików RTF",
"svgGraphics": "Grafika SVG",
"tiffImages": "Obrazy TIFF",
"webpImages": "Obrazy WebP"
}
},
"howItWorks": {
"title": "Jak to działa",
"step1Title": "Prześlij plik",
"step1": "Kliknij lub przeciągnij i upuść plik, aby rozpocząć",
"step2Title": "Przetwarzaj",
"step2": "Kliknij przycisk przetwarzania, aby rozpocząć",
"step3Title": "Pobierz",
"step3": "Natychmiast zapisz przetworzony plik"
},
"relatedTools": {
"title": "Powiązane narzędzia PDF"
},
"loader": {
"processing": "Przetwarzanie..."
},
"alert": {
"title": "Uwaga",
"ok": "OK"
},
"preview": {
"title": "Podgląd dokumentu",
"downloadAsPdf": "Pobierz jako PDF",
"close": "Zamknij"
},
"settings": {
"title": "Ustawienia",
"shortcuts": "Skróty",
"preferences": "Preferencje",
"displayPreferences": "Preferencje wyświetlania",
"searchShortcuts": "Szukaj skrótów...",
"shortcutsInfo": "Naciśnij i przytrzymaj klawisze, aby ustawić skrót. Zmiany są zapisywane automatycznie.",
"shortcutsWarning": "⚠️ Unikaj popularnych skrótów przeglądarki (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N itp.), ponieważ mogą nie działać prawidłowo.",
"import": "Importuj",
"export": "Eksportuj",
"resetToDefaults": "Przywróć domyślne",
"fullWidthMode": "Tryb pełnej szerokości",
"fullWidthDescription": "Używaj pełnej szerokości ekranu dla wszystkich narzędzi zamiast wyśrodkowanego kontenera",
"compactMode": "Tryb kompaktowy",
"compactModeDescription": "Wyświetlaj narzędzia jako kompaktową listę zamiast kart",
"advancedSettings": "Ustawienia zaawansowane",
"advancedSettingsDescription": "Skonfiguruj zewnętrzne moduły przetwarzania (PyMuPDF, Ghostscript, CoherentPDF)",
"settingsAutoSaved": "Ustawienia są zapisywane automatycznie",
"clickToSet": "Kliknij, aby ustawić",
"pressKeys": "Naciśnij klawisze...",
"warnings": {
"alreadyInUse": "Skrót jest już w użyciu",
"assignedTo": "jest już przypisany do:",
"chooseDifferent": "Proszę wybrać inny skrót.",
"reserved": "Ostrzeżenie o zarezerwowanym skrócie",
"commonlyUsed": "jest powszechnie używany do:",
"unreliable": "Ten skrót może nie działać niezawodnie lub może kolidować z działaniem przeglądarki/systemu.",
"useAnyway": "Czy mimo to chcesz go użyć?",
"resetTitle": "Zresetuj skróty",
"resetMessage": "Czy na pewno chcesz zresetować wszystkie skróty do wartości domyślnych?<br><br>Tej akcji nie można cofnąć.",
"importSuccessTitle": "Import zakończony sukcesem",
"importSuccessMessage": "Skróty zostały pomyślnie zaimportowane!",
"importFailTitle": "Import nie powiódł się",
"importFailMessage": "Nie udało się zaimportować skrótów. Nieprawidłowy format pliku."
}
},
"warning": {
"title": "Ostrzeżenie",
"cancel": "Anuluj",
"proceed": "Kontynuuj"
},
"compliance": {
"title": "Twoje dane nigdy nie opuszczają Twojego urządzenia",
"weKeep": "Dbamy o",
"yourInfoSafe": "bezpieczeństwo Twoich informacji",
"byFollowingStandards": "przestrzegając globalnych standardów bezpieczeństwa.",
"processingLocal": "Całe przetwarzanie odbywa się lokalnie na Twoim urządzeniu.",
"gdpr": {
"title": "Zgodność z RODO",
"description": "Chroni dane osobowe i prywatność osób w Unii Europejskiej."
},
"ccpa": {
"title": "Zgodność z CCPA",
"description": "Daje mieszkańcom Kalifornii prawa do kontrolowania sposobu gromadzenia, wykorzystywania i udostępniania ich danych osobowych."
},
"hipaa": {
"title": "Zgodność z HIPAA",
"description": "Ustanawia zabezpieczenia w celu ochrony wrażliwych informacji zdrowotnych w systemie opieki zdrowotnej Stanów Zjednoczonych."
}
},
"faq": {
"title": "Często Zadawane",
"questions": "Pytania",
"sectionTitle": "Często Zadawane Pytania",
"isFree": {
"question": "Czy BentoPDF jest naprawdę darmowy?",
"answer": "Tak, absolutnie. Wszystkie narzędzia w BentoPDF są w 100% darmowe do użytku, bez limitów plików, bez rejestracji i bez znaków wodnych. Wierzymy, że każdy zasługuje na dostęp do prostych, potężnych narzędzi PDF bez barier płatnych."
},
"areFilesSecure": {
"question": "Czy moje pliki są bezpieczne? Gdzie są przetwarzane?",
"answer": "Twoje pliki są maksymalnie bezpieczne, ponieważ nigdy nie opuszczają Twojego komputera. Całe przetwarzanie odbywa się bezpośrednio w Twojej przeglądarce internetowej (po stronie klienta). Nigdy nie wysyłamy Twoich plików na serwer, dzięki czemu zachowujesz pełną prywatność i kontrolę nad swoimi dokumentami."
},
"platforms": {
"question": "Czy to działa na Macu, Windowsie i urządzeniach mobilnych?",
"answer": "Tak! Ponieważ BentoPDF działa całkowicie w Twojej przeglądarce, obsługuje dowolny system operacyjny z nowoczesną przeglądarką internetową, w tym Windows, macOS, Linux, iOS oraz Android."
},
"gdprCompliant": {
"question": "Czy BentoPDF jest zgodny z RODO?",
"answer": "Tak. BentoPDF jest w pełni zgodny z RODO. Ponieważ całe przetwarzanie plików odbywa się lokalnie w Twojej przeglądarce, a my nigdy nie zbieramy ani nie wysyłamy Twoich plików na żaden serwer, nie mamy dostępu do Twoich danych. Gwarantuje to, że zawsze sprawujesz pełną kontrolę nad swoimi dokumentami."
},
"dataStorage": {
"question": "Czy przechowujecie lub śledzicie jakiekolwiek moje pliki?",
"answer": "Nie. Nigdy nie przechowujemy, nie śledzimy ani nie logujemy Twoich plików. Wszystko, co robisz w BentoPDF, odbywa się w pamięci Twojej przeglądarki i znika po zamknięciu strony. Nie ma żadnych transferów, logów historii ani serwerów."
},
"different": {
"question": "Czym różni się BentoPDF od innych narzędzi PDF?",
"answer": "Większość narzędzi PDF wysyła Twoje pliki na serwer w celu ich przetworzenia. BentoPDF nigdy tego nie robi. Wykorzystujemy bezpieczną, nowoczesną technologię internetową, aby przetwarzać Twoje pliki bezpośrednio w przeglądarce. Oznacza to większą wydajność, silniejszą prywatność i pełen spokój ducha."
},
"browserBased": {
"question": "W jaki sposób przetwarzanie w oparciu o przeglądarkę zapewnia mi bezpieczeństwo?",
"answer": "Działając całkowicie wewnątrz Twojej przeglądarki, BentoPDF gwarantuje, że Twoje pliki nigdy nie opuszczą Twojego urządzenia. Eliminuje to ryzyko ataków hakerskich na serwery, naruszeń bezpieczeństwa danych czy nieautoryzowanego dostępu. Twoje pliki pozostają Twoje — zawsze."
},
"analytics": {
"question": "Czy używacie plików cookie lub analityki do mojego śledzenia?",
"answer": "Dbamy o Twoją prywatność. BentoPDF nie śledzi danych osobowych. Używamy Simple Analytics wyłącznie w celu sprawdzenia anonimowej liczby wizyt. Oznacza to, że wiemy, ilu użytkowników odwiedza naszą stronę, ale nigdy nie wiemy, kim jesteś. Simple Analytics jest w pełni zgodne z RODO i szanuje Twoją prywatność."
}
},
"testimonials": {
"title": "Co Nasi",
"users": "Użytkownicy",
"say": "Mówią"
},
"support": {
"title": "Podoba Ci się moja praca?",
"description": "BentoPDF to projekt z pasji, stworzony po to, aby udostępnić darmowy, prywatny i potężny zestaw narzędzi PDF dla każdego. Jeśli uznasz go za przydatny, rozważ wsparcie jego rozwoju. Każda kawa pomaga!",
"buyMeCoffee": "Postaw mi kawę"
},
"footer": {
"copyright": "© 2026 BentoPDF. Wszelkie prawa zastrzeżone.",
"version": "Wersja",
"company": "Firma",
"aboutUs": "O nas",
"faqLink": "FAQ",
"contactUs": "Kontakt",
"legal": "Kwestie prawne",
"termsAndConditions": "Zasady i warunki",
"privacyPolicy": "Polityka prywatności",
"followUs": "Śledź nas"
},
"merge": {
"title": "Połącz pliki PDF",
"description": "Połącz całe pliki lub wybierz konkretne strony do scalenia w nowy dokument.",
"fileMode": "Tryb pliku",
"pageMode": "Tryb strony",
"howItWorks": "Jak to działa:",
"fileModeInstructions": [
"Kliknij i przeciągnij ikonę, aby zmienić kolejność plików.",
"W polu \"Strony\" dla każdego pliku możesz określić zakresy (np. \"1-3, 5\"), aby połączyć tylko te strony.",
"Pozostaw pole \"Strony\" puste, aby dołączyć wszystkie strony z tego pliku."
],
"pageModeInstructions": [
"Poniżej widoczne są wszystkie strony z przesłanych plików PDF.",
"Po prostu przeciągnij i upuść poszczególne miniatury stron, aby ułożyć je w dokładnej kolejności dla nowego pliku."
],
"mergePdfs": "Połącz PDF-y"
},
"common": {
"page": "Strona",
"pages": "Strony",
"of": "z",
"download": "Pobierz",
"cancel": "Anuluj",
"save": "Zapisz",
"delete": "Usuń",
"edit": "Edytuj",
"add": "Dodaj",
"remove": "Usuń",
"loading": "Ładowanie...",
"loadingPageCount": "Wczytywanie stron...",
"error": "Błąd",
"success": "Sukces",
"file": "Plik",
"files": "Pliki",
"close": "Zamknij",
"convert": "Konwertuj",
"unknownError": "Nieznany błąd"
},
"about": {
"hero": {
"title": "Wierzymy, że narzędzia PDF powinny być",
"subtitle": "szybkie, prywatne i darmowe.",
"noCompromises": "Bez kompromisów."
},
"mission": {
"title": "Nasza misja",
"description": "Zapewnienie najbardziej wszechstronnego zestawu narzędzi PDF, który szanuje Twoją prywatność i nigdy nie prosi o płatność. Wierzymy, że podstawowe narzędzia do dokumentów powinny być dostępne dla każdego, wszędzie i bez barier."
},
"philosophy": {
"label": "Nasza główna filozofia",
"title": "Prywatność na pierwszym miejscu. Zawsze.",
"description": "W czasach, gdy dane są towarem, my przyjmujemy inne podejście. Całe przetwarzanie w narzędziach BentoPDF odbywa się lokalnie w Twojej przeglądarce. Oznacza to, że Twoje pliki nigdy nie stykają się z naszymi serwerami, nigdy nie widzimy Twoich dokumentów i nie śledzimy tego, co robisz. Twoje dokumenty pozostają całkowicie i bezsprzecznie prywatne. To nie tylko funkcja; to nasz fundament."
},
"whyBentopdf": {
"title": "Dlaczego",
"speed": {
"title": "Zbudowane dla szybkości",
"description": "Bez czekania na wysłanie lub pobranie z serwera. Przetwarzając pliki bezpośrednio w Twojej przeglądarce przy użyciu nowoczesnych technologii internetowych, takich jak WebAssembly, oferujemy niezrównaną prędkość dla wszystkich naszych narzędzi."
},
"free": {
"title": "Całkowicie darmowe",
"description": "Bez wersji próbnych, bez subskrypcji, bez ukrytych opłat i bez „funkcji premium” wziętych jako zakładników. Wierzymy, że potężne narzędzia PDF powinny być dobrem publicznym, a nie centrum zysków."
},
"noAccount": {
"title": "Konto nie jest wymagane",
"description": "Zacznij natychmiast używać dowolnego narzędzia. Nie potrzebujemy Twojego e-maila, hasła ani żadnych danych osobowych. Twój przepływ pracy powinien być bezproblemowy i anonimowy."
},
"openSource": {
"title": "Duch Open Source",
"description": "Stworzone z myślą o przejrzystości. Korzystamy z niesamowitych bibliotek open-source, takich jak PDF-lib i PDF.js, oraz wierzymy w społeczny wysiłek, dzięki któremu potężne narzędzia są dostępne dla wszystkich."
}
},
"cta": {
"title": "Gotowy, aby zacząć?",
"description": "Dołącz do tysięcy użytkowników, którzy ufają BentoPDF w codziennych zadaniach z dokumentami. Poczuj różnicę, jaką potrafią zrobić prywatność i wydajność.",
"button": "Odkryj wszystkie narzędzia"
}
},
"contact": {
"title": "Bądźmy w kontakcie",
"subtitle": "Z przyjemnością Cię wysłuchamy. Niezależnie od tego, czy masz pytanie, opinię, czy prośbę o nową funkcję, nie wahaj się do nas napisać.",
"email": "Możesz się z nami skontaktować bezpośrednio poprzez e-mail na adres:"
},
"licensing": {
"title": "Licencjonowanie dla",
"subtitle": "Wybierz licencję, która odpowiada Twoim potrzebom."
},
"multiTool": {
"uploadPdfs": "Prześlij pliki PDF",
"upload": "Prześlij",
"addBlankPage": "Dodaj pustą stronę",
"edit": "Edytuj:",
"undo": "Cofnij",
"redo": "Ponów",
"reset": "Zresetuj",
"selection": "Wybór:",
"selectAll": "Zaznacz wszystko",
"deselectAll": "Odznacz wszystko",
"rotate": "Obróć:",
"rotateLeft": "W lewo",
"rotateRight": "W prawo",
"transform": "Przekształć:",
"duplicate": "Powiel",
"split": "Podziel",
"clear": "Wyczyść:",
"delete": "Usuń",
"download": "Pobierz:",
"downloadSelected": "Pobierz wybrane",
"exportPdf": "Eksportuj PDF",
"uploadPdfFiles": "Wybierz pliki PDF lub obrazy",
"dragAndDrop": "Przeciągnij i upuść pliki PDF lub obrazy tutaj, albo kliknij, by wybrać",
"selectFiles": "Wybierz pliki",
"dropToAdd": "Upuść pliki PDF lub obrazy, aby dodać",
"convertingImages": "Konwertowanie obrazów do formatu PDF...",
"failedToConvertImages": "Nie udało się przekonwertować obrazów do pliku PDF.",
"renderingPages": "Renderowanie stron...",
"actions": {
"duplicatePage": "Powiel tę stronę",
"deletePage": "Usuń tę stronę",
"insertPdf": "Wstaw PDF po tej stronie",
"toggleSplit": "Przełącz podział po tej stronie"
},
"pleaseWait": "Proszę czekać",
"pagesRendering": "Strony są nadal renderowane. Proszę czekać...",
"noPagesSelected": "Nie wybrano stron",
"selectOnePage": "Wybierz co najmniej jedną stronę do pobrania.",
"noPages": "Brak stron",
"noPagesToExport": "Nie ma stron do wyeksportowania.",
"renderingTitle": "Renderowanie podglądów stron",
"errorRendering": "Nie udało się wyrenderować miniatur stron",
"error": "Błąd",
"failedToLoad": "Nie udało się załadować"
},
"simpleMode": {
"title": "Narzędzia PDF",
"subtitle": "Wybierz narzędzie, aby rozpocząć"
},
"disabledTool": {
"title": "Narzędzie niedostępne",
"heading": "To narzędzie zostało wyłączone",
"message": "To narzędzie nie jest dostępne w Twoim środowisku. Skontaktuj się z administratorem, aby uzyskać więcej informacji.",
"backHome": "Powrót do strony głównej"
}
}
Loaded 100 of 365 files, more files were not shown because too many files have changed in this diff. Show more