correct the dir of the next example
[PyX/mjg.git] / www / pt2html.py
blob48b0bed9e032cbe8d125dee489e3a8c0cd73ee42
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 parmakebold = re.compile(r"'''(.*?)'''")
76 parmakeitalic = re.compile(r"''(.*?)''")
77 parmakeref = re.compile(r"\[([^]]*)\s([^\s]*)\]")
78 codepattern = re.compile(r"([ \t]*\n)*(?P<data>(([ \t]+[^\n]*)?\n)+)")
79 indentpattern = re.compile(r"([ \t]*\n)*(?P<indent>[ \t]+)")
81 def fromText(self, input, bend=""):
82 title = None
83 pos = 0
84 output = StringIO.StringIO()
85 while not self.emptypattern.match(input, pos):
86 par = self.parpattern.match(input, pos)
87 if par:
88 pos = par.end("data")
89 par = par.group("data").strip()
90 par = par.replace("__version__", pyx.__version__)
91 par = par.replace("&", "&amp;")
92 par = par.replace("<", "&lt;")
93 par = par.replace(">", "&gt;")
94 par = par.replace("\"", "&quot;")
95 par = self.parmakeline.subn(" ", par)[0]
96 par = self.parmakeinline.subn(r"<code>\1</code>", par)[0]
97 par = self.parmakebold.subn(r"<strong>\1</strong>", par)[0]
98 par = self.parmakeitalic.subn(r"<em>\1</em>", par)[0]
99 par = self.parmakeref.subn(r'<a href="\2">\1</a>', par)[0]
100 if not title:
101 title = par
102 else:
103 bends = 0
104 while par.startswith("!"):
105 if not bend:
106 warnings.warn("ignore bend sign")
107 break
108 bends += 1
109 par = par[1:]
110 output.write("%s<p>%s</p>\n" % (bend*bends, par))
111 else:
112 code = self.codepattern.match(input, pos)
113 if not code:
114 raise RuntimeError("couldn't parse text file")
115 pos = code.end("data")
116 code = code.group("data")
117 indent = self.indentpattern.match(code).group("indent")
118 code = re.subn(r"\s*[\r\n]%s" % indent, "\n", code.strip())[0]
119 if len(indent.expandtabs()) >= 4:
120 code = self.fromPython(code + "\n")
121 else:
122 code = "<pre>%s</pre>" % code
123 output.write("<div class=\"codeindent\">%s</div>\n" % code)
124 text = output.getvalue()
125 shorttext = text.split("...")[0]
126 text = text.replace("...", "", 1)
127 return title, shorttext, text
129 makehtml = MakeHtml()
132 class example:
134 def __init__(self, basesrcdir, dir, basename):
135 self.basename = basename
136 if dir:
137 name = os.path.join(dir, basename)
138 else:
139 name = basename
140 relname = os.path.join(basesrcdir, name)
141 self.filename = "%s.py" % name
142 self.code = makehtml.fromPython(codecs.open("%s.py" % relname, encoding="iso-8859-1").read())
143 self.html = "%s.html" % basename
144 self.png = "%s.png" % basename
145 self.width, self.height = Image.open("%s.png" % relname).size
146 self.thumbpng = "%s_thumb.png" % basename
147 self.thumbwidth, self.thumbheight = Image.open("%s_thumb.png" % relname).size
148 self.downloads = []
149 for suffix in ["py", "dat", "jpg", "eps", "pdf"]:
150 try:
151 filesize = "%.1f KB" % (os.path.getsize("%s.%s" % (relname, suffix)) / 1024.0)
152 except OSError:
153 pass
154 else:
155 self.downloads.append({"filename": "%s.%s" % (basename, suffix),
156 "suffixname": ".%s" % suffix,
157 "filesize": filesize,
158 "iconname": "%s.png" % suffix})
159 if os.path.exists("%s.txt" % relname):
160 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")
161 else:
162 self.title = basename
163 self.shorttext = self.text = None
166 class MyPageTemplateFile(PageTemplateFile):
168 def write(self, text):
169 if isinstance(text, str):
170 text = unicode(text, encoding="iso-8859-1")
171 return PageTemplateFile.write(self, text)
174 def mkrellink(linkname, options):
175 # returns a string containing the relative url for linkname (an absolute url)
176 pagename = options["pagename"]
177 while linkname.find("/") != -1 and pagename.find("/") != -1:
178 linknamefirst, linknameother = linkname.split("/", 1)
179 pagenamefirst, pagenameother = pagename.split("/", 1)
180 if linknamefirst == pagenamefirst:
181 linkname = linknameother
182 pagename = pagenameother
183 else:
184 break
185 for i in pagename.split("/")[:-1]:
186 linkname = "../" + linkname
187 return linkname
189 maintemplate = MyPageTemplateFile("maintemplate.pt")
191 latestnews = 2
192 newsdom = xml.dom.minidom.parse("news.pt")
193 news = "".join(["%s%s" % (dt.toxml(), dd.toxml())
194 for dt, dd in zip(newsdom.getElementsByTagName("dt")[:latestnews],
195 newsdom.getElementsByTagName("dd")[:latestnews])])
197 for ptname in glob.glob("*.pt"):
198 if ptname not in ["maintemplate.pt", "exampleindex.pt", "examples.pt", "example.pt"]:
199 htmlname = "%s.html" % ptname[:-3]
200 template = MyPageTemplateFile(ptname)
201 content = template(pagename=htmlname,
202 maintemplate=maintemplate,
203 subtype=None,
204 mkrellink=mkrellink,
205 version=pyx.__version__,
206 news=news)
207 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
210 def processexamples(basedir):
211 exampleindextemplate = MyPageTemplateFile("exampleindex.pt")
212 examplestemplate = MyPageTemplateFile("examples.pt")
213 exampletemplate = MyPageTemplateFile("example.pt")
215 exampledirs = [None]
216 examplepages = []
217 for dir in open(os.path.join("..", basedir, "INDEX")).readlines():
218 dir = dir.strip()
219 if dir.endswith("/"):
220 exampledirs.append(dir)
221 dir = dir.rstrip("/")
222 try:
223 title = open(os.path.join("..", basedir, dir, "README")).readline().strip()
224 except IOError:
225 title = dir
226 examplepages.append({"dir": dir, "title": title})
228 prev = None
229 for dirindex, dir in enumerate(exampledirs):
230 if dir:
231 srcdir = os.path.join("..", basedir, dir)
232 destdir = os.path.join(basedir, dir)
233 bend = "<div class=\"examplebend\"><img src=\"../../bend.png\" width=22 height=31></div>\n"
234 else:
235 srcdir = os.path.join("..", basedir)
236 destdir = basedir
237 bend = "<div class=\"examplebend\"><img src=\"../bend.png\" width=22 height=31></div>\n"
238 try:
239 nextdir = exampledirs[dirindex + 1]
240 nextdir = os.path.join(basedir, nextdir)
241 except IndexError:
242 nextdir = None
243 try:
244 title, shorttext, text = makehtml.fromText(open(os.path.join(srcdir, "README")).read(), bend=bend)
245 except IOError:
246 title = dir
247 text = ""
248 examples = [example(os.path.join("..", basedir), dir, item.strip())
249 for item in open(os.path.join(srcdir, "INDEX")).readlines()
250 if item[-2] != "/"]
251 htmlname = os.path.join(destdir, "index.html")
252 if dir:
253 template = examplestemplate
254 next = os.path.join(destdir, examples[0].html)
255 else:
256 template = exampleindextemplate
257 next = os.path.join(nextdir, "index.html")
258 content = template(pagename=htmlname,
259 maintemplate=maintemplate,
260 dir=dir,
261 title=title,
262 text=text,
263 examples=examples,
264 subtype=basedir,
265 subpages=examplepages,
266 mkrellink=mkrellink,
267 prev=prev,
268 next=next)
269 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
270 prev = os.path.join(destdir, "index.html")
271 if dir:
272 for exampleindex, aexample in enumerate(examples):
273 try:
274 next = os.path.join(destdir, examples[exampleindex+1].html)
275 except (TypeError, IndexError):
276 if nextdir:
277 next = os.path.join(nextdir, "index.html")
278 else:
279 next = None
280 htmlname = os.path.join(destdir, "%s.html" % aexample.basename)
281 content = exampletemplate(pagename=htmlname,
282 maintemplate=maintemplate,
283 dir=dir,
284 example=aexample,
285 subtype=basedir,
286 subpages=examplepages,
287 mkrellink=mkrellink,
288 prev=prev,
289 next=next)
290 codecs.open("build/%s" % htmlname, "w", encoding="iso-8859-1").write(content)
291 prev = os.path.join(destdir, aexample.html)
294 processexamples("examples")
295 processexamples("gallery")