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