diff --git a/CHANGELOG.md b/CHANGELOG.md index cdfb6504..9a8f1b2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html), with the exception that 0.x versions can break between minor versions. +## [Unreleased] +### Fixed +- A single pipe (optional whitespace) now ends a table instead of crashing or + being treated as an empty row, for consistency with GitHub (#255). + ## [0.19.0] - 2022-06-02 ### Added - YAML front matter extension: Limited support for single and double @@ -362,6 +367,7 @@ Initial release of commonmark-java, a port of commonmark.js with extensions for autolinking URLs, GitHub flavored strikethrough and tables. +[Unreleased]: https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.19.0...HEAD [0.19.0]: https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.18.2...commonmark-parent-0.19.0 [0.18.2]: https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.18.1...commonmark-parent-0.18.2 [0.18.1]: https://github.com/commonmark/commonmark-java/compare/commonmark-parent-0.18.0...commonmark-parent-0.18.1 diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableBlockParser.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableBlockParser.java index a203164d..b7cea14d 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableBlockParser.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableBlockParser.java @@ -19,6 +19,8 @@ public class TableBlockParser extends AbstractBlockParser { private final List rowLines = new ArrayList<>(); private final List columns; + private boolean canHaveLazyContinuationLines = true; + private TableBlockParser(List columns, SourceLine headerLine) { this.columns = columns; this.rowLines.add(headerLine); @@ -26,7 +28,7 @@ private TableBlockParser(List columns, SourceLine headerLin @Override public boolean canHaveLazyContinuationLines() { - return true; + return canHaveLazyContinuationLines; } @Override @@ -36,7 +38,17 @@ public Block getBlock() { @Override public BlockContinue tryContinue(ParserState state) { - if (Parsing.find('|', state.getLine().getContent(), 0) != -1) { + CharSequence content = state.getLine().getContent(); + int pipe = Parsing.find('|', content, state.getNextNonSpaceIndex()); + if (pipe != -1) { + if (pipe == state.getNextNonSpaceIndex()) { + // If we *only* have a pipe character (and whitespace), that is not a valid table row and ends the table. + if (Parsing.skipSpaceTab(content, pipe + 1, content.length()) == content.length()) { + // We also don't want the pipe to be added via lazy continuation. + canHaveLazyContinuationLines = false; + return BlockContinue.none(); + } + } return BlockContinue.atIndex(state.getIndex()); } else { return BlockContinue.none(); @@ -128,7 +140,7 @@ private static List split(SourceLine line) { // This row has leading/trailing pipes - skip the leading pipe cellStart = nonSpace + 1; // Strip whitespace from the end but not the pipe or we could miss an empty ("||") cell - int nonSpaceEnd = Parsing.skipSpaceTabBackwards(row, row.length() - 1, cellStart + 1); + int nonSpaceEnd = Parsing.skipSpaceTabBackwards(row, row.length() - 1, cellStart); cellEnd = nonSpaceEnd + 1; } List cells = new ArrayList<>(); diff --git a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTest.java b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTest.java index 4d515321..bef3b8b6 100644 --- a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTest.java +++ b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTest.java @@ -261,21 +261,21 @@ public void pipesOnOutsideZeroLengthHeaders() { "-|-------------|-\n" + "1| 2 |3", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
center header
123
\n"); + "\n" + + "\n" + + "\n" + + "center header\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "1\n" + + "2\n" + + "3\n" + + "\n" + + "\n" + + "\n"); } @Test @@ -664,6 +664,47 @@ public void issue142() { "\n"); } + @Test + public void danglingPipe() { + assertRendering("Abc|Def\n" + + "---|---\n" + + "1|2\n" + + "|", "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n" + + "

|

\n"); + + assertRendering("Abc|Def\n" + + "---|---\n" + + "1|2\n" + + " | ", "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n" + + "

|

\n"); + } + @Test public void attributeProviderIsApplied() { AttributeProviderFactory factory = new AttributeProviderFactory() { @@ -718,7 +759,7 @@ public void sourceSpans() { TableBlock block = (TableBlock) document.getFirstChild(); assertEquals(Arrays.asList(SourceSpan.of(0, 0, 7), SourceSpan.of(1, 0, 7), - SourceSpan.of(2, 0, 4), SourceSpan.of(3, 0, 8), SourceSpan.of(4, 0, 3)), + SourceSpan.of(2, 0, 4), SourceSpan.of(3, 0, 8), SourceSpan.of(4, 0, 3)), block.getSourceSpans()); TableHead head = (TableHead) block.getFirstChild();