From 9ec64961fcbdd7d65529a10daa600fc541b94151 Mon Sep 17 00:00:00 2001 From: Pier-Jean Malandrino Date: Thu, 23 Apr 2026 22:07:58 +0200 Subject: [PATCH] =?UTF-8?q?feat(reasoning):=20bidirectional=20PDF=20?= =?UTF-8?q?=E2=86=94=20graph=20focus=20+=20DocumentView=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Propagate Docling `self_ref` through PageElement so bboxes and graph nodes share a stable identity. Add a Document/Graph mode switch to the reasoning workspace; selecting a node highlights its bbox (numbered badge, focus ring, optional dim of non-visited) and clicking a bbox re-centers the graph. --- document-parser/domain/value_objects.py | 5 + document-parser/infra/local_converter.py | 8 +- .../src/features/analysis/ui/GraphView.vue | 40 +++- .../features/analysis/ui/StructureViewer.vue | 172 +++++++++++++++--- frontend/src/features/reasoning/store.ts | 5 + .../features/reasoning/ui/DocumentView.vue | 95 ++++++++++ .../reasoning/ui/ReasoningWorkspace.vue | 138 +++++++++++++- frontend/src/shared/i18n.ts | 8 + frontend/src/shared/types.ts | 4 + 9 files changed, 446 insertions(+), 29 deletions(-) create mode 100644 frontend/src/features/reasoning/ui/DocumentView.vue diff --git a/document-parser/domain/value_objects.py b/document-parser/domain/value_objects.py index 0885852..e36b91e 100644 --- a/document-parser/domain/value_objects.py +++ b/document-parser/domain/value_objects.py @@ -19,6 +19,11 @@ class PageElement: bbox: list[float] content: str level: int = 0 + # Docling `self_ref` ("#/texts/12", "#/tables/3", …). Empty for items + # that don't have one (rare — defensive default). Lets callers correlate + # a rendered bbox with the corresponding node in the graph without + # resorting to fuzzy bbox matching. + self_ref: str = "" @dataclass(frozen=True) diff --git a/document-parser/infra/local_converter.py b/document-parser/infra/local_converter.py index 6be939e..af39ffa 100644 --- a/document-parser/infra/local_converter.py +++ b/document-parser/infra/local_converter.py @@ -194,7 +194,13 @@ def _process_content_item( content = item.export_to_markdown() pages[page_no].elements.append( - PageElement(type=element_type, bbox=bbox, content=content, level=level) + PageElement( + type=element_type, + bbox=bbox, + content=content, + level=level, + self_ref=getattr(item, "self_ref", "") or "", + ) ) except (AttributeError, KeyError, TypeError, ValueError): logger.warning( diff --git a/frontend/src/features/analysis/ui/GraphView.vue b/frontend/src/features/analysis/ui/GraphView.vue index 4552170..331b32c 100644 --- a/frontend/src/features/analysis/ui/GraphView.vue +++ b/frontend/src/features/analysis/ui/GraphView.vue @@ -19,7 +19,7 @@ + + +