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
documentViewersMap (the multi-instance registry). - One function per file: filename === function name; default-exported arrow function.
docNumis always the last parameter when present, forwarded togetDocumentViewer(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):
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.jsregisters instance 1;CompareDocumentContainer.vueregisters instances 2 and 3 (the compare old/new file viewers). - Only ~13 of ~120 bridge files plumb
docNumthrough; 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.
Navigation, page & viewport
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) — probesdocumentViewer.toolRegistry.register, falls back todocumentViewer.registerTool, returnsfalseif neither exists.initializeViewer.js(15 lines) — destructures{ container, viewer, thumbnailView, outlineView, toggleButton }before forwarding.eventBus.js— returnsgetDocumentViewer().eventBus(not stateful, despite the name).setDocumentName.js/getDocumentName.js— direct property access (getDocumentViewer().docName).
Previously-fixed issues:
checkCertificateIsTrusted.jsused to reference an undefineddata(it now forwards itsdataargument, matching its sibling certificate functions);setActiveSearchResult.jshad areseultparameter typo (nowresult); and thesearch,setActiveSearchResult,clearSearchResults, andsetAnnotationStylesbridge files used an inlinegetDocumentViewer(docNum = 1)reassignment idiom (nowgetDocumentViewer(docNum), relying on thegetDocumentViewer(number = 1)default).
Architectural takeaways
- Facade over the engine — a flat, categorized, stable surface over a monolithic class.
- One stateful seam, by design —
documentViewers.jsis the file to inspect when debugging "which viewer am I talking to". - Default-instance bias — instance 1 is the norm; multi-instance is opt-in per method.
- Clean layering — the bridge never touches stores or DOM;
apis/is the join point.