aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/base/src/main/kotlin/parsers/MarkdownParser.kt44
-rw-r--r--plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt8
-rw-r--r--plugins/base/src/test/kotlin/markdown/ParserTest.kt53
-rw-r--r--plugins/base/src/test/kotlin/model/CommentTest.kt16
4 files changed, 98 insertions, 23 deletions
diff --git a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
index ebcb1b43..2e301f1e 100644
--- a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
+++ b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
@@ -195,7 +195,9 @@ open class MarkdownParser(
private fun markdownFileHandler(node: ASTNode) =
DocTagsFromIElementFactory.getInstance(
node.type,
- children = node.children.evaluateChildren()
+ children = node.children
+ .filterSpacesAndEOL()
+ .evaluateChildren()
)
private fun autoLinksHandler(node: ASTNode): List<DocTag> {
@@ -250,17 +252,23 @@ open class MarkdownParser(
private fun tableHandler(node: ASTNode) = DocTagsFromIElementFactory.getInstance(
GFMElementTypes.TABLE,
- children = node.children.filterTabSeparators().evaluateChildren()
+ children = node.children
+ .filter { it.type == GFMElementTypes.ROW || it.type == GFMElementTypes.HEADER }
+ .evaluateChildren()
)
private fun headerHandler(node: ASTNode) = DocTagsFromIElementFactory.getInstance(
GFMElementTypes.HEADER,
- children = node.children.filterTabSeparators().evaluateChildren()
+ children = node.children
+ .filter { it.type == GFMTokenTypes.CELL }
+ .evaluateChildren()
)
private fun rowHandler(node: ASTNode) = DocTagsFromIElementFactory.getInstance(
GFMElementTypes.ROW,
- children = node.children.filterTabSeparators().evaluateChildren()
+ children = node.children
+ .filter { it.type == GFMTokenTypes.CELL }
+ .evaluateChildren()
)
private fun cellHandler(node: ASTNode) = DocTagsFromIElementFactory.getInstance(
@@ -391,6 +399,9 @@ open class MarkdownParser(
private fun List<ASTNode>.filterTabSeparators() =
this.filterNot { it.type == GFMTokenTypes.TABLE_SEPARATOR }
+ private fun List<ASTNode>.filterSpacesAndEOL() =
+ this.filterNot { it.type == MarkdownTokenTypes.WHITE_SPACE || it.type == MarkdownTokenTypes.EOL }
+
private fun List<ASTNode>.evaluateChildren(keepAllFormatting: Boolean = false): List<DocTag> =
this.removeUselessTokens().swapImagesThatShouldBeLinks(keepAllFormatting).mergeLeafASTNodes().flatMap { visitNode(it, keepAllFormatting) }
@@ -430,9 +441,11 @@ open class MarkdownParser(
MarkdownTokenTypes.HTML_BLOCK_CONTENT
)
+ private fun ASTNode.isNotLeaf() = this is CompositeASTNode || this.type in notLeafNodes
+
private fun List<ASTNode>.isNotLeaf(index: Int): Boolean =
if (index in 0..this.lastIndex)
- (this[index] is CompositeASTNode) || this[index].type in notLeafNodes
+ this[index].isNotLeaf()
else
false
@@ -447,17 +460,13 @@ open class MarkdownParser(
val sIndex = index
while (index < this.lastIndex) {
if (this.isNotLeaf(index + 1) || this[index + 1].startOffset != this[index].endOffset) {
- mergedLeafNode(this, index, startOffset, sIndex)?.run {
- children += this
- }
+ children += mergedLeafNode(this, index, startOffset, sIndex)
break
}
index++
}
if (index == this.lastIndex) {
- mergedLeafNode(this, index, startOffset, sIndex)?.run {
- children += this
- }
+ children += mergedLeafNode(this, index, startOffset, sIndex)
}
}
index++
@@ -465,15 +474,12 @@ open class MarkdownParser(
return children
}
- private fun mergedLeafNode(nodes: List<ASTNode>, index: Int, startOffset: Int, sIndex: Int): LeafASTNode? {
+ private fun mergedLeafNode(nodes: List<ASTNode>, index: Int, startOffset: Int, sIndex: Int): LeafASTNode {
val endOffset = nodes[index].endOffset
- if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty()) {
- val type = if (nodes.subList(sIndex, index)
- .any { it.type == MarkdownTokenTypes.CODE_LINE }
- ) MarkdownTokenTypes.CODE_LINE else MarkdownTokenTypes.TEXT
- return LeafASTNode(type, startOffset, endOffset)
- }
- return null
+ val type = if (nodes.subList(sIndex, index)
+ .any { it.type == MarkdownTokenTypes.CODE_LINE }
+ ) MarkdownTokenTypes.CODE_LINE else MarkdownTokenTypes.TEXT
+ return LeafASTNode(type, startOffset, endOffset)
}
private fun String.transform() = this
diff --git a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
index ea87dce8..fed3f7eb 100644
--- a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
+++ b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
@@ -9,7 +9,6 @@ import org.intellij.markdown.flavours.gfm.GFMTokenTypes
import org.jetbrains.dokka.base.translators.parseWithNormalisedSpaces
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.doc.DocTag.Companion.contentTypeParam
-import java.lang.NullPointerException
object DocTagsFromIElementFactory {
@@ -40,7 +39,12 @@ object DocTagsFromIElementFactory {
body.orEmpty(),
children,
params
- ) else body?.parseWithNormalisedSpaces(renderWhiteCharactersAsSpaces = false).orEmpty()
+ ) else {
+ // corner case: there are only spaces between two Markdown nodes
+ val containsOnlySpaces = body?.isNotEmpty() == true && body.all { it.isWhitespace() }
+ if (containsOnlySpaces) Text(" ", children, params)
+ else body?.parseWithNormalisedSpaces(renderWhiteCharactersAsSpaces = false).orEmpty()
+ }
MarkdownTokenTypes.HORIZONTAL_RULE -> HorizontalRule
MarkdownTokenTypes.HARD_LINE_BREAK -> Br
GFMElementTypes.STRIKETHROUGH -> Strikethrough(children, params)
diff --git a/plugins/base/src/test/kotlin/markdown/ParserTest.kt b/plugins/base/src/test/kotlin/markdown/ParserTest.kt
index 3498f73f..8e813eba 100644
--- a/plugins/base/src/test/kotlin/markdown/ParserTest.kt
+++ b/plugins/base/src/test/kotlin/markdown/ParserTest.kt
@@ -2,16 +2,18 @@ package org.jetbrains.dokka.tests
import markdown.KDocTest
import org.intellij.markdown.MarkdownElementTypes
+import org.jetbrains.dokka.base.parsers.MarkdownParser
import org.jetbrains.dokka.model.doc.*
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
-import kotlin.test.assertTrue
class ParserTest : KDocTest() {
+ private fun parseMarkdownToDocNode(text: String) =
+ MarkdownParser( { null }, "").parseStringToDocNode(text)
+
@Test
fun `Simple text`() {
val kdoc = """
@@ -1519,5 +1521,52 @@ class ParserTest : KDocTest() {
)
executeTest(kdoc, expectedDocumentationNode)
}
+
+ @Test
+ fun `code with backticks`() {
+ val kdoc = "` `` ` ` ``` `"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ CustomDocTag(
+ listOf(
+ P(
+ listOf(
+ CodeInline(listOf(Text("`` "))),
+ Text(" "),
+ CodeInline(listOf(Text("``` "))),
+ )
+ )
+ ), name = MarkdownElementTypes.MARKDOWN_FILE.name
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `should filter spaces in markdown`() {
+ val markdown = """
+ | sdsdds f,*()hhh
+ | dssd hf
+ |
+ | sdsdsds sdd
+ |
+ |
+ | eweww
+ |
+ |
+ |
+ """.trimMargin()
+ val actualDocumentationNode = parseMarkdownToDocNode(markdown).children
+ val expectedDocumentationNode = listOf(
+ P(listOf(Text(" sdsdds f,*()hhh dssd hf"))),
+ P(listOf(Text(" sdsdsds sdd"))),
+ P(listOf(Text(" eweww ")))
+ )
+ print(expectedDocumentationNode)
+ assertEquals(actualDocumentationNode, expectedDocumentationNode)
+ }
}
diff --git a/plugins/base/src/test/kotlin/model/CommentTest.kt b/plugins/base/src/test/kotlin/model/CommentTest.kt
index 6a7b2d89..0742587a 100644
--- a/plugins/base/src/test/kotlin/model/CommentTest.kt
+++ b/plugins/base/src/test/kotlin/model/CommentTest.kt
@@ -251,4 +251,20 @@ class CommentTest : AbstractModelTest("/src/main/kotlin/comment/Test.kt", "comme
}
}
}
+
+ @Test
+ fun `should be space between Markdown nodes`() {
+ inlineModelTest(
+ """
+ |/**
+ | * Rotates paths by `amount` **radians** around (`x`, `y`).
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Rotates paths by amount radians around (x, y).\n"
+ }
+ }
+ }
}