Skip to content

Commit 171c916

Browse files
committed
added markdown rendering support using either markdown2 or markdown
1 parent 06d0d61 commit 171c916

File tree

5 files changed

+77
-0
lines changed

5 files changed

+77
-0
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ install:
9494
- pip install gpg pytz whoosh pyjwt
9595
- pip install pytest-cov codecov
9696
- if [[ $TRAVIS_PYTHON_VERSION != "3.4"* ]]; then pip install docutils; fi
97+
- pip install markdown2
9798

9899
before_script:
99100
# set up mysql database

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ Features:
5858
property 'messages.author' is not allowed (because 'messages' is a
5959
multilink). A multilink at the end (e.g. messages in the example) is
6060
fine.
61+
- Added markdown rendering using either markdown or markdown2.
62+
(Christof Meerwald)
6163

6264
Fixed:
6365

doc/installation.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ pyjwt
116116
To use jwt tokens for login (experimental), install pyjwt. If you
117117
don't have it installed, jwt tokens are not supported.
118118

119+
docutils
120+
To use ReStructuredText rendering you need to have the docutils
121+
package installed.
122+
123+
markdown or markdown2
124+
To use markdown rendering you need to either have the markdown or
125+
markdown2 package installed.
126+
119127
Windows Service
120128
You can run Roundup as a Windows service if pywin32_ is installed.
121129
Otherwise it must be started manually.
@@ -128,6 +136,9 @@ Windows Service
128136
.. _gpg: https://www.gnupg.org/software/gpgme/index.html
129137
.. _pywin32: https://pypi.org/project/pywin32/
130138
.. _jinja2: http://jinja.pocoo.org/
139+
.. _docutils: https://docutils.sourceforge.io/
140+
.. _markdown: https://python-markdown.github.io/
141+
.. _markdown2: https://github.com/trentm/python-markdown2
131142

132143

133144
Getting Roundup

roundup/cgi/templating.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@
5353
from docutils.core import publish_parts as ReStructuredText
5454
except ImportError:
5555
ReStructuredText = None
56+
try:
57+
from markdown2 import markdown
58+
except ImportError:
59+
try:
60+
from markdown import markdown
61+
except ImportError:
62+
markdown = None
5663
try:
5764
from itertools import zip_longest
5865
except ImportError:
@@ -1514,6 +1521,19 @@ def _hyper_repl_rst(self, match):
15141521
# just return the matched text
15151522
return match.group(0)
15161523

1524+
def _hyper_repl_markdown(self, match):
1525+
if match.group('url'):
1526+
s = match.group('url')
1527+
return '[%s](%s)'%(s, s)
1528+
elif match.group('email'):
1529+
s = match.group('email')
1530+
return '[%s](mailto:%s)'%(s, s)
1531+
elif len(match.group('id')) < 10:
1532+
return self._hyper_repl_item(match,'[%(item)s](%(cls)s%(id)s)')
1533+
else:
1534+
# just return the matched text
1535+
return match.group(0)
1536+
15171537
def url_quote(self):
15181538
""" Return the string in plain format but escaped for use in a url """
15191539
return urllib_.quote(self.plain())
@@ -1601,6 +1621,21 @@ def rst(self, hyperlink=1):
16011621
s = self.hyper_re.sub(self._hyper_repl_rst, s)
16021622
return u2s(ReStructuredText(s, writer_name="html")["html_body"])
16031623

1624+
def markdown(self, hyperlink=1):
1625+
""" Render the value of the property as markdown.
1626+
1627+
This requires markdown2 or markdown to be installed separately.
1628+
"""
1629+
if not self.is_view_ok():
1630+
return self._('[hidden]')
1631+
1632+
if not markdown:
1633+
return self.plain(escape=0, hyperlink=hyperlink)
1634+
s = self.plain(escape=0, hyperlink=0)
1635+
if hyperlink:
1636+
s = self.hyper_re.sub(self._hyper_repl_markdown, s)
1637+
return u2s(markdown(s2u(s)))
1638+
16041639
def field(self, **kwargs):
16051640
""" Render the property as a field in HTML.
16061641

test/test_templating.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@
2929
skip_stext = mark_class(pytest.mark.skip(
3030
reason='StructuredText not available'))
3131

32+
try:
33+
skip_markdown = lambda func, *args, **kwargs: func
34+
from markdown2 import markdown
35+
except ImportError:
36+
try:
37+
from markdown import markdown
38+
except ImportError:
39+
markdown = None
40+
skip_markdown = mark_class(pytest.mark.skip(
41+
reason='markdown not available'))
42+
3243
from roundup.anypy.strings import u2s, s2u
3344

3445
class MockDatabase(MockNull):
@@ -236,7 +247,21 @@ def test_string_plain_or_hyperlinked(self):
236247

237248
self.assertEqual(p.hyperlinked(), 'A string &lt;b&gt; with <a href="mailto:[email protected]">[email protected]</a> embedded &amp;lt; html&lt;/b&gt;')
238249

250+
@skip_markdown
251+
def test_string_markdown_installed(self):
252+
pass # just so we have a record of a skipped test
253+
254+
def test_string_markdown(self):
255+
p = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'A string http://localhost with [email protected] *embedded* \u00df'))
256+
if markdown:
257+
self.assertEqual(p.markdown().strip(), u2s(u'<p>A string <a href="http://localhost">http://localhost</a> with <a href="mailto:[email protected]">[email protected]</a> <em>embedded</em> \u00df</p>'))
258+
else:
259+
self.assertEqual(p.markdown(), u2s(u'A string <a href="http://localhost" rel="nofollow noopener">http://localhost</a> with <a href="mailto:[email protected]">[email protected]</a> *embedded* \u00df'))
260+
239261
@skip_rst
262+
def test_string_rst_installed(self):
263+
pass # just so we have a record of a skipped test
264+
240265
def test_string_rst(self):
241266
p = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'A string with [email protected] *embedded* \u00df'))
242267
if ReStructuredText:
@@ -245,6 +270,9 @@ def test_string_rst(self):
245270
self.assertEqual(p.rst(), u2s(u'A string with <a href="mailto:[email protected]">[email protected]</a> *embedded* \u00df'))
246271

247272
@skip_stext
273+
def test_string_stext_installed(self):
274+
pass # just so we have a record of a skipped test
275+
248276
def test_string_stext(self):
249277
p = StringHTMLProperty(self.client, 'test', '1', None, 'test', u2s(u'A string with [email protected] *embedded* \u00df'))
250278
if StructuredText:

0 commit comments

Comments
 (0)