add a share dir todo
[PyX.git] / www / pt2html.py
blob2e3399b9d5006f7c9d0a8e03cb4036601e36d23f
1 import sys, os, os.path, cgi, StringIO, codecs, glob, re, warnings
2 import keyword, token, tokenize
3 import xml.dom.minidom
4 from zope.pagetemplate.pagetemplatefile import PageTemplateFile
5 import Image
7 # make zope 3.2.1 run:
8 import zope.pagetemplate.pagetemplatefile as pagetemplatefile
9 pagetemplatefile.DEFAULT_ENCODING = "latin1"
11 sys.path[:0]=[".."]
12 import pyx
14 _KEYWORD = token.NT_OFFSET
16 tokclasses = {token.NUMBER: 'number',
17 token.OP: 'op',
18 token.STRING: 'string',
19 tokenize.COMMENT: 'comment',
20 token.NAME: 'name',
21 _KEYWORD: 'keyword'}
23 class MakeHtml:
25 def fromPython(self, input):
26 input = StringIO.StringIO(input)
27 self.output = StringIO.StringIO()
28 self.col = 0
29 self.tokclass = None
30 self.output.write("<pre id=python>")
31 tokenize.tokenize(input.readline, self.tokeneater)
32 if self.tokclass is not None:
33 self.output.write('</span>')
34 self.output.write("</pre>\n")
35 return self.output.getvalue()
37 def tokeneater(self, toktype, toktext, (srow, scol), (erow, ecol), line):
38 if toktype == token.ERRORTOKEN:
39 raise RuntimeError("ErrorToken occured")
40 if toktype in [token.NEWLINE, tokenize.NL]:
41 self.output.write('\n')
42 self.col = 0
43 else:
44 # map token type to a color group
45 if token.LPAR <= toktype and toktype <= token.OP:
46 toktype = token.OP
47 elif toktype == token.NAME and keyword.iskeyword(toktext):
48 toktype = _KEYWORD
50 # restore whitespace
51 assert scol >= self.col
52 self.output.write(" "*(scol-self.col))
54 try:
55 tokclass = tokclasses[toktype]
56 except KeyError:
57 tokclass = None
58 if self.tokclass is not None and tokclass != self.tokclass:
59 self.output.write('</span>')
60 if tokclass is not None and tokclass != self.tokclass:
61 self.output.write('<span class="%s">' % tokclass)
62 self.output.write(cgi.escape(toktext))
63 self.tokclass = tokclass
65 # calculate new column position
66 self.col = scol + len(toktext)
67 newline = toktext.rfind("\n")
68 if newline != -1:
69 self.col = len(toktext) - newline - 1
71 emptypattern = re.compile(r"\s*$")
72 parpattern = re.compile(r"([ \t]*\n)*(?P<data>(\S[^\n]*\n)+)(([ \t]*\n)+.*)?")
73 parmakeline = re.compile(r"\s*[\r\n]\s*")
74 parmakeinline = re.compile(r"`(.*?)`")
75 parmakeitalic = re.compile(r"''(.*?)''")
76 parmakebold = re.compile(r"'''(.*?)'''")
77 codepattern = re.compile(r"([ \t]*\n)*(?P<data>(([ \t]+[^\n]*)?\n)+)")
78 indentpattern = re.compile(r"([ \t]*\n)*(?P<indent>[ \t]+)")
80 def fromText(self, input, bend=""):
81 title = None
82 pos = 0
83 output = StringIO.StringIO()
84 while not self.emptypattern.match(input, pos):
85 par = self.parpattern.match(input, pos)
86 if par:
87 pos = par.end("data")
88 par = par.group("data").strip()
89 par = par.replace("__version__", pyx.__version__)
90 par = par.replace("&", "&amp;")
91 par = par.replace("<", "&lt;")
92 par = par.replace(">", "&gt;")
93 par = par.replace("\"", "&quot;")
94 par = self.parmakeline.subn(" ", par)[0]
95 par = self.parmakeinline.subn(r"<code>\1</code>", par)[0]
96 par = self.parmakeitalic.subn(r"<em>\1</em>", par)[0]
97 par = self.parmakebold.subn(r"<strong>\1</strong>", par)[0]
98 if not title:
99 title = par
100 else:
101 bends = 0
102 while par.startswith("!"):
103 if not bend:
104 warnings.warn("ignore bend sign")
105 break
106 bends += 1
107 par = par[1:]
108 output.write("%s<p>%s</p>\n" % (bend*bends, par))
109 else:
110 code = self.codepattern.match(input, pos)
111 if not code:
112 raise RuntimeError("couldn't parse text file")
113 pos = code.end("data")
114 code = code.group("data")
115 indent = self.indentpattern.match(code).group("indent")
116 code = re.subn(r"\s*[\r\n]%s" % indent, "\n", code.strip())[0]
117 output.write("<div class=\"codeindent\">%s</div>\n" % self.fromPython(code + "\n"))
118 text = output.getvalue()
119 shorttext = text.split("...")[0]
120 text = text.replace("...", "", 1)
121 return title, shorttext, text
123 makehtml = MakeHtml()
126 class example:
128 def __init__(self, basename, dir=None):
129 self.basename = basename
130 if dir:
131 name = os.path.join(dir, basename)
132 else:
133 name = basename
134 relname = os.path.join("..", "examples", name)
135 self.filename = "%s.py" % name
136 self.code = makehtml.fromPython(codecs.open("%s.py" % relname, encoding="iso-8859-1").read())
137 self.html = "%s.html" % basename
138 self.png = "%s.png" % basename
139 self.width, self.height = Image.open("%s.png" % relname).size
140 self.thumbpng = "%s_thumb.png" % basename
141 self.thumbwidth, self.thumbheight = Image.open("%s_thumb.png" % relname).size
142 self.downloads = []
143 for suffix in ["py", "dat", "jpg", "eps", "pdf"]:
144 try:
145 filesize = "%.1f KB" % (os.path.getsize("%s.%s" % (relname, suffix)) / 1024.0)
146 except OSError:
147 pass
148 else:
149 self.downloads.append({"filename": "%s.%s" % (basename, suffix),
150 "suffixname": ".%s" % suffix,
151 "filesize": filesize,
152 "iconname": "%s.png" % suffix})
153 if os.path.exists("%s.txt" % relname):
154 self.title, self.shorttext, self.text = makehtml.fromText(codecs.open("%s.txt" % relname, encoding="iso-8859-1").read(), bend="<div class=\"examplebend\"><img src=\"../../bend.png\" width=22 height=31></div>\n")
155 else:
156 self.title = basename
157 self.shorttext = self.text = None
160 class MyPageTemplateFile(PageTemplateFile):
162 def write(self, text):
163 if isinstance(text, str):
164 text = unicode(text, encoding="iso-8859-1")
165 return PageTemplateFile.write(self, text)
168 def mkrellink(linkname, options):
169 # returns a string containing the relative url for linkname (an absolute url)
170 pagename = options["pagename"]
171 while linkname.find("/") != -1 and pagename.find("/") != -1:
172 linknamefirst, linknameother = linkname.split("/", 1)
173 pagenamefirst, pagenameother = pagename.split("/", 1)
174 if linknamefirst == pagenamefirst:
175 linkname = linknameother
176 pagename = pagenameother
177 else:
178 break
179 for i in pagename.split("/")[:-1]:
180 linkname = "../" + linkname
181 return linkname
183 maintemplate = MyPageTemplateFile("maintemplate.pt")
185 latestnews = 2
186 newsdom = xml.dom.minidom.parse("news.pt")
187 news = "".join(["%s%s" % (dt.toxml(), dd.toxml())
188 for dt, dd in zip(newsdom.getElementsByTagName("dt")[:latestnews],
189 newsdom.getElementsByTagName("dd")[:latestnews])])
191 for ptname in glob.glob("*.pt"):
192 if ptname not in ["maintemplate.pt", "exampleindex.pt", "examples.pt", "example.pt"]:
193 htmlname = "%s.html" % ptname[:-3]
194 template = MyPageTemplateFile(ptname)
195 content = template(pagename=htmlname,
196 maintemplate=maintemplate,
197 examplepages=[],
198 mkrellink=mkrellink,
199 version=pyx.__version__,
200 news=news)
201 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
203 exampleindextemplate = MyPageTemplateFile("exampleindex.pt")
204 examplestemplate = MyPageTemplateFile("examples.pt")
205 exampletemplate = MyPageTemplateFile("example.pt")
206 exampledirs = [None]
207 examplepages = []
208 for dir in open("../examples/INDEX").readlines():
209 dir = dir.strip()
210 if dir.endswith("/"):
211 exampledirs.append(dir)
212 dir = dir.rstrip("/")
213 try:
214 title = open("../examples/%s/README" % dir).readline().strip()
215 except:
216 title = dir
217 examplepages.append({"dir": dir, "title": title})
219 prev = None
220 for dirindex, dir in enumerate(exampledirs):
221 srcdir = "../examples"
222 destdir = "examples"
223 try:
224 nextdir = exampledirs[dirindex + 1]
225 nextdir = os.path.join(destdir, nextdir)
226 except IndexError:
227 nextdir = None
228 if dir:
229 srcdir = os.path.join(srcdir, dir)
230 destdir = os.path.join(destdir, dir)
231 try:
232 title, shorttext, text = makehtml.fromText(open(os.path.join(srcdir, "README")).read(),
233 bend="<div class=\"examplebend\"><img src=\"../bend.png\" width=22 height=31></div>\n")
234 except IOError:
235 title = dir
236 text = ""
237 examples = [example(item.strip(), dir)
238 for item in open(os.path.join(srcdir, "INDEX")).readlines()
239 if item[-2] != "/"]
240 htmlname = os.path.join(destdir, "index.html")
241 if dir:
242 template = examplestemplate
243 next = os.path.join(destdir, examples[0].html)
244 else:
245 template = exampleindextemplate
246 next = os.path.join(nextdir, "index.html")
247 content = template(pagename=htmlname,
248 maintemplate=maintemplate,
249 dir=dir,
250 title=title,
251 text=text,
252 examples=examples,
253 examplepages=examplepages,
254 mkrellink=mkrellink,
255 prev=prev,
256 next=next)
257 #print next, htmlname
258 #for line in content.split("\n"):
259 # if line.find("next") != -1:
260 # print line
261 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
262 prev = os.path.join(destdir, "index.html")
263 if dir:
264 for exampleindex, aexample in enumerate(examples):
265 try:
266 next = os.path.join(destdir, examples[exampleindex+1].html)
267 except (TypeError, IndexError):
268 if nextdir:
269 next = os.path.join(nextdir, "index.html")
270 else:
271 next = None
272 htmlname = os.path.join(destdir, "%s.html" % aexample.basename)
273 content = exampletemplate(pagename=htmlname,
274 maintemplate=maintemplate,
275 dir=dir,
276 example=aexample,
277 examplepages=examplepages,
278 mkrellink=mkrellink,
279 prev=prev,
280 next=next)
281 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
282 prev = os.path.join(destdir, aexample.html)