blob: 845a546dabfebea06a75dc7855ff01798ec9e758 [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 Peters52cfa332002-04-19 16:09:26 +0000100# Library Doc list of tuples:
Tim Peters661e4922002-04-20 02:39:44 +0000101# each 'book' : (Dir, Title, First page, Content page, Index page)
Tim Peters52cfa332002-04-19 16:09:26 +0000102#
103supported_libraries = {
104 '2.2': ### Beta!!! fix for actual release
105 [
106 ('.', 'Global Module Index', 'modindex.html', None, None),
Tim Peters5d5e1932002-04-20 02:07:58 +0000107 ('whatsnew', "What's New", 'index.html', 'contents.html', None),
Tim Peters52cfa332002-04-19 16:09:26 +0000108 ('tut','Tutorial','tut.html','node2.html',None),
109 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
110 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
111 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
112 ('ext','Extending and Embedding','ext.html','contents.html',None),
113 ('api','Python/C API','api.html','contents.html','genindex.html'),
114 ('doc','Documenting Python','doc.html','contents.html',None),
115 ('inst','Installing Python Modules', 'inst.html', 'index.html', None),
116 ('dist','Distributing Python Modules', 'dist.html', 'index.html', None),
117 ],
118
119 '2.1.1':
120 [
121 ('.', 'Global Module Index', 'modindex.html', None, None),
122 ('tut','Tutorial','tut.html','node2.html',None),
123 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
124 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
125 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
126 ('ext','Extending and Embedding','ext.html','contents.html',None),
127 ('api','Python/C API','api.html','contents.html','genindex.html'),
128 ('doc','Documenting Python','doc.html','contents.html',None),
129 ('inst','Installing Python Modules', 'inst.html', 'index.html', None),
130 ('dist','Distributing Python Modules', 'dist.html', 'index.html', None),
131 ],
132
133 '2.0.0':
134 [
135 ('.', 'Global Module Index', 'modindex.html', None, None),
136 ('tut','Tutorial','tut.html','node2.html',None),
137 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
138 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
139 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
140 ('ext','Extending and Embedding','ext.html','contents.html',None),
141 ('api','Python/C API','api.html','contents.html','genindex.html'),
142 ('doc','Documenting Python','doc.html','contents.html',None),
143 ('inst','Installing Python Modules', 'inst.html', 'contents.html', None),
144 ('dist','Distributing Python Modules', 'dist.html', 'contents.html', None),
145 ],
146
147 # <dnagata@creo.com> Apr 17/99: library for 1.5.2 version:
148 # <hernan.foffani@iname.com> May 01/99: library for 1.5.2 (04/30/99):
149 '1.5.2':
150 [
151 ('tut','Tutorial','tut.html','node2.html',None),
152 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
153 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
154 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
155 ('ext','Extending and Embedding','ext.html','contents.html',None),
156 ('api','Python/C API','api.html','contents.html','genindex.html'),
157 ('doc','Documenting Python','doc.html','contents.html',None)
158 ],
159
160 # library for 1.5.1 version:
161 '1.5.1':
162 [
163 ('tut','Tutorial','tut.html','contents.html',None),
164 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
165 ('ref','Language Reference','ref-1.html','ref-2.html','ref-11.html'),
166 ('ext','Extending and Embedding','ext.html','contents.html',None),
167 ('api','Python/C API','api.html','contents.html','genindex.html')
168 ],
169
170 # library for 1.5 version:
171 '1.5':
172 [
173 ('tut','Tutorial','tut.html','node1.html',None),
174 ('lib','Library Reference','lib.html','node1.html','node268.html'),
175 ('ref','Language Reference','ref-1.html','ref-2.html','ref-11.html'),
176 ('ext','Extending and Embedding','ext.html','node1.html',None),
177 ('api','Python/C API','api.html','node1.html','node48.html')
178 ]
179}
180
Tim Peters661e4922002-04-20 02:39:44 +0000181class AlmostNullWriter(formatter.NullWriter):
Tim Peters52cfa332002-04-19 16:09:26 +0000182 savedliteral = ''
183
Tim Peters661e4922002-04-20 02:39:44 +0000184 def send_flowing_data(self, data):
Tim Peters52cfa332002-04-19 16:09:26 +0000185 # need the text tag for later
186 datastriped = string.strip(data)
187 if self.savedliteral == '':
188 self.savedliteral = datastriped
189 else:
190 self.savedliteral = string.strip(self.savedliteral +
191 ' ' + datastriped)
192
193
Tim Peters661e4922002-04-20 02:39:44 +0000194class HelpHtmlParser(htmllib.HTMLParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000195 indent = 0 # number of tabs for pritty printing of files
196 ft = None # output file
197 path = None # relative path
198 proc = 0 # if true I process, if false I skip
199 # (some headers, footers, etc.)
200
Tim Peters661e4922002-04-20 02:39:44 +0000201 def begin_group(self):
202 if not self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000203 # first level, start processing
204 self.proc = 1
205 self.indent = self.indent + 1
206
Tim Peters661e4922002-04-20 02:39:44 +0000207 def finnish_group(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000208 self.indent = self.indent - 1
Tim Peters661e4922002-04-20 02:39:44 +0000209 if self.proc and self.indent == 0:
Tim Peters52cfa332002-04-19 16:09:26 +0000210 # if processing and back to root, then stop
211 self.proc = 0
212
Tim Peters661e4922002-04-20 02:39:44 +0000213 def anchor_bgn(self, href, name, type):
214 if self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000215 self.formatter.writer.savedliteral = ''
216 self.ft.write('<OBJECT type="text/sitemap">\n')
217 self.ft.write('\t' * self.indent + \
218 '\t<param name="Local" value="' + self.path + \
219 '/' + href + '">\n')
220
Tim Peters661e4922002-04-20 02:39:44 +0000221 def anchor_end(self):
222 if self.proc:
Tim Peters52cfa332002-04-19 16:09:26 +0000223 self.ft.write('\t' * self.indent + \
224 '\t<param name="Name" value="' + \
225 self.formatter.writer.savedliteral + '">\n')
Tim Peters661e4922002-04-20 02:39:44 +0000226 self.ft.write('\t' * self.indent + '\t</OBJECT>\n')
Tim Peters52cfa332002-04-19 16:09:26 +0000227
Tim Peters661e4922002-04-20 02:39:44 +0000228 def start_dl(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000229 self.begin_group()
230
Tim Peters661e4922002-04-20 02:39:44 +0000231 def end_dl(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000232 self.finnish_group()
233
Tim Peters661e4922002-04-20 02:39:44 +0000234 def do_dt(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000235 # no trailing newline on pourpose!
236 self.ft.write("\t" * self.indent + "<LI>")
237
238
Tim Peters661e4922002-04-20 02:39:44 +0000239class IdxHlpHtmlParser(HelpHtmlParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000240 # nothing special here, seems enough with parent class
241 pass
242
Tim Peters661e4922002-04-20 02:39:44 +0000243class TocHlpHtmlParser(HelpHtmlParser):
Tim Peters52cfa332002-04-19 16:09:26 +0000244
Tim Peters661e4922002-04-20 02:39:44 +0000245 def start_dl(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000246 self.begin_group()
247 self.ft.write('\t' * self.indent + '<UL>\n')
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 self.ft.write('</UL>\n')
252
Tim Peters661e4922002-04-20 02:39:44 +0000253 def start_ul(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000254 self.begin_group()
255 self.ft.write('\t' * self.indent + '<UL>\n')
256
Tim Peters661e4922002-04-20 02:39:44 +0000257 def end_ul(self):
Tim Peters52cfa332002-04-19 16:09:26 +0000258 self.finnish_group()
259 self.ft.write('</UL>\n')
260
Tim Peters661e4922002-04-20 02:39:44 +0000261 def do_li(self, atr_val):
Tim Peters52cfa332002-04-19 16:09:26 +0000262 # no trailing newline on pourpose!
263 self.ft.write("\t" * self.indent + "<LI>")
264
265
Tim Peters661e4922002-04-20 02:39:44 +0000266def index(path, archivo, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000267 f = formatter.AbstractFormatter(AlmostNullWriter())
268 parser = IdxHlpHtmlParser(f)
269 parser.path = path
270 parser.ft = output
271 fil = path + '/' + archivo
272 parser.feed(open(fil).read())
273 parser.close()
274
275
Tim Peters661e4922002-04-20 02:39:44 +0000276def content(path, archivo, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000277 f = formatter.AbstractFormatter(AlmostNullWriter())
278 parser = TocHlpHtmlParser(f)
279 parser.path = path
280 parser.ft = output
281 fil = path + '/' + archivo
282 parser.feed(open(fil).read())
283 parser.close()
284
285
Tim Peters661e4922002-04-20 02:39:44 +0000286def do_index(library, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000287 output.write('<UL>\n')
Tim Peters661e4922002-04-20 02:39:44 +0000288 for book in library:
Tim Peters52cfa332002-04-19 16:09:26 +0000289 print '\t', book[2]
Tim Peters661e4922002-04-20 02:39:44 +0000290 if book[4]:
Tim Peters52cfa332002-04-19 16:09:26 +0000291 index(book[0], book[4], output)
292 output.write('</UL>\n')
293
294
Tim Peters661e4922002-04-20 02:39:44 +0000295def do_content(library, version, output):
Tim Peters52cfa332002-04-19 16:09:26 +0000296 output.write(contents_header % version)
Tim Peters661e4922002-04-20 02:39:44 +0000297 for book in library:
Tim Peters52cfa332002-04-19 16:09:26 +0000298 print '\t', book[2]
299 output.write(object_sitemap % (book[0]+"/"+book[2], book[1]))
Tim Peters661e4922002-04-20 02:39:44 +0000300 if book[3]:
Tim Peters52cfa332002-04-19 16:09:26 +0000301 content(book[0], book[3], output)
302 output.write(contents_footer)
303
Tim Peters460643b2002-04-20 02:37:07 +0000304# Fill in the [FILES] section of the project (.hhp) file.
305# 'library' is the list of directory description tuples from
306# supported_libraries for the version of the docs getting generated.
307def do_project(library, output, arch, version):
Tim Peterse6b63e62002-04-19 18:07:52 +0000308 output.write(project_template % locals())
Tim Peters460643b2002-04-20 02:37:07 +0000309 for book in library:
310 directory = book[0]
311 path = directory + '\\%s\n'
312 for page in os.listdir(directory):
313 if page.endswith('.html') or page.endswith('.css'):
314 output.write(path % page)
Tim Peters52cfa332002-04-19 16:09:26 +0000315
316
Tim Peters661e4922002-04-20 02:39:44 +0000317def openfile(file):
318 try:
Tim Peters52cfa332002-04-19 16:09:26 +0000319 p = open(file, "w")
Tim Peters661e4922002-04-20 02:39:44 +0000320 except IOError, msg:
Tim Peters52cfa332002-04-19 16:09:26 +0000321 print file, ":", msg
322 sys.exit(1)
323 return p
324
Tim Peters661e4922002-04-20 02:39:44 +0000325def usage():
Tim Peters52cfa332002-04-19 16:09:26 +0000326 print usage_mode
327 sys.exit(0)
328
329
330
Tim Peters661e4922002-04-20 02:39:44 +0000331def do_it(args = None):
332 if not args:
Tim Peters52cfa332002-04-19 16:09:26 +0000333 args = sys.argv[1:]
334
Tim Peters661e4922002-04-20 02:39:44 +0000335 if not args:
Tim Peters52cfa332002-04-19 16:09:26 +0000336 usage()
337
Tim Peters661e4922002-04-20 02:39:44 +0000338 try:
Tim Peters52cfa332002-04-19 16:09:26 +0000339 optlist, args = getopt.getopt(args, 'ckpv:')
Tim Peters661e4922002-04-20 02:39:44 +0000340 except getopt.error, msg:
Tim Peters52cfa332002-04-19 16:09:26 +0000341 print msg
342 usage()
343
Tim Peters661e4922002-04-20 02:39:44 +0000344 if not args or len(args) > 1:
Tim Peters52cfa332002-04-19 16:09:26 +0000345 usage()
346 arch = args[0]
347
348 version = None
349 for opt in optlist:
350 if opt[0] == '-v':
351 version = opt[1]
352 break
353 if not version:
354 usage()
355
356 library = supported_libraries[ version ]
357
Tim Peters661e4922002-04-20 02:39:44 +0000358 if not (('-p','') in optlist):
Tim Peters4f109c12002-04-19 18:41:46 +0000359 fname = arch + '.stp'
360 f = openfile(fname)
361 print "Building stoplist", fname, "..."
362 words = stop_list.split()
363 words.sort()
364 for word in words:
365 print >> f, word
366 f.close()
367
Tim Peters52cfa332002-04-19 16:09:26 +0000368 f = openfile(arch + '.hhp')
369 print "Building Project..."
370 do_project(library, f, arch, version)
371 if version == '2.0.0':
372 for image in os.listdir('icons'):
373 f.write('icons'+ '\\' + image + '\n')
374
375 f.close()
376
Tim Peters661e4922002-04-20 02:39:44 +0000377 if not (('-c','') in optlist):
Tim Peters52cfa332002-04-19 16:09:26 +0000378 f = openfile(arch + '.hhc')
379 print "Building Table of Content..."
380 do_content(library, version, f)
381 f.close()
382
Tim Peters661e4922002-04-20 02:39:44 +0000383 if not (('-k','') in optlist):
Tim Peters52cfa332002-04-19 16:09:26 +0000384 f = openfile(arch + '.hhk')
385 print "Building Index..."
386 do_index(library, f)
387 f.close()
388
Tim Peters661e4922002-04-20 02:39:44 +0000389if __name__ == '__main__':
Tim Peters52cfa332002-04-19 16:09:26 +0000390 do_it()