blob: 2ce85c4c5454c41c5d28bcaaeb0a857e8ff99518 [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
89# language, so not point indexing them even if wanted to.
90stop_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:
101# each 'book' : ( Dir, Title, First page, Content page, Index page)
102#
103supported_libraries = {
104 '2.2': ### Beta!!! fix for actual release
105 [
106 ('.', 'Global Module Index', 'modindex.html', None, None),
107 ('tut','Tutorial','tut.html','node2.html',None),
108 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
109 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
110 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
111 ('ext','Extending and Embedding','ext.html','contents.html',None),
112 ('api','Python/C API','api.html','contents.html','genindex.html'),
113 ('doc','Documenting Python','doc.html','contents.html',None),
114 ('inst','Installing Python Modules', 'inst.html', 'index.html', None),
115 ('dist','Distributing Python Modules', 'dist.html', 'index.html', None),
116 ],
117
118 '2.1.1':
119 [
120 ('.', 'Global Module Index', 'modindex.html', None, None),
121 ('tut','Tutorial','tut.html','node2.html',None),
122 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
123 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
124 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
125 ('ext','Extending and Embedding','ext.html','contents.html',None),
126 ('api','Python/C API','api.html','contents.html','genindex.html'),
127 ('doc','Documenting Python','doc.html','contents.html',None),
128 ('inst','Installing Python Modules', 'inst.html', 'index.html', None),
129 ('dist','Distributing Python Modules', 'dist.html', 'index.html', None),
130 ],
131
132 '2.0.0':
133 [
134 ('.', 'Global Module Index', 'modindex.html', None, None),
135 ('tut','Tutorial','tut.html','node2.html',None),
136 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
137 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
138 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
139 ('ext','Extending and Embedding','ext.html','contents.html',None),
140 ('api','Python/C API','api.html','contents.html','genindex.html'),
141 ('doc','Documenting Python','doc.html','contents.html',None),
142 ('inst','Installing Python Modules', 'inst.html', 'contents.html', None),
143 ('dist','Distributing Python Modules', 'dist.html', 'contents.html', None),
144 ],
145
146 # <dnagata@creo.com> Apr 17/99: library for 1.5.2 version:
147 # <hernan.foffani@iname.com> May 01/99: library for 1.5.2 (04/30/99):
148 '1.5.2':
149 [
150 ('tut','Tutorial','tut.html','node2.html',None),
151 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
152 ('ref','Language Reference','ref.html','contents.html','genindex.html'),
153 ('mac','Macintosh Reference','mac.html','contents.html','genindex.html'),
154 ('ext','Extending and Embedding','ext.html','contents.html',None),
155 ('api','Python/C API','api.html','contents.html','genindex.html'),
156 ('doc','Documenting Python','doc.html','contents.html',None)
157 ],
158
159 # library for 1.5.1 version:
160 '1.5.1':
161 [
162 ('tut','Tutorial','tut.html','contents.html',None),
163 ('lib','Library Reference','lib.html','contents.html','genindex.html'),
164 ('ref','Language Reference','ref-1.html','ref-2.html','ref-11.html'),
165 ('ext','Extending and Embedding','ext.html','contents.html',None),
166 ('api','Python/C API','api.html','contents.html','genindex.html')
167 ],
168
169 # library for 1.5 version:
170 '1.5':
171 [
172 ('tut','Tutorial','tut.html','node1.html',None),
173 ('lib','Library Reference','lib.html','node1.html','node268.html'),
174 ('ref','Language Reference','ref-1.html','ref-2.html','ref-11.html'),
175 ('ext','Extending and Embedding','ext.html','node1.html',None),
176 ('api','Python/C API','api.html','node1.html','node48.html')
177 ]
178}
179
180class AlmostNullWriter(formatter.NullWriter) :
181 savedliteral = ''
182
183 def send_flowing_data(self, data) :
184 # need the text tag for later
185 datastriped = string.strip(data)
186 if self.savedliteral == '':
187 self.savedliteral = datastriped
188 else:
189 self.savedliteral = string.strip(self.savedliteral +
190 ' ' + datastriped)
191
192
193class HelpHtmlParser(htmllib.HTMLParser) :
194 indent = 0 # number of tabs for pritty printing of files
195 ft = None # output file
196 path = None # relative path
197 proc = 0 # if true I process, if false I skip
198 # (some headers, footers, etc.)
199
200 def begin_group(self) :
201 if not self.proc :
202 # first level, start processing
203 self.proc = 1
204 self.indent = self.indent + 1
205
206 def finnish_group(self) :
207 self.indent = self.indent - 1
208 if self.proc and self.indent == 0 :
209 # if processing and back to root, then stop
210 self.proc = 0
211
212 def anchor_bgn(self, href, name, type) :
213 if self.proc :
214 self.formatter.writer.savedliteral = ''
215 self.ft.write('<OBJECT type="text/sitemap">\n')
216 self.ft.write('\t' * self.indent + \
217 '\t<param name="Local" value="' + self.path + \
218 '/' + href + '">\n')
219
220 def anchor_end(self) :
221 if self.proc :
222 self.ft.write('\t' * self.indent + \
223 '\t<param name="Name" value="' + \
224 self.formatter.writer.savedliteral + '">\n')
225 self.ft.write('\t' * self.indent + '\t</OBJECT>\n' )
226
227 def start_dl(self, atr_val) :
228 self.begin_group()
229
230 def end_dl(self) :
231 self.finnish_group()
232
233 def do_dt(self, atr_val) :
234 # no trailing newline on pourpose!
235 self.ft.write("\t" * self.indent + "<LI>")
236
237
238class IdxHlpHtmlParser(HelpHtmlParser) :
239 # nothing special here, seems enough with parent class
240 pass
241
242class TocHlpHtmlParser(HelpHtmlParser) :
243
244 def start_dl(self, atr_val) :
245 self.begin_group()
246 self.ft.write('\t' * self.indent + '<UL>\n')
247
248 def end_dl(self) :
249 self.finnish_group()
250 self.ft.write('</UL>\n')
251
252 def start_ul(self, atr_val) :
253 self.begin_group()
254 self.ft.write('\t' * self.indent + '<UL>\n')
255
256 def end_ul(self) :
257 self.finnish_group()
258 self.ft.write('</UL>\n')
259
260 def do_li(self, atr_val) :
261 # no trailing newline on pourpose!
262 self.ft.write("\t" * self.indent + "<LI>")
263
264
265def index(path, archivo, output) :
266 f = formatter.AbstractFormatter(AlmostNullWriter())
267 parser = IdxHlpHtmlParser(f)
268 parser.path = path
269 parser.ft = output
270 fil = path + '/' + archivo
271 parser.feed(open(fil).read())
272 parser.close()
273
274
275def content(path, archivo, output) :
276 f = formatter.AbstractFormatter(AlmostNullWriter())
277 parser = TocHlpHtmlParser(f)
278 parser.path = path
279 parser.ft = output
280 fil = path + '/' + archivo
281 parser.feed(open(fil).read())
282 parser.close()
283
284
285def do_index(library, output) :
286 output.write('<UL>\n')
287 for book in library :
288 print '\t', book[2]
289 if book[4] :
290 index(book[0], book[4], output)
291 output.write('</UL>\n')
292
293
294def do_content(library, version, output) :
295 output.write(contents_header % version)
296 for book in library :
297 print '\t', book[2]
298 output.write(object_sitemap % (book[0]+"/"+book[2], book[1]))
299 if book[3] :
300 content(book[0], book[3], output)
301 output.write(contents_footer)
302
303
304def do_project( library, output, arch, version) :
Tim Peterse6b63e62002-04-19 18:07:52 +0000305 output.write(project_template % locals())
Tim Peters52cfa332002-04-19 16:09:26 +0000306 for book in library :
307 for page in os.listdir(book[0]) :
308 if page[string.rfind(page, '.'):] == '.html' or \
309 page[string.rfind(page, '.'):] == '.css':
310 output.write(book[0]+ '\\' + page + '\n')
311
312
313def openfile(file) :
314 try :
315 p = open(file, "w")
316 except IOError, msg :
317 print file, ":", msg
318 sys.exit(1)
319 return p
320
321def usage() :
322 print usage_mode
323 sys.exit(0)
324
325
326
327def do_it(args = None) :
328 if not args :
329 args = sys.argv[1:]
330
331 if not args :
332 usage()
333
334 try :
335 optlist, args = getopt.getopt(args, 'ckpv:')
336 except getopt.error, msg :
337 print msg
338 usage()
339
340 if not args or len(args) > 1 :
341 usage()
342 arch = args[0]
343
344 version = None
345 for opt in optlist:
346 if opt[0] == '-v':
347 version = opt[1]
348 break
349 if not version:
350 usage()
351
352 library = supported_libraries[ version ]
353
354 if not (('-p','') in optlist) :
Tim Peters4f109c12002-04-19 18:41:46 +0000355 fname = arch + '.stp'
356 f = openfile(fname)
357 print "Building stoplist", fname, "..."
358 words = stop_list.split()
359 words.sort()
360 for word in words:
361 print >> f, word
362 f.close()
363
Tim Peters52cfa332002-04-19 16:09:26 +0000364 f = openfile(arch + '.hhp')
365 print "Building Project..."
366 do_project(library, f, arch, version)
367 if version == '2.0.0':
368 for image in os.listdir('icons'):
369 f.write('icons'+ '\\' + image + '\n')
370
371 f.close()
372
373 if not (('-c','') in optlist) :
374 f = openfile(arch + '.hhc')
375 print "Building Table of Content..."
376 do_content(library, version, f)
377 f.close()
378
379 if not (('-k','') in optlist) :
380 f = openfile(arch + '.hhk')
381 print "Building Index..."
382 do_index(library, f)
383 f.close()
384
385if __name__ == '__main__' :
386 do_it()
387
388