blob: 9ce8f1ea2b7a5db5394c21b229da97f385fd08ba [file] [log] [blame]
Tim Peters4f109c12002-04-19 18:41:46 +00001"""
Tim Peters52cfa332002-04-19 16:09:26 +00002 Makes the necesary files to convert from plain html of
3 Python 1.5 and 1.5.x Documentation to
4 Microsoft HTML Help format version 1.1
5 Doesn't change the html's docs.
6
7 by hernan.foffani@iname.com
8 no copyright and no responsabilities.
9
10 modified by Dale Nagata for Python 1.5.2
11
12 Renamed from make_chm.py to prechm.py, and checked into the Python
13 project, 19-Apr-2002 by Tim Peters. Assorted modifications by Tim
14 and Fred Drake. Obtained from Robin Dunn's .chm packaging of the
15 Python 2.2 docs, at <http://alldunn.com/python/>.
Tim Peters4f109c12002-04-19 18:41:46 +000016"""
Tim Peters52cfa332002-04-19 16:09:26 +000017
18import sys
19import os
20import formatter
21import htmllib
22import string
23import getopt
24
Tim Peters52cfa332002-04-19 16:09:26 +000025usage_mode = '''
26Usage: make_chm.py [-c] [-k] [-p] [-v 1.5[.x]] filename
27 -c: does not build filename.hhc (Table of Contents)
28 -k: does not build filename.hhk (Index)
29 -p: does not build filename.hhp (Project File)
30 -v 1.5[.x]: makes help for the python 1.5[.x] docs
31 (default is python 1.5.2 docs)
32'''
33
Tim Peterse6b63e62002-04-19 18:07:52 +000034# Project file (*.hhp) template. 'arch' is the file basename (like
35# the pythlp in pythlp.hhp); 'version' is the doc version number (like
36# the 2.2 in Python 2.2).
37# The magical numbers in the long line under [WINDOWS] set most of the
38# user-visible features (visible buttons, tabs, etc).
Tim Peters52cfa332002-04-19 16:09:26 +000039project_template = '''
40[OPTIONS]
Tim Peterse6b63e62002-04-19 18:07:52 +000041Compiled file=%(arch)s.chm
42Contents file=%(arch)s.hhc
43Default Window=%(arch)s
Tim Peters52cfa332002-04-19 16:09:26 +000044Default topic=index.html
45Display compile progress=No
Tim Peters4f109c12002-04-19 18:41:46 +000046Full text search stop list file=%(arch)s.stp
Tim Peters52cfa332002-04-19 16:09:26 +000047Full-text search=Yes
Tim Peterse6b63e62002-04-19 18:07:52 +000048Index file=%(arch)s.hhk
Tim Peters52cfa332002-04-19 16:09:26 +000049Language=0x409
Tim Peterse6b63e62002-04-19 18:07:52 +000050Title=Python %(version)s Documentation
Tim Peters52cfa332002-04-19 16:09:26 +000051
52[WINDOWS]
Tim Peterse6b63e62002-04-19 18:07:52 +000053%(arch)s="Python %(version)s Documentation","%(arch)s.hhc","%(arch)s.hhk",\
54"index.html","index.html",,,,,0x63520,220,0x384e,[271,372,740,718],,,,,,,0
Tim Peters52cfa332002-04-19 16:09:26 +000055
56[FILES]
57'''
58
59contents_header = '''
60<OBJECT type="text/site properties">
61 <param name="Window Styles" value="0x801227">
Tim Petersa9053632002-04-19 16:46:43 +000062 <param name="ImageType" value="Folder">
Tim Peters52cfa332002-04-19 16:09:26 +000063</OBJECT>
64<UL>
65<LI> <OBJECT type="text/sitemap">
66 <param name="Name" value="Python %s Docs">
67 <param name="Local" value="./index.html">
68 </OBJECT>
69<UL>
70'''
71
72contents_footer = '''
73</UL></UL>
74'''
75
76object_sitemap = '''
77 <LI> <OBJECT type="text/sitemap">
78 <param name="Local" value="%s">
79 <param name="Name" value="%s">
80 </OBJECT>
81'''
82
Tim Peters4f109c12002-04-19 18:41:46 +000083
84# List of words the full text search facility shouldn't index. This
85# becomes file ARCH.stp. Note that this list must be pretty small!
86# Different versions of the MS docs claim the file has a maximum size of
87# 256 or 512 bytes (including \r\n at the end of each line).
88# Note that "and", "or", "not" and "near" are operators in the search
Tim Peters8d62ad72002-04-20 02:56:20 +000089# language, so no point indexing them even if we wanted to.
Tim Peters4f109c12002-04-19 18:41:46 +000090stop_list = '''
91a an and
92is
93near
94not
95of
96or
97the
98'''
99
Tim Petersd9a10502002-04-20 03:25:02 +0000100# s is a string or None. If None or empty, return None. Else tack '.html'
101# on to the end, unless it's already there.
102def addhtml(s):
103 if s:
104 if not s.endswith('.html'):
105 s += '.html'
106 return s
107
108# Convenience class to hold info about "a book" in HTMLHelp terms == a doc
109# directory in Python terms.
110class Book:
111 def __init__(self, directory, title, firstpage,
112 contentpage=None, indexpage=None):
113 self.directory = directory
114 self.title = title
115 self.firstpage = addhtml(firstpage)
116 self.contentpage = addhtml(contentpage)
117 self.indexpage = addhtml(indexpage)
118
119# Library Doc list of books:
Tim Peters661e4922002-04-20 02:39:44 +0000120# each 'book' : (Dir, Title, First page, Content page, Index page)
Tim Peters52cfa332002-04-19 16:09:26 +0000121supported_libraries = {
122 '2.2': ### Beta!!! fix for actual release
123 [
Tim Petersd9a10502002-04-20 03:25:02 +0000124 Book('.', 'Global Module Index', 'modindex'),
125 Book('whatsnew', "What's New", 'index', 'contents'),
126 Book('tut','Tutorial','tut','node2'),
127 Book('lib','Library Reference','lib','contents','genindex'),
128 Book('ref','Language Reference','ref','contents','genindex'),
129 Book('mac','Macintosh Reference','mac','contents','genindex'),
130 Book('ext','Extending and Embedding','ext','contents'),
131 Book('api','Python/C API','api','contents','genindex'),
132 Book('doc','Documenting Python','doc','contents'),
133 Book('inst','Installing Python Modules', 'inst', 'index'),
134 Book('dist','Distributing Python Modules', 'dist', 'index'),
Tim Peters52cfa332002-04-19 16:09:26 +0000135 ],
136
137 '2.1.1':
138 [
Tim Petersd9a10502002-04-20 03:25:02 +0000139 Book('.', 'Global Module Index', 'modindex'),
140 Book('tut','Tutorial','tut','node2'),
141 Book('lib','Library Reference','lib','contents','genindex'),
142 Book('ref','Language Reference','ref','contents','genindex'),
143 Book('mac','Macintosh Reference','mac','contents','genindex'),
144 Book('ext','Extending and Embedding','ext','contents'),
145 Book('api','Python/C API','api','contents','genindex'),
146 Book('doc','Documenting Python','doc','contents'),
147 Book('inst','Installing Python Modules', 'inst', 'index'),
148 Book('dist','Distributing Python Modules', 'dist', 'index'),
Tim Peters52cfa332002-04-19 16:09:26 +0000149 ],
150
151 '2.0.0':
152 [
Tim Petersd9a10502002-04-20 03:25:02 +0000153 Book('.', 'Global Module Index', 'modindex'),
154 Book('tut','Tutorial','tut','node2'),
155 Book('lib','Library Reference','lib','contents','genindex'),
156 Book('ref','Language Reference','ref','contents','genindex'),
157 Book('mac','Macintosh Reference','mac','contents','genindex'),
158 Book('ext','Extending and Embedding','ext','contents'),
159 Book('api','Python/C API','api','contents','genindex'),
160 Book('doc','Documenting Python','doc','contents'),
161 Book('inst','Installing Python Modules', 'inst', 'contents'),
162 Book('dist','Distributing Python Modules', 'dist', 'contents'),
Tim Peters52cfa332002-04-19 16:09:26 +0000163 ],
164
165 # <dnagata@creo.com> Apr 17/99: library for 1.5.2 version:
166 # <hernan.foffani@iname.com> May 01/99: library for 1.5.2 (04/30/99):
167 '1.5.2':
168 [
Tim Petersd9a10502002-04-20 03:25:02 +0000169 Book('tut','Tutorial','tut','node2'),
170 Book('lib','Library Reference','lib','contents','genindex'),
171 Book('ref','Language Reference','ref','contents','genindex'),
172 Book('mac','Macintosh Reference','mac','contents','genindex'),
173 Book('ext','Extending and Embedding','ext','contents'),
174 Book('api','Python/C API','api','contents','genindex'),
175 Book('doc','Documenting Python','doc','contents')
Tim Peters52cfa332002-04-19 16:09:26 +0000176 ],
177
178 # library for 1.5.1 version:
179 '1.5.1':
180 [
Tim Petersd9a10502002-04-20 03:25:02 +0000181 Book('tut','Tutorial','tut','contents'),
182 Book('lib','Library Reference','lib','contents','genindex'),
183 Book('ref','Language Reference','ref-1','ref-2','ref-11'),
184 Book('ext','Extending and Embedding','ext','contents'),
185 Book('api','Python/C API','api','contents','genindex')
Tim Peters52cfa332002-04-19 16:09:26 +0000186 ],
187
188 # library for 1.5 version:
189 '1.5':
190 [
Tim Petersd9a10502002-04-20 03:25:02 +0000191 Book('tut','Tutorial','tut','node1'),
192 Book('lib','Library Reference','lib','node1','node268'),
193 Book('ref','Language Reference','ref-1','ref-2','ref-11'),
194 Book('ext','Extending and Embedding','ext','node1'),
195 Book('api','Python/C API','api','node1','node48')
Tim Peters52cfa332002-04-19 16:09:26 +0000196 ]
197}
198
Tim Peters661e4922002-04-20 02:39:44 +0000199class AlmostNullWriter(formatter.NullWriter):
Tim Peters52cfa332002-04-19 16:09:26 +0000200 savedliteral = ''
201
Tim Peters661e4922002-04-20 02:39:44 +0000202 def send_flowing_data(self, data):
Tim Peters52cfa332002-04-19 16:09:26 +0000203 # need the text tag for later
204 datastriped = string.strip(data)
205 if self.savedliteral == '':
206 self.savedliteral = datastriped
207 else:
208 self.savedliteral = string.strip(self.savedliteral +
209 ' ' + datastriped)
210
211
Tim Peters661e4922002-04-20 02:39:44 +0000212class HelpHtmlParser(htmllib.HTMLParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000213 indent = 0 # number of tabs for pritty printing of files
214 ft = None # output file
215 path = None # relative path
216 proc = 0 # if true I process, if false I skip
217 # (some headers, footers, etc.)
218
Tim Peters661e4922002-04-20 02:39:44 +0000219 def begin_group(self):
220 if not self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000221 # first level, start processing
222 self.proc = 1
223 self.indent = self.indent + 1
224
Tim Peters661e4922002-04-20 02:39:44 +0000225 def finnish_group(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000226 self.indent = self.indent - 1
Tim Peters661e4922002-04-20 02:39:44 +0000227 if self.proc and self.indent == 0:
Tim Peters52cfa332002-04-19 16:09:26 +0000228 # if processing and back to root, then stop
229 self.proc = 0
230
Tim Peters661e4922002-04-20 02:39:44 +0000231 def anchor_bgn(self, href, name, type):
232 if self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000233 self.formatter.writer.savedliteral = ''
234 self.ft.write('<OBJECT type="text/sitemap">\n')
235 self.ft.write('\t' * self.indent + \
236 '\t<param name="Local" value="' + self.path + \
237 '/' + href + '">\n')
238
Tim Peters661e4922002-04-20 02:39:44 +0000239 def anchor_end(self):
240 if self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000241 self.ft.write('\t' * self.indent + \
242 '\t<param name="Name" value="' + \
243 self.formatter.writer.savedliteral + '">\n')
Tim Peters661e4922002-04-20 02:39:44 +0000244 self.ft.write('\t' * self.indent + '\t</OBJECT>\n')
Tim Peters52cfa332002-04-19 16:09:26 +0000245
Tim Peters661e4922002-04-20 02:39:44 +0000246 def start_dl(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000247 self.begin_group()
248
Tim Peters661e4922002-04-20 02:39:44 +0000249 def end_dl(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000250 self.finnish_group()
251
Tim Peters661e4922002-04-20 02:39:44 +0000252 def do_dt(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000253 # no trailing newline on pourpose!
254 self.ft.write("\t" * self.indent + "<LI>")
255
256
Tim Peters661e4922002-04-20 02:39:44 +0000257class IdxHlpHtmlParser(HelpHtmlParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000258 # nothing special here, seems enough with parent class
259 pass
260
Tim Peters661e4922002-04-20 02:39:44 +0000261class TocHlpHtmlParser(HelpHtmlParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000262
Tim Peters661e4922002-04-20 02:39:44 +0000263 def start_dl(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000264 self.begin_group()
265 self.ft.write('\t' * self.indent + '<UL>\n')
266
Tim Peters661e4922002-04-20 02:39:44 +0000267 def end_dl(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000268 self.finnish_group()
269 self.ft.write('</UL>\n')
270
Tim Peters661e4922002-04-20 02:39:44 +0000271 def start_ul(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000272 self.begin_group()
273 self.ft.write('\t' * self.indent + '<UL>\n')
274
Tim Peters661e4922002-04-20 02:39:44 +0000275 def end_ul(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000276 self.finnish_group()
277 self.ft.write('</UL>\n')
278
Tim Peters661e4922002-04-20 02:39:44 +0000279 def do_li(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000280 # no trailing newline on pourpose!
281 self.ft.write("\t" * self.indent + "<LI>")
282
283
Tim Petersd9a10502002-04-20 03:25:02 +0000284def index(path, indexpage, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000285 f = formatter.AbstractFormatter(AlmostNullWriter())
286 parser = IdxHlpHtmlParser(f)
287 parser.path = path
288 parser.ft = output
Tim Petersd9a10502002-04-20 03:25:02 +0000289 f = open(path + '/' + indexpage)
290 parser.feed(f.read())
Tim Peters52cfa332002-04-19 16:09:26 +0000291 parser.close()
Tim Petersd9a10502002-04-20 03:25:02 +0000292 f.close()
Tim Peters52cfa332002-04-19 16:09:26 +0000293
294
Tim Petersd9a10502002-04-20 03:25:02 +0000295def content(path, contentpage, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000296 f = formatter.AbstractFormatter(AlmostNullWriter())
297 parser = TocHlpHtmlParser(f)
298 parser.path = path
299 parser.ft = output
Tim Petersd9a10502002-04-20 03:25:02 +0000300 f = open(path + '/' + contentpage)
301 parser.feed(f.read())
Tim Peters52cfa332002-04-19 16:09:26 +0000302 parser.close()
Tim Petersd9a10502002-04-20 03:25:02 +0000303 f.close()
Tim Peters52cfa332002-04-19 16:09:26 +0000304
305
Tim Peters661e4922002-04-20 02:39:44 +0000306def do_index(library, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000307 output.write('<UL>\n')
Tim Peters661e4922002-04-20 02:39:44 +0000308 for book in library:
Tim Petersd9a10502002-04-20 03:25:02 +0000309 print '\t', book.title, '-', book.indexpage
310 if book.indexpage:
311 index(book.directory, book.indexpage, output)
Tim Peters52cfa332002-04-19 16:09:26 +0000312 output.write('</UL>\n')
313
314
Tim Peters661e4922002-04-20 02:39:44 +0000315def do_content(library, version, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000316 output.write(contents_header % version)
Tim Peters661e4922002-04-20 02:39:44 +0000317 for book in library:
Tim Petersd9a10502002-04-20 03:25:02 +0000318 print '\t', book.title, '-', book.firstpage
319 output.write(object_sitemap % (book.directory + "/" + book.firstpage,
320 book.title))
321 if book.contentpage:
322 content(book.directory, book.contentpage, output)
Tim Peters52cfa332002-04-19 16:09:26 +0000323 output.write(contents_footer)
324
Tim Peters460643b2002-04-20 02:37:07 +0000325# Fill in the [FILES] section of the project (.hhp) file.
326# 'library' is the list of directory description tuples from
327# supported_libraries for the version of the docs getting generated.
328def do_project(library, output, arch, version):
Tim Peterse6b63e62002-04-19 18:07:52 +0000329 output.write(project_template % locals())
Tim Peters460643b2002-04-20 02:37:07 +0000330 for book in library:
Tim Petersd9a10502002-04-20 03:25:02 +0000331 directory = book.directory
Tim Peters460643b2002-04-20 02:37:07 +0000332 path = directory + '\\%s\n'
333 for page in os.listdir(directory):
334 if page.endswith('.html') or page.endswith('.css'):
335 output.write(path % page)
Tim Peters52cfa332002-04-19 16:09:26 +0000336
337
Tim Peters661e4922002-04-20 02:39:44 +0000338def openfile(file):
339 try:
Tim Peters52cfa332002-04-19 16:09:26 +0000340 p = open(file, "w")
Tim Peters661e4922002-04-20 02:39:44 +0000341 except IOError, msg:
Tim Peters52cfa332002-04-19 16:09:26 +0000342 print file, ":", msg
343 sys.exit(1)
344 return p
345
Tim Peters661e4922002-04-20 02:39:44 +0000346def usage():
Tim Peters52cfa332002-04-19 16:09:26 +0000347 print usage_mode
348 sys.exit(0)
349
350
351
Tim Peters661e4922002-04-20 02:39:44 +0000352def do_it(args = None):
353 if not args:
Tim Peters52cfa332002-04-19 16:09:26 +0000354 args = sys.argv[1:]
355
Tim Peters661e4922002-04-20 02:39:44 +0000356 if not args:
Tim Peters52cfa332002-04-19 16:09:26 +0000357 usage()
358
Tim Peters661e4922002-04-20 02:39:44 +0000359 try:
Tim Peters52cfa332002-04-19 16:09:26 +0000360 optlist, args = getopt.getopt(args, 'ckpv:')
Tim Peters661e4922002-04-20 02:39:44 +0000361 except getopt.error, msg:
Tim Peters52cfa332002-04-19 16:09:26 +0000362 print msg
363 usage()
364
Tim Peters661e4922002-04-20 02:39:44 +0000365 if not args or len(args) > 1:
Tim Peters52cfa332002-04-19 16:09:26 +0000366 usage()
367 arch = args[0]
368
369 version = None
370 for opt in optlist:
371 if opt[0] == '-v':
372 version = opt[1]
373 break
374 if not version:
375 usage()
376
Tim Petersd9a10502002-04-20 03:25:02 +0000377 library = supported_libraries[version]
Tim Peters52cfa332002-04-19 16:09:26 +0000378
Tim Peters661e4922002-04-20 02:39:44 +0000379 if not (('-p','') in optlist):
Tim Peters4f109c12002-04-19 18:41:46 +0000380 fname = arch + '.stp'
381 f = openfile(fname)
382 print "Building stoplist", fname, "..."
383 words = stop_list.split()
384 words.sort()
385 for word in words:
386 print >> f, word
387 f.close()
388
Tim Peters52cfa332002-04-19 16:09:26 +0000389 f = openfile(arch + '.hhp')
390 print "Building Project..."
391 do_project(library, f, arch, version)
392 if version == '2.0.0':
393 for image in os.listdir('icons'):
394 f.write('icons'+ '\\' + image + '\n')
395
396 f.close()
397
Tim Peters661e4922002-04-20 02:39:44 +0000398 if not (('-c','') in optlist):
Tim Peters52cfa332002-04-19 16:09:26 +0000399 f = openfile(arch + '.hhc')
400 print "Building Table of Content..."
401 do_content(library, version, f)
402 f.close()
403
Tim Peters661e4922002-04-20 02:39:44 +0000404 if not (('-k','') in optlist):
Tim Peters52cfa332002-04-19 16:09:26 +0000405 f = openfile(arch + '.hhk')
406 print "Building Index..."
407 do_index(library, f)
408 f.close()
409
Tim Peters661e4922002-04-20 02:39:44 +0000410if __name__ == '__main__':
Tim Peters52cfa332002-04-19 16:09:26 +0000411 do_it()