# HG changeset patch # User Christophe de Vienne # Date 1398884654 -7200 # Node ID 8c2c6fdd8d56021ad144a634810bef52a0f37490 # Parent 340d4ef55b6f8ba27333548d854678b8747f2aae [RichString] Add markdown support Supporting markdown requires the 'Markdown' python packages, and since it widely available on the target platforms adding it as a strong requirements will not be a big constraint. Closes #3814302 diff -r 340d4ef55b6f -r 8c2c6fdd8d56 __pkginfo__.py --- a/__pkginfo__.py Thu Oct 23 14:57:02 2014 +0200 +++ b/__pkginfo__.py Wed Apr 30 21:04:14 2014 +0200 @@ -51,6 +51,7 @@ # server dependencies 'logilab-database': '>= 1.12.1', 'passlib': '', + 'Markdown': '' } __recommends__ = { diff -r 340d4ef55b6f -r 8c2c6fdd8d56 cubicweb.spec --- a/cubicweb.spec Thu Oct 23 14:57:02 2014 +0200 +++ b/cubicweb.spec Wed Apr 30 21:04:14 2014 +0200 @@ -28,6 +28,7 @@ Requires: %{python}-passlib Requires: %{python}-lxml Requires: %{python}-twisted-web +Requires: %{python}-markdown # the schema view uses `dot'; at least on el5, png output requires graphviz-gd Requires: graphviz-gd Requires: gettext diff -r 340d4ef55b6f -r 8c2c6fdd8d56 cwconfig.py --- a/cwconfig.py Thu Oct 23 14:57:02 2014 +0200 +++ b/cwconfig.py Wed Apr 30 21:04:14 2014 +0200 @@ -278,7 +278,7 @@ }), ('default-text-format', {'type' : 'choice', - 'choices': ('text/plain', 'text/rest', 'text/html'), + 'choices': ('text/plain', 'text/rest', 'text/html', 'text/markdown'), 'default': 'text/html', # use fckeditor in the web ui 'help': _('default text format for rich text fields.'), 'group': 'ui', diff -r 340d4ef55b6f -r 8c2c6fdd8d56 debian/control --- a/debian/control Thu Oct 23 14:57:02 2014 +0200 +++ b/debian/control Wed Apr 30 21:04:14 2014 +0200 @@ -124,6 +124,7 @@ ${misc:Depends}, ${python:Depends}, cubicweb-common (= ${source:Version}), + python-markdown, Recommends: python-docutils (>= 0.6), python-vobject, diff -r 340d4ef55b6f -r 8c2c6fdd8d56 ext/markdown.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/markdown.py Wed Apr 30 21:04:14 2014 +0200 @@ -0,0 +1,27 @@ +from __future__ import absolute_import +import markdown + +import logging + +log = logging.getLogger(__name__) + + +def markdown_publish(context, data): + """publish a string formatted as MarkDown Text to HTML + + :type context: a cubicweb application object + + :type data: str + :param data: some MarkDown text + + :rtype: unicode + :return: + the data formatted as HTML or the original data if an error occurred + """ + md = markdown.Markdown() + try: + return md.convert(data) + except: + import traceback; traceback.print_exc() + log.exception("Error while converting Markdown to HTML") + return data diff -r 340d4ef55b6f -r 8c2c6fdd8d56 mttransforms.py --- a/mttransforms.py Thu Oct 23 14:57:02 2014 +0200 +++ b/mttransforms.py Wed Apr 30 21:04:14 2014 +0200 @@ -28,7 +28,7 @@ register_pygments_transforms) from cubicweb.utils import UStringIO -from cubicweb.uilib import rest_publish, html_publish +from cubicweb.uilib import rest_publish, markdown_publish, html_publish HTML_MIMETYPES = ('text/html', 'text/xhtml', 'application/xhtml+xml') @@ -40,6 +40,12 @@ def _convert(self, trdata): return rest_publish(trdata.appobject, trdata.decode()) +class markdown_to_html(Transform): + inputs = ('text/markdown', 'text/x-markdown') + output = 'text/html' + def _convert(self, trdata): + return markdown_publish(trdata.appobject, trdata.decode()) + class html_to_html(Transform): inputs = HTML_MIMETYPES output = 'text/html' @@ -53,6 +59,7 @@ ENGINE = TransformEngine() ENGINE.add_transform(rest_to_html()) +ENGINE.add_transform(markdown_to_html()) ENGINE.add_transform(html_to_html()) try: diff -r 340d4ef55b6f -r 8c2c6fdd8d56 test/unittest_entity.py --- a/test/unittest_entity.py Thu Oct 23 14:57:02 2014 +0200 +++ b/test/unittest_entity.py Wed Apr 30 21:04:14 2014 +0200 @@ -587,6 +587,16 @@ # should be default groups but owners, i.e. managers, users, guests self.assertEqual(len(unrelated), 3) + def test_markdown_printable_value_string(self): + with self.admin_access.web_request() as req: + e = req.create_entity('Card', title=u'rest markdown', + content=u'This is [an example](http://example.com/ "Title") inline link`', + content_format=u'text/markdown') + self.assertEqual( + u'

This is an example inline link`

', + e.printable_value('content')) + def test_printable_value_string(self): with self.admin_access.web_request() as req: e = req.create_entity('Card', title=u'rest test', diff -r 340d4ef55b6f -r 8c2c6fdd8d56 uilib.py --- a/uilib.py Thu Oct 23 14:57:02 2014 +0200 +++ b/uilib.py Wed Apr 30 21:04:14 2014 +0200 @@ -163,6 +163,8 @@ # text publishing ############################################################# +from cubicweb.ext.markdown import markdown_publish # pylint: disable=W0611 + try: from cubicweb.ext.rest import rest_publish # pylint: disable=W0611 except ImportError: @@ -170,6 +172,7 @@ """default behaviour if docutils was not found""" return xml_escape(data) + TAG_PROG = re.compile(r'', re.U) def remove_html_tags(text): """Removes HTML tags from text diff -r 340d4ef55b6f -r 8c2c6fdd8d56 web/formfields.py --- a/web/formfields.py Thu Oct 23 14:57:02 2014 +0200 +++ b/web/formfields.py Wed Apr 30 21:04:14 2014 +0200 @@ -779,11 +779,13 @@ actually contains some text. If the stream format is one of text/plain, text/html, text/rest, + text/markdown then a :class:`~cubicweb.web.formwidgets.TextArea` will be additionaly displayed, allowing to directly the file's content when desired, instead of choosing a file from user's file system. """ - editable_formats = ('text/plain', 'text/html', 'text/rest') + editable_formats = ( + 'text/plain', 'text/html', 'text/rest', 'text/markdown') def render(self, form, renderer): wdgs = [super(EditableFileField, self).render(form, renderer)] diff -r 340d4ef55b6f -r 8c2c6fdd8d56 web/test/unittest_form.py --- a/web/test/unittest_form.py Thu Oct 23 14:57:02 2014 +0200 +++ b/web/test/unittest_form.py Wed Apr 30 21:04:14 2014 +0200 @@ -174,6 +174,7 @@ self._test_richtextfield(req, '''''')