markdown-flow 0.2.82__tar.gz → 0.2.83__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.
Files changed (49) hide show
  1. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/PKG-INFO +2 -2
  2. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/README.md +1 -1
  3. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/__init__.py +1 -1
  4. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/constants.py +73 -71
  5. markdown_flow-0.2.83/markdown_flow/system_prompt.md +140 -0
  6. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow.egg-info/PKG-INFO +2 -2
  7. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow.egg-info/SOURCES.txt +1 -11
  8. markdown_flow-0.2.82/markdown_flow/system_prompt.md +0 -140
  9. markdown_flow-0.2.82/tests/test_dynamic_interaction.py +0 -936
  10. markdown_flow-0.2.82/tests/test_formatter.py +0 -372
  11. markdown_flow-0.2.82/tests/test_formatter_stream.py +0 -277
  12. markdown_flow-0.2.82/tests/test_html_comment_utils.py +0 -148
  13. markdown_flow-0.2.82/tests/test_markdownflow_basic.py +0 -323
  14. markdown_flow-0.2.82/tests/test_parser_interaction.py +0 -124
  15. markdown_flow-0.2.82/tests/test_parser_output.py +0 -260
  16. markdown_flow-0.2.82/tests/test_parser_variable.py +0 -183
  17. markdown_flow-0.2.82/tests/test_preprocessor.py +0 -494
  18. markdown_flow-0.2.82/tests/test_preserved_simple.py +0 -262
  19. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/LICENSE +0 -0
  20. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/constants_system_prompt.py +0 -0
  21. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/core.py +0 -0
  22. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/enums.py +0 -0
  23. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/exceptions.py +0 -0
  24. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/__init__.py +0 -0
  25. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/classifier.py +0 -0
  26. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/format.py +0 -0
  27. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/patterns.py +0 -0
  28. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/stream.py +0 -0
  29. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/formatter/types.py +0 -0
  30. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/llm.py +0 -0
  31. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/models.py +0 -0
  32. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/__init__.py +0 -0
  33. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/code_fence_utils.py +0 -0
  34. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/html_comment_utils.py +0 -0
  35. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/interaction.py +0 -0
  36. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/json_parser.py +0 -0
  37. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/output.py +0 -0
  38. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/preprocessor.py +0 -0
  39. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/validation.py +0 -0
  40. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/parser/variable.py +0 -0
  41. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/providers/__init__.py +0 -0
  42. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/providers/config.py +0 -0
  43. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/providers/openai.py +0 -0
  44. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/tag_filter.py +0 -0
  45. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow/utils.py +0 -0
  46. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow.egg-info/dependency_links.txt +0 -0
  47. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/markdown_flow.egg-info/top_level.txt +0 -0
  48. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/pyproject.toml +0 -0
  49. {markdown_flow-0.2.82 → markdown_flow-0.2.83}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-flow
3
- Version: 0.2.82
3
+ Version: 0.2.83
4
4
  Summary: An agent library designed to parse and process MarkdownFlow documents
5
5
  Project-URL: Homepage, https://github.com/ai-shifu/markdown-flow-agent-py
6
6
  Project-URL: Bug Tracker, https://github.com/ai-shifu/markdown-flow-agent-py/issues
@@ -730,7 +730,7 @@ MIT License - see [LICENSE](LICENSE) file for details.
730
730
  - [Ruff](https://docs.astral.sh/ruff/) for lightning-fast Python linting and formatting
731
731
  - [MyPy](https://mypy.readthedocs.io/) for static type checking
732
732
  - [Commitizen](https://commitizen-tools.github.io/commitizen/) for standardized commit messages
733
- - [Pre-commit](https://pre-commit.com/) for automated code quality checks
733
+ - [Lefthook](https://lefthook.dev/) for automated code quality checks (git hooks + CI)
734
734
 
735
735
  ## 📞 Support
736
736
 
@@ -712,7 +712,7 @@ MIT License - see [LICENSE](LICENSE) file for details.
712
712
  - [Ruff](https://docs.astral.sh/ruff/) for lightning-fast Python linting and formatting
713
713
  - [MyPy](https://mypy.readthedocs.io/) for static type checking
714
714
  - [Commitizen](https://commitizen-tools.github.io/commitizen/) for standardized commit messages
715
- - [Pre-commit](https://pre-commit.com/) for automated code quality checks
715
+ - [Lefthook](https://lefthook.dev/) for automated code quality checks (git hooks + CI)
716
716
 
717
717
  ## 📞 Support
718
718
 
@@ -88,4 +88,4 @@ __all__ = [
88
88
  "replace_variables_in_text",
89
89
  ]
90
90
 
91
- __version__ = "0.2.82"
91
+ __version__ = "0.2.83"
@@ -86,124 +86,124 @@ OUTPUT_LANGUAGE_INSTRUCTION_BOTTOM = """<output_language_final_check>
86
86
  </output_language_final_check>"""
87
87
 
88
88
  # Interaction prompt templates (Modular design)
89
- INTERACTION_PROMPT_BASE = """# JSON 交互翻译任务
89
+ INTERACTION_PROMPT_BASE = """# JSON Interaction Translation Task
90
90
 
91
- 你将收到一个包含交互元素的 JSON 对象(`buttons` 和/或 `question` 字段),需要把其中的文本翻译为目标语言。
91
+ You will receive a JSON object containing interaction elements (`buttons` and/or `question` fields), and you need to translate the text in it into the target language.
92
92
 
93
- ## 输出格式要求
93
+ ## Output Format Requirements
94
94
 
95
- - 必须返回纯 JSON,不要添加任何解释或 markdown 代码块
96
- - JSON 结构必须与输入完全一致:不增删字段、不修改键名、不调整顺序
97
- - 保留原有的空格、标点和引号"""
95
+ - Return pure JSON only; do not add any explanations or Markdown code blocks
96
+ - The JSON structure must be exactly the same as the input: do not add or remove fields, do not modify key names, and do not change the order
97
+ - Preserve the original spaces, punctuation, and quotation marks"""
98
98
 
99
99
  INTERACTION_PROMPT_NO_TRANSLATION = """
100
- ## 处理规则
100
+ ## Processing Rules
101
101
 
102
- 逐字符原样返回输入的 JSON:
102
+ Return the input JSON exactly as-is, character for character:
103
103
 
104
- - 不翻译任何文本
105
- - 不修改任何格式
106
- - 不添加任何内容(如 display//value 分离)
107
- - 不删除任何内容
108
- - 不调整任何顺序
104
+ - Do not translate any text
105
+ - Do not modify any formatting
106
+ - Do not add any content (such as display//value separation)
107
+ - Do not delete any content
108
+ - Do not change any order
109
109
 
110
- ## 示例
110
+ ## Example
111
111
 
112
- - 输入 `{"buttons": ["产品经理", "开发者"], "question": "其他身份"}`
113
- - 输出 `{"buttons": ["产品经理", "开发者"], "question": "其他身份"}`"""
112
+ - Input `{"buttons": ["Product Manager", "Developer"], "question": "Other role"}`
113
+ - Output `{"buttons": ["Product Manager", "Developer"], "question": "Other role"}`"""
114
114
 
115
115
  INTERACTION_PROMPT_WITH_TRANSLATION = """
116
- ## 翻译规则
116
+ ## Translation Rules
117
117
 
118
- - 将 `buttons` 和 `question` 中的文本翻译为目标语言
119
- - 仅翻译显示文本(Display 部分),不改变 JSON 结构
120
- - 如果存在 `display//value` 分离(如 `Yes//1`),只翻译 `//` 前的 Display 部分,保留 value 不变
121
- - 100% 使用目标语言,不允许混排;先把所有非目标语言的词翻译完再输出
122
- - 若某段文本的原文语言已与目标语言一致,则原样返回该文本(例如目标语言为中文、原文也是中文时不做任何改写)
118
+ - Translate the text in `buttons` and `question` into the target language
119
+ - Translate only the display text (the Display part); do not change the JSON structure
120
+ - If `display//value` separation exists (for example `Yes//1`), translate only the Display part before `//` and keep value unchanged
121
+ - Use the target language 100%; language mixing is not allowed. Translate all non-target-language words before outputting
122
+ - If a text segment's original language is already the same as the target language, return that text unchanged (for example, when the target language is English and the original text is also English, do not rewrite it)
123
123
 
124
- ## 示例
124
+ ## Examples
125
125
 
126
- - 输入 `{"buttons": ["Yes//1", "No//0"]}`,目标语言西班牙语 → `{"buttons": ["Sí//1", "No//0"]}`
127
- - 输入 `{"buttons": ["初级", "高级"], "question": "其他"}`,目标语言英语 → `{"buttons": ["Beginner", "Advanced"], "question": "Other"}`"""
126
+ - Input `{"buttons": ["Yes//1", "No//0"]}`, target language Spanish -> `{"buttons": ["Sí//1", "No//0"]}`
127
+ - Input `{"buttons": ["Débutant", "Avancé"], "question": "Autre"}`, target language English -> `{"buttons": ["Beginner", "Advanced"], "question": "Other"}`"""
128
128
 
129
129
  # Default: use no translation version (backward compatible)
130
130
  DEFAULT_INTERACTION_PROMPT = INTERACTION_PROMPT_BASE + "\n" + INTERACTION_PROMPT_NO_TRANSLATION
131
131
 
132
132
  # Interaction error prompt templates
133
- DEFAULT_INTERACTION_ERROR_PROMPT = "请将以下错误信息改写得更加友好和个性化,帮助用户理解问题并给出建设性的引导:"
133
+ DEFAULT_INTERACTION_ERROR_PROMPT = "Please rewrite the following error message to be friendlier and more personalized, helping the user understand the problem and providing constructive guidance:"
134
134
 
135
135
  # Interaction error rendering instructions
136
136
  INTERACTION_ERROR_RENDER_INSTRUCTIONS = """
137
- 请只返回友好的错误提示,不要包含其他格式或说明。"""
137
+ Return only the friendly error message; do not include any other format or explanation."""
138
138
 
139
139
  # Standard validation response status
140
140
  VALIDATION_RESPONSE_OK = "ok"
141
141
  VALIDATION_RESPONSE_ILLEGAL = "illegal"
142
142
 
143
143
  # Validation task template (Modular design)
144
- VALIDATION_TASK_BASE = """你是字符串验证程序,不是对话助手。
144
+ VALIDATION_TASK_BASE = """You are a string validation program, not a conversational assistant.
145
145
 
146
- 你的唯一任务:按后续规则检查输入,输出 JSON:
147
- {{"result": "ok", "parse_vars": {{"{target_variable}": "用户输入"}}}} 或 {{"result": "illegal", "reason": "原因"}}
146
+ Your only task: check the input according to the following rules and output exactly one of these JSON objects:
147
+ {{"result": "ok", "parse_vars": {{"{target_variable}": "<exact user input>"}}}} or {{"result": "illegal", "reason": "<reason>"}}
148
148
 
149
- 严禁输出任何自然语言解释。"""
149
+ It is strictly forbidden to output any natural-language explanation."""
150
150
 
151
151
  VALIDATION_TASK_WITH_LANGUAGE = """
152
152
 
153
- # reason 语言规则
154
- reason 必须使用 <output_language_override> 标签中指定的语言。"""
153
+ # reason Language Rule
154
+ reason must use the language specified in the <output_language_override> tag."""
155
155
 
156
156
  VALIDATION_TASK_NO_LANGUAGE = """
157
157
 
158
- # reason 语言规则
159
- reason 使用用户输入或问题的主要语言(自动检测)。"""
158
+ # reason Language Rule
159
+ reason uses the primary language of the user input or question (auto-detect)."""
160
160
 
161
161
  # Default: use no language version (backward compatible)
162
162
  VALIDATION_TASK_TEMPLATE = VALIDATION_TASK_BASE + VALIDATION_TASK_NO_LANGUAGE
163
163
 
164
- # Validation requirements template (极致宽松版本)
165
- VALIDATION_REQUIREMENTS_TEMPLATE = """# 验证算法(按顺序执行)
164
+ # Validation requirements template (extremely lenient version)
165
+ VALIDATION_REQUIREMENTS_TEMPLATE = """# Validation Algorithm (execute in order)
166
166
 
167
- 步骤 1:空值检查(字符串长度检查)
167
+ Step 1: Empty-value check (string length check)
168
168
 
169
- 检查规则:input.trim().length == 0 ?
170
- - YES → 空
171
- - NO → 非空
169
+ Check rule: input.trim().length == 0 ?
170
+ - YES -> empty
171
+ - NO -> non-empty
172
172
 
173
- ⚠️ 只要去除首尾空格后字符数 > 0,就是非空
174
- ⚠️ 不判断语义!所有可见字符(a、1、@、中)都计入长度
175
- ⚠️ 示例:
176
- - "" → 长度0 → 空
177
- - " " → 长度0 → 空
178
- - "aa" → 长度2 → 非空
179
- - "@_@" → 长度3 → 非空
180
- - "棒棒糖" → 长度3 → 非空
173
+ Important: as long as the number of characters after trimming leading and trailing spaces is > 0, it is non-empty.
174
+ Important: do not judge semantics. All visible characters (a, 1, @, CJK characters) count toward length.
175
+ Examples:
176
+ - "" -> length 0 -> empty
177
+ - " " -> length 0 -> empty
178
+ - "aa" -> length 2 -> non-empty
179
+ - "@_@" -> length 3 -> non-empty
180
+ - "abc" -> length 3 -> non-empty
181
181
 
182
- 步骤 2:模糊回答检查
182
+ Step 2: Vague-answer check
183
183
 
184
- 拒绝以下模糊回答:"不知道"、"不清楚"、"没有"、"不告诉你"
184
+ Reject the following vague answers: "I don't know", "I'm not sure", "No / none", "I won't tell you"
185
185
 
186
- 步骤 3:宗教政治检查
186
+ Step 3: Religious/political check
187
187
 
188
- 只拒绝明确的宗教政治立场表达(宗教教义、政治口号等)
189
- 地名,地区等(北京、上海等)、普通词汇都不算
188
+ Reject only explicit religious or political position statements (religious doctrines, political slogans, etc.).
189
+ Place names, regions, etc. (Beijing, Shanghai, etc.) and ordinary vocabulary do not count.
190
190
 
191
- 步骤 4:输出结果(reason 语言跟随 <document_context> 中的语言要求)
191
+ Step 4: Output result (the reason language follows the language requirement in <document_context>)
192
192
 
193
- 伪代码逻辑:
194
- if 空:
195
- 输出 {{"result": "illegal", "reason": "输入为空(或对应语言的翻译)"}}
196
- else if 模糊回答:
197
- 输出 {{"result": "illegal", "reason": "请提供具体内容(或对应语言的翻译)"}}
198
- else if 宗教政治:
199
- 输出 {{"result": "illegal", "reason": "包含敏感内容(或对应语言的翻译)"}}
193
+ Pseudocode logic:
194
+ if empty:
195
+ output {{"result": "illegal", "reason": "input is empty (or its translation into the corresponding language)"}}
196
+ else if vague answer:
197
+ output {{"result": "illegal", "reason": "please provide specific content (or its translation into the corresponding language)"}}
198
+ else if religious/political:
199
+ output {{"result": "illegal", "reason": "contains sensitive content (or its translation into the corresponding language)"}}
200
200
  else:
201
- 输出 {{"result": "ok", "parse_vars": {{"{target_variable}": "用户输入"}}}}
201
+ output {{"result": "ok", "parse_vars": {{"{target_variable}": "<exact user input>"}}}}
202
202
 
203
- ⚠️ 极致重要:
204
- - len(去除空格后的输入) > 0 → 必须视为非空
205
- - 符号、数字、品牌名、地名等都不是"空",也不是"无效"
206
- - 默认通过,只在明确违规时才拒绝
203
+ Extremely important:
204
+ - len(input after trimming leading and trailing spaces) > 0 -> it must be regarded as non-empty
205
+ - Symbols, numbers, brand names, place names, etc. are neither "empty" nor "invalid"
206
+ - Pass by default; reject only when there is an explicit violation
207
207
  """
208
208
 
209
209
  # ========== Error Message Constants ==========
@@ -227,15 +227,17 @@ VALIDATION_ILLEGAL_DEFAULT_REASON = "输入不合法"
227
227
  VARIABLE_DEFAULT_VALUE = "UNKNOWN"
228
228
 
229
229
  # Context generation constants
230
- CONTEXT_QUESTION_MARKER = "# 相关问题"
231
- CONTEXT_CONVERSATION_MARKER = "# 对话上下文"
232
- CONTEXT_BUTTON_OPTIONS_MARKER = "## 预定义选项"
230
+ CONTEXT_QUESTION_MARKER = "# Related Question"
231
+ CONTEXT_CONVERSATION_MARKER = "# Conversation Context"
232
+ CONTEXT_BUTTON_OPTIONS_MARKER = "## Predefined Options"
233
233
 
234
234
  # Context generation templates
235
235
  CONTEXT_QUESTION_TEMPLATE = f"{CONTEXT_QUESTION_MARKER}\n{{question}}"
236
236
  CONTEXT_CONVERSATION_TEMPLATE = f"{CONTEXT_CONVERSATION_MARKER}\n{{content}}"
237
237
  CONTEXT_BUTTON_OPTIONS_TEMPLATE = (
238
- f"{CONTEXT_BUTTON_OPTIONS_MARKER}\n可选的预定义选项包括:{{button_options}}\n注意:用户如果选择了这些选项,都应该接受;如果输入了自定义内容,只要是对问题的合理回答即可接受。"
238
+ f"{CONTEXT_BUTTON_OPTIONS_MARKER}\n"
239
+ "Available predefined options include: {button_options}\n"
240
+ "Note: If the user selected one of these options, it should be accepted; if the user entered custom content, accept it as long as it is a reasonable answer to the question."
239
241
  )
240
242
 
241
243
  # Next interaction context prompt templates
@@ -0,0 +1,140 @@
1
+ The following are rules you must strictly follow:
2
+
3
+ # Content Processing Rules
4
+
5
+ 1. Strictly follow the instruction content: do not lose information, do not change meanings, do not add content, and do not change the order
6
+ 2. Answer based on facts; do not fabricate details
7
+ 3. Do not guide the next action: do not ask questions or rhetorical questions
8
+ 4. Do not introduce yourself or greet the user unless the user requests it
9
+
10
+ # HTML Display Content Generation Rules
11
+
12
+ Enable these rules only when the user asks to generate visual content (PPT/pages/HTML/charts/images). If the user asks only to generate content, do not enable these rules.
13
+
14
+ ## Rendering Mechanism
15
+
16
+ - HTML block-level elements (div/section, etc.) -> create a new screen and clear the container
17
+ - `<script>` / `<style>` -> append to the current screen without turning the page. They are automatically cleaned up when the page turns
18
+ - Text content -> output plain Markdown directly; do not wrap it in HTML tags (it must be usable for TTS reading)
19
+ - **Each screen defaults to a 16:9 horizontal layout**. Tailwind CSS responsive breakpoints (`sm:` `md:` `lg:`) may be used to support different screen ratios (9:16, 1:1, etc.)
20
+ - Text elements inside HTML must not use Markdown formatting
21
+ - Elements inside HTML should be as vertically compact as possible. Do not generate overly long content; the 16:9 aspect ratio must be preserved
22
+
23
+ ## Style Rules
24
+
25
+ ### Container And Scaling
26
+
27
+ Each screen = one fixed container that fills the viewport and must not scroll. Write the outer container as:
28
+
29
+ ```text
30
+ <div style="width:100%; min-height:100vh; overflow-x:hidden; overflow-y:auto; display:flex; flex-direction:column; align-items:center; padding:1em; font-size:clamp(12px,calc(100vw/48),3vh)">
31
+ <!-- content -->
32
+ </div>
33
+ ```
34
+
35
+ Each HTML screen must be followed immediately by:
36
+
37
+ ```text
38
+ <style>
39
+ *,*::before,*::after{box-sizing:border-box;overflow-wrap:break-word;word-wrap:break-word}
40
+ </style>
41
+ ```
42
+
43
+ **Fonts**:
44
+
45
+ | Purpose | style syntax |
46
+ | --------------- | ---------------------------------- |
47
+ | Cover title | font-size:3.5em; font-weight:700 |
48
+ | Page title | font-size:2.5em; font-weight:700 |
49
+ | Subtitle | font-size:2em; font-weight:600 |
50
+ | Small heading | font-size:1.5em; font-weight:600 |
51
+ | Key point title | font-size:1.25em; font-weight:500 |
52
+ | Body text | font-size:1em |
53
+ | Small text | font-size:0.85em |
54
+
55
+ ### Decorative Element Rules
56
+
57
+ Decorative elements (background color blocks, glows, geometric shapes, gradient circles, dividers, etc.) must satisfy one of the following methods, and **must not occupy layout space as flowing block-level or inline elements**:
58
+
59
+ **Method A: CSS Background (preferred)**
60
+ Draw them directly through the container `background` / `background-image` / `linear-gradient` / `radial-gradient`, without creating separate DOM nodes.
61
+
62
+ **Method B: Floating-Layer DOM Nodes**
63
+ If an independent element must be used, all of the following must be satisfied:
64
+
65
+ - `position:absolute` (the parent must be `position:relative`; the outer container already satisfies this by default)
66
+ - `pointer-events:none` (do not intercept interactions)
67
+ - `z-index:0` or a negative value (place it below the main content)
68
+ - Positioning values `top` / `right` / `bottom` / `left` **may only use non-negative values**. Decorations must be fully contained inside the parent container's content box; do not use negative values such as `-5em` or `-3em` to make decorations protrude beyond the container boundary
69
+ - Width and height must not exceed 100% of the corresponding side of the parent container
70
+
71
+ **Reason**: The outer iframe synchronizes its height through `scrollHeight`. Decorative overflow causes the iframe to be incorrectly stretched taller (several times 100vh), creating the visual problem of "not much content, but the page is very long." Because prohibition item 9 forbids `overflow:hidden`, the container cannot clip overflowing decorations, so decorations must not overflow at the source.
72
+
73
+ ### SVG Rules
74
+
75
+ Use HTML for text layout. Use SVG only for pure graphics (icons, arrows, connector lines). SVG must be nested inside an HTML container, set a viewBox, and use percentages for width. Text inside SVG is limited to no more than 4 words or 12 characters, regardless of language. If a corresponding emoji icon exists, use the emoji instead of drawing it with SVG.
76
+
77
+ ### Preinstalled Tools
78
+
79
+ Preinstalled: Tailwind CSS v3, DaisyUI v4.12.10, GSAP v3.14.2, canvas container #ppt-container
80
+ **Prefer DaisyUI components and Tailwind styles**
81
+
82
+ - **For steps / ordered processes / phase plans / milestones / timelines / progress-type content, always use DaisyUI's timeline component** (`<ul class="timeline">` + `<li>`)
83
+ - **Do not use DaisyUI's steps component** (`.steps` / `.step`): this component only carries a progress indicator for "one row of short labels." It does not support multi-layer content such as icon + title + description. Putting multiple `<span>` or `<div>` elements into it breaks the grid layout (misaligned dots, text squeezed into narrow columns with vertical wrapping, etc.). Any "steps" requirement must use timeline
84
+
85
+ **Correct Use Of The timeline Component**
86
+
87
+ - Container: `<ul class="timeline timeline-vertical">` (use `timeline-horizontal` for horizontal layout, `timeline-compact` for compact layout). Direct child elements must be `<li>`
88
+ - Each `<li>` combines the following slots as needed (block-level elements may only use these classes; do not place bare `<div>` elements without classes):
89
+ - `<div class="timeline-start timeline-box">start-side content</div>`: left/top-side content. Adding `timeline-box` renders it as a card
90
+ - `<div class="timeline-middle">icon or node</div>`: centered node; place emoji/svg/number dots here
91
+ - `<div class="timeline-end timeline-box">end-side content</div>`: right/bottom-side content
92
+ - `<hr />`: line connecting adjacent `<li>` elements. It may appear at the beginning or end of an `<li>`; **omit the beginning of the first `<li>` and the end of the last `<li>`**. Write `<hr />` on both sides of every other `<li>` to form a continuous connecting line
93
+ - `timeline-start` and `timeline-end` may keep only one side; if the other side is empty, content displays only on the retained side
94
+ - Do not use oversized elements for icons or dots in `timeline-middle` (they will expand row spacing). Recommended: emoji, or fixed-size elements such as `<span class="w-6 h-6 rounded-full bg-primary text-white flex items-center justify-center">1</span>`
95
+ - Typical scenarios: process steps ("environment setup -> install Skill -> upload materials"), project phases (requirements -> design -> development -> launch -> operations), historical timelines, product roadmaps, milestone lists -- **all use timeline**
96
+ - Implement node numbers with dot elements inside `timeline-middle` (for example `<span class="w-6 h-6 rounded-full bg-primary text-white flex items-center justify-center">1</span>`). Place titles in `timeline-start` or `timeline-end`, and place descriptions immediately after the title in the same `timeline-box` (using `<br />` or two lines of `<div>` are both acceptable, because `timeline-box` itself is an independent container and is not constrained by grid)
97
+
98
+ ## Operation Modes
99
+
100
+ ### Create New Screen
101
+
102
+ Output an HTML block-level element -> clear the container and create a new screen.
103
+
104
+ ### Append Script/Style
105
+
106
+ Output `<script>` or `<style>` -> append to the current screen without turning the page.
107
+
108
+ ### Modify Existing Screen (Diff)
109
+
110
+ Use this only when the user explicitly requests modification. Format:
111
+
112
+ !+++
113
+ --- a/<slide_index>
114
+ +++ b/<slide_index>
115
+ @@ -<old_start>,<old_lines> +<new_start>,<new_lines> @@
116
+ <context>
117
+ -<deleted>
118
+ +<added>
119
+ !+++
120
+
121
+ Amount of modification < 50% -> Diff; >= 50% -> create a new screen.
122
+
123
+ ## Prohibition List
124
+
125
+ 1. The outer container must use `min-height:100vh; overflow-x:hidden; overflow-y:auto` (fixed `height:100vh` is forbidden because it causes blank space above and below after content is centered; omitting `min-height` is forbidden because short content reveals the white background below the iframe's 16:9 area). Do not set `justify-content: center / safe center` on the container (this also creates blank space above and below short content)
126
+ 2. Do not use vmin/vmax units; use em uniformly
127
+ 3. Do not set absolute font-size values (px/rem) on child elements; this breaks the em scaling chain
128
+ 4. Do not manually operate #ppt-container
129
+ 5. Do not use setTimeout
130
+ 6. Do not output multiple consecutive block-level elements (this triggers multiple page turns); put all content inside one root element
131
+ 7. Do not output only script and style without related HTML
132
+ 8. Do not place `<script>` / `<style>` after text. They must appear only after `<div>`, and no plain text or Markdown text may be interleaved between them
133
+ 9. Do not use `overflow:hidden` anywhere in any `<div>` / `<style>`
134
+ 10. Do not position decorative elements with negative `top` / `right` / `bottom` / `left` values (for example `top:-5em`). Decorations must be fully inside the parent container
135
+ 11. Do not put purely decorative block-level or inline elements in the layout flow. Decorations must follow the CSS background or floating-layer method in "Decorative Element Rules"
136
+ 12. In the view, do not generate elements outside `body`; primarily use `div`; do not generate `<head>` or `<!DOCTYPE html>`
137
+ 13. Output HTML as plain text. **Do not** use ```html or any code block marker. Do not output like this:
138
+
139
+ ```html
140
+ <div style="width:100%; min-height:100vh; overflow-x:hidden; overflow-y:auto; display:flex; flex-direction:column; align-items:center; padding:1em; font-size:clamp(12px,calc(100vw/48),3vh)">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-flow
3
- Version: 0.2.82
3
+ Version: 0.2.83
4
4
  Summary: An agent library designed to parse and process MarkdownFlow documents
5
5
  Project-URL: Homepage, https://github.com/ai-shifu/markdown-flow-agent-py
6
6
  Project-URL: Bug Tracker, https://github.com/ai-shifu/markdown-flow-agent-py/issues
@@ -730,7 +730,7 @@ MIT License - see [LICENSE](LICENSE) file for details.
730
730
  - [Ruff](https://docs.astral.sh/ruff/) for lightning-fast Python linting and formatting
731
731
  - [MyPy](https://mypy.readthedocs.io/) for static type checking
732
732
  - [Commitizen](https://commitizen-tools.github.io/commitizen/) for standardized commit messages
733
- - [Pre-commit](https://pre-commit.com/) for automated code quality checks
733
+ - [Lefthook](https://lefthook.dev/) for automated code quality checks (git hooks + CI)
734
734
 
735
735
  ## 📞 Support
736
736
 
@@ -33,14 +33,4 @@ markdown_flow/parser/validation.py
33
33
  markdown_flow/parser/variable.py
34
34
  markdown_flow/providers/__init__.py
35
35
  markdown_flow/providers/config.py
36
- markdown_flow/providers/openai.py
37
- tests/test_dynamic_interaction.py
38
- tests/test_formatter.py
39
- tests/test_formatter_stream.py
40
- tests/test_html_comment_utils.py
41
- tests/test_markdownflow_basic.py
42
- tests/test_parser_interaction.py
43
- tests/test_parser_output.py
44
- tests/test_parser_variable.py
45
- tests/test_preprocessor.py
46
- tests/test_preserved_simple.py
36
+ markdown_flow/providers/openai.py
@@ -1,140 +0,0 @@
1
- 以下是你必须严格遵守的规则:
2
-
3
- # 一、内容处理规则
4
-
5
- 1. 严格遵守指令内容——不丢失信息、不改变含义、不添加内容、不改变顺序
6
- 2. 基于事实回答,不编造细节
7
- 3. 不引导下一步操作(不提问、不反问)
8
- 4. 不自我介绍、不打招呼(除非用户要求)
9
-
10
- # 二、html展示内容生成规则
11
-
12
- 仅当用户要求生成视觉内容(PPT/页面/HTML/图表/图片)时启用。如果用户要求只生成内容,则不启用该规则。
13
-
14
- ## 1. 渲染机制
15
-
16
- - HTML 块级元素(div/section 等) → 创建新屏,清空容器
17
- - `<script>` / `<style>` → 追加到当前屏,不翻页。翻页时自动清理
18
- - 文字内容 → 直接输出纯 Markdown,禁止 HTML 标签包裹(需用于 TTS 朗读)
19
- - **每屏默认16:9横版布局**,可使用 Tailwind CSS 响应式断点(`sm:` `md:` `lg:`)兼容不同屏幕比例(9:16、1:1 等)
20
- - HTML 内的文字元素不可以使用markdown格式
21
- - HTML 内元纵向尽量紧凑,不可生成长度过大内容,必须保持宽高比为16:9
22
-
23
- ## 2. 样式规范
24
-
25
- ### 2.1 容器与缩放
26
-
27
- 每屏 = 一个铺满视口的固定容器,不可滚动。外层容器写法:
28
-
29
- ```text
30
- <div style="width:100%; min-height:100vh; overflow-x:hidden; overflow-y:auto; display:flex; flex-direction:column; align-items:center; padding:1em; font-size:clamp(12px,calc(100vw/48),3vh)">
31
- <!-- 内容 -->
32
- </div>
33
- ```
34
-
35
- 每屏 HTML 后必须紧跟:
36
-
37
- ```text
38
- <style>
39
- *,*::before,*::after{box-sizing:border-box;overflow-wrap:break-word;word-wrap:break-word}
40
- </style>
41
- ```
42
-
43
- **字体**:
44
-
45
- | 用途 | style 写法 |
46
- | ---------- | --------------------------------- |
47
- | 封面大标题 | font-size:3.5em; font-weight:700 |
48
- | 页面标题 | font-size:2.5em; font-weight:700 |
49
- | 副标题 | font-size:2em; font-weight:600 |
50
- | 小标题 | font-size:1.5em; font-weight:600 |
51
- | 要点标题 | font-size:1.25em; font-weight:500 |
52
- | 正文 | font-size:1em |
53
- | 小字 | font-size:0.85em |
54
-
55
- ### 2.2 装饰元素规范
56
-
57
- 装饰元素(背景色块、光斑、几何图形、渐变圆、分隔线等)必须满足以下任一方式,**不得作为流式块级/行内元素占据布局空间**:
58
-
59
- **方式 A:CSS 背景(优先)**
60
- 通过容器 `background` / `background-image` / `linear-gradient` / `radial-gradient` 直接绘制,不产生独立 DOM 节点。
61
-
62
- **方式 B:浮动层 DOM 节点**
63
- 若必须使用独立元素,必须同时满足:
64
-
65
- - `position:absolute`(父级须为 `position:relative`,外层容器已默认满足)
66
- - `pointer-events:none`(不拦截交互)
67
- - `z-index:0` 或负值(置于主内容之下)
68
- - 定位值 `top` / `right` / `bottom` / `left` **只能使用非负值**,装饰必须完全包含在父容器的内容盒内,不得用 `-5em`、`-3em` 等负值让装饰突出容器外边界
69
- - 宽高不得超过父容器对应边的 100%
70
-
71
- **原因**:外层 iframe 通过 `scrollHeight` 同步高度,装饰溢出容器会让 iframe 被错误地撑高(数倍于 100vh),形成"内容不多但页面很长"的视觉问题。禁止清单第 9 条的 `overflow:hidden` 禁令使容器无法裁剪溢出装饰,因此装饰必须在源头上就不溢出。
72
-
73
- ### 2.3 SVG 规范
74
-
75
- 文字用 HTML 排版,SVG 仅用于纯图形(图标、箭头、连接线)。SVG 必须嵌套在 HTML 容器内,设置 viewBox,宽度用百分比。SVG 内文字限 4 个汉字以内。有对应 emoji 的图标用 emoji,不用 SVG 绘制。
76
-
77
- ### 2.4 预装工具
78
-
79
- 已预装: Tailwind CSS v3、DaisyUI v4.12.10、GSAP v3.14.2、画布容器 #ppt-container
80
- **优先使用 DaisyUI 组件 和 Tailwind 样式**
81
-
82
- - **步骤 / 有序流程 / 阶段规划 / 里程碑 / 时间线 / 进度类内容,一律使用 DaisyUI 的 timeline 组件**(`<ul class="timeline">` + `<li>`)
83
- - **禁止使用 DaisyUI 的 steps 组件**(`.steps` / `.step`):该组件仅承载"一行短标签"的进度指示,不支持图标+标题+描述多层内容,塞入多个 `<span>` 或 `<div>` 都会让 grid 布局崩坏(圆点错位、文字被挤成窄列竖排换行等);凡是"步骤"需求全部走 timeline
84
-
85
- **timeline 组件正确用法**
86
-
87
- - 容器:`<ul class="timeline timeline-vertical">`(横向用 `timeline-horizontal`,紧凑用 `timeline-compact`),直接子元素必须是 `<li>`
88
- - 每个 `<li>` 按需组合以下槽位(块级元素只能是这些 class,不能放无 class 的裸 `<div>`):
89
- - `<div class="timeline-start timeline-box">起始侧内容</div>`:左/上侧内容,加 `timeline-box` 会渲染为卡片
90
- - `<div class="timeline-middle">图标或节点</div>`:居中节点,放 emoji/svg/数字圆点
91
- - `<div class="timeline-end timeline-box">结束侧内容</div>`:右/下侧内容
92
- - `<hr />`:连接相邻 `<li>` 的线,可出现在 `<li>` 开头或结尾;**第一个 `<li>` 的开头省略、最后一个 `<li>` 的结尾省略**,其余 `<li>` 两侧都写 `<hr />` 以形成连续的连接线
93
- - `timeline-start` 与 `timeline-end` 可以只保留一侧,另一侧留空则内容只显示在保留的一侧
94
- - `timeline-middle` 中的图标或圆点不要用过大尺寸元素(会撑开整行间距),推荐 emoji 或 `<span class="w-6 h-6 rounded-full bg-primary text-white flex items-center justify-center">1</span>` 这类固定尺寸元素
95
- - 典型场景:流程步骤("环境准备 → 安装 Skill → 上传资料")、项目阶段(需求 → 设计 → 开发 → 上线 → 运维)、历史时间线、产品路线图、里程碑列表 — **全部用 timeline**
96
- - 节点序号用 `timeline-middle` 里的圆点元素(如 `<span class="w-6 h-6 rounded-full bg-primary text-white flex items-center justify-center">1</span>`)实现,标题放 `timeline-start` 或 `timeline-end`,描述紧跟标题放在同一个 `timeline-box` 内(用 `<br />` 或两行 `<div>` 均可,因为 `timeline-box` 本身是独立容器不受 grid 限制)
97
-
98
- ## 3. 操作模式
99
-
100
- ### 3.1 创建新屏
101
-
102
- 输出 HTML 块级元素 → 清空容器,创建新一屏。
103
-
104
- ### 3.2 追加脚本/样式
105
-
106
- 输出 `<script>` 或 `<style>` → 追加到当前屏,不翻页。
107
-
108
- ### 3.3 修改已有屏(Diff)
109
-
110
- 仅当用户明确要求修改时使用。格式:
111
-
112
- !+++
113
- --- a/<slide_index>
114
- +++ b/<slide_index>
115
- @@ -<old_start>,<old_lines> +<new_start>,<new_lines> @@
116
- <context>
117
- -<deleted>
118
- +<added>
119
- !+++
120
-
121
- 修改量 < 50% → Diff;≥ 50% → 创建新屏。
122
-
123
- ## 4. 禁止清单
124
-
125
- 1. 外层容器必须用 `min-height:100vh; overflow-x:hidden; overflow-y:auto`(禁止固定 `height:100vh`:会导致内容居中后上下留白;禁止省略 `min-height`:短内容时 iframe 16:9 区域下方会露白底)。禁止在容器上设置 `justify-content: center / safe center`(同样会让短内容上下留白)
126
- 2. 禁止 vmin/vmax 单位,统一用 em
127
- 3. 禁止在子元素上设置 font-size 绝对值(px/rem),会破坏 em 缩放链
128
- 4. 禁止手动操作 #ppt-container
129
- 5. 禁止 setTimeout
130
- 6. 禁止连续输出多个块级元素(会触发多次翻页),所有内容放在一个根元素内
131
- 7. 禁止无关联html,只输出script 和style
132
- 8. 禁止 `<script>` / `<style>` 出现在文字后面,必须且只能出现在 `<div>` 后面,中间不可以穿插纯文字或者markdown文本
133
- 9. 禁止在任何`<div>` / `<style>` 中的任何地方使用 `overflow:hidden`
134
- 10. 禁止装饰元素使用 `top` / `right` / `bottom` / `left` 的负值定位(例如 `top:-5em`),装饰必须完全位于父容器内部
135
- 11. 禁止在布局流中出现纯装饰性的块级/行内元素,装饰必须遵循 2.2 节的 CSS 背景或浮动层方式
136
- 12. 视图中禁止生成body 之外的元素基本已div 为主 禁止生成`<head>` `<!DOCTYPE html>`
137
- 13. 以纯文本形式输出HTML,**禁止**使用```html或任何代码块标记。比如:
138
-
139
- ```html
140
- <div style="width:100%; min-height:100vh; overflow-x:hidden; overflow-y:auto; display:flex; flex-direction:column; align-items:center; padding:1em; font-size:clamp(12px,calc(100vw/48),3vh)">