Back to index

moin  1.9.0~rc2
text_gedit.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - "text/html+css" Formatter for feeding the GUI editor
00004 
00005     @copyright: 2005-2006 Bastian Blank, Florian Festi, Thomas Waldmann, Reimar Bauer
00006     @license: GNU GPL, see COPYING for details.
00007 """
00008 
00009 from MoinMoin import log
00010 logging = log.getLogger(__name__)
00011 
00012 from MoinMoin.formatter import FormatterBase, text_html
00013 from MoinMoin import wikiutil
00014 from MoinMoin.Page import Page
00015 from MoinMoin.action import AttachFile
00016 
00017 class Formatter(text_html.Formatter):
00018     """ Send HTML data for the GUI editor """
00019 
00020     # Block elements ####################################################
00021 
00022     def heading(self, on, depth, **kw):
00023         # remember depth of first heading, and adapt counting depth accordingly
00024         if not self._base_depth:
00025             self._base_depth = depth
00026 
00027         count_depth = max(depth - (self._base_depth - 1), 1)
00028         heading_depth = depth
00029 
00030         # closing tag, with empty line after, to make source more readable
00031         if not on:
00032             return self._close('h%d' % heading_depth)
00033         else:
00034             return self._open('h%d' % heading_depth, **kw)
00035 
00036     # Links ##############################################################
00037 
00038     def pagelink(self, on, pagename='', page=None, **kw):
00039         """ Link to a page.
00040 
00041             formatter.text_python will use an optimized call with a page!=None
00042             parameter. DO NOT USE THIS YOURSELF OR IT WILL BREAK.
00043 
00044             See wikiutil.link_tag() for possible keyword parameters.
00045         """
00046         FormatterBase.pagelink(self, on, pagename, page, **kw)
00047         if page is None:
00048             page = Page(self.request, pagename, formatter=self)
00049         return page.link_to(self.request, on=on, **kw)
00050 
00051     def interwikilink(self, on, interwiki='', pagename='', **kw):
00052         """
00053         @keyword title: override using the interwiki wikiname as title
00054         """
00055         if not on:
00056             return self.url(0) # return '</a>'
00057         html_class = 'badinterwiki' # we use badinterwiki in any case to simplify reverse conversion
00058         href = wikiutil.quoteWikinameURL(pagename) or "/" # FCKeditor behaves strange on empty href
00059         title = kw.get('title', interwiki)
00060         return self.url(1, href, title=title, css=html_class) # interwiki links with pages with umlauts
00061 
00062     def attachment_inlined(self, url, text, **kw):
00063         url = wikiutil.escape(url)
00064         text = wikiutil.escape(text)
00065         if url == text:
00066             return '<span style="background-color:#ffff11">{{attachment:%s}}</span>' % url
00067         else:
00068             return '<span style="background-color:#ffff11">{{attachment:%s|%s}}</span>' % (url, text)
00069 
00070     def attachment_link(self, on, url=None, **kw):
00071         assert on in (0, 1, False, True) # make sure we get called the new way, not like the 1.5 api was
00072         _ = self.request.getText
00073         querystr = kw.get('querystr', {})
00074         assert isinstance(querystr, dict) # new in 1.6, only support dicts
00075         if 'do' not in querystr:
00076             querystr['do'] = 'view'
00077         if on:
00078             pagename = self.page.page_name
00079             target = AttachFile.getAttachUrl(pagename, url, self.request, do=querystr['do'])
00080             return self.url(on, target, title="attachment:%s" % wikiutil.quoteWikinameURL(url))
00081         else:
00082             return self.url(on)
00083 
00084     def attachment_image(self, url, **kw):
00085         _ = self.request.getText
00086         # we force the title here, needed later for html>wiki converter
00087         kw['title'] = "attachment:%s" % wikiutil.quoteWikinameURL(url)
00088         pagename = self.page.page_name
00089         if '/' in url:
00090             pagename, target = AttachFile.absoluteName(url, pagename)
00091             url = url.split('/')[-1]
00092         kw['src'] = AttachFile.getAttachUrl(pagename, url, self.request, addts=1)
00093         return self.image(**kw)
00094 
00095     def attachment_drawing(self, url, text, **kw):
00096         # Todo get it to start the drawing editor on a click
00097         try:
00098             drawing_action = AttachFile.get_action(self.request, url, do='modify')
00099             assert drawing_action is not None
00100             attachment_drawing = wikiutil.importPlugin(self.request.cfg, 'action',
00101                                               drawing_action, 'gedit_drawing')
00102             return attachment_drawing(self, url, text, **kw)
00103         except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError, AssertionError):
00104             return url
00105 
00106     def icon(self, type):
00107         return self.request.theme.make_icon(type, title='smiley:%s' % type)
00108 
00109     smiley = icon
00110 
00111     def nowikiword(self, text):
00112         return '<span style="background-color:#ffff11">!</span>' + self.text(text)
00113 
00114     # Dynamic stuff / Plugins ############################################
00115 
00116     def macro(self, macro_obj, name, args, markup=None):
00117         if markup is not None:
00118             result = markup
00119         elif args is not None:
00120             result = "<<%s(%s)>>" % (name, args)
00121         else:
00122             result = "<<%s>>" % name
00123         return '<span style="background-color:#ffff11">%s</span>' % wikiutil.escape(result)
00124 
00125     def parser(self, parser_name, lines):
00126         """ parser_name MUST be valid!
00127         """
00128         result = [self.preformatted(1)]
00129         for line in lines:
00130             result.append(self.text(line))
00131             result.append(self.linebreak(preformatted=1))
00132         result.append(self.preformatted(0))
00133 
00134         return "".join(result)
00135 
00136     # Other ##############################################################
00137 
00138     style2attribute = {
00139         'width': 'width',
00140         'height': 'height',
00141         'background': 'bgcolor',
00142         'background-color': 'bgcolor',
00143         #if this is used as table style="text-align: right", it doesn't work
00144         #if it is transformed to align="right":
00145         #'text-align': 'align',
00146         #'vertical-align': 'valign'
00147         }
00148 
00149     def _style_to_attributes(self, attrs):
00150         if 'style' not in attrs:
00151             return attrs
00152         unknown = []
00153         for entry in attrs['style'].split(';'):
00154             try:
00155                 key, value = entry.split(':')
00156             except ValueError:
00157                 unknown.append(entry)
00158                 continue
00159             key, value = key.strip(), value.strip()
00160             if key in self.style2attribute:
00161                 attrs[self.style2attribute[key]] = value
00162             else:
00163                 unknown.append("%s:%s" % (key, value))
00164         if unknown:
00165             attrs['style'] = ';'.join(unknown)
00166         else:
00167             del attrs['style']
00168         return attrs
00169 
00170     def _checkTableAttr(self, attrs, prefix):
00171         #logging.debug(repr(attrs))
00172         attrs = text_html.Formatter._checkTableAttr(self, attrs, prefix)
00173         #logging.debug(repr(attrs))
00174         attrs = self._style_to_attributes(attrs)
00175         #logging.debug(repr(attrs))
00176         return attrs
00177 
00178     _allowed_table_attrs = {
00179         'table': ['class', 'id', 'style', 'bgcolor', 'width', 'height', ],
00180         'row': ['class', 'id', 'style', 'bgcolor', 'width', 'height', ],
00181         '': ['colspan', 'rowspan', 'class', 'id', 'style', 'bgcolor', 'width', 'height', ],
00182     }
00183 
00184     def table(self, on, attrs=None, **kw):
00185         """ Create table
00186 
00187         @param on: start table
00188         @param attrs: table attributes
00189         @rtype: string
00190         @return start or end tag of a table
00191         """
00192         result = []
00193         if on:
00194             # Open table
00195             if not attrs:
00196                 attrs = {}
00197             else:
00198                 #result.append(self.rawHTML("<!-- ATTRS1: %s -->" % repr(attrs)))
00199                 attrs = self._checkTableAttr(attrs, 'table')
00200                 #result.append(self.rawHTML("<!-- ATTRS2: %s -->" % repr(attrs)))
00201             result.append(self._open('table', newline=1, attr=attrs,
00202                                      allowed_attrs=self._allowed_table_attrs['table'],
00203                                      **kw))
00204         else:
00205             # Close table then div
00206             result.append(self._close('table'))
00207 
00208         return ''.join(result)
00209 
00210     def comment(self, text, **kw):
00211         text = text.rstrip() # workaround for growing amount of blanks at EOL
00212         return self.preformatted(1, css_class='comment') + self.text(text) + self.preformatted(0)
00213 
00214     def strong(self, on, **kw):
00215         tag = 'b'
00216         if on:
00217             return self._open(tag, allowed_attrs=[], **kw)
00218         return self._close(tag)
00219 
00220     def emphasis(self, on, **kw):
00221         tag = 'i'
00222         if on:
00223             return self._open(tag, allowed_attrs=[], **kw)
00224         return self._close(tag)
00225 
00226     def underline(self, on, **kw):
00227         tag = 'u'
00228         if on:
00229             return self._open(tag, allowed_attrs=[], **kw)
00230         return self._close(tag)
00231 
00232     def line_anchordef(self, lineno):
00233         return '' # not needed for gui editor feeding
00234 
00235     def line_anchorlink(self, on, lineno=0):
00236         return '' # not needed for gui editor feeding
00237 
00238     def span(self, on, **kw):
00239         previous_state = self.request.user.show_comments
00240         self.request.user.show_comments = True
00241         ret = text_html.Formatter.span(self, on, **kw)
00242         self.request.user.show_comments = previous_state
00243         return ret