From e1d5292165d132057bd34236b10e5c02fe710043 Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Tue, 28 Jul 2026 21:53:40 +1000 Subject: [PATCH 1/2] Use google-java-format (via spotless) Using AOSP style because: - It's 4 spaces indentation (instead of 2 for the default). 4 spaces matches the current style, so reformatting isn't going to change all lines. - It's also closer to OpenJDK's own style as commonmark-java is vendored there: https://github.com/openjdk/jdk/tree/master/src/jdk.internal.md/share/classes/jdk/internal/org/commonmark --- .idea/google-java-format.xml | 7 +++++++ pom.xml | 12 ++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .idea/google-java-format.xml diff --git a/.idea/google-java-format.xml b/.idea/google-java-format.xml new file mode 100644 index 000000000..05946a82a --- /dev/null +++ b/.idea/google-java-format.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 54edab537..94c76c4ee 100644 --- a/pom.xml +++ b/pom.xml @@ -124,6 +124,18 @@ + + com.diffplug.spotless + spotless-maven-plugin + 3.9.0 + + + + + + + + From bb8c71fc9f070520b282016d69c3a2d4b072ecfd Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Wed, 29 Jul 2026 18:41:00 +1000 Subject: [PATCH 2/2] Format using `mvn spotless:apply` Had to reflow some multi-line comments, but other than that all good. --- .../ext/autolink/AutolinkExtension.java | 23 +- .../commonmark/ext/autolink/AutolinkType.java | 16 +- .../internal/AutolinkPostProcessor.java | 7 +- .../commonmark/ext/autolink/AutolinkTest.java | 74 +- .../ext/footnotes/FootnoteDefinition.java | 12 +- .../ext/footnotes/FootnoteReference.java | 7 +- .../ext/footnotes/FootnotesExtension.java | 64 +- .../ext/footnotes/InlineFootnote.java | 3 +- .../internal/FootnoteBlockParser.java | 34 +- .../internal/FootnoteHtmlNodeRenderer.java | 203 +-- .../internal/FootnoteLinkProcessor.java | 27 +- .../FootnoteMarkdownNodeRenderer.java | 3 +- .../footnotes/FootnoteHtmlRendererTest.java | 440 +++--- .../FootnoteMarkdownRendererTest.java | 20 +- .../ext/footnotes/FootnotesTest.java | 60 +- .../org/commonmark/ext/gfm/alerts/Alert.java | 45 +- .../commonmark/ext/gfm/alerts/AlertTitle.java | 14 +- .../ext/gfm/alerts/AlertsExtension.java | 158 +- .../gfm/alerts/internal/AlertBlockParser.java | 23 +- .../internal/AlertHtmlNodeRenderer.java | 11 +- .../alerts/internal/AlertNodeRenderer.java | 11 +- .../AlertTextContentNodeRenderer.java | 6 +- .../alerts/AlertsMarkdownRendererTest.java | 36 +- .../ext/gfm/alerts/AlertsSpecTest.java | 26 +- .../commonmark/ext/gfm/alerts/AlertsTest.java | 558 +++---- .../alerts/AlertsTextContentRendererTest.java | 60 +- .../gfm/alerts/examples/AlertsExample.java | 75 +- .../ext/gfm/strikethrough/Strikethrough.java | 4 +- .../strikethrough/StrikethroughExtension.java | 88 +- .../StrikethroughDelimiterProcessor.java | 5 +- .../StrikethroughHtmlNodeRenderer.java | 3 +- .../internal/StrikethroughNodeRenderer.java | 3 +- .../StrikethroughTextContentNodeRenderer.java | 4 +- .../StrikethroughMarkdownRendererTest.java | 10 +- .../strikethrough/StrikethroughSpecTest.java | 11 +- .../gfm/strikethrough/StrikethroughTest.java | 46 +- .../commonmark/ext/gfm/tables/TableBlock.java | 7 +- .../commonmark/ext/gfm/tables/TableBody.java | 7 +- .../commonmark/ext/gfm/tables/TableCell.java | 16 +- .../commonmark/ext/gfm/tables/TableHead.java | 7 +- .../commonmark/ext/gfm/tables/TableRow.java | 3 +- .../ext/gfm/tables/TablesExtension.java | 51 +- .../gfm/tables/internal/TableBlockParser.java | 41 +- .../internal/TableHtmlNodeRenderer.java | 6 +- .../internal/TableMarkdownNodeRenderer.java | 8 +- .../tables/internal/TableNodeRenderer.java | 6 +- .../TableTextContentNodeRenderer.java | 3 +- .../gfm/tables/TableMarkdownRendererTest.java | 13 +- .../ext/gfm/tables/TablesSpecTest.java | 11 +- .../commonmark/ext/gfm/tables/TablesTest.java | 1314 +++++++++-------- .../ext/gfm/tables/TablesTextContentTest.java | 25 +- .../anchor/HeadingAnchorExtension.java | 21 +- .../ext/heading/anchor/IdGenerator.java | 56 +- .../internal/HeadingIdAttributeProvider.java | 40 +- .../HeadingAnchorConfigurationTest.java | 28 +- .../ext/heading/anchor/HeadingAnchorTest.java | 47 +- .../ext/image/attributes/ImageAttributes.java | 7 +- .../attributes/ImageAttributesExtension.java | 18 +- .../ImageAttributesAttributeProvider.java | 29 +- .../ImageAttributesDelimiterProcessor.java | 13 +- .../image/attributes/ImageAttributesTest.java | 89 +- .../main/java/org/commonmark/ext/ins/Ins.java | 4 +- .../org/commonmark/ext/ins/InsExtension.java | 52 +- .../ins/internal/InsDelimiterProcessor.java | 3 +- .../ext/ins/internal/InsHtmlNodeRenderer.java | 3 +- .../ext/ins/internal/InsNodeRenderer.java | 3 +- .../ext/ins/InsMarkdownRendererTest.java | 10 +- .../java/org/commonmark/ext/ins/InsTest.java | 31 +- .../task/list/items/TaskListItemMarker.java | 4 +- .../list/items/TaskListItemsExtension.java | 41 +- .../TaskListItemHtmlNodeRenderer.java | 5 +- .../internal/TaskListItemPostProcessor.java | 17 +- .../TaskListItemMarkdownRendererTest.java | 7 +- .../task/list/items/TaskListItemsTest.java | 137 +- .../front/matter/YamlFrontMatterBlock.java | 3 +- .../matter/YamlFrontMatterExtension.java | 42 +- .../ext/front/matter/YamlFrontMatterNode.java | 3 +- .../front/matter/YamlFrontMatterVisitor.java | 9 +- .../internal/YamlFrontMatterBlockParser.java | 24 +- .../YamlFrontMatterMarkdownRendererTest.java | 68 +- .../ext/front/matter/YamlFrontMatterTest.java | 146 +- .../integration/IntegrationTests.java | 7 +- .../integration/BoundsIntegrationTest.java | 14 +- .../commonmark/integration/Extensions.java | 24 +- .../ExtensionsIntegrationTest.java | 30 +- .../MarkdownRendererIntegrationTest.java | 10 +- .../integration/PegDownBenchmark.java | 19 +- .../SourceSpanIntegrationTest.java | 13 +- .../integration/SpecIntegrationTest.java | 50 +- .../java/org/commonmark/ui/DingusApp.java | 49 +- .../java/org/commonmark/testutil/Asserts.java | 3 +- .../org/commonmark/testutil/SpecTestCase.java | 6 +- .../commonmark/testutil/TestResources.java | 7 +- .../commonmark/testutil/example/Example.java | 8 +- .../testutil/example/ExampleReader.java | 30 +- .../main/java/org/commonmark/Extension.java | 11 +- .../org/commonmark/internal/BlockContent.java | 1 - .../internal/BlockContinueImpl.java | 1 - .../commonmark/internal/BlockQuoteParser.java | 4 +- .../java/org/commonmark/internal/Bracket.java | 82 +- .../org/commonmark/internal/Definitions.java | 3 +- .../org/commonmark/internal/Delimiter.java | 20 +- .../internal/DocumentBlockParser.java | 1 - .../commonmark/internal/DocumentParser.java | 165 ++- .../internal/FencedCodeBlockParser.java | 26 +- .../commonmark/internal/HeadingParser.java | 22 +- .../commonmark/internal/HtmlBlockParser.java | 107 +- .../internal/IndentedCodeBlockParser.java | 13 +- .../internal/InlineParserContextImpl.java | 18 +- .../commonmark/internal/InlineParserImpl.java | 243 +-- .../LinkReferenceDefinitionParser.java | 96 +- .../commonmark/internal/ListBlockParser.java | 54 +- .../commonmark/internal/ListItemParser.java | 11 +- .../commonmark/internal/ParagraphParser.java | 6 +- .../internal/StaggeredDelimiterProcessor.java | 28 +- .../internal/ThematicBreakParser.java | 11 +- .../internal/inline/AutolinkInlineParser.java | 18 +- .../inline/BackslashInlineParser.java | 10 +- .../inline/BackticksInlineParser.java | 19 +- .../internal/inline/CoreLinkProcessor.java | 6 +- .../inline/EmphasisDelimiterProcessor.java | 6 +- .../internal/inline/EntityInlineParser.java | 16 +- .../internal/inline/HtmlInlineParser.java | 77 +- .../internal/renderer/NodeRendererMap.java | 8 +- .../commonmark/internal/util/Escaping.java | 67 +- .../internal/util/Html5Entities.java | 6 +- .../commonmark/internal/util/LineReader.java | 16 +- .../commonmark/internal/util/LinkScanner.java | 20 +- .../org/commonmark/node/AbstractVisitor.java | 10 +- .../main/java/org/commonmark/node/Block.java | 7 +- .../java/org/commonmark/node/BlockQuote.java | 5 +- .../java/org/commonmark/node/BulletList.java | 8 +- .../main/java/org/commonmark/node/Code.java | 8 +- .../java/org/commonmark/node/CustomBlock.java | 3 +- .../org/commonmark/node/DefinitionMap.java | 15 +- .../java/org/commonmark/node/Delimited.java | 4 +- .../java/org/commonmark/node/Document.java | 4 +- .../java/org/commonmark/node/Emphasis.java | 7 +- .../org/commonmark/node/FencedCodeBlock.java | 20 +- .../org/commonmark/node/HardLineBreak.java | 2 + .../java/org/commonmark/node/Heading.java | 4 +- .../main/java/org/commonmark/node/Image.java | 4 +- .../commonmark/node/IndentedCodeBlock.java | 2 + .../main/java/org/commonmark/node/Link.java | 26 +- .../node/LinkReferenceDefinition.java | 10 +- .../java/org/commonmark/node/ListBlock.java | 5 +- .../java/org/commonmark/node/ListItem.java | 50 +- .../main/java/org/commonmark/node/Node.java | 12 +- .../main/java/org/commonmark/node/Nodes.java | 8 +- .../java/org/commonmark/node/OrderedList.java | 12 +- .../org/commonmark/node/SoftLineBreak.java | 1 + .../java/org/commonmark/node/SourceSpan.java | 75 +- .../java/org/commonmark/node/SourceSpans.java | 8 +- .../org/commonmark/node/StrongEmphasis.java | 7 +- .../main/java/org/commonmark/node/Text.java | 9 +- .../org/commonmark/node/ThematicBreak.java | 1 + .../java/org/commonmark/node/Visitor.java | 4 +- .../org/commonmark/node/package-info.java | 3 +- .../java/org/commonmark/package-info.java | 9 +- .../commonmark/parser/IncludeSourceSpans.java | 16 +- .../org/commonmark/parser/InlineParser.java | 4 +- .../parser/InlineParserContext.java | 34 +- .../parser/InlineParserFactory.java | 7 +- .../java/org/commonmark/parser/Parser.java | 219 +-- .../org/commonmark/parser/PostProcessor.java | 1 - .../org/commonmark/parser/SourceLine.java | 6 +- .../org/commonmark/parser/SourceLines.java | 3 +- .../parser/beta/InlineContentParser.java | 20 +- .../beta/InlineContentParserFactory.java | 17 +- .../parser/beta/InlineParserState.java | 8 +- .../org/commonmark/parser/beta/LinkInfo.java | 42 +- .../commonmark/parser/beta/LinkProcessor.java | 28 +- .../commonmark/parser/beta/LinkResult.java | 26 +- .../commonmark/parser/beta/ParsedInline.java | 7 +- .../org/commonmark/parser/beta/Position.java | 4 +- .../org/commonmark/parser/beta/Scanner.java | 38 +- .../commonmark/parser/beta/package-info.java | 4 +- .../parser/block/AbstractBlockParser.java | 13 +- .../block/AbstractBlockParserFactory.java | 3 +- .../parser/block/BlockContinue.java | 8 +- .../commonmark/parser/block/BlockParser.java | 39 +- .../parser/block/BlockParserFactory.java | 6 +- .../commonmark/parser/block/BlockStart.java | 45 +- .../parser/block/MatchedBlockParser.java | 13 +- .../commonmark/parser/block/ParserState.java | 17 +- .../commonmark/parser/block/package-info.java | 4 +- .../parser/delimiter/DelimiterProcessor.java | 31 +- .../parser/delimiter/DelimiterRun.java | 28 +- .../org/commonmark/parser/package-info.java | 4 +- .../org/commonmark/renderer/NodeRenderer.java | 13 +- .../renderer/html/AttributeProvider.java | 28 +- .../html/AttributeProviderContext.java | 9 +- .../html/AttributeProviderFactory.java | 4 +- .../renderer/html/CoreHtmlNodeRenderer.java | 26 +- .../renderer/html/DefaultUrlSanitizer.java | 11 +- .../html/HtmlNodeRendererContext.java | 19 +- .../html/HtmlNodeRendererFactory.java | 4 +- .../renderer/html/HtmlRenderer.java | 80 +- .../commonmark/renderer/html/HtmlWriter.java | 3 +- .../renderer/html/UrlSanitizer.java | 9 +- .../renderer/html/package-info.java | 4 +- .../markdown/CoreMarkdownNodeRenderer.java | 199 ++- .../markdown/MarkdownNodeRendererContext.java | 12 +- .../markdown/MarkdownNodeRendererFactory.java | 11 +- .../renderer/markdown/MarkdownRenderer.java | 69 +- .../renderer/markdown/MarkdownWriter.java | 75 +- .../renderer/markdown/package-info.java | 4 +- .../text/CoreTextContentNodeRenderer.java | 6 +- .../renderer/text/LineBreakRendering.java | 15 +- .../text/TextContentNodeRendererContext.java | 13 +- .../text/TextContentNodeRendererFactory.java | 4 +- .../renderer/text/TextContentRenderer.java | 41 +- .../renderer/text/TextContentWriter.java | 36 +- .../renderer/text/package-info.java | 3 +- .../org/commonmark/text/AsciiMatcher.java | 4 +- .../java/org/commonmark/text/CharMatcher.java | 8 +- .../java/org/commonmark/text/Characters.java | 15 +- .../org/commonmark/text/package-info.java | 4 +- .../java/org/commonmark/ProfilingMain.java | 8 +- .../internal/DocumentParserTest.java | 51 +- .../LinkReferenceDefinitionParserTest.java | 14 +- .../internal/util/EscapingTest.java | 4 +- .../internal/util/LineReaderTest.java | 30 +- .../parser/InlineContentParserTest.java | 26 +- .../parser/beta/LinkProcessorTest.java | 14 +- .../commonmark/parser/beta/ScannerTest.java | 68 +- .../markdown/MarkdownRendererTest.java | 64 +- .../markdown/SpecMarkdownRendererTest.java | 25 +- .../commonmark/test/AbstractVisitorTest.java | 19 +- .../test/BlockParserFactoryTest.java | 35 +- .../org/commonmark/test/DelimitedTest.java | 38 +- .../test/DelimiterProcessorTest.java | 60 +- .../test/FencedCodeBlockParserTest.java | 29 +- .../org/commonmark/test/HtmlRendererTest.java | 256 ++-- .../test/InlineParserContextTest.java | 81 +- .../test/LinkReferenceDefinitionNodeTest.java | 13 +- .../commonmark/test/ListBlockParserTest.java | 7 +- .../commonmark/test/ListTightLooseTest.java | 248 ++-- .../test/java/org/commonmark/test/Nodes.java | 12 +- .../java/org/commonmark/test/ParserTest.java | 44 +- .../org/commonmark/test/PathologicalTest.java | 51 +- .../org/commonmark/test/RegressionTest.java | 21 +- .../org/commonmark/test/SourceLineTest.java | 15 +- .../commonmark/test/SourceSpanRenderer.java | 18 +- .../org/commonmark/test/SourceSpanTest.java | 24 +- .../org/commonmark/test/SourceSpansTest.java | 362 +++-- .../org/commonmark/test/SpecBenchmark.java | 15 +- .../org/commonmark/test/SpecCoreTest.java | 57 +- .../org/commonmark/test/SpecCrLfCoreTest.java | 10 +- .../org/commonmark/test/SpecialInputTest.java | 153 +- .../test/TextContentRendererTest.java | 95 +- .../test/TextContentWriterTest.java | 4 +- .../test/ThematicBreakParserTest.java | 4 +- .../org/commonmark/test/UsageExampleTest.java | 49 +- .../org/commonmark/text/CharactersTest.java | 48 +- 255 files changed, 5401 insertions(+), 4568 deletions(-) diff --git a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkExtension.java b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkExtension.java index 7d5a74f30..14222121c 100644 --- a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkExtension.java +++ b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkExtension.java @@ -2,7 +2,6 @@ import java.util.EnumSet; import java.util.Set; - import org.commonmark.Extension; import org.commonmark.ext.autolink.internal.AutolinkPostProcessor; import org.commonmark.parser.Parser; @@ -10,14 +9,12 @@ /** * Extension for automatically turning plain URLs and email addresses into links. - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- *

- * The parsed links are turned into normal {@link org.commonmark.node.Link} nodes. - *

+ * + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The parsed links are turned into normal {@link org.commonmark.node.Link} nodes. */ public class AutolinkExtension implements Parser.ParserExtension { @@ -51,8 +48,8 @@ public static class Builder { private Set linkTypes = EnumSet.allOf(AutolinkType.class); /** - * @param linkTypes the link types that should be converted. By default, - * all {@link AutolinkType}s are converted. + * @param linkTypes the link types that should be converted. By default, all {@link + * AutolinkType}s are converted. * @return {@code this} */ public Builder linkTypes(AutolinkType... linkTypes) { @@ -64,8 +61,8 @@ public Builder linkTypes(AutolinkType... linkTypes) { } /** - * @param linkTypes the link types that should be converted. By default, - * all {@link AutolinkType}s are converted. + * @param linkTypes the link types that should be converted. By default, all {@link + * AutolinkType}s are converted. * @return {@code this} */ public Builder linkTypes(Set linkTypes) { diff --git a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkType.java b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkType.java index 2c8c6574f..24249ef88 100644 --- a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkType.java +++ b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkType.java @@ -1,19 +1,11 @@ package org.commonmark.ext.autolink; -/** - * The types of strings that can be automatically turned into links. - */ +/** The types of strings that can be automatically turned into links. */ public enum AutolinkType { - /** - * URL such as {@code http://example.com} - */ + /** URL such as {@code http://example.com} */ URL, - /** - * Email address such as {@code foo@example.com} - */ + /** Email address such as {@code foo@example.com} */ EMAIL, - /** - * URL such as {@code www.example.com} - */ + /** URL such as {@code www.example.com} */ WWW } diff --git a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java index a381c2f19..124870fd2 100644 --- a/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java +++ b/commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/internal/AutolinkPostProcessor.java @@ -1,5 +1,6 @@ package org.commonmark.ext.autolink.internal; +import java.util.*; import org.commonmark.ext.autolink.AutolinkType; import org.commonmark.node.*; import org.commonmark.parser.PostProcessor; @@ -8,8 +9,6 @@ import org.nibor.autolink.LinkType; import org.nibor.autolink.Span; -import java.util.*; - public class AutolinkPostProcessor implements PostProcessor { private final LinkExtractor linkExtractor; @@ -38,9 +37,7 @@ public AutolinkPostProcessor(Set linkTypes) { } } - this.linkExtractor = LinkExtractor.builder() - .linkTypes(types) - .build(); + this.linkExtractor = LinkExtractor.builder().linkTypes(types).build(); } @Override diff --git a/commonmark-ext-autolink/src/test/java/org/commonmark/ext/autolink/AutolinkTest.java b/commonmark-ext-autolink/src/test/java/org/commonmark/ext/autolink/AutolinkTest.java index 82c3899fc..fb79dfd60 100644 --- a/commonmark-ext-autolink/src/test/java/org/commonmark/ext/autolink/AutolinkTest.java +++ b/commonmark-ext-autolink/src/test/java/org/commonmark/ext/autolink/AutolinkTest.java @@ -1,5 +1,9 @@ package org.commonmark.ext.autolink; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.*; import org.commonmark.parser.IncludeSourceSpans; @@ -8,64 +12,69 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class AutolinkTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(AutolinkExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); - - private static final Set NO_WWW_EXTENSIONS = Set.of(AutolinkExtension.builder() - .linkTypes(AutolinkType.URL, AutolinkType.EMAIL) - .build()); - private static final Parser NO_WWW_PARSER = Parser.builder().extensions(NO_WWW_EXTENSIONS).build(); - private static final HtmlRenderer NO_WWW_RENDERER = HtmlRenderer.builder().extensions(NO_WWW_EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); + + private static final Set NO_WWW_EXTENSIONS = + Set.of( + AutolinkExtension.builder() + .linkTypes(AutolinkType.URL, AutolinkType.EMAIL) + .build()); + private static final Parser NO_WWW_PARSER = + Parser.builder().extensions(NO_WWW_EXTENSIONS).build(); + private static final HtmlRenderer NO_WWW_RENDERER = + HtmlRenderer.builder().extensions(NO_WWW_EXTENSIONS).build(); @Test public void oneTextNode() { - assertRendering("foo http://one.org/ bar http://two.org/", + assertRendering( + "foo http://one.org/ bar http://two.org/", "

foo http://one.org/ bar http://two.org/

\n"); } @Test public void textNodeAndOthers() { - assertRendering("foo http://one.org/ bar `code` baz http://two.org/", + assertRendering( + "foo http://one.org/ bar `code` baz http://two.org/", "

foo http://one.org/ bar code baz http://two.org/

\n"); } @Test public void tricky() { - assertRendering("http://example.com/one. Example 2 (see http://example.com/two). Example 3: http://example.com/foo_(bar)", - "

http://example.com/one. " + - "Example 2 (see http://example.com/two). " + - "Example 3: http://example.com/foo_(bar)

\n"); + assertRendering( + "http://example.com/one. Example 2 (see http://example.com/two). Example 3: http://example.com/foo_(bar)", + "

http://example.com/one. " + + "Example 2 (see http://example.com/two). " + + "Example 3: http://example.com/foo_(bar)

\n"); } @Test public void emailUsesMailto() { - assertRendering("foo@example.com", + assertRendering( + "foo@example.com", "

foo@example.com

\n"); } @Test public void emailWithTldNotLinked() { - assertRendering("foo@com", - "

foo@com

\n"); + assertRendering("foo@com", "

foo@com

\n"); } @Test public void dontLinkTextWithinLinks() { - assertRendering("", + assertRendering( + "", "

http://example.com

\n"); } @Test public void wwwLinks() { - assertRendering("www.example.com", + assertRendering( + "www.example.com", "

www.example.com

\n"); } @@ -77,14 +86,17 @@ public void noWwwLinks() { @Test public void sourceSpans() { - Parser parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); - Node document = parser.parse("abc\n" + - "http://example.com/one\n" + - "def http://example.com/two\n" + - "ghi http://example.com/three jkl"); + Parser parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); + Node document = + parser.parse( + "abc\n" + + "http://example.com/one\n" + + "def http://example.com/two\n" + + "ghi http://example.com/three jkl"); Paragraph paragraph = (Paragraph) document.getFirstChild(); Text abc = (Text) paragraph.getFirstChild(); diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteDefinition.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteDefinition.java index 4a560dc9e..c89bca9f8 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteDefinition.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteDefinition.java @@ -4,13 +4,16 @@ /** * A footnote definition, e.g.: + * *

  * [^foo]: This is the footnote text
  * 
- * The {@link #getLabel() label} is the text in brackets after {@code ^}, so {@code foo} in the example. The contents - * of the footnote are child nodes of the definition, a {@link org.commonmark.node.Paragraph} in the example. - *

- * Footnote definitions are parsed even if there's no corresponding {@link FootnoteReference}. + * + * The {@link #getLabel() label} is the text in brackets after {@code ^}, so {@code foo} in the + * example. The contents of the footnote are child nodes of the definition, a {@link + * org.commonmark.node.Paragraph} in the example. + * + *

Footnote definitions are parsed even if there's no corresponding {@link FootnoteReference}. */ public class FootnoteDefinition extends CustomBlock { @@ -24,4 +27,3 @@ public String getLabel() { return label; } } - diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteReference.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteReference.java index 61dcf8626..c0382fff1 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteReference.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteReference.java @@ -4,9 +4,10 @@ /** * A footnote reference, e.g. [^foo] in Some text with a footnote[^foo] - *

- * The {@link #getLabel() label} is the text within brackets after {@code ^}, so {@code foo} in the example. It needs to - * match the label of a corresponding {@link FootnoteDefinition} for the footnote to be parsed. + * + *

The {@link #getLabel() label} is the text within brackets after {@code ^}, so {@code foo} in + * the example. It needs to match the label of a corresponding {@link FootnoteDefinition} for the + * footnote to be parsed. */ public class FootnoteReference extends CustomNode { private String label; diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnotesExtension.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnotesExtension.java index dd532fa34..4517d14d6 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnotesExtension.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnotesExtension.java @@ -1,5 +1,6 @@ package org.commonmark.ext.footnotes; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.ext.footnotes.internal.*; import org.commonmark.parser.Parser; @@ -9,32 +10,37 @@ import org.commonmark.renderer.markdown.MarkdownNodeRendererFactory; import org.commonmark.renderer.markdown.MarkdownRenderer; -import java.util.Set; - /** * Extension for footnotes with syntax like GitHub Flavored Markdown: + * *


  * Some text with a footnote[^1].
  *
  * [^1]: The text of the footnote.
  * 
+ * * The [^1] is a {@link FootnoteReference}, with "1" being the label. - *

- * The line with [^1]: ... is a {@link FootnoteDefinition}, with the contents as child nodes (can be a - * paragraph like in the example, or other blocks like lists). - *

- * All the footnotes (definitions) will be rendered in a list at the end of a document, no matter where they appear in - * the source. The footnotes will be numbered starting from 1, then 2, etc, depending on the order in which they appear - * in the text (and not dependent on the label). The footnote reference is a link to the footnote, and from the footnote - * there is a link back to the reference (or multiple). - *

- * There is also optional support for inline footnotes, use {@link #builder()} and then set {@link Builder#inlineFootnotes}. * - * @see GitHub docs for footnotes + *

The line with [^1]: ... is a {@link FootnoteDefinition}, with the contents as + * child nodes (can be a paragraph like in the example, or other blocks like lists). + * + *

All the footnotes (definitions) will be rendered in a list at the end of a document, no matter + * where they appear in the source. The footnotes will be numbered starting from 1, then 2, etc, + * depending on the order in which they appear in the text (and not dependent on the label). The + * footnote reference is a link to the footnote, and from the footnote there is a link back to the + * reference (or multiple). + * + *

There is also optional support for inline footnotes, use {@link #builder()} and then set + * {@link Builder#inlineFootnotes}. + * + * @see GitHub + * docs for footnotes */ -public class FootnotesExtension implements Parser.ParserExtension, - HtmlRenderer.HtmlRendererExtension, - MarkdownRenderer.MarkdownRendererExtension { +public class FootnotesExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { private final boolean inlineFootnotes; @@ -42,9 +48,7 @@ private FootnotesExtension(boolean inlineFootnotes) { this.inlineFootnotes = inlineFootnotes; } - /** - * The extension with the default configuration (no support for inline footnotes). - */ + /** The extension with the default configuration (no support for inline footnotes). */ public static Extension create() { return builder().build(); } @@ -70,17 +74,18 @@ public void extend(HtmlRenderer.Builder rendererBuilder) { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new FootnoteMarkdownNodeRenderer(context); - } + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new FootnoteMarkdownNodeRenderer(context); + } - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }); + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + }); } public static class Builder { @@ -89,6 +94,7 @@ public static class Builder { /** * Enable support for inline footnotes without definitions, e.g.: + * *

          * Some text^[this is an inline footnote]
          * 
diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/InlineFootnote.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/InlineFootnote.java index 665d01936..cb16c45f6 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/InlineFootnote.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/InlineFootnote.java @@ -2,5 +2,4 @@ import org.commonmark.node.CustomNode; -public class InlineFootnote extends CustomNode { -} +public class InlineFootnote extends CustomNode {} diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteBlockParser.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteBlockParser.java index 110bdef20..db11b906a 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteBlockParser.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteBlockParser.java @@ -1,16 +1,13 @@ package org.commonmark.ext.footnotes.internal; +import java.util.List; import org.commonmark.ext.footnotes.FootnoteDefinition; import org.commonmark.node.Block; import org.commonmark.node.DefinitionMap; import org.commonmark.parser.block.*; import org.commonmark.text.Characters; -import java.util.List; - -/** - * Parser for a single {@link FootnoteDefinition} block. - */ +/** Parser for a single {@link FootnoteDefinition} block. */ public class FootnoteBlockParser extends AbstractBlockParser { private final FootnoteDefinition block; @@ -37,16 +34,18 @@ public boolean canContain(Block childBlock) { @Override public BlockContinue tryContinue(ParserState parserState) { if (parserState.getIndent() >= 4) { - // It looks like content needs to be indented by 4 so that it's part of a footnote (instead of starting a new block). + // It looks like content needs to be indented by 4 so that it's part of a footnote + // (instead of starting a new block). return BlockContinue.atColumn(4); } else if (parserState.isBlank()) { - // A blank line doesn't finish a footnote yet. If there's another line with indent >= 4 after it, - // that should result in another paragraph in this footnote definition. + // A blank line doesn't finish a footnote yet. If there's another line with indent >= 4 + // after it, that should result in another paragraph in this footnote definition. return BlockContinue.atIndex(parserState.getIndex()); } else { - // We're not continuing to give other block parsers a chance to interrupt this definition. - // But if no other block parser applied (including another FootnotesBlockParser), we will - // accept the line via lazy continuation (same as a block quote). + // We're not continuing to give other block parsers a chance to interrupt this + // definition. But if no other block parser applied (including another + // FootnotesBlockParser), we will accept the line via lazy continuation (same as a block + // quote). return BlockContinue.none(); } } @@ -82,11 +81,16 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar var c = content.charAt(index); switch (c) { case ']': - if (index > labelStart && index + 1 < content.length() && content.charAt(index + 1) == ':') { + if (index > labelStart + && index + 1 < content.length() + && content.charAt(index + 1) == ':') { var label = content.subSequence(labelStart, index).toString(); - // After the colon, any number of spaces is skipped (not part of the content) - var afterSpaces = Characters.skipSpaceTab(content, index + 2, content.length()); - return BlockStart.of(new FootnoteBlockParser(label)).atIndex(afterSpaces); + // After the colon, any number of spaces is skipped (not part of the + // content) + var afterSpaces = + Characters.skipSpaceTab(content, index + 2, content.length()); + return BlockStart.of(new FootnoteBlockParser(label)) + .atIndex(afterSpaces); } else { return BlockStart.none(); } diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteHtmlNodeRenderer.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteHtmlNodeRenderer.java index 70eb048a3..db88a8269 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteHtmlNodeRenderer.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteHtmlNodeRenderer.java @@ -1,5 +1,7 @@ package org.commonmark.ext.footnotes.internal; +import java.util.*; +import java.util.function.Consumer; import org.commonmark.ext.footnotes.FootnoteDefinition; import org.commonmark.ext.footnotes.FootnoteReference; import org.commonmark.ext.footnotes.InlineFootnote; @@ -8,64 +10,68 @@ import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.*; -import java.util.function.Consumer; - /** * HTML rendering for footnotes. - *

- * Aims to match the rendering of cmark-gfm (which is slightly different from GitHub's when it comes to class - * attributes, not sure why). - *

- * Some notes on how rendering works: + * + *

Aims to match the rendering of cmark-gfm (which is slightly different from GitHub's when it + * comes to class attributes, not sure why). + * + *

Some notes on how rendering works: + * *

    - *
  • Footnotes are numbered according to the order of references, starting at 1
  • - *
  • Definitions are rendered at the end of the document, regardless of where the definition was in the source
  • - *
  • Definitions are ordered by number
  • - *
  • Definitions have links back to their references (one or more)
  • + *
  • Footnotes are numbered according to the order of references, starting at 1 + *
  • Definitions are rendered at the end of the document, regardless of where the definition was + * in the source + *
  • Definitions are ordered by number + *
  • Definitions have links back to their references (one or more) *
* *

Nested footnotes

- * Text in footnote definitions can reference other footnotes, even ones that aren't referenced in the main text. - * This makes them tricky because it's not enough to just go through the main text for references. - * And before we can render a definition, we need to know all references (because we add links back to references). - *

- * In other words, footnotes form a directed graph. Footnotes can reference each other so cycles are possible too. - *

- * One way to implement it, which is what cmark-gfm does, is to go through the whole document (including definitions) - * and find all references in order. That guarantees that all definitions are found, but it has strange results for - * ordering or when the reference is in an unreferenced definition, see tests. In graph terms, it renders all - * definitions that have an incoming edge, no matter whether they are connected to the main text or not. - *

- * The way we implement it: + * + * Text in footnote definitions can reference other footnotes, even ones that aren't referenced in + * the main text. This makes them tricky because it's not enough to just go through the main text + * for references. And before we can render a definition, we need to know all references (because we + * add links back to references). + * + *

In other words, footnotes form a directed graph. Footnotes can reference each other so cycles + * are possible too. + * + *

One way to implement it, which is what cmark-gfm does, is to go through the whole document + * (including definitions) and find all references in order. That guarantees that all definitions + * are found, but it has strange results for ordering or when the reference is in an unreferenced + * definition, see tests. In graph terms, it renders all definitions that have an incoming edge, no + * matter whether they are connected to the main text or not. + * + *

The way we implement it: + * *

    - *
  1. Start with the references in the main text; we can render them as we go
  2. - *
  3. After the main text is rendered, we have the referenced definitions, but there might be more from definition text
  4. - *
  5. To find the remaining definitions, we visit the definitions from before to look at references
  6. - *
  7. Repeat (breadth-first search) until we've found all definitions (note that we can't render before that's done because of backrefs)
  8. - *
  9. Now render the definitions (and any references inside)
  10. + *
  11. Start with the references in the main text; we can render them as we go + *
  12. After the main text is rendered, we have the referenced definitions, but there might be + * more from definition text + *
  13. To find the remaining definitions, we visit the definitions from before to look at + * references + *
  14. Repeat (breadth-first search) until we've found all definitions (note that we can't render + * before that's done because of backrefs) + *
  15. Now render the definitions (and any references inside) *
- * This means we only render definitions whose references are actually rendered, and in a meaningful order (all main - * text footnotes first, then any nested ones). + * + * This means we only render definitions whose references are actually rendered, and in a meaningful + * order (all main text footnotes first, then any nested ones). */ public class FootnoteHtmlNodeRenderer implements NodeRenderer { private final HtmlWriter html; private final HtmlNodeRendererContext context; - /** - * All definitions (even potentially unused ones), for looking up references - */ + /** All definitions (even potentially unused ones), for looking up references */ private DefinitionMap definitionMap; - /** - * Definitions that were referenced, in order in which they should be rendered. - */ + /** Definitions that were referenced, in order in which they should be rendered. */ private final Map referencedDefinitions = new LinkedHashMap<>(); /** - * Information about references that should be rendered as footnotes. This doesn't contain all references, just the - * ones from inside definitions. + * Information about references that should be rendered as footnotes. This doesn't contain all + * references, just the ones from inside definitions. */ private final Map references = new HashMap<>(); @@ -81,7 +87,8 @@ public Set> getNodeTypes() { @Override public void beforeRoot(Node rootNode) { - // Collect all definitions first, so we can look them up when encountering a reference later. + // Collect all definitions first, so we can look them up when encountering a reference + // later. var visitor = new DefinitionVisitor(); rootNode.accept(visitor); definitionMap = visitor.definitions; @@ -90,11 +97,12 @@ public void beforeRoot(Node rootNode) { @Override public void render(Node node) { if (node instanceof FootnoteReference) { - // This is called for all references, even ones inside definitions that we render at the end. - // Inside definitions, we have registered the reference already. + // This is called for all references, even ones inside definitions that we render at the + // end. Inside definitions, we have registered the reference already. var ref = (FootnoteReference) node; // Use containsKey because if value is null, we don't need to try registering again. - var info = references.containsKey(ref) ? references.get(ref) : tryRegisterReference(ref); + var info = + references.containsKey(ref) ? references.get(ref) : tryRegisterReference(ref); if (info != null) { renderReference(ref, info); } else { @@ -126,26 +134,30 @@ public void afterRoot(Node rootNode) { html.tag("ol"); html.line(); - // Check whether there are any footnotes inside the definitions that we're about to render. For those, we might - // need to render more definitions. So do a breadth-first search to find all relevant definitions. + // Check whether there are any footnotes inside the definitions that we're about to render. + // For those, we might need to render more definitions. So do a breadth-first search to find + // all relevant definitions. var check = new LinkedList<>(referencedDefinitions.keySet()); while (!check.isEmpty()) { var def = check.removeFirst(); - def.accept(new ShallowReferenceVisitor(def, node -> { - if (node instanceof FootnoteReference) { - var ref = (FootnoteReference) node; - var d = definitionMap.get(ref.getLabel()); - if (d != null) { - if (!referencedDefinitions.containsKey(d)) { - check.addLast(d); - } - references.put(ref, registerReference(d, d.getLabel())); - } - } else if (node instanceof InlineFootnote) { - check.addLast(node); - references.put(node, registerReference(node, null)); - } - })); + def.accept( + new ShallowReferenceVisitor( + def, + node -> { + if (node instanceof FootnoteReference) { + var ref = (FootnoteReference) node; + var d = definitionMap.get(ref.getLabel()); + if (d != null) { + if (!referencedDefinitions.containsKey(d)) { + check.addLast(d); + } + references.put(ref, registerReference(d, d.getLabel())); + } + } else if (node instanceof InlineFootnote) { + check.addLast(node); + references.put(node, registerReference(node, null)); + } + })); } for (var entry : referencedDefinitions.entrySet()) { @@ -169,15 +181,19 @@ private ReferenceInfo tryRegisterReference(FootnoteReference ref) { private ReferenceInfo registerReference(Node node, String label) { // The first referenced definition gets number 1, second one 2, etc. - var referencedDef = referencedDefinitions.computeIfAbsent(node, k -> { - var num = referencedDefinitions.size() + 1; - var key = definitionKey(label, num); - return new ReferencedDefinition(num, key); - }); + var referencedDef = + referencedDefinitions.computeIfAbsent( + node, + k -> { + var num = referencedDefinitions.size() + 1; + var key = definitionKey(label, num); + return new ReferencedDefinition(num, key); + }); var definitionNumber = referencedDef.definitionNumber; - // The reference number for that particular definition. E.g. if there's two references for the same definition, - // the first one is 1, the second one 2, etc. This is needed to give each reference a unique ID so that each - // reference can get its own backlink from the definition. + // The reference number for that particular definition. E.g. if there's two references for + // the same definition, the first one is 1, the second one 2, etc. This is needed to give + // each reference a unique ID so that each reference can get its own backlink from the + // definition. var refNumber = referencedDef.references.size() + 1; var definitionKey = referencedDef.definitionKey; var id = referenceId(definitionKey, refNumber); @@ -212,8 +228,9 @@ private void renderDefinition(Node def, ReferencedDefinition referencedDefinitio var node = def.getFirstChild(); while (node != lastParagraph) { if (node instanceof Paragraph) { - // Because we're manually rendering the

for the last paragraph, do the same for all other - // paragraphs for consistency (Paragraph rendering might be overwritten by a custom renderer). + // Because we're manually rendering the

for the last paragraph, do the same + // for all other paragraphs for consistency (Paragraph rendering might be + // overwritten by a custom renderer). html.tag("p", context.extendAttributes(node, "p", Map.of())); renderChildren(node); html.tag("/p"); @@ -252,7 +269,9 @@ private void renderBackrefs(Node def, ReferencedDefinition referencedDefinition) for (int i = 0; i < refs.size(); i++) { var ref = refs.get(i); var refNumber = i + 1; - var idx = referencedDefinition.definitionNumber + (refNumber > 1 ? ("-" + refNumber) : ""); + var idx = + referencedDefinition.definitionNumber + + (refNumber > 1 ? ("-" + refNumber) : ""); var attrs = new LinkedHashMap(); attrs.put("href", "#" + ref); @@ -262,7 +281,9 @@ private void renderBackrefs(Node def, ReferencedDefinition referencedDefinition) attrs.put("aria-label", "Back to reference " + idx); html.tag("a", context.extendAttributes(def, "a", attrs)); if (refNumber > 1) { - html.tag("sup", context.extendAttributes(def, "sup", Map.of("class", "footnote-ref"))); + html.tag( + "sup", + context.extendAttributes(def, "sup", Map.of("class", "footnote-ref"))); html.raw(String.valueOf(refNumber)); html.tag("/sup"); } @@ -280,8 +301,9 @@ private String referenceId(String definitionKey, int number) { } private String definitionKey(String label, int number) { - // Named definitions use the pattern "fn-{name}" and inline definitions use "fn{number}" so as not to conflict. - // "fn{number}" is also what pandoc uses (for all types), starting with number 1. + // Named definitions use the pattern "fn-{name}" and inline definitions use "fn{number}" so + // as not to conflict. "fn{number}" is also what pandoc uses (for all types), starting with + // number 1. if (label != null) { return "-" + label; } else { @@ -304,7 +326,8 @@ private void renderChildren(Node parent) { private static class DefinitionVisitor extends AbstractVisitor { - private final DefinitionMap definitions = new DefinitionMap<>(FootnoteDefinition.class); + private final DefinitionMap definitions = + new DefinitionMap<>(FootnoteDefinition.class); @Override public void visit(CustomBlock customBlock) { @@ -318,8 +341,8 @@ public void visit(CustomBlock customBlock) { } /** - * Visit footnote references/inline footnotes inside the parent (but not the parent itself). We want a shallow visit - * because the caller wants to control when to descend. + * Visit footnote references/inline footnotes inside the parent (but not the parent itself). We + * want a shallow visit because the caller wants to control when to descend. */ private static class ShallowReferenceVisitor extends AbstractVisitor { private final Node parent; @@ -349,17 +372,16 @@ public void visit(CustomNode customNode) { } private static class ReferencedDefinition { - /** - * The definition number, starting from 1, and in order in which they're referenced. - */ + /** The definition number, starting from 1, and in order in which they're referenced. */ final int definitionNumber; + /** - * The unique key of the definition. Together with a static prefix it forms the ID used in the HTML. + * The unique key of the definition. Together with a static prefix it forms the ID used in + * the HTML. */ final String definitionKey; - /** - * The IDs of references for this definition, for backrefs. - */ + + /** The IDs of references for this definition, for backrefs. */ final List references = new ArrayList<>(); ReferencedDefinition(int definitionNumber, String definitionKey) { @@ -370,16 +392,15 @@ private static class ReferencedDefinition { private static class ReferenceInfo { /** - * The ID of the reference; in the corresponding definition, a link back to this reference will be rendered. + * The ID of the reference; in the corresponding definition, a link back to this reference + * will be rendered. */ private final String id; - /** - * The ID of the definition, for linking to the definition. - */ + + /** The ID of the definition, for linking to the definition. */ private final String definitionId; - /** - * The definition number, rendered in superscript. - */ + + /** The definition number, rendered in superscript. */ private final int definitionNumber; private ReferenceInfo(String id, String definitionId, int definitionNumber) { diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteLinkProcessor.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteLinkProcessor.java index 07b008576..66a889855 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteLinkProcessor.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteLinkProcessor.java @@ -11,17 +11,18 @@ import org.commonmark.parser.beta.Scanner; /** - * For turning e.g. [^foo] into a {@link FootnoteReference}, - * and ^[foo] into an {@link InlineFootnote}. + * For turning e.g. [^foo] into a {@link FootnoteReference}, and ^[foo] + * into an {@link InlineFootnote}. */ public class FootnoteLinkProcessor implements LinkProcessor { @Override public LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContext context) { if (linkInfo.marker() != null && linkInfo.marker().getLiteral().equals("^")) { - // An inline footnote like ^[footnote text]. Note that we only get the marker here if the option is enabled - // on the extension. - return LinkResult.wrapTextIn(new InlineFootnote(), linkInfo.afterTextBracket()).includeMarker(); + // An inline footnote like ^[footnote text]. Note that we only get the marker here if + // the option is enabled on the extension. + return LinkResult.wrapTextIn(new InlineFootnote(), linkInfo.afterTextBracket()) + .includeMarker(); } if (linkInfo.destination() != null) { @@ -35,21 +36,25 @@ public LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContex return LinkResult.none(); } - if (linkInfo.label() != null && context.getDefinition(LinkReferenceDefinition.class, linkInfo.label()) != null) { - // If there's a label after the text and the label has a definition -> it's a link, and it should take - // preference, e.g. in `[^foo][bar]` if `[bar]` has a definition, `[^foo]` won't be a footnote reference. + if (linkInfo.label() != null + && context.getDefinition(LinkReferenceDefinition.class, linkInfo.label()) != null) { + // If there's a label after the text and the label has a definition -> it's a link, and + // it should take preference, e.g. in `[^foo][bar]` if `[bar]` has a definition, + // `[^foo]` won't be a footnote reference. return LinkResult.none(); } var label = text.substring(1); - // Check if we have a definition, otherwise ignore (same behavior as for link reference definitions). - // Note that the definition parser already checked the syntax of the label, we don't need to check again. + // Check if we have a definition, otherwise ignore (same behavior as for link reference + // definitions). Note that the definition parser already checked the syntax of the label, we + // don't need to check again. var def = context.getDefinition(FootnoteDefinition.class, label); if (def == null) { return LinkResult.none(); } - // For footnotes, we only ever consume the text part of the link, not the label part (if any) + // For footnotes, we only ever consume the text part of the link, not the label part (if + // any) var position = linkInfo.afterTextBracket(); // If the marker is `![`, we don't want to include the `!`, so start from bracket return LinkResult.replaceWith(new FootnoteReference(label), position); diff --git a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteMarkdownNodeRenderer.java b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteMarkdownNodeRenderer.java index 3dcf4fc83..0e654cf5e 100644 --- a/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteMarkdownNodeRenderer.java +++ b/commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteMarkdownNodeRenderer.java @@ -1,5 +1,6 @@ package org.commonmark.ext.footnotes.internal; +import java.util.Set; import org.commonmark.ext.footnotes.FootnoteDefinition; import org.commonmark.ext.footnotes.FootnoteReference; import org.commonmark.ext.footnotes.InlineFootnote; @@ -8,8 +9,6 @@ import org.commonmark.renderer.markdown.MarkdownNodeRendererContext; import org.commonmark.renderer.markdown.MarkdownWriter; -import java.util.Set; - public class FootnoteMarkdownNodeRenderer implements NodeRenderer { private final MarkdownWriter writer; diff --git a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteHtmlRendererTest.java b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteHtmlRendererTest.java index bc7d4f74c..1a89693b4 100644 --- a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteHtmlRendererTest.java +++ b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteHtmlRendererTest.java @@ -1,5 +1,7 @@ package org.commonmark.ext.footnotes; +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Document; import org.commonmark.node.Paragraph; @@ -10,40 +12,40 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - public class FootnoteHtmlRendererTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(FootnotesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testOne() { - assertRendering("Test [^foo]\n\n[^foo]: note\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    note

    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + assertRendering( + "Test [^foo]\n\n[^foo]: note\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    note

    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } @Test public void testLabelNormalization() { - // Labels match via their normalized form. For the href and IDs to match, rendering needs to use the - // label from the definition consistently. - assertRendering("Test [^bar]\n\n[^BAR]: note\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    note

    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + // Labels match via their normalized form. For the href and IDs to match, rendering needs to + // use the label from the definition consistently. + assertRendering( + "Test [^bar]\n\n[^BAR]: note\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    note

    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } @Test @@ -52,254 +54,251 @@ public void testMultipleReferences() { // - Numbering is based on the reference order, not the definition order // - The same number is used when a definition is referenced multiple times // - Multiple backrefs are rendered - assertRendering("First [^foo]\n\nThen [^bar]\n\nThen [^foo] again\n\n[^bar]: b\n[^foo]: f\n", - "

First 1

\n" + - "

Then 2

\n" + - "

Then 1 again

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    f 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    b

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRendering( + "First [^foo]\n\nThen [^bar]\n\nThen [^foo] again\n\n[^bar]: b\n[^foo]: f\n", + "

First 1

\n" + + "

Then 2

\n" + + "

Then 1 again

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    f 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    b

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testDefinitionWithTwoParagraphs() { // With two paragraphs, the backref should be added to the second one - assertRendering("Test [^foo]\n\n[^foo]: one\n \n two\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    one

    \n" + - "

    two

    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + assertRendering( + "Test [^foo]\n\n[^foo]: one\n \n two\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    one

    \n" + + "

    two

    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } @Test public void testDefinitionWithList() { - assertRendering("Test [^foo]\n\n[^foo]:\n - one\n - two\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "
      \n" + - "
    • one
    • \n" + - "
    • two
    • \n" + - "
    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + assertRendering( + "Test [^foo]\n\n[^foo]:\n - one\n - two\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "
      \n" + + "
    • one
    • \n" + + "
    • two
    • \n" + + "
    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } // See docs on FootnoteHtmlNodeRenderer about nested footnotes. @Test public void testNestedFootnotesSimple() { - assertRendering("[^foo1]\n" + - "\n" + - "[^foo1]: one [^foo2]\n" + - "[^foo2]: two\n", "

1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    one 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    two

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRendering( + "[^foo1]\n" + "\n" + "[^foo1]: one [^foo2]\n" + "[^foo2]: two\n", + "

1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    one 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    two

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testNestedFootnotesOrder() { // GitHub has a strange result here, the definitions are in order: 1. bar, 2. foo. - // The reason is that the number is done based on all references in document order, including references in - // definitions. So [^bar] from the first line is first. - assertRendering("[^foo]: foo [^bar]\n" + - "\n" + - "[^foo]\n" + - "\n" + - "[^bar]: bar\n", "

1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    foo 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    bar

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + // The reason is that the number is done based on all references in document order, + // including references in definitions. So [^bar] from the first line is first. + assertRendering( + "[^foo]: foo [^bar]\n" + "\n" + "[^foo]\n" + "\n" + "[^bar]: bar\n", + "

1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    foo 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    bar

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testNestedFootnotesOrder2() { - assertRendering("[^1]\n" + - "\n" + - "[^4]: four\n" + - "[^3]: three [^4]\n" + - "[^2]: two [^4]\n" + - "[^1]: one [^2][^3]\n", "

1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    one 23

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    two 4

    \n" + - "
  4. \n" + - "
  5. \n" + - "

    three 4

    \n" + - "
  6. \n" + - "
  7. \n" + - "

    four 2

    \n" + - "
  8. \n" + - "
\n" + - "
\n"); + assertRendering( + "[^1]\n" + + "\n" + + "[^4]: four\n" + + "[^3]: three [^4]\n" + + "[^2]: two [^4]\n" + + "[^1]: one [^2][^3]\n", + "

1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    one 23

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    two 4

    \n" + + "
  4. \n" + + "
  5. \n" + + "

    three 4

    \n" + + "
  6. \n" + + "
  7. \n" + + "

    four 2

    \n" + + "
  8. \n" + + "
\n" + + "
\n"); } @Test public void testNestedFootnotesCycle() { // Footnotes can contain cycles, lol. - assertRendering("[^foo1]\n" + - "\n" + - "[^foo1]: one [^foo2]\n" + - "[^foo2]: two [^foo1]\n", "

1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    one 2 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    two 1

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRendering( + "[^foo1]\n" + "\n" + "[^foo1]: one [^foo2]\n" + "[^foo2]: two [^foo1]\n", + "

1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    one 2 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    two 1

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testNestedFootnotesUnreferenced() { // This should not result in any footnotes, as baz itself isn't referenced. // But GitHub renders bar only, with a broken backref, because bar is referenced from foo. - assertRendering("[^foo]: foo[^bar]\n" + - "[^bar]: bar\n", ""); + assertRendering("[^foo]: foo[^bar]\n" + "[^bar]: bar\n", ""); // And here only 1 is rendered. - assertRendering("[^1]\n" + - "\n" + - "[^1]: one\n" + - "[^foo]: foo[^bar]\n" + - "[^bar]: bar\n", "

1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    one

    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + assertRendering( + "[^1]\n" + "\n" + "[^1]: one\n" + "[^foo]: foo[^bar]\n" + "[^bar]: bar\n", + "

1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    one

    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } @Test public void testInlineFootnotes() { - assertRenderingInline("Test ^[inline *footnote*]", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    inline footnote

    \n" + - "
  2. \n" + - "
\n" + - "
\n"); + assertRenderingInline( + "Test ^[inline *footnote*]", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    inline footnote

    \n" + + "
  2. \n" + + "
\n" + + "
\n"); } @Test public void testInlineFootnotesNested() { - assertRenderingInline("Test ^[inline ^[nested]]", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    inline 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    nested

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRenderingInline( + "Test ^[inline ^[nested]]", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    inline 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    nested

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testInlineFootnoteWithReference() { // This is a bit tricky because the IDs need to be unique. - assertRenderingInline("Test ^[inline [^1]]\n" + - "\n" + - "[^1]: normal", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    inline 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    normal

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRenderingInline( + "Test ^[inline [^1]]\n" + "\n" + "[^1]: normal", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    inline 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    normal

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testInlineFootnoteInsideDefinition() { - assertRenderingInline("Test [^1]\n" + - "\n" + - "[^1]: Definition ^[inline]\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    Definition 2

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    inline

    \n" + - "
  4. \n" + - "
\n" + - "
\n"); + assertRenderingInline( + "Test [^1]\n" + "\n" + "[^1]: Definition ^[inline]\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    Definition 2

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    inline

    \n" + + "
  4. \n" + + "
\n" + + "
\n"); } @Test public void testInlineFootnoteInsideDefinition2() { - // Tricky because of the nested inline footnote which we want to visit after foo (breadth-first). - assertRenderingInline("Test [^1]\n" + - "\n" + - "[^1]: Definition ^[inline ^[nested]] ^[foo]\n", - "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    Definition 2 3

    \n" + - "
  2. \n" + - "
  3. \n" + - "

    inline 4

    \n" + - "
  4. \n" + - "
  5. \n" + - "

    foo

    \n" + - "
  6. \n" + - "
  7. \n" + - "

    nested

    \n" + - "
  8. \n" + - "
\n" + - "
\n"); + // Tricky because of the nested inline footnote which we want to visit after foo + // (breadth-first). + assertRenderingInline( + "Test [^1]\n" + "\n" + "[^1]: Definition ^[inline ^[nested]] ^[foo]\n", + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    Definition 2 3

    \n" + + "
  2. \n" + + "
  3. \n" + + "

    inline 4

    \n" + + "
  4. \n" + + "
  5. \n" + + "

    foo

    \n" + + "
  6. \n" + + "
  7. \n" + + "

    nested

    \n" + + "
  8. \n" + + "
\n" + + "
\n"); } - @Test public void testRenderNodesDirectly() { // Everything should work as expected when rendering from nodes directly (no parsing step). @@ -314,14 +313,15 @@ public void testRenderNodesDirectly() { doc.appendChild(p); doc.appendChild(def); - var expected = "

Test 1

\n" + - "
\n" + - "
    \n" + - "
  1. \n" + - "

    note!

    \n" + - "
  2. \n" + - "
\n" + - "
\n"; + var expected = + "

Test 1

\n" + + "
\n" + + "
    \n" + + "
  1. \n" + + "

    note!

    \n" + + "
  2. \n" + + "
\n" + + "
\n"; Asserts.assertRendering("", expected, RENDERER.render(doc)); } diff --git a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java index 2f1125a02..3c6febe7b 100644 --- a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java +++ b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java @@ -1,19 +1,20 @@ package org.commonmark.ext.footnotes; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class FootnoteMarkdownRendererTest { - private static final Set EXTENSIONS = Set.of(FootnotesExtension.builder().inlineFootnotes(true).build()); + private static final Set EXTENSIONS = + Set.of(FootnotesExtension.builder().inlineFootnotes(true).build()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testSimple() { @@ -22,7 +23,8 @@ public void testSimple() { @Test public void testUnreferenced() { - // Whether a reference has a corresponding definition or vice versa shouldn't matter for Markdown rendering. + // Whether a reference has a corresponding definition or vice versa shouldn't matter for + // Markdown rendering. assertRoundTrip("Test [^foo]\n\n[^foo]: one\n\n[^bar]: two\n"); } @@ -43,8 +45,8 @@ public void testMultipleLines() { @Test public void testMultipleParagraphs() { - // Note that the line between p1 and p2 could be blank too (instead of 4 spaces), but we currently don't - // preserve that information. + // Note that the line between p1 and p2 could be blank too (instead of 4 spaces), but we + // currently don't preserve that information. assertRoundTrip("Test [^1]\n\n[^1]: footnote p1\n \n footnote p2\n"); } diff --git a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnotesTest.java b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnotesTest.java index 7763cedb4..ca76e47cd 100644 --- a/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnotesTest.java +++ b/commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnotesTest.java @@ -1,17 +1,16 @@ package org.commonmark.ext.footnotes; -import org.commonmark.Extension; -import org.commonmark.node.*; -import org.commonmark.parser.IncludeSourceSpans; -import org.commonmark.parser.Parser; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; +import org.commonmark.Extension; +import org.commonmark.node.*; +import org.commonmark.parser.IncludeSourceSpans; +import org.commonmark.parser.Parser; +import org.junit.jupiter.api.Test; public class FootnotesTest { @@ -35,7 +34,8 @@ public void testDefBlockStart() { @Test public void testDefBlockStartInterrupts() { - // This is different from a link reference definition, which can only be at the start of paragraphs. + // This is different from a link reference definition, which can only be at the start of + // paragraphs. var doc = PARSER.parse("test\n[^1]: footnote\n"); var paragraph = find(doc, Paragraph.class); var def = find(doc, FootnoteDefinition.class); @@ -172,7 +172,8 @@ public void testRefWithEmphasisInside() { @Test public void testRefWithEmphasisAround() { - // Emphasis around footnote reference, the * inside needs to be removed from emphasis processing + // Emphasis around footnote reference, the * inside needs to be removed from emphasis + // processing var doc = PARSER.parse("Test *abc [^foo*] def*\n\n[^foo*]: def\n"); var ref = find(doc, FootnoteReference.class); assertThat(ref.getLabel()).isEqualTo("foo*"); @@ -193,8 +194,9 @@ public void testRefAfterBang() { @Test public void testRefAsLabelOnly() { - // [^bar] is a footnote but [foo] is just text, because full reference links (text `foo`, label `^bar`) don't - // resolve as footnotes. If `[foo][^bar]` fails to parse as a bracket, `[^bar]` by itself needs to be tried. + // [^bar] is a footnote but [foo] is just text, because full reference links (text `foo`, + // label `^bar`) don't resolve as footnotes. If `[foo][^bar]` fails to parse as a bracket, + // `[^bar]` by itself needs to be tried. var doc = PARSER.parse("Test [foo][^bar]\n\n[^bar]: footnote\n"); var ref = find(doc, FootnoteReference.class); assertThat(ref.getLabel()).isEqualTo("bar"); @@ -204,7 +206,8 @@ public void testRefAsLabelOnly() { @Test public void testRefWithEmptyLabel() { - // [^bar] is a footnote but [] is just text, because collapsed reference links don't resolve as footnotes + // [^bar] is a footnote but [] is just text, because collapsed reference links don't resolve + // as footnotes var doc = PARSER.parse("Test [^bar][]\n\n[^bar]: footnote\n"); var ref = find(doc, FootnoteReference.class); assertThat(ref.getLabel()).isEqualTo("bar"); @@ -237,8 +240,8 @@ public void testPreferInlineLink() { @Test public void testPreferReferenceLink() { - // This is tricky because `[^*foo*][foo]` is a valid link already. If `[foo]` was not defined, the first bracket - // would be a footnote. + // This is tricky because `[^*foo*][foo]` is a valid link already. If `[foo]` was not + // defined, the first bracket would be a footnote. var doc = PARSER.parse("Test [^*foo*][foo]\n\n[^*foo*]: /url\n\n[foo]: /url"); assertNone(doc, FootnoteReference.class); } @@ -256,10 +259,13 @@ public void testReferenceLinkWithoutDefinition() { @Test public void testFootnoteInLink() { - // Expected to behave the same way as a link within a link, see https://spec.commonmark.org/0.31.2/#example-518 - // i.e. the first (inner) link is parsed, which means the outer one becomes plain text, as nesting links is not - // allowed. - var doc = PARSER.parse("[link with footnote ref [^1]](https://example.com)\n\n[^1]: footnote\n"); + // Expected to behave the same way as a link within a link, see + // https://spec.commonmark.org/0.31.2/#example-518 + // i.e. the first (inner) link is parsed, which means the outer one becomes plain text, as + // nesting links is not allowed. + var doc = + PARSER.parse( + "[link with footnote ref [^1]](https://example.com)\n\n[^1]: footnote\n"); var ref = find(doc, FootnoteReference.class); assertThat(ref.getLabel()).isEqualTo("1"); var paragraph = doc.getFirstChild(); @@ -269,7 +275,9 @@ public void testFootnoteInLink() { @Test public void testFootnoteWithMarkerInLink() { - var doc = PARSER.parse("[link with footnote ref ![^1]](https://example.com)\n\n[^1]: footnote\n"); + var doc = + PARSER.parse( + "[link with footnote ref ![^1]](https://example.com)\n\n[^1]: footnote\n"); var ref = find(doc, FootnoteReference.class); assertThat(ref.getLabel()).isEqualTo("1"); var paragraph = doc.getFirstChild(); @@ -325,7 +333,11 @@ public void testInlineFootnote() { @Test public void testSourcePositions() { - var parser = Parser.builder().extensions(EXTENSIONS).includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build(); + var parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); var doc = parser.parse("Test [^foo]\n\n[^foo]: /url\n"); var ref = find(doc, FootnoteReference.class); @@ -336,11 +348,15 @@ public void testSourcePositions() { } private static void assertNone(Node parent, Class nodeClass) { - assertThat(tryFind(parent, nodeClass)).as(() -> "Node " + parent + " containing " + nodeClass).isNull(); + assertThat(tryFind(parent, nodeClass)) + .as(() -> "Node " + parent + " containing " + nodeClass) + .isNull(); } private static T find(Node parent, Class nodeClass) { - return Objects.requireNonNull(tryFind(parent, nodeClass), "Could not find a " + nodeClass.getSimpleName() + " node in " + parent); + return Objects.requireNonNull( + tryFind(parent, nodeClass), + "Could not find a " + nodeClass.getSimpleName() + " node in " + parent); } private static T tryFind(Node parent, Class nodeClass) { diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/Alert.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/Alert.java index 71c35d24d..5725d53cd 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/Alert.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/Alert.java @@ -21,31 +21,32 @@ public String getType() { /** * @return Whether this alert has any body content (not including the title). - *

+ *

- Examples where this would be {@code true}: + *

{@code
+     * > [!NOTE]
+     * > Body text
      *
-     * - Examples where this would be {@code true}:
-     *   
{@code
-     *   > [!NOTE]
-     *   > Body text
-     *   }
- *
{@code
-     *   > [!NOTE] Custom title
-     *   > Body text
-     *   }
+ * }
+ *
{@code
+     * > [!NOTE] Custom title
+     * > Body text
      *
-     * - Examples where this would be {@code false}:
+     * }
+ * - Examples where this would be {@code false}: + *
{@code
+     * > [!NOTE]
      *
-     *   
{@code
-     *   > [!NOTE]
-     *   }
- *
{@code
-     *   > [!NOTE]
-     *   >
-     *   >
-     *   }
- *
{@code
-     *   > [!NOTE] Custom title
-     *   }
+ * }
+ *
{@code
+     * > [!NOTE]
+     * >
+     * >
+     *
+     * }
+ *
{@code
+     * > [!NOTE] Custom title
+     *
+     * }
*/ public boolean hasBody() { var first = this.getFirstChild(); diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertTitle.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertTitle.java index c085af746..fc537759c 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertTitle.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertTitle.java @@ -5,20 +5,18 @@ /** * Inline content container for the optional custom title of an {@link Alert}. * - *

- * When present, an {@code AlertTitle} is always the first child of an {@link Alert}. - * Its own children are the parsed inline nodes of the title (i.e., the text after - * the {@code [!TYPE]} marker on the same line). For example, in + *

When present, an {@code AlertTitle} is always the first child of an {@link Alert}. Its own + * children are the parsed inline nodes of the title (i.e., the text after the {@code [!TYPE]} + * marker on the same line). For example, in * *

{@code
  * > [!NOTE] Custom _title_
  * > Body text
  * }
* - * the {@code AlertTitle} contains a {@code Text} node ({@code "Custom "}) followed - * by an {@code Emphasis} node wrapping {@code "title"}. + * the {@code AlertTitle} contains a {@code Text} node ({@code "Custom "}) followed by an {@code + * Emphasis} node wrapping {@code "title"}. * * @see AlertsExtension.Builder#allowCustomTitles(boolean) */ -public class AlertTitle extends CustomNode { -} +public class AlertTitle extends CustomNode {} diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertsExtension.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertsExtension.java index ed81a2c3f..3035c9952 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertsExtension.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertsExtension.java @@ -1,5 +1,11 @@ package org.commonmark.ext.gfm.alerts; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.ext.gfm.alerts.internal.AlertBlockParser; import org.commonmark.ext.gfm.alerts.internal.AlertHtmlNodeRenderer; @@ -13,61 +19,60 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.commonmark.renderer.text.TextContentRenderer; -import java.util.HashMap; -import java.util.Locale; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - /** * Extension for GFM alerts using {@code [!TYPE]} syntax (GitHub Flavored Markdown). - *

- * Create with {@link #create()} or {@link #builder()} and configure on builders - * ({@link Parser.Builder#extensions(Iterable)}, {@link HtmlRenderer.Builder#extensions(Iterable)}). - * Parsed alerts become {@link Alert} blocks. If custom alert titles are allowed - * via {@link Builder#allowCustomTitles(boolean)}, the inline formatting of those - * titles will be parsed into {@link AlertTitle} nodes. * - * The {@link #create() default configuration} of this extension will match GFM - * exactly, with the following exceptions: + *

Create with {@link #create()} or {@link #builder()} and configure on builders ({@link + * Parser.Builder#extensions(Iterable)}, {@link HtmlRenderer.Builder#extensions(Iterable)}). Parsed + * alerts become {@link Alert} blocks. If custom alert titles are allowed via {@link + * Builder#allowCustomTitles(boolean)}, the inline formatting of those titles will be parsed into + * {@link AlertTitle} nodes. + * + *

The {@link #create() default configuration} of this extension will match GFM exactly, with the + * following exceptions: * - * - Alert markers take precedence over shortcut reference links. + *

- Alert markers take precedence over shortcut reference links. * - Alerts with no content are allowed. Example: * - *

{@code
- *   
- *   > [!NOTE]
+ * 
{@code
+ * 
+ * > [!NOTE]
+ *
+ * 
+ * > [!NOTE] Custom title
+ *
+ * }
* - * - * > [!NOTE] Custom title - * }
* - Lazy continuation is not allowed between the marker and the body text. Example: * - *
{@code
- *   > [!NOTE]
- *   Lazy body text will be parsed as a new paragraph
- *   }
+ *
{@code
+ * > [!NOTE]
+ * Lazy body text will be parsed as a new paragraph
+ *
+ * }
*/ -public class AlertsExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, - TextContentRenderer.TextContentRendererExtension, MarkdownRenderer.MarkdownRendererExtension { - - /** - * The standard GitHub Flavored Markdown (GFM) types that the extension - * enables by default. These can be overwritten with {@link Builder#setAllowedTypes(Map)}. - */ - public static final Map STANDARD_TYPES = Map.ofEntries( - Map.entry("NOTE", "Note"), - Map.entry("TIP", "Tip"), - Map.entry("IMPORTANT", "Important"), - Map.entry("WARNING", "Warning"), - Map.entry("CAUTION", "Caution") - ); +public class AlertsExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + TextContentRenderer.TextContentRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { /** - * A map of alert marker ({@code [!TYPE]}) to the default title for that marker. + * The standard GitHub Flavored Markdown (GFM) types that the extension enables by default. + * These can be overwritten with {@link Builder#setAllowedTypes(Map)}. */ + public static final Map STANDARD_TYPES = + Map.ofEntries( + Map.entry("NOTE", "Note"), + Map.entry("TIP", "Tip"), + Map.entry("IMPORTANT", "Important"), + Map.entry("WARNING", "Warning"), + Map.entry("CAUTION", "Caution")); + + /** A map of alert marker ({@code [!TYPE]}) to the default title for that marker. */ private final Map allowedTypes; + private final boolean customTitlesAllowed; private final boolean nestedAlertsAllowed; @@ -89,37 +94,39 @@ public static Builder builder() { public void extend(Parser.Builder parserBuilder) { var allowedTypesSet = new HashSet<>(allowedTypes.keySet()); parserBuilder.customBlockParserFactory( - new AlertBlockParser.Factory(allowedTypesSet, customTitlesAllowed, nestedAlertsAllowed)); + new AlertBlockParser.Factory( + allowedTypesSet, customTitlesAllowed, nestedAlertsAllowed)); } @Override public void extend(HtmlRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(context -> new AlertHtmlNodeRenderer(context, allowedTypes)); + rendererBuilder.nodeRendererFactory( + context -> new AlertHtmlNodeRenderer(context, allowedTypes)); } @Override public void extend(TextContentRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(context -> new AlertTextContentNodeRenderer(context, allowedTypes)); + rendererBuilder.nodeRendererFactory( + context -> new AlertTextContentNodeRenderer(context, allowedTypes)); } @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new AlertMarkdownNodeRenderer(context); - } - - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }); + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new AlertMarkdownNodeRenderer(context); + } + + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + }); } - /** - * Builder for configuring the alerts extension. - */ + /** Builder for configuring the alerts extension. */ public static class Builder { private Map allowedTypes = new HashMap<>(STANDARD_TYPES); private boolean customTitlesAllowed = false; @@ -128,12 +135,12 @@ public static class Builder { /** * Sets which alert types will be recognized and parsed into {@link Alert} blocks, * completely overwriting any previous configuration. - *

- * By default, {@link AlertsExtension#STANDARD_TYPES} are used. * - * @param allowedTypes A map of alert type to the default title for that type. - * Must not be null/empty or contain any null/empty keys or - * values. Additionally, all alert types must be uppercase. + *

By default, {@link AlertsExtension#STANDARD_TYPES} are used. + * + * @param allowedTypes A map of alert type to the default title for that type. Must not be + * null/empty or contain any null/empty keys or values. Additionally, all alert types + * must be uppercase. * @return {@code this} * @see Builder#addCustomType(String, String) */ @@ -153,9 +160,9 @@ public Builder setAllowedTypes(Map allowedTypes) { /** * Adds a custom alert type with a default title. - *

- * This can also be used to override the default title of standard GFM types - * (e.g., for localization). + * + *

This can also be used to override the default title of standard GFM types (e.g., for + * localization). * * @param type the alert type (must be uppercase) * @param title the default title for this alert type @@ -169,8 +176,8 @@ public Builder addCustomType(String type, String title) { } /** - * Allows or disallows custom titles on alerts. Inline formatting is supported - * within these titles. + * Allows or disallows custom titles on alerts. Inline formatting is supported within these + * titles. * * @param allow Whether to allow or disallow custom titles on alerts. * @return {@code this} @@ -183,11 +190,11 @@ public Builder allowCustomTitles(boolean allow) { /** * Allows or disallows parsing alerts within non-root blocks ({@code Document}). - *

- * When disallowed, if an alert appears within another block, it will be parsed as - * a regular {@code BlockQuote}. - *

- * Note that even when this is allowed, {@link Parser.Builder#maxOpenBlockParsers(int)} + * + *

When disallowed, if an alert appears within another block, it will be parsed as a + * regular {@code BlockQuote}. + * + *

Note that even when this is allowed, {@link Parser.Builder#maxOpenBlockParsers(int)} * will be respected. * * @param allow Whether to allow or disallow parsing alerts within non-root blocks. @@ -208,10 +215,7 @@ public Extension build() { /** * Checks whether an alert type and default title are valid. * - * @param type The type to validate: - *

- * - Must not be null or empty - * - Must be uppercase + * @param type The type to validate. Must be uppercase. * @param title The default title to validate. Must not be null or empty. */ private void validateTypeAndTitle(String type, String title) { diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertBlockParser.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertBlockParser.java index e7a9f402e..67acbe475 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertBlockParser.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertBlockParser.java @@ -4,7 +4,6 @@ import java.util.Locale; import java.util.Set; import java.util.regex.Pattern; - import org.commonmark.ext.gfm.alerts.Alert; import org.commonmark.ext.gfm.alerts.AlertTitle; import org.commonmark.node.Block; @@ -23,8 +22,10 @@ public class AlertBlockParser extends AbstractBlockParser { - private static final Pattern ALERT_PATTERN_NO_CUSTOM_TITLE = Pattern.compile("^\\[!([a-zA-Z]+)]\\s*$"); - private static final Pattern ALERT_PATTERN_CUSTOM_TITLE = Pattern.compile("^\\[!([a-zA-Z]+)](.*)$"); + private static final Pattern ALERT_PATTERN_NO_CUSTOM_TITLE = + Pattern.compile("^\\[!([a-zA-Z]+)]\\s*$"); + private static final Pattern ALERT_PATTERN_CUSTOM_TITLE = + Pattern.compile("^\\[!([a-zA-Z]+)](.*)$"); private final Alert block; private final SourceLine titleLine; @@ -103,7 +104,10 @@ public static class Factory extends AbstractBlockParserFactory { private final boolean customTitlesAllowed; private final boolean nestedAlertsAllowed; - public Factory(Set allowedTypes, boolean customTitlesAllowed, boolean nestedAlertsAllowed) { + public Factory( + Set allowedTypes, + boolean customTitlesAllowed, + boolean nestedAlertsAllowed) { this.allowedTypes = allowedTypes; this.customTitlesAllowed = customTitlesAllowed; this.nestedAlertsAllowed = nestedAlertsAllowed; @@ -116,7 +120,8 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar return BlockStart.none(); } - if (!nestedAlertsAllowed && !isAtRoot(matchedBlockParser.getMatchedBlockParser().getBlock())) { + if (!nestedAlertsAllowed + && !isAtRoot(matchedBlockParser.getMatchedBlockParser().getBlock())) { return BlockStart.none(); } @@ -176,7 +181,10 @@ private BlockStart tryStartFresh(CharSequence line, int nextNonSpace, ParserStat afterGt = state.getIndex(); } - var pattern = customTitlesAllowed ? ALERT_PATTERN_CUSTOM_TITLE : ALERT_PATTERN_NO_CUSTOM_TITLE; + var pattern = + customTitlesAllowed + ? ALERT_PATTERN_CUSTOM_TITLE + : ALERT_PATTERN_NO_CUSTOM_TITLE; var matcher = pattern.matcher(line.subSequence(afterGt, line.length())); if (!matcher.matches()) { @@ -215,7 +223,8 @@ private BlockStart tryStartFresh(CharSequence line, int nextNonSpace, ParserStat // If we got here via the promotion path, replace the empty BlockQuote. var matched = state.getActiveBlockParser().getBlock(); - if (matched instanceof BlockQuote && matched.getFirstChild() == null + if (matched instanceof BlockQuote + && matched.getFirstChild() == null && (nextNonSpace >= line.length() || line.charAt(nextNonSpace) != '>')) { start = start.replaceActiveBlockParser(); } diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertHtmlNodeRenderer.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertHtmlNodeRenderer.java index 6b9ba6da9..30aea6f04 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertHtmlNodeRenderer.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertHtmlNodeRenderer.java @@ -1,21 +1,21 @@ package org.commonmark.ext.gfm.alerts.internal; +import java.util.LinkedHashMap; +import java.util.Map; import org.commonmark.ext.gfm.alerts.Alert; import org.commonmark.ext.gfm.alerts.AlertTitle; import org.commonmark.node.Node; import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.LinkedHashMap; -import java.util.Map; - public class AlertHtmlNodeRenderer extends AlertNodeRenderer { private final HtmlWriter htmlWriter; private final HtmlNodeRendererContext context; private final Map allowedTypes; - public AlertHtmlNodeRenderer(HtmlNodeRendererContext context, Map allowedTypes) { + public AlertHtmlNodeRenderer( + HtmlNodeRendererContext context, Map allowedTypes) { this.htmlWriter = context.getWriter(); this.context = context; this.allowedTypes = allowedTypes; @@ -39,7 +39,8 @@ protected void renderAlert(Alert alert) { htmlWriter.line(); // Render alert title - htmlWriter.tag("p", context.extendAttributes(alert, "p", Map.of("class", "markdown-alert-title"))); + htmlWriter.tag( + "p", context.extendAttributes(alert, "p", Map.of("class", "markdown-alert-title"))); var first = alert.getFirstChild(); if (first instanceof AlertTitle) { renderChildren(first); diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertNodeRenderer.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertNodeRenderer.java index 42e505cb7..ff4bdf6ad 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertNodeRenderer.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertNodeRenderer.java @@ -1,12 +1,11 @@ package org.commonmark.ext.gfm.alerts.internal; +import java.util.Set; import org.commonmark.ext.gfm.alerts.Alert; import org.commonmark.ext.gfm.alerts.AlertTitle; import org.commonmark.node.Node; import org.commonmark.renderer.NodeRenderer; -import java.util.Set; - public abstract class AlertNodeRenderer implements NodeRenderer { @Override @@ -23,8 +22,8 @@ public void render(Node node) { protected abstract void renderAlert(Alert alert); /** - * Renders the children of a parent node, excluding {@link AlertTitle} nodes. - * {@link AlertTitle} is rendered separately from other content. + * Renders the children of a parent node, excluding {@link AlertTitle} nodes. {@link AlertTitle} + * is rendered separately from other content. * * @param parent the parent node whose children should be rendered */ @@ -42,8 +41,8 @@ protected final void renderChildren(Node parent) { } /** - * Renders a single node. Subclasses must implement this to delegate - * to their context's render method. + * Renders a single node. Subclasses must implement this to delegate to their context's render + * method. * * @param node the node to render */ diff --git a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertTextContentNodeRenderer.java b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertTextContentNodeRenderer.java index c14ea36a4..f494f5812 100644 --- a/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertTextContentNodeRenderer.java +++ b/commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertTextContentNodeRenderer.java @@ -1,5 +1,6 @@ package org.commonmark.ext.gfm.alerts.internal; +import java.util.Map; import org.commonmark.ext.gfm.alerts.Alert; import org.commonmark.ext.gfm.alerts.AlertTitle; import org.commonmark.node.Node; @@ -7,15 +8,14 @@ import org.commonmark.renderer.text.TextContentNodeRendererContext; import org.commonmark.renderer.text.TextContentWriter; -import java.util.Map; - public class AlertTextContentNodeRenderer extends AlertNodeRenderer { private final TextContentNodeRendererContext context; private final TextContentWriter textContent; private final Map allowedTypes; - public AlertTextContentNodeRenderer(TextContentNodeRendererContext context, Map allowedTypes) { + public AlertTextContentNodeRenderer( + TextContentNodeRendererContext context, Map allowedTypes) { this.context = context; this.textContent = context.getWriter(); this.allowedTypes = allowedTypes; diff --git a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsMarkdownRendererTest.java b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsMarkdownRendererTest.java index e31059ed2..f8e73cc06 100644 --- a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsMarkdownRendererTest.java +++ b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsMarkdownRendererTest.java @@ -1,27 +1,26 @@ package org.commonmark.ext.gfm.alerts; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class AlertsMarkdownRendererTest { private static final Set EXTENSIONS = Set.of(AlertsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); - private static final Set EXTENSIONS_CUSTOM_TITLES = Set.of(AlertsExtension.builder().allowCustomTitles(true).build()); - private static final Parser PARSER_CUSTOM_TITLES = Parser.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .build(); - private static final MarkdownRenderer RENDERER_CUSTOM_TITLES = MarkdownRenderer.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .build(); + private static final Set EXTENSIONS_CUSTOM_TITLES = + Set.of(AlertsExtension.builder().allowCustomTitles(true).build()); + private static final Parser PARSER_CUSTOM_TITLES = + Parser.builder().extensions(EXTENSIONS_CUSTOM_TITLES).build(); + private static final MarkdownRenderer RENDERER_CUSTOM_TITLES = + MarkdownRenderer.builder().extensions(EXTENSIONS_CUSTOM_TITLES).build(); @Test public void alertRoundTrip() { @@ -61,9 +60,7 @@ public void alertWithMultipleParagraphs() { @Test public void customTypeRoundTrip() { - var extension = AlertsExtension.builder() - .addCustomType("INFO", "Information") - .build(); + var extension = AlertsExtension.builder().addCustomType("INFO", "Information").build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = MarkdownRenderer.builder().extensions(Set.of(extension)).build(); @@ -99,14 +96,17 @@ public void customTitleRoundTrip() { @Test public void customTitleWithFormattingRoundTrip() { - assertRoundTripCustomTitles("> [!WARNING] Custom _title **with `formatting`**_\n> Be careful\n"); + assertRoundTripCustomTitles( + "> [!WARNING] Custom _title **with `formatting`**_\n> Be careful\n"); } @Test public void customTitleWithMultipleBlocks() { - var input = "> [!NOTE]Title\n> First paragraph\n>\n> Second paragraph\n>\n> - > Nested blocks\n"; + var input = + "> [!NOTE]Title\n> First paragraph\n>\n> Second paragraph\n>\n> - > Nested blocks\n"; // MarkdownWriter always writes the prefix including trailing space - var expected = "> [!NOTE] Title\n> First paragraph\n> \n> Second paragraph\n> \n> - > Nested blocks\n"; + var expected = + "> [!NOTE] Title\n> First paragraph\n> \n> Second paragraph\n> \n> - > Nested blocks\n"; var rendered = RENDERER_CUSTOM_TITLES.render(PARSER_CUSTOM_TITLES.parse(input)); assertThat(rendered).isEqualTo(expected); } diff --git a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsSpecTest.java b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsSpecTest.java index d85aa1d2a..2836db3ac 100644 --- a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsSpecTest.java +++ b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsSpecTest.java @@ -1,5 +1,8 @@ package org.commonmark.ext.gfm.alerts; +import java.net.URL; +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; @@ -11,16 +14,12 @@ import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.net.URL; -import java.util.List; -import java.util.Set; - /** - * Tests the default configuration of {@link AlertsExtension} against how - * GitHub Flavored Markdown (GFM) parses and renders {@link Alert}s. - *

- * This test should only be used for the default configuration of - * {@link AlertsExtension}. Other configurations cause deviation from GFM. + * Tests the default configuration of {@link AlertsExtension} against how GitHub Flavored Markdown + * (GFM) parses and renders {@link Alert}s. + * + *

This test should only be used for the default configuration of {@link AlertsExtension}. Other + * configurations cause deviation from GFM. */ @ParameterizedClass @MethodSource("data") @@ -28,11 +27,12 @@ public class AlertsSpecTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(AlertsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - // Use softbreak("
") to match GitHub's rendering for easier comparison with GitHub API output. - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).softbreak("
\n").build(); + // Use softbreak("
") to match GitHub's rendering for easier comparison with GitHub API + // output. + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).softbreak("
\n").build(); - @Parameter - Example example; + @Parameter Example example; static List data() { URL spec = AlertsSpecTest.class.getResource("/alerts-spec.txt"); diff --git a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTest.java b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTest.java index d98e0e2cf..99c0e8d7a 100644 --- a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTest.java +++ b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTest.java @@ -1,5 +1,11 @@ package org.commonmark.ext.gfm.alerts; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.List; +import java.util.Map; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Emphasis; import org.commonmark.node.SourceSpan; @@ -11,27 +17,26 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class AlertsTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(AlertsExtension.create()); - private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build(); - private static final HtmlRenderer HTML_RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); - - private static final Set EXTENSIONS_CUSTOM_TITLES = Set.of(AlertsExtension.builder().allowCustomTitles(true).build()); - private static final Parser PARSER_CUSTOM_TITLES = Parser.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); - private static final HtmlRenderer HTML_RENDERER_CUSTOM_TITLES = HtmlRenderer.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .build(); + private static final Parser PARSER = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); + private static final HtmlRenderer HTML_RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); + + private static final Set EXTENSIONS_CUSTOM_TITLES = + Set.of(AlertsExtension.builder().allowCustomTitles(true).build()); + private static final Parser PARSER_CUSTOM_TITLES = + Parser.builder() + .extensions(EXTENSIONS_CUSTOM_TITLES) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); + private static final HtmlRenderer HTML_RENDERER_CUSTOM_TITLES = + HtmlRenderer.builder().extensions(EXTENSIONS_CUSTOM_TITLES).build(); @Override protected String render(String source) { @@ -39,103 +44,109 @@ protected String render(String source) { } private void assertRenderingCustomTitles(String source, String expectedResult) { - assertThat(HTML_RENDERER_CUSTOM_TITLES.render(PARSER_CUSTOM_TITLES.parse(source))).isEqualTo(expectedResult); + assertThat(HTML_RENDERER_CUSTOM_TITLES.render(PARSER_CUSTOM_TITLES.parse(source))) + .isEqualTo(expectedResult); } // Custom types @Test public void customType() { - var extension = AlertsExtension.builder() - .addCustomType("INFO", "Information") - .build(); + var extension = AlertsExtension.builder().addCustomType("INFO", "Information").build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - assertThat(renderer.render(parser.parse("> [!INFO]\n> Custom alert"))).isEqualTo( - "

\n" + - "

Information

\n" + - "

Custom alert

\n" + - "
\n"); + assertThat(renderer.render(parser.parse("> [!INFO]\n> Custom alert"))) + .isEqualTo( + "
\n" + + "

Information

\n" + + "

Custom alert

\n" + + "
\n"); } @Test public void multipleCustomTypes() { - var extension = AlertsExtension.builder() - .addCustomType("INFO", "Information") - .addCustomType("SUCCESS", "Success!") - .addCustomType("DANGER", "Danger!") - .build(); + var extension = + AlertsExtension.builder() + .addCustomType("INFO", "Information") + .addCustomType("SUCCESS", "Success!") + .addCustomType("DANGER", "Danger!") + .build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - assertThat(renderer.render(parser.parse("> [!INFO]\n> Info content\n\n> [!SUCCESS]\n> Success content\n\n> [!DANGER]\n> Danger content"))).isEqualTo( - "
\n" + - "

Information

\n" + - "

Info content

\n" + - "
\n" + - "
\n" + - "

Success!

\n" + - "

Success content

\n" + - "
\n" + - "
\n" + - "

Danger!

\n" + - "

Danger content

\n" + - "
\n"); + assertThat( + renderer.render( + parser.parse( + "> [!INFO]\n> Info content\n\n> [!SUCCESS]\n> Success content\n\n> [!DANGER]\n> Danger content"))) + .isEqualTo( + "
\n" + + "

Information

\n" + + "

Info content

\n" + + "
\n" + + "
\n" + + "

Success!

\n" + + "

Success content

\n" + + "
\n" + + "
\n" + + "

Danger!

\n" + + "

Danger content

\n" + + "
\n"); } @Test public void standardTypesWithCustomConfigured() { - var extension = AlertsExtension.builder() - .addCustomType("INFO", "Information") - .build(); + var extension = AlertsExtension.builder().addCustomType("INFO", "Information").build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - assertThat(renderer.render(parser.parse("> [!NOTE]\n> Standard type"))).isEqualTo( - "
\n" + - "

Note

\n" + - "

Standard type

\n" + - "
\n"); + assertThat(renderer.render(parser.parse("> [!NOTE]\n> Standard type"))) + .isEqualTo( + "
\n" + + "

Note

\n" + + "

Standard type

\n" + + "
\n"); } @Test public void overrideStandardTypeTitle() { - var extension = AlertsExtension.builder() - .addCustomType("NOTE", "Nota") - .build(); + var extension = AlertsExtension.builder().addCustomType("NOTE", "Nota").build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - assertThat(renderer.render(parser.parse("> [!NOTE]\n> Localized title"))).isEqualTo( - "
\n" + - "

Nota

\n" + - "

Localized title

\n" + - "
\n"); + assertThat(renderer.render(parser.parse("> [!NOTE]\n> Localized title"))) + .isEqualTo( + "
\n" + + "

Nota

\n" + + "

Localized title

\n" + + "
\n"); } // Custom type validation @Test public void customTypeMustBeUppercase() { - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().addCustomType("info", "Information").build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().addCustomType("info", "Information").build()); } @Test public void customTypeMustNotBeEmpty() { - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().addCustomType("", "Title").build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().addCustomType("", "Title").build()); } @Test public void customTypeTitleMustNotBeEmpty() { - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().addCustomType("INFO", "").build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().addCustomType("INFO", "").build()); } // Overwriting types @@ -143,36 +154,41 @@ public void customTypeTitleMustNotBeEmpty() { @Test public void overwriteStandardTypes() { var allowedTypes = Map.ofEntries(Map.entry("IMPORTANT", "Important")); - var extension = AlertsExtension.builder() - .setAllowedTypes(allowedTypes) - .addCustomType("BUG", "Known Bug") - .build(); + var extension = + AlertsExtension.builder() + .setAllowedTypes(allowedTypes) + .addCustomType("BUG", "Known Bug") + .build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - assertThat(renderer.render(parser.parse("> [!NOTE]\n> Regular block quote"))).isEqualTo( - "
\n" + - "

[!NOTE]\n" + - "Regular block quote

\n" + - "
\n"); - - assertThat(renderer.render(parser.parse("> [!TIP]\n> Regular block quote"))).isEqualTo( - "
\n" + - "

[!TIP]\n" + - "Regular block quote

\n" + - "
\n"); - - assertThat(renderer.render(parser.parse("> [!IMPORTANT]\n> Alert"))).isEqualTo( - "
\n" + - "

Important

\n" + - "

Alert

\n" + - "
\n"); - - assertThat(renderer.render(parser.parse("> [!BUG]\n> Alert"))).isEqualTo( - "
\n" + - "

Known Bug

\n" + - "

Alert

\n" + - "
\n"); + assertThat(renderer.render(parser.parse("> [!NOTE]\n> Regular block quote"))) + .isEqualTo( + "
\n" + + "

[!NOTE]\n" + + "Regular block quote

\n" + + "
\n"); + + assertThat(renderer.render(parser.parse("> [!TIP]\n> Regular block quote"))) + .isEqualTo( + "
\n" + + "

[!TIP]\n" + + "Regular block quote

\n" + + "
\n"); + + assertThat(renderer.render(parser.parse("> [!IMPORTANT]\n> Alert"))) + .isEqualTo( + "
\n" + + "

Important

\n" + + "

Alert

\n" + + "
\n"); + + assertThat(renderer.render(parser.parse("> [!BUG]\n> Alert"))) + .isEqualTo( + "
\n" + + "

Known Bug

\n" + + "

Alert

\n" + + "
\n"); } // Overwriting types validation @@ -180,226 +196,249 @@ public void overwriteStandardTypes() { @Test public void overwriteTypesMustBeUppercase() { var allowedTypes = Map.ofEntries(Map.entry("info", "Info")); - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); } @Test public void overwriteTypesMustNotBeEmpty() { var allowedTypes = Map.ofEntries(Map.entry("", "Info")); - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); } @Test public void overwriteTypesTitleMustNotBeEmpty() { var allowedTypes = Map.ofEntries(Map.entry("INFO", "")); - assertThrows(IllegalArgumentException.class, () -> - AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); + assertThrows( + IllegalArgumentException.class, + () -> AlertsExtension.builder().setAllowedTypes(allowedTypes).build()); } // Custom titles @Test public void customTitle() { - assertRenderingCustomTitles("> [!NOTE] Custom title\n> Note with a custom title", - "
\n" + - "

Custom title

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom title\n> Note with a custom title", + "
\n" + + "

Custom title

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleNoSpace() { - assertRenderingCustomTitles("> [!NOTE]Custom title\n> Note with a custom title", - "
\n" + - "

Custom title

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE]Custom title\n> Note with a custom title", + "
\n" + + "

Custom title

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleExtraSpace() { - assertRenderingCustomTitles("> [!NOTE] Custom title \n> Note with a custom title", - "
\n" + - "

Custom title

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom title \n> Note with a custom title", + "
\n" + + "

Custom title

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleNoHardLineBreak() { - assertRenderingCustomTitles("> [!NOTE] Custom title\\\n> Note with a custom title", - "
\n" + - "

Custom title\\

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom title\\\n> Note with a custom title", + "
\n" + + "

Custom title\\

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleWithComment() { - assertRenderingCustomTitles("> [!NOTE] Custom title \n> Note with a custom title", - "
\n" + - "

Custom title

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom title \n> Note with a custom title", + "
\n" + + "

Custom title

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleWithInlineFormatting() { - assertRenderingCustomTitles("> [!NOTE] Custom _title with **formatting**_\n> Note with a custom title", - "
\n" + - "

Custom title with formatting

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom _title with **formatting**_\n> Note with a custom title", + "
\n" + + "

Custom title with formatting

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleWithLinkAndCode() { - assertRenderingCustomTitles("> [!IMPORTANT] See [docs](https://example.com) or `run()`\n> Note with a custom title", - "
\n" + - "

See docs or run()

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!IMPORTANT] See [docs](https://example.com) or `run()`\n> Note with a custom title", + "
\n" + + "

See docs or run()

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleLeadingEmptyLines() { - assertRenderingCustomTitles(">\n> \n> [!NOTE] Custom **title**\n> Note with a custom title", - "
\n" + - "

Custom title

\n" + - "

Note with a custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + ">\n> \n> [!NOTE] Custom **title**\n> Note with a custom title", + "
\n" + + "

Custom title

\n" + + "

Note with a custom title

\n" + + "
\n"); } @Test public void customTitleNoOverlappingInlines() { - assertRenderingCustomTitles("> [!NOTE] Custom _title with **opening `delimiters\n> Note` with** closing delimiters_", - "
\n" + - "

Custom _title with **opening `delimiters

\n" + - "

Note` with** closing delimiters_

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom _title with **opening `delimiters\n> Note` with** closing delimiters_", + "
\n" + + "

Custom _title with **opening `delimiters

\n" + + "

Note` with** closing delimiters_

\n" + + "
\n"); } @Test public void customTitleIgnoresBlockContent() { - assertRenderingCustomTitles("> [!NOTE] ## Custom title looks like an ATX heading\n>But it's not", - "
\n" + - "

## Custom title looks like an ATX heading

\n" + - "

But it's not

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] ## Custom title looks like an ATX heading\n>But it's not", + "
\n" + + "

## Custom title looks like an ATX heading

\n" + + "

But it's not

\n" + + "
\n"); } @Test public void customTitleNoBody() { // Alerts with no body are allowed. - assertRenderingCustomTitles("> [!NOTE] Custom _title_\n> \n>\n>", - "
\n" + - "

Custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom _title_\n> \n>\n>", + "
\n" + + "

Custom title

\n" + + "
\n"); } @Test public void customTitleNoBodyNoSpace() { - assertRenderingCustomTitles("> [!NOTE] Custom _title_", - "
\n" + - "

Custom title

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom _title_", + "
\n" + + "

Custom title

\n" + + "
\n"); } @Test public void onlyTrailingWhitespaceIsNotCustomTitle() { - assertRenderingCustomTitles("> [!NOTE] \n> Body text", - "
\n" + - "

Note

\n" + - "

Body text

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE] \n> Body text", + "
\n" + + "

Note

\n" + + "

Body text

\n" + + "
\n"); } // Lazy continuation @Test public void noLazyContinuationAfterMarker() { - assertRendering("> [!NOTE]\nBody text", - "
\n" + - "

Note

\n" + - "
\n" + - "

Body text

\n"); + assertRendering( + "> [!NOTE]\nBody text", + "
\n" + + "

Note

\n" + + "
\n" + + "

Body text

\n"); } @Test public void noLazyContinuationAfterTitle() { - assertRenderingCustomTitles("> [!NOTE] Custom title\nBody text", - "
\n" + - "

Custom title

\n" + - "
\n" + - "

Body text

\n"); + assertRenderingCustomTitles( + "> [!NOTE] Custom title\nBody text", + "
\n" + + "

Custom title

\n" + + "
\n" + + "

Body text

\n"); } // Alert markers take precedence over link reference definitions @Test public void alertTakesPrecedence() { - assertRenderingCustomTitles("> [!NOTE]: https://example.com\n> Body text\n\n[!NOTE]", - "
\n" + - "

: https://example.com

\n" + - "

Body text

\n" + - "
\n" + - "

[!NOTE]

\n"); + assertRenderingCustomTitles( + "> [!NOTE]: https://example.com\n> Body text\n\n[!NOTE]", + "
\n" + + "

: https://example.com

\n" + + "

Body text

\n" + + "
\n" + + "

[!NOTE]

\n"); } @Test public void alertTakesPrecedenceBefore() { - assertRenderingCustomTitles("> [!NOTE]\n> Body text\n\n[!NOTE]: https://example.com", - "
\n" + - "

Note

\n" + - "

Body text

\n" + - "
\n"); + assertRenderingCustomTitles( + "> [!NOTE]\n> Body text\n\n[!NOTE]: https://example.com", + "
\n" + + "

Note

\n" + + "

Body text

\n" + + "
\n"); } @Test public void alertTakesPrecedenceAfter() { - assertRenderingCustomTitles("[!NOTE]: https://example.com\n\n> [!NOTE]\n> Body text", - "
\n" + - "

Note

\n" + - "

Body text

\n" + - "
\n"); + assertRenderingCustomTitles( + "[!NOTE]: https://example.com\n\n> [!NOTE]\n> Body text", + "
\n" + + "

Note

\n" + + "

Body text

\n" + + "
\n"); } // Nested alerts @Test public void noNestedAlertsByDefault() { - assertRendering("> [!TIP]\n> Body\n\n- > [!TIP]\n > Nested body", - "
\n" + - "

Tip

\n" + - "

Body

\n" + - "
\n" + - "
    \n" + - "
  • \n" + - "
    \n" + - "

    [!TIP]\n" + - "Nested body

    \n" + - "
    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "> [!TIP]\n> Body\n\n- > [!TIP]\n > Nested body", + "
\n" + + "

Tip

\n" + + "

Body

\n" + + "
\n" + + "
    \n" + + "
  • \n" + + "
    \n" + + "

    [!TIP]\n" + + "Nested body

    \n" + + "
    \n" + + "
  • \n" + + "
\n"); } @Test public void noNestedAlertsByDefaultLeadingEmptyLines() { - assertRendering(">\n> \n> [!TIP]\n> Body\n\n- > [!TIP]\n > Nested body", - "
\n" + - "

Tip

\n" + - "

Body

\n" + - "
\n" + - "
    \n" + - "
  • \n" + - "
    \n" + - "

    [!TIP]\n" + - "Nested body

    \n" + - "
    \n" + - "
  • \n" + - "
\n"); + assertRendering( + ">\n> \n> [!TIP]\n> Body\n\n- > [!TIP]\n > Nested body", + "
\n" + + "

Tip

\n" + + "

Body

\n" + + "
\n" + + "
    \n" + + "
  • \n" + + "
    \n" + + "

    [!TIP]\n" + + "Nested body

    \n" + + "
    \n" + + "
  • \n" + + "
\n"); } @Test @@ -408,46 +447,50 @@ public void nestedAlerts() { var parser = Parser.builder().extensions(Set.of(extension)).build(); var renderer = HtmlRenderer.builder().extensions(Set.of(extension)).build(); - var source = String.join("\n", - "> [!TIP]", - "> Tip body", - "> > [!IMPORTANT]", - "> > Important body", - "", - "- > [!NOTE]", - " > Nested body", - " >", - " > 1. Ordered list body", - " >", - " > > [!CAUTION]", - " > >", - " > > Deeply nested body"); - var expected = String.join("\n", - "
", - "

Tip

", - "

Tip body

", - "
", - "

Important

", - "

Important body

", - "
", - "
", - "
    ", - "
  • ", - "
    ", - "

    Note

    ", - "

    Nested body

    ", - "
      ", - "
    1. ", - "

      Ordered list body

      ", - "
      ", - "

      Caution

      ", - "

      Deeply nested body

      ", - "
      ", - "
    2. ", - "
    ", - "
    ", - "
  • ", - "
\n"); + var source = + String.join( + "\n", + "> [!TIP]", + "> Tip body", + "> > [!IMPORTANT]", + "> > Important body", + "", + "- > [!NOTE]", + " > Nested body", + " >", + " > 1. Ordered list body", + " >", + " > > [!CAUTION]", + " > >", + " > > Deeply nested body"); + var expected = + String.join( + "\n", + "
", + "

Tip

", + "

Tip body

", + "
", + "

Important

", + "

Important body

", + "
", + "
", + "
    ", + "
  • ", + "
    ", + "

    Note

    ", + "

    Nested body

    ", + "
      ", + "
    1. ", + "

      Ordered list body

      ", + "
      ", + "

      Caution

      ", + "

      Deeply nested body

      ", + "
      ", + "
    2. ", + "
    ", + "
    ", + "
  • ", + "
\n"); assertThat(renderer.render(parser.parse(source))).isEqualTo(expected); } @@ -465,9 +508,7 @@ public void alertParsedAsAlertNode() { @Test public void customTypeParsedAsAlertNode() { - var extension = AlertsExtension.builder() - .addCustomType("INFO", "Information") - .build(); + var extension = AlertsExtension.builder().addCustomType("INFO", "Information").build(); var parser = Parser.builder().extensions(Set.of(extension)).build(); @@ -578,5 +619,4 @@ public void titleWithNestedInlineFormattingSourcePosition() { assertThat(((Text) italicText).getLiteral()).isEqualTo("and italic"); assertThat(italicText.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 28, 28, 10))); } - } diff --git a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTextContentRendererTest.java b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTextContentRendererTest.java index 9bc69677c..3979b0488 100644 --- a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTextContentRendererTest.java +++ b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTextContentRendererTest.java @@ -1,5 +1,6 @@ package org.commonmark.ext.gfm.alerts; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.text.LineBreakRendering; @@ -7,33 +8,45 @@ import org.commonmark.testutil.Asserts; import org.junit.jupiter.api.Test; -import java.util.Set; - public class AlertsTextContentRendererTest { private static final Set EXTENSIONS = Set.of(AlertsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final TextContentRenderer COMPACT_RENDERER = TextContentRenderer.builder() - .extensions(EXTENSIONS).build(); - private static final TextContentRenderer SEPARATE_RENDERER = TextContentRenderer.builder() - .extensions(EXTENSIONS).lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS).build(); - private static final TextContentRenderer STRIPPED_RENDERER = TextContentRenderer.builder() - .extensions(EXTENSIONS).lineBreakRendering(LineBreakRendering.STRIP).build(); - - private static final Set EXTENSIONS_CUSTOM_TITLES = Set.of( - AlertsExtension.builder().allowCustomTitles(true).allowNestedAlerts(true).build()); - private static final Parser PARSER_CUSTOM_TITLES = Parser.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES).build(); - - private static final TextContentRenderer COMPACT_RENDERER_CUSTOM = TextContentRenderer.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES).build(); - private static final TextContentRenderer SEPARATE_RENDERER_CUSTOM = TextContentRenderer.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS).build(); - private static final TextContentRenderer STRIPPED_RENDERER_CUSTOM = TextContentRenderer.builder() - .extensions(EXTENSIONS_CUSTOM_TITLES) - .lineBreakRendering(LineBreakRendering.STRIP).build(); + private static final TextContentRenderer COMPACT_RENDERER = + TextContentRenderer.builder().extensions(EXTENSIONS).build(); + private static final TextContentRenderer SEPARATE_RENDERER = + TextContentRenderer.builder() + .extensions(EXTENSIONS) + .lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS) + .build(); + private static final TextContentRenderer STRIPPED_RENDERER = + TextContentRenderer.builder() + .extensions(EXTENSIONS) + .lineBreakRendering(LineBreakRendering.STRIP) + .build(); + + private static final Set EXTENSIONS_CUSTOM_TITLES = + Set.of( + AlertsExtension.builder() + .allowCustomTitles(true) + .allowNestedAlerts(true) + .build()); + private static final Parser PARSER_CUSTOM_TITLES = + Parser.builder().extensions(EXTENSIONS_CUSTOM_TITLES).build(); + + private static final TextContentRenderer COMPACT_RENDERER_CUSTOM = + TextContentRenderer.builder().extensions(EXTENSIONS_CUSTOM_TITLES).build(); + private static final TextContentRenderer SEPARATE_RENDERER_CUSTOM = + TextContentRenderer.builder() + .extensions(EXTENSIONS_CUSTOM_TITLES) + .lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS) + .build(); + private static final TextContentRenderer STRIPPED_RENDERER_CUSTOM = + TextContentRenderer.builder() + .extensions(EXTENSIONS_CUSTOM_TITLES) + .lineBreakRendering(LineBreakRendering.STRIP) + .build(); @Test public void alertNoBody() { @@ -123,7 +136,8 @@ public void alertWithinBlockQuote() { public void alertWithinAlert() { var source = "> [!NOTE] Custom title\n> Body text\n> > [!WARNING]\n> > Nested body text"; assertCompactCustomTitles(source, "Custom title\nBody text\nWarning\nNested body text"); - assertSeparateCustomTitles(source, "Custom title\n\nBody text\n\nWarning\n\nNested body text"); + assertSeparateCustomTitles( + source, "Custom title\n\nBody text\n\nWarning\n\nNested body text"); assertStrippedCustomTitles(source, "Custom title: Body text Warning: Nested body text"); } diff --git a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/examples/AlertsExample.java b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/examples/AlertsExample.java index 34b78385c..26b348016 100644 --- a/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/examples/AlertsExample.java +++ b/commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/examples/AlertsExample.java @@ -1,14 +1,11 @@ package org.commonmark.ext.gfm.alerts.examples; +import java.util.List; import org.commonmark.ext.gfm.alerts.AlertsExtension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; -import java.util.List; - -/** - * Example demonstrating the use of the GFM Alerts extension. - */ +/** Example demonstrating the use of the GFM Alerts extension. */ public class AlertsExample { public static void main(String[] args) { @@ -23,25 +20,22 @@ private static void standardTypesExample() { var extension = AlertsExtension.create(); - var parser = Parser.builder() - .extensions(List.of(extension)) - .build(); - - var renderer = HtmlRenderer.builder() - .extensions(List.of(extension)) - .build(); - - var markdown = "# GFM Alerts Demo\n\n" + - "> [!NOTE]\n" + - "> Highlights information that users should take into account.\n\n" + - "> [!TIP]\n" + - "> Helpful advice for doing things better.\n\n" + - "> [!IMPORTANT]\n" + - "> Key information users need to know.\n\n" + - "> [!WARNING]\n" + - "> Urgent info that needs immediate attention.\n\n" + - "> [!CAUTION]\n" + - "> Advises about risks or negative outcomes.\n"; + var parser = Parser.builder().extensions(List.of(extension)).build(); + + var renderer = HtmlRenderer.builder().extensions(List.of(extension)).build(); + + var markdown = + "# GFM Alerts Demo\n\n" + + "> [!NOTE]\n" + + "> Highlights information that users should take into account.\n\n" + + "> [!TIP]\n" + + "> Helpful advice for doing things better.\n\n" + + "> [!IMPORTANT]\n" + + "> Key information users need to know.\n\n" + + "> [!WARNING]\n" + + "> Urgent info that needs immediate attention.\n\n" + + "> [!CAUTION]\n" + + "> Advises about risks or negative outcomes.\n"; var html = renderer.render(parser.parse(markdown)); @@ -55,25 +49,20 @@ private static void customTypesExample() { System.out.println("CUSTOM ALERT TYPES"); System.out.println("=".repeat(60)); - var extension = AlertsExtension.builder() - .addCustomType("BUG", "Known Bug") - .build(); - - var parser = Parser.builder() - .extensions(List.of(extension)) - .build(); - - var renderer = HtmlRenderer.builder() - .extensions(List.of(extension)) - .build(); - - var markdown = "# Custom Alert Types\n\n" + - "> [!NOTE]\n" + - "> Useful information that users should know.\n\n" + - "> [!TIP]\n" + - "> Helpful advice for doing things better.\n\n" + - "> [!BUG]\n" + - "> This feature has a known issue with large files (see #42).\n"; + var extension = AlertsExtension.builder().addCustomType("BUG", "Known Bug").build(); + + var parser = Parser.builder().extensions(List.of(extension)).build(); + + var renderer = HtmlRenderer.builder().extensions(List.of(extension)).build(); + + var markdown = + "# Custom Alert Types\n\n" + + "> [!NOTE]\n" + + "> Useful information that users should know.\n\n" + + "> [!TIP]\n" + + "> Helpful advice for doing things better.\n\n" + + "> [!BUG]\n" + + "> This feature has a known issue with large files (see #42).\n"; var html = renderer.render(parser.parse(markdown)); diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java index 0c24642bc..76ce213e8 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java @@ -3,9 +3,7 @@ import org.commonmark.node.CustomNode; import org.commonmark.node.Delimited; -/** - * A strikethrough node containing text and other inline nodes as children. - */ +/** A strikethrough node containing text and other inline nodes as children. */ public class Strikethrough extends CustomNode implements Delimited { private String delimiter; diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/StrikethroughExtension.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/StrikethroughExtension.java index 0571aed84..4b18b7d66 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/StrikethroughExtension.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/StrikethroughExtension.java @@ -1,5 +1,6 @@ package org.commonmark.ext.gfm.strikethrough; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.ext.gfm.strikethrough.internal.StrikethroughDelimiterProcessor; import org.commonmark.ext.gfm.strikethrough.internal.StrikethroughHtmlNodeRenderer; @@ -13,38 +14,40 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.commonmark.renderer.text.TextContentRenderer; -import java.util.Set; - /** * Extension for GFM strikethrough using {@code ~} or {@code ~~} (GitHub Flavored Markdown). - *

Example input:

+ * + *

Example input: + * *

{@code ~foo~ or ~~bar~~}
- *

Example output (HTML):

+ * + *

Example output (HTML): + * *

{@code foo or bar}
- *

- * Create the extension with {@link #create()} and then add it to the parser and renderer builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- *

- * The parsed strikethrough text regions are turned into {@link Strikethrough} nodes. - *

- *

- * If you have another extension that only uses a single tilde ({@code ~}) syntax, you will have to configure this - * {@link StrikethroughExtension} to only accept the double tilde syntax, like this: - *

- *
- *     {@code
- *     StrikethroughExtension.builder().requireTwoTildes(true).build();
- *     }
- * 
- *

- * If you don't do that, there's a conflict between the two extensions and you will get an - * {@link IllegalArgumentException} when constructing the parser. - *

+ * + *

Create the extension with {@link #create()} and then add it to the parser and renderer + * builders ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The parsed strikethrough text regions are turned into {@link Strikethrough} nodes. + * + *

If you have another extension that only uses a single tilde ({@code ~}) syntax, you will have + * to configure this {@link StrikethroughExtension} to only accept the double tilde syntax, like + * this: + * + *

{@code
+ * StrikethroughExtension.builder().requireTwoTildes(true).build();
+ *
+ * }
+ * + *

If you don't do that, there's a conflict between the two extensions and you will get an {@link + * IllegalArgumentException} when constructing the parser. */ -public class StrikethroughExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, - TextContentRenderer.TextContentRendererExtension, MarkdownRenderer.MarkdownRendererExtension { +public class StrikethroughExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + TextContentRenderer.TextContentRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { private final boolean requireTwoTildes; @@ -68,7 +71,8 @@ public static Builder builder() { @Override public void extend(Parser.Builder parserBuilder) { - parserBuilder.customDelimiterProcessor(new StrikethroughDelimiterProcessor(requireTwoTildes)); + parserBuilder.customDelimiterProcessor( + new StrikethroughDelimiterProcessor(requireTwoTildes)); } @Override @@ -83,17 +87,18 @@ public void extend(TextContentRenderer.Builder rendererBuilder) { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new StrikethroughMarkdownNodeRenderer(context); - } - - @Override - public Set getSpecialCharacters() { - return Set.of('~'); - } - }); + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new StrikethroughMarkdownNodeRenderer(context); + } + + @Override + public Set getSpecialCharacters() { + return Set.of('~'); + } + }); } public static class Builder { @@ -101,8 +106,9 @@ public static class Builder { private boolean requireTwoTildes = false; /** - * @param requireTwoTildes Whether two tilde characters ({@code ~~}) are required for strikethrough or whether - * one is also enough. Default is {@code false}; both a single tilde and two tildes can be used for strikethrough. + * @param requireTwoTildes Whether two tilde characters ({@code ~~}) are required for + * strikethrough or whether one is also enough. Default is {@code false}; both a single + * tilde and two tildes can be used for strikethrough. * @return {@code this} */ public Builder requireTwoTildes(boolean requireTwoTildes) { diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java index 4657106ab..692b35f67 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughDelimiterProcessor.java @@ -43,7 +43,10 @@ public int process(DelimiterRun openingRun, DelimiterRun closingRun) { Text opener = openingRun.getOpener(); // Wrap nodes between delimiters in strikethrough. - String delimiter = openingRun.length() == 1 ? opener.getLiteral() : opener.getLiteral() + opener.getLiteral(); + String delimiter = + openingRun.length() == 1 + ? opener.getLiteral() + : opener.getLiteral() + opener.getLiteral(); Node strikethrough = new Strikethrough(delimiter); SourceSpans sourceSpans = new SourceSpans(); diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughHtmlNodeRenderer.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughHtmlNodeRenderer.java index b1a82cb03..e5ee31f4e 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughHtmlNodeRenderer.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughHtmlNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.ext.gfm.strikethrough.internal; +import java.util.Map; import org.commonmark.node.Node; import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.Map; - public class StrikethroughHtmlNodeRenderer extends StrikethroughNodeRenderer { private final HtmlNodeRendererContext context; diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughNodeRenderer.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughNodeRenderer.java index 18ed21887..56d94d300 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughNodeRenderer.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.ext.gfm.strikethrough.internal; +import java.util.Set; import org.commonmark.ext.gfm.strikethrough.Strikethrough; import org.commonmark.node.Node; import org.commonmark.renderer.NodeRenderer; -import java.util.Set; - abstract class StrikethroughNodeRenderer implements NodeRenderer { @Override diff --git a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughTextContentNodeRenderer.java b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughTextContentNodeRenderer.java index ebdcd9dbe..a5d6a7e31 100644 --- a/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughTextContentNodeRenderer.java +++ b/commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughTextContentNodeRenderer.java @@ -1,8 +1,8 @@ package org.commonmark.ext.gfm.strikethrough.internal; -import org.commonmark.renderer.text.TextContentWriter; -import org.commonmark.renderer.text.TextContentNodeRendererContext; import org.commonmark.node.Node; +import org.commonmark.renderer.text.TextContentNodeRendererContext; +import org.commonmark.renderer.text.TextContentWriter; public class StrikethroughTextContentNodeRenderer extends StrikethroughNodeRenderer { diff --git a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughMarkdownRendererTest.java b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughMarkdownRendererTest.java index c497a4db3..2d5a6a88d 100644 --- a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughMarkdownRendererTest.java +++ b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughMarkdownRendererTest.java @@ -1,19 +1,19 @@ package org.commonmark.ext.gfm.strikethrough; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class StrikethroughMarkdownRendererTest { private static final Set EXTENSIONS = Set.of(StrikethroughExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testStrikethrough() { diff --git a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughSpecTest.java b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughSpecTest.java index f1199b521..d63a83b51 100644 --- a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughSpecTest.java +++ b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughSpecTest.java @@ -1,5 +1,7 @@ package org.commonmark.ext.gfm.strikethrough; +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; @@ -12,19 +14,16 @@ import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.util.List; -import java.util.Set; - @ParameterizedClass @MethodSource("data") public class StrikethroughSpecTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(StrikethroughExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); - @Parameter - Example example; + @Parameter Example example; static List data() { return ExampleReader.readExamples(TestResources.getGfmSpec(), "strikethrough"); diff --git a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java index c29391cdd..10731ca7e 100644 --- a/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java +++ b/commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughTest.java @@ -1,5 +1,9 @@ package org.commonmark.ext.gfm.strikethrough; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Node; import org.commonmark.node.Paragraph; @@ -14,18 +18,14 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class StrikethroughTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(StrikethroughExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer HTML_RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); - private static final TextContentRenderer CONTENT_RENDERER = TextContentRenderer.builder() - .extensions(EXTENSIONS).build(); + private static final HtmlRenderer HTML_RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final TextContentRenderer CONTENT_RENDERER = + TextContentRenderer.builder().extensions(EXTENSIONS).build(); @Test public void oneTildeIsEnough() { @@ -70,13 +70,15 @@ public void tildesInside() { @Test public void strikethroughWholeParagraphWithOtherDelimiters() { - assertRendering("~~Paragraph with *emphasis* and __strong emphasis__~~", + assertRendering( + "~~Paragraph with *emphasis* and __strong emphasis__~~", "

Paragraph with emphasis and strong emphasis

\n"); } @Test public void insideBlockQuote() { - assertRendering("> strike ~~that~~", + assertRendering( + "> strike ~~that~~", "
\n

strike that

\n
\n"); } @@ -96,12 +98,15 @@ public void textContentRenderer() { @Test public void requireTwoTildesOption() { - Parser parser = Parser.builder() - .extensions(Set.of(StrikethroughExtension.builder() - .requireTwoTildes(true) - .build())) - .customDelimiterProcessor(new SubscriptDelimiterProcessor()) - .build(); + Parser parser = + Parser.builder() + .extensions( + Set.of( + StrikethroughExtension.builder() + .requireTwoTildes(true) + .build())) + .customDelimiterProcessor(new SubscriptDelimiterProcessor()) + .build(); Node document = parser.parse("~foo~ ~~bar~~"); assertThat(CONTENT_RENDERER.render(document)).isEqualTo("(sub)foo(/sub) /bar/"); @@ -109,10 +114,11 @@ public void requireTwoTildesOption() { @Test public void sourceSpans() { - Parser parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); + Parser parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); Node document = parser.parse("hey ~~there~~\n"); Paragraph block = (Paragraph) document.getFirstChild(); diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBlock.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBlock.java index c46fc27ef..3ad550907 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBlock.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBlock.java @@ -2,8 +2,5 @@ import org.commonmark.node.CustomBlock; -/** - * Table block containing a {@link TableHead} and optionally a {@link TableBody}. - */ -public class TableBlock extends CustomBlock { -} +/** Table block containing a {@link TableHead} and optionally a {@link TableBody}. */ +public class TableBlock extends CustomBlock {} diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBody.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBody.java index ddc80deb3..09f5b45b1 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBody.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBody.java @@ -2,8 +2,5 @@ import org.commonmark.node.CustomNode; -/** - * Body part of a {@link TableBlock} containing {@link TableRow TableRows}. - */ -public class TableBody extends CustomNode { -} +/** Body part of a {@link TableBlock} containing {@link TableRow TableRows}. */ +public class TableBody extends CustomNode {} diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableCell.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableCell.java index 033c2dd04..d4ad1f171 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableCell.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableCell.java @@ -2,9 +2,7 @@ import org.commonmark.node.CustomNode; -/** - * Table cell of a {@link TableRow} containing inline nodes. - */ +/** Table cell of a {@link TableRow} containing inline nodes. */ public class TableCell extends CustomNode { private boolean header; @@ -34,7 +32,8 @@ public void setAlignment(Alignment alignment) { } /** - * @return the cell width (the number of dash and colon characters in the delimiter row of the table for this column) + * @return the cell width (the number of dash and colon characters in the delimiter row of the + * table for this column) */ public int getWidth() { return width; @@ -44,11 +43,10 @@ public void setWidth(int width) { this.width = width; } - /** - * How the cell is aligned horizontally. - */ + /** How the cell is aligned horizontally. */ public enum Alignment { - LEFT, CENTER, RIGHT + LEFT, + CENTER, + RIGHT } - } diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableHead.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableHead.java index 96a95e620..fa771f8f7 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableHead.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableHead.java @@ -2,8 +2,5 @@ import org.commonmark.node.CustomNode; -/** - * Head part of a {@link TableBlock} containing {@link TableRow TableRows}. - */ -public class TableHead extends CustomNode { -} +/** Head part of a {@link TableBlock} containing {@link TableRow TableRows}. */ +public class TableHead extends CustomNode {} diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableRow.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableRow.java index 1325875d0..19b31b9bc 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableRow.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableRow.java @@ -5,5 +5,4 @@ /** * Table row of a {@link TableHead} or {@link TableBody} containing {@link TableCell TableCells}. */ -public class TableRow extends CustomNode { -} +public class TableRow extends CustomNode {} diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TablesExtension.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TablesExtension.java index 4740e9aad..582c30aae 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TablesExtension.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TablesExtension.java @@ -1,5 +1,6 @@ package org.commonmark.ext.gfm.tables; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.ext.gfm.tables.internal.TableBlockParser; import org.commonmark.ext.gfm.tables.internal.TableHtmlNodeRenderer; @@ -13,26 +14,25 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.commonmark.renderer.text.TextContentRenderer; -import java.util.Set; - /** * Extension for GFM tables using "|" pipes (GitHub Flavored Markdown). - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- *

- * The parsed tables are turned into {@link TableBlock} blocks. - *

* - * @see Tables (extension) in GitHub Flavored Markdown Spec + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The parsed tables are turned into {@link TableBlock} blocks. + * + * @see Tables (extension) in GitHub + * Flavored Markdown Spec */ -public class TablesExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, - TextContentRenderer.TextContentRendererExtension, MarkdownRenderer.MarkdownRendererExtension { +public class TablesExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + TextContentRenderer.TextContentRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { - private TablesExtension() { - } + private TablesExtension() {} public static Extension create() { return new TablesExtension(); @@ -55,16 +55,17 @@ public void extend(TextContentRenderer.Builder rendererBuilder) { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new TableMarkdownNodeRenderer(context); - } + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new TableMarkdownNodeRenderer(context); + } - @Override - public Set getSpecialCharacters() { - return Set.of('|'); - } - }); + @Override + public Set getSpecialCharacters() { + return Set.of('|'); + } + }); } } 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 49f17194d..5e74e78eb 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 @@ -1,5 +1,7 @@ package org.commonmark.ext.gfm.tables.internal; +import java.util.ArrayList; +import java.util.List; import org.commonmark.ext.gfm.tables.*; import org.commonmark.node.Block; import org.commonmark.node.Node; @@ -10,9 +12,6 @@ import org.commonmark.parser.block.*; import org.commonmark.text.Characters; -import java.util.ArrayList; -import java.util.List; - public class TableBlockParser extends AbstractBlockParser { private final TableBlock block = new TableBlock(); @@ -42,8 +41,10 @@ public BlockContinue tryContinue(ParserState state) { int pipe = Characters.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 (Characters.skipSpaceTab(content, pipe + 1, content.length()) == content.length()) { + // If we *only* have a pipe character (and whitespace), that is not a valid table + // row and ends the table. + if (Characters.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(); @@ -88,7 +89,8 @@ public void parseInlines(InlineParser inlineParser) { // Body starts at index 2. 0 is header, 1 is separator. for (int rowIndex = 2; rowIndex < rowLines.size(); rowIndex++) { SourceLine rowLine = rowLines.get(rowIndex); - SourceSpan sourceSpan = rowIndex < sourceSpans.size() ? sourceSpans.get(rowIndex) : null; + SourceSpan sourceSpan = + rowIndex < sourceSpans.size() ? sourceSpans.get(rowIndex) : null; List cells = split(rowLine); TableRow row = new TableRow(); if (sourceSpan != null) { @@ -103,7 +105,8 @@ public void parseInlines(InlineParser inlineParser) { } if (body == null) { - // It's valid to have a table without body. In that case, don't add an empty TableBody node. + // It's valid to have a table without body. In that case, don't add an empty + // TableBody node. body = new TableBody(); block.appendChild(body); } @@ -152,9 +155,10 @@ private static List split(SourceLine line) { switch (c) { case '\\': if (i + 1 < cellEnd && row.charAt(i + 1) == '|') { - // Pipe is special for table parsing. An escaped pipe doesn't result in a new cell, but is - // passed down to inline parsing as an unescaped pipe. Note that that applies even for the `\|` - // in an input like `\\|` - in other words, table parsing doesn't support escaping backslashes. + // Pipe is special for table parsing. An escaped pipe doesn't result in a + // new cell, but is passed down to inline parsing as an unescaped pipe. Note + // that that applies even for the `\|` in an input like `\\|` - in other + // words, table parsing doesn't support escaping backslashes. sb.append('|'); i++; } else { @@ -176,7 +180,10 @@ private static List split(SourceLine line) { } if (sb.length() > 0) { String content = sb.toString(); - cells.add(SourceLine.of(content, line.substring(cellStart, line.getContent().length()).getSourceSpan())); + cells.add( + SourceLine.of( + content, + line.substring(cellStart, line.getContent().length()).getSourceSpan())); } return cells; } @@ -211,7 +218,8 @@ private static List parseSeparator(CharSequence s) { case '-': case ':': if (pipes == 0 && !columns.isEmpty()) { - // Need a pipe after the first column (first column doesn't need to start with one) + // Need a pipe after the first column (first column doesn't need to start + // with one) return null; } boolean left = false; @@ -274,9 +282,14 @@ public static class Factory extends AbstractBlockParserFactory { @Override public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { List paragraphLines = matchedBlockParser.getParagraphLines().getLines(); - if (!paragraphLines.isEmpty() && Characters.find('|', paragraphLines.get(paragraphLines.size() - 1).getContent(), 0) != -1) { + if (paragraphLines.isEmpty()) { + return BlockStart.none(); + } + var previousLine = paragraphLines.get(paragraphLines.size() - 1).getContent(); + if (Characters.find('|', previousLine, 0) != -1) { SourceLine line = state.getLine(); - SourceLine separatorLine = line.substring(state.getIndex(), line.getContent().length()); + SourceLine separatorLine = + line.substring(state.getIndex(), line.getContent().length()); List columns = parseSeparator(separatorLine.getContent()); if (columns != null && !columns.isEmpty()) { SourceLine paragraph = paragraphLines.get(paragraphLines.size() - 1); diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableHtmlNodeRenderer.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableHtmlNodeRenderer.java index 966c4c151..81e584c9d 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableHtmlNodeRenderer.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableHtmlNodeRenderer.java @@ -1,12 +1,11 @@ package org.commonmark.ext.gfm.tables.internal; +import java.util.Map; import org.commonmark.ext.gfm.tables.*; import org.commonmark.node.Node; import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.Map; - public class TableHtmlNodeRenderer extends TableNodeRenderer { private final HtmlWriter htmlWriter; @@ -69,7 +68,8 @@ private Map getAttributes(Node node, String tagName) { private Map getCellAttributes(TableCell tableCell, String tagName) { if (tableCell.getAlignment() != null) { - return context.extendAttributes(tableCell, tagName, Map.of("align", getAlignValue(tableCell.getAlignment()))); + return context.extendAttributes( + tableCell, tagName, Map.of("align", getAlignValue(tableCell.getAlignment()))); } else { return context.extendAttributes(tableCell, tagName, Map.of()); } diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableMarkdownNodeRenderer.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableMarkdownNodeRenderer.java index b0705f579..a9c4f9049 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableMarkdownNodeRenderer.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableMarkdownNodeRenderer.java @@ -1,16 +1,16 @@ package org.commonmark.ext.gfm.tables.internal; +import java.util.ArrayList; +import java.util.List; import org.commonmark.ext.gfm.tables.*; import org.commonmark.node.Node; import org.commonmark.renderer.markdown.MarkdownNodeRendererContext; import org.commonmark.renderer.markdown.MarkdownWriter; import org.commonmark.text.AsciiMatcher; -import java.util.ArrayList; -import java.util.List; - /** - * The Table node renderer that is needed for rendering GFM tables (GitHub Flavored Markdown) to text content. + * The Table node renderer that is needed for rendering GFM tables (GitHub Flavored Markdown) to + * text content. */ public class TableMarkdownNodeRenderer extends TableNodeRenderer { private final MarkdownWriter writer; diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableNodeRenderer.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableNodeRenderer.java index 2982e1518..4e3a00815 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableNodeRenderer.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.ext.gfm.tables.internal; +import java.util.Set; import org.commonmark.ext.gfm.tables.*; import org.commonmark.node.Node; import org.commonmark.renderer.NodeRenderer; -import java.util.Set; - abstract class TableNodeRenderer implements NodeRenderer { @Override @@ -15,8 +14,7 @@ public Set> getNodeTypes() { TableHead.class, TableBody.class, TableRow.class, - TableCell.class - ); + TableCell.class); } @Override diff --git a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableTextContentNodeRenderer.java b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableTextContentNodeRenderer.java index 0ba6894b5..b9e17c1d3 100644 --- a/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableTextContentNodeRenderer.java +++ b/commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableTextContentNodeRenderer.java @@ -10,7 +10,8 @@ import org.commonmark.renderer.text.TextContentWriter; /** - * The Table node renderer that is needed for rendering GFM tables (GitHub Flavored Markdown) to text content. + * The Table node renderer that is needed for rendering GFM tables (GitHub Flavored Markdown) to + * text content. */ public class TableTextContentNodeRenderer extends TableNodeRenderer { diff --git a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TableMarkdownRendererTest.java b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TableMarkdownRendererTest.java index 85c11206c..32a8218b2 100644 --- a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TableMarkdownRendererTest.java +++ b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TableMarkdownRendererTest.java @@ -1,19 +1,19 @@ package org.commonmark.ext.gfm.tables; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class TableMarkdownRendererTest { private static final Set EXTENSIONS = Set.of(TablesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testHeadNoBody() { @@ -60,7 +60,8 @@ public void testEscaping() { @Test public void testEscaped() { - // `|` in Text nodes needs to be escaped, otherwise the generated Markdown does not get parsed back as a table + // `|` in Text nodes needs to be escaped, otherwise the generated Markdown does not get + // parsed back as a table assertRoundTrip("\\|Abc\\|\n\\|---\\|\n"); } diff --git a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesSpecTest.java b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesSpecTest.java index e7f3db4d1..81def7c2e 100644 --- a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesSpecTest.java +++ b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesSpecTest.java @@ -1,5 +1,7 @@ package org.commonmark.ext.gfm.tables; +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; @@ -12,19 +14,16 @@ import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.util.List; -import java.util.Set; - @ParameterizedClass @MethodSource("data") public class TablesSpecTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(TablesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); - @Parameter - Example example; + @Parameter Example example; static List data() { return ExampleReader.readExamples(TestResources.getGfmSpec(), "table"); 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 98c3ad4d7..f872c0cde 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 @@ -1,5 +1,9 @@ package org.commonmark.ext.gfm.tables; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.*; import org.commonmark.parser.IncludeSourceSpans; @@ -9,16 +13,12 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class TablesTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(TablesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void mustHaveHeaderAndSeparator() { @@ -28,22 +28,26 @@ public void mustHaveHeaderAndSeparator() { @Test public void separatorMustBeOneOrMore() { - assertRendering("Abc|Def\n-|-", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
\n"); - assertRendering("Abc|Def\n--|--", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
\n"); + assertRendering( + "Abc|Def\n-|-", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
\n"); + assertRendering( + "Abc|Def\n--|--", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
\n"); } @Test @@ -55,14 +59,16 @@ public void separatorMustNotContainInvalidChars() { @Test public void separatorCanHaveLeadingSpaceThenPipe() { - assertRendering("Abc|Def\n |---|---", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
\n"); + assertRendering( + "Abc|Def\n |---|---", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
\n"); } @Test @@ -77,25 +83,28 @@ public void separatorNeedsPipes() { @Test public void oneHeadNoBody() { - assertRendering("Abc|Def\n---|---", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
\n"); + assertRendering( + "Abc|Def\n---|---", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
\n"); } @Test public void oneColumnOneHeadNoBody() { - String expected = "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
Abc
\n"; + String expected = + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
Abc
\n"; assertRendering("|Abc\n|---\n", expected); assertRendering("|Abc|\n|---|\n", expected); assertRendering("Abc|\n---|\n", expected); @@ -108,18 +117,19 @@ public void oneColumnOneHeadNoBody() { @Test public void oneColumnOneHeadOneBody() { - String expected = "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
Abc
1
\n"; + String expected = + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
Abc
1
\n"; assertRendering("|Abc\n|---\n|1", expected); assertRendering("|Abc|\n|---|\n|1|", expected); assertRendering("Abc|\n---|\n1|", expected); @@ -130,38 +140,42 @@ public void oneColumnOneHeadOneBody() { @Test public void oneHeadOneBody() { - assertRendering("Abc|Def\n---|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n---|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void spaceBeforeSeparator() { - assertRendering(" |Abc|Def|\n |---|---|\n |1|2|", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + " |Abc|Def|\n |---|---|\n |1|2|", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test @@ -171,368 +185,408 @@ public void separatorMustNotHaveLessPartsThanHead() { @Test public void padding() { - assertRendering(" Abc | Def \n --- | --- \n 1 | 2 ", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + " Abc | Def \n --- | --- \n 1 | 2 ", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void paddingWithCodeBlockIndentation() { - assertRendering("Abc|Def\n---|---\n 1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n---|---\n 1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void pipesOnOutside() { - assertRendering("|Abc|Def|\n|---|---|\n|1|2|", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "|Abc|Def|\n|---|---|\n|1|2|", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void pipesOnOutsideWhitespaceAfterHeader() { - assertRendering("|Abc|Def| \n|---|---|\n|1|2|", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "|Abc|Def| \n|---|---|\n|1|2|", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void pipesOnOutsideZeroLengthHeaders() { // This is literally what someone has done IRL - it helped to expose // an issue with parsing the last header cell correctly - assertRendering("||center header||\n" + - "-|-------------|-\n" + - "1| 2 |3", - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
center header
123
\n"); + assertRendering( + "||center header||\n" + "-|-------------|-\n" + "1| 2 |3", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
center header
123
\n"); } @Test public void inlineElements() { - assertRendering("*Abc*|Def\n---|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "*Abc*|Def\n---|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void escapedPipe() { - assertRendering("Abc|Def\n---|---\n1\\|2|20", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
1|220
\n"); + assertRendering( + "Abc|Def\n---|---\n1\\|2|20", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
1|220
\n"); } @Test public void escapedBackslash() { - // This is a bit weird in the GFM spec IMO. `1\\|2` looks like an escaped backslash, followed by a pipe - // (so two cells). Instead, the `\|` is parsed as an escaped pipe first, so just a single cell. The inline - // parser then gets `1\|2` which renders as `1|2`. - assertRendering("Abc|Def\n---|---\n1\\\\|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
1|2
\n"); + // This is a bit weird in the GFM spec IMO. `1\\|2` looks like an escaped backslash, + // followed by a pipe (so two cells). Instead, the `\|` is parsed as an escaped pipe first, + // so just a single cell. The inline parser then gets `1\|2` which renders as `1|2`. + assertRendering( + "Abc|Def\n---|---\n1\\\\|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
1|2
\n"); } @Test public void escapedOther() { - // This is a tricky one. For \`, we don't want to remove the backslash when we parse the table, otherwise - // inline parsing is wrong. So we have to be careful where we do/don't consume the backslash. - assertRendering("Abc|Def\n---|---\n1|\\`not code`", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
1`not code`
\n"); + // This is a tricky one. For \`, we don't want to remove the backslash when we parse the + // table, otherwise inline parsing is wrong. So we have to be careful where we do/don't + // consume the backslash. + assertRendering( + "Abc|Def\n---|---\n1|\\`not code`", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
1`not code`
\n"); } @Test public void backslashAtEnd() { - assertRendering("Abc|Def\n---|---\n1|2\\", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12\\
\n"); + assertRendering( + "Abc|Def\n---|---\n1|2\\", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12\\
\n"); } @Test public void alignLeft() { - assertRendering("Abc|Def\n:-|-\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n:-|-\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n:---|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:-|-\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:-|-\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:---|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void alignRight() { - assertRendering("Abc|Def\n-:|-\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n--:|--\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n---:|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n-:|-\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n--:|--\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n---:|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void alignCenter() { - assertRendering("Abc|Def\n:-:|-\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n:--:|--\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); - assertRendering("Abc|Def\n:---:|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:-:|-\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:--:|--\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n:---:|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void alignCenterSecond() { - assertRendering("Abc|Def\n---|:---:\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n---|:---:\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void alignLeftWithSpaces() { - assertRendering("Abc|Def\n :--- |---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n :--- |---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test @@ -545,249 +599,272 @@ public void alignmentMarkerMustBeNextToDashes() { @Test public void bodyCanNotHaveMoreColumnsThanHead() { - assertRendering("Abc|Def\n---|---\n1|2|3", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertRendering( + "Abc|Def\n---|---\n1|2|3", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void bodyWithFewerColumnsThanHeadResultsInEmptyCells() { - assertRendering("Abc|Def|Ghi\n---|---|---\n1|2", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDefGhi
12
\n"); + assertRendering( + "Abc|Def|Ghi\n---|---|---\n1|2", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDefGhi
12
\n"); } @Test public void insideBlockQuote() { - 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 tableWithLazyContinuationLine() { - assertRendering("Abc|Def\n---|---\n1|2\nlazy", "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
lazy
\n"); + assertRendering( + "Abc|Def\n---|---\n1|2\nlazy", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
lazy
\n"); } @Test public void issue142() { - assertRendering("||Alveolar|Bilabial\n" + - "|:--|:-:|:-:\n" + - "|**Plosive**|t, d|b\n" + - "|**Tap**|ɾ|", - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AlveolarBilabial
Plosivet, db
Tapɾ
\n"); + assertRendering( + "||Alveolar|Bilabial\n" + + "|:--|:-:|:-:\n" + + "|**Plosive**|t, d|b\n" + + "|**Tap**|ɾ|", + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AlveolarBilabial
Plosivet, db
Tapɾ
\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"); + 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 interruptsParagraph() { - assertRendering("text\n" + - "|a |\n" + - "|---|\n" + - "|b |", "

text

\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
a
b
\n"); + assertRendering( + "text\n" + "|a |\n" + "|---|\n" + "|b |", + "

text

\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
a
b
\n"); } @Test public void attributeProviderIsApplied() { - AttributeProviderFactory factory = context -> (node, tagName, attributes) -> { - if (node instanceof TableBlock) { - attributes.put("test", "block"); - } else if (node instanceof TableHead) { - attributes.put("test", "head"); - } else if (node instanceof TableBody) { - attributes.put("test", "body"); - } else if (node instanceof TableRow) { - attributes.put("test", "row"); - } else if (node instanceof TableCell) { - attributes.put("test", "cell"); - } - }; - HtmlRenderer renderer = HtmlRenderer.builder() - .attributeProviderFactory(factory) - .extensions(EXTENSIONS) - .build(); + AttributeProviderFactory factory = + context -> + (node, tagName, attributes) -> { + if (node instanceof TableBlock) { + attributes.put("test", "block"); + } else if (node instanceof TableHead) { + attributes.put("test", "head"); + } else if (node instanceof TableBody) { + attributes.put("test", "body"); + } else if (node instanceof TableRow) { + attributes.put("test", "row"); + } else if (node instanceof TableCell) { + attributes.put("test", "cell"); + } + }; + HtmlRenderer renderer = + HtmlRenderer.builder() + .attributeProviderFactory(factory) + .extensions(EXTENSIONS) + .build(); String rendered = renderer.render(PARSER.parse("Abc|Def\n---|---\n1|2")); - assertThat(rendered).isEqualTo("\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertThat(rendered) + .isEqualTo( + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void columnWidthIsRecorded() { - AttributeProviderFactory factory = context -> (node, tagName, attributes) -> { - if (node instanceof TableCell && "th".equals(tagName)) { - attributes.put("width", ((TableCell) node).getWidth() + "em"); - } - }; - HtmlRenderer renderer = HtmlRenderer.builder() - .attributeProviderFactory(factory) - .extensions(EXTENSIONS) - .build(); + AttributeProviderFactory factory = + context -> + (node, tagName, attributes) -> { + if (node instanceof TableCell && "th".equals(tagName)) { + attributes.put("width", ((TableCell) node).getWidth() + "em"); + } + }; + HtmlRenderer renderer = + HtmlRenderer.builder() + .attributeProviderFactory(factory) + .extensions(EXTENSIONS) + .build(); String rendered = renderer.render(PARSER.parse("Abc|Def\n-----|---\n1|2")); - assertThat(rendered).isEqualTo("\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "
AbcDef
12
\n"); + assertThat(rendered) + .isEqualTo( + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
AbcDef
12
\n"); } @Test public void sourceSpans() { - Parser parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); + Parser parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); Node document = parser.parse("Abc|Def\n---|---\n|1|2\n 3|four|\n|||\n"); TableBlock block = (TableBlock) document.getFirstChild(); - assertThat(block.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 7), - SourceSpan.of(2, 0, 16, 4), SourceSpan.of(3, 0, 21, 8), SourceSpan.of(4, 0, 30, 3))); + assertThat(block.getSourceSpans()) + .isEqualTo( + List.of( + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 7), + SourceSpan.of(2, 0, 16, 4), + SourceSpan.of(3, 0, 21, 8), + SourceSpan.of(4, 0, 30, 3))); TableHead head = (TableHead) block.getFirstChild(); assertThat(head.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 7))); @@ -797,30 +874,41 @@ public void sourceSpans() { TableCell headRowCell1 = (TableCell) headRow.getFirstChild(); TableCell headRowCell2 = (TableCell) headRow.getLastChild(); assertThat(headRowCell1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 3))); - assertThat(headRowCell1.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 3))); + assertThat(headRowCell1.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 3))); assertThat(headRowCell2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 4, 4, 3))); - assertThat(headRowCell2.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 4, 4, 3))); + assertThat(headRowCell2.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 4, 4, 3))); TableBody body = (TableBody) block.getLastChild(); - assertThat(body.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 0, 16, 4), SourceSpan.of(3, 0, 21, 8), SourceSpan.of(4, 0, 30, 3))); + assertThat(body.getSourceSpans()) + .isEqualTo( + List.of( + SourceSpan.of(2, 0, 16, 4), + SourceSpan.of(3, 0, 21, 8), + SourceSpan.of(4, 0, 30, 3))); TableRow bodyRow1 = (TableRow) body.getFirstChild(); assertThat(bodyRow1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 0, 16, 4))); TableCell bodyRow1Cell1 = (TableCell) bodyRow1.getFirstChild(); TableCell bodyRow1Cell2 = (TableCell) bodyRow1.getLastChild(); assertThat(bodyRow1Cell1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 1, 17, 1))); - assertThat(bodyRow1Cell1.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 1, 17, 1))); + assertThat(bodyRow1Cell1.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(2, 1, 17, 1))); assertThat(bodyRow1Cell2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 3, 19, 1))); - assertThat(bodyRow1Cell2.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(2, 3, 19, 1))); + assertThat(bodyRow1Cell2.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(2, 3, 19, 1))); TableRow bodyRow2 = (TableRow) body.getFirstChild().getNext(); assertThat(bodyRow2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(3, 0, 21, 8))); TableCell bodyRow2Cell1 = (TableCell) bodyRow2.getFirstChild(); TableCell bodyRow2Cell2 = (TableCell) bodyRow2.getLastChild(); assertThat(bodyRow2Cell1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(3, 1, 22, 1))); - assertThat(bodyRow2Cell1.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(3, 1, 22, 1))); + assertThat(bodyRow2Cell1.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(3, 1, 22, 1))); assertThat(bodyRow2Cell2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(3, 3, 24, 4))); - assertThat(bodyRow2Cell2.getFirstChild().getSourceSpans()).isEqualTo(List.of(SourceSpan.of(3, 3, 24, 4))); + assertThat(bodyRow2Cell2.getFirstChild().getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(3, 3, 24, 4))); TableRow bodyRow3 = (TableRow) body.getLastChild(); assertThat(bodyRow3.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(4, 0, 30, 3))); @@ -832,15 +920,12 @@ public void sourceSpans() { @Test public void sourceSpansWhenInterrupting() { - var parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); - var document = parser.parse("a\n" + - "bc\n" + - "|de|\n" + - "|---|\n" + - "|fg|"); + var parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); + var document = parser.parse("a\n" + "bc\n" + "|de|\n" + "|---|\n" + "|fg|"); var paragraph = (Paragraph) document.getFirstChild(); var text = (Text) paragraph.getFirstChild(); @@ -849,15 +934,16 @@ public void sourceSpansWhenInterrupting() { var text2 = (Text) text.getNext().getNext(); assertThat(text2.getLiteral()).isEqualTo("bc"); - assertThat(paragraph.getSourceSpans()).isEqualTo(List.of( - SourceSpan.of(0, 0, 0, 1), - SourceSpan.of(1, 0, 2, 2))); + assertThat(paragraph.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 1), SourceSpan.of(1, 0, 2, 2))); var table = (TableBlock) document.getLastChild(); - assertThat(table.getSourceSpans()).isEqualTo(List.of( - SourceSpan.of(2, 0, 5, 4), - SourceSpan.of(3, 0, 10, 5), - SourceSpan.of(4, 0, 16, 4))); + assertThat(table.getSourceSpans()) + .isEqualTo( + List.of( + SourceSpan.of(2, 0, 5, 4), + SourceSpan.of(3, 0, 10, 5), + SourceSpan.of(4, 0, 16, 4))); } @Override diff --git a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTextContentTest.java b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTextContentTest.java index 966f097fd..a57ce9eac 100644 --- a/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTextContentTest.java +++ b/commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesTextContentTest.java @@ -1,5 +1,6 @@ package org.commonmark.ext.gfm.tables; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.text.LineBreakRendering; @@ -7,19 +8,25 @@ import org.commonmark.testutil.Asserts; import org.junit.jupiter.api.Test; -import java.util.Set; - public class TablesTextContentTest { private static final Set EXTENSIONS = Set.of(TablesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final TextContentRenderer RENDERER = TextContentRenderer.builder().extensions(EXTENSIONS).build(); - - private static final TextContentRenderer COMPACT_RENDERER = TextContentRenderer.builder().extensions(EXTENSIONS).build(); - private static final TextContentRenderer SEPARATE_RENDERER = TextContentRenderer.builder().extensions(EXTENSIONS) - .lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS).build(); - private static final TextContentRenderer STRIPPED_RENDERER = TextContentRenderer.builder().extensions(EXTENSIONS) - .lineBreakRendering(LineBreakRendering.STRIP).build(); + private static final TextContentRenderer RENDERER = + TextContentRenderer.builder().extensions(EXTENSIONS).build(); + + private static final TextContentRenderer COMPACT_RENDERER = + TextContentRenderer.builder().extensions(EXTENSIONS).build(); + private static final TextContentRenderer SEPARATE_RENDERER = + TextContentRenderer.builder() + .extensions(EXTENSIONS) + .lineBreakRendering(LineBreakRendering.SEPARATE_BLOCKS) + .build(); + private static final TextContentRenderer STRIPPED_RENDERER = + TextContentRenderer.builder() + .extensions(EXTENSIONS) + .lineBreakRendering(LineBreakRendering.STRIP) + .build(); @Test public void oneHeadNoBody() { diff --git a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/HeadingAnchorExtension.java b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/HeadingAnchorExtension.java index 5921f3c5b..1b9f5487e 100644 --- a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/HeadingAnchorExtension.java +++ b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/HeadingAnchorExtension.java @@ -6,17 +6,20 @@ /** * Extension for adding auto generated IDs to headings. - *

- * Create it with {@link #create()} or {@link #builder()} and then configure it on the - * renderer builder ({@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- * The heading text will be used to create the id. Multiple headings with the - * same text will result in appending a hyphen and number. For example: + * + *

Create it with {@link #create()} or {@link #builder()} and then configure it on the renderer + * builder ({@link HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The heading text will be used to create the id. Multiple headings with the same text will + * result in appending a hyphen and number. For example: + * *


  * # Heading
  * # Heading
  * 
+ * * will result in + * *

  * <h1 id="heading">Heading</h1>
  * <h1 id="heading-1">Heading</h1>
@@ -52,7 +55,8 @@ public static Builder builder() {
 
     @Override
     public void extend(HtmlRenderer.Builder rendererBuilder) {
-        rendererBuilder.attributeProviderFactory(context -> HeadingIdAttributeProvider.create(defaultId, idPrefix, idSuffix));
+        rendererBuilder.attributeProviderFactory(
+                context -> HeadingIdAttributeProvider.create(defaultId, idPrefix, idSuffix));
     }
 
     public static class Builder {
@@ -61,7 +65,8 @@ public static class Builder {
         private String idSuffix = "";
 
         /**
-         * @param value Default value for the id to take if no generated id can be extracted. Default "id"
+         * @param value Default value for the id to take if no generated id can be extracted.
+         *     Default "id"
          * @return {@code this}
          */
         public Builder defaultId(String value) {
diff --git a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/IdGenerator.java b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/IdGenerator.java
index 2c37433e2..8ab5b3b32 100644
--- a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/IdGenerator.java
+++ b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/IdGenerator.java
@@ -7,8 +7,8 @@
 
 /**
  * Generates strings to be used as identifiers.
- * 

- * Use {@link #builder()} to create an instance. + * + *

Use {@link #builder()} to create an instance. */ public class IdGenerator { private final Pattern allowedCharacters; @@ -33,35 +33,35 @@ public static Builder builder() { } /** - *

* Generate an ID based on the provided text and previously generated IDs. - *

- * This method is not thread safe, concurrent calls can end up - * with non-unique identifiers. - *

- * Note that collision can occur in the case that + * + *

This method is not thread safe, concurrent calls can end up with non-unique identifiers. + * + *

Note that collision can occur in the case that + * *

    - *
  • Method called with 'X'
  • - *
  • Method called with 'X' again
  • - *
  • Method called with 'X-1'
  • + *
  • Method called with 'X' + *
  • Method called with 'X' again + *
  • Method called with 'X-1' *
- *

- * In that case, the three generated IDs will be: + * + *

In that case, the three generated IDs will be: + * *

    - *
  • X
  • - *
  • X-1
  • - *
  • X-1
  • + *
  • X + *
  • X-1 + *
  • X-1 *
- *

- * Therefore if collisions are unacceptable you should ensure that - * numbers are stripped from end of {@code text}. * - * @param text Text that the identifier should be based on. Will be normalised, then used to generate the - * identifier. - * @return {@code text} if this is the first instance that the {@code text} has been passed - * to the method. Otherwise, {@code text + "-" + X} will be returned, where X is the number of times - * that {@code text} has previously been passed in. If {@code text} is empty, the default - * identifier given in the constructor will be used. + *

Therefore if collisions are unacceptable you should ensure that numbers are stripped from + * end of {@code text}. + * + * @param text Text that the identifier should be based on. Will be normalised, then used to + * generate the identifier. + * @return {@code text} if this is the first instance that the {@code text} has been passed to + * the method. Otherwise, {@code text + "-" + X} will be returned, where X is the number of + * times that {@code text} has previously been passed in. If {@code text} is empty, the + * default identifier given in the constructor will be used. */ public String generateId(String text) { String normalizedIdentity = text != null ? normalizeText(text) : defaultIdentifier; @@ -85,7 +85,8 @@ private static Pattern compileAllowedCharactersPattern() { try { return Pattern.compile(regex, Pattern.UNICODE_CHARACTER_CLASS); } catch (IllegalArgumentException e) { - // Android only supports the flag in API level 24. But it actually uses Unicode character classes by + // Android only supports the flag in API level 24. But it actually uses Unicode + // character classes by // default, so not specifying the flag is ok. See issue #71. return Pattern.compile(regex); } @@ -119,7 +120,8 @@ public IdGenerator build() { } /** - * @param defaultId the default identifier to use in case the provided text is empty or only contains unusable characters + * @param defaultId the default identifier to use in case the provided text is empty or only + * contains unusable characters * @return {@code this} */ public Builder defaultId(String defaultId) { diff --git a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/internal/HeadingIdAttributeProvider.java b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/internal/HeadingIdAttributeProvider.java index 6b8792bd5..f7d1b75a1 100644 --- a/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/internal/HeadingIdAttributeProvider.java +++ b/commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/internal/HeadingIdAttributeProvider.java @@ -1,26 +1,23 @@ package org.commonmark.ext.heading.anchor.internal; -import org.commonmark.ext.heading.anchor.IdGenerator; -import org.commonmark.renderer.html.AttributeProvider; -import org.commonmark.node.*; - import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.commonmark.ext.heading.anchor.IdGenerator; +import org.commonmark.node.*; +import org.commonmark.renderer.html.AttributeProvider; public class HeadingIdAttributeProvider implements AttributeProvider { private final IdGenerator idGenerator; private HeadingIdAttributeProvider(String defaultId, String prefix, String suffix) { - idGenerator = IdGenerator.builder() - .defaultId(defaultId) - .prefix(prefix) - .suffix(suffix) - .build(); + idGenerator = + IdGenerator.builder().defaultId(defaultId).prefix(prefix).suffix(suffix).build(); } - public static HeadingIdAttributeProvider create(String defaultId, String prefix, String suffix) { + public static HeadingIdAttributeProvider create( + String defaultId, String prefix, String suffix) { return new HeadingIdAttributeProvider(defaultId, prefix, suffix); } @@ -31,17 +28,18 @@ public void setAttributes(Node node, String tagName, final Map a final List wordList = new ArrayList<>(); - node.accept(new AbstractVisitor() { - @Override - public void visit(Text text) { - wordList.add(text.getLiteral()); - } - - @Override - public void visit(Code code) { - wordList.add(code.getLiteral()); - } - }); + node.accept( + new AbstractVisitor() { + @Override + public void visit(Text text) { + wordList.add(text.getLiteral()); + } + + @Override + public void visit(Code code) { + wordList.add(code.getLiteral()); + } + }); String finalString = ""; for (String word : wordList) { diff --git a/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorConfigurationTest.java b/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorConfigurationTest.java index 438a3a9bd..c78b7c61a 100644 --- a/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorConfigurationTest.java +++ b/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorConfigurationTest.java @@ -1,34 +1,31 @@ package org.commonmark.ext.heading.anchor; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - public class HeadingAnchorConfigurationTest { private static final Parser PARSER = Parser.builder().build(); private HtmlRenderer buildRenderer(String defaultId, String prefix, String suffix) { - Extension ext = HeadingAnchorExtension.builder() - .defaultId(defaultId) - .idPrefix(prefix) - .idSuffix(suffix) - .build(); - return HtmlRenderer.builder() - .extensions(List.of(ext)) - .build(); + Extension ext = + HeadingAnchorExtension.builder() + .defaultId(defaultId) + .idPrefix(prefix) + .idSuffix(suffix) + .build(); + return HtmlRenderer.builder().extensions(List.of(ext)).build(); } @Test public void testDefaultConfigurationHasNoAdditions() { - HtmlRenderer renderer = HtmlRenderer.builder() - .extensions(List.of(HeadingAnchorExtension.create())) - .build(); + HtmlRenderer renderer = + HtmlRenderer.builder().extensions(List.of(HeadingAnchorExtension.create())).build(); assertThat(doRender(renderer, "# ")).isEqualTo("

\n"); } @@ -53,5 +50,4 @@ public void testSuffixAddedToHeader() { private String doRender(HtmlRenderer renderer, String text) { return renderer.render(PARSER.parse(text)); } - } diff --git a/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorTest.java b/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorTest.java index 3149542e3..95ee2d7eb 100644 --- a/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorTest.java +++ b/commonmark-ext-heading-anchor/src/test/java/org/commonmark/ext/heading/anchor/HeadingAnchorTest.java @@ -1,34 +1,35 @@ package org.commonmark.ext.heading.anchor; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.Set; - public class HeadingAnchorTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(HeadingAnchorExtension.create()); private static final Parser PARSER = Parser.builder().build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void baseCaseSingleHeader() { - assertRendering("# Heading here\n", - "

Heading here

\n"); + assertRendering("# Heading here\n", "

Heading here

\n"); } @Test public void singleHeaderWithCodeBlock() { - assertRendering("Hi there\n# Heading `here`\n", + assertRendering( + "Hi there\n# Heading `here`\n", "

Hi there

\n

Heading here

\n"); } @Test public void duplicateHeadersMakeUniqueIds() { - assertRendering("# Heading here\n# Heading here", + assertRendering( + "# Heading here\n# Heading here", "

Heading here

\n

Heading here

\n"); } @@ -44,34 +45,40 @@ public void testUndertieUnicodeDisplayed() { @Test public void testExplicitHeaderCollision() { - assertRendering("# Header\n# Header\n# Header-1", - "

Header

\n" + - "

Header

\n" + - "

Header-1

\n"); + assertRendering( + "# Header\n# Header\n# Header-1", + "

Header

\n" + + "

Header

\n" + + "

Header-1

\n"); } @Test public void testCaseIsIgnoredWhenComparingIds() { - assertRendering("# HEADING here\n" + - "# heading here", - "

HEADING here

\n" + - "

heading here

\n"); + assertRendering( + "# HEADING here\n" + "# heading here", + "

HEADING here

\n" + + "

heading here

\n"); } @Test public void testNestedBlocks() { - assertRendering("## `h` `e` **l** *l* o", + assertRendering( + "## `h` `e` **l** *l* o", "

h e l l o

\n"); } @Test public void boldEmphasisCharacters() { - assertRendering("# _hello_ **there**", "

hello there

\n"); + assertRendering( + "# _hello_ **there**", + "

hello there

\n"); } @Test public void testStrongEmphasis() { - assertRendering("# _**Hi there**_", "

Hi there

\n"); + assertRendering( + "# _**Hi there**_", + "

Hi there

\n"); } @Test @@ -86,7 +93,9 @@ public void testNonAsciiCharacterHeading() { @Test public void testCombiningDiaeresis() { - assertRendering("# Product\u036D\u036B", "

Product\u036D\u036B

\n"); + assertRendering( + "# Product\u036D\u036B", + "

Product\u036D\u036B

\n"); } @Override diff --git a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributes.java b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributes.java index 1ee43958b..1739aae77 100644 --- a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributes.java +++ b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributes.java @@ -1,13 +1,10 @@ package org.commonmark.ext.image.attributes; +import java.util.Map; import org.commonmark.node.CustomNode; import org.commonmark.node.Delimited; -import java.util.Map; - -/** - * A node containing text and other inline nodes as children. - */ +/** A node containing text and other inline nodes as children. */ public class ImageAttributes extends CustomNode implements Delimited { private final Map attributes; diff --git a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributesExtension.java b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributesExtension.java index 9a4de2628..f6becc651 100644 --- a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributesExtension.java +++ b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributesExtension.java @@ -8,18 +8,17 @@ /** * Extension for adding attributes to image nodes. - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

+ * + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). * * @since 0.15.0 */ -public class ImageAttributesExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { +public class ImageAttributesExtension + implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { - private ImageAttributesExtension() { - } + private ImageAttributesExtension() {} public static Extension create() { return new ImageAttributesExtension(); @@ -32,6 +31,7 @@ public void extend(Parser.Builder parserBuilder) { @Override public void extend(HtmlRenderer.Builder rendererBuilder) { - rendererBuilder.attributeProviderFactory(context -> ImageAttributesAttributeProvider.create()); + rendererBuilder.attributeProviderFactory( + context -> ImageAttributesAttributeProvider.create()); } } diff --git a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesAttributeProvider.java b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesAttributeProvider.java index bd89738de..c132c9dcd 100644 --- a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesAttributeProvider.java +++ b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesAttributeProvider.java @@ -1,5 +1,6 @@ package org.commonmark.ext.image.attributes.internal; +import java.util.*; import org.commonmark.ext.image.attributes.ImageAttributes; import org.commonmark.node.AbstractVisitor; import org.commonmark.node.CustomNode; @@ -7,12 +8,9 @@ import org.commonmark.node.Node; import org.commonmark.renderer.html.AttributeProvider; -import java.util.*; - public class ImageAttributesAttributeProvider implements AttributeProvider { - private ImageAttributesAttributeProvider() { - } + private ImageAttributesAttributeProvider() {} public static ImageAttributesAttributeProvider create() { return new ImageAttributesAttributeProvider(); @@ -21,17 +19,18 @@ public static ImageAttributesAttributeProvider create() { @Override public void setAttributes(Node node, String tagName, final Map attributes) { if (node instanceof Image) { - node.accept(new AbstractVisitor() { - @Override - public void visit(CustomNode node) { - if (node instanceof ImageAttributes) { - ImageAttributes imageAttributes = (ImageAttributes) node; - attributes.putAll(imageAttributes.getAttributes()); - // Now that we have used the image attributes we remove the node. - imageAttributes.unlink(); - } - } - }); + node.accept( + new AbstractVisitor() { + @Override + public void visit(CustomNode node) { + if (node instanceof ImageAttributes) { + ImageAttributes imageAttributes = (ImageAttributes) node; + attributes.putAll(imageAttributes.getAttributes()); + // Now that we have used the image attributes we remove the node. + imageAttributes.unlink(); + } + } + }); } } } diff --git a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesDelimiterProcessor.java b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesDelimiterProcessor.java index 06a39ba23..53ba882c9 100644 --- a/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesDelimiterProcessor.java +++ b/commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesDelimiterProcessor.java @@ -1,5 +1,6 @@ package org.commonmark.ext.image.attributes.internal; +import java.util.*; import org.commonmark.ext.image.attributes.ImageAttributes; import org.commonmark.node.Image; import org.commonmark.node.Node; @@ -8,8 +9,6 @@ import org.commonmark.parser.delimiter.DelimiterProcessor; import org.commonmark.parser.delimiter.DelimiterRun; -import java.util.*; - public class ImageAttributesDelimiterProcessor implements DelimiterProcessor { // Only allow a defined set of attributes to be used. @@ -36,8 +35,8 @@ public int process(DelimiterRun openingRun, DelimiterRun closingRun) { return 0; } - // Check if the attributes can be applied - if the previous node is an Image, and if all the attributes are in - // the set of SUPPORTED_ATTRIBUTES + // Check if the attributes can be applied - if the previous node is an Image, and if all the + // attributes are in the set of SUPPORTED_ATTRIBUTES Text opener = openingRun.getOpener(); Node nodeToStyle = opener.getPrevious(); if (!(nodeToStyle instanceof Image)) { @@ -53,7 +52,8 @@ public int process(DelimiterRun openingRun, DelimiterRun closingRun) { content.append(((Text) node).getLiteral()); toUnlink.add(node); } else { - // This node type is not supported, so stop here (no need to check any further ones). + // This node type is not supported, so stop here (no need to check any further + // ones). return 0; } } @@ -65,7 +65,8 @@ public int process(DelimiterRun openingRun, DelimiterRun closingRun) { if (attribute.length > 1 && SUPPORTED_ATTRIBUTES.contains(attribute[0].toLowerCase())) { attributesMap.put(attribute[0], attribute[1]); } else { - // This attribute is not supported, so stop here (no need to check any further ones). + // This attribute is not supported, so stop here (no need to check any further + // ones). return 0; } } diff --git a/commonmark-ext-image-attributes/src/test/java/org/commonmark/ext/image/attributes/ImageAttributesTest.java b/commonmark-ext-image-attributes/src/test/java/org/commonmark/ext/image/attributes/ImageAttributesTest.java index 3edf8497e..4232646a2 100644 --- a/commonmark-ext-image-attributes/src/test/java/org/commonmark/ext/image/attributes/ImageAttributesTest.java +++ b/commonmark-ext-image-attributes/src/test/java/org/commonmark/ext/image/attributes/ImageAttributesTest.java @@ -1,5 +1,9 @@ package org.commonmark.ext.image.attributes; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Node; import org.commonmark.node.Paragraph; @@ -10,44 +14,48 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class ImageAttributesTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(ImageAttributesExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void baseCase() { - assertRendering("![text](/url.png){height=5}", + assertRendering( + "![text](/url.png){height=5}", "

\"text\"

\n"); - assertRendering("![text](/url.png){height=5 width=6}", + assertRendering( + "![text](/url.png){height=5 width=6}", "

\"text\"

\n"); - assertRendering("![text](/url.png){height=99px width=100px}", + assertRendering( + "![text](/url.png){height=99px width=100px}", "

\"text\"

\n"); - assertRendering("![text](/url.png){width=100 height=100}", + assertRendering( + "![text](/url.png){width=100 height=100}", "

\"text\"

\n"); - assertRendering("![text](/url.png){height=4.8 width=3.14}", + assertRendering( + "![text](/url.png){height=4.8 width=3.14}", "

\"text\"

\n"); - assertRendering("![text](/url.png){Width=18 HeIgHt=1001}", + assertRendering( + "![text](/url.png){Width=18 HeIgHt=1001}", "

\"text\"

\n"); - assertRendering("![text](/url.png){height=green width=blue}", + assertRendering( + "![text](/url.png){height=green width=blue}", "

\"text\"

\n"); } @Test public void doubleDelimiters() { - assertRendering("![text](/url.png){{height=5}}", + assertRendering( + "![text](/url.png){{height=5}}", "

\"text\"{{height=5}}

\n"); } @@ -58,55 +66,66 @@ public void mismatchingDelimitersAreIgnored() { @Test public void unsupportedStyleNamesAreLeftUnchanged() { - assertRendering("![text](/url.png){j=502 K=101 img=2 url=5}", + assertRendering( + "![text](/url.png){j=502 K=101 img=2 url=5}", "

\"text\"{j=502 K=101 img=2 url=5}

\n"); - assertRendering("![foo](/url.png){height=3 invalid}\n", + assertRendering( + "![foo](/url.png){height=3 invalid}\n", "

\"foo\"{height=3 invalid}

\n"); - assertRendering("![foo](/url.png){height=3 *test*}\n", + assertRendering( + "![foo](/url.png){height=3 *test*}\n", "

\"foo\"{height=3 test}

\n"); } @Test public void styleWithNoValueIsIgnored() { - assertRendering("![text](/url.png){height}", + assertRendering( + "![text](/url.png){height}", "

\"text\"{height}

\n"); } @Test public void repeatedStyleNameUsesFinalOne() { - assertRendering("![text](/url.png){height=4 height=5 width=1 height=6}", + assertRendering( + "![text](/url.png){height=4 height=5 width=1 height=6}", "

\"text\"

\n"); } @Test public void styleValuesAreEscaped() { - assertRendering("![text](/url.png){height=\"text\"

\n"); - assertRendering("![text](/url.png){height=\"\"img}", + assertRendering( + "![text](/url.png){height=\"\"img}", "

\"text\"

\n"); } @Test public void imageAltTextWithSpaces() { - assertRendering("![Android SDK Manager](/contrib/android-sdk-manager.png){height=502 width=101}", + assertRendering( + "![Android SDK Manager](/contrib/android-sdk-manager.png){height=502 width=101}", "

\"Android

\n"); } @Test public void imageAltTextWithSoftLineBreak() { - assertRendering("![foo\nbar](/url){height=101 width=202}\n", + assertRendering( + "![foo\nbar](/url){height=101 width=202}\n", "

\"foo\nbar\"

\n"); } @Test public void imageAltTextWithHardLineBreak() { - assertRendering("![foo \nbar](/url){height=506 width=1}\n", + assertRendering( + "![foo \nbar](/url){height=506 width=1}\n", "

\"foo\nbar\"

\n"); } @Test public void imageAltTextWithEntities() { - assertRendering("![foo ä](/url){height=99 width=100}\n", + assertRendering( + "![foo ä](/url){height=99 width=100}\n", "

\"foo

\n"); } @@ -114,20 +133,24 @@ public void imageAltTextWithEntities() { public void textNodesAreUnchanged() { assertRendering("x{height=3 width=4}\n", "

x{height=3 width=4}

\n"); assertRendering("x {height=3 width=4}\n", "

x {height=3 width=4}

\n"); - assertRendering("\\documentclass[12pt]{article}\n", "

\\documentclass[12pt]{article}

\n"); - assertRendering("some *text*{height=3 width=4}\n", "

some text{height=3 width=4}

\n"); + assertRendering( + "\\documentclass[12pt]{article}\n", "

\\documentclass[12pt]{article}

\n"); + assertRendering( + "some *text*{height=3 width=4}\n", "

some text{height=3 width=4}

\n"); assertRendering("{NN} text", "

{NN} text

\n"); assertRendering("{}", "

{}

\n"); } @Test public void sourceSpans() { - Parser parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); - - // This doesn't result in image attributes, so source spans should be for the single (merged) text node. + Parser parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); + + // This doesn't result in image attributes, so source spans should be for the single + // (merged) text node. Node document = parser.parse("x{height=3 width=4}\n"); Paragraph block = (Paragraph) document.getFirstChild(); Node text = block.getFirstChild(); diff --git a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/Ins.java b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/Ins.java index 2ebd4f5ca..b6d7a2f2a 100644 --- a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/Ins.java +++ b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/Ins.java @@ -3,9 +3,7 @@ import org.commonmark.node.CustomNode; import org.commonmark.node.Delimited; -/** - * An ins node containing text and other inline nodes as children. - */ +/** An ins node containing text and other inline nodes as children. */ public class Ins extends CustomNode implements Delimited { private static final String DELIMITER = "++"; diff --git a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/InsExtension.java b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/InsExtension.java index 3d2974916..a39b77af8 100644 --- a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/InsExtension.java +++ b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/InsExtension.java @@ -1,5 +1,6 @@ package org.commonmark.ext.ins; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.ext.ins.internal.InsDelimiterProcessor; import org.commonmark.ext.ins.internal.InsHtmlNodeRenderer; @@ -13,23 +14,22 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.commonmark.renderer.text.TextContentRenderer; -import java.util.Set; - /** * Extension for ins using ++ - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- *

- * The parsed ins text regions are turned into {@link Ins} nodes. - *

+ * + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The parsed ins text regions are turned into {@link Ins} nodes. */ -public class InsExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, TextContentRenderer.TextContentRendererExtension, MarkdownRenderer.MarkdownRendererExtension { +public class InsExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + TextContentRenderer.TextContentRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { - private InsExtension() { - } + private InsExtension() {} public static Extension create() { return new InsExtension(); @@ -52,18 +52,20 @@ public void extend(TextContentRenderer.Builder rendererBuilder) { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new InsMarkdownNodeRenderer(context); - } + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new InsMarkdownNodeRenderer(context); + } - @Override - public Set getSpecialCharacters() { - // We technically don't need to escape single occurrences of +, but that's all the extension API - // exposes currently. - return Set.of('+'); - } - }); + @Override + public Set getSpecialCharacters() { + // We technically don't need to escape single occurrences of +, but that's + // all the extension API + // exposes currently. + return Set.of('+'); + } + }); } } diff --git a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsDelimiterProcessor.java b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsDelimiterProcessor.java index b0bfb4c6e..a742c70cf 100644 --- a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsDelimiterProcessor.java +++ b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsDelimiterProcessor.java @@ -28,7 +28,8 @@ public int getMinLength() { @Override public int process(DelimiterRun openingRun, DelimiterRun closingRun) { if (openingRun.length() >= 2 && closingRun.length() >= 2) { - // Use exactly two delimiters even if we have more, and don't care about internal openers/closers. + // Use exactly two delimiters even if we have more, and don't care about internal + // openers/closers. Text opener = openingRun.getOpener(); diff --git a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsHtmlNodeRenderer.java b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsHtmlNodeRenderer.java index dcd05fd59..d4defcbdc 100644 --- a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsHtmlNodeRenderer.java +++ b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsHtmlNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.ext.ins.internal; +import java.util.Map; import org.commonmark.node.Node; import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.Map; - public class InsHtmlNodeRenderer extends InsNodeRenderer { private final HtmlNodeRendererContext context; diff --git a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsNodeRenderer.java b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsNodeRenderer.java index 31f0a64ec..4e8e0283e 100644 --- a/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsNodeRenderer.java +++ b/commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.ext.ins.internal; +import java.util.Set; import org.commonmark.ext.ins.Ins; import org.commonmark.node.Node; import org.commonmark.renderer.NodeRenderer; -import java.util.Set; - abstract class InsNodeRenderer implements NodeRenderer { @Override diff --git a/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsMarkdownRendererTest.java b/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsMarkdownRendererTest.java index 6fc9ead67..023413121 100644 --- a/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsMarkdownRendererTest.java +++ b/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsMarkdownRendererTest.java @@ -1,19 +1,19 @@ package org.commonmark.ext.ins; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class InsMarkdownRendererTest { private static final Set EXTENSIONS = Set.of(InsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testStrikethrough() { diff --git a/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsTest.java b/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsTest.java index a5c91a395..8687d9a06 100644 --- a/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsTest.java +++ b/commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsTest.java @@ -1,5 +1,9 @@ package org.commonmark.ext.ins; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.Node; import org.commonmark.node.Paragraph; @@ -11,18 +15,14 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class InsTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(InsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); - private static final TextContentRenderer CONTENT_RENDERER = TextContentRenderer.builder() - .extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final TextContentRenderer CONTENT_RENDERER = + TextContentRenderer.builder().extensions(EXTENSIONS).build(); @Test public void onePlusIsNotEnough() { @@ -68,13 +68,15 @@ public void plusesInside() { @Test public void insWholeParagraphWithOtherDelimiters() { - assertRendering("++Paragraph with *emphasis* and __strong emphasis__++", + assertRendering( + "++Paragraph with *emphasis* and __strong emphasis__++", "

Paragraph with emphasis and strong emphasis

\n"); } @Test public void insideBlockQuote() { - assertRendering("> underline ++that++", + assertRendering( + "> underline ++that++", "
\n

underline that

\n
\n"); } @@ -94,10 +96,11 @@ public void textContentRenderer() { @Test public void sourceSpans() { - Parser parser = Parser.builder() - .extensions(EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); + Parser parser = + Parser.builder() + .extensions(EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); Node document = parser.parse("hey ++there++\n"); Paragraph block = (Paragraph) document.getFirstChild(); diff --git a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemMarker.java b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemMarker.java index 9eca59bc9..4cfcb73eb 100644 --- a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemMarker.java +++ b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemMarker.java @@ -2,9 +2,7 @@ import org.commonmark.node.CustomNode; -/** - * A marker node indicating that a list item contains a task. - */ +/** A marker node indicating that a list item contains a task. */ public class TaskListItemMarker extends CustomNode { private final boolean checked; diff --git a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemsExtension.java b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemsExtension.java index 1c89256d3..abddc519a 100644 --- a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemsExtension.java +++ b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemsExtension.java @@ -14,19 +14,19 @@ /** * Extension for adding task list items. - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

+ * + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). * * @since 0.15.0 */ -public class TaskListItemsExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, - MarkdownRenderer.MarkdownRendererExtension { +public class TaskListItemsExtension + implements Parser.ParserExtension, + HtmlRenderer.HtmlRendererExtension, + MarkdownRenderer.MarkdownRendererExtension { - private TaskListItemsExtension() { - } + private TaskListItemsExtension() {} public static Extension create() { return new TaskListItemsExtension(); @@ -44,16 +44,17 @@ public void extend(HtmlRenderer.Builder rendererBuilder) { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new TaskListItemMarkdownNodeRenderer(context); - } - - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }); + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new TaskListItemMarkdownNodeRenderer(context); + } + + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + }); } } diff --git a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemHtmlNodeRenderer.java b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemHtmlNodeRenderer.java index a27b125c8..cb1c275b4 100644 --- a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemHtmlNodeRenderer.java +++ b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemHtmlNodeRenderer.java @@ -1,13 +1,12 @@ package org.commonmark.ext.task.list.items.internal; +import java.util.LinkedHashMap; +import java.util.Map; import org.commonmark.ext.task.list.items.TaskListItemMarker; import org.commonmark.node.Node; import org.commonmark.renderer.html.HtmlNodeRendererContext; import org.commonmark.renderer.html.HtmlWriter; -import java.util.LinkedHashMap; -import java.util.Map; - public class TaskListItemHtmlNodeRenderer extends TaskListItemNodeRenderer { private final HtmlNodeRendererContext context; diff --git a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemPostProcessor.java b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemPostProcessor.java index b95c2e30d..2898a8229 100644 --- a/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemPostProcessor.java +++ b/commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemPostProcessor.java @@ -1,12 +1,11 @@ package org.commonmark.ext.task.list.items.internal; -import org.commonmark.ext.task.list.items.TaskListItemMarker; -import org.commonmark.node.*; -import org.commonmark.parser.PostProcessor; - import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.commonmark.ext.task.list.items.TaskListItemMarker; +import org.commonmark.node.*; +import org.commonmark.parser.PostProcessor; public class TaskListItemPostProcessor implements PostProcessor { @@ -31,14 +30,16 @@ public void visit(ListItem listItem) { Matcher matcher = REGEX_TASK_LIST_ITEM.matcher(textNode.getLiteral()); if (matcher.matches()) { String checked = matcher.group(1); - boolean isChecked = Objects.equals(checked, "X") || Objects.equals(checked, "x"); + boolean isChecked = + Objects.equals(checked, "X") || Objects.equals(checked, "x"); // Add the task list item marker node as the first child of the list item. listItem.prependChild(new TaskListItemMarker(isChecked)); - // Parse the node using the input after the task marker (in other words, group 2 from the matcher). - // (Note that the String has been trimmed, so we should add a space between the - // TaskListItemMarker and the text that follows it when we come to render it). + // Parse the node using the input after the task marker (in other words, + // group 2 from the matcher). (Note that the String has been trimmed, so we + // should add a space between the TaskListItemMarker and the text that + // follows it when we come to render it). textNode.setLiteral(matcher.group(2)); } } diff --git a/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemMarkdownRendererTest.java b/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemMarkdownRendererTest.java index cf73f434c..e67768f16 100644 --- a/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemMarkdownRendererTest.java +++ b/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemMarkdownRendererTest.java @@ -1,5 +1,7 @@ package org.commonmark.ext.task.list.items; +import static org.assertj.core.api.Assertions.assertThat; + import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.BulletList; @@ -12,13 +14,12 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class TaskListItemMarkdownRendererTest { private static final Set EXTENSIONS = Set.of(TaskListItemsExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); @Test public void testCheckedRoundTrip() { diff --git a/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemsTest.java b/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemsTest.java index 0adc615a7..dd9290b6e 100644 --- a/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemsTest.java +++ b/commonmark-ext-task-list-items/src/test/java/org/commonmark/ext/task/list/items/TaskListItemsTest.java @@ -1,87 +1,116 @@ package org.commonmark.ext.task.list.items; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.Set; - public class TaskListItemsTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(TaskListItemsExtension.create()); - private static final String HTML_CHECKED = ""; + private static final String HTML_CHECKED = + ""; private static final String HTML_UNCHECKED = ""; private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void baseCase() { - assertRendering("- [x] this is *done*\n", "

    \n
  • " + HTML_CHECKED + " this is done
  • \n
\n"); + assertRendering( + "- [x] this is *done*\n", + "
    \n
  • " + HTML_CHECKED + " this is done
  • \n
\n"); - assertRendering("- [ ] do this\n", "
    \n
  • " + HTML_UNCHECKED + " do this
  • \n
\n"); + assertRendering( + "- [ ] do this\n", "
    \n
  • " + HTML_UNCHECKED + " do this
  • \n
\n"); - assertRendering("- [x] foo\n" + - " - [ ] bar\n" + - " - [x] baz\n" + - "- [ ] bim", - "
    \n" + - "
  • " + HTML_CHECKED + " foo\n" + - "
      \n" + - "
    • " + HTML_UNCHECKED + " bar
    • \n" + - "
    • " + HTML_CHECKED + " baz
    • \n" + - "
    \n" + - "
  • \n" + - "
  • " + HTML_UNCHECKED + " bim
  • \n" + - "
\n"); + assertRendering( + "- [x] foo\n" + " - [ ] bar\n" + " - [x] baz\n" + "- [ ] bim", + "
    \n" + + "
  • " + + HTML_CHECKED + + " foo\n" + + "
      \n" + + "
    • " + + HTML_UNCHECKED + + " bar
    • \n" + + "
    • " + + HTML_CHECKED + + " baz
    • \n" + + "
    \n" + + "
  • \n" + + "
  • " + + HTML_UNCHECKED + + " bim
  • \n" + + "
\n"); - assertRendering("* [ ] do this\n* [ ] and this", - "
    \n
  • " + HTML_UNCHECKED + " do this
  • \n
  • " + HTML_UNCHECKED + " and this
  • \n
\n"); + assertRendering( + "* [ ] do this\n* [ ] and this", + "
    \n
  • " + + HTML_UNCHECKED + + " do this
  • \n
  • " + + HTML_UNCHECKED + + " and this
  • \n
\n"); - assertRendering("+ [x] one\n" + - " - [ ] two\n" + - " * [x] three\n", - "
    \n" + - "
  • " + HTML_CHECKED + " one\n" + - "
      \n" + - "
    • " + HTML_UNCHECKED + " two\n" + - "
        \n" + - "
      • " + HTML_CHECKED + " three
      • \n" + - "
      \n" + - "
    • \n" + - "
    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "+ [x] one\n" + " - [ ] two\n" + " * [x] three\n", + "
    \n" + + "
  • " + + HTML_CHECKED + + " one\n" + + "
      \n" + + "
    • " + + HTML_UNCHECKED + + " two\n" + + "
        \n" + + "
      • " + + HTML_CHECKED + + " three
      • \n" + + "
      \n" + + "
    • \n" + + "
    \n" + + "
  • \n" + + "
\n"); - assertRendering("TODO list\n" + - "---------\n" + - "- [ ] first task\n" + - "- [x] second task\n" + - "- [ ] third task\n\n" + - "Let me know when you are finished", - "

TODO list

\n" + - "
    \n" + - "
  • " + HTML_UNCHECKED + " first task
  • \n" + - "
  • " + HTML_CHECKED + " second task
  • \n" + - "
  • " + HTML_UNCHECKED + " third task
  • \n" + - "
\n" + - "

Let me know when you are finished

\n"); + assertRendering( + "TODO list\n" + + "---------\n" + + "- [ ] first task\n" + + "- [x] second task\n" + + "- [ ] third task\n\n" + + "Let me know when you are finished", + "

TODO list

\n" + + "
    \n" + + "
  • " + + HTML_UNCHECKED + + " first task
  • \n" + + "
  • " + + HTML_CHECKED + + " second task
  • \n" + + "
  • " + + HTML_UNCHECKED + + " third task
  • \n" + + "
\n" + + "

Let me know when you are finished

\n"); } @Test public void notListItem() { assertRendering("[x] this is not a task\n", "

[x] this is not a task

\n"); - assertRendering(" [ ] this is not a task either\n", "

[ ] this is not a task either

\n"); + assertRendering( + " [ ] this is not a task either\n", "

[ ] this is not a task either

\n"); } @Test public void notValidTaskFormat() { assertRendering("- [x]no space\n", "
    \n
  • [x]no space
  • \n
\n"); - assertRendering("- [O] is not a _task_\n", "
    \n
  • [O] is not a task
  • \n
\n"); + assertRendering( + "- [O] is not a _task_\n", "
    \n
  • [O] is not a task
  • \n
\n"); assertRendering("* [] neither is this\n", "
    \n
  • [] neither is this
  • \n
\n"); - assertRendering("* [ ] nor this\n" + - "* [XX] nor this\n", + assertRendering( + "* [ ] nor this\n" + "* [XX] nor this\n", "
    \n
  • [ ] nor this
  • \n
  • [XX] nor this
  • \n
\n"); assertRendering("+ [x]] is not a task\n", "
    \n
  • [x]] is not a task
  • \n
\n"); assertRendering("- [x isn't\n", "
    \n
  • [x isn't
  • \n
\n"); @@ -91,7 +120,9 @@ public void notValidTaskFormat() { assertRendering("+ (x) sorry no\n", "
    \n
  • (x) sorry no
  • \n
\n"); assertRendering("+ {x} sorry not sorry\n", "
    \n
  • {x} sorry not sorry
  • \n
\n"); assertRendering("+ [[x]] nooo\n", "
    \n
  • [[x]] nooo
  • \n
\n"); - assertRendering("+ text before [x] is not a task\n", "
    \n
  • text before [x] is not a task
  • \n
\n"); + assertRendering( + "+ text before [x] is not a task\n", + "
    \n
  • text before [x] is not a task
  • \n
\n"); assertRendering("* [x] \n* [ ] \n", "
    \n
  • [x]
  • \n
  • [ ]
  • \n
\n"); } diff --git a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterBlock.java b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterBlock.java index 0d9aba2d3..5c97d57d2 100644 --- a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterBlock.java +++ b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterBlock.java @@ -2,5 +2,4 @@ import org.commonmark.node.CustomBlock; -public class YamlFrontMatterBlock extends CustomBlock { -} +public class YamlFrontMatterBlock extends CustomBlock {} diff --git a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterExtension.java b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterExtension.java index 99ca17708..9bb1b4528 100644 --- a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterExtension.java +++ b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterExtension.java @@ -13,19 +13,18 @@ /** * Extension for YAML-like metadata. - *

- * Create it with {@link #create()} and then configure it on the builders - * ({@link org.commonmark.parser.Parser.Builder#extensions(Iterable)}, - * {@link HtmlRenderer.Builder#extensions(Iterable)}). - *

- *

- * The parsed metadata is turned into {@link YamlFrontMatterNode}. You can access the metadata using {@link YamlFrontMatterVisitor}. - *

+ * + *

Create it with {@link #create()} and then configure it on the builders ({@link + * org.commonmark.parser.Parser.Builder#extensions(Iterable)}, {@link + * HtmlRenderer.Builder#extensions(Iterable)}). + * + *

The parsed metadata is turned into {@link YamlFrontMatterNode}. You can access the metadata + * using {@link YamlFrontMatterVisitor}. */ -public class YamlFrontMatterExtension implements Parser.ParserExtension, MarkdownRenderer.MarkdownRendererExtension { +public class YamlFrontMatterExtension + implements Parser.ParserExtension, MarkdownRenderer.MarkdownRendererExtension { - private YamlFrontMatterExtension() { - } + private YamlFrontMatterExtension() {} @Override public void extend(Parser.Builder parserBuilder) { @@ -38,16 +37,17 @@ public static Extension create() { @Override public void extend(MarkdownRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new YamlFrontMatterMarkdownNodeRenderer(context); - } + rendererBuilder.nodeRendererFactory( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new YamlFrontMatterMarkdownNodeRenderer(context); + } - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }); + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + }); } } diff --git a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterNode.java b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterNode.java index 20eb3baf7..e5fe473ad 100644 --- a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterNode.java +++ b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterNode.java @@ -1,8 +1,7 @@ package org.commonmark.ext.front.matter; -import org.commonmark.node.CustomNode; - import java.util.List; +import org.commonmark.node.CustomNode; public class YamlFrontMatterNode extends CustomNode { private String key; diff --git a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterVisitor.java b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterVisitor.java index 1c23966f5..e49e22c0d 100644 --- a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterVisitor.java +++ b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterVisitor.java @@ -1,11 +1,10 @@ package org.commonmark.ext.front.matter; -import org.commonmark.node.AbstractVisitor; -import org.commonmark.node.CustomNode; - import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.commonmark.node.AbstractVisitor; +import org.commonmark.node.CustomNode; public class YamlFrontMatterVisitor extends AbstractVisitor { private Map> data; @@ -17,7 +16,9 @@ public YamlFrontMatterVisitor() { @Override public void visit(CustomNode customNode) { if (customNode instanceof YamlFrontMatterNode) { - data.put(((YamlFrontMatterNode) customNode).getKey(), ((YamlFrontMatterNode) customNode).getValues()); + data.put( + ((YamlFrontMatterNode) customNode).getKey(), + ((YamlFrontMatterNode) customNode).getValues()); } else { super.visit(customNode); } diff --git a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/internal/YamlFrontMatterBlockParser.java b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/internal/YamlFrontMatterBlockParser.java index f7f03c001..7d14b403b 100644 --- a/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/internal/YamlFrontMatterBlockParser.java +++ b/commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/internal/YamlFrontMatterBlockParser.java @@ -1,18 +1,18 @@ package org.commonmark.ext.front.matter.internal; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.commonmark.ext.front.matter.YamlFrontMatterBlock; import org.commonmark.ext.front.matter.YamlFrontMatterNode; import org.commonmark.node.Block; import org.commonmark.node.Document; import org.commonmark.parser.block.*; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public class YamlFrontMatterBlockParser extends AbstractBlockParser { - private static final Pattern REGEX_METADATA = Pattern.compile("^[ ]{0,3}([A-Za-z0-9._-]+):\\s*(.*)"); + private static final Pattern REGEX_METADATA = + Pattern.compile("^[ ]{0,3}([A-Za-z0-9._-]+):\\s*(.*)"); private static final Pattern REGEX_METADATA_LIST = Pattern.compile("^[ ]+-\\s*(.*)"); private static final Pattern REGEX_METADATA_LITERAL = Pattern.compile("^\\s*(.*)"); private static final Pattern REGEX_BEGIN = Pattern.compile("^-{3}(\\s.*)?"); @@ -95,9 +95,7 @@ private static String parseString(String s) { } else if (s.startsWith("\"") && s.endsWith("\"")) { String inner = s.substring(1, s.length() - 1); // Only support escaped `\` and `"`, nothing else. - return inner - .replace("\\\"", "\"") - .replace("\\\\", "\\"); + return inner.replace("\\\"", "\"").replace("\\\\", "\\"); } else { return s; } @@ -109,9 +107,11 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar CharSequence line = state.getLine().getContent(); BlockParser parentParser = matchedBlockParser.getMatchedBlockParser(); // check whether this line is the first line of whole document or not - if (parentParser.getBlock() instanceof Document && parentParser.getBlock().getFirstChild() == null && - REGEX_BEGIN.matcher(line).matches()) { - return BlockStart.of(new YamlFrontMatterBlockParser()).atIndex(state.getNextNonSpaceIndex()); + if (parentParser.getBlock() instanceof Document + && parentParser.getBlock().getFirstChild() == null + && REGEX_BEGIN.matcher(line).matches()) { + return BlockStart.of(new YamlFrontMatterBlockParser()) + .atIndex(state.getNextNonSpaceIndex()); } return BlockStart.none(); diff --git a/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterMarkdownRendererTest.java b/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterMarkdownRendererTest.java index 987513ea4..b5bd06058 100644 --- a/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterMarkdownRendererTest.java +++ b/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterMarkdownRendererTest.java @@ -1,5 +1,8 @@ package org.commonmark.ext.front.matter; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.Extension; import org.commonmark.node.Document; import org.commonmark.node.Node; @@ -9,15 +12,12 @@ import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - public class YamlFrontMatterMarkdownRendererTest { private static final List EXTENSIONS = List.of(YamlFrontMatterExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(EXTENSIONS).build(); // ===== Round-trip tests (parse string -> render -> compare to input) ===== @@ -43,7 +43,8 @@ public void testRoundTripListValues() { @Test public void testRoundTripLiteralBlock() { - assertRoundTrip("---\ndescription: |\n first line\n second line\n---\n\nMarkdown content\n"); + assertRoundTrip( + "---\ndescription: |\n first line\n second line\n---\n\nMarkdown content\n"); } @Test @@ -84,7 +85,9 @@ public void testRoundTripEmptyFrontmatter() { @Test public void testProgrammaticallyBuilt() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("title", List.of("My Document")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("title", List.of("My Document")))); assertRenderedEquals(doc, "---\ntitle: My Document\n---\n\nMarkdown content\n"); } @@ -93,29 +96,40 @@ public void testProgrammaticallyBuilt() { @Test public void testValueWithColonSpace() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("value with a: colon inside")))); + var doc = + buildDocumentWithFrontMatter( + List.of( + new YamlFrontMatterNode( + "key", List.of("value with a: colon inside")))); - assertRenderedEquals(doc, "---\nkey: 'value with a: colon inside'\n---\n\nMarkdown content\n"); + assertRenderedEquals( + doc, "---\nkey: 'value with a: colon inside'\n---\n\nMarkdown content\n"); } @Test public void testValueWithColonNoSpace() { // Colon without trailing space is fine unquoted (e.g. timestamps, URLs) - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("time", List.of("12:30:00")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("time", List.of("12:30:00")))); assertRenderedEquals(doc, "---\ntime: 12:30:00\n---\n\nMarkdown content\n"); } @Test public void testValueStartingWithDash() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("- not a list")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("key", List.of("- not a list")))); assertRenderedEquals(doc, "---\nkey: '- not a list'\n---\n\nMarkdown content\n"); } @Test public void testValueStartingWithUnmatchedBracket() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("[broken")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("key", List.of("[broken")))); assertRenderedEquals(doc, "---\nkey: '[broken'\n---\n\nMarkdown content\n"); } @@ -123,14 +137,18 @@ public void testValueStartingWithUnmatchedBracket() { @Test public void testValueStartingWithMatchedBrackets() { // Valid flow list - should NOT be quoted - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("flowList", List.of("[1, 2, 3]")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("flowList", List.of("[1, 2, 3]")))); assertRenderedEquals(doc, "---\nflowList: [1, 2, 3]\n---\n\nMarkdown content\n"); } @Test public void testValueStartingWithUnmatchedBrace() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("{broken")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("key", List.of("{broken")))); assertRenderedEquals(doc, "---\nkey: '{broken'\n---\n\nMarkdown content\n"); } @@ -138,35 +156,47 @@ public void testValueStartingWithUnmatchedBrace() { @Test public void testValueStartingWithMatchedBraces() { // Valid flow mapping - should NOT be quoted - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("flowMapping", List.of("{key: val}")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("flowMapping", List.of("{key: val}")))); assertRenderedEquals(doc, "---\nflowMapping: {key: val}\n---\n\nMarkdown content\n"); } @Test public void testValueContainingHashComment() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("value # not a comment")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("key", List.of("value # not a comment")))); assertRenderedEquals(doc, "---\nkey: 'value # not a comment'\n---\n\nMarkdown content\n"); } @Test public void testValueContainingApostrophe() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("it's a test")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("key", List.of("it's a test")))); assertRenderedEquals(doc, "---\nkey: 'it''s a test'\n---\n\nMarkdown content\n"); } @Test public void testEmptyStringValue() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("empty", List.of("")))); + var doc = + buildDocumentWithFrontMatter( + List.of(new YamlFrontMatterNode("empty", List.of("")))); assertRenderedEquals(doc, "---\nempty: ''\n---\n\nMarkdown content\n"); } @Test public void testValueStartingWithDoubleQuote() { - var doc = buildDocumentWithFrontMatter(List.of(new YamlFrontMatterNode("key", List.of("\"quotes within value\"")))); + var doc = + buildDocumentWithFrontMatter( + List.of( + new YamlFrontMatterNode( + "key", List.of("\"quotes within value\"")))); assertRenderedEquals(doc, "---\nkey: '\"quotes within value\"'\n---\n\nMarkdown content\n"); } diff --git a/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterTest.java b/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterTest.java index e0555dc0a..71da8a936 100644 --- a/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterTest.java +++ b/commonmark-ext-yaml-front-matter/src/test/java/org/commonmark/ext/front/matter/YamlFrontMatterTest.java @@ -1,5 +1,10 @@ package org.commonmark.ext.front.matter; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; +import java.util.Set; import org.commonmark.Extension; import org.commonmark.node.CustomNode; import org.commonmark.node.Node; @@ -8,24 +13,15 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class YamlFrontMatterTest extends RenderingTestCase { private static final Set EXTENSIONS = Set.of(YamlFrontMatterExtension.create()); private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().extensions(EXTENSIONS).build(); @Test public void simpleValue() { - final String input = "---" + - "\nhello: world" + - "\n..." + - "\n" + - "\ngreat"; + final String input = "---" + "\nhello: world" + "\n..." + "\n" + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -40,11 +36,7 @@ public void simpleValue() { @Test public void emptyValue() { - final String input = "---" + - "\nkey:" + - "\n---" + - "\n" + - "\ngreat"; + final String input = "---" + "\nkey:" + "\n---" + "\n" + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -58,13 +50,8 @@ public void emptyValue() { @Test public void listValues() { - final String input = "---" + - "\nlist:" + - "\n - value1" + - "\n - value2" + - "\n..." + - "\n" + - "\ngreat"; + final String input = + "---" + "\nlist:" + "\n - value1" + "\n - value2" + "\n..." + "\n" + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -80,13 +67,14 @@ public void listValues() { @Test public void literalValue1() { - final String input = "---" + - "\nliteral: |" + - "\n hello markdown!" + - "\n literal thing..." + - "\n---" + - "\n" + - "\ngreat"; + final String input = + "---" + + "\nliteral: |" + + "\n hello markdown!" + + "\n literal thing..." + + "\n---" + + "\n" + + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -101,12 +89,8 @@ public void literalValue1() { @Test public void literalValue2() { - final String input = "---" + - "\nliteral: |" + - "\n - hello markdown!" + - "\n---" + - "\n" + - "\ngreat"; + final String input = + "---" + "\nliteral: |" + "\n - hello markdown!" + "\n---" + "\n" + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -121,17 +105,18 @@ public void literalValue2() { @Test public void complexValues() { - final String input = "---" + - "\nsimple: value" + - "\nliteral: |" + - "\n hello markdown!" + - "\n" + - "\n literal literal" + - "\nlist:" + - "\n - value1" + - "\n - value2" + - "\n---" + - "\ngreat"; + final String input = + "---" + + "\nsimple: value" + + "\nliteral: |" + + "\n hello markdown!" + + "\n" + + "\n literal literal" + + "\nlist:" + + "\n - value1" + + "\n - value2" + + "\n---" + + "\ngreat"; final String rendered = "

great

\n"; Map> data = getFrontMatter(input); @@ -156,9 +141,7 @@ public void complexValues() { @Test public void empty() { - final String input = "---\n" + - "---\n" + - "test"; + final String input = "---\n" + "---\n" + "test"; final String rendered = "

test

\n"; Map> data = getFrontMatter(input); @@ -170,12 +153,10 @@ public void empty() { @Test public void yamlInParagraph() { - final String input = "# hello\n" + - "\nhello markdown world!" + - "\n---" + - "\nhello: world" + - "\n---"; - final String rendered = "

hello

\n

hello markdown world!

\n

hello: world

\n"; + final String input = + "# hello\n" + "\nhello markdown world!" + "\n---" + "\nhello: world" + "\n---"; + final String rendered = + "

hello

\n

hello markdown world!

\n

hello: world

\n"; Map> data = getFrontMatter(input); @@ -186,10 +167,7 @@ public void yamlInParagraph() { @Test public void yamlOnSecondLine() { - final String input = "hello\n" + - "\n---" + - "\nhello: world" + - "\n---"; + final String input = "hello\n" + "\n---" + "\nhello: world" + "\n---"; final String rendered = "

hello

\n
\n

hello: world

\n"; Map> data = getFrontMatter(input); @@ -201,8 +179,7 @@ public void yamlOnSecondLine() { @Test public void nonMatchedStartTag() { - final String input = "----\n" + - "test"; + final String input = "----\n" + "test"; final String rendered = "
\n

test

\n"; Map> data = getFrontMatter(input); @@ -214,9 +191,7 @@ public void nonMatchedStartTag() { @Test public void inList() { - final String input = "* ---\n" + - " ---\n" + - "test"; + final String input = "* ---\n" + " ---\n" + "test"; final String rendered = "
    \n
  • \n
    \n
    \n
  • \n
\n

test

\n"; Map> data = getFrontMatter(input); @@ -228,10 +203,7 @@ public void inList() { @Test public void visitorIgnoresOtherCustomNodes() { - final String input = "---" + - "\nhello: world" + - "\n---" + - "\n"; + final String input = "---" + "\nhello: world" + "\n---" + "\n"; YamlFrontMatterVisitor visitor = new YamlFrontMatterVisitor(); Node document = PARSER.parse(input); @@ -246,10 +218,7 @@ public void visitorIgnoresOtherCustomNodes() { @Test public void nodesCanBeModified() { - final String input = "---" + - "\nhello: world" + - "\n---" + - "\n"; + final String input = "---" + "\nhello: world" + "\n---" + "\n"; Node document = PARSER.parse(input); YamlFrontMatterNode node = (YamlFrontMatterNode) document.getFirstChild().getFirstChild(); @@ -267,10 +236,7 @@ public void nodesCanBeModified() { @Test public void dotInKeys() { - final String input = "---" + - "\nms.author: author" + - "\n---" + - "\n"; + final String input = "---" + "\nms.author: author" + "\n---" + "\n"; Map> data = getFrontMatter(input); @@ -282,12 +248,8 @@ public void dotInKeys() { @Test public void singleQuotedLiterals() { - final String input = "---" + - "\nstring: 'It''s me'" + - "\nlist:" + - "\n - 'I''m here'" + - "\n---" + - "\n"; + final String input = + "---" + "\nstring: 'It''s me'" + "\nlist:" + "\n - 'I''m here'" + "\n---" + "\n"; Map> data = getFrontMatter(input); @@ -298,12 +260,13 @@ public void singleQuotedLiterals() { @Test public void doubleQuotedLiteral() { - final String input = "---" + - "\nstring: \"backslash: \\\\ quote: \\\"\"" + - "\nlist:" + - "\n - \"hey\"" + - "\n---" + - "\n"; + final String input = + "---" + + "\nstring: \"backslash: \\\\ quote: \\\"\"" + + "\nlist:" + + "\n - \"hey\"" + + "\n---" + + "\n"; Map> data = getFrontMatter(input); @@ -326,6 +289,5 @@ private Map> getFrontMatter(String input) { } // Custom node for tests - private static class TestNode extends CustomNode { - } + private static class TestNode extends CustomNode {} } diff --git a/commonmark-integration-test/src/main/java/org/commonmark/integration/IntegrationTests.java b/commonmark-integration-test/src/main/java/org/commonmark/integration/IntegrationTests.java index 48e1ee5ba..acd86f4e4 100644 --- a/commonmark-integration-test/src/main/java/org/commonmark/integration/IntegrationTests.java +++ b/commonmark-integration-test/src/main/java/org/commonmark/integration/IntegrationTests.java @@ -9,8 +9,5 @@ // And the javadoc plugin doesn't like if there's no classes with documentation, // -/** - * Module with integration tests. - */ -public class IntegrationTests { -} +/** Module with integration tests. */ +public class IntegrationTests {} diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/BoundsIntegrationTest.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/BoundsIntegrationTest.java index f1259b825..0efd375f1 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/BoundsIntegrationTest.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/BoundsIntegrationTest.java @@ -1,5 +1,8 @@ package org.commonmark.integration; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.testutil.TestResources; @@ -9,21 +12,14 @@ import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests various substrings of the spec examples to check for out of bounds exceptions. - */ +/** Tests various substrings of the spec examples to check for out of bounds exceptions. */ @ParameterizedClass @MethodSource("data") public class BoundsIntegrationTest { private static final Parser PARSER = Parser.builder().build(); - @Parameter - String input; + @Parameter String input; static List data() { return ExampleReader.readExampleSources(TestResources.getSpec()); diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java index 9090c797f..aa5f1f28c 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java @@ -1,5 +1,6 @@ package org.commonmark.integration; +import java.util.List; import org.commonmark.Extension; import org.commonmark.ext.autolink.AutolinkExtension; import org.commonmark.ext.footnotes.FootnotesExtension; @@ -11,18 +12,17 @@ import org.commonmark.ext.ins.InsExtension; import org.commonmark.ext.task.list.items.TaskListItemsExtension; -import java.util.List; - public class Extensions { - static final List ALL_EXTENSIONS = List.of( - AutolinkExtension.create(), - FootnotesExtension.create(), - ImageAttributesExtension.create(), - InsExtension.create(), - AlertsExtension.create(), - StrikethroughExtension.create(), - TablesExtension.create(), - TaskListItemsExtension.create(), - YamlFrontMatterExtension.create()); + static final List ALL_EXTENSIONS = + List.of( + AutolinkExtension.create(), + FootnotesExtension.create(), + ImageAttributesExtension.create(), + InsExtension.create(), + AlertsExtension.create(), + StrikethroughExtension.create(), + TablesExtension.create(), + TaskListItemsExtension.create(), + YamlFrontMatterExtension.create()); } diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/ExtensionsIntegrationTest.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/ExtensionsIntegrationTest.java index 523154d2c..345c02d15 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/ExtensionsIntegrationTest.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/ExtensionsIntegrationTest.java @@ -5,30 +5,30 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -/** - * Tests to ensure all extensions work well together. - */ +/** Tests to ensure all extensions work well together. */ public class ExtensionsIntegrationTest extends RenderingTestCase { - protected static final Parser PARSER = Parser.builder() - .extensions(Extensions.ALL_EXTENSIONS) - .build(); - protected static final HtmlRenderer RENDERER = HtmlRenderer.builder() - .extensions(Extensions.ALL_EXTENSIONS) - .percentEncodeUrls(true) - .build(); + protected static final Parser PARSER = + Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build(); + protected static final HtmlRenderer RENDERER = + HtmlRenderer.builder() + .extensions(Extensions.ALL_EXTENSIONS) + .percentEncodeUrls(true) + .build(); @Test public void testImageAttributes() { - assertRendering("![text](/url.png){height=5 width=6}", "

\"text\"

\n"); + assertRendering( + "![text](/url.png){height=5 width=6}", + "

\"text\"

\n"); } @Test public void testTaskListItems() { - assertRendering("- [ ] task to do\n- [x] task done\n", - "
    \n
  • task to do
  • \n" + - "
  • task done
  • \n
\n"); - + assertRendering( + "- [ ] task to do\n- [x] task done\n", + "
    \n
  • task to do
  • \n" + + "
  • task done
  • \n
\n"); } @Override diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java index 9e64f9717..a9adbb653 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java @@ -1,15 +1,17 @@ package org.commonmark.integration; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.parser.Parser; import org.commonmark.renderer.markdown.MarkdownRenderer; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class MarkdownRendererIntegrationTest { - private static final Parser PARSER = Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build(); - private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(Extensions.ALL_EXTENSIONS).build(); + private static final Parser PARSER = + Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build(); + private static final MarkdownRenderer RENDERER = + MarkdownRenderer.builder().extensions(Extensions.ALL_EXTENSIONS).build(); @Test public void testStrikethroughInTable() { diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/PegDownBenchmark.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/PegDownBenchmark.java index ecc9c2cfd..806dc28b8 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/PegDownBenchmark.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/PegDownBenchmark.java @@ -1,5 +1,6 @@ package org.commonmark.integration; +import java.util.List; import org.commonmark.testutil.TestResources; import org.commonmark.testutil.example.ExampleReader; import org.openjdk.jmh.annotations.Benchmark; @@ -12,20 +13,21 @@ import org.pegdown.Extensions; import org.pegdown.PegDownProcessor; -import java.util.List; - @State(Scope.Benchmark) public class PegDownBenchmark { private static final String SPEC = TestResources.readAsString(TestResources.getSpec()); - private static final List SPEC_EXAMPLES = ExampleReader.readExampleSources(TestResources.getSpec()); - private static final PegDownProcessor PROCESSOR = new PegDownProcessor(Extensions.FENCED_CODE_BLOCKS); + private static final List SPEC_EXAMPLES = + ExampleReader.readExampleSources(TestResources.getSpec()); + private static final PegDownProcessor PROCESSOR = + new PegDownProcessor(Extensions.FENCED_CODE_BLOCKS); public static void main(String[] args) throws Exception { - Options options = new OptionsBuilder() - .parent(new CommandLineOptions(args)) - .include(PegDownBenchmark.class.getName() + ".*") - .build(); + Options options = + new OptionsBuilder() + .parent(new CommandLineOptions(args)) + .include(PegDownBenchmark.class.getName() + ".*") + .build(); new Runner(options).run(); } @@ -47,5 +49,4 @@ private static long parseAndRender(List examples) { } return length; } - } diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/SourceSpanIntegrationTest.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/SourceSpanIntegrationTest.java index 4d18fa937..c43abeec2 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/SourceSpanIntegrationTest.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/SourceSpanIntegrationTest.java @@ -3,15 +3,14 @@ import org.commonmark.parser.IncludeSourceSpans; import org.commonmark.parser.Parser; -/** - * Spec and all extensions, with source spans enabled. - */ +/** Spec and all extensions, with source spans enabled. */ public class SourceSpanIntegrationTest extends SpecIntegrationTest { - protected static final Parser PARSER = Parser.builder() - .extensions(Extensions.ALL_EXTENSIONS) - .includeSourceSpans(IncludeSourceSpans.BLOCKS) - .build(); + protected static final Parser PARSER = + Parser.builder() + .extensions(Extensions.ALL_EXTENSIONS) + .includeSourceSpans(IncludeSourceSpans.BLOCKS) + .build(); @Override protected String render(String source) { diff --git a/commonmark-integration-test/src/test/java/org/commonmark/integration/SpecIntegrationTest.java b/commonmark-integration-test/src/test/java/org/commonmark/integration/SpecIntegrationTest.java index 6dca4024e..0a1a7ae2a 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/integration/SpecIntegrationTest.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/integration/SpecIntegrationTest.java @@ -1,22 +1,24 @@ package org.commonmark.integration; -import org.commonmark.renderer.html.HtmlRenderer; +import static org.commonmark.testutil.Asserts.assertRendering; + +import java.util.*; import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.SpecTestCase; import org.junit.jupiter.api.Test; -import java.util.*; - -import static org.commonmark.testutil.Asserts.assertRendering; - -/** - * Tests that the spec examples still render the same with all extensions enabled. - */ +/** Tests that the spec examples still render the same with all extensions enabled. */ public class SpecIntegrationTest extends SpecTestCase { - protected static final Parser PARSER = Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build(); + protected static final Parser PARSER = + Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build(); // The spec says URL-escaping is optional, but the examples assume that it's enabled. - protected static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(Extensions.ALL_EXTENSIONS).percentEncodeUrls(true).build(); + protected static final HtmlRenderer RENDERER = + HtmlRenderer.builder() + .extensions(Extensions.ALL_EXTENSIONS) + .percentEncodeUrls(true) + .build(); protected static final Map OVERRIDDEN_EXAMPLES = getOverriddenExamples(); @Test @@ -37,22 +39,35 @@ private static Map getOverriddenExamples() { Map m = new HashMap<>(); // Not a spec autolink because of space, but the resulting text contains a valid URL - m.put("\n", "

<https://foo.bar/baz bim>

\n"); + m.put( + "\n", + "

<https://foo.bar/baz bim>

\n"); // Not a spec autolink, but the resulting text contains a valid email - m.put("\n", "

<foo+@bar.example.com>

\n"); + m.put( + "\n", + "

<foo+@bar.example.com>

\n"); - // Not a spec autolink because of unknown scheme, but autolink extension doesn't limit schemes - m.put("\n", "

<heck://bing.bong>

\n"); + // Not a spec autolink because of unknown scheme, but autolink extension doesn't limit + // schemes + m.put( + "\n", + "

<heck://bing.bong>

\n"); // Not a spec autolink because of spaces, but autolink extension doesn't limit schemes - m.put("< https://foo.bar >\n", "

< https://foo.bar >

\n"); + m.put( + "< https://foo.bar >\n", + "

< https://foo.bar >

\n"); // Plain autolink - m.put("https://example.com\n", "

https://example.com

\n"); + m.put( + "https://example.com\n", + "

https://example.com

\n"); // Plain autolink - m.put("foo@bar.example.com\n", "

foo@bar.example.com

\n"); + m.put( + "foo@bar.example.com\n", + "

foo@bar.example.com

\n"); // YAML front matter block m.put("---\nFoo\n---\nBar\n---\nBaz\n", "

Bar

\n

Baz

\n"); @@ -60,5 +75,4 @@ private static Map getOverriddenExamples() { return m; } - } diff --git a/commonmark-integration-test/src/test/java/org/commonmark/ui/DingusApp.java b/commonmark-integration-test/src/test/java/org/commonmark/ui/DingusApp.java index d8132fe25..e7870f411 100644 --- a/commonmark-integration-test/src/test/java/org/commonmark/ui/DingusApp.java +++ b/commonmark-integration-test/src/test/java/org/commonmark/ui/DingusApp.java @@ -1,18 +1,17 @@ package org.commonmark.ui; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; -import org.commonmark.renderer.text.TextContentRenderer; - import java.awt.*; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; +import org.commonmark.renderer.text.TextContentRenderer; /** - * Simple UI to quickly test out different rendering of CommonMark inputs. - * Similar to commonmark.js dingus. - **/ + * Simple UI to quickly test out different rendering of CommonMark inputs. Similar to commonmark.js dingus. + */ public class DingusApp { private final Parser parser = Parser.builder().build(); @@ -57,21 +56,22 @@ private void run() { input.setLineWrap(true); input.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); - input.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - updateOutput(input.getText()); - } + input.getDocument() + .addDocumentListener( + new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + updateOutput(input.getText()); + } - @Override - public void removeUpdate(DocumentEvent e) { - updateOutput(input.getText()); - } + @Override + public void removeUpdate(DocumentEvent e) { + updateOutput(input.getText()); + } - @Override - public void changedUpdate(DocumentEvent e) { - } - }); + @Override + public void changedUpdate(DocumentEvent e) {} + }); tabbedPane.addTab("HTML rendered", htmlVisualRendererOutput); tabbedPane.addTab("HTML source", htmlSourceRendererOutput); @@ -79,10 +79,11 @@ public void changedUpdate(DocumentEvent e) { tabbedPane.addChangeListener(e -> updateOutput(input.getText())); - input.setText("# Example\n" + - "Enter text *here* and see how it renders on the right.\n\n" + - "* Try\n* this\n\n" + - "```\nor this\n```"); + input.setText( + "# Example\n" + + "Enter text *here* and see how it renders on the right.\n\n" + + "* Try\n* this\n\n" + + "```\nor this\n```"); updateOutput(input.getText()); frame.setLayout(new GridLayout()); diff --git a/commonmark-test-util/src/main/java/org/commonmark/testutil/Asserts.java b/commonmark-test-util/src/main/java/org/commonmark/testutil/Asserts.java index 971a1b4ea..89cfdac38 100644 --- a/commonmark-test-util/src/main/java/org/commonmark/testutil/Asserts.java +++ b/commonmark-test-util/src/main/java/org/commonmark/testutil/Asserts.java @@ -3,7 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class Asserts { - public static void assertRendering(String source, String expectedRendering, String actualRendering) { + public static void assertRendering( + String source, String expectedRendering, String actualRendering) { // include source for better assertion errors String expected = showTabs(expectedRendering + "\n\n" + source); String actual = showTabs(actualRendering + "\n\n" + source); diff --git a/commonmark-test-util/src/main/java/org/commonmark/testutil/SpecTestCase.java b/commonmark-test-util/src/main/java/org/commonmark/testutil/SpecTestCase.java index d61afbc4a..ca2f85042 100644 --- a/commonmark-test-util/src/main/java/org/commonmark/testutil/SpecTestCase.java +++ b/commonmark-test-util/src/main/java/org/commonmark/testutil/SpecTestCase.java @@ -1,19 +1,17 @@ package org.commonmark.testutil; +import java.util.List; import org.commonmark.testutil.example.Example; import org.commonmark.testutil.example.ExampleReader; import org.junit.jupiter.params.Parameter; import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.util.List; - @ParameterizedClass @MethodSource("data") public abstract class SpecTestCase { - @Parameter - protected Example example; + @Parameter protected Example example; static List data() { return ExampleReader.readExamples(TestResources.getSpec()); diff --git a/commonmark-test-util/src/main/java/org/commonmark/testutil/TestResources.java b/commonmark-test-util/src/main/java/org/commonmark/testutil/TestResources.java index 5af649a86..1ef86461e 100644 --- a/commonmark-test-util/src/main/java/org/commonmark/testutil/TestResources.java +++ b/commonmark-test-util/src/main/java/org/commonmark/testutil/TestResources.java @@ -20,13 +20,14 @@ public static URL getGfmSpec() { public static List getRegressions() { return List.of( TestResources.class.getResource("/cmark-regression.txt"), - TestResources.class.getResource("/commonmark.js-regression.txt") - ); + TestResources.class.getResource("/commonmark.js-regression.txt")); } public static String readAsString(URL url) { StringBuilder sb = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { + try (BufferedReader reader = + new BufferedReader( + new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { sb.append(line); diff --git a/commonmark-test-util/src/main/java/org/commonmark/testutil/example/Example.java b/commonmark-test-util/src/main/java/org/commonmark/testutil/example/Example.java index 11e87d0aa..39c9f1b63 100644 --- a/commonmark-test-util/src/main/java/org/commonmark/testutil/example/Example.java +++ b/commonmark-test-util/src/main/java/org/commonmark/testutil/example/Example.java @@ -9,7 +9,13 @@ public class Example { private final String source; private final String html; - public Example(String filename, String section, String info, int exampleNumber, String source, String html) { + public Example( + String filename, + String section, + String info, + int exampleNumber, + String source, + String html) { this.filename = filename; this.section = section; this.info = info; diff --git a/commonmark-test-util/src/main/java/org/commonmark/testutil/example/ExampleReader.java b/commonmark-test-util/src/main/java/org/commonmark/testutil/example/ExampleReader.java index d40a10f63..b6ba8b9c1 100644 --- a/commonmark-test-util/src/main/java/org/commonmark/testutil/example/ExampleReader.java +++ b/commonmark-test-util/src/main/java/org/commonmark/testutil/example/ExampleReader.java @@ -10,7 +10,8 @@ import java.util.stream.Collectors; /** - * Reader for files containing examples of CommonMark source and the expected HTML rendering (e.g. spec.txt). + * Reader for files containing examples of CommonMark source and the expected HTML rendering (e.g. + * spec.txt). */ public class ExampleReader { @@ -45,11 +46,15 @@ public static List readExamples(URL url) { public static List readExamples(URL url, String info) { var examples = readExamples(url); - return examples.stream().filter(e -> e.getInfo().contains(info)).collect(Collectors.toList()); + return examples.stream() + .filter(e -> e.getInfo().contains(info)) + .collect(Collectors.toList()); } public static List readExampleObjects(URL url, String info) { - return readExamples(url, info).stream().map(e -> new Object[]{e}).collect(Collectors.toList()); + return readExamples(url, info).stream() + .map(e -> new Object[] {e}) + .collect(Collectors.toList()); } public static List readExampleSources(URL url) { @@ -64,8 +69,8 @@ public static List readExampleSources(URL url) { private List read() throws IOException { resetContents(); - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { processLine(line); @@ -101,8 +106,15 @@ private void processLine(String line) { case HTML: if (line.equals("````````````````````````````````")) { state = State.BEFORE; - examples.add(new Example(filename, section, info, exampleNumber, - source.toString(), html.toString())); + var example = + new Example( + filename, + section, + info, + exampleNumber, + source.toString(), + html.toString()); + examples.add(example); resetContents(); } else { html.append(line).append('\n'); @@ -117,6 +129,8 @@ private void resetContents() { } private enum State { - BEFORE, SOURCE, HTML + BEFORE, + SOURCE, + HTML } } diff --git a/commonmark/src/main/java/org/commonmark/Extension.java b/commonmark/src/main/java/org/commonmark/Extension.java index b0e37456e..d233ca3f4 100644 --- a/commonmark/src/main/java/org/commonmark/Extension.java +++ b/commonmark/src/main/java/org/commonmark/Extension.java @@ -2,10 +2,9 @@ /** * Base interface for a parser/renderer extension. - *

- * Doesn't have any methods itself, but has specific sub interfaces to - * configure parser/renderer. This base interface is for convenience, so that a list of extensions can be built and then - * used for configuring both the parser and renderer in the same way. + * + *

Doesn't have any methods itself, but has specific sub interfaces to configure parser/renderer. + * This base interface is for convenience, so that a list of extensions can be built and then used + * for configuring both the parser and renderer in the same way. */ -public interface Extension { -} +public interface Extension {} diff --git a/commonmark/src/main/java/org/commonmark/internal/BlockContent.java b/commonmark/src/main/java/org/commonmark/internal/BlockContent.java index 9a9ce6f44..aa9306280 100644 --- a/commonmark/src/main/java/org/commonmark/internal/BlockContent.java +++ b/commonmark/src/main/java/org/commonmark/internal/BlockContent.java @@ -25,5 +25,4 @@ public void add(CharSequence line) { public String getString() { return sb.toString(); } - } diff --git a/commonmark/src/main/java/org/commonmark/internal/BlockContinueImpl.java b/commonmark/src/main/java/org/commonmark/internal/BlockContinueImpl.java index 6410c2c2d..c34562933 100644 --- a/commonmark/src/main/java/org/commonmark/internal/BlockContinueImpl.java +++ b/commonmark/src/main/java/org/commonmark/internal/BlockContinueImpl.java @@ -25,5 +25,4 @@ public int getNewColumn() { public boolean isFinalize() { return finalize; } - } diff --git a/commonmark/src/main/java/org/commonmark/internal/BlockQuoteParser.java b/commonmark/src/main/java/org/commonmark/internal/BlockQuoteParser.java index 572c491f8..b3f473527 100644 --- a/commonmark/src/main/java/org/commonmark/internal/BlockQuoteParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/BlockQuoteParser.java @@ -42,7 +42,9 @@ public BlockContinue tryContinue(ParserState state) { private static boolean isMarker(ParserState state, int index) { CharSequence line = state.getLine().getContent(); - return state.getIndent() < Parsing.CODE_BLOCK_INDENT && index < line.length() && line.charAt(index) == '>'; + return state.getIndent() < Parsing.CODE_BLOCK_INDENT + && index < line.length() + && line.charAt(index) == '>'; } public static class Factory extends AbstractBlockParserFactory { diff --git a/commonmark/src/main/java/org/commonmark/internal/Bracket.java b/commonmark/src/main/java/org/commonmark/internal/Bracket.java index c04b6ecda..b4dbb0e9a 100644 --- a/commonmark/src/main/java/org/commonmark/internal/Bracket.java +++ b/commonmark/src/main/java/org/commonmark/internal/Bracket.java @@ -3,65 +3,81 @@ import org.commonmark.node.Text; import org.commonmark.parser.beta.Position; -/** - * Opening bracket for links ({@code [}), images ({@code ![}), or links with other markers. - */ +/** Opening bracket for links ({@code [}), images ({@code ![}), or links with other markers. */ public class Bracket { - /** - * The node of a marker such as {@code !} if present, null otherwise. - */ + /** The node of a marker such as {@code !} if present, null otherwise. */ public final Text markerNode; - /** - * The position of the marker if present, null otherwise. - */ + /** The position of the marker if present, null otherwise. */ public final Position markerPosition; - /** - * The node of {@code [}. - */ + /** The node of {@code [}. */ public final Text bracketNode; - /** - * The position of {@code [}. - */ + /** The position of {@code [}. */ public final Position bracketPosition; - /** - * The position of the content (after the opening bracket) - */ + /** The position of the content (after the opening bracket) */ public final Position contentPosition; - /** - * Previous bracket. - */ + /** Previous bracket. */ public final Bracket previous; - /** - * Previous delimiter (emphasis, etc) before this bracket. - */ + /** Previous delimiter (emphasis, etc) before this bracket. */ public final Delimiter previousDelimiter; - /** - * Whether this bracket is allowed to form a link/image (also known as "active"). - */ + /** Whether this bracket is allowed to form a link/image (also known as "active"). */ public boolean allowed = true; /** - * Whether there is an unescaped bracket (opening or closing) after this opening bracket in the text parsed so far. + * Whether there is an unescaped bracket (opening or closing) after this opening bracket in the + * text parsed so far. */ public boolean bracketAfter = false; - static public Bracket link(Text bracketNode, Position bracketPosition, Position contentPosition, Bracket previous, Delimiter previousDelimiter) { - return new Bracket(null, null, bracketNode, bracketPosition, contentPosition, previous, previousDelimiter); + public static Bracket link( + Text bracketNode, + Position bracketPosition, + Position contentPosition, + Bracket previous, + Delimiter previousDelimiter) { + return new Bracket( + null, + null, + bracketNode, + bracketPosition, + contentPosition, + previous, + previousDelimiter); } - static public Bracket withMarker(Text markerNode, Position markerPosition, Text bracketNode, Position bracketPosition, Position contentPosition, Bracket previous, Delimiter previousDelimiter) { - return new Bracket(markerNode, markerPosition, bracketNode, bracketPosition, contentPosition, previous, previousDelimiter); + public static Bracket withMarker( + Text markerNode, + Position markerPosition, + Text bracketNode, + Position bracketPosition, + Position contentPosition, + Bracket previous, + Delimiter previousDelimiter) { + return new Bracket( + markerNode, + markerPosition, + bracketNode, + bracketPosition, + contentPosition, + previous, + previousDelimiter); } - private Bracket(Text markerNode, Position markerPosition, Text bracketNode, Position bracketPosition, Position contentPosition, Bracket previous, Delimiter previousDelimiter) { + private Bracket( + Text markerNode, + Position markerPosition, + Text bracketNode, + Position bracketPosition, + Position contentPosition, + Bracket previous, + Delimiter previousDelimiter) { this.markerNode = markerNode; this.markerPosition = markerPosition; this.bracketNode = bracketNode; diff --git a/commonmark/src/main/java/org/commonmark/internal/Definitions.java b/commonmark/src/main/java/org/commonmark/internal/Definitions.java index 0377842c9..ad77ef6dc 100644 --- a/commonmark/src/main/java/org/commonmark/internal/Definitions.java +++ b/commonmark/src/main/java/org/commonmark/internal/Definitions.java @@ -1,9 +1,8 @@ package org.commonmark.internal; -import org.commonmark.node.DefinitionMap; - import java.util.HashMap; import java.util.Map; +import org.commonmark.node.DefinitionMap; public class Definitions { diff --git a/commonmark/src/main/java/org/commonmark/internal/Delimiter.java b/commonmark/src/main/java/org/commonmark/internal/Delimiter.java index 9083ce3cb..e652e373d 100644 --- a/commonmark/src/main/java/org/commonmark/internal/Delimiter.java +++ b/commonmark/src/main/java/org/commonmark/internal/Delimiter.java @@ -1,13 +1,10 @@ package org.commonmark.internal; +import java.util.List; import org.commonmark.node.Text; import org.commonmark.parser.delimiter.DelimiterRun; -import java.util.List; - -/** - * Delimiter (emphasis, strong emphasis or custom emphasis). - */ +/** Delimiter (emphasis, strong emphasis or custom emphasis). */ public class Delimiter implements DelimiterRun { public final List characters; @@ -23,7 +20,12 @@ public class Delimiter implements DelimiterRun { public Delimiter previous; public Delimiter next; - public Delimiter(List characters, char delimiterChar, boolean canOpen, boolean canClose, Delimiter previous) { + public Delimiter( + List characters, + char delimiterChar, + boolean canOpen, + boolean canClose, + Delimiter previous) { this.characters = characters; this.delimiterChar = delimiterChar; this.canOpen = canOpen; @@ -65,7 +67,8 @@ public Text getCloser() { @Override public Iterable getOpeners(int length) { if (!(length >= 1 && length <= length())) { - throw new IllegalArgumentException("length must be between 1 and " + length() + ", was " + length); + throw new IllegalArgumentException( + "length must be between 1 and " + length() + ", was " + length); } return characters.subList(characters.size() - length, characters.size()); @@ -74,7 +77,8 @@ public Iterable getOpeners(int length) { @Override public Iterable getClosers(int length) { if (!(length >= 1 && length <= length())) { - throw new IllegalArgumentException("length must be between 1 and " + length() + ", was " + length); + throw new IllegalArgumentException( + "length must be between 1 and " + length() + ", was " + length); } return characters.subList(0, length); diff --git a/commonmark/src/main/java/org/commonmark/internal/DocumentBlockParser.java b/commonmark/src/main/java/org/commonmark/internal/DocumentBlockParser.java index 4b51275ee..2d52c5080 100644 --- a/commonmark/src/main/java/org/commonmark/internal/DocumentBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/DocumentBlockParser.java @@ -29,5 +29,4 @@ public Document getBlock() { public BlockContinue tryContinue(ParserState state) { return BlockContinue.atIndex(state.getIndex()); } - } diff --git a/commonmark/src/main/java/org/commonmark/internal/DocumentParser.java b/commonmark/src/main/java/org/commonmark/internal/DocumentParser.java index 17e7b9c84..6565cec4f 100644 --- a/commonmark/src/main/java/org/commonmark/internal/DocumentParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/DocumentParser.java @@ -1,5 +1,8 @@ package org.commonmark.internal; +import java.io.IOException; +import java.io.Reader; +import java.util.*; import org.commonmark.internal.util.LineReader; import org.commonmark.internal.util.Parsing; import org.commonmark.node.*; @@ -7,26 +10,24 @@ import org.commonmark.parser.InlineParserFactory; import org.commonmark.parser.SourceLine; import org.commonmark.parser.SourceLines; -import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.beta.InlineContentParserFactory; +import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.block.*; import org.commonmark.parser.delimiter.DelimiterProcessor; import org.commonmark.text.Characters; -import java.io.IOException; -import java.io.Reader; -import java.util.*; - public class DocumentParser implements ParserState { - private static final Set> CORE_FACTORY_TYPES = new LinkedHashSet<>(List.of( - BlockQuote.class, - Heading.class, - FencedCodeBlock.class, - HtmlBlock.class, - ThematicBreak.class, - ListBlock.class, - IndentedCodeBlock.class)); + private static final Set> CORE_FACTORY_TYPES = + new LinkedHashSet<>( + List.of( + BlockQuote.class, + Heading.class, + FencedCodeBlock.class, + HtmlBlock.class, + ThematicBreak.class, + ListBlock.class, + IndentedCodeBlock.class)); private static final Map, BlockParserFactory> NODES_TO_CORE_FACTORIES; @@ -44,24 +45,16 @@ public class DocumentParser implements ParserState { private SourceLine line; - /** - * Line index (0-based) - */ + /** Line index (0-based) */ private int lineIndex = -1; - /** - * current index (offset) in input line (0-based) - */ + /** current index (offset) in input line (0-based) */ private int index = 0; - /** - * current column of input line (tab causes column to go to next 4-space tab stop) (0-based) - */ + /** current column of input line (tab causes column to go to next 4-space tab stop) (0-based) */ private int column = 0; - /** - * if the current column is within a tab character (partially consumed tab) - */ + /** if the current column is within a tab character (partially consumed tab) */ private boolean columnIsInTab; private int nextNonSpace = 0; @@ -83,10 +76,15 @@ public class DocumentParser implements ParserState { private final List openBlockParsers = new ArrayList<>(); private final List allBlockParsers = new ArrayList<>(); - public DocumentParser(List blockParserFactories, InlineParserFactory inlineParserFactory, - List inlineContentParserFactories, List delimiterProcessors, - List linkProcessors, Set linkMarkers, - IncludeSourceSpans includeSourceSpans, int maxOpenBlockParsers) { + public DocumentParser( + List blockParserFactories, + InlineParserFactory inlineParserFactory, + List inlineContentParserFactories, + List delimiterProcessors, + List linkProcessors, + Set linkMarkers, + IncludeSourceSpans includeSourceSpans, + int maxOpenBlockParsers) { this.blockParserFactories = blockParserFactories; this.inlineParserFactory = inlineParserFactory; this.inlineContentParserFactories = inlineContentParserFactories; @@ -104,8 +102,11 @@ public static Set> getDefaultBlockParserTypes() { return CORE_FACTORY_TYPES; } - public static List calculateBlockParserFactories(List customBlockParserFactories, Set> enabledBlockTypes) { - // By having the custom factories come first, extensions are able to change behavior of core syntax. + public static List calculateBlockParserFactories( + List customBlockParserFactories, + Set> enabledBlockTypes) { + // By having the custom factories come first, extensions are able to change behavior of core + // syntax. List list = new ArrayList<>(customBlockParserFactories); for (Class blockType : enabledBlockTypes) { list.add(NODES_TO_CORE_FACTORIES.get(blockType)); @@ -116,21 +117,25 @@ public static List calculateBlockParserFactories(List> enabledBlockTypes) { for (Class enabledBlockType : enabledBlockTypes) { if (!NODES_TO_CORE_FACTORIES.containsKey(enabledBlockType)) { - throw new IllegalArgumentException("Can't enable block type " + enabledBlockType + ", possible options are: " + NODES_TO_CORE_FACTORIES.keySet()); + throw new IllegalArgumentException( + "Can't enable block type " + + enabledBlockType + + ", possible options are: " + + NODES_TO_CORE_FACTORIES.keySet()); } } } - /** - * The main parsing function. Returns a parsed document AST. - */ + /** The main parsing function. Returns a parsed document AST. */ public Document parse(String input) { int lineStart = 0; int lineBreak; while ((lineBreak = Characters.findLineBreak(input, lineStart)) != -1) { String line = input.substring(lineStart, lineBreak); parseLine(line, lineStart); - if (lineBreak + 1 < input.length() && input.charAt(lineBreak) == '\r' && input.charAt(lineBreak + 1) == '\n') { + if (lineBreak + 1 < input.length() + && input.charAt(lineBreak) == '\r' + && input.charAt(lineBreak + 1) == '\n') { lineStart = lineBreak + 2; } else { lineStart = lineBreak + 1; @@ -196,14 +201,15 @@ public BlockParser getActiveBlockParser() { } /** - * Analyze a line of text and update the document appropriately. We parse markdown text by calling this on each - * line of input, then finalizing the document. + * Analyze a line of text and update the document appropriately. We parse markdown text by + * calling this on each line of input, then finalizing the document. */ private void parseLine(String ln, int inputIndex) { setLine(ln, inputIndex); // For each containing block, try to parse the associated line start. - // The document will always match, so we can skip the first block parser and start at 1 matches + // The document will always match, so we can skip the first block parser and start at 1 + // matches int matches = 1; for (int i = 1; i < openBlockParsers.size(); i++) { OpenBlockParser openBlockParser = openBlockParsers.get(i); @@ -239,13 +245,16 @@ private void parseLine(String ln, int inputIndex) { // Unless last matched container is a code block, try new container starts, // adding children to the last matched container: - boolean tryBlockStarts = blockParser.getBlock() instanceof Paragraph || blockParser.isContainer(); + boolean tryBlockStarts = + blockParser.getBlock() instanceof Paragraph || blockParser.isContainer(); while (tryBlockStarts) { lastIndex = index; findNextNonSpace(); // this is a little performance optimization: - if (isBlank() || (indent < Parsing.CODE_BLOCK_INDENT && Characters.isLetter(this.line.getContent(), nextNonSpace))) { + if (isBlank() + || (indent < Parsing.CODE_BLOCK_INDENT + && Characters.isLetter(this.line.getContent(), nextNonSpace))) { setNewIndex(nextNonSpace); break; } @@ -259,7 +268,8 @@ private void parseLine(String ln, int inputIndex) { startedNewBlock = true; int sourceIndex = getIndex(); - // We're starting a new block. If we have any previous blocks that need to be closed, we need to do it now. + // We're starting a new block. If we have any previous blocks that need to be closed, we + // need to do it now. if (unmatchedBlocks > 0) { closeBlockParsers(unmatchedBlocks); unmatchedBlocks = 0; @@ -272,11 +282,15 @@ private void parseLine(String ln, int inputIndex) { } List replacedSourceSpans = null; - if (blockStart.getReplaceParagraphLines() >= 1 || blockStart.isReplaceActiveBlockParser()) { + if (blockStart.getReplaceParagraphLines() >= 1 + || blockStart.isReplaceActiveBlockParser()) { var activeBlockParser = getActiveBlockParser(); if (activeBlockParser instanceof ParagraphParser) { var paragraphParser = (ParagraphParser) activeBlockParser; - var lines = blockStart.isReplaceActiveBlockParser() ? Integer.MAX_VALUE : blockStart.getReplaceParagraphLines(); + var lines = + blockStart.isReplaceActiveBlockParser() + ? Integer.MAX_VALUE + : blockStart.getReplaceParagraphLines(); replacedSourceSpans = replaceParagraphLines(lines, paragraphParser); } else if (blockStart.isReplaceActiveBlockParser()) { replacedSourceSpans = prepareActiveBlockParserForReplacement(activeBlockParser); @@ -297,8 +311,9 @@ private void parseLine(String ln, int inputIndex) { // appropriate block. // First check for a lazy continuation line - if (!startedNewBlock && !isBlank() && - getActiveBlockParser().canHaveLazyContinuationLines()) { + if (!startedNewBlock + && !isBlank() + && getActiveBlockParser().canHaveLazyContinuationLines()) { openBlockParsers.get(openBlockParsers.size() - 1).sourceIndex = lastIndex; // lazy paragraph continuation addLine(); @@ -324,7 +339,8 @@ private void parseLine(String ln, int inputIndex) { // list item // ``` // - // The first line does not start a paragraph yet, but we still want to record source positions. + // The first line does not start a paragraph yet, but we still want to record source + // positions. addSourceSpans(); } } @@ -416,13 +432,14 @@ private void advance() { } /** - * Add line content to the active block parser. We assume it can accept lines -- that check should be done before - * calling this. + * Add line content to the active block parser. We assume it can accept lines -- that check + * should be done before calling this. */ private void addLine() { CharSequence content; if (columnIsInTab) { - // Our column is in a partially consumed tab. Expand the remaining columns (to the next tab stop) to spaces. + // Our column is in a partially consumed tab. Expand the remaining columns (to the next + // tab stop) to spaces. int afterTab = index + 1; CharSequence rest = line.getContent().subSequence(afterTab, line.getContent().length()); int spaces = Parsing.columnsToNextTabStop(column); @@ -438,8 +455,10 @@ private void addLine() { content = line.getContent().subSequence(index, line.getContent().length()); } SourceSpan sourceSpan = null; - if (includeSourceSpans == IncludeSourceSpans.BLOCKS_AND_INLINES && index < line.getSourceSpan().getLength()) { - // Note that if we're in a partially-consumed tab the length of the source span and the content don't match. + if (includeSourceSpans == IncludeSourceSpans.BLOCKS_AND_INLINES + && index < line.getSourceSpan().getLength()) { + // Note that if we're in a partially-consumed tab the length of the source span and the + // content don't match. sourceSpan = line.getSourceSpan().subSpan(index); } getActiveBlockParser().addLine(SourceLine.of(content, sourceSpan)); @@ -448,15 +467,17 @@ private void addLine() { private void addSourceSpans() { if (includeSourceSpans != IncludeSourceSpans.NONE) { - // Don't add source spans for Document itself (it would get the whole source text), so start at 1, not 0 + // Don't add source spans for Document itself (it would get the whole source text), so + // start at 1, not 0 for (int i = 1; i < openBlockParsers.size(); i++) { var openBlockParser = openBlockParsers.get(i); - // In case of a lazy continuation line, the index is less than where the block parser would expect the - // contents to start, so let's use whichever is smaller. + // In case of a lazy continuation line, the index is less than where the block + // parser would expect the contents to start, so let's use whichever is smaller. int blockIndex = Math.min(openBlockParser.sourceIndex, index); int length = line.getContent().length() - blockIndex; if (length != 0) { - openBlockParser.blockParser.addSourceSpan(line.getSourceSpan().subSpan(blockIndex)); + openBlockParser.blockParser.addSourceSpan( + line.getSourceSpan().subSpan(blockIndex)); } } } @@ -477,10 +498,17 @@ private BlockStartImpl findBlockStart(BlockParser blockParser) { } /** - * Walk through a block & children recursively, parsing string content into inline content where appropriate. + * Walk through a block & children recursively, parsing string content into inline content where + * appropriate. */ private void processInlines() { - var context = new InlineParserContextImpl(inlineContentParserFactories, delimiterProcessors, linkProcessors, linkMarkers, definitions); + var context = + new InlineParserContextImpl( + inlineContentParserFactories, + delimiterProcessors, + linkProcessors, + linkMarkers, + definitions); var inlineParser = inlineParserFactory.create(context); for (var blockParser : allBlockParsers) { @@ -489,8 +517,8 @@ private void processInlines() { } /** - * Add block of type tag as a child of the tip. If the tip can't accept children, close and finalize it and try - * its parent, and so on until we find a block that can accept children. + * Add block of type tag as a child of the tip. If the tip can't accept children, close and + * finalize it and try its parent, and so on until we find a block that can accept children. */ private void addChild(OpenBlockParser openBlockParser) { while (!getActiveBlockParser().canContain(openBlockParser.blockParser.getBlock())) { @@ -522,7 +550,8 @@ private List prepareActiveBlockParserForReplacement(BlockParser bloc // Note that we don't want to parse inlines here, as it's getting replaced. deactivateBlockParser(); - // Do this so that source positions are calculated, which we will carry over to the replacing block. + // Do this so that source positions are calculated, which we will carry over to the + // replacing block. blockParser.closeBlock(); blockParser.getBlock().unlink(); return blockParser.getBlock().getSourceSpans(); @@ -538,16 +567,16 @@ private void closeBlockParsers(int count) { for (int i = 0; i < count; i++) { BlockParser blockParser = deactivateBlockParser().blockParser; finalize(blockParser); - // Remember for inline parsing. Note that a lot of blocks don't need inline parsing. We could have a - // separate interface (e.g. BlockParserWithInlines) so that we only have to remember those that actually - // have inlines to parse. + // Remember for inline parsing. Note that a lot of blocks don't need inline parsing. We + // could have a separate interface (e.g. BlockParserWithInlines) so that we only have to + // remember those that actually have inlines to parse. allBlockParsers.add(blockParser); } } /** - * Finalize a block. Close it and do any necessary postprocessing, e.g. setting the content of blocks and - * collecting link reference definitions from paragraphs. + * Finalize a block. Close it and do any necessary postprocessing, e.g. setting the content of + * blocks and collecting link reference definitions from paragraphs. */ private void finalize(BlockParser blockParser) { addDefinitionsFrom(blockParser); @@ -560,9 +589,7 @@ private void addDefinitionsFrom(BlockParser blockParser) { } } - /** - * Prepares the input line replacing {@code \0} - */ + /** Prepares the input line replacing {@code \0} */ private static String prepareLine(String line) { if (line.indexOf('\0') == -1) { return line; diff --git a/commonmark/src/main/java/org/commonmark/internal/FencedCodeBlockParser.java b/commonmark/src/main/java/org/commonmark/internal/FencedCodeBlockParser.java index d550f1d25..042e08f6b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/FencedCodeBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/FencedCodeBlockParser.java @@ -1,5 +1,7 @@ package org.commonmark.internal; +import static org.commonmark.internal.util.Escaping.unescapeString; + import org.commonmark.internal.util.Parsing; import org.commonmark.node.Block; import org.commonmark.node.FencedCodeBlock; @@ -7,8 +9,6 @@ import org.commonmark.parser.block.*; import org.commonmark.text.Characters; -import static org.commonmark.internal.util.Escaping.unescapeString; - public class FencedCodeBlockParser extends AbstractBlockParser { private final FencedCodeBlock block = new FencedCodeBlock(); @@ -36,7 +36,9 @@ public BlockContinue tryContinue(ParserState state) { int nextNonSpace = state.getNextNonSpaceIndex(); int newIndex = state.getIndex(); CharSequence line = state.getLine().getContent(); - if (state.getIndent() < Parsing.CODE_BLOCK_INDENT && nextNonSpace < line.length() && tryClosing(line, nextNonSpace)) { + if (state.getIndent() < Parsing.CODE_BLOCK_INDENT + && nextNonSpace < line.length() + && tryClosing(line, nextNonSpace)) { // closing fence - we're at end of line, so we can finalize now return BlockContinue.finished(); } else { @@ -78,17 +80,19 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar } int nextNonSpace = state.getNextNonSpaceIndex(); - FencedCodeBlockParser blockParser = checkOpener(state.getLine().getContent(), nextNonSpace, indent); + FencedCodeBlockParser blockParser = + checkOpener(state.getLine().getContent(), nextNonSpace, indent); if (blockParser != null) { - return BlockStart.of(blockParser).atIndex(nextNonSpace + blockParser.block.getOpeningFenceLength()); + return BlockStart.of(blockParser) + .atIndex(nextNonSpace + blockParser.block.getOpeningFenceLength()); } else { return BlockStart.none(); } } } - // spec: A code fence is a sequence of at least three consecutive backtick characters (`) or tildes (~). (Tildes and - // backticks cannot be mixed.) + // spec: A code fence is a sequence of at least three consecutive backtick characters (`) or + // tildes (~). (Tildes and backticks cannot be mixed.) private static FencedCodeBlockParser checkOpener(CharSequence line, int index, int indent) { int backticks = 0; int tildes = 0; @@ -107,7 +111,8 @@ private static FencedCodeBlockParser checkOpener(CharSequence line, int index, i } } if (backticks >= 3 && tildes == 0) { - // spec: If the info string comes after a backtick fence, it may not contain any backtick characters. + // spec: If the info string comes after a backtick fence, it may not contain any + // backtick characters. if (Characters.find('`', line, index + backticks) != -1) { return null; } @@ -120,8 +125,9 @@ private static FencedCodeBlockParser checkOpener(CharSequence line, int index, i } } - // spec: The content of the code block consists of all subsequent lines, until a closing code fence of the same type - // as the code block began with (backticks or tildes), and with at least as many backticks or tildes as the opening + // spec: The content of the code block consists of all subsequent lines, until a closing code + // fence of the same type as the code block began with (backticks or tildes), and with at least + // as many backticks or tildes as the opening // code fence. private boolean tryClosing(CharSequence line, int index) { int fences = Characters.skip(fenceChar, line, index, line.length()) - index; diff --git a/commonmark/src/main/java/org/commonmark/internal/HeadingParser.java b/commonmark/src/main/java/org/commonmark/internal/HeadingParser.java index 05f070137..402647e0f 100644 --- a/commonmark/src/main/java/org/commonmark/internal/HeadingParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/HeadingParser.java @@ -28,7 +28,8 @@ public Block getBlock() { @Override public BlockContinue tryContinue(ParserState parserState) { - // In both ATX and Setext headings, once we have the heading markup, there's nothing more to parse. + // In both ATX and Setext headings, once we have the heading markup, there's nothing more to + // parse. return BlockContinue.none(); } @@ -48,7 +49,8 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar SourceLine line = state.getLine(); int nextNonSpace = state.getNextNonSpaceIndex(); if (line.getContent().charAt(nextNonSpace) == '#') { - HeadingParser atxHeading = getAtxHeading(line.substring(nextNonSpace, line.getContent().length())); + HeadingParser atxHeading = + getAtxHeading(line.substring(nextNonSpace, line.getContent().length())); if (atxHeading != null) { return BlockStart.of(atxHeading).atIndex(line.getContent().length()); } @@ -68,10 +70,11 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar } } - // spec: An ATX heading consists of a string of characters, parsed as inline content, between an opening sequence of - // 1-6 unescaped # characters and an optional closing sequence of any number of unescaped # characters. The opening - // sequence of # characters must be followed by a space or by the end of line. The optional closing sequence of #s - // must be preceded by a space and may be followed by spaces only. + // spec: An ATX heading consists of a string of characters, parsed as inline content, between an + // opening sequence of 1-6 unescaped # characters and an optional closing sequence of any number + // of unescaped # characters. The opening sequence of # characters must be followed by a space + // or by the end of line. The optional closing sequence of #s must be preceded by a space and + // may be followed by spaces only. private static HeadingParser getAtxHeading(SourceLine line) { Scanner scanner = Scanner.of(SourceLines.of(line)); int level = scanner.matchMultiple('#'); @@ -102,7 +105,8 @@ private static HeadingParser getAtxHeading(SourceLine line) { if (hashCanEnd) { scanner.matchMultiple('#'); int whitespace = scanner.whitespace(); - // If there's other characters, the hashes and spaces were part of the heading + // If there's other characters, the hashes and spaces were part of the + // heading if (scanner.hasNext()) { end = scanner.position(); } @@ -132,8 +136,8 @@ private static HeadingParser getAtxHeading(SourceLine line) { return new HeadingParser(level, source); } - // spec: A setext heading underline is a sequence of = characters or a sequence of - characters, with no more than - // 3 spaces indentation and any number of trailing spaces. + // spec: A setext heading underline is a sequence of = characters or a sequence of - characters, + // with no more than 3 spaces indentation and any number of trailing spaces. private static int getSetextHeadingLevel(CharSequence line, int index) { switch (line.charAt(index)) { case '=': diff --git a/commonmark/src/main/java/org/commonmark/internal/HtmlBlockParser.java b/commonmark/src/main/java/org/commonmark/internal/HtmlBlockParser.java index 123d9ec1f..68848de6b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/HtmlBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/HtmlBlockParser.java @@ -1,13 +1,12 @@ package org.commonmark.internal; +import java.util.regex.Pattern; import org.commonmark.node.Block; import org.commonmark.node.HtmlBlock; import org.commonmark.node.Paragraph; import org.commonmark.parser.SourceLine; import org.commonmark.parser.block.*; -import java.util.regex.Pattern; - public class HtmlBlockParser extends AbstractBlockParser { private static final String TAGNAME = "[A-Za-z][A-Za-z0-9-]*"; @@ -15,63 +14,56 @@ public class HtmlBlockParser extends AbstractBlockParser { private static final String UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+"; private static final String SINGLEQUOTEDVALUE = "'[^']*'"; private static final String DOUBLEQUOTEDVALUE = "\"[^\"]*\""; - private static final String ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE - + "|" + DOUBLEQUOTEDVALUE + ")"; - private static final String ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE - + ")"; - private static final String ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC - + "?)"; + private static final String ATTRIBUTEVALUE = + "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")"; + private static final String ATTRIBUTEVALUESPEC = + "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")"; + private static final String ATTRIBUTE = + "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)"; private static final String OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>"; private static final String CLOSETAG = "]"; - private static final Pattern[][] BLOCK_PATTERNS = new Pattern[][]{ - {null, null}, // not used (no type 0) - { - Pattern.compile("^<(?:script|pre|style|textarea)(?:\\s|>|$)", Pattern.CASE_INSENSITIVE), + private static final Pattern[][] BLOCK_PATTERNS = + new Pattern[][] { + {null, null}, // not used (no type 0) + { + Pattern.compile( + "^<(?:script|pre|style|textarea)(?:\\s|>|$)", Pattern.CASE_INSENSITIVE), Pattern.compile("", Pattern.CASE_INSENSITIVE) - }, - { - Pattern.compile("^") - }, - { - Pattern.compile("^<[?]"), - Pattern.compile("\\?>") - }, - { - Pattern.compile("^") - }, - { - Pattern.compile("^") - }, - { - Pattern.compile("^]|$)", Pattern.CASE_INSENSITIVE), + }, + {Pattern.compile("^")}, + {Pattern.compile("^<[?]"), Pattern.compile("\\?>")}, + {Pattern.compile("^")}, + {Pattern.compile("^")}, + { + Pattern.compile( + "^]|$)", + Pattern.CASE_INSENSITIVE), null // terminated by blank line - }, - { - Pattern.compile("^(?:" + OPENTAG + '|' + CLOSETAG + ")\\s*$", Pattern.CASE_INSENSITIVE), + }, + { + Pattern.compile( + "^(?:" + OPENTAG + '|' + CLOSETAG + ")\\s*$", Pattern.CASE_INSENSITIVE), null // terminated by blank line - } - }; + } + }; private final HtmlBlock block = new HtmlBlock(); private final Pattern closingPattern; @@ -127,14 +119,17 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar if (state.getIndent() < 4 && line.charAt(nextNonSpace) == '<') { for (int blockType = 1; blockType <= 7; blockType++) { // Type 7 can not interrupt a paragraph (not even a lazy one) - if (blockType == 7 && ( - matchedBlockParser.getMatchedBlockParser().getBlock() instanceof Paragraph || - state.getActiveBlockParser().canHaveLazyContinuationLines())) { + if (blockType == 7 + && (matchedBlockParser.getMatchedBlockParser().getBlock() + instanceof Paragraph + || state.getActiveBlockParser() + .canHaveLazyContinuationLines())) { continue; } Pattern opener = BLOCK_PATTERNS[blockType][0]; Pattern closer = BLOCK_PATTERNS[blockType][1]; - boolean matches = opener.matcher(line.subSequence(nextNonSpace, line.length())).find(); + boolean matches = + opener.matcher(line.subSequence(nextNonSpace, line.length())).find(); if (matches) { return BlockStart.of(new HtmlBlockParser(closer)).atIndex(state.getIndex()); } diff --git a/commonmark/src/main/java/org/commonmark/internal/IndentedCodeBlockParser.java b/commonmark/src/main/java/org/commonmark/internal/IndentedCodeBlockParser.java index 3598f5615..b05b0a456 100644 --- a/commonmark/src/main/java/org/commonmark/internal/IndentedCodeBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/IndentedCodeBlockParser.java @@ -1,5 +1,7 @@ package org.commonmark.internal; +import java.util.ArrayList; +import java.util.List; import org.commonmark.internal.util.Parsing; import org.commonmark.node.Block; import org.commonmark.node.IndentedCodeBlock; @@ -8,9 +10,6 @@ import org.commonmark.parser.block.*; import org.commonmark.text.Characters; -import java.util.ArrayList; -import java.util.List; - public class IndentedCodeBlockParser extends AbstractBlockParser { private final IndentedCodeBlock block = new IndentedCodeBlock(); @@ -62,12 +61,14 @@ public static class Factory extends AbstractBlockParserFactory { @Override public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser) { // An indented code block cannot interrupt a paragraph. - if (state.getIndent() >= Parsing.CODE_BLOCK_INDENT && !state.isBlank() && !(state.getActiveBlockParser().getBlock() instanceof Paragraph)) { - return BlockStart.of(new IndentedCodeBlockParser()).atColumn(state.getColumn() + Parsing.CODE_BLOCK_INDENT); + if (state.getIndent() >= Parsing.CODE_BLOCK_INDENT + && !state.isBlank() + && !(state.getActiveBlockParser().getBlock() instanceof Paragraph)) { + return BlockStart.of(new IndentedCodeBlockParser()) + .atColumn(state.getColumn() + Parsing.CODE_BLOCK_INDENT); } else { return BlockStart.none(); } } } } - diff --git a/commonmark/src/main/java/org/commonmark/internal/InlineParserContextImpl.java b/commonmark/src/main/java/org/commonmark/internal/InlineParserContextImpl.java index 233041f62..9b87896fc 100644 --- a/commonmark/src/main/java/org/commonmark/internal/InlineParserContextImpl.java +++ b/commonmark/src/main/java/org/commonmark/internal/InlineParserContextImpl.java @@ -1,14 +1,13 @@ package org.commonmark.internal; +import java.util.List; +import java.util.Set; import org.commonmark.node.LinkReferenceDefinition; import org.commonmark.parser.InlineParserContext; -import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.beta.InlineContentParserFactory; +import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.delimiter.DelimiterProcessor; -import java.util.List; -import java.util.Set; - public class InlineParserContextImpl implements InlineParserContext { private final List inlineContentParserFactories; @@ -17,11 +16,12 @@ public class InlineParserContextImpl implements InlineParserContext { private final Set linkMarkers; private final Definitions definitions; - public InlineParserContextImpl(List inlineContentParserFactories, - List delimiterProcessors, - List linkProcessors, - Set linkMarkers, - Definitions definitions) { + public InlineParserContextImpl( + List inlineContentParserFactories, + List delimiterProcessors, + List linkProcessors, + Set linkMarkers, + Definitions definitions) { this.inlineContentParserFactories = inlineContentParserFactories; this.delimiterProcessors = delimiterProcessors; this.linkProcessors = linkProcessors; diff --git a/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java b/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java index 44422f421..17ecd6d31 100644 --- a/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java +++ b/commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java @@ -1,5 +1,6 @@ package org.commonmark.internal; +import java.util.*; import org.commonmark.internal.inline.*; import org.commonmark.internal.util.Escaping; import org.commonmark.internal.util.LinkScanner; @@ -7,13 +8,11 @@ import org.commonmark.parser.InlineParser; import org.commonmark.parser.InlineParserContext; import org.commonmark.parser.SourceLines; -import org.commonmark.parser.beta.Scanner; import org.commonmark.parser.beta.*; +import org.commonmark.parser.beta.Scanner; import org.commonmark.parser.delimiter.DelimiterProcessor; import org.commonmark.text.Characters; -import java.util.*; - public class InlineParserImpl implements InlineParser, InlineParserState { private final InlineParserContext context; @@ -29,27 +28,34 @@ public class InlineParserImpl implements InlineParser, InlineParserState { private int trailingSpaces; /** - * Top delimiter (emphasis, strong emphasis or custom emphasis). (Brackets are on a separate stack, different - * from the algorithm described in the spec.) + * Top delimiter (emphasis, strong emphasis or custom emphasis). (Brackets are on a separate + * stack, different from the algorithm described in the spec.) */ private Delimiter lastDelimiter; - /** - * Top opening bracket ([ or ![)). - */ + /** Top opening bracket ([ or ![)). */ private Bracket lastBracket; public InlineParserImpl(InlineParserContext context) { this.context = context; - this.inlineContentParserFactories = calculateInlineContentParserFactories(context.getCustomInlineContentParserFactories()); - this.delimiterProcessors = calculateDelimiterProcessors(context.getCustomDelimiterProcessors()); + this.inlineContentParserFactories = + calculateInlineContentParserFactories( + context.getCustomInlineContentParserFactories()); + this.delimiterProcessors = + calculateDelimiterProcessors(context.getCustomDelimiterProcessors()); this.linkProcessors = calculateLinkProcessors(context.getCustomLinkProcessors()); this.linkMarkers = calculateLinkMarkers(context.getCustomLinkMarkers()); - this.specialCharacters = calculateSpecialCharacters(linkMarkers, this.delimiterProcessors.keySet(), this.inlineContentParserFactories); + this.specialCharacters = + calculateSpecialCharacters( + linkMarkers, + this.delimiterProcessors.keySet(), + this.inlineContentParserFactories); } - private List calculateInlineContentParserFactories(List customFactories) { - // Custom parsers can override built-in parsers if they want, so make sure they are tried first + private List calculateInlineContentParserFactories( + List customFactories) { + // Custom parsers can override built-in parsers if they want, so make sure they are tried + // first var list = new ArrayList<>(customFactories); list.add(new BackslashInlineParser.Factory()); list.add(new BackticksInlineParser.Factory()); @@ -60,20 +66,25 @@ private List calculateInlineContentParserFactories(L } private List calculateLinkProcessors(List linkProcessors) { - // Custom link processors can override the built-in behavior, so make sure they are tried first + // Custom link processors can override the built-in behavior, so make sure they are tried + // first var list = new ArrayList<>(linkProcessors); list.add(new CoreLinkProcessor()); return list; } - private static Map calculateDelimiterProcessors(List delimiterProcessors) { + private static Map calculateDelimiterProcessors( + List delimiterProcessors) { var map = new HashMap(); - addDelimiterProcessors(List.of(new AsteriskDelimiterProcessor(), new UnderscoreDelimiterProcessor()), map); + addDelimiterProcessors( + List.of(new AsteriskDelimiterProcessor(), new UnderscoreDelimiterProcessor()), map); addDelimiterProcessors(delimiterProcessors, map); return map; } - private static void addDelimiterProcessors(Iterable delimiterProcessors, Map map) { + private static void addDelimiterProcessors( + Iterable delimiterProcessors, + Map map) { for (DelimiterProcessor delimiterProcessor : delimiterProcessors) { char opening = delimiterProcessor.getOpeningCharacter(); char closing = delimiterProcessor.getClosingCharacter(); @@ -99,10 +110,14 @@ private static void addDelimiterProcessors(Iterable delimite } } - private static void addDelimiterProcessorForChar(char delimiterChar, DelimiterProcessor toAdd, Map delimiterProcessors) { + private static void addDelimiterProcessorForChar( + char delimiterChar, + DelimiterProcessor toAdd, + Map delimiterProcessors) { DelimiterProcessor existing = delimiterProcessors.put(delimiterChar, toAdd); if (existing != null) { - throw new IllegalArgumentException("Delimiter processor conflict with delimiter char '" + delimiterChar + "'"); + throw new IllegalArgumentException( + "Delimiter processor conflict with delimiter char '" + delimiterChar + "'"); } } @@ -115,9 +130,10 @@ private static BitSet calculateLinkMarkers(Set linkMarkers) { return bitSet; } - private static BitSet calculateSpecialCharacters(BitSet linkMarkers, - Set delimiterCharacters, - List inlineContentParserFactories) { + private static BitSet calculateSpecialCharacters( + BitSet linkMarkers, + Set delimiterCharacters, + List inlineContentParserFactories) { BitSet bitSet = (BitSet) linkMarkers.clone(); for (Character c : delimiterCharacters) { bitSet.set(c); @@ -150,9 +166,7 @@ public Scanner scanner() { return scanner; } - /** - * Parse content in block into inline children, appending them to the block node. - */ + /** Parse content in block into inline children, appending them to the block node. */ @Override public void parse(SourceLines lines, Node block) { reset(lines); @@ -187,9 +201,8 @@ private Text text(SourceLines sourceLines) { } /** - * Parse the next inline element in subject, advancing our position. - * On success, return the new inline node. - * On failure, return null. + * Parse the next inline element in subject, advancing our position. On success, return the new + * inline node. On failure, return null. */ private List parseInline() { char c = scanner.peek(); @@ -230,7 +243,8 @@ private List parseInline() { Node node = parsedInlineImpl.getNode(); scanner.setPosition(parsedInlineImpl.getPosition()); if (includeSourceSpans && node.getSourceSpans().isEmpty()) { - node.setSourceSpans(scanner.getSource(position, scanner.position()).getSourceSpans()); + node.setSourceSpans( + scanner.getSource(position, scanner.position()).getSourceSpans()); } return List.of(node); } else { @@ -252,10 +266,9 @@ private List parseInline() { return List.of(parseText()); } - /** - * Attempt to parse delimiters like emphasis, strong emphasis or custom delimiters. - */ - private List parseDelimiters(DelimiterProcessor delimiterProcessor, char delimiterChar) { + /** Attempt to parse delimiters like emphasis, strong emphasis or custom delimiters. */ + private List parseDelimiters( + DelimiterProcessor delimiterProcessor, char delimiterChar) { DelimiterData res = scanDelimiters(delimiterProcessor, delimiterChar); if (res == null) { return null; @@ -264,7 +277,8 @@ private List parseDelimiters(DelimiterProcessor delimiterProcess List characters = res.characters; // Add entry to stack for this opener - lastDelimiter = new Delimiter(characters, delimiterChar, res.canOpen, res.canClose, lastDelimiter); + lastDelimiter = + new Delimiter(characters, delimiterChar, res.canOpen, res.canClose, lastDelimiter); if (lastDelimiter.previous != null) { lastDelimiter.previous.next = lastDelimiter; } @@ -272,9 +286,7 @@ private List parseDelimiters(DelimiterProcessor delimiterProcess return characters; } - /** - * Add open bracket to delimiter stack and add a text node to block's children. - */ + /** Add open bracket to delimiter stack and add a text node to block's children. */ private Node parseOpenBracket() { Position start = scanner.position(); scanner.next(); @@ -288,10 +300,7 @@ private Node parseOpenBracket() { return node; } - /** - * If next character is {@code [}, add a bracket to the stack. - * Otherwise, return null. - */ + /** If next character is {@code [}, add a bracket to the stack. Otherwise, return null. */ private List parseLinkMarker() { var markerPosition = scanner.position(); scanner.next(); @@ -302,7 +311,15 @@ private List parseLinkMarker() { var bracketNode = text(scanner.getSource(bracketPosition, contentPosition)); // Add entry to stack for this opener - addBracket(Bracket.withMarker(bangNode, markerPosition, bracketNode, bracketPosition, contentPosition, lastBracket, lastDelimiter)); + addBracket( + Bracket.withMarker( + bangNode, + markerPosition, + bracketNode, + bracketPosition, + contentPosition, + lastBracket, + lastDelimiter)); return List.of(bangNode, bracketNode); } else { return null; @@ -310,8 +327,9 @@ private List parseLinkMarker() { } /** - * Try to match close bracket against an opening in the delimiter stack. Return either a link or image, or a - * plain [ character. If there is a matching delimiter, remove it from the delimiter stack. + * Try to match close bracket against an opening in the delimiter stack. Return either a link or + * image, or a plain [ character. If there is a matching delimiter, remove it from the delimiter + * stack. */ private Node parseCloseBracket() { Position beforeClose = scanner.position(); @@ -379,7 +397,8 @@ private LinkInfo parseLinkInfo(Bracket opener, Position beforeClose) { // Check to see if we have a link (or image, with a ! in front). The different types: // - Inline: `[foo](/uri)` or with optional title `[foo](/uri "title")` // - Reference links - // - Full: `[foo][bar]` (foo is the text and bar is the label that needs to match a reference) + // - Full: `[foo][bar]` (foo is the text and bar is the label that needs to match a + // reference) // - Collapsed: `[foo][]` (foo is both the text and label) // - Shortcut: `[foo]` (foo is both the text and label) @@ -390,14 +409,21 @@ private LinkInfo parseLinkInfo(Bracket opener, Position beforeClose) { var destinationTitle = parseInlineDestinationTitle(scanner); if (destinationTitle != null) { var text = scanner.getSource(opener.contentPosition, beforeClose).getContent(); - return new LinkInfoImpl(opener.markerNode, opener.bracketNode, text, null, destinationTitle.destination, destinationTitle.title, afterClose); + return new LinkInfoImpl( + opener.markerNode, + opener.bracketNode, + text, + null, + destinationTitle.destination, + destinationTitle.title, + afterClose); } // Not an inline link/image, rewind back to after `]`. scanner.setPosition(afterClose); // Maybe a reference link/image like `[foo][bar]`, `[foo][]` or `[foo]`. - // Note that even `[foo](` could be a valid link if foo is a reference, which is why we try this even if the `(` - // failed to be parsed as an inline link/image before. + // Note that even `[foo](` could be a valid link if foo is a reference, which is why we try + // this even if the `(` failed to be parsed as an inline link/image before. // See if there's a link label like `[bar]` or `[]` var label = parseLinkLabel(scanner); @@ -407,17 +433,20 @@ private LinkInfo parseLinkInfo(Bracket opener, Position beforeClose) { } var textIsReference = label == null || label.isEmpty(); if (opener.bracketAfter && textIsReference && opener.markerNode == null) { - // In case of shortcut or collapsed links, the text is used as the reference. But the reference is not allowed to - // contain an unescaped bracket, so if that's the case we don't need to continue. This is an optimization. + // In case of shortcut or collapsed links, the text is used as the reference. But the + // reference is not allowed to contain an unescaped bracket, so if that's the case we + // don't need to continue. This is an optimization. return null; } var text = scanner.getSource(opener.contentPosition, beforeClose).getContent(); - return new LinkInfoImpl(opener.markerNode, opener.bracketNode, text, label, null, null, afterClose); + return new LinkInfoImpl( + opener.markerNode, opener.bracketNode, text, label, null, null, afterClose); } private Node wrapBracket(Bracket opener, Node wrapperNode, boolean includeMarker) { - // Add all nodes between the opening bracket and now (closing bracket) as child nodes of the link + // Add all nodes between the opening bracket and now (closing bracket) as child nodes of the + // link Node n = opener.bracketNode.getNext(); while (n != null) { Node next = n.getNext(); @@ -426,8 +455,12 @@ private Node wrapBracket(Bracket opener, Node wrapperNode, boolean includeMarker } if (includeSourceSpans) { - var startPosition = includeMarker && opener.markerPosition != null ? opener.markerPosition : opener.bracketPosition; - wrapperNode.setSourceSpans(scanner.getSource(startPosition, scanner.position()).getSourceSpans()); + var startPosition = + includeMarker && opener.markerPosition != null + ? opener.markerPosition + : opener.bracketPosition; + wrapperNode.setSourceSpans( + scanner.getSource(startPosition, scanner.position()).getSourceSpans()); } // Process delimiters such as emphasis inside link/image @@ -440,7 +473,8 @@ private Node wrapBracket(Bracket opener, Node wrapperNode, boolean includeMarker opener.bracketNode.unlink(); removeLastBracket(); - // Links within links are not allowed. We found this link, so there can be no other links around it. + // Links within links are not allowed. We found this link, so there can be no other links + // around it. if (opener.markerNode == null) { disallowPreviousLinks(); } @@ -455,24 +489,30 @@ private Node replaceBracket(Bracket opener, Node node, boolean includeMarker) { } if (includeSourceSpans) { - var startPosition = includeMarker && opener.markerPosition != null ? opener.markerPosition : opener.bracketPosition; - node.setSourceSpans(scanner.getSource(startPosition, scanner.position()).getSourceSpans()); + var startPosition = + includeMarker && opener.markerPosition != null + ? opener.markerPosition + : opener.bracketPosition; + node.setSourceSpans( + scanner.getSource(startPosition, scanner.position()).getSourceSpans()); } removeLastBracket(); // Remove nodes that we added since the opener, because we're replacing them - Node n = includeMarker && opener.markerNode != null ? opener.markerNode : opener.bracketNode; + Node n = + includeMarker && opener.markerNode != null ? opener.markerNode : opener.bracketNode; while (n != null) { var next = n.getNext(); n.unlink(); n = next; } - // Links within links are not allowed. We found this link, so there can be no other links around it. - // Note that this makes any syntax like `[foo]` behave the same as built-in links, which is probably a good - // default (it works for footnotes). It might be useful for a `LinkProcessor` to be able to specify the - // behavior; something we could add to `LinkResult` in the future if requested. + // Links within links are not allowed. We found this link, so there can be no other links + // around it. Note that this makes any syntax like `[foo]` behave the same as built-in + // links, which is probably a good default (it works for footnotes). It might be useful for + // a `LinkProcessor` to be able to specify the behavior; something we could add to + // `LinkResult` in the future if requested. if (opener.markerNode == null || !includeMarker) { disallowPreviousLinks(); } @@ -502,9 +542,7 @@ private void disallowPreviousLinks() { } } - /** - * Try to parse the destination and an optional title for an inline link/image. - */ + /** Try to parse the destination and an optional title for an inline link/image. */ private static DestinationTitle parseInlineDestinationTitle(Scanner scanner) { if (!scanner.next('(')) { return null; @@ -531,9 +569,7 @@ private static DestinationTitle parseInlineDestinationTitle(Scanner scanner) { return new DestinationTitle(dest, title); } - /** - * Attempt to parse link destination, returning the string or null if no match. - */ + /** Attempt to parse link destination, returning the string or null if no match. */ private static String parseLinkDestination(Scanner scanner) { char delimiter = scanner.peek(); Position start = scanner.position(); @@ -553,9 +589,7 @@ private static String parseLinkDestination(Scanner scanner) { return Escaping.unescapeString(dest); } - /** - * Attempt to parse link title (sans quotes), returning the string or null if no match. - */ + /** Attempt to parse link title (sans quotes), returning the string or null if no match. */ private static String parseLinkTitle(Scanner scanner) { Position start = scanner.position(); if (!LinkScanner.scanLinkTitle(scanner)) { @@ -568,9 +602,7 @@ private static String parseLinkTitle(Scanner scanner) { return Escaping.unescapeString(title); } - /** - * Attempt to parse a link label, returning the label between the brackets or null. - */ + /** Attempt to parse a link label, returning the label between the brackets or null. */ static String parseLinkLabel(Scanner scanner) { if (!scanner.next('[')) { return null; @@ -608,7 +640,8 @@ private Node parseLineBreak() { } /** - * Parse the next character as plain text, and possibly more if the following characters are non-special. + * Parse the next character as plain text, and possibly more if the following characters are + * non-special. */ private Node parseText() { Position start = scanner.position(); @@ -626,12 +659,14 @@ private Node parseText() { String content = source.getContent(); if (c == '\n') { - // We parsed until the end of the line. Trim any trailing spaces and remember them (for hard line breaks). + // We parsed until the end of the line. Trim any trailing spaces and remember them (for + // hard line breaks). int end = Characters.skipBackwards(' ', content, content.length() - 1, 0) + 1; trailingSpaces = content.length() - end; content = content.substring(0, end); } else if (c == Scanner.END) { - // For the last line, both tabs and spaces are trimmed for some reason (checked with commonmark.js). + // For the last line, both tabs and spaces are trimmed for some reason (checked with + // commonmark.js). int end = Characters.skipSpaceTabBackwards(content, content.length() - 1, 0) + 1; content = content.substring(0, end); } @@ -642,12 +677,14 @@ private Node parseText() { } /** - * Scan a sequence of characters with code delimiterChar, and return information about the number of delimiters - * and whether they are positioned such that they can open and/or close emphasis or strong emphasis. + * Scan a sequence of characters with code delimiterChar, and return information about the + * number of delimiters and whether they are positioned such that they can open and/or close + * emphasis or strong emphasis. * * @return information about delimiter run, or {@code null} */ - private DelimiterData scanDelimiters(DelimiterProcessor delimiterProcessor, char delimiterChar) { + private DelimiterData scanDelimiters( + DelimiterProcessor delimiterProcessor, char delimiterChar) { int before = scanner.peekPreviousCodePoint(); Position start = scanner.position(); @@ -670,15 +707,20 @@ private DelimiterData scanDelimiters(DelimiterProcessor delimiterProcessor, char int after = scanner.peekCodePoint(); // We could be more lazy here, in most cases we don't need to do every match case. - boolean beforeIsPunctuation = before == Scanner.END || Characters.isPunctuationCodePoint(before); - boolean beforeIsWhitespace = before == Scanner.END || Characters.isWhitespaceCodePoint(before); - boolean afterIsPunctuation = after == Scanner.END || Characters.isPunctuationCodePoint(after); + boolean beforeIsPunctuation = + before == Scanner.END || Characters.isPunctuationCodePoint(before); + boolean beforeIsWhitespace = + before == Scanner.END || Characters.isWhitespaceCodePoint(before); + boolean afterIsPunctuation = + after == Scanner.END || Characters.isPunctuationCodePoint(after); boolean afterIsWhitespace = after == Scanner.END || Characters.isWhitespaceCodePoint(after); - boolean leftFlanking = !afterIsWhitespace && - (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation); - boolean rightFlanking = !beforeIsWhitespace && - (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation); + boolean leftFlanking = + !afterIsWhitespace + && (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation); + boolean rightFlanking = + !beforeIsWhitespace + && (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation); boolean canOpen; boolean canClose; if (delimiterChar == '_') { @@ -718,7 +760,9 @@ private void processDelimiters(Delimiter stackBottom) { boolean openerFound = false; boolean potentialOpenerFound = false; Delimiter opener = closer.previous; - while (opener != null && opener != stackBottom && opener != openersBottom.get(delimiterChar)) { + while (opener != null + && opener != stackBottom + && opener != openersBottom.get(delimiterChar)) { if (opener.canOpen() && opener.delimiterChar == openingDelimiterChar) { potentialOpenerFound = true; usedDelims = delimiterProcessor.process(opener, closer); @@ -762,7 +806,8 @@ private void processDelimiters(Delimiter stackBottom) { removeDelimitersBetween(opener, closer); - // No delimiter characters left to process, so we can remove delimiter and the now empty node. + // No delimiter characters left to process, so we can remove delimiter and the now empty + // node. if (opener.length() == 0) { removeDelimiterAndNodes(opener); } @@ -790,14 +835,16 @@ private void removeDelimitersBetween(Delimiter opener, Delimiter closer) { } /** - * Remove the delimiter and the corresponding text node. For used delimiters, e.g. `*` in `*foo*`. + * Remove the delimiter and the corresponding text node. For used delimiters, e.g. `*` in + * `*foo*`. */ private void removeDelimiterAndNodes(Delimiter delim) { removeDelimiter(delim); } /** - * Remove the delimiter but keep the corresponding node as text. For unused delimiters such as `_` in `foo_bar`. + * Remove the delimiter but keep the corresponding node as text. For unused delimiters such as + * `_` in `foo_bar`. */ private void removeDelimiterKeepNode(Delimiter delim) { removeDelimiter(delim); @@ -897,9 +944,7 @@ private static class DelimiterData { } } - /** - * A destination and optional title for a link or image. - */ + /** A destination and optional title for a link or image. */ private static class DestinationTitle { final String destination; final String title; @@ -920,8 +965,14 @@ private static class LinkInfoImpl implements LinkInfo { private final String title; private final Position afterTextBracket; - private LinkInfoImpl(Text marker, Text openingBracket, String text, String label, - String destination, String title, Position afterTextBracket) { + private LinkInfoImpl( + Text marker, + Text openingBracket, + String text, + String label, + String destination, + String title, + Position afterTextBracket) { this.marker = marker; this.openingBracket = openingBracket; this.text = text; diff --git a/commonmark/src/main/java/org/commonmark/internal/LinkReferenceDefinitionParser.java b/commonmark/src/main/java/org/commonmark/internal/LinkReferenceDefinitionParser.java index 637d3b111..8725a0612 100644 --- a/commonmark/src/main/java/org/commonmark/internal/LinkReferenceDefinitionParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/LinkReferenceDefinitionParser.java @@ -1,5 +1,8 @@ package org.commonmark.internal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.commonmark.internal.util.Escaping; import org.commonmark.internal.util.LinkScanner; import org.commonmark.node.LinkReferenceDefinition; @@ -9,14 +12,11 @@ import org.commonmark.parser.beta.Position; import org.commonmark.parser.beta.Scanner; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - /** * Parser for link reference definitions at the beginning of a paragraph. * - * @see Link reference definitions + * @see Link reference + * definitions */ public class LinkReferenceDefinitionParser { @@ -35,8 +35,8 @@ public class LinkReferenceDefinitionParser { public void parse(SourceLine line) { paragraphLines.add(line); if (state == State.PARAGRAPH) { - // We're in a paragraph now. Link reference definitions can only appear at the beginning, so once - // we're in a paragraph, there's no going back. + // We're in a paragraph now. Link reference definitions can only appear at the + // beginning, so once we're in a paragraph, there's no going back. return; } @@ -44,35 +44,41 @@ public void parse(SourceLine line) { while (scanner.hasNext()) { boolean success; switch (state) { - case START_DEFINITION: { - success = startDefinition(scanner); - break; - } - case LABEL: { - success = label(scanner); - break; - } - case DESTINATION: { - success = destination(scanner); - break; - } - case START_TITLE: { - success = startTitle(scanner); - break; - } - case TITLE: { - success = title(scanner); - break; - } - default: { - throw new IllegalStateException("Unknown parsing state: " + state); - } + case START_DEFINITION: + { + success = startDefinition(scanner); + break; + } + case LABEL: + { + success = label(scanner); + break; + } + case DESTINATION: + { + success = destination(scanner); + break; + } + case START_TITLE: + { + success = startTitle(scanner); + break; + } + case TITLE: + { + success = title(scanner); + break; + } + default: + { + throw new IllegalStateException("Unknown parsing state: " + state); + } } // Parsing failed, which means we fall back to treating text as a paragraph. if (!success) { state = State.PARAGRAPH; - // If parsing of the title part failed, we still have a valid reference that we can add, and we need to - // do it before the source span for this line is added. + // If parsing of the title part failed, we still have a valid reference that we can + // add, and we need to do it before the source span for this line is added. finishReference(); return; } @@ -104,16 +110,20 @@ State getState() { } List removeLines(int lines) { - var removedSpans = Collections.unmodifiableList(new ArrayList<>( - sourceSpans.subList(Math.max(sourceSpans.size() - lines, 0), sourceSpans.size()))); + var removedSpans = + Collections.unmodifiableList( + new ArrayList<>( + sourceSpans.subList( + Math.max(sourceSpans.size() - lines, 0), + sourceSpans.size()))); removeLast(lines, paragraphLines); removeLast(lines, sourceSpans); return removedSpans; } private boolean startDefinition(Scanner scanner) { - // Finish any outstanding references now. We don't do this earlier because we need addSourceSpan to have been - // called before we do it. + // Finish any outstanding references now. We don't do this earlier because we need + // addSourceSpan to have been called before we do it. finishReference(); scanner.whitespace(); @@ -175,14 +185,15 @@ private boolean destination(Scanner scanner) { } String rawDestination = scanner.getSource(start, scanner.position()).getContent(); - destination = rawDestination.startsWith("<") ? - rawDestination.substring(1, rawDestination.length() - 1) : - rawDestination; + destination = + rawDestination.startsWith("<") + ? rawDestination.substring(1, rawDestination.length() - 1) + : rawDestination; int whitespace = scanner.whitespace(); if (!scanner.hasNext()) { - // Destination was at end of line, so this is a valid reference for sure (and maybe a title). - // If not at end of line, wait for title to be valid first. + // Destination was at end of line, so this is a valid reference for sure (and maybe a + // title). If not at end of line, wait for title to be valid first. referenceValid = true; paragraphLines.clear(); } else if (whitespace == 0) { @@ -238,7 +249,8 @@ private boolean title(Scanner scanner) { title.append(scanner.getSource(start, scanner.position()).getContent()); if (!scanner.hasNext()) { - // Title ran until the end of line, so continue on next line (until we find the delimiter) + // Title ran until the end of line, so continue on next line (until we find the + // delimiter) title.append('\n'); return true; } diff --git a/commonmark/src/main/java/org/commonmark/internal/ListBlockParser.java b/commonmark/src/main/java/org/commonmark/internal/ListBlockParser.java index fbf034757..f160b10ff 100644 --- a/commonmark/src/main/java/org/commonmark/internal/ListBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/ListBlockParser.java @@ -1,11 +1,10 @@ package org.commonmark.internal; +import java.util.Objects; import org.commonmark.internal.util.Parsing; import org.commonmark.node.*; import org.commonmark.parser.block.*; -import java.util.Objects; - public class ListBlockParser extends AbstractBlockParser { private final ListBlock block; @@ -25,10 +24,11 @@ public boolean isContainer() { @Override public boolean canContain(Block childBlock) { if (childBlock instanceof ListItem) { - // Another list item is added to this list block. If the previous line was blank, that means this list block - // is "loose" (not tight). + // Another list item is added to this list block. If the previous line was blank, that + // means this list block is "loose" (not tight). // - // spec: A list is loose if any of its constituent list items are separated by blank lines + // spec: A list is loose if any of its constituent list items are separated by blank + // lines if (hadBlankLine && linesAfterBlank == 1) { block.setTight(false); hadBlankLine = false; @@ -52,16 +52,18 @@ public BlockContinue tryContinue(ParserState state) { } else if (hadBlankLine) { linesAfterBlank++; } - // List blocks themselves don't have any markers, only list items. So try to stay in the list. - // If there is a block start other than list item, canContain makes sure that this list is closed. + // List blocks themselves don't have any markers, only list items. So try to stay in the + // list. If there is a block start other than list item, canContain makes sure that this + // list is closed. return BlockContinue.atIndex(state.getIndex()); } - /** - * Parse a list marker and return data on the marker or null. - */ - private static ListData parseList(CharSequence line, final int markerIndex, final int markerColumn, - final boolean inParagraph) { + /** Parse a list marker and return data on the marker or null. */ + private static ListData parseList( + CharSequence line, + final int markerIndex, + final int markerColumn, + final boolean inParagraph) { ListMarkerData listMarker = parseListMarker(line, markerIndex); if (listMarker == null) { return null; @@ -92,7 +94,8 @@ 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).getMarkerStartNumber() != 1) { + if (listBlock instanceof OrderedList + && ((OrderedList) listBlock).getMarkerStartNumber() != 1) { return null; } // Empty list item can not interrupt a paragraph. @@ -128,8 +131,8 @@ private static ListMarkerData parseListMarker(CharSequence line, int index) { } } - // spec: An ordered list marker is a sequence of 1-9 arabic digits (0-9), followed by either a `.` character or a - // `)` character. + // spec: An ordered list marker is a sequence of 1-9 arabic digits (0-9), followed by either a + // `.` character or a `)` character. private static ListMarkerData parseOrderedList(CharSequence line, int index) { int digits = 0; int length = line.length(); @@ -184,15 +187,15 @@ private static boolean isSpaceTabOrEnd(CharSequence line, int index) { } /** - * Returns true if the two list items are of the same type, - * with the same delimiter and bullet character. This is used - * in agglomerating list items into lists. + * Returns true if the two list items are of the same type, with the same delimiter and bullet + * character. This is used in agglomerating list items into lists. */ private static boolean listsMatch(ListBlock a, ListBlock b) { if (a instanceof BulletList && b instanceof BulletList) { return Objects.equals(((BulletList) a).getMarker(), ((BulletList) b).getMarker()); } else if (a instanceof OrderedList && b instanceof OrderedList) { - return Objects.equals(((OrderedList) a).getMarkerDelimiter(), ((OrderedList) b).getMarkerDelimiter()); + return Objects.equals( + ((OrderedList) a).getMarkerDelimiter(), ((OrderedList) b).getMarkerDelimiter()); } return false; } @@ -209,20 +212,23 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar int markerIndex = state.getNextNonSpaceIndex(); int markerColumn = state.getColumn() + state.getIndent(); boolean inParagraph = !matchedBlockParser.getParagraphLines().isEmpty(); - ListData listData = parseList(state.getLine().getContent(), markerIndex, markerColumn, inParagraph); + ListData listData = + parseList(state.getLine().getContent(), markerIndex, markerColumn, inParagraph); if (listData == null) { return BlockStart.none(); } int newColumn = listData.contentColumn; - ListItemParser listItemParser = new ListItemParser(state.getIndent(), newColumn - state.getColumn()); + ListItemParser listItemParser = + new ListItemParser(state.getIndent(), newColumn - state.getColumn()); // prepend the list block if needed - if (!(matched instanceof ListBlockParser) || - !(listsMatch((ListBlock) matched.getBlock(), listData.listBlock))) { + if (!(matched instanceof ListBlockParser) + || !(listsMatch((ListBlock) matched.getBlock(), listData.listBlock))) { ListBlockParser listBlockParser = new ListBlockParser(listData.listBlock); - // We start out with assuming a list is tight. If we find a blank line, we set it to loose later. + // We start out with assuming a list is tight. If we find a blank line, we set it to + // loose later. listData.listBlock.setTight(true); return BlockStart.of(listBlockParser, listItemParser).atColumn(newColumn); diff --git a/commonmark/src/main/java/org/commonmark/internal/ListItemParser.java b/commonmark/src/main/java/org/commonmark/internal/ListItemParser.java index 49722dff2..61549cc4c 100644 --- a/commonmark/src/main/java/org/commonmark/internal/ListItemParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/ListItemParser.java @@ -13,8 +13,8 @@ public class ListItemParser extends AbstractBlockParser { private final ListItem block = new ListItem(); /** - * Minimum number of columns that the content has to be indented (relative to the containing block) to be part of - * this list item. + * Minimum number of columns that the content has to be indented (relative to the containing + * block) to be part of this list item. */ private int contentIndent; @@ -36,8 +36,8 @@ public boolean canContain(Block childBlock) { if (hadBlankLine) { // We saw a blank line in this list item, that means the list block is loose. // - // spec: if any of its constituent list items directly contain two block-level elements with a blank line - // between them + // spec: if any of its constituent list items directly contain two block-level elements + // with a blank line between them Block parent = block.getParent(); if (parent instanceof ListBlock) { ((ListBlock) parent).setTight(false); @@ -59,7 +59,8 @@ public BlockContinue tryContinue(ParserState state) { return BlockContinue.none(); } else { Block activeBlock = state.getActiveBlockParser().getBlock(); - // If the active block is a code block, blank lines in it should not affect if the list is tight. + // If the active block is a code block, blank lines in it should not affect if the + // list is tight. hadBlankLine = activeBlock instanceof Paragraph || activeBlock instanceof ListItem; return BlockContinue.atIndex(state.getNextNonSpaceIndex()); } diff --git a/commonmark/src/main/java/org/commonmark/internal/ParagraphParser.java b/commonmark/src/main/java/org/commonmark/internal/ParagraphParser.java index 27eb1e647..47f69b34a 100644 --- a/commonmark/src/main/java/org/commonmark/internal/ParagraphParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/ParagraphParser.java @@ -1,5 +1,6 @@ package org.commonmark.internal; +import java.util.List; import org.commonmark.node.*; import org.commonmark.parser.InlineParser; import org.commonmark.parser.SourceLine; @@ -8,12 +9,11 @@ import org.commonmark.parser.block.BlockContinue; import org.commonmark.parser.block.ParserState; -import java.util.List; - public class ParagraphParser extends AbstractBlockParser { private final Paragraph block = new Paragraph(); - private final LinkReferenceDefinitionParser linkReferenceDefinitionParser = new LinkReferenceDefinitionParser(); + private final LinkReferenceDefinitionParser linkReferenceDefinitionParser = + new LinkReferenceDefinitionParser(); @Override public boolean canHaveLazyContinuationLines() { diff --git a/commonmark/src/main/java/org/commonmark/internal/StaggeredDelimiterProcessor.java b/commonmark/src/main/java/org/commonmark/internal/StaggeredDelimiterProcessor.java index 2836e346a..98354b8e4 100644 --- a/commonmark/src/main/java/org/commonmark/internal/StaggeredDelimiterProcessor.java +++ b/commonmark/src/main/java/org/commonmark/internal/StaggeredDelimiterProcessor.java @@ -1,28 +1,28 @@ package org.commonmark.internal; -import org.commonmark.parser.delimiter.DelimiterProcessor; -import org.commonmark.parser.delimiter.DelimiterRun; - import java.util.LinkedList; import java.util.ListIterator; +import org.commonmark.parser.delimiter.DelimiterProcessor; +import org.commonmark.parser.delimiter.DelimiterRun; /** - * An implementation of DelimiterProcessor that dispatches all calls to two or more other DelimiterProcessors - * depending on the length of the delimiter run. All child DelimiterProcessors must have different minimum - * lengths. A given delimiter run is dispatched to the child with the largest acceptable minimum length. If no - * child is applicable, the one with the largest minimum length is chosen. + * An implementation of DelimiterProcessor that dispatches all calls to two or more other + * DelimiterProcessors depending on the length of the delimiter run. All child DelimiterProcessors + * must have different minimum lengths. A given delimiter run is dispatched to the child with the + * largest acceptable minimum length. If no child is applicable, the one with the largest minimum + * length is chosen. */ class StaggeredDelimiterProcessor implements DelimiterProcessor { private final char delim; private int minLength = 0; - private LinkedList processors = new LinkedList<>(); // in reverse getMinLength order + private LinkedList processors = + new LinkedList<>(); // in reverse getMinLength order StaggeredDelimiterProcessor(char delim) { this.delim = delim; } - @Override public char getOpeningCharacter() { return delim; @@ -51,7 +51,15 @@ void add(DelimiterProcessor dp) { added = true; break; } else if (len == pLen) { - throw new IllegalArgumentException("Cannot add two delimiter processors for char '" + delim + "' and minimum length " + len + "; conflicting processors: " + p + ", " + dp); + throw new IllegalArgumentException( + "Cannot add two delimiter processors for char '" + + delim + + "' and minimum length " + + len + + "; conflicting processors: " + + p + + ", " + + dp); } } if (!added) { diff --git a/commonmark/src/main/java/org/commonmark/internal/ThematicBreakParser.java b/commonmark/src/main/java/org/commonmark/internal/ThematicBreakParser.java index 0f0613221..366a84254 100644 --- a/commonmark/src/main/java/org/commonmark/internal/ThematicBreakParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/ThematicBreakParser.java @@ -41,8 +41,9 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar } } - // spec: A line consisting of 0-3 spaces of indentation, followed by a sequence of three or more matching -, _, or * - // characters, each followed optionally by any number of spaces, forms a thematic break. + // spec: A line consisting of 0-3 spaces of indentation, followed by a sequence of three or more + // matching -, _, or * characters, each followed optionally by any number of spaces, forms a + // thematic break. private static boolean isThematicBreak(CharSequence line, int index) { int dashes = 0; int underscores = 0; @@ -68,8 +69,8 @@ private static boolean isThematicBreak(CharSequence line, int index) { } } - return ((dashes >= 3 && underscores == 0 && asterisks == 0) || - (underscores >= 3 && dashes == 0 && asterisks == 0) || - (asterisks >= 3 && dashes == 0 && underscores == 0)); + return ((dashes >= 3 && underscores == 0 && asterisks == 0) + || (underscores >= 3 && dashes == 0 && asterisks == 0) + || (asterisks >= 3 && dashes == 0 && underscores == 0)); } } diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/AutolinkInlineParser.java b/commonmark/src/main/java/org/commonmark/internal/inline/AutolinkInlineParser.java index a18966e54..4e3e131fe 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/AutolinkInlineParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/AutolinkInlineParser.java @@ -1,23 +1,21 @@ package org.commonmark.internal.inline; +import java.util.Set; +import java.util.regex.Pattern; import org.commonmark.node.Link; import org.commonmark.node.Text; import org.commonmark.parser.SourceLines; import org.commonmark.parser.beta.*; -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Attempt to parse an autolink (URL or email in pointy brackets). - */ +/** Attempt to parse an autolink (URL or email in pointy brackets). */ public class AutolinkInlineParser implements InlineContentParser { - private static final Pattern URI = Pattern - .compile("^[a-zA-Z][a-zA-Z0-9.+-]{1,31}:[^<>\u0000-\u0020]*$"); + private static final Pattern URI = + Pattern.compile("^[a-zA-Z][a-zA-Z0-9.+-]{1,31}:[^<>\u0000-\u0020]*$"); - private static final Pattern EMAIL = Pattern - .compile("^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$"); + private static final Pattern EMAIL = + Pattern.compile( + "^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$"); @Override public ParsedInline tryParse(InlineParserState inlineParserState) { diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/BackslashInlineParser.java b/commonmark/src/main/java/org/commonmark/internal/inline/BackslashInlineParser.java index 7baeed4de..c4e8f3aff 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/BackslashInlineParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/BackslashInlineParser.java @@ -1,16 +1,16 @@ package org.commonmark.internal.inline; +import java.util.Set; +import java.util.regex.Pattern; import org.commonmark.internal.util.Escaping; import org.commonmark.node.HardLineBreak; import org.commonmark.node.Text; import org.commonmark.parser.beta.*; -import java.util.Set; -import java.util.regex.Pattern; - /** - * Parse a backslash-escaped special character, adding either the escaped character, a hard line break - * (if the backslash is followed by a newline), or a literal backslash to the block's children. + * Parse a backslash-escaped special character, adding either the escaped character, a hard line + * break (if the backslash is followed by a newline), or a literal backslash to the block's + * children. */ public class BackslashInlineParser implements InlineContentParser { diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/BackticksInlineParser.java b/commonmark/src/main/java/org/commonmark/internal/inline/BackticksInlineParser.java index b8e8984e8..f636d31b4 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/BackticksInlineParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/BackticksInlineParser.java @@ -1,15 +1,15 @@ package org.commonmark.internal.inline; +import java.util.Set; import org.commonmark.node.Code; import org.commonmark.node.Text; import org.commonmark.parser.SourceLines; import org.commonmark.parser.beta.*; import org.commonmark.text.Characters; -import java.util.Set; - /** - * Attempt to parse backticks, returning either a backtick code span or a literal sequence of backticks. + * Attempt to parse backticks, returning either a backtick code span or a literal sequence of + * backticks. */ public class BackticksInlineParser implements InlineContentParser { @@ -29,12 +29,13 @@ public ParsedInline tryParse(InlineParserState inlineParserState) { String content = scanner.getSource(afterOpening, beforeClosing).getContent(); content = content.replace('\n', ' '); - // spec: If the resulting string both begins and ends with a space character, but does not consist - // entirely of space characters, a single space character is removed from the front and back. - if (content.length() >= 3 && - content.charAt(0) == ' ' && - content.charAt(content.length() - 1) == ' ' && - Characters.hasNonSpace(content)) { + // spec: If the resulting string both begins and ends with a space character, but + // does not consist entirely of space characters, a single space character is + // removed from the front and back. + if (content.length() >= 3 + && content.charAt(0) == ' ' + && content.charAt(content.length() - 1) == ' ' + && Characters.hasNonSpace(content)) { content = content.substring(1, content.length() - 1); } diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/CoreLinkProcessor.java b/commonmark/src/main/java/org/commonmark/internal/inline/CoreLinkProcessor.java index 528750aba..3c2efe09b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/CoreLinkProcessor.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/CoreLinkProcessor.java @@ -28,9 +28,11 @@ public LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContex return LinkResult.none(); } - private static LinkResult process(LinkInfo linkInfo, Scanner scanner, String destination, String title) { + private static LinkResult process( + LinkInfo linkInfo, Scanner scanner, String destination, String title) { if (linkInfo.marker() != null && linkInfo.marker().getLiteral().equals("!")) { - return LinkResult.wrapTextIn(new Image(destination, title), scanner.position()).includeMarker(); + return LinkResult.wrapTextIn(new Image(destination, title), scanner.position()) + .includeMarker(); } return LinkResult.wrapTextIn(new Link(destination, title), scanner.position()); } diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java b/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java index 493e4299c..9fbedf897 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/EmphasisDelimiterProcessor.java @@ -30,9 +30,9 @@ public int getMinLength() { @Override public int process(DelimiterRun openingRun, DelimiterRun closingRun) { // "multiple of 3" rule for internal delimiter runs - if ((openingRun.canClose() || closingRun.canOpen()) && - closingRun.originalLength() % 3 != 0 && - (openingRun.originalLength() + closingRun.originalLength()) % 3 == 0) { + if ((openingRun.canClose() || closingRun.canOpen()) + && closingRun.originalLength() % 3 != 0 + && (openingRun.originalLength() + closingRun.originalLength()) % 3 == 0) { return 0; } diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/EntityInlineParser.java b/commonmark/src/main/java/org/commonmark/internal/inline/EntityInlineParser.java index c24e60747..e3ed0c08b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/EntityInlineParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/EntityInlineParser.java @@ -1,21 +1,21 @@ package org.commonmark.internal.inline; +import java.util.Set; import org.commonmark.internal.util.Html5Entities; import org.commonmark.node.Text; import org.commonmark.parser.beta.*; import org.commonmark.text.AsciiMatcher; -import java.util.Set; - -/** - * Attempts to parse an HTML entity or numeric character reference. - */ +/** Attempts to parse an HTML entity or numeric character reference. */ public class EntityInlineParser implements InlineContentParser { - private static final AsciiMatcher hex = AsciiMatcher.builder().range('0', '9').range('A', 'F').range('a', 'f').build(); + private static final AsciiMatcher hex = + AsciiMatcher.builder().range('0', '9').range('A', 'F').range('a', 'f').build(); private static final AsciiMatcher dec = AsciiMatcher.builder().range('0', '9').build(); - private static final AsciiMatcher entityStart = AsciiMatcher.builder().range('A', 'Z').range('a', 'z').build(); - private static final AsciiMatcher entityContinue = entityStart.newBuilder().range('0', '9').build(); + private static final AsciiMatcher entityStart = + AsciiMatcher.builder().range('A', 'Z').range('a', 'z').build(); + private static final AsciiMatcher entityContinue = + entityStart.newBuilder().range('0', '9').build(); @Override public ParsedInline tryParse(InlineParserState inlineParserState) { diff --git a/commonmark/src/main/java/org/commonmark/internal/inline/HtmlInlineParser.java b/commonmark/src/main/java/org/commonmark/internal/inline/HtmlInlineParser.java index a48ea5022..b359f732b 100644 --- a/commonmark/src/main/java/org/commonmark/internal/inline/HtmlInlineParser.java +++ b/commonmark/src/main/java/org/commonmark/internal/inline/HtmlInlineParser.java @@ -1,31 +1,46 @@ package org.commonmark.internal.inline; +import java.util.Set; import org.commonmark.node.HtmlInline; import org.commonmark.parser.beta.*; import org.commonmark.text.AsciiMatcher; -import java.util.Set; - -/** - * Attempt to parse inline HTML. - */ +/** Attempt to parse inline HTML. */ public class HtmlInlineParser implements InlineContentParser { - private static final AsciiMatcher asciiLetter = AsciiMatcher.builder().range('A', 'Z').range('a', 'z').build(); + private static final AsciiMatcher asciiLetter = + AsciiMatcher.builder().range('A', 'Z').range('a', 'z').build(); - // spec: A tag name consists of an ASCII letter followed by zero or more ASCII letters, digits, or hyphens (-). + // spec: A tag name consists of an ASCII letter followed by zero or more ASCII letters, digits, + // or hyphens (-). private static final AsciiMatcher tagNameStart = asciiLetter; - private static final AsciiMatcher tagNameContinue = tagNameStart.newBuilder().range('0', '9').c('-').build(); + private static final AsciiMatcher tagNameContinue = + tagNameStart.newBuilder().range('0', '9').c('-').build(); - // spec: An attribute name consists of an ASCII letter, _, or :, followed by zero or more ASCII letters, digits, + // spec: An attribute name consists of an ASCII letter, _, or :, followed by zero or more ASCII + // letters, digits, // _, ., :, or -. (Note: This is the XML specification restricted to ASCII. HTML5 is laxer.) - private static final AsciiMatcher attributeStart = asciiLetter.newBuilder().c('_').c(':').build(); - private static final AsciiMatcher attributeContinue = attributeStart.newBuilder().range('0', '9').c('.').c('-').build(); - // spec: An unquoted attribute value is a nonempty string of characters not including whitespace, ", ', =, <, >, or `. - private static final AsciiMatcher attributeValueEnd = AsciiMatcher.builder() - .c(' ').c('\t').c('\n').c('\u000B').c('\f').c('\r') - .c('"').c('\'').c('=').c('<').c('>').c('`') - .build(); + private static final AsciiMatcher attributeStart = + asciiLetter.newBuilder().c('_').c(':').build(); + private static final AsciiMatcher attributeContinue = + attributeStart.newBuilder().range('0', '9').c('.').c('-').build(); + // spec: An unquoted attribute value is a nonempty string of characters not including + // whitespace, ", ', =, <, >, or `. + private static final AsciiMatcher attributeValueEnd = + AsciiMatcher.builder() + .c(' ') + .c('\t') + .c('\n') + .c('\u000B') + .c('\f') + .c('\r') + .c('"') + .c('\'') + .c('=') + .c('<') + .c('>') + .c('`') + .build(); @Override public ParsedInline tryParse(InlineParserState inlineParserState) { @@ -77,16 +92,17 @@ private static ParsedInline htmlInline(Position start, Scanner scanner) { } private static boolean tryOpenTag(Scanner scanner) { - // spec: An open tag consists of a < character, a tag name, zero or more attributes, optional whitespace, - // an optional / character, and a > character. + // spec: An open tag consists of a < character, a tag name, zero or more attributes, + // optional whitespace, an optional / character, and a > character. scanner.next(); scanner.match(tagNameContinue); boolean whitespace = scanner.whitespace() >= 1; - // spec: An attribute consists of whitespace, an attribute name, and an optional attribute value specification. + // spec: An attribute consists of whitespace, an attribute name, and an optional attribute + // value specification. while (whitespace && scanner.match(attributeStart) >= 1) { scanner.match(attributeContinue); - // spec: An attribute value specification consists of optional whitespace, a = character, - // optional whitespace, and an attribute value. + // spec: An attribute value specification consists of optional whitespace, a = + // character, optional whitespace, and an attribute value. whitespace = scanner.whitespace() >= 1; if (scanner.next('=')) { scanner.whitespace(); @@ -119,7 +135,8 @@ private static boolean tryOpenTag(Scanner scanner) { } private static boolean tryClosingTag(Scanner scanner) { - // spec: A closing tag consists of the string . + // spec: A closing tag consists of the string . scanner.next(); if (scanner.match(tagNameStart) >= 1) { scanner.match(tagNameContinue); @@ -130,8 +147,8 @@ private static boolean tryClosingTag(Scanner scanner) { } private static boolean tryProcessingInstruction(Scanner scanner) { - // spec: A processing instruction consists of the string , - // and the string ?>. + // spec: A processing instruction consists of the string , and the string ?>. scanner.next(); while (scanner.find('?') > 0) { scanner.next(); @@ -144,8 +161,8 @@ private static boolean tryProcessingInstruction(Scanner scanner) { private static boolean tryComment(Scanner scanner) { // spec: An [HTML comment](@) consists of ``, ``, or ``, and `-->` (see the - // [HTML spec](https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state)). + // characters not including the string `-->`, and `-->` (see the [HTML + // spec](https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state)). // Skip first `-` scanner.next(); @@ -169,8 +186,8 @@ private static boolean tryComment(Scanner scanner) { } private static boolean tryCdata(Scanner scanner) { - // spec: A CDATA section consists of the string , - // and the string ]]>. + // spec: A CDATA section consists of the string , and the string ]]>. // Skip `[` scanner.next(); @@ -189,8 +206,8 @@ private static boolean tryCdata(Scanner scanner) { } private static boolean tryDeclaration(Scanner scanner) { - // spec: A declaration consists of the string , and the character >. + // spec: A declaration consists of the string , and the character >. scanner.match(asciiLetter); if (scanner.whitespace() <= 0) { return false; diff --git a/commonmark/src/main/java/org/commonmark/internal/renderer/NodeRendererMap.java b/commonmark/src/main/java/org/commonmark/internal/renderer/NodeRendererMap.java index c74f90758..66f779a91 100644 --- a/commonmark/src/main/java/org/commonmark/internal/renderer/NodeRendererMap.java +++ b/commonmark/src/main/java/org/commonmark/internal/renderer/NodeRendererMap.java @@ -1,12 +1,11 @@ package org.commonmark.internal.renderer; -import org.commonmark.node.Node; -import org.commonmark.renderer.NodeRenderer; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.commonmark.node.Node; +import org.commonmark.renderer.NodeRenderer; public class NodeRendererMap { @@ -14,7 +13,8 @@ public class NodeRendererMap { private final Map, NodeRenderer> renderers = new HashMap<>(32); /** - * Set the renderer for each {@link NodeRenderer#getNodeTypes()}, unless there was already a renderer set (first wins). + * Set the renderer for each {@link NodeRenderer#getNodeTypes()}, unless there was already a + * renderer set (first wins). */ public void add(NodeRenderer nodeRenderer) { nodeRenderers.add(nodeRenderer); diff --git a/commonmark/src/main/java/org/commonmark/internal/util/Escaping.java b/commonmark/src/main/java/org/commonmark/internal/util/Escaping.java index caf802a43..a44110500 100644 --- a/commonmark/src/main/java/org/commonmark/internal/util/Escaping.java +++ b/commonmark/src/main/java/org/commonmark/internal/util/Escaping.java @@ -16,42 +16,47 @@ public class Escaping { private static final Pattern ENTITY_OR_ESCAPED_CHAR = Pattern.compile("\\\\" + ESCAPABLE + '|' + ENTITY, Pattern.CASE_INSENSITIVE); - // From RFC 3986 (see "reserved", "unreserved") except don't escape '[' or ']' to be compatible with JS encodeURI + // From RFC 3986 (see "reserved", "unreserved") except don't escape '[' or ']' to be compatible + // with JS encodeURI private static final Pattern ESCAPE_IN_URI = Pattern.compile("(%[a-fA-F0-9]{0,2}|[^:/?#@!$&'()*+,;=a-zA-Z0-9\\-._~])"); private static final char[] HEX_DIGITS = - new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + new char[] { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; private static final Pattern WHITESPACE = Pattern.compile("[ \t\r\n]+"); - private static final Replacer UNESCAPE_REPLACER = (input, sb) -> { - if (input.charAt(0) == '\\') { - sb.append(input, 1, input.length()); - } else { - sb.append(Html5Entities.entityToString(input)); - } - }; - - private static final Replacer URI_REPLACER = (input, sb) -> { - if (input.startsWith("%")) { - if (input.length() == 3) { - // Already percent-encoded, preserve - sb.append(input); - } else { - // %25 is the percent-encoding for % - sb.append("%25"); - sb.append(input, 1, input.length()); - } - } else { - byte[] bytes = input.getBytes(StandardCharsets.UTF_8); - for (byte b : bytes) { - sb.append('%'); - sb.append(HEX_DIGITS[(b >> 4) & 0xF]); - sb.append(HEX_DIGITS[b & 0xF]); - } - } - }; + private static final Replacer UNESCAPE_REPLACER = + (input, sb) -> { + if (input.charAt(0) == '\\') { + sb.append(input, 1, input.length()); + } else { + sb.append(Html5Entities.entityToString(input)); + } + }; + + private static final Replacer URI_REPLACER = + (input, sb) -> { + if (input.startsWith("%")) { + if (input.length() == 3) { + // Already percent-encoded, preserve + sb.append(input); + } else { + // %25 is the percent-encoding for % + sb.append("%25"); + sb.append(input, 1, input.length()); + } + } else { + byte[] bytes = input.getBytes(StandardCharsets.UTF_8); + for (byte b : bytes) { + sb.append('%'); + sb.append(HEX_DIGITS[(b >> 4) & 0xF]); + sb.append(HEX_DIGITS[b & 0xF]); + } + } + }; public static String escapeHtml(String input) { // Avoid building a new string in the majority of cases (nothing to escape) @@ -89,9 +94,7 @@ public static String escapeHtml(String input) { return sb != null ? sb.toString() : input; } - /** - * Replace entities and backslash escapes with literal characters. - */ + /** Replace entities and backslash escapes with literal characters. */ public static String unescapeString(String s) { if (BACKSLASH_OR_AMP.matcher(s).find()) { return replaceAll(ENTITY_OR_ESCAPED_CHAR, s, UNESCAPE_REPLACER); diff --git a/commonmark/src/main/java/org/commonmark/internal/util/Html5Entities.java b/commonmark/src/main/java/org/commonmark/internal/util/Html5Entities.java index d6034ff14..2e92c9be8 100644 --- a/commonmark/src/main/java/org/commonmark/internal/util/Html5Entities.java +++ b/commonmark/src/main/java/org/commonmark/internal/util/Html5Entities.java @@ -51,7 +51,8 @@ private static Map readEntities() { Map entities = new HashMap<>(); InputStream stream = Html5Entities.class.getResourceAsStream(ENTITY_PATH); Charset charset = StandardCharsets.UTF_8; - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, charset))) { + try (BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(stream, charset))) { String line; while ((line = bufferedReader.readLine()) != null) { if (line.isEmpty()) { @@ -63,7 +64,8 @@ private static Map readEntities() { entities.put(key, value); } } catch (IOException e) { - throw new IllegalStateException("Failed reading data for HTML named character references", e); + throw new IllegalStateException( + "Failed reading data for HTML named character references", e); } entities.put("NewLine", "\n"); return entities; diff --git a/commonmark/src/main/java/org/commonmark/internal/util/LineReader.java b/commonmark/src/main/java/org/commonmark/internal/util/LineReader.java index b44098257..a37e93c92 100644 --- a/commonmark/src/main/java/org/commonmark/internal/util/LineReader.java +++ b/commonmark/src/main/java/org/commonmark/internal/util/LineReader.java @@ -5,12 +5,13 @@ import java.io.Reader; /** - * Reads lines from a reader like {@link java.io.BufferedReader} but also returns the line terminators. - *

- * Line terminators can be either a line feed {@code "\n"}, carriage return {@code "\r"}, or a carriage return followed - * by a line feed {@code "\r\n"}. Call {@link #getLineTerminator()} after {@link #readLine()} to obtain the - * corresponding line terminator. If a stream has a line at the end without a terminator, {@link #getLineTerminator()} - * returns {@code null}. + * Reads lines from a reader like {@link java.io.BufferedReader} but also returns the line + * terminators. + * + *

Line terminators can be either a line feed {@code "\n"}, carriage return {@code "\r"}, or a + * carriage return followed by a line feed {@code "\r\n"}. Call {@link #getLineTerminator()} after + * {@link #readLine()} to obtain the corresponding line terminator. If a stream has a line at the + * end without a terminator, {@link #getLineTerminator()} returns {@code null}. */ public class LineReader implements Closeable { @@ -34,7 +35,8 @@ public LineReader(Reader reader) { /** * Read a line of text. * - * @return the line, or {@code null} when the end of the stream has been reached and no more lines can be read + * @return the line, or {@code null} when the end of the stream has been reached and no more + * lines can be read */ public String readLine() throws IOException { StringBuilder sb = null; diff --git a/commonmark/src/main/java/org/commonmark/internal/util/LinkScanner.java b/commonmark/src/main/java/org/commonmark/internal/util/LinkScanner.java index ffed047e5..b8072ad26 100644 --- a/commonmark/src/main/java/org/commonmark/internal/util/LinkScanner.java +++ b/commonmark/src/main/java/org/commonmark/internal/util/LinkScanner.java @@ -5,9 +5,9 @@ public class LinkScanner { /** - * Attempt to scan the contents of a link label (inside the brackets), stopping after the content or returning false. - * The stopped position can bei either the closing {@code ]}, or the end of the line if the label continues on - * the next line. + * Attempt to scan the contents of a link label (inside the brackets), stopping after the + * content or returning false. The stopped position can bei either the closing {@code ]}, or the + * end of the line if the label continues on the next line. */ public static boolean scanLinkLabelContent(Scanner scanner) { while (scanner.hasNext()) { @@ -21,8 +21,8 @@ public static boolean scanLinkLabelContent(Scanner scanner) { case ']': return true; case '[': - // spec: Unescaped square bracket characters are not allowed inside the opening and closing - // square brackets of link labels. + // spec: Unescaped square bracket characters are not allowed inside the opening + // and closing square brackets of link labels. return false; default: scanner.next(); @@ -31,9 +31,7 @@ public static boolean scanLinkLabelContent(Scanner scanner) { return true; } - /** - * Attempt to scan a link destination, stopping after the destination or returning false. - */ + /** Attempt to scan a link destination, stopping after the destination or returning false. */ public static boolean scanLinkDestination(Scanner scanner) { if (!scanner.hasNext()) { return false; @@ -115,9 +113,9 @@ public static boolean scanLinkTitleContent(Scanner scanner, char endDelimiter) { return true; } - // spec: a nonempty sequence of characters that does not start with <, does not include ASCII space or control - // characters, and includes parentheses only if (a) they are backslash-escaped or (b) they are part of a balanced - // pair of unescaped parentheses + // spec: a nonempty sequence of characters that does not start with <, does not include ASCII + // space or control characters, and includes parentheses only if (a) they are backslash-escaped + // or (b) they are part of a balanced pair of unescaped parentheses private static boolean scanLinkDestinationWithBalancedParens(Scanner scanner) { int parens = 0; boolean empty = true; diff --git a/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java b/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java index 7edd635d7..d39112e07 100644 --- a/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java +++ b/commonmark/src/main/java/org/commonmark/node/AbstractVisitor.java @@ -2,9 +2,9 @@ /** * Abstract visitor that visits all children by default. - *

- * Can be used to only process certain nodes. If you override a method and want visiting to descend into children, - * call {@link #visitChildren}. + * + *

Can be used to only process certain nodes. If you override a method and want visiting to + * descend into children, call {@link #visitChildren}. */ public abstract class AbstractVisitor implements Visitor { @@ -131,8 +131,8 @@ public void visit(CustomNode customNode) { protected void visitChildren(Node parent) { Node node = parent.getFirstChild(); while (node != null) { - // A subclass of this visitor might modify the node, resulting in getNext returning a different node or no - // node after visiting it. So get the next node before visiting. + // A subclass of this visitor might modify the node, resulting in getNext returning a + // different node or no node after visiting it. So get the next node before visiting. Node next = node.getNext(); node.accept(this); node = next; diff --git a/commonmark/src/main/java/org/commonmark/node/Block.java b/commonmark/src/main/java/org/commonmark/node/Block.java index 332346b0e..2434aec62 100644 --- a/commonmark/src/main/java/org/commonmark/node/Block.java +++ b/commonmark/src/main/java/org/commonmark/node/Block.java @@ -1,8 +1,6 @@ package org.commonmark.node; -/** - * Block nodes such as paragraphs, list blocks, code blocks etc. - */ +/** Block nodes such as paragraphs, list blocks, code blocks etc. */ public abstract class Block extends Node { @Override @@ -13,7 +11,8 @@ public Block getParent() { @Override protected void setParent(Node parent) { if (!(parent instanceof Block)) { - throw new IllegalArgumentException("Parent of block must also be block (can not be inline)"); + throw new IllegalArgumentException( + "Parent of block must also be block (can not be inline)"); } super.setParent(parent); } diff --git a/commonmark/src/main/java/org/commonmark/node/BlockQuote.java b/commonmark/src/main/java/org/commonmark/node/BlockQuote.java index f68252398..935abaf48 100644 --- a/commonmark/src/main/java/org/commonmark/node/BlockQuote.java +++ b/commonmark/src/main/java/org/commonmark/node/BlockQuote.java @@ -2,11 +2,12 @@ /** * A block quote, e.g.: + * *

  * > Some quoted text
  * 
- *

- * Note that child nodes are themselves blocks, e.g. {@link Paragraph}, {@link ListBlock} etc. + * + *

Note that child nodes are themselves blocks, e.g. {@link Paragraph}, {@link ListBlock} etc. * * @see CommonMark Spec */ diff --git a/commonmark/src/main/java/org/commonmark/node/BulletList.java b/commonmark/src/main/java/org/commonmark/node/BulletList.java index 014f4d3b2..b5826f2c9 100644 --- a/commonmark/src/main/java/org/commonmark/node/BulletList.java +++ b/commonmark/src/main/java/org/commonmark/node/BulletList.java @@ -2,13 +2,14 @@ /** * A bullet list, e.g.: + * *

  * - One
  * - Two
  * - Three
  * 
- *

- * The children are {@link ListItem} blocks, which contain other blocks (or nested lists). + * + *

The children are {@link ListItem} blocks, which contain other blocks (or nested lists). * * @see CommonMark Spec: List items */ @@ -22,7 +23,8 @@ public void accept(Visitor visitor) { } /** - * @return the bullet list marker that was used, e.g. {@code -}, {@code *} or {@code +}, if available, or null otherwise + * @return the bullet list marker that was used, e.g. {@code -}, {@code *} or {@code +}, if + * available, or null otherwise */ public String getMarker() { return marker; diff --git a/commonmark/src/main/java/org/commonmark/node/Code.java b/commonmark/src/main/java/org/commonmark/node/Code.java index 3b79e0c9c..4de2bc337 100644 --- a/commonmark/src/main/java/org/commonmark/node/Code.java +++ b/commonmark/src/main/java/org/commonmark/node/Code.java @@ -2,6 +2,7 @@ /** * Inline code span, e.g.: + * *

  * Some `inline code`
  * 
@@ -12,8 +13,7 @@ public class Code extends Node { private String literal; - public Code() { - } + public Code() {} public Code(String literal) { this.literal = literal; @@ -25,8 +25,8 @@ public void accept(Visitor visitor) { } /** - * @return the literal text in the code span (note that it's not necessarily the raw text between tildes, - * e.g. when spaces are stripped) + * @return the literal text in the code span (note that it's not necessarily the raw text + * between tildes, e.g. when spaces are stripped) */ public String getLiteral() { return literal; diff --git a/commonmark/src/main/java/org/commonmark/node/CustomBlock.java b/commonmark/src/main/java/org/commonmark/node/CustomBlock.java index cad88933a..3a167c057 100644 --- a/commonmark/src/main/java/org/commonmark/node/CustomBlock.java +++ b/commonmark/src/main/java/org/commonmark/node/CustomBlock.java @@ -1,7 +1,8 @@ package org.commonmark.node; /** - * A block that extensions can subclass to define custom blocks (not part of the core specification). + * A block that extensions can subclass to define custom blocks (not part of the core + * specification). */ public abstract class CustomBlock extends Block { diff --git a/commonmark/src/main/java/org/commonmark/node/DefinitionMap.java b/commonmark/src/main/java/org/commonmark/node/DefinitionMap.java index 59cb88274..09f2ddf01 100644 --- a/commonmark/src/main/java/org/commonmark/node/DefinitionMap.java +++ b/commonmark/src/main/java/org/commonmark/node/DefinitionMap.java @@ -1,15 +1,14 @@ package org.commonmark.node; -import org.commonmark.internal.util.Escaping; - import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import org.commonmark.internal.util.Escaping; /** - * A map that can be used to store and look up reference definitions by a label. The labels are case-insensitive and - * normalized, the same way as for {@link LinkReferenceDefinition} nodes. + * A map that can be used to store and look up reference definitions by a label. The labels are + * case-insensitive and normalized, the same way as for {@link LinkReferenceDefinition} nodes. * * @param the type of value */ @@ -35,10 +34,10 @@ public void addAll(DefinitionMap that) { } /** - * Store a new definition unless one is already in the map. If there is no definition for that label yet, return null. - * Otherwise, return the existing definition. - *

- * The label is normalized by the definition map before storing. + * Store a new definition unless one is already in the map. If there is no definition for that + * label yet, return null. Otherwise, return the existing definition. + * + *

The label is normalized by the definition map before storing. */ public D putIfAbsent(String label, D definition) { String normalizedLabel = Escaping.normalizeLabelContent(label); diff --git a/commonmark/src/main/java/org/commonmark/node/Delimited.java b/commonmark/src/main/java/org/commonmark/node/Delimited.java index ef02c84ad..b6f95b1a6 100644 --- a/commonmark/src/main/java/org/commonmark/node/Delimited.java +++ b/commonmark/src/main/java/org/commonmark/node/Delimited.java @@ -1,8 +1,6 @@ package org.commonmark.node; -/** - * A node that uses delimiters in the source form (e.g. *bold*). - */ +/** A node that uses delimiters in the source form (e.g. *bold*). */ public interface Delimited { /** diff --git a/commonmark/src/main/java/org/commonmark/node/Document.java b/commonmark/src/main/java/org/commonmark/node/Document.java index b4968c206..b5ff45f6e 100644 --- a/commonmark/src/main/java/org/commonmark/node/Document.java +++ b/commonmark/src/main/java/org/commonmark/node/Document.java @@ -1,8 +1,6 @@ package org.commonmark.node; -/** - * The root block of a document, containing the top-level blocks. - */ +/** The root block of a document, containing the top-level blocks. */ public class Document extends Block { @Override diff --git a/commonmark/src/main/java/org/commonmark/node/Emphasis.java b/commonmark/src/main/java/org/commonmark/node/Emphasis.java index 5efc8c327..57e819a91 100644 --- a/commonmark/src/main/java/org/commonmark/node/Emphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/Emphasis.java @@ -2,18 +2,19 @@ /** * Emphasis, e.g.: + * *

  * Some *emphasis* or _emphasis_
  * 
* - * @see CommonMark Spec: Emphasis and strong emphasis + * @see CommonMark Spec: + * Emphasis and strong emphasis */ public class Emphasis extends Node implements Delimited { private String delimiter; - public Emphasis() { - } + public Emphasis() {} public Emphasis(String delimiter) { this.delimiter = delimiter; diff --git a/commonmark/src/main/java/org/commonmark/node/FencedCodeBlock.java b/commonmark/src/main/java/org/commonmark/node/FencedCodeBlock.java index 0e279a470..22922cf33 100644 --- a/commonmark/src/main/java/org/commonmark/node/FencedCodeBlock.java +++ b/commonmark/src/main/java/org/commonmark/node/FencedCodeBlock.java @@ -2,12 +2,14 @@ /** * A fenced code block, e.g.: + * *
  * ```
  * foo
  * bar
  * ```
  * 
+ * *

* * @see CommonMark Spec @@ -28,7 +30,8 @@ public void accept(Visitor visitor) { } /** - * @return the fence character that was used, e.g. {@code `} or {@code ~}, if available, or null otherwise + * @return the fence character that was used, e.g. {@code `} or {@code ~}, if available, or null + * otherwise */ public String getFenceCharacter() { return fenceCharacter; @@ -39,8 +42,8 @@ public void setFenceCharacter(String fenceCharacter) { } /** - * @return the length of the opening fence (how many of {{@link #getFenceCharacter()}} were used to start the code - * block) if available, or null otherwise + * @return the length of the opening fence (how many of {{@link #getFenceCharacter()}} were used + * to start the code block) if available, or null otherwise */ public Integer getOpeningFenceLength() { return openingFenceLength; @@ -55,8 +58,8 @@ public void setOpeningFenceLength(Integer openingFenceLength) { } /** - * @return the length of the closing fence (how many of {@link #getFenceCharacter()} were used to end the code - * block) if available, or null otherwise + * @return the length of the closing fence (how many of {@link #getFenceCharacter()} were used + * to end the code block) if available, or null otherwise */ public Integer getClosingFenceLength() { return closingFenceLength; @@ -102,7 +105,9 @@ public void setLiteral(String literal) { */ @Deprecated public char getFenceChar() { - return fenceCharacter != null && !fenceCharacter.isEmpty() ? fenceCharacter.charAt(0) : '\0'; + return fenceCharacter != null && !fenceCharacter.isEmpty() + ? fenceCharacter.charAt(0) + : '\0'; } /** @@ -132,7 +137,8 @@ public void setFenceLength(int fenceLength) { private static void checkFenceLengths(Integer openingFenceLength, Integer closingFenceLength) { if (openingFenceLength != null && closingFenceLength != null) { if (closingFenceLength < openingFenceLength) { - throw new IllegalArgumentException("fence lengths required to be: closingFenceLength >= openingFenceLength"); + throw new IllegalArgumentException( + "fence lengths required to be: closingFenceLength >= openingFenceLength"); } } } diff --git a/commonmark/src/main/java/org/commonmark/node/HardLineBreak.java b/commonmark/src/main/java/org/commonmark/node/HardLineBreak.java index 28874ec01..9d1c059b9 100644 --- a/commonmark/src/main/java/org/commonmark/node/HardLineBreak.java +++ b/commonmark/src/main/java/org/commonmark/node/HardLineBreak.java @@ -2,10 +2,12 @@ /** * A hard line break, e.g.: + * *

  * line\
  * break
  * 
+ * *

* * @see CommonMark Spec diff --git a/commonmark/src/main/java/org/commonmark/node/Heading.java b/commonmark/src/main/java/org/commonmark/node/Heading.java index 5369d8739..92d275761 100644 --- a/commonmark/src/main/java/org/commonmark/node/Heading.java +++ b/commonmark/src/main/java/org/commonmark/node/Heading.java @@ -2,6 +2,7 @@ /** * A heading, e.g.: + * *

  * First heading
  * =============
@@ -10,7 +11,8 @@
  * 
* * @see CommonMark Spec: ATX headings - * @see CommonMark Spec: Setext headings + * @see CommonMark Spec: Setext + * headings */ public class Heading extends Block { diff --git a/commonmark/src/main/java/org/commonmark/node/Image.java b/commonmark/src/main/java/org/commonmark/node/Image.java index 1b31f6020..62d71d88a 100644 --- a/commonmark/src/main/java/org/commonmark/node/Image.java +++ b/commonmark/src/main/java/org/commonmark/node/Image.java @@ -2,6 +2,7 @@ /** * An image, e.g.: + * *
  * ![foo](/url "title")
  * 
@@ -13,8 +14,7 @@ public class Image extends Node { private String destination; private String title; - public Image() { - } + public Image() {} public Image(String destination, String title) { this.destination = destination; diff --git a/commonmark/src/main/java/org/commonmark/node/IndentedCodeBlock.java b/commonmark/src/main/java/org/commonmark/node/IndentedCodeBlock.java index 97642b7f3..25d01c29e 100644 --- a/commonmark/src/main/java/org/commonmark/node/IndentedCodeBlock.java +++ b/commonmark/src/main/java/org/commonmark/node/IndentedCodeBlock.java @@ -2,12 +2,14 @@ /** * An indented code block, e.g.: + * *

  * Code follows:
  *
  *     foo
  *     bar
  * 
+ * *

* * @see CommonMark Spec diff --git a/commonmark/src/main/java/org/commonmark/node/Link.java b/commonmark/src/main/java/org/commonmark/node/Link.java index 4edc7f676..f4390a151 100644 --- a/commonmark/src/main/java/org/commonmark/node/Link.java +++ b/commonmark/src/main/java/org/commonmark/node/Link.java @@ -2,21 +2,24 @@ /** * A link with a destination and an optional title; the link text is in child nodes. - *

- * Example for an inline link in a CommonMark document: + * + *

Example for an inline link in a CommonMark document: + * *


  * [link](/uri "title")
  * 
- *

- * The corresponding Link node would look like this: + * + *

The corresponding Link node would look like this: + * *

    - *
  • {@link #getDestination()} returns {@code "/uri"} - *
  • {@link #getTitle()} returns {@code "title"} - *
  • A {@link Text} child node with {@link Text#getLiteral() getLiteral} that returns {@code "link"}
  • + *
  • {@link #getDestination()} returns {@code "/uri"} + *
  • {@link #getTitle()} returns {@code "title"} + *
  • A {@link Text} child node with {@link Text#getLiteral() getLiteral} that returns {@code + * "link"} *
- *

- * Note that the text in the link can contain inline formatting, so it could also contain an {@link Image} or - * {@link Emphasis}, etc. + * + *

Note that the text in the link can contain inline formatting, so it could also contain an + * {@link Image} or {@link Emphasis}, etc. * * @see CommonMark Spec */ @@ -25,8 +28,7 @@ public class Link extends Node { private String destination; private String title; - public Link() { - } + public Link() {} public Link(String destination, String title) { this.destination = destination; diff --git a/commonmark/src/main/java/org/commonmark/node/LinkReferenceDefinition.java b/commonmark/src/main/java/org/commonmark/node/LinkReferenceDefinition.java index b866781f0..54321cb63 100644 --- a/commonmark/src/main/java/org/commonmark/node/LinkReferenceDefinition.java +++ b/commonmark/src/main/java/org/commonmark/node/LinkReferenceDefinition.java @@ -2,12 +2,13 @@ /** * A link reference definition, e.g.: + * *


  * [foo]: /url "title"
  * 
- *

- * They can be referenced anywhere else in the document to produce a link using [foo]. The definitions - * themselves are usually not rendered in the final output. + * + *

They can be referenced anywhere else in the document to produce a link using [foo] + * . The definitions themselves are usually not rendered in the final output. * * @see CommonMark Spec */ @@ -17,8 +18,7 @@ public class LinkReferenceDefinition extends Block { private String destination; private String title; - public LinkReferenceDefinition() { - } + public LinkReferenceDefinition() {} public LinkReferenceDefinition(String label, String destination, String title) { this.label = label; diff --git a/commonmark/src/main/java/org/commonmark/node/ListBlock.java b/commonmark/src/main/java/org/commonmark/node/ListBlock.java index 1290bc622..d210a6b27 100644 --- a/commonmark/src/main/java/org/commonmark/node/ListBlock.java +++ b/commonmark/src/main/java/org/commonmark/node/ListBlock.java @@ -1,8 +1,6 @@ package org.commonmark.node; -/** - * A list block like {@link BulletList} or {@link OrderedList}. - */ +/** A list block like {@link BulletList} or {@link OrderedList}. */ public abstract class ListBlock extends Block { private boolean tight; @@ -18,5 +16,4 @@ public boolean isTight() { public void setTight(boolean tight) { this.tight = tight; } - } diff --git a/commonmark/src/main/java/org/commonmark/node/ListItem.java b/commonmark/src/main/java/org/commonmark/node/ListItem.java index c4d1214e7..a53cbbe74 100644 --- a/commonmark/src/main/java/org/commonmark/node/ListItem.java +++ b/commonmark/src/main/java/org/commonmark/node/ListItem.java @@ -1,11 +1,12 @@ package org.commonmark.node; /** - * A child of a {@link ListBlock}, containing other blocks (e.g. {@link Paragraph}, other lists, etc). - *

- * Note that a list item can't directly contain {@link Text}, it needs to be: - * {@link ListItem} : {@link Paragraph} : {@link Text}. - * If you want a list that is rendered tightly, create a list with {@link ListBlock#setTight(boolean)}. + * A child of a {@link ListBlock}, containing other blocks (e.g. {@link Paragraph}, other lists, + * etc). + * + *

Note that a list item can't directly contain {@link Text}, it needs to be: {@link ListItem} : + * {@link Paragraph} : {@link Text}. If you want a list that is rendered tightly, create a list with + * {@link ListBlock#setTight(boolean)}. * * @see CommonMark Spec: List items */ @@ -20,15 +21,21 @@ public void accept(Visitor visitor) { } /** - * Returns the indent of the marker such as "-" or "1." in columns (spaces or tab stop of 4) if available, or null - * otherwise. - *

- * Some examples and their marker indent: + * Returns the indent of the marker such as "-" or "1." in columns (spaces or tab stop of 4) if + * available, or null otherwise. + * + *

Some examples and their marker indent: + * *

- Foo
+ * * Marker indent: 0 + * *
 - Foo
+ * * Marker indent: 1 + * *
  1. Foo
+ * * Marker indent: 2 */ public Integer getMarkerIndent() { @@ -40,19 +47,26 @@ public void setMarkerIndent(Integer markerIndent) { } /** - * 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. - *

- * Some examples and their content indent: + * 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. + * + *

Some examples and their content indent: + * *

- Foo
+ * * Content indent: 2 + * *
 - Foo
+ * * Content indent: 3 + * *
  1. Foo
+ * * Content indent: 5 - *

- * 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. + * + *

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 Integer getContentIndent() { return contentIndent; @@ -63,8 +77,8 @@ public void setContentIndent(Integer contentIndent) { } /** - * @deprecated list items should only contain block nodes; if you're trying to create a list that is rendered - * without paragraphs, use {@link ListBlock#setTight(boolean)} instead. + * @deprecated list items should only contain block nodes; if you're trying to create a list + * that is rendered without paragraphs, use {@link ListBlock#setTight(boolean)} instead. */ @Override @Deprecated diff --git a/commonmark/src/main/java/org/commonmark/node/Node.java b/commonmark/src/main/java/org/commonmark/node/Node.java index abbda67f2..adc64838c 100644 --- a/commonmark/src/main/java/org/commonmark/node/Node.java +++ b/commonmark/src/main/java/org/commonmark/node/Node.java @@ -6,8 +6,8 @@ /** * The base class of all CommonMark AST nodes ({@link Block} and inlines). - *

- * A node can have multiple children, and a parent (except for the root node). + * + *

A node can have multiple children, and a parent (except for the root node). */ public abstract class Node { @@ -85,9 +85,7 @@ public void unlink() { this.prev = null; } - /** - * Inserts the {@code sibling} node after {@code this} node. - */ + /** Inserts the {@code sibling} node after {@code this} node. */ public void insertAfter(Node sibling) { sibling.unlink(); sibling.next = this.next; @@ -102,9 +100,7 @@ public void insertAfter(Node sibling) { } } - /** - * Inserts the {@code sibling} node before {@code this} node. - */ + /** Inserts the {@code sibling} node before {@code this} node. */ public void insertBefore(Node sibling) { sibling.unlink(); sibling.prev = this.prev; diff --git a/commonmark/src/main/java/org/commonmark/node/Nodes.java b/commonmark/src/main/java/org/commonmark/node/Nodes.java index 22d5932af..71e0925db 100644 --- a/commonmark/src/main/java/org/commonmark/node/Nodes.java +++ b/commonmark/src/main/java/org/commonmark/node/Nodes.java @@ -9,12 +9,9 @@ */ public class Nodes { - private Nodes() { - } + private Nodes() {} - /** - * The nodes between (not including) start and end. - */ + /** The nodes between (not including) start and end. */ public static Iterable between(Node start, Node end) { return new NodeIterable(start.getNext(), end); } @@ -63,4 +60,3 @@ public void remove() { } } } - diff --git a/commonmark/src/main/java/org/commonmark/node/OrderedList.java b/commonmark/src/main/java/org/commonmark/node/OrderedList.java index 61f8902c0..70cfd62c2 100644 --- a/commonmark/src/main/java/org/commonmark/node/OrderedList.java +++ b/commonmark/src/main/java/org/commonmark/node/OrderedList.java @@ -2,13 +2,14 @@ /** * An ordered list, e.g.: + * *


  * 1. One
  * 2. Two
  * 3. Three
  * 
- *

- * The children are {@link ListItem} blocks, which contain other blocks (or nested lists). + * + *

The children are {@link ListItem} blocks, which contain other blocks (or nested lists). * * @see CommonMark Spec: List items */ @@ -34,7 +35,8 @@ public void setMarkerStartNumber(Integer markerStartNumber) { } /** - * @return the delimiter used in the marker, e.g. {@code .} or {@code )}, if available, or null otherwise + * @return the delimiter used in the marker, e.g. {@code .} or {@code )}, if available, or null + * otherwise */ public String getMarkerDelimiter() { return markerDelimiter; @@ -65,7 +67,9 @@ public void setStartNumber(int startNumber) { */ @Deprecated public char getDelimiter() { - return markerDelimiter != null && !markerDelimiter.isEmpty() ? markerDelimiter.charAt(0) : '\0'; + return markerDelimiter != null && !markerDelimiter.isEmpty() + ? markerDelimiter.charAt(0) + : '\0'; } /** diff --git a/commonmark/src/main/java/org/commonmark/node/SoftLineBreak.java b/commonmark/src/main/java/org/commonmark/node/SoftLineBreak.java index 87445db56..21ba09411 100644 --- a/commonmark/src/main/java/org/commonmark/node/SoftLineBreak.java +++ b/commonmark/src/main/java/org/commonmark/node/SoftLineBreak.java @@ -2,6 +2,7 @@ /** * A soft line break (as opposed to a {@link HardLineBreak}), e.g. between: + * *

  * foo
  * bar
diff --git a/commonmark/src/main/java/org/commonmark/node/SourceSpan.java b/commonmark/src/main/java/org/commonmark/node/SourceSpan.java
index 6558cc84a..ab797cb18 100644
--- a/commonmark/src/main/java/org/commonmark/node/SourceSpan.java
+++ b/commonmark/src/main/java/org/commonmark/node/SourceSpan.java
@@ -4,22 +4,26 @@
 
 /**
  * A source span references a snippet of text from the source input.
- * 

- * It has a starting position (line and column index) and a length of how many characters it spans. - *

- * For example, this CommonMark source text: + * + *

It has a starting position (line and column index) and a length of how many characters it + * spans. + * + *

For example, this CommonMark source text: + * *


  * > foo
  * 
+ * * The {@link BlockQuote} node would have this source span: line 0, column 0, length 5. - *

- * The {@link Paragraph} node inside it would have: line 0, column 2, length 3. - *

- * If a block has multiple lines, it will have a source span for each line. - *

- * Note that the column index and length are measured in Java characters (UTF-16 code units). If you're outputting them - * to be consumed by another programming language, e.g. one that uses UTF-8 strings, you will need to translate them, - * otherwise characters such as emojis will result in incorrect positions. + * + *

The {@link Paragraph} node inside it would have: line 0, column 2, length 3. + * + *

If a block has multiple lines, it will have a source span for each line. + * + *

Note that the column index and length are measured in Java characters (UTF-16 code units). If + * you're outputting them to be consumed by another programming language, e.g. one that uses UTF-8 + * strings, you will need to translate them, otherwise characters such as emojis will result in + * incorrect positions. * * @since 0.16.0 */ @@ -35,8 +39,8 @@ public static SourceSpan of(int line, int col, int input, int length) { } /** - * @deprecated Use {{@link #of(int, int, int, int)}} instead to also specify input index. Using the deprecated one - * will set {@link #inputIndex} to 0. + * @deprecated Use {{@link #of(int, int, int, int)}} instead to also specify input index. Using + * the deprecated one will set {@link #inputIndex} to 0. */ @Deprecated public static SourceSpan of(int lineIndex, int columnIndex, int length) { @@ -70,8 +74,8 @@ public int getLineIndex() { } /** - * @return 0-based index of column (character on line) in source, e.g. 0 for the first character of a line, 1 for - * the second character, etc + * @return 0-based index of column (character on line) in source, e.g. 0 for the first character + * of a line, 1 for the second character, etc */ public int getColumnIndex() { return columnIndex; @@ -101,21 +105,28 @@ public SourceSpan subSpan(int beginIndex, int endIndex) { throw new IndexOutOfBoundsException("beginIndex " + beginIndex + " + must be >= 0"); } if (beginIndex > length) { - throw new IndexOutOfBoundsException("beginIndex " + beginIndex + " must be <= length " + length); + throw new IndexOutOfBoundsException( + "beginIndex " + beginIndex + " must be <= length " + length); } if (endIndex < 0) { throw new IndexOutOfBoundsException("endIndex " + endIndex + " + must be >= 0"); } if (endIndex > length) { - throw new IndexOutOfBoundsException("endIndex " + endIndex + " must be <= length " + length); + throw new IndexOutOfBoundsException( + "endIndex " + endIndex + " must be <= length " + length); } if (beginIndex > endIndex) { - throw new IndexOutOfBoundsException("beginIndex " + beginIndex + " must be <= endIndex " + endIndex); + throw new IndexOutOfBoundsException( + "beginIndex " + beginIndex + " must be <= endIndex " + endIndex); } if (beginIndex == 0 && endIndex == length) { return this; } - return new SourceSpan(lineIndex, columnIndex + beginIndex, inputIndex + beginIndex, endIndex - beginIndex); + return new SourceSpan( + lineIndex, + columnIndex + beginIndex, + inputIndex + beginIndex, + endIndex - beginIndex); } @Override @@ -127,10 +138,10 @@ public boolean equals(Object o) { return false; } SourceSpan that = (SourceSpan) o; - return lineIndex == that.lineIndex && - columnIndex == that.columnIndex && - inputIndex == that.inputIndex && - length == that.length; + return lineIndex == that.lineIndex + && columnIndex == that.columnIndex + && inputIndex == that.inputIndex + && length == that.length; } @Override @@ -140,11 +151,15 @@ public int hashCode() { @Override public String toString() { - return "SourceSpan{" + - "line=" + lineIndex + - ", column=" + columnIndex + - ", input=" + inputIndex + - ", length=" + length + - "}"; + return "SourceSpan{" + + "line=" + + lineIndex + + ", column=" + + columnIndex + + ", input=" + + inputIndex + + ", length=" + + length + + "}"; } } diff --git a/commonmark/src/main/java/org/commonmark/node/SourceSpans.java b/commonmark/src/main/java/org/commonmark/node/SourceSpans.java index 975d7fbdb..945f1c19a 100644 --- a/commonmark/src/main/java/org/commonmark/node/SourceSpans.java +++ b/commonmark/src/main/java/org/commonmark/node/SourceSpans.java @@ -42,7 +42,13 @@ public void addAll(List other) { SourceSpan a = sourceSpans.get(lastIndex); SourceSpan b = other.get(0); if (a.getInputIndex() + a.getLength() == b.getInputIndex()) { - sourceSpans.set(lastIndex, SourceSpan.of(a.getLineIndex(), a.getColumnIndex(), a.getInputIndex(), a.getLength() + b.getLength())); + sourceSpans.set( + lastIndex, + SourceSpan.of( + a.getLineIndex(), + a.getColumnIndex(), + a.getInputIndex(), + a.getLength() + b.getLength())); sourceSpans.addAll(other.subList(1, other.size())); } else { sourceSpans.addAll(other); diff --git a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java index 0dbeed3df..f09786f84 100644 --- a/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java +++ b/commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java @@ -2,18 +2,19 @@ /** * Strong emphasis, e.g.: + * *


  * Some **strong emphasis** or __strong emphasis__
  * 
* - * @see CommonMark Spec: Emphasis and strong emphasis + * @see CommonMark Spec: + * Emphasis and strong emphasis */ public class StrongEmphasis extends Node implements Delimited { private String delimiter; - public StrongEmphasis() { - } + public StrongEmphasis() {} public StrongEmphasis(String delimiter) { this.delimiter = delimiter; diff --git a/commonmark/src/main/java/org/commonmark/node/Text.java b/commonmark/src/main/java/org/commonmark/node/Text.java index 9a04c41c1..5367f2f3f 100644 --- a/commonmark/src/main/java/org/commonmark/node/Text.java +++ b/commonmark/src/main/java/org/commonmark/node/Text.java @@ -2,11 +2,13 @@ /** * A text node, e.g. in: + * *
  * foo *bar*
  * 
- *

- * The foo is a text node, and the bar inside the emphasis is also a text node. + * + *

The foo is a text node, and the bar inside the emphasis is also a + * text node. * * @see CommonMark Spec */ @@ -14,8 +16,7 @@ public class Text extends Node { private String literal; - public Text() { - } + public Text() {} public Text(String literal) { this.literal = literal; diff --git a/commonmark/src/main/java/org/commonmark/node/ThematicBreak.java b/commonmark/src/main/java/org/commonmark/node/ThematicBreak.java index a31131e07..e2391f57d 100644 --- a/commonmark/src/main/java/org/commonmark/node/ThematicBreak.java +++ b/commonmark/src/main/java/org/commonmark/node/ThematicBreak.java @@ -2,6 +2,7 @@ /** * A thematic break, e.g. between text: + * *

  * Some text
  *
diff --git a/commonmark/src/main/java/org/commonmark/node/Visitor.java b/commonmark/src/main/java/org/commonmark/node/Visitor.java
index a155296f0..0e3fc9f84 100644
--- a/commonmark/src/main/java/org/commonmark/node/Visitor.java
+++ b/commonmark/src/main/java/org/commonmark/node/Visitor.java
@@ -2,8 +2,8 @@
 
 /**
  * Node visitor.
- * 

- * Implementations should subclass {@link AbstractVisitor} instead of implementing this directly. + * + *

Implementations should subclass {@link AbstractVisitor} instead of implementing this directly. */ public interface Visitor { diff --git a/commonmark/src/main/java/org/commonmark/node/package-info.java b/commonmark/src/main/java/org/commonmark/node/package-info.java index e9fee1aba..3408d2e72 100644 --- a/commonmark/src/main/java/org/commonmark/node/package-info.java +++ b/commonmark/src/main/java/org/commonmark/node/package-info.java @@ -1,4 +1,5 @@ /** - * AST node types (see {@link org.commonmark.node.Node}) and visitors (see {@link org.commonmark.node.AbstractVisitor}) + * AST node types (see {@link org.commonmark.node.Node}) and visitors (see {@link + * org.commonmark.node.AbstractVisitor}) */ package org.commonmark.node; diff --git a/commonmark/src/main/java/org/commonmark/package-info.java b/commonmark/src/main/java/org/commonmark/package-info.java index b683017f6..9ff3301e9 100644 --- a/commonmark/src/main/java/org/commonmark/package-info.java +++ b/commonmark/src/main/java/org/commonmark/package-info.java @@ -1,10 +1,11 @@ /** * Root package of commonmark-java + * *

    - *
  • {@link org.commonmark.parser} for parsing input text to AST nodes
  • - *
  • {@link org.commonmark.node} for AST node types and visitors
  • - *
  • {@link org.commonmark.renderer.html} for HTML rendering
  • - *
  • {@link org.commonmark.renderer.markdown} for Markdown rendering
  • + *
  • {@link org.commonmark.parser} for parsing input text to AST nodes + *
  • {@link org.commonmark.node} for AST node types and visitors + *
  • {@link org.commonmark.renderer.html} for HTML rendering + *
  • {@link org.commonmark.renderer.markdown} for Markdown rendering *
*/ package org.commonmark; diff --git a/commonmark/src/main/java/org/commonmark/parser/IncludeSourceSpans.java b/commonmark/src/main/java/org/commonmark/parser/IncludeSourceSpans.java index 91d2b4e00..f53378c2f 100644 --- a/commonmark/src/main/java/org/commonmark/parser/IncludeSourceSpans.java +++ b/commonmark/src/main/java/org/commonmark/parser/IncludeSourceSpans.java @@ -1,22 +1,16 @@ package org.commonmark.parser; /** - * Whether to include {@link org.commonmark.node.SourceSpan} or not while parsing, - * see {@link Parser.Builder#includeSourceSpans(IncludeSourceSpans)}. + * Whether to include {@link org.commonmark.node.SourceSpan} or not while parsing, see {@link + * Parser.Builder#includeSourceSpans(IncludeSourceSpans)}. * * @since 0.16.0 */ public enum IncludeSourceSpans { - /** - * Do not include source spans. - */ + /** Do not include source spans. */ NONE, - /** - * Include source spans on {@link org.commonmark.node.Block} nodes. - */ + /** Include source spans on {@link org.commonmark.node.Block} nodes. */ BLOCKS, - /** - * Include source spans on block nodes and inline nodes. - */ + /** Include source spans on block nodes and inline nodes. */ BLOCKS_AND_INLINES, } diff --git a/commonmark/src/main/java/org/commonmark/parser/InlineParser.java b/commonmark/src/main/java/org/commonmark/parser/InlineParser.java index 49043a64f..1c6714686 100644 --- a/commonmark/src/main/java/org/commonmark/parser/InlineParser.java +++ b/commonmark/src/main/java/org/commonmark/parser/InlineParser.java @@ -2,9 +2,7 @@ import org.commonmark.node.Node; -/** - * Parser for inline content (text, links, emphasized text, etc). - */ +/** Parser for inline content (text, links, emphasized text, etc). */ public interface InlineParser { /** diff --git a/commonmark/src/main/java/org/commonmark/parser/InlineParserContext.java b/commonmark/src/main/java/org/commonmark/parser/InlineParserContext.java index 12007610b..774773273 100644 --- a/commonmark/src/main/java/org/commonmark/parser/InlineParserContext.java +++ b/commonmark/src/main/java/org/commonmark/parser/InlineParserContext.java @@ -1,32 +1,30 @@ package org.commonmark.parser; +import java.util.List; +import java.util.Set; import org.commonmark.node.LinkReferenceDefinition; -import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.beta.InlineContentParserFactory; +import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.delimiter.DelimiterProcessor; -import java.util.List; -import java.util.Set; - -/** - * Context for inline parsing. - */ +/** Context for inline parsing. */ public interface InlineParserContext { /** - * @return custom inline content parsers that have been configured with - * {@link Parser.Builder#customInlineContentParserFactory(InlineContentParserFactory)} + * @return custom inline content parsers that have been configured with {@link + * Parser.Builder#customInlineContentParserFactory(InlineContentParserFactory)} */ List getCustomInlineContentParserFactories(); /** - * @return custom delimiter processors that have been configured with - * {@link Parser.Builder#customDelimiterProcessor(DelimiterProcessor)} + * @return custom delimiter processors that have been configured with {@link + * Parser.Builder#customDelimiterProcessor(DelimiterProcessor)} */ List getCustomDelimiterProcessors(); /** - * @return custom link processors that have been configured with {@link Parser.Builder#linkProcessor}. + * @return custom link processors that have been configured with {@link + * Parser.Builder#linkProcessor}. */ List getCustomLinkProcessors(); @@ -37,9 +35,9 @@ public interface InlineParserContext { /** * Look up a {@link LinkReferenceDefinition} for a given label. - *

- * Note that the passed in label does not need to be normalized; implementations are responsible for doing the - * normalization before lookup. + * + *

Note that the passed in label does not need to be normalized; implementations are + * responsible for doing the normalization before lookup. * * @param label the link label to look up * @return the definition if one exists, {@code null} otherwise @@ -50,9 +48,9 @@ public interface InlineParserContext { /** * Look up a definition of a type for a given label. - *

- * Note that the passed in label does not need to be normalized; implementations are responsible for doing the - * normalization before lookup. + * + *

Note that the passed in label does not need to be normalized; implementations are + * responsible for doing the normalization before lookup. * * @return the definition if one exists, null otherwise */ diff --git a/commonmark/src/main/java/org/commonmark/parser/InlineParserFactory.java b/commonmark/src/main/java/org/commonmark/parser/InlineParserFactory.java index c1640e9d8..0eaac3c30 100644 --- a/commonmark/src/main/java/org/commonmark/parser/InlineParserFactory.java +++ b/commonmark/src/main/java/org/commonmark/parser/InlineParserFactory.java @@ -1,12 +1,11 @@ package org.commonmark.parser; -/** - * Factory for custom inline parser. - */ +/** Factory for custom inline parser. */ public interface InlineParserFactory { /** - * Create an {@link InlineParser} to use for parsing inlines. This is called once per parsed document. + * Create an {@link InlineParser} to use for parsing inlines. This is called once per parsed + * document. */ InlineParser create(InlineParserContext inlineParserContext); } diff --git a/commonmark/src/main/java/org/commonmark/parser/Parser.java b/commonmark/src/main/java/org/commonmark/parser/Parser.java index 8faac789b..23fd75f68 100644 --- a/commonmark/src/main/java/org/commonmark/parser/Parser.java +++ b/commonmark/src/main/java/org/commonmark/parser/Parser.java @@ -1,27 +1,26 @@ package org.commonmark.parser; +import java.io.IOException; +import java.io.Reader; +import java.util.*; import org.commonmark.Extension; import org.commonmark.internal.Definitions; import org.commonmark.internal.DocumentParser; import org.commonmark.internal.InlineParserContextImpl; import org.commonmark.internal.InlineParserImpl; import org.commonmark.node.*; +import org.commonmark.parser.beta.InlineContentParserFactory; import org.commonmark.parser.beta.LinkInfo; import org.commonmark.parser.beta.LinkProcessor; -import org.commonmark.parser.beta.InlineContentParserFactory; import org.commonmark.parser.beta.LinkResult; import org.commonmark.parser.block.BlockParserFactory; import org.commonmark.parser.delimiter.DelimiterProcessor; -import java.io.IOException; -import java.io.Reader; -import java.util.*; - - /** * Parses input text to a tree of nodes. - *

- * Start with the {@link #builder} method, configure the parser and build it. Example: + * + *

Start with the {@link #builder} method, configure the parser and build it. Example: + * *


  * Parser parser = Parser.builder().build();
  * Node document = parser.parse("input text");
@@ -40,7 +39,9 @@ public class Parser {
     private final int maxOpenBlockParsers;
 
     private Parser(Builder builder) {
-        this.blockParserFactories = DocumentParser.calculateBlockParserFactories(builder.blockParserFactories, builder.enabledBlockTypes);
+        this.blockParserFactories =
+                DocumentParser.calculateBlockParserFactories(
+                        builder.blockParserFactories, builder.enabledBlockTypes);
         this.inlineParserFactory = builder.getInlineParserFactory();
         this.postProcessors = builder.postProcessors;
         this.inlineContentParserFactories = builder.inlineContentParserFactories;
@@ -50,10 +51,15 @@ private Parser(Builder builder) {
         this.includeSourceSpans = builder.includeSourceSpans;
         this.maxOpenBlockParsers = builder.maxOpenBlockParsers;
 
-        // Try to construct an inline parser. Invalid configuration might result in an exception, which we want to
-        // detect as soon as possible.
-        var context = new InlineParserContextImpl(
-                inlineContentParserFactories, delimiterProcessors, linkProcessors, linkMarkers, new Definitions());
+        // Try to construct an inline parser. Invalid configuration might result in an exception,
+        // which we want to detect as soon as possible.
+        var context =
+                new InlineParserContextImpl(
+                        inlineContentParserFactories,
+                        delimiterProcessors,
+                        linkProcessors,
+                        linkMarkers,
+                        new Definitions());
         this.inlineParserFactory.create(context);
     }
 
@@ -68,8 +74,8 @@ public static Builder builder() {
 
     /**
      * Parse the specified input text into a tree of nodes.
-     * 

- * This method is thread-safe (a new parser state is used for each invocation). + * + *

This method is thread-safe (a new parser state is used for each invocation). * * @param input the text to parse - must not be null * @return the root node @@ -82,7 +88,9 @@ public Node parse(String input) { } /** - * Parse the specified reader into a tree of nodes. The caller is responsible for closing the reader. + * Parse the specified reader into a tree of nodes. The caller is responsible for closing the + * reader. + * *


      * Parser parser = Parser.builder().build();
      * try (InputStreamReader reader = new InputStreamReader(new FileInputStream("file.md"), StandardCharsets.UTF_8)) {
@@ -90,10 +98,12 @@ public Node parse(String input) {
      *     // ...
      * }
      * 
- * Note that if you have a file with a byte order mark (BOM), you need to skip it before handing the reader to this - * library. There's existing classes that do that, e.g. see {@code BOMInputStream} in Commons IO. - *

- * This method is thread-safe (a new parser state is used for each invocation). + * + * Note that if you have a file with a byte order mark (BOM), you need to skip it before handing + * the reader to this library. There's existing classes that do that, e.g. see {@code + * BOMInputStream} in Commons IO. + * + *

This method is thread-safe (a new parser state is used for each invocation). * * @param input the reader to parse - must not be null * @return the root node @@ -107,8 +117,15 @@ public Node parseReader(Reader input) throws IOException { } private DocumentParser createDocumentParser() { - return new DocumentParser(blockParserFactories, inlineParserFactory, inlineContentParserFactories, - delimiterProcessors, linkProcessors, linkMarkers, includeSourceSpans, maxOpenBlockParsers); + return new DocumentParser( + blockParserFactories, + inlineParserFactory, + inlineContentParserFactories, + delimiterProcessors, + linkProcessors, + linkMarkers, + includeSourceSpans, + maxOpenBlockParsers); } private Node postProcess(Node document) { @@ -118,17 +135,17 @@ private Node postProcess(Node document) { return document; } - /** - * Builder for configuring a {@link Parser}. - */ + /** Builder for configuring a {@link Parser}. */ public static class Builder { private final List blockParserFactories = new ArrayList<>(); - private final List inlineContentParserFactories = new ArrayList<>(); + private final List inlineContentParserFactories = + new ArrayList<>(); private final List delimiterProcessors = new ArrayList<>(); private final List linkProcessors = new ArrayList<>(); private final List postProcessors = new ArrayList<>(); private final Set linkMarkers = new HashSet<>(); - private Set> enabledBlockTypes = DocumentParser.getDefaultBlockParserTypes(); + private Set> enabledBlockTypes = + DocumentParser.getDefaultBlockParserTypes(); private InlineParserFactory inlineParserFactory; private IncludeSourceSpans includeSourceSpans = IncludeSourceSpans.NONE; private int maxOpenBlockParsers = Integer.MAX_VALUE; @@ -157,29 +174,31 @@ public Builder extensions(Iterable extensions) { /** * Describe the list of markdown features the parser will recognize and parse. - *

- * By default, CommonMark will recognize and parse the following set of "block" elements: + * + *

By default, CommonMark will recognize and parse the following set of "block" elements: + * *

    - *
  • {@link Heading} ({@code #}) - *
  • {@link HtmlBlock} ({@code }) - *
  • {@link ThematicBreak} (Horizontal Rule) ({@code ---}) - *
  • {@link FencedCodeBlock} ({@code ```}) - *
  • {@link IndentedCodeBlock} - *
  • {@link BlockQuote} ({@code >}) - *
  • {@link ListBlock} (Ordered / Unordered List) ({@code 1. / *}) + *
  • {@link Heading} ({@code #}) + *
  • {@link HtmlBlock} ({@code }) + *
  • {@link ThematicBreak} (Horizontal Rule) ({@code ---}) + *
  • {@link FencedCodeBlock} ({@code ```}) + *
  • {@link IndentedCodeBlock} + *
  • {@link BlockQuote} ({@code >}) + *
  • {@link ListBlock} (Ordered / Unordered List) ({@code 1. / *}) *
- *

- * To parse only a subset of the features listed above, pass a list of each feature's associated {@link Block} class. - *

- * E.g., to only parse headings and lists: - *

-         *     {@code
-         *     Parser.builder().enabledBlockTypes(Set.of(Heading.class, ListBlock.class));
-         *     }
-         * 
* - * @param enabledBlockTypes A list of block nodes the parser will parse. - * If this list is empty, the parser will not recognize any CommonMark core features. + *

To parse only a subset of the features listed above, pass a list of each feature's + * associated {@link Block} class. + * + *

E.g., to only parse headings and lists: + * + *

{@code
+         * Parser.builder().enabledBlockTypes(Set.of(Heading.class, ListBlock.class));
+         *
+         * }
+ * + * @param enabledBlockTypes A list of block nodes the parser will parse. If this list is + * empty, the parser will not recognize any CommonMark core features. * @return {@code this} */ public Builder enabledBlockTypes(Set> enabledBlockTypes) { @@ -190,9 +209,10 @@ public Builder enabledBlockTypes(Set> enabledBlockTypes) } /** - * Whether to calculate source positions for parsed {@link Node Nodes}, see {@link Node#getSourceSpans()}. - *

- * By default, source spans are disabled. + * Whether to calculate source positions for parsed {@link Node Nodes}, see {@link + * Node#getSourceSpans()}. + * + *

By default, source spans are disabled. * * @param includeSourceSpans which kind of source spans should be included * @return {@code this} @@ -205,12 +225,12 @@ public Builder includeSourceSpans(IncludeSourceSpans includeSourceSpans) { /** * Limit how many block parsers may be open at once while parsing. - *

- * Once the limit is reached, additional block starts are treated as plain text instead of - * creating deeper nested block structure. - *

- * The document root parser is not counted. The default is unlimited, so callers that keep - * using {@code Parser.builder().build()} preserve behavior. + * + *

Once the limit is reached, additional block starts are treated as plain text instead + * of creating deeper nested block structure. + * + *

The document root parser is not counted. The default is unlimited, so callers that + * keep using {@code Parser.builder().build()} preserve behavior. * * @param maxOpenBlockParsers maximum number of open non-document block parsers, must be * zero or greater @@ -226,10 +246,10 @@ public Builder maxOpenBlockParsers(int maxOpenBlockParsers) { /** * Add a custom block parser factory. - *

- * Note that custom factories are applied before the built-in factories. This is so that - * extensions can change how some syntax is parsed that would otherwise be handled by built-in factories. - * "With great power comes great responsibility." + * + *

Note that custom factories are applied before the built-in factories. This is + * so that extensions can change how some syntax is parsed that would otherwise be handled + * by built-in factories. "With great power comes great responsibility." * * @param blockParserFactory a block parser factory implementation * @return {@code this} @@ -241,28 +261,33 @@ public Builder customBlockParserFactory(BlockParserFactory blockParserFactory) { } /** - * Add a factory for a custom inline content parser, for extending inline parsing or overriding built-in parsing. - *

- * Note that parsers are triggered based on a special character as specified by - * {@link InlineContentParserFactory#getTriggerCharacters()}. It is possible to register multiple parsers for the same - * character, or even for some built-in special character such as {@code `}. The custom parsers are tried first - * in order in which they are registered, and then the built-in ones. + * Add a factory for a custom inline content parser, for extending inline parsing or + * overriding built-in parsing. + * + *

Note that parsers are triggered based on a special character as specified by {@link + * InlineContentParserFactory#getTriggerCharacters()}. It is possible to register multiple + * parsers for the same character, or even for some built-in special character such as + * {@code `}. The custom parsers are tried first in order in which they are registered, and + * then the built-in ones. */ - public Builder customInlineContentParserFactory(InlineContentParserFactory inlineContentParserFactory) { - Objects.requireNonNull(inlineContentParserFactory, "inlineContentParser must not be null"); + public Builder customInlineContentParserFactory( + InlineContentParserFactory inlineContentParserFactory) { + Objects.requireNonNull( + inlineContentParserFactory, "inlineContentParser must not be null"); inlineContentParserFactories.add(inlineContentParserFactory); return this; } /** * Add a custom delimiter processor for inline parsing. - *

- * Note that multiple delimiter processors with the same characters can be added, as long as they have a - * different minimum length. In that case, the processor with the shortest matching length is used. Adding more - * than one delimiter processor with the same character and minimum length is invalid. - *

- * If you want more control over how parsing is done, you might want to use - * {@link #customInlineContentParserFactory} instead. + * + *

Note that multiple delimiter processors with the same characters can be added, as long + * as they have a different minimum length. In that case, the processor with the shortest + * matching length is used. Adding more than one delimiter processor with the same character + * and minimum length is invalid. + * + *

If you want more control over how parsing is done, you might want to use {@link + * #customInlineContentParserFactory} instead. * * @param delimiterProcessor a delimiter processor implementation * @return {@code this} @@ -275,9 +300,10 @@ public Builder customDelimiterProcessor(DelimiterProcessor delimiterProcessor) { /** * Add a custom link/image processor for inline parsing. - *

- * Multiple link processors can be added, and will be tried in order in which they were added. If no link - * processor applies, the normal behavior applies. That means these can override built-in link parsing. + * + *

Multiple link processors can be added, and will be tried in order in which they were + * added. If no link processor applies, the normal behavior applies. That means these can + * override built-in link parsing. * * @param linkProcessor a link processor implementation * @return {@code this} @@ -289,12 +315,14 @@ public Builder linkProcessor(LinkProcessor linkProcessor) { } /** - * Add a custom link marker for link processing. A link marker is a character like {@code !} which, if it - * appears before the {@code [} of a link, changes the meaning of the link. - *

- * If a link marker followed by a valid link is parsed, the {@link org.commonmark.parser.beta.LinkInfo} - * that is passed to {@link LinkProcessor} will have its {@link LinkInfo#marker()} set. A link processor should - * check the {@link Text#getLiteral()} and then do any processing, and will probably want to use {@link LinkResult#includeMarker()}. + * Add a custom link marker for link processing. A link marker is a character like {@code !} + * which, if it appears before the {@code [} of a link, changes the meaning of the link. + * + *

If a link marker followed by a valid link is parsed, the {@link + * org.commonmark.parser.beta.LinkInfo} that is passed to {@link LinkProcessor} will have + * its {@link LinkInfo#marker()} set. A link processor should check the {@link + * Text#getLiteral()} and then do any processing, and will probably want to use {@link + * LinkResult#includeMarker()}. * * @param linkMarker a link marker character * @return {@code this} @@ -313,18 +341,13 @@ public Builder postProcessor(PostProcessor postProcessor) { /** * Overrides the parser used for inline markdown processing. - *

- * Provide an implementation of InlineParserFactory which provides a custom inline parser - * to modify how the following are parsed: - * bold (**) - * italic (*) - * strikethrough (~~) - * backtick quote (`) - * link ([title](http://)) - * image (![alt](http://)) - *

- * Note that if this method is not called or the inline parser factory is set to null, then the default - * implementation will be used. + * + *

Provide an implementation of InlineParserFactory which provides a custom inline parser + * to modify how the following are parsed: bold (**) italic (*) strikethrough (~~) backtick + * quote (`) link ([title](http://)) image (![alt](http://)) + * + *

Note that if this method is not called or the inline parser factory is set to null, + * then the default implementation will be used. * * @param inlineParserFactory an inline parser factory implementation * @return {@code this} @@ -343,9 +366,7 @@ private InlineParserFactory getInlineParserFactory() { } } - /** - * Extension for {@link Parser}. - */ + /** Extension for {@link Parser}. */ public interface ParserExtension extends Extension { void extend(Builder parserBuilder); } diff --git a/commonmark/src/main/java/org/commonmark/parser/PostProcessor.java b/commonmark/src/main/java/org/commonmark/parser/PostProcessor.java index be00347ca..ffa79370a 100644 --- a/commonmark/src/main/java/org/commonmark/parser/PostProcessor.java +++ b/commonmark/src/main/java/org/commonmark/parser/PostProcessor.java @@ -9,5 +9,4 @@ public interface PostProcessor { * @return the result of post-processing, may be a modified {@code node} argument */ Node process(Node node); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/SourceLine.java b/commonmark/src/main/java/org/commonmark/parser/SourceLine.java index 92a8cdfaf..da7fe71f4 100644 --- a/commonmark/src/main/java/org/commonmark/parser/SourceLine.java +++ b/commonmark/src/main/java/org/commonmark/parser/SourceLine.java @@ -1,8 +1,7 @@ package org.commonmark.parser; -import org.commonmark.node.SourceSpan; - import java.util.Objects; +import org.commonmark.node.SourceSpan; /** * A line or part of a line from the input source. @@ -39,7 +38,8 @@ public SourceLine substring(int beginIndex, int endIndex) { if (length != 0) { int columnIndex = sourceSpan.getColumnIndex() + beginIndex; int inputIndex = sourceSpan.getInputIndex() + beginIndex; - newSourceSpan = SourceSpan.of(sourceSpan.getLineIndex(), columnIndex, inputIndex, length); + newSourceSpan = + SourceSpan.of(sourceSpan.getLineIndex(), columnIndex, inputIndex, length); } } return SourceLine.of(newContent, newSourceSpan); diff --git a/commonmark/src/main/java/org/commonmark/parser/SourceLines.java b/commonmark/src/main/java/org/commonmark/parser/SourceLines.java index 0b4290341..b21236281 100644 --- a/commonmark/src/main/java/org/commonmark/parser/SourceLines.java +++ b/commonmark/src/main/java/org/commonmark/parser/SourceLines.java @@ -1,9 +1,8 @@ package org.commonmark.parser; -import org.commonmark.node.SourceSpan; - import java.util.ArrayList; import java.util.List; +import org.commonmark.node.SourceSpan; /** * A set of lines ({@link SourceLine}) from the input source. diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParser.java b/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParser.java index bc5c9a54f..83941e76c 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParser.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParser.java @@ -1,21 +1,23 @@ package org.commonmark.parser.beta; /** - * Parser for a type of inline content. Registered via a {@link InlineContentParserFactory} and created by its - * {@link InlineContentParserFactory#create() create} method. The lifetime of this is tied to each inline content - * snippet that is parsed, as a new instance is created for each. + * Parser for a type of inline content. Registered via a {@link InlineContentParserFactory} and + * created by its {@link InlineContentParserFactory#create() create} method. The lifetime of this is + * tied to each inline content snippet that is parsed, as a new instance is created for each. */ public interface InlineContentParser { /** - * Try to parse inline content starting from the current position. Note that the character at the current position - * is one of {@link InlineContentParserFactory#getTriggerCharacters()} of the factory that created this parser. - *

- * For a given inline content snippet that is being parsed, this method can be called multiple times: each time a - * trigger character is encountered. + * Try to parse inline content starting from the current position. Note that the character at + * the current position is one of {@link InlineContentParserFactory#getTriggerCharacters()} of + * the factory that created this parser. + * + *

For a given inline content snippet that is being parsed, this method can be called + * multiple times: each time a trigger character is encountered. * * @param inlineParserState the current state of the inline parser - * @return the result of parsing; can indicate that this parser is not interested, or that parsing was successful + * @return the result of parsing; can indicate that this parser is not interested, or that + * parsing was successful */ ParsedInline tryParse(InlineParserState inlineParserState); } diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParserFactory.java b/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParserFactory.java index c86f93a41..c52abab2a 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParserFactory.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParserFactory.java @@ -4,21 +4,24 @@ /** * A factory for extending inline content parsing. - *

- * See {@link org.commonmark.parser.Parser.Builder#customInlineContentParserFactory} for how to register it. + * + *

See {@link org.commonmark.parser.Parser.Builder#customInlineContentParserFactory} for how to + * register it. */ public interface InlineContentParserFactory { /** - * An inline content parser needs to have a special "trigger" character which activates it. When this character is - * encountered during inline parsing, {@link InlineContentParser#tryParse} is called with the current parser state. - * It can also register for more than one trigger character. + * An inline content parser needs to have a special "trigger" character which activates it. When + * this character is encountered during inline parsing, {@link InlineContentParser#tryParse} is + * called with the current parser state. It can also register for more than one trigger + * character. */ Set getTriggerCharacters(); /** - * Create an {@link InlineContentParser} that will do the parsing. Create is called once per text snippet of inline - * content inside block structures, and then called each time a trigger character is encountered. + * Create an {@link InlineContentParser} that will do the parsing. Create is called once per + * text snippet of inline content inside block structures, and then called each time a trigger + * character is encountered. */ InlineContentParser create(); } diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/InlineParserState.java b/commonmark/src/main/java/org/commonmark/parser/beta/InlineParserState.java index e434d45d6..246aec043 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/InlineParserState.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/InlineParserState.java @@ -3,10 +3,10 @@ public interface InlineParserState { /** - * Return a scanner for the input for the current position (on the trigger character that the inline parser was - * added for). - *

- * Note that this always returns the same instance, if you want to backtrack you need to use + * Return a scanner for the input for the current position (on the trigger character that the + * inline parser was added for). + * + *

Note that this always returns the same instance, if you want to backtrack you need to use * {@link Scanner#position()} and {@link Scanner#setPosition(Position)}. */ Scanner scanner(); diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/LinkInfo.java b/commonmark/src/main/java/org/commonmark/parser/beta/LinkInfo.java index b2fda57e4..210ca9ddb 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/LinkInfo.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/LinkInfo.java @@ -4,62 +4,64 @@ /** * A parsed link/image. There are different types of links. - *

- * Inline links: + * + *

Inline links: + * *

  * [text](destination)
  * [text](destination "title")
  * 
- *

- * Reference links, which have different subtypes. Full:: + * + *

Reference links, which have different subtypes. Full:: + * *

  * [text][label]
  * 
+ * * Collapsed (label is ""): + * *
  * [text][]
  * 
+ * * Shortcut (label is null): + * *
  * [text]
  * 
- * Images use the same syntax as links but with a {@code !} {@link #marker()} front, e.g. {@code ![text](destination)}. + * + * Images use the same syntax as links but with a {@code !} {@link #marker()} front, e.g. {@code + * ![text](destination)}. */ public interface LinkInfo { /** - * The marker if present, or null. A marker is e.g. {@code !} for an image, or a custom marker as specified in - * {@link org.commonmark.parser.Parser.Builder#linkMarker}. + * The marker if present, or null. A marker is e.g. {@code !} for an image, or a custom marker + * as specified in {@link org.commonmark.parser.Parser.Builder#linkMarker}. */ Text marker(); - /** - * The text node of the opening bracket {@code [}. - */ + /** The text node of the opening bracket {@code [}. */ Text openingBracket(); - /** - * The text between the first brackets, e.g. `foo` in `[foo][bar]`. - */ + /** The text between the first brackets, e.g. `foo` in `[foo][bar]`. */ String text(); /** - * The label, or null for inline links or for shortcut links (in which case {@link #text()} should be used as the label). + * The label, or null for inline links or for shortcut links (in which case {@link #text()} + * should be used as the label). */ String label(); - /** - * The destination if available, e.g. in `[foo](destination)`, or null - */ + /** The destination if available, e.g. in `[foo](destination)`, or null */ String destination(); - /** - * The title if available, e.g. in `[foo](destination "title")`, or null - */ + /** The title if available, e.g. in `[foo](destination "title")`, or null */ String title(); /** * The position after the closing text bracket, e.g.: + * *
      * [foo][bar]
      *      ^
diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/LinkProcessor.java b/commonmark/src/main/java/org/commonmark/parser/beta/LinkProcessor.java
index 3e448fd91..595e8d73d 100644
--- a/commonmark/src/main/java/org/commonmark/parser/beta/LinkProcessor.java
+++ b/commonmark/src/main/java/org/commonmark/parser/beta/LinkProcessor.java
@@ -4,37 +4,43 @@
 
 /**
  * An interface to decide how links/images are handled.
+ *
+ * 

Implementations need to be registered with a parser via {@link + * org.commonmark.parser.Parser.Builder#linkProcessor}. Then, when inline parsing is run, each + * parsed link/image is passed to the processor. This includes links like these: + * *

- * Implementations need to be registered with a parser via {@link org.commonmark.parser.Parser.Builder#linkProcessor}. - * Then, when inline parsing is run, each parsed link/image is passed to the processor. This includes links like these: - *

+ * *


  * [text](destination)
  * [text]
  * [text][]
  * [text][label]
  * 
+ * * And images: + * *

  * ![text](destination)
  * ![text]
  * ![text][]
  * ![text][label]
  * 
+ * * See {@link LinkInfo} for accessing various parts of the parsed link/image. - *

- * The processor can then inspect the link/image and decide what to do with it by returning the appropriate - * {@link LinkResult}. If it returns {@link LinkResult#none()}, the next registered processor is tried. If none of them - * apply, the link is handled as it normally would. + * + *

The processor can then inspect the link/image and decide what to do with it by returning the + * appropriate {@link LinkResult}. If it returns {@link LinkResult#none()}, the next registered + * processor is tried. If none of them apply, the link is handled as it normally would. */ public interface LinkProcessor { /** * @param linkInfo information about the parsed link/image - * @param scanner the scanner at the current position after the parsed link/image - * @param context context for inline parsing - * @return what to do with the link/image, e.g. do nothing (try the next processor), wrap the text in a node, or - * replace the link/image with a node + * @param scanner the scanner at the current position after the parsed link/image + * @param context context for inline parsing + * @return what to do with the link/image, e.g. do nothing (try the next processor), wrap the + * text in a node, or replace the link/image with a node */ LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContext context); } diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/LinkResult.java b/commonmark/src/main/java/org/commonmark/parser/beta/LinkResult.java index 43bc82af8..6becc0cb7 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/LinkResult.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/LinkResult.java @@ -3,26 +3,24 @@ import org.commonmark.internal.inline.LinkResultImpl; import org.commonmark.node.Node; -/** - * What to do with a link/image processed by {@link LinkProcessor}. - */ +/** What to do with a link/image processed by {@link LinkProcessor}. */ public interface LinkResult { - /** - * Link not handled by processor. - */ + /** Link not handled by processor. */ static LinkResult none() { return null; } /** * Wrap the link text in a node. This is the normal behavior for links, e.g. for this: + * *


      * [my *text*](destination)
      * 
- * The text is {@code my *text*}, a text node and emphasis. The text is wrapped in a - * {@link org.commonmark.node.Link} node, which means the text is added as child nodes to it. * - * @param node the node to which the link text nodes will be added as child nodes + * The text is {@code my *text*}, a text node and emphasis. The text is wrapped in a {@link + * org.commonmark.node.Link} node, which means the text is added as child nodes to it. + * + * @param node the node to which the link text nodes will be added as child nodes * @param position the position to continue parsing from */ static LinkResult wrapTextIn(Node node, Position position) { @@ -31,12 +29,15 @@ static LinkResult wrapTextIn(Node node, Position position) { /** * Replace the link with a node. E.g. for this: + * *

      * [^foo]
      * 
- * The processor could decide to create a {@code FootnoteReference} node instead which replaces the link. * - * @param node the node to replace the link with + * The processor could decide to create a {@code FootnoteReference} node instead which replaces + * the link. + * + * @param node the node to replace the link with * @param position the position to continue parsing from */ static LinkResult replaceWith(Node node, Position position) { @@ -44,7 +45,8 @@ static LinkResult replaceWith(Node node, Position position) { } /** - * If a {@link LinkInfo#marker()} is present, include it in processing (i.e. treat it the same way as the brackets). + * If a {@link LinkInfo#marker()} is present, include it in processing (i.e. treat it the same + * way as the brackets). */ LinkResult includeMarker(); } diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/ParsedInline.java b/commonmark/src/main/java/org/commonmark/parser/beta/ParsedInline.java index 5d1402cae..c07a260fc 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/ParsedInline.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/ParsedInline.java @@ -1,14 +1,13 @@ package org.commonmark.parser.beta; +import java.util.Objects; import org.commonmark.internal.inline.ParsedInlineImpl; import org.commonmark.node.Node; -import java.util.Objects; - /** * The result of a single inline parser. Use the static methods to create instances. - *

- * This interface is not intended to be implemented by clients. + * + *

This interface is not intended to be implemented by clients. */ public interface ParsedInline { diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/Position.java b/commonmark/src/main/java/org/commonmark/parser/beta/Position.java index 3dbb4870f..5f45ef7f0 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/Position.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/Position.java @@ -1,8 +1,8 @@ package org.commonmark.parser.beta; /** - * Position within a {@link Scanner}. This is intentionally kept opaque so as not to expose the internal structure of - * the Scanner. + * Position within a {@link Scanner}. This is intentionally kept opaque so as not to expose the + * internal structure of the Scanner. */ public class Position { diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/Scanner.java b/commonmark/src/main/java/org/commonmark/parser/beta/Scanner.java index 324639493..1acf39ced 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/Scanner.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/Scanner.java @@ -1,29 +1,29 @@ package org.commonmark.parser.beta; +import java.util.List; import org.commonmark.node.SourceSpan; import org.commonmark.parser.SourceLine; import org.commonmark.parser.SourceLines; import org.commonmark.text.CharMatcher; -import java.util.List; - public class Scanner { /** - * Character representing the end of input source (or outside of the text in case of the "previous" methods). - *

- * Note that we can use NULL to represent this because CommonMark does not allow those in the input (we replace them - * in the beginning of parsing). + * Character representing the end of input source (or outside of the text in case of the + * "previous" methods). + * + *

Note that we can use NULL to represent this because CommonMark does not allow those in the + * input (we replace them in the beginning of parsing). */ public static final char END = '\0'; - // Lines without newlines at the end. The scanner will yield `\n` between lines because they're significant for - // parsing and the final output. There is no `\n` after the last line. + // Lines without newlines at the end. The scanner will yield `\n` between lines because they're + // significant for parsing and the final output. There is no `\n` after the last line. private final List lines; // Which line we're at. private int lineIndex; - // The index within the line. If index == length(), we pretend that there's a `\n` and only advance after we yield - // that. + // The index within the line. If index == length(), we pretend that there's a `\n` and only + // advance after we yield that. private int index; // Current line or "" if at the end of the lines (using "" instead of null saves a null check) @@ -135,8 +135,8 @@ public boolean next(char c) { } /** - * Check if we have the specified content on the line and advanced the position. Note that if you want to match - * newline characters, use {@link #next(char)}. + * Check if we have the specified content on the line and advanced the position. Note that if + * you want to match newline characters, use {@link #next(char)}. * * @param content the text content to match on a single line (excluding newline characters) * @return true if matched and position was advanced, false otherwise @@ -221,8 +221,8 @@ public int find(CharMatcher matcher) { } } - // Don't expose the int index, because it would be good if we could switch input to a List of lines later - // instead of one contiguous String. + // Don't expose the int index, because it would be good if we could switch input to a + // List of lines later instead of one contiguous String. public Position position() { return new Position(lineIndex, index); } @@ -234,8 +234,8 @@ public void setPosition(Position position) { setLine(lines.get(this.lineIndex)); } - // For cases where the caller appends the result to a StringBuilder, we could offer another method to avoid some - // unnecessary copying. + // For cases where the caller appends the result to a StringBuilder, we could offer another + // method to avoid some unnecessary copying. public SourceLines getSource(Position begin, Position end) { if (begin.lineIndex == end.lineIndex) { // Shortcut for common case of text from a single line @@ -271,11 +271,13 @@ private void setLine(SourceLine line) { private void checkPosition(int lineIndex, int index) { if (lineIndex < 0 || lineIndex >= lines.size()) { - throw new IllegalArgumentException("Line index " + lineIndex + " out of range, number of lines: " + lines.size()); + throw new IllegalArgumentException( + "Line index " + lineIndex + " out of range, number of lines: " + lines.size()); } SourceLine line = lines.get(lineIndex); if (index < 0 || index > line.getContent().length()) { - throw new IllegalArgumentException("Index " + index + " out of range, line length: " + line.getContent().length()); + throw new IllegalArgumentException( + "Index " + index + " out of range, line length: " + line.getContent().length()); } } } diff --git a/commonmark/src/main/java/org/commonmark/parser/beta/package-info.java b/commonmark/src/main/java/org/commonmark/parser/beta/package-info.java index 029d80507..f77deb1c9 100644 --- a/commonmark/src/main/java/org/commonmark/parser/beta/package-info.java +++ b/commonmark/src/main/java/org/commonmark/parser/beta/package-info.java @@ -1,4 +1,2 @@ -/** - * Experimental APIs to use for extensions. APIs are subject to change if necessary. - */ +/** Experimental APIs to use for extensions. APIs are subject to change if necessary. */ package org.commonmark.parser.beta; diff --git a/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParser.java b/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParser.java index 4fb1a05ac..69610a664 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParser.java @@ -1,13 +1,12 @@ package org.commonmark.parser.block; +import java.util.List; import org.commonmark.node.Block; import org.commonmark.node.DefinitionMap; import org.commonmark.node.SourceSpan; import org.commonmark.parser.InlineParser; import org.commonmark.parser.SourceLine; -import java.util.List; - public abstract class AbstractBlockParser implements BlockParser { @Override @@ -26,8 +25,7 @@ public boolean canContain(Block childBlock) { } @Override - public void addLine(SourceLine line) { - } + public void addLine(SourceLine line) {} @Override public void addSourceSpan(SourceSpan sourceSpan) { @@ -40,11 +38,8 @@ public List> getDefinitions() { } @Override - public void closeBlock() { - } + public void closeBlock() {} @Override - public void parseInlines(InlineParser inlineParser) { - } - + public void parseInlines(InlineParser inlineParser) {} } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParserFactory.java b/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParserFactory.java index e297ac831..1f19d59b8 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParserFactory.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParserFactory.java @@ -1,4 +1,3 @@ package org.commonmark.parser.block; -public abstract class AbstractBlockParserFactory implements BlockParserFactory { -} +public abstract class AbstractBlockParserFactory implements BlockParserFactory {} diff --git a/commonmark/src/main/java/org/commonmark/parser/block/BlockContinue.java b/commonmark/src/main/java/org/commonmark/parser/block/BlockContinue.java index dc2616065..d57656102 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/BlockContinue.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/BlockContinue.java @@ -2,13 +2,10 @@ import org.commonmark.internal.BlockContinueImpl; -/** - * Result object for continuing parsing of a block, see static methods for constructors. - */ +/** Result object for continuing parsing of a block, see static methods for constructors. */ public class BlockContinue { - protected BlockContinue() { - } + protected BlockContinue() {} public static BlockContinue none() { return null; @@ -25,5 +22,4 @@ public static BlockContinue atColumn(int newColumn) { public static BlockContinue finished() { return new BlockContinueImpl(-1, -1, true); } - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/BlockParser.java b/commonmark/src/main/java/org/commonmark/parser/block/BlockParser.java index 32ff2a474..e18105529 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/BlockParser.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/BlockParser.java @@ -1,33 +1,34 @@ package org.commonmark.parser.block; +import java.util.List; import org.commonmark.node.Block; import org.commonmark.node.DefinitionMap; import org.commonmark.node.SourceSpan; import org.commonmark.parser.InlineParser; import org.commonmark.parser.SourceLine; -import java.util.List; - /** * Parser for a specific block node. - *

- * Implementations should subclass {@link AbstractBlockParser} instead of implementing this directly. + * + *

Implementations should subclass {@link AbstractBlockParser} instead of implementing this + * directly. */ public interface BlockParser { /** - * Return true if the block that is parsed is a container (contains other blocks), or false if it's a leaf. + * Return true if the block that is parsed is a container (contains other blocks), or false if + * it's a leaf. */ boolean isContainer(); /** * Return true if the block can have lazy continuation lines. - *

- * Lazy continuation lines are lines that were rejected by this {@link #tryContinue(ParserState)} but didn't match - * any other block parsers either. - *

- * If true is returned here, those lines will get added via {@link #addLine(SourceLine)}. For false, the block is - * closed instead. + * + *

Lazy continuation lines are lines that were rejected by this {@link + * #tryContinue(ParserState)} but didn't match any other block parsers either. + * + *

If true is returned here, those lines will get added via {@link #addLine(SourceLine)}. For + * false, the block is closed instead. */ boolean canHaveLazyContinuationLines(); @@ -38,28 +39,28 @@ public interface BlockParser { BlockContinue tryContinue(ParserState parserState); /** - * Add the part of a line that belongs to this block parser to parse (i.e. without any container block markers). - * Note that the line will only include a {@link SourceLine#getSourceSpan()} if source spans are enabled for inlines. + * Add the part of a line that belongs to this block parser to parse (i.e. without any container + * block markers). Note that the line will only include a {@link SourceLine#getSourceSpan()} if + * source spans are enabled for inlines. */ void addLine(SourceLine line); /** - * Add a source span of the currently parsed block. The default implementation in {@link AbstractBlockParser} adds - * it to the block. Unless you have some complicated parsing where you need to check source positions, you don't - * need to override this. + * Add a source span of the currently parsed block. The default implementation in {@link + * AbstractBlockParser} adds it to the block. Unless you have some complicated parsing where you + * need to check source positions, you don't need to override this. * * @since 0.16.0 */ void addSourceSpan(SourceSpan sourceSpan); /** - * Return definitions parsed by this parser. The definitions returned here can later be accessed during inline - * parsing via {@link org.commonmark.parser.InlineParserContext#getDefinition}. + * Return definitions parsed by this parser. The definitions returned here can later be accessed + * during inline parsing via {@link org.commonmark.parser.InlineParserContext#getDefinition}. */ List> getDefinitions(); void closeBlock(); void parseInlines(InlineParser inlineParser); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/BlockParserFactory.java b/commonmark/src/main/java/org/commonmark/parser/block/BlockParserFactory.java index 729224761..ced38633b 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/BlockParserFactory.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/BlockParserFactory.java @@ -2,11 +2,11 @@ /** * Parser factory for a block node for determining when a block starts. - *

- * Implementations should subclass {@link AbstractBlockParserFactory} instead of implementing this directly. + * + *

Implementations should subclass {@link AbstractBlockParserFactory} instead of implementing + * this directly. */ public interface BlockParserFactory { BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/BlockStart.java b/commonmark/src/main/java/org/commonmark/parser/block/BlockStart.java index c41f1caa3..df26395bb 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/BlockStart.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/BlockStart.java @@ -2,24 +2,17 @@ import org.commonmark.internal.BlockStartImpl; -/** - * Result object for starting parsing of a block, see static methods for constructors. - */ +/** Result object for starting parsing of a block, see static methods for constructors. */ public abstract class BlockStart { - protected BlockStart() { - } + protected BlockStart() {} - /** - * Result for when there is no block start. - */ + /** Result for when there is no block start. */ public static BlockStart none() { return null; } - /** - * Start block(s) with the specified parser(s). - */ + /** Start block(s) with the specified parser(s). */ public static BlockStart of(BlockParser... blockParsers) { return new BlockStartImpl(blockParsers); } @@ -39,30 +32,32 @@ public static BlockStart of(BlockParser... blockParsers) { public abstract BlockStart atColumn(int newColumn); /** - * @deprecated use {@link #replaceParagraphLines(int)} instead; please raise an issue if that doesn't work for you - * for some reason. + * @deprecated use {@link #replaceParagraphLines(int)} instead; please raise an issue if that + * doesn't work for you for some reason. */ @Deprecated public abstract BlockStart replaceActiveBlockParser(); /** - * Replace a number of lines from the current paragraph (as returned by - * {@link MatchedBlockParser#getParagraphLines()}) with the new block. - *

- * This is useful for parsing blocks that start with normal paragraphs and only have special marker syntax in later - * lines, e.g. in this: + * Replace a number of lines from the current paragraph (as returned by {@link + * MatchedBlockParser#getParagraphLines()}) with the new block. + * + *

This is useful for parsing blocks that start with normal paragraphs and only have special + * marker syntax in later lines, e.g. in this: + * *

      * Foo
      * ===
      * 
- * The Foo line is initially parsed as a normal paragraph, then === is parsed as a heading - * marker, replacing the 1 paragraph line before. The end result is a single Heading block. - *

- * Note that source spans from the replaced lines are automatically added to the new block. * - * @param lines the number of lines to replace (at least 1); use {@link Integer#MAX_VALUE} to replace the whole - * paragraph + * The Foo line is initially parsed as a normal paragraph, then === is + * parsed as a heading marker, replacing the 1 paragraph line before. The end result is a single + * Heading block. + * + *

Note that source spans from the replaced lines are automatically added to the new block. + * + * @param lines the number of lines to replace (at least 1); use {@link Integer#MAX_VALUE} to + * replace the whole paragraph */ public abstract BlockStart replaceParagraphLines(int lines); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/MatchedBlockParser.java b/commonmark/src/main/java/org/commonmark/parser/block/MatchedBlockParser.java index c4619d8c2..3ad49f0ec 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/MatchedBlockParser.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/MatchedBlockParser.java @@ -3,20 +3,21 @@ import org.commonmark.parser.SourceLines; /** - * Open block parser that was last matched during the continue phase. This is different from the currently active - * block parser, as an unmatched block is only closed when a new block is started. - *

This interface is not intended to be implemented by clients.

+ * Open block parser that was last matched during the continue phase. This is different from the + * currently active block parser, as an unmatched block is only closed when a new block is started. + * + *

This interface is not intended to be implemented by clients. */ public interface MatchedBlockParser { BlockParser getMatchedBlockParser(); /** - * Returns the current paragraph lines if the matched block is a paragraph. If you want to use some or all of the - * lines for starting a new block instead, use {@link BlockStart#replaceParagraphLines(int)}. + * Returns the current paragraph lines if the matched block is a paragraph. If you want to use + * some or all of the lines for starting a new block instead, use {@link + * BlockStart#replaceParagraphLines(int)}. * * @return paragraph content or an empty list */ SourceLines getParagraphLines(); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/ParserState.java b/commonmark/src/main/java/org/commonmark/parser/block/ParserState.java index b32bbaee5..e9e3ec1b3 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/ParserState.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/ParserState.java @@ -4,7 +4,8 @@ /** * State of the parser that is used in block parsers. - *

This interface is not intended to be implemented by clients.

+ * + *

This interface is not intended to be implemented by clients. */ public interface ParserState { @@ -19,21 +20,24 @@ public interface ParserState { int getIndex(); /** - * @return the index of the next non-space character starting from {@link #getIndex()} (may be the same) (0-based) + * @return the index of the next non-space character starting from {@link #getIndex()} (may be + * the same) (0-based) */ int getNextNonSpaceIndex(); /** - * The column is the position within the line after tab characters have been processed as 4-space tab stops. - * If the line doesn't contain any tabs, it's the same as the {@link #getIndex()}. If the line starts with a tab, - * followed by text, then the column for the first character of the text is 4 (the index is 1). + * The column is the position within the line after tab characters have been processed as + * 4-space tab stops. If the line doesn't contain any tabs, it's the same as the {@link + * #getIndex()}. If the line starts with a tab, followed by text, then the column for the first + * character of the text is 4 (the index is 1). * * @return the current column within the line (0-based) */ int getColumn(); /** - * @return the indentation in columns (either by spaces or tab stop of 4), starting from {@link #getColumn()} + * @return the indentation in columns (either by spaces or tab stop of 4), starting from {@link + * #getColumn()} */ int getIndent(); @@ -46,5 +50,4 @@ public interface ParserState { * @return the deepest open block parser */ BlockParser getActiveBlockParser(); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/block/package-info.java b/commonmark/src/main/java/org/commonmark/parser/block/package-info.java index 095d4d565..dbb4adb1d 100644 --- a/commonmark/src/main/java/org/commonmark/parser/block/package-info.java +++ b/commonmark/src/main/java/org/commonmark/parser/block/package-info.java @@ -1,4 +1,2 @@ -/** - * Types for extending block parsing - */ +/** Types for extending block parsing */ package org.commonmark.parser.block; diff --git a/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterProcessor.java b/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterProcessor.java index 3b6abf214..67467210e 100644 --- a/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterProcessor.java +++ b/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterProcessor.java @@ -4,22 +4,24 @@ /** * Custom delimiter processor for additional delimiters besides {@code _} and {@code *}. - *

- * Note that implementations of this need to be thread-safe, the same instance may be used by multiple parsers. + * + *

Note that implementations of this need to be thread-safe, the same instance may be used by + * multiple parsers. * * @see org.commonmark.parser.beta.InlineContentParserFactory */ public interface DelimiterProcessor { /** - * @return the character that marks the beginning of a delimited node, must not clash with any built-in special - * characters + * @return the character that marks the beginning of a delimited node, must not clash with any + * built-in special characters */ char getOpeningCharacter(); /** - * @return the character that marks the the ending of a delimited node, must not clash with any built-in special - * characters. Note that for a symmetric delimiter such as "*", this is the same as the opening. + * @return the character that marks the the ending of a delimited node, must not clash with any + * built-in special characters. Note that for a symmetric delimiter such as "*", this is the + * same as the opening. */ char getClosingCharacter(); @@ -30,17 +32,18 @@ public interface DelimiterProcessor { /** * Process the delimiter runs. - *

- * The processor can examine the runs and the nodes and decide if it wants to process or not. If not, it should not - * change any nodes and return 0. If yes, it should do the processing (wrapping nodes, etc) and then return how many - * delimiters were used. - *

- * Note that removal (unlinking) of the used delimiter {@link Text} nodes is done by the caller. + * + *

The processor can examine the runs and the nodes and decide if it wants to process or not. + * If not, it should not change any nodes and return 0. If yes, it should do the processing + * (wrapping nodes, etc) and then return how many delimiters were used. + * + *

Note that removal (unlinking) of the used delimiter {@link Text} nodes is done by the + * caller. * * @param openingRun the opening delimiter run * @param closingRun the closing delimiter run - * @return how many delimiters were used; must not be greater than length of either opener or closer + * @return how many delimiters were used; must not be greater than length of either opener or + * closer */ int process(DelimiterRun openingRun, DelimiterRun closingRun); - } diff --git a/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterRun.java b/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterRun.java index 578eac96b..fd449c6b2 100644 --- a/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterRun.java +++ b/commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterRun.java @@ -2,9 +2,7 @@ import org.commonmark.node.Text; -/** - * A delimiter run is one or more of the same delimiter character, e.g. {@code ***}. - */ +/** A delimiter run is one or more of the same delimiter character, e.g. {@code ***}. */ public interface DelimiterRun { /** @@ -23,8 +21,8 @@ public interface DelimiterRun { int length(); /** - * @return the number of characters originally in this delimiter run; at the start of processing, this is the same - * as {{@link #length()}} + * @return the number of characters originally in this delimiter run; at the start of + * processing, this is the same as {{@link #length()}} */ int originalLength(); @@ -39,20 +37,20 @@ public interface DelimiterRun { Text getCloser(); /** - * Get the opening delimiter nodes for the specified length of delimiters. Length must be between 1 and - * {@link #length()}. - *

- * For example, for a delimiter run {@code ***}, calling this with 1 would return the last {@code *}. - * Calling it with 2 would return the second last {@code *} and the last {@code *}. + * Get the opening delimiter nodes for the specified length of delimiters. Length must be + * between 1 and {@link #length()}. + * + *

For example, for a delimiter run {@code ***}, calling this with 1 would return the last + * {@code *}. Calling it with 2 would return the second last {@code *} and the last {@code *}. */ Iterable getOpeners(int length); /** - * Get the closing delimiter nodes for the specified length of delimiters. Length must be between 1 and - * {@link #length()}. - *

- * For example, for a delimiter run {@code ***}, calling this with 1 would return the first {@code *}. - * Calling it with 2 would return the first {@code *} and the second {@code *}. + * Get the closing delimiter nodes for the specified length of delimiters. Length must be + * between 1 and {@link #length()}. + * + *

For example, for a delimiter run {@code ***}, calling this with 1 would return the first + * {@code *}. Calling it with 2 would return the first {@code *} and the second {@code *}. */ Iterable getClosers(int length); } diff --git a/commonmark/src/main/java/org/commonmark/parser/package-info.java b/commonmark/src/main/java/org/commonmark/parser/package-info.java index 2afb3b96d..753d665dd 100644 --- a/commonmark/src/main/java/org/commonmark/parser/package-info.java +++ b/commonmark/src/main/java/org/commonmark/parser/package-info.java @@ -1,4 +1,2 @@ -/** - * Parsing input text to AST nodes (see {@link org.commonmark.parser.Parser}) - */ +/** Parsing input text to AST nodes (see {@link org.commonmark.parser.Parser}) */ package org.commonmark.parser; diff --git a/commonmark/src/main/java/org/commonmark/renderer/NodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/NodeRenderer.java index 4ae4b5dcd..e8838eb5f 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/NodeRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/NodeRenderer.java @@ -1,12 +1,9 @@ package org.commonmark.renderer; -import org.commonmark.node.Node; - import java.util.Set; +import org.commonmark.node.Node; -/** - * A renderer for a set of node types. - */ +/** A renderer for a set of node types. */ public interface NodeRenderer { /** @@ -26,14 +23,12 @@ public interface NodeRenderer { * * @param rootNode the root (top-level) node */ - default void beforeRoot(Node rootNode) { - } + default void beforeRoot(Node rootNode) {} /** * Called after the root node is rendered, to do any final processing at the end. * * @param rootNode the root (top-level) node */ - default void afterRoot(Node rootNode) { - } + default void afterRoot(Node rootNode) {} } diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProvider.java b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProvider.java index 24a471d46..157eaf8a3 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProvider.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProvider.java @@ -1,29 +1,27 @@ package org.commonmark.renderer.html; -import org.commonmark.node.Node; - import java.util.Map; +import org.commonmark.node.Node; -/** - * Extension point for adding/changing attributes on HTML tags for a node. - */ +/** Extension point for adding/changing attributes on HTML tags for a node. */ public interface AttributeProvider { /** * Set the attributes for a HTML tag of the specified node by modifying the provided map. - *

- * This allows to change or even remove default attributes. With great power comes great responsibility. - *

- * The attribute key and values will be escaped (preserving character entities), so don't escape them here, - * otherwise they will be double-escaped. - *

- * This method may be called multiple times for the same node, if the node is rendered using multiple nested - * tags (e.g. code blocks). + * + *

This allows to change or even remove default attributes. With great power comes great + * responsibility. + * + *

The attribute key and values will be escaped (preserving character entities), so don't + * escape them here, otherwise they will be double-escaped. + * + *

This method may be called multiple times for the same node, if the node is rendered using + * multiple nested tags (e.g. code blocks). * * @param node the node to set attributes for - * @param tagName the HTML tag name that these attributes are for (e.g. {@code h1}, {@code pre}, {@code code}). + * @param tagName the HTML tag name that these attributes are for (e.g. {@code h1}, {@code pre}, + * {@code code}). * @param attributes the attributes, with any default attributes already set in the map */ void setAttributes(Node node, String tagName, Map attributes); - } diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderContext.java b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderContext.java index 0959932bc..cddaec43a 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderContext.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderContext.java @@ -2,8 +2,9 @@ /** * The context for attribute providers. - *

Note: There are currently no methods here, this is for future extensibility.

- *

This interface is not intended to be implemented by clients.

+ * + *

Note: There are currently no methods here, this is for future extensibility. + * + *

This interface is not intended to be implemented by clients. */ -public interface AttributeProviderContext { -} +public interface AttributeProviderContext {} diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderFactory.java b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderFactory.java index d4c12ca06..d093cbf98 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderFactory.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderFactory.java @@ -1,8 +1,6 @@ package org.commonmark.renderer.html; -/** - * Factory for instantiating new attribute providers when rendering is done. - */ +/** Factory for instantiating new attribute providers when rendering is done. */ public interface AttributeProviderFactory { /** diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/CoreHtmlNodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/html/CoreHtmlNodeRenderer.java index 5c536558e..d5e0d8afc 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/CoreHtmlNodeRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/CoreHtmlNodeRenderer.java @@ -1,11 +1,10 @@ package org.commonmark.renderer.html; -import org.commonmark.node.*; -import org.commonmark.renderer.NodeRenderer; - import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import org.commonmark.node.*; +import org.commonmark.renderer.NodeRenderer; /** * The node renderer that renders all the core nodes (comes last in the order of node renderers). @@ -42,8 +41,7 @@ public Set> getNodeTypes() { Code.class, HtmlInline.class, SoftLineBreak.class, - HardLineBreak.class - ); + HardLineBreak.class); } @Override @@ -69,9 +67,12 @@ public void visit(Heading heading) { @Override public void visit(Paragraph paragraph) { - boolean omitP = isInTightList(paragraph) || // - (context.shouldOmitSingleParagraphP() && paragraph.getParent() instanceof Document && // - paragraph.getPrevious() == null && paragraph.getNext() == null); + boolean omitP = + isInTightList(paragraph) + || (context.shouldOmitSingleParagraphP() + && paragraph.getParent() instanceof Document + && paragraph.getPrevious() == null + && paragraph.getNext() == null); if (!omitP) { html.line(); html.tag("p", getAttrs(paragraph, "p")); @@ -172,7 +173,8 @@ public void visit(ListItem listItem) { @Override public void visit(OrderedList orderedList) { - int start = orderedList.getMarkerStartNumber() != null ? orderedList.getMarkerStartNumber() : 1; + int start = + orderedList.getMarkerStartNumber() != null ? orderedList.getMarkerStartNumber() : 1; Map attrs = new LinkedHashMap<>(); if (start != 1) { attrs.put("start", String.valueOf(start)); @@ -268,7 +270,8 @@ private void renderCodeBlock(String literal, Node node, Map attr html.line(); } - private void renderListBlock(ListBlock listBlock, String tagName, Map attributes) { + private void renderListBlock( + ListBlock listBlock, String tagName, Map attributes) { html.line(); html.tag(tagName, attributes); html.line(); @@ -294,7 +297,8 @@ private Map getAttrs(Node node, String tagName) { return getAttrs(node, tagName, Map.of()); } - private Map getAttrs(Node node, String tagName, Map defaultAttributes) { + private Map getAttrs( + Node node, String tagName, Map defaultAttributes) { return context.extendAttributes(node, tagName, defaultAttributes); } diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/DefaultUrlSanitizer.java b/commonmark/src/main/java/org/commonmark/renderer/html/DefaultUrlSanitizer.java index 4c5bed12c..bdf59e809 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/DefaultUrlSanitizer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/DefaultUrlSanitizer.java @@ -3,10 +3,9 @@ import java.util.*; /** - * - * Allows http, https, mailto, and data protocols for url. - * Also allows protocol relative urls, and relative urls. - * Implementation based on https://github.com/OWASP/java-html-sanitizer/blob/f07e44b034a45d94d6fd010279073c38b6933072/src/main/java/org/owasp/html/FilterUrlByProtocolAttributePolicy.java + * Allows http, https, mailto, and data protocols for url. Also allows protocol relative urls, and + * relative urls. Implementation based on + * https://github.com/OWASP/java-html-sanitizer/blob/f07e44b034a45d94d6fd010279073c38b6933072/src/main/java/org/owasp/html/FilterUrlByProtocolAttributePolicy.java */ public class DefaultUrlSanitizer implements UrlSanitizer { private Set protocols; @@ -27,7 +26,7 @@ public String sanitizeLinkUrl(String url) { switch (url.charAt(i)) { case '/': case '#': - case '?': // No protocol. + case '?': // No protocol. break protocol_loop; case ':': String protocol = url.substring(0, i).toLowerCase(); @@ -40,7 +39,6 @@ public String sanitizeLinkUrl(String url) { return url; } - @Override public String sanitizeImageUrl(String url) { return sanitizeLinkUrl(url); @@ -74,7 +72,6 @@ private boolean isHtmlSpace(int ch) { return true; default: return false; - } } } diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererContext.java b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererContext.java index eecff0f44..b9119f0e5 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererContext.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererContext.java @@ -1,11 +1,10 @@ package org.commonmark.renderer.html; +import java.util.Map; import org.commonmark.node.Image; import org.commonmark.node.Link; import org.commonmark.node.Node; -import java.util.Map; - public interface HtmlNodeRendererContext { /** @@ -17,8 +16,9 @@ public interface HtmlNodeRendererContext { /** * Let extensions modify the HTML tag attributes. * - * @param node the node for which the attributes are applied - * @param tagName the HTML tag name that these attributes are for (e.g. {@code h1}, {@code pre}, {@code code}). + * @param node the node for which the attributes are applied + * @param tagName the HTML tag name that these attributes are for (e.g. {@code h1}, {@code pre}, + * {@code code}). * @param attributes the attributes that were calculated by the renderer * @return the extended attributes with added/updated/removed entries */ @@ -35,8 +35,9 @@ public interface HtmlNodeRendererContext { String getSoftbreak(); /** - * Render the specified node and its children using the configured renderers. This should be used to render child - * nodes; be careful not to pass the node that is being rendered, that would result in an endless loop. + * Render the specified node and its children using the configured renderers. This should be + * used to render child nodes; be careful not to pass the node that is being rendered, that + * would result in an endless loop. * * @param node the node to render */ @@ -48,7 +49,8 @@ public interface HtmlNodeRendererContext { boolean shouldEscapeHtml(); /** - * @return whether documents that only contain a single paragraph should be rendered without the {@code

} tag + * @return whether documents that only contain a single paragraph should be rendered without the + * {@code

} tag */ boolean shouldOmitSingleParagraphP(); @@ -59,7 +61,8 @@ public interface HtmlNodeRendererContext { boolean shouldSanitizeUrls(); /** - * @return Sanitizer to use for securing {@link Link} href and {@link Image} src if {@link #shouldSanitizeUrls()} is true. + * @return Sanitizer to use for securing {@link Link} href and {@link Image} src if {@link + * #shouldSanitizeUrls()} is true. * @since 0.14.0 */ UrlSanitizer urlSanitizer(); diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererFactory.java b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererFactory.java index 8a343bf0f..cbfd9bc65 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererFactory.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererFactory.java @@ -2,9 +2,7 @@ import org.commonmark.renderer.NodeRenderer; -/** - * Factory for instantiating new node renderers when rendering is done. - */ +/** Factory for instantiating new node renderers when rendering is done. */ public interface HtmlNodeRendererFactory { /** diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java index b0264fc72..46ae217ff 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlRenderer.java @@ -1,17 +1,17 @@ package org.commonmark.renderer.html; +import java.util.*; import org.commonmark.Extension; import org.commonmark.internal.renderer.NodeRendererMap; import org.commonmark.internal.util.Escaping; import org.commonmark.node.*; import org.commonmark.renderer.Renderer; -import java.util.*; - /** * Renders a tree of nodes to HTML. - *

- * Start with the {@link #builder} method to configure the renderer. Example: + * + *

Start with the {@link #builder} method to configure the renderer. Example: + * *


  * HtmlRenderer renderer = HtmlRenderer.builder().escapeHtml(true).build();
  * renderer.render(node);
@@ -69,9 +69,7 @@ public String render(Node node) {
         return sb.toString();
     }
 
-    /**
-     * Builder for configuring an {@link HtmlRenderer}. See methods for default configuration.
-     */
+    /** Builder for configuring an {@link HtmlRenderer}. See methods for default configuration. */
     public static class Builder {
 
         private String softbreak = "\n";
@@ -91,12 +89,12 @@ public HtmlRenderer build() {
         }
 
         /**
-         * The HTML to use for rendering a softbreak, defaults to {@code "\n"} (meaning the rendered result doesn't have
-         * a line break).
-         * 

- * Set it to {@code "
"} (or {@code "
"} to make them hard breaks. - *

- * Set it to {@code " "} to ignore line wrapping in the source. + * The HTML to use for rendering a softbreak, defaults to {@code "\n"} (meaning the rendered + * result doesn't have a line break). + * + *

Set it to {@code "
"} (or {@code "
"} to make them hard breaks. + * + *

Set it to {@code " "} to ignore line wrapping in the source. * * @param softbreak HTML for softbreak * @return {@code this} @@ -107,10 +105,12 @@ public Builder softbreak(String softbreak) { } /** - * Whether {@link HtmlInline} and {@link HtmlBlock} should be escaped, defaults to {@code false}. - *

- * Note that {@link HtmlInline} is only a tag itself, not the text between an opening tag and a closing tag. So - * markup in the text will be parsed as normal and is not affected by this option. + * Whether {@link HtmlInline} and {@link HtmlBlock} should be escaped, defaults to {@code + * false}. + * + *

Note that {@link HtmlInline} is only a tag itself, not the text between an opening tag + * and a closing tag. So markup in the text will be parsed as normal and is not affected by + * this option. * * @param escapeHtml true for escaping, false for preserving raw HTML * @return {@code this} @@ -121,7 +121,8 @@ public Builder escapeHtml(boolean escapeHtml) { } /** - * Whether {@link Image} src and {@link Link} href should be sanitized, defaults to {@code false}. + * Whether {@link Image} src and {@link Link} href should be sanitized, defaults to {@code + * false}. * * @param sanitizeUrls true for sanitization, false for preserving raw attribute * @return {@code this} @@ -146,13 +147,15 @@ public Builder urlSanitizer(UrlSanitizer urlSanitizer) { /** * Whether URLs of link or images should be percent-encoded, defaults to {@code false}. - *

- * If enabled, the following is done: + * + *

If enabled, the following is done: + * *

    - *
  • Existing percent-encoded parts are preserved (e.g. "%20" is kept as "%20")
  • - *
  • Reserved characters such as "/" are preserved, except for "[" and "]" (see encodeURI in JS)
  • - *
  • Unreserved characters such as "a" are preserved
  • - *
  • Other characters such umlauts are percent-encoded
  • + *
  • Existing percent-encoded parts are preserved (e.g. "%20" is kept as "%20") + *
  • Reserved characters such as "/" are preserved, except for "[" and "]" (see + * encodeURI in JS) + *
  • Unreserved characters such as "a" are preserved + *
  • Other characters such umlauts are percent-encoded *
* * @param percentEncodeUrls true to percent-encode, false for leaving as-is @@ -164,8 +167,9 @@ public Builder percentEncodeUrls(boolean percentEncodeUrls) { } /** - * Whether documents that only contain a single paragraph should be rendered without the {@code

} tag. Set to - * {@code true} to render without the tag; the default of {@code false} always renders the tag. + * Whether documents that only contain a single paragraph should be rendered without the + * {@code

} tag. Set to {@code true} to render without the tag; the default of {@code + * false} always renders the tag. * * @return {@code this} */ @@ -175,23 +179,26 @@ public Builder omitSingleParagraphP(boolean omitSingleParagraphP) { } /** - * Add a factory for an attribute provider for adding/changing HTML attributes to the rendered tags. + * Add a factory for an attribute provider for adding/changing HTML attributes to the + * rendered tags. * * @param attributeProviderFactory the attribute provider factory to add * @return {@code this} */ public Builder attributeProviderFactory(AttributeProviderFactory attributeProviderFactory) { - Objects.requireNonNull(attributeProviderFactory, "attributeProviderFactory must not be null"); + Objects.requireNonNull( + attributeProviderFactory, "attributeProviderFactory must not be null"); this.attributeProviderFactories.add(attributeProviderFactory); return this; } /** - * Add a factory for instantiating a node renderer (done when rendering). This allows to override the rendering - * of node types or define rendering for custom node types. - *

- * If multiple node renderers for the same node type are created, the one from the factory that was added first - * "wins". (This is how the rendering for core node types can be overridden; the default rendering comes last.) + * Add a factory for instantiating a node renderer (done when rendering). This allows to + * override the rendering of node types or define rendering for custom node types. + * + *

If multiple node renderers for the same node type are created, the one from the + * factory that was added first "wins". (This is how the rendering for core node types can + * be overridden; the default rendering comes last.) * * @param nodeRendererFactory the factory for creating a node renderer * @return {@code this} @@ -218,9 +225,7 @@ public Builder extensions(Iterable extensions) { } } - /** - * Extension for {@link HtmlRenderer}. - */ + /** Extension for {@link HtmlRenderer}. */ public interface HtmlRendererExtension extends Extension { void extend(Builder rendererBuilder); } @@ -275,7 +280,8 @@ public String encodeUrl(String url) { } @Override - public Map extendAttributes(Node node, String tagName, Map attributes) { + public Map extendAttributes( + Node node, String tagName, Map attributes) { Map attrs = new LinkedHashMap<>(attributes); setCustomAttributes(node, tagName, attrs); return attrs; diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlWriter.java b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlWriter.java index a4ac05d45..ebe638dc3 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/HtmlWriter.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/HtmlWriter.java @@ -1,10 +1,9 @@ package org.commonmark.renderer.html; -import org.commonmark.internal.util.Escaping; - import java.io.IOException; import java.util.Map; import java.util.Objects; +import org.commonmark.internal.util.Escaping; public class HtmlWriter { diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/UrlSanitizer.java b/commonmark/src/main/java/org/commonmark/renderer/html/UrlSanitizer.java index fb48ca361..dea6d55d2 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/UrlSanitizer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/UrlSanitizer.java @@ -4,10 +4,11 @@ import org.commonmark.node.Link; /** - * Sanitizes urls for img and a elements by whitelisting protocols. - * This is intended to prevent XSS payloads like [Click this totally safe url](javascript:document.xss=true;) - *

- * Implementation based on https://github.com/OWASP/java-html-sanitizer/blob/f07e44b034a45d94d6fd010279073c38b6933072/src/main/java/org/owasp/html/FilterUrlByProtocolAttributePolicy.java + * Sanitizes urls for img and a elements by whitelisting protocols. This is intended to prevent XSS + * payloads like [Click this totally safe url](javascript:document.xss=true;) + * + *

Implementation based on + * https://github.com/OWASP/java-html-sanitizer/blob/f07e44b034a45d94d6fd010279073c38b6933072/src/main/java/org/owasp/html/FilterUrlByProtocolAttributePolicy.java * * @since 0.14.0 */ diff --git a/commonmark/src/main/java/org/commonmark/renderer/html/package-info.java b/commonmark/src/main/java/org/commonmark/renderer/html/package-info.java index 014a4c69c..090ddc7e2 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/html/package-info.java +++ b/commonmark/src/main/java/org/commonmark/renderer/html/package-info.java @@ -1,4 +1,2 @@ -/** - * HTML rendering (see {@link org.commonmark.renderer.html.HtmlRenderer}) - */ +/** HTML rendering (see {@link org.commonmark.renderer.html.HtmlRenderer}) */ package org.commonmark.renderer.html; 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 5a81676f4..d4025128b 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java @@ -1,22 +1,22 @@ package org.commonmark.renderer.markdown; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.commonmark.node.*; import org.commonmark.renderer.NodeRenderer; import org.commonmark.text.AsciiMatcher; import org.commonmark.text.CharMatcher; import org.commonmark.text.Characters; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * The node renderer that renders all the core nodes (comes last in the order of node renderers). - *

- * Note that while sometimes it would be easier to record what kind of syntax was used on parsing (e.g. ATX vs Setext - * heading), this renderer is intended to also work for documents that were created by directly creating - * {@link Node Nodes} instead. So in order to support that, it sometimes needs to do a bit more work. + * + *

Note that while sometimes it would be easier to record what kind of syntax was used on parsing + * (e.g. ATX vs Setext heading), this renderer is intended to also work for documents that were + * created by directly creating {@link Node Nodes} instead. So in order to support that, it + * sometimes needs to do a bit more work. */ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRenderer { @@ -33,9 +33,10 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen protected final MarkdownNodeRendererContext context; private final MarkdownWriter writer; + /** - * If we're currently within a {@link BulletList} or {@link OrderedList}, this keeps the context of that list. - * It has a parent field so that it can represent a stack (for nested lists). + * If we're currently within a {@link BulletList} or {@link OrderedList}, this keeps the context + * of that list. It has a parent field so that it can represent a stack (for nested lists). */ private ListHolder listHolder; @@ -43,7 +44,11 @@ public CoreMarkdownNodeRenderer(MarkdownNodeRendererContext context) { this.context = context; this.writer = context.getWriter(); - textEscape = AsciiMatcher.builder().anyOf("[]<>`*_&\n\\").anyOf(context.getSpecialCharacters()).build(); + textEscape = + AsciiMatcher.builder() + .anyOf("[]<>`*_&\n\\") + .anyOf(context.getSpecialCharacters()) + .build(); textEscapeInHeading = AsciiMatcher.builder(textEscape).anyOf("#").build(); } @@ -69,8 +74,7 @@ public Set> getNodeTypes() { SoftLineBreak.class, StrongEmphasis.class, Text.class, - ThematicBreak.class - ); + ThematicBreak.class); } @Override @@ -108,8 +112,8 @@ public void visit(Heading heading) { visitChildren(heading); writer.line(); if (heading.getLevel() == 1) { - // Note that it would be nice to match the length of the contents instead of just using 3, but that's - // not easy. + // Note that it would be nice to match the length of the contents instead of + // just using 3, but that's not easy. writer.raw("==="); } else { writer.raw("---"); @@ -132,8 +136,8 @@ public void visit(Heading heading) { @Override public void visit(IndentedCodeBlock indentedCodeBlock) { 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) + // 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.writePrefix(" "); writer.pushPrefix(" "); List lines = getLines(literal); @@ -151,19 +155,24 @@ public void visit(IndentedCodeBlock indentedCodeBlock) { @Override public void visit(FencedCodeBlock codeBlock) { String literal = codeBlock.getLiteral(); - String fenceChar = codeBlock.getFenceCharacter() != null ? codeBlock.getFenceCharacter() : "`"; + String fenceChar = + codeBlock.getFenceCharacter() != null ? codeBlock.getFenceCharacter() : "`"; int openingFenceLength; if (codeBlock.getOpeningFenceLength() != null) { // If we have a known fence length, use it openingFenceLength = codeBlock.getOpeningFenceLength(); } else { - // Otherwise, calculate the closing fence length pessimistically, e.g. if the code block itself contains a - // line with ```, we need to use a fence of length 4. If ``` occurs with non-whitespace characters on a + // Otherwise, calculate the closing fence length pessimistically, e.g. if the code block + // itself contains a line with ```, we need to use a fence of length 4. If ``` occurs + // with non-whitespace characters on a // line, we technically don't need a longer fence, but it's not incorrect to do so. int fenceCharsInLiteral = findMaxRunLength(fenceChar, literal); openingFenceLength = Math.max(fenceCharsInLiteral + 1, 3); } - int closingFenceLength = codeBlock.getClosingFenceLength() != null ? codeBlock.getClosingFenceLength() : openingFenceLength; + int closingFenceLength = + codeBlock.getClosingFenceLength() != null + ? codeBlock.getClosingFenceLength() + : openingFenceLength; String openingFence = repeat(fenceChar, openingFenceLength); String closingFence = repeat(fenceChar, closingFenceLength); @@ -251,13 +260,19 @@ public void visit(ListItem listItem) { marker = repeat(" ", markerIndent) + bulletListHolder.marker; } else if (listHolder instanceof OrderedListHolder) { OrderedListHolder orderedListHolder = (OrderedListHolder) listHolder; - marker = repeat(" ", markerIndent) + orderedListHolder.number + orderedListHolder.delimiter; + marker = + repeat(" ", markerIndent) + + orderedListHolder.number + + orderedListHolder.delimiter; orderedListHolder.number++; } else { throw new IllegalStateException("Unknown list holder type: " + listHolder); } Integer contentIndent = listItem.getContentIndent(); - String spaces = contentIndent != null ? repeat(" ", Math.max(contentIndent - marker.length(), 1)) : " "; + String spaces = + contentIndent != null + ? repeat(" ", Math.max(contentIndent - marker.length(), 1)) + : " "; writer.writePrefix(marker); writer.writePrefix(spaces); writer.pushPrefix(repeat(" ", marker.length() + spaces.length())); @@ -281,10 +296,14 @@ public void visit(Code code) { writer.raw('`'); } // If the literal starts or ends with a backtick, surround it with a single space. - // If it starts and ends with a space (but is not only spaces), add an additional space (otherwise they would - // get removed on parsing). - boolean addSpace = literal.startsWith("`") || literal.endsWith("`") || - (literal.startsWith(" ") && literal.endsWith(" ") && Characters.hasNonSpace(literal)); + // If it starts and ends with a space (but is not only spaces), add an additional space + // (otherwise they would get removed on parsing). + boolean addSpace = + literal.startsWith("`") + || literal.endsWith("`") + || (literal.startsWith(" ") + && literal.endsWith(" ") + && Characters.hasNonSpace(literal)); if (addSpace) { writer.raw(' '); } @@ -345,38 +364,47 @@ public void visit(SoftLineBreak softLineBreak) { @Override public void visit(Text text) { - // Text is tricky. In Markdown special characters (`-`, `#` etc.) can be escaped (`\-`, `\#` etc.) so that - // they're parsed as plain text. Currently, whether a character was escaped or not is not recorded in the Node, - // so here we don't know. If we just wrote out those characters unescaped, the resulting Markdown would change - // meaning (turn into a list item, heading, etc.). - // You might say "Why not store that in the Node when parsing", but that wouldn't work for the use case where - // nodes are constructed directly instead of via parsing. This renderer needs to work for that too. - // So currently, when in doubt, we escape. For special characters only occurring at the beginning of a line, - // we only escape them then (we wouldn't want to escape every `.` for example). + // Text is tricky. In Markdown special characters (`-`, `#` etc.) can be escaped (`\-`, `\#` + // etc.) so that they're parsed as plain text. Currently, whether a character was escaped or + // not is not recorded in the Node, so here we don't know. If we just wrote out those + // characters unescaped, the resulting Markdown would change meaning (turn into a list item, + // heading, etc.). + // + // You might say "Why not store that in the Node when parsing", but that wouldn't work for + // the use case where nodes are constructed directly instead of via parsing. This renderer + // needs to work for that too. + // + // So currently, when in doubt, we escape. For special characters only occurring at the + // beginning of a line, we only escape them then (we wouldn't want to escape every `.` for + // example). String literal = text.getLiteral(); if (writer.isAtLineStart() && !literal.isEmpty()) { char c = literal.charAt(0); switch (c) { - case '-': { - // Would be ambiguous with a bullet list marker, escape - writer.raw("\\-"); - literal = literal.substring(1); - break; - } - case '#': { - // Would be ambiguous with an ATX heading, escape - writer.raw("\\#"); - literal = literal.substring(1); - break; - } - case '=': { - // Would be ambiguous with a Setext heading, escape unless it's the first line in the block - if (text.getPrevious() != null) { - writer.raw("\\="); + case '-': + { + // Would be ambiguous with a bullet list marker, escape + writer.raw("\\-"); literal = literal.substring(1); + break; + } + case '#': + { + // Would be ambiguous with an ATX heading, escape + writer.raw("\\#"); + literal = literal.substring(1); + break; + } + case '=': + { + // Would be ambiguous with a Setext heading, escape unless it's the first + // line in the block + if (text.getPrevious() != null) { + writer.raw("\\="); + literal = literal.substring(1); + } + break; } - break; - } case '0': case '1': case '2': @@ -386,26 +414,29 @@ public void visit(Text text) { case '6': case '7': case '8': - case '9': { - // Check for ordered list marker - Matcher m = orderedListMarkerPattern.matcher(literal); - if (m.find()) { - writer.raw(m.group(1)); - writer.raw("\\" + m.group(2)); - literal = literal.substring(m.end()); + case '9': + { + // Check for ordered list marker + Matcher m = orderedListMarkerPattern.matcher(literal); + if (m.find()) { + writer.raw(m.group(1)); + writer.raw("\\" + m.group(2)); + literal = literal.substring(m.end()); + } + break; + } + case '\t': + { + writer.raw(" "); + literal = literal.substring(1); + break; + } + case ' ': + { + writer.raw(" "); + literal = literal.substring(1); + break; } - break; - } - case '\t': { - writer.raw(" "); - literal = literal.substring(1); - break; - } - case ' ': { - writer.raw(" "); - literal = literal.substring(1); - break; - } } } @@ -467,13 +498,13 @@ private static String repeat(String s, int count) { } private static List getLines(String literal) { - // Without -1, split would discard all trailing empty strings, which is not what we want, e.g. it would - // return the same result for "abc", "abc\n" and "abc\n\n". + // Without -1, split would discard all trailing empty strings, which is not what we want, + // e.g. it would return the same result for "abc", "abc\n" and "abc\n\n". // With -1, it returns ["abc"], ["abc", ""] and ["abc", "", ""]. String[] parts = literal.split("\n", -1); if (parts[parts.length - 1].isEmpty()) { - // But we don't want the last empty string, as "\n" is used as a line terminator (not a separator), - // so return without the last element. + // But we don't want the last empty string, as "\n" is used as a line terminator (not a + // separator), so return without the last element. return List.of(parts).subList(0, parts.length - 1); } else { return List.of(parts); @@ -524,14 +555,18 @@ private static class OrderedListHolder extends ListHolder { protected OrderedListHolder(ListHolder parent, OrderedList orderedList) { super(parent); - delimiter = orderedList.getMarkerDelimiter() != null ? orderedList.getMarkerDelimiter() : "."; - number = orderedList.getMarkerStartNumber() != null ? orderedList.getMarkerStartNumber() : 1; + delimiter = + orderedList.getMarkerDelimiter() != null + ? orderedList.getMarkerDelimiter() + : "."; + number = + orderedList.getMarkerStartNumber() != null + ? orderedList.getMarkerStartNumber() + : 1; } } - /** - * Visits nodes to check if there are any soft or hard line breaks. - */ + /** Visits nodes to check if there are any soft or hard line breaks. */ private static class LineBreakVisitor extends AbstractVisitor { private boolean lineBreak = false; diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java index 40640d1b4..40c4fc5a9 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java @@ -1,8 +1,7 @@ package org.commonmark.renderer.markdown; -import org.commonmark.node.Node; - import java.util.Set; +import org.commonmark.node.Node; /** * Context that is passed to custom node renderers, see {@link MarkdownNodeRendererFactory#create}. @@ -15,16 +14,17 @@ public interface MarkdownNodeRendererContext { MarkdownWriter getWriter(); /** - * Render the specified node and its children using the configured renderers. This should be used to render child - * nodes; be careful not to pass the node that is being rendered, that would result in an endless loop. + * Render the specified node and its children using the configured renderers. This should be + * used to render child nodes; be careful not to pass the node that is being rendered, that + * would result in an endless loop. * * @param node the node to render */ void render(Node node); /** - * @return additional special characters that need to be escaped if they occur in normal text; currently only ASCII - * characters are allowed + * @return additional special characters that need to be escaped if they occur in normal text; + * currently only ASCII characters are allowed */ Set getSpecialCharacters(); } diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java index 14221ea56..d0bba666b 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java @@ -1,12 +1,9 @@ package org.commonmark.renderer.markdown; -import org.commonmark.renderer.NodeRenderer; - import java.util.Set; +import org.commonmark.renderer.NodeRenderer; -/** - * Factory for instantiating new node renderers for rendering custom nodes. - */ +/** Factory for instantiating new node renderers for rendering custom nodes. */ public interface MarkdownNodeRendererFactory { /** @@ -18,8 +15,8 @@ public interface MarkdownNodeRendererFactory { NodeRenderer create(MarkdownNodeRendererContext context); /** - * @return the additional special characters that this factory would like to have escaped in normal text; currently - * only ASCII characters are allowed + * @return the additional special characters that this factory would like to have escaped in + * normal text; currently only ASCII characters are allowed */ Set getSpecialCharacters(); } diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java index e4996fb08..1acde9a55 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownRenderer.java @@ -1,26 +1,29 @@ package org.commonmark.renderer.markdown; +import java.util.*; import org.commonmark.Extension; import org.commonmark.internal.renderer.NodeRendererMap; import org.commonmark.node.Node; import org.commonmark.renderer.NodeRenderer; import org.commonmark.renderer.Renderer; -import java.util.*; - /** * Renders nodes to Markdown (CommonMark syntax); use {@link #builder()} to create a renderer. - *

- * Note that it doesn't currently preserve the exact syntax of the original input Markdown (if any): + * + *

Note that it doesn't currently preserve the exact syntax of the original input Markdown (if + * any): + * *

    - *
  • Headings are output as ATX headings if possible (multi-line headings need Setext headings)
  • - *
  • Links are always rendered as inline links (no support for reference links yet)
  • - *
  • Escaping might be over-eager, e.g. a plain {@code *} might be escaped - * even though it doesn't need to be in that particular context
  • - *
  • Leading whitespace in paragraphs is not preserved
  • + *
  • Headings are output as ATX headings if possible (multi-line headings need Setext headings) + *
  • Links are always rendered as inline links (no support for reference links yet) + *
  • Escaping might be over-eager, e.g. a plain {@code *} might be escaped even though it + * doesn't need to be in that particular context + *
  • Leading whitespace in paragraphs is not preserved *
- * However, it should produce Markdown that is semantically equivalent to the input, i.e. if the Markdown was parsed - * again and compared against the original AST, it should be the same (minus bugs). + * + * However, it should produce Markdown that is semantically equivalent to the input, i.e. if the + * Markdown was parsed again and compared against the original AST, it should be the same (minus + * bugs). */ public class MarkdownRenderer implements Renderer { @@ -30,17 +33,18 @@ private MarkdownRenderer(Builder builder) { this.nodeRendererFactories = new ArrayList<>(builder.nodeRendererFactories.size() + 1); this.nodeRendererFactories.addAll(builder.nodeRendererFactories); // Add as last. This means clients can override the rendering of core nodes if they want. - this.nodeRendererFactories.add(new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new CoreMarkdownNodeRenderer(context); - } - - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }); + this.nodeRendererFactories.add( + new MarkdownNodeRendererFactory() { + @Override + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new CoreMarkdownNodeRenderer(context); + } + + @Override + public Set getSpecialCharacters() { + return Set.of(); + } + }); } /** @@ -80,11 +84,12 @@ public MarkdownRenderer build() { } /** - * Add a factory for instantiating a node renderer (done when rendering). This allows to override the rendering - * of node types or define rendering for custom node types. - *

- * If multiple node renderers for the same node type are created, the one from the factory that was added first - * "wins". (This is how the rendering for core node types can be overridden; the default rendering comes last.) + * Add a factory for instantiating a node renderer (done when rendering). This allows to + * override the rendering of node types or define rendering for custom node types. + * + *

If multiple node renderers for the same node type are created, the one from the + * factory that was added first "wins". (This is how the rendering for core node types can + * be overridden; the default rendering comes last.) * * @param nodeRendererFactory the factory for creating a node renderer * @return {@code this} @@ -101,7 +106,8 @@ public Builder nodeRendererFactory(MarkdownNodeRendererFactory nodeRendererFacto public Builder extensions(Iterable extensions) { for (Extension extension : extensions) { if (extension instanceof MarkdownRendererExtension) { - MarkdownRendererExtension markdownRendererExtension = (MarkdownRendererExtension) extension; + MarkdownRendererExtension markdownRendererExtension = + (MarkdownRendererExtension) extension; markdownRendererExtension.extend(this); } } @@ -109,13 +115,12 @@ public Builder extensions(Iterable extensions) { } } - /** - * Extension for {@link MarkdownRenderer} for rendering custom nodes. - */ + /** Extension for {@link MarkdownRenderer} for rendering custom nodes. */ public interface MarkdownRendererExtension extends Extension { /** - * Extend Markdown rendering, usually by registering custom node renderers using {@link Builder#nodeRendererFactory}. + * Extend Markdown rendering, usually by registering custom node renderers using {@link + * Builder#nodeRendererFactory}. * * @param rendererBuilder the renderer builder to extend */ 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 c9f427021..074a8e939 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownWriter.java @@ -1,13 +1,10 @@ package org.commonmark.renderer.markdown; -import org.commonmark.text.CharMatcher; - import java.io.IOException; import java.util.LinkedList; +import org.commonmark.text.CharMatcher; -/** - * Writer for Markdown (CommonMark) text. - */ +/** Writer for Markdown (CommonMark) text. */ public class MarkdownWriter { private final Appendable buffer; @@ -16,8 +13,9 @@ public class MarkdownWriter { private char lastChar; private boolean atLineStart = true; - // Stacks of settings that affect various rendering behaviors. The common pattern here is that callers use "push" to - // change a setting, render some nodes, and then "pop" the setting off the stack again to restore previous state. + // Stacks of settings that affect various rendering behaviors. The common pattern here is that + // callers use "push" to change a setting, render some nodes, and then "pop" the setting off the + // stack again to restore previous state. private final LinkedList prefixes = new LinkedList<>(); private final LinkedList tight = new LinkedList<>(); private final LinkedList rawEscapes = new LinkedList<>(); @@ -26,17 +24,13 @@ public MarkdownWriter(Appendable out) { buffer = out; } - /** - * Write the supplied string (raw/unescaped except if {@link #pushRawEscape} was used). - */ + /** Write the supplied string (raw/unescaped except if {@link #pushRawEscape} was used). */ public void raw(String s) { flushBlockSeparator(); write(s, null); } - /** - * Write the supplied character (raw/unescaped except if {@link #pushRawEscape} was used). - */ + /** Write the supplied character (raw/unescaped except if {@link #pushRawEscape} was used). */ public void raw(char c) { flushBlockSeparator(); write(c); @@ -45,7 +39,7 @@ public void raw(char c) { /** * Write the supplied string with escaping. * - * @param s the string to write + * @param s the string to write * @param escape which characters to escape */ public void text(String s, CharMatcher escape) { @@ -59,9 +53,7 @@ public void text(String s, CharMatcher escape) { atLineStart = false; } - /** - * Write a newline (line terminator). - */ + /** Write a newline (line terminator). */ public void line() { write('\n'); writePrefixes(); @@ -69,19 +61,20 @@ public void line() { } /** - * Enqueue a block separator to be written before the next text is written. Block separators are not written - * straight away because if there are no more blocks to write we don't want a separator (at the end of the document). + * Enqueue a block separator to be written before the next text is written. Block separators are + * not written straight away because if there are no more blocks to write we don't want a + * separator (at the end of the document). */ public void block() { - // Remember whether this should be a tight or loose separator now because tight could get changed in between - // this and the next flush. + // Remember whether this should be a tight or loose separator now because tight could get + // changed in between this and the next flush. blockSeparator = isTight() ? 1 : 2; atLineStart = true; } /** - * Push a prefix onto the top of the stack. All prefixes are written at the beginning of each line, until the - * prefix is popped again. + * Push a prefix onto the top of the stack. All prefixes are written at the beginning of each + * line, until the prefix is popped again. * * @param prefix the raw prefix string */ @@ -100,36 +93,32 @@ public void writePrefix(String prefix) { atLineStart = tmp; } - /** - * Remove the last prefix from the top of the stack. - */ + /** Remove the last prefix from the top of the stack. */ public void popPrefix() { prefixes.removeLast(); } /** - * Change whether blocks are tight or loose. Loose is the default where blocks are separated by a blank line. Tight - * is where blocks are not separated by a blank line. Tight blocks are used in lists, if there are no blank lines - * within the list. - *

- * Note that changing this does not affect block separators that have already been enqueued with {@link #block()}, - * only future ones. + * Change whether blocks are tight or loose. Loose is the default where blocks are separated by + * a blank line. Tight is where blocks are not separated by a blank line. Tight blocks are used + * in lists, if there are no blank lines within the list. + * + *

Note that changing this does not affect block separators that have already been enqueued + * with {@link #block()}, only future ones. */ public void pushTight(boolean tight) { this.tight.addLast(tight); } - /** - * Remove the last "tight" setting from the top of the stack. - */ + /** Remove the last "tight" setting from the top of the stack. */ public void popTight() { this.tight.removeLast(); } /** - * Escape the characters matching the supplied matcher, in all text (text and raw). This might be useful to - * extensions that add another layer of syntax, e.g. the tables extension that uses `|` to separate cells and needs - * all `|` characters to be escaped (even in code spans). + * Escape the characters matching the supplied matcher, in all text (text and raw). This might + * be useful to extensions that add another layer of syntax, e.g. the tables extension that uses + * `|` to separate cells and needs all `|` characters to be escaped (even in code spans). * * @param rawEscape the characters to escape in raw text */ @@ -137,9 +126,7 @@ public void pushRawEscape(CharMatcher rawEscape) { rawEscapes.add(rawEscape); } - /** - * Remove the last raw escape from the top of the stack. - */ + /** Remove the last raw escape from the top of the stack. */ public void popRawEscape() { rawEscapes.removeLast(); } @@ -152,7 +139,8 @@ public char getLastChar() { } /** - * @return whether we're at the line start (not counting any prefixes), i.e. after a {@link #line} or {@link #block}. + * @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 atLineStart; @@ -199,7 +187,8 @@ private void writePrefixes() { } /** - * If a block separator has been enqueued with {@link #block()} but not yet written, write it now. + * If a block separator has been enqueued with {@link #block()} but not yet written, write it + * now. */ private void flushBlockSeparator() { if (blockSeparator != 0) { diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java index f707671d5..8b6b9a464 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java +++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java @@ -1,4 +1,2 @@ -/** - * Markdown rendering (see {@link org.commonmark.renderer.markdown.MarkdownRenderer}) - */ +/** Markdown rendering (see {@link org.commonmark.renderer.markdown.MarkdownRenderer}) */ package org.commonmark.renderer.markdown; diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/CoreTextContentNodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/text/CoreTextContentNodeRenderer.java index 62a1a054d..22718d088 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/CoreTextContentNodeRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/CoreTextContentNodeRenderer.java @@ -1,10 +1,9 @@ package org.commonmark.renderer.text; +import java.util.Set; import org.commonmark.node.*; import org.commonmark.renderer.NodeRenderer; -import java.util.Set; - /** * The node renderer that renders all the core nodes (comes last in the order of node renderers). */ @@ -42,8 +41,7 @@ public Set> getNodeTypes() { Code.class, HtmlInline.class, SoftLineBreak.class, - HardLineBreak.class - ); + HardLineBreak.class); } @Override diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/LineBreakRendering.java b/commonmark/src/main/java/org/commonmark/renderer/text/LineBreakRendering.java index 27eeaf0da..cff8c2086 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/LineBreakRendering.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/LineBreakRendering.java @@ -1,19 +1,14 @@ package org.commonmark.renderer.text; -/** - * Control how line breaks are rendered. - */ +/** Control how line breaks are rendered. */ public enum LineBreakRendering { /** - * Strip all line breaks within blocks and between blocks, resulting in all the text in a single line. + * Strip all line breaks within blocks and between blocks, resulting in all the text in a single + * line. */ STRIP, - /** - * Use single line breaks between blocks, not a blank line (also render all lists as tight). - */ + /** Use single line breaks between blocks, not a blank line (also render all lists as tight). */ COMPACT, - /** - * Separate blocks by a blank line (and respect tight vs loose lists). - */ + /** Separate blocks by a blank line (and respect tight vs loose lists). */ SEPARATE_BLOCKS, } diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java index d6fcb8d77..fbed71f97 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java @@ -4,14 +4,12 @@ public interface TextContentNodeRendererContext { - /** - * Controls how line breaks should be rendered, see {@link LineBreakRendering}. - */ + /** Controls how line breaks should be rendered, see {@link LineBreakRendering}. */ LineBreakRendering lineBreakRendering(); /** - * @return true for stripping new lines and render text as "single line", - * false for keeping all line breaks. + * @return true for stripping new lines and render text as "single line", false for keeping all + * line breaks. * @deprecated Use {@link #lineBreakRendering()} instead */ @Deprecated @@ -23,8 +21,9 @@ public interface TextContentNodeRendererContext { TextContentWriter getWriter(); /** - * Render the specified node and its children using the configured renderers. This should be used to render child - * nodes; be careful not to pass the node that is being rendered, that would result in an endless loop. + * Render the specified node and its children using the configured renderers. This should be + * used to render child nodes; be careful not to pass the node that is being rendered, that + * would result in an endless loop. * * @param node the node to render */ diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererFactory.java b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererFactory.java index bf193dff4..bf471fb34 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererFactory.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererFactory.java @@ -2,9 +2,7 @@ import org.commonmark.renderer.NodeRenderer; -/** - * Factory for instantiating new node renderers when rendering is done. - */ +/** Factory for instantiating new node renderers when rendering is done. */ public interface TextContentNodeRendererFactory { /** diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentRenderer.java index 9a8bcc997..4a7d2d4bc 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentRenderer.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentRenderer.java @@ -1,16 +1,13 @@ package org.commonmark.renderer.text; +import java.util.ArrayList; +import java.util.List; import org.commonmark.Extension; import org.commonmark.internal.renderer.NodeRendererMap; import org.commonmark.node.Node; import org.commonmark.renderer.Renderer; -import java.util.ArrayList; -import java.util.List; - -/** - * Renders nodes to plain text content with minimal markup-like additions. - */ +/** Renders nodes to plain text content with minimal markup-like additions. */ public class TextContentRenderer implements Renderer { private final LineBreakRendering lineBreakRendering; @@ -37,7 +34,8 @@ public static Builder builder() { @Override public void render(Node node, Appendable output) { - RendererContext context = new RendererContext(new TextContentWriter(output, lineBreakRendering)); + RendererContext context = + new RendererContext(new TextContentWriter(output, lineBreakRendering)); context.render(node); } @@ -64,8 +62,8 @@ public TextContentRenderer build() { } /** - * Configure how line breaks (newlines) are rendered, see {@link LineBreakRendering}. - * The default is {@link LineBreakRendering#COMPACT}. + * Configure how line breaks (newlines) are rendered, see {@link LineBreakRendering}. The + * default is {@link LineBreakRendering#COMPACT}. * * @param lineBreakRendering the mode to use * @return {@code this} @@ -78,23 +76,26 @@ public Builder lineBreakRendering(LineBreakRendering lineBreakRendering) { /** * Set the value of flag for stripping new lines. * - * @param stripNewlines true for stripping new lines and render text as "single line", - * false for keeping all line breaks + * @param stripNewlines true for stripping new lines and render text as "single line", false + * for keeping all line breaks * @return {@code this} - * @deprecated Use {@link #lineBreakRendering(LineBreakRendering)} with {@link LineBreakRendering#STRIP} instead + * @deprecated Use {@link #lineBreakRendering(LineBreakRendering)} with {@link + * LineBreakRendering#STRIP} instead */ @Deprecated public Builder stripNewlines(boolean stripNewlines) { - this.lineBreakRendering = stripNewlines ? LineBreakRendering.STRIP : LineBreakRendering.COMPACT; + this.lineBreakRendering = + stripNewlines ? LineBreakRendering.STRIP : LineBreakRendering.COMPACT; return this; } /** - * Add a factory for instantiating a node renderer (done when rendering). This allows to override the rendering - * of node types or define rendering for custom node types. - *

- * If multiple node renderers for the same node type are created, the one from the factory that was added first - * "wins". (This is how the rendering for core node types can be overridden; the default rendering comes last.) + * Add a factory for instantiating a node renderer (done when rendering). This allows to + * override the rendering of node types or define rendering for custom node types. + * + *

If multiple node renderers for the same node type are created, the one from the + * factory that was added first "wins". (This is how the rendering for core node types can + * be overridden; the default rendering comes last.) * * @param nodeRendererFactory the factory for creating a node renderer * @return {@code this} @@ -120,9 +121,7 @@ public Builder extensions(Iterable extensions) { } } - /** - * Extension for {@link TextContentRenderer}. - */ + /** Extension for {@link TextContentRenderer}. */ public interface TextContentRendererExtension extends Extension { void extend(TextContentRenderer.Builder rendererBuilder); } diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentWriter.java b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentWriter.java index 1fb482785..e4cdfe373 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/TextContentWriter.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/TextContentWriter.java @@ -41,8 +41,13 @@ public void line() { } public void block() { - blockSeparator = lineBreakRendering == LineBreakRendering.STRIP ? " " : // - lineBreakRendering == LineBreakRendering.COMPACT || isTight() ? "\n" : "\n\n"; + blockSeparator = + lineBreakRendering == LineBreakRendering.STRIP + ? " " + : // + lineBreakRendering == LineBreakRendering.COMPACT || isTight() + ? "\n" + : "\n\n"; } public void resetBlock() { @@ -64,8 +69,8 @@ public void write(char c) { } /** - * Push a prefix onto the top of the stack. All prefixes are written at the beginning of each line, until the - * prefix is popped again. + * Push a prefix onto the top of the stack. All prefixes are written at the beginning of each + * line, until the prefix is popped again. * * @param prefix the raw prefix string */ @@ -82,28 +87,24 @@ public void writePrefix(String prefix) { write(prefix); } - /** - * Remove the last prefix from the top of the stack. - */ + /** Remove the last prefix from the top of the stack. */ public void popPrefix() { prefixes.removeLast(); } /** - * Change whether blocks are tight or loose. Loose is the default where blocks are separated by a blank line. Tight - * is where blocks are not separated by a blank line. Tight blocks are used in lists, if there are no blank lines - * within the list. - *

- * Note that changing this does not affect block separators that have already been enqueued with {@link #block()}, - * only future ones. + * Change whether blocks are tight or loose. Loose is the default where blocks are separated by + * a blank line. Tight is where blocks are not separated by a blank line. Tight blocks are used + * in lists, if there are no blank lines within the list. + * + *

Note that changing this does not affect block separators that have already been enqueued + * with {@link #block()}, only future ones. */ public void pushTight(boolean tight) { this.tight.addLast(tight); } - /** - * Remove the last "tight" setting from the top of the stack. - */ + /** Remove the last "tight" setting from the top of the stack. */ public void popTight() { this.tight.removeLast(); } @@ -119,7 +120,8 @@ private void writePrefixes() { } /** - * If a block separator has been enqueued with {@link #block()} but not yet written, write it now. + * If a block separator has been enqueued with {@link #block()} but not yet written, write it + * now. */ private void flushBlockSeparator() { if (blockSeparator != null) { diff --git a/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java b/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java index 8309f4bd6..06b4fa31f 100644 --- a/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java +++ b/commonmark/src/main/java/org/commonmark/renderer/text/package-info.java @@ -1,4 +1,5 @@ /** - * Plain text rendering with minimal markup (see {@link org.commonmark.renderer.text.TextContentRenderer}) + * Plain text rendering with minimal markup (see {@link + * org.commonmark.renderer.text.TextContentRenderer}) */ package org.commonmark.renderer.text; diff --git a/commonmark/src/main/java/org/commonmark/text/AsciiMatcher.java b/commonmark/src/main/java/org/commonmark/text/AsciiMatcher.java index 0d9cea458..b3e3b7651 100644 --- a/commonmark/src/main/java/org/commonmark/text/AsciiMatcher.java +++ b/commonmark/src/main/java/org/commonmark/text/AsciiMatcher.java @@ -3,9 +3,7 @@ import java.util.BitSet; import java.util.Set; -/** - * Char matcher that can match ASCII characters efficiently. - */ +/** Char matcher that can match ASCII characters efficiently. */ public class AsciiMatcher implements CharMatcher { private final BitSet set; diff --git a/commonmark/src/main/java/org/commonmark/text/CharMatcher.java b/commonmark/src/main/java/org/commonmark/text/CharMatcher.java index 2833e65c3..6143258a8 100644 --- a/commonmark/src/main/java/org/commonmark/text/CharMatcher.java +++ b/commonmark/src/main/java/org/commonmark/text/CharMatcher.java @@ -2,10 +2,10 @@ /** * Matcher interface for {@code char} values. - *

- * Note that because this matches on {@code char} values only (as opposed to {@code int} code points), - * this only operates on the level of code units and doesn't support supplementary characters - * (see {@link Character#isSupplementaryCodePoint(int)}). + * + *

Note that because this matches on {@code char} values only (as opposed to {@code int} code + * points), this only operates on the level of code units and doesn't support supplementary + * characters (see {@link Character#isSupplementaryCodePoint(int)}). */ public interface CharMatcher { diff --git a/commonmark/src/main/java/org/commonmark/text/Characters.java b/commonmark/src/main/java/org/commonmark/text/Characters.java index ee56ca67e..5832dd6cf 100644 --- a/commonmark/src/main/java/org/commonmark/text/Characters.java +++ b/commonmark/src/main/java/org/commonmark/text/Characters.java @@ -1,8 +1,6 @@ package org.commonmark.text; -/** - * Functions for finding characters in strings or checking characters. - */ +/** Functions for finding characters in strings or checking characters. */ public class Characters { public static int find(char c, CharSequence s, int startIndex) { @@ -57,7 +55,8 @@ public static boolean isSpaceOrTab(CharSequence s, int index) { } /** - * @see Unicode punctuation character + * @see Unicode + * punctuation character */ public static boolean isPunctuationCodePoint(int codePoint) { switch (Character.getType(codePoint)) { @@ -69,7 +68,7 @@ public static boolean isPunctuationCodePoint(int codePoint) { case Character.OTHER_PUNCTUATION: case Character.INITIAL_QUOTE_PUNCTUATION: case Character.FINAL_QUOTE_PUNCTUATION: - // General category "S" (symbol) + // General category "S" (symbol) case Character.MATH_SYMBOL: case Character.CURRENCY_SYMBOL: case Character.MODIFIER_SYMBOL: @@ -94,9 +93,11 @@ public static boolean isPunctuationCodePoint(int codePoint) { } /** - * Check whether the provided code point is a Unicode whitespace character as defined in the spec. + * Check whether the provided code point is a Unicode whitespace character as defined in the + * spec. * - * @see Unicode whitespace character + * @see Unicode + * whitespace character */ public static boolean isWhitespaceCodePoint(int codePoint) { switch (codePoint) { diff --git a/commonmark/src/main/java/org/commonmark/text/package-info.java b/commonmark/src/main/java/org/commonmark/text/package-info.java index ab9eec6f1..6e27fda21 100644 --- a/commonmark/src/main/java/org/commonmark/text/package-info.java +++ b/commonmark/src/main/java/org/commonmark/text/package-info.java @@ -1,4 +1,2 @@ -/** - * Text processing utilities for parsing and rendering, exported for use by extensions - */ +/** Text processing utilities for parsing and rendering, exported for use by extensions */ package org.commonmark.text; diff --git a/commonmark/src/test/java/org/commonmark/ProfilingMain.java b/commonmark/src/test/java/org/commonmark/ProfilingMain.java index 83b1bdaff..15e38bcde 100644 --- a/commonmark/src/test/java/org/commonmark/ProfilingMain.java +++ b/commonmark/src/test/java/org/commonmark/ProfilingMain.java @@ -1,17 +1,17 @@ package org.commonmark; +import java.util.ArrayList; +import java.util.List; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.TestResources; -import java.util.ArrayList; -import java.util.List; - public class ProfilingMain { private static final String SPEC = TestResources.readAsString(TestResources.getSpec()); - // private static final List SPEC_EXAMPLES = ExampleReader.readExampleSources(TestResources.getSpec()); + // private static final List SPEC_EXAMPLES = + // ExampleReader.readExampleSources(TestResources.getSpec()); private static final Parser PARSER = Parser.builder().build(); private static final HtmlRenderer RENDERER = HtmlRenderer.builder().build(); diff --git a/commonmark/src/test/java/org/commonmark/internal/DocumentParserTest.java b/commonmark/src/test/java/org/commonmark/internal/DocumentParserTest.java index a834665ff..815107523 100644 --- a/commonmark/src/test/java/org/commonmark/internal/DocumentParserTest.java +++ b/commonmark/src/test/java/org/commonmark/internal/DocumentParserTest.java @@ -1,31 +1,41 @@ package org.commonmark.internal; -import org.commonmark.node.*; -import org.commonmark.parser.block.BlockParserFactory; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.HashSet; import java.util.List; import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; +import org.commonmark.node.*; +import org.commonmark.parser.block.BlockParserFactory; +import org.junit.jupiter.api.Test; class DocumentParserTest { - private static final List CORE_FACTORIES = List.of( - new BlockQuoteParser.Factory(), - new HeadingParser.Factory(), - new FencedCodeBlockParser.Factory(), - new HtmlBlockParser.Factory(), - new ThematicBreakParser.Factory(), - new ListBlockParser.Factory(), - new IndentedCodeBlockParser.Factory()); + private static final List CORE_FACTORIES = + List.of( + new BlockQuoteParser.Factory(), + new HeadingParser.Factory(), + new FencedCodeBlockParser.Factory(), + new HtmlBlockParser.Factory(), + new ThematicBreakParser.Factory(), + new ListBlockParser.Factory(), + new IndentedCodeBlockParser.Factory()); @Test void calculateBlockParserFactories_givenAFullListOfAllowedNodes_includesAllCoreFactories() { List customParserFactories = List.of(); - var enabledBlockTypes = Set.of(BlockQuote.class, Heading.class, FencedCodeBlock.class, HtmlBlock.class, ThematicBreak.class, ListBlock.class, IndentedCodeBlock.class); + var enabledBlockTypes = + Set.of( + BlockQuote.class, + Heading.class, + FencedCodeBlock.class, + HtmlBlock.class, + ThematicBreak.class, + ListBlock.class, + IndentedCodeBlock.class); - List blockParserFactories = DocumentParser.calculateBlockParserFactories(customParserFactories, enabledBlockTypes); + List blockParserFactories = + DocumentParser.calculateBlockParserFactories( + customParserFactories, enabledBlockTypes); assertThat(blockParserFactories).hasSameSizeAs(CORE_FACTORIES); for (BlockParserFactory factory : CORE_FACTORIES) { @@ -39,13 +49,17 @@ void calculateBlockParserFactories_givenAListOfAllowedNodes_includesAssociatedFa Set> nodes = new HashSet<>(); nodes.add(IndentedCodeBlock.class); - List blockParserFactories = DocumentParser.calculateBlockParserFactories(customParserFactories, nodes); + List blockParserFactories = + DocumentParser.calculateBlockParserFactories(customParserFactories, nodes); assertThat(blockParserFactories).hasSize(1); - assertThat(hasInstance(blockParserFactories, IndentedCodeBlockParser.Factory.class)).isTrue(); + assertThat(hasInstance(blockParserFactories, IndentedCodeBlockParser.Factory.class)) + .isTrue(); } - private boolean hasInstance(List blockParserFactories, Class factoryClass) { + private boolean hasInstance( + List blockParserFactories, + Class factoryClass) { for (BlockParserFactory factory : blockParserFactories) { if (factory.getClass().equals(factoryClass)) { return true; @@ -53,5 +67,4 @@ private boolean hasInstance(List blockParserFactories, Class } return false; } - } diff --git a/commonmark/src/test/java/org/commonmark/internal/LinkReferenceDefinitionParserTest.java b/commonmark/src/test/java/org/commonmark/internal/LinkReferenceDefinitionParserTest.java index b69ada0e9..d9ee3a990 100644 --- a/commonmark/src/test/java/org/commonmark/internal/LinkReferenceDefinitionParserTest.java +++ b/commonmark/src/test/java/org/commonmark/internal/LinkReferenceDefinitionParserTest.java @@ -1,12 +1,12 @@ package org.commonmark.internal; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.internal.LinkReferenceDefinitionParser.State; import org.commonmark.node.LinkReferenceDefinition; import org.commonmark.parser.SourceLine; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - class LinkReferenceDefinitionParserTest { private final LinkReferenceDefinitionParser parser = new LinkReferenceDefinitionParser(); @@ -149,8 +149,8 @@ void testTitleMultiline2() { void testTitleMultiline3() { parse("[foo]: /url"); assertThat(parser.getState()).isEqualTo(State.START_TITLE); - // Note that this looks like a valid title until we parse "bad", at which point we need to treat the whole line - // as a paragraph line and discard any already parsed title. + // Note that this looks like a valid title until we parse "bad", at which point we need to + // treat the whole line as a paragraph line and discard any already parsed title. parse("\"title\" bad"); assertThat(parser.getState()).isEqualTo(State.PARAGRAPH); @@ -192,13 +192,15 @@ private static void assertState(String input, State state, String paragraphConte assertParagraphLines(paragraphContent, parser); } - private static void assertDef(LinkReferenceDefinition def, String label, String destination, String title) { + private static void assertDef( + LinkReferenceDefinition def, String label, String destination, String title) { assertThat(def.getLabel()).isEqualTo(label); assertThat(def.getDestination()).isEqualTo(destination); assertThat(def.getTitle()).isEqualTo(title); } - private static void assertParagraphLines(String expectedContent, LinkReferenceDefinitionParser parser) { + private static void assertParagraphLines( + String expectedContent, LinkReferenceDefinitionParser parser) { String actual = parser.getParagraphLines().getContent(); assertThat(actual).isEqualTo(expectedContent); } diff --git a/commonmark/src/test/java/org/commonmark/internal/util/EscapingTest.java b/commonmark/src/test/java/org/commonmark/internal/util/EscapingTest.java index eb2f1a801..dffe25be9 100644 --- a/commonmark/src/test/java/org/commonmark/internal/util/EscapingTest.java +++ b/commonmark/src/test/java/org/commonmark/internal/util/EscapingTest.java @@ -1,9 +1,9 @@ package org.commonmark.internal.util; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; + class EscapingTest { @Test diff --git a/commonmark/src/test/java/org/commonmark/internal/util/LineReaderTest.java b/commonmark/src/test/java/org/commonmark/internal/util/LineReaderTest.java index 7d0e0beb7..cacc8e579 100644 --- a/commonmark/src/test/java/org/commonmark/internal/util/LineReaderTest.java +++ b/commonmark/src/test/java/org/commonmark/internal/util/LineReaderTest.java @@ -1,17 +1,16 @@ package org.commonmark.internal.util; -import org.junit.jupiter.api.Test; +import static java.util.stream.Collectors.joining; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.commonmark.internal.util.LineReader.CHAR_BUFFER_SIZE; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; - -import static java.util.stream.Collectors.joining; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.commonmark.internal.util.LineReader.CHAR_BUFFER_SIZE; +import org.junit.jupiter.api.Test; class LineReaderTest { @@ -45,12 +44,16 @@ void testReadLine() throws IOException { assertLines(repeat("a", CHAR_BUFFER_SIZE) + "b", "\r"); assertLines("", "\n", "", "\r", "", "\r\n", "", "\n"); - assertLines("what", "\r", "are", "\r", "", "\r", "you", "\r\n", "", "\r\n", "even", "\n", "doing", null); + assertLines( + "what", "\r", "are", "\r", "", "\r", "you", "\r\n", "", "\r\n", "even", "\n", + "doing", null); } @Test void testClose() throws IOException { - var reader = new InputStreamReader(new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8))); + var reader = + new InputStreamReader( + new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8))); var lineReader = new LineReader(reader); lineReader.close(); lineReader.close(); @@ -58,7 +61,9 @@ void testClose() throws IOException { } private void assertLines(String... s) throws IOException { - assertThat(s.length).as("Expected parts needs to be even (pairs of content and terminator)").isEven(); + assertThat(s.length) + .as("Expected parts needs to be even (pairs of content and terminator)") + .isEven(); var input = Arrays.stream(s).filter(Objects::nonNull).collect(joining("")); assertLines(new StringReader(input), s); @@ -86,9 +91,7 @@ private static String repeat(String s, int count) { return sb.toString(); } - /** - * Reader that only reads 0 or 1 chars at a time to test the corner cases. - */ + /** Reader that only reads 0 or 1 chars at a time to test the corner cases. */ private static class SlowStringReader extends Reader { private final String s; @@ -118,7 +121,6 @@ public int read(char[] cbuf, int off, int len) { } @Override - public void close() { - } + public void close() {} } } diff --git a/commonmark/src/test/java/org/commonmark/parser/InlineContentParserTest.java b/commonmark/src/test/java/org/commonmark/parser/InlineContentParserTest.java index d0f45a6bc..167f74f25 100644 --- a/commonmark/src/test/java/org/commonmark/parser/InlineContentParserTest.java +++ b/commonmark/src/test/java/org/commonmark/parser/InlineContentParserTest.java @@ -1,5 +1,8 @@ package org.commonmark.parser; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import org.commonmark.node.*; import org.commonmark.parser.beta.InlineContentParser; import org.commonmark.parser.beta.InlineContentParserFactory; @@ -8,15 +11,14 @@ import org.commonmark.test.Nodes; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - class InlineContentParserTest { @Test void customInlineContentParser() { - var parser = Parser.builder().customInlineContentParserFactory(new DollarInlineParser.Factory()).build(); + var parser = + Parser.builder() + .customInlineContentParserFactory(new DollarInlineParser.Factory()) + .build(); var doc = parser.parse("Test: $hey *there*$ $you$\n\n# Heading $heading$\n"); var inline1 = Nodes.find(doc, DollarInline.class); assertThat(inline1.getLiteral()).isEqualTo("hey *there*"); @@ -28,7 +30,8 @@ void customInlineContentParser() { var inline3 = (DollarInline) heading.getLastChild(); assertThat(inline3.getLiteral()).isEqualTo("heading"); - // Parser is created for each inline snippet, which is why the index resets for the second snippet. + // Parser is created for each inline snippet, which is why the index resets for the second + // snippet. assertThat(inline1.getIndex()).isEqualTo(0); assertThat(inline2.getIndex()).isEqualTo(1); assertThat(inline3.getIndex()).isEqualTo(0); @@ -37,8 +40,12 @@ void customInlineContentParser() { @Test void bangInlineContentParser() { // See if using ! for a custom inline content parser works. - // ![] is used for images, but if it's not followed by a [, it should be possible to parse it differently. - var parser = Parser.builder().customInlineContentParserFactory(new BangInlineParser.Factory()).build(); + // ![] is used for images, but if it's not followed by a [, it should be possible to parse + // it differently. + var parser = + Parser.builder() + .customInlineContentParserFactory(new BangInlineParser.Factory()) + .build(); var doc = parser.parse("![image](url) !notimage"); var image = Nodes.find(doc, Image.class); assertThat(image.getDestination()).isEqualTo("url"); @@ -98,8 +105,7 @@ public InlineContentParser create() { } } - private static class BangInline extends CustomNode { - } + private static class BangInline extends CustomNode {} private static class BangInlineParser implements InlineContentParser { diff --git a/commonmark/src/test/java/org/commonmark/parser/beta/LinkProcessorTest.java b/commonmark/src/test/java/org/commonmark/parser/beta/LinkProcessorTest.java index ef8739128..60dea4814 100644 --- a/commonmark/src/test/java/org/commonmark/parser/beta/LinkProcessorTest.java +++ b/commonmark/src/test/java/org/commonmark/parser/beta/LinkProcessorTest.java @@ -1,21 +1,23 @@ package org.commonmark.parser.beta; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.node.Link; import org.commonmark.node.Text; import org.commonmark.parser.Parser; import org.commonmark.test.Nodes; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - class LinkProcessorTest { @Test void testLinkMarkerShouldNotBeIncludedByDefault() { - // If a link marker is registered but is not processed, the built-in link processor shouldn't consume it. - // And I think by default, other processors shouldn't consume it either (by accident). - // So requiring processors to opt into including the marker is better than requiring them to opt out, - // because processors that look for a marker already need to write some code to deal with the marker anyway, + // If a link marker is registered but is not processed, the built-in link processor + // shouldn't consume it. And I think by default, other processors shouldn't consume it + // either (by accident). + // So requiring processors to opt into including the marker is better + // than requiring them to opt out, because processors that look for a marker already need to + // write some code to deal with the marker anyway, // and will have tests ensuring that the marker is part of the parsed node, not the text. var parser = Parser.builder().linkMarker('^').build(); var doc = parser.parse("^[test](url)"); diff --git a/commonmark/src/test/java/org/commonmark/parser/beta/ScannerTest.java b/commonmark/src/test/java/org/commonmark/parser/beta/ScannerTest.java index bd74cab0e..437812866 100644 --- a/commonmark/src/test/java/org/commonmark/parser/beta/ScannerTest.java +++ b/commonmark/src/test/java/org/commonmark/parser/beta/ScannerTest.java @@ -1,21 +1,18 @@ package org.commonmark.parser.beta; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.node.SourceSpan; import org.commonmark.parser.SourceLine; import org.commonmark.parser.SourceLines; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - class ScannerTest { @Test void testNext() { - Scanner scanner = new Scanner(List.of( - SourceLine.of("foo bar", null)), - 0, 4); + Scanner scanner = new Scanner(List.of(SourceLine.of("foo bar", null)), 0, 4); assertThat(scanner.peek()).isEqualTo('b'); scanner.next(); assertThat(scanner.peek()).isEqualTo('a'); @@ -27,10 +24,8 @@ void testNext() { @Test void testMultipleLines() { - Scanner scanner = new Scanner(List.of( - SourceLine.of("ab", null), - SourceLine.of("cde", null)), - 0, 0); + Scanner scanner = + new Scanner(List.of(SourceLine.of("ab", null), SourceLine.of("cde", null)), 0, 0); assertThat(scanner.hasNext()).isTrue(); assertThat(scanner.peekPreviousCodePoint()).isEqualTo('\0'); assertThat(scanner.peek()).isEqualTo('a'); @@ -84,70 +79,77 @@ void testCodePoints() { @Test void testTextBetween() { - Scanner scanner = new Scanner(List.of( - SourceLine.of("ab", SourceSpan.of(10, 3, 13, 2)), - SourceLine.of("cde", SourceSpan.of(11, 4, 20, 3))), - 0, 0); + Scanner scanner = + new Scanner( + List.of( + SourceLine.of("ab", SourceSpan.of(10, 3, 13, 2)), + SourceLine.of("cde", SourceSpan.of(11, 4, 20, 3))), + 0, + 0); Position start = scanner.position(); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), - "a", - SourceSpan.of(10, 3, 13, 1)); + assertSourceLines( + scanner.getSource(start, scanner.position()), "a", SourceSpan.of(10, 3, 13, 1)); Position afterA = scanner.position(); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), - "ab", - SourceSpan.of(10, 3, 13, 2)); + assertSourceLines( + scanner.getSource(start, scanner.position()), "ab", SourceSpan.of(10, 3, 13, 2)); Position afterB = scanner.position(); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), - "ab\n", - SourceSpan.of(10, 3, 13, 2)); + assertSourceLines( + scanner.getSource(start, scanner.position()), "ab\n", SourceSpan.of(10, 3, 13, 2)); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), + assertSourceLines( + scanner.getSource(start, scanner.position()), "ab\nc", SourceSpan.of(10, 3, 13, 2), SourceSpan.of(11, 4, 20, 1)); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), + assertSourceLines( + scanner.getSource(start, scanner.position()), "ab\ncd", SourceSpan.of(10, 3, 13, 2), SourceSpan.of(11, 4, 20, 2)); scanner.next(); - assertSourceLines(scanner.getSource(start, scanner.position()), + assertSourceLines( + scanner.getSource(start, scanner.position()), "ab\ncde", SourceSpan.of(10, 3, 13, 2), SourceSpan.of(11, 4, 20, 3)); - assertSourceLines(scanner.getSource(afterA, scanner.position()), + assertSourceLines( + scanner.getSource(afterA, scanner.position()), "b\ncde", SourceSpan.of(10, 4, 14, 1), SourceSpan.of(11, 4, 20, 3)); - assertSourceLines(scanner.getSource(afterB, scanner.position()), + assertSourceLines( + scanner.getSource(afterB, scanner.position()), "\ncde", SourceSpan.of(11, 4, 20, 3)); } - private void assertSourceLines(SourceLines sourceLines, String expectedContent, SourceSpan... expectedSourceSpans) { + private void assertSourceLines( + SourceLines sourceLines, String expectedContent, SourceSpan... expectedSourceSpans) { assertThat(sourceLines.getContent()).isEqualTo(expectedContent); assertThat(sourceLines.getSourceSpans()).isEqualTo(List.of(expectedSourceSpans)); } @Test void nextString() { - Scanner scanner = Scanner.of(SourceLines.of(List.of( - SourceLine.of("hey ya", null), - SourceLine.of("hi", null)))); + Scanner scanner = + Scanner.of( + SourceLines.of( + List.of(SourceLine.of("hey ya", null), SourceLine.of("hi", null)))); assertThat(scanner.next("hoy")).isFalse(); assertThat(scanner.next("hey")).isTrue(); assertThat(scanner.next(' ')).isTrue(); 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 6a468a08e..c51fb895f 100644 --- a/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java +++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/MarkdownRendererTest.java @@ -1,15 +1,14 @@ package org.commonmark.renderer.markdown; +import static org.assertj.core.api.Assertions.assertThat; +import static org.commonmark.testutil.Asserts.assertRendering; + +import java.util.Set; import org.commonmark.node.*; import org.commonmark.parser.Parser; import org.commonmark.renderer.NodeRenderer; import org.junit.jupiter.api.Test; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.commonmark.testutil.Asserts.assertRendering; - public class MarkdownRendererTest { // Leaf blocks @@ -120,12 +119,14 @@ public void testBulletListItems() { // Tight list where the second item contains a loose list assertRoundTrip("- Foo\n - Bar\n \n - Baz\n"); - // List item indent. This is a tricky one, but here the amount of space between the list marker and "one" - // determines whether "two" is part of the list item or an indented code block. - // In this case, it's an indented code block because it's not indented enough to be part of the list item. - // If the renderer would just use "- one", then "two" would change from being an indented code block to being - // a paragraph in the list item! So it is important for the renderer to preserve the content indent of the list - // item. + // List item indent. This is a tricky one, but here the amount of space between the list + // marker and "one" determines whether "two" is part of the list item or an indented code + // block. + // In this case, it's an indented code block because it's not indented enough to be part of + // the list item. + // If the renderer would just use "- one", then "two" would change from being an indented + // code block to being a paragraph in the list item! So it is important for the renderer to + // preserve the content indent of the list item. assertRoundTrip(" - one\n\n two\n"); // Empty list @@ -192,8 +193,8 @@ public void testTabs() { @Test public void testEscaping() { - // These are a bit tricky. We always escape some characters, even though they only need escaping if they would - // otherwise result in a different parse result (e.g. a link): + // These are a bit tricky. We always escape some characters, even though they only need + // escaping if they would otherwise result in a different parse result (e.g. a link): assertRoundTrip("\\[a\\](/uri)\n"); assertRoundTrip("\\`abc\\`\n"); @@ -250,7 +251,8 @@ public void testEmphasis() { // Not emphasis (needs * inside words) assertRoundTrip("foo\\_bar\\_\n"); - // Even when rendering a manually constructed tree, the emphasis delimiter needs to be chosen correctly. + // Even when rendering a manually constructed tree, the emphasis delimiter needs to be + // chosen correctly. Document doc = new Document(); Paragraph p = new Paragraph(); doc.appendChild(p); @@ -312,29 +314,31 @@ public void testSoftLineBreaks() { @Test public void overrideNodeRender() { - var nodeRendererFactory = new MarkdownNodeRendererFactory() { - @Override - public NodeRenderer create(MarkdownNodeRendererContext context) { - return new NodeRenderer() { + var nodeRendererFactory = + new MarkdownNodeRendererFactory() { @Override - public Set> getNodeTypes() { - return Set.of(Heading.class); + public NodeRenderer create(MarkdownNodeRendererContext context) { + return new NodeRenderer() { + @Override + public Set> getNodeTypes() { + return Set.of(Heading.class); + } + + @Override + public void render(Node node) { + context.getWriter().raw("# Custom heading"); + } + }; } @Override - public void render(Node node) { - context.getWriter().raw("# Custom heading"); + public Set getSpecialCharacters() { + return Set.of(); } }; - } - - @Override - public Set getSpecialCharacters() { - return Set.of(); - } - }; - MarkdownRenderer renderer = MarkdownRenderer.builder().nodeRendererFactory(nodeRendererFactory).build(); + MarkdownRenderer renderer = + MarkdownRenderer.builder().nodeRendererFactory(nodeRendererFactory).build(); String rendered = renderer.render(parse("# Hello")); assertThat(rendered).isEqualTo("# Custom heading\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 3b88df55d..e2584eeb8 100644 --- a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java +++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java @@ -1,5 +1,11 @@ package org.commonmark.renderer.markdown; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; @@ -8,27 +14,22 @@ import org.commonmark.testutil.example.ExampleReader; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - /** * Tests Markdown rendering using the examples in the spec like this: + * *

    - *
  1. Parses the source to an AST and then renders it back to Markdown
  2. - *
  3. Parses that to an AST and then renders it to HTML
  4. - *
  5. Compares that HTML to the expected HTML of the example: - * If it's the same, then the expected elements were preserved in the Markdown rendering
  6. + *
  7. Parses the source to an AST and then renders it back to Markdown + *
  8. Parses that to an AST and then renders it to HTML + *
  9. Compares that HTML to the expected HTML of the example: If it's the same, then the expected + * elements were preserved in the Markdown rendering *
*/ public class SpecMarkdownRendererTest { public static final MarkdownRenderer MARKDOWN_RENDERER = MarkdownRenderer.builder().build(); // The spec says URL-escaping is optional, but the examples assume that it's enabled. - public static final HtmlRenderer HTML_RENDERER = HtmlRenderer.builder().percentEncodeUrls(true).build(); + public static final HtmlRenderer HTML_RENDERER = + HtmlRenderer.builder().percentEncodeUrls(true).build(); @Test public void testCoverage() { diff --git a/commonmark/src/test/java/org/commonmark/test/AbstractVisitorTest.java b/commonmark/src/test/java/org/commonmark/test/AbstractVisitorTest.java index edb6936f4..fbc7f86bb 100644 --- a/commonmark/src/test/java/org/commonmark/test/AbstractVisitorTest.java +++ b/commonmark/src/test/java/org/commonmark/test/AbstractVisitorTest.java @@ -1,21 +1,22 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.node.*; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class AbstractVisitorTest { @Test public void replacingNodeInVisitorShouldNotDestroyVisitOrder() { - Visitor visitor = new AbstractVisitor() { - @Override - public void visit(Text text) { - text.insertAfter(new Code(text.getLiteral())); - text.unlink(); - } - }; + Visitor visitor = + new AbstractVisitor() { + @Override + public void visit(Text text) { + text.insertAfter(new Code(text.getLiteral())); + text.unlink(); + } + }; Paragraph paragraph = new Paragraph(); paragraph.appendChild(new Text("foo")); diff --git a/commonmark/src/test/java/org/commonmark/test/BlockParserFactoryTest.java b/commonmark/src/test/java/org/commonmark/test/BlockParserFactoryTest.java index b733d7970..e88423aed 100644 --- a/commonmark/src/test/java/org/commonmark/test/BlockParserFactoryTest.java +++ b/commonmark/src/test/java/org/commonmark/test/BlockParserFactoryTest.java @@ -1,5 +1,8 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.node.*; import org.commonmark.parser.IncludeSourceSpans; import org.commonmark.parser.InlineParser; @@ -8,15 +11,12 @@ import org.commonmark.parser.block.*; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - public class BlockParserFactoryTest { @Test public void customBlockParserFactory() { - var parser = Parser.builder().customBlockParserFactory(new DashBlockParser.Factory()).build(); + var parser = + Parser.builder().customBlockParserFactory(new DashBlockParser.Factory()).build(); // The dashes would normally be a ThematicBreak var doc = parser.parse("hey\n\n---\n"); @@ -28,10 +28,11 @@ public void customBlockParserFactory() { @Test public void replaceActiveBlockParser() { - var parser = Parser.builder() - .customBlockParserFactory(new StarHeadingBlockParser.Factory()) - .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) - .build(); + var parser = + Parser.builder() + .customBlockParserFactory(new StarHeadingBlockParser.Factory()) + .includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES) + .build(); var doc = parser.parse("a\nbc\n***\n"); @@ -46,16 +47,17 @@ public void replaceActiveBlockParser() { assertThat(((Text) bc).getLiteral()).isEqualTo("bc"); assertThat(bc.getNext()).isNull(); - assertThat(heading.getSourceSpans()).isEqualTo(List.of( - SourceSpan.of(0, 0, 0, 1), - SourceSpan.of(1, 0, 2, 2), - SourceSpan.of(2, 0, 5, 3))); + assertThat(heading.getSourceSpans()) + .isEqualTo( + List.of( + SourceSpan.of(0, 0, 0, 1), + SourceSpan.of(1, 0, 2, 2), + SourceSpan.of(2, 0, 5, 3))); assertThat(a.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 1))); assertThat(bc.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(1, 0, 2, 2))); } - private static class DashBlock extends CustomBlock { - } + private static class DashBlock extends CustomBlock {} private static class DashBlockParser extends AbstractBlockParser { @@ -83,8 +85,7 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar } } - private static class StarHeading extends CustomBlock { - } + private static class StarHeading extends CustomBlock {} private static class StarHeadingBlockParser extends AbstractBlockParser { diff --git a/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java b/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java index 3f2f0d611..06007e4bd 100644 --- a/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java +++ b/commonmark/src/test/java/org/commonmark/test/DelimitedTest.java @@ -1,38 +1,36 @@ package org.commonmark.test; -import org.commonmark.node.*; -import org.commonmark.parser.Parser; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; +import org.commonmark.node.*; +import org.commonmark.parser.Parser; +import org.junit.jupiter.api.Test; public class DelimitedTest { @Test public void emphasisDelimiters() { - String input = "* *emphasis* \n" - + "* **strong** \n" - + "* _important_ \n" - + "* __CRITICAL__ \n"; + String input = + "* *emphasis* \n" + "* **strong** \n" + "* _important_ \n" + "* __CRITICAL__ \n"; Parser parser = Parser.builder().build(); Node document = parser.parse(input); final List list = new ArrayList<>(); - Visitor visitor = new AbstractVisitor() { - @Override - public void visit(Emphasis node) { - list.add(node); - } - - @Override - public void visit(StrongEmphasis node) { - list.add(node); - } - }; + Visitor visitor = + new AbstractVisitor() { + @Override + public void visit(Emphasis node) { + list.add(node); + } + + @Override + public void visit(StrongEmphasis node) { + list.add(node); + } + }; document.accept(visitor); assertThat(list).hasSize(4); diff --git a/commonmark/src/test/java/org/commonmark/test/DelimiterProcessorTest.java b/commonmark/src/test/java/org/commonmark/test/DelimiterProcessorTest.java index e4920120d..a185c293c 100644 --- a/commonmark/src/test/java/org/commonmark/test/DelimiterProcessorTest.java +++ b/commonmark/src/test/java/org/commonmark/test/DelimiterProcessorTest.java @@ -1,5 +1,10 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Locale; +import java.util.Set; import org.commonmark.node.CustomNode; import org.commonmark.node.Node; import org.commonmark.node.Text; @@ -13,23 +18,20 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import java.util.Locale; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - public class DelimiterProcessorTest extends RenderingTestCase { - private static final Parser PARSER = Parser.builder().customDelimiterProcessor(new AsymmetricDelimiterProcessor()).build(); - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().nodeRendererFactory(new UpperCaseNodeRendererFactory()).build(); + private static final Parser PARSER = + Parser.builder().customDelimiterProcessor(new AsymmetricDelimiterProcessor()).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().nodeRendererFactory(new UpperCaseNodeRendererFactory()).build(); @Test public void delimiterProcessorWithInvalidDelimiterUse() { - Parser parser = Parser.builder() - .customDelimiterProcessor(new CustomDelimiterProcessor(':', 0)) - .customDelimiterProcessor(new CustomDelimiterProcessor(';', -1)) - .build(); + Parser parser = + Parser.builder() + .customDelimiterProcessor(new CustomDelimiterProcessor(':', 0)) + .customDelimiterProcessor(new CustomDelimiterProcessor(';', -1)) + .build(); assertThat(RENDERER.render(parser.parse(":test:"))).isEqualTo("

:test:

\n"); assertThat(RENDERER.render(parser.parse(";test;"))).isEqualTo("

;test;

\n"); } @@ -51,21 +53,26 @@ public void asymmetricDelimiter() { @Test public void multipleDelimitersWithDifferentLengths() { - Parser parser = Parser.builder() - .customDelimiterProcessor(new OneDelimiterProcessor()) - .customDelimiterProcessor(new TwoDelimiterProcessor()) - .build(); - assertThat(RENDERER.render(parser.parse("+one+ ++two++"))).isEqualTo("

(1)one(/1) (2)two(/2)

\n"); - assertThat(RENDERER.render(parser.parse("+++both+++"))).isEqualTo("

(1)(2)both(/2)(/1)

\n"); + Parser parser = + Parser.builder() + .customDelimiterProcessor(new OneDelimiterProcessor()) + .customDelimiterProcessor(new TwoDelimiterProcessor()) + .build(); + assertThat(RENDERER.render(parser.parse("+one+ ++two++"))) + .isEqualTo("

(1)one(/1) (2)two(/2)

\n"); + assertThat(RENDERER.render(parser.parse("+++both+++"))) + .isEqualTo("

(1)(2)both(/2)(/1)

\n"); } @Test public void multipleDelimitersWithSameLengthConflict() { - assertThatThrownBy(() -> - Parser.builder() - .customDelimiterProcessor(new OneDelimiterProcessor()) - .customDelimiterProcessor(new OneDelimiterProcessor()) - .build()).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> + Parser.builder() + .customDelimiterProcessor(new OneDelimiterProcessor()) + .customDelimiterProcessor(new OneDelimiterProcessor()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Override @@ -139,8 +146,7 @@ public int process(DelimiterRun openingRun, DelimiterRun closingRun) { } } - private static class UpperCaseNode extends CustomNode { - } + private static class UpperCaseNode extends CustomNode {} private static class UpperCaseNodeRendererFactory implements HtmlNodeRendererFactory { @@ -166,7 +172,9 @@ public Set> getNodeTypes() { @Override public void render(Node node) { UpperCaseNode upperCaseNode = (UpperCaseNode) node; - for (Node child = upperCaseNode.getFirstChild(); child != null; child = child.getNext()) { + for (Node child = upperCaseNode.getFirstChild(); + child != null; + child = child.getNext()) { if (child instanceof Text) { Text text = (Text) child; text.setLiteral(text.getLiteral().toUpperCase(Locale.ENGLISH)); diff --git a/commonmark/src/test/java/org/commonmark/test/FencedCodeBlockParserTest.java b/commonmark/src/test/java/org/commonmark/test/FencedCodeBlockParserTest.java index 443b0fa51..a07519756 100644 --- a/commonmark/src/test/java/org/commonmark/test/FencedCodeBlockParserTest.java +++ b/commonmark/src/test/java/org/commonmark/test/FencedCodeBlockParserTest.java @@ -1,5 +1,7 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.node.FencedCodeBlock; import org.commonmark.node.Node; import org.commonmark.parser.Parser; @@ -7,8 +9,6 @@ import org.commonmark.testutil.RenderingTestCase; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class FencedCodeBlockParserTest extends RenderingTestCase { private static final Parser PARSER = Parser.builder().build(); @@ -24,36 +24,35 @@ public void backtickInfo() { @Test public void backtickInfoDoesntAllowBacktick() { - assertRendering("```info ` test\ncode\n```", + assertRendering( + "```info ` test\ncode\n```", "

```info ` test\ncode

\n
\n"); } @Test public void backtickAndTildeCantBeMixed() { - assertRendering("``~`\ncode\n``~`", - "

~` code ~`

\n"); + assertRendering("``~`\ncode\n``~`", "

~` code ~`

\n"); } @Test public void closingCanHaveSpacesAfter() { - assertRendering("```\ncode\n``` ", - "
code\n
\n"); + assertRendering("```\ncode\n``` ", "
code\n
\n"); } @Test public void closingCanNotHaveNonSpaces() { - assertRendering("```\ncode\n``` a", - "
code\n``` a\n
\n"); + assertRendering("```\ncode\n``` a", "
code\n``` a\n
\n"); } @Test public void issue151() { - assertRendering("```\nthis code\n\nshould not have BRs or paragraphs in it\nok\n```", - "
this code\n" +
-                        "\n" +
-                        "should not have BRs or paragraphs in it\n" +
-                        "ok\n" +
-                        "
\n"); + assertRendering( + "```\nthis code\n\nshould not have BRs or paragraphs in it\nok\n```", + "
this code\n"
+                        + "\n"
+                        + "should not have BRs or paragraphs in it\n"
+                        + "ok\n"
+                        + "
\n"); } @Override diff --git a/commonmark/src/test/java/org/commonmark/test/HtmlRendererTest.java b/commonmark/src/test/java/org/commonmark/test/HtmlRendererTest.java index 92751147a..cd0811c23 100644 --- a/commonmark/src/test/java/org/commonmark/test/HtmlRendererTest.java +++ b/commonmark/src/test/java/org/commonmark/test/HtmlRendererTest.java @@ -1,45 +1,62 @@ package org.commonmark.test; -import org.commonmark.node.*; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.NodeRenderer; -import org.commonmark.renderer.html.*; -import org.commonmark.testutil.TestResources; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.Map; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.Future; - -import static org.assertj.core.api.Assertions.assertThat; +import org.commonmark.node.*; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.NodeRenderer; +import org.commonmark.renderer.html.*; +import org.commonmark.testutil.TestResources; +import org.junit.jupiter.api.Test; public class HtmlRendererTest { @Test public void htmlAllowingShouldNotEscapeInlineHtml() { - String rendered = htmlAllowingRenderer().render(parse("paragraph with inline & html")); - assertThat(rendered).isEqualTo("

paragraph with inline & html

\n"); + String rendered = + htmlAllowingRenderer() + .render( + parse( + "paragraph with inline & html")); + assertThat(rendered) + .isEqualTo( + "

paragraph with inline & html

\n"); } @Test public void htmlAllowingShouldNotEscapeBlockHtml() { - String rendered = htmlAllowingRenderer().render(parse("
block &
")); + String rendered = + htmlAllowingRenderer() + .render(parse("
block &
")); assertThat(rendered).isEqualTo("
block &
\n"); } @Test public void htmlEscapingShouldEscapeInlineHtml() { - String rendered = htmlEscapingRenderer().render(parse("paragraph with inline & html")); + String rendered = + htmlEscapingRenderer() + .render( + parse( + "paragraph with inline & html")); // Note that & is not escaped, as it's a normal text node, not part of the inline HTML. - assertThat(rendered).isEqualTo("

paragraph with <span id='foo' class="bar">inline & html</span>

\n"); + assertThat(rendered) + .isEqualTo( + "

paragraph with <span id='foo' class="bar">inline & html</span>

\n"); } @Test public void htmlEscapingShouldEscapeHtmlBlocks() { - String rendered = htmlEscapingRenderer().render(parse("
block &
")); - assertThat(rendered).isEqualTo("

<div id='foo' class="bar">block &amp;</div>

\n"); + String rendered = + htmlEscapingRenderer() + .render(parse("
block &
")); + assertThat(rendered) + .isEqualTo( + "

<div id='foo' class="bar">block &amp;</div>

\n"); } @Test @@ -50,9 +67,12 @@ public void textEscaping() { @Test public void characterReferencesWithoutSemicolonsShouldNotBeParsedShouldBeEscaped() { - String input = "[example](javascript:alert('XSS'))"; + String input = + "[example](javascript:alert('XSS'))"; String rendered = defaultRenderer().render(parse(input)); - assertThat(rendered).isEqualTo("

example

\n"); + assertThat(rendered) + .isEqualTo( + "

example

\n"); } @Test @@ -61,7 +81,8 @@ public void attributeEscaping() { Link link = new Link(); link.setDestination(":"); paragraph.appendChild(link); - assertThat(defaultRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(defaultRenderer().render(paragraph)) + .isEqualTo("

\n"); } @Test @@ -70,7 +91,8 @@ public void rawUrlsShouldNotFilterDangerousProtocols() { Link link = new Link(); link.setDestination("javascript:alert(5);"); paragraph.appendChild(link); - assertThat(rawUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(rawUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); } @Test @@ -79,13 +101,15 @@ public void sanitizedUrlsShouldSetRelNoFollow() { Link link = new Link(); link.setDestination("/exampleUrl"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); paragraph = new Paragraph(); link = new Link(); link.setDestination("https://google.com"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); } @Test @@ -94,26 +118,31 @@ public void sanitizedUrlsShouldAllowSafeProtocols() { Link link = new Link(); link.setDestination("http://google.com"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); paragraph = new Paragraph(); link = new Link(); link.setDestination("https://google.com"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); paragraph = new Paragraph(); link = new Link(); link.setDestination("mailto:foo@bar.example.com"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); - String image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAAQSURBVBhXY/iPBVBf8P9/AG8TY51nJdgkAAAAAElFTkSuQmCC"; + String image = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAAQSURBVBhXY/iPBVBf8P9/AG8TY51nJdgkAAAAAElFTkSuQmCC"; paragraph = new Paragraph(); link = new Link(); link.setDestination(image); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); } @Test @@ -122,74 +151,103 @@ public void sanitizedUrlsShouldFilterDangerousProtocols() { Link link = new Link(); link.setDestination("javascript:alert(5);"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); paragraph = new Paragraph(); link = new Link(); link.setDestination("ftp://google.com"); paragraph.appendChild(link); - assertThat(sanitizeUrlsRenderer().render(paragraph)).isEqualTo("

\n"); + assertThat(sanitizeUrlsRenderer().render(paragraph)) + .isEqualTo("

\n"); } @Test public void percentEncodeUrlDisabled() { - assertThat(defaultRenderer().render(parse("[a](foo&bar)"))).isEqualTo("

a

\n"); - assertThat(defaultRenderer().render(parse("[a](ä)"))).isEqualTo("

a

\n"); - assertThat(defaultRenderer().render(parse("[a](foo%20bar)"))).isEqualTo("

a

\n"); + assertThat(defaultRenderer().render(parse("[a](foo&bar)"))) + .isEqualTo("

a

\n"); + assertThat(defaultRenderer().render(parse("[a](ä)"))) + .isEqualTo("

a

\n"); + assertThat(defaultRenderer().render(parse("[a](foo%20bar)"))) + .isEqualTo("

a

\n"); } @Test public void percentEncodeUrl() { // Entities are escaped anyway - assertThat(percentEncodingRenderer().render(parse("[a](foo&bar)"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo&bar)"))) + .isEqualTo("

a

\n"); // Existing encoding is preserved - assertThat(percentEncodingRenderer().render(parse("[a](foo%20bar)"))).isEqualTo("

a

\n"); - assertThat(percentEncodingRenderer().render(parse("[a](foo%61)"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%20bar)"))) + .isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%61)"))) + .isEqualTo("

a

\n"); // Invalid encoding is escaped - assertThat(percentEncodingRenderer().render(parse("[a](foo%)"))).isEqualTo("

a

\n"); - assertThat(percentEncodingRenderer().render(parse("[a](foo%a)"))).isEqualTo("

a

\n"); - assertThat(percentEncodingRenderer().render(parse("[a](foo%a_)"))).isEqualTo("

a

\n"); - assertThat(percentEncodingRenderer().render(parse("[a](foo%xx)"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%)"))) + .isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%a)"))) + .isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%a_)"))) + .isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](foo%xx)"))) + .isEqualTo("

a

\n"); // Reserved characters are preserved, except for '[' and ']' - assertThat(percentEncodingRenderer().render(parse("[a](!*'();:@&=+$,/?#[])"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](!*'();:@&=+$,/?#[])"))) + .isEqualTo("

a

\n"); // Unreserved characters are preserved - assertThat(percentEncodingRenderer().render(parse("[a](ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~)"))).isEqualTo("

a

\n"); + assertThat( + percentEncodingRenderer() + .render( + parse( + "[a](ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~)"))) + .isEqualTo( + "

a

\n"); // Other characters are percent-encoded (LATIN SMALL LETTER A WITH DIAERESIS) - assertThat(percentEncodingRenderer().render(parse("[a](ä)"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](ä)"))) + .isEqualTo("

a

\n"); // Other characters are percent-encoded (MUSICAL SYMBOL G CLEF, surrogate pair in UTF-16) - assertThat(percentEncodingRenderer().render(parse("[a](\uD834\uDD1E)"))).isEqualTo("

a

\n"); + assertThat(percentEncodingRenderer().render(parse("[a](\uD834\uDD1E)"))) + .isEqualTo("

a

\n"); } @Test public void attributeProviderForCodeBlock() { - AttributeProviderFactory custom = context -> (node, tagName, attributes) -> { - if (node instanceof FencedCodeBlock && tagName.equals("code")) { - FencedCodeBlock fencedCodeBlock = (FencedCodeBlock) node; - // Remove the default attribute for info - attributes.remove("class"); - // Put info in custom attribute instead - attributes.put("data-custom", fencedCodeBlock.getInfo()); - } else if (node instanceof FencedCodeBlock && tagName.equals("pre")) { - attributes.put("data-code-block", "fenced"); - } - }; + AttributeProviderFactory custom = + context -> + (node, tagName, attributes) -> { + if (node instanceof FencedCodeBlock && tagName.equals("code")) { + FencedCodeBlock fencedCodeBlock = (FencedCodeBlock) node; + // Remove the default attribute for info + attributes.remove("class"); + // Put info in custom attribute instead + attributes.put("data-custom", fencedCodeBlock.getInfo()); + } else if (node instanceof FencedCodeBlock && tagName.equals("pre")) { + attributes.put("data-code-block", "fenced"); + } + }; HtmlRenderer renderer = HtmlRenderer.builder().attributeProviderFactory(custom).build(); String rendered = renderer.render(parse("```info\ncontent\n```")); - assertThat(rendered).isEqualTo("
content\n
\n"); + assertThat(rendered) + .isEqualTo( + "
content\n
\n"); String rendered2 = renderer.render(parse("```evil\"\ncontent\n```")); - assertThat(rendered2).isEqualTo("
content\n
\n"); + assertThat(rendered2) + .isEqualTo( + "
content\n
\n"); } @Test public void attributeProviderForImage() { - AttributeProviderFactory custom = context -> (node, tagName, attributes) -> { - if (node instanceof Image) { - attributes.remove("alt"); - attributes.put("test", "hey"); - } - }; + AttributeProviderFactory custom = + context -> + (node, tagName, attributes) -> { + if (node instanceof Image) { + attributes.remove("alt"); + attributes.put("test", "hey"); + } + }; HtmlRenderer renderer = HtmlRenderer.builder().attributeProviderFactory(custom).build(); String rendered = renderer.render(parse("![foo](/url)\n")); @@ -198,15 +256,18 @@ public void attributeProviderForImage() { @Test public void attributeProviderFactoryNewInstanceForEachRender() { - AttributeProviderFactory factory = context -> new AttributeProvider() { - int i = 0; - - @Override - public void setAttributes(Node node, String tagName, Map attributes) { - attributes.put("key", "" + i); - i++; - } - }; + AttributeProviderFactory factory = + context -> + new AttributeProvider() { + int i = 0; + + @Override + public void setAttributes( + Node node, String tagName, Map attributes) { + attributes.put("key", "" + i); + i++; + } + }; HtmlRenderer renderer = HtmlRenderer.builder().attributeProviderFactory(factory).build(); String rendered = renderer.render(parse("text node")); @@ -216,51 +277,60 @@ public void setAttributes(Node node, String tagName, Map attribu @Test public void overrideNodeRender() { - HtmlNodeRendererFactory nodeRendererFactory = context -> new NodeRenderer() { - @Override - public Set> getNodeTypes() { - return Set.of(Link.class); - } - - @Override - public void render(Node node) { - context.getWriter().text("test"); - } - }; - - HtmlRenderer renderer = HtmlRenderer.builder().nodeRendererFactory(nodeRendererFactory).build(); + HtmlNodeRendererFactory nodeRendererFactory = + context -> + new NodeRenderer() { + @Override + public Set> getNodeTypes() { + return Set.of(Link.class); + } + + @Override + public void render(Node node) { + context.getWriter().text("test"); + } + }; + + HtmlRenderer renderer = + HtmlRenderer.builder().nodeRendererFactory(nodeRendererFactory).build(); String rendered = renderer.render(parse("foo [bar](/url)")); assertThat(rendered).isEqualTo("

foo test

\n"); } @Test public void orderedListStartZero() { - assertThat(defaultRenderer().render(parse("0. Test\n"))).isEqualTo("
    \n
  1. Test
  2. \n
\n"); + assertThat(defaultRenderer().render(parse("0. Test\n"))) + .isEqualTo("
    \n
  1. Test
  2. \n
\n"); } @Test public void imageAltTextWithSoftLineBreak() { - assertThat(defaultRenderer().render(parse("![foo\nbar](/url)\n"))).isEqualTo("

\"foo\nbar\"

\n"); + assertThat(defaultRenderer().render(parse("![foo\nbar](/url)\n"))) + .isEqualTo("

\"foo\nbar\"

\n"); } @Test public void imageAltTextWithHardLineBreak() { - assertThat(defaultRenderer().render(parse("![foo \nbar](/url)\n"))).isEqualTo("

\"foo\nbar\"

\n"); + assertThat(defaultRenderer().render(parse("![foo \nbar](/url)\n"))) + .isEqualTo("

\"foo\nbar\"

\n"); } @Test public void imageAltTextWithEntities() { - assertThat(defaultRenderer().render(parse("![foo ä](/url)\n"))).isEqualTo("

\"foo

\n"); + assertThat(defaultRenderer().render(parse("![foo ä](/url)\n"))) + .isEqualTo("

\"foo

\n"); } @Test public void imageAltTextWithInlines() { - assertThat(defaultRenderer().render(parse("![_foo_ **bar** [link](/url)](/url)\n"))).isEqualTo("

\"foo

\n"); + assertThat(defaultRenderer().render(parse("![_foo_ **bar** [link](/url)](/url)\n"))) + .isEqualTo("

\"foo

\n"); } @Test public void imageAltTextWithCode() { - assertThat(defaultRenderer().render(parse("![`foo` bar](/url)\n"))).isEqualTo("

\"foo

\n"); + assertThat(defaultRenderer().render(parse("![`foo` bar](/url)\n"))) + .isEqualTo("

\"foo

\n"); } @Test @@ -277,7 +347,8 @@ public void canRenderContentsOfSingleParagraph() { document.appendChild(current); } - assertThat(defaultRenderer().render(document)).isEqualTo("Here I have a test link"); + assertThat(defaultRenderer().render(document)) + .isEqualTo("Here I have a test link"); } @Test @@ -318,7 +389,10 @@ private static HtmlRenderer htmlAllowingRenderer() { } private static HtmlRenderer sanitizeUrlsRenderer() { - return HtmlRenderer.builder().sanitizeUrls(true).urlSanitizer(new DefaultUrlSanitizer()).build(); + return HtmlRenderer.builder() + .sanitizeUrls(true) + .urlSanitizer(new DefaultUrlSanitizer()) + .build(); } private static HtmlRenderer rawUrlsRenderer() { diff --git a/commonmark/src/test/java/org/commonmark/test/InlineParserContextTest.java b/commonmark/src/test/java/org/commonmark/test/InlineParserContextTest.java index c05cac2d2..6d810abdd 100644 --- a/commonmark/src/test/java/org/commonmark/test/InlineParserContextTest.java +++ b/commonmark/src/test/java/org/commonmark/test/InlineParserContextTest.java @@ -1,23 +1,22 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import org.commonmark.internal.InlineParserImpl; -import org.commonmark.parser.beta.LinkProcessor; -import org.commonmark.parser.beta.InlineContentParserFactory; import org.commonmark.node.LinkReferenceDefinition; import org.commonmark.parser.InlineParser; import org.commonmark.parser.InlineParserContext; import org.commonmark.parser.InlineParserFactory; import org.commonmark.parser.Parser; +import org.commonmark.parser.beta.InlineContentParserFactory; +import org.commonmark.parser.beta.LinkProcessor; import org.commonmark.parser.delimiter.DelimiterProcessor; import org.commonmark.renderer.html.HtmlRenderer; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - public class InlineParserContextTest { @Test @@ -42,38 +41,40 @@ static class CapturingInlineParserFactory implements InlineParserFactory { @Override public InlineParser create(final InlineParserContext inlineParserContext) { - InlineParserContext wrappedContext = new InlineParserContext() { - @Override - public List getCustomInlineContentParserFactories() { - return inlineParserContext.getCustomInlineContentParserFactories(); - } - - @Override - public List getCustomDelimiterProcessors() { - return inlineParserContext.getCustomDelimiterProcessors(); - } - - @Override - public List getCustomLinkProcessors() { - return inlineParserContext.getCustomLinkProcessors(); - } - - @Override - public Set getCustomLinkMarkers() { - return inlineParserContext.getCustomLinkMarkers(); - } - - @Override - public LinkReferenceDefinition getLinkReferenceDefinition(String label) { - return getDefinition(LinkReferenceDefinition.class, label); - } - - @Override - public D getDefinition(Class type, String label) { - lookups.add(label); - return inlineParserContext.getDefinition(type, label); - } - }; + InlineParserContext wrappedContext = + new InlineParserContext() { + @Override + public List + getCustomInlineContentParserFactories() { + return inlineParserContext.getCustomInlineContentParserFactories(); + } + + @Override + public List getCustomDelimiterProcessors() { + return inlineParserContext.getCustomDelimiterProcessors(); + } + + @Override + public List getCustomLinkProcessors() { + return inlineParserContext.getCustomLinkProcessors(); + } + + @Override + public Set getCustomLinkMarkers() { + return inlineParserContext.getCustomLinkMarkers(); + } + + @Override + public LinkReferenceDefinition getLinkReferenceDefinition(String label) { + return getDefinition(LinkReferenceDefinition.class, label); + } + + @Override + public D getDefinition(Class type, String label) { + lookups.add(label); + return inlineParserContext.getDefinition(type, label); + } + }; return new InlineParserImpl(wrappedContext); } diff --git a/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionNodeTest.java b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionNodeTest.java index 8410ff028..f3ca037ca 100644 --- a/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionNodeTest.java +++ b/commonmark/src/test/java/org/commonmark/test/LinkReferenceDefinitionNodeTest.java @@ -1,13 +1,12 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; import org.commonmark.node.*; import org.commonmark.parser.Parser; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - public class LinkReferenceDefinitionNodeTest { @Test @@ -47,14 +46,16 @@ public void testMultipleDefinitions() { @Test public void testMultipleDefinitionsWithSameLabel() { - Node document = parse("This is a paragraph with a [foo] link.\n\n[foo]: /url1\n[foo]: /url2"); + Node document = + parse("This is a paragraph with a [foo] link.\n\n[foo]: /url1\n[foo]: /url2"); List nodes = Nodes.getChildren(document); assertThat(nodes).hasSize(3); assertThat(nodes.get(0)).isInstanceOf(Paragraph.class); LinkReferenceDefinition def1 = assertDef(nodes.get(1), "foo"); assertThat(def1.getDestination()).isEqualTo("/url1"); - // When there's multiple definitions with the same label, the first one "wins", as in reference links will use + // When there's multiple definitions with the same label, the first one "wins", as in + // reference links will use // that. But we still want to preserve the original definitions in the document. LinkReferenceDefinition def2 = assertDef(nodes.get(2), "foo"); assertThat(def2.getDestination()).isEqualTo("/url2"); diff --git a/commonmark/src/test/java/org/commonmark/test/ListBlockParserTest.java b/commonmark/src/test/java/org/commonmark/test/ListBlockParserTest.java index 02ac3abff..68241cc32 100644 --- a/commonmark/src/test/java/org/commonmark/test/ListBlockParserTest.java +++ b/commonmark/src/test/java/org/commonmark/test/ListBlockParserTest.java @@ -1,12 +1,12 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; + import org.commonmark.node.ListItem; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class ListBlockParserTest { private static final Parser PARSER = Parser.builder().build(); @@ -56,7 +56,8 @@ public void testOrderedListIndents() { assertListItemIndents("1.\tfoo", 0, 4); } - private void assertListItemIndents(String input, int expectedMarkerIndent, int expectedContentIndent) { + private void assertListItemIndents( + String input, int expectedMarkerIndent, int expectedContentIndent) { Node doc = PARSER.parse(input); ListItem listItem = Nodes.find(doc, ListItem.class); assertThat((int) listItem.getMarkerIndent()).isEqualTo(expectedMarkerIndent); diff --git a/commonmark/src/test/java/org/commonmark/test/ListTightLooseTest.java b/commonmark/src/test/java/org/commonmark/test/ListTightLooseTest.java index c6bda31ed..e606d467e 100644 --- a/commonmark/src/test/java/org/commonmark/test/ListTightLooseTest.java +++ b/commonmark/src/test/java/org/commonmark/test/ListTightLooseTest.java @@ -6,188 +6,150 @@ public class ListTightLooseTest extends CoreRenderingTestCase { @Test public void tight() { - assertRendering("- foo\n" + - "- bar\n" + - "+ baz\n", - "
    \n" + - "
  • foo
  • \n" + - "
  • bar
  • \n" + - "
\n" + - "
    \n" + - "
  • baz
  • \n" + - "
\n"); + assertRendering( + "- foo\n" + "- bar\n" + "+ baz\n", + "
    \n" + + "
  • foo
  • \n" + + "
  • bar
  • \n" + + "
\n" + + "
    \n" + + "
  • baz
  • \n" + + "
\n"); } @Test public void loose() { - assertRendering("- foo\n" + - "\n" + - "- bar\n" + - "\n" + - "\n" + - "- baz\n", - "
    \n" + - "
  • \n" + - "

    foo

    \n" + - "
  • \n" + - "
  • \n" + - "

    bar

    \n" + - "
  • \n" + - "
  • \n" + - "

    baz

    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "- foo\n" + "\n" + "- bar\n" + "\n" + "\n" + "- baz\n", + "
    \n" + + "
  • \n" + + "

    foo

    \n" + + "
  • \n" + + "
  • \n" + + "

    bar

    \n" + + "
  • \n" + + "
  • \n" + + "

    baz

    \n" + + "
  • \n" + + "
\n"); } @Test public void looseNested() { - assertRendering("- foo\n" + - " - bar\n" + - "\n" + - "\n" + - " baz", - "
    \n" + - "
  • foo\n" + - "
      \n" + - "
    • \n" + - "

      bar

      \n" + - "

      baz

      \n" + - "
    • \n" + - "
    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "- foo\n" + " - bar\n" + "\n" + "\n" + " baz", + "
    \n" + + "
  • foo\n" + + "
      \n" + + "
    • \n" + + "

      bar

      \n" + + "

      baz

      \n" + + "
    • \n" + + "
    \n" + + "
  • \n" + + "
\n"); } @Test public void looseNested2() { - assertRendering("- a\n" + - " - b\n" + - "\n" + - " c\n" + - "- d\n", - "
    \n" + - "
  • a\n" + - "
      \n" + - "
    • \n" + - "

      b

      \n" + - "

      c

      \n" + - "
    • \n" + - "
    \n" + - "
  • \n" + - "
  • d
  • \n" + - "
\n"); + assertRendering( + "- a\n" + " - b\n" + "\n" + " c\n" + "- d\n", + "
    \n" + + "
  • a\n" + + "
      \n" + + "
    • \n" + + "

      b

      \n" + + "

      c

      \n" + + "
    • \n" + + "
    \n" + + "
  • \n" + + "
  • d
  • \n" + + "
\n"); } @Test public void looseOuter() { - assertRendering("- foo\n" + - " - bar\n" + - "\n" + - "\n" + - " baz", - "
    \n" + - "
  • \n" + - "

    foo

    \n" + - "
      \n" + - "
    • bar
    • \n" + - "
    \n" + - "

    baz

    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "- foo\n" + " - bar\n" + "\n" + "\n" + " baz", + "
    \n" + + "
  • \n" + + "

    foo

    \n" + + "
      \n" + + "
    • bar
    • \n" + + "
    \n" + + "

    baz

    \n" + + "
  • \n" + + "
\n"); } @Test public void looseListItem() { - assertRendering("- one\n" + - "\n" + - " two\n", - "
    \n" + - "
  • \n" + - "

    one

    \n" + - "

    two

    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "- one\n" + "\n" + " two\n", + "
    \n" + "
  • \n" + "

    one

    \n" + "

    two

    \n" + "
  • \n" + "
\n"); } @Test public void tightWithBlankLineAfter() { - assertRendering("- foo\n" + - "- bar\n" + - "\n", - "
    \n" + - "
  • foo
  • \n" + - "
  • bar
  • \n" + - "
\n"); + assertRendering( + "- foo\n" + "- bar\n" + "\n", + "
    \n" + "
  • foo
  • \n" + "
  • bar
  • \n" + "
\n"); } @Test public void tightListWithCodeBlock() { - assertRendering("- a\n" + - "- ```\n" + - " b\n" + - "\n" + - "\n" + - " ```\n" + - "- c\n", - "
    \n" + - "
  • a
  • \n" + - "
  • \n" + - "
    b\n" +
    -                        "\n" +
    -                        "\n" +
    -                        "
    \n" + - "
  • \n" + - "
  • c
  • \n" + - "
\n"); + assertRendering( + "- a\n" + "- ```\n" + " b\n" + "\n" + "\n" + " ```\n" + "- c\n", + "
    \n" + + "
  • a
  • \n" + + "
  • \n" + + "
    b\n"
    +                        + "\n"
    +                        + "\n"
    +                        + "
    \n" + + "
  • \n" + + "
  • c
  • \n" + + "
\n"); } @Test public void tightListWithCodeBlock2() { - assertRendering("* foo\n" + - " ```\n" + - " bar\n" + - "\n" + - " ```\n" + - " baz\n", - "
    \n" + - "
  • foo\n" + - "
    bar\n" +
    -                        "\n" +
    -                        "
    \n" + - "baz
  • \n" + - "
\n"); + assertRendering( + "* foo\n" + " ```\n" + " bar\n" + "\n" + " ```\n" + " baz\n", + "
    \n" + + "
  • foo\n" + + "
    bar\n"
    +                        + "\n"
    +                        + "
    \n" + + "baz
  • \n" + + "
\n"); } @Test public void looseEmptyListItem() { - assertRendering("* a\n" + - "*\n" + - "\n" + - "* c", - "
    \n" + - "
  • \n" + - "

    a

    \n" + - "
  • \n" + - "
  • \n" + - "
  • \n" + - "

    c

    \n" + - "
  • \n" + - "
\n"); + assertRendering( + "* a\n" + "*\n" + "\n" + "* c", + "
    \n" + + "
  • \n" + + "

    a

    \n" + + "
  • \n" + + "
  • \n" + + "
  • \n" + + "

    c

    \n" + + "
  • \n" + + "
\n"); } @Test public void looseBlankLineAfterCodeBlock() { - assertRendering("1. ```\n" + - " foo\n" + - " ```\n" + - "\n" + - " bar", - "
    \n" + - "
  1. \n" + - "
    foo\n" +
    -                        "
    \n" + - "

    bar

    \n" + - "
  2. \n" + - "
\n"); + assertRendering( + "1. ```\n" + " foo\n" + " ```\n" + "\n" + " bar", + "
    \n" + + "
  1. \n" + + "
    foo\n"
    +                        + "
    \n" + + "

    bar

    \n" + + "
  2. \n" + + "
\n"); } } diff --git a/commonmark/src/test/java/org/commonmark/test/Nodes.java b/commonmark/src/test/java/org/commonmark/test/Nodes.java index 06d04fde6..6e96b11eb 100644 --- a/commonmark/src/test/java/org/commonmark/test/Nodes.java +++ b/commonmark/src/test/java/org/commonmark/test/Nodes.java @@ -1,10 +1,9 @@ package org.commonmark.test; -import org.commonmark.node.Node; - import java.util.ArrayList; import java.util.List; import java.util.Objects; +import org.commonmark.node.Node; public class Nodes { @@ -19,7 +18,7 @@ public static List getChildren(Node parent) { /** * Recursively try to find a node with the given type within the children of the specified node. * - * @param parent The node to get children from (node itself will not be checked) + * @param parent The node to get children from (node itself will not be checked) * @param nodeClass The type of node to find */ public static T tryFind(Node parent, Class nodeClass) { @@ -40,11 +39,12 @@ public static T tryFind(Node parent, Class nodeClass) { } /** - * Recursively try to find a node with the given type within the children of the specified node. Throw if node - * could not be found. + * Recursively try to find a node with the given type within the children of the specified node. + * Throw if node could not be found. */ public static T find(Node parent, Class nodeClass) { - return Objects.requireNonNull(tryFind(parent, nodeClass), + return Objects.requireNonNull( + tryFind(parent, nodeClass), "Could not find a " + nodeClass.getSimpleName() + " node in " + parent); } } diff --git a/commonmark/src/test/java/org/commonmark/test/ParserTest.java b/commonmark/src/test/java/org/commonmark/test/ParserTest.java index 4348563bd..90bbd42d8 100644 --- a/commonmark/src/test/java/org/commonmark/test/ParserTest.java +++ b/commonmark/src/test/java/org/commonmark/test/ParserTest.java @@ -1,11 +1,7 @@ package org.commonmark.test; -import org.commonmark.node.*; -import org.commonmark.parser.*; -import org.commonmark.renderer.html.HtmlRenderer; -import org.commonmark.renderer.markdown.MarkdownRenderer; -import org.commonmark.testutil.TestResources; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.IOException; import java.io.InputStream; @@ -16,9 +12,12 @@ import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.Future; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import org.commonmark.node.*; +import org.commonmark.parser.*; +import org.commonmark.renderer.html.HtmlRenderer; +import org.commonmark.renderer.markdown.MarkdownRenderer; +import org.commonmark.testutil.TestResources; +import org.junit.jupiter.api.Test; public class ParserTest { @@ -62,8 +61,12 @@ public void enabledBlockTypes() { @Test public void enabledBlockTypesThrowsWhenGivenUnknownClass() { // BulletList can't be enabled separately at the moment, only all ListBlock types - assertThatThrownBy(() -> - Parser.builder().enabledBlockTypes(Set.of(Heading.class, BulletList.class)).build()).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> + Parser.builder() + .enabledBlockTypes(Set.of(Heading.class, BulletList.class)) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -89,14 +92,16 @@ public void indentation() { @Test public void inlineParser() { - final InlineParser fakeInlineParser = (lines, node) -> node.appendChild(new ThematicBreak()); + final InlineParser fakeInlineParser = + (lines, node) -> node.appendChild(new ThematicBreak()); InlineParserFactory fakeInlineParserFactory = inlineParserContext -> fakeInlineParser; Parser parser = Parser.builder().inlineParserFactory(fakeInlineParserFactory).build(); String input = "**bold** **bold** ~~strikethrough~~"; - assertThat(parser.parse(input).getFirstChild().getFirstChild()).isInstanceOf(ThematicBreak.class); + assertThat(parser.parse(input).getFirstChild().getFirstChild()) + .isInstanceOf(ThematicBreak.class); } @Test @@ -123,8 +128,8 @@ public void threading() throws Exception { @Test public void maxOpenBlockParsersMustBeZeroOrGreater() { - assertThatThrownBy(() -> - Parser.builder().maxOpenBlockParsers(-1)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> Parser.builder().maxOpenBlockParsers(-1)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -169,11 +174,10 @@ public void maxOpenBlockParsersDegradesTheNinthLogicalListLevelToPlainText() { public void maxOpenBlockParsersAlsoLimitsMixedListAndBlockQuoteNesting() { var parser = Parser.builder().maxOpenBlockParsers(5).build(); - var document = parser.parse(String.join("\n", - "- level1", - " > level2", - " > > level3", - " > > > level4")); + var document = + parser.parse( + String.join( + "\n", "- level1", " > level2", " > > level3", " > > > level4")); var listBlock = document.getFirstChild(); assertThat(listBlock).isInstanceOf(BulletList.class); diff --git a/commonmark/src/test/java/org/commonmark/test/PathologicalTest.java b/commonmark/src/test/java/org/commonmark/test/PathologicalTest.java index 66d39de23..663aa7ced 100644 --- a/commonmark/src/test/java/org/commonmark/test/PathologicalTest.java +++ b/commonmark/src/test/java/org/commonmark/test/PathologicalTest.java @@ -1,15 +1,12 @@ package org.commonmark.test; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.Timeout; -import java.util.concurrent.TimeUnit; - -/** - * Pathological input cases (from commonmark.js). - */ +/** Pathological input cases (from commonmark.js). */ @Timeout(value = 3, unit = TimeUnit.SECONDS) @TestMethodOrder(MethodOrderer.MethodName.class) public class PathologicalTest extends CoreRenderingTestCase { @@ -22,50 +19,41 @@ public void nestedStrongEmphasis() { x = 500; assertRendering( "*a **a ".repeat(x) + "b" + " a** a*".repeat(x), - "

" + "a a ".repeat(x) + "b" + - " a a".repeat(x) + "

\n"); + "

" + + "a a ".repeat(x) + + "b" + + " a a".repeat(x) + + "

\n"); } @Test public void emphasisClosersWithNoOpeners() { - assertRendering( - "a_ ".repeat(x), - "

" + "a_ ".repeat(x - 1) + "a_

\n"); + assertRendering("a_ ".repeat(x), "

" + "a_ ".repeat(x - 1) + "a_

\n"); } @Test public void emphasisOpenersWithNoClosers() { - assertRendering( - "_a ".repeat(x), - "

" + "_a ".repeat(x - 1) + "_a

\n"); + assertRendering("_a ".repeat(x), "

" + "_a ".repeat(x - 1) + "_a

\n"); } @Test public void linkClosersWithNoOpeners() { - assertRendering( - "a] ".repeat(x), - "

" + "a] ".repeat(x - 1) + "a]

\n"); + assertRendering("a] ".repeat(x), "

" + "a] ".repeat(x - 1) + "a]

\n"); } @Test public void linkOpenersWithNoClosers() { - assertRendering( - "[a ".repeat(x), - "

" + "[a ".repeat(x - 1) + "[a

\n"); + assertRendering("[a ".repeat(x), "

" + "[a ".repeat(x - 1) + "[a

\n"); } @Test public void linkOpenersAndEmphasisClosers() { - assertRendering( - "[ a_ ".repeat(x), - "

" + "[ a_ ".repeat(x - 1) + "[ a_

\n"); + assertRendering("[ a_ ".repeat(x), "

" + "[ a_ ".repeat(x - 1) + "[ a_

\n"); } @Test public void mismatchedOpenersAndClosers() { - assertRendering( - "*a_ ".repeat(x), - "

" + "*a_ ".repeat(x - 1) + "*a_

\n"); + assertRendering("*a_ ".repeat(x), "

" + "*a_ ".repeat(x - 1) + "*a_

\n"); } @Test @@ -81,28 +69,23 @@ public void nestedBlockQuotes() { x = 1000; assertRendering( "> ".repeat(x) + "a\n", - "
\n".repeat(x) + "

a

\n" + - "
\n".repeat(x)); + "
\n".repeat(x) + "

a

\n" + "
\n".repeat(x)); } @Test public void hugeHorizontalRule() { - assertRendering( - "*".repeat(10000) + "\n", - "
\n"); + assertRendering("*".repeat(10000) + "\n", "
\n"); } @Test public void backslashInLink() { // See https://github.com/commonmark/commonmark.js/issues/157 - assertRendering("[" + "\\".repeat(x) + "\n", - "

" + "[" + "\\".repeat(x / 2) + "

\n"); + assertRendering("[" + "\\".repeat(x) + "\n", "

" + "[" + "\\".repeat(x / 2) + "

\n"); } @Test public void unclosedInlineLinks() { // See https://github.com/commonmark/commonmark.js/issues/129 - assertRendering("[](".repeat(x) + "\n", - "

" + "[](".repeat(x) + "

\n"); + assertRendering("[](".repeat(x) + "\n", "

" + "[](".repeat(x) + "

\n"); } } diff --git a/commonmark/src/test/java/org/commonmark/test/RegressionTest.java b/commonmark/src/test/java/org/commonmark/test/RegressionTest.java index 900a6518c..a7cc0eabf 100644 --- a/commonmark/src/test/java/org/commonmark/test/RegressionTest.java +++ b/commonmark/src/test/java/org/commonmark/test/RegressionTest.java @@ -1,5 +1,9 @@ package org.commonmark.test; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.RenderingTestCase; @@ -11,23 +15,18 @@ import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - @ParameterizedClass @MethodSource("data") public class RegressionTest extends RenderingTestCase { private static final Parser PARSER = Parser.builder().build(); // The spec says URL-escaping is optional, but the examples assume that it's enabled. - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().percentEncodeUrls(true).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().percentEncodeUrls(true).build(); private static final Map OVERRIDDEN_EXAMPLES = getOverriddenExamples(); - @Parameter - Example example; + @Parameter Example example; static List data() { var data = new ArrayList(); @@ -54,8 +53,10 @@ protected String render(String source) { private static Map getOverriddenExamples() { Map m = new HashMap<>(); - // The only difference is that we don't change `%28` and `%29` to `(` and `)` (percent encoding is preserved) - m.put("[XSS](javascript&colon;alert%28'XSS'%29)\n", + // The only difference is that we don't change `%28` and `%29` to `(` and `)` (percent + // encoding is preserved) + m.put( + "[XSS](javascript&colon;alert%28'XSS'%29)\n", "

XSS

\n"); // Callers should handle BOMs m.put("\uFEFF# Hi\n", "

\uFEFF# Hi

\n"); diff --git a/commonmark/src/test/java/org/commonmark/test/SourceLineTest.java b/commonmark/src/test/java/org/commonmark/test/SourceLineTest.java index 5d34bf410..d59e840fb 100644 --- a/commonmark/src/test/java/org/commonmark/test/SourceLineTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SourceLineTest.java @@ -1,12 +1,12 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import org.commonmark.node.SourceSpan; import org.commonmark.parser.SourceLine; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - public class SourceLineTest { @Test @@ -29,16 +29,19 @@ public void testSubstring() { @Test public void testSubstringBeginOutOfBounds() { var sourceLine = SourceLine.of("abcd", SourceSpan.of(3, 10, 13, 4)); - assertThatThrownBy(() -> sourceLine.substring(3, 2)).isInstanceOf(StringIndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceLine.substring(3, 2)) + .isInstanceOf(StringIndexOutOfBoundsException.class); } @Test public void testSubstringEndOutOfBounds() { var sourceLine = SourceLine.of("abcd", SourceSpan.of(3, 10, 13, 4)); - assertThatThrownBy(() -> sourceLine.substring(0, 5)).isInstanceOf(StringIndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceLine.substring(0, 5)) + .isInstanceOf(StringIndexOutOfBoundsException.class); } - private static void assertSourceLine(SourceLine sourceLine, String expectedContent, SourceSpan expectedSourceSpan) { + private static void assertSourceLine( + SourceLine sourceLine, String expectedContent, SourceSpan expectedSourceSpan) { assertThat(sourceLine.getContent()).isEqualTo(expectedContent); assertThat(sourceLine.getSourceSpan()).isEqualTo(expectedSourceSpan); } diff --git a/commonmark/src/test/java/org/commonmark/test/SourceSpanRenderer.java b/commonmark/src/test/java/org/commonmark/test/SourceSpanRenderer.java index 597a1e31c..3c6bf53ec 100644 --- a/commonmark/src/test/java/org/commonmark/test/SourceSpanRenderer.java +++ b/commonmark/src/test/java/org/commonmark/test/SourceSpanRenderer.java @@ -1,15 +1,12 @@ package org.commonmark.test; +import java.util.*; import org.commonmark.node.AbstractVisitor; import org.commonmark.node.Node; -import java.util.*; - public class SourceSpanRenderer { - /** - * Render source spans in the document using source position's line and column index. - */ + /** Render source spans in the document using source position's line and column index. */ public static String renderWithLineColumn(Node document, String source) { SourceSpanMarkersVisitor visitor = new SourceSpanMarkersVisitor(); document.accept(visitor); @@ -33,9 +30,7 @@ public static String renderWithLineColumn(Node document, String source) { return sb.toString(); } - /** - * Render source spans in the document using source position's input index. - */ + /** Render source spans in the document using source position's input index. */ public static String renderWithInputIndex(Node document, String source) { SourceSpanMarkersVisitor visitor = new SourceSpanMarkersVisitor(); document.accept(visitor); @@ -49,7 +44,8 @@ public static String renderWithInputIndex(Node document, String source) { return sb.toString(); } - private static void appendMarkers(Map> lineMarkers, int columnIndex, StringBuilder sb) { + private static void appendMarkers( + Map> lineMarkers, int columnIndex, StringBuilder sb) { if (lineMarkers != null) { List columnMarkers = lineMarkers.get(columnIndex); if (columnMarkers != null) { @@ -93,7 +89,9 @@ protected void visitChildren(Node parent) { getMarkers(line, col + length).add(0, closer); inputIndexMarkers.computeIfAbsent(input, k -> new LinkedList<>()).add(opener); - inputIndexMarkers.computeIfAbsent(input + length, k -> new LinkedList<>()).add(0, closer); + inputIndexMarkers + .computeIfAbsent(input + length, k -> new LinkedList<>()) + .add(0, closer); } markerIndex++; } diff --git a/commonmark/src/test/java/org/commonmark/test/SourceSpanTest.java b/commonmark/src/test/java/org/commonmark/test/SourceSpanTest.java index f1bb231f4..86e87cc98 100644 --- a/commonmark/src/test/java/org/commonmark/test/SourceSpanTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SourceSpanTest.java @@ -1,11 +1,11 @@ package org.commonmark.test; -import org.commonmark.node.SourceSpan; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import org.commonmark.node.SourceSpan; +import org.junit.jupiter.api.Test; + public class SourceSpanTest { @Test @@ -19,7 +19,8 @@ public void testSubSpan() { assertThat(span.subSpan(2)).isEqualTo(SourceSpan.of(1, 4, 5, 3)); assertThat(span.subSpan(3)).isEqualTo(SourceSpan.of(1, 5, 6, 2)); assertThat(span.subSpan(4)).isEqualTo(SourceSpan.of(1, 6, 7, 1)); - // Not sure if empty spans are useful, but it probably makes sense to mirror how substrings work + // Not sure if empty spans are useful, but it probably makes sense to mirror how substrings + // work assertThat(span.subSpan(5)).isEqualTo(SourceSpan.of(1, 7, 8, 0)); assertThat("abcde".substring(5)).isEqualTo(""); @@ -39,30 +40,35 @@ public void testSubSpan() { @Test public void testSubSpanBeginIndexNegative() { var sourceSpan = SourceSpan.of(1, 2, 3, 5); - assertThatThrownBy(() -> sourceSpan.subSpan(-1)).isInstanceOf(IndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceSpan.subSpan(-1)) + .isInstanceOf(IndexOutOfBoundsException.class); } @Test public void testSubSpanBeginIndexOutOfBounds() { var sourceSpan = SourceSpan.of(1, 2, 3, 5); - assertThatThrownBy(() -> sourceSpan.subSpan(6)).isInstanceOf(IndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceSpan.subSpan(6)) + .isInstanceOf(IndexOutOfBoundsException.class); } @Test public void testSubSpanEndIndexNegative() { var sourceSpan = SourceSpan.of(1, 2, 3, 5); - assertThatThrownBy(() -> sourceSpan.subSpan(0, -1)).isInstanceOf(IndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceSpan.subSpan(0, -1)) + .isInstanceOf(IndexOutOfBoundsException.class); } @Test public void testSubSpanEndIndexOutOfBounds() { var sourceSpan = SourceSpan.of(1, 2, 3, 5); - assertThatThrownBy(() -> sourceSpan.subSpan(0, 6)).isInstanceOf(IndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceSpan.subSpan(0, 6)) + .isInstanceOf(IndexOutOfBoundsException.class); } @Test public void testSubSpanBeginIndexGreaterThanEndIndex() { var sourceSpan = SourceSpan.of(1, 2, 3, 5); - assertThatThrownBy(() -> sourceSpan.subSpan(2, 1)).isInstanceOf(IndexOutOfBoundsException.class); + assertThatThrownBy(() -> sourceSpan.subSpan(2, 1)) + .isInstanceOf(IndexOutOfBoundsException.class); } } diff --git a/commonmark/src/test/java/org/commonmark/test/SourceSpansTest.java b/commonmark/src/test/java/org/commonmark/test/SourceSpansTest.java index f4e9d0a17..ceeff944a 100644 --- a/commonmark/src/test/java/org/commonmark/test/SourceSpansTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SourceSpansTest.java @@ -1,31 +1,52 @@ package org.commonmark.test; -import org.commonmark.node.*; -import org.commonmark.parser.IncludeSourceSpans; -import org.commonmark.parser.Parser; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.io.StringReader; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; +import org.commonmark.node.*; +import org.commonmark.parser.IncludeSourceSpans; +import org.commonmark.parser.Parser; +import org.junit.jupiter.api.Test; public class SourceSpansTest { - private static final Parser PARSER = Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS).build(); - private static final Parser INLINES_PARSER = Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build(); + private static final Parser PARSER = + Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS).build(); + private static final Parser INLINES_PARSER = + Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build(); @Test public void paragraph() { assertSpans("foo\n", Paragraph.class, SourceSpan.of(0, 0, 0, 3)); - assertSpans("foo\nbar\n", Paragraph.class, SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3)); - assertSpans(" foo\n bar\n", Paragraph.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 5)); - assertSpans("> foo\n> bar\n", Paragraph.class, SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 2, 8, 3)); - assertSpans("* foo\n bar\n", Paragraph.class, SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 2, 8, 3)); - assertSpans("* foo\nbar\n", Paragraph.class, SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 0, 6, 3)); + assertSpans( + "foo\nbar\n", + Paragraph.class, + SourceSpan.of(0, 0, 0, 3), + SourceSpan.of(1, 0, 4, 3)); + assertSpans( + " foo\n bar\n", + Paragraph.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 5)); + assertSpans( + "> foo\n> bar\n", + Paragraph.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 2, 8, 3)); + assertSpans( + "* foo\n bar\n", + Paragraph.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 2, 8, 3)); + assertSpans( + "* foo\nbar\n", + Paragraph.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 0, 6, 3)); } @Test @@ -45,10 +66,24 @@ public void atxHeading() { @Test public void setextHeading() { - assertSpans("foo\n===\n", Heading.class, SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3)); - assertSpans("foo\nbar\n====\n", Heading.class, SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3), SourceSpan.of(2, 0, 8, 4)); - assertSpans(" foo\n ===\n", Heading.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 5)); - assertSpans("> foo\n> ===\n", Heading.class, SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 2, 8, 3)); + assertSpans( + "foo\n===\n", Heading.class, SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3)); + assertSpans( + "foo\nbar\n====\n", + Heading.class, + SourceSpan.of(0, 0, 0, 3), + SourceSpan.of(1, 0, 4, 3), + SourceSpan.of(2, 0, 8, 4)); + assertSpans( + " foo\n ===\n", + Heading.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 5)); + assertSpans( + "> foo\n> ===\n", + Heading.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 2, 8, 3)); } @Test @@ -63,30 +98,77 @@ public void indentedCodeBlock() { assertSpans(" \t foo\n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 9)); assertSpans("\t foo\n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 5)); assertSpans("\t foo\n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 6)); - assertSpans(" foo\n bar\n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 8)); - assertSpans(" foo\n\tbar\n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 4)); - assertSpans(" foo\n \n \n", IndentedCodeBlock.class, SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 4), SourceSpan.of(2, 0, 13, 5)); + assertSpans( + " foo\n bar\n", + IndentedCodeBlock.class, + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 8)); + assertSpans( + " foo\n\tbar\n", + IndentedCodeBlock.class, + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 4)); + assertSpans( + " foo\n \n \n", + IndentedCodeBlock.class, + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 4), + SourceSpan.of(2, 0, 13, 5)); assertSpans("> foo\n", IndentedCodeBlock.class, SourceSpan.of(0, 2, 2, 7)); } @Test public void fencedCodeBlock() { - assertSpans("```\nfoo\n```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3), SourceSpan.of(2, 0, 8, 3)); - assertSpans("```\n foo\n```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 4), SourceSpan.of(2, 0, 9, 3)); - assertSpans("```\nfoo\nbar\n```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3), SourceSpan.of(2, 0, 8, 3), SourceSpan.of(3, 0, 12, 3)); - assertSpans(" ```\n foo\n ```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 6), SourceSpan.of(1, 0, 7, 6), SourceSpan.of(2, 0, 14, 6)); - assertSpans(" ```\n foo\nfoo\n```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 4), SourceSpan.of(1, 0, 5, 4), SourceSpan.of(2, 0, 10, 3), SourceSpan.of(3, 0, 14, 3)); - assertSpans("```info\nfoo\n```\n", FencedCodeBlock.class, - SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 3), SourceSpan.of(2, 0, 12, 3)); - assertSpans("* ```\n foo\n ```\n", FencedCodeBlock.class, - SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 2, 8, 3), SourceSpan.of(2, 2, 14, 3)); - assertSpans("> ```\n> foo\n> ```\n", FencedCodeBlock.class, - SourceSpan.of(0, 2, 2, 3), SourceSpan.of(1, 2, 8, 3), SourceSpan.of(2, 2, 14, 3)); + assertSpans( + "```\nfoo\n```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 3), + SourceSpan.of(1, 0, 4, 3), + SourceSpan.of(2, 0, 8, 3)); + assertSpans( + "```\n foo\n```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 3), + SourceSpan.of(1, 0, 4, 4), + SourceSpan.of(2, 0, 9, 3)); + assertSpans( + "```\nfoo\nbar\n```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 3), + SourceSpan.of(1, 0, 4, 3), + SourceSpan.of(2, 0, 8, 3), + SourceSpan.of(3, 0, 12, 3)); + assertSpans( + " ```\n foo\n ```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 6), + SourceSpan.of(1, 0, 7, 6), + SourceSpan.of(2, 0, 14, 6)); + assertSpans( + " ```\n foo\nfoo\n```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 4), + SourceSpan.of(1, 0, 5, 4), + SourceSpan.of(2, 0, 10, 3), + SourceSpan.of(3, 0, 14, 3)); + assertSpans( + "```info\nfoo\n```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 3), + SourceSpan.of(2, 0, 12, 3)); + assertSpans( + "* ```\n foo\n ```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 2, 8, 3), + SourceSpan.of(2, 2, 14, 3)); + assertSpans( + "> ```\n> foo\n> ```\n", + FencedCodeBlock.class, + SourceSpan.of(0, 2, 2, 3), + SourceSpan.of(1, 2, 8, 3), + SourceSpan.of(2, 2, 14, 3)); Node document = PARSER.parse("```\nfoo\n```\nbar\n"); Paragraph paragraph = (Paragraph) document.getLastChild(); @@ -96,7 +178,9 @@ public void fencedCodeBlock() { @Test public void htmlBlock() { assertSpans("
\n", HtmlBlock.class, SourceSpan.of(0, 0, 0, 5)); - assertSpans("
\n foo\n
\n", HtmlBlock.class, + assertSpans( + "
\n foo\n
\n", + HtmlBlock.class, SourceSpan.of(0, 0, 0, 6), SourceSpan.of(1, 0, 7, 4), SourceSpan.of(2, 0, 12, 7)); @@ -109,27 +193,75 @@ public void blockQuote() { assertSpans("> foo\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 5)); assertSpans("> foo\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 6)); assertSpans(" > foo\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 6)); - assertSpans(" > foo\n > bar\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 8), SourceSpan.of(1, 0, 9, 7)); + assertSpans( + " > foo\n > bar\n", + BlockQuote.class, + SourceSpan.of(0, 0, 0, 8), + SourceSpan.of(1, 0, 9, 7)); // Lazy continuations - assertSpans("> foo\nbar\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3)); - assertSpans("> foo\nbar\n> baz\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3), SourceSpan.of(2, 0, 10, 5)); - assertSpans("> > foo\nbar\n", BlockQuote.class, SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 3)); + assertSpans( + "> foo\nbar\n", + BlockQuote.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3)); + assertSpans( + "> foo\nbar\n> baz\n", + BlockQuote.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3), + SourceSpan.of(2, 0, 10, 5)); + assertSpans( + "> > foo\nbar\n", + BlockQuote.class, + SourceSpan.of(0, 0, 0, 7), + SourceSpan.of(1, 0, 8, 3)); } @Test public void listBlock() { assertSpans("* foo\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5)); - assertSpans("* foo\n bar\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 5)); - assertSpans("* foo\n* bar\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 5)); - assertSpans("* foo\n # bar\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 7)); - assertSpans("* foo\n * bar\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 7)); + assertSpans( + "* foo\n bar\n", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 5)); + assertSpans( + "* foo\n* bar\n", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 5)); + assertSpans( + "* foo\n # bar\n", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 7)); + assertSpans( + "* foo\n * bar\n", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 7)); assertSpans("* foo\n> bar\n", ListBlock.class, SourceSpan.of(0, 0, 0, 5)); assertSpans("> * foo\n", ListBlock.class, SourceSpan.of(0, 2, 2, 5)); // Lazy continuations - assertSpans("* foo\nbar\nbaz", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3), SourceSpan.of(2, 0, 10, 3)); - assertSpans("* foo\nbar\n* baz", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3), SourceSpan.of(2, 0, 10, 5)); - assertSpans("* foo\n * bar\nbaz", ListBlock.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 7), SourceSpan.of(2, 0, 14, 3)); + assertSpans( + "* foo\nbar\nbaz", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3), + SourceSpan.of(2, 0, 10, 3)); + assertSpans( + "* foo\nbar\n* baz", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3), + SourceSpan.of(2, 0, 10, 5)); + assertSpans( + "* foo\n * bar\nbaz", + ListBlock.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 7), + SourceSpan.of(2, 0, 14, 3)); Node document = PARSER.parse("* foo\n * bar\n"); ListBlock listBlock = (ListBlock) document.getFirstChild().getFirstChild().getLastChild(); @@ -142,23 +274,40 @@ public void listItem() { assertSpans(" * foo\n", ListItem.class, SourceSpan.of(0, 0, 0, 6)); assertSpans(" * foo\n", ListItem.class, SourceSpan.of(0, 0, 0, 7)); assertSpans(" * foo\n", ListItem.class, SourceSpan.of(0, 0, 0, 8)); - assertSpans("*\n foo\n", ListItem.class, SourceSpan.of(0, 0, 0, 1), SourceSpan.of(1, 0, 2, 5)); - assertSpans("*\n foo\n bar\n", ListItem.class, SourceSpan.of(0, 0, 0, 1), SourceSpan.of(1, 0, 2, 5), SourceSpan.of(2, 0, 8, 5)); + assertSpans( + "*\n foo\n", ListItem.class, SourceSpan.of(0, 0, 0, 1), SourceSpan.of(1, 0, 2, 5)); + assertSpans( + "*\n foo\n bar\n", + ListItem.class, + SourceSpan.of(0, 0, 0, 1), + SourceSpan.of(1, 0, 2, 5), + SourceSpan.of(2, 0, 8, 5)); assertSpans("> * foo\n", ListItem.class, SourceSpan.of(0, 2, 2, 5)); // Lazy continuations - assertSpans("* foo\nbar\n", ListItem.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3)); - assertSpans("* foo\nbar\nbaz\n", ListItem.class, SourceSpan.of(0, 0, 0, 5), SourceSpan.of(1, 0, 6, 3), SourceSpan.of(2, 0, 10, 3)); + assertSpans( + "* foo\nbar\n", + ListItem.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3)); + assertSpans( + "* foo\nbar\nbaz\n", + ListItem.class, + SourceSpan.of(0, 0, 0, 5), + SourceSpan.of(1, 0, 6, 3), + SourceSpan.of(2, 0, 10, 3)); } @Test public void linkReferenceDefinition() { - // This is tricky due to how link reference definition parsing works. It is stripped from the paragraph if it's - // successfully parsed, otherwise it stays part of the paragraph. + // This is tricky due to how link reference definition parsing works. It is stripped from + // the paragraph if it's successfully parsed, otherwise it stays part of the paragraph. Node document = PARSER.parse("[foo]: /url\ntext\n"); - LinkReferenceDefinition linkReferenceDefinition = (LinkReferenceDefinition) document.getFirstChild(); - assertThat(linkReferenceDefinition.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 11))); + LinkReferenceDefinition linkReferenceDefinition = + (LinkReferenceDefinition) document.getFirstChild(); + assertThat(linkReferenceDefinition.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 11))); Paragraph paragraph = (Paragraph) document.getLastChild(); assertThat(paragraph.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(1, 0, 12, 4))); @@ -193,15 +342,18 @@ public void linkReferenceDefinitionWithTitleInvalid() { @Test public void linkReferenceDefinitionHeading() { - // This is probably the trickiest because we have a link reference definition at the start of a paragraph - // that gets replaced because of a heading. Phew. + // This is probably the trickiest because we have a link reference definition at the start + // of a paragraph that gets replaced because of a heading. Phew. Node document = PARSER.parse("[foo]: /url\nHeading\n===\n"); - LinkReferenceDefinition linkReferenceDefinition = (LinkReferenceDefinition) document.getFirstChild(); - assertThat(linkReferenceDefinition.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 11))); + LinkReferenceDefinition linkReferenceDefinition = + (LinkReferenceDefinition) document.getFirstChild(); + assertThat(linkReferenceDefinition.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 11))); Heading heading = (Heading) document.getLastChild(); - assertThat(heading.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(1, 0, 12, 7), SourceSpan.of(2, 0, 20, 3))); + assertThat(heading.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(1, 0, 12, 7), SourceSpan.of(2, 0, 20, 3))); } @Test @@ -212,13 +364,17 @@ public void lazyContinuationLines() { var doc = PARSER.parse("> > > foo\nbar\n"); var bq1 = (BlockQuote) doc.getLastChild(); - assertThat(bq1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 9), SourceSpan.of(1, 0, 10, 3))); + assertThat(bq1.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 9), SourceSpan.of(1, 0, 10, 3))); var bq2 = (BlockQuote) bq1.getLastChild(); - assertThat(bq2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 2, 2, 7), SourceSpan.of(1, 0, 10, 3))); + assertThat(bq2.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 2, 2, 7), SourceSpan.of(1, 0, 10, 3))); var bq3 = (BlockQuote) bq2.getLastChild(); - assertThat(bq3.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 4, 4, 5), SourceSpan.of(1, 0, 10, 3))); + assertThat(bq3.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 4, 4, 5), SourceSpan.of(1, 0, 10, 3))); var paragraph = (Paragraph) bq3.getLastChild(); - assertThat(paragraph.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 6, 6, 3), SourceSpan.of(1, 0, 10, 3))); + assertThat(paragraph.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 6, 6, 3), SourceSpan.of(1, 0, 10, 3))); } { @@ -226,13 +382,17 @@ public void lazyContinuationLines() { var doc = PARSER.parse("> > > foo\nbars\n"); var bq1 = (BlockQuote) doc.getLastChild(); - assertThat(bq1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 9), SourceSpan.of(1, 0, 10, 4))); + assertThat(bq1.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 9), SourceSpan.of(1, 0, 10, 4))); var bq2 = (BlockQuote) bq1.getLastChild(); - assertThat(bq2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 2, 2, 7), SourceSpan.of(1, 0, 10, 4))); + assertThat(bq2.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 2, 2, 7), SourceSpan.of(1, 0, 10, 4))); var bq3 = (BlockQuote) bq2.getLastChild(); - assertThat(bq3.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 4, 4, 5), SourceSpan.of(1, 0, 10, 4))); + assertThat(bq3.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 4, 4, 5), SourceSpan.of(1, 0, 10, 4))); var paragraph = (Paragraph) bq3.getLastChild(); - assertThat(paragraph.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 6, 6, 3), SourceSpan.of(1, 0, 10, 4))); + assertThat(paragraph.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 6, 6, 3), SourceSpan.of(1, 0, 10, 4))); } { @@ -240,15 +400,20 @@ public void lazyContinuationLines() { var doc = PARSER.parse("> 1. > Blockquote\ncontinued here."); var bq1 = (BlockQuote) doc.getLastChild(); - assertThat(bq1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 17), SourceSpan.of(1, 0, 18, 15))); + assertThat(bq1.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 17), SourceSpan.of(1, 0, 18, 15))); var orderedList = (OrderedList) bq1.getLastChild(); - assertThat(orderedList.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 2, 2, 15), SourceSpan.of(1, 0, 18, 15))); + assertThat(orderedList.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 2, 2, 15), SourceSpan.of(1, 0, 18, 15))); var listItem = (ListItem) orderedList.getLastChild(); - assertThat(listItem.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 2, 2, 15), SourceSpan.of(1, 0, 18, 15))); + assertThat(listItem.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 2, 2, 15), SourceSpan.of(1, 0, 18, 15))); var bq2 = (BlockQuote) listItem.getLastChild(); - assertThat(bq2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 5, 5, 12), SourceSpan.of(1, 0, 18, 15))); + assertThat(bq2.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 5, 5, 12), SourceSpan.of(1, 0, 18, 15))); var paragraph = (Paragraph) bq2.getLastChild(); - assertThat(paragraph.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 7, 7, 10), SourceSpan.of(1, 0, 18, 15))); + assertThat(paragraph.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 7, 7, 10), SourceSpan.of(1, 0, 18, 15))); } { @@ -256,18 +421,25 @@ public void lazyContinuationLines() { var doc = PARSER.parse("> > foo\n> bar\n"); var bq1 = (BlockQuote) doc.getLastChild(); - assertThat(bq1.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 5))); + assertThat(bq1.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 0, 0, 7), SourceSpan.of(1, 0, 8, 5))); var bq2 = (BlockQuote) bq1.getLastChild(); - assertThat(bq2.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 2, 2, 5), SourceSpan.of(1, 2, 10, 3))); + assertThat(bq2.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 2, 2, 5), SourceSpan.of(1, 2, 10, 3))); var paragraph = (Paragraph) bq2.getLastChild(); - assertThat(paragraph.getSourceSpans()).isEqualTo(List.of(SourceSpan.of(0, 4, 4, 3), SourceSpan.of(1, 2, 10, 3))); + assertThat(paragraph.getSourceSpans()) + .isEqualTo(List.of(SourceSpan.of(0, 4, 4, 3), SourceSpan.of(1, 2, 10, 3))); } } @Test public void visualCheck() { - assertVisualize("> * foo\n> bar\n> * baz\n", "(> {[* ]})\n(> {[ ]})\n(> {⸢* ⸤baz⸥⸣})\n"); - assertVisualize("> * ```\n> foo\n> ```\n", "(> {[* <```>]})\n(> {[ ]})\n(> {[ <```>]})\n"); + assertVisualize( + "> * foo\n> bar\n> * baz\n", + "(> {[* ]})\n(> {[ ]})\n(> {⸢* ⸤baz⸥⸣})\n"); + assertVisualize( + "> * ```\n> foo\n> ```\n", + "(> {[* <```>]})\n(> {[ ]})\n(> {[ <```>]})\n"); } @Test @@ -276,7 +448,8 @@ public void inlineText() { assertInlineSpans("> foo", Text.class, SourceSpan.of(0, 2, 2, 3)); assertInlineSpans("* foo", Text.class, SourceSpan.of(0, 2, 2, 3)); - // SourceSpans should be merged: ` is a separate Text node while inline parsing and gets merged at the end + // SourceSpans should be merged: ` is a separate Text node while inline parsing and gets + // merged at the end assertInlineSpans("foo`bar", Text.class, SourceSpan.of(0, 0, 0, 7)); assertInlineSpans("foo[bar", Text.class, SourceSpan.of(0, 0, 0, 7)); assertInlineSpans("> foo`bar", Text.class, SourceSpan.of(0, 2, 2, 7)); @@ -305,9 +478,8 @@ public void inlineBackslash() { @Test public void inlineBackticks() { assertInlineSpans("see `code`", Code.class, SourceSpan.of(0, 4, 4, 6)); - assertInlineSpans("`multi\nline`", Code.class, - SourceSpan.of(0, 0, 0, 6), - SourceSpan.of(1, 0, 7, 5)); + assertInlineSpans( + "`multi\nline`", Code.class, SourceSpan.of(0, 0, 0, 6), SourceSpan.of(1, 0, 7, 5)); assertInlineSpans("text ```", Text.class, SourceSpan.of(0, 0, 0, 8)); } @@ -368,13 +540,14 @@ public void tabExpansion() { @Test public void differentLineTerminators() { var input = "foo\nbar\rbaz\r\nqux\r\n\r\n> *hi*"; - assertSpans(input, Paragraph.class, + assertSpans( + input, + Paragraph.class, SourceSpan.of(0, 0, 0, 3), SourceSpan.of(1, 0, 4, 3), SourceSpan.of(2, 0, 8, 3), SourceSpan.of(3, 0, 13, 3)); - assertSpans(input, BlockQuote.class, - SourceSpan.of(5, 0, 20, 6)); + assertSpans(input, BlockQuote.class, SourceSpan.of(5, 0, 20, 6)); assertInlineSpans(input, Emphasis.class, SourceSpan.of(5, 2, 22, 4)); } @@ -385,25 +558,32 @@ private void assertVisualize(String source, String expected) { assertThat(SourceSpanRenderer.renderWithInputIndex(doc, source)).isEqualTo(expected); } - private static void assertSpans(String input, Class nodeClass, SourceSpan... expectedSourceSpans) { + private static void assertSpans( + String input, Class nodeClass, SourceSpan... expectedSourceSpans) { assertSpans(PARSER.parse(input), nodeClass, expectedSourceSpans); try { - assertSpans(PARSER.parseReader(new StringReader(input)), nodeClass, expectedSourceSpans); + assertSpans( + PARSER.parseReader(new StringReader(input)), nodeClass, expectedSourceSpans); } catch (IOException e) { throw new RuntimeException(e); } } - private static void assertInlineSpans(String input, Class nodeClass, SourceSpan... expectedSourceSpans) { + private static void assertInlineSpans( + String input, Class nodeClass, SourceSpan... expectedSourceSpans) { assertSpans(INLINES_PARSER.parse(input), nodeClass, expectedSourceSpans); try { - assertSpans(INLINES_PARSER.parseReader(new StringReader(input)), nodeClass, expectedSourceSpans); + assertSpans( + INLINES_PARSER.parseReader(new StringReader(input)), + nodeClass, + expectedSourceSpans); } catch (IOException e) { throw new RuntimeException(e); } } - private static void assertSpans(Node rootNode, Class nodeClass, SourceSpan... expectedSourceSpans) { + private static void assertSpans( + Node rootNode, Class nodeClass, SourceSpan... expectedSourceSpans) { Node node = findNode(rootNode, nodeClass); assertThat(node.getSourceSpans()).isEqualTo(List.of(expectedSourceSpans)); } diff --git a/commonmark/src/test/java/org/commonmark/test/SpecBenchmark.java b/commonmark/src/test/java/org/commonmark/test/SpecBenchmark.java index e7bb080a8..f116404f9 100644 --- a/commonmark/src/test/java/org/commonmark/test/SpecBenchmark.java +++ b/commonmark/src/test/java/org/commonmark/test/SpecBenchmark.java @@ -1,5 +1,6 @@ package org.commonmark.test; +import java.util.List; import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; @@ -11,8 +12,6 @@ import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; -import java.util.List; - @State(Scope.Benchmark) @Fork(5) @Warmup(iterations = 10) @@ -20,17 +19,19 @@ public class SpecBenchmark { private static final String SPEC = TestResources.readAsString(TestResources.getSpec()); - private static final List SPEC_EXAMPLES = ExampleReader.readExampleSources(TestResources.getSpec()); + private static final List SPEC_EXAMPLES = + ExampleReader.readExampleSources(TestResources.getSpec()); private static final Parser PARSER = Parser.builder().build(); private static final HtmlRenderer RENDERER = HtmlRenderer.builder().build(); private static final Node SPEC_NODE = PARSER.parse(SPEC); public static void main(String[] args) throws Exception { - Options options = new OptionsBuilder() - .parent(new CommandLineOptions(args)) - .include(SpecBenchmark.class.getName() + ".*") - .build(); + Options options = + new OptionsBuilder() + .parent(new CommandLineOptions(args)) + .include(SpecBenchmark.class.getName() + ".*") + .build(); new Runner(options).run(); } diff --git a/commonmark/src/test/java/org/commonmark/test/SpecCoreTest.java b/commonmark/src/test/java/org/commonmark/test/SpecCoreTest.java index 047a1e6cf..d7963da5f 100644 --- a/commonmark/src/test/java/org/commonmark/test/SpecCoreTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SpecCoreTest.java @@ -1,5 +1,8 @@ package org.commonmark.test; +import static org.assertj.core.api.Assertions.fail; +import static org.commonmark.testutil.Asserts.assertRendering; + import org.commonmark.node.AbstractVisitor; import org.commonmark.node.Node; import org.commonmark.node.Text; @@ -8,41 +11,47 @@ import org.commonmark.testutil.SpecTestCase; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.fail; -import static org.commonmark.testutil.Asserts.assertRendering; - public class SpecCoreTest extends SpecTestCase { private static final Parser PARSER = Parser.builder().build(); // The spec says URL-escaping is optional, but the examples assume that it's enabled. - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().percentEncodeUrls(true).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().percentEncodeUrls(true).build(); @Test public void testTextNodesContiguous() { final String source = example.getSource(); Node node = PARSER.parse(source); - node.accept(new AbstractVisitor() { - @Override - protected void visitChildren(Node parent) { - if (parent instanceof Text && parent.getFirstChild() != null) { - fail("Text node is not allowed to have children, literal is \"" + ((Text) parent).getLiteral() + "\""); - } - boolean lastText = false; - Node node = parent.getFirstChild(); - while (node != null) { - if (node instanceof Text) { - if (lastText) { - fail("Adjacent text nodes found, second node literal is \"" + ((Text) node).getLiteral() + "\", source:\n" + source); + node.accept( + new AbstractVisitor() { + @Override + protected void visitChildren(Node parent) { + if (parent instanceof Text && parent.getFirstChild() != null) { + fail( + "Text node is not allowed to have children, literal is \"" + + ((Text) parent).getLiteral() + + "\""); + } + boolean lastText = false; + Node node = parent.getFirstChild(); + while (node != null) { + if (node instanceof Text) { + if (lastText) { + fail( + "Adjacent text nodes found, second node literal is \"" + + ((Text) node).getLiteral() + + "\", source:\n" + + source); + } + lastText = true; + } else { + lastText = false; + } + node = node.getNext(); } - lastText = true; - } else { - lastText = false; + super.visitChildren(parent); } - node = node.getNext(); - } - super.visitChildren(parent); - } - }); + }); } @Test diff --git a/commonmark/src/test/java/org/commonmark/test/SpecCrLfCoreTest.java b/commonmark/src/test/java/org/commonmark/test/SpecCrLfCoreTest.java index eb0fcd0dd..ac2c70890 100644 --- a/commonmark/src/test/java/org/commonmark/test/SpecCrLfCoreTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SpecCrLfCoreTest.java @@ -1,20 +1,22 @@ package org.commonmark.test; +import static org.commonmark.testutil.Asserts.assertRendering; + import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.testutil.SpecTestCase; import org.junit.jupiter.api.Test; -import static org.commonmark.testutil.Asserts.assertRendering; - /** - * Same as {@link SpecCoreTest} but converts line endings to Windows-style CR+LF endings before parsing. + * Same as {@link SpecCoreTest} but converts line endings to Windows-style CR+LF endings before + * parsing. */ public class SpecCrLfCoreTest extends SpecTestCase { private static final Parser PARSER = Parser.builder().build(); // The spec says URL-escaping is optional, but the examples assume that it's enabled. - private static final HtmlRenderer RENDERER = HtmlRenderer.builder().percentEncodeUrls(true).build(); + private static final HtmlRenderer RENDERER = + HtmlRenderer.builder().percentEncodeUrls(true).build(); @Test public void testHtmlRendering() { diff --git a/commonmark/src/test/java/org/commonmark/test/SpecialInputTest.java b/commonmark/src/test/java/org/commonmark/test/SpecialInputTest.java index 45cd3aea2..f252a397f 100644 --- a/commonmark/src/test/java/org/commonmark/test/SpecialInputTest.java +++ b/commonmark/src/test/java/org/commonmark/test/SpecialInputTest.java @@ -31,8 +31,11 @@ public void crLfAtEndShouldBeParsed() { @Test public void mixedLineSeparators() { - assertRendering("- a\n- b\r- c\r\n- d", "
    \n
  • a
  • \n
  • b
  • \n
  • c
  • \n
  • d
  • \n
\n"); - assertRendering("a\n\nb\r\rc\r\n\r\nd\n\re", "

a

\n

b

\n

c

\n

d

\n

e

\n"); + assertRendering( + "- a\n- b\r- c\r\n- d", + "
    \n
  • a
  • \n
  • b
  • \n
  • c
  • \n
  • d
  • \n
\n"); + assertRendering( + "a\n\nb\r\rc\r\n\r\nd\n\re", "

a

\n

b

\n

c

\n

d

\n

e

\n"); } @Test @@ -52,13 +55,16 @@ public void indentedCodeBlockWithMixedTabsAndSpaces() { @Test public void tightListInBlockQuote() { - assertRendering("> *\n> * a", "
\n
    \n
  • \n
  • a
  • \n
\n
\n"); + assertRendering( + "> *\n> * a", "
\n
    \n
  • \n
  • a
  • \n
\n
\n"); } @Test public void looseListInBlockQuote() { // Second line in block quote is considered blank for purpose of loose list - assertRendering("> *\n>\n> * a", "
\n
    \n
  • \n
  • \n

    a

    \n
  • \n
\n
\n"); + assertRendering( + "> *\n>\n> * a", + "
\n
    \n
  • \n
  • \n

    a

    \n
  • \n
\n
\n"); } @Test @@ -68,7 +74,8 @@ public void lineWithOnlySpacesAfterListBullet() { @Test public void listWithTwoSpacesForFirstBullet() { - // We have two spaces after the bullet, but no content. With content, the next line would be required + // We have two spaces after the bullet, but no content. With content, the next line would be + // required assertRendering("* \n foo\n", "
    \n
  • foo
  • \n
\n"); } @@ -79,9 +86,11 @@ public void orderedListMarkerOnly() { @Test public void columnIsInTabOnPreviousLine() { - assertRendering("- foo\n\n\tbar\n\n# baz\n", + assertRendering( + "- foo\n\n\tbar\n\n# baz\n", "
    \n
  • \n

    foo

    \n

    bar

    \n
  • \n
\n

baz

\n"); - assertRendering("- foo\n\n\tbar\n# baz\n", + assertRendering( + "- foo\n\n\tbar\n# baz\n", "
    \n
  • \n

    foo

    \n

    bar

    \n
  • \n
\n

baz

\n"); } @@ -95,15 +104,20 @@ public void linkLabelWithBracket() { @Test public void linkLabelLength() { String label1 = "a".repeat(999); - assertRendering("[foo][" + label1 + "]\n\n[" + label1 + "]: /", "

foo

\n"); - assertRendering("[foo][x" + label1 + "]\n\n[x" + label1 + "]: /", + assertRendering( + "[foo][" + label1 + "]\n\n[" + label1 + "]: /", "

foo

\n"); + assertRendering( + "[foo][x" + label1 + "]\n\n[x" + label1 + "]: /", "

[foo][x" + label1 + "]

\n

[x" + label1 + "]: /

\n"); - assertRendering("[foo][\n" + label1 + "]\n\n[\n" + label1 + "]: /", + assertRendering( + "[foo][\n" + label1 + "]\n\n[\n" + label1 + "]: /", "

[foo][\n" + label1 + "]

\n

[\n" + label1 + "]: /

\n"); String label2 = "a\n".repeat(499); - assertRendering("[foo][" + label2 + "]\n\n[" + label2 + "]: /", "

foo

\n"); - assertRendering("[foo][12" + label2 + "]\n\n[12" + label2 + "]: /", + assertRendering( + "[foo][" + label2 + "]\n\n[" + label2 + "]: /", "

foo

\n"); + assertRendering( + "[foo][12" + label2 + "]\n\n[12" + label2 + "]: /", "

[foo][12" + label2 + "]

\n

[12" + label2 + "]: /

\n"); } @@ -111,7 +125,8 @@ public void linkLabelLength() { public void linkDestinationEscaping() { // Backslash escapes `)` assertRendering("[foo](\\))", "

foo

\n"); - // ` ` is not escapable, so the backslash is a literal backslash and there's an optional space at the end + // ` ` is not escapable, so the backslash is a literal backslash and there's an optional + // space at the end assertRendering("[foo](\\ )", "

foo

\n"); // Backslash is a literal, so valid assertRendering("[foo]()", "

foo

\n"); @@ -141,35 +156,35 @@ public void emphasisMultipleOf3Rule() { @Test public void renderEvenRegexpProducesStackoverflow() { - render("Contents: