<s> """<STR_LIT>""" <EOL> from __future__ import absolute_import <EOL> from __future__ import unicode_literals <EOL> from . import Extension <EOL> from . . preprocessors import Preprocessor <EOL> from . . inlinepatterns import Pattern <EOL> from . . treeprocessors import Treeprocessor <EOL> from . . postprocessors import Postprocessor <EOL> from . . util import etree , text_type <EOL> from . . odict import OrderedDict <EOL> import re <EOL> FN_BACKLINK_TEXT = "<STR_LIT>" <EOL> NBSP_PLACEHOLDER = "<STR_LIT>" <EOL> DEF_RE = re . compile ( r'<STR_LIT>' ) <EOL> TABBED_RE = re . compile ( r'<STR_LIT>' ) <EOL> class FootnoteExtension ( Extension ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . config = { <EOL> '<STR_LIT>' : <EOL> [ "<STR_LIT>" , <EOL> "<STR_LIT>" ] , <EOL> '<STR_LIT>' : <EOL> [ False , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] , <EOL> "<STR_LIT>" : <EOL> [ "<STR_LIT>" , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ] <EOL> } <EOL> super ( FootnoteExtension , self ) . __init__ ( * args , ** kwargs ) <EOL> self . unique_prefix = <NUM_LIT:0> <EOL> self . reset ( ) <EOL> def extendMarkdown ( self , md , md_globals ) : <EOL> """<STR_LIT>""" <EOL> md . registerExtension ( self ) <EOL> self . parser = md . parser <EOL> self . md = md <EOL> md . preprocessors . add ( <EOL> "<STR_LIT>" , FootnotePreprocessor ( self ) , "<STR_LIT>" <EOL> ) <EOL> FOOTNOTE_RE = r'<STR_LIT>' <EOL> md . inlinePatterns . add ( <EOL> "<STR_LIT>" , FootnotePattern ( FOOTNOTE_RE , self ) , "<STR_LIT>" <EOL> ) <EOL> md . treeprocessors . add ( <EOL> "<STR_LIT>" , FootnoteTreeprocessor ( self ) , "<STR_LIT>" <EOL> ) <EOL> md . postprocessors . add ( <EOL> "<STR_LIT>" , FootnotePostprocessor ( self ) , "<STR_LIT>" <EOL> ) <EOL> def reset ( self ) : <EOL> """<STR_LIT>""" <EOL> self . footnotes = OrderedDict ( ) <EOL> self . unique_prefix += <NUM_LIT:1> <EOL> def findFootnotesPlaceholder ( self , root ) : <EOL> """<STR_LIT>""" <EOL> def finder ( element ) : <EOL> for child in element : <EOL> if child . text : <EOL> if child . text . find ( self . getConfig ( "<STR_LIT>" ) ) > - <NUM_LIT:1> : <EOL> return child , element , True <EOL> if child . tail : <EOL> if child . tail . find ( self . getConfig ( "<STR_LIT>" ) ) > - <NUM_LIT:1> : <EOL> return child , element , False <EOL> child_res = finder ( child ) <EOL> if child_res is not None : <EOL> return child_res <EOL> return None <EOL> res = finder ( root ) <EOL> return res <EOL> def setFootnote ( self , id , text ) : <EOL> """<STR_LIT>""" <EOL> self . footnotes [ id ] = text <EOL> def get_separator ( self ) : <EOL> if self . md . output_format in [ '<STR_LIT>' , '<STR_LIT>' ] : <EOL> return '<STR_LIT:->' <EOL> return '<STR_LIT::>' <EOL> def makeFootnoteId ( self , id ) : <EOL> """<STR_LIT>""" <EOL> if self . getConfig ( "<STR_LIT>" ) : <EOL> return '<STR_LIT>' % ( self . get_separator ( ) , self . unique_prefix , id ) <EOL> else : <EOL> return '<STR_LIT>' % ( self . get_separator ( ) , id ) <EOL> def makeFootnoteRefId ( self , id ) : <EOL> """<STR_LIT>""" <EOL> if self . getConfig ( "<STR_LIT>" ) : <EOL> return '<STR_LIT>' % ( self . get_separator ( ) , <EOL> self . unique_prefix , id ) <EOL> else : <EOL> return '<STR_LIT>' % ( self . get_separator ( ) , id ) <EOL> def makeFootnotesDiv ( self , root ) : <EOL> """<STR_LIT>""" <EOL> if not list ( self . footnotes . keys ( ) ) : <EOL> return None <EOL> div = etree . Element ( "<STR_LIT>" ) <EOL> div . set ( '<STR_LIT:class>' , '<STR_LIT>' ) <EOL> etree . SubElement ( div , "<STR_LIT>" ) <EOL> ol = etree . SubElement ( div , "<STR_LIT>" ) <EOL> for id in self . footnotes . keys ( ) : <EOL> li = etree . SubElement ( ol , "<STR_LIT>" ) <EOL> li . set ( "<STR_LIT:id>" , self . makeFootnoteId ( id ) ) <EOL> self . parser . parseChunk ( li , self . footnotes [ id ] ) <EOL> backlink = etree . Element ( "<STR_LIT:a>" ) <EOL> backlink . set ( "<STR_LIT>" , "<STR_LIT:#>" + self . makeFootnoteRefId ( id ) ) <EOL> if self . md . output_format not in [ '<STR_LIT>' , '<STR_LIT>' ] : <EOL> backlink . set ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> backlink . set ( "<STR_LIT:class>" , "<STR_LIT>" ) <EOL> backlink . set ( <EOL> "<STR_LIT:title>" , <EOL> "<STR_LIT>" % <EOL> ( self . footnotes . index ( id ) + <NUM_LIT:1> ) <EOL> ) <EOL> backlink . text = FN_BACKLINK_TEXT <EOL> if li . getchildren ( ) : <EOL> node = li [ - <NUM_LIT:1> ] <EOL> if node . tag == "<STR_LIT:p>" : <EOL> node . text = node . text + NBSP_PLACEHOLDER <EOL> node . append ( backlink ) <EOL> else : <EOL> p = etree . SubElement ( li , "<STR_LIT:p>" ) <EOL> p . append ( backlink ) <EOL> return div <EOL> class FootnotePreprocessor ( Preprocessor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , footnotes ) : <EOL> self . footnotes = footnotes <EOL> def run ( self , lines ) : <EOL> """<STR_LIT>""" <EOL> newlines = [ ] <EOL> i = <NUM_LIT:0> <EOL> while True : <EOL> m = DEF_RE . match ( lines [ i ] ) <EOL> if m : <EOL> fn , _i = self . detectTabbed ( lines [ i + <NUM_LIT:1> : ] ) <EOL> fn . insert ( <NUM_LIT:0> , m . group ( <NUM_LIT:2> ) ) <EOL> i += _i - <NUM_LIT:1> <EOL> self . footnotes . setFootnote ( m . group ( <NUM_LIT:1> ) , "<STR_LIT:\n>" . join ( fn ) ) <EOL> else : <EOL> newlines . append ( lines [ i ] ) <EOL> if len ( lines ) > i + <NUM_LIT:1> : <EOL> i += <NUM_LIT:1> <EOL> else : <EOL> break <EOL> return newlines <EOL> def detectTabbed ( self , lines ) : <EOL> """<STR_LIT>""" <EOL> items = [ ] <EOL> blank_line = False <EOL> i = <NUM_LIT:0> <EOL> def detab ( line ) : <EOL> match = TABBED_RE . match ( line ) <EOL> if match : <EOL> return match . group ( <NUM_LIT:4> ) <EOL> for line in lines : <EOL> if line . strip ( ) : <EOL> detabbed_line = detab ( line ) <EOL> if detabbed_line : <EOL> items . append ( detabbed_line ) <EOL> i += <NUM_LIT:1> <EOL> continue <EOL> elif not blank_line and not DEF_RE . match ( line ) : <EOL> items . append ( line ) <EOL> i += <NUM_LIT:1> <EOL> continue <EOL> else : <EOL> return items , i + <NUM_LIT:1> <EOL> else : <EOL> blank_line = True <EOL> i += <NUM_LIT:1> <EOL> for j in range ( i , len ( lines ) ) : <EOL> if lines [ j ] . strip ( ) : <EOL> next_line = lines [ j ] <EOL> break <EOL> else : <EOL> break <EOL> if detab ( next_line ) : <EOL> items . append ( "<STR_LIT>" ) <EOL> continue <EOL> else : <EOL> break <EOL> else : <EOL> i += <NUM_LIT:1> <EOL> return items , i <EOL> class FootnotePattern ( Pattern ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , pattern , footnotes ) : <EOL> super ( FootnotePattern , self ) . __init__ ( pattern ) <EOL> self . footnotes = footnotes <EOL> def handleMatch ( self , m ) : <EOL> id = m . group ( <NUM_LIT:2> ) <EOL> if id in self . footnotes . footnotes . keys ( ) : <EOL> sup = etree . Element ( "<STR_LIT>" ) <EOL> a = etree . SubElement ( sup , "<STR_LIT:a>" ) <EOL> sup . set ( '<STR_LIT:id>' , self . footnotes . makeFootnoteRefId ( id ) ) <EOL> a . set ( '<STR_LIT>' , '<STR_LIT:#>' + self . footnotes . makeFootnoteId ( id ) ) <EOL> if self . footnotes . md . output_format not in [ '<STR_LIT>' , '<STR_LIT>' ] : <EOL> a . set ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> a . set ( '<STR_LIT:class>' , '<STR_LIT>' ) <EOL> a . text = text_type ( self . footnotes . footnotes . index ( id ) + <NUM_LIT:1> ) <EOL> return sup <EOL> else : <EOL> return None <EOL> class FootnoteTreeprocessor ( Treeprocessor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , footnotes ) : <EOL> self . footnotes = footnotes <EOL> def run ( self , root ) : <EOL> footnotesDiv = self . footnotes . makeFootnotesDiv ( root ) <EOL> if footnotesDiv is not None : <EOL> result = self . footnotes . findFootnotesPlaceholder ( root ) <EOL> if result : <EOL> child , parent , isText = result <EOL> ind = parent . getchildren ( ) . index ( child ) <EOL> if isText : <EOL> parent . remove ( child ) <EOL> parent . insert ( ind , footnotesDiv ) <EOL> else : <EOL> parent . insert ( ind + <NUM_LIT:1> , footnotesDiv ) <EOL> child . tail = None <EOL> else : <EOL> root . append ( footnotesDiv ) <EOL> class FootnotePostprocessor ( Postprocessor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , footnotes ) : <EOL> self . footnotes = footnotes <EOL> def run ( self , text ) : <EOL> text = text . replace ( <EOL> FN_BACKLINK_TEXT , self . footnotes . getConfig ( "<STR_LIT>" ) <EOL> ) <EOL> return text . replace ( NBSP_PLACEHOLDER , "<STR_LIT>" ) <EOL> def makeExtension ( * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> return FootnoteExtension ( * args , ** kwargs ) </s>
