Files
AI-Prototype/prompts/OCR-Viewer.md

7.8 KiB
Raw Blame History

Here's your step-by-step guide. Give Copilot one phase at a time — do not paste them all at once. PHASE 1 — CLEANUP: Remove all cross-highlighting code

Paste this first:

I need to clean up p44-ocr-viewer.html by removing all cross-panel word highlighting code that was never fully working. Do not change any CSS, layout, toolbar, PDF rendering, or OCR text rendering. Only remove the highlighting infrastructure.

Remove the following:

addHoverSpansToTextNodes() — the entire function
highlightBoxesByText() — the entire function
clearHighlightedBoxes() — the entire function
highlightSpansByText() — the entire function
clearHighlightedSpans() — the entire function
renderPlainTextWithLinks() — the entire function
buildIdQueue() — the entire function
dequeueId() — the entire function
The call to addHoverSpansToTextNodes(textOutput) inside showOCRPage()
The highlightSpansByText(title) fallback call inside makeWordBox()
The clearHighlightedSpans() call inside makeWordBox()
state.wordSequence if it was added
state.useJsonOverlay if it was added
All console.log statements added for debugging (the olmOCR word spans logs, PDF.js getTextContent logs)

Also remove the .word-span CSS rules from the stylesheet — the #text-output .word-span block.

After removal, verify:

showOCRPage() still renders text correctly
makeWordBox() still builds overlay boxes (they just won't trigger any cross-panel effects)
The #word-tip footer element can stay but its content should never be set
Sample data / JSON sidecar path must still work

PHASE 2 — Synchronized scrolling

After Phase 1 is working, paste this:

Add synchronized scrolling to p44-ocr-viewer.html. When the user scrolls either panel, the other panel scrolls to the same proportional vertical position.

Implementation:

Get references to both scroll containers: document.getElementById('image-panel-body') and document.getElementById('text-panel-body')
Add a scroll event listener to each. When one fires, calculate the scroll percentage: scrollTop / (scrollHeight - clientHeight). Apply that same percentage to the other panel's scrollTop.
Use a isSyncing boolean flag to prevent the two listeners from triggering each other in a loop. Set it true before programmatically scrolling, then false in a requestAnimationFrame callback after.
Add a toggle button to the toolbar labelled Sync Scroll with an active/inactive visual state (use the existing .tb-btn class). When inactive, the listeners are disconnected. Default state is active.

Constraints:

Do not change any existing scroll behaviour on page navigation
Do not change any CSS other than adding an .active state for the sync button that gives it border-color: var(--gold); color: var(--gold);

PHASE 3 — Click-to-zoom on the left panel

After Phase 2 is working, paste this:

Add click-to-zoom to the left panel (the PDF scan) in p44-ocr-viewer.html.

Implementation:

When the user clicks anywhere on #pdf-canvas, calculate the click position as a percentage of the canvas width and height.
Create a zoom overlay div with id zoom-lens that appears in the top-right corner of the left panel (position absolute, 280px × 200px, dark border, z-index 10). It contains a second canvas #zoom-canvas.
On click, draw a 3× magnified crop of the clicked region onto #zoom-canvas. The crop region is centered on the click point and covers 1/3 of the canvas width and height.
Clicking the same spot again, or clicking #zoom-lens itself, dismisses the zoom overlay.
Add a small ✕ close button in the top-right corner of #zoom-lens.
#zoom-lens styling: background: var(--surface), border: 1px solid var(--gold), border-radius: 4px. Use existing CSS variables throughout.

Constraints:

Do not affect PDF rendering or page navigation
The zoom lens must not appear until after the first click

PHASE 4 — Flag/annotation system

After Phase 3 is working, paste this:

Add a per-page flag/annotation system to p44-ocr-viewer.html. Reviewers can mark pages and the results persist to disk via the existing Python server.

Implementation:

Add three buttons to the right panel header (inside .panel-header, after the existing ocr-sync-label): ✓ Verified, ⚑ Needs Review, ✗ Error Found. Use the existing .tb-btn class. Add a fourth button Clear to remove a flag.
Store flags in a state.flags object keyed by page number: { 1: 'verified', 8: 'error', 12: 'review' }.
On page change, update the visual state of the three buttons to reflect the current page's flag (highlight the active one with border-color: var(--gold); color: var(--gold)).
Save flags by POSTing JSON to /save-flags on the local server. The payload is the entire state.flags object. If the POST fails silently (server doesn't support it yet), store in localStorage as a fallback with key p44-flags.
On startup, fetch /flags.json from the server. If it returns 200, load into state.flags. If it 404s, check localStorage fallback. If neither exists, start with empty flags.
Add a flags-summary display to the footer showing counts: e.g. ✓ 12  ⚑ 4  ✗ 2.
In launch_viewer.py, add a /save-flags POST handler that writes the received JSON to ./flags.json in the project root. Also serve ./flags.json as a static file (it already will be via SimpleHTTPRequestHandler).

Constraints:

Do not change PDF rendering, OCR rendering, or scroll sync
Flags must survive a browser refresh

PHASE 5 — Inline text editing

After Phase 4 is working, paste this:

Make the OCR text panel editable in p44-ocr-viewer.html so reviewers can correct OCR errors inline.

Implementation:

Add a toggle button to the right panel header labelled Edit using the existing .tb-btn class. When active, it shows Editing with gold styling.
When edit mode is active, set #text-output to contenteditable="true" and add a subtle inset border: outline: 1px solid var(--gold-dim) on the element.
When edit mode is toggled off, read the current innerHTML of #text-output, strip all HTML tags to get plain text, and save it as the corrected text for this page in state.corrections[pageNum].
Save corrections by POSTing to /save-corrections with payload { page: N, text: "..." }. If POST fails, store in localStorage under key p44-corrections.
On startup, fetch /corrections.json. If found, load into state.corrections. On page render, if state.corrections[pageNum] exists, display the corrected text instead of the raw olmOCR text.
In launch_viewer.py, add a /save-corrections POST handler that maintains a corrections.json file in the project root — a dict keyed by page number.
Add a visual indicator in the right panel header when the current page has a saved correction: a small gold dot or [edited] label next to the page number.

Constraints:

Switching pages while in edit mode should auto-save before navigating
Do not affect flags, scroll sync, zoom, or PDF rendering

PHASE 6 — Keyboard navigation

After Phase 5 is working, paste this:

Add keyboard navigation to p44-ocr-viewer.html.

Implementation:

Add a keydown event listener on document.
Map the following keys — but only when focus is NOT inside #text-output (to avoid interfering with editing) and NOT inside any input element:
    ArrowRight or l → next page (goToPage(state.currentPage + 1))
    ArrowLeft or j → previous page (goToPage(state.currentPage - 1))
    v → mark current page Verified
    r → mark current page Needs Review
    e → mark current page Error Found
    Escape → close zoom lens if open; exit edit mode if active
Add a small keyboard shortcut hint to the footer, right-aligned, in var(--text-dim) colour: ← → navigate  v/r/e flag  esc close

Constraints:

No key should fire while the user is typing in the edit panel or the page number input
Do not change any existing event listeners