diff --git a/CHANGES.md b/CHANGES.md index 8f027a0e..4e67d00a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## python-markdown2 2.5.6 (not yet released) +- [pull #725] Fix `tables` extra dropping escaped pipes at the end of header and body rows. - [pull #687] Fix AssertionError hashing HTML blocks spread over multiple lines (#686) - [pull #692] Fix XSS from code spans in link titles (#691) - [pull #695] Fix XSS issue from incomplete tags with no attributes (#694) diff --git a/lib/markdown2.py b/lib/markdown2.py index d8a00942..c6596cdf 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -4243,7 +4243,10 @@ def run(self, text: str): @staticmethod def _split_row(row: str) -> list[str]: - row = row.strip().removeprefix('|').removesuffix('|') + row = row.strip().removeprefix('|') + # An escaped final pipe belongs to the last cell, not the table border. + if not row.endswith(r'\|'): + row = row.removesuffix('|') return [ re.sub(r'\\\|', '|', cell.strip()) for cell in re.split(r'(? + + + Name + Operator | + + + + + or + | + + + suffix + value| + + + repeated + || + + + emphasis + value| + + + + + + + + + + + + + + + + + + + + + +
NameOperator |
or|
suffixvalue|
+ + + + + + + + + + + + + + + + + + + + + + +
NameOperator |
or|
suffixvalue|
empty
diff --git a/test/tm-cases/tables_escaped_trailing_pipe.opts b/test/tm-cases/tables_escaped_trailing_pipe.opts new file mode 100644 index 00000000..23983798 --- /dev/null +++ b/test/tm-cases/tables_escaped_trailing_pipe.opts @@ -0,0 +1 @@ +{"extras": ["tables"]} diff --git a/test/tm-cases/tables_escaped_trailing_pipe.text b/test/tm-cases/tables_escaped_trailing_pipe.text new file mode 100644 index 00000000..9610dbb7 --- /dev/null +++ b/test/tm-cases/tables_escaped_trailing_pipe.text @@ -0,0 +1,17 @@ +Name | Operator \| +--- | ---: +or | \| +suffix | value\| +repeated | \|\| +emphasis | **value**\| + +| Name | Operator \| +| --- | --- | +| or | \| +| suffix | value\| + +| Name | Operator \|| +| --- | --- | +| or | \|| +| suffix | value\| | +| empty | |