mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
Added tools for generating CHM files
This commit is contained in:
parent
f2da89ae04
commit
8af65bfe45
26
doc/makepanda/makechm.bat
Executable file
26
doc/makepanda/makechm.bat
Executable file
@ -0,0 +1,26 @@
|
||||
@echo off
|
||||
|
||||
REM
|
||||
REM Verify that we can find the 'makechm' python script
|
||||
REM and the python interpreter. If we can find both, then
|
||||
REM run 'makechm'.
|
||||
REM
|
||||
|
||||
if not exist makepanda\makechm.py goto :missing1
|
||||
if not exist thirdparty\win-python\python.exe goto :missing2
|
||||
thirdparty\win-python\python.exe makepanda\makechm.py %*
|
||||
goto done
|
||||
|
||||
:missing1
|
||||
echo You need to change directory to the root of the panda source tree
|
||||
echo before invoking makechm.
|
||||
goto done
|
||||
|
||||
:missing2
|
||||
echo You seem to be missing the 'thirdparty' directory. You probably checked
|
||||
echo the source code out from sourceforge. The sourceforge repository is
|
||||
echo missing the 'thirdparty' directory. You will need to supplement the
|
||||
echo code by downloading the 'thirdparty' directory from panda3d.etc.cmu.edu
|
||||
goto done
|
||||
|
||||
:done
|
277
doc/makepanda/makechm.py
Executable file
277
doc/makepanda/makechm.py
Executable file
@ -0,0 +1,277 @@
|
||||
########################################################################
|
||||
##
|
||||
## 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 = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="Panda3D - makechm.py">
|
||||
</head>
|
||||
<body>
|
||||
<object type="text/site properties">
|
||||
<param name="Window Styles" value="0x800025">
|
||||
<param name="ImageType" value="Folder">
|
||||
<param name="Font" value="Arial,8,0">
|
||||
</object>
|
||||
<ul>\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("<h2>Table of Contents</h2>")[1].split("</td>")[0]
|
||||
text = "<root>" + text.replace("<li>", "") + "</root>"
|
||||
text = re.sub(re.compile("<!--([^>]+)>"), "", text)
|
||||
result = []
|
||||
for e in xml.dom.minidom.parseString(text).childNodes[0].childNodes:
|
||||
if e.nodeType == Node.ELEMENT_NODE:
|
||||
result.append(parseManualTree(e))
|
||||
return result
|
||||
|
||||
def treeToHTML(tree, dirname, indent = ""):
|
||||
"""Converts a tree into HTML code suitable for .hhc or .hhk files. The tree should be like:
|
||||
[(title, href, [(title, href, [...]), ...]), ...]"""
|
||||
html = ""
|
||||
for title, href, sub in tree:
|
||||
html += indent + "<li><object type=\"text/sitemap\">\n"
|
||||
html += indent + " <param name=\"Name\" value=\"%s\">\n" % title.replace("CXX", "C++").replace("\"", """)
|
||||
html += indent + " <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, href))
|
||||
html += indent + "</object>\n"
|
||||
if sub != None:
|
||||
html += indent + "<ul>\n"
|
||||
html += treeToHTML(sub, dirname, indent + " ")
|
||||
html += indent + "</ul>\n"
|
||||
return html
|
||||
|
||||
def makeCHM(outputfile, dirname, title, special = None):
|
||||
"""Creates a CHM file based on a directory of HTML files. See the top of this file for more info."""
|
||||
assert special == None or special in ["manual", "reference"]
|
||||
reference = (special == "reference")
|
||||
manual = (special == "manual")
|
||||
base = ireplace(outputfile, ".chm", "")
|
||||
if os.path.isfile(base + ".chm"): os.remove(base + ".chm")
|
||||
# Create the hhp file
|
||||
hhp = open(base + ".hhp", "w")
|
||||
hhp.write("[OPTIONS]\n")
|
||||
hhp.write(OPTIONBLOCK % (base + ".chm", base, urldecode(os.path.join(dirname, "index.html")), base, title))
|
||||
hhp.write("\n[FILES]\n")
|
||||
# Create the TOC file and Index file
|
||||
hhk = open(base + ".hhk", "w")
|
||||
hhc = open(base + ".hhc", "w")
|
||||
hhk.write(HTMLBLOCK)
|
||||
hhc.write(HTMLBLOCK)
|
||||
# The manual should be treated as a special case.
|
||||
if manual:
|
||||
hhc.write(" <li><object type=\"text/sitemap\">\n")
|
||||
hhc.write(" <param name=\"Name\" value=\"Main Page\">\n")
|
||||
hhc.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, "index.html")))
|
||||
hhc.write(" </object>\n")
|
||||
for item in parseManualTOC("manual/index.html"):
|
||||
hhc.write(treeToHTML(item, dirname, " "))
|
||||
for i in os.listdir(dirname):
|
||||
hhp.write(os.path.join(dirname, i) + "\n")
|
||||
if i != "index.html":
|
||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", "").replace("_", " ").replace("CXX", "C++"), ".html", "").replace("\"", """))
|
||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
||||
hhk.write(" </object>\n")
|
||||
else:
|
||||
idt = " "
|
||||
# If we are writing out the reference, write some extra stuff.
|
||||
if reference:
|
||||
idt = " "
|
||||
for i, desc in REFERENCEITEMS:
|
||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % desc.replace("\"", """))
|
||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
||||
hhk.write(" </object>\n")
|
||||
hhc.write(" <li><object type=\"text/sitemap\">\n")
|
||||
hhc.write(" <param name=\"Name\" value=\"%s\">\n" % desc.replace("\"", """))
|
||||
hhc.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
||||
hhc.write(" </object>\n")
|
||||
hhc.write(" <ul>\n")
|
||||
# Loop through the directories and write out relevant data.
|
||||
for i in os.listdir(dirname):
|
||||
hhp.write(os.path.join(dirname, i) + "\n")
|
||||
if i != "index.html" and ((not reference) or (not i in ["classes.html", "methods.html", "functions.html"])):
|
||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", ""), ".html", "").replace("\"", """))
|
||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
||||
hhk.write(" </object>\n")
|
||||
hhc.write(idt + "<li><object type=\"text/sitemap\">\n")
|
||||
hhc.write(idt + " <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", ""), ".html", "").replace("\"", """))
|
||||
hhc.write(idt + " <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
||||
hhc.write(idt + "</object>\n")
|
||||
# Close the files.
|
||||
if reference: hhc.write(" </ul>\n")
|
||||
hhk.write(" </ul>\n </body>\n</html>")
|
||||
hhc.write(" </ul>\n </body>\n</html>")
|
||||
hhk.close()
|
||||
hhc.close()
|
||||
hhp.close()
|
||||
# Now, execute the command to compile the files.
|
||||
if os.path.isdir("C:\Program Files\HTML Help Workshop"):
|
||||
cmd = "\"C:\Program Files\HTML Help Workshop\hhc.exe\" %s.hhp" % base
|
||||
else:
|
||||
cmd = "hhc \"%s.hhp\"" % base
|
||||
print cmd
|
||||
os.system(cmd)
|
||||
if not KEEPTEMP:
|
||||
if os.path.isfile("%s.hhp" % base): os.remove("%s.hhp" % base)
|
||||
if os.path.isfile("%s.hhc" % base): os.remove("%s.hhc" % base)
|
||||
if os.path.isfile("%s.hhk" % base): os.remove("%s.hhk" % base)
|
||||
if os.path.isfile("%s.chw" % base): os.remove("%s.chw" % base)
|
||||
if not os.path.isfile(base + ".chm"):
|
||||
print "An error has occurred!"
|
||||
if __name__ == "__main__":
|
||||
exit(1)
|
||||
else:
|
||||
return False
|
||||
if __name__ != "__main__":
|
||||
return True
|
||||
|
||||
def makeManualCHM(outputfile, dirname, title):
|
||||
"""Same as makeCHM, but suitable for converting the Panda3D manual."""
|
||||
return makeCHM(outputfile, dirname, title, special = "manual")
|
||||
|
||||
def makeReferenceCHM(outputfile, dirname, title):
|
||||
"""Same as makeCHM, but converts a structure resembling that of the Panda3D reference."""
|
||||
return makeCHM(outputfile, dirname, title, special = "reference")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Extract a version number, if we have one.
|
||||
VERSION = None
|
||||
try:
|
||||
f = file("built/include/pandaVersion.h","r")
|
||||
pattern = re.compile('^\s*[#]\s*define\s+PANDA_VERSION_STR\s+["]([0-9.]+)["]')
|
||||
for line in f:
|
||||
match = pattern.match(line,0)
|
||||
if (match):
|
||||
VERSION = match.group(1)
|
||||
break
|
||||
f.close()
|
||||
except:
|
||||
# If not, we don't care at all.
|
||||
pass
|
||||
|
||||
# Now, make CHM's for both the manual and reference, if we have them.
|
||||
if not os.path.isdir("manual"):
|
||||
print "No directory named 'manual' found"
|
||||
else:
|
||||
print "Making CHM file for manual..."
|
||||
if VERSION == None:
|
||||
makeManualCHM("panda3d-manual.chm", "manual", "Panda3D Manual")
|
||||
else:
|
||||
makeManualCHM("panda3d-%s-manual.chm" % VERSION, "manual", "Panda3D %s Manual" % VERSION)
|
||||
|
||||
if not os.path.isdir("reference"):
|
||||
print "No directory named 'reference' found"
|
||||
else:
|
||||
print "Making CHM file for API reference..."
|
||||
if VERSION == None:
|
||||
makeReferenceCHM("panda3d-reference.chm", "reference", "Panda3D Reference")
|
||||
else:
|
||||
makeReferenceCHM("panda3d-%s-reference.chm" % VERSION, "reference", "Panda3D %s Reference" % VERSION)
|
||||
|
||||
print "Done!"
|
Loading…
x
Reference in New Issue
Block a user