From f5b04efdae2c48e46f8f108df71308a7521ac223 Mon Sep 17 00:00:00 2001 From: Robin Stocker <robin@nibor.org> Date: Tue, 23 Jan 2024 23:35:48 +1100 Subject: [PATCH] Disregard prefixes for line start logic --- .../markdown/CoreMarkdownNodeRenderer.java | 14 +++++++------- .../renderer/markdown/MarkdownWriter.java | 19 +++++++++++++++++-- .../markdown/MarkdownRendererTest.java | 5 +++++ .../markdown/SpecMarkdownRendererTest.java | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java index 8cb67e0f..11e7ae5f 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java @@ -88,7 +88,7 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen @Override public void visit(BlockQuote blockQuote) { - writer.write("> "); + writer.writePrefix("> "); writer.pushPrefix("> "); visitChildren(blockQuote); writer.popPrefix(); @@ -124,16 +124,16 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen if (listHolder instanceof BulletListHolder) { BulletListHolder bulletListHolder = (BulletListHolder) listHolder; String marker = repeat(" ", listItem.getMarkerIndent()) + bulletListHolder.bulletMarker; - writer.write(marker); - writer.write(repeat(" ", contentIndent - marker.length())); + writer.writePrefix(marker); + writer.writePrefix(repeat(" ", contentIndent - marker.length())); writer.pushPrefix(repeat(" ", contentIndent)); pushedPrefix = true; } else if (listHolder instanceof OrderedListHolder) { OrderedListHolder orderedListHolder = (OrderedListHolder) listHolder; String marker = repeat(" ", listItem.getMarkerIndent()) + orderedListHolder.number + orderedListHolder.delimiter; orderedListHolder.number++; - writer.write(marker); - writer.write(repeat(" ", contentIndent - marker.length())); + writer.writePrefix(marker); + writer.writePrefix(repeat(" ", contentIndent - marker.length())); writer.pushPrefix(repeat(" ", contentIndent)); pushedPrefix = true; } @@ -190,7 +190,7 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen if (indent > 0) { String indentPrefix = repeat(" ", indent); - writer.write(indentPrefix); + writer.writePrefix(indentPrefix); writer.pushPrefix(indentPrefix); } @@ -286,7 +286,7 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen String literal = indentedCodeBlock.getLiteral(); // We need to respect line prefixes which is why we need to write it line by line (e.g. an indented code block // within a block quote) - writer.write(" "); + writer.writePrefix(" "); writer.pushPrefix(" "); List<String> lines = getLines(literal); for (int i = 0; i < lines.size(); i++) { diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java index bc10f020..d95c0bd8 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java @@ -11,7 +11,8 @@ public class MarkdownWriter { private int blockSeparator = 0; private boolean tight; - private char lastChar = '\n'; + private char lastChar; + private boolean atLineStart = true; private final LinkedList<String> prefixes = new LinkedList<>(); public MarkdownWriter(Appendable out) { @@ -22,8 +23,11 @@ public class MarkdownWriter { return lastChar; } + /** + * @return whether we're at the line start (not counting any prefixes), i.e. after a {@link #line} or {@link #block}. + */ public boolean isAtLineStart() { - return lastChar == '\n' || blockSeparator > 0; + return atLineStart; } public void write(String s) { @@ -54,11 +58,13 @@ public class MarkdownWriter { } lastChar = s.charAt(s.length() - 1); + atLineStart = false; } public void line() { append('\n'); writePrefixes(); + atLineStart = true; } /** @@ -69,12 +75,19 @@ public class MarkdownWriter { // Remember whether this should be a tight or loose separator now because tight could get changed in between // this and the next flush. blockSeparator = tight ? 1 : 2; + atLineStart = true; } public void pushPrefix(String prefix) { prefixes.addLast(prefix); } + public void writePrefix(String prefix) { + boolean tmp = atLineStart; + write(prefix); + atLineStart = tmp; + } + public void popPrefix() { prefixes.removeLast(); } @@ -90,6 +103,7 @@ public class MarkdownWriter { if (length != 0) { lastChar = s.charAt(length - 1); } + atLineStart = false; } private void append(char c) { @@ -100,6 +114,7 @@ public class MarkdownWriter { } lastChar = c; + atLineStart = false; } private void writePrefixes() { diff --git a/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java b/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java index 59039799..6f9e1e6f 100644 --- a/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java +++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java @@ -137,6 +137,11 @@ public class MarkdownRendererTest { assertRoundTrip("\\## Test\n"); assertRoundTrip("\\#\n"); assertRoundTrip("Foo\n\\===\n"); + // The beginning of the line within the block, so disregarding prefixes + assertRoundTrip("> \\- Test\n"); + assertRoundTrip("- \\- Test\n"); + // That's not the beginning of the line + assertRoundTrip("`a`- foo\n"); // This is a bit more tricky as we need to check for a list start assertRoundTrip("1\\. Foo\n"); diff --git a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java index d6bdf9cf..39269368 100644 --- a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java +++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java @@ -62,7 +62,7 @@ public class SpecMarkdownRendererTest { System.out.println(); } - int expectedPassed = 647; + int expectedPassed = 650; assertTrue("Expected at least " + expectedPassed + " examples to pass but was " + passes.size(), passes.size() >= expectedPassed); } -- GitLab