python markdown 自定义扩展

参考博客:https://www.cnblogs.com/JiangLe/p/12682912.html

aiofiles            23.2.1    
aiohttp             3.9.1
aiosignal           1.3.1
asgiref             3.7.2
attrs               23.1.0
autobahn            23.6.2
Automat             22.10.0
beautifulsoup4      4.12.3
certifi             2023.11.17
cffi                1.16.0
chardet             5.2.0
charset-normalizer  3.3.2
colorama            0.4.6
constantly          23.10.4
cryptography        42.0.2
daphne              4.0.0
Django              5.0.1
et-xmlfile          1.1.0
frozenlist          1.4.1
html5lib            1.1
hyperlink           21.0.0
idna                3.6
incremental         22.10.0
lxml                4.9.4
Markdown            3.7
multidict           6.0.4
numpy               1.26.4
openpyxl            3.1.2
pip                 25.0.1
pyasn1              0.5.1
pyasn1-modules      0.3.0
pycparser           2.21
pyOpenSSL           24.0.0
requests            2.31.0
service-identity    24.1.0
setuptools          65.5.0
six                 1.16.0
soupsieve           2.5
sqlparse            0.4.4
Twisted             23.10.0
twisted-iocpsupport 1.0.4
txaio               23.1.1
typing_extensions   4.9.0
tzdata              2023.4
urllib3             2.1.0
webencodings        0.5.1
yarl                1.9.4
zope.interface      6.1
md = markdown.Markdown(
        extensions=[
            # 包含 缩写、表格等常用扩展
            # 'markdown.extensions.extra',
            AddButtonToExtension(),
            # 语法高亮扩展
            # 'markdown.extensions.codehilite',
            # 目录
            # 'markdown.extensions.toc',

        ],
    )
import markdown
from markdown.treeprocessors import Treeprocessor
from markdown.extensions import Extension
from xml.etree import ElementTree as ET

# 自定义 Treeprocessor 类
class AddButtonToTreeprocessor(Treeprocessor):
    def run(self, root):
        # 遍历文档树中的所有 <pre> 标签
        for pre in root.iter('pre'):
            # 创建一个 button 元素
            button = ET.Element('button')
            button.text = 'Copy Code'
            button.set('onclick', 'alert("You clicked the copy button!")')

            # 在 <pre> 标签之前插入按钮
            pre.insert(0, button)

        return root


# 自定义扩展类
class AddButtonToExtension(Extension):
    def extendMarkdown(self, md):
        # 注册自定义的 Treeprocessor
        md.treeprocessors.register(AddButtonToTreeprocessor(md), 'add_button_to_pre', 15)

def convert_markdown_to_html(markdown_text):
    # 创建 Markdown 实例并使用自定义扩展
    # md = markdown.Markdown(extensions=[AddButtonToExtension()])
    md = markdown.Markdown(extensions=[])
    return md.convert(markdown_text)

def write_html_to_file(html_content, output_file):
    with open(output_file, 'w', encoding='utf-8') as file:
        file.write(html_content)

if __name__ == "__main__":
    markdown_text = '''
    # Heading 1
    ## Heading 2

    this is c code
    ```
    #include <iostream>

    int main() {
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }
    ```
    '''
    html = convert_markdown_to_html(markdown_text)
    print(html)
    write_html_to_file(html, 'output.html')

代码可复制

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pre Code Copy Button with Hover</title>
    <style>
        pre {
            position: relative;
            background-color: #f4f4f4;
            padding: 20px;
            border: 1px solid #ccc;
            border-radius: 4px;
            overflow-x: auto;
        }

        .copy-button {
            position: absolute;
            top: 10px;
            right: 10px;
            padding: 5px 10px;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            opacity: 0; /* 默认隐藏按钮 */
            transition: opacity 0.3s ease; /* 添加过渡效果 */
        }

        pre:hover .copy-button {
            opacity: 1; /* 鼠标悬停时显示按钮 */
        }
    </style>
</head>

<body>
    <pre>
        <button class="copy-button">复制</button>
        <code>
            function add(a, b) {
                return a + b;
            }
            const result = add(3, 5);
            console.log(result);
        </code>
    </pre>

    <script>
        const copyButtons = document.querySelectorAll('.copy-button');
        copyButtons.forEach(button => {
            button.addEventListener('click', async () => {
                const preElement = button.parentNode;
                const codeElement = preElement.querySelector('code');
                const codeText = codeElement.textContent;

                try {
                    await navigator.clipboard.writeText(codeText);
                    button.textContent = '已复制';
                    setTimeout(() => {
                        button.textContent = '复制';
                    }, 2000);
                } catch (err) {
                    console.error('复制失败:', err);
                }
            });
        });
    </script>
</body>

</html>
文章目录