<s> """<STR_LIT>""" <EOL> from __future__ import absolute_import <EOL> from __future__ import unicode_literals <EOL> from . import Extension <EOL> from . . treeprocessors import Treeprocessor <EOL> from . . util import etree , parseBoolValue , AMP_SUBSTITUTE , HTML_PLACEHOLDER_RE , string_type <EOL> import re <EOL> import unicodedata <EOL> def slugify ( value , separator ) : <EOL> """<STR_LIT>""" <EOL> value = unicodedata . normalize ( '<STR_LIT>' , value ) . encode ( '<STR_LIT:ascii>' , '<STR_LIT:ignore>' ) <EOL> value = re . sub ( '<STR_LIT>' , '<STR_LIT>' , value . decode ( '<STR_LIT:ascii>' ) ) . strip ( ) . lower ( ) <EOL> return re . sub ( '<STR_LIT>' % separator , separator , value ) <EOL> IDCOUNT_RE = re . compile ( r'<STR_LIT>' ) <EOL> def unique ( id , ids ) : <EOL> """<STR_LIT>""" <EOL> while id in ids or not id : <EOL> m = IDCOUNT_RE . match ( id ) <EOL> if m : <EOL> id = '<STR_LIT>' % ( m . group ( <NUM_LIT:1> ) , int ( m . group ( <NUM_LIT:2> ) ) + <NUM_LIT:1> ) <EOL> else : <EOL> id = '<STR_LIT>' % ( id , <NUM_LIT:1> ) <EOL> ids . add ( id ) <EOL> return id <EOL> def stashedHTML2text ( text , md ) : <EOL> """<STR_LIT>""" <EOL> def _html_sub ( m ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> raw , safe = md . htmlStash . rawHtmlBlocks [ int ( m . group ( <NUM_LIT:1> ) ) ] <EOL> except ( IndexError , TypeError ) : <EOL> return m . group ( <NUM_LIT:0> ) <EOL> if md . safeMode and not safe : <EOL> return '<STR_LIT>' <EOL> return re . sub ( r'<STR_LIT>' , '<STR_LIT>' , raw ) <EOL> return HTML_PLACEHOLDER_RE . sub ( _html_sub , text ) <EOL> def nest_toc_tokens ( toc_list ) : <EOL> """<STR_LIT>""" <EOL> ordered_list = [ ] <EOL> if len ( toc_list ) : <EOL> last = toc_list . pop ( <NUM_LIT:0> ) <EOL> last [ '<STR_LIT>' ] = [ ] <EOL> levels = [ last [ '<STR_LIT>' ] ] <EOL> ordered_list . append ( last ) <EOL> parents = [ ] <EOL> while toc_list : <EOL> t = toc_list . pop ( <NUM_LIT:0> ) <EOL> current_level = t [ '<STR_LIT>' ] <EOL> t [ '<STR_LIT>' ] = [ ] <EOL> if current_level < levels [ - <NUM_LIT:1> ] : <EOL> levels . pop ( ) <EOL> to_pop = <NUM_LIT:0> <EOL> for p in reversed ( parents ) : <EOL> if current_level <= p [ '<STR_LIT>' ] : <EOL> to_pop += <NUM_LIT:1> <EOL> else : <EOL> break <EOL> if to_pop : <EOL> levels = levels [ : - to_pop ] <EOL> parents = parents [ : - to_pop ] <EOL> levels . append ( current_level ) <EOL> if current_level == levels [ - <NUM_LIT:1> ] : <EOL> ( parents [ - <NUM_LIT:1> ] [ '<STR_LIT>' ] if parents <EOL> else ordered_list ) . append ( t ) <EOL> else : <EOL> last [ '<STR_LIT>' ] . append ( t ) <EOL> parents . append ( last ) <EOL> levels . append ( current_level ) <EOL> last = t <EOL> return ordered_list <EOL> class TocTreeprocessor ( Treeprocessor ) : <EOL> def __init__ ( self , md , config ) : <EOL> super ( TocTreeprocessor , self ) . __init__ ( md ) <EOL> self . marker = config [ "<STR_LIT>" ] <EOL> self . title = config [ "<STR_LIT:title>" ] <EOL> self . base_level = int ( config [ "<STR_LIT>" ] ) - <NUM_LIT:1> <EOL> self . slugify = config [ "<STR_LIT>" ] <EOL> self . sep = config [ "<STR_LIT>" ] <EOL> self . use_anchors = parseBoolValue ( config [ "<STR_LIT>" ] ) <EOL> self . use_permalinks = parseBoolValue ( config [ "<STR_LIT>" ] , False ) <EOL> if self . use_permalinks is None : <EOL> self . use_permalinks = config [ "<STR_LIT>" ] <EOL> self . header_rgx = re . compile ( "<STR_LIT>" ) <EOL> def iterparent ( self , root ) : <EOL> '''<STR_LIT>''' <EOL> for parent in root . iter ( ) : <EOL> for child in parent : <EOL> yield parent , child <EOL> def replace_marker ( self , root , elem ) : <EOL> '''<STR_LIT>''' <EOL> for ( p , c ) in self . iterparent ( root ) : <EOL> text = '<STR_LIT>' . join ( c . itertext ( ) ) . strip ( ) <EOL> if not text : <EOL> continue <EOL> if c . text and c . text . strip ( ) == self . marker and not self . header_rgx . match ( c . tag ) and c . tag not in [ '<STR_LIT>' , '<STR_LIT:code>' ] : <EOL> for i in range ( len ( p ) ) : <EOL> if p [ i ] == c : <EOL> p [ i ] = elem <EOL> break <EOL> def set_level ( self , elem ) : <EOL> '''<STR_LIT>''' <EOL> level = int ( elem . tag [ - <NUM_LIT:1> ] ) + self . base_level <EOL> if level > <NUM_LIT:6> : <EOL> level = <NUM_LIT:6> <EOL> elem . tag = '<STR_LIT>' % level <EOL> def add_anchor ( self , c , elem_id ) : <EOL> anchor = etree . Element ( "<STR_LIT:a>" ) <EOL> anchor . text = c . text <EOL> anchor . attrib [ "<STR_LIT>" ] = "<STR_LIT:#>" + elem_id <EOL> anchor . attrib [ "<STR_LIT:class>" ] = "<STR_LIT>" <EOL> c . text = "<STR_LIT>" <EOL> for elem in c : <EOL> anchor . append ( elem ) <EOL> c . remove ( elem ) <EOL> c . append ( anchor ) <EOL> def add_permalink ( self , c , elem_id ) : <EOL> permalink = etree . Element ( "<STR_LIT:a>" ) <EOL> permalink . text = ( "<STR_LIT>" % AMP_SUBSTITUTE <EOL> if self . use_permalinks is True <EOL> else self . use_permalinks ) <EOL> permalink . attrib [ "<STR_LIT>" ] = "<STR_LIT:#>" + elem_id <EOL> permalink . attrib [ "<STR_LIT:class>" ] = "<STR_LIT>" <EOL> permalink . attrib [ "<STR_LIT:title>" ] = "<STR_LIT>" <EOL> c . append ( permalink ) <EOL> def build_toc_div ( self , toc_list ) : <EOL> """<STR_LIT>""" <EOL> div = etree . Element ( "<STR_LIT>" ) <EOL> div . attrib [ "<STR_LIT:class>" ] = "<STR_LIT>" <EOL> if self . title : <EOL> header = etree . SubElement ( div , "<STR_LIT>" ) <EOL> header . attrib [ "<STR_LIT:class>" ] = "<STR_LIT>" <EOL> header . text = self . title <EOL> def build_etree_ul ( toc_list , parent ) : <EOL> ul = etree . SubElement ( parent , "<STR_LIT>" ) <EOL> for item in toc_list : <EOL> li = etree . SubElement ( ul , "<STR_LIT>" ) <EOL> link = etree . SubElement ( li , "<STR_LIT:a>" ) <EOL> link . text = item . get ( '<STR_LIT:name>' , '<STR_LIT>' ) <EOL> link . attrib [ "<STR_LIT>" ] = '<STR_LIT:#>' + item . get ( '<STR_LIT:id>' , '<STR_LIT>' ) <EOL> if item [ '<STR_LIT>' ] : <EOL> build_etree_ul ( item [ '<STR_LIT>' ] , li ) <EOL> return ul <EOL> build_etree_ul ( toc_list , div ) <EOL> prettify = self . markdown . treeprocessors . get ( '<STR_LIT>' ) <EOL> if prettify : <EOL> prettify . run ( div ) <EOL> return div <EOL> def run ( self , doc ) : <EOL> used_ids = set ( ) <EOL> for el in doc . iter ( ) : <EOL> if "<STR_LIT:id>" in el . attrib : <EOL> used_ids . add ( el . attrib [ "<STR_LIT:id>" ] ) <EOL> toc_tokens = [ ] <EOL> for el in doc . iter ( ) : <EOL> if isinstance ( el . tag , string_type ) and self . header_rgx . match ( el . tag ) : <EOL> self . set_level ( el ) <EOL> text = '<STR_LIT>' . join ( el . itertext ( ) ) . strip ( ) <EOL> if "<STR_LIT:id>" not in el . attrib : <EOL> innertext = stashedHTML2text ( text , self . markdown ) <EOL> el . attrib [ "<STR_LIT:id>" ] = unique ( self . slugify ( innertext , self . sep ) , used_ids ) <EOL> toc_tokens . append ( { <EOL> '<STR_LIT>' : int ( el . tag [ - <NUM_LIT:1> ] ) , <EOL> '<STR_LIT:id>' : el . attrib [ "<STR_LIT:id>" ] , <EOL> '<STR_LIT:name>' : text <EOL> } ) <EOL> if self . use_anchors : <EOL> self . add_anchor ( el , el . attrib [ "<STR_LIT:id>" ] ) <EOL> if self . use_permalinks : <EOL> self . add_permalink ( el , el . attrib [ "<STR_LIT:id>" ] ) <EOL> div = self . build_toc_div ( nest_toc_tokens ( toc_tokens ) ) <EOL> if self . marker : <EOL> self . replace_marker ( doc , div ) <EOL> toc = self . markdown . serializer ( div ) <EOL> for pp in self . markdown . postprocessors . values ( ) : <EOL> toc = pp . run ( toc ) <EOL> self . markdown . toc = toc <EOL> class TocExtension ( Extension ) : <EOL> TreeProcessorClass = TocTreeprocessor <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> self . config = { <EOL> "<STR_LIT>" : [ '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ] , <EOL> "<STR_LIT:title>" : [ "<STR_LIT>" , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] , <EOL> "<STR_LIT>" : [ False , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] , <EOL> "<STR_LIT>" : [ <NUM_LIT:0> , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] , <EOL> "<STR_LIT>" : [ '<STR_LIT:1>' , '<STR_LIT>' ] , <EOL> "<STR_LIT>" : [ slugify , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] , <EOL> '<STR_LIT>' : [ '<STR_LIT:->' , '<STR_LIT>' ] <EOL> } <EOL> super ( TocExtension , self ) . __init__ ( * args , ** kwargs ) <EOL> def extendMarkdown ( self , md , md_globals ) : <EOL> md . registerExtension ( self ) <EOL> self . md = md <EOL> self . reset ( ) <EOL> tocext = self . TreeProcessorClass ( md , self . getConfigs ( ) ) <EOL> md . treeprocessors . add ( "<STR_LIT>" , tocext , "<STR_LIT>" ) <EOL> def reset ( self ) : <EOL> self . md . toc = '<STR_LIT>' <EOL> def makeExtension ( * args , ** kwargs ) : <EOL> return TocExtension ( * args , ** kwargs ) </s>
