/src/freetype/src/tools/docmaker/tohtml.py

https://bitbucket.org/cabalistic/ogredeps/ · Python · 593 lines · 504 code · 58 blank · 31 comment · 14 complexity · 0b0b44f9c744d85774ba762896396ab7 MD5 · raw file

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