Redaction Plugin
The Redaction Plugin provides the tools to permanently remove sensitive content from a PDF document. Unlike annotations which are simply layered on top, redaction is a destructive process that alters the underlying PDF content, making it unrecoverable.
The process involves two main stages:
- Marking: Users mark content for redaction by selecting text or drawing a rectangle over an area. These marks are called “pending redactions.”
- Committing: Users apply the pending redactions, which permanently removes the marked content from the document in the viewer’s memory and, optionally, draws black boxes in its place.
Redaction is an irreversible process. Once committed, the original content is removed and cannot be restored from the document.
Installation
The plugin has optional but highly recommended dependencies on the Selection and Interaction Manager plugins, which are required for marking text and areas, respectively.
npm install @embedpdf/plugin-redaction @embedpdf/plugin-selection @embedpdf/plugin-interaction-managerRegistration
Import RedactionPluginPackage and its dependencies, then add them to the plugins array. The dependencies should be registered first.
import { createPluginRegistration } from '@embedpdf/core'
// ... other imports
import { InteractionManagerPluginPackage } from '@embedpdf/plugin-interaction-manager/svelte'
import { SelectionPluginPackage } from '@embedpdf/plugin-selection/svelte'
import { RedactionPluginPackage } from '@embedpdf/plugin-redaction/svelte'
const plugins = [
// ... other essential plugins
createPluginRegistration(DocumentManagerPluginPackage, { /* ... */ }),
createPluginRegistration(RenderPluginPackage),
// Register dependencies first
createPluginRegistration(InteractionManagerPluginPackage),
createPluginRegistration(SelectionPluginPackage),
// Register and configure the redaction plugin
createPluginRegistration(RedactionPluginPackage, {
drawBlackBoxes: true, // Draw black boxes over redacted content
}),
]Usage
The plugin’s functionality is primarily managed through the <RedactionLayer /> component and the useRedaction store.
1. Add the <RedactionLayer />
This component is responsible for rendering all redaction-related UI, including the text selection highlights, area selection marquee, and all pending redaction marks. It must be placed inside your <Scroller />’s renderPage snippet and be a child of the <PagePointerProvider>.
<script lang="ts">
import { PagePointerProvider } from '@embedpdf/plugin-interaction-manager/svelte';
import { RedactionLayer } from '@embedpdf/plugin-redaction/svelte';
let { documentId }: { documentId: string } = $props();
</script>
{#snippet renderPage(page)}
<PagePointerProvider {documentId} pageIndex={page.pageIndex}>
<RenderLayer {documentId} pageIndex={page.pageIndex} />
<SelectionLayer {documentId} pageIndex={page.pageIndex} />
<RedactionLayer {documentId} pageIndex={page.pageIndex} />
</PagePointerProvider>
{/snippet}
<Scroller {documentId} {renderPage} />2. Build a Redaction Toolbar
The useRedaction store provides the state of the redaction process (e.g., how many marks are pending) and a provides object with methods to control it for a specific document. You can build a toolbar to allow users to switch between redaction modes and apply their changes.
<script lang="ts">
import { useRedaction } from '@embedpdf/plugin-redaction/svelte';
let { documentId }: { documentId: string } = $props();
const redaction = useRedaction(() => documentId);
</script>
{#if redaction.provides}
<div>
<button onclick={() => redaction.provides?.toggleRedactSelection()}>Mark Text</button>
<button onclick={() => redaction.provides?.toggleMarqueeRedact()}>Mark Area</button>
<span>{redaction.state.pendingCount} pending marks</span>
<button
onclick={() => redaction.provides?.commitAllPending()}
disabled={redaction.state.pendingCount === 0}
>
Apply All Redactions
</button>
</div>
{/if}3. Create a Menu for Pending Marks
You can provide a selectionMenu snippet to the <RedactionLayer /> to display a custom UI when a user clicks on a pending redaction mark. This is useful for allowing users to apply or remove individual marks.
<script lang="ts">
import { RedactionLayer, useRedaction } from '@embedpdf/plugin-redaction/svelte';
let { documentId }: { documentId: string } = $props();
const redaction = useRedaction(() => documentId);
</script>
<RedactionLayer {documentId} pageIndex={page.pageIndex}>
{#snippet selectionMenuSnippet({ selected, context, menuWrapperProps, rect })}
{#if selected}
<span style={menuWrapperProps.style} use:menuWrapperProps.action>
<div
style:position="absolute"
style:top="{rect.size.height + 10}px"
style:left="0"
style:pointer-events="auto"
>
<button onclick={() => redaction.provides?.removePending(context.item.page, context.item.id)}>Remove</button>
</div>
</span>
{/if}
{/snippet}
</RedactionLayer>Live Example
Try marking text or areas for redaction. Use the “Mark Text” button to select text, or “Mark Area” to draw rectangles. Click on a pending mark to see the contextual menu, then apply or remove individual marks. Use “Apply All” to permanently redact all pending marks.
API Reference
Configuration (RedactionPluginConfig)
| Option | Type | Description |
|---|---|---|
drawBlackBoxes | boolean | If true, a black rectangle is drawn over the redacted content after committing. Default: true |
Component: <RedactionLayer />
Renders all UI related to marking and managing redactions.
| Prop | Type | Description |
|---|---|---|
documentId | string | (Required) The ID of the document. |
pageIndex | number | (Required) The page index this layer corresponds to. |
selectionMenu | Snippet | (Optional) A snippet to render a contextual menu when a pending redaction is selected. |
Snippet: selectionMenu
| Prop | Type | Description |
|---|---|---|
context | object | The context containing the item (the pending redaction). |
selected | boolean | true if a pending redaction is currently selected. |
menuWrapperProps | MenuWrapperProps | An object containing style: string for positioning and action: Action to attach to your wrapper element via use:menuWrapperProps.action. |
rect | Rect | The bounding box of the selected pending redaction. |
Store: useRedaction(documentId)
Connects your components to the redaction plugin’s state and methods for a specific document.
Parameters
| Parameter | Type | Description |
|---|---|---|
documentId | () => string | A getter function that returns the document ID to track. |
Returns
| Property | Type | Description |
|---|---|---|
state | RedactionState | An object containing the current state of the redaction process. |
provides | RedactionScope | null | An object with methods to control the plugin, or null if not ready. |
RedactionState Properties
| Property | Type | Description |
|---|---|---|
isRedacting | boolean | true when any redaction mode is active. |
activeType | RedactionMode | null | The currently active mode ('marqueeRedact' or 'redactSelection'). |
pending | object | A map of pending redactions, keyed by page number. |
pendingCount | number | The total number of pending redactions across all pages. |
selected | object | null | The currently selected pending redaction, if any. |
RedactionScope Methods
A selection of key methods available on the provides object:
| Method | Description |
|---|---|
toggleRedactSelection() | Toggles the text redaction mode. |
toggleMarqueeRedact() | Toggles the area redaction mode. |
addPending(items) | Programmatically adds new RedactionItems to the pending queue. |
removePending(page, id) | Removes a specific pending redaction mark. |
clearPending() | Removes all pending redaction marks. |
commitAllPending() | (Destructive) Applies all pending redactions to the document. Returns a Task. |
commitPending(page, id) | (Destructive) Applies a single pending redaction. Returns a Task. |
onStateChange(cb) | Subscribes to any change in the RedactionState. |
onRedactionEvent(cb) | Subscribes to events like adding, removing, or committing redactions. |
Need Help?
Join our community for support, discussions, and to contribute to EmbedPDF's development.