@embedpdf/plugin-redaction 3.0.0-next.13 → 3.0.0-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -24
- package/dist/contract-Ib0iOWF3.cjs +43 -0
- package/dist/contract-Ib0iOWF3.cjs.map +1 -0
- package/dist/contract-TU9orxrO.d.cts +184 -0
- package/dist/contract-TU9orxrO.d.ts +184 -0
- package/dist/contract-eQ3P0UU-.js +33 -0
- package/dist/contract-eQ3P0UU-.js.map +1 -0
- package/dist/contract.cjs +2 -1
- package/dist/contract.d.cts +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/contract.js +2 -2
- package/dist/index.cjs +455 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +455 -192
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/dist/contract--fJOCVRN.d.cts +0 -84
- package/dist/contract--fJOCVRN.d.ts +0 -84
- package/dist/contract-BZLrD3p2.js +0 -7
- package/dist/contract-BZLrD3p2.js.map +0 -1
- package/dist/contract-CyLm5eeQ.cjs +0 -11
- package/dist/contract-CyLm5eeQ.cjs.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["AnnotationToken","InteractionToken","SelectionToken","RedactionToken","AnnotationToken","InteractionToken","SelectionToken"],"sources":["../src/capability.ts","../src/reducer.ts","../src/redaction.plugin.ts"],"sourcesContent":["import type { DocCapability, PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract';\nimport type {\n AnnotationDTO,\n AnnotationRef,\n PdfRect,\n RedactionApplyResult,\n} from '@embedpdf/engine-core';\nimport type {\n RedactionAction,\n RedactionCapability,\n RedactionLabelPatch,\n RedactionPendingItem,\n RedactionState,\n} from './types';\n\n/** Applying destroys content — its own granted power, narrower than annotate.\n * The engine's apply asserts all three (LocalDocumentRedactionService; the\n * cloud route guards match): the redact grant itself, the page-content\n * rewrite, and the annotation consumption. `canApply` mirrors the full set. */\nconst APPLY_CAPABILITIES: readonly DocCapability[] = [\n 'doc.redact',\n 'doc.pages.modify',\n 'doc.annotate.modify',\n];\n\n/** The annotation plugin's model-id convention for a durable ref. */\nconst idOf = (ref: AnnotationRef): string =>\n ref.kind === 'objectNumber'\n ? `obj:${ref.annotObjectNumber}`\n : ref.kind === 'nm'\n ? `nm:${ref.nm}`\n : `idx:${ref.pageObjectNumber}:${ref.index}`;\n\ntype RedactDTO = Extract<AnnotationDTO, { subtype: 'redact' }>;\n\n/** The PDF-space regions a redact mark targets: its quads' boxes, else `/Rect`. */\nfunction regionsOf(dto: RedactDTO): PdfRect[] {\n if (dto.quadPoints.length === 0) return [dto.rect];\n return dto.quadPoints.map((q) => {\n const xs = [q.p1.x, q.p2.x, q.p3.x, q.p4.x];\n const ys = [q.p1.y, q.p2.y, q.p3.y, q.p4.y];\n return {\n left: Math.min(...xs),\n right: Math.max(...xs),\n bottom: Math.min(...ys),\n top: Math.max(...ys),\n };\n });\n}\n\n/** Positive-area intersection — the engine's collateral rule. */\nconst intersects = (a: PdfRect, b: PdfRect): boolean =>\n Math.min(a.right, b.right) > Math.max(a.left, b.left) &&\n Math.min(a.top, b.top) > Math.max(a.bottom, b.bottom);\n\nexport function createRedactionCapability(\n ctx: PluginContext<RedactionState, RedactionAction>,\n): RedactionCapability {\n const anno = ctx.get(AnnotationToken);\n const appliedCallbacks = new Set<(result: RedactionApplyResult) => void>();\n\n const requireDoc = () => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[redaction] no document bound');\n return doc;\n };\n const requireService = () => {\n const doc = requireDoc();\n if (!doc.redaction) throw new Error('[redaction] engine has no redaction service');\n return doc.redaction;\n };\n\n const pons = (): number[] => (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber);\n\n const pageIndexOf = (pon: number): number =>\n ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.index ?? -1;\n\n const pendingOn = (pon: number): RedactDTO[] =>\n anno.list(pon).filter((a): a is RedactDTO => a.subtype === 'redact');\n\n const collectPending = (): RedactionPendingItem[] => {\n const items: RedactionPendingItem[] = [];\n for (const pon of pons()) {\n for (const dto of pendingOn(pon)) {\n items.push({\n id: idOf(dto.ref),\n ref: dto.ref,\n pageObjectNumber: pon,\n pageIndex: pageIndexOf(pon),\n kind: dto.quadPoints.length > 0 ? 'text' : 'area',\n overlayText: dto.overlayText,\n });\n }\n }\n return items;\n };\n\n const fireApplied = (result: RedactionApplyResult) => {\n for (const cb of appliedCallbacks) {\n try {\n cb(result);\n } catch (err) {\n console.error('[redaction] onApplied callback failed', err);\n }\n }\n };\n\n const runApply = async (\n scope: Parameters<ReturnType<typeof requireService>['apply']>[0],\n ): Promise<RedactionApplyResult> => {\n const service = requireService();\n ctx.dispatch({ type: 'APPLY_STARTED' });\n try {\n const result = await service.apply(scope);\n ctx.dispatch({ type: 'APPLY_FINISHED', result });\n fireApplied(result);\n return result;\n } catch (err) {\n ctx.dispatch({ type: 'APPLY_FINISHED', result: null });\n throw err;\n }\n };\n\n // A REMOTE collaborator's apply arrives only as a document event (own\n // applies flow through runApply above). Annotation state + raster\n // invalidation are handled by their own planes; here we only surface it.\n const doc = ctx.doc;\n if (doc) {\n ctx.cleanup(\n doc.events.subscribe((event) => {\n if (event.type !== 'redaction.applied') return;\n if (event.origin.kind !== 'remote') return;\n ctx.dispatch({ type: 'APPLY_FINISHED', result: event });\n fireApplied(event);\n }),\n );\n }\n\n return {\n // Marks are annotations — marking authority IS annotation create\n // authority (the annotation plugin's own twin, not a re-derivation).\n canMark: () => anno.canCreate(),\n // Mirror EVERYTHING the engine's apply asserts, not just the headline\n // capability — a token granted `doc.redact` à la carte without its bit-4\n // siblings must not see an armed Apply button.\n canApply: () => {\n const doc = ctx.doc;\n if (!doc || doc.redaction === undefined) return false;\n return APPLY_CAPABILITIES.every((cap) => doc.security.allows(cap));\n },\n isApplying: () => ctx.getState().applying,\n lastResult: () => ctx.getState().lastResult,\n\n enableRedact: () => ctx.tryGet(InteractionToken)?.activateTool('redact'),\n toggleRedact: () => {\n const interaction = ctx.tryGet(InteractionToken);\n if (!interaction) return;\n interaction.activateTool(interaction.activeToolId() === 'redact' ? 'pointer' : 'redact');\n },\n isRedactActive: () => ctx.tryGet(InteractionToken)?.activeToolId() === 'redact',\n\n queueCurrentSelection: async () => {\n // Marks are optimistic annotation creates — the same gate the pointer\n // path has (the annotation plugin refuses ungated creates too).\n if (!anno.canCreate()) return false;\n const selection = ctx.tryGet(SelectionToken);\n if (!selection || !selection.hasSelection()) return false;\n const snapshot = selection.snapshot();\n for (const page of snapshot.pages) {\n if (page.segments.length === 0) continue;\n // Preserve the selected text frame all the way into `/QuadPoints`.\n // Native apply now uses these exact cells for text removal and the\n // final overlay, so marked == previewed == applied for oriented text.\n anno.createMarkup(\n 'redact',\n page.pon,\n page.segments.map((segment) => segment.quad),\n 'redact',\n );\n }\n selection.clear();\n return true;\n },\n\n preparePending: async () => {\n await Promise.all(pons().map((pon) => anno.ensurePage(pon)));\n },\n getPending: collectPending,\n pendingCount: () => collectPending().length,\n\n estimateCollateral: (ids) => {\n const wanted = ids ? new Set(ids) : null;\n let count = 0;\n for (const pon of pons()) {\n const all = anno.list(pon);\n const marks = all.filter(\n (a): a is RedactDTO => a.subtype === 'redact' && (!wanted || wanted.has(idOf(a.ref))),\n );\n if (marks.length === 0) continue;\n const regions = marks.flatMap(regionsOf);\n for (const other of all) {\n if (other.subtype === 'redact') continue;\n if (regions.some((r) => intersects(r, other.rect))) count++;\n }\n }\n return count;\n },\n\n setLabel: async (ref, patch: RedactionLabelPatch) => {\n const current = anno.get(ref);\n if (!current || current.subtype !== 'redact') {\n throw new Error('[redaction] setLabel target is not a redact annotation');\n }\n // Always carry the current /DA styling: the engine rewrites /DA whenever\n // a label field rides a patch, so a text-only edit must not let the\n // styling fall back to defaults.\n await anno.update(ref, {\n subtype: 'redact',\n ...(patch.overlayText !== undefined ? { overlayText: patch.overlayText } : {}),\n ...(patch.repeat !== undefined ? { repeat: patch.repeat } : {}),\n fontFamily: current.fontFamily,\n fontSize: current.fontSize,\n fontColor: current.fontColor,\n textAlign: current.textAlign,\n });\n },\n\n apply: async (ids) => {\n const wanted = new Set(ids);\n const refs = collectPending()\n .filter((p) => wanted.has(p.id))\n .map((p) => p.ref);\n if (refs.length === 0) throw new Error('[redaction] no matching pending redactions');\n return runApply({ kind: 'annotations', refs });\n },\n\n applyAll: async () => {\n // Pages scope: authoritative for the WHOLE document, including marks on\n // pages this client never loaded. Pages without marks report 'unchanged'.\n const pageObjectNumbers = pons();\n if (pageObjectNumbers.length === 0) throw new Error('[redaction] document has no pages');\n return runApply({ kind: 'pages', pageObjectNumbers });\n },\n\n onApplied: (cb) => {\n appliedCallbacks.add(cb);\n return () => appliedCallbacks.delete(cb);\n },\n };\n}\n","import type { RedactionAction, RedactionState } from './types';\n\nexport const initialRedactionState = (): RedactionState => ({\n applying: false,\n lastResult: null,\n});\n\nexport const redactionReducer = (\n state: RedactionState,\n action: RedactionAction,\n): RedactionState => {\n switch (action.type) {\n case 'APPLY_STARTED':\n return { ...state, applying: true };\n case 'APPLY_FINISHED':\n return { applying: false, lastResult: action.result ?? state.lastResult };\n default:\n return state;\n }\n};\n","import { definePlugin } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract';\nimport { createRedactionCapability } from './capability';\nimport { initialRedactionState, redactionReducer } from './reducer';\nimport { RedactionToken } from './types';\nimport type { RedactionAction, RedactionCapability, RedactionState } from './types';\n\n/**\n * Document-scoped redaction plugin — the DESTRUCTIVE half of the two-stage\n * model. Marking is annotation-plane work (the composed `redact` tool ships\n * with plugin-annotation); this plugin wraps `doc.redaction.apply`, projects\n * the pending queue out of annotation state, and estimates collateral for\n * confirm dialogs. It owns no mark state of its own.\n *\n * Trust boundary: on a layered document, applying rewrites the LAYER's bytes;\n * the immutable base keeps the original. See the package README.\n */\nexport const redactionPlugin = () =>\n definePlugin<RedactionState, RedactionAction, RedactionCapability>({\n id: 'redaction',\n token: RedactionToken,\n scope: 'document',\n requires: [AnnotationToken],\n optional: [InteractionToken, SelectionToken],\n initialState: initialRedactionState,\n reduce: redactionReducer,\n capability: createRedactionCapability,\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["pageQuadBounds","annotationKey","AnnotationToken","SelectionToken","SearchToken","PluginError","annotationKey","PluginError","PluginError","RedactionToken","AnnotationToken","SelectionToken","SearchToken","REDACTION_DEFAULTS","RedactionToken"],"sources":["../src/read/pending.ts","../src/services/events.ts","../src/services/siblings.ts","../src/services/store.ts","../src/services/index.ts","../src/model.ts","../src/sync/document-events.ts","../src/sync/overlay.ts","../src/write/apply.ts","../src/write/marks.ts","../src/controller.ts","../src/redaction.plugin.ts","../src/state.ts"],"sourcesContent":["/**\n * The pending view: `redact` annotations projected as marks, per page and\n * memoized on the annotation plane's own reference-stable lists, plus the\n * client-side collateral estimate.\n */\nimport { rectsOverlap } from '@embedpdf/core-geometry';\nimport { annotationKey, memo, memoByKey, toPageRef } from '@embedpdf/core';\nimport {\n pageQuadBounds,\n type Annotation,\n type AnnotationRef,\n type PageBox,\n type PageRef,\n} from '@embedpdf/engine-core';\n\nimport type {\n RedactionCapability,\n RedactionCollateral,\n RedactionMark,\n RedactionMarkFilter,\n} from '../contract';\nimport type { RedactionContext, RedactionServices } from '../services';\n\ntype RedactDTO = Extract<Annotation, { subtype: 'redact' }>;\n\n/** The regions a redact mark targets: its quads' boxes, else its `rect`. */\nconst regionsOf = (dto: RedactDTO): readonly PageBox[] =>\n dto.quadPoints.length === 0 ? [dto.rect] : dto.quadPoints.map(pageQuadBounds);\n\nconst EMPTY: readonly RedactionMark[] = [];\n\n/** A `redact` annotation as a mark; `pageIndex` is its page's display index. */\nexport const markOf = (record: RedactDTO, pageIndex: number): RedactionMark => ({\n ref: record.ref,\n page: record.ref.page,\n pageIndex,\n kind: record.quadPoints.length > 0 ? 'text' : 'area',\n bounds: record.rect,\n overlayText: record.overlayText ?? null,\n repeat: record.repeat ?? false,\n});\n\nexport function createPendingReads(\n ctx: Pick<RedactionContext, 'getPage'>,\n { store, siblings }: Pick<RedactionServices, 'store' | 'siblings'>,\n) {\n const { pages, pageIndexOf } = store;\n const { annotation } = siblings;\n\n /** One page's marks, the same array while the plane's list and the page's position hold. */\n const marksOn = memoByKey(\n (pageObjectNumber: number) => {\n const page = toPageRef(pageObjectNumber);\n // The page's list is the same array while it holds; the marks are picked from it.\n return [annotation.list({ pages: [page] }), pageIndexOf(page)] as const;\n },\n (_pageObjectNumber, records, pageIndex): readonly RedactionMark[] => {\n const marks = records.flatMap((record): RedactionMark[] =>\n record.subtype === 'redact' ? [markOf(record, pageIndex)] : [],\n );\n return marks.length ? marks : EMPTY;\n },\n );\n\n /** The whole document's marks, the same array while no page's marks changed. */\n const allMarks = memo(\n () => pages().map((page) => marksOn(page.objectNumber)),\n (...perPage: (readonly RedactionMark[])[]): readonly RedactionMark[] =>\n perPage.some((marks) => marks.length) ? perPage.flat() : EMPTY,\n );\n\n /** One page's marks (a ref or an index; none for a page that isn't there), or every mark. */\n const listPending = (filter?: RedactionMarkFilter): readonly RedactionMark[] => {\n if (filter?.page === undefined) return allMarks();\n const layout = ctx.getPage(filter.page);\n return layout ? marksOn(layout.ref.objectNumber) : EMPTY;\n };\n\n /** A record the annotation plugin made or changed, as the mark it is. */\n const markFor = (record: Annotation): RedactionMark | null =>\n record.subtype === 'redact' ? markOf(record, pageIndexOf(record.ref.page)) : null;\n\n const getPending = (ref: AnnotationRef): RedactionMark | null => {\n const key = annotationKey(ref);\n return listPending().find((mark) => annotationKey(mark.ref) === key) ?? null;\n };\n\n const estimateCollateral = (refs?: readonly AnnotationRef[]): RedactionCollateral => {\n const wanted = refs ? new Set(refs.map(annotationKey)) : null;\n const hits: AnnotationRef[] = [];\n for (const page of pages()) {\n const onPage = annotation.list({ pages: [page] });\n const marks = onPage.filter(\n (dto): dto is RedactDTO =>\n dto.subtype === 'redact' && (!wanted || wanted.has(annotationKey(dto.ref))),\n );\n if (marks.length === 0) continue;\n const regions = marks.flatMap(regionsOf);\n for (const other of onPage) {\n if (other.subtype === 'redact') continue;\n if (regions.some((region) => rectsOverlap(region, other.rect))) hits.push(other.ref);\n }\n }\n return { count: hits.length, refs: hits };\n };\n\n return {\n listPending,\n markFor,\n api: {\n listPending,\n getPending,\n getPendingCount: (page?: PageRef | number) =>\n listPending(page === undefined ? undefined : { page }).length,\n estimateCollateral,\n } satisfies Partial<RedactionCapability>,\n };\n}\nexport type RedactionPendingReads = ReturnType<typeof createPendingReads>;\n","/** The capability's two event sources, disposed with the instance. */\nimport type { RedactionAppliedEvent, RedactionPendingChangedEvent } from '../contract';\nimport type { RedactionContext } from './context';\n\nexport function createEvents(ctx: RedactionContext) {\n return {\n applied: ctx.events.source<RedactionAppliedEvent>(),\n pendingChanged: ctx.events.source<RedactionPendingChangedEvent>(),\n };\n}\nexport type RedactionEvents = ReturnType<typeof createEvents>;\n","/** The sibling plugins: annotation (required, host lens), selection and search (optional). */\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { SearchToken } from '@embedpdf/plugin-search/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract';\n\nimport type { RedactionContext } from './context';\n\nexport function resolveSiblings(ctx: RedactionContext) {\n return {\n annotation: ctx.get(AnnotationToken),\n selection: () => ctx.tryGet(SelectionToken),\n search: () => ctx.tryGet(SearchToken),\n };\n}\nexport type RedactionSiblings = ReturnType<typeof resolveSiblings>;\n","/** The page registry reads and the engine's redaction service. */\nimport { PluginError, memo, type DocCapability, type PageRef } from '@embedpdf/core';\n\nimport type { RedactionContext } from './context';\n\n/** Applying destroys content: its own granted power, narrower than annotate.\n * The engine's apply asserts all three (the local redaction service and the\n * cloud route guards alike): the redact grant itself, the page-content\n * rewrite, and the annotation consumption. `canApply` mirrors the full set. */\nexport const APPLY_CAPABILITIES: readonly DocCapability[] = [\n 'doc.redact',\n 'doc.pages.modify',\n 'doc.annotate.modify',\n];\n\nexport function createStore(ctx: RedactionContext) {\n const requireService = () => {\n const service = ctx.doc.redaction;\n if (!service) {\n throw new PluginError('unsupported', 'redaction', 'this engine has no redaction service');\n }\n return service;\n };\n /** Every page's ref, in display order. */\n const pages = (): PageRef[] => (ctx.document()?.pages ?? []).map((page) => page.ref);\n /** Page object number → display index, rebuilt only when the page registry changes. */\n const indexByPage = memo(\n () => [ctx.document()?.pages] as const,\n (layouts) => new Map((layouts ?? []).map((page) => [page.ref.objectNumber, page.index])),\n );\n const pageIndexOf = (page: PageRef): number => indexByPage().get(page.objectNumber) ?? -1;\n const canApply = (): boolean =>\n ctx.doc.redaction !== undefined &&\n APPLY_CAPABILITIES.every((capability) => ctx.doc.security.allows(capability));\n return { requireService, pages, pageIndexOf, canApply };\n}\nexport type RedactionStore = ReturnType<typeof createStore>;\n","/** The plugin-private services every area is built on, created once per instance. */\nimport type { RedactionContext } from './context';\nimport { createEvents, type RedactionEvents } from './events';\nimport { resolveSiblings, type RedactionSiblings } from './siblings';\nimport { createStore, type RedactionStore } from './store';\n\nexport type { RedactionContext } from './context';\n\nexport interface RedactionServices {\n readonly events: RedactionEvents;\n readonly store: RedactionStore;\n readonly siblings: RedactionSiblings;\n}\n\nexport function createServices(ctx: RedactionContext): RedactionServices {\n return { events: createEvents(ctx), store: createStore(ctx), siblings: resolveSiblings(ctx) };\n}\n","/**\n * The redaction session: whether an apply is running and the last confirmed\n * apply result. Marks are annotations and live on the annotation plane. Every\n * function below is a pure transition; the controller applies them with\n * `ctx.state.update`.\n */\nimport type { RedactionApplyResult } from '@embedpdf/engine-core';\n\nexport interface RedactionState {\n /** An apply of this session is running at the engine. */\n readonly applying: boolean;\n /** The last confirmed apply result, from this session or another. */\n readonly lastResult: RedactionApplyResult | null;\n}\n\nexport const initialRedactionState = (): RedactionState => ({\n applying: false,\n lastResult: null,\n});\n\nexport const startApply = (state: RedactionState): RedactionState =>\n state.applying ? state : { ...state, applying: true };\n\nexport const finishApply = (state: RedactionState): RedactionState =>\n state.applying ? { ...state, applying: false } : state;\n\nexport const setLastResult = (\n state: RedactionState,\n result: RedactionApplyResult,\n): RedactionState => (state.lastResult === result ? state : { ...state, lastResult: result });\n","/**\n * Every confirmed apply, from this session or another, arrives as one\n * `redaction.applied` document event: the only place `lastResult` changes and\n * `onApplied` fires. Annotation state and raster invalidation are handled by\n * their own plugins. Marks are annotations, so the pending view changes\n * whenever a `redact` annotation does.\n */\nimport type { AnnotationCreatedEvent } from '@embedpdf/plugin-annotation/contract';\n\nimport { setLastResult } from '../model';\nimport type { RedactionContext, RedactionServices } from '../services';\n\nexport function subscribeChanges(\n ctx: RedactionContext,\n { events, siblings }: Pick<RedactionServices, 'events' | 'siblings'>,\n): void {\n const { applied, pendingChanged } = events;\n const { annotation } = siblings;\n\n ctx.listen(ctx.doc.events, (event) => {\n if (event.type !== 'redaction.applied') return;\n const { type: _type, origin, ...result } = event;\n ctx.state.update(setLastResult, result);\n applied.emit({ result, origin });\n });\n\n const markChanged = ({ annotation: changed }: AnnotationCreatedEvent) => {\n if (changed.subtype === 'redact') pendingChanged.emit({ pages: [changed.page] });\n };\n ctx.listen(annotation.onCreated, markChanged);\n ctx.listen(annotation.onUpdated, markChanged);\n // A deleted record has no subtype any more; the page's list changed either way.\n ctx.listen(annotation.onDeleted, (event) => pendingChanged.emit({ pages: [event.page] }));\n}\n","/**\n * The `overlay` settings as the redact tool's defaults. Every mark takes its\n * look from them: one drawn with the tool, one made from the selected text,\n * and one made from code (`write/marks.ts`). Written when the plugin\n * connects and again whenever the settings change, so a change applies to\n * the marks made from then on; marks already made keep theirs.\n */\nimport type { RedactionSettings } from '../contract';\nimport type { RedactionContext, RedactionServices } from '../services';\n\n/** The redact tool's fields the overlay settings stand for. */\nconst toolDefaultsOf = ({ overlay }: RedactionSettings) => ({\n interiorColor: overlay.fill,\n fontColor: overlay.text.color,\n fontFamily: overlay.text.fontFamily,\n fontSize: overlay.text.fontSize,\n});\n\nexport function syncOverlay(\n ctx: RedactionContext,\n { siblings }: Pick<RedactionServices, 'siblings'>,\n): void {\n const { annotation } = siblings;\n const settings = ctx.settings();\n const write = () => annotation.tools.updateDefaults('redact', toolDefaultsOf(settings.get()));\n write();\n ctx.listen(settings.api.onSettingsChanged, ({ changed }) => {\n if (changed.includes('overlay')) write();\n });\n}\n","/**\n * The destructive half: `doc.redaction.apply` in refs or pages scope. Applies\n * run one at a time, in call order, so each one sees the marks the previous\n * one left. The result reaches `lastResult` and `onApplied` through the\n * confirmed `redaction.applied` event, which the engine publishes before the\n * apply resolves; this area only brackets the call with the `applying` flag.\n */\nimport { PluginError, annotationKey, type OperationOptions } from '@embedpdf/core';\nimport type {\n AnnotationRef,\n PageRef,\n RedactionApplyResult,\n RedactionApplyScope,\n} from '@embedpdf/engine-core';\n\nimport type { RedactionCapability } from '../contract';\nimport { finishApply, startApply } from '../model';\nimport type { RedactionPendingReads } from '../read/pending';\nimport type { RedactionContext, RedactionServices } from '../services';\n\nexport function createApplying(\n ctx: RedactionContext,\n { store }: Pick<RedactionServices, 'store'>,\n { listPending }: Pick<RedactionPendingReads, 'listPending'>,\n) {\n const { requireService, pages } = store;\n const queue = ctx.serialQueue('apply');\n // A download waits for a redaction being applied: its content must not be in the file.\n ctx.onSettle(() => queue.idle());\n\n /**\n * Queue an apply whose scope is computed when its turn comes. One whose\n * signal fired while it waited never starts; one cancelled while the\n * engine applies rejects `operation-cancelled` at once, and the engine's\n * `redaction.applied` says what it removed.\n */\n const runApply = (\n scopeOf: () => RedactionApplyScope,\n options: OperationOptions | undefined,\n ): Promise<RedactionApplyResult> =>\n queue(\n async () => {\n const service = requireService();\n const scope = scopeOf();\n ctx.state.update(startApply);\n try {\n return await ctx.cancellable(options?.signal, service.apply(scope));\n } finally {\n ctx.state.update(finishApply);\n }\n },\n { signal: options?.signal },\n );\n\n const apply = (\n refs: readonly AnnotationRef[],\n options?: OperationOptions,\n ): Promise<RedactionApplyResult> =>\n runApply(() => {\n const wanted = new Set(refs.map(annotationKey));\n const marks = listPending()\n .filter((mark) => wanted.has(annotationKey(mark.ref)))\n .map((mark) => mark.ref);\n if (marks.length === 0) {\n throw new PluginError('not-found', 'redaction', 'no matching pending marks');\n }\n return { annotations: marks };\n }, options);\n\n const applyPages = async (\n targets: readonly (PageRef | number)[],\n options?: OperationOptions,\n ): Promise<RedactionApplyResult> => {\n if (targets.length === 0) {\n throw new PluginError('invalid-input', 'redaction', 'no pages given');\n }\n // Every page is resolved first: a page that isn't there refuses the call.\n const pages = targets.map((page) => ctx.pageOf(page).ref);\n return runApply(() => ({ pages }), options);\n };\n\n const applyAll = (options?: OperationOptions): Promise<RedactionApplyResult> =>\n runApply(() => {\n // Pages scope is authoritative for the whole document, including marks\n // on pages this client never loaded. Pages without marks report 'unchanged'.\n const all = pages();\n if (all.length === 0) {\n throw new PluginError('not-ready', 'redaction', 'the document has no pages');\n }\n return { pages: all };\n }, options);\n\n return { api: { apply, applyPages, applyAll } satisfies Partial<RedactionCapability> };\n}\n","/**\n * Marking: every mark is a `redact` annotation created through the annotation\n * plugin, in the style of the redact tool's defaults, which follow the\n * `overlay` settings (`sync/overlay.ts`). Removing a mark and changing its\n * label are annotation deletes and updates, checked per mark.\n */\nimport {\n PluginError,\n annotationKey,\n toPluginError,\n toPluginErrorInfo,\n type BatchResult,\n type OperationOptions,\n} from '@embedpdf/core';\nimport type { Rect } from '@embedpdf/core-geometry';\nimport type {\n Annotation,\n AnnotationDraft,\n AnnotationRef,\n PageRef,\n SearchQuery,\n} from '@embedpdf/engine-core';\n\nimport type { RedactionCapability, RedactionLabelPatch, RedactionMark } from '../contract';\nimport type { RedactionPendingReads } from '../read/pending';\nimport type { RedactionContext, RedactionServices } from '../services';\n\n/** The redact tool's defaults: the fields a mark draft takes from them. */\ntype RedactDefaults = Pick<\n Extract<AnnotationDraft, { subtype: 'redact' }>,\n 'color' | 'interiorColor' | 'opacity' | 'fontFamily' | 'fontSize' | 'fontColor' | 'textAlign'\n>;\n\n/** Stop before the next step once the caller cancelled. */\nconst throwIfCancelled = (signal: AbortSignal | undefined): void => {\n if (signal?.aborted) {\n throw new PluginError('operation-cancelled', 'redaction', 'operation cancelled', {\n cause: signal.reason,\n });\n }\n};\n\nexport function createMarking(\n ctx: RedactionContext,\n { siblings }: Pick<RedactionServices, 'siblings'>,\n { listPending, markFor }: Pick<RedactionPendingReads, 'listPending' | 'markFor'>,\n) {\n const { annotation, selection, search } = siblings;\n\n /**\n * A new mark's style, as the engine takes it: the redact tool's current\n * defaults, which carry the `overlay` settings, so a mark from code looks\n * like one drawn with the tool.\n */\n const markStyle = (): RedactDefaults => {\n const tool = annotation.tools.getDefaults('redact') as RedactDefaults;\n return {\n color: tool.color,\n interiorColor: tool.interiorColor,\n opacity: tool.opacity,\n fontFamily: tool.fontFamily,\n fontSize: tool.fontSize,\n fontColor: tool.fontColor,\n textAlign: tool.textAlign,\n };\n };\n\n /** The mark a created or changed record is. */\n const markOfRecord = (record: Annotation): RedactionMark => {\n const mark = markFor(record);\n if (!mark) throw new PluginError('operation-failed', 'redaction', 'the record is not a mark');\n return mark;\n };\n\n /** Whether a ref is a mark waiting to be applied. */\n const isPending = (ref: AnnotationRef): boolean => {\n const key = annotationKey(ref);\n return listPending().some((mark) => annotationKey(mark.ref) === key);\n };\n\n const canUnmark = (ref: AnnotationRef): boolean => isPending(ref) && annotation.canDelete(ref);\n const canUpdateLabel = (ref: AnnotationRef): boolean =>\n isPending(ref) && annotation.canUpdate(ref);\n\n const markSelection = async (\n options?: OperationOptions,\n ): Promise<{ marks: readonly RedactionMark[] }> => {\n ctx.assertAllowed('annotations:create', 'redaction.markSelection');\n const plane = selection();\n if (!plane) throw new PluginError('unsupported', 'redaction', 'no selection plugin');\n if (!plane.hasSelection()) return { marks: [] };\n // The selected text frame rides all the way into `/QuadPoints`: native\n // apply uses these exact cells, so marked == previewed == applied.\n const { annotations } = await annotation.createFromSelection('redact', {\n clear: true,\n signal: options?.signal,\n });\n return { marks: annotations.map(markOfRecord) };\n };\n\n const createMark = async (\n page: PageRef,\n region: Pick<Extract<AnnotationDraft, { subtype: 'redact' }>, 'rect' | 'quadPoints'>,\n signal: AbortSignal | undefined,\n ): Promise<RedactionMark> => {\n const created = await annotation.create(\n page,\n { subtype: 'redact', ...region, ...markStyle() },\n undefined,\n { signal },\n );\n return markOfRecord(created.annotation);\n };\n\n const markArea = async (\n page: PageRef | number,\n bounds: Rect,\n options?: OperationOptions,\n ): Promise<{ mark: RedactionMark }> => {\n ctx.assertAllowed('annotations:create', 'redaction.markArea');\n const target = ctx.pageOf(page).ref;\n return { mark: await createMark(target, { rect: bounds }, options?.signal) };\n };\n\n const markPage = async (\n page: PageRef | number,\n options?: OperationOptions,\n ): Promise<{ mark: RedactionMark }> => {\n ctx.assertAllowed('annotations:create', 'redaction.markPage');\n const layout = ctx.pageOf(page);\n const whole = { x: 0, y: 0, width: layout.size.width, height: layout.size.height };\n return { mark: await createMark(layout.ref, { rect: whole }, options?.signal) };\n };\n\n const markMatches = async (\n query: SearchQuery,\n options?: { pages?: readonly (PageRef | number)[] } & OperationOptions,\n ): Promise<{ marks: readonly RedactionMark[] }> => {\n ctx.assertAllowed('annotations:create', 'redaction.markMatches');\n const signal = options?.signal;\n const finder = search();\n if (!finder) throw new PluginError('unsupported', 'redaction', 'no search plugin');\n const wanted = options?.pages\n ? new Set(options.pages.map((page) => ctx.pageOf(page).ref.objectNumber))\n : null;\n await finder.search(query, { signal });\n const marks: RedactionMark[] = [];\n for (const hit of finder.listHits()) {\n if (wanted && !wanted.has(hit.page.objectNumber)) continue;\n if (hit.segments.length === 0) continue;\n throwIfCancelled(signal);\n // The engine's rect covers the quads.\n marks.push(\n await createMark(\n hit.page,\n { quadPoints: hit.segments.map((segment) => segment.quad) },\n signal,\n ),\n );\n }\n return { marks };\n };\n\n const unmark = async (\n refs: readonly AnnotationRef[],\n options?: OperationOptions,\n ): Promise<BatchResult<AnnotationRef, AnnotationRef>> => {\n const signal = options?.signal;\n throwIfCancelled(signal);\n const applied: AnnotationRef[] = [];\n const skipped: BatchResult<AnnotationRef, AnnotationRef>['skipped'][number][] = [];\n const failed: BatchResult<AnnotationRef, AnnotationRef>['failed'][number][] = [];\n for (const ref of refs) {\n if (!isPending(ref)) {\n skipped.push({ ref, reason: 'not a pending redaction mark' });\n continue;\n }\n if (!annotation.canDelete(ref)) {\n const refused = new PluginError(\n 'permission-denied',\n 'redaction',\n 'redaction.unmark requires annotations:delete',\n { permission: 'annotations:delete' },\n );\n failed.push({ ref, error: toPluginErrorInfo(refused) });\n continue;\n }\n try {\n await annotation.delete(ref, { signal });\n applied.push(ref);\n } catch (error) {\n const refused = toPluginError('redaction', error);\n // A cancel ends the batch: the marks removed so far stay removed.\n if (refused.code === 'operation-cancelled') throw refused;\n failed.push({ ref, error: toPluginErrorInfo(refused) });\n }\n }\n return { applied, skipped, failed };\n };\n const clearPending = (options?: OperationOptions) =>\n unmark(\n listPending().map((mark) => mark.ref),\n options,\n );\n\n const updateLabel = async (\n ref: AnnotationRef,\n patch: RedactionLabelPatch,\n options?: OperationOptions,\n ): Promise<{ mark: RedactionMark }> => {\n const current = annotation.get(ref);\n if (!current || current.subtype !== 'redact') {\n throw new PluginError('not-found', 'redaction', 'the target is not a redaction mark');\n }\n if (!annotation.canUpdate(ref)) {\n throw new PluginError(\n 'permission-denied',\n 'redaction',\n 'redaction.updateLabel requires annotations:update',\n { permission: 'annotations:update' },\n );\n }\n try {\n // Always carry the current /DA styling: the engine rewrites /DA whenever\n // a label field rides a patch, so a text-only edit must not let the\n // styling fall back to defaults.\n const updated = await annotation.update(\n ref,\n {\n subtype: 'redact',\n ...(patch.overlayText !== undefined ? { overlayText: patch.overlayText } : {}),\n ...(patch.repeat !== undefined ? { repeat: patch.repeat } : {}),\n fontFamily: current.fontFamily,\n fontSize: current.fontSize,\n fontColor: current.fontColor,\n textAlign: current.textAlign,\n },\n undefined,\n { signal: options?.signal },\n );\n return { mark: markOfRecord(updated.annotation) };\n } catch (error) {\n throw toPluginError('redaction', error);\n }\n };\n\n return {\n api: {\n canUnmark,\n canUpdateLabel,\n markSelection,\n markArea,\n markPage,\n markMatches,\n unmark,\n clearPending,\n updateLabel,\n } satisfies Partial<RedactionCapability>,\n };\n}\n","/**\n * The redaction controller: the composition root. It builds the plugin's\n * services once, wires each area with the services it declares, and\n * assembles the capability from the areas' API slices. No behavior lives\n * here: every verb and read has a home in `read/`, `write/` or `sync/`.\n */\nimport { composeApi } from '@embedpdf/core';\n\nimport type { RedactionCapability } from './contract';\nimport { createPendingReads } from './read/pending';\nimport { createServices, type RedactionContext } from './services';\nimport { subscribeChanges } from './sync/document-events';\nimport { syncOverlay } from './sync/overlay';\nimport { createApplying } from './write/apply';\nimport { createMarking } from './write/marks';\n\nexport function createRedactionController(ctx: RedactionContext) {\n const services = createServices(ctx);\n const { events, store } = services;\n const settings = ctx.settings();\n\n const pending = createPendingReads(ctx, services);\n const marking = createMarking(ctx, services, pending);\n const applying = createApplying(ctx, services, pending);\n\n const api: RedactionCapability = composeApi('redaction', [\n settings.api,\n pending.api,\n marking.api,\n applying.api,\n {\n // Marks are annotations, so marking needs the session's annotation\n // create permission: what the annotation plugin's `canCreate` reads too.\n canMark: () => ctx.allows('annotations:create'),\n canApply: store.canApply,\n isApplying: () => ctx.state.get().applying,\n getLastResult: () => ctx.state.get().lastResult,\n onApplied: events.applied.on,\n onPendingChanged: events.pendingChanged.on,\n },\n ]);\n\n return {\n api,\n connect() {\n subscribeChanges(ctx, services);\n syncOverlay(ctx, services);\n },\n };\n}\n","import { definePlugin } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { SearchToken } from '@embedpdf/plugin-search/contract';\nimport { SelectionToken } from '@embedpdf/plugin-selection/contract';\n\nimport { REDACTION_DEFAULTS, RedactionToken, type RedactionConfig } from './contract';\nimport { createRedactionController } from './controller';\nimport { initialRedactionState } from './model';\n\n/**\n * Document-scoped redaction plugin: the destructive half of the two-stage\n * model. Marking is annotation work (the composed `redact` tool ships with\n * plugin-annotation); this plugin wraps `doc.redaction.apply`, projects the\n * pending queue out of annotation state, and estimates collateral for\n * confirm dialogs. It owns no mark state of its own.\n *\n * Trust boundary: on a layered document, applying rewrites the layer's bytes;\n * the immutable base keeps the original. The package README explains the consequences.\n * `config` is the settings the app registers, over {@link REDACTION_DEFAULTS}.\n */\nexport const redactionPlugin = (config?: RedactionConfig) =>\n definePlugin({\n id: 'redaction',\n token: RedactionToken,\n scope: 'document',\n requires: [AnnotationToken],\n optional: [SelectionToken, SearchToken],\n state: initialRedactionState,\n settings: { defaults: REDACTION_DEFAULTS, registered: config },\n create: createRedactionController,\n });\n","/**\n * The redaction page's State table as code: what `useRedactionState()`\n * returns, and the same fields in every other framework. The marks\n * themselves are not here: `usePendingRedactions()` reads them, so a\n * component that only shows the count doesn't re-render for every mark.\n */\nimport { defineState } from '@embedpdf/core';\n\nimport { RedactionToken } from './contract';\n\nexport const redactionState = defineState(RedactionToken, {\n read: (redaction) => ({\n pendingCount: redaction.getPendingCount(),\n applying: redaction.isApplying(),\n lastResult: redaction.getLastResult(),\n }),\n empty: {\n pendingCount: 0,\n applying: false,\n lastResult: null,\n },\n});\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as RedactionCollateral, c as RedactionMark, d as RedactionSettings, f as RedactionToken, i as RedactionCapability, l as RedactionMarkFilter, n as RedactionAppliedEvent, o as RedactionConfig, r as RedactionApplyResult, s as RedactionLabelPatch, t as REDACTION_DEFAULTS, u as RedactionPendingChangedEvent } from "./contract-TU9orxrO.cjs";
|
|
2
|
+
import { RedactionApplyResult as RedactionApplyResult$1 } from "@embedpdf/engine-core";
|
|
3
|
+
//#region src/model.d.ts
|
|
4
|
+
interface RedactionState {
|
|
5
|
+
/** An apply of this session is running at the engine. */
|
|
6
|
+
readonly applying: boolean;
|
|
7
|
+
/** The last confirmed apply result, from this session or another. */
|
|
8
|
+
readonly lastResult: RedactionApplyResult$1 | null;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
2
11
|
//#region src/redaction.plugin.d.ts
|
|
3
12
|
/**
|
|
4
|
-
* Document-scoped redaction plugin
|
|
5
|
-
* model. Marking is annotation
|
|
6
|
-
*
|
|
7
|
-
*
|
|
13
|
+
* Document-scoped redaction plugin: the destructive half of the two-stage
|
|
14
|
+
* model. Marking is annotation work (the composed `redact` tool ships with
|
|
15
|
+
* plugin-annotation); this plugin wraps `doc.redaction.apply`, projects the
|
|
16
|
+
* pending queue out of annotation state, and estimates collateral for
|
|
8
17
|
* confirm dialogs. It owns no mark state of its own.
|
|
9
18
|
*
|
|
10
|
-
* Trust boundary: on a layered document, applying rewrites the
|
|
11
|
-
* the immutable base keeps the original.
|
|
19
|
+
* Trust boundary: on a layered document, applying rewrites the layer's bytes;
|
|
20
|
+
* the immutable base keeps the original. The package README explains the consequences.
|
|
21
|
+
* `config` is the settings the app registers, over {@link REDACTION_DEFAULTS}.
|
|
12
22
|
*/
|
|
13
|
-
declare const redactionPlugin: () => import("@embedpdf/core").PluginDef<RedactionState,
|
|
23
|
+
declare const redactionPlugin: (config?: RedactionConfig) => import("@embedpdf/core").PluginDef<RedactionState, RedactionCapability, RedactionSettings>;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/state.d.ts
|
|
26
|
+
declare const redactionState: import("@embedpdf/core").StateDeclaration<RedactionCapability, {
|
|
27
|
+
pendingCount: number;
|
|
28
|
+
applying: boolean;
|
|
29
|
+
lastResult: import("@embedpdf/engine-core").RedactionApplyResult | null;
|
|
30
|
+
}>;
|
|
14
31
|
//#endregion
|
|
15
|
-
export { type RedactionApplyResult,
|
|
32
|
+
export { REDACTION_DEFAULTS, RedactionAppliedEvent, type RedactionApplyResult, RedactionCapability, RedactionCollateral, RedactionConfig, RedactionLabelPatch, RedactionMark, RedactionMarkFilter, RedactionPendingChangedEvent, RedactionSettings, RedactionToken, redactionPlugin, redactionState };
|
|
16
33
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as RedactionCollateral, c as RedactionMark, d as RedactionSettings, f as RedactionToken, i as RedactionCapability, l as RedactionMarkFilter, n as RedactionAppliedEvent, o as RedactionConfig, r as RedactionApplyResult, s as RedactionLabelPatch, t as REDACTION_DEFAULTS, u as RedactionPendingChangedEvent } from "./contract-TU9orxrO.js";
|
|
2
|
+
import { RedactionApplyResult as RedactionApplyResult$1 } from "@embedpdf/engine-core";
|
|
3
|
+
//#region src/model.d.ts
|
|
4
|
+
interface RedactionState {
|
|
5
|
+
/** An apply of this session is running at the engine. */
|
|
6
|
+
readonly applying: boolean;
|
|
7
|
+
/** The last confirmed apply result, from this session or another. */
|
|
8
|
+
readonly lastResult: RedactionApplyResult$1 | null;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
2
11
|
//#region src/redaction.plugin.d.ts
|
|
3
12
|
/**
|
|
4
|
-
* Document-scoped redaction plugin
|
|
5
|
-
* model. Marking is annotation
|
|
6
|
-
*
|
|
7
|
-
*
|
|
13
|
+
* Document-scoped redaction plugin: the destructive half of the two-stage
|
|
14
|
+
* model. Marking is annotation work (the composed `redact` tool ships with
|
|
15
|
+
* plugin-annotation); this plugin wraps `doc.redaction.apply`, projects the
|
|
16
|
+
* pending queue out of annotation state, and estimates collateral for
|
|
8
17
|
* confirm dialogs. It owns no mark state of its own.
|
|
9
18
|
*
|
|
10
|
-
* Trust boundary: on a layered document, applying rewrites the
|
|
11
|
-
* the immutable base keeps the original.
|
|
19
|
+
* Trust boundary: on a layered document, applying rewrites the layer's bytes;
|
|
20
|
+
* the immutable base keeps the original. The package README explains the consequences.
|
|
21
|
+
* `config` is the settings the app registers, over {@link REDACTION_DEFAULTS}.
|
|
12
22
|
*/
|
|
13
|
-
declare const redactionPlugin: () => import("@embedpdf/core").PluginDef<RedactionState,
|
|
23
|
+
declare const redactionPlugin: (config?: RedactionConfig) => import("@embedpdf/core").PluginDef<RedactionState, RedactionCapability, RedactionSettings>;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/state.d.ts
|
|
26
|
+
declare const redactionState: import("@embedpdf/core").StateDeclaration<RedactionCapability, {
|
|
27
|
+
pendingCount: number;
|
|
28
|
+
applying: boolean;
|
|
29
|
+
lastResult: import("@embedpdf/engine-core").RedactionApplyResult | null;
|
|
30
|
+
}>;
|
|
14
31
|
//#endregion
|
|
15
|
-
export { type RedactionApplyResult,
|
|
32
|
+
export { REDACTION_DEFAULTS, RedactionAppliedEvent, type RedactionApplyResult, RedactionCapability, RedactionCollateral, RedactionConfig, RedactionLabelPatch, RedactionMark, RedactionMarkFilter, RedactionPendingChangedEvent, RedactionSettings, RedactionToken, redactionPlugin, redactionState };
|
|
16
33
|
//# sourceMappingURL=index.d.ts.map
|