Attachment 'parser_12_13.diff'
Download 1 --- moin--main--1.2--patch-364/MoinMoin/parser/wiki.py 2005-01-16 16:07:50.096079352 +0100
2 +++ moin--main--1.3--patch-546/MoinMoin/parser/wiki.py 2005-01-16 16:08:19.182657520 +0100
3 @@ -6,17 +6,11 @@
4 @license: GNU GPL, see COPYING for details.
5 """
6
7 -# Imports
8 import os, re
9 from MoinMoin import config, wikimacro, wikiutil
10 from MoinMoin.Page import Page
11 from MoinMoin.util import web
12
13 -
14 -#############################################################################
15 -### MoinMoin Wiki Markup Parser
16 -#############################################################################
17 -
18 class Parser:
19 """
20 Object that turns Wiki markup into HTML.
21 @@ -34,29 +28,29 @@
22 # some common strings
23 PARENT_PREFIX = wikiutil.PARENT_PREFIX
24 attachment_schemas = ["attachment", "inline", "drawing"]
25 - punct_pattern = re.escape('''"\'}]|:,.)?!''')
26 - url_pattern = ('http|https|ftp|nntp|news|mailto|telnet|wiki|file|' +
27 - '|'.join(attachment_schemas) +
28 - (config.url_schemas and '|' + '|'.join(config.url_schemas) or ''))
29 + punct_pattern = re.escape(u'''"\'}]|:,.)?!''')
30 + url_pattern = (u'http|https|ftp|nntp|news|mailto|telnet|wiki|file|' +
31 + u'|'.join(attachment_schemas) +
32 + (config.url_schemas and u'|' + u'|'.join(config.url_schemas) or ''))
33
34 # some common rules
35 - word_rule = r'(?:(?<![%(l)s])|^)%(parent)s(?:%(subpages)s(?:[%(u)s][%(l)s]+){2,})+(?![%(u)s%(l)s]+)' % {
36 - 'u': config.upperletters,
37 - 'l': config.lowerletters,
38 + word_rule = ur'(?:(?<![%(l)s])|^)%(parent)s(?:%(subpages)s(?:[%(u)s][%(l)s]+){2,})+(?![%(u)s%(l)s]+)' % {
39 + 'u': config.chars_upper,
40 + 'l': config.chars_lower,
41 'subpages': config.allow_subpages and (wikiutil.CHILD_PREFIX + '?') or '',
42 - 'parent': config.allow_subpages and (r'(?:%s)?' % re.escape(PARENT_PREFIX)) or '',
43 + 'parent': config.allow_subpages and (ur'(?:%s)?' % re.escape(PARENT_PREFIX)) or '',
44 }
45 - url_rule = r'%(url_guard)s(%(url)s)\:([^\s\<%(punct)s]|([%(punct)s][^\s\<%(punct)s]))+' % {
46 - 'url_guard': '(^|(?<!\w))',
47 + url_rule = ur'%(url_guard)s(%(url)s)\:([^\s\<%(punct)s]|([%(punct)s][^\s\<%(punct)s]))+' % {
48 + 'url_guard': u'(^|(?<!\w))',
49 'url': url_pattern,
50 'punct': punct_pattern,
51 }
52
53 - ol_rule = r"^\s+(?:[0-9]+|[aAiI])\.(?:#\d+)?\s"
54 - dl_rule = r"^\s+.*?::\s"
55 + ol_rule = ur"^\s+(?:[0-9]+|[aAiI])\.(?:#\d+)?\s"
56 + dl_rule = ur"^\s+.*?::\s"
57
58 # the big, fat, ugly one ;)
59 - formatting_rules = r"""(?:(?P<emph_ibb>'''''(?=[^']+'''))
60 + formatting_rules = ur"""(?:(?P<emph_ibb>'''''(?=[^']+'''))
61 (?P<emph_ibi>'''''(?=[^']+''))
62 (?P<emph_ib_or_bi>'{5}(?=[^']))
63 (?P<emph>'{2,3})
64 @@ -66,37 +60,44 @@
65 (?P<tt>\{\{\{.*?\}\}\})
66 (?P<processor>(\{\{\{(#!.*|\s*$)))
67 (?P<pre>(\{\{\{ ?|\}\}\}))
68 +(?P<small>(\~- ?|-\~))
69 +(?P<big>(\~\+ ?|\+\~))
70 (?P<rule>-{4,})
71 (?P<comment>^\#\#.*$)
72 -(?P<macro>\[\[(%(macronames)s)(?:\(.*?\))?\]\]))
73 -(?P<li>^\s+\*)
74 +(?P<macro>\[\[(%%(macronames)s)(?:\(.*?\))?\]\]))
75 (?P<ol>%(ol_rule)s)
76 (?P<dl>%(dl_rule)s)
77 +(?P<li>^\s+\*?)
78 (?P<tableZ>\|\| $)
79 -(?P<table>(?:\|\|)+(?:<[^>]*?>)?(?=.))
80 +(?P<table>(?:\|\|)+(?:<[^>]*?>)?(?!\|? $))
81 (?P<heading>^\s*(?P<hmarker>=+)\s.*\s(?P=hmarker) $)
82 (?P<interwiki>[A-Z][a-zA-Z]+\:[^\s'\"\:\<\|]([^\s%(punct)s]|([%(punct)s][^\s%(punct)s]))+)
83 (?P<word>%(word_rule)s)
84 (?P<url_bracket>\[((%(url)s)\:|#|\:)[^\s\]]+(\s[^\]]+)?\])
85 (?P<url>%(url_rule)s)
86 -(?P<email>[-\w._+]+\@[\w-]+\.[\w.-]+)
87 +(?P<email>[-\w._+]+\@[\w-]+(\.[\w-]+)+)
88 (?P<smiley>(?<=\s)(%(smiley)s)(?=\s))
89 (?P<smileyA>^(%(smiley)s)(?=\s))
90 (?P<ent>[<>&])""" % {
91 'url': url_pattern,
92 'punct': punct_pattern,
93 - 'macronames': '|'.join(wikimacro.names),
94 'ol_rule': ol_rule,
95 'dl_rule': dl_rule,
96 'url_rule': url_rule,
97 'word_rule': word_rule,
98 - 'smiley': '|'.join(map(re.escape, config.smileys.keys()))}
99 + 'smiley': u'|'.join(map(re.escape, config.smileys.keys()))}
100 +
101 + # Don't start p before these
102 + no_new_p_before = ("heading rule table tableZ tr td ul ol dl dt dd li "
103 + "processor macro pre")
104 + no_new_p_before = dict(zip(no_new_p_before.split(), [1] * len(no_new_p_before)))
105
106 def __init__(self, raw, request, **kw):
107 self.raw = raw
108 self.request = request
109 self.form = request.form
110 self._ = request.getText
111 + self.cfg = request.cfg
112
113 self.macro = None
114
115 @@ -108,22 +109,31 @@
116 self.in_dd = 0
117 self.in_pre = 0
118 self.in_table = 0
119 + self.is_big = False
120 + self.is_small = False
121 self.inhibit_p = 0 # if set, do not auto-create a <p>aragraph
122 - self.titles = {}
123 + self.titles = request._page_headings
124
125 # holds the nesting level (in chars) of open lists
126 self.list_indents = []
127 self.list_types = []
128 +
129 + self.formatting_rules = self.formatting_rules % {'macronames': u'|'.join(wikimacro.getNames(self.cfg))}
130
131 def _close_item(self, result):
132 #result.append("<!-- close item begin -->\n")
133 - if self.formatter.in_p:
134 - result.append(self.formatter.paragraph(0))
135 + if self.in_table:
136 + result.append(self.formatter.table(0))
137 + self.in_table = 0
138 if self.in_li:
139 self.in_li = 0
140 + if self.formatter.in_p:
141 + result.append(self.formatter.paragraph(0))
142 result.append(self.formatter.listitem(0))
143 if self.in_dd:
144 self.in_dd = 0
145 + if self.formatter.in_p:
146 + result.append(self.formatter.paragraph(0))
147 result.append(self.formatter.definition_desc(0))
148 #result.append("<!-- close item end -->\n")
149
150 @@ -147,12 +157,11 @@
151 elif config.allow_subpages and url[0] == wikiutil.CHILD_PREFIX:
152 # fancy link to subpage [wiki:/SubPage text]
153 return self._word_repl(url, text)
154 - elif Page(url).exists():
155 + elif Page(self.request, url).exists():
156 # fancy link to local page [wiki:LocalPage text]
157 return self._word_repl(url, text)
158
159 wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_wiki(self.request, url)
160 - wikiurl = wikiutil.mapURL(wikiurl)
161 href = wikiutil.join_wiki(wikiurl, wikitail)
162
163 # check for image URL, and possibly return IMG tag
164 @@ -163,19 +172,9 @@
165 if wikitag is None:
166 return self._word_repl(wikitail)
167
168 - # return InterWiki hyperlink
169 - if wikitag_bad:
170 - html_class = 'badinterwiki'
171 - else:
172 - html_class = 'interwiki'
173 - text = self.highlight_text(text) # also cgi.escapes if necessary
174 -
175 - icon = ''
176 - if self.request.user.show_fancy_links:
177 - icon = self.request.theme.make_icon('interwiki', {'wikitag': wikitag})
178 - return self.formatter.url(href, icon + text,
179 - title=wikitag, unescaped=1, pretty_url=kw.get('pretty_url', 0), css = html_class)
180 -
181 + return (self.formatter.interwikilink(1, wikitag, wikitail) +
182 + self.formatter.text(text) +
183 + self.formatter.interwikilink(0))
184
185 def attachment(self, url_and_text, **kw):
186 """ This gets called on attachment URLs.
187 @@ -209,15 +208,15 @@
188 fname = fname + ".png"
189 url = url + ".png"
190 # fallback for old gif drawings (1.1 -> 1.2)
191 - fpath = os.path.join(AttachFile.getAttachDir(pagename), fname)
192 + fpath = AttachFile.getFilename(self.request, pagename, fname)
193 if not os.path.exists(fpath):
194 gfname = fname[:-4] + ".gif"
195 gurl = url[:-4] + ".gif"
196 - gfpath = os.path.join(AttachFile.getAttachDir(pagename), gfname)
197 + gfpath = AttachFile.getFilename(self.request, pagename, gfname)
198 if os.path.exists(gfpath):
199 fname, url, fpath = gfname, gurl, gfpath
200 else:
201 - fpath = os.path.join(AttachFile.getAttachDir(pagename), fname)
202 + fpath = AttachFile.getFilename(self.request, pagename, fname)
203
204 # check whether attachment exists, possibly point to upload form
205 if not os.path.exists(fpath):
206 @@ -226,19 +225,19 @@
207 else:
208 linktext = _('Upload new attachment "%(filename)s"')
209 return wikiutil.link_tag(self.request,
210 - '%s?action=AttachFile&rename=%s%s' % (
211 - wikiutil.quoteWikiname(pagename),
212 - urllib.quote_plus(fname),
213 - drawing and ('&drawing=%s' % urllib.quote(drawing)) or ''),
214 - linktext % {'filename': fname})
215 + self.formatter.text('%s?action=AttachFile&rename=%s%s' % (
216 + wikiutil.quoteWikinameURL(pagename),
217 + urllib.quote_plus(fname.encode(config.charset)),
218 + drawing and ('&drawing=%s' % urllib.quote(drawing.encode(config.charset))) or '')),
219 + linktext % {'filename': self.formatter.text(fname)})
220
221 # check for image URL, and possibly return IMG tag
222 # (images are always inlined, just like for other URLs)
223 if not kw.get('pretty_url', 0) and wikiutil.isPicture(url):
224 if drawing:
225 # check for map file
226 - mappath = os.path.join(AttachFile.getAttachDir(pagename), drawing + '.map')
227 - edit_link = '%s?action=AttachFile&rename=%s&drawing=%s' % (wikiutil.quoteWikiname(pagename), urllib.quote_plus(fname), urllib.quote(drawing))
228 + mappath = AttachFile.getFilename(self.request, pagename, drawing + '.map')
229 + edit_link = self.formatter.text('%s?action=AttachFile&rename=%s&drawing=%s' % (wikiutil.quoteWikinameURL(pagename), urllib.quote_plus(fname.encode(config.charset)), urllib.quote(drawing.encode(config.charset))))
230 if os.path.exists(mappath):
231 # we have a image map. inline it and add a map ref
232 # to the img tag
233 @@ -255,7 +254,7 @@
234 # add alt and title tags to areas
235 map = re.sub('href\s*=\s*"((?!%TWIKIDRAW%).+?)"',r'href="\1" alt="\1" title="\1"',map)
236 # add in edit links plus alt and title attributes
237 - map = map.replace('%TWIKIDRAW%"', edit_link + '" alt="' + _('Edit drawing %(filename)s') % {'filename': fname} + '" title="' + _('Edit drawing %(filename)s') % {'filename': fname} + '"')
238 + map = map.replace('%TWIKIDRAW%"', edit_link + '" alt="' + _('Edit drawing %(filename)s') % {'filename': self.formatter.text(fname)} + '" title="' + _('Edit drawing %(filename)s') % {'filename': self.formatter.text(fname)} + '"')
239 # unxml, because 4.01 concrete will not validate />
240 map = map.replace('/>','>')
241 return map + self.formatter.image(alt=drawing,
242 @@ -265,36 +264,51 @@
243 edit_link,
244 self.formatter.image(alt=url,
245 src=AttachFile.getAttachUrl(pagename, url, self.request, addts=1), html_class="drawing"),
246 - attrs='title="%s"' % (_('Edit drawing %(filename)s') % {'filename': fname}))
247 + attrs='title="%s"' % (_('Edit drawing %(filename)s') % {'filename': self.formatter.text(fname)}))
248 else:
249 return self.formatter.image(alt=url,
250 src=AttachFile.getAttachUrl(pagename, url, self.request, addts=1))
251
252 - # try to inline the attachment (we only accept a list
253 - # of known extensions)
254 + # try to inline the attachment (parser know what they
255 + # can handle)
256 base, ext = os.path.splitext(url)
257 - if inline and ext in ['.py']:
258 - if ext == '.py':
259 - import cStringIO
260 - from MoinMoin.parser import python
261 -
262 - buff = cStringIO.StringIO()
263 - colorizer = python.Parser(open(fpath, 'r').read(), self.request, out = buff)
264 + if inline:
265 + Parser = wikiutil.getParserForExtension(self.cfg, ext)
266 + if Parser is not None:
267 + content = file(fpath, 'r').read()
268 + # Try to decode text. It might return junk, but we don't
269 + # have enough information with attachments.
270 + content = wikiutil.decodeUnknownInput(content)
271 + colorizer = Parser(content, self.request)
272 colorizer.format(self.formatter)
273 - return self.formatter.preformatted(1) + \
274 - self.formatter.rawHTML(buff.getvalue()) + \
275 - self.formatter.preformatted(0)
276 -
277 - return self.formatter.url(
278 - AttachFile.getAttachUrl(pagename, url, self.request),
279 - text, pretty_url=kw.get('pretty_url', 0))
280
281 + url = AttachFile.getAttachUrl(pagename, url, self.request)
282 +
283 + if kw.get('pretty_url', 0) and wikiutil.isPicture(url):
284 + return self.formatter.image(src=url)
285 + else:
286 + return (self.formatter.url(1, url) +
287 + self.formatter.text(text) +
288 + self.formatter.url(0))
289
290 def _u_repl(self, word):
291 """Handle underline."""
292 self.is_u = not self.is_u
293 return self.formatter.underline(self.is_u)
294
295 + def _small_repl(self, word):
296 + """Handle small."""
297 + if word.strip() == '~-' and self.is_small: return word
298 + if word.strip() == '-~' and not self.is_small: return word
299 + self.is_small = not self.is_small
300 + return self.formatter.small(self.is_small)
301 +
302 + def _big_repl(self, word):
303 + """Handle big."""
304 + if word.strip() == '~+' and self.is_big: return word
305 + if word.strip() == '+~' and not self.is_big: return word
306 + self.is_big = not self.is_big
307 + return self.formatter.big(self.is_big)
308
309 def _emph_repl(self, word):
310 """Handle emphasis, i.e. '' and '''."""
311 @@ -337,25 +351,27 @@
312 def _sup_repl(self, word):
313 """Handle superscript."""
314 return self.formatter.sup(1) + \
315 - self.highlight_text(word[1:-1]) + \
316 + self.formatter.text(word[1:-1]) + \
317 self.formatter.sup(0)
318
319
320 def _sub_repl(self, word):
321 """Handle subscript."""
322 return self.formatter.sub(1) + \
323 - self.highlight_text(word[2:-2]) + \
324 + self.formatter.text(word[2:-2]) + \
325 self.formatter.sub(0)
326
327
328 def _rule_repl(self, word):
329 """Handle sequences of dashes."""
330 - self.inhibit_p = 1
331 - result = self._undent()
332 + ##self.inhibit_p = 1
333 + result = self._undent() + self._closeP()
334 if len(word) <= 4:
335 result = result + self.formatter.rule()
336 else:
337 - result = result + self.formatter.rule(min(len(word), 10) - 2)
338 + # Create variable rule size 1 - 6. Actual size defined in css.
339 + size = min(len(word), 10) - 4
340 + result = result + self.formatter.rule(size)
341 return result
342
343
344 @@ -372,20 +388,17 @@
345 if not text:
346 # if a simple, self-referencing link, emit it as plain text
347 if word == self.formatter.page.page_name:
348 - return word
349 + return self.formatter.text(word)
350 text = word
351 if config.allow_subpages and word.startswith(wikiutil.CHILD_PREFIX):
352 word = self.formatter.page.page_name + word
353 - text = self.highlight_text(text)
354 - if word == text:
355 - return self.formatter.pagelink(word)
356 - else:
357 - return self.formatter.pagelink(word, text)
358 + return (self.formatter.pagelink(1, word) +
359 + self.formatter.text(text) +
360 + self.formatter.pagelink(0, word))
361
362 def _notword_repl(self, word):
363 """Handle !NotWikiNames."""
364 - return self.highlight_text(word[1:])
365 -
366 + return self.formatter.text(word[1:])
367
368 def _interwiki_repl(self, word):
369 """Handle InterWiki links."""
370 @@ -400,7 +413,15 @@
371 if scheme in self.attachment_schemas:
372 return self.attachment([word])
373
374 - return self.formatter.url(word, text=self.highlight_text(word))
375 + if wikiutil.isPicture(word):
376 + # Get image name http://here.com/dir/image.gif -> image
377 + name = word.split('/')[-1]
378 + name = ''.join(name.split('.')[:-1])
379 + return self.formatter.image(src=word, alt=name)
380 + else:
381 + return (self.formatter.url(1, word, type='www') +
382 + self.formatter.text(word) +
383 + self.formatter.url(0))
384
385
386 def _wikiname_bracket_repl(self, word):
387 @@ -427,7 +448,9 @@
388
389 if words[0][0] == '#':
390 # anchor link
391 - return self.formatter.url(words[0], self.highlight_text(words[1]))
392 + return (self.formatter.url(1, words[0]) +
393 + self.formatter.text(words[1]) +
394 + self.formatter.url(0))
395
396 scheme = words[0].split(":", 1)[0]
397 if scheme == "wiki": return self.interwiki(words, pretty_url=1)
398 @@ -435,16 +458,21 @@
399 return self.attachment(words, pretty_url=1)
400
401 if wikiutil.isPicture(words[1]) and re.match(self.url_rule, words[1]):
402 - text = self.formatter.image(title=words[0], alt=words[0], src=words[1])
403 + return (self.formatter.url(1, words[0], 'external', unescaped=1) +
404 + self.formatter.image(title=words[0], alt=words[0], src=words[1]) +
405 + self.formatter.url(0))
406 else:
407 - text = web.getLinkIcon(self.request, self.formatter, scheme)
408 - text += self.highlight_text(words[1])
409 - return self.formatter.url(words[0], text, 'external', pretty_url=1, unescaped=1)
410 + return (self.formatter.url(1, words[0], 'external',
411 + type='www', unescaped=1) +
412 + self.formatter.text(words[1]) +
413 + self.formatter.url(0))
414
415
416 def _email_repl(self, word):
417 """Handle email addresses (without a leading mailto:)."""
418 - return self.formatter.url("mailto:" + word, self.highlight_text(word))
419 + return (self.formatter.url(1, "mailto:" + word, type='mailto') +
420 + self.formatter.text(word) +
421 + self.formatter.url(0))
422
423
424 def _ent_repl(self, word):
425 @@ -463,15 +491,22 @@
426 def _li_repl(self, match):
427 """Handle bullet lists."""
428 result = []
429 + indented_only = (match == (" " * len(match)))
430 + if indented_only and self.in_li: return ''
431 +
432 self._close_item(result)
433 - self.inhibit_p = 1
434 + #self.inhibit_p = 1
435 self.in_li = 1
436 css_class = ''
437 if self.line_was_empty and not self.first_list_item:
438 css_class = 'gap'
439 - result.append(" "*4*self._indent_level())
440 - result.append(self.formatter.listitem(1, css_class=css_class))
441 - result.append(self.formatter.paragraph(1))
442 + if indented_only:
443 + result.append(self.formatter.listitem(1, css_class=css_class,
444 + style="list-style-type:none"))
445 + else:
446 + result.append(self.formatter.listitem(1, css_class=css_class))
447 + # Suspected p!
448 + ## result.append(self.formatter.paragraph(1))
449 return ''.join(result)
450
451
452 @@ -484,15 +519,15 @@
453 """Handle definition lists."""
454 result = []
455 self._close_item(result)
456 - self.inhibit_p = 1
457 + #self.inhibit_p = 1
458 self.in_dd = 1
459 result.extend([
460 - " "*4*self._indent_level(),
461 self.formatter.definition_term(1),
462 - self.formatter.text(match[:-3]),
463 + self.formatter.text(match[1:-3]),
464 self.formatter.definition_term(0),
465 self.formatter.definition_desc(1),
466 - self.formatter.paragraph(1)
467 + ## CHANGE: no automatic paragraph
468 + ##self.formatter.paragraph(1)
469 ])
470 return ''.join(result)
471
472 @@ -507,73 +542,72 @@
473 open = [] # don't make one out of these two statements!
474 close = []
475
476 - # Close open paragraphs and list items
477 - if self._indent_level() != new_level:
478 - self._close_item(close)
479 - else:
480 - if not self.line_was_empty:
481 - self.inhibit_p = 1
482 +
483 + if self._indent_level() != new_level and self.in_table:
484 + close.append(self.formatter.table(0))
485 + self.in_table = 0
486 + # #self._close_item(close)
487 + #else:
488 + # if not self.line_was_empty:
489 + # self.inhibit_p = 1
490
491 # Close lists while char-wise indent is greater than the current one
492 - while self._indent_level() > new_level:
493 - indentstr = " "*4*self._indent_level()
494 + while ((self._indent_level() > new_level) or
495 + ( new_level and
496 + (self._indent_level() == new_level) and
497 + (self.list_types[-1]) != list_type)):
498 + self._close_item(close)
499 if self.list_types[-1] == 'ol':
500 tag = self.formatter.number_list(0)
501 elif self.list_types[-1] == 'dl':
502 tag = self.formatter.definition_list(0)
503 else:
504 tag = self.formatter.bullet_list(0)
505 - close.append("\n%s%s\n" % (indentstr, tag))
506 + close.append(tag)
507
508 del(self.list_indents[-1])
509 del(self.list_types[-1])
510
511 - if new_level:
512 - self.inhibit_p = 1
513 - else:
514 - self.inhibit_p = 0
515 + #if new_level:
516 + # self.inhibit_p = 1
517 + #else:
518 + # self.inhibit_p = 0
519 +
520 + if self.list_types: # we are still in a list
521 + if self.list_types[-1] == 'dl':
522 + self.in_dd = 1
523 + else:
524 + self.in_li = 1
525
526 - # XXX This would give valid, but silly looking html.
527 - # the right way is that inner list has to be CONTAINED in outer li -
528 - # but in the one before, not a new one, like this code does:
529 - #if self.list_types: # we are still in a list, bracket with li /li
530 - # if self.list_types[-1] in ['ol', 'ul']:
531 - # open.append(" "*4*new_level)
532 - # open.append(self.formatter.listitem(0))
533 - # elif self.list_types[-1] == 'dl':
534 - # open.append(" "*4*new_level)
535 - # open.append(self.formatter.definition_desc(0))
536 -
537 # Open new list, if necessary
538 if self._indent_level() < new_level:
539 - # XXX see comment 10 lines above
540 - #if self.list_types: # we already are in a list, bracket with li /li
541 - # if self.list_types[-1] in ['ol', 'ul']:
542 - # open.append(" "*4*new_level)
543 - # open.append(self.formatter.listitem(1))
544 - # elif self.list_types[-1] == 'dl':
545 - # open.append(" "*4*new_level)
546 - # open.append(self.formatter.definition_desc(1))
547
548 self.list_indents.append(new_level)
549 self.list_types.append(list_type)
550 +
551 + if self.formatter.in_p:
552 + close.append(self.formatter.paragraph(0))
553
554 - indentstr = " "*4*new_level
555 if list_type == 'ol':
556 tag = self.formatter.number_list(1, numtype, numstart)
557 elif list_type == 'dl':
558 tag = self.formatter.definition_list(1)
559 else:
560 tag = self.formatter.bullet_list(1)
561 - open.append("\n%s%s\n" % (indentstr, tag))
562 + open.append(tag)
563
564 self.first_list_item = 1
565 - self.inhibit_p = 1
566 -
567 + ## Maybe this prevent p creation in lists?
568 + ##self.inhibit_p = 1
569 + self.in_li = 0
570 + self.in_dd = 0
571 # If list level changes, close an open table
572 if self.in_table and (open or close):
573 close[0:0] = [self.formatter.table(0)]
574 self.in_table = 0
575 +
576 + ## Maybe this prevent p creation in lists?
577 + ##self.inhibit_p = bool(self.list_types)
578
579 return ''.join(close) + ''.join(open)
580
581 @@ -599,7 +633,7 @@
582 def _tt_repl(self, word):
583 """Handle inline code."""
584 return self.formatter.code(1) + \
585 - self.highlight_text(word[3:-3]) + \
586 + self.formatter.text(word[3:-3]) + \
587 self.formatter.code(0)
588
589
590 @@ -607,7 +641,7 @@
591 """Handle backticked inline code."""
592 if len(word) == 2: return ""
593 return self.formatter.code(1) + \
594 - self.highlight_text(word[1:-1]) + \
595 + self.formatter.text(word[1:-1]) + \
596 self.formatter.code(0)
597
598
599 @@ -689,22 +723,32 @@
600 def _tableZ_repl(self, word):
601 """Handle table row end."""
602 if self.in_table:
603 - return self.formatter.table_cell(0) + self.formatter.table_row(0)
604 + result = ''
605 + # REMOVED: check for self.in_li, p should always close
606 + if self.formatter.in_p:
607 + result = self.formatter.paragraph(0)
608 + result += self.formatter.table_cell(0) + self.formatter.table_row(0)
609 + return result
610 else:
611 return word
612
613 def _table_repl(self, word):
614 """Handle table cell separator."""
615 if self.in_table:
616 + result = []
617 # check for attributes
618 attrs, attrerr = self._getTableAttrs(word)
619
620 # start the table row?
621 if self.table_rowstart:
622 self.table_rowstart = 0
623 - leader = self.formatter.table_row(1, attrs)
624 + result.append(self.formatter.table_row(1, attrs))
625 else:
626 - leader = self.formatter.table_cell(0)
627 + # Close table cell, first closing open p
628 + # REMOVED check for self.in_li, paragraph should close always!
629 + if self.formatter.in_p:
630 + result.append(self.formatter.paragraph(0))
631 + result.append(self.formatter.table_cell(0))
632
633 # check for adjacent cell markers
634 if word.count("|") > 2:
635 @@ -713,8 +757,9 @@
636 if not attrs.has_key('colspan'):
637 attrs['colspan'] = '"%d"' % (word.count("|")/2)
638
639 - # return the complete cell markup
640 - return leader + self.formatter.table_cell(1, attrs) + attrerr
641 + # return the complete cell markup
642 + result.append(self.formatter.table_cell(1, attrs) + attrerr)
643 + return ''.join(result)
644 else:
645 return word
646
647 @@ -723,13 +768,7 @@
648 """Handle section headings."""
649 import sha
650
651 - self.inhibit_p = 1
652 - icons = ''
653 - if self.request.user.show_topbottom:
654 - bottom = self.request.theme.make_icon('bottom')
655 - icons = icons + self.formatter.url("#bottom", bottom, unescaped=1)
656 - top = self.request.theme.make_icon('top')
657 - icons = icons + self.formatter.url("#top", top, unescaped=1)
658 + ##self.inhibit_p = 1
659
660 h = word.strip()
661 level = 1
662 @@ -737,46 +776,57 @@
663 level = level+1
664 depth = min(5,level)
665
666 + # this is needed for Included pages
667 + # TODO but it might still result in unpredictable results
668 + # when included the same page multiple times
669 title_text = h[level:-level].strip()
670 - self.titles.setdefault(title_text, 0)
671 - self.titles[title_text] += 1
672 + pntt = self.formatter.page.page_name + title_text
673 + self.titles.setdefault(pntt, 0)
674 + self.titles[pntt] += 1
675
676 unique_id = ''
677 - if self.titles[title_text] > 1:
678 - unique_id = '-%d' % self.titles[title_text]
679 -
680 - return self.formatter.heading(depth, self.highlight_text(title_text), icons=icons, id="head-"+sha.new(title_text).hexdigest()+unique_id)
681 -
682 -
683 + if self.titles[pntt] > 1:
684 + unique_id = '-%d' % self.titles[pntt]
685 + result = self._closeP()
686 + result += self.formatter.heading(1, depth, id="head-"+sha.new(pntt.encode(config.charset)).hexdigest()+unique_id)
687 +
688 + return (result + self.formatter.text(title_text) +
689 + self.formatter.heading(0, depth))
690 +
691 def _processor_repl(self, word):
692 """Handle processed code displays."""
693 if word[:3] == '{{{': word = word[3:]
694
695 self.processor = None
696 self.processor_name = None
697 + self.processor_is_parser = 0
698 s_word = word.strip()
699 if s_word == '#!':
700 # empty bang paths lead to a normal code display
701 # can be used to escape real, non-empty bang paths
702 word = ''
703 self.in_pre = 3
704 - return self.formatter.preformatted(1)
705 + return self._closeP() + self.formatter.preformatted(1)
706 elif s_word[:2] == '#!':
707 + # first try to find a processor for this (will go away in 1.4)
708 processor_name = s_word[2:].split()[0]
709 - self.processor = wikiutil.importPlugin("processor", processor_name, "process")
710 - if not self.processor and s_word.find('python') > 0:
711 - from MoinMoin.processor.Colorize import process
712 - self.processor = process
713 - self.processor_name = "Colorize"
714 + self.processor = wikiutil.importPlugin(
715 + self.request.cfg, "processor", processor_name, "process")
716 + # now look for a parser with that name
717 + if self.processor is None:
718 + self.processor = wikiutil.importPlugin(
719 + self.request.cfg, "parser", processor_name, "Parser")
720 + if self.processor:
721 + self.processor_is_parser = 1
722
723 if self.processor:
724 self.processor_name = processor_name
725 self.in_pre = 2
726 self.colorize_lines = [word]
727 return ''
728 - elif s_word:
729 + elif s_word:
730 self.in_pre = 3
731 - return self.formatter.preformatted(1) + \
732 + return self._closeP() + self.formatter.preformatted(1) + \
733 self.formatter.text(s_word + ' (-)')
734 else:
735 self.in_pre = 1
736 @@ -787,17 +837,18 @@
737 word = word.strip()
738 if word == '{{{' and not self.in_pre:
739 self.in_pre = 3
740 - return self.formatter.preformatted(self.in_pre)
741 + ##self.inhibit_p = 1
742 + return self._closeP() + self.formatter.preformatted(self.in_pre)
743 elif word == '}}}' and self.in_pre:
744 self.in_pre = 0
745 - self.inhibit_p = 1
746 + self.inhibit_p = 0
747 return self.formatter.preformatted(self.in_pre)
748 return word
749
750
751 def _smiley_repl(self, word):
752 """Handle smileys."""
753 - return wikiutil.getSmiley(word, self.formatter)
754 + return self.formatter.smiley(word)
755
756 _smileyA_repl = _smiley_repl
757
758 @@ -805,7 +856,11 @@
759 def _comment_repl(self, word):
760 return ''
761
762 -
763 + def _closeP(self):
764 + if self.formatter.in_p:
765 + return self.formatter.paragraph(0)
766 + return ''
767 +
768 def _macro_repl(self, word):
769 """Handle macros ([[macroname]])."""
770 macro_name = word[2:-2]
771 @@ -820,71 +875,63 @@
772 # create macro instance
773 if self.macro is None:
774 self.macro = wikimacro.Macro(self)
775 -
776 - # call the macro
777 return self.formatter.macro(self.macro, macro_name, args)
778
779 -
780 - def highlight_text(self, text, **kw):
781 - if not self.hilite_re: return self.formatter.text(text)
782 -
783 - # work around for dom/xml formatter
784 - # if not self.hilite_re: return text
785 - # XXX bad idea: this allowed `<b>raw html</b>` to get through!
786 -
787 - result = []
788 - lastpos = 0
789 - match = self.hilite_re.search(text)
790 - while match and lastpos < len(text):
791 - # add the match we found
792 - result.append(self.formatter.text(text[lastpos:match.start()]))
793 - result.append(self.formatter.highlight(1))
794 - result.append(self.formatter.text(match.group(0)))
795 - result.append(self.formatter.highlight(0))
796 -
797 - # search for the next one
798 - lastpos = match.end() + (match.end() == lastpos)
799 - match = self.hilite_re.search(text, lastpos)
800 -
801 - result.append(self.formatter.text(text[lastpos:]))
802 - return ''.join(result)
803 -
804 def scan(self, scan_re, line):
805 - """ scans the line for wiki syntax and replaces the
806 - found regular expressions
807 - calls highlight_text if self.hilite_re is set
808 + """ Scans one line
809 +
810 + Append text before match, invoke replace() with match, and
811 + add text after match.
812 """
813 result = []
814 lastpos = 0
815 - match = scan_re.search(line)
816 - while match and lastpos < len(line):
817 - # add the match we found
818 - if self.hilite_re:
819 - result.append(self.highlight_text(line[lastpos:match.start()]))
820 - else:
821 +
822 + ###result.append(u'<span class="info">[scan: <tt>"%s"</tt>]</span>' % line)
823 +
824 + for match in scan_re.finditer(line):
825 + # Add text before the match
826 + if lastpos < match.start():
827 +
828 + ###result.append(u'<span class="info">[add text before match: <tt>"%s"</tt>]</span>' % line[lastpos:match.start()])
829 +
830 + if not (self.inhibit_p or self.in_pre or self.formatter.in_p):
831 + result.append(self.formatter.paragraph(1))
832 result.append(self.formatter.text(line[lastpos:match.start()]))
833 +
834 + # Replace match with markup
835 result.append(self.replace(match))
836 -
837 - # search for the next one
838 - lastpos = match.end() + (match.end() == lastpos)
839 - match = scan_re.search(line, lastpos)
840 -
841 - if self.hilite_re:
842 - result.append(self.highlight_text(line[lastpos:]))
843 - else:
844 - result.append(self.formatter.text(line[lastpos:]))
845 - return ''.join(result)
846 + lastpos = match.end()
847 +
848 + ###result.append('<span class="info">[no match, add rest: <tt>"%s"<tt>]</span>' % line[lastpos:])
849 +
850 + # No match: Add paragraph with the text of the line
851 + if not (self.in_pre or self.inhibit_p or
852 + self.formatter.in_p) and lastpos < len(line):
853 + result.append(self.formatter.paragraph(1))
854 + result.append(self.formatter.text(line[lastpos:]))
855 + return u''.join(result)
856
857 def replace(self, match):
858 - #hit = filter(lambda g: g[1], match.groupdict().items())
859 + """ Replace match using type name """
860 + result = []
861 for type, hit in match.groupdict().items():
862 if hit is not None and type != "hmarker":
863 - ##print "###", cgi.escape(`type`), cgi.escape(`hit`), "###"
864 +
865 + ###result.append(u'<span class="info">[replace: %s: "%s"]</span>' % (type, hit))
866 if self.in_pre and type not in ['pre', 'ent']:
867 - return self.highlight_text(hit)
868 + return self.formatter.text(hit)
869 else:
870 - return getattr(self, '_' + type + '_repl')(hit)
871 + # Open p for certain types
872 + if not (self.inhibit_p or self.formatter.in_p
873 + or self.in_pre or (type in self.no_new_p_before)):
874 + result.append(self.formatter.paragraph(1))
875 +
876 + # Get replace method and replece hit
877 + replace = getattr(self, '_' + type + '_repl')
878 + result.append(replace(hit))
879 + return ''.join(result)
880 else:
881 + # We should never get here
882 import pprint
883 raise Exception("Can't handle match " + `match`
884 + "\n" + pprint.pformat(match.groupdict())
885 @@ -892,7 +939,6 @@
886
887 return ""
888
889 -
890 def format(self, formatter):
891 """ For each line, scan through looking for magic
892 strings, outputting verbatim any intervening text.
893 @@ -902,23 +948,25 @@
894
895 # prepare regex patterns
896 rules = self.formatting_rules.replace('\n', '|')
897 - if config.allow_extended_names:
898 - rules = rules + r'|(?P<wikiname_bracket>\[".*?"\])'
899 - if config.bang_meta:
900 - rules = r'(?P<notword>!%(word_rule)s)|%(rules)s' % {
901 + if self.cfg.allow_extended_names:
902 + rules = rules + ur'|(?P<wikiname_bracket>\[".*?"\])'
903 + if self.cfg.bang_meta:
904 + rules = ur'(?P<notword>!%(word_rule)s)|%(rules)s' % {
905 'word_rule': self.word_rule,
906 'rules': rules,
907 }
908 - if config.backtick_meta:
909 - rules = rules + r'|(?P<tt_bt>`.*?`)'
910 - if config.allow_numeric_entities:
911 - rules = r'(?P<ent_numeric>&#\d{1,5};)|' + rules
912 -
913 - scan_re = re.compile(rules)
914 - number_re = re.compile(self.ol_rule)
915 - term_re = re.compile(self.dl_rule)
916 - indent_re = re.compile("^\s*")
917 - eol_re = re.compile(r'\r?\n')
918 + if self.cfg.backtick_meta:
919 + rules = rules + ur'|(?P<tt_bt>`.*?`)'
920 + if self.cfg.allow_numeric_entities:
921 + rules = ur'(?P<ent_numeric>&#\d{1,5};)|' + rules
922 +
923 + self.request.clock.start('compile_huge_and_ugly')
924 + scan_re = re.compile(rules, re.UNICODE)
925 + number_re = re.compile(self.ol_rule, re.UNICODE)
926 + term_re = re.compile(self.dl_rule, re.UNICODE)
927 + indent_re = re.compile("^\s*", re.UNICODE)
928 + eol_re = re.compile(r'\r?\n', re.UNICODE)
929 + self.request.clock.stop('compile_huge_and_ugly')
930
931 # get text and replace TABs
932 rawtext = self.raw.expandtabs()
933 @@ -928,6 +976,7 @@
934 self.lines = eol_re.split(rawtext)
935 self.line_is_empty = 0
936
937 + # Main loop
938 for line in self.lines:
939 self.lineno = self.lineno + 1
940 self.table_rowstart = 1
941 @@ -937,25 +986,32 @@
942 self.inhibit_p = 0
943
944 if self.in_pre:
945 + # TODO: move this into function
946 # still looking for processing instructions
947 + # TODO: use strings for pre state, not numbers
948 if self.in_pre == 1:
949 self.processor = None
950 + self.processor_is_parser = 0
951 processor_name = ''
952 if (line.strip()[:2] == "#!"):
953 - from MoinMoin.processor import processors
954 processor_name = line.strip()[2:].split()[0]
955 - self.processor = wikiutil.importPlugin("processor", processor_name, "process")
956 - if not self.processor and (line.find('python') > 0):
957 - from MoinMoin.processor.Colorize import process
958 - self.processor = process
959 - processor_name = "Colorize"
960 + self.processor = wikiutil.importPlugin(
961 + self.request.cfg, "processor", processor_name, "process")
962 +
963 + # now look for a parser with that name
964 + if self.processor is None:
965 + self.processor = wikiutil.importPlugin(
966 + self.request.cfg, "parser", processor_name, "Parser")
967 + if self.processor:
968 + self.processor_is_parser = 1
969 if self.processor:
970 self.in_pre = 2
971 self.colorize_lines = [line]
972 self.processor_name = processor_name
973 continue
974 else:
975 - self.request.write(self.formatter.preformatted(1))
976 + self.request.write(self._closeP() +
977 + self.formatter.preformatted(1))
978 self.in_pre = 3
979 if self.in_pre == 2:
980 # processing mode
981 @@ -965,8 +1021,14 @@
982 continue
983 if line[:endpos]:
984 self.colorize_lines.append(line[:endpos])
985 - self.request.write(
986 - self.formatter.processor(self.processor_name, self.colorize_lines))
987 +
988 + # Close p before calling processor
989 + # TODO: do we really need this?
990 + self.request.write(self._closeP())
991 + res = self.formatter.processor(self.processor_name,
992 + self.colorize_lines,
993 + self.processor_is_parser)
994 + self.request.write(res)
995 del self.colorize_lines
996 self.in_pre = 0
997 self.processor = None
998 @@ -974,19 +1036,23 @@
999 # send rest of line through regex machinery
1000 line = line[endpos+3:]
1001 else:
1002 - # paragraph break on empty lines
1003 + # we don't have \n as whitespace any more
1004 + # This is the space between lines we join to one paragraph
1005 + line = line + ' '
1006 +
1007 + # Paragraph break on empty lines
1008 if not line.strip():
1009 - #self.request.write("<!-- empty line start -->\n")
1010 - if self.formatter.in_p:
1011 - self.request.write(self.formatter.paragraph(0))
1012 if self.in_table:
1013 self.request.write(self.formatter.table(0))
1014 self.in_table = 0
1015 + # CHANGE: removed check for not self.list_types
1016 + # p should close on every empty line
1017 + if (self.formatter.in_p):
1018 + self.request.write(self.formatter.paragraph(0))
1019 self.line_is_empty = 1
1020 - #self.request.write("<!-- empty line end -->\n")
1021 continue
1022
1023 - # check indent level
1024 + # Check indent level
1025 indent = indent_re.match(line)
1026 indlen = len(indent.group(0))
1027 indtype = "ul"
1028 @@ -1010,45 +1076,50 @@
1029 indtype = "dl"
1030
1031 # output proper indentation tags
1032 - #self.request.write("<!-- inhibit_p==%d -->\n" % self.inhibit_p)
1033 - #self.request.write("<!-- #%d calling _indent_to -->\n" % self.lineno)
1034 - self.request.write(self._indent_to(indlen, indtype, numtype, numstart))
1035 - #self.request.write("<!-- #%d after calling _indent_to -->\n" % self.lineno)
1036 - #self.request.write("<!-- inhibit_p==%d -->\n" % self.inhibit_p)
1037 + self.request.write(self._indent_to(indlen, indtype, numtype,
1038 + numstart))
1039
1040 - # start or end table mode
1041 - if not self.in_table and line[indlen:indlen+2] == "||" and line[-2:] == "||":
1042 + # Table mode
1043 + # TODO: move into function?
1044 + if (not self.in_table and line[indlen:indlen + 2] == "||"
1045 + and line[-3:] == "|| " and len(line) >= 5 + indlen):
1046 + # Start table
1047 + if self.list_types and not self.in_li:
1048 + self.request.write(self.formatter.listitem
1049 + (1, style="list-style-type:none"))
1050 + ## CHANGE: no automatic p on li
1051 + ##self.request.write(self.formatter.paragraph(1))
1052 + self.in_li = 1
1053 +
1054 + # CHANGE: removed check for self.in_li
1055 + # paragraph should end before table, always!
1056 + if self.formatter.in_p:
1057 + self.request.write(self.formatter.paragraph(0))
1058 attrs, attrerr = self._getTableAttrs(line[indlen+2:])
1059 self.request.write(self.formatter.table(1, attrs) + attrerr)
1060 - self.in_table = self.lineno
1061 - elif self.in_table and not(line[:2]=="##" or # intra-table comments should not break a table
1062 - line[indlen:indlen+2] == "||" and line[-2:] == "||"):
1063 + self.in_table = True # self.lineno
1064 + elif (self.in_table and not
1065 + # intra-table comments should not break a table
1066 + (line[:2]=="##" or
1067 + line[indlen:indlen + 2] == "||" and
1068 + line[-3:] == "|| " and
1069 + len(line) >= 5 + indlen)):
1070 +
1071 + # Close table
1072 self.request.write(self.formatter.table(0))
1073 self.in_table = 0
1074 -
1075 - # convert line from wiki markup to HTML and print it
1076 - if not self.in_pre: # we don't want to have trailing blanks in pre
1077 - line = line + " " # we don't have \n as whitespace any more
1078 -
1079 - formatted_line = self.scan(scan_re, line) # this also sets self.inhibit_p as side effect!
1080 -
1081 - #self.request.write("<!-- inhibit_p==%d -->\n" % self.inhibit_p)
1082 - if not (self.inhibit_p or self.in_pre or self.in_table or self.formatter.in_p):
1083 - self.request.write(self.formatter.paragraph(1))
1084 -
1085 - #self.request.write("<!-- %s\n start -->\n" % line)
1086 +
1087 + # Scan line, format and write
1088 + formatted_line = self.scan(scan_re, line)
1089 self.request.write(formatted_line)
1090 - #self.request.write("<!-- end -->\n")
1091
1092 if self.in_pre:
1093 self.request.write(self.formatter.linebreak())
1094 - #if self.in_li:
1095 - # self.in_li = 0
1096 - # self.request.write(self.formatter.listitem(0))
1097
1098 - # close code displays, paragraphs, tables and open lists
1099 + # Close code displays, paragraphs, tables and open lists
1100 + self.request.write(self._undent())
1101 if self.in_pre: self.request.write(self.formatter.preformatted(0))
1102 if self.formatter.in_p: self.request.write(self.formatter.paragraph(0))
1103 if self.in_table: self.request.write(self.formatter.table(0))
1104 - self.request.write(self._undent())
1105 +
1106
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.