Skip to content

Commit 42a025f

Browse files
committed
TextContentRenderer: Replace stripNewlines with lineBreakRendering
1 parent f82f1e6 commit 42a025f

File tree

6 files changed

+159
-73
lines changed

6 files changed

+159
-73
lines changed

commonmark/src/main/java/org/commonmark/renderer/text/CoreTextContentNodeRenderer.java

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,20 @@ public void visit(BlockQuote blockQuote) {
6565
// LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
6666
textContent.write('\u00AB');
6767
visitChildren(blockQuote);
68+
textContent.resetBlock();
6869
// RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
6970
textContent.write('\u00BB');
7071

71-
writeEndOfLineIfNeeded(blockQuote, null);
72+
textContent.block();
7273
}
7374

7475
@Override
7576
public void visit(BulletList bulletList) {
76-
if (listHolder != null) {
77-
writeEndOfLine();
78-
}
77+
// TODO: isTight()
7978
listHolder = new BulletListHolder(listHolder, bulletList);
8079
visitChildren(bulletList);
81-
writeEndOfLineIfNeeded(bulletList, null);
82-
if (listHolder.getParent() != null) {
83-
listHolder = listHolder.getParent();
84-
} else {
85-
listHolder = null;
86-
}
80+
textContent.block();
81+
listHolder = listHolder.getParent();
8782
}
8883

8984
@Override
@@ -95,31 +90,40 @@ public void visit(Code code) {
9590

9691
@Override
9792
public void visit(FencedCodeBlock fencedCodeBlock) {
98-
if (context.stripNewlines()) {
99-
textContent.writeStripped(fencedCodeBlock.getLiteral());
100-
writeEndOfLineIfNeeded(fencedCodeBlock, null);
93+
var literal = stripTrailingNewline(fencedCodeBlock.getLiteral());
94+
if (stripNewlines()) {
95+
textContent.writeStripped(literal);
10196
} else {
102-
textContent.write(fencedCodeBlock.getLiteral());
97+
textContent.write(literal);
10398
}
99+
textContent.block();
104100
}
105101

106102
@Override
107103
public void visit(HardLineBreak hardLineBreak) {
108-
writeEndOfLineIfNeeded(hardLineBreak, null);
104+
if (stripNewlines()) {
105+
textContent.whitespace();
106+
} else {
107+
textContent.line();
108+
}
109109
}
110110

111111
@Override
112112
public void visit(Heading heading) {
113113
visitChildren(heading);
114-
writeEndOfLineIfNeeded(heading, ':');
114+
if (stripNewlines()) {
115+
textContent.write(": ");
116+
} else {
117+
textContent.block();
118+
}
115119
}
116120

117121
@Override
118122
public void visit(ThematicBreak thematicBreak) {
119-
if (!context.stripNewlines()) {
123+
if (!stripNewlines()) {
120124
textContent.write("***");
121125
}
122-
writeEndOfLineIfNeeded(thematicBreak, null);
126+
textContent.block();
123127
}
124128

125129
@Override
@@ -139,12 +143,13 @@ public void visit(Image image) {
139143

140144
@Override
141145
public void visit(IndentedCodeBlock indentedCodeBlock) {
142-
if (context.stripNewlines()) {
143-
textContent.writeStripped(indentedCodeBlock.getLiteral());
144-
writeEndOfLineIfNeeded(indentedCodeBlock, null);
146+
var literal = stripTrailingNewline(indentedCodeBlock.getLiteral());
147+
if (stripNewlines()) {
148+
textContent.writeStripped(literal);
145149
} else {
146-
textContent.write(indentedCodeBlock.getLiteral());
150+
textContent.write(literal);
147151
}
152+
textContent.block();
148153
}
149154

150155
@Override
@@ -156,48 +161,43 @@ public void visit(Link link) {
156161
public void visit(ListItem listItem) {
157162
if (listHolder != null && listHolder instanceof OrderedListHolder) {
158163
OrderedListHolder orderedListHolder = (OrderedListHolder) listHolder;
159-
String indent = context.stripNewlines() ? "" : orderedListHolder.getIndent();
164+
String indent = stripNewlines() ? "" : orderedListHolder.getIndent();
160165
textContent.write(indent + orderedListHolder.getCounter() + orderedListHolder.getDelimiter() + " ");
161166
visitChildren(listItem);
162-
writeEndOfLineIfNeeded(listItem, null);
167+
textContent.block();
163168
orderedListHolder.increaseCounter();
164169
} else if (listHolder != null && listHolder instanceof BulletListHolder) {
165170
BulletListHolder bulletListHolder = (BulletListHolder) listHolder;
166-
if (!context.stripNewlines()) {
171+
if (!stripNewlines()) {
167172
textContent.write(bulletListHolder.getIndent() + bulletListHolder.getMarker() + " ");
168173
}
169174
visitChildren(listItem);
170-
writeEndOfLineIfNeeded(listItem, null);
175+
textContent.block();
171176
}
172177
}
173178

174179
@Override
175180
public void visit(OrderedList orderedList) {
176-
if (listHolder != null) {
177-
writeEndOfLine();
178-
}
181+
// TODO: isTight()
179182
listHolder = new OrderedListHolder(listHolder, orderedList);
180183
visitChildren(orderedList);
181-
writeEndOfLineIfNeeded(orderedList, null);
182-
if (listHolder.getParent() != null) {
183-
listHolder = listHolder.getParent();
184-
} else {
185-
listHolder = null;
186-
}
184+
textContent.block();
185+
listHolder = listHolder.getParent();
187186
}
188187

189188
@Override
190189
public void visit(Paragraph paragraph) {
191190
visitChildren(paragraph);
192-
// Add "end of line" only if its "root paragraph.
193-
if (paragraph.getParent() == null || paragraph.getParent() instanceof Document) {
194-
writeEndOfLineIfNeeded(paragraph, null);
195-
}
191+
textContent.block();
196192
}
197193

198194
@Override
199195
public void visit(SoftLineBreak softLineBreak) {
200-
writeEndOfLineIfNeeded(softLineBreak, null);
196+
if (stripNewlines()) {
197+
textContent.whitespace();
198+
} else {
199+
textContent.line();
200+
}
201201
}
202202

203203
@Override
@@ -216,7 +216,7 @@ protected void visitChildren(Node parent) {
216216
}
217217

218218
private void writeText(String text) {
219-
if (context.stripNewlines()) {
219+
if (stripNewlines()) {
220220
textContent.writeStripped(text);
221221
} else {
222222
textContent.write(text);
@@ -255,26 +255,15 @@ private void writeLink(Node node, String title, String destination) {
255255
}
256256
}
257257

258-
private void writeEndOfLineIfNeeded(Node node, Character c) {
259-
if (context.stripNewlines()) {
260-
if (c != null) {
261-
textContent.write(c);
262-
}
263-
if (node.getNext() != null) {
264-
textContent.whitespace();
265-
}
266-
} else {
267-
if (node.getNext() != null) {
268-
textContent.line();
269-
}
270-
}
258+
private boolean stripNewlines() {
259+
return context.lineBreakRendering() == LineBreakRendering.STRIP;
271260
}
272261

273-
private void writeEndOfLine() {
274-
if (context.stripNewlines()) {
275-
textContent.whitespace();
262+
private static String stripTrailingNewline(String s) {
263+
if (s.endsWith("\n")) {
264+
return s.substring(0, s.length() - 1);
276265
} else {
277-
textContent.line();
266+
return s;
278267
}
279268
}
280269
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.commonmark.renderer.text;
2+
3+
/**
4+
* Control how line breaks are rendered.
5+
*/
6+
public enum LineBreakRendering {
7+
/**
8+
* Strip all line breaks within blocks and between blocks, resulting in all the text in a single line.
9+
*/
10+
STRIP,
11+
/**
12+
* Use single line breaks between blocks, not a blank line (also render all lists as tight).
13+
*/
14+
COMPACT,
15+
/**
16+
* Separate blocks by a blank line (and respect tight vs loose lists).
17+
*/
18+
SEPARATE_BLOCKS,
19+
}

commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@
44

55
public interface TextContentNodeRendererContext {
66

7+
/**
8+
* TODO
9+
*
10+
* @return
11+
*/
12+
LineBreakRendering lineBreakRendering();
13+
714
/**
815
* @return true for stripping new lines and render text as "single line",
916
* false for keeping all line breaks.
17+
* @deprecated Use {@link #lineBreakRendering()} instead
1018
*/
19+
@Deprecated
1120
boolean stripNewlines();
1221

1322
/**

commonmark/src/main/java/org/commonmark/renderer/text/TextContentRenderer.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
*/
1515
public class TextContentRenderer implements Renderer {
1616

17-
private final boolean stripNewlines;
17+
private final LineBreakRendering lineBreakRendering;
1818

1919
private final List<TextContentNodeRendererFactory> nodeRendererFactories;
2020

2121
private TextContentRenderer(Builder builder) {
22-
this.stripNewlines = builder.stripNewlines;
22+
this.lineBreakRendering = builder.lineBreakRendering;
2323

2424
this.nodeRendererFactories = new ArrayList<>(builder.nodeRendererFactories.size() + 1);
2525
this.nodeRendererFactories.addAll(builder.nodeRendererFactories);
@@ -43,7 +43,7 @@ public static Builder builder() {
4343

4444
@Override
4545
public void render(Node node, Appendable output) {
46-
RendererContext context = new RendererContext(new TextContentWriter(output));
46+
RendererContext context = new RendererContext(new TextContentWriter(output, lineBreakRendering));
4747
context.render(node);
4848
}
4949

@@ -59,8 +59,8 @@ public String render(Node node) {
5959
*/
6060
public static class Builder {
6161

62-
private boolean stripNewlines = false;
6362
private List<TextContentNodeRendererFactory> nodeRendererFactories = new ArrayList<>();
63+
private LineBreakRendering lineBreakRendering = LineBreakRendering.COMPACT;
6464

6565
/**
6666
* @return the configured {@link TextContentRenderer}
@@ -69,15 +69,28 @@ public TextContentRenderer build() {
6969
return new TextContentRenderer(this);
7070
}
7171

72+
/**
73+
* TODO
74+
*
75+
* @param lineBreakRendering
76+
* @return
77+
*/
78+
public Builder lineBreakRendering(LineBreakRendering lineBreakRendering) {
79+
this.lineBreakRendering = lineBreakRendering;
80+
return this;
81+
}
82+
7283
/**
7384
* Set the value of flag for stripping new lines.
7485
*
7586
* @param stripNewlines true for stripping new lines and render text as "single line",
7687
* false for keeping all line breaks
7788
* @return {@code this}
89+
* @deprecated Use {@link #lineBreakRendering(LineBreakRendering)} with {@link LineBreakRendering#STRIP} instead
7890
*/
91+
@Deprecated
7992
public Builder stripNewlines(boolean stripNewlines) {
80-
this.stripNewlines = stripNewlines;
93+
this.lineBreakRendering = stripNewlines ? LineBreakRendering.STRIP : LineBreakRendering.COMPACT;
8194
return this;
8295
}
8396

@@ -134,9 +147,14 @@ private RendererContext(TextContentWriter textContentWriter) {
134147
}
135148
}
136149

150+
@Override
151+
public LineBreakRendering lineBreakRendering() {
152+
return lineBreakRendering;
153+
}
154+
137155
@Override
138156
public boolean stripNewlines() {
139-
return stripNewlines;
157+
return lineBreakRendering == LineBreakRendering.STRIP;
140158
}
141159

142160
@Override

0 commit comments

Comments
 (0)