markdown-flow 0.2.84__tar.gz → 0.2.85__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.
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/PKG-INFO +1 -1
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/__init__.py +9 -2
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/__init__.py +2 -0
- markdown_flow-0.2.85/markdown_flow/formatter/sanitize.py +95 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/system_prompt.md +1 -1
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/PKG-INFO +1 -1
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/SOURCES.txt +1 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/LICENSE +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/README.md +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/constants.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/constants_system_prompt.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/core.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/enums.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/exceptions.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/classifier.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/format.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/patterns.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/stream.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/types.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/llm.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/models.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/__init__.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/code_fence_utils.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/html_comment_utils.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/interaction.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/json_parser.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/output.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/preprocessor.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/validation.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/variable.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/__init__.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/config.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/openai.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/tag_filter.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/utils.py +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/dependency_links.txt +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/top_level.txt +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/pyproject.toml +0 -0
- {markdown_flow-0.2.84 → markdown_flow-0.2.85}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.85
|
|
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
|
|
@@ -51,7 +51,13 @@ Import Guide:
|
|
|
51
51
|
# Import core classes and enums
|
|
52
52
|
from .core import MarkdownFlow
|
|
53
53
|
from .enums import BlockType, InputType
|
|
54
|
-
from .formatter import
|
|
54
|
+
from .formatter import (
|
|
55
|
+
ElementType,
|
|
56
|
+
FormattedElement,
|
|
57
|
+
StreamFormatter,
|
|
58
|
+
format_content,
|
|
59
|
+
strip_untagged_code_fences,
|
|
60
|
+
)
|
|
55
61
|
from .llm import LLMProvider, LLMResult, ProcessMode
|
|
56
62
|
from .parser import (
|
|
57
63
|
InteractionParser,
|
|
@@ -81,6 +87,7 @@ __all__ = [
|
|
|
81
87
|
"FormattedElement",
|
|
82
88
|
"StreamFormatter",
|
|
83
89
|
"format_content",
|
|
90
|
+
"strip_untagged_code_fences",
|
|
84
91
|
# Main utility functions
|
|
85
92
|
"generate_smart_validation_template",
|
|
86
93
|
"extract_interaction_question",
|
|
@@ -88,4 +95,4 @@ __all__ = [
|
|
|
88
95
|
"replace_variables_in_text",
|
|
89
96
|
]
|
|
90
97
|
|
|
91
|
-
__version__ = "0.2.
|
|
98
|
+
__version__ = "0.2.85"
|
|
@@ -5,6 +5,7 @@ Provides content classification and structured output for SSE streams.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from .format import format_content
|
|
8
|
+
from .sanitize import strip_untagged_code_fences
|
|
8
9
|
from .stream import StreamFormatter
|
|
9
10
|
from .types import ClassifyResult, ElementType, FormattedElement
|
|
10
11
|
|
|
@@ -15,4 +16,5 @@ __all__ = [
|
|
|
15
16
|
"ClassifyResult",
|
|
16
17
|
"format_content",
|
|
17
18
|
"StreamFormatter",
|
|
19
|
+
"strip_untagged_code_fences",
|
|
18
20
|
]
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Content Sanitizer
|
|
3
|
+
|
|
4
|
+
Utilities for cleaning LLM-generated content before it is classified and
|
|
5
|
+
rendered.
|
|
6
|
+
|
|
7
|
+
Motivation
|
|
8
|
+
----------
|
|
9
|
+
LLMs intermittently wrap otherwise-renderable output (block-level HTML, SVG
|
|
10
|
+
infographics, plain narrative) in an *untagged* fenced code block, e.g. a bare
|
|
11
|
+
``` line with no info string, sometimes even leaving it unclosed. CommonMark
|
|
12
|
+
faithfully turns that region into a code block, so a renderer shows the raw
|
|
13
|
+
HTML source instead of the intended visual.
|
|
14
|
+
|
|
15
|
+
This module targets that specific artifact while preserving deliberate code
|
|
16
|
+
blocks. It relies on a simple, explicit convention: **source that is meant to
|
|
17
|
+
be displayed as code carries a language tag** (``` ```html ```, ``` ```python ```,
|
|
18
|
+
``` ```mermaid ```). An *untagged* fence therefore carries no "show the source"
|
|
19
|
+
intent and is treated as noise that can be removed so the wrapped content
|
|
20
|
+
renders normally.
|
|
21
|
+
|
|
22
|
+
The transformation is opt-in: callers apply it explicitly to generated content.
|
|
23
|
+
It does not change the behaviour of the classifier or ``format_content``.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from ..parser.code_fence_utils import is_code_fence_end, parse_code_fence_start
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _fence_info_string(fence_line: str, fence_char: str) -> str:
|
|
30
|
+
"""Return the info string (language tag) of a fence opening line."""
|
|
31
|
+
return fence_line.lstrip(" ").lstrip(fence_char).strip()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def strip_untagged_code_fences(content: str) -> str:
|
|
35
|
+
"""Remove untagged (language-less) code-fence markers from ``content``.
|
|
36
|
+
|
|
37
|
+
An untagged fence is a fence opening line whose info string is empty
|
|
38
|
+
(a bare ``` or ~~~ with no language). Such markers are dropped so the text
|
|
39
|
+
they wrapped renders as normal Markdown/HTML instead of code. This handles
|
|
40
|
+
both paired bare fences and a single unclosed/stray bare fence.
|
|
41
|
+
|
|
42
|
+
Language-tagged fences (``` ```html ```, ``` ```mermaid ```, ...) and their
|
|
43
|
+
contents are left untouched, including their bare closing fence line.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
content: Raw content, typically LLM output.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Content with untagged fence markers removed. Everything else, including
|
|
50
|
+
the lines that were inside an untagged fence, is preserved verbatim.
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
>>> strip_untagged_code_fences("```\\n<div>x</div>\\n```")
|
|
54
|
+
'<div>x</div>'
|
|
55
|
+
>>> strip_untagged_code_fences("```html\\n<div>x</div>\\n```")
|
|
56
|
+
'```html\\n<div>x</div>\\n```'
|
|
57
|
+
"""
|
|
58
|
+
if not content or ("```" not in content and "~~~" not in content):
|
|
59
|
+
return content
|
|
60
|
+
|
|
61
|
+
lines = content.split("\n")
|
|
62
|
+
result: list[str] = []
|
|
63
|
+
|
|
64
|
+
# When inside a language-tagged fence we copy lines verbatim until the
|
|
65
|
+
# matching closing fence, so nested bare backticks and the closing fence
|
|
66
|
+
# itself are preserved.
|
|
67
|
+
inside_tagged_fence = False
|
|
68
|
+
open_fence = None
|
|
69
|
+
|
|
70
|
+
for line in lines:
|
|
71
|
+
if inside_tagged_fence:
|
|
72
|
+
result.append(line)
|
|
73
|
+
if open_fence is not None and is_code_fence_end(line, open_fence):
|
|
74
|
+
inside_tagged_fence = False
|
|
75
|
+
open_fence = None
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
fence = parse_code_fence_start(line)
|
|
79
|
+
if fence is None:
|
|
80
|
+
result.append(line)
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
info = _fence_info_string(fence.line, fence.char)
|
|
84
|
+
if info == "":
|
|
85
|
+
# Untagged fence at the top level: drop the marker line, keep the
|
|
86
|
+
# content it wrapped. Paired and unclosed bare fences both collapse
|
|
87
|
+
# here because we never enter a fenced state for them.
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
# Language-tagged fence: keep it and preserve everything up to its close.
|
|
91
|
+
result.append(line)
|
|
92
|
+
inside_tagged_fence = True
|
|
93
|
+
open_fence = fence
|
|
94
|
+
|
|
95
|
+
return "\n".join(result)
|
|
@@ -138,5 +138,5 @@ Amount of modification < 50% -> Diff; >= 50% -> create a new screen.
|
|
|
138
138
|
13. Output HTML as plain text. **Do not** use ```html or any code block marker. Do not output like this:
|
|
139
139
|
|
|
140
140
|
```html
|
|
141
|
-
|
|
141
|
+
html code here
|
|
142
142
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.85
|
|
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
|
|
@@ -20,6 +20,7 @@ markdown_flow/formatter/__init__.py
|
|
|
20
20
|
markdown_flow/formatter/classifier.py
|
|
21
21
|
markdown_flow/formatter/format.py
|
|
22
22
|
markdown_flow/formatter/patterns.py
|
|
23
|
+
markdown_flow/formatter/sanitize.py
|
|
23
24
|
markdown_flow/formatter/stream.py
|
|
24
25
|
markdown_flow/formatter/types.py
|
|
25
26
|
markdown_flow/parser/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|