diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2021-12-06 16:20:51 +0300 |
---|---|---|
committer | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2021-12-06 16:20:51 +0300 |
commit | c68c05a1e8876e9b8555df7bcdfeaca3e100f0d1 (patch) | |
tree | d9c20d2118d6679175ef8ab9f7dfc6d49aba5af3 /plugins/base/src | |
parent | 35a69e0322fcd271dccadcc2ee8cbb61dcafe62e (diff) | |
download | dokka-c68c05a1e8876e9b8555df7bcdfeaca3e100f0d1.tar.gz dokka-c68c05a1e8876e9b8555df7bcdfeaca3e100f0d1.tar.bz2 dokka-c68c05a1e8876e9b8555df7bcdfeaca3e100f0d1.zip |
Description list support for JavaDocs (#2213)
Diffstat (limited to 'plugins/base/src')
7 files changed, 264 insertions, 14 deletions
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index b61d513a..304b96fa 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -8,7 +8,6 @@ import org.jetbrains.dokka.base.DokkaBaseConfiguration import org.jetbrains.dokka.base.DokkaBaseConfiguration.Companion.defaultFooterMessage import org.jetbrains.dokka.base.renderers.* import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer -import org.jetbrains.dokka.base.renderers.pageId import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint import org.jetbrains.dokka.base.resolvers.local.DokkaBaseLocationProvider import org.jetbrains.dokka.base.templating.* @@ -295,8 +294,31 @@ open class HtmlRenderer( node: ContentList, pageContext: ContentPage, sourceSetRestriction: Set<DisplaySourceSet>? - ) = if (node.ordered) ol { buildListItems(node.children, pageContext, sourceSetRestriction) } - else ul { buildListItems(node.children, pageContext, sourceSetRestriction) } + ) = if (node.ordered) { + ol { buildListItems(node.children, pageContext, sourceSetRestriction) } + } else if (node.hasStyle(ListStyle.DescriptionList)) { + dl { buildListItems(node.children, pageContext, sourceSetRestriction) } + } else { + ul { buildListItems(node.children, pageContext, sourceSetRestriction) } + } + + open fun DL.buildListItems( + items: List<ContentNode>, + pageContext: ContentPage, + sourceSetRestriction: Set<DisplaySourceSet>? = null + ) { + items.forEach { + when { + it.hasStyle(ListStyle.DescriptionTerm) -> dt { + it.build(this@buildListItems, pageContext, sourceSetRestriction) + } + it.hasStyle(ListStyle.DescriptionDetails) -> dd { + it.build(this@buildListItems, pageContext, sourceSetRestriction) + } + else -> it.build(this, pageContext, sourceSetRestriction) + } + } + } open fun OL.buildListItems( items: List<ContentNode>, diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt index 8c2e1c99..2b4317c5 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt @@ -4,10 +4,10 @@ import org.intellij.markdown.MarkdownElementTypes import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.model.properties.PropertyContainer +import org.jetbrains.dokka.model.properties.plus import org.jetbrains.dokka.model.toDisplaySourceSets import org.jetbrains.dokka.pages.* import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import org.jetbrains.dokka.model.properties.plus open class DocTagToContentConverter : CommentsToContentConverter { override fun buildContent( @@ -39,14 +39,14 @@ open class DocTagToContentConverter : CommentsToContentConverter { ) ) - fun buildList(ordered: Boolean, start: Int = 1) = + fun buildList(ordered: Boolean, newStyles: Set<Style> = emptySet(), start: Int = 1) = listOf( ContentList( buildChildren(docTag), ordered, dci, sourceSets.toDisplaySourceSets(), - styles, + if (newStyles.isEmpty()) styles else styles + newStyles, ((PropertyContainer.empty<ContentNode>()) + SimpleAttr("start", start.toString())) ) ) @@ -68,10 +68,27 @@ open class DocTagToContentConverter : CommentsToContentConverter { is H5 -> buildHeader(5) is H6 -> buildHeader(6) is Ul -> buildList(false) - is Ol -> buildList(true, docTag.params["start"]?.toInt() ?: 1) + is Ol -> buildList(true, start = docTag.params["start"]?.toInt() ?: 1) is Li -> listOf( ContentGroup(buildChildren(docTag), dci, sourceSets.toDisplaySourceSets(), styles, extra) ) + is Dl -> buildList(false, newStyles = setOf(ListStyle.DescriptionList)) + is Dt -> listOf( + ContentGroup( + buildChildren(docTag), + dci, + sourceSets.toDisplaySourceSets(), + styles + ListStyle.DescriptionTerm + ) + ) + is Dd -> listOf( + ContentGroup( + buildChildren(docTag), + dci, + sourceSets.toDisplaySourceSets(), + styles + ListStyle.DescriptionDetails + ) + ) is Br -> buildNewLine() is B -> buildChildren(docTag, setOf(TextStyle.Strong)) is I -> buildChildren(docTag, setOf(TextStyle.Italic)) diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt index 7d4f5c05..8c3fcd84 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt @@ -173,6 +173,18 @@ open class PageContentBuilder( contents += ListBuilder(true, mainDRI, sourceSets, kind, styles, extra).apply(operation).build() } + fun descriptionList( + kind: Kind = ContentKind.Main, + sourceSets: Set<DokkaSourceSet> = mainSourcesetData, + styles: Set<Style> = mainStyles, + extra: PropertyContainer<ContentNode> = mainExtra, + operation: ListBuilder.() -> Unit = {} + ) { + contents += ListBuilder(false, mainDRI, sourceSets, kind, styles + ListStyle.DescriptionList, extra) + .apply(operation) + .build() + } + internal fun headers(vararg label: String) = contentFor(mainDRI, mainSourcesetData) { label.forEach { text(it) } } diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt index d74a1ca4..f9f591b2 100644 --- a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt +++ b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt @@ -14,17 +14,21 @@ import org.jetbrains.dokka.base.parsers.MarkdownParser import org.jetbrains.dokka.base.translators.parseHtmlEncodedWithNormalisedSpaces import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.doc.* +import org.jetbrains.dokka.model.doc.Deprecated import org.jetbrains.dokka.utilities.DokkaLogger import org.jetbrains.dokka.utilities.enumValueOrNull +import org.jetbrains.dokka.utilities.htmlEscape import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.util.CommentSaver.Companion.tokenType import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespace import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jsoup.Jsoup -import org.jsoup.nodes.* +import org.jsoup.nodes.Comment +import org.jsoup.nodes.Element +import org.jsoup.nodes.Node +import org.jsoup.nodes.TextNode import java.util.* -import org.jetbrains.dokka.utilities.htmlEscape interface JavaDocumentationParser { fun parseDocumentation(element: PsiNamedElement): DocumentationNode @@ -396,6 +400,9 @@ class JavadocParser( "ul" -> ifChildrenPresent { Ul(children) } "ol" -> ifChildrenPresent { Ol(children) } "li" -> listOf(Li(children)) + "dl" -> ifChildrenPresent { Dl(children) } + "dt" -> listOf(Dt(children)) + "dd" -> listOf(Dd(children)) "a" -> listOf(createLink(element, children)) "table" -> ifChildrenPresent { Table(children) } "tr" -> ifChildrenPresent { Tr(children) } diff --git a/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt b/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt index e6e1e105..c066075a 100644 --- a/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt +++ b/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt @@ -5,10 +5,9 @@ import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest import org.jetbrains.dokka.model.DEnum import org.jetbrains.dokka.model.DModule import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.doc.P import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import utils.* +import utils.text class JavadocParserTest : BaseAbstractTest() { @@ -249,4 +248,105 @@ class JavadocParserTest : BaseAbstractTest() { } } } + + @Test + fun `description list tag`() { + val source = """ + |/src/main/kotlin/test/Test.java + |package example + | + | /** + | * <dl> + | * <dt> + | * <code>name="<i>name</i>"</code> + | * </dt> + | * <dd> + | * A URI path segment. The subdirectory name for this value is contained in the + | * <code>path</code> attribute. + | * </dd> + | * <dt> + | * <code>path="<i>path</i>"</code> + | * </dt> + | * <dd> + | * The subdirectory you're sharing. While the <i>name</i> attribute is a URI path + | * segment, the <i>path</i> value is an actual subdirectory name. + | * </dd> + | * </dl> + | */ + | public class Test {} + """.trimIndent() + + val expected = listOf( + Dl( + listOf( + Dt( + listOf( + CodeInline( + listOf( + Text("name=\""), + I( + listOf( + Text("name") + ) + ), + Text("\"") + ) + ), + ) + ), + Dd( + listOf( + Text(" A URI path segment. The subdirectory name for this value is contained in the "), + CodeInline( + listOf( + Text("path") + ) + ), + Text(" attribute. ") + ) + ), + + Dt( + listOf( + CodeInline( + listOf( + Text("path=\""), + I( + listOf( + Text("path") + ) + ), + Text("\"") + ) + ) + ) + ), + Dd( + listOf( + Text(" The subdirectory you're sharing. While the "), + I( + listOf( + Text("name") + ) + ), + Text(" attribute is a URI path segment, the "), + I( + listOf( + Text("path") + ) + ), + Text(" value is an actual subdirectory name. ") + ) + ) + ) + ) + ) + + testInline(source, configuration) { + documentablesCreationStage = { modules -> + val docs = modules.first().packages.first().classlikes.single().documentation.first().value + assertEquals(expected, docs.children.first().root.children) + } + } + } } diff --git a/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt b/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt new file mode 100644 index 00000000..d578ba5e --- /dev/null +++ b/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt @@ -0,0 +1,41 @@ +package renderers.html + +import org.jetbrains.dokka.base.renderers.html.HtmlRenderer +import org.jetbrains.dokka.pages.ListStyle +import org.junit.jupiter.api.Test +import renderers.testPage +import utils.Dd +import utils.Dl +import utils.Dt +import utils.match + + +class ListStylesTest : HtmlRenderingOnlyTestBase() { + + @Test + fun `description list render`() { + val page = testPage { + descriptionList { + item(styles = setOf(ListStyle.DescriptionTerm)) { + text("Description term #1") + } + item(styles = setOf(ListStyle.DescriptionTerm)) { + text("Description term #2") + } + item(styles = setOf(ListStyle.DescriptionDetails)) { + text("Description details describing terms #1 and #2") + } + } + } + + + HtmlRenderer(context).render(page) + renderedContent.match( + Dl( + Dt("Description term #1"), + Dt("Description term #2"), + Dd("Description details describing terms #1 and #2") + ) + ) + } +}
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt index 8703a4a9..6d8730f1 100644 --- a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt +++ b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt @@ -1,13 +1,14 @@ package transformers +import matchers.content.* import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.doc.* -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test -import matchers.content.* import org.jetbrains.dokka.pages.* import org.jetbrains.kotlin.utils.addToStdlib.assertedCast +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test class CommentsToContentConverterTest { private val converter = DocTagToContentConverter() @@ -422,4 +423,54 @@ class CommentsToContentConverterTest { } } } + + @Test + fun `description list`() { + val docTag = + Dl( + listOf( + Dt( + listOf( + Text("description list can have...") + ) + ), + Dt( + listOf( + Text("... two consecutive description terms") + ) + ), + Dd( + listOf( + Text("and usually has some sort of a description, like this one") + ) + ) + ) + ) + + executeTest(docTag) { + composite<ContentList> { + check { + assertTrue(style.contains(ListStyle.DescriptionList)) { "Expected DL style" } + } + group { + check { + assertTrue(style.contains(ListStyle.DescriptionTerm)) { "Expected DT style" } + } + +"description list can have..." + } + group { + check { + assertTrue(style.contains(ListStyle.DescriptionTerm)) { "Expected DT style" } + } + +"... two consecutive description terms" + } + group { + check { + assertTrue(style.contains(ListStyle.DescriptionDetails)) { "Expected DD style" } + } + +"and usually has some sort of a description, like this one" + } + } + } + } }
\ No newline at end of file |