Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.28.0</version>
</dependency>

<!-- Compile-time dependencies -->
<dependency>
Expand All @@ -66,6 +61,17 @@
<artifactId>auto-service-annotations</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.28.0</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.28.0</version>
<scope>compile</scope>
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.google.googlejavaformat.java.javadoc.Token.MarkdownCodeSpanStart;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownFencedCodeBlock;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownHardLineBreak;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownTable;
import com.google.googlejavaformat.java.javadoc.Token.MoeBeginStripComment;
import com.google.googlejavaformat.java.javadoc.Token.MoeEndStripComment;
import com.google.googlejavaformat.java.javadoc.Token.OptionalLineBreak;
Expand Down Expand Up @@ -137,6 +138,7 @@ private static String render(List<Token> input, int blockIndent, boolean classic
case MarkdownHardLineBreak unused -> output.writeMarkdownHardLineBreak();
case Literal t -> output.writeLiteral(t);
case MarkdownFencedCodeBlock t -> output.writeMarkdownFencedCodeBlock(t);
case MarkdownTable t -> output.writeMarkdownTable(t);
case ListItemCloseTag unused -> {}
case OptionalLineBreak unused -> {}
case ParagraphCloseTag unused -> {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.google.googlejavaformat.java.javadoc.Token.ListOpenTag;
import com.google.googlejavaformat.java.javadoc.Token.Literal;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownFencedCodeBlock;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownTable;
import com.google.googlejavaformat.java.javadoc.Token.MoeBeginStripComment;
import com.google.googlejavaformat.java.javadoc.Token.MoeEndStripComment;
import com.google.googlejavaformat.java.javadoc.Token.PreCloseTag;
Expand All @@ -44,6 +45,7 @@
import com.google.googlejavaformat.java.javadoc.Token.StartOfLineToken;
import com.google.googlejavaformat.java.javadoc.Token.TableCloseTag;
import com.google.googlejavaformat.java.javadoc.Token.TableOpenTag;
import java.util.List;

/**
* Stateful object that accepts "requests" and "writes," producing formatted Javadoc.
Expand Down Expand Up @@ -335,6 +337,9 @@ void writeLiteral(Literal token) {
}

void writeMarkdownFencedCodeBlock(MarkdownFencedCodeBlock token) {
if (!token.precededByNonWhitespace() && wroteAnythingSignificant) {
requestBlankLine();
}
flushWhitespace();
output.append(token.start());
token
Expand All @@ -350,6 +355,20 @@ void writeMarkdownFencedCodeBlock(MarkdownFencedCodeBlock token) {
requestBlankLine();
}

void writeMarkdownTable(MarkdownTable token) {
if (!token.precededByNonWhitespace() && wroteAnythingSignificant) {
requestBlankLine();
}
flushWhitespace();
List<String> lines = token.value().lines().toList();
output.append(lines.get(0));
for (String line : lines.subList(1, lines.size())) {
writeNewline(AutoIndent.NO_AUTO_INDENT);
output.append(line);
}
requestBlankLine();
}

@Override
public String toString() {
return output.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@
import com.google.googlejavaformat.java.javadoc.Token.MarkdownCodeSpanEnd;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownCodeSpanStart;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownFencedCodeBlock;
import com.google.googlejavaformat.java.javadoc.Token.MarkdownTable;
import com.google.googlejavaformat.java.javadoc.Token.ParagraphCloseTag;
import com.google.googlejavaformat.java.javadoc.Token.ParagraphOpenTag;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.BulletList;
import org.commonmark.node.Code;
import org.commonmark.node.FencedCodeBlock;
Expand Down Expand Up @@ -92,6 +96,10 @@ void visit(Node node) {
case OrderedList orderedList -> addSpan(orderedList, LIST_OPEN_TOKEN, LIST_CLOSE_TOKEN);
case ListItem listItem -> alreadyVisitedChildren = visitListItem(listItem);
case FencedCodeBlock fencedCodeBlock -> visitFencedCodeBlock(fencedCodeBlock);
case TableBlock tableBlock -> {
visitTableBlock(tableBlock);
alreadyVisitedChildren = true;
}
case Code code -> visitCodeSpan(code);
// TODO: others
default -> {}
Expand Down Expand Up @@ -128,16 +136,30 @@ private void visitFencedCodeBlock(FencedCodeBlock fencedCodeBlock) {
// indentation gets subtracted from FencedCodeBlock.getLiteral(), which is the actual text
// represented by the code block.
int start = startPosition(fencedCodeBlock) + fencedCodeBlock.getFenceIndent();
boolean precededByNonWhitespace = precededByNonWhitespace(start);
int closingLength =
Objects.requireNonNullElse(
fencedCodeBlock.getClosingFenceLength(), fencedCodeBlock.getOpeningFenceLength());
MarkdownFencedCodeBlock token =
new MarkdownFencedCodeBlock(
input.substring(start, endPosition(fencedCodeBlock)),
fencedCodeBlock.getFenceCharacter().repeat(fencedCodeBlock.getOpeningFenceLength())
+ fencedCodeBlock.getInfo(),
fencedCodeBlock.getFenceCharacter().repeat(fencedCodeBlock.getClosingFenceLength()),
fencedCodeBlock.getLiteral());
fencedCodeBlock.getFenceCharacter().repeat(closingLength),
fencedCodeBlock.getLiteral(),
precededByNonWhitespace);
positionToToken.get(start).addLast(token);
}

private void visitTableBlock(TableBlock tableBlock) {
int start = startPosition(tableBlock);
boolean precededByNonWhitespace = precededByNonWhitespace(start);
int end = endPosition(tableBlock);
positionToToken
.get(start)
.addLast(new MarkdownTable(input.substring(start, end), precededByNonWhitespace));
}

private void visitCodeSpan(Code code) {
int start = startPosition(code);
int end = endPosition(code);
Expand All @@ -164,6 +186,15 @@ private void visitNodeList(Node node) {
}
}

private boolean precededByNonWhitespace(int position) {
for (int i = position - 1; i >= 0 && input.charAt(i) != '\n'; i--) {
if (!Character.isWhitespace(input.charAt(i))) {
return true;
}
}
return false;
}

/**
* Adds tokens for the given node, {@code startToken} at the point where the node starts in the
* input, and {@code endToken} at the point where it ends. The {@code startToken} goes after any
Expand Down Expand Up @@ -195,7 +226,10 @@ public String toString() {
}

private static final Parser PARSER =
Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build();
Parser.builder()
.includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES)
.extensions(ImmutableList.of(TablesExtension.create()))
.build();

private static final HeaderOpenTag HEADER_OPEN_TOKEN = new HeaderOpenTag("");
private static final HeaderCloseTag HEADER_CLOSE_TOKEN = new HeaderCloseTag("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,29 @@ record MarkdownCodeSpanEnd(String value) implements Token {}
* @param end the end fence.
* @param literal the text that the code block represents. This does not include the start and end
* fences, nor any indentation that precedes these fences and every intervening line.
* @param precededByNonWhitespace whether the start of the code block is preceded by at least one
* non-whitespace character on the same line, for example {@code - ```}.
*/
record MarkdownFencedCodeBlock(String value, String start, String end, String literal)
record MarkdownFencedCodeBlock(
String value, String start, String end, String literal, boolean precededByNonWhitespace)
implements Token {}

/**
* A Markdown table, like:
*
* {@snippet :
* | foo | bar |
* | --- | --- |
* | baz | qux |
* }
*
* @param value the full text of the table as it appeared in the input, including the delimiters
* and the literal content.
* @param precededByNonWhitespace whether the start of the table is preceded by at least one
* non-whitespace character on the same line, for example {@code - |foo|bar|}.
*/
record MarkdownTable(String value, boolean precededByNonWhitespace) implements Token {}

/**
* Whitespace that is not in a {@code <pre>} or {@code <table>} section. Whitespace includes
* leading newlines, asterisks, and tabs and spaces. In the output, it is translated to newlines
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,12 @@ public void markdownFencedCodeBlocks() {
/// in a list
/// ```
///
/// - flibbertigibbet
///
/// ```
/// code block in a list after text
/// ```
///
/// ~~~java
/// code block
/// with tildes and an info string ("java")
Expand All @@ -1761,6 +1767,12 @@ class Test {}
/// in a list
/// ```
///
/// - flibbertigibbet
///
/// ```
/// code block in a list after text
/// ```
///
/// ~~~java
/// code block
/// with tildes and an info string ("java")
Expand Down Expand Up @@ -1993,22 +2005,25 @@ public void markdownTables() {
assume().that(MARKDOWN_JAVADOC_SUPPORTED).isTrue();
String input =
"""
/// Table McTableface
///
/// | foo | bar |
/// | --- | --- |
/// | baz | qux |
///
/// - |foo|bar|
/// |--:|:--|
/// |baz|qux|
///
/// - Another list.
///
/// | which | contains |
/// | ----- | -------- |
/// | a | table |
class Test {}
""";
// TODO: unmangle the tables
String expected =
"""
/// | foo | bar | | --- | --- | | baz | qux |
/// - |foo|bar| |--:|:--| |baz|qux|
class Test {}
""";
// We don't currently try to align the column markers in the rows of the last table.
String expected = input;
doFormatTest(input, expected);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,19 @@ public void codeBlock() {
int secondCodeEnd = text.indexOf("~~~", secondCodeStart + 3) + 3;
int thirdCodeStart = text.indexOf("````", secondCodeEnd);
int thirdCodeEnd = text.indexOf("````", thirdCodeStart + 4) + 4;
boolean precededByNonWhitespace = true;
ImmutableListMultimap<Integer, Token> expected =
ImmutableListMultimap.<Integer, Token>builder()
.put(bullet, new ListOpenTag(""))
.put(bullet, new ListItemOpenTag("- "))
.put(
firstCodeStart,
new MarkdownFencedCodeBlock(
text.substring(firstCodeStart, firstCodeEnd), "```", "```", "foo\nbar\n"))
text.substring(firstCodeStart, firstCodeEnd),
"```",
"```",
"foo\nbar\n",
/* precededByNonWhitespace= */ true))
.put(firstCodeEnd, new ListItemCloseTag(""))
.put(firstCodeEnd, new ListCloseTag(""))
.put(
Expand All @@ -145,14 +150,16 @@ public void codeBlock() {
text.substring(secondCodeStart, secondCodeEnd),
"~~~java",
"~~~",
"code\nwith tildes\n"))
"code\nwith tildes\n",
/* precededByNonWhitespace= */ false))
.put(
thirdCodeStart,
new MarkdownFencedCodeBlock(
text.substring(thirdCodeStart, thirdCodeEnd),
"````",
"````",
"indented code\nwith more than three backticks\n"))
"indented code\nwith more than three backticks\n",
/* precededByNonWhitespace= */ false))
.build();
assertThat(map).isEqualTo(expected);
}
Expand Down
Loading