39
|
1 # -*- coding: utf-8 -*-
|
|
2 #
|
|
3 # Copyright (C) 2004-2006 Edgewall Software
|
|
4 # Copyright (C) 2004 Daniel Lundin <daniel@edgewall.com>
|
|
5 # All rights reserved.
|
|
6 #
|
|
7 # This software is licensed as described in the file COPYING, which
|
|
8 # you should have received as part of this distribution. The terms
|
|
9 # are also available at http://trac.edgewall.com/license.html.
|
|
10 #
|
|
11 # This software consists of voluntary contributions made by many
|
|
12 # individuals. For the exact contribution history, see the revision
|
|
13 # history and logs, available at http://projects.edgewall.com/trac/.
|
|
14 #
|
|
15 # Author: Daniel Lundin <daniel@edgewall.com>
|
|
16
|
|
17 """Syntax highlighting module, based on the SilverCity module.
|
|
18
|
|
19 Get it at: http://silvercity.sourceforge.net/
|
|
20 """
|
|
21
|
|
22 import re
|
|
23 from StringIO import StringIO
|
|
24
|
|
25 from trac.core import *
|
|
26 from trac.config import ListOption
|
|
27 from trac.mimeview.api import IHTMLPreviewRenderer, Mimeview
|
|
28
|
|
29 __all__ = ['SilverCityRenderer']
|
|
30
|
|
31 types = {
|
|
32 'text/css': ('CSS', 3),
|
|
33 'text/html': ('HyperText', 3, {'asp.default.language':1}),
|
|
34 'application/xml': ('XML', 3),
|
|
35 'application/xhtml+xml': ('HyperText', 3, {'asp.default.language':1}),
|
|
36 'application/x-javascript': ('CPP', 3), # Kludgy.
|
|
37 'text/x-asp': ('HyperText', 3, {'asp.default.language':2}),
|
|
38 'text/x-c++hdr': ('CPP', 3),
|
|
39 'text/x-c++src': ('CPP', 3),
|
|
40 'text/x-chdr': ('CPP', 3),
|
|
41 'text/x-csrc': ('CPP', 3),
|
|
42 'text/x-perl': ('Perl', 3),
|
|
43 'text/x-php': ('HyperText', 3, {'asp.default.language':4}),
|
|
44 'application/x-httpd-php': ('HyperText', 3, {'asp.default.language':4}),
|
|
45 'application/x-httpd-php4': ('HyperText', 3, {'asp.default.language':4}),
|
|
46 'application/x-httpd-php3': ('HyperText', 3, {'asp.default.language':4}),
|
|
47 'text/x-javascript': ('CPP', 3), # Kludgy.
|
|
48 'text/x-psp': ('HyperText', 3, {'asp.default.language':3}),
|
|
49 'text/x-python': ('Python', 3),
|
|
50 'text/x-ruby': ('Ruby', 3),
|
|
51 'text/x-sql': ('SQL', 3),
|
|
52 'text/xml': ('XML', 3),
|
|
53 'text/xslt': ('XSLT', 3),
|
|
54 'image/svg+xml': ('XML', 3)
|
|
55 }
|
|
56
|
|
57 CRLF_RE = re.compile('\r$', re.MULTILINE)
|
|
58
|
|
59
|
|
60 class SilverCityRenderer(Component):
|
|
61 """Syntax highlighting based on SilverCity."""
|
|
62
|
|
63 implements(IHTMLPreviewRenderer)
|
|
64
|
|
65 enscript_modes = ListOption('mimeviewer', 'silvercity_modes',
|
|
66 '',
|
|
67 """List of additional MIME types known by SilverCity.
|
|
68 For each, a tuple `mimetype:mode:quality` has to be
|
|
69 specified, where `mimetype` is the MIME type,
|
|
70 `mode` is the corresponding SilverCity mode to be used
|
|
71 for the conversion and `quality` is the quality ratio
|
|
72 associated to this conversion.
|
|
73 That can also be used to override the default
|
|
74 quality ratio used by the SilverCity render, which is 3
|
|
75 (''since 0.10'').""")
|
|
76
|
|
77 expand_tabs = True
|
|
78
|
|
79 def __init__(self):
|
|
80 self._types = None
|
|
81
|
|
82 def get_quality_ratio(self, mimetype):
|
|
83 # Extend default MIME type to mode mappings with configured ones
|
|
84 if not self._types:
|
|
85 self._types = {}
|
|
86 self._types.update(types)
|
|
87 self._types.update(
|
|
88 Mimeview(self.env).configured_modes_mapping('silvercity'))
|
|
89 return self._types.get(mimetype, (None, 0))[1]
|
|
90
|
|
91 def render(self, req, mimetype, content, filename=None, rev=None):
|
|
92 import SilverCity
|
|
93 try:
|
|
94 mimetype = mimetype.split(';', 1)[0]
|
|
95 typelang = self._types[mimetype]
|
|
96 lang = typelang[0]
|
|
97 module = getattr(SilverCity, lang)
|
|
98 generator = getattr(module, lang + "HTMLGenerator")
|
|
99 try:
|
|
100 allprops = typelang[2]
|
|
101 propset = SilverCity.PropertySet()
|
|
102 for p in allprops.keys():
|
|
103 propset[p] = allprops[p]
|
|
104 except IndexError:
|
|
105 pass
|
|
106 except (KeyError, AttributeError):
|
|
107 err = "No SilverCity lexer found for mime-type '%s'." % mimetype
|
|
108 raise Exception, err
|
|
109
|
|
110 # SilverCity does not like unicode strings
|
|
111 content = content.encode('utf-8')
|
|
112
|
|
113 # SilverCity generates extra empty line against some types of
|
|
114 # the line such as comment or #include with CRLF. So we
|
|
115 # standardize to LF end-of-line style before call.
|
|
116 content = CRLF_RE.sub('', content)
|
|
117
|
|
118 buf = StringIO()
|
|
119 generator().generate_html(buf, content)
|
|
120
|
|
121 br_re = re.compile(r'<br\s*/?>$', re.MULTILINE)
|
|
122 span_default_re = re.compile(r'<span class="\w+_default">(.*?)</span>',
|
|
123 re.DOTALL)
|
|
124 html = span_default_re.sub(r'\1', br_re.sub('', buf.getvalue()))
|
|
125
|
|
126 # Convert the output back to a unicode string
|
|
127 html = html.decode('utf-8')
|
|
128
|
|
129 # SilverCity generates _way_ too many non-breaking spaces...
|
|
130 # We don't need them anyway, so replace them by normal spaces
|
|
131 return html.replace(' ', ' ').splitlines()
|