diff options
author | vmishenev <vad-mishenev@yandex.ru> | 2021-08-25 17:14:31 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-25 16:14:31 +0200 |
commit | 4fa9524e52d8ff422bb355336e3810ab28ae135c (patch) | |
tree | 66d2bc381ffc7d5c598cee4ea9e0ba13f81b1d7b /plugins/base/src | |
parent | 742f96bdf5c0b842e68dfaf43f4ab3446e87e3df (diff) | |
download | dokka-4fa9524e52d8ff422bb355336e3810ab28ae135c.tar.gz dokka-4fa9524e52d8ff422bb355336e3810ab28ae135c.tar.bz2 dokka-4fa9524e52d8ff422bb355336e3810ab28ae135c.zip |
Manual highlighting webhelp (#2079)
* Add manual code highlighting
* Fix test
* Add kotlinAsJava highlighting
* Add runtime highlighting via Prism
* Add copy-button for code block
* Add tests and refactor
* Replace `<br>` for prism.js
* Parse trivial default values
Co-authored-by: Marcin Aman <marcin.aman@gmail.com>
Diffstat (limited to 'plugins/base/src')
17 files changed, 450 insertions, 154 deletions
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index 3cf914ce..31753332 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -677,13 +677,15 @@ open class HtmlRenderer( pageContext: ContentPage ) { div("sample-container") { - val stylesWithBlock = code.style + TextStyle.Block - code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) { - attributes["theme"] = "idea" - pre { + val codeLang = "lang-" + code.language.ifEmpty { "kotlin" } + val stylesWithBlock = code.style + TextStyle.Block + codeLang + pre { + code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) { + attributes["theme"] = "idea" code.children.forEach { buildContentNode(it, pageContext) } } } + copyButton() } } @@ -691,7 +693,9 @@ open class HtmlRenderer( code: ContentCodeInline, pageContext: ContentPage ) { - code { + val codeLang = "lang-" + code.language.ifEmpty { "kotlin" } + val stylesWithBlock = code.style + codeLang + code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) { code.children.forEach { buildContentNode(it, pageContext) } } } @@ -725,6 +729,7 @@ open class HtmlRenderer( TextStyle.Italic -> i { body() } TextStyle.Strikethrough -> strike { body() } TextStyle.Strong -> strong { body() } + is TokenStyle -> span("token " + styleToApply.toString().toLowerCase()) { body() } else -> body() } } diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt index 9faf4d17..347e16bf 100644 --- a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt +++ b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt @@ -87,6 +87,7 @@ class ScriptsInstaller(private val dokkaContext: DokkaContext) : PageTransformer "scripts/navigation-loader.js", "scripts/platform-content-handler.js", "scripts/main.js", + "scripts/prism.js" ) override fun invoke(input: RootPageNode): RootPageNode = @@ -104,7 +105,8 @@ class StylesInstaller(private val dokkaContext: DokkaContext) : PageTransformer private val stylesPages = listOf( "styles/style.css", "styles/jetbrains-mono.css", - "styles/main.css" + "styles/main.css", + "styles/prism.css" ) override fun invoke(input: RootPageNode): RootPageNode = diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt index d17fa276..94af96e2 100644 --- a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt +++ b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt @@ -8,7 +8,6 @@ import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.drisOfAllNestedBounds import org.jetbrains.dokka.model.AnnotationTarget -import org.jetbrains.dokka.model.doc.DocumentationNode interface JvmSignatureUtils { @@ -80,21 +79,22 @@ interface JvmSignatureUtils { when (renderAtStrategy) { is All, is OnlyOnce -> { - text("@") when(a.scope) { - Annotations.AnnotationScope.GETTER -> text("get:") - Annotations.AnnotationScope.SETTER -> text("set:") + Annotations.AnnotationScope.GETTER -> text("@get:", styles = mainStyles + TokenStyle.Annotation) + Annotations.AnnotationScope.SETTER -> text("@set:", styles = mainStyles + TokenStyle.Annotation) + else -> text("@", styles = mainStyles + TokenStyle.Annotation) } + link(a.dri.classNames!!, a.dri, styles = mainStyles + TokenStyle.Annotation) } - is Never -> Unit + is Never -> link(a.dri.classNames!!, a.dri) } - link(a.dri.classNames!!, a.dri) val isNoWrappedBrackets = a.params.entries.isEmpty() && renderAtStrategy is OnlyOnce listParams( a.params.entries, if (isNoWrappedBrackets) null else Pair('(', ')') ) { - text(it.key + " = ") + text(it.key) + text(" = ", styles = mainStyles + TokenStyle.Operator) when (renderAtStrategy) { is All -> All is Never, is OnlyOnce -> Never @@ -116,8 +116,9 @@ interface JvmSignatureUtils { } is EnumValue -> link(a.enumName, a.enumDri) is ClassValue -> link(a.className + classExtension, a.classDRI) - is StringValue -> group(styles = setOf(TextStyle.Breakable)) { text( "\"${a.text()}\"") } - is LiteralValue -> group(styles = setOf(TextStyle.Breakable)) { text(a.text()) } + is StringValue -> group(styles = setOf(TextStyle.Breakable)) { stringLiteral( "\"${a.text()}\"") } + is BooleanValue -> group(styles = setOf(TextStyle.Breakable)) { booleanLiteral(a.value) } + is LiteralValue -> group(styles = setOf(TextStyle.Breakable)) { constant(a.text()) } } private fun<T> PageContentBuilder.DocumentableContentBuilder.listParams( @@ -125,14 +126,14 @@ interface JvmSignatureUtils { listBrackets: Pair<Char, Char>?, outFn: PageContentBuilder.DocumentableContentBuilder.(T) -> Unit ) { - listBrackets?.let{ text(it.first.toString()) } + listBrackets?.let{ punctuation(it.first.toString()) } params.forEachIndexed { i, it -> group(styles = setOf(TextStyle.BreakableAfter)) { this.outFn(it) - if (i != params.size - 1) text(", ") + if (i != params.size - 1) punctuation(", ") } } - listBrackets?.let{ text(it.second.toString()) } + listBrackets?.let{ punctuation(it.second.toString()) } } fun PageContentBuilder.DocumentableContentBuilder.annotationsBlockWithIgnored( diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt index bd967518..8db37012 100644 --- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt +++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt @@ -15,6 +15,7 @@ import org.jetbrains.dokka.model.properties.WithExtraProperties import org.jetbrains.dokka.pages.ContentKind import org.jetbrains.dokka.pages.ContentNode import org.jetbrains.dokka.pages.TextStyle +import org.jetbrains.dokka.pages.TokenStyle import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle @@ -60,7 +61,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog it !in ignoredExtraModifiers || entry.key.analysisPlatform in (platformSpecificModifiers[it] ?: emptySet()) } - } + }, styles = mainStyles + TokenStyle.Keyword ) { it.toSignatureString() } @@ -78,8 +79,15 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog annotationsBlock(e) link(e.name, e.dri, styles = emptySet()) e.extra[ConstructorValues]?.let { constructorValues -> - constructorValues.values[it] - text(constructorValues.values[it]?.joinToString(prefix = "(", postfix = ")") ?: "") + constructorValues.values[it]?.let { values -> + punctuation("(") + list( + elements = values, + separator = ", ", + separatorStyles = mainStyles + TokenStyle.Punctuation, + ) { highlightValue(it) } + punctuation(")") + } } } } @@ -93,9 +101,9 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog ?: emptySet()), sourceSets = setOf(sourceSet) ) { - text("typealias ") + keyword("typealias ") link(c.name.orEmpty(), c.dri) - text(" = ") + operator(" = ") signatureForProjection(aliasedType) } @@ -118,10 +126,9 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog sourceSets = setOf(sourceSet) ) { annotationsBlock(c) - text(c.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "") + c.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } if (c is DClass) { - text( - if (c.modifier[sourceSet] !in ignoredModifiers) + val modifier = if (c.modifier[sourceSet] !in ignoredModifiers) when { c.extra[AdditionalModifiers]?.content?.get(sourceSet)?.contains(ExtraModifiers.KotlinOnlyModifiers.Data) == true -> "" c.modifier[sourceSet] is JavaModifier.Empty -> "${KotlinModifier.Open.name} " @@ -129,33 +136,35 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog } else "" - ) + modifier.takeIf { it.isNotEmpty() }?.let { keyword(it) } } when (c) { is DClass -> { processExtraModifiers(c) - text("class ") + keyword("class ") } is DInterface -> { processExtraModifiers(c) - text("interface ") + keyword("interface ") } is DEnum -> { processExtraModifiers(c) - text("enum ") + keyword("enum ") } is DObject -> { processExtraModifiers(c) - text("object ") + keyword("object ") } is DAnnotation -> { processExtraModifiers(c) - text("annotation class ") + keyword("annotation class ") } } link(c.name!!, c.dri) if (c is WithGenerics) { - list(c.generics, prefix = "<", suffix = ">") { + list(c.generics, prefix = "<", suffix = ">", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { annotationsInline(it) +buildSignature(it) } @@ -166,18 +175,20 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog if (pConstructor.annotations().values.any { it.isNotEmpty() }) { text(nbsp.toString()) annotationsInline(pConstructor) - text("constructor") + keyword("constructor") } list( - pConstructor.parameters, - "(", - ")", - ", ", - pConstructor.sourceSets.toSet() + elements = pConstructor.parameters, + prefix = "(", + suffix = ")", + separator = ", ", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Punctuation, + sourceSets = pConstructor.sourceSets.toSet() ) { annotationsInline(it) text(it.name.orEmpty()) - text(": ") + operator(": ") signatureForProjection(it.type) } } @@ -186,7 +197,9 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog c.supertypes.filter { it.key == sourceSet }.map { (s, typeConstructors) -> list(typeConstructors, prefix = " : ", sourceSets = setOf(s)) { link(it.typeConstructor.dri.sureClassNames, it.typeConstructor.dri, sourceSets = setOf(s)) - list(it.typeConstructor.projections, prefix = "<", suffix = "> ") { + list(it.typeConstructor.projections, prefix = "<", suffix = "> ", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { signatureForProjection(it) } } @@ -203,31 +216,42 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog sourceSets = setOf(it) ) { annotationsBlock(p) - text(p.visibility[it].takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "") - text( - p.modifier[it].takeIf { it !in ignoredModifiers }?.let { + p.visibility[it].takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } + p.modifier[it].takeIf { it !in ignoredModifiers }?.let { if (it is JavaModifier.Empty) KotlinModifier.Open else it - }?.name?.let { "$it " } ?: "" - ) - text(p.modifiers()[it]?.toSignatureString() ?: "") - p.setter?.let { text("var ") } ?: text("val ") - list(p.generics, prefix = "<", suffix = "> ") { + }?.name?.let { keyword("$it ") } + p.modifiers()[it]?.toSignatureString()?.let { keyword(it) } + p.setter?.let { keyword("var ") } ?: keyword("val ") + list(p.generics, prefix = "<", suffix = "> ", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { annotationsInline(it) +buildSignature(it) } p.receiver?.also { signatureForProjection(it.type) - text(".") + punctuation(".") } link(p.name, p.dri) - text(": ") + operator(": ") signatureForProjection(p.type) p.extra[DefaultValue]?.run { - text(" = $value") + operator(" = ") + highlightValue(value) } } } + private fun PageContentBuilder.DocumentableContentBuilder.highlightValue(expr: Expression) = when (expr) { + is IntegerConstant -> constant(expr.value.toString()) + is FloatConstant -> constant(expr.value.toString() + "f") + is DoubleConstant -> constant(expr.value.toString()) + is BooleanConstant -> booleanLiteral(expr.value) + is StringConstant -> stringLiteral("\"${expr.value}\"") + is ComplexExpression -> text(expr.value) + else -> Unit + } + private fun functionSignature(f: DFunction) = f.sourceSets.map { contentBuilder.contentFor( @@ -237,37 +261,40 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog sourceSets = setOf(it) ) { annotationsBlock(f) - text(f.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "") - text(f.modifier[it]?.takeIf { it !in ignoredModifiers }?.let { + f.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } + f.modifier[it]?.takeIf { it !in ignoredModifiers }?.let { if (it is JavaModifier.Empty) KotlinModifier.Open else it - }?.name?.let { "$it " } ?: "" - ) - text(f.modifiers()[it]?.toSignatureString() ?: "") - text("fun ") + }?.name?.let { keyword("$it ") } + f.modifiers()[it]?.toSignatureString()?.let { keyword(it) } + keyword("fun ") val usedGenerics = if (f.isConstructor) f.generics.filter { f uses it } else f.generics - list(usedGenerics, prefix = "<", suffix = "> ") { + list(usedGenerics, prefix = "<", suffix = "> ", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { annotationsInline(it) +buildSignature(it) } f.receiver?.also { signatureForProjection(it.type) - text(".") + punctuation(".") } - link(f.name, f.dri) - text("(") - list(f.parameters) { + link(f.name, f.dri, styles = mainStyles + TokenStyle.Function) + punctuation("(") + list(f.parameters, + separatorStyles = mainStyles + TokenStyle.Punctuation) { annotationsInline(it) processExtraModifiers(it) text(it.name!!) - text(": ") + operator(": ") signatureForProjection(it.type) it.extra[DefaultValue]?.run { - text(" = $value") + operator(" = ") + highlightValue(value) } } - text(")") + punctuation(")") if (f.documentReturnType()) { - text(": ") + operator(": ") signatureForProjection(f.type) } } @@ -291,11 +318,11 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog sourceSets = platforms.toSet() ) { annotationsBlock(t) - text(t.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "") + t.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } processExtraModifiers(t) - text("typealias ") + keyword("typealias ") signatureForProjection(t.type) - text(" = ") + operator(" = ") signatureForTypealiasTarget(t, type) } } @@ -306,7 +333,8 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog t.sourceSets.map { contentBuilder.contentFor(t, styles = t.stylesIfDeprecated(it), sourceSets = setOf(it)) { signatureForProjection(t.variantTypeParameter.withDri(t.dri.withTargetToDeclaration())) - list(t.nontrivialBounds, prefix = " : ") { bound -> + list(t.nontrivialBounds, prefix = " : ", + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { bound -> signatureForProjection(bound) } } @@ -338,24 +366,29 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog val linkText = if (showFullyQualifiedName && p.dri.packageName != null) { "${p.dri.packageName}.${p.dri.classNames.orEmpty()}" } else p.dri.classNames.orEmpty() - if (p.presentableName != null) text(p.presentableName + ": ") + if (p.presentableName != null) { + text(p.presentableName!!) + operator(": ") + } annotationsInline(p) link(linkText, p.dri) - list(p.projections, prefix = "<", suffix = ">") { + list(p.projections, prefix = "<", suffix = ">", + separatorStyles = mainStyles + TokenStyle.Punctuation, + surroundingCharactersStyle = mainStyles + TokenStyle.Operator) { signatureForProjection(it, showFullyQualifiedName) } } is Variance<*> -> group(styles = emptySet()) { - text("$p ".takeIf { it.isNotBlank() } ?: "") + keyword("$p ".takeIf { it.isNotBlank() } ?: "") signatureForProjection(p.inner, showFullyQualifiedName) } - is Star -> text("*") + is Star -> operator("*") is Nullable -> group(styles = emptySet()) { signatureForProjection(p.inner, showFullyQualifiedName) - text("?") + operator("?") } is TypeAliased -> signatureForProjection(p.typeAlias) @@ -373,12 +406,15 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog private fun funType(dri: DRI, sourceSets: Set<DokkaSourceSet>, type: FunctionalTypeConstructor) = contentBuilder.contentFor(dri, sourceSets, ContentKind.Main) { - if (type.presentableName != null) text(type.presentableName + ": ") - if (type.isSuspendable) text("suspend ") + if (type.presentableName != null) { + text(type.presentableName!!) + operator(": ") + } + if (type.isSuspendable) keyword("suspend ") if (type.isExtensionFunction) { signatureForProjection(type.projections.first()) - text(".") + punctuation(".") } val args = if (type.isExtensionFunction) @@ -386,12 +422,13 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog else type.projections - text("(") + punctuation("(") args.subList(0, args.size - 1).forEachIndexed { i, arg -> signatureForProjection(arg) - if (i < args.size - 2) text(", ") + if (i < args.size - 2) punctuation(", ") } - text(") -> ") + punctuation(")") + operator(" -> ") signatureForProjection(args.last()) } } 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 a02f1b53..8c2e1c99 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt @@ -108,7 +108,7 @@ open class DocTagToContentConverter : CommentsToContentConverter { is BlockQuote, is Pre, is CodeBlock -> listOf( ContentCodeBlock( buildChildren(docTag), - "", + docTag.params.getOrDefault("lang", ""), dci, sourceSets.toDisplaySourceSets(), styles diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 3ff8ffc3..d986056c 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka.base.translators.descriptors import com.intellij.psi.PsiNamedElement +import com.intellij.psi.util.PsiLiteralUtil.* import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.runBlocking @@ -29,6 +30,8 @@ import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTransla import org.jetbrains.dokka.utilities.DokkaLogger import org.jetbrains.dokka.utilities.parallelMap import org.jetbrains.dokka.utilities.parallelMapNotNull +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.dokka.model.BooleanConstant import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType import org.jetbrains.kotlin.builtins.isExtensionFunctionType @@ -38,7 +41,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations import org.jetbrains.kotlin.idea.kdoc.findKDoc import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi @@ -53,7 +55,6 @@ import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.LocalClass import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.NormalClass import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull -import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement @@ -1011,25 +1012,33 @@ private class DokkaDescriptorVisitor( if (kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) this else overriddenDescriptors.first().getConcreteDescriptor() as T - private fun ValueParameterDescriptor.getDefaultValue(): String? = - (source as? KotlinSourceElement)?.psi?.children?.find { it is KtExpression }?.text + private fun ValueParameterDescriptor.getDefaultValue(): Expression? = + ((source as? KotlinSourceElement)?.psi as? KtParameter)?.defaultValue?.toDefaultValueExpression() - private suspend fun PropertyDescriptor.getDefaultValue(): String? = - (source as? KotlinSourceElement)?.psi?.children?.find { it is KtConstantExpression }?.text + private suspend fun PropertyDescriptor.getDefaultValue(): Expression? = + (source as? KotlinSourceElement)?.psi?.children?.filterIsInstance<KtConstantExpression>()?.firstOrNull() + ?.toDefaultValueExpression() private suspend fun ClassDescriptor.getAppliedConstructorParameters() = (source as PsiSourceElement).psi?.children?.flatMap { - it.safeAs<KtInitializerList>()?.initializersAsText().orEmpty() + it.safeAs<KtInitializerList>()?.initializersAsExpression().orEmpty() }.orEmpty() - private suspend fun KtInitializerList.initializersAsText() = + private suspend fun KtInitializerList.initializersAsExpression() = initializers.firstIsInstanceOrNull<KtCallElement>() ?.getValueArgumentsInParentheses() - ?.flatMap { it.childrenAsText() } + ?.map { it.getArgumentExpression()?.toDefaultValueExpression() ?: ComplexExpression("") } .orEmpty() - private fun ValueArgument.childrenAsText() = - this.safeAs<KtValueArgument>()?.children?.map { it.text }.orEmpty() + private fun KtExpression.toDefaultValueExpression(): Expression? = when (node?.elementType) { + KtNodeTypes.INTEGER_CONSTANT -> parseLong(node?.text)?.let { IntegerConstant(it) } + KtNodeTypes.FLOAT_CONSTANT -> if (node?.text?.toLowerCase()?.endsWith('f') == true) + parseFloat(node?.text)?.let { FloatConstant(it) } + else parseDouble(node?.text)?.let { DoubleConstant(it) } + KtNodeTypes.BOOLEAN_CONSTANT -> BooleanConstant(node?.text == "true") + KtNodeTypes.STRING_TEMPLATE -> StringConstant(node.findChildByType(KtNodeTypes.LITERAL_STRING_TEMPLATE_ENTRY)?.text.orEmpty()) + else -> node?.text?.let { ComplexExpression(it) } + } private data class ClassInfo(val ancestry: List<AncestryLevel>, val docs: SourceSetDependent<DocumentationNode>) { val supertypes: List<TypeConstructorWithKind> diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt index f98e284f..cbab6273 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt @@ -122,6 +122,13 @@ open class PageContentBuilder( header(1, text, sourceSets = sourceSets, styles = styles, extra = extra, block = block) } + fun constant(text: String) = text(text, styles = mainStyles + TokenStyle.Constant) + fun keyword(text: String) = text(text, styles = mainStyles + TokenStyle.Keyword) + fun stringLiteral(text: String) = text(text, styles = mainStyles + TokenStyle.String) + fun booleanLiteral(value: Boolean) = text(value.toString(), styles = mainStyles + TokenStyle.Boolean) + fun punctuation(text: String) = text(text, styles = mainStyles + TokenStyle.Punctuation) + fun operator(text: String) = text(text, styles = mainStyles + TokenStyle.Operator) + fun text( text: String, kind: Kind = ContentKind.Main, @@ -194,16 +201,18 @@ open class PageContentBuilder( suffix: String = "", separator: String = ", ", sourceSets: Set<DokkaSourceSet> = mainSourcesetData, // TODO: children should be aware of this platform data + surroundingCharactersStyle: Set<Style> = mainStyles, + separatorStyles: Set<Style> = mainStyles, operation: DocumentableContentBuilder.(T) -> Unit ) { if (elements.isNotEmpty()) { - if (prefix.isNotEmpty()) text(prefix, sourceSets = sourceSets) + if (prefix.isNotEmpty()) text(prefix, sourceSets = sourceSets, styles = surroundingCharactersStyle) elements.dropLast(1).forEach { operation(it) - text(separator, sourceSets = sourceSets) + text(separator, sourceSets = sourceSets, styles = separatorStyles) } operation(elements.last()) - if (suffix.isNotEmpty()) text(suffix, sourceSets = sourceSets) + if (suffix.isNotEmpty()) text(suffix, sourceSets = sourceSets, styles = surroundingCharactersStyle) } } @@ -380,11 +389,12 @@ open class PageContentBuilder( fun <T> sourceSetDependentText( value: SourceSetDependent<T>, sourceSets: Set<DokkaSourceSet> = value.keys, + styles: Set<Style> = mainStyles, transform: (T) -> String ) = value.entries.filter { it.key in sourceSets }.mapNotNull { (p, v) -> transform(v).takeIf { it.isNotBlank() }?.let { it to p } }.groupBy({ it.first }) { it.second }.forEach { - text(it.key, sourceSets = it.value.toSet()) + text(it.key, sourceSets = it.value.toSet(), styles = styles) } } diff --git a/plugins/base/src/main/resources/dokka/scripts/prism.js b/plugins/base/src/main/resources/dokka/scripts/prism.js new file mode 100644 index 00000000..88fee76e --- /dev/null +++ b/plugins/base/src/main/resources/dokka/scripts/prism.js @@ -0,0 +1,13 @@ +/* PrismJS 1.24.1 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+java+javadoc+javadoclike+kotlin&plugins=keep-markup */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,e={},M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++n}),e.__id},clone:function t(e,r){var a,n;switch(r=r||{},M.util.type(e)){case"Object":if(n=M.util.objId(e),r[n])return r[n];for(var i in a={},r[n]=a,e)e.hasOwnProperty(i)&&(a[i]=t(e[i],r));return a;case"Array":return n=M.util.objId(e),r[n]?r[n]:(a=[],r[n]=a,e.forEach(function(e,n){a[n]=t(e,r)}),a);default:return e}},getLanguage:function(e){for(;e&&!c.test(e.className);)e=e.parentElement;return e?(e.className.match(c)||[,"none"])[1].toLowerCase():"none"},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(e){var n=(/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(e.stack)||[])[1];if(n){var t=document.getElementsByTagName("script");for(var r in t)if(t[r].src==n)return t[r]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:e,plaintext:e,text:e,txt:e,extend:function(e,n){var t=M.util.clone(M.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(t,e,n,r){var a=(r=r||M.languages)[t],i={};for(var l in a)if(a.hasOwnProperty(l)){if(l==e)for(var o in n)n.hasOwnProperty(o)&&(i[o]=n[o]);n.hasOwnProperty(l)||(i[l]=a[l])}var s=r[t];return r[t]=i,M.languages.DFS(M.languages,function(e,n){n===s&&e!=t&&(this[e]=i)}),i},DFS:function e(n,t,r,a){a=a||{};var i=M.util.objId;for(var l in n)if(n.hasOwnProperty(l)){t.call(n,l,n[l],r||l);var o=n[l],s=M.util.type(o);"Object"!==s||a[i(o)]?"Array"!==s||a[i(o)]||(a[i(o)]=!0,e(o,t,l,a)):(a[i(o)]=!0,e(o,t,null,a))}}},plugins:{},highlightAll:function(e,n){M.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};M.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),M.hooks.run("before-all-elements-highlight",r);for(var a,i=0;a=r.elements[i++];)M.highlightElement(a,!0===n,r.callback)},highlightElement:function(e,n,t){var r=M.util.getLanguage(e),a=M.languages[r];e.className=e.className.replace(c,"").replace(/\s+/g," ")+" language-"+r;var i=e.parentElement;i&&"pre"===i.nodeName.toLowerCase()&&(i.className=i.className.replace(c,"").replace(/\s+/g," ")+" language-"+r);var l={element:e,language:r,grammar:a,code:e.textContent};function o(e){l.highlightedCode=e,M.hooks.run("before-insert",l),l.element.innerHTML=l.highlightedCode,M.hooks.run("after-highlight",l),M.hooks.run("complete",l),t&&t.call(l.element)}if(M.hooks.run("before-sanity-check",l),(i=l.element.parentElement)&&"pre"===i.nodeName.toLowerCase()&&!i.hasAttribute("tabindex")&&i.setAttribute("tabindex","0"),!l.code)return M.hooks.run("complete",l),void(t&&t.call(l.element));if(M.hooks.run("before-highlight",l),l.grammar)if(n&&u.Worker){var s=new Worker(M.filename);s.onmessage=function(e){o(e.data)},s.postMessage(JSON.stringify({language:l.language,code:l.code,immediateClose:!0}))}else o(M.highlight(l.code,l.grammar,l.language));else o(M.util.encode(l.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};return M.hooks.run("before-tokenize",r),r.tokens=M.tokenize(r.code,r.grammar),M.hooks.run("after-tokenize",r),W.stringify(M.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new i;return I(a,a.head,e),function e(n,t,r,a,i,l){for(var o in r)if(r.hasOwnProperty(o)&&r[o]){var s=r[o];s=Array.isArray(s)?s:[s];for(var u=0;u<s.length;++u){if(l&&l.cause==o+","+u)return;var c=s[u],g=c.inside,f=!!c.lookbehind,h=!!c.greedy,d=c.alias;if(h&&!c.pattern.global){var p=c.pattern.toString().match(/[imsuy]*$/)[0];c.pattern=RegExp(c.pattern.source,p+"g")}for(var v=c.pattern||c,m=a.next,y=i;m!==t.tail&&!(l&&y>=l.reach);y+=m.value.length,m=m.next){var b=m.value;if(t.length>n.length)return;if(!(b instanceof W)){var k,x=1;if(h){if(!(k=z(v,y,n,f)))break;var w=k.index,A=k.index+k[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var E=m;E!==t.tail&&(P<A||"string"==typeof E.value);E=E.next)x++,P+=E.value.length;x--,b=n.slice(y,P),k.index-=y}else if(!(k=z(v,0,b,f)))continue;var w=k.index,S=k[0],O=b.slice(0,w),L=b.slice(w+S.length),N=y+b.length;l&&N>l.reach&&(l.reach=N);var j=m.prev;O&&(j=I(t,j,O),y+=O.length),q(t,j,x);var C=new W(o,g?M.tokenize(S,g):S,d,S);if(m=I(t,j,C),L&&I(t,m,L),1<x){var _={cause:o+","+u,reach:N};e(n,t,r,m.prev,y,_),l&&_.reach>l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function z(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function q(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;(n.next=r).prev=n,e.length-=a}if(u.Prism=M,W.stringify=function n(e,t){if("string"==typeof e)return e;if(Array.isArray(e)){var r="";return e.forEach(function(e){r+=n(e,t)}),r}var a={type:e.type,content:n(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t},i=e.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(a.classes,i):a.classes.push(i)),M.hooks.run("wrap",a);var l="";for(var o in a.attributes)l+=" "+o+'="'+(a.attributes[o]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+l+">"+a.content+"</"+a.tag+">"},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var t=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(t&&(M.filename=t.src,t.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var a=document.readyState;"loading"===a||"interactive"===a&&t&&t.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:/<!--[\s\S]*?-->/,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata:/<!\[CDATA\[[\s\S]*?\]\]>/i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var t={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",a={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{"class-name":[a,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(/<keyword>/g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +!function(p){var a=p.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:param|arg|arguments)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(a,"addSupport",{value:function(a,e){"string"==typeof a&&(a=[a]),a.forEach(function(a){!function(a,e){var n="doc-comment",t=p.languages[a];if(t){var r=t[n];if(!r){var o={"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}};r=(t=p.languages.insertBefore(a,"comment",o))[n]}if(r instanceof RegExp&&(r=t[n]={pattern:r}),Array.isArray(r))for(var i=0,s=r.length;i<s;i++)r[i]instanceof RegExp&&(r[i]={pattern:r[i]}),e(r[i]);else e(r)}}(a,function(a){a.inside||(a.inside={}),a.inside.rest=e})})}}),a.addSupport(["java","javascript","php"],a)}(Prism); +!function(a){var e=/(^(?:[\t ]*(?:\*\s*)*))[^*\s].*$/m,n="(?:\\b[a-zA-Z]\\w+\\s*\\.\\s*)*\\b[A-Z]\\w*(?:\\s*<mem>)?|<mem>".replace(/<mem>/g,function(){return"#\\s*\\w+(?:\\s*\\([^()]*\\))?"});a.languages.javadoc=a.languages.extend("javadoclike",{}),a.languages.insertBefore("javadoc","keyword",{reference:{pattern:RegExp("(@(?:exception|throws|see|link|linkplain|value)\\s+(?:\\*\\s*)?)(?:"+n+")"),lookbehind:!0,inside:{function:{pattern:/(#\s*)\w+(?=\s*\()/,lookbehind:!0},field:{pattern:/(#\s*)\w+/,lookbehind:!0},namespace:{pattern:/\b(?:[a-z]\w*\s*\.\s*)+/,inside:{punctuation:/\./}},"class-name":/\b[A-Z]\w*/,keyword:a.languages.java.keyword,punctuation:/[#()[\],.]/}},"class-name":{pattern:/(@param\s+)<[A-Z]\w*>/,lookbehind:!0,inside:{punctuation:/[.<>]/}},"code-section":[{pattern:/(\{@code\s+(?!\s))(?:[^\s{}]|\s+(?![\s}])|\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})+(?=\s*\})/,lookbehind:!0,inside:{code:{pattern:e,lookbehind:!0,inside:a.languages.java,alias:"language-java"}}},{pattern:/(<(code|pre|tt)>(?!<code>)\s*)\S(?:\S|\s+\S)*?(?=\s*<\/\2>)/,lookbehind:!0,inside:{line:{pattern:e,lookbehind:!0,inside:{tag:a.languages.markup.tag,entity:a.languages.markup.entity,code:{pattern:/.+/,inside:a.languages.java,alias:"language-java"}}}}}],tag:a.languages.markup.tag,entity:a.languages.markup.entity}),a.languages.javadoclike.addSupport("java",a.languages.javadoc)}(Prism); +!function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"],e.languages.insertBefore("kotlin","string",{"raw-string":{pattern:/("""|''')[\s\S]*?\1/,alias:"string"}}),e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}});var n=[{pattern:/\$\{[^}]+\}/,inside:{delimiter:{pattern:/^\$\{|\}$/,alias:"variable"},rest:e.languages.kotlin}},{pattern:/\$\w+/,alias:"variable"}];e.languages.kotlin.string.inside=e.languages.kotlin["raw-string"].inside={interpolation:n},e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(Prism); +"undefined"!=typeof Prism&&"undefined"!=typeof document&&document.createRange&&(Prism.plugins.KeepMarkup=!0,Prism.hooks.add("before-highlight",function(e){if(e.element.children.length&&Prism.util.isActive(e.element,"keep-markup",!0)){var a=0,s=[],p=function(e,n){var o={};n||(o.clone=e.cloneNode(!1),o.posOpen=a,s.push(o));for(var t=0,d=e.childNodes.length;t<d;t++){var r=e.childNodes[t];1===r.nodeType?p(r):3===r.nodeType&&(a+=r.data.length)}n||(o.posClose=a)};p(e.element,!0),s&&s.length&&(e.keepMarkup=s)}}),Prism.hooks.add("after-highlight",function(n){if(n.keepMarkup&&n.keepMarkup.length){var a=function(e,n){for(var o=0,t=e.childNodes.length;o<t;o++){var d=e.childNodes[o];if(1===d.nodeType){if(!a(d,n))return!1}else 3===d.nodeType&&(!n.nodeStart&&n.pos+d.data.length>n.node.posOpen&&(n.nodeStart=d,n.nodeStartPos=n.node.posOpen-n.pos),n.nodeStart&&n.pos+d.data.length>=n.node.posClose&&(n.nodeEnd=d,n.nodeEndPos=n.node.posClose-n.pos),n.pos+=d.data.length);if(n.nodeStart&&n.nodeEnd){var r=document.createRange();return r.setStart(n.nodeStart,n.nodeStartPos),r.setEnd(n.nodeEnd,n.nodeEndPos),n.node.clone.appendChild(r.extractContents()),r.insertNode(n.node.clone),r.detach(),!1}}return!0};n.keepMarkup.forEach(function(e){a(n.element,{node:e,pos:0})}),n.highlightedCode=n.element.innerHTML}})); +Prism.hooks.add('before-sanity-check', function (env){env.element.innerHTML = env.element.innerHTML.replace(/<br>/g, '\n');env.code = env.element.textContent;}); diff --git a/plugins/base/src/main/resources/dokka/styles/prism.css b/plugins/base/src/main/resources/dokka/styles/prism.css new file mode 100644 index 00000000..62ade383 --- /dev/null +++ b/plugins/base/src/main/resources/dokka/styles/prism.css @@ -0,0 +1,92 @@ +code .token { + white-space: pre-line; +} + +/* PrismJS 1.24.1 +https://prismjs.com/download.html#themes=prism&languages=clike+java+javadoclike+kotlin&plugins=keep-markup */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.token.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.annotation, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + /* This background color was intended by the author of this theme. */ + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; + font-size: inherit; /* to override .keyword */ +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.annotation,.control,.field,.filename,.keyword,.menupath,.property,.string,.value { + color: #27282c; + color: var(--wh-color-text-bold); + font-weight: 700; +}
\ No newline at end of file diff --git a/plugins/base/src/main/resources/dokka/styles/style.css b/plugins/base/src/main/resources/dokka/styles/style.css index b9d22c3d..7a2dfae0 100644 --- a/plugins/base/src/main/resources/dokka/styles/style.css +++ b/plugins/base/src/main/resources/dokka/styles/style.css @@ -276,6 +276,7 @@ html ::-webkit-scrollbar-thumb { } .sample-container, div.CodeMirror { + position: relative; display: flex; flex-direction: column; } @@ -315,6 +316,7 @@ code.paragraph { padding: 12px 32px 12px 12px; border-radius: 8px; line-height: 24px; + position: relative; } .symbol > a { @@ -325,15 +327,15 @@ code.paragraph { cursor: pointer; } -.symbol span.copy-icon { +.symbol span.copy-icon, .sample-container span.copy-icon { display: none; } -.symbol:hover span.copy-icon { +.symbol:hover span.copy-icon, .sample-container:hover span.copy-icon { display: inline-block; } -.symbol span.copy-icon::before { +.symbol span.copy-icon::before, .sample-container span.copy-icon::before { width: 24px; height: 24px; display: inline-block; @@ -346,7 +348,7 @@ code.paragraph { background-color: var(--secondary-text-color); } -.symbol span.copy-icon:hover::before { +.symbol span.copy-icon:hover::before, .sample-container span.copy-icon:hover::before { background-color: var(--color-dark); } @@ -394,7 +396,7 @@ code.paragraph { padding-right: 14px; } -.symbol .top-right-position { +.symbol .top-right-position, .sample-container .top-right-position { /* it is important for a parent to have a position: relative */ position: absolute; top: 8px; diff --git a/plugins/base/src/test/kotlin/content/HighlightingTest.kt b/plugins/base/src/test/kotlin/content/HighlightingTest.kt new file mode 100644 index 00000000..39acd2ca --- /dev/null +++ b/plugins/base/src/test/kotlin/content/HighlightingTest.kt @@ -0,0 +1,79 @@ +package content + +import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest +import org.jetbrains.dokka.model.dfs +import org.jetbrains.dokka.pages.* +import org.junit.jupiter.api.Test +import kotlin.test.assertTrue + +class HighlightingTest : BaseAbstractTest() { + private val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + classpath = listOf(commonStdlibPath!!) + externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) + } + } + } + + @Test + fun `open suspend fun`() { + testInline( + """ + |/src/main/kotlin/test/Test.kt + |package example + | + | open suspend fun simpleFun(): String = "Celebrimbor" + """, + configuration + ) { + pagesTransformationStage = { module -> + val symbol = (module.dfs { it.name == "simpleFun" } as MemberPageNode).content + .dfs { it is ContentGroup && it.dci.kind == ContentKind.Symbol } + val children = symbol?.children + + for (it in listOf( + Pair(0, TokenStyle.Keyword), Pair(1, TokenStyle.Keyword), Pair(2, TokenStyle.Keyword), + Pair(4, TokenStyle.Punctuation), Pair(5, TokenStyle.Punctuation), Pair(6, TokenStyle.Operator) + )) + assertTrue(children?.get(it.first)?.style?.contains(it.second) == true) + assertTrue(children?.get(3)?.children?.first()?.style?.contains(TokenStyle.Function) == true) + } + } + } + + @Test + fun `plain typealias of plain class with annotation`() { + testInline( + """ + |/src/main/kotlin/common/Test.kt + |package example + | + |@MustBeDocumented + |@Target(AnnotationTarget.TYPEALIAS) + |annotation class SomeAnnotation + | + |@SomeAnnotation + |typealias PlainTypealias = Int + | + """.trimMargin(), + configuration + ) { + pagesTransformationStage = { module -> + val symbol = (module.dfs { it.name == "example" } as PackagePageNode).content + .dfs { it is ContentGroup && it.dci.kind == ContentKind.Symbol } + val children = symbol?.children + + for (it in listOf( + Pair(1, TokenStyle.Keyword), Pair(3, TokenStyle.Operator) + )) + assertTrue(children?.get(it.first)?.style?.contains(it.second) == true) + val annotation = children?.first()?.children?.first() + + assertTrue(annotation?.children?.get(0)?.style?.contains(TokenStyle.Annotation) == true) + assertTrue(annotation?.children?.get(1)?.children?.first()?.style?.contains(TokenStyle.Annotation) == true) + } + } + } +}
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/enums/EnumsTest.kt b/plugins/base/src/test/kotlin/enums/EnumsTest.kt index 2535140c..59a4c6f2 100644 --- a/plugins/base/src/test/kotlin/enums/EnumsTest.kt +++ b/plugins/base/src/test/kotlin/enums/EnumsTest.kt @@ -1,11 +1,9 @@ package enums import matchers.content.* -import org.jetbrains.dokka.model.ConstructorValues -import org.jetbrains.dokka.model.DEnum -import org.jetbrains.dokka.model.dfs import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest +import org.jetbrains.dokka.model.* import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test @@ -119,8 +117,8 @@ class EnumsTest : BaseAbstractTest() { assertEquals(1, first.extra.allOfType<ConstructorValues>().size) assertEquals(1, second.extra.allOfType<ConstructorValues>().size) - assertEquals(listOf("\"e1\"", "1", "true"), first.extra.allOfType<ConstructorValues>().first().values.values.first()) - assertEquals(listOf("\"e2\"", "2", "false"), second.extra.allOfType<ConstructorValues>().first().values.values.first()) + assertEquals(listOf(StringConstant("e1"), IntegerConstant(1), BooleanConstant(true)), first.extra.allOfType<ConstructorValues>().first().values.values.first()) + assertEquals(listOf(StringConstant("e2"), IntegerConstant(2), BooleanConstant(false)), second.extra.allOfType<ConstructorValues>().first().values.values.first()) } } } diff --git a/plugins/base/src/test/kotlin/model/FunctionsTest.kt b/plugins/base/src/test/kotlin/model/FunctionsTest.kt index 10ff29b4..eca5daea 100644 --- a/plugins/base/src/test/kotlin/model/FunctionsTest.kt +++ b/plugins/base/src/test/kotlin/model/FunctionsTest.kt @@ -344,7 +344,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun parameters.forEach { p -> p.name equals "x" p.type.name.assertNotNull("Parameter type: ") equals "String" - p.extra[DefaultValue]?.value equals "\"\"" + p.extra[DefaultValue]?.value equals StringConstant("") } } } @@ -363,7 +363,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun parameters.forEach { p -> p.name equals "x" p.type.name.assertNotNull("Parameter type: ") equals "Float" - p.extra[DefaultValue]?.value equals "3.14f" + p.extra[DefaultValue]?.value equals FloatConstant(3.14f) } } } diff --git a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt b/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt index 3c38e68c..d65a4f6e 100644 --- a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt +++ b/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt @@ -2,14 +2,13 @@ package renderers.html import org.jetbrains.dokka.base.renderers.html.HtmlRenderer import org.jetbrains.dokka.pages.TextStyle +import org.jetbrains.dokka.pages.TokenStyle import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.junit.jupiter.api.Test import renderers.testPage -import utils.B -import utils.I -import utils.STRIKE -import utils.match +import utils.* +import kotlin.test.assertEquals class TextStylesTest : HtmlRenderingOnlyTestBase() { @Test @@ -40,6 +39,16 @@ class TextStylesTest : HtmlRenderingOnlyTestBase() { } @Test + fun `should include token styles`(){ + val page = testPage { + text("keyword", styles = setOf(TokenStyle.Keyword)) + } + HtmlRenderer(context).render(page) + renderedContent.match(Span("keyword")) + assertEquals(renderedContent.children().last().attr("class"), "token keyword") + } + + @Test fun `should include multiple styles at one`(){ val page = testPage { text( diff --git a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt index 35d91175..e631117f 100644 --- a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt @@ -44,7 +44,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -62,7 +63,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -80,7 +82,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -98,7 +101,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (param: ", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": (param: ", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -117,7 +121,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -135,7 +140,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -153,7 +159,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": suspend ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -171,7 +178,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (param: ", A("Int"), ") -> ", A("String"), Span() + "val ", A("nF"), ": suspend (param: ", A("Int"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -202,7 +210,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { A("Boolean"), ") -> ", A("String"), - Span() + Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -227,7 +236,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-java-class/index.html").signature().last().match( - "open val ", A("javaFunction"), ": (", A("Integer"), ") -> ", A("String"), Span() + "open val ", A("javaFunction"), ": (", A("Integer"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -252,7 +262,8 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-java-class/index.html").signature().last().match( - "open val ", A("kotlinFunction"), ": (", A("Integer"), ") -> ", A("String"), Span() + "open val ", A("kotlinFunction"), ": (", A("Integer"), ") -> ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt index a56c408b..d8b23d77 100644 --- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt @@ -36,7 +36,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(): ", A("String"), Span() + "fun ", A("simpleFun"), "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -54,7 +55,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "open fun ", A("simpleFun"), "(): ", A("String"), Span() + "open fun ", A("simpleFun"), "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -72,7 +74,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "open suspend fun ", A("simpleFun"), "(): ", A("String"), Span() + "open suspend fun ", A("simpleFun"), "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -92,7 +95,8 @@ class SignatureTest : BaseAbstractTest() { writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "fun ", A("simpleFun"), "(a: ", A("Int"), ", b: ", A("Boolean"), ", c: ", A("Any"), - "): ", A("String"), Span() + "): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -111,7 +115,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "fun ", A("simpleFun"), "(a: (", A("Int"), - ") -> ", A("String"), "): ", A("String"), Span() + ") -> ", A("String"), "): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -130,7 +135,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "fun <", A("T"), "> ", A("simpleFun"), "(): ", - A("T"), Span() + A("T"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -149,7 +155,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), - "(): ", A("T"), Span() + "(): ", A("T"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -168,7 +175,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "inline suspend fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), - "(a: ", A("Int"), ", b: ", A("String"), "): ", A("T"), Span() + "(a: ", A("Int"), ", b: ", A("String"), "): ", A("T"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -186,7 +194,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(vararg params: ", A("Int"), ")", Span() + "fun ", A("simpleFun"), "(vararg params: ", A("Int"), ")", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -204,7 +213,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-simple-class/index.html").firstSignature().match( - "class ", A("SimpleClass"), Span() + "class ", A("SimpleClass"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -223,7 +233,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-inheriting-class-from-generic-type/index.html").firstSignature().match( "class ", A("InheritingClassFromGenericType"), " <", A("T"), " : ", A("Number"), ", ", A("R"), " : ", A("CharSequence"), - "> : ", A("Comparable"), "<", A("T"), "> , ", A("Collection"), "<", A("R"), ">", Span() + "> : ", A("Comparable"), "<", A("T"), "> , ", A("Collection"), "<", A("R"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -241,7 +252,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-k-runnable/index.html").firstSignature().match( - "fun interface ", A("KRunnable"), Span() + "fun interface ", A("KRunnable"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -273,7 +285,8 @@ class SignatureTest : BaseAbstractTest() { Div("@", A("Marking")) ), "fun ", A("simpleFun"), - "(): ", A("String"), Span() + "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -307,7 +320,8 @@ class SignatureTest : BaseAbstractTest() { Div("@set:", A("Marking")) ), "var ", A("str"), - ": ", A("String"), Span() + ": ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -347,7 +361,8 @@ class SignatureTest : BaseAbstractTest() { Div("@", A("Marking2"), "(", Span("int = ", Span("1")), Wbr, ")") ), "fun ", A("simpleFun"), - "(): ", A("String"), Span() + "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -387,7 +402,8 @@ class SignatureTest : BaseAbstractTest() { ) ), "fun ", A("simpleFun"), - "(): ", A("String"), Span() + "(): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -436,7 +452,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("test/example/-foo/index.html").signature().toList()[1].match( - "typealias ", A("Foo"), " = ", A("Bar"), Span() + "typealias ", A("Foo"), " = ", A("Bar"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -460,7 +477,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example.html").signature().first().match( - "typealias ", A("PlainTypealias"), " = ", A("Int"), Span() + "typealias ", A("PlainTypealias"), " = ", A("Int"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -494,7 +512,8 @@ class SignatureTest : BaseAbstractTest() { "@", A("SomeAnnotation") ) ), - "typealias ", A("PlainTypealias"), " = ", A("Int"), Span() + "typealias ", A("PlainTypealias"), " = ", A("Int"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -519,7 +538,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example.html").signature().first().match( "typealias ", A("PlainTypealias"), " = ", A("Comparable"), - "<", A("Int"), ">", Span() + "<", A("Int"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -545,7 +565,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example.html").signature().first().match( "typealias ", A("GenericTypealias"), "<", A("T"), "> = ", A("Comparable"), - "<", A("T"), ">", Span() + "<", A("T"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -573,7 +594,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( "fun ", A("someFun"), "(xd: ", A("XD"), "<", A("Int"), - ", ", A("String"), ">):", A("Int"), Span() + ", ", A("String"), ">):", A("Int"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -618,7 +640,7 @@ class SignatureTest : BaseAbstractTest() { arrayOf("fun ", A("GenericClass"), "(x: ", A("Int"), ")", Span()), ) ).forEach { - it.first.match(*it.second) + it.first.match(*it.second, ignoreSpanWithTokenStyle = true) } } } @@ -637,7 +659,8 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( "fun", A("simpleFun"), "(int: ", A("Int"), " = 1, string: ", A("String"), - " = \"string\"): ", A("String"), Span() + " = \"string\"): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -655,7 +678,8 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "const val ", A("simpleVal"), ": ", A("Int"), " = 1", Span() + "const val ", A("simpleVal"), ": ", A("Int"), " = 1", Span(), + ignoreSpanWithTokenStyle = true ) } } diff --git a/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt index d988bafe..c5d49cec 100644 --- a/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt @@ -38,7 +38,8 @@ class VarianceSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<in ", A("T"), ">", Span() + "class ", A("Generic"), "<in ", A("T"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -56,7 +57,8 @@ class VarianceSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<out ", A("T"), ">", Span() + "class ", A("Generic"), "<out ", A("T"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -74,7 +76,8 @@ class VarianceSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<", A("T"), ">", Span() + "class ", A("Generic"), "<", A("T"), ">", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -92,7 +95,8 @@ class VarianceSignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<out ", A("T"), ":", A("List"), "<", A("CharSequence"), ">>", Span() + "class ", A("Generic"), "<out ", A("T"), ":", A("List"), "<", A("CharSequence"), ">>", Span(), + ignoreSpanWithTokenStyle = true ) } } |