1 # ToHTML (c) 2002, 2003, 2005, 2006, 2007, 2008
2 # David Turner <david@freetype.org>
6 from formatter import *
11 # The following defines the HTML header used by all generated pages.
13 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
14 "http://www.w3.org/TR/html4/loose.dtd">
17 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
23 <style type="text/css">
24 body { font-family: Verdana, Geneva, Arial, Helvetica, serif;
26 background: #FFFFFF; }
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;
35 a:link { color: #0000EF; }
36 a:visited { color: #51188E; }
37 a:hover { color: #FF0000; }
39 span.keyword { font-family: monospace;
44 pre.colored { color: blue; }
46 ul.empty { list-style-type: none; }
53 <table align=center><tr><td><font size=-1>[<a href="\
57 <table align=center><tr><td width="100%"></td>
58 <td><font size=-1>[<a href="\
62 ">Index</a>]</font></td>
63 <td width="100%"></td>
64 <td><font size=-1>[<a href="\
68 ">TOC</a>]</font></td></tr></table>
73 ">Index</a>]</font></td>
74 <td width="100%"></td></tr></table>
79 API Reference</h1></center>
83 # The HTML footer used by all generated pages.
89 # The header and footer used for each section.
90 section_title_header = "<center><h1>"
91 section_title_footer = "</h1></center>"
93 # The header and footer used for code segments.
94 code_header = '<pre class="colored">'
95 code_footer = '</pre>'
97 # Paragraph header and footer.
101 # Block header and footer.
102 block_header = '<table align=center width="75%"><tr><td>'
103 block_footer_start = """\
106 <table align=center width="75%"><tr><td><font size=-2>[<a href="\
108 block_footer_middle = """\
109 ">Index</a>]</font></td>
110 <td width="100%"></td>
111 <td><font size=-2>[<a href="\
113 block_footer_end = """\
114 ">TOC</a>]</font></td></tr></table>
117 # Description header/footer.
118 description_header = '<table align=center width="87%"><tr><td>'
119 description_footer = "</td></tr></table><br>"
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>"
126 # Header location header/footer.
127 header_location_header = '<table align=center width="87%"><tr><td>'
128 header_location_footer = "</td></tr></table><br>"
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>"
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>'
140 index_footer_start = """\
142 <table><tr><td width="100%"></td>
143 <td><font size=-2>[<a href="\
145 index_footer_end = """\
146 ">TOC</a>]</font></td></tr></table>
150 toc_footer_start = """\
152 <table><tr><td><font size=-2>[<a href="\
154 toc_footer_end = """\
155 ">Index</a>]</font></td>
156 <td width="100%"></td>
161 # source language keyword coloration/styling
162 keyword_prefix = '<span class="keyword">'
163 keyword_suffix = '</span>'
165 section_synopsis_header = '<h2>Synopsis</h2>'
166 section_synopsis_footer = ''
169 # Translate a single line of source to HTML. This will convert
170 # a "<" into "<.", ">" into ">.", etc.
171 def html_quote( line ):
172 result = string.replace( line, "&", "&" )
173 result = string.replace( result, "<", "<" )
174 result = string.replace( result, ">", ">" )
178 # same as 'html_quote', but ignores left and right brackets
179 def html_quote0( line ):
180 return string.replace( line, "&", "&" )
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] ) == "":
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,
198 class HtmlFormatter( Formatter ):
200 def __init__( self, processor, project_title, file_prefix ):
201 Formatter.__init__( self, processor )
203 global html_header_1, html_header_2, html_header_3
204 global html_header_4, html_header_5, html_footer
207 file_prefix = file_prefix + "-"
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 + \
216 html_header_3 + file_prefix + "index.html" + \
217 html_header_4 + file_prefix + "toc.html" + \
218 html_header_5 + project_title + \
221 self.html_index_header = html_header_1 + project_title + \
223 html_header_3i + file_prefix + "toc.html" + \
224 html_header_5 + project_title + \
227 self.html_toc_header = html_header_1 + project_title + \
229 html_header_3 + file_prefix + "index.html" + \
230 html_header_5t + project_title + \
233 self.html_footer = "<center><font size=""-2"">generated on " + \
234 time.asctime( time.localtime( time.time() ) ) + \
235 "</font></center>" + html_footer
239 def make_section_url( self, section ):
240 return self.file_prefix + section.name + ".html"
242 def make_block_url( self, block ):
243 return self.make_section_url( block.section ) + "#" + block.name
245 def make_html_words( self, words ):
246 """ convert a series of simple words into some HTML text """
249 line = html_quote( words[0] )
251 line = line + " " + html_quote( w )
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 )
263 block = self.identifiers[name]
264 url = self.make_block_url( block )
265 return '<a href="' + url + '">' + name + '</a>' + rest
267 # we detected a cross-reference to an unknown item
269 "WARNING: undefined cross reference '" + name + "'.\n" )
270 return '?' + name + '?' + rest
272 # look for italics and bolds
273 m = re_italic.match( word )
277 return '<i>' + name + '</i>' + rest
279 m = re_bold.match( word )
283 return '<b>' + name + '</b>' + rest
285 return html_quote( word )
287 def make_html_para( self, words ):
288 """ convert words of a paragraph into tagged HTML text, handle xrefs """
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‘\2’\3', \
298 # convert tilde into non-breakable space
299 line = string.replace( line, "~", " " )
301 return para_header + line + para_footer
303 def make_html_code( self, lines ):
304 """ convert a code sequence to HTML """
305 line = code_header + '\n'
307 line = line + html_quote( l ) + '\n'
309 return line + code_footer
311 def make_html_items( self, items ):
312 """ convert a field's content into some valid HTML """
316 lines.append( self.make_html_code( item.lines ) )
318 lines.append( self.make_html_para( item.words ) )
320 return string.join( lines, '\n' )
322 def print_html_items( self, items ):
323 print self.make_html_items( items )
325 def print_html_field( self, field ):
327 print "<table><tr valign=top><td><b>" + field.name + "</b></td><td>"
329 print self.make_html_items( field.items )
332 print "</td></tr></table>"
334 def html_source_quote( self, line, block_name = None ):
337 m = re_source_crossref.match( line )
340 prefix = html_quote( m.group( 1 ) )
341 length = len( m.group( 0 ) )
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>'
355 result = result + html_quote( line[:length] )
359 result = result + html_quote( line )
364 def print_html_field_list( self, fields ):
366 print "<table cellpadding=3 border=0>"
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>"
372 print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
374 self.print_html_items( field.items )
378 def print_html_markup( self, markup ):
380 for field in markup.fields:
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
386 table_fields.append( field )
389 self.print_html_field_list( table_fields )
392 self.print_html_items( field.items )
395 self.print_html_field_list( table_fields )
398 # Formatting the index
400 def index_enter( self ):
401 print self.html_index_header
402 self.index_items = {}
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
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
414 print "<table align=center border=0 cellpadding=0 cellspacing=0>"
415 for r in range( rows ):
417 for c in range( self.columns ):
420 bname = self.block_index[r + c * rows]
421 url = self.index_items[bname]
422 line = line + '<td><a href="' + url + '">' + bname + '</a></td>'
424 line = line + '<td></td>'
425 line = line + "</tr>"
430 print index_footer_start + \
431 self.file_prefix + "toc.html" + \
434 print self.html_footer
436 self.index_items = {}
438 def index_dump( self, index_filename = None ):
439 if index_filename == None:
440 index_filename = self.file_prefix + "index.html"
442 Formatter.index_dump( self, index_filename )
445 # Formatting the table of content
447 def toc_enter( self ):
448 print self.html_toc_header
449 print "<center><h1>Table of Contents</h1></center>"
451 def toc_chapter_enter( self, chapter ):
452 print chapter_header + string.join( chapter.title ) + chapter_inter
453 print "<table cellpadding=5>"
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>'
460 print self.make_html_para( section.abstract )
462 def toc_section_exit( self, section ):
465 def toc_chapter_exit( self, chapter ):
469 def toc_index( self, index_filename ):
470 print chapter_header + \
471 '<a href="' + index_filename + '">Global Index</a>' + \
472 chapter_inter + chapter_footer
474 def toc_exit( self ):
475 print toc_footer_start + \
476 self.file_prefix + "index.html" + \
479 print self.html_footer
481 def toc_dump( self, toc_filename = None, index_filename = None ):
482 if toc_filename == None:
483 toc_filename = self.file_prefix + "toc.html"
485 if index_filename == None:
486 index_filename = self.file_prefix + "index.html"
488 Formatter.toc_dump( self, toc_filename, index_filename )
491 # Formatting sections
493 def section_enter( self, section ):
494 print self.html_header
496 print section_title_header
498 print section_title_footer
501 for b in section.blocks.values():
502 if len( b.name ) > maxwidth:
503 maxwidth = len( b.name )
505 width = 70 # XXX magic number
507 # print section synopsis
508 print section_synopsis_header
509 print "<table align=center cellspacing=5 cellpadding=0 border=0>"
511 columns = width / maxwidth
515 count = len( section.block_names )
516 rows = ( count + columns - 1 ) / columns
518 for r in range( rows ):
520 for c in range( columns ):
522 line = line + '<td></td><td>'
524 name = section.block_names[i]
525 line = line + '<a href="#' + name + '">' + name + '</a>'
527 line = line + '</td>'
528 line = line + "</tr>"
531 print "</table><br><br>"
532 print section_synopsis_footer
534 print description_header
535 print self.make_html_items( section.description )
536 print description_footer
538 def block_enter( self, block ):
541 # place html anchor if needed
543 print '<h4><a name="' + block.name + '">' + block.name + '</a></h4>'
545 # dump the block C source lines now
548 for f in self.headers.keys():
549 if block.source.filename.find( f ) >= 0:
550 header = self.headers[f] + ' (' + f + ')'
554 # sys.stderr.write( \
555 # 'WARNING: No header macro for ' + block.source.filename + '.\n' )
558 print header_location_header
559 print 'Defined in ' + header + '.'
560 print header_location_footer
564 print self.html_source_quote( l, block.name )
567 def markup_enter( self, markup, block ):
568 if markup.tag == "description":
569 print description_header
571 print marker_header + markup.tag + marker_inter
573 self.print_html_markup( markup )
575 def markup_exit( self, markup, block ):
576 if markup.tag == "description":
577 print description_footer
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" + \
586 def section_exit( self, section ):
589 def section_dump_all( self ):
590 for section in self.sections:
591 self.section_dump( section, self.file_prefix + section.name + '.html' )