annotate rhodecode/lib/markup_renderer.py @ 1769:025f3333c769 beta

@mention highlighting
author Marcin Kuzminski <marcin@python-works.com>
date Thu, 08 Dec 2011 03:36:13 +0200
parents bb3c2111bf92
children cf51bbfb120e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1604
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
2 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
3 rhodecode.lib.markup_renderer
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
5
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
6
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
7 Renderer for markup languages with ability to parse using rst or markdown
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
8
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
9 :created_on: Oct 27, 2011
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
10 :author: marcink
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
12 :license: GPLv3, see COPYING for more details.
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
13 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
14 # This program is free software: you can redistribute it and/or modify
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
15 # it under the terms of the GNU General Public License as published by
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
16 # the Free Software Foundation, either version 3 of the License, or
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
17 # (at your option) any later version.
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
18 #
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
19 # This program is distributed in the hope that it will be useful,
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
22 # GNU General Public License for more details.
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
23 #
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
24 # You should have received a copy of the GNU General Public License
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
26
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
27 import re
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
28 import logging
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
29
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
30 from rhodecode.lib import safe_unicode
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
31
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
32 log = logging.getLogger(__name__)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
33
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
34 class MarkupRenderer(object):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
35 RESTRUCTUREDTEXT_DISALLOWED_DIRECTIVES = ['include', 'meta', 'raw']
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
36
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
37 MARKDOWN_PAT = re.compile(r'md|mkdn?|mdown|markdown',re.IGNORECASE)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
38 RST_PAT = re.compile(r're?st',re.IGNORECASE)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
39 PLAIN_PAT = re.compile(r'readme',re.IGNORECASE)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
40
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
41 def __detect_renderer(self, source, filename=None):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
42 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
43 runs detection of what renderer should be used for generating html
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
44 from a markup language
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
45
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
46 filename can be also explicitly a renderer name
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
47
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
48 :param source:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
49 :param filename:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
50 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
51
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
52 if MarkupRenderer.MARKDOWN_PAT.findall(filename):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
53 detected_renderer = 'markdown'
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
54 elif MarkupRenderer.RST_PAT.findall(filename):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
55 detected_renderer = 'rst'
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
56 elif MarkupRenderer.PLAIN_PAT.findall(filename):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
57 detected_renderer = 'rst'
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
58 else:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
59 detected_renderer = 'plain'
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
60
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
61 return getattr(MarkupRenderer, detected_renderer)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
62
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
63
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
64 def render(self, source, filename=None):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
65 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
66 Renders a given filename using detected renderer
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
67 it detects renderers based on file extension or mimetype.
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
68 At last it will just do a simple html replacing new lines with <br/>
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
69
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
70 :param file_name:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
71 :param source:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
72 """
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
73
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
74 renderer = self.__detect_renderer(source, filename)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
75 readme_data = renderer(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
76 return readme_data
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
77
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
78 @classmethod
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
79 def plain(cls, source):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
80 source = safe_unicode(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
81 def urlify_text(text):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
82 url_pat = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
83 '|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)')
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
84
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
85 def url_func(match_obj):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
86 url_full = match_obj.groups()[0]
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
87 return '<a href="%(url)s">%(url)s</a>' % ({'url':url_full})
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
88
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
89 return url_pat.sub(url_func, text)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
90
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
91 source = urlify_text(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
92 return '<br />' + source.replace("\n", '<br />')
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
93
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
94
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
95 @classmethod
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
96 def markdown(cls, source):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
97 source = safe_unicode(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
98 try:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
99 import markdown as __markdown
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
100 return __markdown.markdown(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
101 except ImportError:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
102 log.warning('Install markdown to use this function')
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
103 return cls.plain(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
104
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
105
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
106 @classmethod
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
107 def rst(cls, source):
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
108 source = safe_unicode(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
109 try:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
110 from docutils.core import publish_parts
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
111 from docutils.parsers.rst import directives
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
112 docutils_settings = dict([(alias, None) for alias in
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
113 cls.RESTRUCTUREDTEXT_DISALLOWED_DIRECTIVES])
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
114
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
115 docutils_settings.update({'input_encoding': 'unicode',
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
116 'report_level':4})
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
117
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
118 for k, v in docutils_settings.iteritems():
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
119 directives.register_directive(k, v)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
120
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
121 parts = publish_parts(source=source,
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
122 writer_name="html4css1",
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
123 settings_overrides=docutils_settings)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
124
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
125 return parts['html_title'] + parts["fragment"]
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
126 except ImportError:
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
127 log.warning('Install docutils to use this function')
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
128 return cls.plain(source)
bb3c2111bf92 initial version of markup renderer
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
129
1769
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
130 @classmethod
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
131 def rst_with_mentions(cls, source):
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
132 mention_pat = re.compile(r'(?:^@|\s@)(\w+)')
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
133
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
134 def wrapp(match_obj):
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
135 uname = match_obj.groups()[0]
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
136 return ' **@%(uname)s** ' % {'uname':uname}
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
137 mention_hl = mention_pat.sub(wrapp, source).strip()
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
138 return cls.rst(mention_hl)
025f3333c769 @mention highlighting
Marcin Kuzminski <marcin@python-works.com>
parents: 1604
diff changeset
139