2 # -*- coding: utf-8 -*-
14 #sys.stdin = codecs.getreader('utf_8')(sys.stdin)
15 #sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
17 alist = ["a", "a:href", "a:name", "b", "br" ]
20 tag_filter = HTMLTagFilter.HTMLTagFilter(HTMLTagFilter.DENY_ALLOW, alist, dlist)
21 path_to_index = "./_markup_index"
23 class _InputStream(object):
24 """InputStream base class."""
33 """function for iterator"""
37 class Markupper(object):
41 self._input_iter = None
46 def index_add(self, key, val):
48 Add key and value to index.
56 self._index[key] = val
62 return self._index[key]
64 def index_haskey(self, key):
65 return self._index.has_key(key)
67 def markup(self, input_iter, release="0"):
71 @param input_iter: iterator to use as input
72 @type input_iter: iterator
74 self.input_iter = input_iter
75 self._page_counter = 1
76 self._image_border = 0
77 # alist = ["a", "a:href", "a:name", "b", "br" ]
79 # tag_filter = HTMLTagFilter.HTMLTagFilter(HTMLTagFilter.DENY_ALLOW, alist, dlist)
80 self._release = release
82 self.index_add("figs", [])
85 for line in self.input_iter:
86 # line = self._default_markup_rule(line)
88 if re.search(ur"^☆{{{$", line):
91 elif re.search(ur"^☆image_dir:", line):
92 self._image_dir = re.search(ur"^☆image_dir:\s*(.*)$", line).group(1)
94 elif re.search(ur"^☆image_border:\s(on|On|ON)", line):
95 self._image_border = 1
97 elif re.search(ur"^☆comment\s{{{$", line):
100 elif re.search(ur"^☆\*", line):
101 self._anchor = re.sub(ur"^☆\*", "", line).strip()
103 elif re.search(ur"^☆clear\s+", line):
106 elif re.search(ur"^・", line):
109 elif re.search(ur"^[0-9]\.", line):
112 elif re.search(ur"^☆begin-column:", line):
113 self._begin_column(line)
115 elif re.search(ur"^☆end-column", line):
116 self._end_column(line)
118 elif re.search(ur"^☆space", line):
121 elif re.search(ur"^☆call_tables", line):
122 self._call_tables(line)
124 elif re.search(ur"^●", line):
127 elif re.search(ur"^○", line):
130 elif re.search(ur"^◇", line):
133 elif re.search(ur"^☆----", line):
136 elif re.search(ur"^☆\+---", line):
139 elif re.search(ur"^☆表", line):
142 elif re.search(ur"^☆図", line):
145 elif re.search(ur"^☆写真", line):
148 elif re.search(ur"^☆リスト", line):
151 elif re.search(ur"^☆flow", line):
155 if re.search(ur"^ ", line):
156 self._paragraph(line)
160 if re.search(r"^\s*$", line):
168 def _clear(self, line):
169 print """<div style="clear:left;"> </div>
172 def _head_l(self, line):
174 if re.search(ur"\*{[a-zA-Z0-9_]*}\s*$", line):
175 self._anchor = re.search(ur"\*\{([a-zA-Z0-9_]*)\}\s*$", line).group(1)
176 line = re.sub(ur"\s*\*\{[a-zA-Z0-9_]*\}\s*$", "", line)
178 line = self._default_markup_rule(line)
179 if self._anchor != "":
180 line = re.sub(ur"^●(.*)$", ur'<div id="%s"><h3>\1</h3></div>' % self._anchor, line)
183 line = re.sub(ur"^●(.*)$", ur"<h3>\1</h3>", line)
186 def _head_m(self, line):
188 if re.search(ur"\*{[a-zA-Z0-9_]*}\s*$", line):
189 self._anchor = re.search(ur"\*\{([a-zA-Z0-9_]*)\}\s*$", line).group(1)
190 line = re.sub(ur"\s*\*\{[a-zA-Z0-9_]*\}\s*$", "", line)
192 line = self._default_markup_rule(line)
193 if self._anchor != "":
194 line = re.sub(ur"^○(.*)$", ur'<div id="%s"><h4>\1</h4></div>' % self._anchor, line)
197 line = re.sub(ur"^○(.*)$", ur"<h4>\1</h4>", line)
200 def _head_s(self, line):
202 if re.search(ur"\*{[a-zA-Z0-9_]*}\s*$", line):
203 self._anchor = re.search(ur"\*\{([a-zA-Z0-9_]*)\}\s*$", line).group(1)
204 line = re.sub(ur"\s*\*\{[a-zA-Z0-9_]*\}\s*$", "", line)
206 line = self._default_markup_rule(line)
207 if self._anchor != "":
208 line = re.sub(ur"^◇(.*)$", ur'<div id="%s"><h5>\1</h5></div>' % self._anchor, line)
211 line = re.sub(ur"^◇(.*)$", ur"<h5>\1</h5>", line)
214 def _paragraph(self, line):
215 line = self._default_markup_rule(line)
216 line = "<p>" + line + "</p>"
219 def _newpage(self, line):
220 line = re.sub(ur"☆----.*-{0,1}", u"<hr>", line)
223 def load_index(self, path_to_index):
227 @param path_to_index: index db's path
228 @type path_to_index: string
232 index_file = open(path_to_index, "r")
233 self._index_past = pickle.load(index_file)
236 sys.stderr.write("warn: cannot read index file,\n")
238 def save_index(self, path_to_index):
242 @param path_to_index: index db's path
243 @type path_to_index: string
247 index_file = open(path_to_index, "w")
248 pickle.dump(self._index, index_file)
251 sys.stderr.write("warn: cannot write index file,\n")
253 def make_hashlist(self, path_to_hashfile):
257 @param path_to_hashfile: hashfile's path
258 @type path_to_hashfile: string
261 file_img_hash = open(path_to_hashfile, "r")
263 sys.stderr.write("cannot open file: %s" % path_img_hash)
267 for line in file_img_hash:
268 splited = line.strip().split("\t", 2)
269 # hashlist's format: <hash> \t <filename>
270 self.hashlist[splited[1]] = splited[0]
272 def _call_tagles(self):
275 def _escape(self, line):
276 line = re.sub(ur"&", ur"&", line)
277 line = re.sub(ur"<", ur"<", line)
278 line = re.sub(ur">", ur">", line)
281 def _default_markup_rule(self, line):
283 apply default markup rules.
285 @param line: string to apply markup
288 line = self._escape(line)
291 # line = tag_filter.apply(line)
293 line = re.sub(ur"[★*](動画[0-9〜~、]+)", ur"<b>\1</b>", line)
294 line = re.sub(ur"[★*](表[0-9〜~、]+)", ur"<b>\1</b>", line)
295 line = re.sub(ur"[★*](図[0-9〜~、]+)", ur"<b>\1</b>", line)
296 line = re.sub(ur"[★*](写真[0-9〜~、]+)", ur"<b>\1</b>", line)
297 line = re.sub(ur"[★*](リスト[0-9~〜、]+)", ur"<b>\1</b>", line)
298 line = re.sub(ur"[★*](コラム[0-9〜~、]+)", ur"<b>\1</b>", line)
299 line = re.sub(ur"[★*]b\[(.*?)\]", ur"<b>\1</b>", line)
300 line = re.sub(ur"[★*]b\{(.*?)\}", ur"<b>\1</b>", line)
301 line = re.sub(ur"[★*]g\[(.*?)]", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
302 line = re.sub(ur"[★*]g{(.*?)}", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
303 line = re.sub(ur"[★*]\[(\S*) (.*?)\]", r'<a href="\1">\2</a>', line)
304 line = re.sub(ur"[★*]\[(\S*)\]", r'<a href="\1">\1</a>', line)
307 if re.search(ur"^☆#", line):
313 def _ulist(self, line):
316 while re.search(ur"^・", line):
317 line = self._default_markup_rule(line)
318 print re.sub(ur"^・(.*)$", ur"<li>\1</li>", line.strip())
319 line = self.input_iter.next()
322 def _olist(self, line):
325 while re.search(ur"^[0-9]+\.", line):
326 line = self._default_markup_rule(line)
327 print re.sub(ur"^[0-9]+\.(.*)$", ur"<li>\1</li>", line.strip())
328 line = self.input_iter.next()
333 def _begin_column(self, line):
334 """Proccess column"""
336 str_title = re.search(ur"^☆begin-column:(.*)$", line).group(1)
337 except AttributeError:
341 <div class="column" style="background:#DDDDDD;font-size:85%%;padding:8px;">
346 def _end_column(self, line):
351 def _list_start(self):
357 def _list(self, line):
359 str_title = re.search(ur"^☆(リスト.*)$", line).group(1)
360 except AttributeError:
362 print "<p class='caption'><b>%s</b></p>" % (str_title)
363 print self._list_start()
365 for line in self.input_iter:
366 line = line.strip("\n\r")
367 line = self._escape(line)
368 line = re.sub(ur"[★*]b\[(.*?)]", ur"<b>\1</b>", line)
369 line = re.sub(ur"[★*]b{(.*?)}", ur"<b>\1</b>", line)
370 line = re.sub(ur"[★*]g\[(.*?)]", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
371 line = re.sub(ur"[★*]g{(.*?)}", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
372 if re.search(ur"""^☆\+---""", line):
375 print self._list_end()
377 def _code(self, line):
378 print self._list_start()
380 for line in self.input_iter:
381 line = self._escape(line)
382 line = re.sub(ur"[★*]b\[(.*?)]", ur"<b>\1</b>", line)
383 line = re.sub(ur"[★*]b{(.*?)}", ur"<b>\1</b>", line)
384 line = re.sub(ur"[★*]g\[(.*?)]", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
385 line = re.sub(ur"[★*]g{(.*?)}", ur"<span style='color:#F55;font-weight:bold;'>\1</span>", line)
387 if re.search(ur"^☆\+---$", line):
390 print self._list_end()
392 def _inline(self, line):
393 for line in self.input_iter:
395 if re.search(ur"^☆}}}", line):
399 def _comment(self, line):
400 for line in self.input_iter:
402 if re.search(ur"^☆}}}", line):
405 def _space(self, line):
408 def _flow(self, line):
409 down_arrow = "http://static.sourceforge.jp/crystal/22x22/actions/1downarrow.png"
410 flow_header = """<div style="text-align:center; border: 1px solid; background-color:#EFF2F0; width:90%; margin: 0 auto 1em;">
412 flow_title = """<div style="text-align:left; padding:4px 4px 4px 1em; margin-bottom: 1em; border-bottom: 1px solid; font-weight: bold; background-color:#BCD;">
415 flow_footer = """</div>
423 arrow = '<div style="margin:1em auto;"><img src="%s"></div>\n' % (down_arrow,)
425 rex_title = re.compile(ur"^☆flow\s+(.*)$")
426 if rex_title.search(line):
427 title = rex_title.search(line).group(1)
431 rex_file = re.compile(ur"^([^:]*):(.*)$")
433 for line in self.input_iter:
434 if re.search(r"^\s*$", line):
436 match = rex_file.search(line)
438 file = os.path.join(self._image_dir, match.group(1))
439 cap = self._default_markup_rule(match.group(2))
442 fig = self._anchored_fig(file, cap)
443 outputs.append(flow_item % (fig, cap))
446 print flow_title % (title,)
447 print arrow.join(outputs)
451 def _fig_start(self, cap="", styles=[], width=0, height=0):
452 params = dict(style="", tablewidth="")
454 params["style"] = "width:%d;" % (width,)
455 params["tablewidth"] = 'width="%d"' % (width,)
457 if "lfloat" in styles:
458 return """<table %(tablewidth)s align="center" border="0" cellpadding="0" cellspacing="0" style="float:left; padding-left: 0.5em; %(style)s">
459 <tr> <td valign="top" align="center">
461 elif "left" in styles:
462 return """<table %(tablewidth)s border="0" cellpadding="0" cellspacing="0" style="padding-left: 0.5em; %(style)s">
463 <tr> <td valign="top" align="center">
466 return """<table %(tablewidth)s align="center" border="0" cellpadding="0" cellspacing="0">
467 <tr> <td valign="top" align="center">
470 def _fig_end(self, cap="", styles=[]):
471 return """</td> </tr>
472 <tr> <td><span style="font-size: 80%%; font-weight: bold;">
478 def _get_png_geom(self, filepath):
479 s = filepath.split('.')
481 if (ext == 'JPG') or (ext == 'jpg'):
482 (w, h) = getjpggeom.get_jpeg_geometory(filepath)
485 desc = deterfile.file(filepath)
488 m = re.match(r"([0-9]+)\s*x\s*([0-9]+)", desc[1])
490 err = ", ".join(desc)
491 raise Exception("deterfile error: %s, file: %s . " % (err,filepath))
495 return (int(w), int(h))
499 def _fig(self, line):
501 str_title = re.search(ur"^☆(図.*)$", line).group(1)
502 except AttributeError:
504 if str_title.find(u"図*") == 0:
505 str_title = str_title.replace(u"図*", "")
506 line = self.input_iter.next()
508 if line.find("@") == 0:
509 styles = line.strip().replace("@", "").split(",")
510 line = self.input_iter.next()
516 match_o1 = re.search(ur"<([^,]*?)>", line)
517 match_o2 = re.search(ur"<(.*?),\s*(.*?)>", line)
518 if not match_o1 == None:
519 imgname = match_o1.group(1)
520 imgname = os.path.join(self._image_dir, imgname)
521 imgname_s = re.sub(r"(.[A-Za-z0-9_]+)$", r"_s\1", imgname)
522 elif not match_o2 == None:
523 imgname = match_o2.group(1)
524 imgname = os.path.join(self._image_dir, imgname)
525 imgname_s = match_o2.group(2)
526 imgname_s = os.path.join(self._image_dir, imgname_s)
529 geom = self._get_png_geom(imgname_s)
531 sys.stderr.write(str(e) + "\nline: " + line.encode("utf-8"))
537 print self._fig_start("", styles, width=w, height=h)
539 print self._fig_start("", styles)
540 print self._anchored_fig(imgname, str_title, imgname_s)
541 print self._fig_end(str_title, styles);
543 dic = self.index("figs")
546 dic.append(imgname_s)
548 def _photo(self, line):
550 str_title = re.search(ur"^☆(写真.*)$", line).group(1)
551 except AttributeError:
553 if str_title.find(u"写真*") == 0:
554 str_title = str_title.replace(u"写真*", "")
555 line = self.input_iter.next()
557 if line.find("@") == 0:
558 styles = line.strip().replace("@", "").split(",")
559 line = self.input_iter.next()
565 match_o1 = re.search(ur"<([^,]*?)>", line)
566 match_o2 = re.search(ur"<(.*?),\s*(.*?)>", line)
567 if not match_o1 == None:
568 imgname = match_o1.group(1)
569 imgname = os.path.join(self._image_dir, imgname)
570 imgname_s = re.sub(r"(.[A-Za-z0-9_]+)$", r"_s\1", imgname)
571 elif not match_o2 == None:
572 imgname = match_o2.group(1)
573 imgname = os.path.join(self._image_dir, imgname)
574 imgname_s = match_o2.group(2)
575 imgname_s = os.path.join(self._image_dir, imgname_s)
577 geom = self._get_png_geom(imgname_s)
581 print self._fig_start("", styles, width=w, height=h)
583 print self._fig_start("", styles)
584 print self._anchored_fig(imgname, str_title, imgname_s)
585 print self._fig_end(str_title, styles);
587 dic = self.index("figs")
590 dic.append(imgname_s)
593 def _anchored_fig(self, file, alt, file_s=""):
596 file_s = re.sub(r"(.[A-Za-z0-9_]+)$", r"_s\1", file)
598 if not os.path.isfile(file_s):
601 alt = re.sub(r"""<[A-Za-z0-9!/]+.*?>""", "", alt)
603 ret = """<a href="%s">
604 <img src="%s" alt="%s">
606 """ % (file, file_s, alt)
612 def _fig_release(self, line):
614 str_title = re.search(ur"^☆(図.*)$", line).group(1)
615 except AttributeError:
617 print self._fig_start()
619 line = self.input_iter.next()
624 match_o1 = re.search(ur"<([^,]*?)>", line)
625 match_o2 = re.search(ur"<(.*?),\s*(.*?)>", line)
626 if not match_o1 == None:
627 imgname = match_o1.group(1)
628 imgname_s = re.sub(r"(.[A-Za-z0-9_]+)$", r"_s\1", match_o1.group(1))
629 elif not match_o2 == None:
630 imgname = match_o1.group(1)
631 imgname_s = match_o1.group(2)
634 hash = self.hashlist.get(imgname, "")
635 hash_s = self.hashlist.get(imgname_s, "")
639 print """<a href="/blob.pl?id=%s">
640 <slash type="image" id="%s" title="%s">
642 """ % (hash, hash_s, str_title)
645 dic = self.index("figs")
648 dic.append(imgname_s)
650 print self._fig_end(str_title);
653 def _table_start(self, cap):
654 return """<div style="width:90%%; margin-left:auto;margin-right:auto;"><table align="center" border="1" class="table" width="100%%">
655 <caption><b>%s</b></caption>
658 def _table_end(self, footnote=""):
659 return "</table>\n%s</div>\n" % (footnote,)
661 def _table(self, line):
663 self._table_buf1 = ""
666 str_title = re.search(ur"^☆(表.*)$", line).group(1)
667 fig_name = re.search(ur"^☆(表[0-9A-Z]*)", line).group(1)
668 except AttributeError:
671 if str_title.find(u"表*") == 0:
672 str_title = str_title.replace(u"表*", "")
674 print self._table_start(str_title)
675 self._table_buf1 = self._table_start(str_title)
680 for line in self.input_iter:
681 line = line.strip(" \n")
682 line = self._default_markup_rule(line)
683 if re.search(ur"^\s*$", line):
685 if re.search(ur"^※", line):
686 footnote = re.search(ur"^(※.*)$", line).group(1)
688 if re.search(ur"^〓", line):
689 line = re.sub(ur"^〓", "", line)
693 table_contents.append([])
695 for item in line.split("\t"):
700 while table_contents[num_row-n][num_col]["item"] == "":
702 table_contents[num_row-n][num_col]["row"] += 1
708 while table_contents[num_row][num_col-n]["item"] == "":
710 table_contents[num_row][num_col-n]["col"] += 1
716 while table_contents[num_row-n][num_col]["item"] == "":
718 table_contents[num_row-n][num_col]["row"] += 1
723 if re.search(r'^".*"$', item):
724 item = re.search(r'^"(.*)"$', item).group(1)
725 table_contents[num_row].append({"tag":"th","item":item,"row":1,"col":1})
727 table_contents[num_row].append({"tag":tag_mode,"item":item,"row":1,"col":1})
728 num_col = num_col + 1
729 num_row = num_row + 1
731 for row_item in table_contents:
733 for item in row_item:
734 if item["item"] == "":
736 line = line + "<" + item["tag"]
737 if not item["row"] == 1:
738 line = line + (' rowspan="%s"' % item["row"])
739 if not item["col"] == 1:
740 line = line + (' colspan="%s"' % item["col"])
742 line = line + item["item"]
743 line = line + "</" + item["tag"] + ">"
744 line = line + "</tr>\n"
746 self._table_buf1 = self._table_buf1 + line
748 # line = "<tr><th>" + re.sub(ur"^〓", "", line) + "</th></tr>"
749 # line = line.replace("\t", "</th><th>")
752 # line = "<tr><td>" + line + "</td></tr>"
753 # line = line.replace("\t", "</td><td>")
756 print self._table_end(footnote)
757 self._table_buf1 = self._table_buf1 + self._table_end()
758 if self.index_haskey("tables"):
759 self.index("tables")[fig_name] = self._table_buf1
761 self.index_add("tables", {fig_name:self._table_buf1})
763 def _call_tables(self, line):
765 fig_name = re.search(ur"^☆call_tables\((表[0-9A-Z]+)", line).group(1)
766 except AttributeError:
768 print self.index("tables")[fig_name]