PDF Generation Template Editor
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
This guide covers the utility modules (helpers/), Vue composables (hooks/), and registries (constants/) that support the UI layer.
src/helpers/ | File | Purpose |
|---|---|
device.js | Device/browser detection (detailed below). |
hotkeysManager.js | Minimal keyboard-shortcut manager: register(combo, handler), unregister(combo), initialize(), destroy(). Not yet wired into the app. |
loadDocument.js | Convenience wrapper around core.loadDocument(src, options, docNum) that wires the engine's progress callback to useDocument.setLoadingProgress. Usable helper (the live loading path in DocumentContainer.vue calls core.loadDocument directly). |
initDocument.js | Live bootstrap: new ComPDFKitViewer(options) from lib/webview.min.js, then core.setDocumentViewer(1, documentViewer). |
setupI18n.js | i18next initialization reference (declares Languages[] catalog + languageRules). |
getHashParameters.js | Parses window.location.hash into a key/value object (typed boolean coercion). |
getPopupPosition.js | Computes screen coordinates for annotation popups. |
loadScript.js | loadScript(src, warning) — Promise wrapper injecting <script> into <head>. Also exports loadConfig(initOptions) (the iframe↔parent config handshake). |
renderStampPreview.js | Floating .stamp-preview div that follows the mouse showing a stamp image. |
utils.js | uploadFile(extension), hslToRgb, convertColor, areColorsSimilar(c1, c2, threshold=10). |
annotationPermissions.js | canCopyAnnotations({ isReadOnly, isUserAdmin, currentAuthor, annotations }). |
device.js Exports booleans/functions computed once at module load from navigator.userAgent and window.innerWidth:
isDesktop() (> 900), isTabletOrMobile() (<= 900), isMobile / isMobileSize() (< 640).isMac, isWindows, isIOS (incl. iOS 13 MacIntel+touch), isAndroid, isHarmonyOSMobile, isiPad.isMobileDevice (iOS || Android || HarmonyOS || webOS/BlackBerry/IEMobile/Opera Mini) and isMobileDeviceFunc().isChrome, isSafari, isChromeOniOS, isFirefoxOniOS, isFirefox, isIEEdge, isIEEdgeChromium, isIE11, isIE, isIEEdgeLegacy.device.js is pulled in by ~27 components/stores; isMobileDevice / isiPad drive the mobile guards in setActiveToolMode / setToolbarGroup.
getPopupPosition.js getAnnotationPopupPositionBasedOn(rect, pageNumber, popup, documentViewerKey=1, position='right') → { left, top }. Pipeline: convert page-space rect corners to window coords via core.pageToWindow; read popup.getBoundingClientRect(); clamp left (center or right-aligned, BOUNDARY_PADDING=4) and top (prefer below the annotation at annotBottom + ANNOTATION_PADDING, fall back to above, then to the side with more space).
src/hooks/ | File | Status | Purpose |
|---|---|---|
useSearch.js | Functional, self-contained | Returns reactive search state (searchQuery, searchResults, currentIndex, searching, currentResult) plus search(), setActiveResult(), clear() methods that delegate to core.search / core.setActiveSearchResult / core.clearSearchResults. Does not touch the global document store, so it does not conflict with the store-driven search panel. |
useOnAnnotationPopupOpen.js | Functional, no consumers | Returns a { selectedAnnotation } ref; registers annotationSelected / annotationDeselected and removes them via onScopeDispose, so listeners are cleaned up when the owning scope disposes. |
Both hooks are currently orphaned (no consumers found by grep). They are safe to use as-is; alternatively prefer the store-based approach for search.
src/constants/ dataElements.js A centralized UPPER_SNAKE_CASE → camelCase/kebab-case map of every dataElement identifier — the single source of truth for the store's activeElements / disabledElements / activeElementsTab / headers keys. Sections: toolbar/header buttons, annotation tools, popup actions, crop popup, redaction, form tools, measurement tools, content editor, compare, document actions, panels, dialogs, disable-only chrome, and tab constants (ThumbnailsButton, OutlinesButton, AnnotationButton, LayersButton, SignatureButton, SearchButton, General, Appearance, Preference, Standard, Dynamic, Custom, Keyboard, Trackpad, …).
toolNames.js Three exports:
ToolNames — UPPER_SNAKE → camelCase map of every tool name (View, Annotation, Form, Measurement, Content editor, Signature, Security).DataElementToToolName — reverse map from DataElements.*_BUTTON to ToolNames.*.map — { [toolName]: { tool, toolName? } } lookup used by document.js#setToolState.register(tool) — adds a custom tool to map.panel.js panelNames — { pageModePanel, stampPanel } (lazy-rendered panels).noLazyPanelNames — { stylePanel, leftPanel, rightPanel, linkPanel, colorSeparationPanel, contentEditorPanel, redactionPanel } (eager-rendered panels).src/api_helpers/ | File | Purpose |
|---|---|
createEncapsulatedStore.js | Wraps a Pinia store to expose only dispatch(action)(args) and getState(key) (deep-cloned). Used by popup APIs, getPassword, getPanels. |
createPopupAPI.js | Builds the UI.Popup interface (add / update / getItems) for a given popup data-element. |