~ubuntu-branches/ubuntu/oneiric/moin/oneiric-security

« back to all changes in this revision

Viewing changes to MoinMoin/parser/_creole.py

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-03-30 12:55:34 UTC
  • mfrom: (0.1.17 sid)
  • Revision ID: james.westby@ubuntu.com-20100330125534-4c2ufc1rok24447l
Tags: 1.9.2-2ubuntu1
* Merge from Debian testing (LP: #521834). Based on work by Stefan Ebner.
  Remaining changes:
 - Remove python-xml from Suggests field, the package isn't anymore in
   sys.path.
 - Demote fckeditor from Recommends to Suggests; the code was previously
   embedded in moin, but it was also disabled, so there's no reason for us
   to pull this in by default currently. Note: This isn't necessary anymore
   but needs a MIR for fckeditor, so postpone dropping this change until
   lucid+1
* debian/rules:
  - Replace hardcoded python2.5 with python* and hardcore python2.6 for ln
* debian/control.in: drop versioned depends on cdbs

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
"""
24
24
 
25
25
import re
26
 
 
27
 
# Whether the parser should convert \n into <br>.
28
 
bloglike_lines = False
 
26
import sys
 
27
 
 
28
__version__ = '1.1'
 
29
 
29
30
 
30
31
class Rules:
31
32
    """Hold all the rules for generating regular expressions."""
32
33
 
33
34
    # For the inline elements:
34
35
    proto = r'http|https|ftp|nntp|news|mailto|telnet|file|irc'
35
 
    url =  r'''(?P<url>
36
 
            (^ | (?<=\s | [.,:;!?()/=]))
37
 
            (?P<escaped_url>~)?
38
 
            (?P<url_target> (?P<url_proto> %s ):\S+? )
39
 
            ($ | (?=\s | [,.:;!?()] (\s | $)))
40
 
        )''' % proto
41
36
    link = r'''(?P<link>
42
37
            \[\[
43
38
            (?P<link_target>.+?) \s*
76
71
            (?P<head_tail>=*) \s*
77
72
            $
78
73
        )'''
79
 
    if bloglike_lines:
80
 
        text = r'(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?'
81
 
    else:
82
 
        text = r'(?P<text> .+ )'
 
74
    text = r'(?P<text> .+ )'
83
75
    list = r'''(?P<list>
84
76
            ^ [ \t]* ([*][^*\#]|[\#][^\#*]).* $
85
77
            ( \n[ \t]* [*\#]+.* $ )*
118
110
            ) \s*
119
111
        ''' % '|'.join([link, macro, image, code])
120
112
 
 
113
    def __init__(self, bloglike_lines=False, url_protocols=None,
 
114
                 wiki_words=False):
 
115
        c = re.compile
 
116
        # For pre escaping, in creole 1.0 done with ~:
 
117
        self.pre_escape_re = c(self.pre_escape, re.M | re.X)
 
118
        # for link descriptions
 
119
        self.link_re = c('|'.join([self.image, self.linebreak,
 
120
                                   self.char]), re.X | re.U)
 
121
        # for list items
 
122
        self.item_re = c(self.item, re.X | re.U | re.M)
 
123
        # for table cells
 
124
        self.cell_re = c(self.cell, re.X | re.U)
 
125
 
 
126
        # For block elements:
 
127
        if bloglike_lines:
 
128
            self.text = r'(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?'
 
129
        self.block_re = c('|'.join([self.line, self.head, self.separator,
 
130
                                    self.pre, self.list, self.table,
 
131
                                    self.text]), re.X | re.U | re.M)
 
132
 
 
133
        # For inline elements:
 
134
        if url_protocols is not None:
 
135
            self.proto = '|'.join(re.escape(p) for p in url_protocols)
 
136
        self.url =  r'''(?P<url>
 
137
            (^ | (?<=\s | [.,:;!?()/=]))
 
138
            (?P<escaped_url>~)?
 
139
            (?P<url_target> (?P<url_proto> %s ):\S+? )
 
140
            ($ | (?=\s | [,.:;!?()] (\s | $))))''' % self.proto
 
141
        inline_elements = [self.link, self.url, self.macro,
 
142
                           self.code, self.image, self.strong,
 
143
                           self.emph, self.linebreak,
 
144
                           self.escape, self.char]
 
145
        if wiki_words:
 
146
            import unicodedata
 
147
            up_case = u''.join(unichr(i) for i in xrange(sys.maxunicode)
 
148
                               if unicodedata.category(unichr(i))=='Lu')
 
149
            self.wiki = ur'''(?P<wiki>[%s]\w+[%s]\w+)''' % (up_case, up_case)
 
150
            inline_elements.insert(3, self.wiki)
 
151
        self.inline_re = c('|'.join(inline_elements), re.X | re.U)
 
152
 
121
153
class Parser:
122
154
    """
123
155
    Parse the raw text and create a document object
124
156
    that can be converted into output using Emitter.
 
157
 
 
158
    A separate instance should be created for parsing a new document.
 
159
    The first parameter is the raw text to be parsed. An optional second
 
160
    argument is the Rules object to use. You can customize the parsing
 
161
    rules to enable optional features or extend the parser.
125
162
    """
126
163
 
127
 
    # For pre escaping, in creole 1.0 done with ~:
128
 
    pre_escape_re = re.compile(Rules.pre_escape, re.M | re.X)
129
 
    link_re = re.compile('|'.join([Rules.image, Rules.linebreak, Rules.char]), re.X | re.U) # for link descriptions
130
 
    item_re = re.compile(Rules.item, re.X | re.U | re.M) # for list items
131
 
    cell_re = re.compile(Rules.cell, re.X | re.U) # for table cells
132
 
    # For block elements:
133
 
    block_re = re.compile('|'.join([Rules.line, Rules.head, Rules.separator,
134
 
        Rules.pre, Rules.list, Rules.table, Rules.text]), re.X | re.U | re.M)
135
 
    # For inline elements:
136
 
    inline_re = re.compile('|'.join([Rules.link, Rules.url, Rules.macro,
137
 
        Rules.code, Rules.image, Rules.strong, Rules.emph, Rules.linebreak,
138
 
        Rules.escape, Rules.char]), re.X | re.U)
139
 
 
140
 
    def __init__(self, raw):
 
164
    def __init__(self, raw, rules=None):
 
165
        self.rules = rules or Rules()
141
166
        self.raw = raw
142
167
        self.root = DocNode('document', None)
143
168
        self.cur = self.root        # The most recent document node
184
209
        self.cur = DocNode('link', self.cur)
185
210
        self.cur.content = target
186
211
        self.text = None
187
 
        re.sub(self.link_re, self._replace, text)
 
212
        re.sub(self.rules.link_re, self._replace, text)
188
213
        self.cur = parent
189
214
        self.text = None
190
215
    _link_target_repl = _link_repl
191
216
    _link_text_repl = _link_repl
192
217
 
 
218
    def _wiki_repl(self, groups):
 
219
        """Handle WikiWord links, if enabled."""
 
220
 
 
221
        text = groups.get('wiki', '')
 
222
        node = DocNode('link', self.cur)
 
223
        node.content = text
 
224
        DocNode('text', node, node.content)
 
225
        self.text = None
 
226
 
193
227
    def _macro_repl(self, groups):
194
228
        """Handles macros using the placeholder syntax."""
195
229
 
249
283
 
250
284
    def _list_repl(self, groups):
251
285
        text = groups.get('list', u'')
252
 
        self.item_re.sub(self._replace, text)
 
286
        self.rules.item_re.sub(self._replace, text)
253
287
 
254
288
    def _head_repl(self, groups):
255
289
        self.cur = self._upto(self.cur, ('document', 'section', 'blockquote'))
285
319
        tr = DocNode('table_row', tb)
286
320
 
287
321
        text = ''
288
 
        for m in self.cell_re.finditer(row):
 
322
        for m in self.rules.cell_re.finditer(row):
289
323
            cell = m.group('cell')
290
324
            if cell:
291
325
                self.cur = DocNode('table_cell', tr)
305
339
        text = groups.get('pre_text', u'')
306
340
        def remove_tilde(m):
307
341
            return m.group('indent') + m.group('rest')
308
 
        text = self.pre_escape_re.sub(remove_tilde, text)
 
342
        text = self.rules.pre_escape_re.sub(remove_tilde, text)
309
343
        node = DocNode('preformatted', self.cur, text)
310
344
        node.sect = kind or ''
311
345
        self.text = None
363
397
    def parse_inline(self, raw):
364
398
        """Recognize inline elements inside blocks."""
365
399
 
366
 
        re.sub(self.inline_re, self._replace, raw)
 
400
        re.sub(self.rules.inline_re, self._replace, raw)
367
401
 
368
402
    def parse_block(self, raw):
369
403
        """Recognize block elements."""
370
404
 
371
 
        re.sub(self.block_re, self._replace, raw)
 
405
        re.sub(self.rules.block_re, self._replace, raw)
372
406
 
373
407
    def parse(self):
374
408
        """Parse the text given as self.raw and return DOM tree."""
378
412
 
379
413
#################### Helper classes
380
414
 
381
 
### The document model and emitter follow
 
415
### The document model
382
416
 
383
417
class DocNode:
384
418
    """