aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorKamil Doległo <kamilok1965@interia.pl>2019-10-31 23:13:09 +0100
committerKamil Doległo <kamilok1965@interia.pl>2019-10-31 23:13:36 +0100
commit41b9edd65e58735e69f29369942ef953baadeb3b (patch)
tree97979272908bc99fb38f1354e4de589b7b556e21 /core/src
parent5f36bdd75e32743f54193aa8eff8cd5185b3cf67 (diff)
downloaddokka-41b9edd65e58735e69f29369942ef953baadeb3b.tar.gz
dokka-41b9edd65e58735e69f29369942ef953baadeb3b.tar.bz2
dokka-41b9edd65e58735e69f29369942ef953baadeb3b.zip
Add markdown content builder
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/kotlin/pages/ContentNodes.kt41
-rw-r--r--core/src/main/kotlin/pages/NewContentBuilder.kt181
-rw-r--r--core/src/test/kotlin/markdownParser/MarkdownParserTest.kt10
3 files changed, 139 insertions, 93 deletions
diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt
index afb81995..2dffbb17 100644
--- a/core/src/main/kotlin/pages/ContentNodes.kt
+++ b/core/src/main/kotlin/pages/ContentNodes.kt
@@ -9,8 +9,8 @@ interface ContentNode {
/** Comment consisting of parts, eg. [ContentText]s, [ContentLink]s and so on */
data class ContentComment(val parts: List<ContentNode>,
- override val platforms: List<PlatformData>,
- override val annotations: List<Annotation> = emptyList()
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
): ContentNode
/** Simple text */
@@ -20,24 +20,24 @@ data class ContentText(val text: String,
): ContentNode
///** Headers */ TODO for next iteration
-data class ContentHeader(val text: String,
+data class ContentHeader(val items: List<ContentNode>,
val level: Int,
- override val platforms: List<PlatformData>,
- override val annotations: List<Annotation> = emptyList()
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
): ContentNode
/** Lists */
data class ContentList(val items: List<ContentNode>,
- val ordered: Boolean,
- override val platforms: List<PlatformData>,
- override val annotations: List<Annotation> = emptyList()
+ val ordered: Boolean,
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
): ContentNode
/** Styled elements, eg. bold, strikethrough, emphasis and so on **/
data class ContentStyle(val items: List<ContentNode>,
- val style: ContentNode,
- override val platforms: List<PlatformData>,
- override val annotations: List<Annotation> = emptyList()
+ val style: IStyle,
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
): ContentNode
/** Code blocks */
@@ -53,13 +53,20 @@ data class ContentSymbol(val parts: List<ContentNode>,
override val annotations: List<Annotation> = emptyList()
): ContentNode
-/** All links that have te be resolved */
+/** All links to classes, packages, etc. that have te be resolved */
data class ContentLink(val text: String,
val address: DRI,
override val platforms: List<PlatformData>,
override val annotations: List<Annotation> = emptyList()
): ContentNode
+/** All links that do not need to be resolved */
+data class ContentResolvedLink(val text: String,
+ val address: String,
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
+): ContentNode
+
/** Blocks of [ContentNode]s with name, eg. Functions, Types, Properties, etc. */
data class ContentBlock(val name: String,
val children: List<ContentNode>,
@@ -69,9 +76,15 @@ data class ContentBlock(val name: String,
/** Logical grouping of [ContentNode]s, eg. [ContentLink], [ContentText] and [ContentSymbol] for one entity */
data class ContentGroup(val children: List<ContentNode>,
- override val platforms: List<PlatformData>,
- override val annotations: List<Annotation> = emptyList()
+ override val platforms: List<PlatformData>,
+ override val annotations: List<Annotation> = emptyList()
): ContentNode
/** All annotations */
data class Annotation(val name: String)
+
+interface IStyle
+
+enum class Style: IStyle {
+ Emphasis, Strong, Paragraph
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/pages/NewContentBuilder.kt b/core/src/main/kotlin/pages/NewContentBuilder.kt
index 05b649d1..89c509ea 100644
--- a/core/src/main/kotlin/pages/NewContentBuilder.kt
+++ b/core/src/main/kotlin/pages/NewContentBuilder.kt
@@ -4,24 +4,37 @@ import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.MarkdownTokenTypes
import org.jetbrains.dokka.MarkdownNode
-fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<ContentNode> {
+class NewContentBuilder {
+ fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<ContentNode> {
// println(tree.toTestString())
- fun buildChildren(node: MarkdownNode) = node.children.flatMap{ buildContent(it, platforms)}
-
- return when (node.type) {
- MarkdownElementTypes.ATX_1 -> ContentHeader(node.text, 1, platforms) // TODO Header levels: ??
- MarkdownElementTypes.ATX_2 -> ContentHeader("", 2, platforms)
- MarkdownElementTypes.ATX_3 -> ContentHeader("", 3, platforms)
- MarkdownElementTypes.ATX_4 -> ContentHeader("", 4, platforms)
- MarkdownElementTypes.ATX_5 -> ContentHeader("", 5, platforms)
- MarkdownElementTypes.ATX_6 -> ContentHeader("", 6, platforms)
- MarkdownElementTypes.UNORDERED_LIST -> ContentList(buildChildren(node), false, platforms)
- MarkdownElementTypes.ORDERED_LIST -> ContentList(buildChildren(node), true, platforms)
- MarkdownElementTypes.LIST_ITEM -> TODO()
- MarkdownElementTypes.EMPH -> ContentStyle(buildChildren(node), ContentText("", platforms), platforms) // TODO
- MarkdownElementTypes.STRONG -> ContentStyle(buildChildren(node), ContentText("", platforms), platforms) // TODO
- MarkdownElementTypes.CODE_SPAN -> TODO()
+ fun buildChildren(node: MarkdownNode) = node.children.flatMap { buildContent(it, platforms) }.coalesceText()
+
+ return when (node.type) {
+ MarkdownElementTypes.ATX_1 -> listOf(ContentHeader(buildChildren(node), 1, platforms))
+ MarkdownElementTypes.ATX_2 -> listOf(ContentHeader(buildChildren(node), 2, platforms))
+ MarkdownElementTypes.ATX_3 -> listOf(ContentHeader(buildChildren(node), 3, platforms))
+ MarkdownElementTypes.ATX_4 -> listOf(ContentHeader(buildChildren(node), 4, platforms))
+ MarkdownElementTypes.ATX_5 -> listOf(ContentHeader(buildChildren(node), 5, platforms))
+ MarkdownElementTypes.ATX_6 -> listOf(ContentHeader(buildChildren(node), 6, platforms))
+ MarkdownElementTypes.UNORDERED_LIST -> listOf(ContentList(buildChildren(node), false, platforms))
+ MarkdownElementTypes.ORDERED_LIST -> listOf(ContentList(buildChildren(node), true, platforms))
+ MarkdownElementTypes.LIST_ITEM -> TODO()
+ MarkdownElementTypes.EMPH -> listOf(
+ ContentStyle(
+ buildChildren(node),
+ Style.Emphasis,
+ platforms
+ )
+ )// TODO
+ MarkdownElementTypes.STRONG -> listOf(
+ ContentStyle(
+ buildChildren(node),
+ Style.Strong,
+ platforms
+ )
+ ) // TODO
+ MarkdownElementTypes.CODE_SPAN -> TODO()
// val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text
// if (startDelimiter != null) {
// val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter)
@@ -29,14 +42,14 @@ fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<Conten
// parent.append(codeSpan)
// }
- MarkdownElementTypes.CODE_BLOCK,
- MarkdownElementTypes.CODE_FENCE -> {
- val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: ""
- ContentCode(buildChildren(node).toString(), language, platforms) // TODO
- }
- MarkdownElementTypes.PARAGRAPH -> ContentText(buildChildren(node).toString(), platforms) // TODO
+ MarkdownElementTypes.CODE_BLOCK,
+ MarkdownElementTypes.CODE_FENCE -> {
+ val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: ""
+ listOf(ContentCode(buildChildren(node).toString(), language, platforms)) // TODO
+ }
+ MarkdownElementTypes.PARAGRAPH -> listOf(ContentStyle(buildChildren(node), Style.Paragraph, platforms)) // TODO
- MarkdownElementTypes.INLINE_LINK -> {
+ MarkdownElementTypes.INLINE_LINK -> {
// val linkTextNode = node.child(MarkdownElementTypes.LINK_TEXT)
// val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)
// if (linkTextNode != null) {
@@ -50,12 +63,12 @@ fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<Conten
// parent.append(link)
// }
// }
- //TODO: Linking!!!
+ //TODO: Linking!!!
// ContentLink()
- TODO()
- }
- MarkdownElementTypes.SHORT_REFERENCE_LINK,
- MarkdownElementTypes.FULL_REFERENCE_LINK -> {
+ TODO()
+ }
+ MarkdownElementTypes.SHORT_REFERENCE_LINK,
+ MarkdownElementTypes.FULL_REFERENCE_LINK -> {
// val labelElement = node.child(MarkdownElementTypes.LINK_LABEL)
// if (labelElement != null) {
// val linkInfo = linkResolver.getLinkInfo(labelElement.text)
@@ -72,36 +85,36 @@ fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<Conten
// }
// parent.append(link)
// }
- TODO()
- }
- MarkdownTokenTypes.WHITE_SPACE -> {
- // Don't append first space if start of header (it is added during formatting later)
- // v
- // #### Some Heading
+ TODO()
+ }
+ MarkdownTokenTypes.WHITE_SPACE -> {
+ // Don't append first space if start of header (it is added during formatting later)
+ // v
+ // #### Some Heading
// if (nodeStack.peek() !is ContentHeading || node.parent?.children?.first() != node) {
// parent.append(ContentText(node.text))
// }
- ContentText(" ", platforms)
- }
- MarkdownTokenTypes.EOL -> {
+ listOf(ContentText(" ", platforms))
+ }
+ MarkdownTokenTypes.EOL -> {
// if ((keepEol(nodeStack.peek()) && node.parent?.children?.last() != node) ||
// // Keep extra blank lines when processing lists (affects Markdown formatting)
// (processingList(nodeStack.peek()) && node.previous?.type == MarkdownTokenTypes.EOL)) {
// parent.append(ContentText(node.text))
// }
- ContentText("\n", platforms) // TODO?
- }
+ emptyList()
+ }
- MarkdownTokenTypes.CODE_LINE -> {
- ContentText(node.text, platforms) // TODO check
+ MarkdownTokenTypes.CODE_LINE -> {
+ listOf(ContentText(node.text, platforms)) // TODO check
// if (parent is ContentBlockCode) {
// parent.append(content)
// } else {
// parent.append(ContentBlockCode().apply { append(content) })
// }
- }
+ }
- MarkdownTokenTypes.TEXT ->
+ MarkdownTokenTypes.TEXT ->
// fun createEntityOrText(text: String): ContentNode {
// if (text == "&amp;" || text == "&quot;" || text == "&lt;" || text == "&gt;") {
// return ContentEntity(text)
@@ -117,40 +130,64 @@ fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<Conten
// }
//
// parent.append(createEntityOrText(node.text))
- ContentText(node.text, platforms) // TODO
+ listOf(ContentText(node.text, platforms)) // TODO
- MarkdownTokenTypes.EMPH ->
+ MarkdownTokenTypes.EMPH ->
// val parentNodeType = node.parent?.type
// if (parentNodeType != MarkdownElementTypes.EMPH && parentNodeType != MarkdownElementTypes.STRONG) {
// parent.append(ContentText(node.text))
// }
- ContentStyle(buildChildren(node), ContentText("", platforms), platforms) // TODO
-
-
- MarkdownTokenTypes.COLON,
- MarkdownTokenTypes.SINGLE_QUOTE,
- MarkdownTokenTypes.DOUBLE_QUOTE,
- MarkdownTokenTypes.LT,
- MarkdownTokenTypes.GT,
- MarkdownTokenTypes.LPAREN,
- MarkdownTokenTypes.RPAREN,
- MarkdownTokenTypes.LBRACKET,
- MarkdownTokenTypes.RBRACKET,
- MarkdownTokenTypes.EXCLAMATION_MARK,
- MarkdownTokenTypes.BACKTICK,
- MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
- ContentText(node.text, platforms)
+ listOf(ContentStyle(buildChildren(node), Style.Emphasis, platforms)) // TODO
+
+ MarkdownTokenTypes.COLON,
+ MarkdownTokenTypes.SINGLE_QUOTE,
+ MarkdownTokenTypes.DOUBLE_QUOTE,
+ MarkdownTokenTypes.LT,
+ MarkdownTokenTypes.GT,
+ MarkdownTokenTypes.LPAREN,
+ MarkdownTokenTypes.RPAREN,
+ MarkdownTokenTypes.LBRACKET,
+ MarkdownTokenTypes.RBRACKET,
+ MarkdownTokenTypes.EXCLAMATION_MARK,
+ MarkdownTokenTypes.BACKTICK,
+ MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
+ listOf(ContentText(node.text, platforms))
+ }
+
+ MarkdownElementTypes.LINK_DEFINITION -> TODO()
+
+ MarkdownTokenTypes.EMAIL_AUTOLINK ->
+ listOf(ContentResolvedLink(node.text, "mailto:${node.text}", platforms))
+
+ else -> buildChildren(node)
}
-
- MarkdownElementTypes.LINK_DEFINITION -> TODO()
-
-
- MarkdownTokenTypes.EMAIL_AUTOLINK ->
- ContentText(node.text, platforms) // TODO: create new ContentType for email to create mailto: links
-
-
- else -> ContentText("", platforms)
-
- }.let {listOf(it)}
+ }
+
+ private fun Collection<ContentNode>.coalesceText() =
+ this
+ .sliceWhen { prev, next -> prev::class != next::class }
+ .flatMap { nodes ->
+ when (nodes.first()) {
+ is ContentText -> listOf(ContentText(nodes.joinToString("") { (it as ContentText).text }, nodes.first().platforms))
+ else -> nodes
+ }
+ }
+}
+
+fun <T> Collection<T>.sliceWhen(predicate: (before: T, after: T)->Boolean): Collection<Collection<T>> {
+ val newCollection = mutableListOf<Collection<T>>()
+ var currentSlice = mutableListOf<T>()
+ for ((prev, next) in this.windowed(2, 1, false)) {
+ currentSlice.add(prev)
+ if(predicate(prev, next)) {
+ newCollection.add(currentSlice)
+ currentSlice = mutableListOf<T>()
+ }
+ }
+ if(this.isNotEmpty()) {
+ currentSlice.add(this.last())
+ newCollection.add(currentSlice)
+ }
+ return newCollection
} \ No newline at end of file
diff --git a/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt b/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt
index 466d78a6..70554045 100644
--- a/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt
+++ b/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt
@@ -1,12 +1,8 @@
package org.jetbrains.dokka.tests.markdownParser
-import junit.framework.Assert.assertEquals
-import junit.framework.Assert.assertTrue
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.buildContent
+import org.jetbrains.dokka.pages.NewContentBuilder
import org.jetbrains.dokka.parseMarkdown
-import org.jetbrains.dokka.resolvers.ExternalLocationProvider
+import org.junit.Assert.assertTrue
import org.junit.Test
@@ -20,7 +16,7 @@ class MarkdownParserTest {
let's say there are some parentheses, like ( and )
""".trimIndent()
val node = parseMarkdown(markdown)
- val content = buildContent(node, emptyList())
+ val content = NewContentBuilder().buildContent(node, emptyList())
assertTrue(content.isNotEmpty())
}