diff --git a/ckan/controllers/api.py b/ckan/controllers/api.py
index ee1f34f6ebd..45ecd0029c9 100644
--- a/ckan/controllers/api.py
+++ b/ckan/controllers/api.py
@@ -572,7 +572,7 @@ def _get_search_params(cls, request_params):
def markdown(self, ver=None):
raw_markdown = request.params.get('q', '')
- results = ckan.misc.MarkdownFormat().to_html(raw_markdown)
+ results = h.render_markdown(raw_markdown)
return self._finish_ok(results)
diff --git a/ckan/controllers/group.py b/ckan/controllers/group.py
index ba204cc4cae..614b6e350a6 100644
--- a/ckan/controllers/group.py
+++ b/ckan/controllers/group.py
@@ -176,14 +176,7 @@ def read(self, id):
else:
q += ' groups: "%s"' % c.group_dict.get('name')
- try:
- description_formatted = ckan.misc.MarkdownFormat().to_html(
- c.group_dict.get('description', ''))
- c.description_formatted = genshi.HTML(description_formatted)
- except Exception, e:
- error_msg = "%s" %\
- _("Cannot render description")
- c.description_formatted = genshi.HTML(error_msg)
+ c.description_formatted = h.render_markdown(c.group_dict.get('description'))
context['return_query'] = True
diff --git a/ckan/controllers/user.py b/ckan/controllers/user.py
index 7a4ef42f7df..e8b9232f42c 100644
--- a/ckan/controllers/user.py
+++ b/ckan/controllers/user.py
@@ -3,11 +3,9 @@
from pylons import session, c, g, request, config
from pylons.i18n import _
-import genshi
import ckan.lib.i18n as i18n
import ckan.lib.base as base
-import ckan.misc as misc
import ckan.model as model
import ckan.lib.helpers as h
import ckan.new_authz as new_authz
@@ -73,7 +71,7 @@ def _setup_template_variables(self, context, data_dict):
abort(401, _('Not authorized to see this page'))
c.user_dict = user_dict
c.is_myself = user_dict['name'] == c.user
- c.about_formatted = self._format_about(user_dict['about'])
+ c.about_formatted = h.render_markdown(user_dict['about'])
## end hooks
@@ -620,13 +618,3 @@ def unfollow(self, id):
or e.error_dict)
h.flash_error(error_message)
h.redirect_to(controller='user', action='read', id=id)
-
- def _format_about(self, about):
- about_formatted = misc.MarkdownFormat().to_html(about)
- try:
- html = genshi.HTML(about_formatted)
- except genshi.ParseError, e:
- log.error('Could not print "about" field Field: %r Error: %r',
- about, e)
- html = _('Error: Could not parse About text')
- return html
diff --git a/ckan/lib/dictization/model_dictize.py b/ckan/lib/dictization/model_dictize.py
index d61c68e73b1..d2a74071923 100644
--- a/ckan/lib/dictization/model_dictize.py
+++ b/ckan/lib/dictization/model_dictize.py
@@ -4,7 +4,6 @@
from pylons import config
from sqlalchemy.sql import select
-import ckan.misc as misc
import ckan.logic as logic
import ckan.plugins as plugins
import ckan.lib.helpers as h
@@ -530,7 +529,7 @@ def package_to_api(pkg, context):
dictized['license'] = pkg.license.title if pkg.license else None
dictized['ratings_average'] = pkg.get_average_rating()
dictized['ratings_count'] = len(pkg.ratings)
- dictized['notes_rendered'] = misc.MarkdownFormat().to_html(pkg.notes)
+ dictized['notes_rendered'] = h.render_markdown(pkg.notes)
site_url = config.get('ckan.site_url', None)
if site_url:
diff --git a/ckan/lib/package_saver.py b/ckan/lib/package_saver.py
index 1a1a9a8e7f6..5b3f876151f 100644
--- a/ckan/lib/package_saver.py
+++ b/ckan/lib/package_saver.py
@@ -1,4 +1,3 @@
-import genshi
from sqlalchemy import orm
import ckan.lib.helpers as h
from ckan.lib.base import *
@@ -22,12 +21,8 @@ def render_package(cls, pkg, context):
render.
Note that the actual calling of render('package/read') is left
to the caller.'''
- try:
- notes_formatted = ckan.misc.MarkdownFormat().to_html(pkg.get('notes',''))
- c.pkg_notes_formatted = genshi.HTML(notes_formatted)
- except Exception, e:
- error_msg = "%s" % _("Cannot render package description")
- c.pkg_notes_formatted = genshi.HTML(error_msg)
+ c.pkg_notes_formatted = h.render_markdown(pkg.get('notes'))
+
c.current_rating, c.num_ratings = ckan.rating.get_rating(context['package'])
url = pkg.get('url', '')
c.pkg_url_link = h.link_to(url, url, rel='foaf:homepage', target='_blank') \
diff --git a/ckan/misc.py b/ckan/misc.py
deleted file mode 100644
index 29f3ae6447b..00000000000
--- a/ckan/misc.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import re
-import logging
-import urllib
-import webhelpers.markdown
-
-from pylons.i18n import _
-
-log = logging.getLogger(__name__)
-
-class TextFormat(object):
-
- def to_html(self, instr):
- raise NotImplementedError()
-
-
-class MarkdownFormat(TextFormat):
- internal_link = re.compile('(dataset|package|group):([a-z0-9\-_]+)')
-
- # tag names are allowed more characters, including spaces. So are
- # treated specially.
- internal_tag_link = re.compile(\
- r"""(tag): # group 1
- ( # capture name (inc. quotes) (group 2)
- (")? # optional quotes for multi-word name (group 3)
- ( # begin capture of the name w/o quotes (group 4)
- (?(3) # if the quotes matched in group 3
- [ \w\-.] # then capture spaces (as well as other things)
- | # else
- [\w\-.] # don't capture spaces
- ) # end
- +) # end capture of the name w/o quotes (group 4)
- (?(3)") # close opening quote if necessary
- ) # end capture of the name with quotes (group 2)
- """, re.VERBOSE|re.UNICODE)
- normal_link = re.compile('<(http:[^>]+)>')
-
- html_whitelist = 'b center li ol p table td tr ul'.split(' ')
- whitelist_elem = re.compile(r'<(\/?((%s)(\s[^>]*)?))>' % "|".join(html_whitelist), re.IGNORECASE)
- whitelist_escp = re.compile(r'\\xfc\\xfd(\/?((%s)(\s[^>]*?)?))\\xfd\\xfc' % "|".join(html_whitelist), re.IGNORECASE)
- normal_link = re.compile(r']*?href="([^"]*?)"[^>]*?>', re.IGNORECASE)
- abbrev_link = re.compile(r'<(http://[^>]*)>', re.IGNORECASE)
- any_link = re.compile(r']*?>', re.IGNORECASE)
- close_link = re.compile(r'<(\/a[^>]*)>', re.IGNORECASE)
- link_escp = re.compile(r'\\xfc\\xfd(\/?(%s)[^>]*?)\\xfd\\xfc' % "|".join(['a']), re.IGNORECASE)
- web_address = re.compile(r'(\s| )((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)', re.IGNORECASE)
-
- def to_html(self, text):
- if text is None:
- return ''
- # Encode whitelist elements.
- text = self.whitelist_elem.sub(r'\\\\xfc\\\\xfd\1\\\\xfd\\\\xfc', text)
-
- # Encode links only in an acceptable format (guard against spammers)
- text = self.normal_link.sub(r'\\\\xfc\\\\xfda href="\1" target="_blank" rel="nofollow"\\\\xfd\\\\xfc', text)
- text = self.abbrev_link.sub(r'\\\\xfc\\\\xfda href="\1" target="_blank" rel="nofollow"\\\\xfd\\\\xfc\1