diff --git a/blog/author-alam.html b/blog/author-alam.html new file mode 100644 index 00000000..7881ecc0 --- /dev/null +++ b/blog/author-alam.html @@ -0,0 +1,142 @@ + + + + + + Alam, Creator of BentoPDF + + + + + + + + + + + + + + + + + + {{> navbar }} + +
+
+ Alam +
+

Alam

+

Creator and maintainer of BentoPDF

+
+
+ +

+ I’m Alam, and I build + BentoPDF, + a free, open-source PDF toolkit with 100+ tools that run entirely in + your browser. +

+

+ There’s no uploading your files to a server, no account to create, and + no tracking. Your documents stay on your device. The + source code + is public, so you can see how it works yourself. BentoPDF is + AGPL-licensed and self-hostable. +

+

+ 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. +

+

+ 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. +

+

+ And if I get something wrong, please + open an issue. I’ll fix it and add a note to the post. +

+ +

+ You can find me on + GitHub + and + LinkedIn. +

+ +

+ Read the blog +

+
+ + {{> footer }} + + + + + + + diff --git a/blog/edit-pdf-without-uploading.html b/blog/edit-pdf-without-uploading.html new file mode 100644 index 00000000..dd3297dd --- /dev/null +++ b/blog/edit-pdf-without-uploading.html @@ -0,0 +1,472 @@ + + + + + + + How to Edit a PDF Without Uploading It Anywhere | BentoPDF Blog + + + + + + + + + + + + + + + + + + + {{> navbar }} + +
+ + +

+ How to edit a PDF without uploading it anywhere +

+ +
+ Alam +
+ Alam, builds BentoPDF · + +
+
+ +

+ You can edit a PDF in your browser without uploading the file to a + server. +

+

+ Open + BentoPDF's PDF editor, 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. +

+
    +
  1. Open the tool.
  2. +
  3. Drop in your PDF.
  4. +
  5. Click on the text you want to change.
  6. +
  7. Type your changes.
  8. +
  9. Download the edited PDF.
  10. +
+

+ 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 + 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 + 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 + and type into them. If you'd rather have real fields, + Create PDF Form + 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 + 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 + 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 + 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 + 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 + 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. 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. +

+ +
+

Edit your PDF now

+

+ Free, no signup. Your file stays on your device. +

+ Open the PDF editor +
+
+ + {{> footer }} + + + + + + + + + diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 00000000..98d2cd25 --- /dev/null +++ b/blog/index.html @@ -0,0 +1,87 @@ + + + + + + The BentoPDF Blog | Privacy-First PDF Guides + + + + + + + + + + + + + + + + + + {{> navbar }} + +
+

+ The BentoPDF Blog +

+

+ I'm + Alam. I build BentoPDF and write about PDFs, how they work, and the weird + things I run into along the way. +

+
+ +
+
+ +

+ How to edit a PDF without uploading it anywhere +

+

+ Rewrite text, fill forms, redact properly, and sign, locally on your + device. +

+ September 3, 2026 +
+
+
+ + {{> footer }} + + + + + + diff --git a/blog/posts/edit-pdf-without-uploading.md b/blog/posts/edit-pdf-without-uploading.md new file mode 100644 index 00000000..8493401a --- /dev/null +++ b/blog/posts/edit-pdf-without-uploading.md @@ -0,0 +1,136 @@ +--- +{ + '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. diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index f7ec0fa6..c4591fa8 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -115,7 +115,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 +176,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' }, diff --git a/docs/tools/change-permissions.md b/docs/tools/change-permissions.md index 46608ed8..e237f97c 100644 --- a/docs/tools/change-permissions.md +++ b/docs/tools/change-permissions.md @@ -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 diff --git a/docs/tools/digital-sign-pdf.md b/docs/tools/digital-sign-pdf.md index bc6797fa..7b42f87f 100644 --- a/docs/tools/digital-sign-pdf.md +++ b/docs/tools/digital-sign-pdf.md @@ -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 diff --git a/docs/tools/flatten-pdf.md b/docs/tools/flatten-pdf.md index b361a324..82e3a437 100644 --- a/docs/tools/flatten-pdf.md +++ b/docs/tools/flatten-pdf.md @@ -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 diff --git a/docs/tools/index.md b/docs/tools/index.md index 08b4053a..a55fdbbe 100644 --- a/docs/tools/index.md +++ b/docs/tools/index.md @@ -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.
-- [**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. diff --git a/docs/tools/pdf-to-markdown.md b/docs/tools/pdf-to-markdown.md index dd180d3c..54552b98 100644 --- a/docs/tools/pdf-to-markdown.md +++ b/docs/tools/pdf-to-markdown.md @@ -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) diff --git a/docs/tools/pdf-to-text.md b/docs/tools/pdf-to-text.md index e95c6123..acea1c83 100644 --- a/docs/tools/pdf-to-text.md +++ b/docs/tools/pdf-to-text.md @@ -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) diff --git a/docs/tools/pdf-to-docx.md b/docs/tools/pdf-to-word.md similarity index 100% rename from docs/tools/pdf-to-docx.md rename to docs/tools/pdf-to-word.md diff --git a/docs/tools/encrypt-pdf.md b/docs/tools/protect-pdf.md similarity index 97% rename from docs/tools/encrypt-pdf.md rename to docs/tools/protect-pdf.md index 8b402da3..62e781ac 100644 --- a/docs/tools/encrypt-pdf.md +++ b/docs/tools/protect-pdf.md @@ -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 diff --git a/docs/tools/remove-metadata.md b/docs/tools/remove-metadata.md index e27adbf4..3918c725 100644 --- a/docs/tools/remove-metadata.md +++ b/docs/tools/remove-metadata.md @@ -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 diff --git a/docs/tools/remove-restrictions.md b/docs/tools/remove-restrictions.md index 8f41f4f0..180a5ca8 100644 --- a/docs/tools/remove-restrictions.md +++ b/docs/tools/remove-restrictions.md @@ -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 diff --git a/docs/tools/sanitize-pdf.md b/docs/tools/sanitize-pdf.md index 327f4fb3..916d41ee 100644 --- a/docs/tools/sanitize-pdf.md +++ b/docs/tools/sanitize-pdf.md @@ -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 diff --git a/docs/tools/decrypt-pdf.md b/docs/tools/unlock-pdf.md similarity index 97% rename from docs/tools/decrypt-pdf.md rename to docs/tools/unlock-pdf.md index f21965a0..e329b8a1 100644 --- a/docs/tools/decrypt-pdf.md +++ b/docs/tools/unlock-pdf.md @@ -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 diff --git a/index.html b/index.html index cf11a2e2..6adb458a 100644 --- a/index.html +++ b/index.html @@ -12,7 +12,7 @@ />
+ > + {{> tool-links-static }} +
JSON to PDF

Data to PDF

- + @@ -425,48 +425,144 @@
- Are these pdf converter tools really free? - - -

- 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. -

-
- -
- - Are my files private and secure? + Which file formats can I convert to PDF?

- Absolutely! All processing happens entirely in your browser. Your - files never leave your device, are never uploaded to servers. - Complete privacy guaranteed. + 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, + Images to PDF + accepts them all in one batch and puts each image on its own page.

-
- Is there a file size limit? + What can I convert a PDF into?

- No file size limits! Process files of any size. Browser-based - processing means no artificial limitations. + 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, + PDF to PDF/A + outputs PDF/A-1b, 2b, or 3b, and a separate tool turns a color PDF + into a grayscale one.

-
- Do I need to install software? + Does PDF to Word keep the layout?

- 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. + PDF to Word + 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. +

+
+
+ + Why is my converted Word or text file empty? + + +

+ 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 + OCR PDF + first to add a searchable text layer, then convert the result. +

+
+
+ + Can I get tables out of a PDF into Excel? + + +

+ PDF to Excel + 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. +

+
+
+ + Do I need Microsoft Office installed to convert Word, Excel, or + PowerPoint files? + + +

+ 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; + Word to PDF, 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. +

+
+
+ + Will converting a PDF to JPG or PNG lose quality? + + +

+ Pages are rendered at twice their native size, so a letter-size + page becomes an image of roughly 1,224 by 1,584 pixels. + PDF to JPG + 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. +

+
+
+ + Are my files uploaded to a server during conversion? + + +

+ 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.

diff --git a/pdf-editor.html b/pdf-editor.html index 066b3a57..ee52abf2 100644 --- a/pdf-editor.html +++ b/pdf-editor.html @@ -5,7 +5,7 @@ - PDF Editor - Free Online PDF Editor Tools | BentoPDF + PDF Editing Tools - All Free Online PDF Editors | BentoPDF - +
- Are these pdf editor tools really free? - - -

- 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. -

-
- -
- - Are my files private and secure? + Can I change the existing text in a PDF?

- Absolutely! All processing happens entirely in your browser. Your - files never leave your device, are never uploaded to servers. - Complete privacy guaranteed. + Edit PDF Text + 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.

-
- Is there a file size limit? + What can I do in the Edit PDF tool?

- No file size limits! Process files of any size. Browser-based - processing means no artificial limitations. + The + Edit PDF + 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.

-
- Do I need to install software? + How do I make a PDF smaller?

- 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. + Compress PDF + offers two methods. Condense strips unused structure, downsamples + images to a target DPI, and subsets fonts while keeping text + selectable and links working; Photon re-renders each page as a + JPEG, which saves more on scans and photo-heavy files but leaves + text unselectable. Start with the Balanced level and only step up + to Aggressive or Extreme if the file is still too large. +

+
+
+ + Which editing tools keep my text selectable? + + +

+ 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, and the Photon + compression mode does the same. If you need searchable text after + one of those, run the result through + OCR PDF. +

+
+
+ + Can I add page numbers or a header and footer? + + +

+ Page Numbers + 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. +

+
+
+ + Can I put a watermark on every page? + + +

+ Add Watermark + 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. +

+
+
+ + Can I rotate a single page, or fix a slightly tilted scan? + + +

+ Rotate PDF + 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. +

+
+
+ + Does editing a PDF here upload it anywhere? + + +

+ 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.

diff --git a/pdf-merge-split.html b/pdf-merge-split.html index ff1a75ac..c1ef1161 100644 --- a/pdf-merge-split.html +++ b/pdf-merge-split.html @@ -254,48 +254,142 @@
- Are these pdf merge & split tools really free? - - -

- 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. -

-
- -
- - Are my files private and secure? + How do I combine several PDFs into one file?

- Absolutely! All processing happens entirely in your browser. Your - files never leave your device, are never uploaded to servers. - Complete privacy guaranteed. + Add two or more files to + Merge PDF + 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.

-
- Is there a file size limit? + What are the different ways to split a PDF?

- No file size limits! Process files of any size. Browser-based - processing means no artificial limitations. + Split PDF + 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.

-
- Do I need to install software? + What's the difference between Split, Extract Pages, and Delete + Pages?

- 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. + Extract Pages + 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. +

+
+
+ + Can I reorder pages or duplicate a page? + + +

+ Organize PDF + 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. +

+
+
+ + My scanner put all the front pages first and all the backs after. + How do I fix the order? + + +

+ Duplex Collate + 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. +

+
+
+ + How do I print a PDF as a folded booklet? + + +

+ PDF Booklet + 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. +

+
+
+ + Can I see what changed between two versions of a PDF? + + +

+ Compare PDFs + 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. +

+
+
+ + Are my files uploaded when I merge or split them? + + +

+ 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.

diff --git a/pdf-security.html b/pdf-security.html index 434c7cb2..2f92c51e 100644 --- a/pdf-security.html +++ b/pdf-security.html @@ -111,12 +111,12 @@
- +

Encrypt PDF

Add password

- +

Decrypt PDF

Remove password

@@ -229,48 +229,148 @@
- Are these PDF security tools really free? - - -

- 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. -

-
- -
- - Are my files private and secure? + What's the difference between protecting a PDF with a password and + restricting its permissions?

- Absolutely! All processing happens entirely in your browser. Your - files never leave your device and are never uploaded to servers. - Complete privacy is guaranteed. + A user password, set with + Protect PDF, 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.

-
- Is there a file size limit? + How strong is the password protection?

- No file size limits! Process files of any size. Browser-based - processing means no artificial limitations. + 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.

-
- Do I need to install software? + Can I remove a password from a PDF if I don't know it?

- 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. + No. + Unlock PDF + 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. +

+
+
+ + What's the difference between Sign PDF and a digital signature? + + +

+ 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. + Digital Signature + 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. +

+
+
+ + How do I redact text so it's actually gone? + + +

+ Use the redaction tool in the + PDF Editor, which permanently removes the marked content from the page + instead of just covering it with a box. Redaction only deals with + what's on the page, 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. +

+
+
+ + What's the difference between Remove Metadata and Sanitize PDF? + + +

+ Remove Metadata + 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. +

+
+
+ + What does flattening a PDF do, and when should I use it? + + +

+ Flatten PDF + 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. +

+
+
+ + Are my passwords, certificates, or files sent to a server? + + +

+ 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.

diff --git a/public/images/author-alam.jpg b/public/images/author-alam.jpg new file mode 100644 index 00000000..2aebe4fc Binary files /dev/null and b/public/images/author-alam.jpg differ diff --git a/public/locales/ar/tools.json b/public/locales/ar/tools.json index 36ce7715..c3f8e519 100644 --- a/public/locales/ar/tools.json +++ b/public/locales/ar/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "نعم! فعّل خيار \"التكرار\" وستتكرر صفحات التراكب على جميع صفحات الملف الأساسي. العلامة المائية ذات الصفحة الواحدة ستُطبق على كل صفحة.", "faqPrivacyQuestion": "هل ملفاتي خاصة وآمنة؟", "faqPrivacyAnswer": "بالتأكيد! تتم جميع المعالجة في متصفحك. لا تغادر ملفاتك جهازك أبداً، مما يضمن خصوصية كاملة." + }, + "unlockPdf": { + "name": "فك تشفير PDF", + "subtitle": "فتح PDF بإزالة حماية كلمة المرور." + }, + "protectPdf": { + "name": "تشفير PDF", + "subtitle": "قفل PDF بإضافة كلمة مرور." } } diff --git a/public/locales/be/tools.json b/public/locales/be/tools.json index b5ad9ab0..858af326 100644 --- a/public/locales/be/tools.json +++ b/public/locales/be/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Так! Уключыце опцыю \"Паўтараць\" і старонкі накладання будуць паўтарацца на ўсіх старонках базавага файла. Аднастаронкавы вадзяны знак будзе прымяняцца да кожнай старонкі.", "faqPrivacyQuestion": "Ці з'яўляюцца мае файлы прыватнымі і бяспечнымі?", "faqPrivacyAnswer": "Безумоўна! Уся апрацоўка адбываецца ў вашым браўзеры. Вашы файлы ніколі не пакідаюць вашу прыладу, забяспечваючы поўную прыватнасць." + }, + "unlockPdf": { + "name": "Расшыфраваць PDF", + "subtitle": "Разблакіраваць PDF, выдаліўшы пароль." + }, + "protectPdf": { + "name": "Зашыфраваць PDF", + "subtitle": "Заблакіраваць PDF, дадаўшы пароль." } } diff --git a/public/locales/da/tools.json b/public/locales/da/tools.json index a505aedc..fffc2a54 100644 --- a/public/locales/da/tools.json +++ b/public/locales/da/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/de/tools.json b/public/locales/de/tools.json index f6c8df25..e90cebc5 100644 --- a/public/locales/de/tools.json +++ b/public/locales/de/tools.json @@ -1311,5 +1311,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." } } diff --git a/public/locales/en/tools.json b/public/locales/en/tools.json index c553d5a4..5838c8a3 100644 --- a/public/locales/en/tools.json +++ b/public/locales/en/tools.json @@ -1313,5 +1313,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." } } diff --git a/public/locales/es/tools.json b/public/locales/es/tools.json index 50cd32b0..46f83148 100644 --- a/public/locales/es/tools.json +++ b/public/locales/es/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/fr/tools.json b/public/locales/fr/tools.json index f502ef7f..5bbcec34 100644 --- a/public/locales/fr/tools.json +++ b/public/locales/fr/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/id/tools.json b/public/locales/id/tools.json index 2a5caf9e..00b3f0b9 100644 --- a/public/locales/id/tools.json +++ b/public/locales/id/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/it/tools.json b/public/locales/it/tools.json index ded8cea7..a39cbf3f 100644 --- a/public/locales/it/tools.json +++ b/public/locales/it/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/ja/tools.json b/public/locales/ja/tools.json index 001006af..0bfa7c18 100644 --- a/public/locales/ja/tools.json +++ b/public/locales/ja/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "はい! 「ループ」オプションを有効にすると、オーバーレイPDFページがすべてのベース ページにわたって繰り返されます。単一ページのウォーターマークはすべてのページに適用されます。", "faqPrivacyQuestion": "私のファイルは非公開で安全ですか?", "faqPrivacyAnswer": "絶対に!すべての処理はブラウザ内で行われます。ファイルがデバイスの外に出ることはなく、完全なプライバシーが確保されます。" + }, + "unlockPdf": { + "name": "PDFの復号化", + "subtitle": "パスワード保護を解除してPDFのロックを解除します。" + }, + "protectPdf": { + "name": "PDFの暗号化", + "subtitle": "パスワードを追加してPDFをロックします。" } } diff --git a/public/locales/ko/tools.json b/public/locales/ko/tools.json index fa78425f..ff9f95d4 100644 --- a/public/locales/ko/tools.json +++ b/public/locales/ko/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "네! \"반복\" 옵션을 활성화하면 오버레이 페이지가 모든 기본 페이지에 반복됩니다. 단일 페이지 워터마크가 모든 페이지에 적용됩니다.", "faqPrivacyQuestion": "내 파일은 비공개이고 안전한가요?", "faqPrivacyAnswer": "물론입니다! 모든 처리는 브라우저에서 이루어집니다. 파일이 기기를 떠나지 않아 완전한 개인정보 보호가 보장됩니다." + }, + "unlockPdf": { + "name": "PDF 복호화", + "subtitle": "비밀번호를 제거하여 PDF 잠금을 해제합니다." + }, + "protectPdf": { + "name": "PDF 암호화", + "subtitle": "비밀번호를 설정하여 PDF를 보호합니다." } } diff --git a/public/locales/nl/tools.json b/public/locales/nl/tools.json index 766e4312..ae8c1ed8 100644 --- a/public/locales/nl/tools.json +++ b/public/locales/nl/tools.json @@ -1312,5 +1312,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." } } diff --git a/public/locales/pt/tools.json b/public/locales/pt/tools.json index 99705801..09c0e42a 100644 --- a/public/locales/pt/tools.json +++ b/public/locales/pt/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Sim! Ative a opção \"Repetir\" e as páginas de sobreposição se repetirão em todas as páginas base. Uma marca d'água de uma página será aplicada a cada página.", "faqPrivacyQuestion": "Os meus ficheiros são privados e seguros?", "faqPrivacyAnswer": "Com certeza! Todo o processamento acontece no seu navegador. Os seus ficheiros nunca saem do seu dispositivo, garantindo total privacidade." + }, + "unlockPdf": { + "name": "Descriptografar PDF", + "subtitle": "Desbloqueie o PDF removendo a proteção por senha." + }, + "protectPdf": { + "name": "Criptografar PDF", + "subtitle": "Bloqueie seu PDF adicionando uma senha." } } diff --git a/public/locales/ru/tools.json b/public/locales/ru/tools.json index be9cac07..df75fec3 100644 --- a/public/locales/ru/tools.json +++ b/public/locales/ru/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Да! Включите опцию \"Повтор\" и страницы наложения будут повторяться на всех страницах базового файла. Одностраничный водяной знак будет применён к каждой странице.", "faqPrivacyQuestion": "Мои файлы конфиденциальны и защищены?", "faqPrivacyAnswer": "Безусловно! Вся обработка происходит в вашем браузере. Ваши файлы никогда не покидают ваше устройство, обеспечивая полную конфиденциальность." + }, + "unlockPdf": { + "name": "Расшифровка документа", + "subtitle": "Снять защиту документа, удалив пароль." + }, + "protectPdf": { + "name": "Шифрование документа", + "subtitle": "Защитить документ с помощью пароля." } } diff --git a/public/locales/sk/tools.json b/public/locales/sk/tools.json index b3af13b1..70c15f9a 100644 --- a/public/locales/sk/tools.json +++ b/public/locales/sk/tools.json @@ -1311,5 +1311,13 @@ "faqSinglePageAnswer": "Áno! Zapnite možnosť \"Opakovať\" a vaše PDF na prekrytie sa bude opakovať na všetkých stranách základu. Jednostranový vodoznak sa aplikuje na každú stranu.", "faqPrivacyQuestion": "Sú moje súbory v súkromí a v bezpečí?", "faqPrivacyAnswer": "Absolútne! Všetko spracovanie prebieha vo vašom prehliadači. Vaše súbory nikdy neopustia vaše zariadenie, čo zabezpečuje úplné súkromie." + }, + "unlockPdf": { + "name": "Dešifrovať PDF", + "subtitle": "Odomknúť PDF odstránením ochrany heslom." + }, + "protectPdf": { + "name": "Zašifrovať PDF", + "subtitle": "Uzamknúť vaše PDF pridaním hesla." } } diff --git a/public/locales/sv/tools.json b/public/locales/sv/tools.json index 5eba4cdf..1ea80ce5 100644 --- a/public/locales/sv/tools.json +++ b/public/locales/sv/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Ja! Aktivera alternativet \"Upprepa\" och dina överläggsidor upprepas på alla bassidor. En ensidig vattenstämpel tillämpas på varje sida.", "faqPrivacyQuestion": "Är mina filer privata och säkra?", "faqPrivacyAnswer": "Absolut! All bearbetning sker i din webbläsare. Dina filer lämnar aldrig din enhet, vilket garanterar fullständig integritet." + }, + "unlockPdf": { + "name": "Dekryptera PDF", + "subtitle": "Lås upp PDF genom att ta bort lösenordsskydd." + }, + "protectPdf": { + "name": "Kryptera PDF", + "subtitle": "Lås din PDF genom att lägga till ett lösenord." } } diff --git a/public/locales/tr/tools.json b/public/locales/tr/tools.json index dbb229ac..8026935a 100644 --- a/public/locales/tr/tools.json +++ b/public/locales/tr/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Evet! \"Tekrarla\" seçeneğini etkinleştirin ve üst katman sayfalarınız tüm temel sayfalarda tekrarlanır. Tek sayfalık bir filigran her sayfaya uygulanır.", "faqPrivacyQuestion": "Dosyalarım gizli ve güvende mi?", "faqPrivacyAnswer": "Kesinlikle! Tüm işleme tarayıcınızda gerçekleşir. Dosyalarınız cihazınızı asla terk etmez, tam gizlilik sağlanır." + }, + "unlockPdf": { + "name": "PDF'nin Şifresini Çöz", + "subtitle": "Şifre korumasını kaldırarak PDF'nin kilidini açın." + }, + "protectPdf": { + "name": "PDF'yi Şifrele", + "subtitle": "PDF'nizi şifre ekleyerek koruyun." } } diff --git a/public/locales/uk/tools.json b/public/locales/uk/tools.json index a1c470b9..d2415591 100644 --- a/public/locales/uk/tools.json +++ b/public/locales/uk/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Так! Увімкніть опцію «Повторювати», і сторінки накладання будуть застосовані до всіх сторінок. Один водяний знак — на всі сторінки.", "faqPrivacyQuestion": "Чи безпечні мої файли?", "faqPrivacyAnswer": "Так! Уся обробка відбувається у вашому браузері. Файли не покидають ваш пристрій." + }, + "unlockPdf": { + "name": "Розблокувати PDF", + "subtitle": "Видалити пароль і зняти захист PDF." + }, + "protectPdf": { + "name": "Зашифрувати PDF", + "subtitle": "Захистити PDF паролем." } } diff --git a/public/locales/vi/tools.json b/public/locales/vi/tools.json index c36b6f0e..97b34d62 100644 --- a/public/locales/vi/tools.json +++ b/public/locales/vi/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "Có! Bật tùy chọn \"Lặp lại\" và các trang chồng sẽ lặp lại trên tất cả các trang gốc. Hình mờ một trang sẽ được áp dụng cho mọi trang.", "faqPrivacyQuestion": "Tệp của tôi có được bảo mật không?", "faqPrivacyAnswer": "Chắc chắn! Toàn bộ quá trình xử lý diễn ra trong trình duyệt của bạn. Tệp của bạn không bao giờ rời khỏi thiết bị, đảm bảo quyền riêng tư hoàn toàn." + }, + "unlockPdf": { + "name": "Giải mã PDF", + "subtitle": "Mở khóa PDF bằng cách xóa bảo vệ mật khẩu." + }, + "protectPdf": { + "name": "Mã hóa PDF", + "subtitle": "Khóa PDF của bạn bằng cách thêm mật khẩu." } } diff --git a/public/locales/zh-TW/tools.json b/public/locales/zh-TW/tools.json index bcf27f0c..cf614d35 100644 --- a/public/locales/zh-TW/tools.json +++ b/public/locales/zh-TW/tools.json @@ -1311,5 +1311,13 @@ "faqSinglePageAnswer": "可以!啟用重複使用功能後,疊加 PDF 的頁面會在所有基礎頁面上重複套用。單頁浮水印會套用至每一頁。", "faqPrivacyQuestion": "我的檔案是否私密安全?", "faqPrivacyAnswer": "當然!所有處理都在您的瀏覽器中進行。您的檔案永遠不會離開您的裝置,確保完全隱私。" + }, + "unlockPdf": { + "name": "解密 PDF", + "subtitle": "透過移除密碼保護解鎖 PDF。" + }, + "protectPdf": { + "name": "加密 PDF", + "subtitle": "透過新增密碼為您的 PDF 上鎖。" } } diff --git a/public/locales/zh/tools.json b/public/locales/zh/tools.json index b155385f..c150c838 100644 --- a/public/locales/zh/tools.json +++ b/public/locales/zh/tools.json @@ -1312,5 +1312,13 @@ "faqSinglePageAnswer": "可以!启用\"循环\"选项,叠加页面将在所有基础页面上重复。单页水印将应用到每一页。", "faqPrivacyQuestion": "我的文件是否私密安全?", "faqPrivacyAnswer": "当然!所有处理都在您的浏览器中进行。您的文件永远不会离开您的设备,确保完全隐私。" + }, + "unlockPdf": { + "name": "解密 PDF", + "subtitle": "通过移除密码保护解锁 PDF。" + }, + "protectPdf": { + "name": "加密 PDF", + "subtitle": "通过添加密码锁定您的 PDF。" } } diff --git a/scripts/enhance-seo-pages.mjs b/scripts/enhance-seo-pages.mjs new file mode 100644 index 00000000..51ffd7be --- /dev/null +++ b/scripts/enhance-seo-pages.mjs @@ -0,0 +1,174 @@ +import fs from 'fs'; +import path from 'path'; +import { JSDOM } from 'jsdom'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const DIST_DIR = path.resolve(__dirname, '../dist'); +const SITE_URL = (process.env.SITE_URL || 'https://www.bentopdf.com').replace( + /\/+$/, + '' +); + +const FALLBACK_SOCIAL_IMAGE = '/images/og-tools.png'; + +function listTopLevelHtml() { + return fs + .readdirSync(DIST_DIR) + .filter((f) => f.endsWith('.html')) + .map((f) => path.join(DIST_DIR, f)); +} + +function imageExists(url) { + if (!url) return true; + let pathname; + try { + pathname = url.startsWith('http') ? new URL(url).pathname : url; + } catch { + return true; + } + if (!pathname.startsWith('/images/')) return true; + return fs.existsSync(path.join(DIST_DIR, pathname.replace(/^\//, ''))); +} + +function fixSocialImages(document) { + const selectors = ['meta[property="og:image"]', 'meta[name="twitter:image"]']; + for (const selector of selectors) { + for (const meta of document.querySelectorAll(selector)) { + const value = meta.getAttribute('content'); + if (!imageExists(value)) { + meta.setAttribute('content', `${SITE_URL}${FALLBACK_SOCIAL_IMAGE}`); + } + } + } +} + +function fixApplicationCategory(document) { + for (const script of document.querySelectorAll( + 'script[type="application/ld+json"]' + )) { + let data; + try { + data = JSON.parse(script.textContent || ''); + } catch { + continue; + } + if ( + data && + (data['@type'] === 'SoftwareApplication' || + data['@type'] === 'WebApplication') && + data.applicationCategory !== 'UtilitiesApplication' + ) { + data.applicationCategory = 'UtilitiesApplication'; + script.textContent = JSON.stringify(data, null, 2); + } + } +} + +function hasLdType(document, typeName) { + return [ + ...document.querySelectorAll('script[type="application/ld+json"]'), + ].some((s) => (s.textContent || '').includes(`"${typeName}"`)); +} + +function injectFaqSchema(document) { + if (hasLdType(document, 'FAQPage')) return false; + const items = []; + for (const details of document.querySelectorAll('details.faq-d')) { + const summary = details.querySelector('summary'); + const answer = details.querySelector('p'); + if (!summary || !answer) continue; + const question = summary.textContent.replace(/\s+/g, ' ').trim(); + const answerText = answer.textContent.replace(/\s+/g, ' ').trim(); + if (!question || !answerText) continue; + items.push({ + '@type': 'Question', + name: question, + acceptedAnswer: { '@type': 'Answer', text: answerText }, + }); + } + if (items.length === 0) return false; + const script = document.createElement('script'); + script.setAttribute('type', 'application/ld+json'); + script.textContent = JSON.stringify( + { + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: items, + }, + null, + 2 + ); + document.body.appendChild(script); + return true; +} + +function injectWebsiteSchema(document) { + if (hasLdType(document, 'WebSite')) return; + const script = document.createElement('script'); + script.setAttribute('type', 'application/ld+json'); + script.textContent = JSON.stringify( + { + '@context': 'https://schema.org', + '@type': 'WebSite', + name: 'BentoPDF', + alternateName: ['Bento PDF', 'BentoPDF.com'], + url: `${SITE_URL}/`, + }, + null, + 2 + ); + document.body.appendChild(script); +} + +function rewriteInternalLinks(document, knownSlugs) { + for (const link of document.querySelectorAll('a[href]')) { + const href = link.getAttribute('href'); + if (!href || /^(https?:|\/\/|#|mailto:|tel:|data:)/.test(href)) continue; + const match = href.match( + /^(?:\.\/|\/)?([a-z0-9][a-z0-9-]{0,64})\.html(#[^#]{0,128})?$/ + ); + if (!match) continue; + if (!knownSlugs.has(match[1])) continue; + const target = match[1] === 'index' ? '/' : `/${match[1]}`; + link.setAttribute('href', `${target}${match[2] || ''}`); + } +} + +function enhance() { + if (!fs.existsSync(DIST_DIR)) { + console.error('enhance-seo-pages: dist not found, run vite build first'); + process.exit(1); + } + const files = listTopLevelHtml(); + const knownSlugs = new Set(files.map((f) => path.basename(f, '.html'))); + + let faqSchemaCount = 0; + for (const file of files) { + const slug = path.basename(file, '.html'); + const dom = new JSDOM(fs.readFileSync(file, 'utf-8')); + const document = dom.window.document; + + fixSocialImages(document); + fixApplicationCategory(document); + rewriteInternalLinks(document, knownSlugs); + + if (slug === 'index') { + injectWebsiteSchema(document); + } + + if (slug !== '404') { + if (injectFaqSchema(document)) faqSchemaCount++; + } + + fs.writeFileSync(file, dom.serialize()); + dom.window.close(); + } + console.log( + `SEO enhance: ${files.length} pages processed, ${faqSchemaCount} FAQPage schemas added.` + ); +} + +enhance(); diff --git a/scripts/generate-blog.mjs b/scripts/generate-blog.mjs new file mode 100644 index 00000000..cc7c16d5 --- /dev/null +++ b/scripts/generate-blog.mjs @@ -0,0 +1,429 @@ +import fs from 'fs'; +import path from 'path'; +import { marked } from 'marked'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const POSTS_DIR = path.resolve(__dirname, '../blog/posts'); +const BLOG_DIR = path.resolve(__dirname, '../blog'); +const SITE_URL = 'https://www.bentopdf.com'; +const AUTHOR = { + name: 'Alam', + url: `${SITE_URL}/blog/author-alam`, + image: `${SITE_URL}/images/author-alam.jpg`, + profiles: [ + 'https://github.com/alam00000', + 'https://www.linkedin.com/in/abdullah-alam01/', + ], +}; + +const LINK_CLASS = 'text-indigo-300 hover:text-indigo-400'; + +function escapeHtml(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +function styleBody(html) { + return html + .replace(/

/g, '

') + .replace(/

/g, '

') + .replace(/

/g, '

') + .replace( + /

    /g, + '
      ' + ) + .replace( + /
        /g, + '
          ' + ) + .replace( + /#]/g, '') + .replace(/^\s*\d+\.\s+/gm, '') + .replace(/^\s*[-+]\s+/gm, '') + .replace(/\s+/g, ' ') + .trim(); +} + +function questionSections(body) { + const sections = []; + const parts = body.split(/^##\s+/m).slice(1); + for (const part of parts) { + const newline = part.indexOf('\n'); + const heading = (newline === -1 ? part : part.slice(0, newline)).trim(); + if (!heading.endsWith('?')) continue; + const answer = plainText(newline === -1 ? '' : part.slice(newline + 1)); + if (!answer) continue; + sections.push({ q: heading, a: answer.slice(0, 600) }); + } + return sections; +} + +function faqSchema(entries) { + if (entries.length === 0) return ''; + return ` + `; +} + +function renderFaqs(faqs) { + if (!faqs || faqs.length === 0) return ''; + const items = faqs + .map( + (f) => `
          + ${escapeHtml(f.q)} +

          + ${renderInline(f.a)} +

          +
          ` + ) + .join('\n'); + return ` +

          FAQ

          +
          +${items} +
          `; +} + +function renderCta(cta) { + if (!cta) return ''; + return ` +
          `; +} + +function renderPost({ slug, meta, body }) { + const url = `${SITE_URL}/blog/${slug}`; + const updated = meta.updated || meta.date; + const bodyHtml = styleBody(marked.parse(body)); + const faqEntries = + meta.faqs && meta.faqs.length > 0 ? meta.faqs : questionSections(body); + + return ` + + + + + ${escapeHtml(meta.title)} + + + + + + + + + + + + + + + + + + {{> navbar }} + +
          + + +

          + ${escapeHtml(meta.h1)} +

          + +
          + ${AUTHOR.name} +
          + ${AUTHOR.name}, + builds BentoPDF · + +
          +
          + +${bodyHtml} +${renderCta(meta.cta)} +${renderFaqs(meta.faqs)} +
          + + {{> footer }} + + + + + + ${faqSchema(faqEntries)} + + +`; +} + +function renderIndex(posts) { + const cards = posts + .map( + ({ slug, meta }) => ` +

          + ${escapeHtml(meta.h1)} +

          +

          + ${escapeHtml(meta.card)} +

          + ${formatDate(meta.date)} +
          ` + ) + .join('\n\n'); + + return ` + + + + + The BentoPDF Blog | Privacy-First PDF Guides + + + + + + + + + + + + + + + + + + {{> navbar }} + +
          +

          The BentoPDF Blog

          +

          + I'm Alam. I build + BentoPDF and write about PDFs, how they work, and the weird things I + run into along the way. +

          +
          + +
          +
          +${cards} +
          +
          + + {{> footer }} + + + + + + +`; +} + +function generate() { + if (!fs.existsSync(POSTS_DIR)) { + console.log('generate-blog: no blog/posts directory, skipping'); + return; + } + const files = fs + .readdirSync(POSTS_DIR) + .filter((f) => f.endsWith('.md')) + .sort(); + const posts = files.map(parsePost); + posts.sort((a, b) => (a.meta.date < b.meta.date ? 1 : -1)); + + const keep = new Set(['index.html', 'author-alam.html']); + for (const post of posts) { + fs.writeFileSync( + path.join(BLOG_DIR, `${post.slug}.html`), + renderPost(post) + ); + keep.add(`${post.slug}.html`); + } + fs.writeFileSync(path.join(BLOG_DIR, 'index.html'), renderIndex(posts)); + + for (const entry of fs.readdirSync(BLOG_DIR)) { + if (entry.endsWith('.html') && !keep.has(entry)) { + fs.rmSync(path.join(BLOG_DIR, entry)); + console.log(`generate-blog: removed stale ${entry}`); + } + } + + console.log( + `generate-blog: ${posts.length} posts + index generated from blog/posts/` + ); +} + +generate(); diff --git a/scripts/generate-i18n-pages.mjs b/scripts/generate-i18n-pages.mjs index b65b0271..01af4cd5 100644 --- a/scripts/generate-i18n-pages.mjs +++ b/scripts/generate-i18n-pages.mjs @@ -59,7 +59,47 @@ function buildUrl(langPrefix, pagePath) { if (BASE_PATH && BASE_PATH !== '') parts.push(BASE_PATH.replace(/^\//, '')); if (langPrefix) parts.push(langPrefix); if (pagePath) parts.push(pagePath.replace(/^\//, '')); - return parts.filter(Boolean).join('/').replace(/\/+$/, '') || SITE_URL; + const url = parts.filter(Boolean).join('/').replace(/\/+$/, '') || SITE_URL; + return langPrefix && !pagePath ? `${url}/` : url; +} + +function resolveTranslation(langResources, key) { + let namespace = 'common'; + let keyPath = key; + const colonIndex = key.indexOf(':'); + if (colonIndex !== -1) { + namespace = key.slice(0, colonIndex); + keyPath = key.slice(colonIndex + 1); + } + let node = langResources[namespace]; + for (const segment of keyPath.split('.')) { + if (node == null || typeof node !== 'object') return null; + node = node[segment]; + } + return typeof node === 'string' && node ? node : null; +} + +function applyServerTranslations(document, langResources) { + document.querySelectorAll('[data-i18n]').forEach((element) => { + const key = element.getAttribute('data-i18n'); + if (!key) return; + const translation = resolveTranslation(langResources, key); + if (translation) element.textContent = translation; + }); + + document.querySelectorAll('[data-i18n-placeholder]').forEach((element) => { + const key = element.getAttribute('data-i18n-placeholder'); + if (!key) return; + const translation = resolveTranslation(langResources, key); + if (translation) element.setAttribute('placeholder', translation); + }); + + document.querySelectorAll('[data-i18n-title]').forEach((element) => { + const key = element.getAttribute('data-i18n-title'); + if (!key) return; + const translation = resolveTranslation(langResources, key); + if (translation) element.setAttribute('title', translation); + }); } const ORGANIZATION_LD_MARKER = 'data-bentopdf-organization'; @@ -105,10 +145,24 @@ function buildLocalHomeHref(lang) { return `${BASE_PATH}${langSegment}`.replace(/\/+/g, '/'); } +function removeStaticBreadcrumbLd(document) { + for (const script of document.querySelectorAll( + `script[type="application/ld+json"]:not([${BREADCRUMB_MARKER}])` + )) { + try { + const parsed = JSON.parse(script.textContent || ''); + if (parsed && parsed['@type'] === 'BreadcrumbList') script.remove(); + } catch { + continue; + } + } +} + function injectToolBreadcrumb(document, lang, toolName, toolUrl) { const h1 = document.querySelector('h1[data-i18n^="tools:"]'); if (!h1) return; if (document.querySelector(`[${BREADCRUMB_MARKER}]`)) return; + removeStaticBreadcrumbLd(document); const homeUrl = buildUrl(lang === 'en' ? '' : lang, ''); @@ -191,6 +245,8 @@ function processFileForLanguage( document.documentElement.lang = lang; document.documentElement.dir = lang === 'ar' ? 'rtl' : 'ltr'; + applyServerTranslations(document, translations[lang]); + let title = null; let description = null; @@ -247,14 +303,13 @@ function processFileForLanguage( document.head.appendChild(defaultLink); const localizedUrl = buildUrl(lang, pagePath); - const canonicalUrl = buildUrl('', pagePath); let canonical = document.querySelector('link[rel="canonical"]'); if (!canonical) { canonical = document.createElement('link'); canonical.rel = 'canonical'; document.head.appendChild(canonical); } - canonical.href = canonicalUrl; + canonical.href = localizedUrl; const ogUrl = document.querySelector('meta[property="og:url"]'); if (ogUrl) ogUrl.content = localizedUrl; @@ -288,6 +343,8 @@ function processFileForLanguage( if (href.startsWith('/assets/') || href.includes('/assets/')) return; + if (href === '/blog' || href.startsWith('/blog/')) return; + const langPrefixRegex = new RegExp( `^(${BASE_PATH})?/(${languages.join('|')})(/|$)` ); diff --git a/scripts/generate-sitemap.mjs b/scripts/generate-sitemap.mjs index 9a6f87f8..019d01fe 100644 --- a/scripts/generate-sitemap.mjs +++ b/scripts/generate-sitemap.mjs @@ -1,5 +1,6 @@ import fs from 'fs'; import path from 'path'; +import { execFileSync } from 'child_process'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); @@ -32,9 +33,17 @@ const PRIORITY_MAP = { 'excel-to-pdf': 0.9, 'powerpoint-to-pdf': 0.9, 'jpg-to-pdf': 0.9, - 'pdf-to-docx': 0.9, + 'pdf-to-word': 0.9, + 'unlock-pdf': 0.9, + 'protect-pdf': 0.9, 'pdf-to-excel': 0.9, 'pdf-to-jpg': 0.9, + 'compress-pdf-to-100kb': 0.8, + 'compress-pdf-to-200kb': 0.8, + 'compress-pdf-to-500kb': 0.8, + 'compress-pdf-to-1mb': 0.8, + 'compress-pdf-to-2mb': 0.8, + 'compress-pdf-for-email': 0.8, about: 0.8, faq: 0.8, contact: 0.7, @@ -52,7 +61,7 @@ function buildUrl(lang, pageName) { if (lang === 'en') { return pagePath ? `${SITE_URL}/${pagePath}` : SITE_URL; } - return pagePath ? `${SITE_URL}/${lang}/${pagePath}` : `${SITE_URL}/${lang}`; + return pagePath ? `${SITE_URL}/${lang}/${pagePath}` : `${SITE_URL}/${lang}/`; } function generateSitemap() { @@ -66,22 +75,48 @@ function generateSitemap() { .map((file) => file.replace('.html', '')) .filter((name) => !EXCLUDED_PAGES.has(name)); + const projectRoot = path.resolve(__dirname, '..'); const lastModCache = new Map(); - const getLastMod = (lang, pageName) => { - const cacheKey = `${lang}::${pageName}`; - if (lastModCache.has(cacheKey)) return lastModCache.get(cacheKey); + const getLastMod = (pageName) => { + if (lastModCache.has(pageName)) return lastModCache.get(pageName); const fileName = `${pageName}.html`; - const filePath = - lang === 'en' - ? path.join(DIST_DIR, fileName) - : path.join(DIST_DIR, lang, fileName); - let iso; - try { - iso = fs.statSync(filePath).mtime.toISOString().slice(0, 10); - } catch { - iso = new Date().toISOString().slice(0, 10); + const candidates = [ + path.join(projectRoot, 'src', 'pages', fileName), + path.join(projectRoot, fileName), + ]; + let iso = null; + for (const sourcePath of candidates) { + if (!fs.existsSync(sourcePath)) continue; + try { + const out = execFileSync( + 'git', + ['log', '-1', '--format=%cI', '--', sourcePath], + { cwd: projectRoot, encoding: 'utf-8' } + ).trim(); + if (out) iso = out.slice(0, 10); + } catch { + iso = null; + } + if (!iso) { + try { + iso = fs.statSync(sourcePath).mtime.toISOString().slice(0, 10); + } catch { + iso = null; + } + } + break; } - lastModCache.set(cacheKey, iso); + if (!iso) { + try { + iso = fs + .statSync(path.join(DIST_DIR, fileName)) + .mtime.toISOString() + .slice(0, 10); + } catch { + iso = new Date().toISOString().slice(0, 10); + } + } + lastModCache.set(pageName, iso); return iso; }; @@ -93,12 +128,11 @@ function generateSitemap() { for (const pageName of htmlFiles) { const priority = getPriority(pageName); const url = buildUrl('en', pageName); - const lastmod = getLastMod('en', pageName); + const lastmod = getLastMod(pageName); sitemap += ` ${url} ${lastmod} - weekly ${priority} `; @@ -114,6 +148,48 @@ function generateSitemap() { `; } + const blogDir = path.join(DIST_DIR, 'blog'); + let blogCount = 0; + if (fs.existsSync(blogDir)) { + const blogFiles = fs + .readdirSync(blogDir) + .filter((file) => file.endsWith('.html')) + .map((file) => file.replace('.html', '')); + for (const name of blogFiles) { + const url = + name === 'index' ? `${SITE_URL}/blog/` : `${SITE_URL}/blog/${name}`; + const sourcePath = path.join(projectRoot, 'blog', `${name}.html`); + let lastmod; + try { + const out = execFileSync( + 'git', + ['log', '-1', '--format=%cI', '--', sourcePath], + { cwd: projectRoot, encoding: 'utf-8' } + ).trim(); + lastmod = out ? out.slice(0, 10) : null; + } catch { + lastmod = null; + } + if (!lastmod) { + try { + lastmod = fs.statSync(sourcePath).mtime.toISOString().slice(0, 10); + } catch { + lastmod = new Date().toISOString().slice(0, 10); + } + } + sitemap += ` + ${url} + ${lastmod} + 0.7 + +`; + blogCount++; + } + } + if (blogCount > 0) { + console.log(` Blog: ${blogCount} URLs added (English only)`); + } + sitemap += ` `; diff --git a/scripts/generate-static-tool-links.mjs b/scripts/generate-static-tool-links.mjs new file mode 100644 index 00000000..c0bc4756 --- /dev/null +++ b/scripts/generate-static-tool-links.mjs @@ -0,0 +1,106 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const TOOLS_CONFIG = path.resolve(__dirname, '../src/js/config/tools.ts'); +const PAGES_DIR = path.resolve(__dirname, '../src/pages'); +const PARTIAL_PATH = path.resolve( + __dirname, + '../src/partials/tool-links-static.html' +); + +function escapeHtml(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +function unescapeTs(value) { + return value.replace(/\\'/g, "'").replace(/\\\\/g, '\\'); +} + +function parseCategories(source) { + const headers = [ + ...source.matchAll(/name:\s*'((?:[^'\\]|\\.)*)',\s*\n\s*tools:\s*\[/g), + ].map((m) => ({ name: unescapeTs(m[1]), index: m.index })); + + const toolMatches = [ + ...source.matchAll( + /\{[^{}]*?href:\s*import\.meta\.env\.BASE_URL\s*\+\s*'((?:[^'\\]|\\.)*)'[^{}]*?\}/gs + ), + ]; + const categories = headers.map((h) => ({ name: h.name, tools: [] })); + for (const match of toolMatches) { + const block = match[0]; + const hrefFile = unescapeTs(match[1]); + const nameMatch = block.match(/name:\s*'((?:[^'\\]|\\.)*)'/s); + const subtitleMatch = block.match(/subtitle:\s*\n?\s*'((?:[^'\\]|\\.)*)'/s); + if (!nameMatch) continue; + + let categoryIndex = -1; + for (let i = 0; i < headers.length; i++) { + if (headers[i].index < match.index) categoryIndex = i; + } + if (categoryIndex === -1) continue; + + categories[categoryIndex].tools.push({ + slug: hrefFile.replace(/\.html$/, ''), + name: unescapeTs(nameMatch[1]), + subtitle: subtitleMatch ? unescapeTs(subtitleMatch[1]) : '', + }); + } + return categories.filter((c) => c.tools.length > 0); +} + +function generate() { + const source = fs.readFileSync(TOOLS_CONFIG, 'utf-8'); + const categories = parseCategories(source); + const existingPages = new Set( + fs + .readdirSync(PAGES_DIR) + .filter((f) => f.endsWith('.html')) + .map((f) => f.replace(/\.html$/, '')) + ); + + const seen = new Set(); + const lines = []; + let toolCount = 0; + for (const category of categories) { + const tools = category.tools.filter( + (t) => existingPages.has(t.slug) && !seen.has(t.slug) + ); + if (tools.length === 0) continue; + for (const t of tools) seen.add(t.slug); + lines.push( + `

          ${escapeHtml(category.name)}

          ` + ); + for (const tool of tools) { + toolCount++; + lines.push( + `` + + `

          ${escapeHtml(tool.name)}

          ` + + `

          ${escapeHtml(tool.subtitle)}

          ` + + `
          ` + ); + } + } + + if (toolCount < 50) { + console.error( + `generate-static-tool-links: only ${toolCount} tools parsed from tools.ts — parser is likely out of sync with the config format` + ); + process.exit(1); + } + + fs.writeFileSync(PARTIAL_PATH, lines.join('\n') + '\n'); + console.log( + `Static tool links: ${toolCount} tools in ${categories.length} categories -> src/partials/tool-links-static.html` + ); +} + +generate(); diff --git a/scripts/include-docs-in-dist.js b/scripts/include-docs-in-dist.js index 64c4b935..12bee6a7 100644 --- a/scripts/include-docs-in-dist.js +++ b/scripts/include-docs-in-dist.js @@ -11,46 +11,95 @@ const mainDistPath = path.join(projectRoot, 'dist'); const targetDocsPath = path.join(mainDistPath, 'docs'); function copyDir(src, dest) { - if (!fs.existsSync(dest)) { - fs.mkdirSync(dest, { recursive: true }); - } + if (!fs.existsSync(dest)) { + fs.mkdirSync(dest, { recursive: true }); + } - const entries = fs.readdirSync(src, { withFileTypes: true }); + const entries = fs.readdirSync(src, { withFileTypes: true }); - for (const entry of entries) { - const srcPath = path.join(src, entry.name); - const destPath = path.join(dest, entry.name); + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); - if (entry.isDirectory()) { - copyDir(srcPath, destPath); - } else { - fs.copyFileSync(srcPath, destPath); - } + if (entry.isDirectory()) { + copyDir(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); } + } } console.log('Including docs in dist...'); if (!fs.existsSync(docsDistPath)) { - console.error('Error: Docs build not found. Please run "npm run docs:build" first.'); - process.exit(1); + console.error( + 'Error: Docs build not found. Please run "npm run docs:build" first.' + ); + process.exit(1); } if (!fs.existsSync(mainDistPath)) { - console.error('Error: Main dist folder not found. Please run "npm run build" first.'); - process.exit(1); + console.error( + 'Error: Main dist folder not found. Please run "npm run build" first.' + ); + process.exit(1); } try { - console.log(`Copying from: ${docsDistPath}`); - console.log(`Copying to: ${targetDocsPath}`); + console.log(`Copying from: ${docsDistPath}`); + console.log(`Copying to: ${targetDocsPath}`); - copyDir(docsDistPath, targetDocsPath); + copyDir(docsDistPath, targetDocsPath); - console.log('Docs successfully included in dist/docs!'); + console.log('Docs successfully included in dist/docs!'); - const files = fs.readdirSync(targetDocsPath); - console.log(`Copied ${files.length} items to dist/docs`); + const files = fs.readdirSync(targetDocsPath); + console.log(`Copied ${files.length} items to dist/docs`); + + addDocsToSitemap(); } catch (error) { - console.error('Error copying docs:', error.message); - process.exit(1); + console.error('Error copying docs:', error.message); + process.exit(1); +} + +function listDocsHtml(dir, prefix) { + const urls = []; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (entry.isDirectory()) { + if (entry.name === 'assets' || entry.name.startsWith('.')) continue; + urls.push( + ...listDocsHtml(path.join(dir, entry.name), `${prefix}/${entry.name}`) + ); + } else if (entry.name.endsWith('.html') && entry.name !== '404.html') { + const slug = entry.name.replace(/\.html$/, ''); + urls.push(slug === 'index' ? `${prefix}/` : `${prefix}/${slug}`); + } + } + return urls; +} + +function addDocsToSitemap() { + const siteUrl = (process.env.SITE_URL || 'https://www.bentopdf.com').replace( + /\/+$/, + '' + ); + const sitemapPath = path.join(mainDistPath, 'sitemap.xml'); + if (!fs.existsSync(sitemapPath)) { + console.warn( + 'sitemap.xml not found in dist; skipping docs sitemap entries' + ); + return; + } + let xml = fs.readFileSync(sitemapPath, 'utf-8'); + if (xml.includes(`${siteUrl}/docs/`)) return; + + const urls = listDocsHtml(targetDocsPath, '/docs'); + const entries = urls + .map( + (url) => + ` \n ${siteUrl}${url}\n 0.6\n \n` + ) + .join(''); + xml = xml.replace('', `${entries}`); + fs.writeFileSync(sitemapPath, xml); + console.log(`Added ${urls.length} docs URLs to sitemap.xml`); } diff --git a/scripts/seo-audit.mjs b/scripts/seo-audit.mjs index ba866cee..d9fbce93 100644 --- a/scripts/seo-audit.mjs +++ b/scripts/seo-audit.mjs @@ -67,6 +67,12 @@ function findAll(html, regex) { return out; } +const LOCALE_DIRS = new Set( + fs + .readdirSync(LOCALES_DIR) + .filter((d) => fs.statSync(path.join(LOCALES_DIR, d)).isDirectory()) +); + function expectedCanonicalForFile(rel) { const parts = rel.split('/'); const fileName = parts.pop(); @@ -74,12 +80,40 @@ function expectedCanonicalForFile(rel) { const slug = baseName === 'index' ? '' : baseName; const segments = [SITE_URL]; if (BASE_PATH) segments.push(BASE_PATH.replace(/^\//, '')); + for (const dir of parts) { + if (LOCALE_DIRS.has(dir) || dir === 'blog') segments.push(dir); + } if (slug) segments.push(slug); return segments.join('/').replace(/\/+$/, '') || SITE_URL; } -function auditHtml(file) { +function auditHtml(file, knownSlugs) { const html = fs.readFileSync(file.full, 'utf-8'); + const isLocalized = file.rel.split('/').some((seg) => LOCALE_DIRS.has(seg)); + + if (!isLocalized && /[—–]/.test(html)) { + fail( + 'em-dash', + `${file.rel}: contains an em or en dash (house style forbids them)` + ); + } + + if (!isLocalized) { + const internal = findAll(html, /]+href=["'](\/[^"'#?]*)["']/g); + for (const href of internal) { + const clean = href.replace(/\/$/, ''); + if (clean === '') continue; + const seg = clean.slice(1); + if (seg.includes('/')) continue; + if (LOCALE_DIRS.has(seg) || seg === 'blog' || seg === 'docs') continue; + if (!knownSlugs.has(seg)) { + fail( + 'dead-link', + `${file.rel}: links to "${href}" but no such page exists in dist` + ); + } + } + } const titles = findAll(html, /]*>[\s\S]*?<\/title>/g); if (titles.length === 0) { fail('title', `${file.rel}: no `); @@ -147,7 +181,7 @@ function auditHtml(file) { ); } - const emptyI18n = html.match(/<span[^>]*data-i18n="[^"]+"[^>]*>\s*<\/span>/g); + const emptyI18n = html.match(/<span[^>]*data-i18n="[^"]+"[^>]*><\/span>/g); if (emptyI18n && emptyI18n.length > 0) { fail( 'data-i18n', @@ -176,10 +210,76 @@ function auditHtml(file) { `${file.rel}: hreflang href host "${url.hostname}" != expected "${HOST}"` ); } + const trimmed = url.pathname.replace(/^\/|\/$/g, ''); + if (LOCALE_DIRS.has(trimmed) && !url.pathname.endsWith('/')) { + fail( + 'hreflang', + `${file.rel}: language-home hreflang "${m[1]}" must end with "/" (the server 301s the slashless form)` + ); + } } catch { fail('hreflang', `${file.rel}: hreflang href "${m[1]}" not a valid URL`); } } + + const descriptions = findAll( + html, + /<meta[^>]+name=["']description["'][^>]*content=["']([^"']*)["']/g + ); + if (descriptions.length > 1) { + fail( + 'description', + `${file.rel}: ${descriptions.length} meta description tags (expected 1)` + ); + } + for (const desc of descriptions) { + if (desc.includes('★')) { + fail('description', `${file.rel}: meta description contains "★"`); + } + } + + const isTopLevel = !file.rel.includes('/'); + if (isTopLevel) { + const socialImages = findAll( + html, + /<meta[^>]+(?:property=["']og:image["']|name=["']twitter:image["'])[^>]*content=["']([^"']+)["']/g + ); + for (const image of socialImages) { + let pathname; + try { + pathname = image.startsWith('http') ? new URL(image).pathname : image; + } catch { + continue; + } + if ( + pathname.startsWith('/images/') && + !fs.existsSync(path.join(DIST_DIR, pathname.replace(/^\//, ''))) + ) { + fail( + 'social-image', + `${file.rel}: og/twitter image "${pathname}" does not exist in dist` + ); + } + } + + if (html.includes('faq-d') && !html.includes('"FAQPage"')) { + fail( + 'faq-schema', + `${file.rel}: visible FAQ section without FAQPage JSON-LD` + ); + } + + const internalHtmlLinks = findAll( + html, + /<a[^>]+href=["'](\/?[a-z0-9][a-z0-9-]*\.html)["']/g + ); + for (const href of internalHtmlLinks) { + fail( + 'internal-link', + `${file.rel}: internal link "${href}" should be extensionless` + ); + } + } } function auditSitemap() { @@ -248,7 +348,12 @@ function main() { fail('audit', 'no HTML files found in dist/'); } - for (const file of files) auditHtml(file); + const knownSlugs = new Set( + files + .filter((f) => !f.rel.includes('/')) + .map((f) => f.rel.replace(/\.html$/, '')) + ); + for (const file of files) auditHtml(file, knownSlugs); auditSitemap(); const total = failures.length + warnings.length; diff --git a/src/js/config/tools.ts b/src/js/config/tools.ts index 88b67fd1..9b55ab7e 100644 --- a/src/js/config/tools.ts +++ b/src/js/config/tools.ts @@ -499,7 +499,7 @@ const baseCategories = [ subtitle: 'Convert PDF files to JSON format.', }, { - href: import.meta.env.BASE_URL + 'pdf-to-docx.html', + href: import.meta.env.BASE_URL + 'pdf-to-word.html', name: 'PDF to Word', icon: 'ph-microsoft-word-logo', subtitle: 'Convert PDF files to editable Word documents.', @@ -778,10 +778,10 @@ const baseCategories = [ name: 'Secure PDF', tools: [ { - href: import.meta.env.BASE_URL + 'encrypt-pdf.html', - name: 'Encrypt PDF', + href: import.meta.env.BASE_URL + 'protect-pdf.html', + name: 'Protect PDF', icon: 'ph-lock', - subtitle: 'Lock your PDF by adding a password.', + subtitle: 'Password protect a PDF with strong AES encryption.', }, { href: import.meta.env.BASE_URL + 'sanitize-pdf.html', @@ -790,10 +790,10 @@ const baseCategories = [ subtitle: 'Remove metadata, annotations, scripts, and more.', }, { - href: import.meta.env.BASE_URL + 'decrypt-pdf.html', - name: 'Decrypt PDF', + href: import.meta.env.BASE_URL + 'unlock-pdf.html', + name: 'Unlock PDF', icon: 'ph-lock-open', - subtitle: 'Unlock PDF by removing password protection.', + subtitle: 'Remove the password from a PDF so it opens freely.', }, { href: import.meta.env.BASE_URL + 'flatten-pdf.html', diff --git a/src/js/logic/pdf-to-docx-page.ts b/src/js/logic/pdf-to-word-page.ts similarity index 100% rename from src/js/logic/pdf-to-docx-page.ts rename to src/js/logic/pdf-to-word-page.ts diff --git a/src/js/logic/encrypt-pdf-page.ts b/src/js/logic/protect-pdf-page.ts similarity index 100% rename from src/js/logic/encrypt-pdf-page.ts rename to src/js/logic/protect-pdf-page.ts diff --git a/src/js/logic/decrypt-pdf-page.ts b/src/js/logic/unlock-pdf-page.ts similarity index 100% rename from src/js/logic/decrypt-pdf-page.ts rename to src/js/logic/unlock-pdf-page.ts diff --git a/src/js/utils/disabled-tools.ts b/src/js/utils/disabled-tools.ts index 5f35c622..cf759288 100644 --- a/src/js/utils/disabled-tools.ts +++ b/src/js/utils/disabled-tools.ts @@ -1,6 +1,18 @@ import type { AppConfig } from '@/types'; -const disabledToolsSet = new Set<string>(__DISABLED_TOOLS__); +const RENAMED_TOOL_IDS: Record<string, string> = { + 'decrypt-pdf': 'unlock-pdf', + 'encrypt-pdf': 'protect-pdf', + 'pdf-to-docx': 'pdf-to-word', +}; + +function normalizeToolId(toolId: string): string { + return RENAMED_TOOL_IDS[toolId] ?? toolId; +} + +const disabledToolsSet = new Set<string>( + __DISABLED_TOOLS__.map(normalizeToolId) +); let runtimeConfigLoaded = false; let editorDisabledCategories: string[] = []; @@ -23,7 +35,7 @@ export async function loadRuntimeConfig(): Promise<void> { if (Array.isArray(config.disabledTools)) { for (const toolId of config.disabledTools) { if (typeof toolId === 'string') { - disabledToolsSet.add(toolId); + disabledToolsSet.add(normalizeToolId(toolId)); } } } diff --git a/src/js/workflow/nodes/registry.ts b/src/js/workflow/nodes/registry.ts index 2525c2a3..48bdf156 100644 --- a/src/js/workflow/nodes/registry.ts +++ b/src/js/workflow/nodes/registry.ts @@ -557,7 +557,7 @@ export const nodeRegistry: Record<string, NodeRegistryEntry> = { icon: 'ph-lock', description: 'Encrypt PDF with password', factory: () => new EncryptNode(), - toolPageId: 'encrypt-pdf', + toolPageId: 'protect-pdf', }, DecryptNode: { label: 'Decrypt', @@ -565,7 +565,7 @@ export const nodeRegistry: Record<string, NodeRegistryEntry> = { icon: 'ph-lock-open', description: 'Remove PDF password protection', factory: () => new DecryptNode(), - toolPageId: 'decrypt-pdf', + toolPageId: 'unlock-pdf', }, SanitizeNode: { label: 'Sanitize', @@ -653,7 +653,7 @@ export const nodeRegistry: Record<string, NodeRegistryEntry> = { icon: 'ph-microsoft-word-logo', description: 'Convert PDF to Word document', factory: () => new PdfToDocxNode(), - toolPageId: 'pdf-to-docx', + toolPageId: 'pdf-to-word', }, PdfToXlsxNode: { label: 'PDF to XLSX', diff --git a/src/pages/add-attachments.html b/src/pages/add-attachments.html index df3cf972..b9f9f4d1 100644 --- a/src/pages/add-attachments.html +++ b/src/pages/add-attachments.html @@ -11,7 +11,7 @@ /> <meta name="description" - content="★ Add Attachments online free - Add attachments PDFs easily ★ No signup ★ Unlimited files ★ Privacy-first ★ Works in browser ★ Fast & secure" + content="Embed one or more files into your PDF. Free, no uploads, no signup. Runs entirely in your browser." /> <meta name="keywords" content="add attachments, online pdf" /> <meta name="author" content="BentoPDF" /> @@ -35,7 +35,7 @@ /> <meta property="og:description" - content="★ Add Attachments online free - Add attachments PDFs easily ★ No signup ★ Unlimited files ★ Privacy-first ★ Works in browser ★ Fast & secure" + content="Embed one or more files into your PDF. Free, no uploads, no signup. Runs entirely in your browser." /> <meta property="og:image" @@ -54,7 +54,7 @@ <meta name="twitter:title" content="Add Attachments Free" /> <meta name="twitter:description" - content="★ Add Attachments online free - Add attachments PDFs easily ★ No signup ★ Unlimited files ★ Privacy-first ★ Works in browser" + content="Embed one or more files into your PDF. Free, no uploads, no signup. Runs entirely in your browser." /> <meta name="twitter:image" @@ -68,10 +68,6 @@ <meta name="apple-mobile-web-app-title" content="Add Attachments" /> <title>Add Attachments to PDF - BentoPDF - @@ -389,32 +385,115 @@
          - Is add attachments really free? + What kinds of files can I embed in a PDF?

          - Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Any file type: spreadsheets, images, ZIP archives, CAD drawings, + even executables. The tool doesn't inspect or convert the file; it + stores the bytes inside the PDF under the original file name, and + you can embed several files in one pass.

          - Are my files private and secure? + What's the difference between document-level and page-level + attachments?

          - Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Document-level attachments belong to the PDF as a whole and appear + in the reader's attachments panel. Page-level attachments are tied + to the pages you list in the page range field (for example 1,3,5-7), + and the same file is attached to every page in that range. Document + level is the safer choice, since some viewers never show page-level + attachments.

          - Is there a file size limit? + Where do the attached files show up when someone opens the PDF?

          - No! Process files of any size, as many times as you want, completely - free. + In readers that have an attachments panel, such as Adobe Acrobat + Reader or Firefox's built-in viewer, they're listed by file name and + can be opened or saved from there. Viewers without that panel won't + show them at all, although the files are still inside the PDF. +

          +
          +
          + + Does embedding files make the PDF bigger? + + +

          + Yes, by roughly the size of each attachment, since the file's bytes + are stored inside the PDF. A 40 MB spreadsheet attached to a 1 MB + report yields a PDF of about 41 MB, so keep attachment size in mind + before emailing the result. +

          +
          +
          + + Is the file I attach uploaded anywhere when I embed it? + + +

          + No. The PDF and the attachments are read and combined in your + browser by the CoherentPDF WebAssembly module, and the result is + downloaded straight from the page. Nothing is sent to a server. +

          +
          +
          + + Why does the tool say an advanced processing module is required? + + +

          + Embedding uses the CoherentPDF (cpdf) module, which loads on demand + from a CDN the first time you use it rather than shipping with the + main site. If you self-host BentoPDF or work in an air-gapped setup, + you can point the tool at your own copy of the module on the + Advanced Features settings + page. +

          +
          +
          + + Can I remove an attachment later? + + +

          + Yes. + Edit Attachments + lists every embedded file and lets you remove individual ones or all + of them, and Extract Attachments saves them back out as separate + downloads. +

          +
          +
          + + Will attaching files break a digital signature on the PDF? + + +

          + Yes. Adding attachments rewrites the file, which invalidates any + existing digital signature. Attach the files first, then sign the + finished PDF with + Digital Sign PDF.

          diff --git a/src/pages/add-blank-page.html b/src/pages/add-blank-page.html index 054d4f3a..17cc878e 100644 --- a/src/pages/add-blank-page.html +++ b/src/pages/add-blank-page.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ /> Add Blank Page - BentoPDF - @@ -377,32 +373,105 @@
          - Is add blank page really free? + Where will the blank page be inserted?

          - Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + The position number is how many existing pages come before the new + blank pages. Enter 0 to put them at the very start, 3 to insert them + after page 3, or the total page count to append them at the end.

          - Are my files private and secure? + What size are the blank pages?

          - Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Each blank page copies the width and height of your document's first + page, so a Letter document gets Letter blanks and an A4 document + gets A4 blanks. If your PDF mixes page sizes, the blanks still match + page 1 rather than the pages next to them.

          - Is there a file size limit? + Can I add more than one blank page at a time?

          - No! Process files of any size, as many times as you want, completely - free. + Enter any count of 1 or more and all of them are inserted together + at the same position. To add blanks at several different spots, run + the tool again on the output, or use + PDF Multi Tool + to arrange pages visually. +

          +
          +
          + + Does it keep bookmarks and document properties? + + +

          + Page content, images, text, and annotations on the pages are kept as + they are. The document is rebuilt page by page, so bookmarks (the + outline panel) and properties such as title and author aren't + carried over to the new file. +

          +
          +
          + + Is the inserted page completely empty? + + +

          + Yes. It has no text, no page number, and no printed note, just a + white page of the same size as page 1. If you want page numbers on + it afterward, run the result through + Page Numbers. +

          +
          +
          + + Can I use this to make every chapter start on a right-hand page for + double-sided printing? + + +

          + You can, one position per run. Insert a blank after each chapter + that ends on an odd page, download, then repeat on the new file for + the next chapter. The output keeps the original filename, so rename + copies as you go to avoid mixing them up. +

          +
          +
          + + Can I add blank pages to a password-protected PDF? + + +

          + If the file needs a password to open, the tool asks for it before + reading the page count. The new file is saved without the password, + so protect it again afterward if you need to. +

          +
          +
          + + Is my PDF uploaded to add the page? + + +

          + No. The page count is read and the new document is assembled in your + browser with pdf-lib, a JavaScript PDF library, and the download + comes straight from memory. Nothing is sent to a server.

          diff --git a/src/pages/add-page-labels.html b/src/pages/add-page-labels.html index 30d36ceb..7caa68a6 100644 --- a/src/pages/add-page-labels.html +++ b/src/pages/add-page-labels.html @@ -465,39 +465,105 @@
          - What is a page label? + How do I label appendix pages A-1, A-2, A-3? -

          - A page label is the numbering shown by PDF readers in thumbnails, - page navigation, and print dialogs. It does not print new text onto - the page itself. +

          + Add a rule for the appendix page range, keep Decimal Arabic as the + style, and type A- in the Label Prefix field. With the default start + value of 1 the pages become A-1, A-2, A-3, and a second rule with + the prefix B- handles the next appendix.

          - Can I mix Roman numerals and normal numbers? + Can page numbering start at 0 or at a number other than 1? -

          - Yes. Add multiple rules, such as 1-4 with LowercaseRoman and 5-20 - with DecimalArabic. +

          + Each rule has a Start Value field that defaults to 1. Set it to 0 + for zero-based numbering, or to any other number, for example 15 so + a chapter extracted from a longer book keeps its original page + numbers.

          - Do my files stay private? + What does 'Continue numbering across disjoint ranges' do? -

          - Yes. The processing happens in your browser using CoherentPDF WASM. - Your PDF does not leave your device. +

          + Turn it on when one rule covers pages that aren't contiguous, such + as 1-9,30-40 or odd, and you want the labels to keep counting in + sequence across the gap. With it off, each separate block of pages + starts again from the start value. +

          +
          +
          + + What happens to the page labels the PDF already has? + + +

          + The 'Remove existing page labels' box is checked by default, so the + old labels are cleared before your rules are applied. Uncheck it if + you only want to relabel some pages and keep the existing labels on + the rest. +

          +
          +
          + + Which page range formats can I type? + + +

          + Leave the field empty to cover every page, or use forms like 1-4, 7, + odd, or 1-9,30-40. Page numbers refer to physical positions in the + file, not to labels the PDF may already display. +

          +
          +
          + + Can I add labels to a password-protected PDF? + + +

          + Not directly. The tool stops with a Protected PDF message, so remove + the password first with + Unlock PDF + and then upload the copy that no longer needs one. +

          +
          +
          + + Why does the tool ask me to configure CoherentPDF? + + +

          + Page labels are written by the CoherentPDF engine, which normally + loads from a CDN the first time you use the tool. If that default + has been turned off in a self-hosted build, you'll be prompted to + point + WASM Settings + at a copy of the library. +

          +
          +
          + + How do I check that the labels were applied? + + +

          + Open the downloaded PDF in a reader that displays page labels, such + as Adobe Acrobat or Firefox's built-in viewer, and look at the page + number box in the toolbar. It shows the label, for example iv or + A-1, instead of the plain page index.

          diff --git a/src/pages/add-stamps.html b/src/pages/add-stamps.html index 74428d51..b52b5011 100644 --- a/src/pages/add-stamps.html +++ b/src/pages/add-stamps.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ />
          - Is add stamps really free? + What kind of stamps can I add with this tool?

          - Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + This tool places image stamps, so you pick an image file such as a + PNG or JPG (a company seal, an APPROVED graphic, a scanned notary + stamp) and drop it onto the page. For text-only marks like a + diagonal DRAFT label, + Add Watermark + is the better fit.

          - Are my files private and secure? + What does the Stamp Username field do?

          - Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + The name you enter is recorded on each stamp you create as its + author, so reviewers can see who placed it. Set it before you upload + the PDF. It's optional, and leaving it blank creates stamps without + a name attached.

          - Is there a file size limit? + Can I put the same stamp on every page at once?

          - No! Process files of any size, as many times as you want, completely - free. + No. Stamps are placed one at a time on the page you're viewing, and + you can move and resize each one before saving. If you need an + identical mark on all pages, use the image mode in + Add Watermark, which can apply one image to every page in a single step. +

          +
          +
          + + Are the stamps permanent, or can they be removed later? + + +

          + Stamps are saved as PDF stamp annotations, so a PDF editor can still + select, move, or delete them. If you want them merged into the page + content so they can't be lifted off, run the saved file through + Flatten PDF. +

          +
          +
          + + How do I move or resize a stamp after placing it? + + +

          + Click the stamp in the viewer to select it, then drag it to a new + position or pull its corner handles to change the size. Nothing is + final until you click Save Stamped PDF, so you can adjust as much as + you like first. +

          +
          +
          + + What's the difference between this and Sign PDF? + + +

          + Sign PDF + is built for signatures: you draw one, type one, or upload one and + place it on the page. Add Stamps is for reusable image marks such as + seals, RECEIVED stamps, or QC stamps, with your name recorded as the + author of each one. +

          +
          +
          + + Does the stamp tool work on password-protected PDFs? + + +

          + If the file needs a password to open, the tool asks for it before + loading the viewer. You need the open password; the tool doesn't + bypass encryption. +

          +
          +
          + + Is my document uploaded when I stamp it? + + +

          + No. The viewer, the stamp editor, and the export all run in your + browser, and the stamped PDF is written on your device. Nothing is + sent to a server, which matters when you're stamping contracts, + inspection reports, or notarized documents.

diff --git a/src/pages/add-watermark.html b/src/pages/add-watermark.html index e5095c3a..89406342 100644 --- a/src/pages/add-watermark.html +++ b/src/pages/add-watermark.html @@ -7,11 +7,11 @@ @@ -28,11 +28,11 @@ - + - Add Watermark - BentoPDF - + Watermark PDF Free - Add Text or Image Watermarks | BentoPDF @@ -776,32 +775,101 @@
- Is add watermark really free? + Can I watermark only certain pages of a PDF?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Yes. Type a range such as 1-3, 5, 7-9 in the Page Range field, or + leave it set to "all". If you want different text or a different + position on individual pages, uncheck "Apply to all pages" and use + the page arrows above the preview to set each page separately.

- Are my files private and secure? + How do I add a diagonal CONFIDENTIAL or DRAFT watermark across the + page?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Stay in Text mode, type the word, and raise the font size (10 to 200 + points, default 72) until it spans the page. The angle slider + already defaults to -45 degrees for the classic diagonal look, so + usually you only need to enlarge the text and drag it to the center + of the preview.

- Is there a file size limit? + Can I use a logo image as the watermark?

- No! Process files of any size, as many times as you want, completely - free. + Switch to Image mode and upload a PNG or JPG; other image formats + aren't accepted. A PNG with a transparent background blends best + with the page. You can scale it from 10% to 200%, set its opacity + and angle, and drag it into position on the preview. +

+
+
+ + What does the Tiled layout do? + + +

+ Tiled repeats the watermark across the whole page in a diagonal grid + that follows the rotation angle, so the mark runs edge to edge. The + horizontal and vertical gap sliders control the spacing between + tiles as a percentage of the watermark size. Lower the opacity when + tiling so the document underneath stays readable. +

+
+
+ + Can someone remove the watermark afterward? + + +

+ The watermark is drawn into the page content rather than added as a + separate annotation, so it can't be deleted with one click in a PDF + viewer. It isn't tamper-proof though. For a harder-to-strip result, + use Tiled mode, or check "Flatten watermark" to bake every page into + pixels, which also makes the document's text unselectable. +

+
+
+ + Does adding a watermark change the original text or image quality? + + +

+ No. The pages keep their original text, images, and dimensions, and + the watermark is placed on top, so text stays selectable and + searchable. The exception is the "Flatten watermark" option, which + re-renders every page as an image at 2.5x scale and removes + selectable text. +

+
+
+ + What opacity should I use for a watermark? + + +

+ The slider runs from 0.05 to 1 and defaults to 0.3. Values between + 0.2 and 0.4 keep the mark visible without hiding the content beneath + it; go higher only for small marks placed in a margin or corner. +

+
+
+ + Is my PDF uploaded when I add a watermark? + + +

+ No. The live preview, the drag-and-drop editor, and the final + rendering all run inside your browser with pdf-lib, so neither the + PDF nor a logo image you add leaves your device.

diff --git a/src/pages/adjust-colors.html b/src/pages/adjust-colors.html index f703ab7d..d9292a24 100644 --- a/src/pages/adjust-colors.html +++ b/src/pages/adjust-colors.html @@ -10,7 +10,7 @@ /> Adjust Colors - BentoPDF - @@ -467,7 +463,7 @@

Change PDF background

Text Color

@@ -486,32 +482,115 @@
- Is adjust colors really free? + How do I brighten a dark scanned PDF?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Move the Brightness slider (range -100 to +100) up to lighten the + page, and raise Contrast if the text still looks washed out. When + only the midtones are too dark, the Gamma slider (0.2 to 5.0) lifts + them without blowing out the white background. The preview updates + as you drag, so you can check the first page before applying the + settings to all of them.

- Are my files private and secure? + Can I convert a color PDF to grayscale with this tool?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Drag the Saturation slider all the way to -100 and every page + becomes grayscale, which also cuts ink use when printing. If you + don't need any of the other adjustments, the + grayscale conversion tool + does the same thing in one step.

- Is there a file size limit? + What do the hue, temperature, and tint sliders do?

- No! Process files of any size, as many times as you want, completely - free. + Hue Shift rotates every color around the color wheel by 0 to 360 + degrees while leaving whites, grays, and blacks untouched. + Temperature (-50 to +50) shifts the page toward blue on the cool end + or yellow-orange on the warm end, and Tint (-50 to +50) shifts + between green and magenta, which is useful for photos scanned with a + color cast. +

+
+
+ + Will the text still be selectable after adjusting colors? + + +

+ No. To apply the changes, each page is rendered to an image at 2x + resolution and saved into a new PDF, so the output is image-based + and text can't be selected or searched. Keep your original for + editing, or run the result through + OCR + to add a searchable text layer. +

+
+
+ + Why is my PDF larger after adjusting the colors? + + +

+ Every page is stored as a full-page PNG image instead of text and + vector drawing commands, so the file usually grows, especially for + text-heavy documents. Running the result through + Compress PDF + afterward brings the size back down. +

+
+
+ + Can I give a PDF a sepia or vintage look? + + +

+ Raise the Sepia slider (0 to 100) to add a brown tone; higher values + give a stronger antique look. Combine it with a small drop in + Contrast or Saturation to soften the result, and click Reset at any + point to return every slider to its default. +

+
+
+ + Does the preview show every page or only the first one? + + +

+ The live preview renders the first page only, so you can test + settings quickly. When you click Apply, the same settings are + processed on every page of the document and the adjusted PDF + downloads. +

+
+
+ + Is my PDF uploaded anywhere when I adjust its colors? + + +

+ No. The page rendering and the color math run in your browser, and + the adjusted PDF is assembled on your device, so the file never + leaves your computer.

diff --git a/src/pages/alternate-merge.html b/src/pages/alternate-merge.html index 367892f9..c37b4323 100644 --- a/src/pages/alternate-merge.html +++ b/src/pages/alternate-merge.html @@ -11,7 +11,7 @@ /> @@ -35,7 +35,7 @@ /> Alternate & Mix PDF Pages - BentoPDF - @@ -360,32 +356,116 @@
- Is alternate merge really free? + What does alternate merge do that a normal merge doesn't?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + A normal merge appends whole files one after another. Alternate + merge takes page 1 from each file in turn, then page 2 from each, + and so on, so the pages of two or more PDFs are interleaved into a + single document. If you only need files back to back, use + Merge PDF.

- Are my files private and secure? + How do I fix a double-sided scan where the fronts and backs are in + separate PDFs?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Upload the fronts PDF first and the backs PDF second, then click Mix + Pages. The output alternates front 1, back 1, front 2, back 2 and so + on. If the backs were scanned last page first, flip that file with + Reverse Pages + before mixing.

- Is there a file size limit? + The fronts and backs are in the same PDF, not separate files. Which + tool do I need?

- No! Process files of any size, as many times as you want, completely - free. + This tool interleaves separate files. If one PDF holds all the + fronts followed by all the backs, + Duplex Collate + splits that single file at the midpoint and interleaves the two + halves, with an option to reverse the back block. +

+
+
+ + What happens if the PDFs have different page counts? + + +

+ Interleaving continues until the shorter file runs out, and the + remaining pages from the longer file are appended in order at the + end. No pages are dropped. +

+
+
+ + Can I interleave more than two PDFs? + + +

+ Any number of files from two upward. With three files the output + goes A1, B1, C1, A2, B2, C2 and so on, following the order shown in + the file list, which you can change by dragging the grip handles. +

+
+
+ + Does the output keep bookmarks and page numbers from the original + files? + + +

+ Bookmarks from each source file are carried into the mixed PDF. Page + labels are reset to a plain 1 to N sequence by default; turn on the + option to keep original page labels if you want each file's own + labels, which can produce duplicates such as two pages both labeled + 1. +

+
+
+ + Can I alternate pages from password-protected PDFs? + + +

+ If a file is encrypted you're asked for its password when it loads, + and the decrypted copy is used for mixing. The output isn't + encrypted, so use + Protect PDF + afterward if it needs a password again. +

+
+
+ + Are the PDFs uploaded to a server while they're being interleaved? + + +

+ No. The files are read in your browser and interleaved by a + WebAssembly build of cpdf running in a background worker on your + device, and the finished alternated-mixed.pdf is saved straight from + the browser.

diff --git a/src/pages/background-color.html b/src/pages/background-color.html index c6c93e5a..80a8373c 100644 --- a/src/pages/background-color.html +++ b/src/pages/background-color.html @@ -11,7 +11,7 @@ /> @@ -35,7 +35,7 @@ /> Change Background Color - BentoPDF - @@ -332,32 +328,107 @@
- Is background color really free? + How do I change the background color of a PDF without losing the + text?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Upload the PDF, pick a color, and the tool draws a solid rectangle + behind each page and places the original page content on top of it. + The text stays real text, so it remains selectable and searchable, + and the page dimensions don't change.

- Are my files private and secure? + Why didn't the background color show up on some pages?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + The color sits underneath the existing content, so any page that + already has an opaque background covers it up. Scanned pages, which + are usually one full-page image, and pages with a drawn white + background are the most common cases.

- Is there a file size limit? + Does the color apply to every page or can I pick specific pages?

- No! Process files of any size, as many times as you want, completely - free. + There's no page range option, so the same color is applied to every + page in the document. To color only certain pages, pull them out + with + Split PDF, color that file, and merge it back. +

+
+
+ + What colors work best as a PDF background? + + +

+ Light, muted tones such as cream, ivory, or pale yellow keep black + text readable, which is why the default is a light yellow (#FFFFCC). + A dark background makes normal black text hard to read because the + text color isn't changed; use + Change Text Color + on the result if you want light text on a dark page. +

+
+
+ + Will links, form fields, or bookmarks survive the color change? + + +

+ No. Each page is re-embedded as a drawing on top of the color layer + and written into a new file, so link annotations, form fields, + comments, and bookmarks aren't carried over. Change the background + first and add those elements afterward. +

+
+
+ + Does changing the background turn my pages into images or make the + file bigger? + + +

+ Pages aren't rasterized. The tool works at the PDF object level and + only adds a filled rectangle per page, so fonts and vector graphics + stay intact and the file size stays close to the original. +

+
+
+ + Is my PDF uploaded when I change its background color? + + +

+ No. The color layer is added by code running in your browser and the + finished file is saved directly from the page to your device. The + document isn't sent to a server at any point. +

+
+
+ + Can I change the background color of a password-protected PDF? + + +

+ If the PDF needs a password to open, the tool prompts you for it and + then processes the file as usual. The output is saved without that + password, so protect it again with + Protect PDF + if you still need it locked.

diff --git a/src/pages/bates-numbering.html b/src/pages/bates-numbering.html index 81c328b9..09943d3a 100644 --- a/src/pages/bates-numbering.html +++ b/src/pages/bates-numbering.html @@ -476,33 +476,104 @@
- What is Bates numbering? + What does the Bates number look like on the page?

- Bates numbering is a method of indexing legal documents for easy - identification and retrieval. Each page receives a unique sequential - number, often combined with a prefix or suffix. + By default it's a six-digit zero-padded number such as 000001 placed + at the footer center in 10 pt Helvetica. Presets can add an exhibit + number, a case label, and a page number, for example Exhibit 1 Case + XYZ 000001 Page 1, and the preview box shows the exact text before + you process anything.

- Can I number multiple files at once? + Can I use my own prefix or case number instead of the presets?

- Yes! Upload multiple PDFs and the bates numbers will continue - sequentially across all files. Drag files to reorder them. + Yes. Pick Custom style and write a template with placeholders: + [BATES] for the sequential number, [PAGE] for the page number within + the file, [FILE] for the file counter, and [FILENAME] for the source + file name. A template like SMITH-[BATES] produces SMITH-000001, + SMITH-000002, and so on.

- Are my files secure? + Does the numbering continue across multiple PDFs or restart for each + file?

- All processing happens entirely in your browser. Your files never - leave your device. + It continues. If the first file has 30 pages and numbering starts at + 1, the second file begins at 000031, following the order of the file + list, which you can rearrange by dragging. There's no option to + restart the count per file; process the files separately if you need + that. +

+
+
+ + How many digits can the number have? + + +

+ Zero padding can be 3, 4, 5, or 6 digits, or turned off so 1, 2, 3 + print without leading zeros. The count itself isn't capped; if it + grows past the padding width, the extra digits are still printed. +

+
+
+ + Where does the stamp go, and will it cover my content? + + +

+ You choose one of six spots: header or footer, at the left, center, + or right. The margin scales with the page, roughly 4 percent of the + width or height with a floor of 8 points and a cap of 40, so the + stamp sits in the same relative place on Letter, A4, and oversized + exhibits. Existing content isn't shifted, so on pages printed edge + to edge the stamp can overlap it. +

+
+
+ + Are Bates numbers searchable text or an image? + + +

+ They're real text drawn in Helvetica, Times New Roman, or Courier, + so they can be selected, searched, and read by review software + without OCR. These are the built-in PDF standard fonts, which cover + Latin characters only, so a template containing other scripts will + fail. +

+
+
+ + Are my discovery documents uploaded to a server for stamping? + + +

+ No. Stamping happens inside your browser and the numbered files are + written straight to your downloads folder. Nothing about the + documents, the case name, or the numbering leaves the machine, which + matters for privileged material. +

+
+
+ + What do I get when I stamp several files at once? + + +

+ Each PDF is numbered as its own file and keeps its original name; a + single file downloads directly, and two or more download together as + bates_numbered.zip. The files aren't merged, so the page counts and + order inside each document stay as they were.

diff --git a/src/pages/bmp-to-pdf.html b/src/pages/bmp-to-pdf.html index cdf8ea43..7c78ff16 100644 --- a/src/pages/bmp-to-pdf.html +++ b/src/pages/bmp-to-pdf.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ /> BMP to PDF - BentoPDF - @@ -326,32 +322,108 @@
- Is bmp to pdf really free? + Can I combine several BMP files into one PDF?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Yes. Every BMP you add becomes its own page in a single PDF, in the + order shown in the file list. There's no option to produce one PDF + per file, so convert files separately if you need them split.

- Are my files private and secure? + Why is the PDF smaller than my BMP files?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + BMP stores uncompressed pixels, so the files are large. The + converter redraws each image and stores it in the PDF as lossless + PNG, which usually shrinks it considerably without changing a single + pixel.

- Is there a file size limit? + Is any image quality lost in the conversion?

- No! Process files of any size, as many times as you want, completely - free. + No. Pixels are stored losslessly and there's no quality setting on + this tool, so the output has the same resolution and colors as the + source. If you need a smaller file afterward, run the PDF through + Compress PDF. +

+
+
+ + What page size does the PDF get when I convert a BMP? + + +

+ Each page is sized to the image's pixel dimensions at one point per + pixel, so a 2480 by 3508 pixel scan produces a page about 34 by 49 + inches rather than A4. Viewers and printers scale it to fit, and + Fix Page Size + can resize every page to A4 or Letter afterward. +

+
+
+ + Why does it say one of my files is invalid? + + +

+ Images are decoded by your browser, which handles standard Windows + bitmaps. Unusual variants such as OS/2 headers or rare compression + modes can fail; re-saving the file as a standard 24-bit BMP or as + PNG in any image editor fixes it. +

+
+
+ + Can I mix BMP with JPG or PNG files? + + +

+ This tool accepts only .bmp files and skips anything else you add. + Use + Images to PDF + when you need to combine several formats into one document. +

+
+
+ + Does the BMP's DPI setting affect the result? + + +

+ No. The resolution stored in the file header is ignored and page + size comes purely from pixel count, so two images with the same + pixel dimensions produce identical pages regardless of their DPI. +

+
+
+ + Are my BMP files uploaded anywhere? + + +

+ No. Decoding uses your browser's own image support and the PDF is + assembled locally with pdf-lib, so scanner or medical imaging + exports never leave your computer.

diff --git a/src/pages/bookmark.html b/src/pages/bookmark.html index 485a2afc..d82eb23e 100644 --- a/src/pages/bookmark.html +++ b/src/pages/bookmark.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ />
- Is bookmark really free? + How do I add bookmarks to a PDF that doesn't have any?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Upload the PDF, go to a page, type a title, and click Add to Page; + drag entries to nest or reorder them. Click Save PDF with Bookmarks + to download the result. For a printed contents page inside the + document rather than sidebar navigation, use + Table of Contents + instead.

- Are my files private and secure? + Will my existing bookmarks be kept?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Only if you check Auto-extract existing bookmarks before uploading, + or use the extract button afterward, so they load into the panel. + When you save, the panel's contents replace the PDF's bookmark tree + entirely, so anything not loaded into the editor is dropped.

- Is there a file size limit? + What is the CSV format for importing bookmarks?

- No! Process files of any size, as many times as you want, completely - free. + A header row followed by one line per bookmark with three columns: + title,page,level. Titles containing commas go in double quotes, page + is the 1-based page number, and level controls nesting, with the + lowest number for top-level entries and each deeper child adding + one. +

+
+
+ + Can a bookmark jump to a specific spot on a page instead of the top? + + +

+ Open the bookmark's edit dialog, turn on Set custom destination, and + either type X and Y coordinates plus a zoom percentage or click the + pick button and then click the exact spot on the page preview. The + bookmark is saved as an XYZ destination, which most readers honor. +

+
+
+ + Can I color or bold bookmarks? + + +

+ Each bookmark can be red, blue, green, yellow, purple, or a custom + hex color, and styled bold, italic, or bold italic. Turn on Batch + Mode to select several bookmarks and apply a color or style to all + of them at once. +

+
+
+ + How do I get bookmarks out of a PDF for editing in a spreadsheet? + + +

+ Load them with Auto-extract, then use Export to CSV or Export to + JSON; the file is named after your PDF with a -bookmarks suffix. The + CSV opens in Excel or Google Sheets, and once you've edited it you + can import it back and save a new PDF. +

+
+
+ + Does the editor work on password-protected PDFs? + + +

+ You'll be asked for the password when you upload the file, and the + editor opens once it's entered. The saved PDF is written without the + password, so protect it again afterward if you need to. +

+
+
+ + Is my PDF uploaded while I edit bookmarks? + + +

+ No. The page preview, the bookmark tree, and the final save are all + handled in your browser with PDF.js and pdf-lib, so the file never + leaves your computer.

diff --git a/src/pages/cbz-to-pdf.html b/src/pages/cbz-to-pdf.html index 72962f88..bcb24f52 100644 --- a/src/pages/cbz-to-pdf.html +++ b/src/pages/cbz-to-pdf.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ /> CBZ to PDF - Convert XPS/OCBZ to PDF - BentoPDF - @@ -333,32 +329,103 @@
- Is cbz to pdf really free? + Does converting a CBZ to PDF reduce the image quality?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + JPEG and PNG pages are copied into the PDF as they are, with no + re-encoding, so the artwork looks exactly like the original and the + file size stays about the same. Other formats such as WebP, GIF, or + BMP are decoded and re-saved as lossless PNG before embedding.

- Are my files private and secure? + How does the tool decide the page order?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Pages are sorted by filename using natural ordering, so page2.jpg + comes before page10.jpg. Files in subfolders are included and sorted + by their full path, and non-image files such as ComicInfo.xml are + ignored.

- Is there a file size limit? + What page size do the comic pages get in the PDF?

- No! Process files of any size, as many times as you want, completely - free. + Each page is sized to the pixel dimensions of its image, one point + per pixel, so a double-page spread comes out as a wide landscape + page and single pages stay portrait. There's no option to force one + size here; if you need uniform pages, run the result through + Fix Page Size. +

+
+
+ + Can I convert CBR files as well as CBZ? + + +

+ .cbr archives are accepted and can be mixed with .cbz files in the + same batch. CBR files are routed through the PyMuPDF engine, which + downloads on first use, so they take a little longer than CBZ files, + which are unpacked directly in the browser. +

+
+
+ + Which image formats inside the archive are supported? + + +

+ JPEG and PNG are embedded directly. GIF, BMP, WebP, AVIF, TIFF, + HEIC, and JXL are converted to PNG by your browser first, so those + less common formats only work if your browser can display them; + TIFF, HEIC, and JXL fail in some browsers. The converter checks the + actual image data rather than the extension, so a PNG named .jpg + still works. +

+
+
+ + Is there a limit on archive size or page count? + + +

+ A single CBZ can hold up to 2,000 images, with each image capped at + 100 MB and 500 MB of uncompressed image data per archive. Those + limits keep the browser from running out of memory, and they're far + above a typical comic issue. +

+
+
+ + What happens when I convert several comics at once? + + +

+ Each archive becomes its own PDF named after the original file. One + file downloads directly; two or more are bundled into + comic-converted.zip. +

+
+
+ + Are my comic files uploaded anywhere? + + +

+ No. CBZ archives are unzipped and rebuilt as PDFs entirely inside + your browser, and CBR files are handled by an engine that also runs + locally. Nothing from your collection leaves your device.

diff --git a/src/pages/change-permissions.html b/src/pages/change-permissions.html index 0d03155d..04201e8d 100644 --- a/src/pages/change-permissions.html +++ b/src/pages/change-permissions.html @@ -11,7 +11,7 @@ /> @@ -35,7 +35,7 @@ /> Change PDF Permissions - Manage PDF Security - BentoPDF - @@ -445,32 +441,111 @@
- Is change permissions really free? + What is the difference between a user password and an owner + password?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + The user password is required to open the PDF at all. The owner + password protects the permission settings and is what someone needs + to change or remove them later. Set only an owner password if anyone + should be able to open the file but with printing, copying, or + editing restricted.

- Are my files private and secure? + Why does the tool ask for an owner password when I set permissions?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Permission flags are only enforced when an owner password exists; + without one, PDF readers treat the file as unrestricted. The tool + therefore requires a New Owner Password whenever you set permissions + or a user password.

- Is there a file size limit? + How do I stop people from copying text or printing my PDF?

- No! Process files of any size, as many times as you want, completely - free. + Uncheck "Allow Copying Text" and "Allow Printing", enter a New Owner + Password, and click Change Permissions. Adobe Reader and other + compliant viewers will then block those actions. Some third-party + tools ignore permission flags, so for sensitive material consider + rasterizing the pages + as well. +

+
+
+ + Which permissions can I control? + + +

+ Seven checkboxes: printing, copying text, modifying content, + annotating, filling forms, document assembly (inserting, deleting, + or rotating pages), and page extraction. An unchecked box means the + action is not allowed. +

+
+
+ + What encryption does Change Permissions use? + + +

+ The output is encrypted with 256-bit AES. That also makes this a + quick way to upgrade an old RC4-encrypted PDF: enter its current + password, set new passwords, and the file is rewritten with AES-256. +

+
+
+ + Can I change permissions on a PDF that is already password + protected? + + +

+ Yes, enter the existing password in the Current Password field. The + tool opens the file with it, then re-encrypts it with your new + passwords and permission settings; a wrong current password produces + an error and nothing is changed. +

+
+
+ + How do I remove all restrictions instead of changing them? + + +

+ Leave both new password fields empty and click Change Permissions. + The output is fully decrypted with no passwords and no permission + flags. If you don't have the current password, use + Remove Restrictions + instead, which works without one when the PDF opens freely. +

+
+
+ + Is my PDF or its owner password sent anywhere when I change + permissions? + + +

+ No. The encryption is done by QPDF compiled to WebAssembly inside + your browser tab, so the file and every password you type stay on + your device.

diff --git a/src/pages/combine-single-page.html b/src/pages/combine-single-page.html index 58e4ffc8..a0f6bd19 100644 --- a/src/pages/combine-single-page.html +++ b/src/pages/combine-single-page.html @@ -11,7 +11,7 @@ /> @@ -35,7 +35,7 @@ /> Combine to Single Page - BentoPDF - @@ -409,32 +405,100 @@
- Is combine single page really free? + How do I merge all pages of a PDF into one long page?

- Yes! BentoPDF is 100% free with no hidden fees, no signup required, - and unlimited file processing. + Upload the PDF, keep Layout Direction set to Vertical, and click the + process button. Every page is placed top to bottom on one continuous + page, with the output width matching the widest source page and + narrower pages centered.

- Are my files private and secure? + Can I put the pages side by side instead of stacked?

- Absolutely! All processing happens in your browser. Your files never - leave your device, ensuring complete privacy. + Choose Horizontal (Left to Right) in Layout Direction. Pages are + laid out in order from left to right on a single wide page, and + pages shorter than the tallest one are centered vertically.

- Is there a file size limit? + Can I add a gap or a line between the pages?

- No! Process files of any size, as many times as you want, completely - free. + Spacing (0 by default) adds a gap between pages, measured in the + PDF's own units where 72 equals one inch, and Background Color fills + that gap. Turn on Add Separator Lines to draw a line through the + middle of each gap, with its own thickness (0.5 units and up, in + steps of 0.5) and color. +

+
+
+ + Does the background color apply to the whole page or only the gaps? + + +

+ It fills the whole output page underneath the source pages, so it + shows in the spacing between pages and in any margin where a + narrower page is centered. With white selected, the default, no fill + is drawn at all. +

+
+
+ + Will the text in the combined page still be selectable? + + +

+ No. Each source page is rendered to an image at 2x resolution and + drawn onto the new page, so the result is a picture of your pages + rather than live text. Keep the original PDF if you need to copy or + search text later. +

+
+
+ + Is there a limit to how many pages I can stitch together? + + +

+ The tool doesn't set one, but the output grows with every page you + add: a 100-page document becomes a page roughly 100 pages tall. Some + readers struggle with very large pages; Adobe Reader, for example, + doesn't display pages larger than 200 inches on a side. +

+
+
+ + What is a single long-page PDF useful for? + + +

+ It suits scrolling previews for the web, design mockups, comic + strips, and storyboards where the reader scrolls instead of flipping + pages. If you want several pages printed on one sheet in a grid, + N-Up PDF + is the better fit. +

+
+
+ + Does the combined PDF get uploaded to a server? + + +

+ No. Rendering the pages and building the new single-page PDF both + happen in your browser, and the file stays on your device the whole + time.

diff --git a/src/pages/compare-pdfs.html b/src/pages/compare-pdfs.html index 408e5d6b..3e802fd6 100644 --- a/src/pages/compare-pdfs.html +++ b/src/pages/compare-pdfs.html @@ -11,7 +11,7 @@ /> @@ -32,7 +32,7 @@ /> Compare PDFs - BentoPDF -