01 引言
在日常使用 markdown 编写文档时,我们有时会需要将 markdown 格式的文本转换为纯文本,去除其中的各种标记符号,如标题符号、列表符号、代码块标记等。手动去除这些标记不仅效率低下,还容易出错。本文将介绍如何使用 python 和 pyqt5 库来创建一个简单易用的 markdown 格式消除工具,并且支持实时预览和文件保存功能。
02 环境准备
在开始之前,我们需要安装一些必要的库。主要用到的是 pyqt5 用于创建图形用户界面(gui),以及 python 内置的 re 库用于正则表达式匹配,用于去除 markdown 格式。可以使用以下命令来安装 pyqt5:
pip install pyqt5
03 实现思路
我们的 markdown 格式消除工具主要包含以下几个部分:
图形用户界面(gui):使用 pyqt5 创建一个窗口,包含输入框、输出框和一些操作按钮,如导入文本、清除格式、复制文本、保存文本等。
markdown 格式处理:使用正则表达式匹配 markdown 标记符号,并将其替换为空字符串,从而实现格式消除。
实时预览:当用户在输入框中输入或修改 markdown 文本时,实时更新输出框中的纯文本内容。
文件操作:支持直接拖入或导入 markdown 文件和保存处理后的纯文本文件。
04 完整代码
import sys import re from pyqt5.qtwidgets import ( qapplication, qwidget, qvboxlayout, qtextedit, qpushbutton, qlabel, qfiledialog, qhboxlayout ) from pyqt5.qtgui import qfont, qclipboard from pyqt5.qtcore import qt, pyqtslot class markdownremoverapp(qwidget): def __init__(self): super().__init__() self.dark_theme = false # 初始为亮色主题 self.setacceptdrops(true) # 启用拖放功能 self.init_ui() def init_ui(self): """初始化界面""" # 设置窗口标题和大小 self.setwindowtitle("markdown 格式清除工具") self.setgeometry(100, 100, 800, 800) # 设置全局字体 font = qfont("arial", 12) self.setfont(font) # 整体水平布局 main_h_layout = qhboxlayout() # 左侧文本编辑区域垂直布局 left_v_layout = qvboxlayout() # 原始 markdown 文本部分 self.left_label = qlabel("原始 markdown 文本") self.left_label.setstylesheet("font-size: 14px; font-weight: bold;") self.left_text_edit = qtextedit() self.left_text_edit.setstylesheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;") left_v_layout.addwidget(self.left_label) left_v_layout.addwidget(self.left_text_edit) # 清除 markdown 后的文本部分 self.right_label = qlabel("清除 markdown 后的文本") self.right_label.setstylesheet("font-size: 14px; font-weight: bold;") self.right_text_edit = qtextedit() self.right_text_edit.setstylesheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;") left_v_layout.addwidget(self.right_label) left_v_layout.addwidget(self.right_text_edit) # 右侧按钮垂直布局 right_v_layout = qvboxlayout() # 导入文本按钮 self.import_button = qpushbutton("导入文本") self.import_button.setstylesheet(""" qpushbutton { background-color: #4caf50; color: white; font-family: arial; font-size: 14px; font-weight: bold; padding: 12px 20px; border-radius: 8px; border: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } qpushbutton:hover { background-color: #66bb6a; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); } qpushbutton:pressed { background-color: #388e3c; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transform: translatey(2px); } """) self.import_button.setcursor(qt.pointinghandcursor) self.import_button.clicked.connect(self.import_text) # 一键复制按钮 self.copy_button = qpushbutton("一键复制") self.copy_button.setstylesheet(""" qpushbutton { background-color: #ff9800; color: white; font-family: arial; font-size: 14px; font-weight: bold; padding: 12px 20px; border-radius: 8px; border: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } qpushbutton:hover { background-color: #ffb74d; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); } qpushbutton:pressed { background-color: #f57c00; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transform: translatey(2px); } """) self.copy_button.setcursor(qt.pointinghandcursor) self.copy_button.clicked.connect(self.copy_text) # 一键清除按钮 self.clear_all_button = qpushbutton("一键清除") self.clear_all_button.setstylesheet(""" qpushbutton { background-color: #f44336; color: white; font-family: arial; font-size: 14px; font-weight: bold; padding: 12px 20px; border-radius: 8px; border: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } qpushbutton:hover { background-color: #ef5350; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); } qpushbutton:pressed { background-color: #d32f2f; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transform: translatey(2px); } """) self.clear_all_button.setcursor(qt.pointinghandcursor) self.clear_all_button.clicked.connect(self.clear_all_text) # 主题切换按钮 self.theme_button = qpushbutton("切换主题") self.theme_button.setstylesheet(""" qpushbutton { background-color: #607d8b; color: white; font-family: arial; font-size: 14px; font-weight: bold; padding: 12px 20px; border-radius: 8px; border: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } qpushbutton:hover { background-color: #78909c; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); } qpushbutton:pressed { background-color: #546e7a; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transform: translatey(2px); } """) self.theme_button.setcursor(qt.pointinghandcursor) self.theme_button.clicked.connect(self.toggle_theme) # 保存处理后文本按钮 self.save_button = qpushbutton("保存处理后的文本") self.save_button.setstylesheet(""" qpushbutton { background-color: #9e9e9e; color: white; font-family: arial; font-size: 14px; font-weight: bold; padding: 12px 20px; border-radius: 8px; border: none; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } qpushbutton:hover { background-color: #bdbdbd; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); } qpushbutton:pressed { background-color: #757575; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transform: translatey(2px); } """) self.save_button.setcursor(qt.pointinghandcursor) self.save_button.clicked.connect(self.save_text) # 将按钮添加到右侧按钮布局 right_v_layout.addwidget(self.import_button) right_v_layout.addwidget(self.copy_button) right_v_layout.addwidget(self.clear_all_button) right_v_layout.addwidget(self.theme_button) right_v_layout.addwidget(self.save_button) # 将左侧文本编辑区域布局和右侧按钮布局添加到整体水平布局 main_h_layout.addlayout(left_v_layout) main_h_layout.addlayout(right_v_layout) # 设置主布局 self.setlayout(main_h_layout) # 连接文本改变信号实现实时预览 self.left_text_edit.textchanged.connect(self.update_preview) @pyqtslot() def update_preview(self): """实时更新清除 markdown 格式后的文本预览""" markdown_text = self.left_text_edit.toplaintext() cleaned_text = self._remove_markdown(markdown_text) self.right_text_edit.setplaintext(cleaned_text) def import_text(self): """导入文本文件""" # 打开文件选择对话框 file_path, _ = qfiledialog.getopenfilename( self, "选择文本文件", "", "文本文件 (*.txt);;所有文件 (*)" ) if file_path: # 读取文件内容 try: with open(file_path, "r", encoding="utf-8") as file: content = file.read() # 将内容加载到左侧文本框 self.left_text_edit.setplaintext(content) except exception as e: print(f"读取文件出错: {e}") def copy_text(self): """将清除 markdown 格式后的文本复制到剪贴板""" clipboard = qapplication.clipboard() cleaned_text = self.right_text_edit.toplaintext() clipboard.settext(cleaned_text) def clear_all_text(self): """一键清除左右文本框的内容""" self.left_text_edit.clear() self.right_text_edit.clear() def _remove_markdown(self, text): """ 移除 markdown 格式并返回纯文本 """ # 转换转义字符 text = re.sub(r'\\([\\`*{}[\]()\#+\-.!_>~|])', r'\1', text) # 删除代码块(多行) text = re.sub(r'```[\s\s]*?```', '', text) # 删除行内代码 text = re.sub(r'`([^`]+)`', r'\1', text) # 处理图片和链接 text = re.sub(r'!\[(.*?)\]\([^)]*\)', r'\1', text) # 图片 text = re.sub(r'\[(.*?)\]\([^)]*\)', r'\1', text) # 链接 # 处理粗体/斜体 text = re.sub(r'\*\*(\*?[\s\s]+?)\*\*', r'\1', text) # **bold** text = re.sub(r'__([\s\s]+?)__', r'\1', text) # __underline__ text = re.sub(r'\*([\s\s]+?)\*', r'\1', text) # *italic* text = re.sub(r'_([\s\s]+?)_', r'\1', text) # _italic_ # 清除标题符号 text = re.sub(r'^#+\s*', '', text, flags=re.multiline) # 清除列表符号(支持多级列表) text = re.sub(r'^([\s]*[-*+]|\d+\.)\s+', '', text, flags=re.multiline) # 清除引用块符号 text = re.sub(r'^>\s*', '', text, flags=re.multiline) # 清除分隔线 text = re.sub(r'^[-*_]{3,}\s*$', '', text, flags=re.multiline) # 合并多余空行并去除首尾空白 text = re.sub(r'\n{3,}', '\n\n', text) return text.strip() def toggle_theme(self): if self.dark_theme: # 切换到亮色主题 self.setstylesheet("") self.left_text_edit.setstylesheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;") self.right_text_edit.setstylesheet("background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px;") self.left_label.setstylesheet("font-size: 14px; font-weight: bold;") self.right_label.setstylesheet("font-size: 14px; font-weight: bold;") self.dark_theme = false else: # 切换到暗色主题 self.setstylesheet("background-color: #212121; color: white;") self.left_text_edit.setstylesheet("background-color: #424242; border: 1px solid #616161; padding: 10px; color: white;") self.right_text_edit.setstylesheet("background-color: #424242; border: 1px solid #616161; padding: 10px; color: white;") self.left_label.setstylesheet("font-size: 14px; font-weight: bold; color: white;") self.right_label.setstylesheet("font-size: 14px; font-weight: bold; color: white;") self.dark_theme = true def save_text(self): """保存处理后的文本到指定文件""" file_path, _ = qfiledialog.getsavefilename(self, "保存文件", "", "文本文件 (*.txt)") if file_path: try: text = self.right_text_edit.toplaintext() with open(file_path, 'w', encoding='utf-8') as file: file.write(text) except exception as e: print(f"保存文件出错: {e}") def dragenterevent(self, event): """处理拖入事件,检查是否是文件""" if event.mimedata().hasurls(): for url in event.mimedata().urls(): if url.tolocalfile().endswith(('.txt', '.md')): event.acceptproposedaction() return event.ignore() def dropevent(self, event): """处理放下事件,读取文件内容并加载到左侧文本框""" for url in event.mimedata().urls(): file_path = url.tolocalfile() if file_path.endswith(('.txt', '.md')): try: with open(file_path, 'r', encoding='utf-8') as file: content = file.read() self.left_text_edit.setplaintext(content) except exception as e: print(f"读取文件出错: {e}") # 主程序入口 if __name__ == "__main__": app = qapplication(sys.argv) window = markdownremoverapp() window.show() sys.exit(app.exec_())
05 运行结果
到此这篇关于python实现markdown格式消除工具的文章就介绍到这了,更多相关python markdown格式消除内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论