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.
Files changed (39) hide show
  1. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/PKG-INFO +1 -1
  2. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/__init__.py +9 -2
  3. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/__init__.py +2 -0
  4. markdown_flow-0.2.85/markdown_flow/formatter/sanitize.py +95 -0
  5. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/system_prompt.md +1 -1
  6. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/PKG-INFO +1 -1
  7. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/SOURCES.txt +1 -0
  8. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/LICENSE +0 -0
  9. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/README.md +0 -0
  10. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/constants.py +0 -0
  11. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/constants_system_prompt.py +0 -0
  12. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/core.py +0 -0
  13. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/enums.py +0 -0
  14. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/exceptions.py +0 -0
  15. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/classifier.py +0 -0
  16. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/format.py +0 -0
  17. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/patterns.py +0 -0
  18. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/stream.py +0 -0
  19. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/formatter/types.py +0 -0
  20. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/llm.py +0 -0
  21. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/models.py +0 -0
  22. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/__init__.py +0 -0
  23. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/code_fence_utils.py +0 -0
  24. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/html_comment_utils.py +0 -0
  25. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/interaction.py +0 -0
  26. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/json_parser.py +0 -0
  27. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/output.py +0 -0
  28. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/preprocessor.py +0 -0
  29. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/validation.py +0 -0
  30. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/parser/variable.py +0 -0
  31. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/__init__.py +0 -0
  32. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/config.py +0 -0
  33. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/providers/openai.py +0 -0
  34. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/tag_filter.py +0 -0
  35. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow/utils.py +0 -0
  36. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/dependency_links.txt +0 -0
  37. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/markdown_flow.egg-info/top_level.txt +0 -0
  38. {markdown_flow-0.2.84 → markdown_flow-0.2.85}/pyproject.toml +0 -0
  39. {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.84
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 ElementType, FormattedElement, StreamFormatter, format_content
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.84"
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
- <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)">
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.84
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