misc/libfreetype/src/tools/docmaker/tohtml.py
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 #  ToHTML (c) 2002, 2003, 2005, 2006, 2007, 2008
       
     2 #    David Turner <david@freetype.org>
       
     3 
       
     4 from sources import *
       
     5 from content import *
       
     6 from formatter import *
       
     7 
       
     8 import time
       
     9 
       
    10 
       
    11 # The following defines the HTML header used by all generated pages.
       
    12 html_header_1 = """\
       
    13 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       
    14 "http://www.w3.org/TR/html4/loose.dtd">
       
    15 <html>
       
    16 <head>
       
    17 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
       
    18 <title>\
       
    19 """
       
    20 
       
    21 html_header_2 = """\
       
    22  API Reference</title>
       
    23 <style type="text/css">
       
    24   body { font-family: Verdana, Geneva, Arial, Helvetica, serif;
       
    25          color: #000000;
       
    26          background: #FFFFFF; }
       
    27 
       
    28   p { text-align: justify; }
       
    29   h1 { text-align: center; }
       
    30   li { text-align: justify; }
       
    31   td { padding: 0 0.5em 0 0.5em; }
       
    32   td.left { padding: 0 0.5em 0 0.5em;
       
    33             text-align: left; }
       
    34 
       
    35   a:link { color: #0000EF; }
       
    36   a:visited { color: #51188E; }
       
    37   a:hover { color: #FF0000; }
       
    38 
       
    39   span.keyword { font-family: monospace;
       
    40                  text-align: left;
       
    41                  white-space: pre;
       
    42                  color: darkblue; }
       
    43 
       
    44   pre.colored { color: blue; }
       
    45 
       
    46   ul.empty { list-style-type: none; }
       
    47 </style>
       
    48 </head>
       
    49 <body>
       
    50 """
       
    51 
       
    52 html_header_3 = """
       
    53 <table align=center><tr><td><font size=-1>[<a href="\
       
    54 """
       
    55 
       
    56 html_header_3i = """
       
    57 <table align=center><tr><td width="100%"></td>
       
    58 <td><font size=-1>[<a href="\
       
    59 """
       
    60 
       
    61 html_header_4 = """\
       
    62 ">Index</a>]</font></td>
       
    63 <td width="100%"></td>
       
    64 <td><font size=-1>[<a href="\
       
    65 """
       
    66 
       
    67 html_header_5 = """\
       
    68 ">TOC</a>]</font></td></tr></table>
       
    69 <center><h1>\
       
    70 """
       
    71 
       
    72 html_header_5t = """\
       
    73 ">Index</a>]</font></td>
       
    74 <td width="100%"></td></tr></table>
       
    75 <center><h1>\
       
    76 """
       
    77 
       
    78 html_header_6 = """\
       
    79  API Reference</h1></center>
       
    80 """
       
    81 
       
    82 
       
    83 # The HTML footer used by all generated pages.
       
    84 html_footer = """\
       
    85 </body>
       
    86 </html>\
       
    87 """
       
    88 
       
    89 # The header and footer used for each section.
       
    90 section_title_header = "<center><h1>"
       
    91 section_title_footer = "</h1></center>"
       
    92 
       
    93 # The header and footer used for code segments.
       
    94 code_header = '<pre class="colored">'
       
    95 code_footer = '</pre>'
       
    96 
       
    97 # Paragraph header and footer.
       
    98 para_header = "<p>"
       
    99 para_footer = "</p>"
       
   100 
       
   101 # Block header and footer.
       
   102 block_header        = '<table align=center width="75%"><tr><td>'
       
   103 block_footer_start  = """\
       
   104 </td></tr></table>
       
   105 <hr width="75%">
       
   106 <table align=center width="75%"><tr><td><font size=-2>[<a href="\
       
   107 """
       
   108 block_footer_middle = """\
       
   109 ">Index</a>]</font></td>
       
   110 <td width="100%"></td>
       
   111 <td><font size=-2>[<a href="\
       
   112 """
       
   113 block_footer_end    = """\
       
   114 ">TOC</a>]</font></td></tr></table>
       
   115 """
       
   116 
       
   117 # Description header/footer.
       
   118 description_header = '<table align=center width="87%"><tr><td>'
       
   119 description_footer = "</td></tr></table><br>"
       
   120 
       
   121 # Marker header/inter/footer combination.
       
   122 marker_header = '<table align=center width="87%" cellpadding=5><tr bgcolor="#EEEEFF"><td><em><b>'
       
   123 marker_inter  = "</b></em></td></tr><tr><td>"
       
   124 marker_footer = "</td></tr></table>"
       
   125 
       
   126 # Header location header/footer.
       
   127 header_location_header = '<table align=center width="87%"><tr><td>'
       
   128 header_location_footer = "</td></tr></table><br>"
       
   129 
       
   130 # Source code extracts header/footer.
       
   131 source_header = '<table align=center width="87%"><tr bgcolor="#D6E8FF"><td><pre>\n'
       
   132 source_footer = "\n</pre></table><br>"
       
   133 
       
   134 # Chapter header/inter/footer.
       
   135 chapter_header = '<br><table align=center width="75%"><tr><td><h2>'
       
   136 chapter_inter  = '</h2><ul class="empty"><li>'
       
   137 chapter_footer = '</li></ul></td></tr></table>'
       
   138 
       
   139 # Index footer.
       
   140 index_footer_start = """\
       
   141 <hr>
       
   142 <table><tr><td width="100%"></td>
       
   143 <td><font size=-2>[<a href="\
       
   144 """
       
   145 index_footer_end = """\
       
   146 ">TOC</a>]</font></td></tr></table>
       
   147 """
       
   148 
       
   149 # TOC footer.
       
   150 toc_footer_start = """\
       
   151 <hr>
       
   152 <table><tr><td><font size=-2>[<a href="\
       
   153 """
       
   154 toc_footer_end = """\
       
   155 ">Index</a>]</font></td>
       
   156 <td width="100%"></td>
       
   157 </tr></table>
       
   158 """
       
   159 
       
   160 
       
   161 # source language keyword coloration/styling
       
   162 keyword_prefix = '<span class="keyword">'
       
   163 keyword_suffix = '</span>'
       
   164 
       
   165 section_synopsis_header = '<h2>Synopsis</h2>'
       
   166 section_synopsis_footer = ''
       
   167 
       
   168 
       
   169 # Translate a single line of source to HTML.  This will convert
       
   170 # a "<" into "&lt.", ">" into "&gt.", etc.
       
   171 def  html_quote( line ):
       
   172     result = string.replace( line, "&", "&amp;" )
       
   173     result = string.replace( result, "<", "&lt;" )
       
   174     result = string.replace( result, ">", "&gt;" )
       
   175     return result
       
   176 
       
   177 
       
   178 # same as 'html_quote', but ignores left and right brackets
       
   179 def  html_quote0( line ):
       
   180     return string.replace( line, "&", "&amp;" )
       
   181 
       
   182 
       
   183 def  dump_html_code( lines, prefix = "" ):
       
   184     # clean the last empty lines
       
   185     l = len( self.lines )
       
   186     while l > 0 and string.strip( self.lines[l - 1] ) == "":
       
   187         l = l - 1
       
   188 
       
   189     # The code footer should be directly appended to the last code
       
   190     # line to avoid an additional blank line.
       
   191     print prefix + code_header,
       
   192     for line in self.lines[0 : l + 1]:
       
   193         print '\n' + prefix + html_quote( line ),
       
   194     print prefix + code_footer,
       
   195 
       
   196 
       
   197 
       
   198 class  HtmlFormatter( Formatter ):
       
   199 
       
   200     def  __init__( self, processor, project_title, file_prefix ):
       
   201         Formatter.__init__( self, processor )
       
   202 
       
   203         global html_header_1, html_header_2, html_header_3
       
   204         global html_header_4, html_header_5, html_footer
       
   205 
       
   206         if file_prefix:
       
   207             file_prefix = file_prefix + "-"
       
   208         else:
       
   209             file_prefix = ""
       
   210 
       
   211         self.headers           = processor.headers
       
   212         self.project_title     = project_title
       
   213         self.file_prefix       = file_prefix
       
   214         self.html_header       = html_header_1 + project_title +              \
       
   215                                  html_header_2 +                              \
       
   216                                  html_header_3 + file_prefix + "index.html" + \
       
   217                                  html_header_4 + file_prefix + "toc.html" +   \
       
   218                                  html_header_5 + project_title +              \
       
   219                                  html_header_6
       
   220 
       
   221         self.html_index_header = html_header_1 + project_title +             \
       
   222                                  html_header_2 +                             \
       
   223                                  html_header_3i + file_prefix + "toc.html" + \
       
   224                                  html_header_5 + project_title +             \
       
   225                                  html_header_6
       
   226 
       
   227         self.html_toc_header   = html_header_1 + project_title +              \
       
   228                                  html_header_2 +                              \
       
   229                                  html_header_3 + file_prefix + "index.html" + \
       
   230                                  html_header_5t + project_title +             \
       
   231                                  html_header_6
       
   232 
       
   233         self.html_footer       = "<center><font size=""-2"">generated on " +     \
       
   234                                  time.asctime( time.localtime( time.time() ) ) + \
       
   235                                  "</font></center>" + html_footer
       
   236 
       
   237         self.columns = 3
       
   238 
       
   239     def  make_section_url( self, section ):
       
   240         return self.file_prefix + section.name + ".html"
       
   241 
       
   242     def  make_block_url( self, block ):
       
   243         return self.make_section_url( block.section ) + "#" + block.name
       
   244 
       
   245     def  make_html_words( self, words ):
       
   246         """ convert a series of simple words into some HTML text """
       
   247         line = ""
       
   248         if words:
       
   249             line = html_quote( words[0] )
       
   250             for w in words[1:]:
       
   251                 line = line + " " + html_quote( w )
       
   252 
       
   253         return line
       
   254 
       
   255     def  make_html_word( self, word ):
       
   256         """analyze a simple word to detect cross-references and styling"""
       
   257         # look for cross-references
       
   258         m = re_crossref.match( word )
       
   259         if m:
       
   260             try:
       
   261                 name = m.group( 1 )
       
   262                 rest = m.group( 2 )
       
   263                 block = self.identifiers[name]
       
   264                 url   = self.make_block_url( block )
       
   265                 return '<a href="' + url + '">' + name + '</a>' + rest
       
   266             except:
       
   267                 # we detected a cross-reference to an unknown item
       
   268                 sys.stderr.write( \
       
   269                    "WARNING: undefined cross reference '" + name + "'.\n" )
       
   270                 return '?' + name + '?' + rest
       
   271 
       
   272         # look for italics and bolds
       
   273         m = re_italic.match( word )
       
   274         if m:
       
   275             name = m.group( 1 )
       
   276             rest = m.group( 3 )
       
   277             return '<i>' + name + '</i>' + rest
       
   278 
       
   279         m = re_bold.match( word )
       
   280         if m:
       
   281             name = m.group( 1 )
       
   282             rest = m.group( 3 )
       
   283             return '<b>' + name + '</b>' + rest
       
   284 
       
   285         return html_quote( word )
       
   286 
       
   287     def  make_html_para( self, words ):
       
   288         """ convert words of a paragraph into tagged HTML text, handle xrefs """
       
   289         line = ""
       
   290         if words:
       
   291             line = self.make_html_word( words[0] )
       
   292             for word in words[1:]:
       
   293                 line = line + " " + self.make_html_word( word )
       
   294             # convert `...' quotations into real left and right single quotes
       
   295             line = re.sub( r"(^|\W)`(.*?)'(\W|$)",  \
       
   296                            r'\1&lsquo;\2&rsquo;\3', \
       
   297                            line )
       
   298             # convert tilde into non-breakable space
       
   299             line = string.replace( line, "~", "&nbsp;" )
       
   300 
       
   301         return para_header + line + para_footer
       
   302 
       
   303     def  make_html_code( self, lines ):
       
   304         """ convert a code sequence to HTML """
       
   305         line = code_header + '\n'
       
   306         for l in lines:
       
   307             line = line + html_quote( l ) + '\n'
       
   308 
       
   309         return line + code_footer
       
   310 
       
   311     def  make_html_items( self, items ):
       
   312         """ convert a field's content into some valid HTML """
       
   313         lines = []
       
   314         for item in items:
       
   315             if item.lines:
       
   316                 lines.append( self.make_html_code( item.lines ) )
       
   317             else:
       
   318                 lines.append( self.make_html_para( item.words ) )
       
   319 
       
   320         return string.join( lines, '\n' )
       
   321 
       
   322     def  print_html_items( self, items ):
       
   323         print self.make_html_items( items )
       
   324 
       
   325     def  print_html_field( self, field ):
       
   326         if field.name:
       
   327             print "<table><tr valign=top><td><b>" + field.name + "</b></td><td>"
       
   328 
       
   329         print self.make_html_items( field.items )
       
   330 
       
   331         if field.name:
       
   332             print "</td></tr></table>"
       
   333 
       
   334     def  html_source_quote( self, line, block_name = None ):
       
   335         result = ""
       
   336         while line:
       
   337             m = re_source_crossref.match( line )
       
   338             if m:
       
   339                 name   = m.group( 2 )
       
   340                 prefix = html_quote( m.group( 1 ) )
       
   341                 length = len( m.group( 0 ) )
       
   342 
       
   343                 if name == block_name:
       
   344                     # this is the current block name, if any
       
   345                     result = result + prefix + '<b>' + name + '</b>'
       
   346                 elif re_source_keywords.match( name ):
       
   347                     # this is a C keyword
       
   348                     result = result + prefix + keyword_prefix + name + keyword_suffix
       
   349                 elif self.identifiers.has_key( name ):
       
   350                     # this is a known identifier
       
   351                     block = self.identifiers[name]
       
   352                     result = result + prefix + '<a href="' + \
       
   353                              self.make_block_url( block ) + '">' + name + '</a>'
       
   354                 else:
       
   355                     result = result + html_quote( line[:length] )
       
   356 
       
   357                 line = line[length:]
       
   358             else:
       
   359                 result = result + html_quote( line )
       
   360                 line   = []
       
   361 
       
   362         return result
       
   363 
       
   364     def  print_html_field_list( self, fields ):
       
   365         print "<p></p>"
       
   366         print "<table cellpadding=3 border=0>"
       
   367         for field in fields:
       
   368             if len( field.name ) > 22:
       
   369               print "<tr valign=top><td colspan=0><b>" + field.name + "</b></td></tr>"
       
   370               print "<tr valign=top><td></td><td>"
       
   371             else:
       
   372               print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
       
   373 
       
   374             self.print_html_items( field.items )
       
   375             print "</td></tr>"
       
   376         print "</table>"
       
   377 
       
   378     def  print_html_markup( self, markup ):
       
   379         table_fields = []
       
   380         for field in markup.fields:
       
   381             if field.name:
       
   382                 # we begin a new series of field or value definitions, we
       
   383                 # will record them in the 'table_fields' list before outputting
       
   384                 # all of them as a single table
       
   385                 #
       
   386                 table_fields.append( field )
       
   387             else:
       
   388                 if table_fields:
       
   389                     self.print_html_field_list( table_fields )
       
   390                     table_fields = []
       
   391 
       
   392                 self.print_html_items( field.items )
       
   393 
       
   394         if table_fields:
       
   395             self.print_html_field_list( table_fields )
       
   396 
       
   397     #
       
   398     #  Formatting the index
       
   399     #
       
   400     def  index_enter( self ):
       
   401         print self.html_index_header
       
   402         self.index_items = {}
       
   403 
       
   404     def  index_name_enter( self, name ):
       
   405         block = self.identifiers[name]
       
   406         url   = self.make_block_url( block )
       
   407         self.index_items[name] = url
       
   408 
       
   409     def  index_exit( self ):
       
   410         # block_index already contains the sorted list of index names
       
   411         count = len( self.block_index )
       
   412         rows  = ( count + self.columns - 1 ) / self.columns
       
   413 
       
   414         print "<table align=center border=0 cellpadding=0 cellspacing=0>"
       
   415         for r in range( rows ):
       
   416             line = "<tr>"
       
   417             for c in range( self.columns ):
       
   418                 i = r + c * rows
       
   419                 if i < count:
       
   420                     bname = self.block_index[r + c * rows]
       
   421                     url   = self.index_items[bname]
       
   422                     line = line + '<td><a href="' + url + '">' + bname + '</a></td>'
       
   423                 else:
       
   424                     line = line + '<td></td>'
       
   425             line = line + "</tr>"
       
   426             print line
       
   427 
       
   428         print "</table>"
       
   429 
       
   430         print index_footer_start +            \
       
   431               self.file_prefix + "toc.html" + \
       
   432               index_footer_end
       
   433 
       
   434         print self.html_footer
       
   435 
       
   436         self.index_items = {}
       
   437 
       
   438     def  index_dump( self, index_filename = None ):
       
   439         if index_filename == None:
       
   440             index_filename = self.file_prefix + "index.html"
       
   441 
       
   442         Formatter.index_dump( self, index_filename )
       
   443 
       
   444     #
       
   445     #  Formatting the table of content
       
   446     #
       
   447     def  toc_enter( self ):
       
   448         print self.html_toc_header
       
   449         print "<center><h1>Table of Contents</h1></center>"
       
   450 
       
   451     def  toc_chapter_enter( self, chapter ):
       
   452         print  chapter_header + string.join( chapter.title ) + chapter_inter
       
   453         print "<table cellpadding=5>"
       
   454 
       
   455     def  toc_section_enter( self, section ):
       
   456         print '<tr valign=top><td class="left">'
       
   457         print '<a href="' + self.make_section_url( section ) + '">' + \
       
   458                section.title + '</a></td><td>'
       
   459 
       
   460         print self.make_html_para( section.abstract )
       
   461 
       
   462     def  toc_section_exit( self, section ):
       
   463         print "</td></tr>"
       
   464 
       
   465     def  toc_chapter_exit( self, chapter ):
       
   466         print "</table>"
       
   467         print chapter_footer
       
   468 
       
   469     def  toc_index( self, index_filename ):
       
   470         print chapter_header +                                      \
       
   471               '<a href="' + index_filename + '">Global Index</a>' + \
       
   472               chapter_inter + chapter_footer
       
   473 
       
   474     def  toc_exit( self ):
       
   475         print toc_footer_start +                \
       
   476               self.file_prefix + "index.html" + \
       
   477               toc_footer_end
       
   478 
       
   479         print self.html_footer
       
   480 
       
   481     def  toc_dump( self, toc_filename = None, index_filename = None ):
       
   482         if toc_filename == None:
       
   483             toc_filename = self.file_prefix + "toc.html"
       
   484 
       
   485         if index_filename == None:
       
   486             index_filename = self.file_prefix + "index.html"
       
   487 
       
   488         Formatter.toc_dump( self, toc_filename, index_filename )
       
   489 
       
   490     #
       
   491     #  Formatting sections
       
   492     #
       
   493     def  section_enter( self, section ):
       
   494         print self.html_header
       
   495 
       
   496         print section_title_header
       
   497         print section.title
       
   498         print section_title_footer
       
   499 
       
   500         maxwidth = 0
       
   501         for b in section.blocks.values():
       
   502             if len( b.name ) > maxwidth:
       
   503                 maxwidth = len( b.name )
       
   504 
       
   505         width = 70  # XXX magic number
       
   506         if maxwidth <> 0:
       
   507             # print section synopsis
       
   508             print section_synopsis_header
       
   509             print "<table align=center cellspacing=5 cellpadding=0 border=0>"
       
   510 
       
   511             columns = width / maxwidth
       
   512             if columns < 1:
       
   513                 columns = 1
       
   514 
       
   515             count = len( section.block_names )
       
   516             rows  = ( count + columns - 1 ) / columns
       
   517 
       
   518             for r in range( rows ):
       
   519                 line = "<tr>"
       
   520                 for c in range( columns ):
       
   521                     i = r + c * rows
       
   522                     line = line + '<td></td><td>'
       
   523                     if i < count:
       
   524                         name = section.block_names[i]
       
   525                         line = line + '<a href="#' + name + '">' + name + '</a>'
       
   526 
       
   527                     line = line + '</td>'
       
   528                 line = line + "</tr>"
       
   529                 print line
       
   530 
       
   531             print "</table><br><br>"
       
   532             print section_synopsis_footer
       
   533 
       
   534         print description_header
       
   535         print self.make_html_items( section.description )
       
   536         print description_footer
       
   537 
       
   538     def  block_enter( self, block ):
       
   539         print block_header
       
   540 
       
   541         # place html anchor if needed
       
   542         if block.name:
       
   543             print '<h4><a name="' + block.name + '">' + block.name + '</a></h4>'
       
   544 
       
   545         # dump the block C source lines now
       
   546         if block.code:
       
   547             header = ''
       
   548             for f in self.headers.keys():
       
   549                 if block.source.filename.find( f ) >= 0:
       
   550                     header = self.headers[f] + ' (' + f + ')'
       
   551                     break;
       
   552                 
       
   553 #           if not header:
       
   554 #               sys.stderr.write( \
       
   555 #                 'WARNING: No header macro for ' + block.source.filename + '.\n' )
       
   556 
       
   557             if header:
       
   558                 print header_location_header
       
   559                 print 'Defined in ' + header + '.'
       
   560                 print header_location_footer
       
   561 
       
   562             print source_header
       
   563             for l in block.code:
       
   564                 print self.html_source_quote( l, block.name )
       
   565             print source_footer
       
   566 
       
   567     def  markup_enter( self, markup, block ):
       
   568         if markup.tag == "description":
       
   569             print description_header
       
   570         else:
       
   571             print marker_header + markup.tag + marker_inter
       
   572 
       
   573         self.print_html_markup( markup )
       
   574 
       
   575     def  markup_exit( self, markup, block ):
       
   576         if markup.tag == "description":
       
   577             print description_footer
       
   578         else:
       
   579             print marker_footer
       
   580 
       
   581     def  block_exit( self, block ):
       
   582         print block_footer_start + self.file_prefix + "index.html" + \
       
   583               block_footer_middle + self.file_prefix + "toc.html" +  \
       
   584               block_footer_end
       
   585 
       
   586     def  section_exit( self, section ):
       
   587         print html_footer
       
   588 
       
   589     def  section_dump_all( self ):
       
   590         for section in self.sections:
       
   591             self.section_dump( section, self.file_prefix + section.name + '.html' )
       
   592 
       
   593 # eof