1+ from __future__ import annotations
2+
13from pathlib import Path
24
35from docutils import nodes
@@ -14,21 +16,20 @@ class PEPContents(transforms.Transform):
1416 def apply (self ) -> None :
1517 if not Path (self .document ["source" ]).match ("pep-*" ):
1618 return # not a PEP file, exit early
17-
1819 # Create the contents placeholder section
19- title = nodes .title ("" , "Contents" )
20- contents_topic = nodes .topic ("" , title , classes = [ "contents" ] )
20+ title = nodes .title ("" , "" , nodes . Text ( " Contents") )
21+ contents_section = nodes .section ("" , title )
2122 if not self .document .has_name ("contents" ):
22- contents_topic ["names" ].append ("contents" )
23- self .document .note_implicit_target (contents_topic )
23+ contents_section ["names" ].append ("contents" )
24+ self .document .note_implicit_target (contents_section )
2425
2526 # Add a table of contents builder
2627 pending = nodes .pending (Contents )
27- contents_topic += pending
28+ contents_section += pending
2829 self .document .note_pending (pending )
2930
3031 # Insert the toc after title and PEP headers
31- self .document .children [0 ].insert (2 , contents_topic )
32+ self .document .children [0 ].insert (2 , contents_section )
3233
3334 # Add a horizontal rule before contents
3435 transition = nodes .transition ()
@@ -37,27 +38,42 @@ def apply(self) -> None:
3738
3839class Contents (parts .Contents ):
3940 """Build Table of Contents from document."""
40- def __init__ (self , document , startnode = None ):
41+ def __init__ (self , document : nodes . document , startnode : nodes . Node | None = None ):
4142 super ().__init__ (document , startnode )
4243
4344 # used in parts.Contents.build_contents
4445 self .toc_id = None
4546 self .backlinks = None
4647
4748 def apply (self ) -> None :
48- # used in parts.Contents.build_contents
49- self .toc_id = self .startnode .parent ["ids" ][0 ]
50- self .backlinks = self .document .settings .toc_backlinks
51-
52- # let the writer (or output software) build the contents list?
53- if getattr (self .document .settings , "use_latex_toc" , False ):
54- # move customisation settings to the parent node
55- self .startnode .parent .attributes .update (self .startnode .details )
56- self .startnode .parent .remove (self .startnode )
49+ contents = self .build_contents (self .document [0 ][4 :]) # skip PEP title, headers, <hr/>, and contents
50+ if contents :
51+ self .startnode .replace_self (contents )
5752 else :
58- contents = self .build_contents (self .document [0 ])
59- if contents :
60- self .startnode .replace_self (contents )
61- else :
62- # if no contents, remove the empty placeholder
63- self .startnode .parent .parent .remove (self .startnode .parent )
53+ # if no contents, remove the empty placeholder
54+ self .startnode .parent .parent .remove (self .startnode .parent )
55+
56+ def build_contents (self , node : nodes .Node | list [nodes .Node ], _level : None = None ):
57+ entries = []
58+ children = getattr (node , "children" , node )
59+
60+ for section in children :
61+ if not isinstance (section , nodes .section ):
62+ continue
63+
64+ title = section [0 ]
65+
66+ # remove all pre-existing hyperlinks in the title (e.g. PEP references)
67+ while (link_node := title .next_node (nodes .reference )) is not None :
68+ link_node .replace_self (link_node [0 ])
69+ ref_id = section ['ids' ][0 ]
70+ title ["refid" ] = ref_id # Add a link to self
71+ entry_text = self .copy_and_filter (title )
72+ reference = nodes .reference ("" , "" , refid = ref_id , * entry_text )
73+ item = nodes .list_item ("" , nodes .paragraph ("" , "" , reference ))
74+
75+ item += self .build_contents (section ) # recurse to add sub-sections
76+ entries .append (item )
77+ if entries :
78+ return nodes .bullet_list ('' , * entries )
79+ return []
0 commit comments