zarkdown 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.4
2
+ Name: zarkdown
3
+ Version: 2.0.1
4
+ Summary: Zarkdown - 键盘友好型纯文本标记语言
5
+ Author-email: yangzizhoudiwuxuande <yangzizhou2026@outlook.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yangzizhoudiwuxuande/zarkdown
8
+ Project-URL: Bug Tracker, https://github.com/yangzizhoudiwuxuande/zarkdown/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+
14
+ # ✨ Zarkdown (版本2.0.1)
15
+
16
+ > **键盘友好型纯文本标记语言** —— 所有符号均位于键盘主键区,无需按 Shift 组合键。
17
+
18
+ [![Python Version](https://img.shields.io/badge/python-3.6+-blue.svg)](https://python.org)
19
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
20
+ [![GitHub Stars](https://img.shields.io/github/stars/yangzizhoudiwuxuande/zarkdown)](https://github.com/yangzizhoudiwuxuande/zarkdown/stargazers)
21
+
22
+ Zarkdown 是一种全新的纯文本标记语言,专为**快速写作**和**极致键盘效率**而设计。它适合用来写笔记、技术文档、博客文章,甚至可以作为配置文件的格式。
23
+
24
+ ---
25
+
26
+ ## 🎯 设计哲学
27
+
28
+ - **键盘友好**:所有语法符号都在主键区,手指不需要大范围移动
29
+ - **直观易记**:`/` 表示标题(像路径层级),`?` 表示加粗(像强调语气)
30
+ - **纯文本**:任何文本编辑器都能打开,人类可读性强
31
+ - **可扩展**:支持表格、代码块、脚注等高级功能
32
+
33
+ ---
34
+
35
+ ## 📜 完整语法表
36
+
37
+ | 效果 | 语法 | 示例 | 渲染为 |
38
+ | :--- | :--- | :--- | :--- |
39
+ | **标题 1~4 级** | `/` `//` `///` `////` + 空格 | `/ 大标题` | `<h1>`~`<h4>` |
40
+ | **粗体** | `?文字?` | `?重要?` | `<strong>` |
41
+ | **斜体** | `\文字\` | `\斜体\` | `<i>` |
42
+ | **删除线** | `-文字-` | `-删掉-` | `<del>` |
43
+ | **超链接** | `*文字*(链接)` | `*点击*(https://x.com)` | `<a>` |
44
+ | **图片** | `$图片名$(链接)` | `$logo$(./pic.png)` | `<img>` |
45
+ | **行内代码** | `~文字~` | `~npm i~` | `<code>` |
46
+ | **多行代码块** | `~语言` 开头 + `~` 结尾 | `~python`...`~` | `<pre><code>` |
47
+ | **无序列表** | `!文字`(行首) | `!苹果` | `<ul><li>` |
48
+ | **有序列表** | `•文字`(行首,U+2022) | `•第一` | `<ol><li>` |
49
+ | **引用** | `\|文字`(行首) | `\| 引文` | `<blockquote>` |
50
+ | **表格** | `\| 表头 \|` + `------` | 见下方示例 | `<table>` |
51
+ | **注释** | `<文字>`(不含URL) | `<备注>` | `<!-- -->` |
52
+ | **脚注** | `[数字]<文字>` | `[1]<说明>` | `<sup title="">` |
53
+ | **分割线** | `-----`(独占一行) | | `<hr>` |
54
+ | **转义** | `^` 加在任意符号前 | `^/ 不是标题` | 原样输出 |
55
+
56
+ ---
57
+
58
+ ## 🚀 快速上手
59
+
60
+ ### 安装
61
+
62
+ ```bash
63
+ # 克隆仓库
64
+ git clone https://github.com/yangzizhoudiwuxuande/zarkdown.git
65
+ cd zarkdown
66
+
67
+ # 创建虚拟环境(推荐)
68
+ python3 -m venv venv
69
+ source venv/bin/activate # Windows: venv\Scripts\activate
70
+
71
+ # 安装
72
+ pip install -e .
73
+ ```
74
+ ---
75
+
76
+ ## 使用
77
+
78
+ ```bash
79
+ # 转换 .zkdn 文件为 .html
80
+ zarkdown example.zkdn -o example.html
81
+
82
+ # 直接输出到终端(不生成文件)
83
+ zarkdown example.zkdn
84
+ ```
85
+ ---
86
+
87
+ ## 示例
88
+ ### 转为HTML
89
+ 创建一个`hello.zkdn`文件:
90
+ ```zkdn
91
+ / Zarkdown 欢迎页
92
+
93
+ ?恭喜?,您的格式已经跑通了!
94
+
95
+ 这里有一个链接:*点击访问*(https://github.com/yangzizhoudiwuxuande)
96
+
97
+ ~python
98
+ print("Hello Zarkdown!")
99
+ ~
100
+
101
+ ```
102
+ 然后运行:
103
+ ```bash
104
+ zarkdown hello.zkdn -w
105
+ ```
106
+ 浏览器会自动打开,显示渲染后的 HTML 页面。修改 `hello.zkdn` 并保存,页面会自动刷新。
107
+ ### 转为Word/LaTex
108
+ 转为Word/LaTex需要安装Pandoc。
109
+
110
+ ```bash
111
+ brew install pandoc
112
+ ```
113
+
114
+ 转为Word
115
+ ```bash
116
+ zarkdown my_note.zkdn -f docx
117
+ ```
118
+
119
+ 转为LaTex
120
+ ```bash
121
+ zarkdown my_note.zkdn -f latex
122
+ ```
123
+
124
+ ## 📸 效果预览
125
+ [![pm4y4lF.png](https://s41.ax1x.com/2026/08/01/pm4y4lF.png)](https://imgchr.com/i/pm4y4lF)
126
+
127
+ ## 贡献
128
+ 欢迎任何形式的贡献!你可以:
129
+
130
+ * 🐛 报告 Bug(在 Issues 中描述)
131
+ * 💡 提出新功能建议
132
+ * 📝 完善文档
133
+ * 🔧 提交 Pull Request
134
+ ## 📄 许可证
135
+ 本项目采用 MIT License 开源协议,你可以自由使用、修改、分发。
136
+ ## ❤️ 致谢
137
+ 感谢你阅读这份文档!如果觉得 Zarkdown 有趣,欢迎给项目点一颗 ⭐ 星,让更多人看到它。
138
+ ## 📝 更新日志
139
+ **v2.0.1 (2026-08-01)**
140
+ - **语法错误检查器**
141
+ 转换前自动扫描全文,检测未闭合的成对符号(`?`、`\`、`-`、`~`、`*`、`$`、`[`、`<`),并精确报告行号和列号,帮助用户快速定位问题。
142
+
143
+ - **括号配对检查**
144
+ 针对超链接 `*文字*(链接)` 和图片 `$图片名$(链接)`,自动检测缺失的闭合括号 `)`,避免生成无效链接。
145
+
146
+ - **多行表格支持**
147
+ 表格单元格内允许换行,通过缩进续行自动合并内容,并在输出中转换为 `<br>` 换行符。
148
+
149
+ - **转义字符 `^`**
150
+ 在任意特殊符号前添加 `^` 即可原样输出,避免被解析器处理,例如 `^/ 不是标题`。
151
+
152
+ - **智能跳过机制**
153
+ 错误检查器自动跳过分割线(以 `-----` 开头的行)、表格分隔行以及多行代码块内部内容,避免误报。
154
+
155
+ - **自动生成输出文件名**
156
+ 若不指定 `-o`,输出文件名将根据输入文件名和格式自动生成(如 `note.html`、`note.pdf` 等)。
157
+
158
+ **v2.0.0 (2026-07-28)**
159
+ * 支持导出为Word/LaTex等格式(需安装Pandoc)
160
+
161
+ **v1.2.2 (2026-07-26)**
162
+ * 支持多行表格
163
+
164
+ **v1.2.1 (2026-07-26)**
165
+ * 支持嵌套语法(粗体里套斜体、超链接里套粗体等)
166
+
167
+
168
+ **v1.2.0 (2026-07-25)**
169
+ * 使引用和表格变得更好看
170
+
171
+ **v1.1.0 (2026-07-25)**
172
+ * ✨ 新增 `-w` 监听模式,保存即自动重新转换
173
+ * ✨ 自动在浏览器中打开生成 HTML,实现实时预览
174
+ * 🐛 修复中文编码问题,兼容带 BOM 的 UTF-8 文件
175
+ * 🐛 修复 macOS 下相对路径打开失败的问题
176
+ * 📝 完善 README 文档,增加完整语法表和示例
177
+
178
+ **v1.0.0 (2026-07-25)**
179
+ * 🎉 首次发布,支持完整的 Zarkdown 语法
180
+
181
+
182
+ ---
183
+
184
+ Happy Writing with Zarkdown!
185
+
186
+ ## 联系
187
+ yangzizhou2026@outlook.com
@@ -0,0 +1,174 @@
1
+ # ✨ Zarkdown (版本2.0.1)
2
+
3
+ > **键盘友好型纯文本标记语言** —— 所有符号均位于键盘主键区,无需按 Shift 组合键。
4
+
5
+ [![Python Version](https://img.shields.io/badge/python-3.6+-blue.svg)](https://python.org)
6
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![GitHub Stars](https://img.shields.io/github/stars/yangzizhoudiwuxuande/zarkdown)](https://github.com/yangzizhoudiwuxuande/zarkdown/stargazers)
8
+
9
+ Zarkdown 是一种全新的纯文本标记语言,专为**快速写作**和**极致键盘效率**而设计。它适合用来写笔记、技术文档、博客文章,甚至可以作为配置文件的格式。
10
+
11
+ ---
12
+
13
+ ## 🎯 设计哲学
14
+
15
+ - **键盘友好**:所有语法符号都在主键区,手指不需要大范围移动
16
+ - **直观易记**:`/` 表示标题(像路径层级),`?` 表示加粗(像强调语气)
17
+ - **纯文本**:任何文本编辑器都能打开,人类可读性强
18
+ - **可扩展**:支持表格、代码块、脚注等高级功能
19
+
20
+ ---
21
+
22
+ ## 📜 完整语法表
23
+
24
+ | 效果 | 语法 | 示例 | 渲染为 |
25
+ | :--- | :--- | :--- | :--- |
26
+ | **标题 1~4 级** | `/` `//` `///` `////` + 空格 | `/ 大标题` | `<h1>`~`<h4>` |
27
+ | **粗体** | `?文字?` | `?重要?` | `<strong>` |
28
+ | **斜体** | `\文字\` | `\斜体\` | `<i>` |
29
+ | **删除线** | `-文字-` | `-删掉-` | `<del>` |
30
+ | **超链接** | `*文字*(链接)` | `*点击*(https://x.com)` | `<a>` |
31
+ | **图片** | `$图片名$(链接)` | `$logo$(./pic.png)` | `<img>` |
32
+ | **行内代码** | `~文字~` | `~npm i~` | `<code>` |
33
+ | **多行代码块** | `~语言` 开头 + `~` 结尾 | `~python`...`~` | `<pre><code>` |
34
+ | **无序列表** | `!文字`(行首) | `!苹果` | `<ul><li>` |
35
+ | **有序列表** | `•文字`(行首,U+2022) | `•第一` | `<ol><li>` |
36
+ | **引用** | `\|文字`(行首) | `\| 引文` | `<blockquote>` |
37
+ | **表格** | `\| 表头 \|` + `------` | 见下方示例 | `<table>` |
38
+ | **注释** | `<文字>`(不含URL) | `<备注>` | `<!-- -->` |
39
+ | **脚注** | `[数字]<文字>` | `[1]<说明>` | `<sup title="">` |
40
+ | **分割线** | `-----`(独占一行) | | `<hr>` |
41
+ | **转义** | `^` 加在任意符号前 | `^/ 不是标题` | 原样输出 |
42
+
43
+ ---
44
+
45
+ ## 🚀 快速上手
46
+
47
+ ### 安装
48
+
49
+ ```bash
50
+ # 克隆仓库
51
+ git clone https://github.com/yangzizhoudiwuxuande/zarkdown.git
52
+ cd zarkdown
53
+
54
+ # 创建虚拟环境(推荐)
55
+ python3 -m venv venv
56
+ source venv/bin/activate # Windows: venv\Scripts\activate
57
+
58
+ # 安装
59
+ pip install -e .
60
+ ```
61
+ ---
62
+
63
+ ## 使用
64
+
65
+ ```bash
66
+ # 转换 .zkdn 文件为 .html
67
+ zarkdown example.zkdn -o example.html
68
+
69
+ # 直接输出到终端(不生成文件)
70
+ zarkdown example.zkdn
71
+ ```
72
+ ---
73
+
74
+ ## 示例
75
+ ### 转为HTML
76
+ 创建一个`hello.zkdn`文件:
77
+ ```zkdn
78
+ / Zarkdown 欢迎页
79
+
80
+ ?恭喜?,您的格式已经跑通了!
81
+
82
+ 这里有一个链接:*点击访问*(https://github.com/yangzizhoudiwuxuande)
83
+
84
+ ~python
85
+ print("Hello Zarkdown!")
86
+ ~
87
+
88
+ ```
89
+ 然后运行:
90
+ ```bash
91
+ zarkdown hello.zkdn -w
92
+ ```
93
+ 浏览器会自动打开,显示渲染后的 HTML 页面。修改 `hello.zkdn` 并保存,页面会自动刷新。
94
+ ### 转为Word/LaTex
95
+ 转为Word/LaTex需要安装Pandoc。
96
+
97
+ ```bash
98
+ brew install pandoc
99
+ ```
100
+
101
+ 转为Word
102
+ ```bash
103
+ zarkdown my_note.zkdn -f docx
104
+ ```
105
+
106
+ 转为LaTex
107
+ ```bash
108
+ zarkdown my_note.zkdn -f latex
109
+ ```
110
+
111
+ ## 📸 效果预览
112
+ [![pm4y4lF.png](https://s41.ax1x.com/2026/08/01/pm4y4lF.png)](https://imgchr.com/i/pm4y4lF)
113
+
114
+ ## 贡献
115
+ 欢迎任何形式的贡献!你可以:
116
+
117
+ * 🐛 报告 Bug(在 Issues 中描述)
118
+ * 💡 提出新功能建议
119
+ * 📝 完善文档
120
+ * 🔧 提交 Pull Request
121
+ ## 📄 许可证
122
+ 本项目采用 MIT License 开源协议,你可以自由使用、修改、分发。
123
+ ## ❤️ 致谢
124
+ 感谢你阅读这份文档!如果觉得 Zarkdown 有趣,欢迎给项目点一颗 ⭐ 星,让更多人看到它。
125
+ ## 📝 更新日志
126
+ **v2.0.1 (2026-08-01)**
127
+ - **语法错误检查器**
128
+ 转换前自动扫描全文,检测未闭合的成对符号(`?`、`\`、`-`、`~`、`*`、`$`、`[`、`<`),并精确报告行号和列号,帮助用户快速定位问题。
129
+
130
+ - **括号配对检查**
131
+ 针对超链接 `*文字*(链接)` 和图片 `$图片名$(链接)`,自动检测缺失的闭合括号 `)`,避免生成无效链接。
132
+
133
+ - **多行表格支持**
134
+ 表格单元格内允许换行,通过缩进续行自动合并内容,并在输出中转换为 `<br>` 换行符。
135
+
136
+ - **转义字符 `^`**
137
+ 在任意特殊符号前添加 `^` 即可原样输出,避免被解析器处理,例如 `^/ 不是标题`。
138
+
139
+ - **智能跳过机制**
140
+ 错误检查器自动跳过分割线(以 `-----` 开头的行)、表格分隔行以及多行代码块内部内容,避免误报。
141
+
142
+ - **自动生成输出文件名**
143
+ 若不指定 `-o`,输出文件名将根据输入文件名和格式自动生成(如 `note.html`、`note.pdf` 等)。
144
+
145
+ **v2.0.0 (2026-07-28)**
146
+ * 支持导出为Word/LaTex等格式(需安装Pandoc)
147
+
148
+ **v1.2.2 (2026-07-26)**
149
+ * 支持多行表格
150
+
151
+ **v1.2.1 (2026-07-26)**
152
+ * 支持嵌套语法(粗体里套斜体、超链接里套粗体等)
153
+
154
+
155
+ **v1.2.0 (2026-07-25)**
156
+ * 使引用和表格变得更好看
157
+
158
+ **v1.1.0 (2026-07-25)**
159
+ * ✨ 新增 `-w` 监听模式,保存即自动重新转换
160
+ * ✨ 自动在浏览器中打开生成 HTML,实现实时预览
161
+ * 🐛 修复中文编码问题,兼容带 BOM 的 UTF-8 文件
162
+ * 🐛 修复 macOS 下相对路径打开失败的问题
163
+ * 📝 完善 README 文档,增加完整语法表和示例
164
+
165
+ **v1.0.0 (2026-07-25)**
166
+ * 🎉 首次发布,支持完整的 Zarkdown 语法
167
+
168
+
169
+ ---
170
+
171
+ Happy Writing with Zarkdown!
172
+
173
+ ## 联系
174
+ yangzizhou2026@outlook.com
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "zarkdown"
7
+ version = "2.0.1"
8
+ authors = [
9
+ { name = "yangzizhoudiwuxuande", email = "yangzizhou2026@outlook.com" },
10
+ ]
11
+ description = "Zarkdown - 键盘友好型纯文本标记语言"
12
+ readme = "README.md"
13
+ license = { text = "MIT" } # 使用 SPDX 表达式,代替 classifier
14
+ requires-python = ">=3.6"
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ # 移除了 License 分类器
19
+ ]
20
+
21
+ [project.scripts]
22
+ zarkdown = "zarkdown.core:main" # 命令行入口点
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/yangzizhoudiwuxuande/zarkdown"
26
+ "Bug Tracker" = "https://github.com/yangzizhoudiwuxuande/zarkdown/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,607 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ Zarkdown 核心转换引擎
6
+ 支持嵌套语法、转义、实时预览、多行表格、多格式导出 (HTML/PDF/DOCX/LaTeX)
7
+ 内置错误检查器(跳过代码块、分割线/表格分隔符)
8
+ """
9
+
10
+ import re
11
+ import sys
12
+ import argparse
13
+ import os
14
+ import time
15
+ import webbrowser
16
+
17
+ # ------------------------------------------------------------
18
+ # 可选依赖:pypandoc(用于 PDF/DOCX/LaTeX 导出)
19
+ # ------------------------------------------------------------
20
+ try:
21
+ import pypandoc
22
+ except ImportError:
23
+ pypandoc = None
24
+
25
+
26
+ # ============================================================
27
+ # 0. 错误检查器(修复:跳过分割线/表格分隔符)
28
+ # ============================================================
29
+
30
+ def validate_zarkdown(text):
31
+ """
32
+ 检查 Zarkdown 文本中的语法错误:
33
+ 1. 未闭合的成对符号(? \\ - ~ * $ [ <)
34
+ 2. 超链接/图片中缺少闭合括号 )
35
+ 自动跳过:
36
+ - 多行代码块(~python ... ~)
37
+ - 分割线/表格分隔符(以 5 个以上 - 开头的行)
38
+ """
39
+ errors = []
40
+ lines = text.split('\n')
41
+
42
+ symmetric_pairs = {'?', '\\', '-', '~', '*', '$'}
43
+ asymmetric_pairs = {'[': ']', '<': '>'}
44
+
45
+ in_code_block = False
46
+
47
+ for line_num, line in enumerate(lines, start=1):
48
+ stripped = line.strip()
49
+
50
+ # ---- 检测多行代码块 ----
51
+ if not in_code_block:
52
+ if re.match(r'^~[a-zA-Z0-9_]+$', stripped):
53
+ in_code_block = True
54
+ continue
55
+ else:
56
+ if stripped == '~':
57
+ in_code_block = False
58
+ continue
59
+ continue # 代码块内不检查
60
+
61
+ # ---- 跳过分割线和表格分隔符(以 5 个以上 - 开头) ----
62
+ if re.match(r'^-{5,}', stripped):
63
+ continue
64
+
65
+ # ---- 正常行检查 ----
66
+ stack = []
67
+ i = 0
68
+ n = len(line)
69
+ while i < n:
70
+ ch = line[i]
71
+
72
+ if ch == '^' and i + 1 < n:
73
+ i += 2
74
+ continue
75
+
76
+ if ch in symmetric_pairs:
77
+ if stack and stack[-1][0] == ch:
78
+ stack.pop()
79
+ else:
80
+ stack.append((ch, i + 1))
81
+ i += 1
82
+ continue
83
+
84
+ if ch in asymmetric_pairs:
85
+ stack.append((ch, i + 1))
86
+ i += 1
87
+ continue
88
+
89
+ if ch in asymmetric_pairs.values():
90
+ expected_open = {v: k for k, v in asymmetric_pairs.items()}[ch]
91
+ if stack and stack[-1][0] == expected_open:
92
+ stack.pop()
93
+ else:
94
+ errors.append({
95
+ 'line': line_num,
96
+ 'col': i + 1,
97
+ 'symbol': ch,
98
+ 'msg': f"多余的 '{ch}' 结束符,没有对应的起始符"
99
+ })
100
+ i += 1
101
+ continue
102
+
103
+ i += 1
104
+
105
+ for sym, col in stack:
106
+ errors.append({
107
+ 'line': line_num,
108
+ 'col': col,
109
+ 'symbol': sym,
110
+ 'msg': f"未闭合的 '{sym}' 起始符"
111
+ })
112
+
113
+ # ---- 检查超链接/图片的括号 () ----
114
+ i = 0
115
+ n = len(line)
116
+ while i < n:
117
+ ch = line[i]
118
+
119
+ # 超链接模式:*文字*(
120
+ if ch == '*' and i + 1 < n:
121
+ j = i + 1
122
+ while j < n and line[j] != '*':
123
+ if line[j] == '^' and j + 1 < n:
124
+ j += 2
125
+ continue
126
+ j += 1
127
+ if j < n and line[j] == '*':
128
+ if j + 1 < n and line[j + 1] == '(':
129
+ k = j + 2
130
+ while k < n and line[k] != ')':
131
+ k += 1
132
+ if k >= n:
133
+ errors.append({
134
+ 'line': line_num,
135
+ 'col': j + 2,
136
+ 'symbol': '(',
137
+ 'msg': "超链接缺少闭合的 ')'"
138
+ })
139
+ i = j + 1
140
+ continue
141
+ else:
142
+ i += 1
143
+ continue
144
+
145
+ # 图片模式:$图片名$(
146
+ if ch == '$' and i + 1 < n:
147
+ j = i + 1
148
+ while j < n and line[j] != '$':
149
+ if line[j] == '^' and j + 1 < n:
150
+ j += 2
151
+ continue
152
+ j += 1
153
+ if j < n and line[j] == '$':
154
+ if j + 1 < n and line[j + 1] == '(':
155
+ k = j + 2
156
+ while k < n and line[k] != ')':
157
+ k += 1
158
+ if k >= n:
159
+ errors.append({
160
+ 'line': line_num,
161
+ 'col': j + 2,
162
+ 'symbol': '(',
163
+ 'msg': "图片缺少闭合的 ')'"
164
+ })
165
+ i = j + 1
166
+ continue
167
+ else:
168
+ i += 1
169
+ continue
170
+
171
+ i += 1
172
+
173
+ return errors
174
+
175
+
176
+ def print_errors(errors):
177
+ """友好地打印错误信息"""
178
+ if not errors:
179
+ return
180
+ print("❌ 发现以下语法错误:\n")
181
+ for err in errors:
182
+ print(f" 第 {err['line']} 行,第 {err['col']} 列:{err['msg']} (符号: {err['symbol']})")
183
+ print(f"\n共发现 {len(errors)} 个错误,请修正后再试。")
184
+
185
+
186
+ # ============================================================
187
+ # 1. 转义处理(^符号)
188
+ # ============================================================
189
+
190
+ def escape_text(text):
191
+ """将 ^符号 替换为不可打印占位符"""
192
+ def repl(m):
193
+ return f'\x00ESC_{ord(m.group(1))}\x00'
194
+ return re.sub(r'\^([/\\?~\-*$•|!<\[\]])', repl, text)
195
+
196
+
197
+ def unescape_text(text):
198
+ """恢复占位符为原字符"""
199
+ return re.sub(r'\x00ESC_(\d+)\x00', lambda m: chr(int(m.group(1))), text)
200
+
201
+
202
+ # ============================================================
203
+ # 2. 递归解析器(处理嵌套行内标记)
204
+ # ============================================================
205
+
206
+ class _InlineParser:
207
+ def __init__(self, text):
208
+ self.text = text
209
+ self.pos = 0
210
+ self.n = len(text)
211
+
212
+ def parse(self):
213
+ parts = []
214
+ while self.pos < self.n:
215
+ ch = self.text[self.pos]
216
+ if ch == '^':
217
+ self.pos += 1
218
+ if self.pos < self.n:
219
+ parts.append(self.text[self.pos])
220
+ self.pos += 1
221
+ continue
222
+ if ch == '?':
223
+ parts.append(self._parse_until('?', '<strong>', '</strong>'))
224
+ elif ch == '\\':
225
+ parts.append(self._parse_until('\\', '<i>', '</i>'))
226
+ elif ch == '-':
227
+ parts.append(self._parse_until('-', '<del>', '</del>'))
228
+ elif ch == '~':
229
+ parts.append(self._parse_until('~', '<code>', '</code>'))
230
+ elif ch == '*':
231
+ parts.append(self._parse_link())
232
+ else:
233
+ parts.append(ch)
234
+ self.pos += 1
235
+ return ''.join(parts)
236
+
237
+ def _parse_until(self, end_char, open_tag, close_tag):
238
+ self.pos += 1
239
+ inner_chars = []
240
+ while self.pos < self.n and self.text[self.pos] != end_char:
241
+ ch = self.text[self.pos]
242
+ if ch == '^':
243
+ self.pos += 1
244
+ if self.pos < self.n:
245
+ inner_chars.append(self.text[self.pos])
246
+ self.pos += 1
247
+ continue
248
+ inner_chars.append(ch)
249
+ self.pos += 1
250
+ if self.pos < self.n and self.text[self.pos] == end_char:
251
+ self.pos += 1
252
+ inner_text = ''.join(inner_chars)
253
+ parsed_inner = _InlineParser(inner_text).parse()
254
+ return f'{open_tag}{parsed_inner}{close_tag}'
255
+
256
+ def _parse_link(self):
257
+ self.pos += 1
258
+ text_start = self.pos
259
+ while self.pos < self.n and self.text[self.pos] != '*':
260
+ if self.text[self.pos] == '^':
261
+ self.pos += 1
262
+ if self.pos < self.n:
263
+ self.pos += 1
264
+ continue
265
+ self.pos += 1
266
+ if self.pos >= self.n or self.text[self.pos] != '*':
267
+ return '*' + self.text[text_start:self.pos]
268
+ link_text = self.text[text_start:self.pos]
269
+ self.pos += 1
270
+ if self.pos < self.n and self.text[self.pos] == '(':
271
+ self.pos += 1
272
+ url_start = self.pos
273
+ while self.pos < self.n and self.text[self.pos] != ')':
274
+ self.pos += 1
275
+ if self.pos < self.n and self.text[self.pos] == ')':
276
+ url = self.text[url_start:self.pos]
277
+ self.pos += 1
278
+ parsed_text = _InlineParser(link_text).parse()
279
+ return f'<a href="{url}">{parsed_text}</a>'
280
+ else:
281
+ return '*' + link_text + '*(' + self.text[url_start:self.pos]
282
+ else:
283
+ return '*' + link_text + '*'
284
+
285
+
286
+ # ============================================================
287
+ # 3. 行内解析入口
288
+ # ============================================================
289
+
290
+ def parse_inline(text):
291
+ escaped_text = escape_text(text)
292
+ def replace_comment(m):
293
+ if re.search(r'https?://|ftp://|@', m.group(1)):
294
+ return m.group(0)
295
+ return f'<!-- {m.group(1)} -->'
296
+ escaped_text = re.sub(r'<([^>]+)>', replace_comment, escaped_text)
297
+ escaped_text = re.sub(r'\[(\d+)\]<([^>]+)>', r'<sup title="\2">[\1]</sup>', escaped_text)
298
+ escaped_text = re.sub(r'\$(.+?)\$\(([^\)]+)\)', r'<img src="\2" alt="\1">', escaped_text)
299
+ parser = _InlineParser(escaped_text)
300
+ result = parser.parse()
301
+ result = unescape_text(result)
302
+ return result
303
+
304
+
305
+ # ============================================================
306
+ # 4. 块级解析(支持多行表格)
307
+ # ============================================================
308
+
309
+ def zarkdown_to_html(text):
310
+ lines = text.split('\n')
311
+ result, i = [], 0
312
+
313
+ while i < len(lines):
314
+ raw_line = lines[i]
315
+ escaped_line = escape_text(raw_line)
316
+
317
+ # ---- 多行代码块 ----
318
+ if re.match(r'^~[a-zA-Z0-9_]+$', raw_line.strip()):
319
+ lang = raw_line.strip()[1:]
320
+ code_lines = []
321
+ i += 1
322
+ while i < len(lines) and lines[i].strip() != '~':
323
+ code_lines.append(lines[i])
324
+ i += 1
325
+ if i < len(lines) and lines[i].strip() == '~':
326
+ i += 1
327
+ result.append(f'<pre><code class="language-{lang}">{"\n".join(code_lines)}</code></pre>')
328
+ continue
329
+
330
+ # ---- 表格(支持多行单元格) ----
331
+ if re.match(r'^\|.*\|$', escaped_line) and i + 2 < len(lines):
332
+ next_esc = escape_text(lines[i+1])
333
+ after_esc = escape_text(lines[i+2]) if i+2 < len(lines) else ''
334
+ if re.match(r'^-{5,}$', next_esc.strip()) and re.match(r'^\|.*\|$', after_esc):
335
+ headers = [h.strip() for h in escaped_line.split('|')[1:-1]]
336
+ html = ['<table><thead><tr>']
337
+ for h in headers:
338
+ html.append(f'<th>{parse_inline(h)}</th>')
339
+ html.append('</tr></thead><tbody>')
340
+ j = i + 2
341
+ current_cells = None
342
+ in_data_row = False
343
+ while j < len(lines):
344
+ cur_raw = lines[j]
345
+ cur_esc = escape_text(cur_raw)
346
+ trimmed = cur_esc.strip()
347
+ if re.match(r'^-{5,}$', trimmed):
348
+ j += 1
349
+ continue
350
+ if re.match(r'^\|.*\|$', cur_esc):
351
+ if in_data_row and current_cells is not None:
352
+ html.append('<tr>')
353
+ for cell in current_cells:
354
+ html.append(f'<td>{parse_inline(cell)}</td>')
355
+ html.append('</tr>')
356
+ current_cells = None
357
+ in_data_row = False
358
+ cells = [c.strip() for c in cur_esc.split('|')[1:-1]]
359
+ while len(cells) < len(headers):
360
+ cells.append('')
361
+ current_cells = cells
362
+ in_data_row = True
363
+ j += 1
364
+ continue
365
+ elif in_data_row and cur_raw.startswith(' '):
366
+ if current_cells and len(current_cells) > 0:
367
+ content = cur_raw.lstrip()
368
+ current_cells[-1] = current_cells[-1] + '[Z_BR]' + content
369
+ j += 1
370
+ continue
371
+ else:
372
+ break
373
+ if in_data_row and current_cells is not None:
374
+ html.append('<tr>')
375
+ for cell in current_cells:
376
+ html.append(f'<td>{parse_inline(cell)}</td>')
377
+ html.append('</tr>')
378
+ html.append('</tbody></table>')
379
+ result.append(''.join(html))
380
+ i = j
381
+ continue
382
+
383
+ # ---- 标题 ----
384
+ if re.match(r'^//// ', escaped_line):
385
+ result.append(f'<h4>{parse_inline(escaped_line[5:])}</h4>')
386
+ elif re.match(r'^/// ', escaped_line):
387
+ result.append(f'<h3>{parse_inline(escaped_line[4:])}</h3>')
388
+ elif re.match(r'^// ', escaped_line):
389
+ result.append(f'<h2>{parse_inline(escaped_line[3:])}</h2>')
390
+ elif re.match(r'^/ ', escaped_line):
391
+ result.append(f'<h1>{parse_inline(escaped_line[2:])}</h1>')
392
+
393
+ # ---- 无序列表 ----
394
+ elif escaped_line.startswith('!'):
395
+ items = []
396
+ while i < len(lines) and escape_text(lines[i]).startswith('!'):
397
+ items.append(f'<li>{parse_inline(escape_text(lines[i])[1:].strip())}</li>')
398
+ i += 1
399
+ result.append(f'<ul>{"".join(items)}</ul>')
400
+ continue
401
+
402
+ # ---- 有序列表 ----
403
+ elif escaped_line.startswith('•'):
404
+ items = []
405
+ while i < len(lines) and escape_text(lines[i]).startswith('•'):
406
+ items.append(f'<li>{parse_inline(escape_text(lines[i])[1:].strip())}</li>')
407
+ i += 1
408
+ result.append(f'<ol>{"".join(items)}</ol>')
409
+ continue
410
+
411
+ # ---- 引用 ----
412
+ elif escaped_line.startswith('|'):
413
+ result.append(f'<blockquote>{parse_inline(escaped_line[1:].strip())}</blockquote>')
414
+
415
+ # ---- 分割线 ----
416
+ elif re.match(r'^-{5,}$', escaped_line.strip()):
417
+ result.append('<hr>')
418
+
419
+ # ---- 普通段落 ----
420
+ else:
421
+ if raw_line.strip():
422
+ result.append(f'<p>{parse_inline(escaped_line)}</p>')
423
+ else:
424
+ result.append('')
425
+ i += 1
426
+
427
+ # 拼接 HTML 内容
428
+ html_content = '\n'.join(result)
429
+ # 将占位符 [Z_BR] 替换为真正的 <br>
430
+ html_content = html_content.replace('[Z_BR]', '<br>')
431
+
432
+ # 返回完整 HTML 页面
433
+ return f'''<!DOCTYPE html>
434
+ <html>
435
+ <head>
436
+ <meta charset="UTF-8">
437
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
438
+ <title>Zarkdown 输出</title>
439
+ <style>
440
+ body {{
441
+ max-width: 800px;
442
+ margin: 40px auto;
443
+ padding: 0 20px;
444
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
445
+ line-height: 1.6;
446
+ color: #1e1e2f;
447
+ background-color: #fafafa;
448
+ }}
449
+ h1, h2, h3, h4 {{ color: #1e1e2f; margin-top: 1.5em; }}
450
+ h1 {{ border-bottom: 2px solid #eee; padding-bottom: 0.3em; }}
451
+ blockquote {{
452
+ margin: 1.2em 0;
453
+ padding: 0.8em 1.2em;
454
+ border-left: 4px solid #4a90d9;
455
+ background-color: #f0f4ff;
456
+ border-radius: 0 4px 4px 0;
457
+ color: #2c3e50;
458
+ }}
459
+ table {{
460
+ border-collapse: collapse;
461
+ width: 100%;
462
+ margin: 1em 0;
463
+ font-size: 0.95em;
464
+ }}
465
+ th, td {{
466
+ border: 1px solid #ddd;
467
+ padding: 8px 12px;
468
+ text-align: left;
469
+ vertical-align: top;
470
+ }}
471
+ th {{
472
+ background-color: #f2f2f2;
473
+ font-weight: 600;
474
+ }}
475
+ tr:nth-child(even) {{ background-color: #f9f9f9; }}
476
+ pre {{
477
+ background: #f6f8fa;
478
+ padding: 16px;
479
+ border-radius: 6px;
480
+ overflow-x: auto;
481
+ }}
482
+ code {{
483
+ font-family: "SF Mono", "Fira Code", monospace;
484
+ font-size: 0.9em;
485
+ }}
486
+ hr {{
487
+ border: none;
488
+ border-top: 2px dashed #ccc;
489
+ margin: 2em 0;
490
+ }}
491
+ sup {{
492
+ background: #eee;
493
+ padding: 0.1em 0.4em;
494
+ border-radius: 4px;
495
+ font-size: 0.75em;
496
+ cursor: help;
497
+ }}
498
+ img {{
499
+ max-width: 100%;
500
+ height: auto;
501
+ }}
502
+ </style>
503
+ </head>
504
+ <body>
505
+ {html_content}
506
+ </body>
507
+ </html>'''
508
+
509
+
510
+ # ============================================================
511
+ # 5. 命令行入口(集成错误检查器,支持 --no-check)
512
+ # ============================================================
513
+
514
+ def main():
515
+ parser = argparse.ArgumentParser(description="将 Zarkdown 文件转为 HTML/PDF/DOCX/LaTeX")
516
+ parser.add_argument("input", help="输入的 .zkdn 文件路径")
517
+ parser.add_argument("-o", "--output", help="输出的文件路径(默认:根据输入文件名和格式自动生成)", default=None)
518
+ parser.add_argument("-w", "--watch", action="store_true", help="监听文件变化,自动重新转换并刷新浏览器(仅 HTML 格式)")
519
+ parser.add_argument("-f", "--format",
520
+ choices=['html', 'pdf', 'docx', 'latex'],
521
+ default='html',
522
+ help="输出格式: html, pdf, docx, latex (默认: html)")
523
+ parser.add_argument("--no-check", action="store_true", help="跳过语法错误检查(不推荐)")
524
+ args = parser.parse_args()
525
+
526
+ # 自动生成输出文件名
527
+ if args.output is None:
528
+ base = args.input.rsplit('.', 1)[0]
529
+ if args.format == 'html':
530
+ args.output = base + '.html'
531
+ elif args.format == 'pdf':
532
+ args.output = base + '.pdf'
533
+ elif args.format == 'docx':
534
+ args.output = base + '.docx'
535
+ elif args.format == 'latex':
536
+ args.output = base + '.tex'
537
+ else:
538
+ args.output = base + '.html'
539
+
540
+ def convert():
541
+ try:
542
+ with open(args.input, 'r', encoding='utf-8-sig') as f:
543
+ content = f.read()
544
+
545
+ # ---- 执行错误检查(除非用户指定 --no-check) ----
546
+ if not args.no_check:
547
+ errors = validate_zarkdown(content)
548
+ if errors:
549
+ print_errors(errors)
550
+ return # 停止转换
551
+
552
+ # ---- 正常转换 ----
553
+ html = zarkdown_to_html(content)
554
+
555
+ if args.format == 'html':
556
+ with open(args.output, 'w', encoding='utf-8') as f:
557
+ f.write(html)
558
+ print(f"✅ {args.input} -> {args.output} ({time.strftime('%H:%M:%S')})")
559
+ if args.watch:
560
+ webbrowser.open('file://' + os.path.abspath(args.output))
561
+ else:
562
+ if pypandoc is None:
563
+ print("❌ 导出 PDF/DOCX/LaTeX 需要安装 pypandoc 和 pandoc 工具。")
564
+ print(" pip install pypandoc")
565
+ print(" https://pandoc.org/installing.html")
566
+ return
567
+ extra_args = []
568
+ if args.format == 'pdf':
569
+ extra_args = ['--pdf-engine=xelatex']
570
+ try:
571
+ pypandoc.convert_text(
572
+ html,
573
+ to=args.format,
574
+ format='html',
575
+ outputfile=args.output,
576
+ extra_args=extra_args
577
+ )
578
+ print(f"✅ {args.input} -> {args.output} ({args.format}) ({time.strftime('%H:%M:%S')})")
579
+ except Exception as e:
580
+ print(f"❌ 导出 {args.format} 失败: {e}")
581
+ print(" 请确认 pandoc 已正确安装,且 PDF 导出需要 LaTeX 引擎 (如 xelatex)")
582
+ except FileNotFoundError:
583
+ print(f"❌ 错误:找不到文件 {args.input}")
584
+ except Exception as e:
585
+ print(f"❌ 转换出错: {e}")
586
+
587
+ # 首次转换
588
+ convert()
589
+
590
+ if args.watch and args.format == 'html':
591
+ print(f"👀 正在监听 {args.input} 的变化(按 Ctrl+C 停止)...")
592
+ try:
593
+ last_mtime = os.path.getmtime(args.input)
594
+ while True:
595
+ current_mtime = os.path.getmtime(args.input)
596
+ if current_mtime > last_mtime:
597
+ last_mtime = current_mtime
598
+ convert()
599
+ time.sleep(0.5)
600
+ except KeyboardInterrupt:
601
+ print("\n👋 停止监听")
602
+ elif args.watch and args.format != 'html':
603
+ print("⚠️ 监听模式仅支持 HTML 格式。请使用 -f html 或移除 -w 参数。")
604
+
605
+
606
+ if __name__ == "__main__":
607
+ main()
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.4
2
+ Name: zarkdown
3
+ Version: 2.0.1
4
+ Summary: Zarkdown - 键盘友好型纯文本标记语言
5
+ Author-email: yangzizhoudiwuxuande <yangzizhou2026@outlook.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yangzizhoudiwuxuande/zarkdown
8
+ Project-URL: Bug Tracker, https://github.com/yangzizhoudiwuxuande/zarkdown/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+
14
+ # ✨ Zarkdown (版本2.0.1)
15
+
16
+ > **键盘友好型纯文本标记语言** —— 所有符号均位于键盘主键区,无需按 Shift 组合键。
17
+
18
+ [![Python Version](https://img.shields.io/badge/python-3.6+-blue.svg)](https://python.org)
19
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
20
+ [![GitHub Stars](https://img.shields.io/github/stars/yangzizhoudiwuxuande/zarkdown)](https://github.com/yangzizhoudiwuxuande/zarkdown/stargazers)
21
+
22
+ Zarkdown 是一种全新的纯文本标记语言,专为**快速写作**和**极致键盘效率**而设计。它适合用来写笔记、技术文档、博客文章,甚至可以作为配置文件的格式。
23
+
24
+ ---
25
+
26
+ ## 🎯 设计哲学
27
+
28
+ - **键盘友好**:所有语法符号都在主键区,手指不需要大范围移动
29
+ - **直观易记**:`/` 表示标题(像路径层级),`?` 表示加粗(像强调语气)
30
+ - **纯文本**:任何文本编辑器都能打开,人类可读性强
31
+ - **可扩展**:支持表格、代码块、脚注等高级功能
32
+
33
+ ---
34
+
35
+ ## 📜 完整语法表
36
+
37
+ | 效果 | 语法 | 示例 | 渲染为 |
38
+ | :--- | :--- | :--- | :--- |
39
+ | **标题 1~4 级** | `/` `//` `///` `////` + 空格 | `/ 大标题` | `<h1>`~`<h4>` |
40
+ | **粗体** | `?文字?` | `?重要?` | `<strong>` |
41
+ | **斜体** | `\文字\` | `\斜体\` | `<i>` |
42
+ | **删除线** | `-文字-` | `-删掉-` | `<del>` |
43
+ | **超链接** | `*文字*(链接)` | `*点击*(https://x.com)` | `<a>` |
44
+ | **图片** | `$图片名$(链接)` | `$logo$(./pic.png)` | `<img>` |
45
+ | **行内代码** | `~文字~` | `~npm i~` | `<code>` |
46
+ | **多行代码块** | `~语言` 开头 + `~` 结尾 | `~python`...`~` | `<pre><code>` |
47
+ | **无序列表** | `!文字`(行首) | `!苹果` | `<ul><li>` |
48
+ | **有序列表** | `•文字`(行首,U+2022) | `•第一` | `<ol><li>` |
49
+ | **引用** | `\|文字`(行首) | `\| 引文` | `<blockquote>` |
50
+ | **表格** | `\| 表头 \|` + `------` | 见下方示例 | `<table>` |
51
+ | **注释** | `<文字>`(不含URL) | `<备注>` | `<!-- -->` |
52
+ | **脚注** | `[数字]<文字>` | `[1]<说明>` | `<sup title="">` |
53
+ | **分割线** | `-----`(独占一行) | | `<hr>` |
54
+ | **转义** | `^` 加在任意符号前 | `^/ 不是标题` | 原样输出 |
55
+
56
+ ---
57
+
58
+ ## 🚀 快速上手
59
+
60
+ ### 安装
61
+
62
+ ```bash
63
+ # 克隆仓库
64
+ git clone https://github.com/yangzizhoudiwuxuande/zarkdown.git
65
+ cd zarkdown
66
+
67
+ # 创建虚拟环境(推荐)
68
+ python3 -m venv venv
69
+ source venv/bin/activate # Windows: venv\Scripts\activate
70
+
71
+ # 安装
72
+ pip install -e .
73
+ ```
74
+ ---
75
+
76
+ ## 使用
77
+
78
+ ```bash
79
+ # 转换 .zkdn 文件为 .html
80
+ zarkdown example.zkdn -o example.html
81
+
82
+ # 直接输出到终端(不生成文件)
83
+ zarkdown example.zkdn
84
+ ```
85
+ ---
86
+
87
+ ## 示例
88
+ ### 转为HTML
89
+ 创建一个`hello.zkdn`文件:
90
+ ```zkdn
91
+ / Zarkdown 欢迎页
92
+
93
+ ?恭喜?,您的格式已经跑通了!
94
+
95
+ 这里有一个链接:*点击访问*(https://github.com/yangzizhoudiwuxuande)
96
+
97
+ ~python
98
+ print("Hello Zarkdown!")
99
+ ~
100
+
101
+ ```
102
+ 然后运行:
103
+ ```bash
104
+ zarkdown hello.zkdn -w
105
+ ```
106
+ 浏览器会自动打开,显示渲染后的 HTML 页面。修改 `hello.zkdn` 并保存,页面会自动刷新。
107
+ ### 转为Word/LaTex
108
+ 转为Word/LaTex需要安装Pandoc。
109
+
110
+ ```bash
111
+ brew install pandoc
112
+ ```
113
+
114
+ 转为Word
115
+ ```bash
116
+ zarkdown my_note.zkdn -f docx
117
+ ```
118
+
119
+ 转为LaTex
120
+ ```bash
121
+ zarkdown my_note.zkdn -f latex
122
+ ```
123
+
124
+ ## 📸 效果预览
125
+ [![pm4y4lF.png](https://s41.ax1x.com/2026/08/01/pm4y4lF.png)](https://imgchr.com/i/pm4y4lF)
126
+
127
+ ## 贡献
128
+ 欢迎任何形式的贡献!你可以:
129
+
130
+ * 🐛 报告 Bug(在 Issues 中描述)
131
+ * 💡 提出新功能建议
132
+ * 📝 完善文档
133
+ * 🔧 提交 Pull Request
134
+ ## 📄 许可证
135
+ 本项目采用 MIT License 开源协议,你可以自由使用、修改、分发。
136
+ ## ❤️ 致谢
137
+ 感谢你阅读这份文档!如果觉得 Zarkdown 有趣,欢迎给项目点一颗 ⭐ 星,让更多人看到它。
138
+ ## 📝 更新日志
139
+ **v2.0.1 (2026-08-01)**
140
+ - **语法错误检查器**
141
+ 转换前自动扫描全文,检测未闭合的成对符号(`?`、`\`、`-`、`~`、`*`、`$`、`[`、`<`),并精确报告行号和列号,帮助用户快速定位问题。
142
+
143
+ - **括号配对检查**
144
+ 针对超链接 `*文字*(链接)` 和图片 `$图片名$(链接)`,自动检测缺失的闭合括号 `)`,避免生成无效链接。
145
+
146
+ - **多行表格支持**
147
+ 表格单元格内允许换行,通过缩进续行自动合并内容,并在输出中转换为 `<br>` 换行符。
148
+
149
+ - **转义字符 `^`**
150
+ 在任意特殊符号前添加 `^` 即可原样输出,避免被解析器处理,例如 `^/ 不是标题`。
151
+
152
+ - **智能跳过机制**
153
+ 错误检查器自动跳过分割线(以 `-----` 开头的行)、表格分隔行以及多行代码块内部内容,避免误报。
154
+
155
+ - **自动生成输出文件名**
156
+ 若不指定 `-o`,输出文件名将根据输入文件名和格式自动生成(如 `note.html`、`note.pdf` 等)。
157
+
158
+ **v2.0.0 (2026-07-28)**
159
+ * 支持导出为Word/LaTex等格式(需安装Pandoc)
160
+
161
+ **v1.2.2 (2026-07-26)**
162
+ * 支持多行表格
163
+
164
+ **v1.2.1 (2026-07-26)**
165
+ * 支持嵌套语法(粗体里套斜体、超链接里套粗体等)
166
+
167
+
168
+ **v1.2.0 (2026-07-25)**
169
+ * 使引用和表格变得更好看
170
+
171
+ **v1.1.0 (2026-07-25)**
172
+ * ✨ 新增 `-w` 监听模式,保存即自动重新转换
173
+ * ✨ 自动在浏览器中打开生成 HTML,实现实时预览
174
+ * 🐛 修复中文编码问题,兼容带 BOM 的 UTF-8 文件
175
+ * 🐛 修复 macOS 下相对路径打开失败的问题
176
+ * 📝 完善 README 文档,增加完整语法表和示例
177
+
178
+ **v1.0.0 (2026-07-25)**
179
+ * 🎉 首次发布,支持完整的 Zarkdown 语法
180
+
181
+
182
+ ---
183
+
184
+ Happy Writing with Zarkdown!
185
+
186
+ ## 联系
187
+ yangzizhou2026@outlook.com
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/zarkdown/__init__.py
4
+ src/zarkdown/core.py
5
+ src/zarkdown.egg-info/PKG-INFO
6
+ src/zarkdown.egg-info/SOURCES.txt
7
+ src/zarkdown.egg-info/dependency_links.txt
8
+ src/zarkdown.egg-info/entry_points.txt
9
+ src/zarkdown.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ zarkdown = zarkdown.core:main
@@ -0,0 +1 @@
1
+ zarkdown