|
tw@2613
|
1 |
# -*- coding: iso-8859-1 -*-
|
|
tw@2614
|
2 |
"""
|
|
tw@2614
|
3 |
MoinMoin - Creole wiki markup parser
|
|
tw@2613
|
4 |
|
|
tw@2614
|
5 |
See http://wikicreole.org/ for latest specs.
|
|
tw@2613
|
6 |
|
|
tw@2616
|
7 |
Notes:
|
|
tw@2616
|
8 |
* No markup allowed in headings.
|
|
tw@2616
|
9 |
Creole 1.0 does not require us to support this.
|
|
tw@2616
|
10 |
* No markup allowed in table headings.
|
|
tw@2616
|
11 |
Creole 1.0 does not require us to support this.
|
|
tw@2616
|
12 |
* No (non-bracketed) generic url recognition: this is "mission impossible"
|
|
moindev@2858
|
13 |
except if you want to risk lots of false positives. Only known protocols
|
|
moindev@2858
|
14 |
are recognized.
|
|
moindev@2858
|
15 |
* We do not allow ":" before "//" italic markup to avoid urls with
|
|
moindev@2858
|
16 |
unrecognized schemes (like wtf://server/path) triggering italic rendering
|
|
moindev@2858
|
17 |
for the rest of the paragraph.
|
|
tw@2616
|
18 |
|
|
tw@2614
|
19 |
@copyright: 2007 MoinMoin:RadomirDopieralski (creole 0.5 implementation),
|
|
tw@2614
|
20 |
2007 MoinMoin:ThomasWaldmann (updates)
|
|
tw@2614
|
21 |
@license: GNU GPL, see COPYING for details.
|
|
tw@2613
|
22 |
"""
|
|
tw@2613
|
23 |
|
|
tw@2613
|
24 |
import re
|
|
tw@2613
|
25 |
import StringIO
|
|
moindev@2960
|
26 |
from MoinMoin import config, wikiutil
|
|
moindev@2960
|
27 |
from MoinMoin.macro import Macro
|
|
moindev@2890
|
28 |
from _creole import Parser as CreoleParser
|
|
tw@2613
|
29 |
|
|
tw@2613
|
30 |
Dependencies = []
|
|
tw@2613
|
31 |
|
|
johannes@3784
|
32 |
_ = lambda x: x
|
|
johannes@3784
|
33 |
|
|
tw@2613
|
34 |
class Parser:
|
|
tw@2613
|
35 |
"""
|
|
moindev@2857
|
36 |
Glue the DocParser and DocEmitter with the
|
|
tw@2613
|
37 |
MoinMoin current API.
|
|
tw@2613
|
38 |
"""
|
|
moindev@2858
|
39 |
|
|
tw@2613
|
40 |
# Enable caching
|
|
tw@2613
|
41 |
caching = 1
|
|
moindev@2858
|
42 |
Dependencies = Dependencies
|
|
johannes@3784
|
43 |
quickhelp = _(u"""\
|
|
johannes@3784
|
44 |
Emphasis:: <<Verbatim(//)>>''italics''<<Verbatim(//)>>; <<Verbatim(**)>>'''bold'''<<Verbatim(**)>>; <<Verbatim(**//)>>'''''bold italics'''''<<Verbatim(//**)>>; <<Verbatim(//)>>''mixed ''<<Verbatim(**)>>'''''bold'''<<Verbatim(**)>> and italics''<<Verbatim(//)>>;
|
|
johannes@3784
|
45 |
Horizontal Rule:: <<Verbatim(----)>>
|
|
johannes@3784
|
46 |
Force Linebreak:: <<Verbatim(\\\\)>>
|
|
johannes@3784
|
47 |
Headings:: = Title 1 =; == Title 2 ==; === Title 3 ===; ==== Title 4 ====; ===== Title 5 =====.
|
|
johannes@3784
|
48 |
Lists:: * bullets; ** sub-bullets; # numbered items; ## numbered sub items.
|
|
johannes@3784
|
49 |
Links:: <<Verbatim([[target]])>>; <<Verbatim([[target|linktext]])>>.
|
|
johannes@3784
|
50 |
Tables:: |= header text | cell text | more cell text |;
|
|
johannes@3784
|
51 |
|
|
johannes@3784
|
52 |
(!) For more help, see HelpOnEditing or HelpOnCreoleSyntax.
|
|
johannes@3784
|
53 |
""")
|
|
tw@2613
|
54 |
|
|
tw@2613
|
55 |
def __init__(self, raw, request, **kw):
|
|
tw@2613
|
56 |
"""Create a minimal Parser object with required attributes."""
|
|
moindev@2858
|
57 |
|
|
tw@2613
|
58 |
self.request = request
|
|
tw@2613
|
59 |
self.form = request.form
|
|
tw@2613
|
60 |
self.raw = raw
|
|
tw@2613
|
61 |
|
|
tw@2613
|
62 |
def format(self, formatter):
|
|
tw@2613
|
63 |
"""Create and call the true parser and emitter."""
|
|
moindev@2858
|
64 |
|
|
moindev@2895
|
65 |
document = CreoleParser(self.raw).parse()
|
|
moindev@2960
|
66 |
result = Emitter(document, formatter, self.request, Macro(self)).emit()
|
|
tw@2613
|
67 |
self.request.write(result)
|
|
tw@2613
|
68 |
|
|
moindev@2890
|
69 |
class Rules:
|
|
moindev@2890
|
70 |
# For the link targets:
|
|
moindev@2890
|
71 |
proto = r'http|https|ftp|nntp|news|mailto|telnet|file|irc'
|
|
moindev@2890
|
72 |
extern = r'(?P<extern_addr>(?P<extern_proto>%s):.*)' % proto
|
|
moindev@2890
|
73 |
attach = r'''
|
|
moindev@2890
|
74 |
(?P<attach_scheme> attachment | drawing | image ):
|
|
moindev@2890
|
75 |
(?P<attach_addr> .* )
|
|
moindev@2890
|
76 |
'''
|
|
moindev@2890
|
77 |
interwiki = r'''
|
|
moindev@2890
|
78 |
(?P<inter_wiki> [A-Z][a-zA-Z]+ ) :
|
|
moindev@2890
|
79 |
(?P<inter_page> .* )
|
|
moindev@2890
|
80 |
'''
|
|
moindev@2890
|
81 |
page = r'(?P<page_name> .* )'
|
|
moindev@2890
|
82 |
|
|
moindev@2890
|
83 |
|
|
moindev@2889
|
84 |
class Emitter:
|
|
moindev@2857
|
85 |
"""
|
|
moindev@2857
|
86 |
Generate the output for the document
|
|
moindev@2857
|
87 |
tree consisting of DocNodes.
|
|
moindev@2857
|
88 |
"""
|
|
tw@2613
|
89 |
|
|
moindev@2870
|
90 |
addr_re = re.compile('|'.join([
|
|
moindev@2890
|
91 |
Rules.extern,
|
|
moindev@2890
|
92 |
Rules.attach,
|
|
moindev@2890
|
93 |
Rules.interwiki,
|
|
moindev@2890
|
94 |
Rules.page
|
|
moindev@2870
|
95 |
]), re.X | re.U) # for addresses
|
|
moindev@2870
|
96 |
|
|
moindev@2960
|
97 |
def __init__(self, root, formatter, request, macro):
|
|
tw@2613
|
98 |
self.root = root
|
|
tw@2613
|
99 |
self.formatter = formatter
|
|
tw@2613
|
100 |
self.request = request
|
|
tw@2613
|
101 |
self.form = request.form
|
|
moindev@2960
|
102 |
self.macro = macro
|
|
tw@2613
|
103 |
|
|
tw@2613
|
104 |
def get_text(self, node):
|
|
tw@2613
|
105 |
"""Try to emit whatever text is in the node."""
|
|
moindev@2857
|
106 |
|
|
tw@2613
|
107 |
try:
|
|
tw@2613
|
108 |
return node.children[0].content or ''
|
|
tw@2613
|
109 |
except:
|
|
tw@2613
|
110 |
return node.content or ''
|
|
tw@2613
|
111 |
|
|
tw@2613
|
112 |
# *_emit methods for emitting nodes of the document:
|
|
tw@2613
|
113 |
|
|
tw@2613
|
114 |
def document_emit(self, node):
|
|
tw@2613
|
115 |
return self.emit_children(node)
|
|
tw@2613
|
116 |
|
|
tw@2613
|
117 |
def text_emit(self, node):
|
|
tw@2613
|
118 |
return self.formatter.text(node.content or '')
|
|
tw@2613
|
119 |
|
|
moindev@2865
|
120 |
def separator_emit(self, node):
|
|
tw@2613
|
121 |
return self.formatter.rule()
|
|
tw@2613
|
122 |
|
|
tw@2613
|
123 |
def paragraph_emit(self, node):
|
|
tw@2613
|
124 |
return ''.join([
|
|
tw@2613
|
125 |
self.formatter.paragraph(1),
|
|
tw@2613
|
126 |
self.emit_children(node),
|
|
tw@2613
|
127 |
self.formatter.paragraph(0),
|
|
tw@2613
|
128 |
])
|
|
tw@2613
|
129 |
|
|
tw@2613
|
130 |
def bullet_list_emit(self, node):
|
|
tw@2613
|
131 |
return ''.join([
|
|
tw@2613
|
132 |
self.formatter.bullet_list(1),
|
|
tw@2613
|
133 |
self.emit_children(node),
|
|
tw@2613
|
134 |
self.formatter.bullet_list(0),
|
|
tw@2613
|
135 |
])
|
|
tw@2613
|
136 |
|
|
tw@2613
|
137 |
def number_list_emit(self, node):
|
|
tw@2613
|
138 |
return ''.join([
|
|
tw@2613
|
139 |
self.formatter.number_list(1),
|
|
tw@2613
|
140 |
self.emit_children(node),
|
|
tw@2613
|
141 |
self.formatter.number_list(0),
|
|
tw@2613
|
142 |
])
|
|
tw@2613
|
143 |
|
|
tw@2613
|
144 |
def list_item_emit(self, node):
|
|
tw@2613
|
145 |
return ''.join([
|
|
tw@2613
|
146 |
self.formatter.listitem(1),
|
|
tw@2613
|
147 |
self.emit_children(node),
|
|
tw@2613
|
148 |
self.formatter.listitem(0),
|
|
tw@2613
|
149 |
])
|
|
tw@2613
|
150 |
|
|
moindev@2864
|
151 |
# Not used
|
|
moindev@2864
|
152 |
# def definition_list_emit(self, node):
|
|
moindev@2864
|
153 |
# return ''.join([
|
|
moindev@2864
|
154 |
# self.formatter.definition_list(1),
|
|
moindev@2864
|
155 |
# self.emit_children(node),
|
|
moindev@2864
|
156 |
# self.formatter.definition_list(0),
|
|
moindev@2864
|
157 |
# ])
|
|
tw@2613
|
158 |
|
|
moindev@2864
|
159 |
# Not used
|
|
moindev@2864
|
160 |
# def term_emit(self, node):
|
|
moindev@2864
|
161 |
# return ''.join([
|
|
moindev@2864
|
162 |
# self.formatter.definition_term(1),
|
|
moindev@2864
|
163 |
# self.emit_children(node),
|
|
moindev@2864
|
164 |
# self.formatter.definition_term(0),
|
|
moindev@2864
|
165 |
# ])
|
|
tw@2613
|
166 |
|
|
moindev@2864
|
167 |
# Not used
|
|
moindev@2864
|
168 |
# def definition_emit(self, node):
|
|
moindev@2864
|
169 |
# return ''.join([
|
|
moindev@2864
|
170 |
# self.formatter.definition_desc(1),
|
|
moindev@2864
|
171 |
# self.emit_children(node),
|
|
moindev@2864
|
172 |
# self.formatter.definition_desc(0),
|
|
moindev@2864
|
173 |
# ])
|
|
tw@2613
|
174 |
|
|
tw@2613
|
175 |
def table_emit(self, node):
|
|
tw@2613
|
176 |
return ''.join([
|
|
tw@2613
|
177 |
self.formatter.table(1, attrs=getattr(node, 'attrs', '')),
|
|
tw@2613
|
178 |
self.emit_children(node),
|
|
tw@2613
|
179 |
self.formatter.table(0),
|
|
tw@2613
|
180 |
])
|
|
tw@2613
|
181 |
|
|
tw@2613
|
182 |
def table_row_emit(self, node):
|
|
tw@2613
|
183 |
return ''.join([
|
|
tw@2613
|
184 |
self.formatter.table_row(1, attrs=getattr(node, 'attrs', '')),
|
|
tw@2613
|
185 |
self.emit_children(node),
|
|
tw@2613
|
186 |
self.formatter.table_row(0),
|
|
tw@2613
|
187 |
])
|
|
tw@2613
|
188 |
|
|
tw@2613
|
189 |
def table_cell_emit(self, node):
|
|
tw@2613
|
190 |
return ''.join([
|
|
tw@2613
|
191 |
self.formatter.table_cell(1, attrs=getattr(node, 'attrs', '')),
|
|
tw@2613
|
192 |
self.emit_children(node),
|
|
tw@2613
|
193 |
self.formatter.table_cell(0),
|
|
tw@2613
|
194 |
])
|
|
tw@2613
|
195 |
|
|
tw@2613
|
196 |
def table_head_emit(self, node):
|
|
tw@2613
|
197 |
return ''.join([
|
|
tw@2613
|
198 |
self.formatter.rawHTML('<th>'),
|
|
tw@2613
|
199 |
self.emit_children(node),
|
|
tw@2613
|
200 |
self.formatter.rawHTML('</th>'),
|
|
tw@2613
|
201 |
])
|
|
tw@2613
|
202 |
|
|
tw@2613
|
203 |
def emphasis_emit(self, node):
|
|
tw@2613
|
204 |
return ''.join([
|
|
tw@2613
|
205 |
self.formatter.emphasis(1),
|
|
tw@2613
|
206 |
self.emit_children(node),
|
|
tw@2613
|
207 |
self.formatter.emphasis(0),
|
|
tw@2613
|
208 |
])
|
|
tw@2613
|
209 |
|
|
moindev@2864
|
210 |
# Not used
|
|
moindev@2864
|
211 |
# def quote_emit(self, node):
|
|
moindev@2864
|
212 |
# return ''.join([
|
|
moindev@2864
|
213 |
# self.formatter.rawHTML('<q>'),
|
|
moindev@2864
|
214 |
# self.emit_children(node),
|
|
moindev@2864
|
215 |
# self.formatter.rawHTML('</q>'),
|
|
moindev@2864
|
216 |
# ])
|
|
tw@2613
|
217 |
|
|
tw@2613
|
218 |
def strong_emit(self, node):
|
|
tw@2613
|
219 |
return ''.join([
|
|
tw@2613
|
220 |
self.formatter.strong(1),
|
|
tw@2613
|
221 |
self.emit_children(node),
|
|
tw@2613
|
222 |
self.formatter.strong(0),
|
|
tw@2613
|
223 |
])
|
|
tw@2613
|
224 |
|
|
moindev@2864
|
225 |
# Not used
|
|
moindev@2864
|
226 |
# def smiley_emit(self, node):
|
|
moindev@2864
|
227 |
# return self.formatter.smiley(node.content)
|
|
tw@2613
|
228 |
|
|
tw@2613
|
229 |
def header_emit(self, node):
|
|
tw@4560
|
230 |
text = self.get_text(node)
|
|
tw@2613
|
231 |
return ''.join([
|
|
tw@4560
|
232 |
self.formatter.heading(1, node.level, id=text),
|
|
tw@4560
|
233 |
self.formatter.text(text),
|
|
tw@2613
|
234 |
self.formatter.heading(0, node.level),
|
|
tw@2613
|
235 |
])
|
|
tw@2613
|
236 |
|
|
tw@2613
|
237 |
def code_emit(self, node):
|
|
moindev@2858
|
238 |
# XXX The current formatter will replace all spaces with , so we need
|
|
moindev@2858
|
239 |
# to use rawHTML instead, until that is fixed.
|
|
moindev@2858
|
240 |
# return ''.join([
|
|
moindev@2858
|
241 |
# self.formatter.code(1),
|
|
moindev@2858
|
242 |
# self.formatter.text(node.content or ''),
|
|
moindev@2858
|
243 |
# self.formatter.code(0),
|
|
moindev@2858
|
244 |
# ])
|
|
tw@2613
|
245 |
return ''.join([
|
|
moindev@2858
|
246 |
self.formatter.rawHTML('<tt>'),
|
|
tw@2613
|
247 |
self.formatter.text(node.content or ''),
|
|
moindev@2858
|
248 |
self.formatter.rawHTML('</tt>'),
|
|
tw@2613
|
249 |
])
|
|
tw@2613
|
250 |
|
|
moindev@2864
|
251 |
# Not used
|
|
moindev@2864
|
252 |
# def abbr_emit(self, node):
|
|
moindev@2864
|
253 |
# return ''.join([
|
|
moindev@2864
|
254 |
# self.formatter.rawHTML('<abbr title="%s">' % node.title),
|
|
moindev@2864
|
255 |
# self.formatter.text(node.content or ''),
|
|
moindev@2864
|
256 |
# self.formatter.rawHTML('</abbr>'),
|
|
moindev@2864
|
257 |
# ])
|
|
tw@2613
|
258 |
|
|
moindev@2870
|
259 |
def link_emit(self, node):
|
|
moindev@2870
|
260 |
target = node.content
|
|
moindev@2870
|
261 |
m = self.addr_re.match(target)
|
|
moindev@2870
|
262 |
if m:
|
|
moindev@2870
|
263 |
if m.group('page_name'):
|
|
moindev@2870
|
264 |
# link to a page
|
|
moindev@2870
|
265 |
word = m.group('page_name')
|
|
moindev@2870
|
266 |
if word.startswith(wikiutil.PARENT_PREFIX):
|
|
moindev@2870
|
267 |
word = word[wikiutil.PARENT_PREFIX_LEN:]
|
|
moindev@2870
|
268 |
elif word.startswith(wikiutil.CHILD_PREFIX):
|
|
moindev@2870
|
269 |
word = "%s/%s" % (self.formatter.page.page_name,
|
|
moindev@2870
|
270 |
word[wikiutil.CHILD_PREFIX_LEN:])
|
|
tw@4493
|
271 |
word, anchor = wikiutil.split_anchor(word)
|
|
moindev@2870
|
272 |
return ''.join([
|
|
moindev@2870
|
273 |
self.formatter.pagelink(1, word, anchor=anchor),
|
|
moindev@3041
|
274 |
self.emit_children(node) or self.formatter.text(target),
|
|
moindev@2870
|
275 |
self.formatter.pagelink(0, word),
|
|
moindev@2870
|
276 |
])
|
|
moindev@2870
|
277 |
elif m.group('extern_addr'):
|
|
moindev@2870
|
278 |
# external link
|
|
moindev@2870
|
279 |
address = m.group('extern_addr')
|
|
moindev@2870
|
280 |
proto = m.group('extern_proto')
|
|
moindev@2870
|
281 |
return ''.join([
|
|
moindev@2870
|
282 |
self.formatter.url(1, address, css=proto),
|
|
moindev@3041
|
283 |
self.emit_children(node) or self.formatter.text(target),
|
|
moindev@2870
|
284 |
self.formatter.url(0),
|
|
moindev@2870
|
285 |
])
|
|
moindev@2870
|
286 |
elif m.group('inter_wiki'):
|
|
moindev@2870
|
287 |
# interwiki link
|
|
moindev@2870
|
288 |
wiki = m.group('inter_wiki')
|
|
moindev@2870
|
289 |
page = m.group('inter_page')
|
|
tw@4493
|
290 |
page, anchor = wikiutil.split_anchor(page)
|
|
moindev@2870
|
291 |
return ''.join([
|
|
tw@4493
|
292 |
self.formatter.interwikilink(1, wiki, page, anchor=anchor),
|
|
moindev@3041
|
293 |
self.emit_children(node) or self.formatter.text(page),
|
|
moindev@2870
|
294 |
self.formatter.interwikilink(0),
|
|
moindev@2870
|
295 |
])
|
|
moindev@2870
|
296 |
elif m.group('attach_scheme'):
|
|
moindev@2870
|
297 |
# link to an attachment
|
|
moindev@2870
|
298 |
scheme = m.group('attach_scheme')
|
|
moindev@2870
|
299 |
attachment = m.group('attach_addr')
|
|
tw@4569
|
300 |
url = wikiutil.url_unquote(attachment)
|
|
moindev@2870
|
301 |
text = self.get_text(node)
|
|
moindev@2870
|
302 |
return ''.join([
|
|
moindev@2870
|
303 |
self.formatter.attachment_link(1, url),
|
|
moindev@2870
|
304 |
self.formatter.text(text),
|
|
moindev@2870
|
305 |
self.formatter.attachment_link(0)
|
|
moindev@2870
|
306 |
])
|
|
moindev@2871
|
307 |
return "".join(["[[", self.formatter.text(target), "]]"])
|
|
tw@2613
|
308 |
|
|
moindev@2871
|
309 |
# Not used
|
|
moindev@2871
|
310 |
# def anchor_link_emit(self, node):
|
|
moindev@2871
|
311 |
# return ''.join([
|
|
moindev@2871
|
312 |
# self.formatter.url(1, node.content, css='anchor'),
|
|
moindev@2871
|
313 |
# self.emit_children(node),
|
|
moindev@2871
|
314 |
# self.formatter.url(0),
|
|
moindev@2871
|
315 |
# ])
|
|
tw@2613
|
316 |
|
|
moindev@2871
|
317 |
def image_emit(self, node):
|
|
moindev@2871
|
318 |
target = node.content
|
|
moindev@2871
|
319 |
text = self.get_text(node)
|
|
moindev@2871
|
320 |
m = self.addr_re.match(target)
|
|
moindev@2871
|
321 |
if m:
|
|
moindev@2871
|
322 |
if m.group('page_name'):
|
|
moindev@2872
|
323 |
# inserted anchors
|
|
tw@4569
|
324 |
url = wikiutil.url_unquote(target)
|
|
moindev@2872
|
325 |
if target.startswith('#'):
|
|
tw@4560
|
326 |
return self.formatter.anchordef(url[1:])
|
|
moindev@2871
|
327 |
# default to images
|
|
moindev@2871
|
328 |
return self.formatter.attachment_image(
|
|
moindev@2871
|
329 |
url, alt=text, html_class='image')
|
|
moindev@2871
|
330 |
elif m.group('extern_addr'):
|
|
moindev@2871
|
331 |
# external link
|
|
moindev@2871
|
332 |
address = m.group('extern_addr')
|
|
moindev@2871
|
333 |
proto = m.group('extern_proto')
|
|
tw@4569
|
334 |
url = wikiutil.url_unquote(address)
|
|
moindev@2871
|
335 |
return self.formatter.image(
|
|
moindev@2871
|
336 |
src=url, alt=text, html_class='external_image')
|
|
moindev@2871
|
337 |
elif m.group('attach_scheme'):
|
|
moindev@2871
|
338 |
# link to an attachment
|
|
moindev@2871
|
339 |
scheme = m.group('attach_scheme')
|
|
moindev@2871
|
340 |
attachment = m.group('attach_addr')
|
|
tw@4569
|
341 |
url = wikiutil.url_unquote(attachment)
|
|
moindev@2871
|
342 |
if scheme == 'image':
|
|
moindev@2871
|
343 |
return self.formatter.attachment_image(
|
|
moindev@2871
|
344 |
url, alt=text, html_class='image')
|
|
moindev@2871
|
345 |
elif scheme == 'drawing':
|
|
tw@4476
|
346 |
return self.formatter.attachment_drawing(url, text, alt=text)
|
|
moindev@2871
|
347 |
else:
|
|
moindev@2871
|
348 |
pass
|
|
moindev@2871
|
349 |
elif m.group('inter_wiki'):
|
|
moindev@2871
|
350 |
# interwiki link
|
|
moindev@2871
|
351 |
pass
|
|
moindev@2871
|
352 |
# return "".join(["{{", self.formatter.text(target), "}}"])
|
|
tw@4569
|
353 |
url = wikiutil.url_unquote(node.content)
|
|
tw@2613
|
354 |
return self.formatter.attachment_inlined(url, text)
|
|
tw@2613
|
355 |
|
|
moindev@2871
|
356 |
# Not used
|
|
moindev@2871
|
357 |
# def drawing_emit(self, node):
|
|
tw@4569
|
358 |
# url = wikiutil.url_unquote(node.content)
|
|
moindev@2871
|
359 |
# text = self.get_text(node)
|
|
moindev@2871
|
360 |
# return self.formatter.attachment_drawing(url, text)
|
|
tw@2613
|
361 |
|
|
moindev@2871
|
362 |
# Not used
|
|
moindev@2871
|
363 |
# def figure_emit(self, node):
|
|
moindev@2871
|
364 |
# text = self.get_text(node)
|
|
tw@4569
|
365 |
# url = wikiutil.url_unquote(node.content)
|
|
moindev@2871
|
366 |
# return ''.join([
|
|
moindev@2871
|
367 |
# self.formatter.rawHTML('<div class="figure">'),
|
|
moindev@2871
|
368 |
# self.get_image(url, text), self.emit_children(node),
|
|
moindev@2871
|
369 |
# self.formatter.rawHTML('</div>'),
|
|
moindev@2871
|
370 |
# ])
|
|
tw@2613
|
371 |
|
|
moindev@2871
|
372 |
# Not used
|
|
moindev@2871
|
373 |
# def bad_link_emit(self, node):
|
|
moindev@2871
|
374 |
# return self.formatter.text(''.join([
|
|
moindev@2871
|
375 |
# '[[',
|
|
moindev@2871
|
376 |
# node.content or '',
|
|
moindev@2871
|
377 |
# ']]',
|
|
moindev@2871
|
378 |
# ]))
|
|
tw@2613
|
379 |
|
|
tw@2613
|
380 |
def macro_emit(self, node):
|
|
tw@2613
|
381 |
macro_name = node.content
|
|
tw@2613
|
382 |
args = node.args
|
|
moindev@2963
|
383 |
return self.formatter.macro(self.macro, macro_name, args)
|
|
tw@2613
|
384 |
|
|
moindev@2864
|
385 |
# Not used
|
|
moindev@2864
|
386 |
# def section_emit(self, node):
|
|
moindev@2864
|
387 |
# return ''.join([
|
|
moindev@2864
|
388 |
# self.formatter.rawHTML(
|
|
moindev@2864
|
389 |
# '<div class="%s" style="%s">' % (node.sect, node.style)),
|
|
moindev@2864
|
390 |
# self.emit_children(node),
|
|
moindev@2864
|
391 |
# self.formatter.rawHTML('</div>'),
|
|
moindev@2864
|
392 |
# ])
|
|
tw@2613
|
393 |
|
|
tw@2613
|
394 |
def break_emit(self, node):
|
|
moindev@2868
|
395 |
return self.formatter.linebreak(preformatted=0)
|
|
tw@2613
|
396 |
|
|
moindev@2864
|
397 |
# Not used
|
|
moindev@2864
|
398 |
# def blockquote_emit(self, node):
|
|
moindev@2864
|
399 |
# return ''.join([
|
|
moindev@2864
|
400 |
# self.formatter.rawHTML('<blockquote>'),
|
|
moindev@2864
|
401 |
# self.emit_children(node),
|
|
moindev@2864
|
402 |
# self.formatter.rawHTML('</blockquote>'),
|
|
moindev@2864
|
403 |
# ])
|
|
tw@2613
|
404 |
|
|
tw@2613
|
405 |
def preformatted_emit(self, node):
|
|
tw@2620
|
406 |
parser_name = getattr(node, 'sect', '')
|
|
tw@2620
|
407 |
if parser_name:
|
|
moindev@2963
|
408 |
# The formatter.parser will *sometimes* just return the result
|
|
moindev@2963
|
409 |
# and *sometimes* try to write it directly. We need to take both
|
|
moindev@2963
|
410 |
# cases into account!
|
|
moindev@2963
|
411 |
lines = node.content.split(u'\n')
|
|
moindev@2963
|
412 |
buf = StringIO.StringIO()
|
|
moindev@2866
|
413 |
try:
|
|
moindev@2963
|
414 |
try:
|
|
moindev@2963
|
415 |
self.request.redirect(buf)
|
|
moindev@2963
|
416 |
ret = self.formatter.parser(parser_name, lines)
|
|
moindev@2963
|
417 |
finally:
|
|
moindev@2963
|
418 |
self.request.redirect()
|
|
moindev@2963
|
419 |
buf.flush()
|
|
moindev@2963
|
420 |
writ = buf.getvalue()
|
|
moindev@2963
|
421 |
buf.close()
|
|
rb@3070
|
422 |
return ret + writ
|
|
moindev@2866
|
423 |
except wikiutil.PluginMissingError:
|
|
moindev@2866
|
424 |
pass
|
|
moindev@2866
|
425 |
return ''.join([
|
|
moindev@2866
|
426 |
self.formatter.preformatted(1),
|
|
moindev@2866
|
427 |
self.formatter.text(node.content),
|
|
moindev@2866
|
428 |
self.formatter.preformatted(0),
|
|
moindev@2866
|
429 |
])
|
|
tw@2613
|
430 |
|
|
tw@2613
|
431 |
def default_emit(self, node):
|
|
moindev@2868
|
432 |
"""Fallback function for emitting unknown nodes."""
|
|
moindev@2868
|
433 |
|
|
tw@2613
|
434 |
return ''.join([
|
|
tw@2613
|
435 |
self.formatter.preformatted(1),
|
|
tw@2613
|
436 |
self.formatter.text('<%s>\n' % node.kind),
|
|
tw@2613
|
437 |
self.emit_children(node),
|
|
tw@2613
|
438 |
self.formatter.preformatted(0),
|
|
tw@2613
|
439 |
])
|
|
tw@2613
|
440 |
|
|
tw@2613
|
441 |
def emit_children(self, node):
|
|
tw@2613
|
442 |
"""Emit all the children of a node."""
|
|
moindev@2868
|
443 |
|
|
tw@2613
|
444 |
return ''.join([self.emit_node(child) for child in node.children])
|
|
tw@2613
|
445 |
|
|
tw@2613
|
446 |
def emit_node(self, node):
|
|
moindev@2868
|
447 |
"""Emit a single node."""
|
|
moindev@2868
|
448 |
|
|
moindev@2864
|
449 |
emit = getattr(self, '%s_emit' % node.kind, self.default_emit)
|
|
tw@2613
|
450 |
return emit(node)
|
|
tw@2613
|
451 |
|
|
tw@2613
|
452 |
def emit(self):
|
|
moindev@2868
|
453 |
"""Emit the document represented by self.root DOM tree."""
|
|
moindev@2868
|
454 |
|
|
tw@2613
|
455 |
# Try to disable 'smart' formatting if possible
|
|
tw@2613
|
456 |
magic_save = getattr(self.formatter, 'no_magic', False)
|
|
tw@2613
|
457 |
self.formatter.no_magic = True
|
|
tw@2613
|
458 |
output = '\n'.join([
|
|
tw@2613
|
459 |
self.emit_node(self.root),
|
|
tw@2613
|
460 |
])
|
|
moindev@2864
|
461 |
# restore 'smart' formatting if it was set
|
|
tw@2613
|
462 |
self.formatter.no_magic = magic_save
|
|
tw@2613
|
463 |
return output
|
|
johannes@3784
|
464 |
|
|
johannes@3784
|
465 |
del _
|