抑制Python Markdown在<p></p>中换行的文本

13

我正在使用Python Markdown 作为Jinja2的过滤器来生成HTML。在此过程中,我从渲染输入中填充表格条目。通过Markdown过滤器传递输入始终将文本包装在段落标记中,因此表格中的每个条目都被包装在<p></p>中,而我不想要这样。

我已经阅读了Markdown文档和第三方扩展列表,但似乎除了编写自己的扩展程序之外,没有其他方法可以抑制这种行为。是否有其他方法可以抑制段落标签包装?或者我走错了路?

更新:这是我现在使用的肮脏可怕的恶心代码:

def safe_markdown(text):
  p = '<p>'
  np = '</p>'
  md = markdown.markdown(text)
  if md.startswith(p) and md.endswith(np): #you filthy bastard
    md = md[len(p):-len(np)]
  return jinja2.Markup(md)

env = jinja2.Environment(...)
env.filters['markdown'] = safe_markdown 

更新2(回复Aaron的答案):

感谢您的帮助,但问题肯定是由于Markdown引起的。以下是Jinja模板的一个示例部分:

        {%- if spc.docs -%}
<td>{{ spc.docs|markdown }}</td></tr>
        {%- else -%}
<td></td></tr>
        {%- endif -%}
如果spc.docs只是'foo',生成的html将变成<td><p>foo</p></td></tr>,除非我使用肮脏的hack。
更新3
这里有一个不那么恶心的hack,虽然仍然是一个hack,并不算真正的“答案”,在我看来。
def safe_markdown(text):
    md = markdown.markdown(text)
    return jinja2.Markup(md)

def safe_markdown_td(text):
    text = ''.join(['<td>', text, '</td>'])
    return safe_markdown(text)

env = jinja2.Environment(...)
env.filters['markdown'] = safe_markdown
env.filters['markdowntd'] = safe_markdown_td

那么模板就变成了:

        {%- if spc.docs -%}
{{ spc.docs|markdowntd }}</tr>
        {%- else -%}
<td></td></tr>
        {%- endif -%}

嘿,我更新了我的答案。这也是一个不太好的hack,但可能不是一个肮脏的恶劣的hack。虽然它感觉比startswithendswith调用要好。 - Aaron Meier
6个回答

2
任何时候使用markdown,你都必须接受一些关于html最终结构的严重妥协。有许多结构是你无法表达的。不要把它看作是html的替代品,而是将其视为另一种语言来简单地编写内容。
可能发生的情况是将表格单元格内容包装在段落标签中会破坏你的布局,如果是这样,你应该使用CSS来修复它:
td p {
  margin: 0;
  padding: 0;
}

2
刚好遇到了同样的问题——使用markdown.markdown()时,会免费添加不需要的开头/结尾段落标签。
以下对于我而言效果很好,对于我不想让markdown()将其作为段落包含起来的字符串。与其直接调用markdown(),我将其包装在一个正则表达式中,以删除有问题的段落标记,并且不会干扰我Markdown中嵌入的任何预定的硬换行
from markdown import markdown

# ... other stuff ...

def no_p_markdown(non_p_string) -> str:
    ''' Strip enclosing paragraph marks, <p> ... </p>, 
        which markdown() forces, and which interfere with some jinja2 layout
    '''
    return re.sub("(^<P>|</P>$)", "", markdown(non_p_string), flags=re.IGNORECASE)

# ... other stuff ...

non_p_html = no_p_markdown("my markdown text not intended for a paragraph")

1

另一种去除烦人的外部标签的方法是编写一个简单的剥离函数:

def strip(s):
    """ strips outer html tags """

    start = s.find('>')+1
    end = len(s)-s[::-1].find('<')-1

    return s[start:end]

1

我同意,那个黑客是肮脏的(但总比没有好)。

根据我的经验,在表格中出现奇怪的问题,特别是在 <td> 中,通常是由于标记格式不正确造成的。这可能也是你的情况。

>>> import markdown
>>> markdown.version
'2.1.1'
>>> text = '''
... <table>
... <tr>
...     <td>
...             Here's some fancy text
...
...             and some more
...     </td>
...     <td>Here's other text</td>
... </tr>
... </table>
... 
... This should be in a **paragraph.**
... '''
>>> markdown.markdown(text)
u"<table>
<tr>
    <td>
        Here's some fancy text

        and some more
    </td>
    <td>Here's other text</td>
</tr>
</table>
<p>This should be in a <strong>paragraph.</strong></p>"

看到了吗?表格中没有疯狂的段落标签。

还有一种可能是Jinja出了问题,添加了这些标签。我个人没有注意到这种行为,但也许值得尝试一下带和不带模板过滤器的实验。

还有一件事。Markdown很棒,虽然会失去一些控制权,但我认为你选择的非常好。

编辑 对不起,Elhefe,我当时并没有完全理解发生了什么。我也遇到过这个问题!我的解决方法:如果不想要段落,则将那些东西包裹在 <div> 中。

>>> markdown.markdown(text)
u'<p>Here be some <em>foo</em></p>'
>>> text = '<div>Here be some *foo*</div>'
>>> markdown.markdown(text)
u'<div>Here be some *foo*</div>'

但这并不能解决你的问题。我能想到的唯一办法就是在标记之前将文本包含在<td></td>中。

什么?这确实很奇怪。我试一下——算了,我没有理解发生了什么!在OQ上发表评论。 - Aaron Meier
重新编辑:你正在混淆模型和视图,愿上帝怜悯你的异教徒灵魂。我会为你祈祷。 - elhefe
实际上,nm - 有一种方法可以使其正常工作而不会干扰模型。请参见OQ。 - elhefe

1

当我使用Markdown将HTML标记添加到一些用户定义的字符串中的配置文件中时,我遇到了同样的问题,以便他们不必学习HTML(这就是Markdown的用途,对吧?)。这些字符串嵌入在其他可能已经是

元素的HTML中。所以我不想在中间再加一个。有两件事:

  1. 如果已经包装在任何块级标记中(在此处列出:https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements),则Markdown的convert()不会向提供的文本添加

    标签。

  2. 如果这对您不起作用,则可以扩展Markdown以覆盖convert()方法以剥离

    标签。

    from markdown import Markdown
    class EMarkdown(Markdown):
    def convert(self, text):
        t = super().convert(text)
        t = t.removeprefix("<p>").removesuffix("</p>")
        return t

将其扩展到所有块级标记留给读者作为练习。;-)


0
我曾经遇到过同样的问题,即使用<p> </p>标签会破坏我的表格。对我来说最简单的解决方法是在CSS中添加


td p {display:inline;}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接