├── .codecov.yml ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── commonmark-android-test ├── .gitignore ├── README.md ├── app │ ├── build.gradle │ ├── lint.xml │ └── src │ │ └── main │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── commonmark-ext-autolink ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── autolink │ │ │ ├── AutolinkExtension.java │ │ │ └── internal │ │ │ └── AutolinkPostProcessor.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── autolink │ └── AutolinkTest.java ├── commonmark-ext-footnotes ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── footnotes │ │ │ ├── FootnoteDefinition.java │ │ │ ├── FootnoteReference.java │ │ │ ├── FootnotesExtension.java │ │ │ ├── InlineFootnote.java │ │ │ └── internal │ │ │ ├── FootnoteBlockParser.java │ │ │ ├── FootnoteHtmlNodeRenderer.java │ │ │ ├── FootnoteLinkProcessor.java │ │ │ └── FootnoteMarkdownNodeRenderer.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ ├── java │ └── org │ │ └── commonmark │ │ └── ext │ │ └── footnotes │ │ ├── FootnoteHtmlRendererTest.java │ │ ├── FootnoteMarkdownRendererTest.java │ │ └── FootnotesTest.java │ └── resources │ └── footnotes.html ├── commonmark-ext-gfm-strikethrough ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── gfm │ │ │ └── strikethrough │ │ │ ├── Strikethrough.java │ │ │ ├── StrikethroughExtension.java │ │ │ └── internal │ │ │ ├── StrikethroughDelimiterProcessor.java │ │ │ ├── StrikethroughHtmlNodeRenderer.java │ │ │ ├── StrikethroughMarkdownNodeRenderer.java │ │ │ ├── StrikethroughNodeRenderer.java │ │ │ └── StrikethroughTextContentNodeRenderer.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── gfm │ └── strikethrough │ ├── StrikethroughMarkdownRendererTest.java │ ├── StrikethroughSpecTest.java │ └── StrikethroughTest.java ├── commonmark-ext-gfm-tables ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── gfm │ │ │ └── tables │ │ │ ├── TableBlock.java │ │ │ ├── TableBody.java │ │ │ ├── TableCell.java │ │ │ ├── TableHead.java │ │ │ ├── TableRow.java │ │ │ ├── TablesExtension.java │ │ │ └── internal │ │ │ ├── TableBlockParser.java │ │ │ ├── TableHtmlNodeRenderer.java │ │ │ ├── TableMarkdownNodeRenderer.java │ │ │ ├── TableNodeRenderer.java │ │ │ └── TableTextContentNodeRenderer.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── gfm │ └── tables │ ├── TableMarkdownRendererTest.java │ ├── TablesSpecTest.java │ ├── TablesTest.java │ └── TablesTextContentTest.java ├── commonmark-ext-heading-anchor ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── heading │ │ │ └── anchor │ │ │ ├── HeadingAnchorExtension.java │ │ │ ├── IdGenerator.java │ │ │ └── internal │ │ │ └── HeadingIdAttributeProvider.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── heading │ └── anchor │ ├── HeadingAnchorConfigurationTest.java │ └── HeadingAnchorTest.java ├── commonmark-ext-image-attributes ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── image │ │ │ └── attributes │ │ │ ├── ImageAttributes.java │ │ │ ├── ImageAttributesExtension.java │ │ │ └── internal │ │ │ ├── ImageAttributesAttributeProvider.java │ │ │ └── ImageAttributesDelimiterProcessor.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── image │ └── attributes │ └── ImageAttributesTest.java ├── commonmark-ext-ins ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── ins │ │ │ ├── Ins.java │ │ │ ├── InsExtension.java │ │ │ └── internal │ │ │ ├── InsDelimiterProcessor.java │ │ │ ├── InsHtmlNodeRenderer.java │ │ │ ├── InsMarkdownNodeRenderer.java │ │ │ ├── InsNodeRenderer.java │ │ │ └── InsTextContentNodeRenderer.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── ins │ ├── InsMarkdownRendererTest.java │ └── InsTest.java ├── commonmark-ext-task-list-items ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── task │ │ │ └── list │ │ │ └── items │ │ │ ├── TaskListItemMarker.java │ │ │ ├── TaskListItemsExtension.java │ │ │ └── internal │ │ │ ├── TaskListItemHtmlNodeRenderer.java │ │ │ └── TaskListItemPostProcessor.java │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── task │ └── list │ └── items │ └── TaskListItemsTest.java ├── commonmark-ext-yaml-front-matter ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ └── ext │ │ │ └── front │ │ │ └── matter │ │ │ ├── YamlFrontMatterBlock.java │ │ │ ├── YamlFrontMatterExtension.java │ │ │ ├── YamlFrontMatterNode.java │ │ │ ├── YamlFrontMatterVisitor.java │ │ │ └── internal │ │ │ └── YamlFrontMatterBlockParser.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ └── ext │ └── front │ └── matter │ └── YamlFrontMatterTest.java ├── commonmark-integration-test ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── commonmark │ │ │ └── integration │ │ │ └── IntegrationTests.java │ └── resources │ │ └── META-INF │ │ └── LICENSE.txt │ └── test │ └── java │ └── org │ └── commonmark │ ├── integration │ ├── BoundsIntegrationTest.java │ ├── Extensions.java │ ├── ExtensionsIntegrationTest.java │ ├── MarkdownRendererIntegrationTest.java │ ├── PegDownBenchmark.java │ ├── SourceSpanIntegrationTest.java │ └── SpecIntegrationTest.java │ └── ui │ └── DingusApp.java ├── commonmark-test-util ├── pom.xml └── src │ └── main │ ├── java │ ├── module-info.java │ └── org │ │ └── commonmark │ │ └── testutil │ │ ├── Asserts.java │ │ ├── RenderingTestCase.java │ │ ├── SpecTestCase.java │ │ ├── TestResources.java │ │ └── example │ │ ├── Example.java │ │ └── ExampleReader.java │ └── resources │ ├── META-INF │ └── LICENSE.txt │ ├── README.md │ ├── cmark-regression.txt │ ├── commonmark.js-regression.txt │ ├── gfm-spec.txt │ └── spec.txt ├── commonmark ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── module-info.java │ │ └── org │ │ │ └── commonmark │ │ │ ├── Extension.java │ │ │ ├── internal │ │ │ ├── BlockContent.java │ │ │ ├── BlockContinueImpl.java │ │ │ ├── BlockQuoteParser.java │ │ │ ├── BlockStartImpl.java │ │ │ ├── Bracket.java │ │ │ ├── Definitions.java │ │ │ ├── Delimiter.java │ │ │ ├── DocumentBlockParser.java │ │ │ ├── DocumentParser.java │ │ │ ├── FencedCodeBlockParser.java │ │ │ ├── HeadingParser.java │ │ │ ├── HtmlBlockParser.java │ │ │ ├── IndentedCodeBlockParser.java │ │ │ ├── InlineParserContextImpl.java │ │ │ ├── InlineParserImpl.java │ │ │ ├── LinkReferenceDefinitionParser.java │ │ │ ├── ListBlockParser.java │ │ │ ├── ListItemParser.java │ │ │ ├── ParagraphParser.java │ │ │ ├── StaggeredDelimiterProcessor.java │ │ │ ├── ThematicBreakParser.java │ │ │ ├── inline │ │ │ │ ├── AsteriskDelimiterProcessor.java │ │ │ │ ├── AutolinkInlineParser.java │ │ │ │ ├── BackslashInlineParser.java │ │ │ │ ├── BackticksInlineParser.java │ │ │ │ ├── CoreLinkProcessor.java │ │ │ │ ├── EmphasisDelimiterProcessor.java │ │ │ │ ├── EntityInlineParser.java │ │ │ │ ├── HtmlInlineParser.java │ │ │ │ ├── LinkResultImpl.java │ │ │ │ ├── ParsedInlineImpl.java │ │ │ │ └── UnderscoreDelimiterProcessor.java │ │ │ ├── renderer │ │ │ │ ├── NodeRendererMap.java │ │ │ │ └── text │ │ │ │ │ ├── BulletListHolder.java │ │ │ │ │ ├── ListHolder.java │ │ │ │ │ └── OrderedListHolder.java │ │ │ └── util │ │ │ │ ├── Escaping.java │ │ │ │ ├── Html5Entities.java │ │ │ │ ├── LineReader.java │ │ │ │ ├── LinkScanner.java │ │ │ │ └── Parsing.java │ │ │ ├── node │ │ │ ├── AbstractVisitor.java │ │ │ ├── Block.java │ │ │ ├── BlockQuote.java │ │ │ ├── BulletList.java │ │ │ ├── Code.java │ │ │ ├── CustomBlock.java │ │ │ ├── CustomNode.java │ │ │ ├── DefinitionMap.java │ │ │ ├── Delimited.java │ │ │ ├── Document.java │ │ │ ├── Emphasis.java │ │ │ ├── FencedCodeBlock.java │ │ │ ├── HardLineBreak.java │ │ │ ├── Heading.java │ │ │ ├── HtmlBlock.java │ │ │ ├── HtmlInline.java │ │ │ ├── Image.java │ │ │ ├── IndentedCodeBlock.java │ │ │ ├── Link.java │ │ │ ├── LinkReferenceDefinition.java │ │ │ ├── ListBlock.java │ │ │ ├── ListItem.java │ │ │ ├── Node.java │ │ │ ├── Nodes.java │ │ │ ├── OrderedList.java │ │ │ ├── Paragraph.java │ │ │ ├── SoftLineBreak.java │ │ │ ├── SourceSpan.java │ │ │ ├── SourceSpans.java │ │ │ ├── StrongEmphasis.java │ │ │ ├── Text.java │ │ │ ├── ThematicBreak.java │ │ │ ├── Visitor.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── parser │ │ │ ├── IncludeSourceSpans.java │ │ │ ├── InlineParser.java │ │ │ ├── InlineParserContext.java │ │ │ ├── InlineParserFactory.java │ │ │ ├── Parser.java │ │ │ ├── PostProcessor.java │ │ │ ├── SourceLine.java │ │ │ ├── SourceLines.java │ │ │ ├── beta │ │ │ │ ├── InlineContentParser.java │ │ │ │ ├── InlineContentParserFactory.java │ │ │ │ ├── InlineParserState.java │ │ │ │ ├── LinkInfo.java │ │ │ │ ├── LinkProcessor.java │ │ │ │ ├── LinkResult.java │ │ │ │ ├── ParsedInline.java │ │ │ │ ├── Position.java │ │ │ │ ├── Scanner.java │ │ │ │ └── package-info.java │ │ │ ├── block │ │ │ │ ├── AbstractBlockParser.java │ │ │ │ ├── AbstractBlockParserFactory.java │ │ │ │ ├── BlockContinue.java │ │ │ │ ├── BlockParser.java │ │ │ │ ├── BlockParserFactory.java │ │ │ │ ├── BlockStart.java │ │ │ │ ├── MatchedBlockParser.java │ │ │ │ ├── ParserState.java │ │ │ │ └── package-info.java │ │ │ ├── delimiter │ │ │ │ ├── DelimiterProcessor.java │ │ │ │ └── DelimiterRun.java │ │ │ └── package-info.java │ │ │ ├── renderer │ │ │ ├── NodeRenderer.java │ │ │ ├── Renderer.java │ │ │ ├── html │ │ │ │ ├── AttributeProvider.java │ │ │ │ ├── AttributeProviderContext.java │ │ │ │ ├── AttributeProviderFactory.java │ │ │ │ ├── CoreHtmlNodeRenderer.java │ │ │ │ ├── DefaultUrlSanitizer.java │ │ │ │ ├── HtmlNodeRendererContext.java │ │ │ │ ├── HtmlNodeRendererFactory.java │ │ │ │ ├── HtmlRenderer.java │ │ │ │ ├── HtmlWriter.java │ │ │ │ ├── UrlSanitizer.java │ │ │ │ └── package-info.java │ │ │ ├── markdown │ │ │ │ ├── CoreMarkdownNodeRenderer.java │ │ │ │ ├── MarkdownNodeRendererContext.java │ │ │ │ ├── MarkdownNodeRendererFactory.java │ │ │ │ ├── MarkdownRenderer.java │ │ │ │ ├── MarkdownWriter.java │ │ │ │ └── package-info.java │ │ │ └── text │ │ │ │ ├── CoreTextContentNodeRenderer.java │ │ │ │ ├── LineBreakRendering.java │ │ │ │ ├── TextContentNodeRendererContext.java │ │ │ │ ├── TextContentNodeRendererFactory.java │ │ │ │ ├── TextContentRenderer.java │ │ │ │ ├── TextContentWriter.java │ │ │ │ └── package-info.java │ │ │ └── text │ │ │ ├── AsciiMatcher.java │ │ │ ├── CharMatcher.java │ │ │ ├── Characters.java │ │ │ └── package-info.java │ ├── javadoc │ │ └── overview.html │ └── resources │ │ ├── META-INF │ │ └── LICENSE.txt │ │ └── org │ │ └── commonmark │ │ └── internal │ │ └── util │ │ └── entities.txt │ └── test │ └── java │ └── org │ └── commonmark │ ├── ProfilingMain.java │ ├── internal │ ├── DocumentParserTest.java │ ├── LinkReferenceDefinitionParserTest.java │ └── util │ │ ├── EscapingTest.java │ │ └── LineReaderTest.java │ ├── parser │ ├── InlineContentParserTest.java │ └── beta │ │ ├── LinkProcessorTest.java │ │ └── ScannerTest.java │ ├── renderer │ └── markdown │ │ ├── MarkdownRendererTest.java │ │ └── SpecMarkdownRendererTest.java │ ├── test │ ├── AbstractVisitorTest.java │ ├── CoreRenderingTestCase.java │ ├── DelimitedTest.java │ ├── DelimiterProcessorTest.java │ ├── FencedCodeBlockParserTest.java │ ├── HeadingParserTest.java │ ├── HtmlInlineParserTest.java │ ├── HtmlRendererTest.java │ ├── InlineParserContextTest.java │ ├── LinkReferenceDefinitionNodeTest.java │ ├── ListBlockParserTest.java │ ├── ListTightLooseTest.java │ ├── Nodes.java │ ├── ParserTest.java │ ├── PathologicalTest.java │ ├── RegressionTest.java │ ├── SourceLineTest.java │ ├── SourceSpanRenderer.java │ ├── SourceSpanTest.java │ ├── SourceSpansTest.java │ ├── SpecBenchmark.java │ ├── SpecCoreTest.java │ ├── SpecCrLfCoreTest.java │ ├── SpecialInputTest.java │ ├── TextContentRendererTest.java │ ├── TextContentWriterTest.java │ ├── ThematicBreakParserTest.java │ └── UsageExampleTest.java │ └── text │ └── CharactersTest.java ├── etc ├── benchmark.sh ├── entities.js └── update-spec.sh ├── mvnw ├── pom.xml └── renovate.json /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: 2 | layout: "diff, flags, files" 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | [*.java] 9 | indent_style = space 10 | indent_size = 4 11 | continuation_indent_size = 8 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Some input not render as you expect? Include an example so we can help 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | Steps to reproduce the problem (provide example Markdown if applicable): 11 | 12 | ``` 13 | my markdown 14 | ``` 15 | 16 | Expected behavior: 17 | 18 | ``` 19 | expected HTML 20 | ``` 21 | 22 | Actual behavior: 23 | 24 | ``` 25 | actual HTML 26 | ``` 27 | 28 | (Also see what the reference implementation does: https://spec.commonmark.org/dingus/) 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. Include source code if possible. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/en/actions/language-and-framework-guides/building-and-testing-java-with-maven 2 | 3 | name: ci 4 | 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | java: [11, 17, 21, 23] 13 | steps: 14 | - name: Checkout sources 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up JDK 18 | uses: actions/setup-java@v4 19 | with: 20 | java-version: ${{ matrix.java }} 21 | distribution: 'zulu' 22 | 23 | - name: Build 24 | run: mvn -B package javadoc:javadoc 25 | 26 | coverage: 27 | runs-on: ubuntu-latest 28 | if: ${{ github.event_name == 'push' }} 29 | steps: 30 | - name: Checkout sources 31 | uses: actions/checkout@v4 32 | 33 | - name: Set up JDK 34 | uses: actions/setup-java@v4 35 | with: 36 | java-version: 11 37 | distribution: 'zulu' 38 | 39 | - name: Build with coverage 40 | run: mvn -B -Pcoverage clean test jacoco:report-aggregate 41 | 42 | - name: Publish coverage 43 | uses: codecov/codecov-action@v4 44 | with: 45 | fail_ci_if_error: true 46 | token: ${{ secrets.CODECOV_TOKEN }} 47 | 48 | android-compatibility: 49 | runs-on: ubuntu-latest 50 | steps: 51 | - name: Checkout sources 52 | uses: actions/checkout@v4 53 | 54 | - name: Set up JDK 55 | uses: actions/setup-java@v4 56 | with: 57 | java-version: 11 58 | distribution: 'zulu' 59 | 60 | - name: Android Lint checks 61 | run: cd commonmark-android-test && ./gradlew :app:lint 62 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # See: 2 | # https://docs.github.com/en/free-pro-team@latest/actions/guides/publishing-java-packages-with-maven 3 | # https://central.sonatype.org/pages/apache-maven.html 4 | # https://github.com/actions/setup-java 5 | 6 | name: release 7 | 8 | on: 9 | workflow_dispatch: 10 | 11 | jobs: 12 | release: 13 | environment: maven_central 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout sources 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up Maven Central repository 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: 11 23 | distribution: 'zulu' 24 | server-id: ossrh 25 | server-username: MAVEN_USERNAME # env variable to use for username in release 26 | server-password: MAVEN_PASSWORD # env variable to use for password in release 27 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} 28 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable to use for passphrase in release 29 | 30 | - name: Set up Git user 31 | run: | 32 | git config --global user.name "${{ secrets.GIT_USER_NAME }}" 33 | git config --global user.email "${{ secrets.GIT_USER_EMAIL }}" 34 | 35 | - name: Release 36 | run: | 37 | mvn -B -Dusername=${{ secrets.GH_USERNAME }} -Dpassword=${{ secrets.GH_ACCESS_TOKEN }} release:prepare 38 | mvn -B release:perform 39 | env: 40 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 41 | MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 42 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .project 3 | .classpath 4 | .settings/ 5 | 6 | # IntelliJ IDEA 7 | .idea 8 | *.iml 9 | 10 | # Maven 11 | target/ 12 | 13 | # macOS 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Hey, thanks for your interest in contributing to this library! We welcome any 5 | type of pull request, issues and comments! 😀 6 | 7 | For pull requests, make sure you: 8 | 9 | * Add tests for new features and bug fixes 10 | * Follow the existing style (always use braces, 4 space indent) 11 | * Separate unrelated changes into multiple pull requests 12 | 13 | If you are interested in working on something but don't know what, see the 14 | existing issues with label "help wanted". 15 | 16 | For bigger changes, make sure you start a discussion first by creating 17 | an issue and explaining the intended change. 18 | 19 | The [sourcespy dashboard](https://sourcespy.com/github/commonmarkcommonmarkjava/) 20 | provides a high level overview of the repository including 21 | [class diagram](https://sourcespy.com/github/commonmarkcommonmarkjava/xx-omodel-.html), 22 | [module dependencies](https://sourcespy.com/github/commonmarkcommonmarkjava/xx-omodulesc-.html), 23 | [module hierarchy](https://sourcespy.com/github/commonmarkcommonmarkjava/xx-omodules-.html), 24 | [external libraries](https://sourcespy.com/github/commonmarkcommonmarkjava/xx-ojavalibs-.html), 25 | and other components of the system. 26 | 27 | Releasing 28 | --------- 29 | 30 | Releases are done from the "release" workflow on GitHub Actions. 31 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Robin Stocker 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-android-test/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | local.properties 3 | test.properties 4 | gradle.properties 5 | build 6 | -------------------------------------------------------------------------------- /commonmark-android-test/README.md: -------------------------------------------------------------------------------- 1 | commonmark-android-test 2 | ======================= 3 | 4 | This module ensures that commonmark-java is supported on Android by running `lint` checks on library sources. 5 | Current `minSdk` is 19 6 | 7 | Requirements: 8 | 9 | * Java 11 or above 10 | * Android SDK 30 11 | 12 | Configuration 13 | ----- 14 | 15 | 1. Download Android SDK 16 | 2. Be sure that SDK Platform 30 is installed. It's recommended to use x86 17 | 3. Export to PATH: `path_to_android_sdk/platform-tools` and `path_to_android_sdk/tools` 18 | 4. Create 2 properties files in commonmark-android-test 19 | 20 | /local.properties 21 | ```properties 22 | sdk.dir=/path_to_android_sdk 23 | ``` 24 | 25 | Usage 26 | ----- 27 | 28 | #### Run lint checked 29 | 30 | on Mac/Linux: 31 | ```shell 32 | ./gradlew :app:lint 33 | ``` 34 | 35 | on Windows: 36 | ```bat 37 | .\gradlew :app:lint 38 | ``` 39 | 40 | Links 41 | ----- 42 | [Gradle Documentations](https://docs.gradle.org/current/userguide/userguide.html) 43 | [Android Gradle Plugin Docs](http://tools.android.com/tech-docs/new-build-system) 44 | -------------------------------------------------------------------------------- /commonmark-android-test/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | namespace "org.commonmark.android.test" 5 | compileSdk 30 6 | 7 | defaultConfig { 8 | applicationId "org.commonmark.android.test" 9 | minSdk 19 10 | targetSdk 30 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | 15 | compileOptions { 16 | sourceCompatibility JavaVersion.VERSION_11 17 | targetCompatibility JavaVersion.VERSION_11 18 | } 19 | 20 | packagingOptions { 21 | exclude 'META-INF/LICENSE' 22 | exclude 'META-INF/LICENSE.txt' 23 | exclude 'META-INF/NOTICE' 24 | exclude 'META-INF/NOTICE.txt' 25 | } 26 | 27 | // we add other modules sources in order for lint to process them (lint operates on sources) 28 | sourceSets { 29 | main { 30 | java { 31 | [ 32 | '../../commonmark', 33 | '../../commonmark-ext-autolink', 34 | '../../commonmark-ext-gfm-strikethrough', 35 | '../../commonmark-ext-gfm-tables', 36 | '../../commonmark-ext-heading-anchor', 37 | '../../commonmark-ext-ins', 38 | '../../commonmark-ext-yaml-front-matter' 39 | ].forEach { d -> 40 | // don't include module-info files, otherwise we get 41 | // "too many module declarations found" 42 | PatternSet patternSet = new PatternSet().exclude('**/module-info.java') 43 | srcDirs += fileTree("$d/src/main/java").matching(patternSet) 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | dependencies { 51 | implementation('org.nibor.autolink:autolink:0.11.0') 52 | } 53 | -------------------------------------------------------------------------------- /commonmark-android-test/app/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /commonmark-android-test/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /commonmark-android-test/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:7.4.2' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | mavenCentral() 14 | google() 15 | } 16 | } 17 | 18 | task clean(type: Delete) { 19 | delete rootProject.buildDir 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /commonmark-android-test/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/commonmark/commonmark-java/749c0110cb48d8338b10593b849992d00d9d7611/commonmark-android-test/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /commonmark-android-test/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /commonmark-android-test/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /commonmark-ext-autolink/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-autolink 11 | commonmark-java extension for autolinking 12 | commonmark-java extension for turning plain URLs and email addresses into links 13 | 14 | 15 | 0.11.0 16 | 17 | 18 | 19 | 20 | org.commonmark 21 | commonmark 22 | 23 | 24 | org.nibor.autolink 25 | autolink 26 | ${autolink.version} 27 | 28 | 29 | 30 | org.commonmark 31 | commonmark-test-util 32 | test 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /commonmark-ext-autolink/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.autolink { 2 | exports org.commonmark.ext.autolink; 3 | 4 | requires transitive org.commonmark; 5 | requires org.nibor.autolink; 6 | } 7 | -------------------------------------------------------------------------------- /commonmark-ext-autolink/src/main/java/org/commonmark/ext/autolink/AutolinkExtension.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.autolink; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.autolink.internal.AutolinkPostProcessor; 5 | import org.commonmark.parser.Parser; 6 | import org.commonmark.renderer.html.HtmlRenderer; 7 | 8 | /** 9 | * Extension for automatically turning plain URLs and email addresses into links. 10 | *

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

15 | *

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

18 | */ 19 | public class AutolinkExtension implements Parser.ParserExtension { 20 | 21 | private AutolinkExtension() { 22 | } 23 | 24 | public static Extension create() { 25 | return new AutolinkExtension(); 26 | } 27 | 28 | @Override 29 | public void extend(Parser.Builder parserBuilder) { 30 | parserBuilder.postProcessor(new AutolinkPostProcessor()); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /commonmark-ext-autolink/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for automatically turning plain URLs and email addresses into links 4 |

See {@link org.commonmark.ext.autolink.AutolinkExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-autolink/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-footnotes 11 | commonmark-java extension for footnotes 12 | commonmark-java extension for footnotes using [^1] syntax 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.footnotes { 2 | exports org.commonmark.ext.footnotes; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteDefinition.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.footnotes; 2 | 3 | import org.commonmark.node.CustomBlock; 4 | 5 | /** 6 | * A footnote definition, e.g.: 7 | *

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

13 | * Footnote definitions are parsed even if there's no corresponding {@link FootnoteReference}. 14 | */ 15 | public class FootnoteDefinition extends CustomBlock { 16 | 17 | private String label; 18 | 19 | public FootnoteDefinition(String label) { 20 | this.label = label; 21 | } 22 | 23 | public String getLabel() { 24 | return label; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/FootnoteReference.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.footnotes; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * A footnote reference, e.g. [^foo] in Some text with a footnote[^foo] 7 | *

8 | * The {@link #getLabel() label} is the text within brackets after {@code ^}, so {@code foo} in the example. It needs to 9 | * match the label of a corresponding {@link FootnoteDefinition} for the footnote to be parsed. 10 | */ 11 | public class FootnoteReference extends CustomNode { 12 | private String label; 13 | 14 | public FootnoteReference(String label) { 15 | this.label = label; 16 | } 17 | 18 | public String getLabel() { 19 | return label; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/InlineFootnote.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.footnotes; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | public class InlineFootnote extends CustomNode { 6 | } 7 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for footnotes using [^1] syntax 4 |

See {@link org.commonmark.ext.footnotes.FootnotesExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.footnotes; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.parser.Parser; 6 | import org.commonmark.renderer.markdown.MarkdownRenderer; 7 | import org.junit.Test; 8 | 9 | import java.util.Set; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | public class FootnoteMarkdownRendererTest { 14 | private static final Set EXTENSIONS = Set.of(FootnotesExtension.builder().inlineFootnotes(true).build()); 15 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 16 | private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); 17 | 18 | @Test 19 | public void testSimple() { 20 | assertRoundTrip("Test [^foo]\n\n[^foo]: note\n"); 21 | } 22 | 23 | @Test 24 | public void testUnreferenced() { 25 | // Whether a reference has a corresponding definition or vice versa shouldn't matter for Markdown rendering. 26 | assertRoundTrip("Test [^foo]\n\n[^foo]: one\n[^bar]: two\n"); 27 | } 28 | 29 | @Test 30 | public void testFootnoteWithBlock() { 31 | assertRoundTrip("Test [^foo]\n\n[^foo]: - foo\n - bar\n"); 32 | } 33 | 34 | @Test 35 | public void testBackslashInLabel() { 36 | assertRoundTrip("[^\\foo]\n\n[^\\foo]: note\n"); 37 | } 38 | 39 | @Test 40 | public void testInline() { 41 | assertRoundTrip("^[test *foo*]\n"); 42 | } 43 | 44 | private void assertRoundTrip(String input) { 45 | String rendered = parseAndRender(input); 46 | assertEquals(input, rendered); 47 | } 48 | 49 | private String parseAndRender(String source) { 50 | Node parsed = PARSER.parse(source); 51 | return RENDERER.render(parsed); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /commonmark-ext-footnotes/src/test/resources/footnotes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Footnotes testing 7 | 12 | 13 | 14 | 15 | Paste HTML from footnote rendering in here to manually check that linking works as expected. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-gfm-strikethrough 11 | commonmark-java extension for strikethrough 12 | commonmark-java extension for GFM strikethrough using ~~ (GitHub Flavored Markdown) 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.gfm.strikethrough { 2 | exports org.commonmark.ext.gfm.strikethrough; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/Strikethrough.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough; 2 | 3 | import org.commonmark.node.CustomNode; 4 | import org.commonmark.node.Delimited; 5 | 6 | /** 7 | * A strikethrough node containing text and other inline nodes as children. 8 | */ 9 | public class Strikethrough extends CustomNode implements Delimited { 10 | 11 | private String delimiter; 12 | 13 | public Strikethrough(String delimiter) { 14 | this.delimiter = delimiter; 15 | } 16 | 17 | @Override 18 | public String getOpeningDelimiter() { 19 | return delimiter; 20 | } 21 | 22 | @Override 23 | public String getClosingDelimiter() { 24 | return delimiter; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughHtmlNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 5 | import org.commonmark.renderer.html.HtmlWriter; 6 | 7 | import java.util.Map; 8 | 9 | public class StrikethroughHtmlNodeRenderer extends StrikethroughNodeRenderer { 10 | 11 | private final HtmlNodeRendererContext context; 12 | private final HtmlWriter html; 13 | 14 | public StrikethroughHtmlNodeRenderer(HtmlNodeRendererContext context) { 15 | this.context = context; 16 | this.html = context.getWriter(); 17 | } 18 | 19 | @Override 20 | public void render(Node node) { 21 | Map attributes = context.extendAttributes(node, "del", Map.of()); 22 | html.tag("del", attributes); 23 | renderChildren(node); 24 | html.tag("/del"); 25 | } 26 | 27 | private void renderChildren(Node parent) { 28 | Node node = parent.getFirstChild(); 29 | while (node != null) { 30 | Node next = node.getNext(); 31 | context.render(node); 32 | node = next; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughMarkdownNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough.internal; 2 | 3 | import org.commonmark.ext.gfm.strikethrough.Strikethrough; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.markdown.MarkdownNodeRendererContext; 6 | import org.commonmark.renderer.markdown.MarkdownWriter; 7 | 8 | public class StrikethroughMarkdownNodeRenderer extends StrikethroughNodeRenderer { 9 | 10 | private final MarkdownNodeRendererContext context; 11 | private final MarkdownWriter writer; 12 | 13 | public StrikethroughMarkdownNodeRenderer(MarkdownNodeRendererContext context) { 14 | this.context = context; 15 | this.writer = context.getWriter(); 16 | } 17 | 18 | @Override 19 | public void render(Node node) { 20 | Strikethrough strikethrough = (Strikethrough) node; 21 | writer.raw(strikethrough.getOpeningDelimiter()); 22 | renderChildren(node); 23 | writer.raw(strikethrough.getClosingDelimiter()); 24 | } 25 | 26 | private void renderChildren(Node parent) { 27 | Node node = parent.getFirstChild(); 28 | while (node != null) { 29 | Node next = node.getNext(); 30 | context.render(node); 31 | node = next; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough.internal; 2 | 3 | import org.commonmark.ext.gfm.strikethrough.Strikethrough; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | 7 | import java.util.Set; 8 | 9 | abstract class StrikethroughNodeRenderer implements NodeRenderer { 10 | 11 | @Override 12 | public Set> getNodeTypes() { 13 | return Set.of(Strikethrough.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/java/org/commonmark/ext/gfm/strikethrough/internal/StrikethroughTextContentNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough.internal; 2 | 3 | import org.commonmark.renderer.text.TextContentWriter; 4 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 5 | import org.commonmark.node.Node; 6 | 7 | public class StrikethroughTextContentNodeRenderer extends StrikethroughNodeRenderer { 8 | 9 | private final TextContentNodeRendererContext context; 10 | private final TextContentWriter textContent; 11 | 12 | public StrikethroughTextContentNodeRenderer(TextContentNodeRendererContext context) { 13 | this.context = context; 14 | this.textContent = context.getWriter(); 15 | } 16 | 17 | @Override 18 | public void render(Node node) { 19 | textContent.write('/'); 20 | renderChildren(node); 21 | textContent.write('/'); 22 | } 23 | 24 | private void renderChildren(Node parent) { 25 | Node node = parent.getFirstChild(); 26 | while (node != null) { 27 | Node next = node.getNext(); 28 | context.render(node); 29 | node = next; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for GFM strikethrough using ~~ (GitHub Flavored Markdown) 4 |

See {@link org.commonmark.ext.gfm.strikethrough.StrikethroughExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughMarkdownRendererTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.markdown.MarkdownRenderer; 6 | import org.junit.Test; 7 | 8 | import java.util.Set; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | public class StrikethroughMarkdownRendererTest { 13 | 14 | private static final Set EXTENSIONS = Set.of(StrikethroughExtension.create()); 15 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 16 | private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); 17 | 18 | @Test 19 | public void testStrikethrough() { 20 | assertRoundTrip("~foo~ ~bar~\n"); 21 | assertRoundTrip("~~foo~~ ~~bar~~\n"); 22 | assertRoundTrip("~~f\\~oo~~ ~~bar~~\n"); 23 | 24 | assertRoundTrip("\\~foo\\~\n"); 25 | } 26 | 27 | protected String render(String source) { 28 | return RENDERER.render(PARSER.parse(source)); 29 | } 30 | 31 | private void assertRoundTrip(String input) { 32 | String rendered = render(input); 33 | assertEquals(input, rendered); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-strikethrough/src/test/java/org/commonmark/ext/gfm/strikethrough/StrikethroughSpecTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.strikethrough; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.html.HtmlRenderer; 6 | import org.commonmark.testutil.RenderingTestCase; 7 | import org.commonmark.testutil.TestResources; 8 | import org.commonmark.testutil.example.Example; 9 | import org.commonmark.testutil.example.ExampleReader; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.junit.runners.Parameterized; 13 | import org.junit.runners.Parameterized.Parameters; 14 | 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | @RunWith(Parameterized.class) 19 | public class StrikethroughSpecTest extends RenderingTestCase { 20 | 21 | private static final Set EXTENSIONS = Set.of(StrikethroughExtension.create()); 22 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 23 | private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); 24 | 25 | private final Example example; 26 | 27 | public StrikethroughSpecTest(Example example) { 28 | this.example = example; 29 | } 30 | 31 | @Parameters(name = "{0}") 32 | public static List data() { 33 | return ExampleReader.readExampleObjects(TestResources.getGfmSpec(), "strikethrough"); 34 | } 35 | 36 | @Test 37 | public void testHtmlRendering() { 38 | assertRendering(example.getSource(), example.getHtml()); 39 | } 40 | 41 | @Override 42 | protected String render(String source) { 43 | return RENDERER.render(PARSER.parse(source)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-gfm-tables 11 | commonmark-java extension for tables 12 | commonmark-java extension for GFM tables using "|" pipes (GitHub Flavored Markdown) 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.gfm.tables { 2 | exports org.commonmark.ext.gfm.tables; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.node.CustomBlock; 4 | 5 | /** 6 | * Table block containing a {@link TableHead} and optionally a {@link TableBody}. 7 | */ 8 | public class TableBlock extends CustomBlock { 9 | } 10 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableBody.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * Body part of a {@link TableBlock} containing {@link TableRow TableRows}. 7 | */ 8 | public class TableBody extends CustomNode { 9 | } 10 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableCell.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * Table cell of a {@link TableRow} containing inline nodes. 7 | */ 8 | public class TableCell extends CustomNode { 9 | 10 | private boolean header; 11 | private Alignment alignment; 12 | private int width; 13 | 14 | /** 15 | * @return whether the cell is a header or not 16 | */ 17 | public boolean isHeader() { 18 | return header; 19 | } 20 | 21 | public void setHeader(boolean header) { 22 | this.header = header; 23 | } 24 | 25 | /** 26 | * @return the cell alignment or {@code null} if no specific alignment 27 | */ 28 | public Alignment getAlignment() { 29 | return alignment; 30 | } 31 | 32 | public void setAlignment(Alignment alignment) { 33 | this.alignment = alignment; 34 | } 35 | 36 | /** 37 | * @return the cell width (the number of dash and colon characters in the delimiter row of the table for this column) 38 | */ 39 | public int getWidth() { 40 | return width; 41 | } 42 | 43 | public void setWidth(int width) { 44 | this.width = width; 45 | } 46 | 47 | /** 48 | * How the cell is aligned horizontally. 49 | */ 50 | public enum Alignment { 51 | LEFT, CENTER, RIGHT 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableHead.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * Head part of a {@link TableBlock} containing {@link TableRow TableRows}. 7 | */ 8 | public class TableHead extends CustomNode { 9 | } 10 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/TableRow.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * Table row of a {@link TableHead} or {@link TableBody} containing {@link TableCell TableCells}. 7 | */ 8 | public class TableRow extends CustomNode { 9 | } 10 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/java/org/commonmark/ext/gfm/tables/internal/TableNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables.internal; 2 | 3 | import org.commonmark.ext.gfm.tables.*; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | 7 | import java.util.Set; 8 | 9 | abstract class TableNodeRenderer implements NodeRenderer { 10 | 11 | @Override 12 | public Set> getNodeTypes() { 13 | return Set.of( 14 | TableBlock.class, 15 | TableHead.class, 16 | TableBody.class, 17 | TableRow.class, 18 | TableCell.class 19 | ); 20 | } 21 | 22 | @Override 23 | public void render(Node node) { 24 | if (node instanceof TableBlock) { 25 | renderBlock((TableBlock) node); 26 | } else if (node instanceof TableHead) { 27 | renderHead((TableHead) node); 28 | } else if (node instanceof TableBody) { 29 | renderBody((TableBody) node); 30 | } else if (node instanceof TableRow) { 31 | renderRow((TableRow) node); 32 | } else if (node instanceof TableCell) { 33 | renderCell((TableCell) node); 34 | } 35 | } 36 | 37 | protected abstract void renderBlock(TableBlock node); 38 | 39 | protected abstract void renderHead(TableHead node); 40 | 41 | protected abstract void renderBody(TableBody node); 42 | 43 | protected abstract void renderRow(TableRow node); 44 | 45 | protected abstract void renderCell(TableCell node); 46 | } 47 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for GFM tables using "|" pipes (GitHub Flavored Markdown) 4 |

See {@link org.commonmark.ext.gfm.tables.TablesExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-gfm-tables/src/test/java/org/commonmark/ext/gfm/tables/TablesSpecTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.gfm.tables; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.html.HtmlRenderer; 6 | import org.commonmark.testutil.RenderingTestCase; 7 | import org.commonmark.testutil.TestResources; 8 | import org.commonmark.testutil.example.Example; 9 | import org.commonmark.testutil.example.ExampleReader; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.junit.runners.Parameterized; 13 | import org.junit.runners.Parameterized.Parameters; 14 | 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | @RunWith(Parameterized.class) 19 | public class TablesSpecTest extends RenderingTestCase { 20 | 21 | private static final Set EXTENSIONS = Set.of(TablesExtension.create()); 22 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 23 | private static final HtmlRenderer RENDERER = HtmlRenderer.builder().extensions(EXTENSIONS).build(); 24 | 25 | private final Example example; 26 | 27 | public TablesSpecTest(Example example) { 28 | this.example = example; 29 | } 30 | 31 | @Parameters(name = "{0}") 32 | public static List data() { 33 | return ExampleReader.readExampleObjects(TestResources.getGfmSpec(), "table"); 34 | } 35 | 36 | @Test 37 | public void testHtmlRendering() { 38 | assertRendering(example.getSource(), example.getHtml()); 39 | } 40 | 41 | @Override 42 | protected String render(String source) { 43 | return RENDERER.render(PARSER.parse(source)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commonmark-ext-heading-anchor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-heading-anchor 11 | commonmark-java extension for adding id attributes to h tags 12 | commonmark-java extension for adding unique id attributes to header tags 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-heading-anchor/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.heading.anchor { 2 | exports org.commonmark.ext.heading.anchor; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-heading-anchor/src/main/java/org/commonmark/ext/heading/anchor/internal/HeadingIdAttributeProvider.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.heading.anchor.internal; 2 | 3 | import org.commonmark.ext.heading.anchor.IdGenerator; 4 | import org.commonmark.renderer.html.AttributeProvider; 5 | import org.commonmark.node.*; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class HeadingIdAttributeProvider implements AttributeProvider { 12 | 13 | private final IdGenerator idGenerator; 14 | 15 | private HeadingIdAttributeProvider(String defaultId, String prefix, String suffix) { 16 | idGenerator = IdGenerator.builder() 17 | .defaultId(defaultId) 18 | .prefix(prefix) 19 | .suffix(suffix) 20 | .build(); 21 | } 22 | 23 | public static HeadingIdAttributeProvider create(String defaultId, String prefix, String suffix) { 24 | return new HeadingIdAttributeProvider(defaultId, prefix, suffix); 25 | } 26 | 27 | @Override 28 | public void setAttributes(Node node, String tagName, final Map attributes) { 29 | 30 | if (node instanceof Heading) { 31 | 32 | final List wordList = new ArrayList<>(); 33 | 34 | node.accept(new AbstractVisitor() { 35 | @Override 36 | public void visit(Text text) { 37 | wordList.add(text.getLiteral()); 38 | } 39 | 40 | @Override 41 | public void visit(Code code) { 42 | wordList.add(code.getLiteral()); 43 | } 44 | }); 45 | 46 | String finalString = ""; 47 | for (String word : wordList) { 48 | finalString += word; 49 | } 50 | finalString = finalString.trim().toLowerCase(); 51 | 52 | attributes.put("id", idGenerator.generateId(finalString)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /commonmark-ext-heading-anchor/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for automatically adding {@code id} attributes to all headers 4 |

See {@link org.commonmark.ext.heading.anchor.HeadingAnchorExtension} or use 5 | {@link org.commonmark.ext.heading.anchor.IdGenerator} directly.

6 | 7 | 8 | -------------------------------------------------------------------------------- /commonmark-ext-heading-anchor/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-image-attributes 11 | commonmark-java extension for image attributes 12 | commonmark-java extension for adding attributes to images 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.image.attributes { 2 | exports org.commonmark.ext.image.attributes; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributes.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.image.attributes; 2 | 3 | import org.commonmark.node.CustomNode; 4 | import org.commonmark.node.Delimited; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * A node containing text and other inline nodes as children. 10 | */ 11 | public class ImageAttributes extends CustomNode implements Delimited { 12 | 13 | private final Map attributes; 14 | 15 | public ImageAttributes(Map attributes) { 16 | this.attributes = attributes; 17 | } 18 | 19 | @Override 20 | public String getOpeningDelimiter() { 21 | return "{"; 22 | } 23 | 24 | @Override 25 | public String getClosingDelimiter() { 26 | return "}"; 27 | } 28 | 29 | public Map getAttributes() { 30 | return attributes; 31 | } 32 | 33 | @Override 34 | protected String toStringAttributes() { 35 | return "imageAttributes=" + attributes; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/ImageAttributesExtension.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.image.attributes; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.image.attributes.internal.ImageAttributesAttributeProvider; 5 | import org.commonmark.ext.image.attributes.internal.ImageAttributesDelimiterProcessor; 6 | import org.commonmark.parser.Parser; 7 | import org.commonmark.renderer.html.AttributeProvider; 8 | import org.commonmark.renderer.html.AttributeProviderContext; 9 | import org.commonmark.renderer.html.AttributeProviderFactory; 10 | import org.commonmark.renderer.html.HtmlRenderer; 11 | 12 | /** 13 | * Extension for adding attributes to image nodes. 14 | *

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

19 | * 20 | * @since 0.15.0 21 | */ 22 | public class ImageAttributesExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { 23 | 24 | private ImageAttributesExtension() { 25 | } 26 | 27 | public static Extension create() { 28 | return new ImageAttributesExtension(); 29 | } 30 | 31 | @Override 32 | public void extend(Parser.Builder parserBuilder) { 33 | parserBuilder.customDelimiterProcessor(new ImageAttributesDelimiterProcessor()); 34 | } 35 | 36 | @Override 37 | public void extend(HtmlRenderer.Builder rendererBuilder) { 38 | rendererBuilder.attributeProviderFactory(new AttributeProviderFactory() { 39 | @Override 40 | public AttributeProvider create(AttributeProviderContext context) { 41 | return ImageAttributesAttributeProvider.create(); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/java/org/commonmark/ext/image/attributes/internal/ImageAttributesAttributeProvider.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.image.attributes.internal; 2 | 3 | import org.commonmark.ext.image.attributes.ImageAttributes; 4 | import org.commonmark.node.AbstractVisitor; 5 | import org.commonmark.node.CustomNode; 6 | import org.commonmark.node.Image; 7 | import org.commonmark.node.Node; 8 | import org.commonmark.renderer.html.AttributeProvider; 9 | 10 | import java.util.*; 11 | 12 | public class ImageAttributesAttributeProvider implements AttributeProvider { 13 | 14 | private ImageAttributesAttributeProvider() { 15 | } 16 | 17 | public static ImageAttributesAttributeProvider create() { 18 | return new ImageAttributesAttributeProvider(); 19 | } 20 | 21 | @Override 22 | public void setAttributes(Node node, String tagName, final Map attributes) { 23 | if (node instanceof Image) { 24 | node.accept(new AbstractVisitor() { 25 | @Override 26 | public void visit(CustomNode node) { 27 | if (node instanceof ImageAttributes) { 28 | ImageAttributes imageAttributes = (ImageAttributes) node; 29 | for (Map.Entry entry : imageAttributes.getAttributes().entrySet()) { 30 | attributes.put(entry.getKey(), entry.getValue()); 31 | } 32 | // Now that we have used the image attributes we remove the node. 33 | imageAttributes.unlink(); 34 | } 35 | } 36 | }); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for adding attributes to image nodes 4 |

See {@link org.commonmark.ext.image.attributes.ImageAttributes}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-image-attributes/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-ins/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-ins 11 | commonmark-java extension for <ins> (underline) 12 | commonmark-java extension for <ins> using ++ 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.ins { 2 | exports org.commonmark.ext.ins; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/Ins.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins; 2 | 3 | import org.commonmark.node.CustomNode; 4 | import org.commonmark.node.Delimited; 5 | 6 | /** 7 | * An ins node containing text and other inline nodes as children. 8 | */ 9 | public class Ins extends CustomNode implements Delimited { 10 | 11 | private static final String DELIMITER = "++"; 12 | 13 | @Override 14 | public String getOpeningDelimiter() { 15 | return DELIMITER; 16 | } 17 | 18 | @Override 19 | public String getClosingDelimiter() { 20 | return DELIMITER; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsDelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins.internal; 2 | 3 | import org.commonmark.ext.ins.Ins; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.node.Nodes; 6 | import org.commonmark.node.SourceSpans; 7 | import org.commonmark.node.Text; 8 | import org.commonmark.parser.delimiter.DelimiterProcessor; 9 | import org.commonmark.parser.delimiter.DelimiterRun; 10 | 11 | public class InsDelimiterProcessor implements DelimiterProcessor { 12 | 13 | @Override 14 | public char getOpeningCharacter() { 15 | return '+'; 16 | } 17 | 18 | @Override 19 | public char getClosingCharacter() { 20 | return '+'; 21 | } 22 | 23 | @Override 24 | public int getMinLength() { 25 | return 2; 26 | } 27 | 28 | @Override 29 | public int process(DelimiterRun openingRun, DelimiterRun closingRun) { 30 | if (openingRun.length() >= 2 && closingRun.length() >= 2) { 31 | // Use exactly two delimiters even if we have more, and don't care about internal openers/closers. 32 | 33 | Text opener = openingRun.getOpener(); 34 | 35 | // Wrap nodes between delimiters in ins. 36 | Node ins = new Ins(); 37 | 38 | SourceSpans sourceSpans = new SourceSpans(); 39 | sourceSpans.addAllFrom(openingRun.getOpeners(2)); 40 | 41 | for (Node node : Nodes.between(opener, closingRun.getCloser())) { 42 | ins.appendChild(node); 43 | sourceSpans.addAll(node.getSourceSpans()); 44 | } 45 | 46 | sourceSpans.addAllFrom(closingRun.getClosers(2)); 47 | ins.setSourceSpans(sourceSpans.getSourceSpans()); 48 | 49 | opener.insertAfter(ins); 50 | 51 | return 2; 52 | } else { 53 | return 0; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsHtmlNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 5 | import org.commonmark.renderer.html.HtmlWriter; 6 | 7 | import java.util.Map; 8 | 9 | public class InsHtmlNodeRenderer extends InsNodeRenderer { 10 | 11 | private final HtmlNodeRendererContext context; 12 | private final HtmlWriter html; 13 | 14 | public InsHtmlNodeRenderer(HtmlNodeRendererContext context) { 15 | this.context = context; 16 | this.html = context.getWriter(); 17 | } 18 | 19 | @Override 20 | public void render(Node node) { 21 | Map attributes = context.extendAttributes(node, "ins", Map.of()); 22 | html.tag("ins", attributes); 23 | renderChildren(node); 24 | html.tag("/ins"); 25 | } 26 | 27 | private void renderChildren(Node parent) { 28 | Node node = parent.getFirstChild(); 29 | while (node != null) { 30 | Node next = node.getNext(); 31 | context.render(node); 32 | node = next; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsMarkdownNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.markdown.MarkdownNodeRendererContext; 5 | import org.commonmark.renderer.markdown.MarkdownWriter; 6 | 7 | public class InsMarkdownNodeRenderer extends InsNodeRenderer { 8 | 9 | private final MarkdownNodeRendererContext context; 10 | private final MarkdownWriter writer; 11 | 12 | public InsMarkdownNodeRenderer(MarkdownNodeRendererContext context) { 13 | this.context = context; 14 | this.writer = context.getWriter(); 15 | } 16 | 17 | @Override 18 | public void render(Node node) { 19 | writer.raw("++"); 20 | renderChildren(node); 21 | writer.raw("++"); 22 | } 23 | 24 | private void renderChildren(Node parent) { 25 | Node node = parent.getFirstChild(); 26 | while (node != null) { 27 | Node next = node.getNext(); 28 | context.render(node); 29 | node = next; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins.internal; 2 | 3 | import org.commonmark.ext.ins.Ins; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | 7 | import java.util.Set; 8 | 9 | abstract class InsNodeRenderer implements NodeRenderer { 10 | 11 | @Override 12 | public Set> getNodeTypes() { 13 | return Set.of(Ins.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/java/org/commonmark/ext/ins/internal/InsTextContentNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 5 | 6 | public class InsTextContentNodeRenderer extends InsNodeRenderer { 7 | 8 | private final TextContentNodeRendererContext context; 9 | 10 | public InsTextContentNodeRenderer(TextContentNodeRendererContext context) { 11 | this.context = context; 12 | } 13 | 14 | @Override 15 | public void render(Node node) { 16 | renderChildren(node); 17 | } 18 | 19 | private void renderChildren(Node parent) { 20 | Node node = parent.getFirstChild(); 21 | while (node != null) { 22 | Node next = node.getNext(); 23 | context.render(node); 24 | node = next; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for ins (underline) using ++ 4 |

See {@link org.commonmark.ext.ins.InsExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-ins/src/test/java/org/commonmark/ext/ins/InsMarkdownRendererTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.ins; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.markdown.MarkdownRenderer; 6 | import org.junit.Test; 7 | 8 | import java.util.Set; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | public class InsMarkdownRendererTest { 13 | 14 | private static final Set EXTENSIONS = Set.of(InsExtension.create()); 15 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 16 | private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); 17 | 18 | @Test 19 | public void testStrikethrough() { 20 | assertRoundTrip("++foo++\n"); 21 | 22 | assertRoundTrip("\\+\\+foo\\+\\+\n"); 23 | } 24 | 25 | protected String render(String source) { 26 | return RENDERER.render(PARSER.parse(source)); 27 | } 28 | 29 | private void assertRoundTrip(String input) { 30 | String rendered = render(input); 31 | assertEquals(input, rendered); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-task-list-items 11 | commonmark-java extension for task list items 12 | commonmark-java extension for task list items 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.task.list.items { 2 | exports org.commonmark.ext.task.list.items; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemMarker.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.task.list.items; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | /** 6 | * A marker node indicating that a list item contains a task. 7 | */ 8 | public class TaskListItemMarker extends CustomNode { 9 | 10 | private final boolean checked; 11 | 12 | public TaskListItemMarker(boolean checked) { 13 | this.checked = checked; 14 | } 15 | 16 | public boolean isChecked() { 17 | return checked; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/TaskListItemsExtension.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.task.list.items; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.task.list.items.internal.TaskListItemHtmlNodeRenderer; 5 | import org.commonmark.ext.task.list.items.internal.TaskListItemPostProcessor; 6 | import org.commonmark.parser.Parser; 7 | import org.commonmark.renderer.NodeRenderer; 8 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 9 | import org.commonmark.renderer.html.HtmlNodeRendererFactory; 10 | import org.commonmark.renderer.html.HtmlRenderer; 11 | 12 | /** 13 | * Extension for adding task list items. 14 | *

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

19 | * 20 | * @since 0.15.0 21 | */ 22 | public class TaskListItemsExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { 23 | 24 | private TaskListItemsExtension() { 25 | } 26 | 27 | public static Extension create() { 28 | return new TaskListItemsExtension(); 29 | } 30 | 31 | @Override 32 | public void extend(Parser.Builder parserBuilder) { 33 | parserBuilder.postProcessor(new TaskListItemPostProcessor()); 34 | } 35 | 36 | @Override 37 | public void extend(HtmlRenderer.Builder rendererBuilder) { 38 | rendererBuilder.nodeRendererFactory(new HtmlNodeRendererFactory() { 39 | @Override 40 | public NodeRenderer create(HtmlNodeRendererContext context) { 41 | return new TaskListItemHtmlNodeRenderer(context); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/src/main/java/org/commonmark/ext/task/list/items/internal/TaskListItemHtmlNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.task.list.items.internal; 2 | 3 | import org.commonmark.ext.task.list.items.TaskListItemMarker; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 7 | import org.commonmark.renderer.html.HtmlWriter; 8 | 9 | import java.util.LinkedHashMap; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | public class TaskListItemHtmlNodeRenderer implements NodeRenderer { 14 | 15 | private final HtmlNodeRendererContext context; 16 | private final HtmlWriter html; 17 | 18 | public TaskListItemHtmlNodeRenderer(HtmlNodeRendererContext context) { 19 | this.context = context; 20 | this.html = context.getWriter(); 21 | } 22 | 23 | @Override 24 | public Set> getNodeTypes() { 25 | return Set.of(TaskListItemMarker.class); 26 | } 27 | 28 | @Override 29 | public void render(Node node) { 30 | if (node instanceof TaskListItemMarker) { 31 | Map attributes = new LinkedHashMap<>(); 32 | attributes.put("type", "checkbox"); 33 | attributes.put("disabled", ""); 34 | if (((TaskListItemMarker) node).isChecked()) { 35 | attributes.put("checked", ""); 36 | } 37 | html.tag("input", context.extendAttributes(node, "input", attributes)); 38 | // Add a space after the input tag (as the next text node has been trimmed) 39 | html.text(" "); 40 | renderChildren(node); 41 | } 42 | } 43 | 44 | private void renderChildren(Node parent) { 45 | Node node = parent.getFirstChild(); 46 | while (node != null) { 47 | Node next = node.getNext(); 48 | context.render(node); 49 | node = next; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /commonmark-ext-task-list-items/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | commonmark-parent 6 | org.commonmark 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-ext-yaml-front-matter 11 | commonmark-java extension for YAML front matter 12 | commonmark-java extension for YAML front matter 13 | 14 | 15 | 16 | org.commonmark 17 | commonmark 18 | 19 | 20 | 21 | org.commonmark 22 | commonmark-test-util 23 | test 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.ext.front.matter { 2 | exports org.commonmark.ext.front.matter; 3 | 4 | requires transitive org.commonmark; 5 | } 6 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.front.matter; 2 | 3 | import org.commonmark.node.CustomBlock; 4 | 5 | public class YamlFrontMatterBlock extends CustomBlock { 6 | } 7 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterExtension.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.front.matter; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.front.matter.internal.YamlFrontMatterBlockParser; 5 | import org.commonmark.parser.Parser; 6 | import org.commonmark.renderer.html.HtmlRenderer; 7 | 8 | /** 9 | * Extension for YAML-like metadata. 10 | *

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

15 | *

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

18 | */ 19 | public class YamlFrontMatterExtension implements Parser.ParserExtension { 20 | 21 | private YamlFrontMatterExtension() { 22 | } 23 | 24 | @Override 25 | public void extend(Parser.Builder parserBuilder) { 26 | parserBuilder.customBlockParserFactory(new YamlFrontMatterBlockParser.Factory()); 27 | } 28 | 29 | public static Extension create() { 30 | return new YamlFrontMatterExtension(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterNode.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.front.matter; 2 | 3 | import org.commonmark.node.CustomNode; 4 | 5 | import java.util.List; 6 | 7 | public class YamlFrontMatterNode extends CustomNode { 8 | private String key; 9 | private List values; 10 | 11 | public YamlFrontMatterNode(String key, List values) { 12 | this.key = key; 13 | this.values = values; 14 | } 15 | 16 | public String getKey() { 17 | return key; 18 | } 19 | 20 | public void setKey(String key) { 21 | this.key = key; 22 | } 23 | 24 | public List getValues() { 25 | return values; 26 | } 27 | 28 | public void setValues(List values) { 29 | this.values = values; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/java/org/commonmark/ext/front/matter/YamlFrontMatterVisitor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.ext.front.matter; 2 | 3 | import org.commonmark.node.AbstractVisitor; 4 | import org.commonmark.node.CustomNode; 5 | 6 | import java.util.LinkedHashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class YamlFrontMatterVisitor extends AbstractVisitor { 11 | private Map> data; 12 | 13 | public YamlFrontMatterVisitor() { 14 | data = new LinkedHashMap<>(); 15 | } 16 | 17 | @Override 18 | public void visit(CustomNode customNode) { 19 | if (customNode instanceof YamlFrontMatterNode) { 20 | data.put(((YamlFrontMatterNode) customNode).getKey(), ((YamlFrontMatterNode) customNode).getValues()); 21 | } else { 22 | super.visit(customNode); 23 | } 24 | } 25 | 26 | public Map> getData() { 27 | return data; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extension for YAML front matter 4 |

See {@link org.commonmark.ext.front.matter.YamlFrontMatterExtension}

5 | 6 | 7 | -------------------------------------------------------------------------------- /commonmark-ext-yaml-front-matter/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/main/java/org/commonmark/integration/IntegrationTests.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | // Prevent maven-gpg-plugin from failing with this error: 4 | // The project artifact has not been assembled yet. 5 | // Please do not invoke this goal before the lifecycle phase "package". 6 | // 7 | // Apparently it doesn't like a module that doesn't have any classes in main, 8 | // because that means no jar is generated. 9 | // And the javadoc plugin doesn't like if there's no classes with documentation, 10 | // 11 | 12 | /** 13 | * Module with integration tests. 14 | */ 15 | public class IntegrationTests { 16 | } 17 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.autolink.AutolinkExtension; 5 | import org.commonmark.ext.front.matter.YamlFrontMatterExtension; 6 | import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension; 7 | import org.commonmark.ext.gfm.tables.TablesExtension; 8 | import org.commonmark.ext.image.attributes.ImageAttributesExtension; 9 | import org.commonmark.ext.ins.InsExtension; 10 | import org.commonmark.ext.task.list.items.TaskListItemsExtension; 11 | 12 | import java.util.List; 13 | 14 | public class Extensions { 15 | 16 | static final List ALL_EXTENSIONS = List.of( 17 | AutolinkExtension.create(), 18 | ImageAttributesExtension.create(), 19 | InsExtension.create(), 20 | StrikethroughExtension.create(), 21 | TablesExtension.create(), 22 | TaskListItemsExtension.create(), 23 | YamlFrontMatterExtension.create()); 24 | } 25 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/test/java/org/commonmark/integration/ExtensionsIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | import org.commonmark.parser.Parser; 4 | import org.commonmark.renderer.html.HtmlRenderer; 5 | import org.commonmark.testutil.RenderingTestCase; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Tests to ensure all extensions work well together. 10 | */ 11 | public class ExtensionsIntegrationTest extends RenderingTestCase { 12 | 13 | protected static final Parser PARSER = Parser.builder() 14 | .extensions(Extensions.ALL_EXTENSIONS) 15 | .build(); 16 | protected static final HtmlRenderer RENDERER = HtmlRenderer.builder() 17 | .extensions(Extensions.ALL_EXTENSIONS) 18 | .percentEncodeUrls(true) 19 | .build(); 20 | 21 | @Test 22 | public void testImageAttributes() { 23 | assertRendering("![text](/url.png){height=5 width=6}", "

\"text\"

\n"); 24 | } 25 | 26 | @Test 27 | public void testTaskListItems() { 28 | assertRendering("- [ ] task to do\n- [x] task done\n", 29 | "
    \n
  • task to do
  • \n" + 30 | "
  • task done
  • \n
\n"); 31 | 32 | } 33 | 34 | @Override 35 | protected String render(String source) { 36 | return RENDERER.render(PARSER.parse(source)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.ext.autolink.AutolinkExtension; 5 | import org.commonmark.ext.front.matter.YamlFrontMatterExtension; 6 | import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension; 7 | import org.commonmark.ext.gfm.tables.TablesExtension; 8 | import org.commonmark.ext.image.attributes.ImageAttributesExtension; 9 | import org.commonmark.ext.ins.InsExtension; 10 | import org.commonmark.ext.task.list.items.TaskListItemsExtension; 11 | import org.commonmark.parser.Parser; 12 | import org.commonmark.renderer.markdown.MarkdownRenderer; 13 | import org.junit.Test; 14 | 15 | import java.util.List; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | 19 | public class MarkdownRendererIntegrationTest { 20 | 21 | private static final List EXTENSIONS = List.of( 22 | AutolinkExtension.create(), 23 | ImageAttributesExtension.create(), 24 | InsExtension.create(), 25 | StrikethroughExtension.create(), 26 | TablesExtension.create(), 27 | TaskListItemsExtension.create(), 28 | YamlFrontMatterExtension.create()); 29 | private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build(); 30 | private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build(); 31 | 32 | @Test 33 | public void testStrikethroughInTable() { 34 | assertRoundTrip("|Abc|\n|---|\n|~strikethrough~|\n|\\~escaped\\~|\n"); 35 | } 36 | 37 | private String render(String source) { 38 | return RENDERER.render(PARSER.parse(source)); 39 | } 40 | 41 | private void assertRoundTrip(String input) { 42 | String rendered = render(input); 43 | assertEquals(input, rendered); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/test/java/org/commonmark/integration/PegDownBenchmark.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | import org.commonmark.testutil.TestResources; 4 | import org.commonmark.testutil.example.ExampleReader; 5 | import org.openjdk.jmh.annotations.Benchmark; 6 | import org.openjdk.jmh.annotations.Scope; 7 | import org.openjdk.jmh.annotations.State; 8 | import org.openjdk.jmh.runner.Runner; 9 | import org.openjdk.jmh.runner.options.CommandLineOptions; 10 | import org.openjdk.jmh.runner.options.Options; 11 | import org.openjdk.jmh.runner.options.OptionsBuilder; 12 | import org.pegdown.Extensions; 13 | import org.pegdown.PegDownProcessor; 14 | 15 | import java.util.List; 16 | 17 | @State(Scope.Benchmark) 18 | public class PegDownBenchmark { 19 | 20 | private static final String SPEC = TestResources.readAsString(TestResources.getSpec()); 21 | private static final List SPEC_EXAMPLES = ExampleReader.readExampleSources(TestResources.getSpec()); 22 | private static final PegDownProcessor PROCESSOR = new PegDownProcessor(Extensions.FENCED_CODE_BLOCKS); 23 | 24 | public static void main(String[] args) throws Exception { 25 | Options options = new OptionsBuilder() 26 | .parent(new CommandLineOptions(args)) 27 | .include(PegDownBenchmark.class.getName() + ".*") 28 | .build(); 29 | new Runner(options).run(); 30 | } 31 | 32 | @Benchmark 33 | public long wholeSpec() { 34 | return parseAndRender(List.of(SPEC)); 35 | } 36 | 37 | @Benchmark 38 | public long examples() { 39 | return parseAndRender(SPEC_EXAMPLES); 40 | } 41 | 42 | private static long parseAndRender(List examples) { 43 | long length = 0; 44 | for (String example : examples) { 45 | String result = PROCESSOR.markdownToHtml(example); 46 | length += result.length(); 47 | } 48 | return length; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /commonmark-integration-test/src/test/java/org/commonmark/integration/SourceSpanIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.integration; 2 | 3 | import org.commonmark.parser.IncludeSourceSpans; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.testutil.example.Example; 6 | 7 | /** 8 | * Spec and all extensions, with source spans enabled. 9 | */ 10 | public class SourceSpanIntegrationTest extends SpecIntegrationTest { 11 | 12 | protected static final Parser PARSER = Parser.builder() 13 | .extensions(Extensions.ALL_EXTENSIONS) 14 | .includeSourceSpans(IncludeSourceSpans.BLOCKS) 15 | .build(); 16 | 17 | public SourceSpanIntegrationTest(Example example) { 18 | super(example); 19 | } 20 | 21 | @Override 22 | protected String render(String source) { 23 | return RENDERER.render(PARSER.parse(source)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /commonmark-test-util/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.commonmark 6 | commonmark-parent 7 | 0.24.1-SNAPSHOT 8 | 9 | 10 | commonmark-test-util 11 | commonmark-java test utilities 12 | commonmark-java classes for tests 13 | 14 | 15 | 16 | junit 17 | junit 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark.testutil { 2 | exports org.commonmark.testutil; 3 | exports org.commonmark.testutil.example; 4 | 5 | requires junit; 6 | } 7 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/org/commonmark/testutil/Asserts.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.testutil; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | public class Asserts { 6 | public static void assertRendering(String source, String expectedRendering, String actualRendering) { 7 | // include source for better assertion errors 8 | String expected = showTabs(expectedRendering + "\n\n" + source); 9 | String actual = showTabs(actualRendering + "\n\n" + source); 10 | assertEquals(expected, actual); 11 | } 12 | 13 | private static String showTabs(String s) { 14 | // Tabs are shown as "rightwards arrow" for easier comparison 15 | return s.replace("\t", "\u2192"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/org/commonmark/testutil/RenderingTestCase.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.testutil; 2 | 3 | public abstract class RenderingTestCase { 4 | 5 | protected abstract String render(String source); 6 | 7 | protected void assertRendering(String source, String expectedResult) { 8 | Asserts.assertRendering(source, expectedResult, render(source)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/org/commonmark/testutil/SpecTestCase.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.testutil; 2 | 3 | import org.commonmark.testutil.example.Example; 4 | import org.commonmark.testutil.example.ExampleReader; 5 | import org.junit.runner.RunWith; 6 | import org.junit.runners.Parameterized; 7 | import org.junit.runners.Parameterized.Parameters; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @RunWith(Parameterized.class) 13 | public abstract class SpecTestCase { 14 | 15 | protected final Example example; 16 | 17 | public SpecTestCase(Example example) { 18 | this.example = example; 19 | } 20 | 21 | @Parameters(name = "{0}") 22 | public static List data() { 23 | List examples = ExampleReader.readExamples(TestResources.getSpec()); 24 | List data = new ArrayList<>(); 25 | for (Example example : examples) { 26 | data.add(new Object[]{example}); 27 | } 28 | return data; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/org/commonmark/testutil/TestResources.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.testutil; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.net.URL; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.List; 9 | 10 | public class TestResources { 11 | 12 | public static URL getSpec() { 13 | return TestResources.class.getResource("/spec.txt"); 14 | } 15 | 16 | public static URL getGfmSpec() { 17 | return TestResources.class.getResource("/gfm-spec.txt"); 18 | } 19 | 20 | public static List getRegressions() { 21 | return List.of( 22 | TestResources.class.getResource("/cmark-regression.txt"), 23 | TestResources.class.getResource("/commonmark.js-regression.txt") 24 | ); 25 | } 26 | 27 | public static String readAsString(URL url) { 28 | StringBuilder sb = new StringBuilder(); 29 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { 30 | String line; 31 | while ((line = reader.readLine()) != null) { 32 | sb.append(line); 33 | sb.append("\n"); 34 | } 35 | return sb.toString(); 36 | } catch (IOException e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/java/org/commonmark/testutil/example/Example.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.testutil.example; 2 | 3 | public class Example { 4 | 5 | private final String filename; 6 | private final String section; 7 | private final String info; 8 | private final int exampleNumber; 9 | private final String source; 10 | private final String html; 11 | 12 | public Example(String filename, String section, String info, int exampleNumber, String source, String html) { 13 | this.filename = filename; 14 | this.section = section; 15 | this.info = info; 16 | this.exampleNumber = exampleNumber; 17 | this.source = source; 18 | this.html = html; 19 | } 20 | 21 | public String getInfo() { 22 | return info; 23 | } 24 | 25 | public String getSource() { 26 | return source; 27 | } 28 | 29 | public String getHtml() { 30 | return html; 31 | } 32 | 33 | public String getSection() { 34 | return section; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "File \"" + filename + "\" section \"" + section + "\" example " + exampleNumber; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark-test-util/src/main/resources/README.md: -------------------------------------------------------------------------------- 1 | These files are copied from the CommonMark repositories, namely: 2 | 3 | https://github.com/commonmark/commonmark-spec/blob/master/spec.txt 4 | https://github.com/commonmark/cmark/blob/master/test/regression.txt 5 | https://github.com/commonmark/commonmark.js/blob/master/test/regression.txt 6 | 7 | They are licensed as stated in those repositories. 8 | -------------------------------------------------------------------------------- /commonmark/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module org.commonmark { 2 | exports org.commonmark; 3 | exports org.commonmark.node; 4 | exports org.commonmark.parser; 5 | exports org.commonmark.parser.beta; 6 | exports org.commonmark.parser.block; 7 | exports org.commonmark.parser.delimiter; 8 | exports org.commonmark.renderer; 9 | exports org.commonmark.renderer.html; 10 | exports org.commonmark.renderer.markdown; 11 | exports org.commonmark.renderer.text; 12 | exports org.commonmark.text; 13 | } 14 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/Extension.java: -------------------------------------------------------------------------------- 1 | package org.commonmark; 2 | 3 | /** 4 | * Base interface for a parser/renderer extension. 5 | *

6 | * Doesn't have any methods itself, but has specific sub interfaces to 7 | * configure parser/renderer. This base interface is for convenience, so that a list of extensions can be built and then 8 | * used for configuring both the parser and renderer in the same way. 9 | */ 10 | public interface Extension { 11 | } 12 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/BlockContent.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal; 2 | 3 | class BlockContent { 4 | 5 | private final StringBuilder sb; 6 | 7 | private int lineCount = 0; 8 | 9 | public BlockContent() { 10 | sb = new StringBuilder(); 11 | } 12 | 13 | public BlockContent(String content) { 14 | sb = new StringBuilder(content); 15 | } 16 | 17 | public void add(CharSequence line) { 18 | if (lineCount != 0) { 19 | sb.append('\n'); 20 | } 21 | sb.append(line); 22 | lineCount++; 23 | } 24 | 25 | public String getString() { 26 | return sb.toString(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/BlockContinueImpl.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal; 2 | 3 | import org.commonmark.parser.block.BlockContinue; 4 | 5 | public class BlockContinueImpl extends BlockContinue { 6 | 7 | private final int newIndex; 8 | private final int newColumn; 9 | private final boolean finalize; 10 | 11 | public BlockContinueImpl(int newIndex, int newColumn, boolean finalize) { 12 | this.newIndex = newIndex; 13 | this.newColumn = newColumn; 14 | this.finalize = finalize; 15 | } 16 | 17 | public int getNewIndex() { 18 | return newIndex; 19 | } 20 | 21 | public int getNewColumn() { 22 | return newColumn; 23 | } 24 | 25 | public boolean isFinalize() { 26 | return finalize; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/BlockStartImpl.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal; 2 | 3 | import org.commonmark.parser.block.BlockParser; 4 | import org.commonmark.parser.block.BlockStart; 5 | 6 | public class BlockStartImpl extends BlockStart { 7 | 8 | private final BlockParser[] blockParsers; 9 | private int newIndex = -1; 10 | private int newColumn = -1; 11 | private boolean replaceActiveBlockParser = false; 12 | 13 | public BlockStartImpl(BlockParser... blockParsers) { 14 | this.blockParsers = blockParsers; 15 | } 16 | 17 | public BlockParser[] getBlockParsers() { 18 | return blockParsers; 19 | } 20 | 21 | public int getNewIndex() { 22 | return newIndex; 23 | } 24 | 25 | public int getNewColumn() { 26 | return newColumn; 27 | } 28 | 29 | public boolean isReplaceActiveBlockParser() { 30 | return replaceActiveBlockParser; 31 | } 32 | 33 | @Override 34 | public BlockStart atIndex(int newIndex) { 35 | this.newIndex = newIndex; 36 | return this; 37 | } 38 | 39 | @Override 40 | public BlockStart atColumn(int newColumn) { 41 | this.newColumn = newColumn; 42 | return this; 43 | } 44 | 45 | @Override 46 | public BlockStart replaceActiveBlockParser() { 47 | this.replaceActiveBlockParser = true; 48 | return this; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/Definitions.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal; 2 | 3 | import org.commonmark.node.DefinitionMap; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class Definitions { 9 | 10 | private final Map, DefinitionMap> definitionsByType = new HashMap<>(); 11 | 12 | public void addDefinitions(DefinitionMap definitionMap) { 13 | var existingMap = getMap(definitionMap.getType()); 14 | if (existingMap == null) { 15 | definitionsByType.put(definitionMap.getType(), definitionMap); 16 | } else { 17 | existingMap.addAll(definitionMap); 18 | } 19 | } 20 | 21 | public V getDefinition(Class type, String label) { 22 | var definitionMap = getMap(type); 23 | if (definitionMap == null) { 24 | return null; 25 | } 26 | return definitionMap.get(label); 27 | } 28 | 29 | private DefinitionMap getMap(Class type) { 30 | //noinspection unchecked 31 | return (DefinitionMap) definitionsByType.get(type); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/DocumentBlockParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal; 2 | 3 | import org.commonmark.node.Block; 4 | import org.commonmark.node.Document; 5 | import org.commonmark.parser.SourceLine; 6 | import org.commonmark.parser.block.AbstractBlockParser; 7 | import org.commonmark.parser.block.BlockContinue; 8 | import org.commonmark.parser.block.ParserState; 9 | 10 | public class DocumentBlockParser extends AbstractBlockParser { 11 | 12 | private final Document document = new Document(); 13 | 14 | @Override 15 | public boolean isContainer() { 16 | return true; 17 | } 18 | 19 | @Override 20 | public boolean canContain(Block block) { 21 | return true; 22 | } 23 | 24 | @Override 25 | public Document getBlock() { 26 | return document; 27 | } 28 | 29 | @Override 30 | public BlockContinue tryContinue(ParserState state) { 31 | return BlockContinue.atIndex(state.getIndex()); 32 | } 33 | 34 | @Override 35 | public void addLine(SourceLine line) { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/AsteriskDelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | public class AsteriskDelimiterProcessor extends EmphasisDelimiterProcessor { 4 | 5 | public AsteriskDelimiterProcessor() { 6 | super('*'); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/BackslashInlineParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | import org.commonmark.internal.util.Escaping; 4 | import org.commonmark.node.HardLineBreak; 5 | import org.commonmark.node.Text; 6 | import org.commonmark.parser.beta.*; 7 | 8 | import java.util.Set; 9 | import java.util.regex.Pattern; 10 | 11 | /** 12 | * Parse a backslash-escaped special character, adding either the escaped character, a hard line break 13 | * (if the backslash is followed by a newline), or a literal backslash to the block's children. 14 | */ 15 | public class BackslashInlineParser implements InlineContentParser { 16 | 17 | private static final Pattern ESCAPABLE = Pattern.compile('^' + Escaping.ESCAPABLE); 18 | 19 | @Override 20 | public ParsedInline tryParse(InlineParserState inlineParserState) { 21 | Scanner scanner = inlineParserState.scanner(); 22 | // Backslash 23 | scanner.next(); 24 | 25 | char next = scanner.peek(); 26 | if (next == '\n') { 27 | scanner.next(); 28 | return ParsedInline.of(new HardLineBreak(), scanner.position()); 29 | } else if (ESCAPABLE.matcher(String.valueOf(next)).matches()) { 30 | scanner.next(); 31 | return ParsedInline.of(new Text(String.valueOf(next)), scanner.position()); 32 | } else { 33 | return ParsedInline.of(new Text("\\"), scanner.position()); 34 | } 35 | } 36 | 37 | public static class Factory implements InlineContentParserFactory { 38 | @Override 39 | public Set getTriggerCharacters() { 40 | return Set.of('\\'); 41 | } 42 | 43 | @Override 44 | public InlineContentParser create() { 45 | return new BackslashInlineParser(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/CoreLinkProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | import org.commonmark.node.Image; 4 | import org.commonmark.node.Link; 5 | import org.commonmark.node.LinkReferenceDefinition; 6 | import org.commonmark.parser.InlineParserContext; 7 | import org.commonmark.parser.beta.LinkInfo; 8 | import org.commonmark.parser.beta.LinkProcessor; 9 | import org.commonmark.parser.beta.LinkResult; 10 | import org.commonmark.parser.beta.Scanner; 11 | 12 | public class CoreLinkProcessor implements LinkProcessor { 13 | 14 | @Override 15 | public LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContext context) { 16 | if (linkInfo.destination() != null) { 17 | // Inline link 18 | return process(linkInfo, scanner, linkInfo.destination(), linkInfo.title()); 19 | } 20 | 21 | var label = linkInfo.label(); 22 | var ref = label != null && !label.isEmpty() ? label : linkInfo.text(); 23 | var def = context.getDefinition(LinkReferenceDefinition.class, ref); 24 | if (def != null) { 25 | // Reference link 26 | return process(linkInfo, scanner, def.getDestination(), def.getTitle()); 27 | } 28 | return LinkResult.none(); 29 | } 30 | 31 | private static LinkResult process(LinkInfo linkInfo, Scanner scanner, String destination, String title) { 32 | if (linkInfo.marker() != null && linkInfo.marker().getLiteral().equals("!")) { 33 | return LinkResult.wrapTextIn(new Image(destination, title), scanner.position()).includeMarker(); 34 | } 35 | return LinkResult.wrapTextIn(new Link(destination, title), scanner.position()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/LinkResultImpl.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.parser.beta.LinkResult; 5 | import org.commonmark.parser.beta.Position; 6 | 7 | public class LinkResultImpl implements LinkResult { 8 | @Override 9 | public LinkResult includeMarker() { 10 | includeMarker = true; 11 | return this; 12 | } 13 | 14 | public enum Type { 15 | WRAP, 16 | REPLACE 17 | } 18 | 19 | private final Type type; 20 | private final Node node; 21 | private final Position position; 22 | 23 | private boolean includeMarker = false; 24 | 25 | public LinkResultImpl(Type type, Node node, Position position) { 26 | this.type = type; 27 | this.node = node; 28 | this.position = position; 29 | } 30 | 31 | public Type getType() { 32 | return type; 33 | } 34 | 35 | public Node getNode() { 36 | return node; 37 | } 38 | 39 | public Position getPosition() { 40 | return position; 41 | } 42 | 43 | public boolean isIncludeMarker() { 44 | return includeMarker; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/ParsedInlineImpl.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.parser.beta.ParsedInline; 5 | import org.commonmark.parser.beta.Position; 6 | 7 | public class ParsedInlineImpl implements ParsedInline { 8 | private final Node node; 9 | private final Position position; 10 | 11 | public ParsedInlineImpl(Node node, Position position) { 12 | this.node = node; 13 | this.position = position; 14 | } 15 | 16 | public Node getNode() { 17 | return node; 18 | } 19 | 20 | public Position getPosition() { 21 | return position; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/inline/UnderscoreDelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.inline; 2 | 3 | public class UnderscoreDelimiterProcessor extends EmphasisDelimiterProcessor { 4 | 5 | public UnderscoreDelimiterProcessor() { 6 | super('_'); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/renderer/NodeRendererMap.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.renderer; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.NodeRenderer; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class NodeRendererMap { 12 | 13 | private final List nodeRenderers = new ArrayList<>(); 14 | private final Map, NodeRenderer> renderers = new HashMap<>(32); 15 | 16 | /** 17 | * Set the renderer for each {@link NodeRenderer#getNodeTypes()}, unless there was already a renderer set (first wins). 18 | */ 19 | public void add(NodeRenderer nodeRenderer) { 20 | nodeRenderers.add(nodeRenderer); 21 | for (var nodeType : nodeRenderer.getNodeTypes()) { 22 | // The first node renderer for a node type "wins". 23 | renderers.putIfAbsent(nodeType, nodeRenderer); 24 | } 25 | } 26 | 27 | public void render(Node node) { 28 | var nodeRenderer = renderers.get(node.getClass()); 29 | if (nodeRenderer != null) { 30 | nodeRenderer.render(node); 31 | } 32 | } 33 | 34 | public void beforeRoot(Node node) { 35 | nodeRenderers.forEach(r -> r.beforeRoot(node)); 36 | } 37 | 38 | public void afterRoot(Node node) { 39 | nodeRenderers.forEach(r -> r.afterRoot(node)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/renderer/text/BulletListHolder.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.renderer.text; 2 | 3 | import org.commonmark.node.BulletList; 4 | 5 | public class BulletListHolder extends ListHolder { 6 | private final String marker; 7 | 8 | public BulletListHolder(ListHolder parent, BulletList list) { 9 | super(parent); 10 | marker = list.getMarker(); 11 | } 12 | 13 | public String getMarker() { 14 | return marker; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/renderer/text/ListHolder.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.renderer.text; 2 | 3 | public abstract class ListHolder { 4 | private static final String INDENT_DEFAULT = " "; 5 | private static final String INDENT_EMPTY = ""; 6 | 7 | private final ListHolder parent; 8 | private final String indent; 9 | 10 | ListHolder(ListHolder parent) { 11 | this.parent = parent; 12 | 13 | if (parent != null) { 14 | indent = parent.indent + INDENT_DEFAULT; 15 | } else { 16 | indent = INDENT_EMPTY; 17 | } 18 | } 19 | 20 | public ListHolder getParent() { 21 | return parent; 22 | } 23 | 24 | public String getIndent() { 25 | return indent; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/renderer/text/OrderedListHolder.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.renderer.text; 2 | 3 | import org.commonmark.node.OrderedList; 4 | 5 | public class OrderedListHolder extends ListHolder { 6 | private final String delimiter; 7 | private int counter; 8 | 9 | public OrderedListHolder(ListHolder parent, OrderedList list) { 10 | super(parent); 11 | delimiter = list.getMarkerDelimiter() != null ? list.getMarkerDelimiter() : "."; 12 | counter = list.getMarkerStartNumber() != null ? list.getMarkerStartNumber() : 1; 13 | } 14 | 15 | public String getDelimiter() { 16 | return delimiter; 17 | } 18 | 19 | public int getCounter() { 20 | return counter; 21 | } 22 | 23 | public void increaseCounter() { 24 | counter++; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/internal/util/Parsing.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.util; 2 | 3 | public class Parsing { 4 | public static int CODE_BLOCK_INDENT = 4; 5 | 6 | public static int columnsToNextTabStop(int column) { 7 | // Tab stop is 4 8 | return 4 - (column % 4); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Block.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Block nodes such as paragraphs, list blocks, code blocks etc. 5 | */ 6 | public abstract class Block extends Node { 7 | 8 | @Override 9 | public Block getParent() { 10 | return (Block) super.getParent(); 11 | } 12 | 13 | @Override 14 | protected void setParent(Node parent) { 15 | if (!(parent instanceof Block)) { 16 | throw new IllegalArgumentException("Parent of block must also be block (can not be inline)"); 17 | } 18 | super.setParent(parent); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/BlockQuote.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A block quote, e.g.: 5 | *

 6 |  * > Some quoted text
 7 |  * 
8 | *

9 | * Note that child nodes are themselves blocks, e.g. {@link Paragraph}, {@link ListBlock} etc. 10 | * 11 | * @see CommonMark Spec 12 | */ 13 | public class BlockQuote extends Block { 14 | 15 | @Override 16 | public void accept(Visitor visitor) { 17 | visitor.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/BulletList.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A bullet list, e.g.: 5 | *

 6 |  * - One
 7 |  * - Two
 8 |  * - Three
 9 |  * 
10 | *

11 | * The children are {@link ListItem} blocks, which contain other blocks (or nested lists). 12 | * 13 | * @see CommonMark Spec: List items 14 | */ 15 | public class BulletList extends ListBlock { 16 | 17 | private String marker; 18 | 19 | @Override 20 | public void accept(Visitor visitor) { 21 | visitor.visit(this); 22 | } 23 | 24 | /** 25 | * @return the bullet list marker that was used, e.g. {@code -}, {@code *} or {@code +}, if available, or null otherwise 26 | */ 27 | public String getMarker() { 28 | return marker; 29 | } 30 | 31 | public void setMarker(String marker) { 32 | this.marker = marker; 33 | } 34 | 35 | /** 36 | * @deprecated use {@link #getMarker()} instead 37 | */ 38 | @Deprecated 39 | public char getBulletMarker() { 40 | return marker != null && !marker.isEmpty() ? marker.charAt(0) : '\0'; 41 | } 42 | 43 | /** 44 | * @deprecated use {@link #getMarker()} instead 45 | */ 46 | @Deprecated 47 | public void setBulletMarker(char bulletMarker) { 48 | this.marker = bulletMarker != '\0' ? String.valueOf(bulletMarker) : null; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Code.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Inline code span, e.g.: 5 | *

 6 |  * Some `inline code`
 7 |  * 
8 | * 9 | * @see CommonMark Spec 10 | */ 11 | public class Code extends Node { 12 | 13 | private String literal; 14 | 15 | public Code() { 16 | } 17 | 18 | public Code(String literal) { 19 | this.literal = literal; 20 | } 21 | 22 | @Override 23 | public void accept(Visitor visitor) { 24 | visitor.visit(this); 25 | } 26 | 27 | /** 28 | * @return the literal text in the code span (note that it's not necessarily the raw text between tildes, 29 | * e.g. when spaces are stripped) 30 | */ 31 | public String getLiteral() { 32 | return literal; 33 | } 34 | 35 | public void setLiteral(String literal) { 36 | this.literal = literal; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/CustomBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A block that extensions can subclass to define custom blocks (not part of the core specification). 5 | */ 6 | public abstract class CustomBlock extends Block { 7 | 8 | @Override 9 | public void accept(Visitor visitor) { 10 | visitor.visit(this); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/CustomNode.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A node that extensions can subclass to define custom nodes (not part of the core specification). 5 | */ 6 | public abstract class CustomNode extends Node { 7 | @Override 8 | public void accept(Visitor visitor) { 9 | visitor.visit(this); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Delimited.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A node that uses delimiters in the source form (e.g. *bold*). 5 | */ 6 | public interface Delimited { 7 | 8 | /** 9 | * @return the opening (beginning) delimiter, e.g. * 10 | */ 11 | String getOpeningDelimiter(); 12 | 13 | /** 14 | * @return the closing (ending) delimiter, e.g. * 15 | */ 16 | String getClosingDelimiter(); 17 | } 18 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Document.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * The root block of a document, containing the top-level blocks. 5 | */ 6 | public class Document extends Block { 7 | 8 | @Override 9 | public void accept(Visitor visitor) { 10 | visitor.visit(this); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Emphasis.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Emphasis, e.g.: 5 | *
 6 |  * Some *emphasis* or _emphasis_
 7 |  * 
8 | * 9 | * @see CommonMark Spec: Emphasis and strong emphasis 10 | */ 11 | public class Emphasis extends Node implements Delimited { 12 | 13 | private String delimiter; 14 | 15 | public Emphasis() { 16 | } 17 | 18 | public Emphasis(String delimiter) { 19 | this.delimiter = delimiter; 20 | } 21 | 22 | public void setDelimiter(String delimiter) { 23 | this.delimiter = delimiter; 24 | } 25 | 26 | @Override 27 | public String getOpeningDelimiter() { 28 | return delimiter; 29 | } 30 | 31 | @Override 32 | public String getClosingDelimiter() { 33 | return delimiter; 34 | } 35 | 36 | @Override 37 | public void accept(Visitor visitor) { 38 | visitor.visit(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/HardLineBreak.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A hard line break, e.g.: 5 | *
 6 |  * line\
 7 |  * break
 8 |  * 
9 | *

10 | * 11 | * @see CommonMark Spec 12 | */ 13 | public class HardLineBreak extends Node { 14 | 15 | @Override 16 | public void accept(Visitor visitor) { 17 | visitor.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Heading.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A heading, e.g.: 5 | *

 6 |  * First heading
 7 |  * =============
 8 |  *
 9 |  * ## Another heading
10 |  * 
11 | * 12 | * @see CommonMark Spec: ATX headings 13 | * @see CommonMark Spec: Setext headings 14 | */ 15 | public class Heading extends Block { 16 | 17 | private int level; 18 | 19 | @Override 20 | public void accept(Visitor visitor) { 21 | visitor.visit(this); 22 | } 23 | 24 | public int getLevel() { 25 | return level; 26 | } 27 | 28 | public void setLevel(int level) { 29 | this.level = level; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/HtmlBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * HTML block 5 | * 6 | * @see CommonMark Spec 7 | */ 8 | public class HtmlBlock extends Block { 9 | 10 | private String literal; 11 | 12 | @Override 13 | public void accept(Visitor visitor) { 14 | visitor.visit(this); 15 | } 16 | 17 | public String getLiteral() { 18 | return literal; 19 | } 20 | 21 | public void setLiteral(String literal) { 22 | this.literal = literal; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/HtmlInline.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Inline HTML element. 5 | * 6 | * @see CommonMark Spec 7 | */ 8 | public class HtmlInline extends Node { 9 | 10 | private String literal; 11 | 12 | @Override 13 | public void accept(Visitor visitor) { 14 | visitor.visit(this); 15 | } 16 | 17 | public String getLiteral() { 18 | return literal; 19 | } 20 | 21 | public void setLiteral(String literal) { 22 | this.literal = literal; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Image.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * An image, e.g.: 5 | *
 6 |  * ![foo](/url "title")
 7 |  * 
8 | * 9 | * @see CommonMark Spec 10 | */ 11 | public class Image extends Node { 12 | 13 | private String destination; 14 | private String title; 15 | 16 | public Image() { 17 | } 18 | 19 | public Image(String destination, String title) { 20 | this.destination = destination; 21 | this.title = title; 22 | } 23 | 24 | @Override 25 | public void accept(Visitor visitor) { 26 | visitor.visit(this); 27 | } 28 | 29 | public String getDestination() { 30 | return destination; 31 | } 32 | 33 | public void setDestination(String destination) { 34 | this.destination = destination; 35 | } 36 | 37 | public String getTitle() { 38 | return title; 39 | } 40 | 41 | public void setTitle(String title) { 42 | this.title = title; 43 | } 44 | 45 | @Override 46 | protected String toStringAttributes() { 47 | return "destination=" + destination + ", title=" + title; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/IndentedCodeBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * An indented code block, e.g.: 5 | *

 6 |  * Code follows:
 7 |  *
 8 |  *     foo
 9 |  *     bar
10 |  * 
11 | *

12 | * 13 | * @see CommonMark Spec 14 | */ 15 | public class IndentedCodeBlock extends Block { 16 | 17 | private String literal; 18 | 19 | @Override 20 | public void accept(Visitor visitor) { 21 | visitor.visit(this); 22 | } 23 | 24 | public String getLiteral() { 25 | return literal; 26 | } 27 | 28 | public void setLiteral(String literal) { 29 | this.literal = literal; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Link.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A link with a destination and an optional title; the link text is in child nodes. 5 | *

6 | * Example for an inline link in a CommonMark document: 7 | *


 8 |  * [link](/uri "title")
 9 |  * 
10 | *

11 | * The corresponding Link node would look like this: 12 | *

    13 | *
  • {@link #getDestination()} returns {@code "/uri"} 14 | *
  • {@link #getTitle()} returns {@code "title"} 15 | *
  • A {@link Text} child node with {@link Text#getLiteral() getLiteral} that returns {@code "link"}
  • 16 | *
17 | *

18 | * Note that the text in the link can contain inline formatting, so it could also contain an {@link Image} or 19 | * {@link Emphasis}, etc. 20 | * 21 | * @see CommonMark Spec 22 | */ 23 | public class Link extends Node { 24 | 25 | private String destination; 26 | private String title; 27 | 28 | public Link() { 29 | } 30 | 31 | public Link(String destination, String title) { 32 | this.destination = destination; 33 | this.title = title; 34 | } 35 | 36 | @Override 37 | public void accept(Visitor visitor) { 38 | visitor.visit(this); 39 | } 40 | 41 | public String getDestination() { 42 | return destination; 43 | } 44 | 45 | public void setDestination(String destination) { 46 | this.destination = destination; 47 | } 48 | 49 | /** 50 | * @return the title or null 51 | */ 52 | public String getTitle() { 53 | return title; 54 | } 55 | 56 | public void setTitle(String title) { 57 | this.title = title; 58 | } 59 | 60 | @Override 61 | protected String toStringAttributes() { 62 | return "destination=" + destination + ", title=" + title; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/LinkReferenceDefinition.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A link reference definition, e.g.: 5 | *


 6 |  * [foo]: /url "title"
 7 |  * 
8 | *

9 | * They can be referenced anywhere else in the document to produce a link using [foo]. The definitions 10 | * themselves are usually not rendered in the final output. 11 | * 12 | * @see CommonMark Spec 13 | */ 14 | public class LinkReferenceDefinition extends Block { 15 | 16 | private String label; 17 | private String destination; 18 | private String title; 19 | 20 | public LinkReferenceDefinition() { 21 | } 22 | 23 | public LinkReferenceDefinition(String label, String destination, String title) { 24 | this.label = label; 25 | this.destination = destination; 26 | this.title = title; 27 | } 28 | 29 | public String getLabel() { 30 | return label; 31 | } 32 | 33 | public void setLabel(String label) { 34 | this.label = label; 35 | } 36 | 37 | public String getDestination() { 38 | return destination; 39 | } 40 | 41 | public void setDestination(String destination) { 42 | this.destination = destination; 43 | } 44 | 45 | public String getTitle() { 46 | return title; 47 | } 48 | 49 | public void setTitle(String title) { 50 | this.title = title; 51 | } 52 | 53 | @Override 54 | public void accept(Visitor visitor) { 55 | visitor.visit(this); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/ListBlock.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A list block like {@link BulletList} or {@link OrderedList}. 5 | */ 6 | public abstract class ListBlock extends Block { 7 | 8 | private boolean tight; 9 | 10 | /** 11 | * @return whether this list is tight or loose 12 | * @see CommonMark Spec for tight lists 13 | */ 14 | public boolean isTight() { 15 | return tight; 16 | } 17 | 18 | public void setTight(boolean tight) { 19 | this.tight = tight; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/ListItem.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A child of a {@link ListBlock}, containing other blocks (e.g. {@link Paragraph}, other lists, etc). 5 | * 6 | * @see CommonMark Spec: List items 7 | */ 8 | public class ListItem extends Block { 9 | 10 | private Integer markerIndent; 11 | private Integer contentIndent; 12 | 13 | @Override 14 | public void accept(Visitor visitor) { 15 | visitor.visit(this); 16 | } 17 | 18 | /** 19 | * Returns the indent of the marker such as "-" or "1." in columns (spaces or tab stop of 4) if available, or null 20 | * otherwise. 21 | *

22 | * Some examples and their marker indent: 23 | *

- Foo
24 | * Marker indent: 0 25 | *
 - Foo
26 | * Marker indent: 1 27 | *
  1. Foo
28 | * Marker indent: 2 29 | */ 30 | public Integer getMarkerIndent() { 31 | return markerIndent; 32 | } 33 | 34 | public void setMarkerIndent(Integer markerIndent) { 35 | this.markerIndent = markerIndent; 36 | } 37 | 38 | /** 39 | * Returns the indent of the content in columns (spaces or tab stop of 4) if available, or null otherwise. 40 | * The content indent is counted from the beginning of the line and includes the marker on the first line. 41 | *

42 | * Some examples and their content indent: 43 | *

- Foo
44 | * Content indent: 2 45 | *
 - Foo
46 | * Content indent: 3 47 | *
  1. Foo
48 | * Content indent: 5 49 | *

50 | * Note that subsequent lines in the same list item need to be indented by at least the content indent to be counted 51 | * as part of the list item. 52 | */ 53 | public Integer getContentIndent() { 54 | return contentIndent; 55 | } 56 | 57 | public void setContentIndent(Integer contentIndent) { 58 | this.contentIndent = contentIndent; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Nodes.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | import java.util.Iterator; 4 | 5 | /** 6 | * Utility class for working with multiple {@link Node}s. 7 | * 8 | * @since 0.16.0 9 | */ 10 | public class Nodes { 11 | 12 | private Nodes() { 13 | } 14 | 15 | /** 16 | * The nodes between (not including) start and end. 17 | */ 18 | public static Iterable between(Node start, Node end) { 19 | return new NodeIterable(start.getNext(), end); 20 | } 21 | 22 | private static class NodeIterable implements Iterable { 23 | 24 | private final Node first; 25 | private final Node end; 26 | 27 | private NodeIterable(Node first, Node end) { 28 | this.first = first; 29 | this.end = end; 30 | } 31 | 32 | @Override 33 | public Iterator iterator() { 34 | return new NodeIterator(first, end); 35 | } 36 | } 37 | 38 | private static class NodeIterator implements Iterator { 39 | 40 | private Node node; 41 | private final Node end; 42 | 43 | private NodeIterator(Node first, Node end) { 44 | node = first; 45 | this.end = end; 46 | } 47 | 48 | @Override 49 | public boolean hasNext() { 50 | return node != null && node != end; 51 | } 52 | 53 | @Override 54 | public Node next() { 55 | Node result = node; 56 | node = node.getNext(); 57 | return result; 58 | } 59 | 60 | @Override 61 | public void remove() { 62 | throw new UnsupportedOperationException("remove"); 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Paragraph.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A paragraph block, contains inline nodes such as {@link Text} 5 | * 6 | * @see CommonMark Spec 7 | */ 8 | public class Paragraph extends Block { 9 | 10 | @Override 11 | public void accept(Visitor visitor) { 12 | visitor.visit(this); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/SoftLineBreak.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A soft line break (as opposed to a {@link HardLineBreak}), e.g. between: 5 | *

 6 |  * foo
 7 |  * bar
 8 |  * 
9 | * 10 | * @see CommonMark Spec 11 | */ 12 | public class SoftLineBreak extends Node { 13 | 14 | @Override 15 | public void accept(Visitor visitor) { 16 | visitor.visit(this); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/SourceSpans.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * A list of source spans that can be added to. Takes care of merging adjacent source spans. 8 | * 9 | * @since 0.16.0 10 | */ 11 | public class SourceSpans { 12 | 13 | private List sourceSpans; 14 | 15 | public static SourceSpans empty() { 16 | return new SourceSpans(); 17 | } 18 | 19 | public List getSourceSpans() { 20 | return sourceSpans != null ? sourceSpans : List.of(); 21 | } 22 | 23 | public void addAllFrom(Iterable nodes) { 24 | for (Node node : nodes) { 25 | addAll(node.getSourceSpans()); 26 | } 27 | } 28 | 29 | public void addAll(List other) { 30 | if (other.isEmpty()) { 31 | return; 32 | } 33 | 34 | if (sourceSpans == null) { 35 | sourceSpans = new ArrayList<>(); 36 | } 37 | 38 | if (sourceSpans.isEmpty()) { 39 | sourceSpans.addAll(other); 40 | } else { 41 | int lastIndex = sourceSpans.size() - 1; 42 | SourceSpan a = sourceSpans.get(lastIndex); 43 | SourceSpan b = other.get(0); 44 | if (a.getInputIndex() + a.getLength() == b.getInputIndex()) { 45 | sourceSpans.set(lastIndex, SourceSpan.of(a.getLineIndex(), a.getColumnIndex(), a.getInputIndex(), a.getLength() + b.getLength())); 46 | sourceSpans.addAll(other.subList(1, other.size())); 47 | } else { 48 | sourceSpans.addAll(other); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/StrongEmphasis.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Strong emphasis, e.g.: 5 | *

 6 |  * Some **strong emphasis** or __strong emphasis__
 7 |  * 
8 | * 9 | * @see CommonMark Spec: Emphasis and strong emphasis 10 | */ 11 | public class StrongEmphasis extends Node implements Delimited { 12 | 13 | private String delimiter; 14 | 15 | public StrongEmphasis() { 16 | } 17 | 18 | public StrongEmphasis(String delimiter) { 19 | this.delimiter = delimiter; 20 | } 21 | 22 | public void setDelimiter(String delimiter) { 23 | this.delimiter = delimiter; 24 | } 25 | 26 | @Override 27 | public String getOpeningDelimiter() { 28 | return delimiter; 29 | } 30 | 31 | @Override 32 | public String getClosingDelimiter() { 33 | return delimiter; 34 | } 35 | 36 | @Override 37 | public void accept(Visitor visitor) { 38 | visitor.visit(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Text.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A text node, e.g. in: 5 | *
 6 |  * foo *bar*
 7 |  * 
8 | *

9 | * The foo is a text node, and the bar inside the emphasis is also a text node. 10 | * 11 | * @see CommonMark Spec 12 | */ 13 | public class Text extends Node { 14 | 15 | private String literal; 16 | 17 | public Text() { 18 | } 19 | 20 | public Text(String literal) { 21 | this.literal = literal; 22 | } 23 | 24 | @Override 25 | public void accept(Visitor visitor) { 26 | visitor.visit(this); 27 | } 28 | 29 | public String getLiteral() { 30 | return literal; 31 | } 32 | 33 | public void setLiteral(String literal) { 34 | this.literal = literal; 35 | } 36 | 37 | @Override 38 | protected String toStringAttributes() { 39 | return "literal=" + literal; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/ThematicBreak.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * A thematic break, e.g. between text: 5 | *

 6 |  * Some text
 7 |  *
 8 |  * ___
 9 |  *
10 |  * Some other text.
11 |  * 
12 | * 13 | * @see CommonMark Spec 14 | */ 15 | public class ThematicBreak extends Block { 16 | 17 | private String literal; 18 | 19 | @Override 20 | public void accept(Visitor visitor) { 21 | visitor.visit(this); 22 | } 23 | 24 | /** 25 | * @return the source literal that represents this node, if available 26 | */ 27 | public String getLiteral() { 28 | return literal; 29 | } 30 | 31 | public void setLiteral(String literal) { 32 | this.literal = literal; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/Visitor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.node; 2 | 3 | /** 4 | * Node visitor. 5 | *

6 | * Implementations should subclass {@link AbstractVisitor} instead of implementing this directly. 7 | */ 8 | public interface Visitor { 9 | 10 | void visit(BlockQuote blockQuote); 11 | 12 | void visit(BulletList bulletList); 13 | 14 | void visit(Code code); 15 | 16 | void visit(Document document); 17 | 18 | void visit(Emphasis emphasis); 19 | 20 | void visit(FencedCodeBlock fencedCodeBlock); 21 | 22 | void visit(HardLineBreak hardLineBreak); 23 | 24 | void visit(Heading heading); 25 | 26 | void visit(ThematicBreak thematicBreak); 27 | 28 | void visit(HtmlInline htmlInline); 29 | 30 | void visit(HtmlBlock htmlBlock); 31 | 32 | void visit(Image image); 33 | 34 | void visit(IndentedCodeBlock indentedCodeBlock); 35 | 36 | void visit(Link link); 37 | 38 | void visit(ListItem listItem); 39 | 40 | void visit(OrderedList orderedList); 41 | 42 | void visit(Paragraph paragraph); 43 | 44 | void visit(SoftLineBreak softLineBreak); 45 | 46 | void visit(StrongEmphasis strongEmphasis); 47 | 48 | void visit(Text text); 49 | 50 | void visit(LinkReferenceDefinition linkReferenceDefinition); 51 | 52 | void visit(CustomBlock customBlock); 53 | 54 | void visit(CustomNode customNode); 55 | } 56 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/node/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * AST node types (see {@link org.commonmark.node.Node}) and visitors (see {@link org.commonmark.node.AbstractVisitor}) 3 | */ 4 | package org.commonmark.node; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Root package of commonmark-java 3 | *

    4 | *
  • {@link org.commonmark.parser} for parsing input text to AST nodes
  • 5 | *
  • {@link org.commonmark.node} for AST node types and visitors
  • 6 | *
  • {@link org.commonmark.renderer.html} for HTML rendering
  • 7 | *
  • {@link org.commonmark.renderer.markdown} for Markdown rendering
  • 8 | *
9 | */ 10 | package org.commonmark; 11 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/IncludeSourceSpans.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | /** 4 | * Whether to include {@link org.commonmark.node.SourceSpan} or not while parsing, 5 | * see {@link Parser.Builder#includeSourceSpans(IncludeSourceSpans)}. 6 | * 7 | * @since 0.16.0 8 | */ 9 | public enum IncludeSourceSpans { 10 | /** 11 | * Do not include source spans. 12 | */ 13 | NONE, 14 | /** 15 | * Include source spans on {@link org.commonmark.node.Block} nodes. 16 | */ 17 | BLOCKS, 18 | /** 19 | * Include source spans on block nodes and inline nodes. 20 | */ 21 | BLOCKS_AND_INLINES, 22 | } 23 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/InlineParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | /** 6 | * Parser for inline content (text, links, emphasized text, etc). 7 | */ 8 | public interface InlineParser { 9 | 10 | /** 11 | * @param lines the source content to parse as inline 12 | * @param node the node to append resulting nodes to (as children) 13 | */ 14 | void parse(SourceLines lines, Node node); 15 | } 16 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/InlineParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | /** 4 | * Factory for custom inline parser. 5 | */ 6 | public interface InlineParserFactory { 7 | 8 | /** 9 | * Create an {@link InlineParser} to use for parsing inlines. This is called once per parsed document. 10 | */ 11 | InlineParser create(InlineParserContext inlineParserContext); 12 | } 13 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/PostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | public interface PostProcessor { 6 | 7 | /** 8 | * @param node the node to post-process 9 | * @return the result of post-processing, may be a modified {@code node} argument 10 | */ 11 | Node process(Node node); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/SourceLine.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | import org.commonmark.node.SourceSpan; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * A line or part of a line from the input source. 9 | * 10 | * @since 0.16.0 11 | */ 12 | public class SourceLine { 13 | 14 | private final CharSequence content; 15 | private final SourceSpan sourceSpan; 16 | 17 | public static SourceLine of(CharSequence content, SourceSpan sourceSpan) { 18 | return new SourceLine(content, sourceSpan); 19 | } 20 | 21 | private SourceLine(CharSequence content, SourceSpan sourceSpan) { 22 | this.content = Objects.requireNonNull(content, "content must not be null"); 23 | this.sourceSpan = sourceSpan; 24 | } 25 | 26 | public CharSequence getContent() { 27 | return content; 28 | } 29 | 30 | public SourceSpan getSourceSpan() { 31 | return sourceSpan; 32 | } 33 | 34 | public SourceLine substring(int beginIndex, int endIndex) { 35 | CharSequence newContent = content.subSequence(beginIndex, endIndex); 36 | SourceSpan newSourceSpan = null; 37 | if (sourceSpan != null) { 38 | int length = endIndex - beginIndex; 39 | if (length != 0) { 40 | int columnIndex = sourceSpan.getColumnIndex() + beginIndex; 41 | int inputIndex = sourceSpan.getInputIndex() + beginIndex; 42 | newSourceSpan = SourceSpan.of(sourceSpan.getLineIndex(), columnIndex, inputIndex, length); 43 | } 44 | } 45 | return SourceLine.of(newContent, newSourceSpan); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/SourceLines.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser; 2 | 3 | import org.commonmark.node.SourceSpan; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * A set of lines ({@link SourceLine}) from the input source. 10 | * 11 | * @since 0.16.0 12 | */ 13 | public class SourceLines { 14 | 15 | private final List lines = new ArrayList<>(); 16 | 17 | public static SourceLines empty() { 18 | return new SourceLines(); 19 | } 20 | 21 | public static SourceLines of(SourceLine sourceLine) { 22 | SourceLines sourceLines = new SourceLines(); 23 | sourceLines.addLine(sourceLine); 24 | return sourceLines; 25 | } 26 | 27 | public static SourceLines of(List sourceLines) { 28 | SourceLines result = new SourceLines(); 29 | result.lines.addAll(sourceLines); 30 | return result; 31 | } 32 | 33 | public void addLine(SourceLine sourceLine) { 34 | lines.add(sourceLine); 35 | } 36 | 37 | public List getLines() { 38 | return lines; 39 | } 40 | 41 | public boolean isEmpty() { 42 | return lines.isEmpty(); 43 | } 44 | 45 | public String getContent() { 46 | StringBuilder sb = new StringBuilder(); 47 | for (int i = 0; i < lines.size(); i++) { 48 | if (i != 0) { 49 | sb.append('\n'); 50 | } 51 | sb.append(lines.get(i).getContent()); 52 | } 53 | return sb.toString(); 54 | } 55 | 56 | public List getSourceSpans() { 57 | List sourceSpans = new ArrayList<>(); 58 | for (SourceLine line : lines) { 59 | SourceSpan sourceSpan = line.getSourceSpan(); 60 | if (sourceSpan != null) { 61 | sourceSpans.add(sourceSpan); 62 | } 63 | } 64 | return sourceSpans; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | /** 4 | * Parser for a type of inline content. Registered via a {@link InlineContentParserFactory} and created by its 5 | * {@link InlineContentParserFactory#create() create} method. The lifetime of this is tied to each inline content 6 | * snippet that is parsed, as a new instance is created for each. 7 | */ 8 | public interface InlineContentParser { 9 | 10 | /** 11 | * Try to parse inline content starting from the current position. Note that the character at the current position 12 | * is one of {@link InlineContentParserFactory#getTriggerCharacters()} of the factory that created this parser. 13 | *

14 | * For a given inline content snippet that is being parsed, this method can be called multiple times: each time a 15 | * trigger character is encountered. 16 | * 17 | * @param inlineParserState the current state of the inline parser 18 | * @return the result of parsing; can indicate that this parser is not interested, or that parsing was successful 19 | */ 20 | ParsedInline tryParse(InlineParserState inlineParserState); 21 | } 22 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/InlineContentParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * A factory for extending inline content parsing. 7 | *

8 | * See {@link org.commonmark.parser.Parser.Builder#customInlineContentParserFactory} for how to register it. 9 | */ 10 | public interface InlineContentParserFactory { 11 | 12 | /** 13 | * An inline content parser needs to have a special "trigger" character which activates it. When this character is 14 | * encountered during inline parsing, {@link InlineContentParser#tryParse} is called with the current parser state. 15 | * It can also register for more than one trigger character. 16 | */ 17 | Set getTriggerCharacters(); 18 | 19 | /** 20 | * Create an {@link InlineContentParser} that will do the parsing. Create is called once per text snippet of inline 21 | * content inside block structures, and then called each time a trigger character is encountered. 22 | */ 23 | InlineContentParser create(); 24 | } 25 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/InlineParserState.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | public interface InlineParserState { 4 | 5 | /** 6 | * Return a scanner for the input for the current position (on the trigger character that the inline parser was 7 | * added for). 8 | *

9 | * Note that this always returns the same instance, if you want to backtrack you need to use 10 | * {@link Scanner#position()} and {@link Scanner#setPosition(Position)}. 11 | */ 12 | Scanner scanner(); 13 | } 14 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/LinkInfo.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import org.commonmark.node.Text; 4 | 5 | /** 6 | * A parsed link/image. There are different types of links. 7 | *

8 | * Inline links: 9 | *

10 |  * [text](destination)
11 |  * [text](destination "title")
12 |  * 
13 | *

14 | * Reference links, which have different subtypes. Full:: 15 | *

16 |  * [text][label]
17 |  * 
18 | * Collapsed (label is ""): 19 | *
20 |  * [text][]
21 |  * 
22 | * Shortcut (label is null): 23 | *
24 |  * [text]
25 |  * 
26 | * Images use the same syntax as links but with a {@code !} {@link #marker()} front, e.g. {@code ![text](destination)}. 27 | */ 28 | public interface LinkInfo { 29 | 30 | /** 31 | * The marker if present, or null. A marker is e.g. {@code !} for an image, or a custom marker as specified in 32 | * {@link org.commonmark.parser.Parser.Builder#linkMarker}. 33 | */ 34 | Text marker(); 35 | 36 | /** 37 | * The text node of the opening bracket {@code [}. 38 | */ 39 | Text openingBracket(); 40 | 41 | /** 42 | * The text between the first brackets, e.g. `foo` in `[foo][bar]`. 43 | */ 44 | String text(); 45 | 46 | /** 47 | * The label, or null for inline links or for shortcut links (in which case {@link #text()} should be used as the label). 48 | */ 49 | String label(); 50 | 51 | /** 52 | * The destination if available, e.g. in `[foo](destination)`, or null 53 | */ 54 | String destination(); 55 | 56 | /** 57 | * The title if available, e.g. in `[foo](destination "title")`, or null 58 | */ 59 | String title(); 60 | 61 | /** 62 | * The position after the closing text bracket, e.g.: 63 | *
64 |      * [foo][bar]
65 |      *      ^
66 |      * 
67 | */ 68 | Position afterTextBracket(); 69 | } 70 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/LinkProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import org.commonmark.parser.InlineParserContext; 4 | 5 | /** 6 | * An interface to decide how links/images are handled. 7 | *

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

11 | *


12 |  * [text](destination)
13 |  * [text]
14 |  * [text][]
15 |  * [text][label]
16 |  * 
17 | * And images: 18 | *

19 |  * ![text](destination)
20 |  * ![text]
21 |  * ![text][]
22 |  * ![text][label]
23 |  * 
24 | * See {@link LinkInfo} for accessing various parts of the parsed link/image. 25 | *

26 | * The processor can then inspect the link/image and decide what to do with it by returning the appropriate 27 | * {@link LinkResult}. If it returns {@link LinkResult#none()}, the next registered processor is tried. If none of them 28 | * apply, the link is handled as it normally would. 29 | */ 30 | public interface LinkProcessor { 31 | 32 | /** 33 | * @param linkInfo information about the parsed link/image 34 | * @param scanner the scanner at the current position after the parsed link/image 35 | * @param context context for inline parsing 36 | * @return what to do with the link/image, e.g. do nothing (try the next processor), wrap the text in a node, or 37 | * replace the link/image with a node 38 | */ 39 | LinkResult process(LinkInfo linkInfo, Scanner scanner, InlineParserContext context); 40 | } 41 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/LinkResult.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import org.commonmark.internal.inline.LinkResultImpl; 4 | import org.commonmark.node.Node; 5 | 6 | /** 7 | * What to do with a link/image processed by {@link LinkProcessor}. 8 | */ 9 | public interface LinkResult { 10 | /** 11 | * Link not handled by processor. 12 | */ 13 | static LinkResult none() { 14 | return null; 15 | } 16 | 17 | /** 18 | * Wrap the link text in a node. This is the normal behavior for links, e.g. for this: 19 | *


20 |      * [my *text*](destination)
21 |      * 
22 | * The text is {@code my *text*}, a text node and emphasis. The text is wrapped in a 23 | * {@link org.commonmark.node.Link} node, which means the text is added as child nodes to it. 24 | * 25 | * @param node the node to which the link text nodes will be added as child nodes 26 | * @param position the position to continue parsing from 27 | */ 28 | static LinkResult wrapTextIn(Node node, Position position) { 29 | return new LinkResultImpl(LinkResultImpl.Type.WRAP, node, position); 30 | } 31 | 32 | /** 33 | * Replace the link with a node. E.g. for this: 34 | *

35 |      * [^foo]
36 |      * 
37 | * The processor could decide to create a {@code FootnoteReference} node instead which replaces the link. 38 | * 39 | * @param node the node to replace the link with 40 | * @param position the position to continue parsing from 41 | */ 42 | static LinkResult replaceWith(Node node, Position position) { 43 | return new LinkResultImpl(LinkResultImpl.Type.REPLACE, node, position); 44 | } 45 | 46 | /** 47 | * If a {@link LinkInfo#marker()} is present, include it in processing (i.e. treat it the same way as the brackets). 48 | */ 49 | LinkResult includeMarker(); 50 | } 51 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/ParsedInline.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import org.commonmark.internal.inline.ParsedInlineImpl; 4 | import org.commonmark.node.Node; 5 | 6 | import java.util.Objects; 7 | 8 | /** 9 | * The result of a single inline parser. Use the static methods to create instances. 10 | *

11 | * This interface is not intended to be implemented by clients. 12 | */ 13 | public interface ParsedInline { 14 | 15 | static ParsedInline none() { 16 | return null; 17 | } 18 | 19 | static ParsedInline of(Node node, Position position) { 20 | Objects.requireNonNull(node, "node must not be null"); 21 | Objects.requireNonNull(position, "position must not be null"); 22 | return new ParsedInlineImpl(node, position); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/Position.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | /** 4 | * Position within a {@link Scanner}. This is intentionally kept opaque so as not to expose the internal structure of 5 | * the Scanner. 6 | */ 7 | public class Position { 8 | 9 | final int lineIndex; 10 | final int index; 11 | 12 | Position(int lineIndex, int index) { 13 | this.lineIndex = lineIndex; 14 | this.index = index; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/beta/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Experimental APIs to use for extensions. APIs are subject to change if necessary. 3 | */ 4 | package org.commonmark.parser.beta; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | import org.commonmark.node.Block; 4 | import org.commonmark.node.DefinitionMap; 5 | import org.commonmark.node.SourceSpan; 6 | import org.commonmark.parser.InlineParser; 7 | import org.commonmark.parser.SourceLine; 8 | 9 | import java.util.List; 10 | 11 | public abstract class AbstractBlockParser implements BlockParser { 12 | 13 | @Override 14 | public boolean isContainer() { 15 | return false; 16 | } 17 | 18 | @Override 19 | public boolean canHaveLazyContinuationLines() { 20 | return false; 21 | } 22 | 23 | @Override 24 | public boolean canContain(Block childBlock) { 25 | return false; 26 | } 27 | 28 | @Override 29 | public void addLine(SourceLine line) { 30 | } 31 | 32 | @Override 33 | public void addSourceSpan(SourceSpan sourceSpan) { 34 | getBlock().addSourceSpan(sourceSpan); 35 | } 36 | 37 | @Override 38 | public List> getDefinitions() { 39 | return List.of(); 40 | } 41 | 42 | @Override 43 | public void closeBlock() { 44 | } 45 | 46 | @Override 47 | public void parseInlines(InlineParser inlineParser) { 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/AbstractBlockParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | public abstract class AbstractBlockParserFactory implements BlockParserFactory { 4 | } 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/BlockContinue.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | import org.commonmark.internal.BlockContinueImpl; 4 | 5 | /** 6 | * Result object for continuing parsing of a block, see static methods for constructors. 7 | */ 8 | public class BlockContinue { 9 | 10 | protected BlockContinue() { 11 | } 12 | 13 | public static BlockContinue none() { 14 | return null; 15 | } 16 | 17 | public static BlockContinue atIndex(int newIndex) { 18 | return new BlockContinueImpl(newIndex, -1, false); 19 | } 20 | 21 | public static BlockContinue atColumn(int newColumn) { 22 | return new BlockContinueImpl(-1, newColumn, false); 23 | } 24 | 25 | public static BlockContinue finished() { 26 | return new BlockContinueImpl(-1, -1, true); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/BlockParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | /** 4 | * Parser factory for a block node for determining when a block starts. 5 | *

6 | * Implementations should subclass {@link AbstractBlockParserFactory} instead of implementing this directly. 7 | */ 8 | public interface BlockParserFactory { 9 | 10 | BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockParser); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/BlockStart.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | import org.commonmark.internal.BlockStartImpl; 4 | 5 | /** 6 | * Result object for starting parsing of a block, see static methods for constructors. 7 | */ 8 | public abstract class BlockStart { 9 | 10 | protected BlockStart() { 11 | } 12 | 13 | public static BlockStart none() { 14 | return null; 15 | } 16 | 17 | public static BlockStart of(BlockParser... blockParsers) { 18 | return new BlockStartImpl(blockParsers); 19 | } 20 | 21 | public abstract BlockStart atIndex(int newIndex); 22 | 23 | public abstract BlockStart atColumn(int newColumn); 24 | 25 | public abstract BlockStart replaceActiveBlockParser(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/MatchedBlockParser.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | import org.commonmark.parser.SourceLines; 4 | 5 | /** 6 | * Open block parser that was last matched during the continue phase. This is different from the currently active 7 | * block parser, as an unmatched block is only closed when a new block is started. 8 | *

This interface is not intended to be implemented by clients.

9 | */ 10 | public interface MatchedBlockParser { 11 | 12 | BlockParser getMatchedBlockParser(); 13 | 14 | /** 15 | * Returns the current paragraph lines if the matched block is a paragraph. 16 | * 17 | * @return paragraph content or an empty list 18 | */ 19 | SourceLines getParagraphLines(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/ParserState.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.block; 2 | 3 | import org.commonmark.parser.SourceLine; 4 | 5 | /** 6 | * State of the parser that is used in block parsers. 7 | *

This interface is not intended to be implemented by clients.

8 | */ 9 | public interface ParserState { 10 | 11 | /** 12 | * @return the current source line being parsed (full line) 13 | */ 14 | SourceLine getLine(); 15 | 16 | /** 17 | * @return the current index within the line (0-based) 18 | */ 19 | int getIndex(); 20 | 21 | /** 22 | * @return the index of the next non-space character starting from {@link #getIndex()} (may be the same) (0-based) 23 | */ 24 | int getNextNonSpaceIndex(); 25 | 26 | /** 27 | * The column is the position within the line after tab characters have been processed as 4-space tab stops. 28 | * If the line doesn't contain any tabs, it's the same as the {@link #getIndex()}. If the line starts with a tab, 29 | * followed by text, then the column for the first character of the text is 4 (the index is 1). 30 | * 31 | * @return the current column within the line (0-based) 32 | */ 33 | int getColumn(); 34 | 35 | /** 36 | * @return the indentation in columns (either by spaces or tab stop of 4), starting from {@link #getColumn()} 37 | */ 38 | int getIndent(); 39 | 40 | /** 41 | * @return true if the current line is blank starting from the index 42 | */ 43 | boolean isBlank(); 44 | 45 | /** 46 | * @return the deepest open block parser 47 | */ 48 | BlockParser getActiveBlockParser(); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/block/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Types for extending block parsing 3 | */ 4 | package org.commonmark.parser.block; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/delimiter/DelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.delimiter; 2 | 3 | import org.commonmark.node.Text; 4 | 5 | /** 6 | * Custom delimiter processor for additional delimiters besides {@code _} and {@code *}. 7 | *

8 | * Note that implementations of this need to be thread-safe, the same instance may be used by multiple parsers. 9 | * 10 | * @see org.commonmark.parser.beta.InlineContentParserFactory 11 | */ 12 | public interface DelimiterProcessor { 13 | 14 | /** 15 | * @return the character that marks the beginning of a delimited node, must not clash with any built-in special 16 | * characters 17 | */ 18 | char getOpeningCharacter(); 19 | 20 | /** 21 | * @return the character that marks the the ending of a delimited node, must not clash with any built-in special 22 | * characters. Note that for a symmetric delimiter such as "*", this is the same as the opening. 23 | */ 24 | char getClosingCharacter(); 25 | 26 | /** 27 | * Minimum number of delimiter characters that are needed to activate this. Must be at least 1. 28 | */ 29 | int getMinLength(); 30 | 31 | /** 32 | * Process the delimiter runs. 33 | *

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

38 | * Note that removal (unlinking) of the used delimiter {@link Text} nodes is done by the caller. 39 | * 40 | * @param openingRun the opening delimiter run 41 | * @param closingRun the closing delimiter run 42 | * @return how many delimiters were used; must not be greater than length of either opener or closer 43 | */ 44 | int process(DelimiterRun openingRun, DelimiterRun closingRun); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/parser/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Parsing input text to AST nodes (see {@link org.commonmark.parser.Parser}) 3 | */ 4 | package org.commonmark.parser; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/NodeRenderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * A renderer for a set of node types. 9 | */ 10 | public interface NodeRenderer { 11 | 12 | /** 13 | * @return the types of nodes that this renderer handles 14 | */ 15 | Set> getNodeTypes(); 16 | 17 | /** 18 | * Render the specified node. 19 | * 20 | * @param node the node to render, will be an instance of one of {@link #getNodeTypes()} 21 | */ 22 | void render(Node node); 23 | 24 | /** 25 | * Called before the root node is rendered, to do any initial processing at the start. 26 | * 27 | * @param rootNode the root (top-level) node 28 | */ 29 | default void beforeRoot(Node rootNode) { 30 | } 31 | 32 | /** 33 | * Called after the root node is rendered, to do any final processing at the end. 34 | * 35 | * @param rootNode the root (top-level) node 36 | */ 37 | default void afterRoot(Node rootNode) { 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/Renderer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | public interface Renderer { 6 | 7 | /** 8 | * Render the tree of nodes to output. 9 | * 10 | * @param node the root node 11 | * @param output output for rendering 12 | */ 13 | void render(Node node, Appendable output); 14 | 15 | /** 16 | * Render the tree of nodes to string. 17 | * 18 | * @param node the root node 19 | * @return the rendered string 20 | */ 21 | String render(Node node); 22 | } 23 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/AttributeProvider.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.html; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * Extension point for adding/changing attributes on HTML tags for a node. 9 | */ 10 | public interface AttributeProvider { 11 | 12 | /** 13 | * Set the attributes for a HTML tag of the specified node by modifying the provided map. 14 | *

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

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

20 | * This method may be called multiple times for the same node, if the node is rendered using multiple nested 21 | * tags (e.g. code blocks). 22 | * 23 | * @param node the node to set attributes for 24 | * @param tagName the HTML tag name that these attributes are for (e.g. {@code h1}, {@code pre}, {@code code}). 25 | * @param attributes the attributes, with any default attributes already set in the map 26 | */ 27 | void setAttributes(Node node, String tagName, Map attributes); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderContext.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.html; 2 | 3 | /** 4 | * The context for attribute providers. 5 | *

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

6 | *

This interface is not intended to be implemented by clients.

7 | */ 8 | public interface AttributeProviderContext { 9 | } 10 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/AttributeProviderFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.html; 2 | 3 | /** 4 | * Factory for instantiating new attribute providers when rendering is done. 5 | */ 6 | public interface AttributeProviderFactory { 7 | 8 | /** 9 | * Create a new attribute provider. 10 | * 11 | * @param context for this attribute provider 12 | * @return an AttributeProvider 13 | */ 14 | AttributeProvider create(AttributeProviderContext context); 15 | } 16 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/HtmlNodeRendererFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.html; 2 | 3 | import org.commonmark.renderer.NodeRenderer; 4 | 5 | /** 6 | * Factory for instantiating new node renderers when rendering is done. 7 | */ 8 | public interface HtmlNodeRendererFactory { 9 | 10 | /** 11 | * Create a new node renderer for the specified rendering context. 12 | * 13 | * @param context the context for rendering (normally passed on to the node renderer) 14 | * @return a node renderer 15 | */ 16 | NodeRenderer create(HtmlNodeRendererContext context); 17 | } 18 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/UrlSanitizer.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.html; 2 | 3 | import org.commonmark.node.Image; 4 | import org.commonmark.node.Link; 5 | 6 | /** 7 | * Sanitizes urls for img and a elements by whitelisting protocols. 8 | * This is intended to prevent XSS payloads like [Click this totally safe url](javascript:document.xss=true;) 9 | *

10 | * Implementation based on https://github.com/OWASP/java-html-sanitizer/blob/f07e44b034a45d94d6fd010279073c38b6933072/src/main/java/org/owasp/html/FilterUrlByProtocolAttributePolicy.java 11 | * 12 | * @since 0.14.0 13 | */ 14 | public interface UrlSanitizer { 15 | /** 16 | * Sanitize a url for use in the href attribute of a {@link Link}. 17 | * 18 | * @param url Link to sanitize 19 | * @return Sanitized link 20 | */ 21 | String sanitizeLinkUrl(String url); 22 | 23 | /** 24 | * Sanitize a url for use in the src attribute of a {@link Image}. 25 | * 26 | * @param url Link to sanitize 27 | * @return Sanitized link {@link Image} 28 | */ 29 | String sanitizeImageUrl(String url); 30 | } 31 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/html/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * HTML rendering (see {@link org.commonmark.renderer.html.HtmlRenderer}) 3 | */ 4 | package org.commonmark.renderer.html; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererContext.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.markdown; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * Context that is passed to custom node renderers, see {@link MarkdownNodeRendererFactory#create}. 9 | */ 10 | public interface MarkdownNodeRendererContext { 11 | 12 | /** 13 | * @return the writer to use 14 | */ 15 | MarkdownWriter getWriter(); 16 | 17 | /** 18 | * Render the specified node and its children using the configured renderers. This should be used to render child 19 | * nodes; be careful not to pass the node that is being rendered, that would result in an endless loop. 20 | * 21 | * @param node the node to render 22 | */ 23 | void render(Node node); 24 | 25 | /** 26 | * @return additional special characters that need to be escaped if they occur in normal text; currently only ASCII 27 | * characters are allowed 28 | */ 29 | Set getSpecialCharacters(); 30 | } 31 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/markdown/MarkdownNodeRendererFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.markdown; 2 | 3 | import org.commonmark.renderer.NodeRenderer; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * Factory for instantiating new node renderers for rendering custom nodes. 9 | */ 10 | public interface MarkdownNodeRendererFactory { 11 | 12 | /** 13 | * Create a new node renderer for the specified rendering context. 14 | * 15 | * @param context the context for rendering (normally passed on to the node renderer) 16 | * @return a node renderer 17 | */ 18 | NodeRenderer create(MarkdownNodeRendererContext context); 19 | 20 | /** 21 | * @return the additional special characters that this factory would like to have escaped in normal text; currently 22 | * only ASCII characters are allowed 23 | */ 24 | Set getSpecialCharacters(); 25 | } 26 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/markdown/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Markdown rendering (see {@link org.commonmark.renderer.markdown.MarkdownRenderer}) 3 | */ 4 | package org.commonmark.renderer.markdown; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/text/LineBreakRendering.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.text; 2 | 3 | /** 4 | * Control how line breaks are rendered. 5 | */ 6 | public enum LineBreakRendering { 7 | /** 8 | * Strip all line breaks within blocks and between blocks, resulting in all the text in a single line. 9 | */ 10 | STRIP, 11 | /** 12 | * Use single line breaks between blocks, not a blank line (also render all lists as tight). 13 | */ 14 | COMPACT, 15 | /** 16 | * Separate blocks by a blank line (and respect tight vs loose lists). 17 | */ 18 | SEPARATE_BLOCKS, 19 | } 20 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererContext.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.text; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | public interface TextContentNodeRendererContext { 6 | 7 | /** 8 | * Controls how line breaks should be rendered, see {@link LineBreakRendering}. 9 | */ 10 | LineBreakRendering lineBreakRendering(); 11 | 12 | /** 13 | * @return true for stripping new lines and render text as "single line", 14 | * false for keeping all line breaks. 15 | * @deprecated Use {@link #lineBreakRendering()} instead 16 | */ 17 | @Deprecated 18 | boolean stripNewlines(); 19 | 20 | /** 21 | * @return the writer to use 22 | */ 23 | TextContentWriter getWriter(); 24 | 25 | /** 26 | * Render the specified node and its children using the configured renderers. This should be used to render child 27 | * nodes; be careful not to pass the node that is being rendered, that would result in an endless loop. 28 | * 29 | * @param node the node to render 30 | */ 31 | void render(Node node); 32 | } 33 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/text/TextContentNodeRendererFactory.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.renderer.text; 2 | 3 | import org.commonmark.renderer.NodeRenderer; 4 | 5 | /** 6 | * Factory for instantiating new node renderers when rendering is done. 7 | */ 8 | public interface TextContentNodeRendererFactory { 9 | 10 | /** 11 | * Create a new node renderer for the specified rendering context. 12 | * 13 | * @param context the context for rendering (normally passed on to the node renderer) 14 | * @return a node renderer 15 | */ 16 | NodeRenderer create(TextContentNodeRendererContext context); 17 | } 18 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/renderer/text/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Plain text rendering with minimal markup (see {@link org.commonmark.renderer.text.TextContentRenderer}) 3 | */ 4 | package org.commonmark.renderer.text; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/text/AsciiMatcher.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.text; 2 | 3 | import java.util.BitSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Char matcher that can match ASCII characters efficiently. 8 | */ 9 | public class AsciiMatcher implements CharMatcher { 10 | private final BitSet set; 11 | 12 | private AsciiMatcher(Builder builder) { 13 | this.set = builder.set; 14 | } 15 | 16 | @Override 17 | public boolean matches(char c) { 18 | return set.get(c); 19 | } 20 | 21 | public Builder newBuilder() { 22 | return new Builder((BitSet) set.clone()); 23 | } 24 | 25 | public static Builder builder() { 26 | return new Builder(new BitSet()); 27 | } 28 | 29 | public static Builder builder(AsciiMatcher matcher) { 30 | return new Builder((BitSet) matcher.set.clone()); 31 | } 32 | 33 | public static class Builder { 34 | private final BitSet set; 35 | 36 | private Builder(BitSet set) { 37 | this.set = set; 38 | } 39 | 40 | public Builder c(char c) { 41 | if (c > 127) { 42 | throw new IllegalArgumentException("Can only match ASCII characters"); 43 | } 44 | set.set(c); 45 | return this; 46 | } 47 | 48 | public Builder anyOf(String s) { 49 | for (int i = 0; i < s.length(); i++) { 50 | c(s.charAt(i)); 51 | } 52 | return this; 53 | } 54 | 55 | public Builder anyOf(Set characters) { 56 | for (Character c : characters) { 57 | c(c); 58 | } 59 | return this; 60 | } 61 | 62 | public Builder range(char from, char toInclusive) { 63 | for (char c = from; c <= toInclusive; c++) { 64 | c(c); 65 | } 66 | return this; 67 | } 68 | 69 | public AsciiMatcher build() { 70 | return new AsciiMatcher(this); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/text/CharMatcher.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.text; 2 | 3 | /** 4 | * Matcher interface for {@code char} values. 5 | *

6 | * Note that because this matches on {@code char} values only (as opposed to {@code int} code points), 7 | * this only operates on the level of code units and doesn't support supplementary characters 8 | * (see {@link Character#isSupplementaryCodePoint(int)}). 9 | */ 10 | public interface CharMatcher { 11 | 12 | boolean matches(char c); 13 | } 14 | -------------------------------------------------------------------------------- /commonmark/src/main/java/org/commonmark/text/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Text processing utilities for parsing and rendering, exported for use by extensions 3 | */ 4 | package org.commonmark.text; 5 | -------------------------------------------------------------------------------- /commonmark/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Java implementation of CommonMark for parsing markdown and rendering to HTML (core library) 4 |

Example:

5 |
    import org.commonmark.node.*;
 6 |     import org.commonmark.parser.Parser;
 7 |     import org.commonmark.renderer.html.HtmlRenderer;
 8 | 
 9 |     Parser parser = Parser.builder().build();
10 |     Node document = parser.parse("This is *Sparta*");
11 |     HtmlRenderer renderer = HtmlRenderer.builder().escapeHtml(true).build();
12 |     renderer.render(document);  // "<p>This is <em>Sparta</em></p>\n"
13 | 
14 |

See the following packages for details:

15 |
    16 |
  • {@link org.commonmark.parser} for parsing input text to AST nodes
  • 17 |
  • {@link org.commonmark.node} for AST node types and visitors
  • 18 |
  • {@link org.commonmark.renderer.html} for HTML rendering
  • 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /commonmark/src/main/resources/META-INF/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Atlassian Pty Ltd 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/ProfilingMain.java: -------------------------------------------------------------------------------- 1 | package org.commonmark; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.html.HtmlRenderer; 6 | import org.commonmark.testutil.TestResources; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class ProfilingMain { 12 | 13 | private static final String SPEC = TestResources.readAsString(TestResources.getSpec()); 14 | // private static final List SPEC_EXAMPLES = ExampleReader.readExampleSources(TestResources.getSpec()); 15 | private static final Parser PARSER = Parser.builder().build(); 16 | private static final HtmlRenderer RENDERER = HtmlRenderer.builder().build(); 17 | 18 | public static void main(String[] args) throws Exception { 19 | System.out.println("Attach profiler, then press enter to start parsing."); 20 | System.in.read(); 21 | System.out.println("Parsing"); 22 | List nodes = parse(List.of(SPEC)); 23 | System.out.println("Finished parsing, press enter to start rendering"); 24 | System.in.read(); 25 | System.out.println(render(nodes)); 26 | System.out.println("Finished rendering"); 27 | } 28 | 29 | private static List parse(List examples) { 30 | List nodes = new ArrayList<>(); 31 | for (String example : examples) { 32 | Node doc = PARSER.parse(example); 33 | nodes.add(doc); 34 | } 35 | return nodes; 36 | } 37 | 38 | private static long render(List examples) { 39 | long length = 0; 40 | for (Node example : examples) { 41 | String result = RENDERER.render(example); 42 | length += result.length(); 43 | } 44 | return length; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/internal/util/EscapingTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.internal.util; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class EscapingTest { 8 | 9 | @Test 10 | public void testEscapeHtml() { 11 | assertEquals("nothing to escape", Escaping.escapeHtml("nothing to escape")); 12 | assertEquals("&", Escaping.escapeHtml("&")); 13 | assertEquals("<", Escaping.escapeHtml("<")); 14 | assertEquals(">", Escaping.escapeHtml(">")); 15 | assertEquals(""", Escaping.escapeHtml("\"")); 16 | assertEquals("< start", Escaping.escapeHtml("< start")); 17 | assertEquals("end >", Escaping.escapeHtml("end >")); 18 | assertEquals("< both >", Escaping.escapeHtml("< both >")); 19 | assertEquals("< middle & too >", Escaping.escapeHtml("< middle & too >")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/parser/beta/LinkProcessorTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.parser.beta; 2 | 3 | import org.commonmark.node.Link; 4 | import org.commonmark.node.Text; 5 | import org.commonmark.parser.Parser; 6 | import org.commonmark.test.Nodes; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class LinkProcessorTest { 12 | @Test 13 | public void testLinkMarkerShouldNotBeIncludedByDefault() { 14 | // If a link marker is registered but is not processed, the built-in link processor shouldn't consume it. 15 | // And I think by default, other processors shouldn't consume it either (by accident). 16 | // So requiring processors to opt into including the marker is better than requiring them to opt out, 17 | // because processors that look for a marker already need to write some code to deal with the marker anyway, 18 | // and will have tests ensuring that the marker is part of the parsed node, not the text. 19 | var parser = Parser.builder().linkMarker('^').build(); 20 | var doc = parser.parse("^[test](url)"); 21 | var link = Nodes.find(doc, Link.class); 22 | assertEquals("url", link.getDestination()); 23 | assertEquals("^", ((Text) link.getPrevious()).getLiteral()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/AbstractVisitorTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.node.*; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertNull; 8 | 9 | public class AbstractVisitorTest { 10 | 11 | @Test 12 | public void replacingNodeInVisitorShouldNotDestroyVisitOrder() { 13 | Visitor visitor = new AbstractVisitor() { 14 | @Override 15 | public void visit(Text text) { 16 | text.insertAfter(new Code(text.getLiteral())); 17 | text.unlink(); 18 | } 19 | }; 20 | 21 | Paragraph paragraph = new Paragraph(); 22 | paragraph.appendChild(new Text("foo")); 23 | paragraph.appendChild(new Text("bar")); 24 | 25 | paragraph.accept(visitor); 26 | 27 | assertCode("foo", paragraph.getFirstChild()); 28 | assertCode("bar", paragraph.getFirstChild().getNext()); 29 | assertNull(paragraph.getFirstChild().getNext().getNext()); 30 | assertCode("bar", paragraph.getLastChild()); 31 | } 32 | 33 | private static void assertCode(String expectedLiteral, Node node) { 34 | assertEquals("Expected node to be a Code node: " + node, Code.class, node.getClass()); 35 | Code code = (Code) node; 36 | assertEquals(expectedLiteral, code.getLiteral()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/CoreRenderingTestCase.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.parser.Parser; 4 | import org.commonmark.renderer.html.HtmlRenderer; 5 | import org.commonmark.testutil.RenderingTestCase; 6 | 7 | public class CoreRenderingTestCase extends RenderingTestCase { 8 | 9 | private static final Parser PARSER = Parser.builder().build(); 10 | private static final HtmlRenderer RENDERER = HtmlRenderer.builder().build(); 11 | 12 | @Override 13 | protected String render(String source) { 14 | return RENDERER.render(PARSER.parse(source)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/DelimitedTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.node.*; 4 | import org.commonmark.parser.Parser; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | public class DelimitedTest { 13 | 14 | @Test 15 | public void emphasisDelimiters() { 16 | String input = "* *emphasis* \n" 17 | + "* **strong** \n" 18 | + "* _important_ \n" 19 | + "* __CRITICAL__ \n"; 20 | 21 | Parser parser = Parser.builder().build(); 22 | Node document = parser.parse(input); 23 | 24 | final List list = new ArrayList<>(); 25 | Visitor visitor = new AbstractVisitor() { 26 | @Override 27 | public void visit(Emphasis node) { 28 | list.add(node); 29 | } 30 | 31 | @Override 32 | public void visit(StrongEmphasis node) { 33 | list.add(node); 34 | } 35 | }; 36 | document.accept(visitor); 37 | 38 | assertEquals(4, list.size()); 39 | 40 | Delimited emphasis = list.get(0); 41 | Delimited strong = list.get(1); 42 | Delimited important = list.get(2); 43 | Delimited critical = list.get(3); 44 | 45 | assertEquals("*", emphasis.getOpeningDelimiter()); 46 | assertEquals("*", emphasis.getClosingDelimiter()); 47 | assertEquals("**", strong.getOpeningDelimiter()); 48 | assertEquals("**", strong.getClosingDelimiter()); 49 | assertEquals("_", important.getOpeningDelimiter()); 50 | assertEquals("_", important.getClosingDelimiter()); 51 | assertEquals("__", critical.getOpeningDelimiter()); 52 | assertEquals("__", critical.getClosingDelimiter()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/HtmlInlineParserTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.junit.Test; 4 | 5 | public class HtmlInlineParserTest extends CoreRenderingTestCase { 6 | 7 | @Test 8 | public void comment() { 9 | assertRendering("inline ", "

inline

\n"); 10 | assertRendering("inline ", "

inline

\n"); 11 | assertRendering("inline ", "

inline

\n"); 12 | assertRendering("inline ", "

inline

\n"); 13 | assertRendering("inline ", "

inline

\n"); 14 | assertRendering("inline -->", "

inline -->

\n"); 15 | assertRendering("inline -->", "

inline -->

\n"); 16 | } 17 | 18 | @Test 19 | public void cdata() { 20 | assertRendering("inline ", "

inline

\n"); 21 | assertRendering("inline ", "

inline

\n"); 22 | } 23 | 24 | @Test 25 | public void declaration() { 26 | // Whitespace is mandatory 27 | assertRendering("inline ", "

inline <!FOO>

\n"); 28 | assertRendering("inline ", "

inline

\n"); 29 | assertRendering("inline ", "

inline

\n"); 30 | 31 | // Lowercase 32 | assertRendering("inline ", "

inline

\n"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/Nodes.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.node.Node; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Objects; 8 | 9 | public class Nodes { 10 | 11 | public static List getChildren(Node parent) { 12 | List children = new ArrayList<>(); 13 | for (Node child = parent.getFirstChild(); child != null; child = child.getNext()) { 14 | children.add(child); 15 | } 16 | return children; 17 | } 18 | 19 | /** 20 | * Recursively try to find a node with the given type within the children of the specified node. 21 | * 22 | * @param parent The node to get children from (node itself will not be checked) 23 | * @param nodeClass The type of node to find 24 | */ 25 | public static T tryFind(Node parent, Class nodeClass) { 26 | Node node = parent.getFirstChild(); 27 | while (node != null) { 28 | Node next = node.getNext(); 29 | if (nodeClass.isInstance(node)) { 30 | //noinspection unchecked 31 | return (T) node; 32 | } 33 | T result = tryFind(node, nodeClass); 34 | if (result != null) { 35 | return result; 36 | } 37 | node = next; 38 | } 39 | return null; 40 | } 41 | 42 | /** 43 | * Recursively try to find a node with the given type within the children of the specified node. Throw if node 44 | * could not be found. 45 | */ 46 | public static T find(Node parent, Class nodeClass) { 47 | return Objects.requireNonNull(tryFind(parent, nodeClass), 48 | "Could not find a " + nodeClass.getSimpleName() + " node in " + parent); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/SourceLineTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.node.SourceSpan; 4 | import org.commonmark.parser.SourceLine; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class SourceLineTest { 10 | 11 | @Test 12 | public void testSubstring() { 13 | SourceLine line = SourceLine.of("abcd", SourceSpan.of(3, 10, 13, 4)); 14 | 15 | assertSourceLine(line.substring(0, 4), "abcd", SourceSpan.of(3, 10, 13, 4)); 16 | assertSourceLine(line.substring(0, 3), "abc", SourceSpan.of(3, 10, 13, 3)); 17 | assertSourceLine(line.substring(0, 2), "ab", SourceSpan.of(3, 10, 13, 2)); 18 | assertSourceLine(line.substring(0, 1), "a", SourceSpan.of(3, 10, 13, 1)); 19 | assertSourceLine(line.substring(0, 0), "", null); 20 | 21 | assertSourceLine(line.substring(1, 4), "bcd", SourceSpan.of(3, 11, 14, 3)); 22 | assertSourceLine(line.substring(1, 3), "bc", SourceSpan.of(3, 11, 14, 2)); 23 | 24 | assertSourceLine(line.substring(3, 4), "d", SourceSpan.of(3, 13, 16, 1)); 25 | assertSourceLine(line.substring(4, 4), "", null); 26 | } 27 | 28 | @Test(expected = StringIndexOutOfBoundsException.class) 29 | public void testSubstringBeginOutOfBounds() { 30 | SourceLine.of("abcd", SourceSpan.of(3, 10, 13, 4)).substring(3, 2); 31 | } 32 | 33 | @Test(expected = StringIndexOutOfBoundsException.class) 34 | public void testSubstringEndOutOfBounds() { 35 | SourceLine.of("abcd", SourceSpan.of(3, 10, 13, 4)).substring(0, 5); 36 | } 37 | 38 | private static void assertSourceLine(SourceLine sourceLine, String expectedContent, SourceSpan expectedSourceSpan) { 39 | assertEquals(expectedContent, sourceLine.getContent()); 40 | assertEquals(expectedSourceSpan, sourceLine.getSourceSpan()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/SpecCrLfCoreTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.parser.Parser; 4 | import org.commonmark.renderer.html.HtmlRenderer; 5 | import org.commonmark.testutil.SpecTestCase; 6 | import org.commonmark.testutil.example.Example; 7 | import org.junit.Test; 8 | 9 | import static org.commonmark.testutil.Asserts.assertRendering; 10 | 11 | /** 12 | * Same as {@link SpecCoreTest} but converts line endings to Windows-style CR+LF endings before parsing. 13 | */ 14 | public class SpecCrLfCoreTest extends SpecTestCase { 15 | 16 | private static final Parser PARSER = Parser.builder().build(); 17 | // The spec says URL-escaping is optional, but the examples assume that it's enabled. 18 | private static final HtmlRenderer RENDERER = HtmlRenderer.builder().percentEncodeUrls(true).build(); 19 | 20 | public SpecCrLfCoreTest(Example example) { 21 | super(example); 22 | } 23 | 24 | @Test 25 | public void testHtmlRendering() { 26 | assertRendering(example.getSource(), example.getHtml(), render(example.getSource())); 27 | } 28 | 29 | private String render(String source) { 30 | String windowsStyle = source.replace("\n", "\r\n"); 31 | return RENDERER.render(PARSER.parse(windowsStyle)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/TextContentWriterTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.renderer.text.TextContentWriter; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.*; 7 | 8 | public class TextContentWriterTest { 9 | 10 | @Test 11 | public void whitespace() throws Exception { 12 | StringBuilder stringBuilder = new StringBuilder(); 13 | TextContentWriter writer = new TextContentWriter(stringBuilder); 14 | writer.write("foo"); 15 | writer.whitespace(); 16 | writer.write("bar"); 17 | assertEquals("foo bar", stringBuilder.toString()); 18 | } 19 | 20 | @Test 21 | public void colon() throws Exception { 22 | StringBuilder stringBuilder = new StringBuilder(); 23 | TextContentWriter writer = new TextContentWriter(stringBuilder); 24 | writer.write("foo"); 25 | writer.colon(); 26 | writer.write("bar"); 27 | assertEquals("foo:bar", stringBuilder.toString()); 28 | } 29 | 30 | @Test 31 | public void line() throws Exception { 32 | StringBuilder stringBuilder = new StringBuilder(); 33 | TextContentWriter writer = new TextContentWriter(stringBuilder); 34 | writer.write("foo"); 35 | writer.line(); 36 | writer.write("bar"); 37 | assertEquals("foo\nbar", stringBuilder.toString()); 38 | } 39 | 40 | @Test 41 | public void writeStripped() throws Exception { 42 | StringBuilder stringBuilder = new StringBuilder(); 43 | TextContentWriter writer = new TextContentWriter(stringBuilder); 44 | writer.writeStripped("foo\n bar"); 45 | assertEquals("foo bar", stringBuilder.toString()); 46 | } 47 | 48 | @Test 49 | public void write() throws Exception { 50 | StringBuilder stringBuilder = new StringBuilder(); 51 | TextContentWriter writer = new TextContentWriter(stringBuilder); 52 | writer.writeStripped("foo bar"); 53 | assertEquals("foo bar", stringBuilder.toString()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/test/ThematicBreakParserTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.test; 2 | 3 | import org.commonmark.node.ThematicBreak; 4 | import org.commonmark.parser.Parser; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class ThematicBreakParserTest { 10 | 11 | private static final Parser PARSER = Parser.builder().build(); 12 | 13 | @Test 14 | public void testLiteral() { 15 | assertLiteral("***", "***"); 16 | assertLiteral("-- -", "-- -"); 17 | assertLiteral(" __ __ __ ", " __ __ __ "); 18 | assertLiteral("***", "> ***"); 19 | } 20 | 21 | private static void assertLiteral(String expected, String input) { 22 | var tb = Nodes.find(PARSER.parse(input), ThematicBreak.class); 23 | assertEquals(expected, tb.getLiteral()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /commonmark/src/test/java/org/commonmark/text/CharactersTest.java: -------------------------------------------------------------------------------- 1 | package org.commonmark.text; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class CharactersTest { 9 | 10 | @Test 11 | public void isPunctuation() { 12 | // From https://spec.commonmark.org/0.29/#ascii-punctuation-character 13 | char[] chars = { 14 | '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', // (U+0021–2F) 15 | ':', ';', '<', '=', '>', '?', '@', // (U+003A–0040) 16 | '[', '\\', ']', '^', '_', '`', // (U+005B–0060) 17 | '{', '|', '}', '~' // (U+007B–007E) 18 | }; 19 | 20 | for (char c : chars) { 21 | assertTrue("Expected to be punctuation: " + c, Characters.isPunctuationCodePoint(c)); 22 | } 23 | } 24 | 25 | @Test 26 | public void isBlank() { 27 | assertTrue(Characters.isBlank("")); 28 | assertTrue(Characters.isBlank(" ")); 29 | assertTrue(Characters.isBlank("\t")); 30 | assertTrue(Characters.isBlank(" \t")); 31 | assertFalse(Characters.isBlank("a")); 32 | assertFalse(Characters.isBlank("\f")); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /etc/benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $(dirname $0)/.. 4 | mvn -pl commonmark -Pbenchmark -DskipTests clean package exec:exec 5 | -------------------------------------------------------------------------------- /etc/entities.js: -------------------------------------------------------------------------------- 1 | // 1. curl -O "https://html.spec.whatwg.org/multipage/entities.json" 2 | // 2. run this script with node 3 | 4 | var fs = require('fs'); 5 | var data = JSON.parse(fs.readFileSync("entities.json")); 6 | 7 | var result = ""; 8 | for (var key in data) { 9 | // exclude names not ending with ";" as per CommonMark spec 10 | if (!data.hasOwnProperty(key) || key.slice(-1) !== ";") { 11 | continue; 12 | } 13 | // special handling 14 | if (key === 'NewLine') { 15 | continue; 16 | } 17 | result += key.slice(1, -1) + '=' + data[key].characters + '\n'; 18 | } 19 | fs.writeFileSync("entities.properties", result); 20 | -------------------------------------------------------------------------------- /etc/update-spec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$#" -ne 1 ]; then 4 | echo "usage: $0 " 5 | exit 1 6 | fi 7 | 8 | version=$1 9 | curl -L "https://raw.githubusercontent.com/commonmark/commonmark-spec/$version/spec.txt" -o commonmark-test-util/src/main/resources/spec.txt 10 | curl -L "https://raw.githubusercontent.com/github/cmark-gfm/master/test/spec.txt" -o commonmark-test-util/src/main/resources/gfm-spec.txt 11 | 12 | echo "Check cmark and commonmark.js regression.txt:" 13 | echo "https://github.com/commonmark/cmark/blob/master/test/regression.txt" 14 | echo "https://github.com/commonmark/commonmark.js/blob/master/test/regression.txt" 15 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | --------------------------------------------------------------------------------