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