diff --git a/README.md b/README.md index 2059cd3..09cfae0 100644 --- a/README.md +++ b/README.md @@ -871,6 +871,16 @@ docker run -d -p 3000:8080 \ Both methods can be combined — the lists are merged. For the full list of tool IDs, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-specific-tools). +You can also disable specific features inside the PDF Editor (e.g., redaction, forms) without disabling the entire editor. Add `editorDisabledCategories` to your `config.json`: + +```json +{ + "editorDisabledCategories": ["redaction"] +} +``` + +For the full list of editor categories, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-editor-features). + ### 🔒 Security Features BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security: diff --git a/docs/self-hosting/docker.md b/docs/self-hosting/docker.md index e062a07..f983594 100644 --- a/docs/self-hosting/docker.md +++ b/docs/self-hosting/docker.md @@ -204,6 +204,45 @@ services: Both methods can be combined — the lists are merged. If a tool appears in either, it is disabled. +#### Disabling Editor Features + +You can also disable specific features inside the PDF Editor (e.g., redaction, annotations, forms) without disabling the entire editor tool. Add `editorDisabledCategories` to your `config.json`: + +```json +{ + "editorDisabledCategories": ["redaction", "annotation-stamp"] +} +``` + +
+Full list of editor categories + +**Zoom:** `zoom`, `zoom-in`, `zoom-out`, `zoom-fit-page`, `zoom-fit-width`, `zoom-marquee`, `zoom-level` + +**Annotation:** `annotation`, `annotation-markup`, `annotation-highlight`, `annotation-underline`, `annotation-strikeout`, `annotation-squiggly`, `annotation-ink`, `annotation-text`, `annotation-stamp` + +**Shapes:** `annotation-shape`, `annotation-rectangle`, `annotation-circle`, `annotation-line`, `annotation-arrow`, `annotation-polygon`, `annotation-polyline` + +**Form:** `form`, `form-textfield`, `form-checkbox`, `form-radio`, `form-select`, `form-listbox`, `form-fill-mode` + +**Redaction:** `redaction`, `redaction-area`, `redaction-text`, `redaction-apply`, `redaction-clear` + +**Document:** `document`, `document-open`, `document-close`, `document-print`, `document-capture`, `document-export`, `document-fullscreen`, `document-protect` + +**Page:** `page`, `spread`, `rotate`, `scroll`, `navigation` + +**Panel:** `panel`, `panel-sidebar`, `panel-search`, `panel-comment` + +**Tools:** `tools`, `pan`, `pointer`, `capture` + +**Selection:** `selection`, `selection-copy` + +**History:** `history`, `history-undo`, `history-redo` + +
+ +Categories are hierarchical — disabling a parent (e.g., `annotation`) disables all its children. + ### Custom WASM URLs (Air-Gapped / Self-Hosted) > [!IMPORTANT] diff --git a/docs/self-hosting/index.md b/docs/self-hosting/index.md index d1d1f79..707a1f5 100644 --- a/docs/self-hosting/index.md +++ b/docs/self-hosting/index.md @@ -164,7 +164,9 @@ docker run -d -p 3000:8080 \ ghcr.io/alam00000/bentopdf:latest ``` -Both methods can be combined — the lists are merged. See the [Docker guide](/self-hosting/docker#disabling-specific-tools) for full details. +Both methods can be combined — the lists are merged. + +You can also disable specific features inside the PDF Editor (e.g., redaction) without disabling the entire tool by adding `editorDisabledCategories` to `config.json`. See the [Docker guide](/self-hosting/docker#disabling-editor-features) for the full list of categories. ## Deployment Guides diff --git a/src/js/logic/edit-pdf-page.ts b/src/js/logic/edit-pdf-page.ts index 1a0c986..3828392 100644 --- a/src/js/logic/edit-pdf-page.ts +++ b/src/js/logic/edit-pdf-page.ts @@ -4,6 +4,7 @@ import { showAlert, showLoader, hideLoader } from '../ui.js'; import { formatBytes, downloadFile } from '../utils/helpers.js'; import { makeUniqueFileKey } from '../utils/deduplicate-filename.js'; import { batchDecryptIfNeeded } from '../utils/password-prompt.js'; +import { getEditorDisabledCategories } from '../utils/disabled-tools.js'; const embedPdfWasmUrl = new URL( 'embedpdf-snippet/dist/pdfium.wasm', @@ -130,7 +131,9 @@ async function handleFiles(files: FileList) { pdfWrapper.classList.remove('hidden'); const { default: EmbedPDF } = await import('embedpdf-snippet'); + const disabledCategories = getEditorDisabledCategories(); viewerInstance = EmbedPDF.init({ + disabledCategories, type: 'container', target: pdfContainer, worker: true, diff --git a/src/js/types/config-types.ts b/src/js/types/config-types.ts index 40c29c5..191df36 100644 --- a/src/js/types/config-types.ts +++ b/src/js/types/config-types.ts @@ -1,3 +1,4 @@ export interface AppConfig { disabledTools?: string[]; + editorDisabledCategories?: string[]; } diff --git a/src/js/utils/disabled-tools.ts b/src/js/utils/disabled-tools.ts index a70491d..dfbc704 100644 --- a/src/js/utils/disabled-tools.ts +++ b/src/js/utils/disabled-tools.ts @@ -2,6 +2,7 @@ import type { AppConfig } from '@/types'; const disabledToolsSet = new Set(__DISABLED_TOOLS__); let runtimeConfigLoaded = false; +let editorDisabledCategories: string[] = []; export async function loadRuntimeConfig(): Promise { if (runtimeConfigLoaded) return; @@ -21,6 +22,11 @@ export async function loadRuntimeConfig(): Promise { } } } + if (Array.isArray(config.editorDisabledCategories)) { + editorDisabledCategories = config.editorDisabledCategories.filter( + (c): c is string => typeof c === 'string' + ); + } } catch {} } @@ -36,6 +42,10 @@ export function getToolIdFromPath(): string | null { return withoutExt?.[1] ?? null; } +export function getEditorDisabledCategories(): string[] { + return editorDisabledCategories; +} + export function isCurrentPageDisabled(): boolean { const toolId = getToolIdFromPath(); if (!toolId) return false;