chatgpt-md-converter 0.3.9__py3-none-any.whl → 0.3.10__py3-none-any.whl

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.
@@ -35,30 +35,91 @@ def render_node(node: Node, state: RenderState) -> str:
35
35
  return render_nodes(node.children, state)
36
36
 
37
37
 
38
+ def _split_surrounding_whitespace(text: str) -> tuple[str, str, str]:
39
+ """Return leading whitespace, core text, and trailing whitespace."""
40
+
41
+ start = 0
42
+ end = len(text)
43
+
44
+ while start < end and text[start].isspace():
45
+ start += 1
46
+
47
+ while end > start and text[end - 1].isspace():
48
+ end -= 1
49
+
50
+ return text[:start], text[start:end], text[end:]
51
+
52
+
53
+ def _italic_boundary_conflict(marker: str, core: str) -> bool:
54
+ if marker == "*":
55
+ return core.startswith("*") or core.endswith("*")
56
+
57
+ if marker == "_":
58
+ starts = core.startswith("_")
59
+ if starts and len(core) > 1 and core[1] == "_":
60
+ starts = False
61
+
62
+ ends = core.endswith("_")
63
+ if ends and len(core) > 1 and core[-2] == "_":
64
+ ends = False
65
+
66
+ return starts or ends
67
+
68
+ return False
69
+
70
+
71
+ def _choose_italic_marker(state: RenderState, core: str) -> str:
72
+ depth = state.italic_depth
73
+
74
+ if state.bold_depth > 0 and depth == 0:
75
+ candidates = ["_", "*"]
76
+ elif depth % 2 == 0:
77
+ candidates = ["*", "_"]
78
+ else:
79
+ candidates = ["_", "*"]
80
+
81
+ for marker in candidates:
82
+ if not _italic_boundary_conflict(marker, core):
83
+ return marker
84
+
85
+ return candidates[0]
86
+
87
+
38
88
  def _handle_bold(node: Node, state: RenderState) -> str:
39
89
  inner_state = state.child(bold_depth=state.bold_depth + 1)
40
90
  inner = render_nodes(node.children, inner_state)
41
- return f"**{inner}**"
91
+ leading, core, trailing = _split_surrounding_whitespace(inner)
92
+ if not core:
93
+ return leading + trailing
94
+ return f"{leading}**{core}**{trailing}"
42
95
 
43
96
 
44
97
  def _handle_italic(node: Node, state: RenderState) -> str:
45
98
  depth = state.italic_depth
46
- in_bold = state.bold_depth > 0 and depth == 0
47
- marker = "_" if in_bold else ("*" if depth % 2 == 0 else "_")
48
99
  inner_state = state.child(italic_depth=depth + 1)
49
100
  inner = render_nodes(node.children, inner_state)
50
- return f"{marker}{inner}{marker}"
101
+ leading, core, trailing = _split_surrounding_whitespace(inner)
102
+ if not core:
103
+ return leading + trailing
104
+ marker = _choose_italic_marker(state, core)
105
+ return f"{leading}{marker}{core}{marker}{trailing}"
51
106
 
52
107
 
53
108
  def _handle_inline_marker(node: Node, state: RenderState) -> str:
54
109
  marker_open, marker_close = _INLINE_MARKERS[node.tag.lower()]
55
110
  inner = render_nodes(node.children, state)
56
- return f"{marker_open}{inner}{marker_close}"
111
+ leading, core, trailing = _split_surrounding_whitespace(inner)
112
+ if not core:
113
+ return leading + trailing
114
+ return f"{leading}{marker_open}{core}{marker_close}{trailing}"
57
115
 
58
116
 
59
117
  def _handle_spoiler(node: Node, state: RenderState) -> str:
60
118
  inner = render_nodes(node.children, state)
61
- return f"||{inner}||"
119
+ leading, core, trailing = _split_surrounding_whitespace(inner)
120
+ if not core:
121
+ return leading + trailing
122
+ return f"{leading}||{core}||{trailing}"
62
123
 
63
124
 
64
125
  def _handle_code(node: Node, state: RenderState) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatgpt_md_converter
3
- Version: 0.3.9
3
+ Version: 0.3.10
4
4
  Summary: A package for converting markdown to HTML for chat Telegram bots
5
5
  Home-page: https://github.com/botfather-dev/formatter-chatgpt-telegram
6
6
  Author: Kostiantyn Kriuchkov
@@ -3,7 +3,7 @@ chatgpt_md_converter/html_splitter.py,sha256=DdjJx0I-A9rZHOxS-0LXsy7YUrgrkrtdeqZ
3
3
  chatgpt_md_converter/html_to_markdown.py,sha256=XlLpQD7W_AooWrvTtvrGVwfPPa80tDKWuT1iT6Vzygw,174
4
4
  chatgpt_md_converter/telegram_formatter.py,sha256=w3tjoSdRH_UdoFmGeXe7I47dhDIceXuGOA1oCLMnUmM,87
5
5
  chatgpt_md_converter/html_markdown/escaping.py,sha256=wJA4vUJQVcxpkJ4sCIYIWKaqffb_O72R93H81hTgTxA,1808
6
- chatgpt_md_converter/html_markdown/handlers.py,sha256=dJw-IuvFG7eeTVclx9QOS2NEvqlF2K7i3MJ_llt1YYc,4939
6
+ chatgpt_md_converter/html_markdown/handlers.py,sha256=A0QjL8eZTnlVupEQH3Ped9Ek81KLKS7cp4BdD-0R3tI,6653
7
7
  chatgpt_md_converter/html_markdown/renderer.py,sha256=en-fAr3Bhmm4ZndDaPKV8nLVQ_7HpS_NFBSWcrQporY,438
8
8
  chatgpt_md_converter/html_markdown/state.py,sha256=sxbz0ucCakI0KgR86EMZx0nvfU1oiqgVUofujFTeKoo,432
9
9
  chatgpt_md_converter/html_markdown/tree.py,sha256=ryohrhO2X5QepZev3087qPoGmMznqHDwH00TNGoW6a4,2154
@@ -13,8 +13,8 @@ chatgpt_md_converter/telegram_markdown/inline.py,sha256=Phe4T5tu7Y7drH17YW-iOVEq
13
13
  chatgpt_md_converter/telegram_markdown/postprocess.py,sha256=jUf01tAIqHQ1NxNlVGsvU-Yw8SDOHtMoS7MUzaQLf_8,775
14
14
  chatgpt_md_converter/telegram_markdown/preprocess.py,sha256=c9Wzs7DUumXgrgndCeHbCfV1qLzXVJlLHOtXC3Ne2Nk,1362
15
15
  chatgpt_md_converter/telegram_markdown/renderer.py,sha256=ZX0reJLVC_2Fvw26dnSSpK_xr_Kpfp9oTyQw57FCqu0,1957
16
- chatgpt_md_converter-0.3.9.dist-info/licenses/LICENSE,sha256=SDr2jeP-s2g4vf17-jdLXrrqA4_mU7L_RtSJlv4Y2mk,1077
17
- chatgpt_md_converter-0.3.9.dist-info/METADATA,sha256=P5508ZIm4iTdBtFpA03j5CDy3E7iXEVnx2tkWSZMGbc,6604
18
- chatgpt_md_converter-0.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- chatgpt_md_converter-0.3.9.dist-info/top_level.txt,sha256=T2o7csVtZgr-Pwm83aSUkZn0humJmDFNqW38tRSsNqw,21
20
- chatgpt_md_converter-0.3.9.dist-info/RECORD,,
16
+ chatgpt_md_converter-0.3.10.dist-info/licenses/LICENSE,sha256=SDr2jeP-s2g4vf17-jdLXrrqA4_mU7L_RtSJlv4Y2mk,1077
17
+ chatgpt_md_converter-0.3.10.dist-info/METADATA,sha256=iJ5mg4yzhbKVF9mqmCm7IW3yjFtcijvkMcUbCKtVYsE,6605
18
+ chatgpt_md_converter-0.3.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ chatgpt_md_converter-0.3.10.dist-info/top_level.txt,sha256=T2o7csVtZgr-Pwm83aSUkZn0humJmDFNqW38tRSsNqw,21
20
+ chatgpt_md_converter-0.3.10.dist-info/RECORD,,