@@ -86,12 +86,44 @@ def order_toc_list(toc_list):
8686
8787
8888class TocTreeprocessor (Treeprocessor ):
89+ def __init__ (self , md , config ):
90+ super (TocTreeprocessor , self ).__init__ (md )
91+
92+ self .marker = config ["marker" ]
93+ self .title = config ["title" ]
94+ self .slugify = config ["slugify" ]
95+ self .use_anchors = parseBoolValue (config ["anchorlink" ])
96+ self .use_permalinks = parseBoolValue (config ["permalink" ], False )
97+ if self .use_permalinks is None :
98+ self .use_permalinks = config ["permalink" ]
99+
100+ self .header_rgx = re .compile ("[Hh][123456]" )
89101
90- # Iterator wrapper to get parent and child all at once
91102 def iterparent (self , root ):
92- for parent in root .getiterator ():
103+ ''' Iterator wrapper to get parent and child all at once. '''
104+ for parent in root .iter ():
93105 for child in parent :
94106 yield parent , child
107+
108+ def replace_marker (self , root , elem ):
109+ ''' Replace marker with elem. '''
110+ for (p , c ) in self .iterparent (root ):
111+ text = '' .join (itertext (c )).strip ()
112+ if not text :
113+ continue
114+
115+ # To keep the output from screwing up the
116+ # validation by putting a <div> inside of a <p>
117+ # we actually replace the <p> in its entirety.
118+ # We do not allow the marker inside a header as that
119+ # would causes an enless loop of placing a new TOC
120+ # inside previously generated TOC.
121+ if c .text and c .text .strip () == self .marker and \
122+ not self .header_rgx .match (c .tag ) and c .tag not in ['pre' , 'code' ]:
123+ for i in range (len (p )):
124+ if p [i ] == c :
125+ p [i ] = elem
126+ break
95127
96128 def add_anchor (self , c , elem_id ): # @ReservedAssignment
97129 anchor = etree .Element ("a" )
@@ -116,10 +148,10 @@ def add_permalink(self, c, elem_id):
116148
117149 def build_toc_etree (self , div , toc_list ):
118150 # Add title to the div
119- if self .config [ " title" ] :
151+ if self .title :
120152 header = etree .SubElement (div , "span" )
121153 header .attrib ["class" ] = "toctitle"
122- header .text = self .config [ " title" ]
154+ header .text = self .title
123155
124156 def build_etree_ul (toc_list , parent ):
125157 ul = etree .SubElement (parent , "ul" )
@@ -136,62 +168,37 @@ def build_etree_ul(toc_list, parent):
136168 return build_etree_ul (toc_list , div )
137169
138170 def run (self , doc ):
139-
140- div = etree .Element ("div" )
141- div .attrib ["class" ] = "toc"
142- header_rgx = re .compile ("[Hh][123456]" )
143-
144- self .use_anchors = parseBoolValue (self .config ["anchorlink" ])
145- self .use_permalinks = parseBoolValue (self .config ["permalink" ], False )
146- if self .use_permalinks is None :
147- self .use_permalinks = self .config ["permalink" ]
148-
149171 # Get a list of id attributes
150172 used_ids = set ()
151- for c in doc .getiterator ():
152- if "id" in c .attrib :
153- used_ids .add (c .attrib ["id" ])
173+ for el in doc .iter ():
174+ if "id" in el .attrib :
175+ used_ids .add (el .attrib ["id" ])
154176
177+ div = etree .Element ("div" )
178+ div .attrib ["class" ] = "toc"
179+ self .replace_marker (doc , div )
180+
155181 toc_list = []
156- for (p , c ) in self .iterparent (doc ):
157- text = '' .join (itertext (c )).strip ()
158- if not text :
159- continue
160-
161- # To keep the output from screwing up the
162- # validation by putting a <div> inside of a <p>
163- # we actually replace the <p> in its entirety.
164- # We do not allow the marker inside a header as that
165- # would causes an enless loop of placing a new TOC
166- # inside previously generated TOC.
167- if c .text and c .text .strip () == self .config ["marker" ] and \
168- not header_rgx .match (c .tag ) and c .tag not in ['pre' , 'code' ]:
169- for i in range (len (p )):
170- if p [i ] == c :
171- p [i ] = div
172- break
173-
174- if header_rgx .match (c .tag ):
175-
182+ for el in doc .iter ():
183+ if self .header_rgx .match (el .tag ):
184+ text = '' .join (itertext (el )).strip ()
185+
176186 # Do not override pre-existing ids
177- if "id" not in c .attrib :
187+ if "id" not in el .attrib :
178188 elem_id = stashedHTML2text (text , self .markdown )
179- elem_id = unique (self .config ["slugify" ](elem_id , '-' ),
180- used_ids )
181- c .attrib ["id" ] = elem_id
189+ elem_id = unique (self .slugify (elem_id , '-' ), used_ids )
190+ el .attrib ["id" ] = elem_id
182191 else :
183- elem_id = c .attrib ["id" ]
184-
185- tag_level = int (c .tag [- 1 ])
192+ elem_id = el .attrib ["id" ]
186193
187- toc_list .append ({'level' : tag_level ,
194+ toc_list .append ({'level' : int ( el . tag [ - 1 ]) ,
188195 'id' : elem_id ,
189196 'name' : text })
190197
191198 if self .use_anchors :
192- self .add_anchor (c , elem_id )
199+ self .add_anchor (el , elem_id )
193200 if self .use_permalinks :
194- self .add_permalink (c , elem_id )
201+ self .add_permalink (el , elem_id )
195202
196203 toc_list_nested = order_toc_list (toc_list )
197204 self .build_toc_etree (div , toc_list_nested )
@@ -235,8 +242,7 @@ def extendMarkdown(self, md, md_globals):
235242 md .registerExtension (self )
236243 self .md = md
237244 self .reset ()
238- tocext = self .TreeProcessorClass (md )
239- tocext .config = self .getConfigs ()
245+ tocext = self .TreeProcessorClass (md , self .getConfigs ())
240246 # Headerid ext is set to '>prettify'. With this set to '_end',
241247 # it should always come after headerid ext (and honor ids assinged
242248 # by the header id extension) if both are used. Same goes for
0 commit comments