mirror of
https://github.com/ZhuLinsen/daily_stock_analysis
synced 2026-09-20 10:53:33 +08:00
fix: preserve empty markdown table cells (#1806)
This commit is contained in:
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- [修复] 修复通知 Markdown 表格转换在空单元格后将后续内容错配到错误表头的问题。
|
||||
- [修复] 将 Docker 可安装的 Longbridge SDK 版本固定为 0.2.75,避免 `longbridge>=0.2.77` 从包索引消失后导致 docker-build 失败。
|
||||
|
||||
- [改进] Web 设置页新增首次启动配置检查卡,串联基础配置状态、自选股入口、模型配置入口和一次简短试跑。
|
||||
|
||||
@@ -458,8 +458,12 @@ def _is_markdown_table_separator(row: str) -> bool:
|
||||
|
||||
|
||||
def _parse_markdown_table_row(row: str) -> List[str]:
|
||||
cells = [c.strip() for c in row.strip().strip('|').split('|')]
|
||||
return [c for c in cells if c]
|
||||
stripped = row.strip()
|
||||
if stripped.startswith('|'):
|
||||
stripped = stripped[1:]
|
||||
if stripped.endswith('|'):
|
||||
stripped = stripped[:-1]
|
||||
return [c.strip() for c in stripped.split('|')]
|
||||
|
||||
|
||||
def _strip_inline_markdown(text: str) -> str:
|
||||
@@ -500,6 +504,8 @@ def _flush_table_as_key_value_rows(buffer: List[str], output: List[str], *, bull
|
||||
header = rows[0]
|
||||
data_rows = rows[1:] if len(rows) > 1 else []
|
||||
for row in data_rows:
|
||||
if len(row) < len(header):
|
||||
row = row + [""] * (len(header) - len(row))
|
||||
if len(header) == 2 and len(row) >= 2:
|
||||
output.append(f"{bullet} {_format_two_column_table_row(header, row)}")
|
||||
continue
|
||||
@@ -772,8 +778,7 @@ def format_feishu_markdown(content: str) -> str:
|
||||
|
||||
def _parse_row(row: str) -> List[str]:
|
||||
"""解析表格行,提取单元格"""
|
||||
cells = [c.strip() for c in row.strip().strip('|').split('|')]
|
||||
return [c for c in cells if c]
|
||||
return _parse_markdown_table_row(row)
|
||||
|
||||
rows = []
|
||||
for raw in buffer:
|
||||
@@ -790,6 +795,8 @@ def format_feishu_markdown(content: str) -> str:
|
||||
header = rows[0]
|
||||
data_rows = rows[1:] if len(rows) > 1 else []
|
||||
for row in data_rows:
|
||||
if len(row) < len(header):
|
||||
row = row + [""] * (len(header) - len(row))
|
||||
pairs = []
|
||||
for idx, cell in enumerate(row):
|
||||
key = header[idx] if idx < len(header) else f"列{idx + 1}"
|
||||
|
||||
@@ -342,6 +342,21 @@ class TestNotificationMarkdownFormatters(unittest.TestCase):
|
||||
self.assertNotIn("价格指标:MA5", result)
|
||||
self.assertNotIn("类型:N/A", result)
|
||||
|
||||
def test_markdown_tables_to_key_value_rows_preserves_empty_cells(self):
|
||||
text = (
|
||||
"| Header1 | Header2 | Header3 |\n"
|
||||
"|---------|---------|---------|\n"
|
||||
"| Value1 | | Value3 |\n"
|
||||
"| Tail1 | Tail2 | |"
|
||||
)
|
||||
colon = "\uff1a"
|
||||
|
||||
result = markdown_tables_to_key_value_rows(text)
|
||||
|
||||
self.assertIn(f"Header1{colon}Value1 | Header2{colon} | Header3{colon}Value3", result)
|
||||
self.assertIn(f"Header1{colon}Tail1 | Header2{colon}Tail2 | Header3{colon}", result)
|
||||
self.assertNotIn(f"Header2{colon}Value3", result)
|
||||
|
||||
def test_markdown_tables_to_key_value_rows_keeps_fenced_code_tables(self):
|
||||
text = (
|
||||
"```markdown\n"
|
||||
@@ -372,6 +387,19 @@ class TestNotificationMarkdownFormatters(unittest.TestCase):
|
||||
self.assertIn("• 股票:600519 | 信号:强势", result)
|
||||
self.assertIn("• 关注量能", result)
|
||||
|
||||
def test_feishu_formatter_preserves_empty_table_cells(self):
|
||||
text = (
|
||||
"| Header1 | Header2 | Header3 |\n"
|
||||
"|---------|---------|---------|\n"
|
||||
"| Value1 | | Value3 |"
|
||||
)
|
||||
colon = "\uff1a"
|
||||
|
||||
result = format_feishu_markdown(text)
|
||||
|
||||
self.assertIn(f"Header1{colon}Value1 | Header2{colon} | Header3{colon}Value3", result)
|
||||
self.assertNotIn(f"Header2{colon}Value3", result)
|
||||
|
||||
def test_telegram_formatter_uses_supported_markdown(self):
|
||||
text = "## 日报\n\n| 股票 | 信号 |\n| --- | --- |\n| 600519 | 强势 |\n\n[详情](https://example.com/report)"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user