diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt index 08abe8d05..f3f8d8f9e 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt @@ -1,80 +1,79 @@ package org.jetbrains.jewel.markdown import org.commonmark.node.Block -import org.commonmark.node.Heading as CMHeading -import org.commonmark.node.Paragraph as CMParagraph +import org.jetbrains.jewel.foundation.GenerateDataFunctions +import org.jetbrains.jewel.foundation.InternalJewelApi public sealed interface MarkdownBlock { - public data class BlockQuote(val children: List) : MarkdownBlock + + @GenerateDataFunctions + public class BlockQuote(public val children: List) : MarkdownBlock public sealed interface CodeBlock : MarkdownBlock { public val content: String - public data class IndentedCodeBlock( - override val content: String, - ) : CodeBlock + @GenerateDataFunctions + public class IndentedCodeBlock(override val content: String) : CodeBlock - public data class FencedCodeBlock( + @GenerateDataFunctions + public class FencedCodeBlock( override val content: String, - val mimeType: MimeType?, + public val mimeType: MimeType?, ) : CodeBlock } public interface CustomBlock : MarkdownBlock - @JvmInline - public value class Heading( - private val nativeBlock: CMHeading, - ) : MarkdownBlock, BlockWithInlineMarkdown { - override val inlineContent: Iterable - get() = nativeBlock.inlineContent() + @GenerateDataFunctions + public class Heading( + override val inlineContent: List, + public val level: Int, + ) : MarkdownBlock, BlockWithInlineMarkdown - public val level: Int - get() = nativeBlock.level - } - - public data class HtmlBlock(val content: String) : MarkdownBlock + @GenerateDataFunctions + public class HtmlBlock(public val content: String) : MarkdownBlock public sealed interface ListBlock : MarkdownBlock { public val children: List public val isTight: Boolean - public data class OrderedList( + @GenerateDataFunctions + public class OrderedList( override val children: List, override val isTight: Boolean, - val startFrom: Int, - val delimiter: String, + public val startFrom: Int, + public val delimiter: String, ) : ListBlock - public data class UnorderedList( + @GenerateDataFunctions + public class UnorderedList( override val children: List, override val isTight: Boolean, - val marker: String, + public val marker: String, ) : ListBlock } - public data class ListItem( - val children: List, - ) : MarkdownBlock + @GenerateDataFunctions + public class ListItem(public val children: List) : MarkdownBlock - public object ThematicBreak : MarkdownBlock + public data object ThematicBreak : MarkdownBlock - @JvmInline - public value class Paragraph(private val nativeBlock: CMParagraph) : MarkdownBlock, BlockWithInlineMarkdown { - override val inlineContent: Iterable - get() = nativeBlock.inlineContent() - } + @GenerateDataFunctions + public class Paragraph( + override val inlineContent: List, + ) : MarkdownBlock, BlockWithInlineMarkdown } public interface BlockWithInlineMarkdown { public val inlineContent: Iterable } -private fun Block.inlineContent(): Iterable = +@InternalJewelApi +public fun Block.readInlineContent(): Iterable = object : Iterable { override fun iterator(): Iterator = object : Iterator { - var current = this@inlineContent.firstChild + var current = this@readInlineContent.firstChild override fun hasNext(): Boolean = current != null diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt index 6bb19e48b..2985e1016 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt @@ -176,7 +176,7 @@ public class MarkdownProcessor( private fun Node.tryProcessMarkdownBlock(): MarkdownBlock? = // Non-Block children are ignored when (this) { - is Paragraph -> MarkdownBlock.Paragraph(this) + is Paragraph -> toMarkdownParagraph() is Heading -> toMarkdownHeadingOrNull() is BulletList -> toMarkdownListOrNull() is OrderedList -> toMarkdownListOrNull() @@ -193,11 +193,18 @@ public class MarkdownProcessor( else -> null } - private fun BlockQuote.toMarkdownBlockQuote(): MarkdownBlock.BlockQuote = MarkdownBlock.BlockQuote(processChildren(this)) + private fun Paragraph.toMarkdownParagraph(): MarkdownBlock.Paragraph = + MarkdownBlock.Paragraph(readInlineContent().toList()) + + private fun BlockQuote.toMarkdownBlockQuote(): MarkdownBlock.BlockQuote = + MarkdownBlock.BlockQuote(processChildren(this)) private fun Heading.toMarkdownHeadingOrNull(): MarkdownBlock.Heading? { if (level < 1 || level > 6) return null - return MarkdownBlock.Heading(this) + return MarkdownBlock.Heading( + inlineContent = readInlineContent().toList(), + level = level + ) } private fun FencedCodeBlock.toMarkdownCodeBlockOrNull(): CodeBlock.FencedCodeBlock = diff --git a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt index de0be8a10..2718fa4c6 100644 --- a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt +++ b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt @@ -3,6 +3,7 @@ package org.jetbrains.jewel.markdown import org.commonmark.internal.InlineParserContextImpl import org.commonmark.internal.InlineParserImpl import org.commonmark.internal.LinkReferenceDefinitions +import org.commonmark.node.Block import org.commonmark.node.Node import org.commonmark.parser.Parser import org.commonmark.parser.SourceLine @@ -22,6 +23,8 @@ import org.jetbrains.jewel.markdown.MarkdownBlock.ListItem import org.jetbrains.jewel.markdown.MarkdownBlock.Paragraph import org.jetbrains.jewel.markdown.MarkdownBlock.ThematicBreak import org.junit.Assert +import org.commonmark.node.Heading as CMHeading +import org.commonmark.node.Paragraph as CMParagraph fun List.assertEquals(vararg expected: MarkdownBlock) { val differences = findDifferences(expected.toList(), indentSize = 0) @@ -238,7 +241,7 @@ private fun Node.children() = /** skip root Document and Paragraph nodes */ private fun inlineMarkdowns(content: String): List { val document = parser.parse(content).firstChild ?: return emptyList() - return if (document.firstChild is org.commonmark.node.Paragraph) { + return if (document.firstChild is CMParagraph) { document.firstChild } else { document @@ -249,31 +252,27 @@ private val inlineParser = InlineParserImpl(InlineParserContextImpl(emptyList(), fun paragraph( @Language("Markdown") content: String, -): Paragraph = - Paragraph( - org.commonmark.node.Paragraph().let { block -> - inlineParser.parse(SourceLines.of(content.lines().map { SourceLine.of(it, null) }), block) - block - }, - ) +) = + Paragraph(CMParagraph().parseInline(content)) fun heading( level: Int, @Language("Markdown") content: String, -) = Heading( - org.commonmark.node.Heading().let { block -> - inlineParser.parse(SourceLines.of(SourceLine.of(content, null)), block) - block.level = level - block - }, -) +) = + Heading(inlineContent = CMHeading().parseInline(content), level = level) + +private fun Block.parseInline(content: String): List { + inlineParser.parse(SourceLines.of(SourceLine.of(content, null)), this) + return readInlineContent().toList() +} fun indentedCodeBlock(content: String) = IndentedCodeBlock(content) fun fencedCodeBlock( content: String, mimeType: MimeType? = null, -) = FencedCodeBlock(content, mimeType) +) = + FencedCodeBlock(content, mimeType) fun blockQuote(vararg contents: MarkdownBlock) = BlockQuote(contents.toList()) @@ -281,14 +280,16 @@ fun unorderedList( vararg items: ListItem, isTight: Boolean = true, marker: String = "-", -) = UnorderedList(items.toList(), isTight, marker) +) = + UnorderedList(items.toList(), isTight, marker) fun orderedList( vararg items: ListItem, isTight: Boolean = true, startFrom: Int = 1, delimiter: String = ".", -) = OrderedList(items.toList(), isTight, startFrom, delimiter) +) = + OrderedList(items.toList(), isTight, startFrom, delimiter) fun listItem(vararg items: MarkdownBlock) = ListItem(items.toList())