diff --git a/docs/pdf-json-editor-backlog.md b/docs/pdf-json-editor-backlog.md
index a87a596b1..fdc7d032e 100644
--- a/docs/pdf-json-editor-backlog.md
+++ b/docs/pdf-json-editor-backlog.md
@@ -6,11 +6,6 @@
- Extend conversion logic so fallback kicks in only when conversion fails, and track which elements rely on the synthetic font to avoid mixing source glyphs (`PdfJsonConversionService.java:998-1090`, `1840-2012`).
- Update the viewer/renderer to surface conversion errors and block editing when no faithful font can be produced.
-- **Vector Artwork Preview**
- - Reuse `contentStreams` already emitted by the backend to render vector paths alongside text/images in the React workspace (`frontend/src/proprietary/components/tools/pdfJsonEditor/PdfJsonEditorView.tsx:1048-1285`).
- - Either render via Canvas/SVG on the client or call back to a server-rendered bitmap for the background. Keep edited text/images layered on top.
- - Maintain export fidelity by writing any untouched vector stream back during PDF regeneration (`PdfJsonConversionService.java:1714-1799`, `520-612`).
-
- **Lazy Fetch Endpoints**
- Provide separate endpoints to fetch:
1. Raw COS dictionaries/font programs when the user opens advanced panels.
diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json
index a8aa15173..9c216ceec 100644
--- a/frontend/public/locales/en-GB/translation.json
+++ b/frontend/public/locales/en-GB/translation.json
@@ -4431,6 +4431,7 @@
"noTextOnPage": "No editable text was detected on this page.",
"emptyGroup": "[Empty Group]",
"imageLabel": "Placed image",
+ "pagePreviewAlt": "Page preview",
"empty": {
"title": "No document loaded",
"subtitle": "Load a PDF or JSON file to begin editing text content."
diff --git a/frontend/src/proprietary/components/tools/pdfJsonEditor/PdfJsonEditorView.tsx b/frontend/src/proprietary/components/tools/pdfJsonEditor/PdfJsonEditorView.tsx
index c3ae8cd1e..e14ba1f64 100644
--- a/frontend/src/proprietary/components/tools/pdfJsonEditor/PdfJsonEditorView.tsx
+++ b/frontend/src/proprietary/components/tools/pdfJsonEditor/PdfJsonEditorView.tsx
@@ -219,9 +219,11 @@ const PdfJsonEditorView = ({ data }: PdfJsonEditorViewProps) => {
document: pdfDocument,
groupsByPage,
imagesByPage,
+ pagePreviews,
selectedPage,
dirtyPages,
hasDocument,
+ hasVectorPreview,
fileName,
errorMessage,
isGeneratingPdf,
@@ -229,6 +231,7 @@ const PdfJsonEditorView = ({ data }: PdfJsonEditorViewProps) => {
conversionProgress,
hasChanges,
forceSingleTextElement,
+ requestPagePreview,
onLoadJson,
onSelectPage,
onGroupEdit,
@@ -403,6 +406,7 @@ const PdfJsonEditorView = ({ data }: PdfJsonEditorViewProps) => {
const currentPage = pages[selectedPage] ?? null;
const pageGroups = groupsByPage[selectedPage] ?? [];
const pageImages = imagesByPage[selectedPage] ?? [];
+ const pagePreview = pagePreviews.get(selectedPage);
const extractPreferredFontId = useCallback((target?: TextGroup | null) => {
if (!target) {
@@ -615,12 +619,21 @@ const PdfJsonEditorView = ({ data }: PdfJsonEditorViewProps) => {
),
[pageImages],
);
-
const { width: pageWidth, height: pageHeight } = pageDimensions(currentPage);
const scale = useMemo(() => Math.min(MAX_RENDER_WIDTH / pageWidth, 1.5), [pageWidth]);
const scaledWidth = pageWidth * scale;
const scaledHeight = pageHeight * scale;
+ useEffect(() => {
+ if (!hasDocument || !hasVectorPreview) {
+ return;
+ }
+ requestPagePreview(selectedPage, scale);
+ if (selectedPage + 1 < pages.length) {
+ requestPagePreview(selectedPage + 1, scale);
+ }
+ }, [hasDocument, hasVectorPreview, selectedPage, scale, pages.length, requestPagePreview]);
+
useEffect(() => {
setActiveGroupId(null);
setEditingGroupId(null);
@@ -1123,7 +1136,23 @@ const PdfJsonEditorView = ({ data }: PdfJsonEditorViewProps) => {
}}
ref={containerRef}
>
- {orderedImages.map((image, imageIndex) => {
+ {pagePreview && (
+
+ )}
+ {orderedImages.map((image, imageIndex) => {
if (!image?.imageData) {
return null;
}
diff --git a/frontend/src/proprietary/tools/pdfJsonEditor/PdfJsonEditor.tsx b/frontend/src/proprietary/tools/pdfJsonEditor/PdfJsonEditor.tsx
index 47b183102..4c1c6034a 100644
--- a/frontend/src/proprietary/tools/pdfJsonEditor/PdfJsonEditor.tsx
+++ b/frontend/src/proprietary/tools/pdfJsonEditor/PdfJsonEditor.tsx
@@ -10,6 +10,8 @@ import { CONVERSION_ENDPOINTS } from '@app/constants/convertConstants';
import apiClient from '@app/services/apiClient';
import { downloadBlob, downloadTextAsFile } from '@app/utils/downloadUtils';
import { getFilenameFromHeaders } from '@app/utils/fileResponseUtils';
+import { pdfWorkerManager } from '@core/services/pdfWorkerManager';
+import { Util } from 'pdfjs-dist/legacy/build/pdf.mjs';
import {
PdfJsonDocument,
PdfJsonImageElement,
@@ -27,6 +29,7 @@ import {
valueOr,
} from './pdfJsonEditorUtils';
import PdfJsonEditorView from '@app/components/tools/pdfJsonEditor/PdfJsonEditorView';
+import type { PDFDocumentProxy } from 'pdfjs-dist';
const VIEW_ID = 'pdfJsonEditorView';
const WORKBENCH_ID = 'custom:pdfJsonEditor' as const;
@@ -75,6 +78,8 @@ const PdfJsonEditor = ({ onComplete, onError }: BaseToolProps) => {
message: string;
} | null>(null);
const [forceSingleTextElement, setForceSingleTextElement] = useState(false);
+ const [hasVectorPreview, setHasVectorPreview] = useState(false);
+ const [pagePreviews, setPagePreviews] = useState