trentm / django-markdown-deux

A django app that provides Markdown-related template tags using the python-markdown2 library.
Other
287 stars 62 forks source link

Fenced code blocks do not receive pre tag #20

Open constantinevitt opened 8 years ago

constantinevitt commented 8 years ago

Suppose I have a database entry where I have the following "fenced code block"

(triple back tick) some fenced code block another line (triple back tick)

I also have the following model method in django models.py

def get_markdown(self):
        return mark_safe(markdown(self.body))
        where body = models.TextField()

Then the result being returned by the method is the following html code...

<p><code>
some fenced code block
another line
</code></p>

The <pre> tag is missing and it also displays inline rather than receiving the line break.

Ljz7 commented 8 years ago

Hello,

Same problem here. Even with 4 spaces and a blank line before the content, the code is not well formated.

constantinevitt commented 8 years ago

I think the owner of the package / repository is no longer maintaining it at all... There are open issues which have not received any feedback from him since 2014.

Ljz7 commented 8 years ago

Anyway, I found another solution :

  1. I uninstalled django-markdown-deux
  2. I follow this tuto : Using Markdown with Django 1.7
  3. Adding this extension in the return of the template tag function : Fenced Code Blocks

So my templatetags/markdown_parser.py looks like this :

from django import template
import markdown

register = template.Library()

@register.filter
def parse_md(text):
    # safe_mode governs how the function handles raw HTML
    return markdown.markdown(
        text,
        safe_mode='escape',
        extensions=[
            'markdown.extensions.nl2br',
            'markdown.extensions.fenced_code'
        ]
    )

Hope it helps

constantinevitt commented 8 years ago

Thanks for the find, it is certainly helpful. However, processing markdown at the template level is not a good idea, furthermore, safe_mode is deprecated Python-Markdown 2.6 Release Notes http://pythonhosted.org/Markdown/reference.html#safe_mode

I do suggest reading the comments and links on your link, they elaborate on my above comments.

Ljz7 commented 8 years ago

Ok, thanks you for the tips, I'll fix my code and post back the final function here.

PS : Your links lead to 404 when clicked, I had to c/p.

constantinevitt commented 8 years ago

It's the link you posted, I dragged it from your post into mine... hahaha, I guess it didn't work... I corrected it

constantinevitt commented 8 years ago

Here is my solution using the above information...

this is the model.py file

from django.utils.safestring import mark_safe
from markdown import markdown
from markdown.extensions import Extension

class EscapeHtml(Extension):
    def extendMarkdown(self, md, md_globals):
        del md.preprocessors['html_block']
        del md.inlinePatterns['html']

class Post(models.Model):
    body = models.TextField()

    def get_markdown(self):
        return mark_safe(markdown(
                            self.body,
                            extensions=[
                                EscapeHtml(),
                                'markdown.extensions.nl2br',
                                'markdown.extensions.fenced_code'
                                ]
                            )
                        )

... then in the template I just use {{ post.get_markdown }}

There is no need for template tags.

Ljz7 commented 8 years ago

Waw, your solution is great !

Thank you for sharing !

Héhé, no need django-markdown-deux anymore. = P You rule !

constantinevitt commented 8 years ago

Credit goes to you... you found the original post, I just read a little more into it... =)

Ljz7 commented 8 years ago

It works like a charm and in a secure way.

We should create a new Repository. = P

lek-tin commented 7 years ago

@contstantine AMazing solution, thanks!

Does anyone know whether the "markdown" package is still supported in Python 3?

ldelriof commented 7 years ago

for those who use the tag {% markdown %} ... MD content ... {% endmarkdown %} in the template this is my solution

  1. followed @Ljz7's solution on adding the template tag on my app
  2. use markdown deux original markdown_deux_tags.py as model
  3. create myapp/templatetags/markdown_filter.py
from django import template
import markdown

register = template.Library()

@register.tag(name="markdown")
def markdown_tag(parser, token):
    nodelist = parser.parse(('endmarkdown',))
    bits = token.split_contents()
    if len(bits) == 1:
        style = "default"
    elif len(bits) == 2:
        style = bits[1]
    else:
        raise template.TemplateSyntaxError("`markdown` tag requires exactly "
            "zero or one arguments")
    parser.delete_first_token() # consume '{% endmarkdown %}'
    return MarkdownNode(style, nodelist)

class MarkdownNode(template.Node):
    def __init__(self, style, nodelist):
        self.style = style
        self.nodelist = nodelist
    def render(self, context):
        value = self.nodelist.render(context)
        try:
            return markdown.markdown(value,
              extensions=[
                  'markdown.extensions.nl2br',
                  'markdown.extensions.fenced_code'
              ])
        except ImportError:
            if settings.DEBUG:
                raise template.TemplateSyntaxError("Error in `markdown` tag: "
                    "The python-markdown2 library isn't installed.")
            return force_text(value)

so now my template can be used like this

{% load markdown_filter %}

{% markdown %}

markdown content with fenced_code

{% endmarkdown %}
jtank38 commented 7 years ago

Thank you!! it's displaying the code blocks, but the code section is weirdly wide, anyone else find this?