slack-markdown-parser 2.5.0__tar.gz → 2.5.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.
Files changed (18) hide show
  1. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/CHANGELOG.md +6 -0
  2. {slack_markdown_parser-2.5.0/slack_markdown_parser.egg-info → slack_markdown_parser-2.5.1}/PKG-INFO +1 -1
  3. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/docs/spec-ja.md +1 -0
  4. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/docs/spec.md +1 -0
  5. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/pyproject.toml +1 -1
  6. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser/__init__.py +1 -1
  7. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser/converter.py +30 -11
  8. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1/slack_markdown_parser.egg-info}/PKG-INFO +1 -1
  9. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/LICENSE +0 -0
  10. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/MANIFEST.in +0 -0
  11. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/README-ja.md +0 -0
  12. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/README.md +0 -0
  13. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/setup.cfg +0 -0
  14. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser/py.typed +0 -0
  15. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser.egg-info/SOURCES.txt +0 -0
  16. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser.egg-info/dependency_links.txt +0 -0
  17. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser.egg-info/requires.txt +0 -0
  18. {slack_markdown_parser-2.5.0 → slack_markdown_parser-2.5.1}/slack_markdown_parser.egg-info/top_level.txt +0 -0
@@ -6,6 +6,12 @@ The format is based on Keep a Changelog, and the project follows Semantic Versio
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.5.1] - 2026-06-11
10
+
11
+ ### Fixed
12
+
13
+ - Stopped a lone `<` in a table cell from swallowing later cell separators. The cell splitter tracked angle brackets with a stateful flag that any `<` turned on and only a `>` turned off, so a bare `<` with no closing `>` on the same line — a comparison like `x < y` or a threshold like `< 100ms`, both common in LLM-generated tables — silently merged the remaining cells into one, shifted the columns, and filled the lost trailing cell with `-`. Pipes are now protected only inside valid Slack angle tokens (links, mentions, `<!date^...>`), which are consumed whole; a bare `<` stays literal. The heading+table-row splitter shares the same scan, so a `# Heading |a|b|` line now also splits when the heading contains a lone `<`, and standalone `parse_markdown_table` / `normalize_markdown_tables` now match the sanitized pipeline's behavior.
14
+
9
15
  ## [2.5.0] - 2026-06-11
10
16
 
11
17
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slack-markdown-parser
3
- Version: 2.5.0
3
+ Version: 2.5.1
4
4
  Summary: Convert LLM Markdown into Slack Block Kit messages
5
5
  Author: darkgaldragon
6
6
  License-Expression: MIT
@@ -138,6 +138,7 @@ LLM は外枠パイプの省略、区切り行の欠落、列数の不一致な
138
138
  - Slack リンク `<url|text>` 内のパイプはセル区切りとして扱わない
139
139
  - インラインコード `` `...` `` 内のパイプもセル区切りとして扱わない
140
140
  - エスケープされたパイプ `\|` はセル区切りとして扱わず、表示時にバックスラッシュを除去して `|` として出力する
141
+ - パイプ保護領域を開くのは有効な Slack 角括弧トークン(リンク・メンション・`<!date^...>`)のみ。`x < y` の比較演算子や `< 100ms` のような閾値表記の裸の `<` はリテラルのまま扱われ、後続のセル区切りを飲み込まない
141
142
 
142
143
  ## テーブルセル装飾
143
144
 
@@ -138,6 +138,7 @@ LLMs often emit tables with omitted outer pipes, missing separator rows, or inco
138
138
  - Treat pipes inside Slack links such as `<url|text>` as literal content, not as cell separators
139
139
  - Treat pipes inside inline code `` `...` `` as literal content, not as cell separators
140
140
  - Treat escaped pipes `\|` as literal content and remove the backslash in the final displayed text
141
+ - Only valid Slack angle tokens (links, mentions, `<!date^...>`) open a pipe-protected region; a bare `<` — such as the comparison in `x < y` or a threshold like `< 100ms` — stays literal and does not swallow later cell separators
141
142
 
142
143
  ## Table cell styling
143
144
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "slack-markdown-parser"
7
- version = "2.5.0"
7
+ version = "2.5.1"
8
8
  description = "Convert LLM Markdown into Slack Block Kit messages"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  """slack-markdown-parser public package API."""
2
2
 
3
- __version__ = "2.5.0"
3
+ __version__ = "2.5.1"
4
4
  __license__ = "MIT"
5
5
 
6
6
  from .converter import (
@@ -1193,8 +1193,26 @@ def _format_markdown_with_spacing_metadata(text: str) -> tuple[str, list[int]]:
1193
1193
  add_zero_width_spaces = add_zero_width_spaces_to_markdown
1194
1194
 
1195
1195
 
1196
+ def _match_slack_angle_token_end(text: str, start: int) -> int | None:
1197
+ """Return the end index (exclusive) of a valid Slack angle token at ``start``.
1198
+
1199
+ Only recognized Slack tokens (links, mentions, ``<!date^…>``) protect
1200
+ their inner pipes from cell splitting. A bare ``<`` — e.g. the comparison
1201
+ in ``x < y`` — is literal text and must not open a protected region;
1202
+ a stateful "inside angle brackets" flag did exactly that, so one lone
1203
+ ``<`` swallowed every later pipe on the line into a single cell.
1204
+ """
1205
+ if start >= len(text) or text[start] != "<":
1206
+ return None
1207
+ closing = text.find(">", start + 1)
1208
+ if closing == -1:
1209
+ return None
1210
+ token = text[start : closing + 1]
1211
+ return closing + 1 if _is_allowed_slack_angle_token(token) else None
1212
+
1213
+
1196
1214
  def _split_markdown_table_cells(line: str) -> list[str]:
1197
- """Split markdown table cells while preserving pipes inside <...|...> links."""
1215
+ """Split markdown table cells while preserving pipes inside Slack tokens."""
1198
1216
  working = line.strip()
1199
1217
  if not working:
1200
1218
  return []
@@ -1206,7 +1224,6 @@ def _split_markdown_table_cells(line: str) -> list[str]:
1206
1224
 
1207
1225
  cells: list[str] = []
1208
1226
  current: list[str] = []
1209
- in_angle = False
1210
1227
  escaped = False
1211
1228
  cursor = 0
1212
1229
 
@@ -1232,11 +1249,13 @@ def _split_markdown_table_cells(line: str) -> list[str]:
1232
1249
  continue
1233
1250
 
1234
1251
  if ch == "<":
1235
- in_angle = True
1236
- elif ch == ">" and in_angle:
1237
- in_angle = False
1252
+ token_end = _match_slack_angle_token_end(working, cursor)
1253
+ if token_end is not None:
1254
+ current.append(working[cursor:token_end])
1255
+ cursor = token_end
1256
+ continue
1238
1257
 
1239
- if ch == "|" and not in_angle:
1258
+ if ch == "|":
1240
1259
  cells.append("".join(current).strip())
1241
1260
  current = []
1242
1261
  cursor += 1
@@ -1281,7 +1300,6 @@ def _split_heading_and_table_row(
1281
1300
  if "|" not in line:
1282
1301
  return None
1283
1302
 
1284
- in_angle = False
1285
1303
  escaped = False
1286
1304
  first_pipe = -1
1287
1305
  cursor = 0
@@ -1301,10 +1319,11 @@ def _split_heading_and_table_row(
1301
1319
  cursor = code_span_end
1302
1320
  continue
1303
1321
  if ch == "<":
1304
- in_angle = True
1305
- elif ch == ">" and in_angle:
1306
- in_angle = False
1307
- elif ch == "|" and not in_angle:
1322
+ token_end = _match_slack_angle_token_end(line, cursor)
1323
+ if token_end is not None:
1324
+ cursor = token_end
1325
+ continue
1326
+ if ch == "|":
1308
1327
  first_pipe = cursor
1309
1328
  break
1310
1329
  cursor += 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slack-markdown-parser
3
- Version: 2.5.0
3
+ Version: 2.5.1
4
4
  Summary: Convert LLM Markdown into Slack Block Kit messages
5
5
  Author: darkgaldragon
6
6
  License-Expression: MIT