########################################################################
##
## Win32 Usage: makepanda\makechm.bat
## Linux Usage: makepanda/makechm.py
##
## To use this script, you will need to have hhc.exe on your system.
## For verbose output, run with -v or --verbose option.
## To keep the temporary .hhc, .hhk, .hhp, .chw files use -k or --keep.
##
## You can also import this file as a python module. You will then have
## access to three functions: makeCHM, makeManualCHM, makeReferenceCHM.
## This is how you call them:
## makeCHM(outputfile, dirname, title)
## where outputfile is the filename where the .chm file will be written,
## and dirname is the directory containing the html files to include.
## Title will be the title of the CHM file.
## The functions makeManualCHM and makeReferenceCHM work exactly the
## same, except that they work with a structure resembling that of the
## Panda3D manual and reference, respectively.
## Note: outputfile should not contain spaces.
##
########################################################################
__all__ = ["makeCHM", "makeManualCHM", "makeReferenceCHM"]
import os, re
from sys import exit
import xml.dom.minidom
from xml.dom.minidom import Node
VERBOSE = False
KEEPTEMP = False
if __name__ == "__main__":
from sys import argv
VERBOSE = ("-v" in argv) or ("-vk" in argv) or ("-kv" in argv) or ("--verbose" in argv)
KEEPTEMP = ("-k" in argv) or ("-kv" in argv) or ("-vk" in argv) or ("--keep" in argv)
OPTIONBLOCK = """
Binary TOC=Yes
Compatibility=1.1 or later
Compiled file=%s
Contents file=%s.hhc
Default Font=Arial,10,0
Default topic=%s
Display compile progress=VERBOSE
Full-text search=Yes
Index file=%s.hhk
Language=0x409 English (United States)
Title=%s""".replace("VERBOSE", VERBOSE and "Yes" or "No")
HTMLBLOCK = """
\n"""
REFERENCEITEMS = [
("index.html", "Main Page"),
("methods.html", "Methods"),
("functions.html", "Global Functions"),
("classes.html", "Classes"),
]
def urldecode(url):
regex = re.compile("%([0-9a-hA-H][0-9a-hA-H])", re.M)
return regex.sub(lambda x: chr(int(x.group(1), 16)), url)
def ireplace(string, target, replacement):
"""Case-insensitive replace."""
index = string.lower().find(target.lower())
if index >= 0:
result = string[:index] + replacement + string[index + len(target):]
return result
else:
return string
def parseAnchor(node):
"""Parses an XML minidom node representing an anchor and returns a tuple
containing the href and the content of the link."""
assert node.nodeType == Node.ELEMENT_NODE
assert node.localName == "a"
href = ""
title = ""
for localName, a in node.attributes.items():
if localName.lower() == "href":
href = a
for e in node.childNodes:
if e.nodeType == Node.TEXT_NODE:
title += e.data
return href, title
def parseManualTree(node):
"""Parses a tree of the manual Main_Page and returns it through a list containing tuples:
[(title, href, [(title, href, [...]), ...]), ...]"""
if node.nodeType != Node.ELEMENT_NODE: return []
result = []
lastadded = None
for e in node.childNodes:
if e.nodeType == Node.ELEMENT_NODE:
if e.localName == "ol":
assert lastadded != None
for i in xrange(len(result)):
if result[i][:2] == lastadded:
result[i] = lastadded + (parseManualTree(e),)
elif e.localName == "a":
href, title = parseAnchor(e)
lastadded = title, href
result.append((title, href, None))
return result
def parseManualTOC(filename):
"""Reads the manual's Main_Page file and returns a list of all the trees found."""
filename = open(filename)
text = filename.read()
filename.close()
text = text.split("