feat: improve PDF.js integration with custom canvas renderer#3648
Merged
hmiguim merged 8 commits intodevelopmentfrom Apr 17, 2026
Merged
feat: improve PDF.js integration with custom canvas renderer#3648hmiguim merged 8 commits intodevelopmentfrom
hmiguim merged 8 commits intodevelopmentfrom
Conversation
Remove extracted pdf_viewer.mjs and pdf_viewer.mjs.map files that were used to inspect the PDF.js webjar during development. These files are not part of the actual implementation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous approach modified span.innerHTML to insert <mark> elements inside PDF.js text layer spans. This broke the scaleX transforms that PDF.js sets on each span, causing marks to be mispositioned or invisible. New approach: - Use the Range API to locate the exact rendered rect of each text match - Create absolutely-positioned <div class="rodaPdfHighlight"> overlays inside the page container (position:relative), not inside the text spans - Falls back to the span bounding rect when text node content doesn't match exactly (e.g. nested elements) - clearHighlights now simply removes the overlay divs - focusSearchMatch scrolls precisely to the selected highlight element - CSS updated: .rodaPdfHighlight is now a positioned div, removing the inline mark-specific margin/padding/color properties Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous manual canvas+TextLayer approach was incompatible with PDF.js v5's CSS-custom-property-based text layer layout (--total-scale-factor, --font-height, --scale-x, etc.), which is only set up correctly by pdf_viewer.css. This caused search highlights to appear in completely wrong positions. This commit switches to the official PDF.js high-level components, exactly as used by the mozilla.github.io/pdf.js/web/viewer.html demo: - PDFViewer handles page rendering (canvas + text layer) correctly - PDFFindController handles text search and highlight via the EventBus - pdf_viewer.css is dynamically loaded once from the webjar so that the text layer CSS custom properties are defined - Our toolbar dispatches EventBus 'find'/'findbarclose' events instead of custom DOM manipulation - Removed all manual canvas rendering, TextLayer construction, Range- based highlight overlays, and presentation-mode overlay code - CSS updated: added rodaPdfScrollWrapper/rodaPdfScrollContainer layout, removed rodaPdfPages/rodaPdfPage/rodaPdfCanvas/rodaPdfTextLayer/ rodaPdfHighlight/presentation-mode rules (pdf_viewer.css owns those) - PDFViewer container is position:absolute as required by the library - Viewer height is 80vh (min 400px); fullscreen remains 100vh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PDFViewer checks getComputedStyle(container).position === 'absolute' at construction time. The CSS class alone is not reliable (possible GWT class pruning or loading-order race). Set all critical layout properties inline on scrollContainer, scrollWrapper, and content so the check always passes regardless of CSS class availability. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kage pdf_viewer.css sets :root CSS custom properties (including dark-mode media queries like --csstools-color-scheme--light) that leaked into the host application and affected unrelated components. Instead of loading the file via a global <link>, we now fetch the CSS text, replace every ':root' selector with '.rodaPdfViewer', and inject the result as a <style> element. Since all PDF.js DOM elements are descendants of .rodaPdfViewer, custom properties defined there are still inherited by .pdfViewer, .page, .textLayer, and .highlight — but they no longer pollute the rest of the page. Falls back to a global <link> if fetch fails (e.g. strict CSP). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chrome DevTools probes /.well-known/appspecific/com.chrome.devtools.json on every page load, which causes Spring's ExceptionHandlerExceptionResolver to log a WARN for every request. Set that logger to ERROR level so the harmless NoResourceFoundException no longer fills the logs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the iframe-based PDF.js viewer (`web/viewer.html`) with a self-contained PDF renderer built on the PDF.js high-level viewer components (`PDFViewer` + `PDFFindController`), the same approach used by the official Mozilla PDF.js demo.
Changes
Motivation
The old iframe approach required URL-encoding workarounds and loaded the entire PDF.js web application (with its own UI chrome), making styling and integration difficult. The new approach:
Test plan
🤖 Generated with Claude Code