1
# -*- coding: utf-8 -*-
3
MoinMoin - docbook Formatter
5
@copyright: 2005 by Mikko Virkkil�<mvirkkil@cc.hut.fi>
6
@license: GNU GPL, see COPYING for details.
9
from MoinMoin.formatter.base import FormatterBase
10
from MoinMoin import wikiutil, i18n, config
11
from xml.sax import saxutils
13
class Formatter(FormatterBase):
18
hardspace = u'###CRAP###'
20
section_should_break = ["abstract",'para', 'emphasis']
22
def __init__(self, request, **kw):
23
'''We should use this for creating the doc'''
24
apply(FormatterBase.__init__, (self, request), kw)
25
from xml.dom import getDOMImplementation
26
dom = getDOMImplementation( "4DOM" )
27
self.doc = dom.createDocument(None, "article", dom.createDocumentType("article","-//OASIS//DTD DocBook V4.3//EN","http://www.docbook.org/xml/4.3/docbookx.dtd" ))
28
self.root = self.doc.documentElement
31
def startDocument(self, pagename):
32
info = self.doc.createElement("articleinfo")
33
title = self.doc.createElement("title")
34
title.appendChild( self.doc.createTextNode(pagename) )
35
info.appendChild(title)
36
self.root.appendChild(info)
39
def startContent(self, content_id="content", **kwargs):
44
def endDocument(self):
45
from xml.dom.ext import PrettyPrint
48
a=StringIO.StringIO(txt)
49
PrettyPrint(self.doc,a)
55
self.cur.appendChild( self.doc.createTextNode(text) )
60
def heading(self, on, depth, **kw):
61
while self.cur.nodeName in self.section_should_break:
62
self.cur=self.cur.parentNode
65
if depth <= self.realdepth:
66
for i in range(depth, self.realdepth):
67
while(self.cur.nodeName!="section"):
68
self.cur=self.cur.parentNode
70
if len(self.cur.childNodes)<3:
71
self._addEmptyNode("para")
73
self.cur=self.cur.parentNode
76
section = self.doc.createElement("section")
77
self.cur.appendChild(section)
80
title=self.doc.createElement("title")
81
self.cur.appendChild(title)
86
self.cur=self.cur.parentNode
93
def paragraph(self, on):
94
FormatterBase.paragraph(self, on)
96
para=self.doc.createElement("para")
97
self.cur.appendChild(para)
100
self.cur=self.cur.parentNode
103
def linebreak(self, preformatted=1):
111
def _handleNode(self, name, on, attributes=()):
113
node=self.doc.createElement(name)
114
self.cur.appendChild(node)
115
if len(attributes)>0:
116
for (name,value) in attributes:
117
node.setAttribute(name,value)
120
self.cur=self.cur.parentNode
123
def _addEmptyNode(self,name, attributes=()):
124
node=self.doc.createElement(name)
125
self.cur.appendChild(node)
126
if len(attributes)>0:
127
for (name,value) in attributes:
128
node.setAttribute(name,value)
130
### Inline ##########################################################
132
def _handleFormatting(self,name, on, attributes=()):
133
#We add all the elements we create to the list of elements that should not contain a section
134
if name not in self.section_should_break:
135
self.section_should_break.append(name)
137
return self._handleNode(name,on,attributes)
139
def strong(self, on):
140
return self._handleFormatting("emphasis",on , [['role','bold']] )
142
def emphasis(self, on):
143
return self._handleFormatting("emphasis",on)
145
def underline(self, on):
146
return self._handleFormatting("emphasis",on , [['role','underline']] )
148
def highlight(self, on):
149
return self._handleFormatting("emphasis",on , [['role','highlight']] )
152
return self._handleFormatting("superscript",on)
155
return self._handleFormatting("subscript",on)
158
return self._handleFormatting("code",on)
160
def preformatted(self, on):
161
return self._handleFormatting("screen",on)
164
### Lists ###########################################################
166
def number_list(self, on, type=None, start=None):
167
docbook_ol_types={ '1':"arabic",
173
if type and docbook_ol_types.has_key(type):
174
attrs=[("numeration", docbook_ol_types[type])]
178
return self._handleNode('orderedlist',on,attrs)
181
def bullet_list(self, on):
182
return self._handleNode("itemizedlist",on)
184
def definition_list(self, on):
185
return self._handleNode("glosslist",on)
188
'''When on is false, we back out just on level. This is
189
ok because we know definition_desc gets called, and we
190
back out two levels there'''
191
def definition_term(self, on, compact=0):
193
entry=self.doc.createElement('glossentry')
194
term=self.doc.createElement('glossterm')
195
entry.appendChild(term)
196
self.cur.appendChild(entry)
200
self.cur=self.cur.parentNode
203
'''We backout two levels when 'on' is false, to leave the glossentry stuff'''
204
def definition_desc(self, on):
206
return self._handleNode("glossdef",on)
208
self.cur=self.cur.parentNode.parentNode
211
def listitem(self, on, **kw):
213
node=self.doc.createElement("listitem")
214
self.cur.appendChild(node)
218
self.cur=self.cur.parentNode
222
### Links ###########################################################
224
#FIXME: This is quite crappy
225
def pagelink(self, on, pagename='', page=None, **kw):
226
apply(FormatterBase.pagelink, (self, on, pagename, page), kw)
228
return self.interwikilink(on,'self',pagename) #FIXME
230
#FIXME: This is even more crappy
231
def interwikilink(self, on, interwiki='', pagename='', **kw):
236
wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_wiki(self.request, '%s:%s' % (interwiki, pagename))
237
wikiurl = wikiutil.mapURL(self.request, wikiurl)
238
href = wikiutil.join_wiki(wikiurl, wikitail)
241
#return self._handleNode("link",on,[['linkend',interwiki+"/"+pagename]]) #FIXME
244
def url(self, on, url=None, css=None, **kw):
245
return self._handleNode("ulink",on,[['url',url]])
247
def anchordef(self, name):
248
self._handleNode("anchor",True,[['id',name]])
249
self._handleNode("ulink",False)
252
def anchorlink(self, on, name='', id=None):
255
attrs.append( ('endterm',name) )
257
attrs.append( ('linkend',id) )
259
attrs.append( ('linkend',name) )
261
return self._handleNode("link",on,attrs)
264
### Images and Smileys ##############################################
265
def image(self, **kw):
266
media=self.doc.createElement('inlinemediaobject')
268
imagewrap=self.doc.createElement('imageobject')
269
media.appendChild(imagewrap)
271
image=self.doc.createElement('imagedata')
272
if kw.has_key('src'):
273
image.setAttribute('fileref',kw['src'])
274
if kw.has_key('width'):
275
image.setAttribute('width',kw['width'])
276
if kw.has_key('height'):
277
image.setAttribute('depth',kw['height'])
278
imagewrap.appendChild(image)
280
if kw.has_key('alt'):
281
txtcontainer=self.doc.createElement('textobject')
282
media.appendChild(txtcontainer)
283
txtphrase=self.doc.createElement('phrase')
284
txtphrase.appendChild( self.doc.createTextNode(kw['alt']) )
285
txtcontainer.appendChild(txtphrase)
287
self.cur.appendChild(media)
290
def smiley(self, text):
291
w, h, b, img = config.smileys[text.strip()]
293
if not href.startswith('/'):
294
href = self.request.theme.img_url(img)
295
return self.image(src=href, alt=text, width=str(w), height=str(h))
297
def icon(self, type):
298
return ''#self.request.theme.make_icon(type)
300
### Tables ##########################################################
302
#FIXME: We should copy code from text_html.py for attr handling
305
def table(self, on, attrs=None):
307
if attrs and attrs.has_key('id'):
308
sanitized_attrs[id]=attrs['id']
310
self._handleNode("table",on,sanitized_attrs)
312
self._addEmptyNode("caption") #dtd for table requires caption
316
def table_row(self, on, attrs=None):
318
if attrs and attrs.has_key('id'):
319
sanitized_attrs[id]=attrs['id']
320
return self._handleNode("tr",on,sanitized_attrs)
322
def table_cell(self, on, attrs=None):
324
if attrs and attrs.has_key('id'):
325
sanitized_attrs[id]=attrs['id']
326
return self._handleNode("td",on,sanitized_attrs)
329
### Code ############################################################
330
def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
338
attrs=[ ['id',code_id],
339
['linenumbering',show],
340
['startinglinenumber',str(start)],
341
['language',code_type],
342
['format','linespecific']
344
return self._handleFormatting("screen", on, attrs )
346
def code_line(self, on):
347
return '' #No clue why something should be done here
352
def code_token(self, on, tok_type):
353
toks_map={ 'ID':'methodname',
356
'Comment':'lineannotation',
367
if toks_map.has_key(tok_type) and toks_map[tok_type] != '':
368
return self._handleFormatting(toks_map[tok_type],on)
373
### Not supported ###################################################
374
def rule(self, size=0):
383
def rawHTML(self, markup):
384
""" This allows emitting pre-formatted HTML markup, and should be
385
used wisely (i.e. very seldom).
387
Using this event while generating content results in unwanted
388
effects, like loss of markup or insertion of CDATA sections
389
when output goes to XML formats.
393
def escapedText(self, on):
394
""" This allows emitting text as-is, anything special will
395
be escaped (at least in HTML, some text output format
396
would possibly do nothing here)