Skip to content

Commit 7f698be

Browse files
committed
fix: escape pipe chars in markdown table cells for extra field values (fixes #832)
1 parent 4c37bae commit 7f698be

3 files changed

Lines changed: 43 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
### Fixed
11+
- Fix markdown export breaking table structure when extra field values contain pipe characters (#832)
12+
1013
## [0.11.6] - 2026-03-17
1114

1215
### Fixed

datacontract/export/markdown_exporter.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,20 @@ def render_header(key: str) -> str:
366366

367367
if isinstance(value_extra, list) and len(value_extra):
368368
if isinstance(value_extra[0], dict):
369-
parts.append(array_of_dict_to_markdown(value_extra))
369+
raw = array_of_dict_to_markdown(value_extra)
370+
if is_in_table_cell:
371+
raw = raw.replace("|", "&#124;").replace("\n", "<br />")
372+
parts.append(raw)
370373
elif isinstance(value_extra[0], str):
371-
parts.append(array_to_markdown(value_extra))
374+
raw = array_to_markdown(value_extra)
375+
if is_in_table_cell:
376+
raw = raw.replace("\n", "<br />")
377+
parts.append(raw)
372378
elif isinstance(value_extra, dict):
373-
parts.append(dict_to_markdown(value_extra))
379+
raw = dict_to_markdown(value_extra)
380+
if is_in_table_cell:
381+
raw = raw.replace("\n", "<br />")
382+
parts.append(raw)
374383
else:
375384
parts.append(f"{str(value_extra)}{value_line_ending}")
376385

tests/test_export_markdown.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,31 @@ def test_to_markdown():
3030

3131
with open("fixtures/markdown/export/expected.md", "r") as file:
3232
assert result == file.read()
33+
34+
35+
def test_pipe_chars_escaped_in_table_cells():
36+
"""Regression test for #832: pipe chars in extra field values should be escaped when inside table cells."""
37+
from open_data_contract_standard.model import OpenDataContractStandard
38+
import yaml
39+
40+
contract_yaml = """
41+
id: test-pipe-escape
42+
schema:
43+
- name: orders
44+
properties:
45+
- name: order_id
46+
logicalType: string
47+
config:
48+
mapping: "a | b | c"
49+
"""
50+
contract = OpenDataContractStandard.model_validate(yaml.safe_load(contract_yaml))
51+
result = to_markdown(contract)
52+
53+
# Find the table row for order_id
54+
lines = [line for line in result.split("\n") if "order_id" in line and line.startswith("|")]
55+
assert lines, "order_id table row not found"
56+
row = lines[0]
57+
# The row must have exactly 4 pipe chars as table delimiters (| col1 | col2 | col3 |)
58+
assert row.count("|") == 4, (
59+
f"Expected 4 pipe delimiters in row, got {row.count('|')}: {row!r}"
60+
)

0 commit comments

Comments
 (0)