Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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
  594.