@@ -15,8 +15,62 @@ def _yaml_frontmatter(source_name: str, doc_id: str, description: str = "") -> s
1515 return "---\n " + "\n " .join (lines ) + "\n ---\n "
1616
1717
18- def _render_nodes_summary (nodes : list [dict ], depth : int ) -> str :
19- """Recursively render nodes for the *summary* view (summaries only)."""
18+ def _image_per_page (pages : list [dict ] | None ) -> dict [int , list [str ]]:
19+ """Map 1-based page number -> list of wiki-root-relative image paths.
20+
21+ ``pages`` is the per-page list written to ``wiki/sources/<doc>.json`` (each
22+ item has a 1-based ``page`` and an ``images`` list of ``{"path": ...}``
23+ dicts whose paths are wiki-root-relative like
24+ ``sources/images/<doc>/p1_img1.png``). Returns a dict keyed by page number
25+ for O(1) lookup while rendering nodes.
26+ """
27+ if not pages :
28+ return {}
29+ per_page : dict [int , list [str ]] = {}
30+ for item in pages :
31+ page = item .get ("page" )
32+ if not isinstance (page , int ) or page < 1 :
33+ continue
34+ paths = [
35+ img ["path" ]
36+ for img in item .get ("images" , [])
37+ if isinstance (img , dict ) and isinstance (img .get ("path" ), str )
38+ ]
39+ if paths :
40+ per_page .setdefault (page , []).extend (paths )
41+ return per_page
42+
43+
44+ def _summary_relative_path (wiki_root_path : str ) -> str :
45+ """Rewrite a wiki-root-relative image path for a page under ``wiki/summaries/``.
46+
47+ Image paths in the per-page JSON are wiki-root-relative
48+ (``sources/images/<doc>/file.png``). The summary lives one directory deeper
49+ (``wiki/summaries/<doc>.md``), so the path that resolves for Obsidian /
50+ GitHub is ``../`` + the wiki-root-relative path.
51+ """
52+ return f"../{ wiki_root_path } " if wiki_root_path else ""
53+
54+
55+ def _render_nodes_summary (
56+ nodes : list [dict ],
57+ depth : int ,
58+ per_page_images : dict [int , list [str ]] | None = None ,
59+ emitted : set [str ] | None = None ,
60+ ) -> str :
61+ """Recursively render nodes for the *summary* view (summaries only).
62+
63+ When ``per_page_images`` is provided, each node's page range embeds the
64+ images extracted from those pages (as ````
65+ links), skirting the PageIndex private-cache refs that are stripped from
66+ node text. ``emitted`` tracks already-rendered paths so a figure spanning
67+ pages covered by several sibling nodes is only shown once.
68+ """
69+ if per_page_images is None :
70+ per_page_images = {}
71+ if emitted is None :
72+ emitted = set ()
73+
2074 lines : list [str ] = []
2175 heading_prefix = "#" * min (depth , 6 )
2276 for node in nodes :
@@ -27,22 +81,43 @@ def _render_nodes_summary(nodes: list[dict], depth: int) -> str:
2781 children = node .get ("nodes" , [])
2882
2983 lines .append (f"{ heading_prefix } { title } (pages { start } –{ end } )\n " )
84+
85+ # Embed figures for the node's page range. Node indices are 0-based
86+ # page indices; the per-page image map is keyed by 1-based page number.
87+ node_images : list [str ] = []
88+ if isinstance (start , int ) and isinstance (end , int ):
89+ lo , hi = start + 1 , end + 1
90+ for page_num in range (lo , hi + 1 ):
91+ for path in per_page_images .get (page_num , []):
92+ if path not in emitted :
93+ emitted .add (path )
94+ node_images .append (_summary_relative_path (path ))
95+ for img_path in node_images :
96+ lines .append (f"\n " )
97+
3098 if summary :
3199 lines .append (f"Summary: { summary } \n " )
32100 if children :
33- lines .append (_render_nodes_summary (children , depth + 1 ))
101+ lines .append (_render_nodes_summary (children , depth + 1 , per_page_images , emitted ))
34102
35103 return "\n " .join (lines )
36104
37105
38- def render_summary_md (tree : dict , source_name : str , doc_id : str , description : str = "" ) -> str :
106+ def render_summary_md (
107+ tree : dict ,
108+ source_name : str ,
109+ doc_id : str ,
110+ description : str = "" ,
111+ pages : list [dict ] | None = None ,
112+ ) -> str :
39113 """Render the summary Markdown page for a PageIndex tree.
40114
41- Renders each node as a heading with page range and its summary text.
42- Includes a YAML frontmatter block with ``type: "Summary"`` and an
43- optional ``description`` field.
115+ Renders each node as a heading with page range and its summary text, and
116+ embeds the page images (when ``pages`` is supplied). Includes a YAML
117+ frontmatter block with ``type: "Summary"`` and an optional ``description``
118+ field.
44119 """
45- frontmatter = _yaml_frontmatter (source_name , doc_id , description )
120+ frontmatter_block = _yaml_frontmatter (source_name , doc_id , description )
46121 structure = tree .get ("structure" , [])
47- body = _render_nodes_summary (structure , depth = 1 )
48- return frontmatter + "\n " + body
122+ body = _render_nodes_summary (structure , depth = 1 , per_page_images = _image_per_page ( pages ) )
123+ return frontmatter_block + "\n " + body
0 commit comments