Changeset - 7563624e712c
[Not reviewed]
default
0 1 0
Marcin Kuzminski - 12 years ago 2013-06-17 22:47:36
marcin@python-works.com
Added github flavored markdown style rendering into markdown
rendered. It has a san newline handling behavior. More
here: https://help.github.com/articles/github-flavored-markdown
1 file changed with 48 insertions and 3 deletions:
0 comments (0 inline, 0 general)
rhodecode/lib/markup_renderer.py
Show inline comments
 
@@ -40,7 +40,7 @@ class MarkupRenderer(object):
 
    RST_PAT = re.compile(r're?st', re.IGNORECASE)
 
    PLAIN_PAT = re.compile(r'readme', re.IGNORECASE)
 

	
 
    def __detect_renderer(self, source, filename=None):
 
    def _detect_renderer(self, source, filename=None):
 
        """
 
        runs detection of what renderer should be used for generating html
 
        from a markup language
 
@@ -62,6 +62,49 @@ class MarkupRenderer(object):
 

	
 
        return getattr(MarkupRenderer, detected_renderer)
 

	
 
    @classmethod
 
    def _flavored_markdown(cls, text):
 
        """
 
        Github style flavored markdown
 

	
 
        :param text:
 
        """
 
        from hashlib import md5
 

	
 
        # Extract pre blocks.
 
        extractions = {}
 
        def pre_extraction_callback(matchobj):
 
            digest = md5(matchobj.group(0)).hexdigest()
 
            extractions[digest] = matchobj.group(0)
 
            return "{gfm-extraction-%s}" % digest
 
        pattern = re.compile(r'<pre>.*?</pre>', re.MULTILINE | re.DOTALL)
 
        text = re.sub(pattern, pre_extraction_callback, text)
 

	
 
        # Prevent foo_bar_baz from ending up with an italic word in the middle.
 
        def italic_callback(matchobj):
 
            s = matchobj.group(0)
 
            if list(s).count('_') >= 2:
 
                return s.replace('_', '\_')
 
            return s
 
        text = re.sub(r'^(?! {4}|\t)\w+_\w+_\w[\w_]*', italic_callback, text)
 

	
 
        # In very clear cases, let newlines become <br /> tags.
 
        def newline_callback(matchobj):
 
            if len(matchobj.group(1)) == 1:
 
                return matchobj.group(0).rstrip() + '  \n'
 
            else:
 
                return matchobj.group(0)
 
        pattern = re.compile(r'^[\w\<][^\n]*(\n+)', re.MULTILINE)
 
        text = re.sub(pattern, newline_callback, text)
 

	
 
        # Insert pre block extractions.
 
        def pre_insert_callback(matchobj):
 
            return '\n\n' + extractions[matchobj.group(1)]
 
        text = re.sub(r'{gfm-extraction-([0-9a-f]{32})\}',
 
                      pre_insert_callback, text)
 

	
 
        return text
 

	
 
    def render(self, source, filename=None):
 
        """
 
        Renders a given filename using detected renderer
 
@@ -72,7 +115,7 @@ class MarkupRenderer(object):
 
        :param source:
 
        """
 

	
 
        renderer = self.__detect_renderer(source, filename)
 
        renderer = self._detect_renderer(source, filename)
 
        readme_data = renderer(source)
 
        return readme_data
 

	
 
@@ -94,10 +137,12 @@ class MarkupRenderer(object):
 
        return '<br />' + source.replace("\n", '<br />')
 

	
 
    @classmethod
 
    def markdown(cls, source, safe=True):
 
    def markdown(cls, source, safe=True, flavored=False):
 
        source = safe_unicode(source)
 
        try:
 
            import markdown as __markdown
 
            if flavored:
 
                source = cls._flavored_markdown(source)
 
            return __markdown.markdown(source, ['codehilite', 'extra'])
 
        except ImportError:
 
            log.warning('Install markdown to use this function')
0 comments (0 inline, 0 general)