<s> import re <EOL> from functools import partial <EOL> from itertools import cycle <EOL> class LinkFormatter ( object ) : <EOL> _image_exts = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> _link = re . compile ( '<STR_LIT>' ) <EOL> _url = re . compile ( '''<STR_LIT>''' , re . VERBOSE | re . MULTILINE ) <EOL> def format_url ( self , text ) : <EOL> return self . _format_url ( text , format_as_image = False ) <EOL> def _format_url ( self , text , format_as_image = True ) : <EOL> if '<STR_LIT>' not in text : <EOL> return text <EOL> return self . _url . sub ( partial ( self . _replace_url , format_as_image ) , text ) <EOL> def _replace_url ( self , format_as_image , match ) : <EOL> pre = match . group ( <NUM_LIT:1> ) <EOL> url = match . group ( <NUM_LIT:3> ) <EOL> if format_as_image and self . _is_image ( url ) : <EOL> return pre + self . _get_image ( url ) <EOL> return pre + self . _get_link ( url ) <EOL> def _get_image ( self , src , title = None ) : <EOL> return '<STR_LIT>' % ( self . _quot ( src ) , self . _quot ( title or src ) ) <EOL> def _get_link ( self , href , content = None ) : <EOL> return '<STR_LIT>' % ( self . _quot ( href ) , content or href ) <EOL> def _quot ( self , attr ) : <EOL> return attr if '<STR_LIT:">' not in attr else attr . replace ( '<STR_LIT:">' , '<STR_LIT>' ) <EOL> def format_link ( self , text ) : <EOL> tokens = self . _link . split ( text ) <EOL> formatters = cycle ( ( self . _format_url , self . _format_link ) ) <EOL> return '<STR_LIT>' . join ( f ( t ) for f , t in zip ( formatters , tokens ) ) <EOL> def _format_link ( self , text ) : <EOL> link , content = [ t . strip ( ) for t in text . split ( '<STR_LIT:|>' , <NUM_LIT:1> ) ] <EOL> if self . _is_image ( content ) : <EOL> content = self . _get_image ( content , link ) <EOL> elif self . _is_image ( link ) : <EOL> return self . _get_image ( link , content ) <EOL> return self . _get_link ( link , content ) <EOL> def _is_image ( self , text ) : <EOL> return text . lower ( ) . endswith ( self . _image_exts ) <EOL> class LineFormatter ( object ) : <EOL> handles = lambda self , line : True <EOL> newline = '<STR_LIT:\n>' <EOL> _bold = re . compile ( '''<STR_LIT>''' , re . VERBOSE ) <EOL> _italic = re . compile ( '''<STR_LIT>''' , re . VERBOSE ) <EOL> def __init__ ( self ) : <EOL> self . _format_link = LinkFormatter ( ) . format_link <EOL> def format ( self , line ) : <EOL> return self . _format_link ( self . _format_italic ( self . _format_bold ( line ) ) ) <EOL> def _format_bold ( self , line ) : <EOL> return self . _bold . sub ( '<STR_LIT>' , line ) if '<STR_LIT:*>' in line else line <EOL> def _format_italic ( self , line ) : <EOL> return self . _italic . sub ( '<STR_LIT>' , line ) if '<STR_LIT:_>' in line else line <EOL> class HtmlFormatter ( object ) : <EOL> def __init__ ( self ) : <EOL> self . _results = [ ] <EOL> self . _formatters = [ TableFormatter ( ) , <EOL> PreformattedFormatter ( ) , <EOL> ListFormatter ( ) , <EOL> HeaderFormatter ( ) , <EOL> RulerFormatter ( ) ] <EOL> self . _formatters . append ( ParagraphFormatter ( self . _formatters [ : ] ) ) <EOL> self . _current = None <EOL> def format ( self , text ) : <EOL> for line in text . splitlines ( ) : <EOL> self . _process_line ( line ) <EOL> self . _end_current ( ) <EOL> return '<STR_LIT:\n>' . join ( self . _results ) <EOL> def _process_line ( self , line ) : <EOL> if not line . strip ( ) : <EOL> self . _end_current ( ) <EOL> elif self . _current and self . _current . handles ( line ) : <EOL> self . _current . add ( line ) <EOL> else : <EOL> self . _end_current ( ) <EOL> self . _current = self . _find_formatter ( line ) <EOL> self . _current . add ( line ) <EOL> def _end_current ( self ) : <EOL> if self . _current : <EOL> self . _results . append ( self . _current . end ( ) ) <EOL> self . _current = None <EOL> def _find_formatter ( self , line ) : <EOL> for formatter in self . _formatters : <EOL> if formatter . handles ( line ) : <EOL> return formatter <EOL> class _Formatter ( object ) : <EOL> _strip_lines = True <EOL> def __init__ ( self ) : <EOL> self . _lines = [ ] <EOL> def handles ( self , line ) : <EOL> return self . _handles ( line . strip ( ) if self . _strip_lines else line ) <EOL> def _handles ( self , line ) : <EOL> raise NotImplementedError <EOL> def add ( self , line ) : <EOL> self . _lines . append ( line . strip ( ) if self . _strip_lines else line ) <EOL> def end ( self ) : <EOL> result = self . format ( self . _lines ) <EOL> self . _lines = [ ] <EOL> return result <EOL> def format ( self , lines ) : <EOL> raise NotImplementedError <EOL> class _SingleLineFormatter ( _Formatter ) : <EOL> def _handles ( self , line ) : <EOL> return not self . _lines and self . _match ( line ) <EOL> def _match ( self , line ) : <EOL> raise NotImplementedError <EOL> def format ( self , lines ) : <EOL> return self . format_line ( lines [ <NUM_LIT:0> ] ) <EOL> def format_line ( self , line ) : <EOL> raise NotImplementedError <EOL> class RulerFormatter ( _SingleLineFormatter ) : <EOL> _match = re . compile ( '<STR_LIT>' ) . match <EOL> def format_line ( self , line ) : <EOL> return '<STR_LIT>' <EOL> class HeaderFormatter ( _SingleLineFormatter ) : <EOL> _match = re . compile ( r'<STR_LIT>' ) . match <EOL> def format_line ( self , line ) : <EOL> level , text = self . _match ( line ) . groups ( ) <EOL> level = len ( level ) + <NUM_LIT:1> <EOL> return '<STR_LIT>' % ( level , text , level ) <EOL> class ParagraphFormatter ( _Formatter ) : <EOL> _format_line = LineFormatter ( ) . format <EOL> def __init__ ( self , other_formatters ) : <EOL> _Formatter . __init__ ( self ) <EOL> self . _other_formatters = other_formatters <EOL> def _handles ( self , line ) : <EOL> return not any ( other . handles ( line ) <EOL> for other in self . _other_formatters ) <EOL> def format ( self , lines ) : <EOL> return '<STR_LIT>' % self . _format_line ( '<STR_LIT:U+0020>' . join ( lines ) ) <EOL> class TableFormatter ( _Formatter ) : <EOL> _table_line = re . compile ( '<STR_LIT>' ) <EOL> _line_splitter = re . compile ( '<STR_LIT>' ) <EOL> _format_cell = LineFormatter ( ) . format <EOL> def _handles ( self , line ) : <EOL> return self . _table_line . match ( line ) is not None <EOL> def format ( self , lines ) : <EOL> return self . _format_table ( [ self . _split_to_cells ( l ) for l in lines ] ) <EOL> def _split_to_cells ( self , line ) : <EOL> return [ cell . strip ( ) for cell in self . _line_splitter . split ( line [ <NUM_LIT:1> : - <NUM_LIT:1> ] ) ] <EOL> def _format_table ( self , rows ) : <EOL> maxlen = max ( len ( row ) for row in rows ) <EOL> table = [ '<STR_LIT>' ] <EOL> for row in rows : <EOL> row += [ '<STR_LIT>' ] * ( maxlen - len ( row ) ) <EOL> table . append ( '<STR_LIT>' ) <EOL> table . extend ( '<STR_LIT>' % self . _format_cell ( c ) for c in row ) <EOL> table . append ( '<STR_LIT>' ) <EOL> table . append ( '<STR_LIT>' ) <EOL> return '<STR_LIT:\n>' . join ( table ) <EOL> class PreformattedFormatter ( _Formatter ) : <EOL> _format_line = LineFormatter ( ) . format <EOL> def _handles ( self , line ) : <EOL> return line . startswith ( '<STR_LIT>' ) or line == '<STR_LIT:|>' <EOL> def format ( self , lines ) : <EOL> lines = [ self . _format_line ( line [ <NUM_LIT:2> : ] ) for line in lines ] <EOL> return '<STR_LIT:\n>' . join ( [ '<STR_LIT>' ] + lines + [ '<STR_LIT>' ] ) <EOL> class ListFormatter ( _Formatter ) : <EOL> _strip_lines = False <EOL> _format_item = LineFormatter ( ) . format <EOL> def _handles ( self , line ) : <EOL> return line . strip ( ) . startswith ( '<STR_LIT>' ) or line . startswith ( '<STR_LIT:U+0020>' ) and self . _lines <EOL> def format ( self , lines ) : <EOL> items = [ '<STR_LIT>' % self . _format_item ( line ) <EOL> for line in self . _combine_lines ( lines ) ] <EOL> return '<STR_LIT:\n>' . join ( [ '<STR_LIT>' ] + items + [ '<STR_LIT>' ] ) <EOL> def _combine_lines ( self , lines ) : <EOL> current = [ ] <EOL> for line in lines : <EOL> line = line . strip ( ) <EOL> if not line . startswith ( '<STR_LIT>' ) : <EOL> current . append ( line ) <EOL> continue <EOL> if current : <EOL> yield '<STR_LIT:U+0020>' . join ( current ) <EOL> current = [ line [ <NUM_LIT:2> : ] . strip ( ) ] <EOL> yield '<STR_LIT:U+0020>' . join ( current ) </s>
