EANCH-WP-0004: HtmlViewer scroll parity and viewer-shell workplan
Export HtmlViewerAdapter from package root, add scrollRequestKey parity, register finished workplan, update SCOPE.
This commit is contained in:
parent
49d9810c93
commit
bbeba96173
4 changed files with 119 additions and 5 deletions
5
SCOPE.md
5
SCOPE.md
|
|
@ -51,10 +51,9 @@ Selector *behavior* lives here; selector *type interfaces* live in
|
||||||
During the umbrella-first MVP these belong to the appropriate citation-evidence
|
During the umbrella-first MVP these belong to the appropriate citation-evidence
|
||||||
subsystem. This repo may depend on **`citation-engine` only** (DependencyMap §4).
|
subsystem. This repo may depend on **`citation-engine` only** (DependencyMap §4).
|
||||||
|
|
||||||
### Still deferred (beyond EANCH-WP-0002 / EANCH-WP-0003)
|
### Still deferred (beyond EANCH-WP-0004)
|
||||||
|
|
||||||
- `FragmentSelector` (export-only deep links)
|
- `FragmentSelector` (export-only deep links)
|
||||||
- wiring `HtmlViewerAdapter` into `citation-work` / the umbrella review shell
|
|
||||||
- human-confirmation UI for ambiguous/fuzzy matches
|
- human-confirmation UI for ambiguous/fuzzy matches
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -81,7 +80,7 @@ subsystem. This repo may depend on **`citation-engine` only** (DependencyMap §4
|
||||||
- Status: active — standalone package consumed by `citation-evidence`
|
- Status: active — standalone package consumed by `citation-evidence`
|
||||||
- Implementation: PDF + HTML/Markdown selector paths, stale/orphan/fuzzy resolution,
|
- Implementation: PDF + HTML/Markdown selector paths, stale/orphan/fuzzy resolution,
|
||||||
`PdfViewerAdapter`, and `HtmlViewerAdapter` (`evidence-anchor/dom`)
|
`PdfViewerAdapter`, and `HtmlViewerAdapter` (`evidence-anchor/dom`)
|
||||||
- Stability: evolving — shared contracts stable; viewer wiring in the umbrella is next
|
- Stability: evolving — shared contracts stable; HTML/MD wired in `citation-work` ViewerShell
|
||||||
- Usage: internal (consumed by `citation-evidence` during MVP)
|
- Usage: internal (consumed by `citation-evidence` during MVP)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ export interface HtmlViewerAdapterProps {
|
||||||
readonly representation: DocumentRepresentation;
|
readonly representation: DocumentRepresentation;
|
||||||
readonly storedAnnotations?: readonly StoredHtmlAnnotation[];
|
readonly storedAnnotations?: readonly StoredHtmlAnnotation[];
|
||||||
readonly scrollToAnnotationId?: string;
|
readonly scrollToAnnotationId?: string;
|
||||||
|
/**
|
||||||
|
* Bumps when the same annotation should be re-scrolled (e.g. repeat click).
|
||||||
|
* Format is opaque — typically `${annotationId}:${version}`.
|
||||||
|
*/
|
||||||
|
readonly scrollRequestKey?: string;
|
||||||
readonly activeAnnotationId?: string | null;
|
readonly activeAnnotationId?: string | null;
|
||||||
readonly debug?: HtmlViewerDebugOptions;
|
readonly debug?: HtmlViewerDebugOptions;
|
||||||
onSelectionCaptured?(capture: DomSelectionCapture, selectors: Selector[]): void;
|
onSelectionCaptured?(capture: DomSelectionCapture, selectors: Selector[]): void;
|
||||||
|
|
@ -50,6 +55,7 @@ export function HtmlViewerAdapter(props: HtmlViewerAdapterProps): ReactNode {
|
||||||
representation,
|
representation,
|
||||||
storedAnnotations = [],
|
storedAnnotations = [],
|
||||||
scrollToAnnotationId,
|
scrollToAnnotationId,
|
||||||
|
scrollRequestKey,
|
||||||
activeAnnotationId,
|
activeAnnotationId,
|
||||||
debug,
|
debug,
|
||||||
onSelectionCaptured,
|
onSelectionCaptured,
|
||||||
|
|
@ -91,12 +97,13 @@ export function HtmlViewerAdapter(props: HtmlViewerAdapterProps): ReactNode {
|
||||||
}, [html, storedAnnotations, representation, activeAnnotationId]);
|
}, [html, storedAnnotations, representation, activeAnnotationId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scrollToAnnotationId || !rootRef.current) return;
|
const requestKey = scrollRequestKey ?? scrollToAnnotationId ?? null;
|
||||||
|
if (!requestKey || !scrollToAnnotationId || !rootRef.current) return;
|
||||||
const mark = rootRef.current.querySelector(
|
const mark = rootRef.current.querySelector(
|
||||||
`[data-highlight-id="${CSS.escape(scrollToAnnotationId)}"]`,
|
`[data-highlight-id="${CSS.escape(scrollToAnnotationId)}"]`,
|
||||||
);
|
);
|
||||||
mark?.scrollIntoView({ block: "center", behavior: "smooth" });
|
mark?.scrollIntoView({ block: "center", behavior: "smooth" });
|
||||||
}, [scrollToAnnotationId, renderedHtml]);
|
}, [scrollToAnnotationId, scrollRequestKey, renderedHtml]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
14
src/index.ts
14
src/index.ts
|
|
@ -20,6 +20,20 @@ export {
|
||||||
type CreateSelectorsOptions,
|
type CreateSelectorsOptions,
|
||||||
} from "./selectors";
|
} from "./selectors";
|
||||||
|
|
||||||
|
// DOM adapter (re-exported from the src/dom/ boundary).
|
||||||
|
export {
|
||||||
|
HtmlViewerAdapter,
|
||||||
|
resolveHtmlSelectors,
|
||||||
|
scrollToHtmlTarget,
|
||||||
|
renderHtmlHighlight,
|
||||||
|
captureFromRange,
|
||||||
|
domPathToNode,
|
||||||
|
nodeAtPath,
|
||||||
|
type HtmlViewerAdapterProps,
|
||||||
|
type HtmlViewerDebugOptions,
|
||||||
|
type StoredHtmlAnnotation,
|
||||||
|
} from "./dom";
|
||||||
|
|
||||||
// PDF adapter + helpers (re-exported from the src/pdf/ boundary).
|
// PDF adapter + helpers (re-exported from the src/pdf/ boundary).
|
||||||
export {
|
export {
|
||||||
PdfViewerAdapter,
|
PdfViewerAdapter,
|
||||||
|
|
|
||||||
94
workplans/EANCH-WP-0004-viewer-shell-dom-wiring.md
Normal file
94
workplans/EANCH-WP-0004-viewer-shell-dom-wiring.md
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
---
|
||||||
|
id: EANCH-WP-0004
|
||||||
|
type: workplan
|
||||||
|
title: "Wire HtmlViewerAdapter into the review workspace viewer shell"
|
||||||
|
domain: infotech
|
||||||
|
repo: evidence-anchor
|
||||||
|
status: finished
|
||||||
|
owner: codex
|
||||||
|
topic_slug: citation_evidence_mvp
|
||||||
|
created: "2026-07-09"
|
||||||
|
updated: "2026-07-09"
|
||||||
|
spec_refs:
|
||||||
|
- INTENT.md
|
||||||
|
- SCOPE.md
|
||||||
|
- ../citation-evidence/wiki/SharedContracts.md
|
||||||
|
- src/dom/html-viewer-adapter.tsx
|
||||||
|
---
|
||||||
|
|
||||||
|
# EANCH-WP-0004 — Viewer Shell DOM Wiring
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Connect `HtmlViewerAdapter` (`evidence-anchor/dom`) to the citation-evidence
|
||||||
|
review workspace so users can upload, view, select, annotate, and reopen
|
||||||
|
HTML/Markdown documents — not only PDFs.
|
||||||
|
|
||||||
|
## Task Breakdown
|
||||||
|
|
||||||
|
## T01 — Browser upload path for HTML/Markdown
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: EANCH-WP-0004-T01
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `ingestHtmlFromFile` / `ingestMarkdownFromFile` and `resolveDomViewerHtml`
|
||||||
|
to `evidence-source/browser`, extending the byte store to hold non-PDF bytes.
|
||||||
|
|
||||||
|
## T02 — Upload dropzone accepts HTML/Markdown
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: EANCH-WP-0004-T02
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
depends_on: [T01]
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend `citation-work` `UploadDropzone` to ingest `.html` / `.md` files via
|
||||||
|
the new browser helpers.
|
||||||
|
|
||||||
|
## T03 — ViewerShell routes by representation type
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: EANCH-WP-0004-T03
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
depends_on: [T02]
|
||||||
|
```
|
||||||
|
|
||||||
|
Branch `ViewerShell` on `representationType`: PDF → `PdfViewerAdapter`,
|
||||||
|
`html-dom` / `markdown-rendered` → `HtmlViewerAdapter`. Widen
|
||||||
|
`PendingSelection` to `SelectionCapture`.
|
||||||
|
|
||||||
|
## T04 — HtmlViewerAdapter scroll parity
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: EANCH-WP-0004-T04
|
||||||
|
status: done
|
||||||
|
priority: medium
|
||||||
|
depends_on: [T03]
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `scrollRequestKey` to `HtmlViewerAdapter` so repeat-click re-scroll works
|
||||||
|
like the PDF adapter.
|
||||||
|
|
||||||
|
## T05 — Verification + close-out
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: EANCH-WP-0004-T05
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
depends_on: [T04]
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests green in `evidence-source`, `evidence-anchor`, `citation-work`, and
|
||||||
|
`citation-evidence`; `fix-consistency` clean; progress note.
|
||||||
|
|
||||||
|
**Verification (2026-07-09):**
|
||||||
|
|
||||||
|
- `evidence-source`: 82 tests (browser view-html + upload).
|
||||||
|
- `evidence-anchor`: 42 tests; `HtmlViewerAdapter` scroll parity.
|
||||||
|
- `citation-work`: 12 tests including `ViewerShell.dom.test.tsx`.
|
||||||
|
- `citation-evidence`: typecheck clean.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue