1 """
2 MoinMoin - MoinMoin Wiki Markup Parser
3
4 Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
5 All rights reserved, see COPYING for details.
6
7 $Id: FabianFranz_2fwiki_2epy,v 1.1 2002/06/19 01:43:05 linuxwiki Exp $
8 """
9
10
11 import cgi, os, re, sys
12 from MoinMoin import config, user, wikimacro, wikiutil, util
13 from MoinMoin.Page import Page
14 from MoinMoin.i18n import _
15
16
17
18
19
20
21 class Parser:
22 """
23 Object that turns Wiki markup into HTML.
24
25 All formatting commands can be parsed one line at a time, though
26 some state is carried over between lines.
27
28 Methods named like _*_repl() are responsible to handle the named regex
29 patterns defined in print_html().
30 """
31
32
33
34
35
36 mybuffer = [""]
37
38 attachment_schemas = ["attachment", "inline", "drawing"]
39 punct_pattern = re.escape('''"'}]|:,.)?!''')
40 url_pattern = ('http|https|ftp|nntp|news|mailto|telnet|wiki|file|' +
41 '|'.join(attachment_schemas) +
42 (config.url_schemas and '|' + '|'.join(config.url_schemas) or ''))
43
44
45 word_rule = r'(?:%(subpages)s(?:[%(u)s][%(l)s]+){2,})+' % {
46 'u': config.upperletters,
47 'l': config.lowerletters,
48 'subpages': config.allow_subpages and '/?' or '',
49 }
50 url_rule = r'%(url_guard)s(%(url)s)\:([^\s\<%(punct)s]|([%(punct)s][^\s\<%(punct)s]))+' % {
51 'url_guard': ('(^|(?<!\w))', '')[sys.version < "2"],
52 'url': url_pattern,
53 'punct': punct_pattern,
54 }
55
56 ol_rule = r"^\s+(?:[0-9]+|[aAiI])\.(?:#\d+)?\s"
57 dl_rule = r"^\s+.*?::\s"
58
59
60 formatting_rules = r"""(?:(?P<emph_ibb>'''''(?=[^']+'''))
61 (?P<emph_ibi>'''''(?=[^']+''))
62 (?P<emph_ib_or_bi>'{5}(?=[^']))
63 (?P<emph>'{2,3})
64 (?P<sup>\^.*?\^)
65 (?P<tt>\{\{\{.*?\}\}\})
66 (?P<processor>(\{\{\{#!.*))
67 (?P<pre>(\{\{\{ ?|\}\}\}))
68 (?P<rule>-{4,})
69 (?P<comment>^\#\#.*$)
70 (?P<macro>\[\[(%(macronames)s)(?:\(.*?\))?\]\]))
71 (?P<li>^\s+\*)
72 (?P<ol>%(ol_rule)s)
73 (?P<dl>%(dl_rule)s)
74 (?P<tableZ>\|\| $)
75 (?P<table>(?:\|\|)+(?:<[^>]*?>)?(?=.))
76 (?P<heading>^\s*(?P<hmarker>=+)\s.*\s(?P=hmarker) $)
77 (?P<interwiki>[A-Z][a-zA-Z]+\:[^\s'\"\:\<]([^\s%(punct)s]|([%(punct)s][^\s%(punct)s]))+)
78 (?P<word>%(word_rule)s)
79 (?P<url_bracket>\[((%(url)s)\:|#)[^\s\]]+(\s[^\]]+)?\])
80 (?P<url>%(url_rule)s)
81 (?P<email>[-\w._+]+\@[\w-]+\.[\w.-]+)
82 (?P<smiley>\s(%(smiley)s)\s)
83 (?P<smileyA>^(%(smiley)s)\s)
84 (?P<ent>[<>&])""" % {
85 'url': url_pattern,
86 'punct': punct_pattern,
87 'macronames': '|'.join(wikimacro.names),
88 'ol_rule': ol_rule,
89 'dl_rule': dl_rule,
90 'url_rule': url_rule,
91 'word_rule': word_rule,
92 'smiley': '|'.join(map(re.escape, wikiutil.smileys.keys()))}
93
94 def __init__(self, raw, request, **kw):
95 self.raw = raw
96 self.request = request
97
98 self.macro = None
99
100 self.is_em = 0
101 self.is_b = 0
102 self.lineno = 0
103 self.in_li = 0
104 self.in_dd = 0
105 self.in_pre = 0
106 self.in_table = 0
107
108
109 self.list_indents = []
110 self.list_types = []
111
112
113
114 def mywrite(self, line):
115 self.mybuffer.append(line)
116
117
118 def myflush(self):
119 sys.stdout.write(''.join(self.mybuffer))
120 self.mybuffer=[""]
121
122 def myread(self):
123 return ''.join(self.mybuffer)
124
125 def _check_p(self):
126 if not (self.formatter.in_p or self.in_pre):
127 self.mywrite(self.formatter.paragraph(1))
128
129
130 def _close_item(self, result):
131 if self.formatter.in_p:
132 result.append(self.formatter.paragraph(0))
133 if self.in_li:
134 self.in_li = 0
135 result.append(self.formatter.listitem(0))
136 if self.in_dd:
137 self.in_dd = 0
138 result.append(self.formatter.definition_desc(0))
139
140
141 def interwiki(self, url_and_text, **kw):
142 self._check_p()
143
144 if len(url_and_text) == 1:
145 url = url_and_text[0]
146 text = None
147 else:
148 url, text = url_and_text
149
150 url = url[5:]
151 if text is None:
152 tag, tail = wikiutil.split_wiki(url)
153 if tag:
154 text = tail
155 else:
156 text = url
157 url = ""
158 elif config.allow_subpages and url[0] == '/':
159
160 return self._word_repl(url, text)
161 elif Page(url).exists():
162
163 return self._word_repl(url, text)
164
165 import urllib
166 wikitag, wikiurl, wikitail = wikiutil.resolve_wiki(url)
167 wikiurl = wikiutil.mapURL(wikiurl)
168 href = wikiutil.join_wiki(wikiurl, wikitail)
169
170
171 if not kw.get('pretty_url') and wikiutil.isPicture(wikitail):
172 return self.formatter.image(border=0, src=href)
173
174
175 if wikitag is None:
176 return self._word_repl(wikitail)
177
178
179 prefix = config.url_prefix
180 badwiki = wikitag == "BadWikiTag"
181 text = self.highlight_text(text)
182
183 icon = ''
184 if self.request.user.show_fancy_links:
185 icon = self.formatter.image(width=16, height=16, hspace=2,
186 border=badwiki,
187 src=prefix+"/img/moin-inter.gif",
188 alt="[%s]" % wikitag)
189 return self.formatter.url(href, icon + text,
190 title=wikitag, unescaped=1, pretty_url=kw.get('pretty_url', 0))
191
192
193 def attachment(self, url_and_text, **kw):
194 """ This gets called on attachment URLs.
195 """
196 self._check_p()
197
198 if len(url_and_text) == 1:
199 url = url_and_text[0]
200 text = None
201 else:
202 url, text = url_and_text
203
204 inline = url[0] == 'i'
205 drawing = url[0] == 'd'
206 url = url.split(":", 1)[1]
207 text = text or url
208
209 pagename = self.formatter.page.page_name
210 parts = url.split('/')
211 if len(parts) > 1:
212
213 pagename = '/'.join(parts[:-1])
214 url = parts[-1]
215
216 import urllib
217 from MoinMoin.action import AttachFile
218 fname = wikiutil.taintfilename(url)
219 if drawing:
220 drawing = fname
221 fname += ".gif"
222 url += ".gif"
223 fpath = os.path.join(AttachFile.getAttachDir(pagename), fname)
224
225
226 if not os.path.exists(fpath):
227 if drawing:
228 linktext = _('Create new drawing "%(filename)s"')
229 else:
230 linktext = _('Upload new attachment "%(filename)s"')
231 return wikiutil.link_tag(
232 '%s?action=AttachFile&rename=%s%s' % (
233 wikiutil.quoteWikiname(pagename),
234 urllib.quote_plus(fname),
235 drawing and ('&drawing=%s' % urllib.quote(drawing)) or ''),
236 linktext % {'filename': fname})
237
238
239
240 if not kw.get('pretty_url') and wikiutil.isPicture(url):
241 return self.formatter.image(border=0, alt=url,
242 src=AttachFile.getAttachUrl(pagename, url, addts=1))
243
244
245
246 base, ext = os.path.splitext(url)
247 if inline and ext in ['.py']:
248 if ext == '.py':
249 import cStringIO
250 from MoinMoin.parser import python
251
252 buff = cStringIO.StringIO()
253 colorizer = python.Parser(open(fpath, 'r').read(), self.request, out = buff)
254 colorizer.format(self.formatter, self.form)
255 return self.formatter.preformatted(1) + \
256 self.formatter.rawHTML(buff.getvalue()) + \
257 self.formatter.preformatted(0)
258
259 return self.formatter.url(
260 AttachFile.getAttachUrl(pagename, url),
261 text, pretty_url=kw.get('pretty_url', 0))
262
263
264 def _emph_repl(self, word):
265 """Handle emphasis, i.e. '' and '''."""
266 self._check_p()
267
268 if len(word) == 3:
269 self.is_b = not self.is_b
270 if self.is_em and self.is_b: self.is_b = 2
271 return self.formatter.strong(self.is_b)
272 else:
273 self.is_em = not self.is_em
274 if self.is_em and self.is_b: self.is_em = 2
275 return self.formatter.emphasis(self.is_em)
276
277 def _emph_ibb_repl(self, word):
278 """Handle mixed emphasis, i.e. ''''' followed by '''."""
279 self._check_p()
280 self.is_b = not self.is_b
281 self.is_em = not self.is_em
282 if self.is_em and self.is_b: self.is_b = 2
283 return self.formatter.emphasis(self.is_em) + self.formatter.strong(self.is_b)
284
285 def _emph_ibi_repl(self, word):
286 """Handle mixed emphasis, i.e. ''''' followed by ''."""
287 self._check_p()
288 self.is_b = not self.is_b
289 self.is_em = not self.is_em
290 if self.is_em and self.is_b: self.is_em = 2
291 return self.formatter.strong(self.is_b) + self.formatter.emphasis(self.is_em)
292
293 def _emph_ib_or_bi_repl(self, word):
294 """Handle mixed emphasis, exactly five '''''."""
295 self._check_p()
296
297 b_before_em = self.is_b > self.is_em > 0
298 self.is_b = not self.is_b
299 self.is_em = not self.is_em
300 if b_before_em:
301 return self.formatter.strong(self.is_b) + self.formatter.emphasis(self.is_em)
302 else:
303 return self.formatter.emphasis(self.is_em) + self.formatter.strong(self.is_b)
304
305
306 def _sup_repl(self, word):
307 """Handle superscript."""
308 self._check_p()
309 return self.formatter.sup(1) + \
310 self.highlight_text(word[1:-1]) + \
311 self.formatter.sup(0)
312
313
314 def _rule_repl(self, word):
315 """Handle sequences of dashes."""
316 result = self._undent()
317 if len(word) <= 4:
318 result += self.formatter.rule()
319 else:
320 result += self.formatter.rule(min(len(word), 10) - 2)
321 return result
322
323
324 def _word_repl(self, word, text=None):
325 """Handle WikiNames."""
326 self._check_p()
327 if not text: text = word
328 if config.allow_subpages and word[0] == '/':
329 word = self.formatter.page.page_name + word
330 text = self.highlight_text(text)
331 if word == text:
332 return self.formatter.pagelink(word)
333 else:
334 return self.formatter.pagelink(word, text)
335
336 def _notword_repl(self, word):
337 """Handle !NotWikiNames."""
338 self._check_p()
339 return self.highlight_text(word[1:])
340
341
342 def _interwiki_repl(self, word):
343 """Handle InterWiki links."""
344 self._check_p()
345 return self.interwiki(["wiki:" + word])
346
347
348 def _url_repl(self, word):
349 """Handle literal URLs including inline images."""
350 self._check_p()
351 scheme = word.split(":", 1)[0]
352
353 if scheme == "wiki": return self.interwiki([word])
354 if scheme in self.attachment_schemas:
355 return self.attachment([word])
356
357 return self.formatter.url(word, text=self.highlight_text(word))
358
359
360 def _wikiname_bracket_repl(self, word):
361 """Handle special-char wikinames."""
362 return self._word_repl(word[2:-2])
363
364
365 def _url_bracket_repl(self, word):
366 """Handle bracketed URLs."""
367 self._check_p()
368 words = word[1:-1].split(None, 1)
369 if len(words) == 1: words = words * 2
370
371 if words[0][0] == '#':
372
373 return self.formatter.url(words[0], self.highlight_text(words[1]))
374
375 scheme = words[0].split(":", 1)[0]
376 if scheme == "wiki": return self.interwiki(words, pretty_url=1)
377 if scheme in self.attachment_schemas:
378 return self.attachment(words, pretty_url=1)
379
380 icon = ("www", 11, 11)
381 if scheme == "mailto": icon = ("email", 14, 10)
382 if scheme == "news": icon = ("news", 10, 11)
383 if scheme == "telnet": icon = ("telnet", 10, 11)
384 if scheme == "ftp": icon = ("ftp", 11, 11)
385 if scheme == "file": icon = ("ftp", 11, 11)
386
387
388
389 text = ''
390 if self.request.user.show_fancy_links:
391 text += self.formatter.image(
392 src="%s/img/moin-%s.gif" % (config.url_prefix, icon[0]),
393 width=icon[1], height=icon[2], border=0, hspace=4,
394 alt="[%s]" % icon[0].upper()
395 )
396 text += self.highlight_text(words[1])
397 return self.formatter.url(words[0], text, 'external', pretty_url=1, unescaped=1)
398
399
400 def _email_repl(self, word):
401 """Handle email addresses (without a leading mailto:)."""
402 self._check_p()
403 return self.formatter.url("mailto:" + word, self.highlight_text(word))
404
405
406 def _ent_repl(self, word):
407 """Handle SGML entities."""
408 self._check_p()
409 return self.formatter.text(word)
410
411
412
413
414
415 def _ent_numeric_repl(self, word):
416 """Handle numeric SGML entities."""
417 self._check_p()
418 return self.formatter.rawHTML(word)
419
420
421 def _li_repl(self, match):
422 """Handle bullet lists."""
423 result = []
424 self._close_item(result)
425 self.in_li = 1
426 result.append(self.formatter.listitem(1))
427 result.append(self.formatter.paragraph(1))
428 return ''.join(result)
429
430
431 def _ol_repl(self, match):
432 """Handle numbered lists."""
433 return self._li_repl(match)
434
435
436 def _dl_repl(self, match):
437 """Handle definition lists."""
438 result = []
439 self._close_item(result)
440 self.in_dd = 1
441 result.extend([
442 self.formatter.definition_term(1),
443 match[:-3],
444 self.formatter.definition_term(0),
445 self.formatter.definition_desc(1)
446 ])
447 return ''.join(result)
448
449
450 def _tt_repl(self, word):
451 """Handle inline code."""
452 self._check_p()
453 return self.formatter.code(1) + \
454 self.highlight_text(word[3:-3]) + \
455 self.formatter.code(0)
456
457
458 def _tt_bt_repl(self, word):
459 """Handle backticked inline code."""
460 if len(word) == 2: return ""
461 self._check_p()
462 return self.formatter.code(1) + \
463 self.highlight_text(word[1:-1]) + \
464 self.formatter.code(0)
465
466
467 def _getTableAttrs(self, attrdef):
468
469 while attrdef and attrdef[0] == "|":
470 attrdef = attrdef[1:]
471 if not attrdef or attrdef[0] != "<":
472 return {}, ''
473 attrdef = attrdef[1:]
474
475
476 def table_extension(key, parser, attrs):
477 msg = ''
478 if key[0].isdigit():
479 token = parser.get_token()
480 if token != '%':
481 wanted = '%'
482 msg = _('Expected "%(wanted)s" after "%(key)s", got "%(token)s"') % locals()
483 else:
484 try:
485 dummy = int(key)
486 except ValueError:
487 msg = _('Expected an integer "%(key)s" before "%(token)s"') % locals()
488 else:
489 attrs['width'] = '"%s"' % key
490 elif key == '-':
491 arg = parser.get_token()
492 try:
493 dummy = int(arg)
494 except ValueError:
495 msg = _('Expected an integer "%(arg)s" after "%(key)s"') % locals()
496 else:
497 attrs['colspan'] = '"%s"' % arg
498 elif key == '|':
499 arg = parser.get_token()
500 try:
501 dummy = int(arg)
502 except ValueError:
503 msg = _('Expected an integer "%(arg)s" after "%(key)s"') % locals()
504 else:
505 attrs['rowspan'] = '"%s"' % arg
506 elif key == '(':
507 attrs['align'] = '"left"'
508 elif key == ':':
509 attrs['align'] = '"center"'
510 elif key == ')':
511 attrs['align'] = '"right"'
512 elif key == '^':
513 attrs['valign'] = '"top"'
514 elif key == 'v':
515 attrs['valign'] = '"bottom"'
516 elif key == '#':
517 arg = parser.get_token()
518 try:
519 if len(arg) != 6: raise ValueError
520 dummy = int(arg, 16)
521 except ValueError:
522 msg = _('Expected a color value "%(arg)s" after "%(key)s"' % locals())
523 else:
524 attrs['bgcolor'] = '"%s"' % arg
525 else:
526 msg = None
527 return msg
528
529
530 attr, msg = wikiutil.parseAttributes(attrdef, '>', table_extension)
531 if msg: msg = '<strong class="highlight">%s</strong>' % msg
532 return attr, msg
533
534 def _tableZ_repl(self, word):
535 """Handle table row end."""
536 if self.in_table:
537 return self.formatter.table_cell(0) + self.formatter.table_row(0)
538 else:
539 return word
540
541
542 def _table_repl(self, word):
543 """Handle table cell separator."""
544 if self.in_table:
545
546 attrs, attrerr = self._getTableAttrs(word)
547
548
549 if self.table_rowstart:
550 self.table_rowstart = 0
551 leader = self.formatter.table_row(1, attrs)
552 else:
553 leader = self.formatter.table_cell(0)
554
555
556 if word.count("|") > 2:
557 if 'align' not in attrs:
558 attrs['align'] = '"center"'
559 if 'colspan' not in attrs:
560 attrs['colspan'] = '"%d"' % (word.count("|")/2)
561
562
563 return leader + self.formatter.table_cell(1, attrs) + attrerr
564 else:
565 return word
566
567
568 def _heading_repl(self, word):
569 """Handle section headings."""
570 import sha
571
572 icons = ''
573 if self.request.user.show_topbottom:
574 bottom = self.formatter.image(width=14, height=10, hspace=2, vspace=6, align="right",
575 border=0, src=config.url_prefix+"/img/moin-bottom.gif", alt="[BOTTOM]")
576 icons += self.formatter.url("#bottom", bottom, unescaped=1)
577 top = self.formatter.image(width=14, height=10, hspace=2, vspace=6, align="right",
578 border=0, src=config.url_prefix+"/img/moin-top.gif", alt="[TOP]")
579 icons += self.formatter.url("#top", top, unescaped=1)
580
581 h = word.strip()
582 level = 1
583 while h[level] == '=': level += 1
584 depth = min(5,level)
585 headline = h[level:-level].strip()
586 return \
587 self.formatter.anchordef("head-"+sha.new(headline).hexdigest()) + \
588 self.formatter.heading(depth, self.highlight_text(headline, flow=0), icons=icons)
589
590
591 def _processor_repl(self, word):
592 """Handle processed code displays."""
593 if word[:3] == '{{{': word = word[3:]
594
595 from MoinMoin.processor import processors
596 self.processor = None
597 processor_name = word[2:].split()[0]
598 if processor_name in processors:
599 self.processor = util.importName("MoinMoin.processor." +
600 processor_name, "process")
601
602 if self.processor:
603 self.in_pre = 2
604 self.colorize_lines = [word]
605 return ''
606 else:
607 self._check_p()
608 self.in_pre = 1
609 return self.formatter.preformatted(self.in_pre) + \
610 self.formatter.text(word)
611
612
613 def _pre_repl(self, word):
614 """Handle code displays."""
615 word = word.strip()
616 if word == '{{{' and not self.in_pre:
617 self._check_p()
618 self.in_pre = 1
619 return self.formatter.preformatted(self.in_pre)
620 elif word == '}}}' and self.in_pre:
621 self.in_pre = 0
622 return self.formatter.preformatted(self.in_pre)
623
624 return word
625
626
627 def _smiley_repl(self, word):
628 """Handle smileys."""
629 self._check_p()
630 return wikiutil.getSmiley(word, self.formatter)
631
632 _smileyA_repl = _smiley_repl
633
634
635 def _comment_repl(self, word):
636 return ''
637
638
639 def _macro_repl(self, word):
640 """Handle macros ([[macroname]])."""
641 self._check_p()
642 macro_name = word[2:-2]
643
644
645 args = None
646 if macro_name.count("("):
647 macro_name, args = macro_name.split('(', 1)
648 args = args[:-1]
649
650
651 if self.macro is None:
652 self.macro = wikimacro.Macro(self)
653
654
655 return self.macro.execute(macro_name, args)
656
657
658 def _indent_level(self):
659 """Return current char-wise indent level."""
660 return len(self.list_indents) and self.list_indents[-1]
661
662
663 def _indent_to(self, new_level, list_type, numtype, numstart):
664 """Close and open lists."""
665 close = []
666 open = ''
667
668
669 if self._indent_level() != new_level:
670 self._close_item(close)
671
672
673 while self._indent_level() > new_level:
674 if self.list_types[-1] == 'ol':
675 close.append(self.formatter.number_list(0))
676 elif self.list_types[-1] == 'dl':
677 close.append(self.formatter.definition_list(0))
678 else:
679 close.append(self.formatter.bullet_list(0))
680
681 del(self.list_indents[-1])
682 del(self.list_types[-1])
683
684
685 if self._indent_level() < new_level:
686 self.list_indents.append(new_level)
687 self.list_types.append(list_type)
688 if list_type == 'ol':
689 open += self.formatter.number_list(1, numtype, numstart)
690 elif list_type == 'dl':
691 open += self.formatter.definition_list(1)
692 else:
693 open += self.formatter.bullet_list(1)
694
695
696 if self.in_table and (open or close):
697 close.insert(0, self.formatter.table(0))
698 self.in_table = 0
699
700 return ''.join(close) + open
701
702
703 def _undent(self):
704 """Close all open lists."""
705 result = []
706 self._close_item(result)
707 for type in self.list_types:
708 if type == 'ol':
709 result.append(self.formatter.number_list(0))
710 elif type == 'dl':
711 result.append(self.formatter.definition_list(0))
712 else:
713 result.append(self.formatter.bullet_list(0))
714 self.list_indents = []
715 self.list_types = []
716 return ''.join(result)
717
718
719 def highlight_text(self, text, **kw):
720 if kw.get('flow', 1): self._check_p()
721 if not self.hilite_re: return self.formatter.text(text)
722
723 result = []
724 lastpos = 0
725 match = self.hilite_re.search(text)
726 while match and lastpos < len(text):
727
728 result.append(self.formatter.text(text[lastpos:match.start()]))
729 result.append(self.formatter.highlight(1))
730 result.append(self.formatter.text(match.group(0)))
731 result.append(self.formatter.highlight(0))
732
733
734 lastpos = match.end() + (match.end() == lastpos)
735 match = self.hilite_re.search(text, lastpos)
736
737 result.append(self.formatter.text(text[lastpos:]))
738 return ''.join(result)
739
740 def highlight_scan(self, scan_re, line):
741 result = []
742 lastpos = 0
743 match = scan_re.search(line)
744 while match and lastpos < len(line):
745
746 result.append(self.highlight_text(line[lastpos:match.start()]))
747 result.append(self.replace(match))
748
749
750 lastpos = match.end() + (match.end() == lastpos)
751 match = scan_re.search(line, lastpos)
752
753 result.append(self.highlight_text(line[lastpos:]))
754 return ''.join(result)
755
756
757 def replace(self, match):
758
759 for type, hit in match.groupdict().items():
760 if hit is not None and type != "hmarker":
761
762 if self.in_pre and type not in ['pre', 'ent']:
763 return self.highlight_text(hit)
764 else:
765 return getattr(self, '_' + type + '_repl')(hit)
766 else:
767 import pprint
768 raise Exception("Can't handle match " + `match`
769 + "\n" + pprint.pformat(match.groupdict())
770 + "\n" + pprint.pformat(match.groups()) )
771
772 return ""
773
774
775
776 def format(self, formatter, form, printing=1):
777 """ For each line, scan through looking for magic
778 strings, outputting verbatim any intervening text.
779 """
780 self.formatter = formatter
781 self.form = form
782 self.hilite_re = self.formatter.page.hilite_re
783 self.mybuffer = ['']
784
785
786 rules = self.formatting_rules.replace('\n', '|')
787 if config.allow_extended_names:
788 rules = rules + r'|(?P<wikiname_bracket>\[".*?"\])'
789 if config.bang_meta:
790 rules = r'(?P<notword>!%(word_rule)s)|%(rules)s' % {
791 'word_rule': self.word_rule,
792 'rules': rules,
793 }
794 if config.backtick_meta:
795 rules = rules + r'|(?P<tt_bt>`.*?`)'
796 if config.allow_numeric_entities:
797 rules = r'(?P<ent_numeric>&#\d{1,5};)|' + rules
798
799 scan_re = re.compile(rules)
800 number_re = re.compile(self.ol_rule)
801 term_re = re.compile(self.dl_rule)
802 indent_re = re.compile("^\s*")
803 eol_re = re.compile(r'\r?\n')
804
805
806 rawtext = self.raw.expandtabs()
807
808
809 self.lineno = 0
810 self.lines = eol_re.split(rawtext)
811 for line in self.lines:
812 self.lineno = self.lineno + 1
813 self.table_rowstart = 1
814
815 if self.in_pre:
816 if self.in_pre == 2:
817
818 endpos = line.find("}}}")
819 if endpos == -1:
820 self.colorize_lines.append(line)
821 continue
822
823 self.processor(self.request, self.formatter, self.colorize_lines)
824 del self.colorize_lines
825 self.in_pre = 0
826
827
828 line = line[endpos+3:]
829 elif line.strip()[:2] == "#!" and line.find('python') > 0:
830 from MoinMoin.processor.Colorize import process
831 self.processor = process
832 self.in_pre = 2
833 self.colorize_lines = [line]
834 continue
835 else:
836
837 if not line.strip():
838 if self.formatter.in_p:
839 self.mywrite(self.formatter.paragraph(0))
840 if self.in_table:
841 self.mywrite(self.formatter.table(0))
842 self.in_table = 0
843 continue
844
845
846 indent = indent_re.match(line)
847 indlen = len(indent.group(0))
848 indtype = "ul"
849 numtype = None
850 numstart = None
851 if indlen:
852 match = number_re.match(line)
853 if match:
854 numtype, numstart = match.group(0).strip().split('.')
855 numtype = numtype[0]
856
857 if numstart and numstart[0] == "#":
858 numstart = int(numstart[1:])
859 else:
860 numstart = None
861
862 indtype = "ol"
863 else:
864 match = term_re.match(line)
865 if match:
866 indtype = "dl"
867
868
869 print self._indent_to(indlen, indtype, numtype, numstart)
870
871
872 if not self.in_table and line[indlen:indlen+2] == "||" and line[-2:] == "||":
873 attrs, attrerr = self._getTableAttrs(line[indlen+2:])
874 self.mywrite(self.formatter.table(1, attrs) + attrerr)
875 self.in_table = self.lineno
876 elif self.in_table and not(line[indlen:indlen+2] == "||" and line[-2:] == "||"):
877 self.mywrite(self.formatter.table(0))
878 self.in_table = 0
879
880
881 if self.hilite_re:
882 self.mywrite(self.highlight_scan(scan_re, line + " "))
883 else:
884 line, count = re.subn(scan_re, self.replace, line + " ")
885
886 self._check_p()
887 self.mywrite(line)
888
889 if self.in_pre:
890 self.mywrite(self.formatter.linebreak())
891
892
893
894
895
896 if self.in_pre: self.mywrite(self.formatter.preformatted(0))
897 if self.formatter.in_p: self.mywrite(self.formatter.paragraph(0))
898 if self.in_table: self.mywrite(self.formatter.table(0))
899 self.mywrite(self._undent())
900 if printing==1:
901 self.myflush()
902 else:
903 return self.myread()