Python,Markdown和Tailwind:最佳搭档!

您正在使用Python渲染内容,并希望展示一些Markdown,但您的页面样式使用Tailwind。通过Tailwind的内置重置,您如何为Markdown中的标签添加样式?本文展示了如何实现这一点。

我假设您正在使用Python的Markdown包。

最近,我在一个项目中需要渲染一些Markdown描述。Markdown是一个很棒的包,可以快速将Markdown内容转换为标准的HTML输出。对于我的项目而言,最大的挑战是标签没有样式。因此,项目中的所有内容看起来都一样。因为我使用了Tailwind CSS (opens new window),我需要添加类以使标签看起来更加清晰。

我可以实现我的目标的一种方法是将这些标签包装在一个容器中(例如.description),然后在我的CSS文件中编写一些自定义规则。使用Tailwind的@apply功能,这是一条完全可行的路径。实际上,这就是我在这个站点上使用的策略。但在这个站点上使用这种策略多年后,我发现了一些让我想尝试其他方法的烦恼。

要使这个方法起作用,我们将使用一个Markdown扩展

完成后,我们将使用我们的扩展,如:

import markdown

from .extensions import TailwindExtension

with open('content.md', 'r') as f:
    html_output = markdown.markdown(
        f.read(),
        extensions=[TailwindExtension()]
    )

如果您阅读关于Markdown扩展的内容 (opens new window),您将了解到,在扩展内部,您可以使用各种处理器来操作Markdown数据的输入流或HTML输出。

我们需要寻找的处理器是Treeprocessor。在内部,Markdown包使用XML ElementTree (opens new window) API。Treeprocessor提供对HTML输出的根树的访问。我们的扩展策略是为我们定义类的任何找到的标签添加类。

首先,我们可以看一下自定义树处理器的实现。

# extensions.py
...

from markdown.treeprocessors import Treeprocessor

...

class TailwindTreeProcessor(Treeprocessor):
    """遍历根节点并修改任何发现的标签"""

    classes = {
        "a": "underline text-blue-700 hover:text-blue-500",
        "p": "pb-4 text-normal",
    }

    def run(self, root):
        for node in root.iter():
            tag_classes = self.classes.get(node.tag)
            if tag_classes:
                node.attrib["class"] = tag_classes

处理器:

  • 实现了必需的run方法,让我们可以访问root节点
  • 遍历每个标签。ElementTree API将自动递归进入树。
  • 通过node.tag检查标签名称,看是否为该标签定义了任何类。classes字典指定了我们想要自定义的标签。
  • 如果存在自定义类,则将class属性添加到标签中。

就是这样!

让我们通过展示如何将处理器连接到扩展来完成图片。

# extensions.py
from markdown.extensions import Extension
from markdown.treeprocessors import Treeprocessor


class TailwindExtension(Extension):
    """一个用于向标签添加类的扩展"""

    def extendMarkdown(self, md):
        md.treeprocessors.register(
            TailwindTreeProcessor(md), "tailwind", 20)


class TailwindTreeProcessor(Treeprocessor):
    """遍历根节点并修改任何发现的标签"""

    classes = {
        "a": "underline text-blue-700 hover:text-blue-500",
        "p": "pb-4 text-normal",
    }

    def run(self, root):
        for node in root.iter():
            tag_classes = self.classes.get(node.tag)
            if tag_classes:
                node.attrib["class"] = tag_classes

扩展必须定义extendMarkdown并注册处理器。根据您使用的处理器类型,注册的位置会有一些奇怪之处。在我们的情况下,md.treeprocessors是注册我们的处理器的正确位置。查看文档以了解传递给register的参数。

在完成之前,您需要另外一件事。因为我们正在为这个扩展文件添加类,所以需要确保Tailwind正在扫描这个文件。如果不这样做,那么您构建的Tailwind CSS文件将缺少这些类。最初我忽略了这一点,并且对此感到困惑,直到我发现了这个配置更改。以下是在您的tailwind.conf.js文件中可能看起来的配置更改。

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./templates/**/*.html",
    // 在Markdown扩展中嵌入了一些Tailwind类。
    "./path/to/extensions.py",
  ],
}

希望这能帮助您使Markdown内容在您的Tailwind样式项目中看起来更美观。