如何用Python开发一个功能全面的Markdown编辑工具
在这篇博客中,我将详细分析和讲解一段用Python
开发的Markdown编辑工具代码。这款工具支持Markdown内容的编辑、HTML预览、导出为PDF和保存为图片的功能,同时还可以实现代码高亮。
C:\pythoncode\new\MarkdownToPdfJpegPreview.py
功能介绍
这款Markdown编辑工具基于wxPython
开发,核心功能包括:
-
Markdown编辑与HTML实时预览:
- 提供编辑区域(Memo)供用户录入Markdown内容。
- 使用
wx.html2.WebView
组件将Markdown内容转为HTML并实时预览。
-
代码高亮:
- 使用Highlight.js实现Markdown代码段的语法高亮。
-
导出功能:
- 支持将Markdown保存为
.md
文件。 - 将HTML预览内容导出为PDF文件。
- 将HTML内容保存为JPEG格式的图片。
- 支持将Markdown保存为
环境准备
所需的依赖库:
- wxPython:构建图形界面
- markdown:将Markdown解析为HTML
- pdfkit:将HTML转换为PDF文件
- imgkit:将HTML保存为图片
- Pillow:处理图像
可以通过以下命令安装:
pip install wxPython markdown pdfkit imgkit pillow
安装wkhtmltopdf
和wkhtmltoimage
工具:
pdfkit
和imgkit
需要wkhtmltopdf
和wkhtmltoimage
工具的支持。
- 下载地址:wkhtmltopdf
- 安装后,将工具路径(如
C:\Program Files\wkhtmltopdf\bin
)加入环境变量,或在代码中显式指定路径。
代码分析
下面是实现Markdown编辑工具的完整代码:
import wx
import wx.html2 # HTML浏览器控件
import markdown # Markdown解析模块
import pdfkit # HTML转PDF模块
from PIL import Image
from io import BytesIO
import imgkit
def markdown_to_html_with_highlight(md_content):
"""将Markdown转换为HTML并添加代码高亮支持"""
html_content = markdown.markdown(md_content, extensions=['fenced_code'])
# 添加Highlight.js脚本和样式
highlight_js = '''
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
'''
return f"{highlight_js}<body>{html_content}</body>"
class MarkdownApp(wx.Frame):
def __init__(self):
super().__init__(None, title="Markdown编辑工具", size=(1000, 700))
self.InitUI()
def InitUI(self):
# 工具栏
toolbar = self.CreateToolBar()
toolbar.AddTool(wx.ID_SAVE, "保存 Markdown", wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE))
toolbar.AddTool(wx.ID_PREVIEW, "预览", wx.ArtProvider.GetBitmap(wx.ART_FIND))
toolbar.AddTool(wx.ID_PRINT, "生成 PDF", wx.ArtProvider.GetBitmap(wx.ART_PRINT))
toolbar.AddTool(wx.ID_SAVEAS, "保存为图片", wx.ArtProvider.GetBitmap(wx.ART_PASTE))
toolbar.Realize()
# 绑定工具栏按钮事件
self.Bind(wx.EVT_TOOL, self.OnSaveMarkdown, id=wx.ID_SAVE)
self.Bind(wx.EVT_TOOL, self.OnPreview, id=wx.ID_PREVIEW)
self.Bind(wx.EVT_TOOL, self.OnGeneratePDF, id=wx.ID_PRINT)
self.Bind(wx.EVT_TOOL, self.OnSaveImage, id=wx.ID_SAVEAS)
# 布局
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
self.memo = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
self.browser = wx.html2.WebView.New(panel)
vbox.Add(self.memo, 1, wx.EXPAND)
vbox.Add(self.browser, 1, wx.EXPAND)
panel.SetSizer(vbox)
self.Show()
def OnPreview(self, event):
"""预览Markdown内容为HTML"""
md_content = self.memo.GetValue()
html_content = markdown_to_html_with_highlight(md_content)
self.browser.SetPage(html_content, "")
def OnSaveMarkdown(self, event):
"""保存Markdown为.md文件"""
with wx.FileDialog(self, "保存 Markdown", wildcard="Markdown 文件 (*.md)|*.md",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return
path = dialog.GetPath()
with open(path, 'w', encoding='utf-8') as file:
file.write(self.memo.GetValue())
def OnGeneratePDF(self, event):
"""生成PDF文件"""
md_content = self.memo.GetValue()
html_content = markdown.markdown(md_content)
with wx.FileDialog(self, "保存 PDF 文件", wildcard="PDF 文件 (*.pdf)|*.pdf",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return
path = dialog.GetPath()
config = pdfkit.configuration(wkhtmltopdf='C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe')
pdfkit.from_string(html_content, path, configuration=config)
def OnSaveImage(self, event):
"""保存HTML内容为JPEG图片"""
md_content = self.memo.GetValue()
html_content = markdown.markdown(md_content)
with wx.FileDialog(self, "保存图片", wildcard="JPEG 文件 (*.jpeg)|*.jpeg",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog:
if dialog.ShowModal() == wx.ID_CANCEL:
return
path = dialog.GetPath()
config = imgkit.config(wkhtmltoimage='C:/Program Files/wkhtmltopdf/bin/wkhtmltoimage.exe')
img_data = imgkit.from_string(html_content, False, config=config)
image = Image.open(BytesIO(img_data))
image.save(path, format="JPEG")
if __name__ == "__main__":
app = wx.App()
MarkdownApp()
app.MainLoop()
功能解析
-
Markdown解析与HTML预览:
markdown.markdown()
方法将Markdown内容转为HTML。- 通过Highlight.js实现代码块的语法高亮。
-
生成PDF:
- 使用
pdfkit
模块的from_string()
方法将HTML内容保存为PDF。 - 需要确保
wkhtmltopdf
工具正确安装并指定路径。
需要安装wkhtmltopdf应用程序
https://wkhtmltopdf.org/downloads.html
- 使用
-
保存为图片:
- 使用
imgkit
模块生成HTML内容的图片。 - 使用
Pillow
库将生成的图像数据保存为JPEG格式。
- 使用
-
界面交互:
- 使用
wxPython
的工具栏和对话框实现文件保存等功能。 - 提供预览功能让用户直观地查看Markdown效果。
- 使用