Skip to content

Commit

Permalink
KT-50452 Make flexible html for customization (#2374)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmishenev committed Mar 10, 2022
1 parent 8537f0f commit 597b365
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 138 deletions.
41 changes: 36 additions & 5 deletions docs/src/doc/docs/user_guide/base-specific/frontend.md
Expand Up @@ -2,12 +2,12 @@

## Prerequisites

Dokka's Html format requires a web server to view documentation correctly.
Dokka's HTML format requires a web server to view documentation correctly.
This can be achieved by using the one that is build in IntelliJ or providing your own.
If this requisite is not fulfilled Dokka with fail to load navigation pane and search bars.

!!! important
Concepts specified below apply only to configuration of the Base Plugin (that contains Html format)
Concepts specified below apply only to configuration of the Base Plugin (that contains HTML format)
and needs to be applied via pluginsConfiguration and not on the root one.

## Modifying assets
Expand All @@ -20,19 +20,21 @@ Currently, user can modify:

Every file provided in those values will be applied to **every** page.

Dokka uses 3 stylesheets:
Dokka uses 4 stylesheets:

* `style.css` - main css file responsible for styling the page
* `jetbrains-mono.css` - fonts used across dokka
* `logo-styles.css` - logo styling
* [`prism.css`](https://github.com/Kotlin/dokka/blob/master/plugins/base/src/main/resources/dokka/styles/prism.css) - code highlighting

User can choose to add or override those files.
Also, it uses js scripts. The actual ones are [here](https://github.com/Kotlin/dokka/tree/master/plugins/base/src/main/resources/dokka/scripts).
User can choose to add or override those files - stylesheets and js scripts.
Resources will be overridden when in `pluginConfiguration` block there is a resource with the same name.

## Modifying footer

Dokka supports custom messages in the footer via `footerMessage` string property on base plugin configuration.
Keep in mind that this value will be passed exactly to the output html, so it has to be valid and escaped correctly.
Keep in mind that this value will be passed exactly to the output HTML, so it has to be valid and escaped correctly.

## Separating inherited members

Expand Down Expand Up @@ -69,3 +71,32 @@ In order to override a logo and style it accordingly a css file named `logo-styl


For build system specific instructions please visit dedicated pages: [gradle](../gradle/usage.md#applying-plugins), [maven](../maven/usage.md#applying-plugins) and [cli](../cli/usage.md#configuration-options)

## Custom HTML pages

Templates are taken from the folder that is defined by the `templatesDir` property.
To customize HTML output, you can use the [default template](https://github.com/Kotlin/dokka/blob/master/plugins/base/src/main/resources/dokka/templates) as a starting point.

!!! note
To change page assets, you can set properties `customAssets` and `customStyleSheets`.
Assets are handled by Dokka itself, not FreeMaker.

Currently, there is only one template file with predefined name `base.ftl`. It defines general design of all pages to render.
If `templatesDir` is defined, Dokka will find the `base.ftl` file there.

Variables given below are available to the template:
- `${pageName}` - the page name
- `${footerMessage}` - text that is set by the `footerMessage` property
- `${sourceSets}` - a nullable list of source sets, only for multi-platform pages. Each source set has `name`, `platfrom` and `filter` properties.

Also, Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html) can be used:
- `<@content/>` - main content
- `<@resources/>` - scripts, stylesheets
- `<@version/>` - version ([versioning-plugin](https://kotlin.github.io/dokka/1.6.10/user_guide/versioning/versioning/) will replace this with a version navigator)
- `<@template_cmd name="...""> ...</@template_cmd>` - is used for variables that depend on the root project (such `pathToRoot`, `projectName`). They are available only inside the directive. This is processed by a multi-module task that assembles partial outputs from modules.
Example:
```
<@template_cmd name="projectName">
<span>${projectName}</span>
</@template_cmd>
```
1 change: 1 addition & 0 deletions gradle.properties
Expand Up @@ -11,6 +11,7 @@ jsoup_version=1.13.1
idea_version=211.7442.40
language_version=1.4
jackson_version=2.12.4
freemarker_version=2.3.31
# Code style
kotlin.code.style=official
# Gradle settings
Expand Down
63 changes: 59 additions & 4 deletions plugins/base/api/base.api
Expand Up @@ -71,34 +71,38 @@ public final class org/jetbrains/dokka/base/DokkaBaseConfiguration : org/jetbrai
public static final field mergeImplicitExpectActualDeclarationsDefault Z
public static final field separateInheritedMembersDefault Z
public fun <init> ()V
public fun <init> (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;Z)V
public synthetic fun <init> (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZLjava/io/File;)V
public synthetic fun <init> (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZLjava/io/File;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/util/List;
public final fun component2 ()Ljava/util/List;
public final fun component3 ()Z
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Z
public final fun copy (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;Z)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;
public final fun component6 ()Ljava/io/File;
public final fun copy (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZLjava/io/File;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZLjava/io/File;ILjava/lang/Object;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;
public fun equals (Ljava/lang/Object;)Z
public final fun getCustomAssets ()Ljava/util/List;
public final fun getCustomStyleSheets ()Ljava/util/List;
public final fun getFooterMessage ()Ljava/lang/String;
public final fun getMergeImplicitExpectActualDeclarations ()Z
public final fun getSeparateInheritedMembers ()Z
public final fun getTemplatesDir ()Ljava/io/File;
public fun hashCode ()I
public final fun setCustomAssets (Ljava/util/List;)V
public final fun setCustomStyleSheets (Ljava/util/List;)V
public final fun setFooterMessage (Ljava/lang/String;)V
public final fun setMergeImplicitExpectActualDeclarations (Z)V
public final fun setSeparateInheritedMembers (Z)V
public final fun setTemplatesDir (Ljava/io/File;)V
public fun toString ()Ljava/lang/String;
}

public final class org/jetbrains/dokka/base/DokkaBaseConfiguration$Companion {
public final fun getDefaultCustomAssets ()Ljava/util/List;
public final fun getDefaultCustomStyleSheets ()Ljava/util/List;
public final fun getDefaultFooterMessage ()Ljava/lang/String;
public final fun getDefaultTemplatesDir ()Ljava/io/File;
}

public final class org/jetbrains/dokka/base/generation/SingleModuleGeneration : org/jetbrains/dokka/generation/Generation {
Expand Down Expand Up @@ -216,6 +220,7 @@ public final class org/jetbrains/dokka/base/parsers/moduleAndPackage/ParseModule
}

public final class org/jetbrains/dokka/base/renderers/ContentTypeCheckingKt {
public static final fun getURIExtension (Ljava/lang/String;)Ljava/lang/String;
public static final fun isImage (Ljava/lang/String;)Z
public static final fun isImage (Lorg/jetbrains/dokka/pages/ContentEmbeddedResource;)Z
}
Expand Down Expand Up @@ -526,6 +531,7 @@ public final class org/jetbrains/dokka/base/renderers/html/TagsKt {
public static final fun templateCommand (Lkotlinx/html/TagConsumer;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static synthetic fun templateCommand$default (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun templateCommand$default (Lkotlinx/html/TagConsumer;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
public static final fun templateCommandAsHtmlComment (Ljava/lang/Appendable;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;)V
public static final fun templateCommandAsHtmlComment (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun templateCommandAsHtmlComment$default (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static final fun templateCommandFor (Lorg/jetbrains/dokka/base/templating/Command;Lkotlinx/html/TagConsumer;)Lorg/jetbrains/dokka/base/renderers/html/TemplateCommand;
Expand Down Expand Up @@ -578,6 +584,55 @@ public final class org/jetbrains/dokka/base/renderers/html/command/consumers/Res
public fun processCommandAndFinalize (Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/dokka/base/renderers/html/command/consumers/ImmediateResolutionTagConsumer;)Ljava/lang/Object;
}

public final class org/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelFactory : org/jetbrains/dokka/base/renderers/html/innerTemplating/TemplateModelFactory {
public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
public fun buildModel (Lorg/jetbrains/dokka/pages/PageNode;Ljava/util/List;Lorg/jetbrains/dokka/base/resolvers/local/LocationProvider;ZLjava/lang/String;)Ljava/util/Map;
public fun buildSharedModel ()Ljava/util/Map;
public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
}

public final class org/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelFactory$SourceSetModel {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelFactory$SourceSetModel;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelFactory$SourceSetModel;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelFactory$SourceSetModel;
public fun equals (Ljava/lang/Object;)Z
public final fun getFilter ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
public final fun getPlatform ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class org/jetbrains/dokka/base/renderers/html/innerTemplating/DefaultTemplateModelMerger : org/jetbrains/dokka/base/renderers/html/innerTemplating/TemplateModelMerger {
public fun <init> ()V
public fun invoke (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
}

public final class org/jetbrains/dokka/base/renderers/html/innerTemplating/DokkaTemplateTypes : java/lang/Enum {
public static final field BASE Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DokkaTemplateTypes;
public final fun getPath ()Ljava/lang/String;
public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DokkaTemplateTypes;
public static fun values ()[Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DokkaTemplateTypes;
}

public final class org/jetbrains/dokka/base/renderers/html/innerTemplating/HtmlTemplater {
public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
public final fun renderFromTemplate (Lorg/jetbrains/dokka/base/renderers/html/innerTemplating/DokkaTemplateTypes;Lkotlin/jvm/functions/Function0;)Ljava/lang/String;
public final fun setupSharedModel (Ljava/util/Map;)V
}

public abstract interface class org/jetbrains/dokka/base/renderers/html/innerTemplating/TemplateModelFactory {
public abstract fun buildModel (Lorg/jetbrains/dokka/pages/PageNode;Ljava/util/List;Lorg/jetbrains/dokka/base/resolvers/local/LocationProvider;ZLjava/lang/String;)Ljava/util/Map;
public abstract fun buildSharedModel ()Ljava/util/Map;
}

public abstract interface class org/jetbrains/dokka/base/renderers/html/innerTemplating/TemplateModelMerger {
public abstract fun invoke (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
}

public final class org/jetbrains/dokka/base/resolvers/anchors/SymbolAnchorHint : org/jetbrains/dokka/model/properties/ExtraProperty {
public static final field Companion Lorg/jetbrains/dokka/base/resolvers/anchors/SymbolAnchorHint$Companion;
public fun <init> (Ljava/lang/String;Lorg/jetbrains/dokka/pages/Kind;)V
Expand Down
4 changes: 4 additions & 0 deletions plugins/base/build.gradle.kts
Expand Up @@ -11,6 +11,10 @@ dependencies {

val jackson_version: String by project
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version")

val freemarker_version: String by project
implementation("org.freemarker:freemarker:$freemarker_version")

testImplementation(project(":plugins:base:base-test-utils"))
testImplementation(project(":core:content-matcher-test-utils"))

Expand Down
4 changes: 3 additions & 1 deletion plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt
Expand Up @@ -9,13 +9,15 @@ data class DokkaBaseConfiguration(
var customAssets: List<File> = defaultCustomAssets,
var separateInheritedMembers: Boolean = separateInheritedMembersDefault,
var footerMessage: String = defaultFooterMessage,
var mergeImplicitExpectActualDeclarations: Boolean = mergeImplicitExpectActualDeclarationsDefault
var mergeImplicitExpectActualDeclarations: Boolean = mergeImplicitExpectActualDeclarationsDefault,
var templatesDir: File? = defaultTemplatesDir
) : ConfigurableBlock {
companion object {
val defaultFooterMessage = "© ${Year.now().value} Copyright"
val defaultCustomStyleSheets: List<File> = emptyList()
val defaultCustomAssets: List<File> = emptyList()
const val separateInheritedMembersDefault: Boolean = false
const val mergeImplicitExpectActualDeclarationsDefault: Boolean = false
val defaultTemplatesDir: File? = null
}
}
Expand Up @@ -8,8 +8,11 @@ fun ContentEmbeddedResource.isImage(): Boolean {
return File(address).extension.toLowerCase() in imageExtensions
}

val String.URIExtension: String
get() = substringBefore('?').substringAfterLast('.')

fun String.isImage(): Boolean =
substringBefore('?').substringAfterLast('.') in imageExtensions
URIExtension in imageExtensions

object HtmlFileExtensions {
val imageExtensions = setOf("png", "jpg", "jpeg", "gif", "bmp", "tif", "webp", "svg")
Expand Down

0 comments on commit 597b365

Please sign in to comment.