Skip to content

Commit 4a408e1

Browse files
committed
Fix parsing of mathblocks
1 parent 1106f14 commit 4a408e1

File tree

3 files changed

+39
-41
lines changed

3 files changed

+39
-41
lines changed

mathnotes/block_index.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,34 @@ def _render_all_blocks(self):
145145
# Initialize rendered blocks storage for this file
146146
self.rendered_blocks[file_path] = {}
147147

148-
# Render all blocks in this file
149-
for marker_id, block in block_markers.items():
150-
# Ensure trailing slash before fragment
148+
# Process blocks in dependency order: children before parents
149+
# First, identify root blocks (blocks without parents) and process recursively
150+
processed_blocks = set()
151+
152+
def process_block_tree(block, marker_id):
153+
"""Recursively process a block and its children."""
154+
if marker_id in processed_blocks:
155+
return
156+
157+
# First process all child blocks
158+
for child_marker_id, child_block in block_markers.items():
159+
if child_block.parent == block:
160+
process_block_tree(child_block, child_marker_id)
161+
162+
# Now process this block
151163
base_url = f"/mathnotes/{canonical_url}"
152164
if not base_url.endswith('/'):
153165
base_url += '/'
154166
full_url = f"{base_url}#{block.label}" if block.label else base_url
155167
self._process_block_content(block, block_markers, parser, full_url)
156168
# Store the rendered HTML by marker ID
157169
self.rendered_blocks[file_path][marker_id] = block.rendered_html
170+
processed_blocks.add(marker_id)
171+
172+
# Process all root blocks (blocks without parents)
173+
for marker_id, block in block_markers.items():
174+
if block.parent is None:
175+
process_block_tree(block, marker_id)
158176

159177
# Clean up temporary storage
160178
del self._pending_files
@@ -191,7 +209,20 @@ def _process_block_content(self, block: MathBlock, block_markers: Dict[str, Math
191209
html_content = html_content.replace(r"\*", "*")
192210
html_content = html_content.replace(r"\~", "~")
193211

212+
# Remove child block markers for tooltip use
213+
# Tooltips should only show the block's own content, not nested blocks
214+
clean_html = html_content
215+
for marker_id, child_block in block_markers.items():
216+
if child_block.parent == block and marker_id in clean_html:
217+
# Remove the marker entirely - don't include child content in tooltips
218+
clean_html = clean_html.replace(f"<p>{marker_id}</p>", "")
219+
clean_html = clean_html.replace(marker_id, "")
220+
221+
# Store the clean inner HTML content (for tooltips and other uses)
222+
block.content_html = clean_html
223+
194224
# Render the complete block HTML using the same method as page view
225+
# This will wrap the content and replace child markers with full child HTML
195226
block.rendered_html = parser.render_block_html(block, html_content, block_markers, self.md, full_url)
196227

197228

mathnotes/sitegenerator/builder.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ def setup_global_context(self):
8383
if self.block_index and hasattr(self.block_index, 'index'):
8484
tooltip_data = {}
8585
for label, ref in self.block_index.index.items():
86+
# Use the processed HTML content (with references converted to links)
8687
tooltip_data[label] = {
8788
'type': ref.block.block_type.value,
8889
'title': ref.block.title or '',
89-
'content': ref.block.content,
90+
'content': ref.block.content_html,
9091
'url': ref.full_url
9192
}
9293

mathnotes/structured_math.py

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MathBlock:
4141
metadata: Dict[str, Any] = field(default_factory=dict)
4242
children: List["MathBlock"] = field(default_factory=list)
4343
parent: Optional["MathBlock"] = None
44+
content_html: Optional[str] = None # Stores the inner HTML content (without wrapper)
4445

4546
@property
4647
def css_class(self) -> str:
@@ -422,8 +423,8 @@ def render_block_html(
422423
# Render child blocks that are referenced in the content
423424
for marker_id, child_block in block_markers.items():
424425
if child_block.parent == block and marker_id in processed_content:
425-
# Render the child block
426-
child_html = self._render_child_block(child_block, block_markers, md_processor)
426+
# Child blocks are always processed first, so rendered_html is available
427+
child_html = child_block.rendered_html
427428
# Replace marker with rendered child
428429
processed_content = processed_content.replace(f"<p>{marker_id}</p>", child_html)
429430
processed_content = processed_content.replace(marker_id, child_html)
@@ -441,41 +442,6 @@ def render_block_html(
441442

442443
return "\n".join(html_parts)
443444

444-
def _render_child_block(
445-
self, block: MathBlock, block_markers: Dict[str, MathBlock], md_processor
446-
) -> str:
447-
"""Render a child block with its content."""
448-
# Process the block's content through markdown
449-
block_content = block.content
450-
451-
# Process cross-references using the unified processor (first pass)
452-
block_ref_processor = BlockReferenceProcessor(
453-
block_markers=block_markers,
454-
current_file=self.current_file,
455-
block_index=self.block_index,
456-
)
457-
block_content = block_ref_processor.process_references(block_content)
458-
459-
# Protect math before markdown processing
460-
child_math_protector = MathProtector(prefix="CHILDMATH")
461-
block_content = child_math_protector.protect_math(block_content)
462-
463-
# Process through markdown
464-
block_html = md_processor.convert(block_content)
465-
md_processor.reset()
466-
467-
# Restore math
468-
block_html = child_math_protector.restore_math(block_html)
469-
470-
# Process embedded blocks after markdown conversion (second pass)
471-
if block_ref_processor.embedded_blocks:
472-
block_html = block_ref_processor.process_embedded_blocks(block_html, md_processor)
473-
474-
# Render the block with nested support
475-
# For child blocks on the same page, use #label as URL
476-
url = f"#{block.label}" if block.label else None
477-
return self.render_block_html(block, block_html, block_markers, md_processor, url)
478-
479445
def get_blocks_by_type(self, block_type: MathBlockType) -> List[MathBlock]:
480446
"""Get all blocks of a specific type."""
481447
return [block for block in self.blocks if block.block_type == block_type]

0 commit comments

Comments
 (0)