欢迎光临
我们一直在努力

python:Flask 3, mistune 2, 实现在线编辑 Markdown 文档的 Web 服务程序

承上一篇: nodejs: 能在线编辑 Markdown 文档的 Web 服务程序,更多扩展功能

模仿 app2.js, 请用 python编程 : flask 3, mistune 2, 或者其它模块 实现同样功能的Web服务

以下是使用 Flask 3 + Mistune 2 实现与 app2.js 相同功能的 Python Web 服务,包含 Markdown 解析(支持代码高亮、Mermaid、表格、公式)、文档保存/加载/列表查询等核心功能:

1. 先安装依赖

pip install flask==3.0.3 mistune==2.0.5
pip install pygments python-multipart python-dotenv

2. 完整代码(app.py)

# -*- coding: utf-8 -*-
""" Markdown 在线编辑器 (支持表格/公式/Mermaid) """
import os
import json
from pathlib import Path
import mistune
from mistune.renderers import HTMLRenderer
from mistune.plugins import table, task_lists, footnotes
from pygments import highlight
from pygments.lexers import get_lexer_by_name, guess_lexer
from pygments.formatters import HtmlFormatter
from flask import Flask, render_template, request, jsonify, send_from_directory

# 初始化 Flask 应用
app = Flask(__name__, static_url_path='/',
static_folder='public', # 静态文件目录(对应前端资源)
template_folder='views') # 模板目录(对应editor.html)

# 配置
app.config['JSON_AS_ASCII'] = False # 支持中文
DOCS_DIR = Path(__file__).parent / 'docs' # 文档保存目录
DOCS_DIR.mkdir(exist_ok=True) # 确保目录存在

# —- Markdown 解析配置 —-
# 自定义代码高亮渲染器(支持 Mermaid/代码高亮)
class CustomRenderer(HTMLRenderer):
def block_code(self, code, info=None):
# 处理 Mermaid 代码块
if info and info.strip() == 'mermaid':
return f'<div class="mermaid">{mistune.escape(code)}</div>'

# 处理普通代码块高亮
try:
# 尝试获取指定语言的 lexer
lexer = get_lexer_by_name(info.strip()) if info else guess_lexer(code)
except:
# 自动检测语言
lexer = guess_lexer(code)

# 使用 Pygments 高亮代码
formatter = HtmlFormatter(
noclasses=False, # 生成带类名的 HTML(配合 highlight.js 样式)
cssclass='hljs', # 兼容 highlight.js 样式类
linenos=False # 不显示行号(可根据需求开启)
)
highlighted = highlight(code, lexer, formatter)
return f'<pre>{highlighted}</pre>'

# 初始化 Mistune 解析器(启用所有扩展)
markdown_parser = mistune.create_markdown(
renderer=CustomRenderer(),
plugins=[
'table', # 表格支持
'task_lists', # 任务列表支持
'footnotes' # 脚注支持
],
escape=False # 关键配置:禁用字符转义
)

# —- 路由配置 —-
# 首页 – 编辑器界面
@app.route('/')
def index():
return render_template('editor.html', title='Markdown 在线编辑器 (支持表格/公式/Mermaid)')

# 解析 Markdown 为 HTML (API)
@app.route('/api/parse', methods=['POST'])
def parse_markdown():
try:
data = request.get_json()
markdown = data.get('markdown', '')

if not markdown:
return jsonify({'error': 'Markdown 内容不能为空'}), 400

# 解析 Markdown 为 HTML
html = markdown_parser(markdown)
return jsonify({'html': html})

except Exception as e:
return jsonify({'error': f'解析 Markdown 失败: {str(e)}'}), 500

# 保存文档 (API)
@app.route('/api/save', methods=['POST'])
def save_document():
try:
data = request.get_json()
filename = data.get('filename', '').strip()
content = data.get('content', '').strip()

if not filename or not content:
return jsonify({'error': '文件名和内容不能为空'}), 400

# 拼接文件路径
file_path = DOCS_DIR / f'{filename}.md'
# 写入文件(UTF-8 编码)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)

return jsonify({
'success': True,
'message': '文件保存成功',
'filePath': str(file_path)
})

except Exception as e:
return jsonify({'error': f'保存文件失败: {str(e)}'}), 500

# 加载文档 (API)
@app.route('/api/load/<filename>', methods=['GET'])
def load_document(filename):
try:
file_path = DOCS_DIR / f'{filename}.md'

# 检查文件是否存在
if not file_path.exists():
return jsonify({'error': '文件不存在'}), 404

# 读取文件内容
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()

return jsonify({'success': True, 'content': content})

except Exception as e:
return jsonify({'error': f'加载文件失败: {str(e)}'}), 500

# 获取文档列表 (API)
@app.route('/api/docs', methods=['GET'])
def list_docs():
try:
# 读取目录下所有 .md 文件
docs = []
for file in DOCS_DIR.glob('*.md'):
docs.append({
'name': file.stem, # 不带扩展名的文件名
'path': str(file)
})

return jsonify({'success': True, 'docs': docs})

except Exception as e:
return jsonify({'error': f'获取文档列表失败: {str(e)}'}), 500

# 静态文件服务(兼容前端资源加载)
@app.route('/public/<path:path>')
def serve_static(path):
return send_from_directory('public', path)

# —- 启动服务器 —-
if __name__ == '__main__':
# 启动 Flask 开发服务器(生产环境建议用 Gunicorn)
app.run(
host='127.0.0.1', # 不允许外部访问
port=8000, # 与原 Node.js 端口保持一致
debug=True # 开发模式(生产环境关闭)
)

3. 目录结构说明

需要和原 Node.js 版本保持一致的目录结构,确保前端页面能正常加载:

TREE /F md-editor
md-editor
├── app.py # Python 服务端代码
├── docs/ # 文档保存目录(自动创建)
│ └── demo.md
├── public/ # 静态资源目录(前端 JS/CSS)
│ ├── js/
│ │ ├── mermaid.min.js
│ │ └── highlight.min.js
│ └── css/
│ └── github-dark.min.css
└── views/ # 模板目录
└── editor.html # 原 Node.js 版本的 editor.ejs(无需修改)

4. 核心功能说明

  • Markdown 解析:

    • 使用 mistune 2 作为核心解析器,兼容 GFM 规范
    • 自定义渲染器支持 Mermaid 代码块(输出 <div class="mermaid">)
    • 使用 Pygments 实现代码高亮(兼容 highlight.js 样式)
    • 启用表格、任务列表、脚注等扩展
  • API 接口:

    • /api/parse:POST 请求,解析 Markdown 为 HTML
    • /api/save:POST 请求,保存 Markdown 文档
    • /api/load/<filename>:GET 请求,加载指定文档
    • /api/docs:GET 请求,获取所有文档列表
  • 前端兼容:

    • 静态资源路径、接口地址与原 Node.js 版本完全一致
    • 复用原 editor.html 前端页面,只需修改一行 cd public\\css rename editor.ejs editor.html 修改第6行:<title>{{ title }}</title>
  • 5. 运行方式

    直接运行

    python app.py

    生产环境建议用 Gunicorn

    gunicorn -w 4 -b 0.0.0.0:8000 app:app

    6. 关键注意事项

  • 静态资源:需要将原 Node.js 版本中 public 目录下的 js/mermaid.min.js、js/highlight.min.js、css/github-dark.min.css 复制到 Python 项目的 public 目录中。
  • 公式渲染:数学公式渲染仍由前端 KaTeX 处理,服务端仅负责 Markdown 解析,与原逻辑一致。
  • 编码:所有文件读写均使用 UTF-8 编码,确保中文正常显示。
  • 兼容性:接口返回格式与原 Node.js 版本完全一致,前端无需任何修改即可对接。
  • 该实现完整复刻了原 Node.js 版本的所有核心功能,同时符合 Python/Flask 的开发规范,可直接替换原服务端使用。

    赞(0)
    未经允许不得转载:171主机测评 » python:Flask 3, mistune 2, 实现在线编辑 Markdown 文档的 Web 服务程序
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址