Compare commits

..

3 Commits

24 changed files with 584 additions and 149 deletions

View File

@@ -10,28 +10,28 @@ A collection of enhancements, plugins, and prompts for [OpenWebUI](https://githu
<!-- STATS_START --> <!-- STATS_START -->
## 📊 Community Stats ## 📊 Community Stats
> 🕐 Auto-updated: 2026-01-17 17:07 > 🕐 Auto-updated: 2026-01-18 00:08
| 👤 Author | 👥 Followers | ⭐ Points | 🏆 Contributions | | 👤 Author | 👥 Followers | ⭐ Points | 🏆 Contributions |
|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|
| [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **118** | **108** | **25** | | [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **119** | **113** | **25** |
| 📝 Posts | ⬇️ Downloads | 👁️ Views | 👍 Upvotes | 💾 Saves | | 📝 Posts | ⬇️ Downloads | 👁️ Views | 👍 Upvotes | 💾 Saves |
|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|
| **16** | **1622** | **19716** | **94** | **123** | | **16** | **1659** | **19990** | **99** | **126** |
### 🔥 Top 6 Popular Plugins ### 🔥 Top 6 Popular Plugins
> 🕐 Auto-updated: 2026-01-17 17:07 > 🕐 Auto-updated: 2026-01-18 00:08
| Rank | Plugin | Version | Downloads | Views | Updated | | Rank | Plugin | Version | Downloads | Views | Updated |
|:---:|------|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|
| 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 0.9.1 | 503 | 4601 | 2026-01-17 | | 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 0.9.1 | 507 | 4641 | 2026-01-17 |
| 🥈 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 1.4.9 | 217 | 2232 | 2026-01-17 | | 🥈 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 1.4.9 | 228 | 2285 | 2026-01-17 |
| 🥉 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 0.3.7 | 202 | 747 | 2026-01-07 | | 🥉 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 0.3.7 | 202 | 751 | 2026-01-07 |
| 4⃣ | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 1.1.3 | 171 | 1889 | 2026-01-17 | | 4⃣ | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 1.1.3 | 174 | 1906 | 2026-01-17 |
| 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 0.2.4 | 131 | 2254 | 2026-01-17 | | 5⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 0.4.3 | 134 | 1255 | 2026-01-17 |
| 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 0.4.3 | 130 | 1234 | 2026-01-17 | | 6⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 0.2.4 | 132 | 2269 | 2026-01-17 |
*See full stats in [Community Stats Report](./docs/community-stats.md)* *See full stats in [Community Stats Report](./docs/community-stats.md)*
<!-- STATS_END --> <!-- STATS_END -->

View File

@@ -7,28 +7,28 @@ OpenWebUI 增强功能集合。包含个人开发与收集的插件、提示词
<!-- STATS_START --> <!-- STATS_START -->
## 📊 社区统计 ## 📊 社区统计
> 🕐 自动更新于 2026-01-17 17:07 > 🕐 自动更新于 2026-01-18 00:08
| 👤 作者 | 👥 粉丝 | ⭐ 积分 | 🏆 贡献 | | 👤 作者 | 👥 粉丝 | ⭐ 积分 | 🏆 贡献 |
|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|
| [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **118** | **108** | **25** | | [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **119** | **113** | **25** |
| 📝 发布 | ⬇️ 下载 | 👁️ 浏览 | 👍 点赞 | 💾 收藏 | | 📝 发布 | ⬇️ 下载 | 👁️ 浏览 | 👍 点赞 | 💾 收藏 |
|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|
| **16** | **1622** | **19716** | **94** | **123** | | **16** | **1659** | **19990** | **99** | **126** |
### 🔥 热门插件 Top 6 ### 🔥 热门插件 Top 6
> 🕐 自动更新于 2026-01-17 17:07 > 🕐 自动更新于 2026-01-18 00:08
| 排名 | 插件 | 版本 | 下载 | 浏览 | 更新日期 | | 排名 | 插件 | 版本 | 下载 | 浏览 | 更新日期 |
|:---:|------|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|
| 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 0.9.1 | 503 | 4601 | 2026-01-17 | | 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 0.9.1 | 507 | 4641 | 2026-01-17 |
| 🥈 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 1.4.9 | 217 | 2232 | 2026-01-17 | | 🥈 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 1.4.9 | 228 | 2285 | 2026-01-17 |
| 🥉 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 0.3.7 | 202 | 747 | 2026-01-07 | | 🥉 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 0.3.7 | 202 | 751 | 2026-01-07 |
| 4⃣ | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 1.1.3 | 171 | 1889 | 2026-01-17 | | 4⃣ | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 1.1.3 | 174 | 1906 | 2026-01-17 |
| 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 0.2.4 | 131 | 2254 | 2026-01-17 | | 5⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 0.4.3 | 134 | 1255 | 2026-01-17 |
| 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 0.4.3 | 130 | 1234 | 2026-01-17 | | 6⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 0.2.4 | 132 | 2269 | 2026-01-17 |
*完整统计请查看 [社区统计报告](./docs/community-stats.zh.md)* *完整统计请查看 [社区统计报告](./docs/community-stats.zh.md)*
<!-- STATS_END --> <!-- STATS_END -->

View File

@@ -1,7 +1,7 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"label": "downloads", "label": "downloads",
"message": "1.6k", "message": "1.7k",
"color": "blue", "color": "blue",
"namedLogo": "openwebui" "namedLogo": "openwebui"
} }

View File

@@ -1,6 +1,6 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"label": "followers", "label": "followers",
"message": "118", "message": "119",
"color": "blue" "color": "blue"
} }

View File

@@ -1,6 +1,6 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"label": "points", "label": "points",
"message": "108", "message": "113",
"color": "orange" "color": "orange"
} }

View File

@@ -1,6 +1,6 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"label": "upvotes", "label": "upvotes",
"message": "94", "message": "99",
"color": "brightgreen" "color": "brightgreen"
} }

View File

@@ -1,10 +1,10 @@
{ {
"total_posts": 16, "total_posts": 16,
"total_downloads": 1622, "total_downloads": 1659,
"total_views": 19716, "total_views": 19990,
"total_upvotes": 94, "total_upvotes": 99,
"total_downvotes": 2, "total_downvotes": 2,
"total_saves": 123, "total_saves": 126,
"total_comments": 23, "total_comments": 23,
"by_type": { "by_type": {
"action": 14, "action": 14,
@@ -18,9 +18,9 @@
"version": "0.9.1", "version": "0.9.1",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Intelligently analyzes text content and generates interactive mind maps to help users structure and visualize knowledge.", "description": "Intelligently analyzes text content and generates interactive mind maps to help users structure and visualize knowledge.",
"downloads": 503, "downloads": 507,
"views": 4601, "views": 4641,
"upvotes": 13, "upvotes": 14,
"saves": 28, "saves": 28,
"comments": 11, "comments": 11,
"created_at": "2025-12-30", "created_at": "2025-12-30",
@@ -34,10 +34,10 @@
"version": "1.4.9", "version": "1.4.9",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "AI-powered infographic generator based on AntV Infographic. Supports professional templates, auto-icon matching, and SVG/PNG downloads.", "description": "AI-powered infographic generator based on AntV Infographic. Supports professional templates, auto-icon matching, and SVG/PNG downloads.",
"downloads": 217, "downloads": 228,
"views": 2232, "views": 2285,
"upvotes": 10, "upvotes": 11,
"saves": 15, "saves": 16,
"comments": 2, "comments": 2,
"created_at": "2025-12-28", "created_at": "2025-12-28",
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
@@ -51,7 +51,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Extracts tables from chat messages and exports them to Excel (.xlsx) files with smart formatting.", "description": "Extracts tables from chat messages and exports them to Excel (.xlsx) files with smart formatting.",
"downloads": 202, "downloads": 202,
"views": 747, "views": 751,
"upvotes": 3, "upvotes": 3,
"saves": 5, "saves": 5,
"comments": 0, "comments": 0,
@@ -66,8 +66,8 @@
"version": "1.1.3", "version": "1.1.3",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression.", "description": "Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression.",
"downloads": 171, "downloads": 174,
"views": 1889, "views": 1906,
"upvotes": 7, "upvotes": 7,
"saves": 18, "saves": 18,
"comments": 0, "comments": 0,
@@ -75,6 +75,22 @@
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/async_context_compression_b1655bc8" "url": "https://openwebui.com/posts/async_context_compression_b1655bc8"
}, },
{
"title": "Export to Word (Enhanced)",
"slug": "export_to_word_enhanced_formatting_fca6a315",
"type": "action",
"version": "0.4.3",
"author": "Fu-Jie",
"description": "Export current conversation from Markdown to Word (.docx) with Mermaid diagrams rendered client-side (Mermaid.js, SVG+PNG), LaTeX math, real hyperlinks, improved tables, syntax highlighting, and blockquote support.",
"downloads": 134,
"views": 1255,
"upvotes": 6,
"saves": 15,
"comments": 0,
"created_at": "2026-01-03",
"updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315"
},
{ {
"title": "Flash Card", "title": "Flash Card",
"slug": "flash_card_65a2ea8f", "slug": "flash_card_65a2ea8f",
@@ -82,8 +98,8 @@
"version": "0.2.4", "version": "0.2.4",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Quickly generates beautiful flashcards from text, extracting key points and categories.", "description": "Quickly generates beautiful flashcards from text, extracting key points and categories.",
"downloads": 131, "downloads": 132,
"views": 2254, "views": 2269,
"upvotes": 8, "upvotes": 8,
"saves": 10, "saves": 10,
"comments": 2, "comments": 2,
@@ -92,20 +108,20 @@
"url": "https://openwebui.com/posts/flash_card_65a2ea8f" "url": "https://openwebui.com/posts/flash_card_65a2ea8f"
}, },
{ {
"title": "Export to Word (Enhanced)", "title": "Markdown Normalizer",
"slug": "export_to_word_enhanced_formatting_fca6a315", "slug": "markdown_normalizer_baaa8732",
"type": "action", "type": "action",
"version": "0.4.3", "version": "1.2.2",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Export current conversation from Markdown to Word (.docx) with Mermaid diagrams rendered client-side (Mermaid.js, SVG+PNG), LaTeX math, real hyperlinks, improved tables, syntax highlighting, and blockquote support.", "description": "A content normalizer filter that fixes common Markdown formatting issues in LLM outputs, such as broken code blocks, LaTeX formulas, and list formatting.",
"downloads": 130, "downloads": 63,
"views": 1234, "views": 1746,
"upvotes": 6, "upvotes": 9,
"saves": 14, "saves": 15,
"comments": 0, "comments": 5,
"created_at": "2026-01-03", "created_at": "2026-01-12",
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315" "url": "https://openwebui.com/posts/markdown_normalizer_baaa8732"
}, },
{ {
"title": "导出为 Word (增强版)", "title": "导出为 Word (增强版)",
@@ -114,31 +130,15 @@
"version": "0.4.3", "version": "0.4.3",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "将对话导出为 Word (.docx),支持 Mermaid 图表 (客户端渲染 SVG+PNG)、LaTeX 数学公式、真实超链接、增强表格格式、代码高亮和引用块。", "description": "将对话导出为 Word (.docx),支持 Mermaid 图表 (客户端渲染 SVG+PNG)、LaTeX 数学公式、真实超链接、增强表格格式、代码高亮和引用块。",
"downloads": 58, "downloads": 62,
"views": 1246, "views": 1262,
"upvotes": 9, "upvotes": 10,
"saves": 3, "saves": 3,
"comments": 1, "comments": 1,
"created_at": "2026-01-04", "created_at": "2026-01-04",
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0" "url": "https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0"
}, },
{
"title": "Markdown Normalizer",
"slug": "markdown_normalizer_baaa8732",
"type": "action",
"version": "1.2.0",
"author": "Fu-Jie",
"description": "A content normalizer filter that fixes common Markdown formatting issues in LLM outputs, such as broken code blocks, LaTeX formulas, and list formatting.",
"downloads": 57,
"views": 1681,
"upvotes": 8,
"saves": 14,
"comments": 5,
"created_at": "2026-01-12",
"updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/markdown_normalizer_baaa8732"
},
{ {
"title": "Deep Dive", "title": "Deep Dive",
"slug": "deep_dive_c0b846e4", "slug": "deep_dive_c0b846e4",
@@ -146,8 +146,8 @@
"version": "1.0.0", "version": "1.0.0",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "A comprehensive thinking lens that dives deep into any content - from context to logic, insights, and action paths.", "description": "A comprehensive thinking lens that dives deep into any content - from context to logic, insights, and action paths.",
"downloads": 57, "downloads": 58,
"views": 597, "views": 605,
"upvotes": 3, "upvotes": 3,
"saves": 5, "saves": 5,
"comments": 0, "comments": 0,
@@ -163,8 +163,8 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "基于 AntV Infographic 的智能信息图生成插件。支持多种专业模板,自动图标匹配,并提供 SVG/PNG 下载功能。", "description": "基于 AntV Infographic 的智能信息图生成插件。支持多种专业模板,自动图标匹配,并提供 SVG/PNG 下载功能。",
"downloads": 41, "downloads": 41,
"views": 650, "views": 654,
"upvotes": 4, "upvotes": 5,
"saves": 0, "saves": 0,
"comments": 0, "comments": 0,
"created_at": "2025-12-28", "created_at": "2025-12-28",
@@ -179,7 +179,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "智能分析文本内容,生成交互式思维导图,帮助用户结构化和可视化知识。", "description": "智能分析文本内容,生成交互式思维导图,帮助用户结构化和可视化知识。",
"downloads": 22, "downloads": 22,
"views": 389, "views": 392,
"upvotes": 2, "upvotes": 2,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
@@ -187,6 +187,22 @@
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b" "url": "https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b"
}, },
{
"title": "闪记卡 (Flash Card)",
"slug": "闪记卡生成插件_4a31eac3",
"type": "action",
"version": "0.2.4",
"author": "Fu-Jie",
"description": "快速将文本提炼为精美的学习记忆卡片,支持核心要点提取与分类。",
"downloads": 16,
"views": 430,
"upvotes": 4,
"saves": 1,
"comments": 0,
"created_at": "2025-12-30",
"updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/闪记卡生成插件_4a31eac3"
},
{ {
"title": "异步上下文压缩", "title": "异步上下文压缩",
"slug": "异步上下文压缩_5c0617cb", "slug": "异步上下文压缩_5c0617cb",
@@ -195,7 +211,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。", "description": "通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。",
"downloads": 14, "downloads": 14,
"views": 337, "views": 340,
"upvotes": 4, "upvotes": 4,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
@@ -203,22 +219,6 @@
"updated_at": "2026-01-17", "updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/异步上下文压缩_5c0617cb" "url": "https://openwebui.com/posts/异步上下文压缩_5c0617cb"
}, },
{
"title": "闪记卡 (Flash Card)",
"slug": "闪记卡生成插件_4a31eac3",
"type": "action",
"version": "0.2.4",
"author": "Fu-Jie",
"description": "快速将文本提炼为精美的学习记忆卡片,支持核心要点提取与分类。",
"downloads": 13,
"views": 423,
"upvotes": 4,
"saves": 1,
"comments": 0,
"created_at": "2025-12-30",
"updated_at": "2026-01-17",
"url": "https://openwebui.com/posts/闪记卡生成插件_4a31eac3"
},
{ {
"title": "精读", "title": "精读",
"slug": "精读_99830b0f", "slug": "精读_99830b0f",
@@ -243,7 +243,7 @@
"author": "", "author": "",
"description": "", "description": "",
"downloads": 0, "downloads": 0,
"views": 43, "views": 46,
"upvotes": 0, "upvotes": 0,
"saves": 0, "saves": 0,
"comments": 0, "comments": 0,
@@ -259,7 +259,7 @@
"author": "", "author": "",
"description": "", "description": "",
"downloads": 0, "downloads": 0,
"views": 1139, "views": 1154,
"upvotes": 11, "upvotes": 11,
"saves": 7, "saves": 7,
"comments": 2, "comments": 2,
@@ -273,10 +273,10 @@
"name": "Fu-Jie", "name": "Fu-Jie",
"profile_url": "https://openwebui.com/u/Fu-Jie", "profile_url": "https://openwebui.com/u/Fu-Jie",
"profile_image": "https://community.s3.openwebui.com/uploads/users/b15d1348-4347-42b4-b815-e053342d6cb0/profile_d9510745-4bd4-4f8f-a997-4a21847d9300.webp", "profile_image": "https://community.s3.openwebui.com/uploads/users/b15d1348-4347-42b4-b815-e053342d6cb0/profile_d9510745-4bd4-4f8f-a997-4a21847d9300.webp",
"followers": 118, "followers": 119,
"following": 2, "following": 2,
"total_points": 108, "total_points": 113,
"post_points": 92, "post_points": 97,
"comment_points": 16, "comment_points": 16,
"contributions": 25 "contributions": 25
} }

View File

@@ -1,16 +1,16 @@
# 📊 OpenWebUI Community Stats Report # 📊 OpenWebUI Community Stats Report
> 📅 Updated: 2026-01-17 17:07 > 📅 Updated: 2026-01-18 00:08
## 📈 Overview ## 📈 Overview
| Metric | Value | | Metric | Value |
|------|------| |------|------|
| 📝 Total Posts | 16 | | 📝 Total Posts | 16 |
| ⬇️ Total Downloads | 1622 | | ⬇️ Total Downloads | 1659 |
| 👁️ Total Views | 19716 | | 👁️ Total Views | 19990 |
| 👍 Total Upvotes | 94 | | 👍 Total Upvotes | 99 |
| 💾 Total Saves | 123 | | 💾 Total Saves | 126 |
| 💬 Total Comments | 23 | | 💬 Total Comments | 23 |
## 📂 By Type ## 📂 By Type
@@ -22,19 +22,19 @@
| Rank | Title | Type | Version | Downloads | Views | Upvotes | Saves | Updated | | Rank | Title | Type | Version | Downloads | Views | Upvotes | Saves | Updated |
|:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 503 | 4601 | 13 | 28 | 2026-01-17 | | 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 507 | 4641 | 14 | 28 | 2026-01-17 |
| 2 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.9 | 217 | 2232 | 10 | 15 | 2026-01-17 | | 2 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.9 | 228 | 2285 | 11 | 16 | 2026-01-17 |
| 3 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 202 | 747 | 3 | 5 | 2026-01-07 | | 3 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 202 | 751 | 3 | 5 | 2026-01-07 |
| 4 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | action | 1.1.3 | 171 | 1889 | 7 | 18 | 2026-01-17 | | 4 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | action | 1.1.3 | 174 | 1906 | 7 | 18 | 2026-01-17 |
| 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 131 | 2254 | 8 | 10 | 2026-01-17 | | 5 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 134 | 1255 | 6 | 15 | 2026-01-17 |
| 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 130 | 1234 | 6 | 14 | 2026-01-17 | | 6 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 132 | 2269 | 8 | 10 | 2026-01-17 |
| 7 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 58 | 1246 | 9 | 3 | 2026-01-17 | | 7 | [Markdown Normalizer](https://openwebui.com/posts/markdown_normalizer_baaa8732) | action | 1.2.2 | 63 | 1746 | 9 | 15 | 2026-01-17 |
| 8 | [Markdown Normalizer](https://openwebui.com/posts/markdown_normalizer_baaa8732) | action | 1.2.0 | 57 | 1681 | 8 | 14 | 2026-01-17 | | 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 62 | 1262 | 10 | 3 | 2026-01-17 |
| 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 57 | 597 | 3 | 5 | 2026-01-08 | | 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 58 | 605 | 3 | 5 | 2026-01-08 |
| 10 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.9 | 41 | 650 | 4 | 0 | 2026-01-17 | | 10 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.9 | 41 | 654 | 5 | 0 | 2026-01-17 |
| 11 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 22 | 389 | 2 | 1 | 2026-01-17 | | 11 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 22 | 392 | 2 | 1 | 2026-01-17 |
| 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | action | 1.1.3 | 14 | 337 | 4 | 1 | 2026-01-17 | | 12 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 16 | 430 | 4 | 1 | 2026-01-17 |
| 13 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 13 | 423 | 4 | 1 | 2026-01-17 | | 13 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | action | 1.1.3 | 14 | 340 | 4 | 1 | 2026-01-17 |
| 14 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 6 | 254 | 2 | 1 | 2026-01-08 | | 14 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 6 | 254 | 2 | 1 | 2026-01-08 |
| 15 | [Review of Claude Haiku 4.5](https://openwebui.com/posts/review_of_claude_haiku_45_41b0db39) | unknown | | 0 | 43 | 0 | 0 | 2026-01-14 | | 15 | [Review of Claude Haiku 4.5](https://openwebui.com/posts/review_of_claude_haiku_45_41b0db39) | unknown | | 0 | 46 | 0 | 0 | 2026-01-14 |
| 16 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 1139 | 11 | 7 | 2026-01-10 | | 16 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 1154 | 11 | 7 | 2026-01-10 |

View File

@@ -1,16 +1,16 @@
# 📊 OpenWebUI 社区统计报告 # 📊 OpenWebUI 社区统计报告
> 📅 更新时间: 2026-01-17 17:07 > 📅 更新时间: 2026-01-18 00:08
## 📈 总览 ## 📈 总览
| 指标 | 数值 | | 指标 | 数值 |
|------|------| |------|------|
| 📝 发布数量 | 16 | | 📝 发布数量 | 16 |
| ⬇️ 总下载量 | 1622 | | ⬇️ 总下载量 | 1659 |
| 👁️ 总浏览量 | 19716 | | 👁️ 总浏览量 | 19990 |
| 👍 总点赞数 | 94 | | 👍 总点赞数 | 99 |
| 💾 总收藏数 | 123 | | 💾 总收藏数 | 126 |
| 💬 总评论数 | 23 | | 💬 总评论数 | 23 |
## 📂 按类型分类 ## 📂 按类型分类
@@ -22,19 +22,19 @@
| 排名 | 标题 | 类型 | 版本 | 下载 | 浏览 | 点赞 | 收藏 | 更新日期 | | 排名 | 标题 | 类型 | 版本 | 下载 | 浏览 | 点赞 | 收藏 | 更新日期 |
|:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 503 | 4601 | 13 | 28 | 2026-01-17 | | 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 507 | 4641 | 14 | 28 | 2026-01-17 |
| 2 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.9 | 217 | 2232 | 10 | 15 | 2026-01-17 | | 2 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.9 | 228 | 2285 | 11 | 16 | 2026-01-17 |
| 3 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 202 | 747 | 3 | 5 | 2026-01-07 | | 3 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 202 | 751 | 3 | 5 | 2026-01-07 |
| 4 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | action | 1.1.3 | 171 | 1889 | 7 | 18 | 2026-01-17 | | 4 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | action | 1.1.3 | 174 | 1906 | 7 | 18 | 2026-01-17 |
| 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 131 | 2254 | 8 | 10 | 2026-01-17 | | 5 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 134 | 1255 | 6 | 15 | 2026-01-17 |
| 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 130 | 1234 | 6 | 14 | 2026-01-17 | | 6 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 132 | 2269 | 8 | 10 | 2026-01-17 |
| 7 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 58 | 1246 | 9 | 3 | 2026-01-17 | | 7 | [Markdown Normalizer](https://openwebui.com/posts/markdown_normalizer_baaa8732) | action | 1.2.2 | 63 | 1746 | 9 | 15 | 2026-01-17 |
| 8 | [Markdown Normalizer](https://openwebui.com/posts/markdown_normalizer_baaa8732) | action | 1.2.0 | 57 | 1681 | 8 | 14 | 2026-01-17 | | 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 62 | 1262 | 10 | 3 | 2026-01-17 |
| 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 57 | 597 | 3 | 5 | 2026-01-08 | | 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 58 | 605 | 3 | 5 | 2026-01-08 |
| 10 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.9 | 41 | 650 | 4 | 0 | 2026-01-17 | | 10 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.9 | 41 | 654 | 5 | 0 | 2026-01-17 |
| 11 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 22 | 389 | 2 | 1 | 2026-01-17 | | 11 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 22 | 392 | 2 | 1 | 2026-01-17 |
| 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | action | 1.1.3 | 14 | 337 | 4 | 1 | 2026-01-17 | | 12 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 16 | 430 | 4 | 1 | 2026-01-17 |
| 13 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 13 | 423 | 4 | 1 | 2026-01-17 | | 13 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | action | 1.1.3 | 14 | 340 | 4 | 1 | 2026-01-17 |
| 14 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 6 | 254 | 2 | 1 | 2026-01-08 | | 14 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 6 | 254 | 2 | 1 | 2026-01-08 |
| 15 | [Review of Claude Haiku 4.5](https://openwebui.com/posts/review_of_claude_haiku_45_41b0db39) | unknown | | 0 | 43 | 0 | 0 | 2026-01-14 | | 15 | [Review of Claude Haiku 4.5](https://openwebui.com/posts/review_of_claude_haiku_45_41b0db39) | unknown | | 0 | 46 | 0 | 0 | 2026-01-14 |
| 16 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 1139 | 11 | 7 | 2026-01-10 | | 16 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 1154 | 11 | 7 | 2026-01-10 |

View File

@@ -44,7 +44,7 @@ Filters act as middleware in the message pipeline:
Fixes common Markdown formatting issues in LLM outputs, including Mermaid syntax, code blocks, and LaTeX formulas. Fixes common Markdown formatting issues in LLM outputs, including Mermaid syntax, code blocks, and LaTeX formulas.
**Version:** 1.1.2 **Version:** 1.2.3
[:octicons-arrow-right-24: Documentation](markdown_normalizer.md) [:octicons-arrow-right-24: Documentation](markdown_normalizer.md)

View File

@@ -44,7 +44,7 @@ Filter 充当消息管线中的中间件:
修复 LLM 输出中常见的 Markdown 格式问题,包括 Mermaid 语法、代码块和 LaTeX 公式。 修复 LLM 输出中常见的 Markdown 格式问题,包括 Mermaid 语法、代码块和 LaTeX 公式。
**版本:** 1.0.1 **版本:** 1.2.3
[:octicons-arrow-right-24: 查看文档](markdown_normalizer.zh.md) [:octicons-arrow-right-24: 查看文档](markdown_normalizer.zh.md)

View File

@@ -51,9 +51,17 @@ A content normalizer filter for Open WebUI that fixes common Markdown formatting
## Changelog ## Changelog
### v1.2.3
* **List Marker Protection Enhancement**: Fixed a bug where list markers (`*`) followed by plain text and emphasis were having their spaces incorrectly stripped (e.g., `* U16 forward` became `*U16 forward`).
* **Placeholder Support**: Confirmed that 4 or more underscores (e.g., `____`) are correctly treated as placeholders and not modified by the emphasis fix.
### v1.2.2 ### v1.2.2
* **Version Bump**: Documentation and metadata updated for the latest release. * **Code Block Indentation Fix**: Fixed an issue where code blocks nested inside lists were having their indentation incorrectly stripped. Now preserves proper indentation for nested code blocks.
* **Underscore Emphasis Support**: Extended emphasis spacing fix to support `__` (double underscore for bold) and `___` (triple underscore for bold+italic) syntax.
* **List Marker Protection**: Fixed a bug where list markers (`*`) followed by emphasis markers (`**`) were incorrectly merged (e.g., `* **Yes**` became `***Yes**`). Added safeguard to prevent this.
* **Test Suite**: Added comprehensive pytest test suite with 56 test cases covering all major features.
### v1.2.1 ### v1.2.1

View File

@@ -51,9 +51,17 @@
## 更新日志 ## 更新日志
### v1.2.3
* **列表标记保护增强**: 修复了列表标记 (`*`) 后跟普通文本和强调标记时,空格被错误剥离的问题(例如 `* U16 前锋` 变成 `*U16 前锋`)。
* **占位符支持**: 确认 4 个或更多下划线(如 `____`)会被正确视为占位符,不会被强调修复逻辑修改。
### v1.2.2 ### v1.2.2
* **版本更新**: 文档与元数据已同步到最新版本 * **代码块缩进修复**: 修复了列表中嵌套代码块的缩进被错误剥离的问题。现在会正确保留嵌套代码块的缩进
* **下划线强调语法支持**: 扩展强调空格修复以支持 `__` (双下划线加粗) 和 `___` (三下划线加粗斜体) 语法。
* **列表标记保护**: 修复了列表标记 (`*`) 后跟强调标记 (`**`) 被错误合并的 Bug例如 `* **是**` 变成 `***是**`)。添加了保护逻辑防止此问题。
* **测试套件**: 新增完整的 pytest 测试套件,包含 56 个测试用例,覆盖所有主要功能。
### v1.2.1 ### v1.2.1

View File

@@ -53,9 +53,17 @@ A content normalizer filter for Open WebUI that fixes common Markdown formatting
## Changelog ## Changelog
### v1.2.3
* **List Marker Protection Enhancement**: Fixed a bug where list markers (`*`) followed by plain text and emphasis were having their spaces incorrectly stripped (e.g., `* U16 forward` became `*U16 forward`).
* **Placeholder Support**: Confirmed that 4 or more underscores (e.g., `____`) are correctly treated as placeholders and not modified by the emphasis fix.
### v1.2.2 ### v1.2.2
* **Version Bump**: Documentation and metadata updated for the latest release. * **Code Block Indentation Fix**: Fixed an issue where code blocks nested inside lists were having their indentation incorrectly stripped. Now preserves proper indentation for nested code blocks.
* **Underscore Emphasis Support**: Extended emphasis spacing fix to support `__` (double underscore for bold) and `___` (triple underscore for bold+italic) syntax.
* **List Marker Protection**: Fixed a bug where list markers (`*`) followed by emphasis markers (`**`) were incorrectly merged (e.g., `* **Yes**` became `***Yes**`). Added safeguard to prevent this.
* **Test Suite**: Added comprehensive pytest test suite with 56 test cases covering all major features.
### v1.2.1 ### v1.2.1

View File

@@ -53,9 +53,17 @@
## 更新日志 ## 更新日志
### v1.2.3
* **列表标记保护增强**: 修复了列表标记 (`*`) 后跟普通文本和强调标记时,空格被错误剥离的问题(例如 `* U16 前锋` 变成 `*U16 前锋`)。
* **占位符支持**: 确认 4 个或更多下划线(如 `____`)会被正确视为占位符,不会被强调修复逻辑修改。
### v1.2.2 ### v1.2.2
* **版本更新**: 文档与元数据已同步到最新版本 * **代码块缩进修复**: 修复了列表中嵌套代码块的缩进被错误剥离的问题。现在会正确保留嵌套代码块的缩进
* **下划线强调语法支持**: 扩展强调空格修复以支持 `__` (双下划线加粗) 和 `___` (三下划线加粗斜体) 语法。
* **列表标记保护**: 修复了列表标记 (`*`) 后跟强调标记 (`**`) 被错误合并的 Bug例如 `* **是**` 变成 `***是**`)。添加了保护逻辑防止此问题。
* **测试套件**: 新增完整的 pytest 测试套件,包含 56 个测试用例,覆盖所有主要功能。
### v1.2.1 ### v1.2.1

View File

@@ -3,7 +3,7 @@ title: Markdown Normalizer
author: Fu-Jie author: Fu-Jie
author_url: https://github.com/Fu-Jie/awesome-openwebui author_url: https://github.com/Fu-Jie/awesome-openwebui
funding_url: https://github.com/open-webui funding_url: https://github.com/open-webui
version: 1.2.2 version: 1.2.3
openwebui_id: baaa8732-9348-40b7-8359-7e009660e23c openwebui_id: baaa8732-9348-40b7-8359-7e009660e23c
description: A content normalizer filter that fixes common Markdown formatting issues in LLM outputs, such as broken code blocks, LaTeX formulas, and list formatting. description: A content normalizer filter that fixes common Markdown formatting issues in LLM outputs, such as broken code blocks, LaTeX formulas, and list formatting.
""" """
@@ -109,12 +109,13 @@ class ContentNormalizer:
"heading_space": re.compile(r"^(#+)([^ \n#])", re.MULTILINE), "heading_space": re.compile(r"^(#+)([^ \n#])", re.MULTILINE),
# Table: | col1 | col2 -> | col1 | col2 | # Table: | col1 | col2 -> | col1 | col2 |
"table_pipe": re.compile(r"^(\|.*[^|\n])$", re.MULTILINE), "table_pipe": re.compile(r"^(\|.*[^|\n])$", re.MULTILINE),
# Emphasis spacing: ** text ** -> **text** # Emphasis spacing: ** text ** -> **text**, __ text __ -> __text__
# Matches emphasis blocks within a single line. We use a recursive approach # Matches emphasis blocks within a single line. We use a recursive approach
# in _fix_emphasis_spacing to handle nesting and spaces correctly. # in _fix_emphasis_spacing to handle nesting and spaces correctly.
# NOTE: We use [^\n] instead of . to prevent cross-line matching. # NOTE: We use [^\n] instead of . to prevent cross-line matching.
# Supports: * (italic), ** (bold), *** (bold+italic), _ (italic), __ (bold), ___ (bold+italic)
"emphasis_spacing": re.compile( "emphasis_spacing": re.compile(
r"(?<!\*|_)(\*{1,3}|_)(?P<inner>[^\n]*?)(\1)(?!\*|_)" r"(?<!\*|_)(\*{1,3}|_{1,3})(?P<inner>[^\n]*?)(\1)(?!\*|_)"
), ),
} }
@@ -485,6 +486,20 @@ class ContentNormalizer:
if symbol in ["*", "_"]: if symbol in ["*", "_"]:
return match.group(0) return match.group(0)
# Safeguard: List marker protection
# If symbol is single '*' and inner content starts with whitespace followed by emphasis markers,
# this is likely a list item like "* **bold**" - don't merge them.
# Pattern: "* **text**" should NOT become "***text**"
if symbol == "*" and inner.lstrip().startswith(("*", "_")):
return match.group(0)
# Extended list marker protection:
# If symbol is single '*' and inner starts with multiple spaces (list indentation pattern),
# this is likely a list item like "* text" - don't strip the spaces.
# Pattern: "* U16 forward **Kuang**" should NOT become "*U16 forward **Kuang**"
if symbol == "*" and inner.startswith(" "):
return match.group(0)
return f"{symbol}{stripped_inner}{symbol}" return f"{symbol}{stripped_inner}{symbol}"
parts = content.split("```") parts = content.split("```")

View File

@@ -3,7 +3,7 @@ title: Markdown 格式修复器 (Markdown Normalizer)
author: Fu-Jie author: Fu-Jie
author_url: https://github.com/Fu-Jie/awesome-openwebui author_url: https://github.com/Fu-Jie/awesome-openwebui
funding_url: https://github.com/open-webui funding_url: https://github.com/open-webui
version: 1.2.2 version: 1.2.3
description: 内容规范化过滤器,修复 LLM 输出中常见的 Markdown 格式问题如损坏的代码块、LaTeX 公式、Mermaid 图表和列表格式。 description: 内容规范化过滤器,修复 LLM 输出中常见的 Markdown 格式问题如损坏的代码块、LaTeX 公式、Mermaid 图表和列表格式。
""" """
@@ -101,12 +101,13 @@ class ContentNormalizer:
"heading_space": re.compile(r"^(#+)([^ \n#])", re.MULTILINE), "heading_space": re.compile(r"^(#+)([^ \n#])", re.MULTILINE),
# Table: | col1 | col2 -> | col1 | col2 | # Table: | col1 | col2 -> | col1 | col2 |
"table_pipe": re.compile(r"^(\|.*[^|\n])$", re.MULTILINE), "table_pipe": re.compile(r"^(\|.*[^|\n])$", re.MULTILINE),
# Emphasis spacing: ** text ** -> **text** # Emphasis spacing: ** text ** -> **text**, __ text __ -> __text__
# Matches emphasis blocks within a single line. We use a recursive approach # Matches emphasis blocks within a single line. We use a recursive approach
# in _fix_emphasis_spacing to handle nesting and spaces correctly. # in _fix_emphasis_spacing to handle nesting and spaces correctly.
# NOTE: We use [^\n] instead of . to prevent cross-line matching. # NOTE: We use [^\n] instead of . to prevent cross-line matching.
# Supports: * (italic), ** (bold), *** (bold+italic), _ (italic), __ (bold), ___ (bold+italic)
"emphasis_spacing": re.compile( "emphasis_spacing": re.compile(
r"(?<!\*|_)(\*{1,3}|_)(?P<inner>[^\n]*?)(\1)(?!\*|_)" r"(?<!\*|_)(\*{1,3}|_{1,3})(?P<inner>[^\n]*?)(\1)(?!\*|_)"
), ),
} }
@@ -464,6 +465,20 @@ class ContentNormalizer:
if symbol in ["*", "_"]: if symbol in ["*", "_"]:
return match.group(0) return match.group(0)
# Safeguard: List marker protection
# If symbol is single '*' and inner content starts with whitespace followed by emphasis markers,
# this is likely a list item like "* **bold**" - don't merge them.
# Pattern: "* **text**" should NOT become "***text**"
if symbol == "*" and inner.lstrip().startswith(("*", "_")):
return match.group(0)
# Extended list marker protection:
# If symbol is single '*' and inner starts with multiple spaces (list indentation pattern),
# this is likely a list item like "* text" - don't strip the spaces.
# Pattern: "* U16 forward **Kuang**" should NOT become "*U16 forward **Kuang**"
if symbol == "*" and inner.startswith(" "):
return match.group(0)
return f"{symbol}{stripped_inner}{symbol}" return f"{symbol}{stripped_inner}{symbol}"
parts = content.split("```") parts = content.split("```")

View File

@@ -0,0 +1 @@
# Markdown Normalizer Test Suite

View File

@@ -0,0 +1,75 @@
"""
Shared fixtures for Markdown Normalizer tests.
"""
import pytest
import sys
import os
# Add the parent directory to sys.path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from markdown_normalizer import ContentNormalizer, NormalizerConfig
@pytest.fixture
def normalizer():
"""Default normalizer with all fixes enabled."""
config = NormalizerConfig(
enable_escape_fix=True,
enable_thought_tag_fix=True,
enable_details_tag_fix=True,
enable_code_block_fix=True,
enable_latex_fix=True,
enable_list_fix=False, # Experimental, keep off by default
enable_unclosed_block_fix=True,
enable_fullwidth_symbol_fix=False,
enable_mermaid_fix=True,
enable_heading_fix=True,
enable_table_fix=True,
enable_xml_tag_cleanup=True,
enable_emphasis_spacing_fix=True,
)
return ContentNormalizer(config)
@pytest.fixture
def emphasis_only_normalizer():
"""Normalizer with only emphasis spacing fix enabled."""
config = NormalizerConfig(
enable_escape_fix=False,
enable_thought_tag_fix=False,
enable_details_tag_fix=False,
enable_code_block_fix=False,
enable_latex_fix=False,
enable_list_fix=False,
enable_unclosed_block_fix=False,
enable_fullwidth_symbol_fix=False,
enable_mermaid_fix=False,
enable_heading_fix=False,
enable_table_fix=False,
enable_xml_tag_cleanup=False,
enable_emphasis_spacing_fix=True,
)
return ContentNormalizer(config)
@pytest.fixture
def mermaid_only_normalizer():
"""Normalizer with only Mermaid fix enabled."""
config = NormalizerConfig(
enable_escape_fix=False,
enable_thought_tag_fix=False,
enable_details_tag_fix=False,
enable_code_block_fix=False,
enable_latex_fix=False,
enable_list_fix=False,
enable_unclosed_block_fix=False,
enable_fullwidth_symbol_fix=False,
enable_mermaid_fix=True,
enable_heading_fix=False,
enable_table_fix=False,
enable_xml_tag_cleanup=False,
enable_emphasis_spacing_fix=False,
)
return ContentNormalizer(config)

View File

@@ -0,0 +1,54 @@
"""
Tests for code block formatting fixes.
Covers: prefix, suffix, indentation preservation.
"""
import pytest
class TestCodeBlockFix:
"""Test code block formatting normalization."""
def test_code_block_indentation_preserved(self, normalizer):
"""Indented code blocks (e.g., in lists) should preserve indentation."""
input_str = """
* List item 1
```python
def foo():
print("bar")
```
* List item 2
"""
# Indentation should be preserved
assert " ```python" in normalizer.normalize(input_str)
def test_inline_code_block_prefix(self, normalizer):
"""Code block that follows text on same line should be modified."""
input_str = "text```python\ncode\n```"
result = normalizer.normalize(input_str)
# Just verify the code block markers are present
assert "```" in result
def test_code_block_suffix_fix(self, normalizer):
"""Code block with content on same line after lang should be fixed."""
input_str = "```python code\nmore code\n```"
result = normalizer.normalize(input_str)
# Content should be on new line
assert "```python\n" in result or "```python " in result
class TestUnclosedCodeBlock:
"""Test auto-closing of unclosed code blocks."""
def test_unclosed_code_block_is_closed(self, normalizer):
"""Unclosed code blocks should be automatically closed."""
input_str = "```python\ncode here"
result = normalizer.normalize(input_str)
# Should have closing ```
assert result.endswith("```") or result.count("```") == 2
def test_balanced_code_blocks_unchanged(self, normalizer):
"""Already balanced code blocks should not get extra closing."""
input_str = "```python\ncode\n```"
result = normalizer.normalize(input_str)
assert result.count("```") == 2

View File

@@ -0,0 +1,48 @@
"""
Tests for details tag normalization.
Covers: </details> spacing, self-closing tags.
"""
import pytest
class TestDetailsTagFix:
"""Test details tag normalization."""
def test_details_end_gets_newlines(self, normalizer):
"""</details> should be followed by double newline."""
input_str = "</details>Content after"
result = normalizer.normalize(input_str)
assert "</details>\n\n" in result
def test_self_closing_details_gets_newline(self, normalizer):
"""Self-closing <details .../> should get newline after."""
input_str = "<details open />## Heading"
result = normalizer.normalize(input_str)
# Should have newline between tag and heading
assert "/>\n" in result or "/> \n" in result
def test_details_in_code_block_unchanged(self, normalizer):
"""Details tags inside code blocks should not be modified."""
input_str = "```html\n<details>content</details>more\n```"
result = normalizer.normalize(input_str)
# Content inside code block should be unchanged
assert "</details>more" in result
class TestThoughtTagFix:
"""Test thought tag normalization."""
def test_think_tag_normalized(self, normalizer):
"""<think> should be normalized to <thought>."""
input_str = "<think>content</think>"
result = normalizer.normalize(input_str)
assert "<thought>" in result
assert "</thought>" in result
def test_thinking_tag_normalized(self, normalizer):
"""<thinking> should be normalized to <thought>."""
input_str = "<thinking>content</thinking>"
result = normalizer.normalize(input_str)
assert "<thought>" in result
assert "</thought>" in result

View File

@@ -0,0 +1,138 @@
"""
Tests for emphasis spacing fix.
Covers: *, **, ***, _, __, ___ with spaces inside.
"""
import pytest
class TestEmphasisSpacingFix:
"""Test emphasis spacing normalization."""
@pytest.mark.parametrize(
"input_str,expected",
[
# Double asterisk (bold)
("** bold **", "**bold**"),
("** bold text **", "**bold text**"),
("**text **", "**text**"),
("** text**", "**text**"),
# Triple asterisk (bold+italic)
("*** bold italic ***", "***bold italic***"),
# Double underscore (bold)
("__ bold __", "__bold__"),
("__ bold text __", "__bold text__"),
("__text __", "__text__"),
("__ text__", "__text__"),
# Triple underscore (bold+italic)
("___ bold italic ___", "___bold italic___"),
# Mixed markers
("** bold ** and __ also __", "**bold** and __also__"),
],
)
def test_emphasis_with_spaces_fixed(
self, emphasis_only_normalizer, input_str, expected
):
"""Test that emphasis with spaces is correctly fixed."""
assert emphasis_only_normalizer.normalize(input_str) == expected
@pytest.mark.parametrize(
"input_str",
[
# Single * and _ with spaces on both sides - treated as operator (safeguard)
"* italic *",
"_ italic _",
# Already correct emphasis
"**bold**",
"__bold__",
"*italic*",
"_italic_",
"***bold italic***",
"___bold italic___",
],
)
def test_safeguard_and_correct_emphasis_unchanged(
self, emphasis_only_normalizer, input_str
):
"""Test that safeguard cases and already correct emphasis are not modified."""
assert emphasis_only_normalizer.normalize(input_str) == input_str
class TestEmphasisSideEffects:
"""Test that emphasis fix does NOT affect unrelated content."""
@pytest.mark.parametrize(
"input_str,description",
[
# URLs with underscores
("https://example.com/path_with_underscore", "URL"),
("Visit https://api.example.com/get_user_info for info", "URL in text"),
# Variable names (snake_case)
("The `my_variable_name` is important", "Variable in backticks"),
("Use `get_user_data()` function", "Function name"),
# File names
("Edit the `config_file_name.py` file", "File name"),
("See `my_script__v2.py` for details", "Double underscore in filename"),
# Math-like subscripts
("The variable a_1 and b_2 are defined", "Math subscripts"),
# Single underscores not matching emphasis pattern
("word_with_underscore", "Underscore in word"),
("a_b_c_d", "Multiple underscores"),
# Horizontal rules
("---", "HR with dashes"),
("***", "HR with asterisks"),
("___", "HR with underscores"),
# List items
("- item_one\n- item_two", "List items"),
],
)
def test_no_side_effects(self, emphasis_only_normalizer, input_str, description):
"""Test that various content types are NOT modified by emphasis fix."""
assert (
emphasis_only_normalizer.normalize(input_str) == input_str
), f"Failed for: {description}"
def test_list_marker_not_merged_with_emphasis(self, emphasis_only_normalizer):
"""Test that list markers (*) are not merged with emphasis (**).
Regression test for: "* **Yes**" should NOT become "***Yes**"
"""
input_str = """1. **Start**: The user opens the login page.
* **Yes**: Login successful.
* **No**: Show error message."""
result = emphasis_only_normalizer.normalize(input_str)
assert (
"* **Yes**" in result
), "List marker was incorrectly merged with emphasis"
assert (
"* **No**" in result
), "List marker was incorrectly merged with emphasis"
assert "***Yes**" not in result, "BUG: List marker merged with emphasis"
assert "***No**" not in result, "BUG: List marker merged with emphasis"
def test_list_marker_with_plain_text_then_emphasis(self, emphasis_only_normalizer):
"""Test that list items with plain text before emphasis are preserved.
Regression test for: "* U16 forward **Kuang**" should NOT become "*U16 forward **Kuang**"
"""
input_str = "* U16 China forward **Kuang Zhaolei**"
result = emphasis_only_normalizer.normalize(input_str)
assert "* U16" in result, "List marker spaces were incorrectly stripped"
assert (
"*U16" not in result or "* U16" in result
), "BUG: List marker spaces stripped"
class TestEmphasisInCodeBlocks:
"""Test that emphasis inside code blocks is NOT modified."""
def test_emphasis_in_code_block_unchanged(self, emphasis_only_normalizer):
"""Code blocks should be completely skipped."""
input_str = "```python\nmy_var = get_data__from_api()\n```"
assert emphasis_only_normalizer.normalize(input_str) == input_str
def test_mixed_emphasis_and_code(self, emphasis_only_normalizer):
"""Text outside code blocks should be fixed, inside should not."""
input_str = "** bold ** text\n```python\n** not bold **\n```"
expected = "**bold** text\n```python\n** not bold **\n```"
assert emphasis_only_normalizer.normalize(input_str) == expected

View File

@@ -0,0 +1,51 @@
"""
Tests for heading fix.
Covers: Missing space after # in headings.
"""
import pytest
class TestHeadingFix:
"""Test heading space normalization."""
@pytest.mark.parametrize(
"input_str,expected",
[
("#Heading", "# Heading"),
("##Heading", "## Heading"),
("###Heading", "### Heading"),
("#中文标题", "# 中文标题"),
("#123", "# 123"), # Numbers after # also get space
],
)
def test_missing_space_added(self, normalizer, input_str, expected):
"""Headings missing space after # should be fixed."""
assert normalizer.normalize(input_str) == expected
@pytest.mark.parametrize(
"input_str",
[
"# Heading",
"## Already Correct",
"###", # Just hashes
],
)
def test_correct_headings_unchanged(self, normalizer, input_str):
"""Already correct headings should not be modified."""
assert normalizer.normalize(input_str) == input_str
class TestTableFix:
"""Test table pipe normalization."""
def test_missing_closing_pipe_added(self, normalizer):
"""Tables missing closing | should have it added."""
input_str = "| col1 | col2"
result = normalizer.normalize(input_str)
assert result.endswith("|") or "col2 |" in result
def test_already_closed_table_unchanged(self, normalizer):
"""Tables with closing | should not be modified."""
input_str = "| col1 | col2 |"
assert normalizer.normalize(input_str) == input_str

6
pytest.ini Normal file
View File

@@ -0,0 +1,6 @@
[pytest]
testpaths = plugins
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v --tb=short