@@ -179,9 +179,8 @@ def render_package(self, item: ItemData) -> t.Iterable[str]:
179179 for child in children_by_type ["class" ]:
180180 full_name = child ["full_name" ]
181181 short_name = full_name .split ('.' )[- 1 ]
182- # Create anchor that matches auto-generated markdown anchors from headers
183- anchor = self ._create_anchor (full_name )
184- name_link = f"[`{ short_name } `](#{ anchor } )"
182+ # Use context-aware linking (same-page anchor vs cross-page)
183+ name_link = self ._get_cross_reference_link (full_name , short_name , item ["full_name" ])
185184 # Get full description (first paragraph, not truncated)
186185 doc_lines = child .get ('doc' , '' ).strip ().split ('\n ' )
187186 if doc_lines and doc_lines [0 ]:
@@ -208,9 +207,8 @@ def render_package(self, item: ItemData) -> t.Iterable[str]:
208207 for child in children_by_type ["function" ]:
209208 full_name = child ["full_name" ]
210209 short_name = full_name .split ('.' )[- 1 ]
211- # Create proper anchor that matches the header (use full name for anchor)
212- anchor = self ._create_anchor (full_name )
213- name_link = f"[`{ short_name } `](#{ anchor } )"
210+ # Use context-aware linking (same-page anchor vs cross-page)
211+ name_link = self ._get_cross_reference_link (full_name , short_name , item ["full_name" ])
214212 # Get full description (first paragraph, not truncated)
215213 doc_lines = child .get ('doc' , '' ).strip ().split ('\n ' )
216214 if doc_lines and doc_lines [0 ]:
@@ -627,32 +625,70 @@ def _generate_slug(self, full_name: str) -> str:
627625 def _generate_anchor_id (self , full_name : str ) -> str :
628626 """Generate anchor ID from full_name for use in <Anchor> components."""
629627 return full_name .replace ('.' , '' ).replace ('_' , '' ).lower ()
628+
629+ def _are_on_same_page (self , item1_name : str , item2_name : str ) -> bool :
630+ """Determine if two items are rendered on the same page."""
631+ item1 = self .get_item (item1_name )
632+ item2 = self .get_item (item2_name )
633+
634+ if not item1 or not item2 :
635+ return False
636+
637+ # Each item type gets its own page, except for direct children
638+ item1_page = self ._get_page_for_item (item1_name )
639+ item2_page = self ._get_page_for_item (item2_name )
640+
641+ return item1_page == item2_page
642+
643+ def _get_page_for_item (self , full_name : str ) -> str :
644+ """Get the page where this item is rendered."""
645+ item = self .get_item (full_name )
646+ if not item :
647+ return full_name
648+
649+ item_type = item ['type' ]
650+ parts = full_name .split ('.' )
651+
652+ # Only packages, modules, and classes get their own dedicated pages
653+ if item_type in ('package' , 'module' , 'class' ):
654+ return full_name
655+
656+ # Functions, methods, properties, attributes, data are rendered on their parent's page
657+ elif item_type in ('function' , 'method' , 'property' , 'attribute' , 'data' ):
658+ # Find the parent (class, module, or package)
659+ for i in range (len (parts ) - 1 , 0 , - 1 ):
660+ parent_name = '.' .join (parts [:i ])
661+ parent_item = self .get_item (parent_name )
662+ if parent_item and parent_item ['type' ] in ('package' , 'module' , 'class' ):
663+ return parent_name
664+
665+ # Fallback - shouldn't happen
666+ return full_name
667+
668+ else :
669+ # Unknown type, assume it gets its own page
670+ return full_name
630671
631- def _get_cross_reference_link (self , target_name : str , display_name : str = None ) -> str :
672+ def _get_cross_reference_link (self , target_name : str , display_name : str = None , current_page : str = None ) -> str :
632673 """Generate cross-reference link to another documented object."""
633674 # Check if target exists in our database
634675 target_item = self .get_item (target_name )
635676 if target_item is None :
636677 # Return plain text if target not found
637678 return f"`{ display_name or target_name } `"
638679
639- # Determine the correct page to link to
640- target_parts = target_name . split ( '.' )
680+ link_text = display_name or target_name . split ( '.' )[ - 1 ]
681+ anchor_id = self . _generate_anchor_id ( target_name )
641682
642- # For items that get their own pages (packages, modules, classes, functions)
643- if target_item ['type' ] in ('package' , 'module' , 'class' , 'function' ):
644- # Link directly to their own page
645- page_slug = self ._generate_slug (target_name )
646- anchor_id = self ._generate_anchor_id (target_name )
647- link_text = display_name or target_parts [- 1 ]
648- return f"[`{ link_text } `]({ page_slug } #{ anchor_id } )"
683+ # Determine if target is on same page as current page
684+ if current_page and self ._are_on_same_page (target_name , current_page ):
685+ # Same page - use anchor link only
686+ return f"[`{ link_text } `](#{ anchor_id } )"
649687 else :
650- # For class members (methods, attributes), link to the class page
651- parent_name = '.' .join (target_parts [:- 1 ]) # Remove method/attribute name
652- parent_slug = self ._generate_slug (parent_name )
653- anchor_id = self ._generate_anchor_id (target_name )
654- link_text = display_name or target_parts [- 1 ]
655- return f"[`{ link_text } `]({ parent_slug } #{ anchor_id } )"
688+ # Different page - use cross-page link
689+ target_page = self ._get_page_for_item (target_name )
690+ target_page_slug = self ._generate_slug (target_page )
691+ return f"[`{ link_text } `]({ target_page_slug } #{ anchor_id } )"
656692
657693 def _format_code_block_with_links (self , code : str , language : str = "python" ) -> str :
658694 """Format code block with deep linking using CodeBlock component."""
0 commit comments