From 8e5c63d035ef44a269b8c43430f43f5c8eebfb63 Mon Sep 17 00:00:00 2001 From: Ignat Beresnev Date: Fri, 10 Nov 2023 11:46:54 +0100 Subject: Restructure the project to utilize included builds (#3174) * Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich --- .../innerTemplating/DefaultTemplateModelFactory.kt | 234 --------------------- .../innerTemplating/DefaultTemplateModelMerger.kt | 20 -- .../html/innerTemplating/HtmlTemplater.kt | 82 -------- .../html/innerTemplating/TemplateModelFactory.kt | 19 -- .../html/innerTemplating/TemplateModelMerger.kt | 9 - 5 files changed, 364 deletions(-) delete mode 100644 plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt delete mode 100644 plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt delete mode 100644 plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt delete mode 100644 plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt delete mode 100644 plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt (limited to 'plugins/base/src/main/kotlin/renderers/html/innerTemplating') diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt deleted file mode 100644 index fe6f0089..00000000 --- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.base.renderers.html.innerTemplating - -import freemarker.core.Environment -import freemarker.template.* -import kotlinx.html.* -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.DokkaBaseConfiguration -import org.jetbrains.dokka.base.renderers.URIExtension -import org.jetbrains.dokka.base.renderers.html.TEMPLATE_REPLACEMENT -import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer -import org.jetbrains.dokka.base.renderers.html.templateCommand -import org.jetbrains.dokka.base.renderers.html.templateCommandAsHtmlComment -import org.jetbrains.dokka.base.renderers.isImage -import org.jetbrains.dokka.base.resolvers.local.LocationProvider -import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand -import org.jetbrains.dokka.base.templating.ProjectNameSubstitutionCommand -import org.jetbrains.dokka.base.templating.ReplaceVersionsCommand -import org.jetbrains.dokka.base.templating.SubstitutionCommand -import org.jetbrains.dokka.model.DisplaySourceSet -import org.jetbrains.dokka.model.withDescendants -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.PageNode -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.configuration -import java.net.URI - -public class DefaultTemplateModelFactory( - public val context: DokkaContext -) : TemplateModelFactory { - private val configuration = configuration(context) - private val isPartial = context.configuration.delayTemplateSubstitution - - private fun TagConsumer.prepareForTemplates() = - if (context.configuration.delayTemplateSubstitution || this is ImmediateResolutionTagConsumer) this - else ImmediateResolutionTagConsumer(this, context) - - public data class SourceSetModel(val name: String, val platform: String, val filter: String) - - override fun buildModel( - page: PageNode, - resources: List, - locationProvider: LocationProvider, - content: String - ): TemplateMap { - val path = locationProvider.resolve(page) - val pathToRoot = locationProvider.pathToRoot(page) - val mapper = mutableMapOf() - mapper["pageName"] = page.name - mapper["resources"] = PrintDirective { - val sb = StringBuilder() - if (isPartial) - sb.templateCommandAsHtmlComment( - PathToRootSubstitutionCommand( - TEMPLATE_REPLACEMENT, - default = pathToRoot - ) - ) { resourcesForPage(TEMPLATE_REPLACEMENT, resources) } - else - sb.resourcesForPage(pathToRoot, resources) - sb.toString() - } - mapper["content"] = PrintDirective { content } - mapper["version"] = PrintDirective { - createHTML().prepareForTemplates().templateCommand(ReplaceVersionsCommand(path.orEmpty())) - } - mapper["template_cmd"] = TemplateDirective(context.configuration, pathToRoot) - - if (page is ContentPage) { - val sourceSets = page.content.withDescendants() - .flatMap { it.sourceSets } - .distinct() - .sortedBy { it.comparableKey } - .map { SourceSetModel(it.name, it.platform.key, it.sourceSetIDs.merged.toString()) } - .toList() - - if (sourceSets.isNotEmpty()) { - mapper["sourceSets"] = sourceSets - } - } - return mapper - } - - override fun buildSharedModel(): TemplateMap { - val mapper = mutableMapOf() - - mapper["footerMessage"] = - (configuration?.footerMessage?.takeIf(String::isNotBlank) ?: DokkaBaseConfiguration.defaultFooterMessage) - - configuration?.homepageLink?.takeIf(String::isNotBlank)?.let { mapper["homepageLink"] = it } - - return mapper - } - - private val DisplaySourceSet.comparableKey - get() = sourceSetIDs.merged.let { it.scopeId + it.sourceSetName } - private val String.isAbsolute: Boolean - get() = URI(this).isAbsolute - - private fun Appendable.resourcesForPage(pathToRoot: String, resources: List): Unit = - resources.forEach { resource -> - - val resourceHtml = with(createHTML()) { - when { - - resource.URIExtension == "css" -> - link( - rel = LinkRel.stylesheet, - href = if (resource.isAbsolute) resource else "$pathToRoot$resource" - ) - - resource.URIExtension == "js" -> - script( - type = ScriptType.textJavaScript, - src = if (resource.isAbsolute) resource else "$pathToRoot$resource" - ) { - if (resource == "scripts/main.js" || resource.endsWith("_deferred.js")) - defer = true - else - async = true - } - - resource.isImage() -> link(href = if (resource.isAbsolute) resource else "$pathToRoot$resource") - else -> null - } - } - if (resourceHtml != null) { - append(resourceHtml) - } - } - -} - -private class PrintDirective(val generateData: () -> String) : TemplateDirectiveModel { - override fun execute( - env: Environment, - params: MutableMap?, - loopVars: Array?, - body: TemplateDirectiveBody? - ) { - if (params?.isNotEmpty() == true) throw TemplateModelException( - "Parameters are not allowed" - ) - if (loopVars?.isNotEmpty() == true) throw TemplateModelException( - "Loop variables are not allowed" - ) - env.out.write(generateData()) - } -} - -private class TemplateDirective( - val configuration: DokkaConfiguration, - val pathToRoot: String -) : TemplateDirectiveModel { - override fun execute( - env: Environment, - params: MutableMap?, - loopVars: Array?, - body: TemplateDirectiveBody? - ) { - val commandName = params?.get(PARAM_NAME) ?: throw TemplateModelException( - "The required $PARAM_NAME parameter is missing." - ) - val replacement = (params[PARAM_REPLACEMENT] as? SimpleScalar)?.asString ?: TEMPLATE_REPLACEMENT - - when ((commandName as? SimpleScalar)?.asString) { - "pathToRoot" -> { - body ?: throw TemplateModelException( - "No directive body for $commandName command." - ) - executeSubstituteCommand( - PathToRootSubstitutionCommand( - replacement, pathToRoot - ), - "pathToRoot", - pathToRoot, - Context(env, body) - ) - } - - "projectName" -> { - body ?: throw TemplateModelException( - "No directive body $commandName command." - ) - executeSubstituteCommand( - ProjectNameSubstitutionCommand( - replacement, configuration.moduleName - ), - "projectName", - configuration.moduleName, - Context(env, body) - ) - } - - else -> throw TemplateModelException( - "The parameter $PARAM_NAME $commandName is unknown" - ) - } - } - - private data class Context(val env: Environment, val body: TemplateDirectiveBody) - - private fun executeSubstituteCommand( - command: SubstitutionCommand, - name: String, - value: String, - ctx: Context - ) { - if (configuration.delayTemplateSubstitution) - ctx.env.out.templateCommandAsHtmlComment(command) { - renderWithLocalVar(name, command.pattern, ctx) - } - else { - renderWithLocalVar(name, value, ctx) - } - } - - private fun renderWithLocalVar(name: String, value: String, ctx: Context) = - with(ctx) { - env.setVariable(name, SimpleScalar(value)) - body.render(env.out) - env.setVariable(name, null) - } - - companion object { - const val PARAM_NAME = "name" - const val PARAM_REPLACEMENT = "replacement" - } -} diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt deleted file mode 100644 index 2f17183d..00000000 --- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.base.renderers.html.innerTemplating - -public class DefaultTemplateModelMerger : TemplateModelMerger { - override fun invoke( - factories: List, - buildModel: TemplateModelFactory.() -> TemplateMap - ): TemplateMap { - val mapper = mutableMapOf() - factories.map(buildModel).forEach { partialModel -> - partialModel.forEach { (k, v) -> - mapper[k] = v - } - } - return mapper - } -} diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt deleted file mode 100644 index 1638c9c0..00000000 --- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.base.renderers.html.innerTemplating - -import freemarker.cache.ClassTemplateLoader -import freemarker.cache.FileTemplateLoader -import freemarker.cache.MultiTemplateLoader -import freemarker.log.Logger -import freemarker.template.Configuration -import freemarker.template.TemplateExceptionHandler -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.DokkaBaseConfiguration -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.configuration -import java.io.StringWriter - - -public enum class DokkaTemplateTypes( - public val path: String -) { - BASE("base.ftl") -} - -public typealias TemplateMap = Map - -public class HtmlTemplater( - context: DokkaContext -) { - - init { - // to disable logging, but it isn't reliable see [Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY] - // (use SLF4j further) - System.setProperty( - Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY, - System.getProperty(Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY) ?: Logger.LIBRARY_NAME_NONE - ) - } - - private val configuration = configuration(context) - private val templaterConfiguration = - Configuration(Configuration.VERSION_2_3_31).apply { configureTemplateEngine() } - - private fun Configuration.configureTemplateEngine() { - val loaderFromResources = ClassTemplateLoader(javaClass, "/dokka/templates") - templateLoader = configuration?.templatesDir?.let { - MultiTemplateLoader( - arrayOf( - FileTemplateLoader(it), - loaderFromResources - ) - ) - } ?: loaderFromResources - - unsetLocale() - defaultEncoding = "UTF-8" - templateExceptionHandler = TemplateExceptionHandler.RETHROW_HANDLER - logTemplateExceptions = false - wrapUncheckedExceptions = true - fallbackOnNullLoopVariable = false - templateUpdateDelayMilliseconds = Long.MAX_VALUE - } - - public fun setupSharedModel(model: TemplateMap) { - templaterConfiguration.setSharedVariables(model) - } - - public fun renderFromTemplate( - templateType: DokkaTemplateTypes, - generateModel: () -> TemplateMap - ): String { - val out = StringWriter() - // Freemarker has own thread-safe cache to keep templates - val template = templaterConfiguration.getTemplate(templateType.path) - val model = generateModel() - template.process(model, out) - - return out.toString() - } -} - diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt deleted file mode 100644 index 3af11bf9..00000000 --- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.base.renderers.html.innerTemplating - -import org.jetbrains.dokka.base.resolvers.local.LocationProvider -import org.jetbrains.dokka.pages.PageNode - -public interface TemplateModelFactory { - public fun buildModel( - page: PageNode, - resources: List, - locationProvider: LocationProvider, - content: String - ): TemplateMap - - public fun buildSharedModel(): TemplateMap -} diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt deleted file mode 100644 index ada0c6cd..00000000 --- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.base.renderers.html.innerTemplating - -public fun interface TemplateModelMerger { - public fun invoke(factories: List, buildModel: TemplateModelFactory.() -> TemplateMap): TemplateMap -} -- cgit