Skip to content
ComPDF
New Release

Open-Source PDF SDK & AI Document Processing

Get the full self-hosted SDK and AI document processing on GitHub. One-click deploy to quickly build your document workflows.

Core Bridge

The core bridge (packages/webview/src/core/) is the stateless facade between the Vue webview UI and the ComPDFKit Core engine. It hides the monolithic ComPDFKitViewer class behind ~120 thin functions and is the only layer permitted to call the engine.

Role and rules

  • Stateless: no business state, no DOM operations. The only mutable structure is the documentViewers Map (the multi-instance registry).
  • One function per file: filename === function name; default-exported arrow function.
  • docNum is always the last parameter when present, forwarded to getDocumentViewer(docNum).
  • Pure delegation: a typical bridge file is one line — getDocumentViewer(docNum).<engineMethod>(args...). Light argument destructuring is the only transformation.
  • One-way dependency: apis/ → core/ → engine. The bridge never touches Pinia stores or the DOM.

The multi-instance registry — documentViewers.js

The only stateful file (24 lines):

javascript
import ComPDFKitViewer from '../../lib/webview.min.js'
const documentViewerMap = new Map();

export const setDocumentViewer = (number, documentViewer, options) => {
  if (documentViewer) {
    documentViewerMap.set(number, documentViewer);   // pre-built viewer
  } else {
    const viewer = new ComPDFKitViewer(options);     // or construct here
    documentViewerMap.set(number, viewer);
  }
};
export const deleteDocumentViewer = (number) => { documentViewerMap.delete(number); };
export const getDocumentViewer = (number = 1) => documentViewerMap.get(number);
export const getDocumentViewers = () => Array.from(documentViewerMap.values());
  • Default instance = 1. getDocumentViewer() resolves to instance 1 (the primary document).
  • Two registration modes: store an externally-constructed viewer, or construct one internally from options.
  • Registration sites: helpers/initDocument.js registers instance 1; CompareDocumentContainer.vue registers instances 2 and 3 (the compare old/new file viewers).
  • Only ~13 of ~120 bridge files plumb docNum through; the rest are hardwired to instance 1.

Categorized capability map

core/index.js re-exports ~120 bridge functions. By domain:

Lifecycle & multi-instance

getDocumentViewer, setDocumentViewer, getDocumentViewers, deleteDocumentViewer, init, initConfig, initializeViewer.

Document loading, metadata & editing

loadDocument, getPagesCount, getCurrentPage, getDocumentName, setDocumentName, getOutlines, getOptionUrl, download, getDocEditorPages, saveDocumentEdit, compare.

nextPage, previousPage, pageNumberChanged, rotateClockwise, rotateCounterclockwise, zoomIn, zoomOut, scaleChanged, getScale, getScrollViewElement, getSelectedPage, pageToWindow, windowToPage, requestFullScreenMode, toggleSidebar, switchScrollMode, switchSpreadMode, webViewerNamedAction, webViewerPageMode.

Search & text

search, setActiveSearchResult, clearSearchResults, getSelectedText.

Annotations — CRUD, manager & history

getAnnotationsList, getAnnotationManager, getAnnotationHistoryManager, importAnnotations, exportAnnotations, exportXfdf, saveAnnotations, removeAllAnnotations, selectAnnotation, jumpToAnnotation, setAnnotationStyles, addAnnotationImage, handleReplyAnnotation, setUnselectableAnnotationTypes, getUnselectableAnnotationTypes, enableAutoSelectOnCreate, disableAutoSelectOnCreate, updateViewWithColorIndex, showPopup, handlePopup, setAnnotator.

Annotations — stamps & highlights

getDynamicStampPreview, getStampRect, handleStamp, setHighlightLink, setHighlightForm.

Tools

setTool, switchTool, setToolMode, getToolMode, getToolStyles, setToolStyles, registerTool, setDefaultSelect, setEraseMode, getEraseMode.

Content editing

switchAnnotationEditorMode, setContentEditorProperty, getContentEditManager, getContentEditHistoryManager, addEditorImage, getCropedPageImage.

Forms

handleField, enableSkipNoRequired, disableSkipNoRequired, isSkipNoRequired, setConsecutiveType, getConsecutiveType, disableFillConsecutively, isFillConsecutively, getFormSignFilledAndUnfilled, getRequiredFormSign, setAutoJumpNextSign.

Digital signatures

handleSign, getSignature, deleteSignature, verifySignature, getVerificationResult.

Certificates, security & permissions

loadCertificates, addToTrustedCertificateLists, checkCertificateIsTrusted, checkPermissionPassword, getPermission, setPassword, removePassword, checkPassword.

Redaction & flatten

applyRedactions, flattenPdf, flattenPdfDownload.

Layers & measurement

setLayers, exportLayers, setMeasurementDefaults.

Users & access control

setCurrentUser, getCurrentUser, isUserAdmin, isReadOnlyModeEnabled.

Property panel, events, printing, viewer element

setPropertyPanel, setInitProperty, eventBus, addEvent, removeEvent, triggerPrinting, getViewerElement, handleCreateStatus.

How apis/ consumes the bridge

apis/index.js does import core from '@/core' and spreads the entire bridge into objForWebViewerCore, published as window.instance.Core. It also exposes the default instance directly: window.instance.docViewer = core.getDocumentViewer().

Only 2 of ~67 apis/ files import core directly (index.js, registerTool.js); all others receive it via injection. The apis/ layer is the join point that composes bridge calls with store mutations (e.g. saveDocumentEditor.js calls core.saveDocumentEdit(), then orchestrates store actions and more bridge calls).

Notable exceptions

A few bridge files deviate from the clean one-liner pattern (useful to know when debugging):

  • registerTool.js (26 lines) — probes documentViewer.toolRegistry.register, falls back to documentViewer.registerTool, returns false if neither exists.
  • initializeViewer.js (15 lines) — destructures { container, viewer, thumbnailView, outlineView, toggleButton } before forwarding.
  • eventBus.js — returns getDocumentViewer().eventBus (not stateful, despite the name).
  • setDocumentName.js / getDocumentName.js — direct property access (getDocumentViewer().docName).

Previously-fixed issues: checkCertificateIsTrusted.js used to reference an undefined data (it now forwards its data argument, matching its sibling certificate functions); setActiveSearchResult.js had a reseult parameter typo (now result); and the search, setActiveSearchResult, clearSearchResults, and setAnnotationStyles bridge files used an inline getDocumentViewer(docNum = 1) reassignment idiom (now getDocumentViewer(docNum), relying on the getDocumentViewer(number = 1) default).

Architectural takeaways

  1. Facade over the engine — a flat, categorized, stable surface over a monolithic class.
  2. One stateful seam, by designdocumentViewers.js is the file to inspect when debugging "which viewer am I talking to".
  3. Default-instance bias — instance 1 is the norm; multi-instance is opt-in per method.
  4. Clean layering — the bridge never touches stores or DOM; apis/ is the join point.