Dateianhang 'gaga2.py'

Herunterladen

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

Gespeicherte Dateianhänge

Um Dateianhänge in eine Seite einzufügen sollte unbedingt eine Angabe wie attachment:dateiname benutzt werden, wie sie auch in der folgenden Liste der Dateien erscheint. Es sollte niemals die URL des Verweises ("laden") kopiert werden, da sich diese jederzeit ändern kann und damit der Verweis auf die Datei brechen würde.
  • [laden | anzeigen] (2003-01-06 21:05:53, 34.5 KB) [[attachment:gaga2.py]]
  • [laden | anzeigen] (2003-01-06 19:48:20, 1.8 KB) [[attachment:trie.py]]
 Alle Dateien | Ausgewählte Dateien: löschen verschieben auf Seite kopieren auf Seite

Sie dürfen keine Anhänge an diese Seite anhängen!