Skip to content

Commit

Permalink
Merge pull request #311 from commonmark/fix-markdown-renderer-lists-f…
Browse files Browse the repository at this point in the history
…rom-ast

Fix markdown renderer for manually created list nodes
  • Loading branch information
robinst authored Mar 14, 2024
2 parents 4a6b944 + 16c6ff2 commit ccdf1a3
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.commonmark.node.*;
import org.commonmark.parser.block.*;

import java.util.Objects;

public class ListBlockParser extends AbstractBlockParser {

private final ListBlock block;
Expand Down Expand Up @@ -90,7 +92,7 @@ private static ListData parseList(CharSequence line, final int markerIndex, fina

if (inParagraph) {
// If the list item is ordered, the start number must be 1 to interrupt a paragraph.
if (listBlock instanceof OrderedList && ((OrderedList) listBlock).getStartNumber() != 1) {
if (listBlock instanceof OrderedList && ((OrderedList) listBlock).getMarkerStartNumber() != 1) {
return null;
}
// Empty list item can not interrupt a paragraph.
Expand All @@ -116,7 +118,7 @@ private static ListMarkerData parseListMarker(CharSequence line, int index) {
case '*':
if (isSpaceTabOrEnd(line, index + 1)) {
BulletList bulletList = new BulletList();
bulletList.setBulletMarker(c);
bulletList.setMarker(String.valueOf(c));
return new ListMarkerData(bulletList, index + 1);
} else {
return null;
Expand Down Expand Up @@ -154,8 +156,8 @@ private static ListMarkerData parseOrderedList(CharSequence line, int index) {
if (digits >= 1 && isSpaceTabOrEnd(line, i + 1)) {
String number = line.subSequence(index, i).toString();
OrderedList orderedList = new OrderedList();
orderedList.setStartNumber(Integer.parseInt(number));
orderedList.setDelimiter(c);
orderedList.setMarkerStartNumber(Integer.parseInt(number));
orderedList.setMarkerDelimiter(String.valueOf(c));
return new ListMarkerData(orderedList, i + 1);
} else {
return null;
Expand Down Expand Up @@ -188,17 +190,13 @@ private static boolean isSpaceTabOrEnd(CharSequence line, int index) {
*/
private static boolean listsMatch(ListBlock a, ListBlock b) {
if (a instanceof BulletList && b instanceof BulletList) {
return equals(((BulletList) a).getBulletMarker(), ((BulletList) b).getBulletMarker());
return Objects.equals(((BulletList) a).getMarker(), ((BulletList) b).getMarker());
} else if (a instanceof OrderedList && b instanceof OrderedList) {
return equals(((OrderedList) a).getDelimiter(), ((OrderedList) b).getDelimiter());
return Objects.equals(((OrderedList) a).getMarkerDelimiter(), ((OrderedList) b).getMarkerDelimiter());
}
return false;
}

private static boolean equals(Object a, Object b) {
return (a == null) ? (b == null) : a.equals(b);
}

public static class Factory extends AbstractBlockParserFactory {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import org.commonmark.node.BulletList;

public class BulletListHolder extends ListHolder {
private final char marker;
private final String marker;

public BulletListHolder(ListHolder parent, BulletList list) {
super(parent);
marker = list.getBulletMarker();
marker = list.getMarker();
}

public char getMarker() {
public String getMarker() {
return marker;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
import org.commonmark.node.OrderedList;

public class OrderedListHolder extends ListHolder {
private final char delimiter;
private final String delimiter;
private int counter;

public OrderedListHolder(ListHolder parent, OrderedList list) {
super(parent);
delimiter = list.getDelimiter();
counter = list.getStartNumber();
delimiter = list.getMarkerDelimiter() != null ? list.getMarkerDelimiter() : ".";
counter = list.getMarkerStartNumber() != null ? list.getMarkerStartNumber() : 1;
}

public char getDelimiter() {
public String getDelimiter() {
return delimiter;
}

Expand Down
26 changes: 22 additions & 4 deletions commonmark/src/main/java/org/commonmark/node/BulletList.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,37 @@

public class BulletList extends ListBlock {

private char bulletMarker;
private String marker;

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

/**
* @return the bullet list marker that was used, e.g. {@code -}, {@code *} or {@code +}, if available, or null otherwise
*/
public String getMarker() {
return marker;
}

public void setMarker(String marker) {
this.marker = marker;
}

/**
* @deprecated use {@link #getMarker()} instead
*/
@Deprecated
public char getBulletMarker() {
return bulletMarker;
return marker != null && !marker.isEmpty() ? marker.charAt(0) : '\0';
}

/**
* @deprecated use {@link #getMarker()} instead
*/
@Deprecated
public void setBulletMarker(char bulletMarker) {
this.bulletMarker = bulletMarker;
this.marker = bulletMarker != '\0' ? String.valueOf(bulletMarker) : null;
}

}
19 changes: 10 additions & 9 deletions commonmark/src/main/java/org/commonmark/node/ListItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

public class ListItem extends Block {

private int markerIndent;
private int contentIndent;
private Integer markerIndent;
private Integer contentIndent;

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

/**
* Returns the indent of the marker such as "-" or "1." in columns (spaces or tab stop of 4).
* Returns the indent of the marker such as "-" or "1." in columns (spaces or tab stop of 4) if available, or null
* otherwise.
* <p>
* Some examples and their marker indent:
* <pre>- Foo</pre>
Expand All @@ -21,17 +22,17 @@ public void accept(Visitor visitor) {
* <pre> 1. Foo</pre>
* Marker indent: 2
*/
public int getMarkerIndent() {
public Integer getMarkerIndent() {
return markerIndent;
}

public void setMarkerIndent(int markerIndent) {
public void setMarkerIndent(Integer markerIndent) {
this.markerIndent = markerIndent;
}

/**
* Returns the indent of the content in columns (spaces or tab stop of 4). The content indent is counted from the
* beginning of the line and includes the marker on the first line.
* Returns the indent of the content in columns (spaces or tab stop of 4) if available, or null otherwise.
* The content indent is counted from the beginning of the line and includes the marker on the first line.
* <p>
* Some examples and their content indent:
* <pre>- Foo</pre>
Expand All @@ -44,11 +45,11 @@ public void setMarkerIndent(int markerIndent) {
* Note that subsequent lines in the same list item need to be indented by at least the content indent to be counted
* as part of the list item.
*/
public int getContentIndent() {
public Integer getContentIndent() {
return contentIndent;
}

public void setContentIndent(int contentIndent) {
public void setContentIndent(Integer contentIndent) {
this.contentIndent = contentIndent;
}
}
51 changes: 44 additions & 7 deletions commonmark/src/main/java/org/commonmark/node/OrderedList.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,65 @@

public class OrderedList extends ListBlock {

private int startNumber;
private char delimiter;
private String markerDelimiter;
private Integer markerStartNumber;

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

/**
* @return the start number used in the marker, e.g. {@code 1}, if available, or null otherwise
*/
public Integer getMarkerStartNumber() {
return markerStartNumber;
}

public void setMarkerStartNumber(Integer markerStartNumber) {
this.markerStartNumber = markerStartNumber;
}

/**
* @return the delimiter used in the marker, e.g. {@code .} or {@code )}, if available, or null otherwise
*/
public String getMarkerDelimiter() {
return markerDelimiter;
}

public void setMarkerDelimiter(String markerDelimiter) {
this.markerDelimiter = markerDelimiter;
}

/**
* @deprecated use {@link #getMarkerStartNumber()} instead
*/
@Deprecated
public int getStartNumber() {
return startNumber;
return markerStartNumber != null ? markerStartNumber : 0;
}

/**
* @deprecated use {@link #setMarkerStartNumber} instead
*/
@Deprecated
public void setStartNumber(int startNumber) {
this.startNumber = startNumber;
this.markerStartNumber = startNumber != 0 ? startNumber : null;
}

/**
* @deprecated use {@link #getMarkerDelimiter()} instead
*/
@Deprecated
public char getDelimiter() {
return delimiter;
return markerDelimiter != null && !markerDelimiter.isEmpty() ? markerDelimiter.charAt(0) : '\0';
}

/**
* @deprecated use {@link #setMarkerDelimiter} instead
*/
@Deprecated
public void setDelimiter(char delimiter) {
this.delimiter = delimiter;
this.markerDelimiter = delimiter != '\0' ? String.valueOf(delimiter) : null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public void visit(ListItem listItem) {

@Override
public void visit(OrderedList orderedList) {
int start = orderedList.getStartNumber();
int start = orderedList.getMarkerStartNumber() != null ? orderedList.getMarkerStartNumber() : 1;
Map<String, String> attrs = new LinkedHashMap<>();
if (start != 1) {
attrs.put("start", String.valueOf(start));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,33 +227,32 @@ public void visit(OrderedList orderedList) {

@Override
public void visit(ListItem listItem) {
int contentIndent = listItem.getContentIndent();
boolean pushedPrefix = false;
int markerIndent = listItem.getMarkerIndent() != null ? listItem.getMarkerIndent() : 0;
String marker;
if (listHolder instanceof BulletListHolder) {
BulletListHolder bulletListHolder = (BulletListHolder) listHolder;
String marker = repeat(" ", listItem.getMarkerIndent()) + bulletListHolder.bulletMarker;
writer.writePrefix(marker);
writer.writePrefix(repeat(" ", contentIndent - marker.length()));
writer.pushPrefix(repeat(" ", contentIndent));
pushedPrefix = true;
marker = repeat(" ", markerIndent) + bulletListHolder.marker;
} else if (listHolder instanceof OrderedListHolder) {
OrderedListHolder orderedListHolder = (OrderedListHolder) listHolder;
String marker = repeat(" ", listItem.getMarkerIndent()) + orderedListHolder.number + orderedListHolder.delimiter;
marker = repeat(" ", markerIndent) + orderedListHolder.number + orderedListHolder.delimiter;
orderedListHolder.number++;
writer.writePrefix(marker);
writer.writePrefix(repeat(" ", contentIndent - marker.length()));
writer.pushPrefix(repeat(" ", contentIndent));
pushedPrefix = true;
} else {
throw new IllegalStateException("Unknown list holder type: " + listHolder);
}
Integer contentIndent = listItem.getContentIndent();
String spaces = contentIndent != null ? repeat(" ", contentIndent - marker.length()) : " ";
writer.writePrefix(marker);
writer.writePrefix(spaces);
writer.pushPrefix(repeat(" ", marker.length() + spaces.length()));

if (listItem.getFirstChild() == null) {
// Empty list item
writer.block();
} else {
visitChildren(listItem);
}
if (pushedPrefix) {
writer.popPrefix();
}

writer.popPrefix();
}

@Override
Expand Down Expand Up @@ -489,22 +488,22 @@ protected ListHolder(ListHolder parent) {
}

private static class BulletListHolder extends ListHolder {
final char bulletMarker;
final String marker;

public BulletListHolder(ListHolder parent, BulletList bulletList) {
super(parent);
this.bulletMarker = bulletList.getBulletMarker();
this.marker = bulletList.getMarker() != null ? bulletList.getMarker() : "-";
}
}

private static class OrderedListHolder extends ListHolder {
final char delimiter;
final String delimiter;
private int number;

protected OrderedListHolder(ListHolder parent, OrderedList orderedList) {
super(parent);
delimiter = orderedList.getDelimiter();
number = orderedList.getStartNumber();
delimiter = orderedList.getMarkerDelimiter() != null ? orderedList.getMarkerDelimiter() : ".";
number = orderedList.getMarkerStartNumber() != null ? orderedList.getMarkerStartNumber() : 1;
}
}

Expand Down
Loading

0 comments on commit ccdf1a3

Please sign in to comment.