fix(export): escape backslashes in tag table cells
A backslash right before a pipe, as in the tag name a\|b, turned the escaped pipe into "\|": the table splitter reads "\\" as an escaped backslash and the pipe as a column separator, shifting the row. Cells now escape '\' before '|'. Recorded in PLAN 5.8.
This commit is contained in:
1 parent
b6e8e07d78
commit
9277e2a331
3 files changed
+29
-4
No files matched your search
@@ -204,6 +204,29 @@ public class MarkdownExporterTests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TagTableCellsEscapeBackslashesSoAPipeAfterOneStaysEscaped()
|
||||
{
|
||||
CultureInfo? original = Resources.Culture;
|
||||
try
|
||||
{
|
||||
Resources.Culture = new CultureInfo("en");
|
||||
var tag = new TagModel(1, @"a\|b", RgbColor.Parse("#112233"), @"C:\temp\");
|
||||
string markdown = MarkdownExporter.Export(
|
||||
"W",
|
||||
[new ColumnModel(1, "C", string.Empty, 1, 1)],
|
||||
[],
|
||||
[(tag, 0L)],
|
||||
ExportedAt);
|
||||
|
||||
StringAssert.Contains(markdown, @"| a\\\|b | #112233 | C:\\temp\\ | 0 |");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Resources.Culture = original;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow("plain", "`plain`")]
|
||||
[DataRow("a`b", "``a`b``")]
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace YKanBan.Export;
|
||||
/// uses that one per-language pattern. The whole document uses LF line endings
|
||||
/// on every platform. Card bodies and column descriptions are emitted verbatim
|
||||
/// apart from line endings; column and card titles are collapsed to one line;
|
||||
/// tag names become inline code with a long enough backtick fence; tag table cells escape '|' and turn line breaks into <br>. The
|
||||
/// tag names become inline code with a long enough backtick fence; tag table cells escape '\' and '|' and turn line breaks into <br>. The
|
||||
/// output is meant for reading only — there is no re-import.
|
||||
/// </summary>
|
||||
public static class MarkdownExporter
|
||||
@@ -130,12 +130,14 @@ public static class MarkdownExporter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a table cell: escaped pipe characters, line breaks as <br>.
|
||||
/// Formats a table cell: escaped backslashes and pipe characters, line breaks as <br>.
|
||||
/// </summary>
|
||||
/// <param name="text">The raw cell text.</param>
|
||||
/// <returns>The escaped single-line text.</returns>
|
||||
private static string Cell(string text) =>
|
||||
text.Replace("|", "\\|").Replace("\r\n", "<br>").Replace("\r", "<br>").Replace("\n", "<br>");
|
||||
// Backslashes first: the table splitter reads "\\" as an escaped backslash, so the
|
||||
// '|' after a literal backslash would otherwise end the cell.
|
||||
text.Replace("\\", "\\\\").Replace("|", "\\|").Replace("\r\n", "<br>").Replace("\r", "<br>").Replace("\n", "<br>");
|
||||
|
||||
/// <summary>
|
||||
/// Renders text as an inline code span whose backtick fence is one longer than
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ card_tags: (card_id, tag_id) 复合主键,双向 ON DELETE CASCADE
|
||||
- 空列也保留(体现看板结构);无标题卡片以 `### #61` 呈现
|
||||
- 转义规则:
|
||||
- 标签名以行内代码呈现,定界反引号数量 = 名称内最长连续反引号串长度 + 1(名称以反引号开头/结尾时两侧加空格)
|
||||
- 标签总表单元格内 `|` → `\|`,换行 → `<br>`
|
||||
- 标签总表单元格内 `\` → `\\`(先于 `|` 处理,否则 `a\|b` 中的 `|` 会被当成列分隔符),`|` → `\|`,换行 → `<br>`
|
||||
- 卡片正文与列 description **原样输出**(接受其中 Markdown 结构干扰文档层级,已接受)
|
||||
|
||||
### 5.9 主题(亮 / 暗 / 跟随系统)
|
||||
|
||||
Reference in new issue
Block a user