diff options
Diffstat (limited to 'plugins/gfm')
8 files changed, 1046 insertions, 0 deletions
diff --git a/plugins/gfm/build.gradle.kts b/plugins/gfm/build.gradle.kts new file mode 100644 index 00000000..3f69043d --- /dev/null +++ b/plugins/gfm/build.gradle.kts @@ -0,0 +1,11 @@ +import org.jetbrains.registerDokkaArtifactPublication + +dependencies { + implementation(project(":plugins:base")) + testImplementation(project(":plugins:base")) + testImplementation(project(":plugins:base:test-utils")) +} + +registerDokkaArtifactPublication("gfmPlugin") { + artifactId = "gfm-plugin" +} diff --git a/plugins/gfm/src/main/kotlin/GfmPlugin.kt b/plugins/gfm/src/main/kotlin/GfmPlugin.kt new file mode 100644 index 00000000..dcc9c0a6 --- /dev/null +++ b/plugins/gfm/src/main/kotlin/GfmPlugin.kt @@ -0,0 +1,345 @@ +package org.jetbrains.dokka.gfm + +import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.base.renderers.DefaultRenderer +import org.jetbrains.dokka.base.renderers.PackageListCreator +import org.jetbrains.dokka.base.renderers.RootCreator +import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProvider +import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory +import org.jetbrains.dokka.pages.* +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.plugability.DokkaPlugin +import org.jetbrains.dokka.plugability.plugin +import org.jetbrains.dokka.plugability.query +import org.jetbrains.dokka.transformers.pages.PageTransformer + +class GfmPlugin : DokkaPlugin() { + + val gfmPreprocessors by extensionPoint<PageTransformer>() + + private val dokkaBase by lazy { plugin<DokkaBase>() } + + val renderer by extending { + (CoreExtensions.renderer + providing { CommonmarkRenderer(it) } + override dokkaBase.htmlRenderer) + } + + val locationProvider by extending { + (dokkaBase.locationProviderFactory + providing { MarkdownLocationProviderFactory(it) } + override dokkaBase.locationProvider) + } + + val rootCreator by extending { + gfmPreprocessors with RootCreator + } + + val packageListCreator by extending { + (gfmPreprocessors + providing { PackageListCreator(it, "gfm", "md") } + order { after(rootCreator) }) + } +} + +open class CommonmarkRenderer( + context: DokkaContext +) : DefaultRenderer<StringBuilder>(context) { + + override val preprocessors = context.plugin<GfmPlugin>().query { gfmPreprocessors } + + override fun StringBuilder.wrapGroup( + node: ContentGroup, + pageContext: ContentPage, + childrenCallback: StringBuilder.() -> Unit + ) { + return when { + node.hasStyle(TextStyle.Block) -> { + childrenCallback() + buildNewLine() + } + node.hasStyle(TextStyle.Paragraph) -> { + buildParagraph() + childrenCallback() + buildParagraph() + } + else -> childrenCallback() + } + } + + override fun StringBuilder.buildHeader(level: Int, node: ContentHeader, content: StringBuilder.() -> Unit) { + buildParagraph() + append("#".repeat(level) + " ") + content() + buildNewLine() + } + + override fun StringBuilder.buildLink(address: String, content: StringBuilder.() -> Unit) { + append("[") + content() + append("]($address)") + } + + override fun StringBuilder.buildList( + node: ContentList, + pageContext: ContentPage, + sourceSetRestriction: Set<DokkaSourceSet>? + ) { + buildListLevel(node, pageContext) + } + + private fun StringBuilder.buildListItem(items: List<ContentNode>, pageContext: ContentPage) { + items.forEach { + if (it is ContentList) { + buildList(it, pageContext) + } else { + append("<li>") + append(buildString { it.build(this, pageContext, it.sourceSets) }.trim()) + append("</li>") + } + } + } + + private fun StringBuilder.buildListLevel(node: ContentList, pageContext: ContentPage) { + if (node.ordered) { + append("<ol>") + buildListItem(node.children, pageContext) + append("</ol>") + } else { + append("<ul>") + buildListItem(node.children, pageContext) + append("</ul>") + } + } + + override fun StringBuilder.buildNewLine() { + append(" \n") + } + + private fun StringBuilder.buildParagraph() { + append("\n\n") + } + + override fun StringBuilder.buildPlatformDependent( + content: PlatformHintedContent, + pageContext: ContentPage, + sourceSetRestriction: Set<DokkaSourceSet>? + ) { + buildPlatformDependentItem(content.inner, content.sourceSets, pageContext) + } + + private fun StringBuilder.buildPlatformDependentItem( + content: ContentNode, + sourceSets: Set<DokkaSourceSet>, + pageContext: ContentPage, + ) { + if (content is ContentGroup && content.children.firstOrNull { it is ContentTable } != null) { + buildContentNode(content, pageContext, sourceSets) + } else { + val distinct = sourceSets.map { + it to buildString { buildContentNode(content, pageContext, setOf(it)) } + }.groupBy(Pair<DokkaSourceSet, String>::second, Pair<DokkaSourceSet, String>::first) + + distinct.filter { it.key.isNotBlank() }.forEach { (text, platforms) -> + append(" ") + buildSourceSetTags(platforms.toSet()) + append(" $text ") + buildNewLine() + } + } + } + + override fun StringBuilder.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage) { + append("Resource") + } + + override fun StringBuilder.buildTable( + node: ContentTable, + pageContext: ContentPage, + sourceSetRestriction: Set<DokkaSourceSet>? + ) { + buildNewLine() + if (node.dci.kind == ContentKind.Sample || node.dci.kind == ContentKind.Parameters) { + node.sourceSets.forEach { sourcesetData -> + append(sourcesetData.displayName) + buildNewLine() + buildTable( + node.copy( + children = node.children.filter { it.sourceSets.contains(sourcesetData) }, + dci = node.dci.copy(kind = ContentKind.Main) + ), pageContext, sourceSetRestriction + ) + buildNewLine() + } + } else { + val size = node.header.size + + if (node.header.isNotEmpty()) { + append("| ") + node.header.forEach { + it.children.forEach { + append(" ") + it.build(this, pageContext, it.sourceSets) + } + append("| ") + } + append("\n") + } else { + append("| ".repeat(size)) + if (size > 0) append("|\n") + } + + append("|---".repeat(size)) + if (size > 0) append("|\n") + + node.children.forEach { + val builder = StringBuilder() + it.children.forEach { + builder.append("| ") + builder.append(buildString { it.build(this, pageContext) }.replace(Regex("#+ "), "") ) // Workaround for headers inside tables + } + append(builder.toString().withEntersAsHtml()) + append(" | ".repeat(size - it.children.size)) + append("\n") + } + } + } + + override fun StringBuilder.buildText(textNode: ContentText) { + if(textNode.text.isNotBlank()) { + val decorators = decorators(textNode.style) + append(textNode.text.takeWhile { it == ' ' } ) + append(decorators) + append(textNode.text.trim()) + append(decorators.reversed()) + append(textNode.text.takeLastWhile { it == ' ' }) + } + } + + override fun StringBuilder.buildNavigation(page: PageNode) { + locationProvider.ancestors(page).asReversed().forEach { node -> + append("/") + if (node.isNavigable) buildLink(node, page) + else append(node.name) + } + buildParagraph() + } + + override fun buildPage(page: ContentPage, content: (StringBuilder, ContentPage) -> Unit): String = + buildString { + content(this, page) + } + + override fun buildError(node: ContentNode) { + context.logger.warn("Markdown renderer has encountered problem. The unmatched node is $node") + } + + override fun StringBuilder.buildDivergent(node: ContentDivergentGroup, pageContext: ContentPage) { + + val distinct = + node.groupDivergentInstances(pageContext, { instance, contentPage, sourceSet -> + instance.before?.let { before -> + buildString { buildContentNode(before, pageContext, setOf(sourceSet)) } + } ?: "" + }, { instance, contentPage, sourceSet -> + instance.after?.let { after -> + buildString { buildContentNode(after, pageContext, setOf(sourceSet)) } + } ?: "" + }) + + distinct.values.forEach { entry -> + val (instance, sourceSets) = entry.getInstanceAndSourceSets() + + buildSourceSetTags(sourceSets) + buildNewLine() + instance.before?.let { + append("Brief description") + buildNewLine() + buildContentNode(it, pageContext, setOf(sourceSets.first())) // It's workaround to render content only once + buildNewLine() + } + + append("Content") + buildNewLine() + entry.groupBy { buildString { buildContentNode(it.first.divergent, pageContext, setOf(it.second)) } } + .values.forEach { innerEntry -> + val (innerInstance, innerSourceSets) = innerEntry.getInstanceAndSourceSets() + if(sourceSets.size > 1) { + buildSourceSetTags(innerSourceSets) + buildNewLine() + } + innerInstance.divergent.build(this@buildDivergent, pageContext, setOf(innerSourceSets.first())) // It's workaround to render content only once + buildNewLine() + } + + instance.after?.let { + append("More info") + buildNewLine() + buildContentNode(it, pageContext, setOf(sourceSets.first())) // It's workaround to render content only once + buildNewLine() + } + + buildParagraph() + } + } + + private fun decorators(styles: Set<Style>) = buildString { + styles.forEach { + when (it) { + TextStyle.Bold -> append("**") + TextStyle.Italic -> append("*") + TextStyle.Strong -> append("**") + TextStyle.Strikethrough -> append("~~") + else -> Unit + } + } + } + + private val PageNode.isNavigable: Boolean + get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing + + private fun StringBuilder.buildLink(to: PageNode, from: PageNode) = + buildLink(locationProvider.resolve(to, from)) { + append(to.name) + } + + override suspend fun renderPage(page: PageNode) { + val path by lazy { locationProvider.resolve(page, skipExtension = true) } + when (page) { + is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".md") + is RendererSpecificPage -> when (val strategy = page.strategy) { + is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path) + is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "") + is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".md") + RenderingStrategy.DoNothing -> Unit + } + else -> throw AssertionError( + "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content" + ) + } + } + + private fun String.withEntersAsHtml(): String = replace("\n", "<br>") + + private fun List<Pair<ContentDivergentInstance, DokkaSourceSet>>.getInstanceAndSourceSets() = this.let { Pair(it.first().first, it.map { it.second }.toSet()) } + + private fun StringBuilder.buildSourceSetTags(sourceSets: Set<DokkaSourceSet>) = + append(sourceSets.joinToString(prefix = "[", postfix = "]") { it.displayName }) +} + +class MarkdownLocationProviderFactory(val context: DokkaContext) : LocationProviderFactory { + + override fun getLocationProvider(pageNode: RootPageNode) = MarkdownLocationProvider(pageNode, context) +} + +class MarkdownLocationProvider( + pageGraphRoot: RootPageNode, + dokkaContext: DokkaContext +) : DefaultLocationProvider( + pageGraphRoot, + dokkaContext +) { + override val extension = ".md" +} diff --git a/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin new file mode 100644 index 00000000..ae291d68 --- /dev/null +++ b/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin @@ -0,0 +1 @@ +org.jetbrains.dokka.gfm.GfmPlugin diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt new file mode 100644 index 00000000..0c8b942e --- /dev/null +++ b/plugins/gfm/src/test/kotlin/renderers/gfm/DivergentTest.kt @@ -0,0 +1,374 @@ +package renderers.gfm + +import org.jetbrains.dokka.DokkaSourceSetID +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.SourceRootImpl +import org.jetbrains.dokka.gfm.CommonmarkRenderer +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.pages.ContentDivergentGroup +import org.junit.jupiter.api.Test +import renderers.defaultSourceSet +import renderers.TestPage + +class DivergentTest : GfmRenderingOnlyTestBase() { + private val js = defaultSourceSet.copy( + "root", + "js", + DokkaSourceSetID("root", "js"), + analysisPlatform = Platform.js, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + private val jvm = defaultSourceSet.copy( + "root", + "jvm", + DokkaSourceSetID("root", "jvm"), + analysisPlatform = Platform.jvm, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + private val native = defaultSourceSet.copy( + "root", + "native", + DokkaSourceSetID("root", "native"), + analysisPlatform = Platform.native, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + + @Test + fun simpleWrappingCase() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("a") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[js] \nContent \na \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun noPlatformHintCase() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test"), implicitlySourceSetHinted = false) { + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("a") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[js] \nContent \na \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentBetweenSourceSets() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("a") + } + } + instance(setOf(DRI("test", "Test")), setOf(jvm)) { + divergent { + text("b") + } + } + instance(setOf(DRI("test", "Test")), setOf(native)) { + divergent { + text("c") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[js, jvm, native] \nContent \n[js] \na \n[jvm] \nb \n[native] \nc \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentInOneSourceSet() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("a") + } + } + instance(setOf(DRI("test", "Test2")), setOf(js)) { + divergent { + text("b") + } + } + instance(setOf(DRI("test", "Test3")), setOf(js)) { + divergent { + text("c") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[js] \nContent \na \nb \nc \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentInAndBetweenSourceSets() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + divergent { + text("a") + } + } + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("b") + } + } + instance(setOf(DRI("test", "Test")), setOf(jvm)) { + divergent { + text("c") + } + } + instance(setOf(DRI("test", "Test2")), setOf(js)) { + divergent { + text("d") + } + } + instance(setOf(DRI("test", "Test3")), setOf(native)) { + divergent { + text("e") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native, js, jvm] \nContent \n[native] \na \n[js] \nb \n[jvm] \nc \n[js] \nd \n[native] \ne \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentInAndBetweenSourceSetsWithGrouping() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + divergent { + text("a") + } + after { + text("a+") + } + } + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("b") + } + after { + text("bd+") + } + } + instance(setOf(DRI("test", "Test")), setOf(jvm)) { + divergent { + text("c") + } + } + instance(setOf(DRI("test", "Test2")), setOf(js)) { + divergent { + text("d") + } + after { + text("bd+") + } + } + instance(setOf(DRI("test", "Test3")), setOf(native)) { + divergent { + text("e") + } + after { + text("e+") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nContent \na \nMore info \na+ \n\n\n[js] \nContent \nb \nd \nMore info \nbd+ \n\n\n[jvm] \nContent \nc \n\n\n[native] \nContent \ne \nMore info \ne+ \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentSameBefore() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + before { + text("ab-") + } + divergent { + text("a") + } + } + instance(setOf(DRI("test", "Test2")), setOf(native)) { + before { + text("ab-") + } + divergent { + text("b") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nBrief description \nab- \nContent \na \nb \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentSameAfter() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + divergent { + text("a") + } + after { + text("ab+") + } + } + instance(setOf(DRI("test", "Test2")), setOf(native)) { + divergent { + text("b") + } + after { + text("ab+") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nContent \na \nb \nMore info \nab+ \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentGroupedByBeforeAndAfter() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + before { + text("ab-") + } + divergent { + text("a") + } + after { + text("ab+") + } + } + instance(setOf(DRI("test", "Test2")), setOf(native)) { + before { + text("ab-") + } + divergent { + text("b") + } + after { + text("ab+") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nBrief description \nab- \nContent \na \nb \nMore info \nab+ \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentDifferentBeforeAndAfter() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + before { + text("a-") + } + divergent { + text("a") + } + after { + text("ab+") + } + } + instance(setOf(DRI("test", "Test2")), setOf(native)) { + before { + text("b-") + } + divergent { + text("b") + } + after { + text("ab+") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nBrief description \na- \nContent \na \nMore info \nab+ \n\n\n[native] \nBrief description \nb- \nContent \nb \nMore info \nab+ \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun divergentInAndBetweenSourceSetsWithGroupingAncCommonParts() { + val page = TestPage { + divergentGroup(ContentDivergentGroup.GroupID("test")) { + instance(setOf(DRI("test", "Test")), setOf(native)) { + divergent { + text("a") + } + after { + text("a+") + } + } + instance(setOf(DRI("test", "Test")), setOf(js)) { + divergent { + text("b") + } + after { + text("bd+") + } + } + instance(setOf(DRI("test", "Test")), setOf(jvm)) { + divergent { + text("c") + } + after { + text("bd+") + } + } + instance(setOf(DRI("test", "Test2")), setOf(js)) { + divergent { + text("d") + } + after { + text("bd+") + } + } + instance(setOf(DRI("test", "Test3")), setOf(native)) { + divergent { + text("e") + } + after { + text("e+") + } + } + } + } + val expect = "//[testPage](test-page.md)\n\n[native] \nContent \na \nMore info \na+ \n\n\n[js, jvm] \nContent \n[js] \nb \n[jvm] \nc \n[js] \nd \nMore info \nbd+ \n\n\n[native] \nContent \ne \nMore info \ne+ \n\n\n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } +}
\ No newline at end of file diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt new file mode 100644 index 00000000..6d0dd3a6 --- /dev/null +++ b/plugins/gfm/src/test/kotlin/renderers/gfm/GfmRenderingOnlyTestBase.kt @@ -0,0 +1,32 @@ +package renderers.gfm + +import org.jetbrains.dokka.DokkaConfigurationImpl +import org.jetbrains.dokka.gfm.GfmPlugin +import org.jetbrains.dokka.gfm.MarkdownLocationProviderFactory +import org.jetbrains.dokka.testApi.context.MockContext +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.base.renderers.RootCreator +import org.jetbrains.dokka.base.resolvers.external.DokkaExternalLocationProviderFactory +import org.jetbrains.dokka.base.resolvers.external.JavadocExternalLocationProviderFactory +import renderers.RenderingOnlyTestBase +import utils.TestOutputWriter + +abstract class GfmRenderingOnlyTestBase : RenderingOnlyTestBase<String>() { + + val files = TestOutputWriter() + override val context = MockContext( + DokkaBase().outputWriter to { _ -> files }, + DokkaBase().locationProviderFactory to ::MarkdownLocationProviderFactory, + DokkaBase().externalLocationProviderFactory to { ::JavadocExternalLocationProviderFactory }, + DokkaBase().externalLocationProviderFactory to { ::DokkaExternalLocationProviderFactory }, + GfmPlugin().gfmPreprocessors to { _ -> RootCreator }, + + testConfiguration = DokkaConfigurationImpl( + "", null, false, emptyList(), emptyList(), emptyMap(), emptyList(), false + ) + ) + + override val renderedContent: String by lazy { + files.contents.getValue("test-page.md") + } +} diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/GroupWrappingTest.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/GroupWrappingTest.kt new file mode 100644 index 00000000..42839282 --- /dev/null +++ b/plugins/gfm/src/test/kotlin/renderers/gfm/GroupWrappingTest.kt @@ -0,0 +1,76 @@ +package renderers.gfm + +import org.jetbrains.dokka.gfm.CommonmarkRenderer +import org.jetbrains.dokka.pages.TextStyle +import org.junit.jupiter.api.Test +import renderers.* + +class GroupWrappingTest : GfmRenderingOnlyTestBase() { + + @Test + fun notWrapped() { + val page = TestPage { + group { + text("a") + text("b") + } + text("c") + } + + CommonmarkRenderer(context).render(page) + + assert(renderedContent == "//[testPage](test-page.md)\n\nabc") + } + + @Test + fun paragraphWrapped() { + val page = TestPage { + group(styles = setOf(TextStyle.Paragraph)) { + text("a") + text("b") + } + text("c") + } + + CommonmarkRenderer(context).render(page) + + assert(renderedContent == "//[testPage](test-page.md)\n\n\n\nab\n\nc") + } + + @Test + fun blockWrapped() { + val page = TestPage { + group(styles = setOf(TextStyle.Block)) { + text("a") + text("b") + } + text("c") + } + + CommonmarkRenderer(context).render(page) + + assert(renderedContent == "//[testPage](test-page.md)\n\nab \nc") + } + + @Test + fun nested() { + val page = TestPage { + group(styles = setOf(TextStyle.Block)) { + text("a") + group(styles = setOf(TextStyle.Block)) { + group(styles = setOf(TextStyle.Block)) { + text("b") + text("c") + } + } + text("d") + } + } + + CommonmarkRenderer(context).render(page) + +// renderedContent.match(Div("a", Div(Div("bc")), "d")) + assert(renderedContent == "//[testPage](test-page.md)\n\nabc \n \nd \n") + } + +} diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/SimpleElementsTest.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/SimpleElementsTest.kt new file mode 100644 index 00000000..7464c079 --- /dev/null +++ b/plugins/gfm/src/test/kotlin/renderers/gfm/SimpleElementsTest.kt @@ -0,0 +1,70 @@ +package renderers.gfm + +import org.jetbrains.dokka.gfm.CommonmarkRenderer +import org.junit.jupiter.api.Test +import renderers.TestPage +import org.jetbrains.dokka.base.translators.documentables.* +import org.jetbrains.dokka.pages.TextStyle + +class SimpleElementsTest : GfmRenderingOnlyTestBase() { + + @Test + fun header() { + val page = TestPage { + header(1, "The Hobbit or There and Back Again") + } + val expect = "//[testPage](test-page.md)\n\n\n\n# The Hobbit or There and Back Again \n" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun link() { + val page = TestPage { + link("They are not all accounted for, the lost Seeing Stones.", "http://www.google.com") + } + val expect = "//[testPage](test-page.md)\n\n[They are not all accounted for, the lost Seeing Stones.](http://www.google.com)" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun bold() { + val page = TestPage { + text("That there’s some good in this world, Mr. Frodo… and it’s worth fighting for.", styles = setOf(TextStyle.Bold)) + } + val expect = "//[testPage](test-page.md)\n\n**That there’s some good in this world, Mr. Frodo… and it’s worth fighting for.**" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun italic() { + val page = TestPage { + text("Even the smallest person can change the course of the future.", styles = setOf(TextStyle.Italic)) + } + val expect = "//[testPage](test-page.md)\n\n*Even the smallest person can change the course of the future.*" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun italicAndBold() { + val page = TestPage { + text("There is no curse in Elvish, Entish, or the tongues of Men for this treachery.", styles = setOf(TextStyle.Bold, TextStyle.Italic)) + } + val expect = "//[testPage](test-page.md)\n\n***There is no curse in Elvish, Entish, or the tongues of Men for this treachery.***" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } + + @Test + fun strikethrough() { + val page = TestPage { + text("A day may come when the courage of men fails… but it is not THIS day", styles = setOf(TextStyle.Strikethrough)) + } + val expect = "//[testPage](test-page.md)\n\n~~A day may come when the courage of men fails… but it is not THIS day~~" + CommonmarkRenderer(context).render(page) + assert(renderedContent == expect) + } +}
\ No newline at end of file diff --git a/plugins/gfm/src/test/kotlin/renderers/gfm/SourceSetDependentHintTest.kt b/plugins/gfm/src/test/kotlin/renderers/gfm/SourceSetDependentHintTest.kt new file mode 100644 index 00000000..e181e3a2 --- /dev/null +++ b/plugins/gfm/src/test/kotlin/renderers/gfm/SourceSetDependentHintTest.kt @@ -0,0 +1,137 @@ +package renderers.gfm + +import org.jetbrains.dokka.DokkaSourceSetID +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.SourceRootImpl +import org.jetbrains.dokka.gfm.CommonmarkRenderer +import org.jetbrains.dokka.pages.TextStyle +import org.junit.jupiter.api.Test +import renderers.TestPage +import renderers.defaultSourceSet + +class SourceSetDependentHintTest : GfmRenderingOnlyTestBase() { + + private val pl1 = defaultSourceSet.copy( + "root", + "pl1", + DokkaSourceSetID("root", "pl1"), + analysisPlatform = Platform.js, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + private val pl2 = defaultSourceSet.copy( + "root", + "pl2", + DokkaSourceSetID("root", "pl2"), + analysisPlatform = Platform.jvm, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + private val pl3 = defaultSourceSet.copy( + "root", + "pl3", + DokkaSourceSetID("root", "pl3"), + analysisPlatform = Platform.native, + sourceRoots = listOf(SourceRootImpl("pl1")) + ) + + @Test + fun platformIndependentCase() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { + text("a") + text("b") + text("c") + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1, pl2, pl3] abc \n \n") + } + + @Test + fun completelyDivergentCase() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { + text("a", sourceSets = setOf(pl1)) + text("b", sourceSets = setOf(pl2)) + text("c", sourceSets = setOf(pl3)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1] a \n \n [pl2] b \n \n [pl3] c \n \n") + } + + @Test + fun overlappingCase() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { + text("a", sourceSets = setOf(pl1)) + text("b", sourceSets = setOf(pl1, pl2)) + text("c", sourceSets = setOf(pl2)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1] ab \n \n [pl2] bc \n \n") + } + + @Test + fun caseThatCanBeSimplified() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { + text("a", sourceSets = setOf(pl1, pl2)) + text("b", sourceSets = setOf(pl1)) + text("b", sourceSets = setOf(pl2)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1, pl2] ab \n \n") + } + + @Test + fun caseWithGroupBreakingSimplification() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { + group(styles = setOf(TextStyle.Block)) { + text("a", sourceSets = setOf(pl1, pl2)) + text("b", sourceSets = setOf(pl1)) + } + text("b", sourceSets = setOf(pl2)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1] ab \n \n \n [pl2] a \nb \n \n") + } + + @Test + fun caseWithGroupNotBreakingSimplification() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2)) { + group { + text("a", sourceSets = setOf(pl1, pl2)) + text("b", sourceSets = setOf(pl1)) + } + text("b", sourceSets = setOf(pl2)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1, pl2] ab \n") + } + + @Test + fun partiallyUnifiedCase() { + val page = TestPage { + sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { + text("a", sourceSets = setOf(pl1)) + text("a", sourceSets = setOf(pl2)) + text("b", sourceSets = setOf(pl3)) + } + } + + CommonmarkRenderer(context).render(page) + assert(renderedContent == "//[testPage](test-page.md)\n\n [pl1, pl2] a \n \n [pl3] b \n \n") + } +}
\ No newline at end of file |