首页 > 解决方案 > Markdown:注册模式的处理订单

问题描述

InlineProcessor我已经根据模式出现时正确匹配的对象为 Markdown 编写了一个 python 扩展:

自定义扩展:

from markdown.util import AtomicString, etree
from markdown.extensions import Extension
from markdown.inlinepatterns import InlineProcessor

RE = r'(#)(\S{3,})'

class MyPattern(InlineProcessor):
    def handleMatch(self, m, data):
        tag = m.group(2)

        el = etree.Element("a")
        el.set('href', f'/{tag}')
        el.text = AtomicString(f'#{tag}')

        return el, m.start(0), m.end(0)

class MyExtension(Extension):
    def extendMarkdown(self, md, md_globals):
        # If processed by attr_list extension, not by this one
        md.inlinePatterns.register(MyPattern(RE, md), 'my_tag', 200)

def makeExtension(*args, **kwargs):
    return MyExtension(*args, **kwargs)

在: markdown('foo #bar')

出去: <p>foo <a href="/bar">#bar</a></p>

但是我的扩展在 python markdown 的额外内容中破坏了一个名为attr_list的本机功能。

在: ### Title {style="color:#FF0000;"}

出去: <h3>Title {style="color:<a href="/FF0000;&quot;}">#FF0000;"}</a></h3>

我不确定是否正确理解Python-Markdown如何在文本上注册/应用模式。我尝试用一​​个大数字注册我的模式以将其放在流程的最后,md.inlinePatterns.register(MyPattern(RE, md), 'my_tag', 200)但它没有完成这项工作。

我查看了attr_list 扩展的源代码,它们使用Treeprocessor基于类。我需要有一个基于Treeprocessor而不是InlineProcessor我的MyPattern的类吗?要找到一种方法不将我的标签应用于元素如何已经与另一个元素匹配(那里:)attr_list

标签: pythonmarkdown

解决方案


您需要一个不会导致错误匹配的更严格的正则表达式。或者您可能需要更改您使用的语法,以免与其他合法文本发生冲突。

首先,事件的顺序是正确的。使用您的示例输入:

### Title {style="color:#FF0000;"}

InlineProcessor得到它时,到目前为止它已被处理为:

<h3>Title {style="color:#FF0000;"}</h3>

请注意,现在存在块级标签 ( <h3>),但attr_list尚未处理。那是你的问题。您的正则表达式正在匹配#FF0000;"}并将其转换为链接:<a href="/FF0000;&quot;}">#FF0000;"}</a>

最后,在完成所有 InlinePrecessor 之后,attr_list运行 TreeProsessor,但由于中间有链接,它不会将文本识别为有效的 attr_list 并忽略它(应该如此)。

换句话说,您的问题与订单完全无关。您不能在 attr_list TreeProcessor 之后运行内联处理器,因此您需要探索其他替代方案。你至少有两个选择:

  1. 重写您的正则表达式以不存在错误匹配。您可能想尝试使用单词边界或其他东西。
  2. 重新考虑您提议的新语法。#bar是一种非常模糊的语法,可能会在文本的其他地方再次出现并导致错误匹配。也许您可以要求将其括在括号中或使用哈希以外的其他字符。

就个人而言,我强烈建议第二种选择。阅读其中的一些文本#bar,这不是很明显的链接。但是,[#bar](或类似的)会更清楚。


推荐阅读