【问题标题】:Can Python-Markdown support imageboard-style links?Python-Markdown 可以支持图像板样式的链接吗?
【发布时间】:2021-11-20 03:30:18
【问题描述】:

我想在 Python-Markdown 中添加一个额外的语法:如果 n 是一个正整数,>>n 应该扩展为 <a href="#post-n">n</a>。 (双尖括号 (>>) 是在imageboard forums 中创建链接的常规语法。)

默认情况下,Python-Markdown 将 >>n 扩展为嵌套块引用:<blockquote><blockquote>n</blockquote></blockquote>。有没有办法从>>n 创建链接,同时保留blockquote 的默认行为的其余部分?换句话说,如果x 是一个正整数,>>x 应该展开成一个链接,但如果x 不是一个正整数,>>x 仍然应该展开成嵌套的块引用。

我已阅读相关的 wiki 文章:Tutorial 1 Writing Extensions for Python Markdown。根据我在 wiki 中学到的知识,我编写了一个自定义扩展:

import markdown
import xml.etree.ElementTree as ET
from markdown.extensions import Extension
from markdown.inlinepatterns import Pattern


class ImageboardLinkPattern(Pattern):
    def handleMatch(self, match):
        number = match.group('number')
        # Create link.
        element = ET.Element('a', attrib={'href': f'#post-{number}'})
        element.text = f'>>{number}'
        return element


class ImageboardLinkExtension(Extension):
    def extendMarkdown(self, md):
        IMAGEBOARD_LINK_RE = '>>(?P<number>[1-9][0-9]*)'
        imageboard_link = ImageboardLinkPattern(IMAGEBOARD_LINK_RE)
        md.inlinePatterns['imageboard_link'] = imageboard_link


html = markdown.markdown('>>123',
                         extensions=[ImageboardLinkExtension()])
print(html)

但是,&gt;&gt;123 仍会产生 &lt;blockquote&gt;&lt;blockquote&gt;123&lt;/blockquote&gt;&lt;/blockquote&gt;。上面的实现有什么问题?

【问题讨论】:

    标签: python markdown python-markdown


    【解决方案1】:

    问题是您的新语法与先前存在的块引用语法冲突。如果曾经调用过您的扩展程序,它可能会起作用。然而,由于冲突,这从未发生过。请注意,它们是五种类型的处理器。作为documented

    • 预处理器在将源传递给解析器之前对其进行更改。
    • 块处理器处理由空行分隔的文本块。
    • 树处理器修改构造的 ElementTree
    • 内联处理器是内联元素的常用树处理器,例如*strong*
    • 后处理器会在解析器的输出返回之前对其进行处理。

    这里重要的是处理器按该顺序运行。换句话说,所有块处理器都在运行任何内联处理器之前运行。因此,blockquote 块处理器首先在您的输入上运行并删除双尖括号,将行的其余部分包裹在双 blockquote 标记中。当您的内联处理器看到文档时,您的正则表达式将不再匹配,因此永远不会被调用。

    话虽如此,内联处理器是实现链接语法的正确方法。但是,您需要执行以下两项操作之一才能使其正常工作。

    1. 更改语法,使其不与任何预先存在的语法发生冲突;或
    2. 更改块引用行为以避免冲突。

    就个人而言,我会推荐选项 1,但我了解您正在尝试从另一个环境实现预先存在的语法。因此,如果您想探索选项 2,那么我建议您可能使 blockquote 语法更严格一些。例如,虽然不是必需的,但推荐的语法是始终在块引用中的尖括号后插入一个空格。将BlockquoteProcessor 更改为需要空格应该相对简单,这将导致您的语法不再冲突。

    这其实很简单。您可能注意到,整个语法是通过一个相当简单的正则表达式定义的:

    RE = re.compile(r'(^|\n)[ ]{0,3}>[ ]?(.*)')
    

    您只需重写它,以便不再接受 0 空格(&gt; 而不是 &gt;[ ]?)。首先导入现有处理器并对其进行子类化,然后覆盖正则表达式:

    from markdown.blockprocessors import BlockquoteProcessor
    
    class CustomBlockquoteProcessor(BlockquoteProcessor):
        RE = re.compile(r'(^|\n)[ ]{0,3}> (.*)')
    

    最后,您只需要告诉 Markdown 使用您的自定义类而不是默认类。将以下内容添加到 ImageboardLinkExtension 类的 extendMarkdown 方法中:

    md.parser.blockprocessors.register(CustomBlockQuoteProcessor(md.parser), 'quote', 20)
    

    现在块引用语法将不再与您的链接语法发生冲突,您将有机会在文本上运行您的代码。请注意始终为任何实际的块引用包含现在所需的空间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      相关资源
      最近更新 更多