From ccae21079f1e5249e795c9a2101b8b1dd20d7385 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 26 Oct 2022 13:50:19 +0200 Subject: [PATCH 01/14] Revise documentation --- .github/workflows/gh-pages.yml | 12 +- docs/README.md | 88 +++ docs/cfg/build-script.xml | 10 + docs/cfg/buildprofiles.xml | 42 ++ docs/dokka.tree | 24 + docs/images/dokkaHtmlCollector-example.png | Bin 0 -> 94387 bytes docs/images/dokkaHtmlMultiModule-example.png | Bin 0 -> 52393 bytes docs/images/javadoc-format-example.png | Bin 0 -> 168563 bytes docs/images/versioning-plugin-example.png | Bin 0 -> 43684 bytes docs/project.ihp | 10 + docs/topics/formats/html.md | 278 +++++++++ docs/topics/formats/javadoc.md | 92 +++ docs/topics/formats/markdown.md | 172 ++++++ docs/topics/overview.md | 21 + docs/topics/plugins/plugins_introduction.md | 261 +++++++++ docs/topics/plugins/versioning.md | 315 ++++++++++ docs/topics/runners/cli.md | 288 ++++++++++ docs/topics/runners/gradle.md | 539 ++++++++++++++++++ docs/topics/runners/maven.md | 227 ++++++++ docs/vars.list | 9 + {docs => mkdocs}/build.gradle.kts | 0 .../src/doc/docs/community/plugins-list.md | 0 .../src/doc/docs/community/slack.md | 0 .../architecture/architecture_overview.md | 0 .../architecture/data_model/documentables.md | 0 .../architecture/data_model/extra.md | 0 .../architecture/data_model/page_content.md | 0 .../extension_points/base_extensions.md | 0 .../extension_points/core_extensions.md | 0 .../extension_points/introduction.md | 0 .../doc/docs/developer_guide/introduction.md | 0 .../plugin-development/introduction.md | 0 .../sample-plugin-tutorial.md | 0 .../src/doc/docs/developer_guide/workflow.md | 0 .../src/doc/docs/dokka_colors.css | 0 {docs => mkdocs}/src/doc/docs/faq.md | 0 {docs => mkdocs}/src/doc/docs/favicon.svg | 0 .../src/doc/docs/images/mathjax_demo.png | Bin .../src/doc/docs/images/mermaid_demo.png | Bin {docs => mkdocs}/src/doc/docs/index.md | 0 .../src/doc/docs/survey_banner.js | 2 +- .../src/doc/docs/user_guide/applying/cli.md | 0 .../doc/docs/user_guide/applying/gradle.md | 0 .../src/doc/docs/user_guide/applying/maven.md | 0 .../src/doc/docs/user_guide/introduction.md | 0 .../docs/user_guide/output-formats/html.md | 0 .../docs/user_guide/plugins/android-plugin.md | 0 .../user_guide/plugins/versioning-plugin.md | 0 {docs => mkdocs}/src/doc/mkdocs.yml | 0 settings.gradle.kts | 4 +- 50 files changed, 2385 insertions(+), 9 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/cfg/build-script.xml create mode 100644 docs/cfg/buildprofiles.xml create mode 100644 docs/dokka.tree create mode 100644 docs/images/dokkaHtmlCollector-example.png create mode 100644 docs/images/dokkaHtmlMultiModule-example.png create mode 100644 docs/images/javadoc-format-example.png create mode 100644 docs/images/versioning-plugin-example.png create mode 100644 docs/project.ihp create mode 100644 docs/topics/formats/html.md create mode 100644 docs/topics/formats/javadoc.md create mode 100644 docs/topics/formats/markdown.md create mode 100644 docs/topics/overview.md create mode 100644 docs/topics/plugins/plugins_introduction.md create mode 100644 docs/topics/plugins/versioning.md create mode 100644 docs/topics/runners/cli.md create mode 100644 docs/topics/runners/gradle.md create mode 100644 docs/topics/runners/maven.md create mode 100644 docs/vars.list rename {docs => mkdocs}/build.gradle.kts (100%) rename {docs => mkdocs}/src/doc/docs/community/plugins-list.md (100%) rename {docs => mkdocs}/src/doc/docs/community/slack.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/architecture_overview.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/data_model/documentables.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/data_model/extra.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/data_model/page_content.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/extension_points/base_extensions.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/extension_points/core_extensions.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/architecture/extension_points/introduction.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/introduction.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/plugin-development/introduction.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/plugin-development/sample-plugin-tutorial.md (100%) rename {docs => mkdocs}/src/doc/docs/developer_guide/workflow.md (100%) rename {docs => mkdocs}/src/doc/docs/dokka_colors.css (100%) rename {docs => mkdocs}/src/doc/docs/faq.md (100%) rename {docs => mkdocs}/src/doc/docs/favicon.svg (100%) rename {docs => mkdocs}/src/doc/docs/images/mathjax_demo.png (100%) rename {docs => mkdocs}/src/doc/docs/images/mermaid_demo.png (100%) rename {docs => mkdocs}/src/doc/docs/index.md (100%) rename {docs => mkdocs}/src/doc/docs/survey_banner.js (99%) rename {docs => mkdocs}/src/doc/docs/user_guide/applying/cli.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/applying/gradle.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/applying/maven.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/introduction.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/output-formats/html.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/plugins/android-plugin.md (100%) rename {docs => mkdocs}/src/doc/docs/user_guide/plugins/versioning-plugin.md (100%) rename {docs => mkdocs}/src/doc/mkdocs.yml (100%) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 9a744d38a8..8bb860fe92 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -19,8 +19,8 @@ jobs: id: filter with: filters: | - docs_changed: - - 'docs/**' + mkdocs_changed: + - 'mkdocs/**' working-directory: ./dokka - uses: actions/setup-java@v3 with: @@ -30,17 +30,17 @@ jobs: - uses: gradle/gradle-build-action@v2 - name: Get current dokka version run: echo "DOKKA_VERSION=`./gradlew :properties | grep '^version:.*' | cut -d ' ' -f 2`" >> $GITHUB_ENV - if: github.event_name == 'release' || steps.filter.outputs.docs_changed == 'true' + if: github.event_name == 'release' || steps.filter.outputs.mkdocs_changed == 'true' working-directory: ./dokka - name: Build docs run: ./gradlew mkdocsBuild -Pdokka_version=$DOKKA_VERSION --info - if: github.event_name == 'release' || steps.filter.outputs.docs_changed == 'true' + if: github.event_name == 'release' || steps.filter.outputs.mkdocs_changed == 'true' working-directory: ./dokka - name: Deploy uses: peaceiris/actions-gh-pages@v3 - if: github.event_name == 'release' || steps.filter.outputs.docs_changed == 'true' + if: github.event_name == 'release' || steps.filter.outputs.mkdocs_changed == 'true' with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./dokka/docs/build/mkdocs + publish_dir: ./dokka/mkdocs/build/mkdocs keep_files: true full_commit_message: Publish ${{ env.DOKKA_VERSION }} documentation diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..52e982d7c2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,88 @@ +# docs + +This module contains documentation for Dokka that is deployed to [kotlinlang.org](https://kotlinlang.org/) + +Documentation format is basically markdown with some DSL that is used internally at JetBrains. + +## Project structure + +* `dokka.tree` represents Table of Contents +* `vars.list` contains variables that you can use throughout documentation +* `topics` directory contains documentation topics themselves + +## DSL + +### Title + +Each page must have a title. By default, this title is used in ToC as well. + +```text +[//]: # (title: Name of topic) +``` + +Note that title is basically a level 1 header, and it has to be the only one. So all other headers within topics must +be at least level 2, otherwise sidebar navigation may not work as expected. + +### Notes + +```text +> This is a simple note +> +{type="note"} +``` + +### Tips + +```text +> This is a useful tip +> +{type="tip"} +``` + +### Warning + +```text +> This is a warning +> +{type="warning"} +``` + +### Tabs + +Tabs can be used to give instructions that are specific to a build system or something else. + +Content inside tabs is not limited to just text - it can be code blocks, tips, etc. + +```text + + + +Instructions specific to Kotlin + + + +Instructions specific to Groovy + + + +Instructions specific to Maven + + + +Instructions specific to CLI + + + +``` + +Notice the use of `group-key` - this groups all tabs on the page, and when the user switches to a tab - it switches to +all tabs with this key throughout the whole page. This is convenient for the user, since if they switched to Groovy tab, +they probably want other tabs to be of that value as well. + +## Documentation preview + +Unfortunately, at the moment, to properly preview documentation you need to be a JetBrains employee +or have access to internal infrastructure. + +If you do have access, download `Stardust` plugin (ask around for instructions), and on the right sidebar you'll see +`Stardust Article Preview` tab, open it. diff --git a/docs/cfg/build-script.xml b/docs/cfg/build-script.xml new file mode 100644 index 0000000000..8911c1e087 --- /dev/null +++ b/docs/cfg/build-script.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/docs/cfg/buildprofiles.xml b/docs/cfg/buildprofiles.xml new file mode 100644 index 0000000000..614e57fe7d --- /dev/null +++ b/docs/cfg/buildprofiles.xml @@ -0,0 +1,42 @@ + + + + + blue_romb_blt.png + seealso_blt.gif + topic.gif + folder.gif + note.gif + notice_purple.gif + tip.gif + mark.gif + iconpdf.png + moveUp.gif + hr.gif + bg_idea_big.jpg + IDEA.gif + images + printable.png + css + blt_pdf.png + http://www.jetbrains.com/idea/ + Developer Community:http://www.jetbrains.net/devnet/community/idea/kb + + 2 + jetbrains + true + true + true + null + https://support.jetbrains.com + webmaster@jetbrains.com + true + https://www.jetbrains.com/search/json/ + + + + + topic.web.new.xsl + + + \ No newline at end of file diff --git a/docs/dokka.tree b/docs/dokka.tree new file mode 100644 index 0000000000..eb1da12d24 --- /dev/null +++ b/docs/dokka.tree @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/dokkaHtmlCollector-example.png b/docs/images/dokkaHtmlCollector-example.png new file mode 100644 index 0000000000000000000000000000000000000000..5bd74d8d58b56c02293b50de52c52d93a7b2d05c GIT binary patch literal 94387 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≧QGS2 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

f+Xq|rKdXJ({5iQ5@|o%Tn18Ayyg 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 + + + + + + + + + diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md new file mode 100644 index 0000000000..8004d82086 --- /dev/null +++ b/docs/topics/formats/html.md @@ -0,0 +1,278 @@ +[//]: # (title: HTML) + +HTML is Dokka's default and recommended format. You can see it in action by browsing documentation +for [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/). + +## Generating HTML documentation + +This format comes standard in all runners: + +* For [Gradle](gradle.md#generating-documentation), run `dokkaHtml` or `dokkaHtmlMultiModule` tasks. +* For [Maven](maven.md#generating-documentation), run `dokka:dokka` goal. +* For [CLI runner](cli.md), run it with [HTML dependencies](cli.md#generating-documentation). + +> HTML pages generated by this format require a web server in order to render everything correctly. +> +> You can use any free static site hosting service, such as +> [GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages). +> +> Locally, you can use the [built-in IntelliJ web server](https://www.jetbrains.com/help/idea/php-built-in-web-server.html). +> +{type="note"} + +## Configuration + +HTML format is Dokka's base format, so it is configurable through `DokkaBase` and `DokkaBaseConfiguration`. + + + + +Via type-safe Kotlin DSL: + +```kotlin +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.base.DokkaBaseConfiguration + +buildscript { + dependencies { + classpath("org.jetbrains.dokka:dokka-base:%dokkaVersion%") + } +} + +tasks.withType().configureEach { + pluginConfiguration { + customAssets = listOf(file("my-image.png")) + customStyleSheets = listOf(file("my-styles.css")) + footerMessage = "(c) 2022 MyOrg" + separateInheritedMembers = false + templatesDir = file("dokka/templates") + mergeImplicitExpectActualDeclarations = false + } +} +``` + +Via JSON: + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType().configureEach { + val dokkaBaseConfiguration = """ + { + "customAssets": ["${file("assets/my-image.png")}"], + "customStyleSheets": ["${file("assets/my-styles.css")}"], + "footerMessage": "(c) 2022 MyOrg", + "separateInheritedMembers": false, + "templatesDir": "${file("dokka/templates")}", + "mergeImplicitExpectActualDeclarations": false + } + """ + pluginsMapConfiguration.set( + mapOf( + // fully qualified plugin name to json configuration + "org.jetbrains.dokka.base.DokkaBase" to dokkaBaseConfiguration + ) + ) +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType(DokkaTask.class) { + String dokkaBaseConfiguration = """ + { + "customAssets": ["${file("assets/my-image.png")}"], + "customStyleSheets": ["${file("assets/my-styles.css")}"], + "footerMessage": "(c) 2022 MyOrg" + "separateInheritedMembers": false, + "templatesDir": "${file("dokka/templates")}", + "mergeImplicitExpectActualDeclarations": false + } + """ + pluginsMapConfiguration.set( + // fully qualified plugin name to json configuration + ["org.jetbrains.dokka.base.DokkaBase": dokkaBaseConfiguration] + ) +} +``` + + + + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + + + + ${project.basedir}/my-image.png + + + ${project.basedir}/my-styles.css + + (c) MyOrg 2022 Maven + false + ${project.basedir}/dokka/templates + false + + + + +``` + + + + +Via [command line arguments](cli.md#running-with-command-line-arguments): + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + ... + -pluginsConfiguration "org.jetbrains.dokka.base.DokkaBase={\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg\", \"separateInheritedMembers\": false, \"templatesDir\": \"dokka/templates\", \"mergeImplicitExpectActualDeclarations\": false} +" +``` + +Via [JSON configuration](cli.md#running-with-json-configuration): + +```json +{ + "moduleName": "Dokka Example", + "pluginsConfiguration": [ + { + "fqPluginName": "org.jetbrains.dokka.base.DokkaBase", + "serializationFormat": "JSON", + "values": "{\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg\", \"separateInheritedMembers\": false, \"templatesDir\": \"dokka/templates\", \"mergeImplicitExpectActualDeclarations\": false}" + } + ] +} +``` + + + + +For details, see [configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins) section. + +### Configuration options + +| **Option** | **Description** | +|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `customAssets` | List of paths for image assets to be bundled with documentation. Can have any extension. See [modifying assets](#customizing-assets) section for details. | +| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. See [modifying styles](#customizing-styles) section for details. | +| `footerMessage` | Text displayed in the footer. | +| `separateInheritedMembers` | Boolean property. If set to `true`, Dokka will render properties/functions and inherited properties/inherited functions separately. Disabled by default. | +| `templatesDir` | Path to the directory with custom HTML templates. See [templates](#templates) section for more details. | +| `mergeImplicitExpectActualDeclarations` | Boolean property. If set to true, Dokka will merge declarations that are not declared as expect/actual, but have the same fully qualified name. Can be useful in legacy codebases. Disabled by default. | + + +## Customization + +HTML format is highly customizable to the point where you wouldn't be able to tell it was generated by Dokka. + +### Customizing styles + +You can provide your own stylesheets by setting `customStyleSheets` +[configuration property](#configuration). These files will be applied to every page. + +Files with the same name will be overwritten, so it is possible to override stylesheets that Dokka uses: + +| **Stylesheet name** | **Description** | +|----------------------|---------------------------------------------------------------| +| `style.css` | Main stylesheet, contains most styles used across all pages | +| `logo-styles.css` | Header logo styling | +| `prism.css` | Styles for [PrismJS](https://prismjs.com/) syntax highlighter | +| `jetbrains-mono.css` | Font styling | + +All of these are +[available on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/styles). + +### Customizing assets + +You can provide your own images to be bundled with documentation by setting `customAssets` +[configuration property](#configuration). These files will be copied to `/images` directory. + +Files with the same name will be overwritten, so it is possible to override images and icons that Dokka uses. The most +useful and relevant one being `logo-icon.svg`, which is the image that's used in the header. The rest is mostly icons. + +You can view all images used by Dokka on +[GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/images). + +### Changing the logo + +To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. If your +image has similar size, it should not look out of place. + +However, if your image has different dimensions or you want to use a `.png` image instead of the default `.svg`, +you can [override `logo-styles.css` stylesheet](#customizing-styles). + +For more details, see +[custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). + +### Modifying footer + +You can modify the footer message by setting `footerMessage` [configuration property](#configuration). + +### Templates + +Dokka provides the ability to modify [FreeMarker](https://freemarker.apache.org/) templates used for generating +documentation pages. + +You can completely change the header, add your own banners/menus/search, load analytics, change body styling and so on. + +Dokka uses the following templates: + +| **Template** | **Description** | +|-----------------------------------|-------------------------------------------------------------------------------------------------------------------| +| `base.ftl` | Defines general design of all pages to be rendered. | +| `includes/header.ft` | Page header that by default contains the logo, version, source set selector, light/dark theme switch and search. | +| `includes/footer.ft` | Page footer that contains `footerMessage` [configuration property](#configuration) and copyright. | +| `includes/page_metadata.ft` | Metadata used within `` container. | +| `includes/source_set_selector.ft` | [Source set](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) selector in the header. | + +`base.ftl` template is the base template and it includes all the other ones. You can find all templates +[on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/templates). + +You can override any template by setting `templatesDir` [configuration property](#configuration). Dokka will look +for the exact template names within given directory. If it fails to find user-defined templates, it will use the +default ones. + +#### Variables + +Following variables are available inside all templates: + +| **Variable** | **Description** | +|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `${pageName}` | Page name | +| `${footerMessage}` | Text which is set by the `footerMessage` [configuration property](#configuration) | +| `${sourceSets}` | Nullable list of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for multi-platform pages. Each item has `name`, `platform` and `filter` properties. | +| `${projectName}` | Project name. Available only within `template_cmd` directive. | +| `${pathToRoot}` | Path to root from current page. Useful for locating assets. Available only within `template_cmd` directive. | + +Variables `projectName` and `pathToRoot` are available only within `@template_cmd` directive as they require more +context and thus need to be resolved at later stages by the [MultiModule](gradle.md#multi-project-builds) task: + +```html +<@template_cmd name="projectName"> + ${projectName} + +``` + +#### Directives + +Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html) can also be used: + +| **Variable** | **Description** | +|----------------------------|----------------------------------------------------------------------------------------------------------------------------------------| +| `<@content/>` | Main page content. | +| `<@resources/>` | Resources such as scripts and stylesheets. | +| `<@version/>` | Module version taken from configuration. If [versioning plugin](versioning.md) is applied, it will be replaced with version navigator. | + diff --git a/docs/topics/formats/javadoc.md b/docs/topics/formats/javadoc.md new file mode 100644 index 0000000000..a319d38a5d --- /dev/null +++ b/docs/topics/formats/javadoc.md @@ -0,0 +1,92 @@ +[//]: # (title: Javadoc) + +> Javadoc output format is still in Alpha, use at your own risk, expect bugs and migration issues. Correct +> integration with tools that accept Java's Javadoc HTML as input is not guaranteed. +> +{type="warning"} + +Dokka's Javadoc output format is a lookalike of Java's +[Javadoc HTML format](https://docs.oracle.com/en/java/javase/19/docs/api/index.html). + +It tries to visually mimic HTML pages generated by the Javadoc tool, but it's not a direct implementation +and it's not an exact copy. + +![Screenshot of javadoc output format](javadoc-format-example.png){height=750} + +All Kotlin code and signatures are rendered as seen from Java's perspective, this is achieved with +[Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and +applied by default for this format. + +Javadoc output format is a rendering [Dokka plugin](plugins_introduction.md), maintained by the Dokka team. +It is [open source](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). + +## Geneatring Javadoc documentation + +> Javadoc format does not support multiplatform projects. +> +{type="note"} + + + + + +Dokka's [Gradle plugin](gradle.md) ships with Javadoc format included, you can use the following tasks: + +| **Task** | **Description** | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJavadoc` | Generates Javadoc documentation for a single project. | +| `dokkaJavadocCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | + +`javadoc.jar` [can be built separately](gradle.md#building-javadoc-jar). + + + + +Dokka's [Maven plugin](maven.md) ships with Javadoc format built in, you can generate documentation +with the following goals: + +| **Goal** | **Description** | +|--------------------|------------------------------------------------------------------------------| +| `dokka:javadoc` | Generates documentation in Javadoc format | +| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in Javadoc format | + + + + + +Since Javadoc format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the +[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). + +Javadoc format has two dependencies that you will need to provide as jar files as well: + +* [kotlin-as-java plugin](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-as-java-plugin/%dokkaVersion%) +* [korte-jvm](https://mvnrepository.com/artifact/com.soywiz.korlibs.korte/korte-jvm/3.3.0) + +Via [command line arguments](cli.md#running-with-command-line-arguments): + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./javadoc-plugin-%dokkaVersion%.jar" \ + ... +``` + +Via [JSON configuration](cli.md#running-with-json-configuration): + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./kotlin-as-java-plugin-%dokkaVersion%.jar", + "./korte-jvm-3.3.0.jar", + "./javadoc-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + +For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. + + + diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/markdown.md new file mode 100644 index 0000000000..edae3fed6a --- /dev/null +++ b/docs/topics/formats/markdown.md @@ -0,0 +1,172 @@ +[//]: # (title: Markdown) + +> Markdown output formats are still in Alpha, use at your own risk, expect bugs and migration issues. +> +{type="warning"} + +Dokka is able to generate documentation in [GitHub Flavored](#gfm) and [Jekyll](#jekyll) compatible Markdown. + +These formats give you more freedom in terms of hosting documentation as the output can be embedded right into your +documentation website. For example, see [OkHttp's API reference](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) +pages. + +Markdown output formats are rendering [Dokka plugin](plugins_introduction.md), maintained by the Dokka team, and +they are open source. + +## GFM + +GFM format generates documentation in [GitHub Flavored Markdown](https://github.github.com/gfm/). + + + + +Dokka's [Gradle plugin](gradle.md) ships with GFM format included, you can use the following tasks: + +| **Task** | **Description** | +|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaGfm` | Generates GFM documentation for a single project. | +| `dokkaGfmMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. Generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaGfmCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | + + + + +Since GFM format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to apply it as a plugin +dependency: + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + org.jetbrains.dokka + gfm-plugin + %dokkaVersion% + + + + +``` + +After that, running `dokka:dokka` goal should produce documentation in GFM format. + +For more information, see [other output formats](maven.md#other-output-formats) section for the Maven plugin. + + + + +Since GFM format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the +[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) and pass it to +`pluginsClasspath`. + +Via [command line arguments](cli.md#running-with-command-line-arguments): + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./gfm-plugin-%dokkaVersion%.jar" \ + ... +``` + +Via [JSON configuration](cli.md#running-with-json-configuration): + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./gfm-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + +For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. + + + + +You can find sources [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/gfm). + +## Jekyll + +Jekyll format generates documentation in [Jekyll](https://jekyllrb.com/) compatible Markdown. + + + + +Dokka's [Gradle plugin](gradle.md) ships with Jekyll format included, you can use the following tasks: + +| **Task** | **Description** | +|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJekyll` | Generates Jekyll documentation for a single project. | +| `dokkaJekyllMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. Generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaJekyllCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | + + + + +Since Jekyll format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to apply it as a plugin +dependency: + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + org.jetbrains.dokka + jekyll-plugin + %dokkaVersion% + + + + +``` + +After that, running `dokka:dokka` goal should produce documentation in GFM format. + +For more information, see [other output formats](maven.md#other-output-formats) section for the Maven plugin. + + + + +Since Jekyll format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the +[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/jekyll-plugin/%dokkaVersion%). This format is also +based on [GFM](#gfm) format, so you need to provide it as a dependency as well. Both jars need to be passed to +`pluginsClasspath`: + +Via [command line arguments](cli.md#running-with-command-line-arguments): + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./gfm-plugin-%dokkaVersion%.jar;./jekyll-plugin-%dokkaVersion%.jar" \ + ... +``` + +Via [JSON configuration](cli.md#running-with-json-configuration): + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./gfm-plugin-%dokkaVersion%.jar", + "./jekyll-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + +For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. + + + + +You can find sources [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/jekyll). diff --git a/docs/topics/overview.md b/docs/topics/overview.md new file mode 100644 index 0000000000..ad8443d34d --- /dev/null +++ b/docs/topics/overview.md @@ -0,0 +1,21 @@ +[//]: # (title: Overview) + +Dokka is an API documentation engine for Kotlin. + +Just like Kotlin itself, Dokka supports mixed-language projects: it understands Kotlin's +[KDoc comments](https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax) and Java's +[Javadoc comments](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html). + +Dokka can generate documentation in multiple formats, including its own and modern [HTML format](html.md), +multiple flavours of [Markdown](markdown.md) and Java's [Javadoc HTML](javadoc.md). + +Libraries that use Dokka for API reference docs: + +* [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/) +* [detekt](https://detekt.dev/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.html) +* [Ktor](https://api.ktor.io/) +* [Spring Framework](https://docs.spring.io/spring-framework/docs/current/kdoc-api/) +* [OkHttp](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) (Markdown) + +Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or [command line](cli.md). It is also +[highly pluggable](plugins_introduction.md). diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/plugins/plugins_introduction.md new file mode 100644 index 0000000000..e5bb4a38b0 --- /dev/null +++ b/docs/topics/plugins/plugins_introduction.md @@ -0,0 +1,261 @@ +[//]: # (title: Dokka plugins) + +Dokka was built from the ground up to be easily extensible and highly customizable, which allows the community +to implement plugins for missing or very specific features that are not provided out of the box. + +Dokka plugins range anywhere from supporting other programming language sources to exotic output formats. You can add +support for your own KDoc tags or annotations, teach Dokka how to render different DSLs that are found in KDoc +descriptions, visually redesign Dokka's pages to be seamlessly integrated into your company's website, integrate it +with other tools and so much more. + +If you want to learn how to create Dokka plugins, see +[Developer guides](https://kotlin.github.io/dokka/%dokkaVersion%/developer_guide/introduction/). + +## Applying Dokka plugins + +Dokka plugins are published as separate artifacts, so to apply a Dokka plugin you only need to add as a dependency. +From there, the plugin will extend Dokka by itself - no extra actions needed. + +> Plugins that use the same extension points or work in a similar way can interfere with each other. +> This may lead to visual bugs, general undefined behaviour or even failed builds. If you notice anything of that +> nature, it's a good idea to check which plugins are applied and what they do. +> +{type="note"} + +Let's have a look at how you can apply [mathjax plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) +to your project: + + + + +Gradle plugin creates convenient dependency configurations that allow you to apply plugins universally or +for a specific output format only. + +```kotlin +dependencies { + // will be applied universally + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:%dokkaVersion%") + + // will be applied for single-module dokkaHtml task only + dokkaHtmlPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%") + + // will be applied for html format in multi-project builds + dokkaHtmlPartialPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%") +} +``` + + + + +Gradle plugin creates convenient dependency configurations that allow you to apply Dokka plugins universally or +for a specific output format only. + +```groovy +dependencies { + // will be applied universally + dokkaPlugin 'org.jetbrains.dokka:mathjax-plugin:%dokkaVersion%' + + // will be applied for single-module dokkaHtml task only + dokkaHtmlPlugin 'org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%' + + // will be applied for html format in multi-project builds + dokkaHtmlPartialPlugin 'org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%' +} +``` + + + + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + org.jetbrains.dokka + mathjax-plugin + %dokkaVersion% + + + + +``` + + + + +If you are using the [CLI](cli.md) runner with [command line arguments](cli.md#running-with-command-line-arguments), +Dokka plugins should be passed as `.jar` files to `-pluginsClasspath`: + +```Shell +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./mathjax-plugin-%dokkaVersion%.jar" \ + ... +``` + +If you are using [JSON configuration](cli.md#running-with-json-configuration), Dokka plugins should be specified under +`pluginsClasspath`. + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./mathjax-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + + + + +## Configuring Dokka plugins + +Dokka plugins can also have configuration options of their own. Consult plugin's documentation to see which +options are available. + +Let's have a look at how you can configure `DokkaBase` plugin, which is responsible for generating [HTML](html.md) +documentation, by adding a custom image to assets (`customAssets` option), by adding custom style sheets +(`customStyleSheets` option) and by modifying the footer message (`footerMessage` option): + + + + +Gradle's Kotlin DSL allows for type-safe plugin configuration. This is achievable by adding plugin's artifact to classpath +dependencies in `buildscript` block, and then importing plugin and configuration classes: + +```kotlin +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.base.DokkaBaseConfiguration + +buildscript { + dependencies { + classpath("org.jetbrains.dokka:dokka-base:%dokkaVersion%") + } +} + +tasks.withType().configureEach { + pluginConfiguration { + customAssets = listOf(file("my-image.png")) + customStyleSheets = listOf(file("my-styles.css")) + footerMessage = "(c) 2022 MyOrg" + } +} +``` + +Alternatively, plugins can be configured via JSON. This way no additional dependencies are needed. + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType().configureEach { + val dokkaBaseConfiguration = """ + { + "customAssets": ["${file("assets/my-image.png")}"], + "customStyleSheets": ["${file("assets/my-styles.css")}"], + "footerMessage": "(c) 2022 MyOrg" + } + """ + pluginsMapConfiguration.set( + mapOf( + // fully qualified plugin name to json configuration + "org.jetbrains.dokka.base.DokkaBase" to dokkaBaseConfiguration + ) + ) +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType(DokkaTask.class) { + String dokkaBaseConfiguration = """ + { + "customAssets": ["${file("assets/my-image.png")}"], + "customStyleSheets": ["${file("assets/my-styles.css")}"], + "footerMessage": "(c) 2022 MyOrg" + } + """ + pluginsMapConfiguration.set( + // fully qualified plugin name to json configuration + ["org.jetbrains.dokka.base.DokkaBase": dokkaBaseConfiguration] + ) +} +``` + + + + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + + + + ${project.basedir}/my-image.png + + + ${project.basedir}/my-styles.css + + (c) MyOrg 2022 Maven + + + + +``` + + + + +If you are using the [CLI](cli.md) runner with [command line arguments](cli.md#running-with-command-line-arguments), +use `-pluginsConfiguration` argument that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. + +If you need to configure multiple plugins, you can pass multiple values separated by `^^`. + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + ... + -pluginsConfiguration "org.jetbrains.dokka.base.DokkaBase={\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg CLI\"}" +``` + +If you are using [JSON configuration](cli.md#running-with-json-configuration), there exists a similar +`pluginsConfiguration` array that accepts JSON as values. + +```json +{ + "moduleName": "Dokka Example", + "pluginsConfiguration": [ + { + "fqPluginName": "org.jetbrains.dokka.base.DokkaBase", + "serializationFormat": "JSON", + "values": "{\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg\"}" + } + ] +} +``` + + + + +## Notable plugins + +| **Name** | **Description** | +|-----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| +| [Android documentation plugin](https://github.com/Kotlin/dokka/tree/master/plugins/android-documentation) | Improves documentation experience on Android platform | +| [Versioning plugin](versioning.md) | Adds version selector and helps organize documentation for different version of your application/library | +| [MermaidJS HTML plugin](https://github.com/glureau/dokka-mermaid) | Renders [MermaidJS](https://mermaid-js.github.io/mermaid/#/) diagrams and visualizations found in KDocs | +| [Mathjax HTML plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) | Pretty prints mathematics found in KDocs | +| [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | diff --git a/docs/topics/plugins/versioning.md b/docs/topics/plugins/versioning.md new file mode 100644 index 0000000000..9a7c003993 --- /dev/null +++ b/docs/topics/plugins/versioning.md @@ -0,0 +1,315 @@ +[//]: # (title: Versioning plugin) + +Versioning plugin aims to provide the ability to host documentation for multiple versions of your library/application +with seamless switching between them. This, in turn, provides better experience for your users. + +![Screenshot of documentation version dropdown](versioning-plugin-example.png){height=350} + +> Versioning plugin only works with [HTML](html.md) format. +> +{type="note"} + +## Applying the plugin + +You can apply Versioning plugin the same way as other [Dokka plugins](plugins_introduction.md#applying-dokka-plugins): + + + + +```kotlin +dependencies { + dokkaHtmlPlugin("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") +} +``` + + + + +```groovy +dependencies { + dokkaHtmlPlugin 'org.jetbrains.dokka:versioning-plugin:%dokkaVersion%' +} +``` + + + + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + org.jetbrains.dokka + versioning-plugin + %dokkaVersion% + + + + +``` + + + + +You can find versioning plugin's artifact on +[mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/versioning-plugin/%dokkaVersion%) or by browsing +[maven central repository](https://repo1.maven.org/maven2/org/jetbrains/dokka/versioning-plugin/%dokkaVersion%/) +directly, and pass it to `pliginsClasspath`. + +Via [command line arguments](cli.md#running-with-command-line-arguments): + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./versioning-plugin-%dokkaVersion%.jar" \ + ... +``` + +Via [JSON configuration](cli.md#running-with-json-configuration): + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./versioning-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + + + + +## Configuration + +### Configuration options + +Versioning plugin has a number of optional configuration properties: + +| **Task** | **Description** | +|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `version` | Version of your application/library for which documentation is going to be generated. This will be the version in the dropdown menu. | +| `versionsOrdering` | Optional list of strings that represents the order in which versions should appear in the dropdown. Must match version string exactly. First item of the list is the topmost in the dropdown. | +| `olderVersionsDir` | Optional path to a parent folder that contains other documentation versions. Requires a certain [directory structure](#directory-structure). | +| `olderVersions` | Optional list of paths to other documentation versions. Must point to Dokka's outputs directly. Useful if different versions are scattered and cannot be put into a single directory. | +| `renderVersionsNavigationOnAllPages` | Optional boolean indicating whether to render navigation dropdown on all pages. True by default. | + +#### Directory structure + +Note that the directory passed to `olderVersionsDir` requires a specific structure: + +```text +. +└── olderVersionsDir + └── 1.7.10 + ├── + └── 1.7.20 + ├── +... +``` + +### Configuration example + + + + +```kotlin +import org.jetbrains.dokka.versioning.VersioningPlugin +import org.jetbrains.dokka.versioning.VersioningConfiguration + +buildscript { + dependencies { + classpath("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") + } +} + +tasks.dokkaHtml { + pluginConfiguration { + version = "1.5" + versionsOrdering = listOf("1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1") + olderVersionsDir = file("documentation/version") + olderVersions = listOf(file("documentation/alpha/alpha-2"), file("documentation/alpha/alpha-1")) + renderVersionsNavigationOnAllPages = true + } +} +``` + +Alternatively, you can configure it via JSON: + +```kotlin + val versioningConfiguration = """ + { + "version": "1.5", + "versionsOrdering": ["1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1"], + "olderVersionsDir": "documentation/version", + "olderVersions": ["documentation/alpha/alpha-2", "documentation/alpha/alpha-1"], + "renderVersionsNavigationOnAllPages": true + } + """ + pluginsMapConfiguration.set( + mapOf( + "org.jetbrains.dokka.versioning.VersioningPlugin" to versioningConfiguration + ) + ) +``` + + + + +```groovy +dokkaHtml { + String versioningConfiguration = """ + { + "version": "1.5", + "versionsOrdering": ["1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1"], + "olderVersionsDir": "documentation/version", + "olderVersions": ["documentation/alpha/alpha-2", "documentation/alpha/alpha-1"], + "renderVersionsNavigationOnAllPages": true + } + """ + pluginsMapConfiguration.set( + ["org.jetbrains.dokka.versioning.VersioningPlugin": versioningConfiguration] + ) +} +``` + + + + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + 1.5 + + 1.5 + 1.4 + 1.3 + 1.2 + 1.1 + alpha-2 + alpha-1 + + ${project.basedir}/documentation/version + + ${project.basedir}/documentation/alpha/alpha-2 + ${project.basedir}/documentation/alpha/alpha-1 + + true + + + + +``` + + + + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + ... + -pluginsConfiguration "org.jetbrains.dokka.versioning.VersioningPlugin={\"version\": \"1.5\", \"versionsOrdering\": [\"1.5\", \"1.4\", \"1.3\", \"1.2\", \"1.1\", \"alpha-2\", \"alpha-1\"], \"olderVersionsDir\": \"documentation/version\", \"olderVersions\": [\"documentation/alpha/alpha-2\", \"documentation/alpha/alpha-1\"], \"renderVersionsNavigationOnAllPages\": true}" + +``` + +Alternatively, via JSON configuration: +```json +{ + "moduleName": "Dokka Example", + ... + "pluginsConfiguration": [ + { + "fqPluginName": "org.jetbrains.dokka.versioning.VersioningPlugin", + "serializationFormat": "JSON", + "values": "{\"version\": \"1.5\", \"versionsOrdering\": [\"1.5\", \"1.4\", \"1.3\", \"1.2\", \"1.1\", \"alpha-2\", \"alpha-1\"], \"olderVersionsDir\": \"documentation/version\", \"olderVersions\": [\"documentation/alpha/alpha-2\", \"documentation/alpha/alpha-1\"], \"renderVersionsNavigationOnAllPages\": true}" + } + ] +} +``` + + + + +## Generating versioned documentation + +With versioning plugin applied and configured, no other steps are needed: documentation can be built the usual way. + +Versioning plugin will add a `version.json` file to the output folder. This file will be used by the plugin to match +versions and generate version navigation. If your previously generated documentation does not have that file, you +may need to re-generate it. + +Versioning plugin will also bundle all other documentation versions that have been passed through `olderVersionsDir` +and `olderVersions` configuration properties by putting them inside `older` directory. + +## Usage example + +There is no single correct way to configure the plugin, it can be tailored to your liking and needs. However, +it can be a bit overwhelming when starting out. Below you will find one of the ways it can be configured so that you +can begin publishing versioned documentation right away. + +The main idea behind it is the following: + +1. One directory will contains all versions of your documentation. For instance, `documentation/version/{version_string}`. + This is your archive, you will need to preserve it for future builds. +2. Output directory of all new builds will be set to that directory as well, under `documentation/version/{new_version}` +3. When new builds are executed, the plugin will look for previous versions of documentation in the archive directory. +4. Once new documentation has been generated, it needs to be **copied** to some place accessible by the user: + GitHub pages, nginx static directories, and so on. It needs to be copied and not moved because Dokka will still need + this version for future builds, otherwise there will be a gap in the archive. +5. Once it has been safely copied away, you can remove `older` directory from the archived version. This helps reduce + the overhead of each version bundling all previous versions as these files are effectively duplicate. + +```kotlin +import org.jetbrains.dokka.versioning.VersioningPlugin +import org.jetbrains.dokka.versioning.VersioningConfiguration + +buildscript { + dependencies { + classpath("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") + } +} + +dependencies { + dokkaPlugin("org.jetbrains.dokka:versioning-plugin:$dokkaVersion") +} + +tasks.dokkaHtml { + // can be any persistent folder where + // you store documentation by version + val docVersionsDir = projectDir.resolve("documentation/version") + + // version for which you are currently generating docs + val currentVersion = "1.3" + + // set output to folder with all other versions + // as you'll need current version for future builds + val currentDocsDir = docVersionsDir.resolve(currentVersion) + outputDirectory.set(currentDocsDir) + + pluginConfiguration { + olderVersionsDir = docVersionsDir + version = currentVersion + } + + doLast { + // this folder will contain latest documentation with all + // previous versions included, so it's ready to be published. + // make sure it's copied and not moved - you'll still need this + // version for future builds + currentDocsDir.copyTo(file("/my/hosting")) + + // only once current documentation has been safely moved, + // remove previous versions bundled in it. They will not + // be needed in future builds, it's just overhead + currentDocsDir.resolve("older").deleteRecursively() + } +} +``` diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md new file mode 100644 index 0000000000..e7c210cec0 --- /dev/null +++ b/docs/topics/runners/cli.md @@ -0,0 +1,288 @@ +[//]: # (title: CLI runner) + +If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) plugin, Dokka has +a command line runner for generating documentation without any build tools. + +In comparison, it has the same, if not more, capabilities as the Gradle plugin, although it is considerably more +difficult to set up as there is no autoconfiguration, especially in multiplatform and multimodule environments. + +CLI runner is published as a separate artifact to Maven Central under `org.jetbrains.dokka:dokka-cli`, so you can +find it on [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-cli) or by browsing +[maven central repository directories](https://repo1.maven.org/maven2/org/jetbrains/dokka/dokka-cli/) directly. + +## Getting started + +With `dokka-cli-%dokkaVersion%.jar` file on your computer, you can run it with `-help` to see available arguments and their description: + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar -help +``` + +It also works for some nested arguments, such as `-sourceSet`: + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help +``` + +## Generating documentation + +### Pre-requisites + +Since there is no build tool to manage dependencies, you will have to provide dependency `.jar` files yourself. + +Dependencies you will need for any format: + +| **Group** | **Artifact** | **Version** | **Link** | +|-----------------------|----------------------------|----------------|-----------------------------------------------------------------------------------------------------------------| +| `org.jetbrains.dokka` | `dokka-base` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-base/%dokkaVersion%) | +| `org.jetbrains.dokka` | `dokka-analysis` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-analysis/%dokkaVersion%) | +| `org.jetbrains.dokka` | `kotlin-analysis-compiler` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-compiler/%dokkaVersion%) | +| `org.jetbrains.dokka` | `kotlin-analysis-intellij` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-intellij/%dokkaVersion%) | + +Additional dependencies for [HTML](html.md) format: + +| **Group** | **Artifact** | **Version** | **Link** | +|-------------------------|--------------------|-------------|--------------------------------------------------------------------------------------------------| +| `org.jetbrains.kotlinx` | `kotlinx-html-jvm` | 0.8.0 | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-html-jvm/0.8.0) | +| `org.freemarker` | `freemarker` | 2.3.31 | [mvnrepository](https://mvnrepository.com/artifact/org.freemarker/freemarker/2.3.31) | + + +### Running with command line arguments + +You can pass command line arguments to configure the CLI runner. + +At the very least you would need to provide the following arguments: +* `-pluginsClasspath` - a list of absolute/relative paths to downloaded dependencies, separated by semi-colons `;` +* `-sourceSet` - an absolute path to code sources for which to generate documentation +* `-outputDir` - an absolute/relative path of documentation output directory + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;./dokka-analysis-%dokkaVersion%.jar;./kotlin-analysis-intellij-%dokkaVersion%.jar;./kotlin-analysis-compiler-%dokkaVersion%.jar;./kotlinx-html-jvm-0.8.0.jar;./freemarker-2.3.31.jar" \ + -sourceSet "-src /home/myCoolProject/src/main/kotlin" \ + -outputDir "./dokka/html" +``` + +> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler` +> artifact, otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. +> +{type="note"} + +Executing the given example should generate documentation in [HTML](html.md) format. + +See [all command line arguments](#command-line-arguments) for more details. + +### Running with JSON configuration + +It is possible to configure the CLI runner with JSON. In this case, you will need to provide an +absolute/relative path to the JSON configuration file,and all the other configuration options will be parsed from it. + +```Bash +java -jar dokka-cli-%dokkaVersion%.jar dokka-configuration.json +``` + +At the very least, you would need the following configuration: +```json +{ + "outputDir": "./dokka/html", + "sourceSets": [ + { + "sourceSetID": { + "scopeId": "html", + "sourceSetName": "main" + }, + "sourceRoots": [ + "/home/myCoolProject/src/main/kotlin" + ] + } + ], + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "./kotlinx-html-jvm-0.8.0.jar", + "./dokka-analysis-%dokkaVersion%.jar", + "./kotlin-analysis-intellij-%dokkaVersion%.jar", + "./kotlin-analysis-compiler-%dokkaVersion%.jar", + "./freemarker-2.3.31.jar" + ] +} +``` + +> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`, +> otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. +> +{type="note"} + +See [JSON configuration options](#json-configuration) for more details. + +### Other output formats + +By default, `dokka-base` artifact contains [HTML](html.md) format only. + +All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use them, you have to put it +on plugins classpath. + +For example, if you want to generate documentation in [GFM](markdown.md#gfm) format, you have to download and +pass [gfm-plugin's jar](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into +`pluginsClasspath` configuration option. + +Via command line arguments: + +```Shell +java -jar dokka-cli-%dokkaVersion%.jar \ + -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./gfm-plugin-%dokkaVersion%.jar" \ + ... +``` + +Via JSON configuration: + +```json +{ + ... + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "...", + "./gfm-plugin-%dokkaVersion%.jar" + ], + ... +} +``` + +With GFM plugin on classpath, CLI runner should generate documentation in GFM format, no extra actions +needed. + +For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#geneatring-javadoc-documentation) topics. + +## Configuration + +### Command line arguments + +TODO paste output of `-help` after correcting in-code descriptions. + +### JSON configuration + +TODO add descriptions for each setting as a separate entry in a table +TODO add a link to Dokka's api reference, to DokkaConfiguration class + +```json +{ + "moduleName": "Dokka Example", + "moduleVersion": null, + "outputDir": "./build/dokka/html", + "failOnWarning": false, + "suppressObviousFunctions": true, + "suppressInheritedMembers": false, + "offlineMode": false, + "sourceLinks": [ + { + "localDirectory": "src/main/kotlin", + "remoteUrl": "https://github.com/Kotlin/dokka/tree/master/src/main/kotlin", + "remoteLineSuffix": "#L" + } + ], + "externalDocumentationLinks": [ + { + "url": "https://docs.oracle.com/javase/8/docs/api/", + "packageListUrl": "https://docs.oracle.com/javase/8/docs/api/package-list" + }, + { + "url": "https://kotlinlang.org/api/latest/jvm/stdlib/", + "packageListUrl": "https://kotlinlang.org/api/latest/jvm/stdlib/package-list" + } + ], + "perPackageOptions": [ + { + "matchingRegex": ".*internal.*", + "suppress": false, + "reportUndocumented": false, + "skipDeprecated": false, + "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"] + } + ], + "sourceSets": [ + { + "displayName": "jvm", + "sourceSetID": { + "scopeId": "html", + "sourceSetName": "main" + }, + "dependentSourceSets": [ + { + "scopeId": "dependentSourceSetScopeId", + "sourceSetName": "dependentSourceSetName" + } + ], + "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"], + "reportUndocumented": false, + "skipEmptyPackages": true, + "skipDeprecated": false, + "jdkVersion": 8, + "languageVersion": "1.7", + "apiVersion": "1.7", + "noStdlibLink": false, + "noJdkLink": false, + "includes": [ + "module.md" + ], + "analysisPlatform": "jvm", + "sourceRoots": [ + "/home/ignat/IdeaProjects/dokka-debug-mvn/src/main/kotlin" + ], + "classpath": [ + "libs/kotlin-stdlib-%kotlinVersion%.jar", + "libs/kotlin-stdlib-common-%kotlinVersion%.jar" + ], + "samples": [ + "samples/basic.kt" + ], + "suppressedFiles": [ + "src/main/kotlin/org/jetbrains/dokka/Suppressed.kt" + ], + "sourceLinks": [ + { + "localDirectory": "src/main/kotlin", + "remoteUrl": "https://github.com/Kotlin/dokka/tree/master/src/main/kotlin", + "remoteLineSuffix": "#L" + } + ], + "externalDocumentationLinks": [ + { + "url": "https://docs.oracle.com/javase/8/docs/api/", + "packageListUrl": "https://docs.oracle.com/javase/8/docs/api/package-list" + }, + { + "url": "https://kotlinlang.org/api/latest/jvm/stdlib/", + "packageListUrl": "https://kotlinlang.org/api/latest/jvm/stdlib/package-list" + } + ], + "perPackageOptions": [ + { + "matchingRegex": ".*internal.*", + "suppress": false, + "reportUndocumented": false, + "skipDeprecated": false, + "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"] + } + ] + } + ], + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "./kotlinx-html-jvm-0.8.0.jar", + "./dokka-analysis-%dokkaVersion%.jar", + "./kotlin-analysis-intellij-%dokkaVersion%.jar", + "./kotlin-analysis-compiler-%dokkaVersion%.jar", + "./freemarker-2.3.31.jar" + ], + "pluginsConfiguration": [ + { + "fqPluginName": "org.jetbrains.dokka.base.DokkaBase", + "serializationFormat": "JSON", + "values": "{\"separateInheritedMembers\":false,\"footerMessage\":\"© 2021 pretty good Copyright\"}" + } + ], + "includes": [ + "module.md" + ], + "finalizeCoroutines": true +} +``` diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md new file mode 100644 index 0000000000..d3b4aa3018 --- /dev/null +++ b/docs/topics/runners/gradle.md @@ -0,0 +1,539 @@ +[//]: # (title: Gradle plugin) + +To generate documentation for a Gradle-based project, you can use [Dokka Gradle plugin](#applying-the-plugin). + +It comes with basic autoconfiguration (including multimodule and multiplatform projects), has convenient +[Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of +[configuration options](#configuration) to customize output. + +## Applying the plugin + +The recommended way of applying the plugin is via +[plugins DSL](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block): + + + + +```kotlin +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} +``` + + + + +```groovy +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} +``` + + + + +> Under the hood, Dokka uses [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform autoconfiguration +> of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for which documentation +> should be generated, so make sure Kotlin Gradle Plugin is applied as well, or configure source sets manually. +> +{type="note"} + +> If you are using Dokka in a +> [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), +> you will have to add [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) as a dependency in order for +> it to work properly: +> +> +> +> +> ```kotlin +> implementation(kotlin("gradle-plugin", "%kotlinVersion%")) +> ``` +> +> +> +> +> ```groovy +> implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:%kotlinVersion%' +> ``` +> +> +> +> +{type="note"} + + +### Legacy plugin application + +If you cannot use plugins DSL for some reason, you can use +[the legacy method](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application) of applying +plugins. + + + + +```kotlin +buildscript { + dependencies { + classpath("org.jetbrains.dokka:dokka-gradle-plugin:%dokkaVersion%") + } +} + +apply(plugin="org.jetbrains.dokka") +``` + +> Note that by applying Dokka this way, certain type-safe accessors will not be available in Kotlin DSL. +> +{type="note"} + + + + +```groovy +buildscript { + dependencies { + classpath 'org.jetbrains.dokka:dokka-gradle-plugin:%dokkaVersion%' + } +} + +apply plugin: 'org.jetbrains.dokka' +``` + + + + +## Generating documentation + +Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) formats built in, +and adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. + +### Single project builds + +Use the following tasks to build documentation for simple, single project applications and libraries: + +| **Task** | **Description** | +|----------------|-------------------------------------------------------------------------------------| +| `dokkaHtml` | Generates documentation in [HTML](html.md) format. | +| `dokkaGfm` | Generates documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | +| `dokkaJavadoc` | Generates documentation in [Javadoc](javadoc.md) format. | +| `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | + +By default, you will find generated documentation under `build/dokka/{format}` directory of your project. +Output location, among other things, can be [configured](#configuration) separately. + +### Multi-project builds + +For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), you can +use tasks which are created for all parent projects automatically: + +| **Task** | **Description** | +|--------------------------|--------------------------------------------------------------------------------------------------| +| `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](html.md) format. | +| `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | +| `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | + +> [Javadoc](javadoc.md) output format does not have a MultiModule task, but a [Collector](#collector-tasks) task can +> be used instead. +> +{type="note"} + +A _MultiModule_ task generates documentation for each subproject individually via [partial](#partial-tasks) tasks, +collects and processes all outputs, and produces complete documentation with a common table of contents and resolved +cross-project references. + +By default, you will find ready-to-use documentation under `{parentProject}/build/dokka/{format}MultiModule` directory. + +##### MultiModule task example + +Given a project with the following structure: + +```text +parentProject + └── childProjectA + ├── demo + ├── ChildProjectAClass + └── childProjectB + ├── demo + ├── ChildProjectBClass +``` + +You will see these pages generated after running `dokkaHtmlMultiModule`: + +![Screenshot for output of dokkaHtmlMultiModule task](dokkaHtmlMultiModule-example.png){width=600} + +Visit [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +for more details. + +#### Partial tasks + +Each subproject will have _partial_ tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, +and `dokkaJekyllPartial`. + +These tasks are not intended to be used independently and exist only to be called by the parent's MultiModule task. + +Output generated by partial tasks contains non-displayable formatting along with unresolved templates and references. + +> If you want to generate documentation for a single subproject only, use +> [single project tasks](#single-project-builds). For instance, `:subproject:dokkaHtml`. + +#### Collector tasks + +Similar to MultiModule tasks, _Collector_ tasks will be created for each parent project: `dokkaHtmlCollector`, +`dokkaGfmCollector`, `dokkaJavadocCollector` and `dokkaJekyllCollector`. + +A Collector task executes corresponding [single project task](#single-project-builds) for each subproject (for example, +`dokkaHtml`), and merges all outputs into a single virtual project. + +Resulting documentation will look as if you have a single project +build that contains all declarations from the subprojects. + +> Use `dokkaJavadocCollector` task if you need to create Javadoc documentation for your multi-project build. +> +{type="tip"} + +#### Collector results + +Given a project with the following structure: + +```text +parentProject + └── childProjectA + ├── demo + ├── ChildProjectAClass + └── childProjectB + ├── demo + ├── ChildProjectBClass +``` + +You will see these pages generated after running `dokkaHtmlCollector`: + +![Screenshot for output of dokkaHtmlCollector task](dokkaHtmlCollector-example.png){width=800} + +Visit [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +for more details. + +## Building javadoc.jar + +In order to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API reference +documentation. + +Dokka's Gradle plugin does not provide any way to do this out of the box, but it can be achieved with custom Gradle +tasks, one for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: + + + + +```kotlin +tasks.register("dokkaHtmlJar") { + dependsOn(tasks.dokkaHtml) + from(tasks.dokkaHtml.flatMap { it.outputDirectory }) + archiveClassifier.set("html-docs") +} + +tasks.register("dokkaJavadocJar") { + dependsOn(tasks.dokkaJavadoc) + from(tasks.dokkaJavadoc.flatMap { it.outputDirectory }) + archiveClassifier.set("javadoc") +} +``` + + + + +```groovy +tasks.register('dokkaHtmlJar', Jar.class) { + dependsOn(dokkaHtml) + from(dokkaHtml) + archiveClassifier.set("html-docs") +} + +tasks.register('dokkaJavadocJar', Jar.class) { + dependsOn(dokkaJavadoc) + from(dokkaJavadoc) + archiveClassifier.set("javadoc") +} +``` + + + + +> If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to +> host of your library's API documentation for free and without any setup - it will take documentation pages straight +> from the artifact. It works with both HTML and Javadoc formats as demonstrated by +> [this example](https://javadoc.io/doc/com.trib3/server/latest/index.html). +> +{type="tip"} + +## Configuration + +You can configure tasks/formats individually + + + + +If you applied Dokka via [plugins DSL](#applying-the-plugin) block: + +```kotlin +tasks.dokkaHtml { + outputDirectory.set(buildDir.resolve("documentation/html")) +} + +tasks.dokkaGfm { + outputDirectory.set(buildDir.resolve("documentation/markdown")) +} + +tasks.dokkaHtmlPartial { + outputDirectory.set(buildDir.resolve("docs/partial")) +} +``` + +If you applied Dokka with the [buildscript block](#legacy-plugin-application): + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.named("dokkaHtml") { + outputDirectory.set(buildDir.resolve("documentation/html")) +} +``` + + + + +```groovy + +dokkaHtml { + outputDirectory.set(file("build/documentation/html")) +} + +dokkaGfm { + outputDirectory.set(file("build/documentation/markdown")) +} + +dokkaHtmlPartial { + outputDirectory.set(file("build/docs/partial")) +} +``` + + + + +Alternatively, you can configure all tasks/formats at once, including [MultiModule](#multi-project-builds), +[Partial](#partial-tasks) and [Collector](#collector-tasks) tasks as well. This is often the simplest solution. + + + + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.gradle.DokkaTaskPartial +import org.jetbrains.dokka.DokkaConfiguration.Visibility + +// configure all dokka tasks, including multimodule, partial and collector +tasks.withType().configureEach { + dokkaSourceSets.configureEach { + documentedVisibilities.set( + setOf( + Visibility.PUBLIC, + Visibility.PROTECTED, + ) + ) + + perPackageOption { + matchingRegex.set(".*internal.*") + suppress.set(true) + } + } +} + +// configure partial tasks of all output formats, +// these can have subproject-specific settings +tasks.withType(DokkaTaskPartial::class).configureEach { + dokkaSourceSets.configureEach { + includes.from("README.md") + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.gradle.DokkaTaskPartial + +// configure all dokka tasks, including multimodule, partial and collector +tasks.withType(DokkaTask.class) { + dokkaSourceSets.configureEach { + documentedVisibilities.set([ + DokkaConfiguration.Visibility.PUBLIC, + DokkaConfiguration.Visibility.PROTECTED + ]) + + perPackageOption { + matchingRegex.set(".*internal.*") + suppress.set(true) + } + } +} + +// configure partial tasks of all output formats, +// these can have subproject-specific settings +tasks.withType(DokkaTaskPartial.class) { + dokkaSourceSets.configureEach { + includes.from("README.md") + } +} +``` + + + + +### Full configuration + +TODO add descriptions for each setting as a separate entry in a table + + + + +```kotlin +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.Platform +import java.net.URL + +tasks.withType().configureEach { + moduleName.set(project.name) + moduleVersion.set(project.version.toString()) + outputDirectory.set(buildDir.resolve("dokka/$name")) + failOnWarning.set(false) + suppressObviousFunctions.set(true) + suppressInheritedMembers.set(false) + offlineMode.set(false) + + dokkaSourceSets { + named("customSourceSet") { + dependsOn("sourceSetDependency") + } + configureEach { + suppress.set(false) + displayName.set(name) + documentedVisibilities.set(setOf(Visibility.PUBLIC)) + reportUndocumented.set(false) + skipEmptyPackages.set(true) + skipDeprecated.set(false) + suppressGeneratedFiles.set(true) + jdkVersion.set(8) + languageVersion.set("1.7") + apiVersion.set("1.7") + noStdlibLink.set(false) + noJdkLink.set(false) + noAndroidSdkLink.set(false) + includes.from(project.files(), "packages.md", "extra.md") + platform.set(Platform.DEFAULT) + sourceRoots.from(file("src")) + classpath.from(project.files(), file("libs/dependency.jar")) + samples.from(project.files(), "samples/Basic.kt", "samples/Advanced.kt") + + sourceLink { + localDirectory.set(projectDir.resolve("src")) + remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteLineSuffix.set("#L") + } + + externalDocumentationLink { + url.set(URL("https://kotlinlang.org/api/latest/jvm/stdlib/")) + packageListUrl.set( + rootProject.projectDir.resolve("stdlib.package.list").toURL() + ) + } + + perPackageOption { + matchingRegex.set(".*api.*") + suppress.set(false) + skipDeprecated.set(false) + reportUndocumented.set(false) + documentedVisibilities.set( + setOf( + Visibility.PUBLIC, + Visibility.PRIVATE, + Visibility.PROTECTED, + Visibility.INTERNAL, + Visibility.PACKAGE + ) + ) + } + } + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.Platform +import java.net.URL + +tasks.withType(DokkaTask.class) { + moduleName.set(project.name) + moduleVersion.set(project.version.toString()) + outputDirectory.set(file("build/dokka/$name")) + failOnWarning.set(false) + suppressObviousFunctions.set(true) + suppressInheritedMembers.set(false) + offlineMode.set(false) + + dokkaSourceSets { + named("customSourceSet") { + dependsOn("sourceSetDependency") + } + configureEach { + suppress.set(false) + displayName.set(name) + documentedVisibilities.set([Visibility.PUBLIC]) + reportUndocumented.set(false) + skipEmptyPackages.set(true) + skipDeprecated.set(false) + suppressGeneratedFiles.set(true) + jdkVersion.set(8) + languageVersion.set("1.7") + apiVersion.set("1.7") + noStdlibLink.set(false) + noJdkLink.set(false) + noAndroidSdkLink.set(false) + includes.from(project.files(), "packages.md", "extra.md") + platform.set(Platform.DEFAULT) + sourceRoots.from(file("src")) + classpath.from(project.files(), file("libs/dependency.jar")) + samples.from(project.files(), "samples/Basic.kt", "samples/Advanced.kt") + + sourceLink { + localDirectory.set(file("src")) + remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteLineSuffix.set("#L") + } + + externalDocumentationLink { + url.set(new URL("https://kotlinlang.org/api/latest/jvm/stdlib/")) + packageListUrl.set( + file("stdlib.package.list").toURL() + ) + } + + perPackageOption { + matchingRegex.set(".*api.*") + suppress.set(false) + skipDeprecated.set(false) + reportUndocumented.set(false) + documentedVisibilities.set([Visibility.PUBLIC]) + } + } + } +} +``` + + + diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md new file mode 100644 index 0000000000..a6f619598c --- /dev/null +++ b/docs/topics/runners/maven.md @@ -0,0 +1,227 @@ +[//]: # (title: Maven plugin) + +To generate documentation for Maven-based projects, you can use [Dokka Maven plugin](#applying-the-plugin). + +> Compared to the [Gradle plugin](gradle.md), Maven plugin has only basic features and +> **does not support multiplatform projects**. +> +{type="note"} + +## Applying the plugin + +To apply the plugin, you need to add it to the plugins section of your POM: + +```xml + + + + org.jetbrains.dokka + dokka-maven-plugin + %dokkaVersion% + + + pre-site + + dokka + + + + + + +``` + +## Generating documentation + +Following goals are provided by the plugin: + +| **Goal** | **Description** | +|-----------------------|---------------------------------------------------------------------------------------------| +| `dokka:dokka` | Generates documentation with Dokka plugins applied. [HTML](html.md) format by default. | +| `dokka:javadoc` | Generates documentation in [Javadoc](javadoc.md) format. | +| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in [Javadoc](javadoc.md) format. | + +> Unlike [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin only comes with [HTML](html.md) format built in +> and does not provide any separate goals to generate documentation in other formats. In order to do that, you will have +> to [apply other formats as Dokka plugins](#other-output-formats) and re-run `dokka:dokka` goal. +> +{type="note"} + +### Other output formats + +By default, Maven plugin will build documentation in [HTML](html.md) format. + +All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use it, you have to apply +it as a dependency. + +For example, for [GFM](markdown.md#gfm) format, you have to use apply `org.jetbrains.dokka:gfm-plugin` in the following way: + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + + + org.jetbrains.dokka + gfm-plugin + %dokkaVersion% + + + + +``` + +After that, running `dokka:dokka` goal should produce documentation in GFM format. + +You can learn more about Dokka plugins in [a separate topic](plugins_introduction.md). + +## Building javadoc.jar + +Unlike [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin comes with ready-to-use `dokka:javadocJar` goal. +By default, it will generate documentation in [Javadoc](javadoc.md) format under `target` folder. + +If you are not satisfied with the built-in goal or want to customize the output (for instance, you want to generate +documentation in [HTML](html.md) format instead of Javadoc), similar behaviour can be achieved by adding the +Maven jar plugin with the following configuration: + +```xml + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + test-jar + + + + dokka-jar + package + + jar + + + dokka + ${project.build.directory}/dokka + true + + + + +``` + +The documentation and the archive for it can then be generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: + +```Bash +mvn dokka:dokka jar:jar@dokka-jar +``` + +## Configuration + +Maven's plugin configuration block can be used to configure Dokka. + +Below you will find basic configuration that only changes output location of documentation. See +[all configuration elements](#all-configuration-elements) section to find out what else is possible. + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + ${project.basedir}/target/documentation/dokka + + +``` + +### All configuration elements + +TODO add descriptions for each setting as a separate entry in a table + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + ... + + false + ${project.artifactId} + ${project.basedir}/target/documentation + false + true + false + false + + JVM + +

${project.basedir}/src/main/kotlin + + JVM + + PUBLIC + PRIVATE + PROTECTED + INTERNAL + PACKAGE + + false + false + true + + /path/to/dir + /path/to/file + + 8 + 1.7 + 1.7 + false + false + + packages.md + extra.md + + JVM + + + src/main/kotlin + JVM + + + ${project.compileClasspathElements} + + ${project.basedir}/samples + + + + ${project.basedir}/src/main/kotlin + https://github.com/kotlin/dokka/tree/master/src/main/kotlin + #L + + + + + https://kotlinlang.org/api/latest/jvm/stdlib/ + file:/${project.basedir}/stdlib.package.list + + + + + .*api.* + false + false + false + + PUBLIC + PRIVATE + PROTECTED + INTERNAL + PACKAGE + + + + + +``` diff --git a/docs/vars.list b/docs/vars.list new file mode 100644 index 0000000000..bd5bcfc516 --- /dev/null +++ b/docs/vars.list @@ -0,0 +1,9 @@ + + + + + diff --git a/docs/build.gradle.kts b/mkdocs/build.gradle.kts similarity index 100% rename from docs/build.gradle.kts rename to mkdocs/build.gradle.kts diff --git a/docs/src/doc/docs/community/plugins-list.md b/mkdocs/src/doc/docs/community/plugins-list.md similarity index 100% rename from docs/src/doc/docs/community/plugins-list.md rename to mkdocs/src/doc/docs/community/plugins-list.md diff --git a/docs/src/doc/docs/community/slack.md b/mkdocs/src/doc/docs/community/slack.md similarity index 100% rename from docs/src/doc/docs/community/slack.md rename to mkdocs/src/doc/docs/community/slack.md diff --git a/docs/src/doc/docs/developer_guide/architecture/architecture_overview.md b/mkdocs/src/doc/docs/developer_guide/architecture/architecture_overview.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/architecture_overview.md rename to mkdocs/src/doc/docs/developer_guide/architecture/architecture_overview.md diff --git a/docs/src/doc/docs/developer_guide/architecture/data_model/documentables.md b/mkdocs/src/doc/docs/developer_guide/architecture/data_model/documentables.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/data_model/documentables.md rename to mkdocs/src/doc/docs/developer_guide/architecture/data_model/documentables.md diff --git a/docs/src/doc/docs/developer_guide/architecture/data_model/extra.md b/mkdocs/src/doc/docs/developer_guide/architecture/data_model/extra.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/data_model/extra.md rename to mkdocs/src/doc/docs/developer_guide/architecture/data_model/extra.md diff --git a/docs/src/doc/docs/developer_guide/architecture/data_model/page_content.md b/mkdocs/src/doc/docs/developer_guide/architecture/data_model/page_content.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/data_model/page_content.md rename to mkdocs/src/doc/docs/developer_guide/architecture/data_model/page_content.md diff --git a/docs/src/doc/docs/developer_guide/architecture/extension_points/base_extensions.md b/mkdocs/src/doc/docs/developer_guide/architecture/extension_points/base_extensions.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/extension_points/base_extensions.md rename to mkdocs/src/doc/docs/developer_guide/architecture/extension_points/base_extensions.md diff --git a/docs/src/doc/docs/developer_guide/architecture/extension_points/core_extensions.md b/mkdocs/src/doc/docs/developer_guide/architecture/extension_points/core_extensions.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/extension_points/core_extensions.md rename to mkdocs/src/doc/docs/developer_guide/architecture/extension_points/core_extensions.md diff --git a/docs/src/doc/docs/developer_guide/architecture/extension_points/introduction.md b/mkdocs/src/doc/docs/developer_guide/architecture/extension_points/introduction.md similarity index 100% rename from docs/src/doc/docs/developer_guide/architecture/extension_points/introduction.md rename to mkdocs/src/doc/docs/developer_guide/architecture/extension_points/introduction.md diff --git a/docs/src/doc/docs/developer_guide/introduction.md b/mkdocs/src/doc/docs/developer_guide/introduction.md similarity index 100% rename from docs/src/doc/docs/developer_guide/introduction.md rename to mkdocs/src/doc/docs/developer_guide/introduction.md diff --git a/docs/src/doc/docs/developer_guide/plugin-development/introduction.md b/mkdocs/src/doc/docs/developer_guide/plugin-development/introduction.md similarity index 100% rename from docs/src/doc/docs/developer_guide/plugin-development/introduction.md rename to mkdocs/src/doc/docs/developer_guide/plugin-development/introduction.md diff --git a/docs/src/doc/docs/developer_guide/plugin-development/sample-plugin-tutorial.md b/mkdocs/src/doc/docs/developer_guide/plugin-development/sample-plugin-tutorial.md similarity index 100% rename from docs/src/doc/docs/developer_guide/plugin-development/sample-plugin-tutorial.md rename to mkdocs/src/doc/docs/developer_guide/plugin-development/sample-plugin-tutorial.md diff --git a/docs/src/doc/docs/developer_guide/workflow.md b/mkdocs/src/doc/docs/developer_guide/workflow.md similarity index 100% rename from docs/src/doc/docs/developer_guide/workflow.md rename to mkdocs/src/doc/docs/developer_guide/workflow.md diff --git a/docs/src/doc/docs/dokka_colors.css b/mkdocs/src/doc/docs/dokka_colors.css similarity index 100% rename from docs/src/doc/docs/dokka_colors.css rename to mkdocs/src/doc/docs/dokka_colors.css diff --git a/docs/src/doc/docs/faq.md b/mkdocs/src/doc/docs/faq.md similarity index 100% rename from docs/src/doc/docs/faq.md rename to mkdocs/src/doc/docs/faq.md diff --git a/docs/src/doc/docs/favicon.svg b/mkdocs/src/doc/docs/favicon.svg similarity index 100% rename from docs/src/doc/docs/favicon.svg rename to mkdocs/src/doc/docs/favicon.svg diff --git a/docs/src/doc/docs/images/mathjax_demo.png b/mkdocs/src/doc/docs/images/mathjax_demo.png similarity index 100% rename from docs/src/doc/docs/images/mathjax_demo.png rename to mkdocs/src/doc/docs/images/mathjax_demo.png diff --git a/docs/src/doc/docs/images/mermaid_demo.png b/mkdocs/src/doc/docs/images/mermaid_demo.png similarity index 100% rename from docs/src/doc/docs/images/mermaid_demo.png rename to mkdocs/src/doc/docs/images/mermaid_demo.png diff --git a/docs/src/doc/docs/index.md b/mkdocs/src/doc/docs/index.md similarity index 100% rename from docs/src/doc/docs/index.md rename to mkdocs/src/doc/docs/index.md diff --git a/docs/src/doc/docs/survey_banner.js b/mkdocs/src/doc/docs/survey_banner.js similarity index 99% rename from docs/src/doc/docs/survey_banner.js rename to mkdocs/src/doc/docs/survey_banner.js index 2feec82ef1..b4592f1fc1 100644 --- a/docs/src/doc/docs/survey_banner.js +++ b/mkdocs/src/doc/docs/survey_banner.js @@ -5,4 +5,4 @@ window.addEventListener('load', () => { appended.innerText = "Take part in our Dokka devX survey. It helps us a lot, and gives you a chance to win a prize! -->" document.body.prepend(appended) window.scrollTo(0, 0); -}) \ No newline at end of file +}) diff --git a/docs/src/doc/docs/user_guide/applying/cli.md b/mkdocs/src/doc/docs/user_guide/applying/cli.md similarity index 100% rename from docs/src/doc/docs/user_guide/applying/cli.md rename to mkdocs/src/doc/docs/user_guide/applying/cli.md diff --git a/docs/src/doc/docs/user_guide/applying/gradle.md b/mkdocs/src/doc/docs/user_guide/applying/gradle.md similarity index 100% rename from docs/src/doc/docs/user_guide/applying/gradle.md rename to mkdocs/src/doc/docs/user_guide/applying/gradle.md diff --git a/docs/src/doc/docs/user_guide/applying/maven.md b/mkdocs/src/doc/docs/user_guide/applying/maven.md similarity index 100% rename from docs/src/doc/docs/user_guide/applying/maven.md rename to mkdocs/src/doc/docs/user_guide/applying/maven.md diff --git a/docs/src/doc/docs/user_guide/introduction.md b/mkdocs/src/doc/docs/user_guide/introduction.md similarity index 100% rename from docs/src/doc/docs/user_guide/introduction.md rename to mkdocs/src/doc/docs/user_guide/introduction.md diff --git a/docs/src/doc/docs/user_guide/output-formats/html.md b/mkdocs/src/doc/docs/user_guide/output-formats/html.md similarity index 100% rename from docs/src/doc/docs/user_guide/output-formats/html.md rename to mkdocs/src/doc/docs/user_guide/output-formats/html.md diff --git a/docs/src/doc/docs/user_guide/plugins/android-plugin.md b/mkdocs/src/doc/docs/user_guide/plugins/android-plugin.md similarity index 100% rename from docs/src/doc/docs/user_guide/plugins/android-plugin.md rename to mkdocs/src/doc/docs/user_guide/plugins/android-plugin.md diff --git a/docs/src/doc/docs/user_guide/plugins/versioning-plugin.md b/mkdocs/src/doc/docs/user_guide/plugins/versioning-plugin.md similarity index 100% rename from docs/src/doc/docs/user_guide/plugins/versioning-plugin.md rename to mkdocs/src/doc/docs/user_guide/plugins/versioning-plugin.md diff --git a/docs/src/doc/mkdocs.yml b/mkdocs/src/doc/mkdocs.yml similarity index 100% rename from docs/src/doc/mkdocs.yml rename to mkdocs/src/doc/mkdocs.yml diff --git a/settings.gradle.kts b/settings.gradle.kts index 859df2bb17..677d78124a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,7 +36,7 @@ include("integration-tests:maven") include("test-utils") -include("docs") +include("mkdocs") pluginManagement { val kotlin_version: String by settings @@ -59,4 +59,4 @@ gradleEnterprise { termsOfServiceAgree = "yes" publishAlwaysIf(isCiBuild) } -} \ No newline at end of file +} From d33aeadd3cb5e069d0fcef628ae273d0a2470491 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 26 Oct 2022 23:14:09 +0200 Subject: [PATCH 02/14] Fix typos --- docs/topics/formats/html.md | 2 +- docs/topics/plugins/plugins_introduction.md | 2 +- docs/topics/runners/cli.md | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index 8004d82086..2f6dcd8f0f 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -22,7 +22,7 @@ This format comes standard in all runners: ## Configuration -HTML format is Dokka's base format, so it is configurable through `DokkaBase` and `DokkaBaseConfiguration`. +HTML format is Dokka's base format, so it is configurable through `DokkaBase` and `DokkaBaseConfiguration`: diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/plugins/plugins_introduction.md index e5bb4a38b0..6b6e18e5df 100644 --- a/docs/topics/plugins/plugins_introduction.md +++ b/docs/topics/plugins/plugins_introduction.md @@ -13,7 +13,7 @@ If you want to learn how to create Dokka plugins, see ## Applying Dokka plugins -Dokka plugins are published as separate artifacts, so to apply a Dokka plugin you only need to add as a dependency. +Dokka plugins are published as separate artifacts, so to apply a Dokka plugin you only need to add it as a dependency. From there, the plugin will extend Dokka by itself - no extra actions needed. > Plugins that use the same extension points or work in a similar way can interfere with each other. diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index e7c210cec0..2b1c340c2b 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -1,6 +1,6 @@ [//]: # (title: CLI runner) -If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) plugin, Dokka has +If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) plugins, Dokka has a command line runner for generating documentation without any build tools. In comparison, it has the same, if not more, capabilities as the Gradle plugin, although it is considerably more @@ -63,8 +63,8 @@ java -jar dokka-cli-%dokkaVersion%.jar \ -outputDir "./dokka/html" ``` -> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler` -> artifact, otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. +> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`, +> otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. > {type="note"} @@ -75,7 +75,7 @@ See [all command line arguments](#command-line-arguments) for more details. ### Running with JSON configuration It is possible to configure the CLI runner with JSON. In this case, you will need to provide an -absolute/relative path to the JSON configuration file,and all the other configuration options will be parsed from it. +absolute/relative path to the JSON configuration file, and all other configuration options will be parsed from it. ```Bash java -jar dokka-cli-%dokkaVersion%.jar dokka-configuration.json From bf1ad46f032b8f7c73a683bea761a77b44637444 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 2 Nov 2022 08:27:08 +0100 Subject: [PATCH 03/14] Address review comments --- docs/topics/formats/html.md | 16 ++-- docs/topics/overview.md | 96 ++++++++++++++++++++- docs/topics/plugins/plugins_introduction.md | 10 +++ docs/topics/plugins/versioning.md | 18 +++- docs/topics/runners/cli.md | 4 +- docs/topics/runners/gradle.md | 93 ++++++++++---------- docs/topics/runners/maven.md | 26 +++--- 7 files changed, 191 insertions(+), 72 deletions(-) diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index 2f6dcd8f0f..36f92055c5 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -164,14 +164,14 @@ For details, see [configuring Dokka plugins](plugins_introduction.md#configuring ### Configuration options -| **Option** | **Description** | -|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `customAssets` | List of paths for image assets to be bundled with documentation. Can have any extension. See [modifying assets](#customizing-assets) section for details. | -| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. See [modifying styles](#customizing-styles) section for details. | -| `footerMessage` | Text displayed in the footer. | -| `separateInheritedMembers` | Boolean property. If set to `true`, Dokka will render properties/functions and inherited properties/inherited functions separately. Disabled by default. | -| `templatesDir` | Path to the directory with custom HTML templates. See [templates](#templates) section for more details. | -| `mergeImplicitExpectActualDeclarations` | Boolean property. If set to true, Dokka will merge declarations that are not declared as expect/actual, but have the same fully qualified name. Can be useful in legacy codebases. Disabled by default. | +| **Option** | **Description** | +|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `customAssets` | List of paths for image assets to be bundled with documentation. Can have any extension. See [modifying assets](#customizing-assets) section for details. | +| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. See [modifying styles](#customizing-styles) section for details. | +| `footerMessage` | Text displayed in the footer. | +| `separateInheritedMembers` | Boolean property. If set to `true`, Dokka will render properties/functions and inherited properties/inherited functions separately. Disabled by default. | +| `templatesDir` | Path to the directory with custom HTML templates. See [templates](#templates) section for more details. | +| `mergeImplicitExpectActualDeclarations` | Boolean property. If set to true, Dokka will merge declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. Can be useful in legacy codebases. Disabled by default. | ## Customization diff --git a/docs/topics/overview.md b/docs/topics/overview.md index ad8443d34d..bbdd0c84ae 100644 --- a/docs/topics/overview.md +++ b/docs/topics/overview.md @@ -12,10 +12,102 @@ multiple flavours of [Markdown](markdown.md) and Java's [Javadoc HTML](javadoc.m Libraries that use Dokka for API reference docs: * [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/) -* [detekt](https://detekt.dev/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.html) +* [Bitmovin](https://cdn.bitmovin.com/player/android/3/docs/index.html) +* [Hexagon](https://hexagonkt.com/api/index.html) * [Ktor](https://api.ktor.io/) -* [Spring Framework](https://docs.spring.io/spring-framework/docs/current/kdoc-api/) * [OkHttp](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) (Markdown) Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or [command line](cli.md). It is also [highly pluggable](plugins_introduction.md). + +## Quickstart + + + + +Apply Dokka Gradle plugin in the root project: + +```kotlin +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} +``` + +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well: + +```kotlin +subprojects { + apply(plugin = "org.jetbrains.dokka") +} +``` + +To generate documentation run the following Gradle tasks: + +* `dokkaHtml` for single-project builds. +* `dokkaHtmlMultiModule` for multi-module builds. + +By default, output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. + +Learn more about Gradle configuration in a separate [topic dedicated to Gradle](gradle.md). + + + + +Apply Dokka Gradle plugin in the root project: + +```groovy +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} +``` + +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well: + +```groovy +subprojects { + apply plugin: 'org.jetbrains.dokka' +} +``` + +To generate documentation run the following Gradle tasks: + +* `dokkaHtml` for single-project builds. +* `dokkaHtmlMultiModule` for multi-module builds. + +By default, output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. + +Learn more about Gradle configuration in a separate [topic dedicated to Gradle](gradle.md). + + + + +Add Dokka Maven plugin to the plugins section of your POM: + +```xml + + + + org.jetbrains.dokka + dokka-maven-plugin + %dokkaVersion% + + + pre-site + + dokka + + + + + + +``` + +To generate documentation run `dokka:dokka` goal. + +By default, output directory is set to `target/dokka`. + +Learn more about Maven configuration in a separate [topic dedicated to Maven](maven.md). + + + diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/plugins/plugins_introduction.md index 6b6e18e5df..af352cfa27 100644 --- a/docs/topics/plugins/plugins_introduction.md +++ b/docs/topics/plugins/plugins_introduction.md @@ -44,6 +44,11 @@ dependencies { } ``` +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins in +> subprojects as well as in their parent project. +> +{type="note"} + @@ -63,6 +68,11 @@ dependencies { } ``` +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins in +> subprojects as well as in their parent project. +> +{type="note"} + diff --git a/docs/topics/plugins/versioning.md b/docs/topics/plugins/versioning.md index 9a7c003993..8148682474 100644 --- a/docs/topics/plugins/versioning.md +++ b/docs/topics/plugins/versioning.md @@ -22,6 +22,11 @@ dependencies { } ``` +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply versioning plugin in +> subprojects as well as in their parent project. +> +{type="note"} + @@ -31,6 +36,11 @@ dependencies { } ``` +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply versioning plugin in +> subprojects as well as in their parent project. +> +{type="note"} + @@ -90,7 +100,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): Versioning plugin has a number of optional configuration properties: -| **Task** | **Description** | +| **Property** | **Description** | |--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `version` | Version of your application/library for which documentation is going to be generated. This will be the version in the dropdown menu. | | `versionsOrdering` | Optional list of strings that represents the order in which versions should appear in the dropdown. Must match version string exactly. First item of the list is the topmost in the dropdown. | @@ -242,9 +252,9 @@ Alternatively, via JSON configuration: With versioning plugin applied and configured, no other steps are needed: documentation can be built the usual way. -Versioning plugin will add a `version.json` file to the output folder. This file will be used by the plugin to match -versions and generate version navigation. If your previously generated documentation does not have that file, you -may need to re-generate it. +Among other things, versioning plugin will add a `version.json` file to the output folder. This file will be used by the +plugin to match versions and generate version navigation. If your previously generated documentation does not have that +file, you will need to re-generate documentation for such versions -- adding just the file will not work. Versioning plugin will also bundle all other documentation versions that have been passed through `olderVersionsDir` and `olderVersions` configuration properties by putting them inside `older` directory. diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index 2b1c340c2b..556bdd8698 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -116,12 +116,12 @@ See [JSON configuration options](#json-configuration) for more details. ### Other output formats -By default, `dokka-base` artifact contains [HTML](html.md) format only. +By default, `dokka-base` artifact contains stable [HTML](html.md) format only. All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use them, you have to put it on plugins classpath. -For example, if you want to generate documentation in [GFM](markdown.md#gfm) format, you have to download and +For example, if you want to generate documentation in experimental [GFM](markdown.md#gfm) format, you have to download and pass [gfm-plugin's jar](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into `pluginsClasspath` configuration option. diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md index d3b4aa3018..08729be8a8 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/gradle.md @@ -62,46 +62,10 @@ plugins { > {type="note"} - -### Legacy plugin application - If you cannot use plugins DSL for some reason, you can use [the legacy method](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application) of applying plugins. - - - -```kotlin -buildscript { - dependencies { - classpath("org.jetbrains.dokka:dokka-gradle-plugin:%dokkaVersion%") - } -} - -apply(plugin="org.jetbrains.dokka") -``` - -> Note that by applying Dokka this way, certain type-safe accessors will not be available in Kotlin DSL. -> -{type="note"} - - - - -```groovy -buildscript { - dependencies { - classpath 'org.jetbrains.dokka:dokka-gradle-plugin:%dokkaVersion%' - } -} - -apply plugin: 'org.jetbrains.dokka' -``` - - - - ## Generating documentation Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) formats built in, @@ -111,9 +75,16 @@ and adds a number of tasks for generating documentation, both for [single](#sing Use the following tasks to build documentation for simple, single project applications and libraries: +#### Stable formats + | **Task** | **Description** | |----------------|-------------------------------------------------------------------------------------| | `dokkaHtml` | Generates documentation in [HTML](html.md) format. | + +#### Experimental formats + +| **Task** | **Description** | +|----------------|-------------------------------------------------------------------------------------| | `dokkaGfm` | Generates documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | | `dokkaJavadoc` | Generates documentation in [Javadoc](javadoc.md) format. | | `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | @@ -123,12 +94,50 @@ Output location, among other things, can be [configured](#configuration) separat ### Multi-project builds -For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), you can -use tasks which are created for all parent projects automatically: +For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), you need +to apply the Dokka plugin in subprojects that you want to generate documentation for as well as in their parent project. + +You can use `allprojects {}` and `subprojects {}` Gradle configurations to achieve that: + + + + +```kotlin +subprojects { + apply(plugin = "org.jetbrains.dokka") +} +``` + + + + +```groovy +subprojects { + apply plugin: 'org.jetbrains.dokka' +} +``` + + + + +#### MultiModule tasks + +`MultiModule` tasks generate documentation for each subproject individually via [partial](#partial-tasks) tasks, +collect and process all outputs, and produce complete documentation with a common table of contents and resolved +cross-project references. + +Dokka creates the following tasks for **parent** projects automatically: + +#### Stable formats | **Task** | **Description** | |--------------------------|--------------------------------------------------------------------------------------------------| | `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](html.md) format. | + +#### Experimental formats + +| **Task** | **Description** | +|--------------------------|--------------------------------------------------------------------------------------------------| | `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | | `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | @@ -137,13 +146,9 @@ use tasks which are created for all parent projects automatically: > {type="note"} -A _MultiModule_ task generates documentation for each subproject individually via [partial](#partial-tasks) tasks, -collects and processes all outputs, and produces complete documentation with a common table of contents and resolved -cross-project references. - By default, you will find ready-to-use documentation under `{parentProject}/build/dokka/{format}MultiModule` directory. -##### MultiModule task example +#### MultiModule task example Given a project with the following structure: @@ -287,7 +292,7 @@ tasks.dokkaHtmlPartial { } ``` -If you applied Dokka with the [buildscript block](#legacy-plugin-application): +If you applied Dokka with the [buildscript block](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application): ```kotlin import org.jetbrains.dokka.gradle.DokkaTask diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index a6f619598c..c578ebb310 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -3,7 +3,7 @@ To generate documentation for Maven-based projects, you can use [Dokka Maven plugin](#applying-the-plugin). > Compared to the [Gradle plugin](gradle.md), Maven plugin has only basic features and -> **does not support multiplatform projects**. +> does not provide support for multimodule builds out of the box. > {type="note"} @@ -35,17 +35,18 @@ To apply the plugin, you need to add it to the plugins section of your POM: Following goals are provided by the plugin: -| **Goal** | **Description** | -|-----------------------|---------------------------------------------------------------------------------------------| -| `dokka:dokka` | Generates documentation with Dokka plugins applied. [HTML](html.md) format by default. | -| `dokka:javadoc` | Generates documentation in [Javadoc](javadoc.md) format. | -| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in [Javadoc](javadoc.md) format. | +### Stable -> Unlike [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin only comes with [HTML](html.md) format built in -> and does not provide any separate goals to generate documentation in other formats. In order to do that, you will have -> to [apply other formats as Dokka plugins](#other-output-formats) and re-run `dokka:dokka` goal. -> -{type="note"} +| **Goal** | **Description** | +|---------------|----------------------------------------------------------------------------------------| +| `dokka:dokka` | Generates documentation with Dokka plugins applied. [HTML](html.md) format by default. | + +### Experimental + +| **Goal** | **Description** | +|--------------------|---------------------------------------------------------------------------------------------| +| `dokka:javadoc` | Generates documentation in [Javadoc](javadoc.md) format. | +| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in [Javadoc](javadoc.md) format. | ### Other output formats @@ -54,7 +55,8 @@ By default, Maven plugin will build documentation in [HTML](html.md) format. All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use it, you have to apply it as a dependency. -For example, for [GFM](markdown.md#gfm) format, you have to use apply `org.jetbrains.dokka:gfm-plugin` in the following way: +For example, to use experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in +the following way: ```xml From 47252c8a8e382f0b81f7a1a8f6a5f94329708ffe Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 16 Nov 2022 03:25:10 +0100 Subject: [PATCH 04/14] Add descriptions for configuration options --- core/api/core.api | 7 +- core/src/main/kotlin/DokkaBootstrapImpl.kt | 36 - core/src/main/kotlin/configuration.kt | 46 +- core/src/main/kotlin/defaultConfiguration.kt | 8 +- docs/topics/formats/html.md | 33 +- docs/topics/formats/markdown.md | 2 +- docs/topics/overview.md | 5 + docs/topics/plugins/plugins_introduction.md | 10 +- docs/topics/plugins/versioning.md | 25 +- docs/topics/runners/cli.md | 590 ++++++++++++- docs/topics/runners/gradle.md | 787 ++++++++++++++++-- docs/topics/runners/maven.md | 420 +++++++++- runners/cli/api/cli.api | 10 +- .../org/jetbrains/dokka/CliArgumentTypes.kt | 91 ++ .../org/jetbrains/dokka/GlobalArguments.kt | 164 ++++ .../kotlin/org/jetbrains/dokka/LinkMapper.kt | 37 + .../jetbrains/dokka/PackageOptionsParser.kt | 34 + .../dokka/SourceSetArgumentsParser.kt | 155 ++++ .../main/kotlin/org/jetbrains/dokka/main.kt | 429 +--------- .../dokka/gradle/AbstractDokkaTask.kt | 134 ++- .../dokka/gradle/DokkaMultiModuleTask.kt | 27 + ...urceSetImpl.kt => DokkaSourceSetMapper.kt} | 0 .../gradle/GradleDokkaSourceSetBuilder.kt | 353 +++++++- .../GradleDokkaSourceSetBuilderExtensions.kt | 9 + .../GradleExternalDocumentationLinkBuilder.kt | 48 ++ .../gradle/GradlePackageOptionsBuilder.kt | 74 +- .../dokka/gradle/GradleSourceLinkBuilder.kt | 50 ++ runners/maven-plugin/api/maven-plugin.api | 32 +- .../maven-plugin/src/main/kotlin/DokkaMojo.kt | 289 +++++-- .../ExternalDocumentationLinkBuilder.kt | 63 ++ .../src/main/kotlin/PackageOptions.kt | 85 ++ .../src/main/kotlin/SourceLinkMapItem.kt | 65 ++ 32 files changed, 3384 insertions(+), 734 deletions(-) create mode 100644 runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt create mode 100644 runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt create mode 100644 runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt create mode 100644 runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt create mode 100644 runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt rename runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/{toDokkaSourceSetImpl.kt => DokkaSourceSetMapper.kt} (100%) create mode 100644 runners/maven-plugin/src/main/kotlin/ExternalDocumentationLinkBuilder.kt create mode 100644 runners/maven-plugin/src/main/kotlin/PackageOptions.kt create mode 100644 runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt diff --git a/core/api/core.api b/core/api/core.api index 7d29d872bc..f466ed71e0 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -57,10 +57,6 @@ public final class org/jetbrains/dokka/DokkaBootstrapImpl$DokkaProxyLogger : org public fun warn (Ljava/lang/String;)V } -public final class org/jetbrains/dokka/DokkaBootstrapImplKt { - public static final fun parsePerPackageOptions (Ljava/util/List;)Ljava/util/List; -} - public abstract interface class org/jetbrains/dokka/DokkaConfiguration : java/io/Serializable { public abstract fun getCacheRoot ()Ljava/io/File; public abstract fun getDelayTemplateSubstitution ()Z @@ -215,6 +211,7 @@ public final class org/jetbrains/dokka/DokkaDefaults { public static final field format Ljava/lang/String; public static final field includeNonPublic Z public static final field jdkVersion I + public static final field noAndroidSdkLink Z public static final field noJdkLink Z public static final field noStdlibLink Z public static final field offlineMode Z @@ -224,6 +221,7 @@ public final class org/jetbrains/dokka/DokkaDefaults { public static final field sourceSetDisplayName Ljava/lang/String; public static final field sourceSetName Ljava/lang/String; public static final field suppress Z + public static final field suppressGeneratedFiles Z public static final field suppressInheritedMembers Z public static final field suppressObviousFunctions Z public final fun getAnalysisPlatform ()Lorg/jetbrains/dokka/Platform; @@ -365,6 +363,7 @@ public final class org/jetbrains/dokka/GlobalDokkaConfiguration { public final class org/jetbrains/dokka/PackageOptionsImpl : org/jetbrains/dokka/DokkaConfiguration$PackageOptions { public fun (Ljava/lang/String;ZLjava/lang/Boolean;ZZLjava/util/Set;)V + public synthetic fun (Ljava/lang/String;ZLjava/lang/Boolean;ZZLjava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Z public final fun component3 ()Ljava/lang/Boolean; diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index 75c4c0afe9..114bade7d2 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -1,45 +1,9 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.DokkaConfiguration.PackageOptions import org.jetbrains.dokka.utilities.DokkaLogger import java.util.function.BiConsumer - -fun parsePerPackageOptions(args: List): List = args.map { it.split(",") }.map { - val matchingRegex = it.first() - - val options = it.subList(1, it.size) - - val deprecated = options.find { it.endsWith("skipDeprecated") }?.startsWith("+") - ?: DokkaDefaults.skipDeprecated - - val reportUndocumented = options.find { it.endsWith("reportUndocumented") }?.startsWith("+") - ?: DokkaDefaults.reportUndocumented - - val privateApi = options.find { it.endsWith("includeNonPublic") }?.startsWith("+") - ?: DokkaDefaults.includeNonPublic - - val suppress = options.find { it.endsWith("suppress") }?.startsWith("+") - ?: DokkaDefaults.suppress - - val documentedVisibilities = options - .filter { it.matches(Regex("\\+visibility:.+")) } // matches '+visibility:' with at least one symbol after the semicolon - .map { DokkaConfiguration.Visibility.fromString(it.split(":")[1]) } - .toSet() - .ifEmpty { DokkaDefaults.documentedVisibilities } - - PackageOptionsImpl( - matchingRegex, - includeNonPublic = privateApi, - documentedVisibilities = documentedVisibilities, - reportUndocumented = reportUndocumented, - skipDeprecated = !deprecated, - suppress = suppress - ) -} - - /** * Accessed with reflection */ diff --git a/core/src/main/kotlin/configuration.kt b/core/src/main/kotlin/configuration.kt index c26faf2877..77384acee5 100644 --- a/core/src/main/kotlin/configuration.kt +++ b/core/src/main/kotlin/configuration.kt @@ -12,30 +12,38 @@ import java.net.URL object DokkaDefaults { val moduleName: String = "root" + val moduleVersion: String? = null val outputDir = File("./dokka") - const val format: String = "html" - val cacheRoot: File? = null - const val offlineMode: Boolean = false const val failOnWarning: Boolean = false - const val delayTemplateSubstitution: Boolean = false + const val suppressObviousFunctions = true + const val suppressInheritedMembers = false + const val offlineMode: Boolean = false + + const val sourceSetDisplayName = "JVM" + const val sourceSetName = "main" + val analysisPlatform: Platform = Platform.DEFAULT + + const val suppress: Boolean = false + const val suppressGeneratedFiles: Boolean = true - const val includeNonPublic: Boolean = false - val documentedVisibilities: Set = setOf(DokkaConfiguration.Visibility.PUBLIC) - const val reportUndocumented: Boolean = false const val skipEmptyPackages: Boolean = true const val skipDeprecated: Boolean = false - const val jdkVersion: Int = 8 + + const val reportUndocumented: Boolean = false + const val noStdlibLink: Boolean = false + const val noAndroidSdkLink: Boolean = false const val noJdkLink: Boolean = false - val analysisPlatform: Platform = Platform.DEFAULT - const val suppress: Boolean = false + const val jdkVersion: Int = 8 + + const val includeNonPublic: Boolean = false + val documentedVisibilities: Set = setOf(DokkaConfiguration.Visibility.PUBLIC) - const val sourceSetDisplayName = "JVM" - const val sourceSetName = "main" - val moduleVersion: String? = null val pluginsConfiguration = mutableListOf() - const val suppressObviousFunctions = true - const val suppressInheritedMembers = false + + const val delayTemplateSubstitution: Boolean = false + + val cacheRoot: File? = null } enum class Platform(val key: String) { @@ -88,10 +96,12 @@ data class DokkaSourceSetID( fun DokkaConfigurationImpl(json: String): DokkaConfigurationImpl = parseJson(json) /** - * Global options are applied to all packages and modules and overwrite package configuration. + * Global options can be configured and applied to all packages and modules at once, overwriting package configuration. + * + * These are handy if we have multiple source sets sharing the same global options as it reduces the size of the + * boilerplate. Otherwise, the user would be forced to repeat all these options for each source set. * - * These are handy if we have multiple sourcesets sharing the same global options as it reduces the size of the boilerplate. - * Otherwise, the user would be enforced to repeat all these options per each sourceset. + * @see [apply] to learn how to apply global configuration */ data class GlobalDokkaConfiguration( val perPackageOptions: List?, diff --git a/core/src/main/kotlin/defaultConfiguration.kt b/core/src/main/kotlin/defaultConfiguration.kt index 8c7c8b5da4..6615457085 100644 --- a/core/src/main/kotlin/defaultConfiguration.kt +++ b/core/src/main/kotlin/defaultConfiguration.kt @@ -71,9 +71,9 @@ data class SourceLinkDefinitionImpl( fun parseSourceLinkDefinition(srcLink: String): SourceLinkDefinitionImpl { val (path, urlAndLine) = srcLink.split('=') return SourceLinkDefinitionImpl( - File(path).canonicalPath, - URL(urlAndLine.substringBefore("#")), - urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" }) + localDirectory = File(path).canonicalPath, + remoteUrl = URL(urlAndLine.substringBefore("#")), + remoteLineSuffix = urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" }) } } } @@ -85,7 +85,7 @@ data class PackageOptionsImpl( override val reportUndocumented: Boolean?, override val skipDeprecated: Boolean, override val suppress: Boolean, - override val documentedVisibilities: Set, + override val documentedVisibilities: Set, // TODO add default to DokkaDefaults.documentedVisibilities ) : DokkaConfiguration.PackageOptions diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index 36f92055c5..2d0c6f6774 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -22,7 +22,8 @@ This format comes standard in all runners: ## Configuration -HTML format is Dokka's base format, so it is configurable through `DokkaBase` and `DokkaBaseConfiguration`: +HTML format is Dokka's base format, so it is configurable through `DokkaBase` and `DokkaBaseConfiguration` +classes: @@ -160,7 +161,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): -For details, see [configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins) section. +For more details, see [configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins) topic. ### Configuration options @@ -176,7 +177,7 @@ For details, see [configuring Dokka plugins](plugins_introduction.md#configuring ## Customization -HTML format is highly customizable to the point where you wouldn't be able to tell it was generated by Dokka. +HTML format provides a number of customization options. ### Customizing styles @@ -192,7 +193,7 @@ Files with the same name will be overwritten, so it is possible to override styl | `prism.css` | Styles for [PrismJS](https://prismjs.com/) syntax highlighter | | `jetbrains-mono.css` | Font styling | -All of these are +Source code for all of the used styles is [available on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/styles). ### Customizing assets @@ -203,7 +204,7 @@ You can provide your own images to be bundled with documentation by setting `cus Files with the same name will be overwritten, so it is possible to override images and icons that Dokka uses. The most useful and relevant one being `logo-icon.svg`, which is the image that's used in the header. The rest is mostly icons. -You can view all images used by Dokka on +You can find all images used by Dokka on [GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/images). ### Changing the logo @@ -211,10 +212,10 @@ You can view all images used by Dokka on To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. If your image has similar size, it should not look out of place. -However, if your image has different dimensions or you want to use a `.png` image instead of the default `.svg`, -you can [override `logo-styles.css` stylesheet](#customizing-styles). +However, if your image has different dimensions or you want to use a `.png` image instead of the default `.svg` file, +you can [override `logo-styles.css` stylesheet](#customizing-styles) and make it fit. -For more details, see +For an example of how to do it, see [custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). ### Modifying footer @@ -226,7 +227,7 @@ You can modify the footer message by setting `footerMessage` [configuration prop Dokka provides the ability to modify [FreeMarker](https://freemarker.apache.org/) templates used for generating documentation pages. -You can completely change the header, add your own banners/menus/search, load analytics, change body styling and so on. +You can change the header completely, add your own banners/menus/search, load analytics, change body styling and so on. Dokka uses the following templates: @@ -238,7 +239,7 @@ Dokka uses the following templates: | `includes/page_metadata.ft` | Metadata used within `` container. | | `includes/source_set_selector.ft` | [Source set](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) selector in the header. | -`base.ftl` template is the base template and it includes all the other ones. You can find all templates +`base.ftl` template is the base template and it includes all the other ones. You can find source code for all templates [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/templates). You can override any template by setting `templatesDir` [configuration property](#configuration). Dokka will look @@ -268,11 +269,11 @@ context and thus need to be resolved at later stages by the [MultiModule](gradle #### Directives -Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html) can also be used: +You can also use the following Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html): -| **Variable** | **Description** | -|----------------------------|----------------------------------------------------------------------------------------------------------------------------------------| -| `<@content/>` | Main page content. | -| `<@resources/>` | Resources such as scripts and stylesheets. | -| `<@version/>` | Module version taken from configuration. If [versioning plugin](versioning.md) is applied, it will be replaced with version navigator. | +| **Variable** | **Description** | +|-----------------|----------------------------------------------------------------------------------------------------------------------------------------| +| `<@content/>` | Main page content. | +| `<@resources/>` | Resources such as scripts and stylesheets. | +| `<@version/>` | Module version taken from configuration. If [versioning plugin](versioning.md) is applied, it will be replaced with version navigator. | diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/markdown.md index edae3fed6a..42ed18cf64 100644 --- a/docs/topics/formats/markdown.md +++ b/docs/topics/formats/markdown.md @@ -10,7 +10,7 @@ These formats give you more freedom in terms of hosting documentation as the out documentation website. For example, see [OkHttp's API reference](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) pages. -Markdown output formats are rendering [Dokka plugin](plugins_introduction.md), maintained by the Dokka team, and +Markdown output formats are rendering [Dokka plugins](plugins_introduction.md), maintained by the Dokka team, and they are open source. ## GFM diff --git a/docs/topics/overview.md b/docs/topics/overview.md index bbdd0c84ae..f88a9d884a 100644 --- a/docs/topics/overview.md +++ b/docs/topics/overview.md @@ -111,3 +111,8 @@ Learn more about Maven configuration in a separate [topic dedicated to Maven](ma + +## Community + +Dokka has a dedicated `#dokka` channel in [Kotlin Community Slack](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up) +where you can chat about Dokka itself, its plugins and how to develop them, and get in touch with maintainers. diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/plugins/plugins_introduction.md index af352cfa27..3b162e0c3e 100644 --- a/docs/topics/plugins/plugins_introduction.md +++ b/docs/topics/plugins/plugins_introduction.md @@ -17,12 +17,14 @@ Dokka plugins are published as separate artifacts, so to apply a Dokka plugin yo From there, the plugin will extend Dokka by itself - no extra actions needed. > Plugins that use the same extension points or work in a similar way can interfere with each other. -> This may lead to visual bugs, general undefined behaviour or even failed builds. If you notice anything of that -> nature, it's a good idea to check which plugins are applied and what they do. +> This may lead to visual bugs, general undefined behaviour or even failed builds. However, it should not lead to +> concurrency issues since Dokka does not expose any mutable data structures or objects. +> +> If you notice any problems of such nature, it's a good idea to check which plugins are applied and what they do. > {type="note"} -Let's have a look at how you can apply [mathjax plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) +Let's have a look at how you can apply the [mathjax plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) to your project: @@ -125,7 +127,7 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), D ## Configuring Dokka plugins -Dokka plugins can also have configuration options of their own. Consult plugin's documentation to see which +Dokka plugins can also have configuration options of their own. Consult used plugin's documentation to see which options are available. Let's have a look at how you can configure `DokkaBase` plugin, which is responsible for generating [HTML](html.md) diff --git a/docs/topics/plugins/versioning.md b/docs/topics/plugins/versioning.md index 8148682474..9cdbeebfb3 100644 --- a/docs/topics/plugins/versioning.md +++ b/docs/topics/plugins/versioning.md @@ -9,9 +9,12 @@ with seamless switching between them. This, in turn, provides better experience > {type="note"} +Visit [versioning plugin example project](https://github.com/Kotlin/dokka/tree/1.7.20/examples/gradle/dokka-versioning-multimodule-example) +to see it in action as well as how it can be configured. + ## Applying the plugin -You can apply Versioning plugin the same way as other [Dokka plugins](plugins_introduction.md#applying-dokka-plugins): +You can apply the versioning plugin the same way as other [Dokka plugins](plugins_introduction.md#applying-dokka-plugins): @@ -100,13 +103,13 @@ Via [JSON configuration](cli.md#running-with-json-configuration): Versioning plugin has a number of optional configuration properties: -| **Property** | **Description** | -|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `version` | Version of your application/library for which documentation is going to be generated. This will be the version in the dropdown menu. | -| `versionsOrdering` | Optional list of strings that represents the order in which versions should appear in the dropdown. Must match version string exactly. First item of the list is the topmost in the dropdown. | -| `olderVersionsDir` | Optional path to a parent folder that contains other documentation versions. Requires a certain [directory structure](#directory-structure). | -| `olderVersions` | Optional list of paths to other documentation versions. Must point to Dokka's outputs directly. Useful if different versions are scattered and cannot be put into a single directory. | -| `renderVersionsNavigationOnAllPages` | Optional boolean indicating whether to render navigation dropdown on all pages. True by default. | +| **Property** | **Description** | +|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `version` | Version of your application/library for which documentation is going to be generated. This will be the version in the dropdown menu. | +| `versionsOrdering` | Optional list of strings that represents the order in which versions should appear in the dropdown menu. Must match versions string exactly. First item of the list is the topmost in the dropdown. | +| `olderVersionsDir` | Optional path to a parent folder that contains other documentation versions. Requires a certain [directory structure](#directory-structure). | +| `olderVersions` | Optional list of paths to other documentation versions. Must point to Dokka's outputs directly. Useful if different versions are scattered and cannot be put into a single directory. | +| `renderVersionsNavigationOnAllPages` | Optional boolean indicating whether to render navigation dropdown on all pages. True by default. | #### Directory structure @@ -267,15 +270,15 @@ can begin publishing versioned documentation right away. The main idea behind it is the following: -1. One directory will contains all versions of your documentation. For instance, `documentation/version/{version_string}`. +1. One directory will contain all versions of your documentation. For instance, `documentation/version/{doc_version}`. This is your archive, you will need to preserve it for future builds. 2. Output directory of all new builds will be set to that directory as well, under `documentation/version/{new_version}` 3. When new builds are executed, the plugin will look for previous versions of documentation in the archive directory. 4. Once new documentation has been generated, it needs to be **copied** to some place accessible by the user: GitHub pages, nginx static directories, and so on. It needs to be copied and not moved because Dokka will still need this version for future builds, otherwise there will be a gap in the archive. -5. Once it has been safely copied away, you can remove `older` directory from the archived version. This helps reduce - the overhead of each version bundling all previous versions as these files are effectively duplicate. +5. Once it has been safely copied away, you can remove `older` directory from the newly generated and archived version. + This helps reduce the overhead of each version bundling all previous versions, as these files are effectively duplicates. ```kotlin import org.jetbrains.dokka.versioning.VersioningPlugin diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index 556bdd8698..59999ee34f 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -70,7 +70,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ Executing the given example should generate documentation in [HTML](html.md) format. -See [all command line arguments](#command-line-arguments) for more details. +See [command line arguments](#command-line-arguments) for more configuration details. ### Running with JSON configuration @@ -88,7 +88,7 @@ At the very least, you would need the following configuration: "sourceSets": [ { "sourceSetID": { - "scopeId": "html", + "scopeId": "moduleName", "sourceSetName": "main" }, "sourceRoots": [ @@ -152,16 +152,585 @@ needed. For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#geneatring-javadoc-documentation) topics. -## Configuration +## Command line arguments -### Command line arguments +You can see short descriptions for command line arguments by running: -TODO paste output of `-help` after correcting in-code descriptions. +```Bash +java -jar dokka-cli-%dokkaVersion%.jar -help +``` + +Summary: + +- `-moduleName` -> Name of the project/module. +- `-moduleVersion` -> Documented version. +- `-outputDir` -> Output directory path, `./dokka` by default. +- `-sourceSet` -> Configuration for a Dokka source set. Contains nested configuration. +- `-pluginsConfiguration` -> Configuration for Dokka plugins. +- `-pluginsClasspath` -> List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons. +- `-offlineMode` -> Whether to resolve remote files/links over network. +- `-failOnWarning` -> Whether to fail documentation generation if Dokka has emitted a warning or an error. +- `-delayTemplateSubstitution` -> Delay substitution of some elements. Used in incremental builds of + multimodule projects. +- `-noSuppressObviousFunctions` -> Whether to suppress obvious functions such as inherited from `kotlin.Any` + and `java.lang.Object`. +- `-includes` -> Markdown files that contain module and package documentation. Accepts multiple values separated by + semicolons. +- `-suppressInheritedMembers` -> Whether to suppress inherited members that aren't explicitly overridden in a + given class. +- `-globalPackageOptions` -> Global list of package configurations in format + `"matchingRegex,-deprecated,-privateApi,+warnUndocumented,+suppress;+visibility:PUBLIC;..."`. + Accepts multiple values separated by semicolons. +- `-globalLinks` -> Global external documentation links in format `{url}^{packageListUrl}`. + Accepts multiple values separated by `^^`. +- `-globalSrcLink` -> Global mapping between a source directory and a Web service for browsing the code. + Accepts multiple paths separated by semicolons. +- `-helpSourceSet` -> Prints help for nested `-sourceSet` configuration. +- `-loggingLevel` -> Logging level, possible values: `DEBUG, PROGRESS, INFO, WARN, ERROR`. +- `-help, -h` -> Usage info. + +#### Source set arguments + +You can also see short descriptions for nested `-sourceSet` configuration: -### JSON configuration +```Bash +java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help +``` -TODO add descriptions for each setting as a separate entry in a table -TODO add a link to Dokka's api reference, to DokkaConfiguration class +Summary: + +- `-sourceSetName` -> Name of the source set. +- `-displayName` -> Display name of the source set, used both internally and externally. +- `-classpath` -> Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons. +- `-src` -> Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons. +- `-dependentSourceSets` -> Names of dependent source sets in format `moduleName/sourceSetName`. + Accepts multiple paths separated by semicolons. +- `-samples` -> List of directories or files that contain sample functions. Accepts multiple paths separated by semicolons. +- `-includes` -> Markdown files that contain module and package documentation. Accepts multiple paths separated by semicolons. +- `-includeNonPublic` -> Deprecated, use `documentedVisibilities`. + Possible values: `PUBLIC`, `PRIVATE`, `PROTECTED`, `INTERNAL`, `PACKAGE`. +- `-documentedVisibilities` -> Visibilities to be documented. Accepts multiple values separated by semicolons. +- `-reportUndocumented` -> Whether to report undocumented declarations. +- `-noSkipEmptyPackages` -> Whether to create pages for empty packages. +- `-skipDeprecated` -> Whether to skip deprecated declarations. +- `-jdkVersion` -> Version of JDK to use for linking to JDK Javadocs. +- `-languageVersion` -> Language version used for setting up analysis and samples. +- `-apiVersion` -> Kotlin API version used for setting up analysis and samples. +- `-noStdlibLink` -> Whether to generate links to Standard library. +- `-noJdkLink` -> Whether to generate links to JDK Javadocs. +- `-suppressedFiles` -> Paths to files to be suppressed. Accepts multiple paths separated by semicolons. +- `-analysisPlatform` -> Platform used for setting up analysis. +- `-perPackageOptions` -> List of package source set configuration in format + `matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...`. Accepts multiple values separated by semicolons. +- `-externalDocumentationLinks` -> External documentation links in format `{url}^{packageListUrl}`. + Accepts multiple values separated by `^^`. +- `-srcLink` -> Mapping between a source directory and a Web service for browsing the code. + Accepts multiple paths separated by semicolons. +- `-help`, `-h` -> Usage info + +## JSON configuration + +Below you will find examples and detailed descriptions for each configuration section. You can also find an example +with [all configuration options](#complete-configuration) applied at once at the very bottom. + +### General configuration + +```json +{ + "moduleName": "Dokka Example", + "moduleVersion": null, + "outputDir": "./build/dokka/html", + "failOnWarning": false, + "suppressObviousFunctions": true, + "suppressInheritedMembers": false, + "offlineMode": false, + "includes": [ + "module.md" + ], + "sourceLinks": [ + { "_comment": "Options are described in a separate section" } + ], + "perPackageOptions": [ + { "_comment": "Options are described in a separate section" } + ], + "externalDocumentationLinks": [ + { "_comment": "Options are described in a separate section" } + ], + "sourceSets": [ + { "_comment": "Options are described in a separate section" } + ], + "pluginsClasspath": [ + "./dokka-base-%dokkaVersion%.jar", + "./kotlinx-html-jvm-0.8.0.jar", + "./dokka-analysis-%dokkaVersion%.jar", + "./kotlin-analysis-intellij-%dokkaVersion%.jar", + "./kotlin-analysis-compiler-%dokkaVersion%.jar", + "./freemarker-2.3.31.jar" + ] +} +``` + + + +

Display name used to refer to the module. Used for ToC, navigation, logging, etc.

+

Default is root.

+
+ +

Module version.

+

Default is empty.

+
+ +

Directory to which documentation will be generated, regardless of format.

+

Default is ./dokka

+
+ +

+ Whether to fail documentation generation if Dokka has emitted a warning or an error. + Will wait until all errors and warnings have been emitted first. +

+

This setting works well with reportUndocumented

+

Default is false.

+
+ +

Whether to suppress obvious functions.

+

+ A function is considered to be obvious if it is: + +

  • + Inherited from kotlin.Any, Kotlin.Enum, java.lang.Object or + java.lang.Enum, such as equals, hashCode, toString. +
  • +
  • + Synthetic (generated by the compiler) and does not have any documentation, such as + dataClass.componentN or dataClass.copy. +
  • + +

    +

    Default is true.

    +
    + +

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    +

    + Note: this can suppress functions such as equals / hashCode / toString, + but cannot suppress synthetic functions such as dataClass.componentN and + dataClass.copy. Use suppressObviousFunctions + for that. +

    +

    Default is false.

    +
    + +

    Whether to resolve remote files/links over network.

    +

    + This includes package-lists used for generating external documentation links: + for instance, to make classes from standard library clickable. +

    +

    + Setting this to true can significantly speed up build times in certain cases, + but can also worsen documentation quality and user experience, for instance by + not resolving some dependency's class/member links. +

    +

    + Note: you can cache fetched files locally and provide them to + Dokka as local paths. See externalDocumentationLinks. +

    +

    Default is false.

    +
    + +
    +

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +

    Can be configured on per-package basis.

    + + +

    + Individual and additional configuration of Kotlin + source sets. +

    +

    For a list of possible options, see source set configuration.

    +
    + +

    Global configuration of source links that will be applied for all source sets.

    +

    For a list of possible options, see source link configuration.

    +
    + +

    Global configuration of matched packages, regardless of the source set they are in.

    +

    For a list of possible options, see per-package configuration.

    +
    + +

    Global configuration of external documentation links, regardless of the source set they are used in.

    +

    For a list of possible options, see external documentation configuration.

    +
    + +

    List of jars with Dokka plugins and their dependencies.

    +
    + + +### Source set configuration + +Configuration of Kotlin +[source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). + +```json +{ + "sourceSets": [ + { + "displayName": "jvm", + "sourceSetID": { + "scopeId": "moduleName", + "sourceSetName": "main" + }, + "dependentSourceSets": [ + { + "scopeId": "dependentSourceSetScopeId", + "sourceSetName": "dependentSourceSetName" + } + ], + "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"], + "reportUndocumented": false, + "skipEmptyPackages": true, + "skipDeprecated": false, + "jdkVersion": 8, + "languageVersion": "1.7", + "apiVersion": "1.7", + "noStdlibLink": false, + "noJdkLink": false, + "includes": [ + "module.md" + ], + "analysisPlatform": "jvm", + "sourceRoots": [ + "/home/ignat/IdeaProjects/dokka-debug-mvn/src/main/kotlin" + ], + "classpath": [ + "libs/kotlin-stdlib-%kotlinVersion%.jar", + "libs/kotlin-stdlib-common-%kotlinVersion%.jar" + ], + "samples": [ + "samples/basic.kt" + ], + "suppressedFiles": [ + "src/main/kotlin/org/jetbrains/dokka/Suppressed.kt" + ], + "sourceLinks": [ + { "_comment": "Options are described in a separate section" } + ], + "perPackageOptions": [ + { "_comment": "Options are described in a separate section" } + ], + "externalDocumentationLinks": [ + { "_comment": "Options are described in a separate section" } + ] + } + ] +} +``` + + + +

    Display name used to refer to the source set.

    +

    + The name will be used both externally (for example, as source set name visible to documentation readers) and + internally (for example, for logging messages of reportUndocumented). +

    +

    Platform name could be used if you don't have a better alternative.

    +
    + +

    Technical ID of the source set

    +
    + +

    Set of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations, + as well as if you want to exclude public declarations and only document internal API. +

    +

    Can be configured on per-package basis.

    +

    + Possible values: + +

  • PUBLIC
  • +
  • PRIVATE
  • +
  • PROTECTED
  • +
  • INTERNAL
  • +
  • PACKAGE
  • + +

    +

    Default is PUBLIC.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning. Can be overridden for a specific package

    +

    Default is false.

    +
    + +

    + Whether to skip packages that contain no visible declarations after + various filters have been applied. +

    +

    + For instance, if skipDeprecated is set to true and your package contains only + deprecated declarations, it will be considered to be empty. +

    +

    Default for CLI runner is false.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be overridden on package level.

    +

    Default is false.

    +
    + +

    JDK version to use when generating external documentation links for Java types.

    +

    + For instance, if you use java.util.UUID from JDK in some public declaration signature, + and this property is set to 8, Dokka will generate an external documentation link + to JDK 8 Javadocs for it. +

    +
    + +

    + Kotlin language version + used for setting up analysis and @sample + environment. +

    +
    + +

    + Kotlin API version + used for setting up analysis and @sample + environment. +

    +
    + +

    + Whether to generate external documentation links that lead to API reference + documentation for Kotlin's standard library when declarations from it are used. +

    +

    Default is false, meaning links will be generated.

    +
    + +

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    +

    The version of JDK Javadocs is determined by jdkVersion property.

    +

    Default is false, meaning links will be generated.

    +
    + +

    + List of Markdown files that contain + module and package documentation. +

    +

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +
    + +

    + Platform to be used for setting up code analysis and + @sample environment. +

    +

    The default value is deduced from information provided by the Kotlin Gradle plugin.

    +

    + Possible values: + +

  • jvm
  • +
  • common
  • +
  • js
  • +
  • native
  • + +

    +
    + +

    + Source code roots to be analyzed and documented. + Accepts directories and individual .kt / .java files. +

    +
    + +

    + Classpath for analysis and interactive samples. If you use a declaration from a dependency, + it should be present on the classpath to be resolved. +

    +

    Property accepts both .jar and .klib files.

    +
    + +

    + List of directories or files that contain sample functions which are referenced via + @sample KDoc tag. +

    +
    + +

    Files to be suppressed when generating documentation.

    +
    + +

    Configuration of source links that will be applied only for this source set.

    +

    For a list of possible options, see source link configuration.

    +
    + +

    Configuration specific to matched packages within this source set.

    +

    For a list of possible options, see per-package configuration.

    +
    + +

    Configuration of external documentation links that will be applied only for this source set.

    +

    For a list of possible options, see external documentation configuration.

    +
    +
    + +### Source link configuration + +Configuration block that allows adding a `source` link to each signature +which leads to `remoteUrl` with a specific line number (configurable by setting `remoteLineSuffix`), +letting documentation readers find source code for each declaration. + +For an example, see documentation for +[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function from `kotlinx.coroutines`. + +Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) + +```json +{ + "sourceLinks": [ + { + "localDirectory": "src/main/kotlin", + "remoteUrl": "https://github.com/Kotlin/dokka/tree/master/src/main/kotlin", + "remoteLineSuffix": "#L" + } + ] +} +``` + + + +

    Path to the local source directory.

    +
    + +

    + URL of source code hosting service that can be accessed by documentation readers, + like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + source code links of declarations. +

    +
    + +

    + Suffix used to append source code line number to the URL. This will help readers navigate + not only to the file, but to the specific line number of the declaration. +

    +

    + The number itself will be appended to the specified suffix. For instance, + if this property is set to #L and the line number is 10, resulting URL suffix + will be #L10. +

    +

    + Suffixes used by popular services: + +

  • GitHub: #L
  • +
  • GitLab: #L
  • +
  • Bitbucket: #lines-
  • + +

    +

    Default is empty (no suffix).

    +
    +
    + +### Per-package configuration + +Configuration block that allows setting some options for specific packages matched by `matchingRegex`. + +Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) + +```json +{ + "perPackageOptions": [ + { + "matchingRegex": ".*internal.*", + "suppress": false, + "skipDeprecated": false, + "reportUndocumented": false, + "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"] + } + ] +} +``` + + + +

    Regular expression that is used to match the package.

    +
    + +

    Whether this package should be skipped when generating documentation.

    +

    Default is false.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be set on project/module level.

    +

    Default is false.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations from + this package and without KDocs, after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning.

    +

    Can be configured on source set level.

    +

    Default is false.

    +
    + +

    Set of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations within a + specific package, as well as if you want to exclude public declarations and only document internal API. +

    +

    Can be configured on source set level.

    +

    Default is PUBLIC.

    +
    +
    + +### External documentation configuration + +Configuration block that allows creating links leading to externally hosted documentation of your dependencies. + +For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your +documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is +[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external +documentation links for it, allowing Dokka to generate links for used types, making them clickable +and appear resolved. + +Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) + +```json +{ + "externalDocumentationLinks": [ + { + "url": "https://kotlinlang.org/api/kotlinx.serialization/", + "packageListUrl": "https://kotlinlang.org/api/kotlinx.serialization/package-list" + } + ] +} +``` + + + +

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    + Dokka will do its best to automatically find package-list for the given URL, + and link declarations together. +

    +

    + If automatic resolution fails or if you want to use locally cached files instead, + consider providing packageListUrl. +

    +
    + +

    + Specifies the exact location of a package-list instead of relying on Dokka + automatically resolving it. Can also be a locally cached file to avoid network calls. +

    +
    +
    + +### Complete configuration + +Below you can see all possible configuration options applied at once. ```json { @@ -202,7 +771,7 @@ TODO add a link to Dokka's api reference, to DokkaConfiguration class { "displayName": "jvm", "sourceSetID": { - "scopeId": "html", + "scopeId": "moduleName", "sourceSetName": "main" }, "dependentSourceSets": [ @@ -282,7 +851,6 @@ TODO add a link to Dokka's api reference, to DokkaConfiguration class ], "includes": [ "module.md" - ], - "finalizeCoroutines": true + ] } ``` diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md index 08729be8a8..78b2b75943 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/gradle.md @@ -2,10 +2,13 @@ To generate documentation for a Gradle-based project, you can use [Dokka Gradle plugin](#applying-the-plugin). -It comes with basic autoconfiguration (including multimodule and multiplatform projects), has convenient +It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient [Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of [configuration options](#configuration) to customize output. +You can play around with Dokka and see how it can be configured for various projects by visiting +[Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). + ## Applying the plugin The recommended way of applying the plugin is via @@ -32,31 +35,57 @@ plugins { -> Under the hood, Dokka uses [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform autoconfiguration +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well. +You can use `allprojects {}` and `subprojects {}` Gradle configurations to achieve that: + + + + +```kotlin +subprojects { + apply(plugin = "org.jetbrains.dokka") +} +``` + + + + +```groovy +subprojects { + apply plugin: 'org.jetbrains.dokka' +} +``` + + + + +> Under the hood, Dokka uses [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform +> autoconfiguration > of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for which documentation -> should be generated, so make sure Kotlin Gradle Plugin is applied as well, or configure source sets manually. +> should be generated, so make sure Kotlin Gradle Plugin is applied as well, or +> [configure source sets](#source-set-configuration) manually. > -{type="note"} +{type="note"} -> If you are using Dokka in a -> [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), +> If you are using Dokka in a +> [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), > you will have to add [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) as a dependency in order for > it to work properly: > > > -> +> > ```kotlin > implementation(kotlin("gradle-plugin", "%kotlinVersion%")) > ``` -> +> > > -> +> > ```groovy > implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:%kotlinVersion%' > ``` -> +> > > > @@ -69,7 +98,8 @@ plugins. ## Generating documentation Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) formats built in, -and adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. +and adds a number of tasks for generating documentation, both for [single](#single-project-builds) +and [multi-project](#multi-project-builds) builds. ### Single project builds @@ -94,31 +124,8 @@ Output location, among other things, can be [configured](#configuration) separat ### Multi-project builds -For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), you need -to apply the Dokka plugin in subprojects that you want to generate documentation for as well as in their parent project. - -You can use `allprojects {}` and `subprojects {}` Gradle configurations to achieve that: - - - - -```kotlin -subprojects { - apply(plugin = "org.jetbrains.dokka") -} -``` - - - - -```groovy -subprojects { - apply plugin: 'org.jetbrains.dokka' -} -``` - - - +For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), make sure +you apply the Dokka plugin in subprojects that you want to generate documentation for, as well as in their parent project. #### MultiModule tasks @@ -172,28 +179,29 @@ for more details. #### Partial tasks Each subproject will have _partial_ tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, -and `dokkaJekyllPartial`. +and `dokkaJekyllPartial`. -These tasks are not intended to be used independently and exist only to be called by the parent's MultiModule task. +These tasks are not intended to be used independently and exist only to be called by the parent's +[MultiModule](#multimodule-tasks) task. Output generated by partial tasks contains non-displayable formatting along with unresolved templates and references. -> If you want to generate documentation for a single subproject only, use +> If you want to generate documentation for a single subproject only, use > [single project tasks](#single-project-builds). For instance, `:subproject:dokkaHtml`. #### Collector tasks -Similar to MultiModule tasks, _Collector_ tasks will be created for each parent project: `dokkaHtmlCollector`, +Similar to MultiModule tasks, _Collector_ tasks will be created for each parent project: `dokkaHtmlCollector`, `dokkaGfmCollector`, `dokkaJavadocCollector` and `dokkaJekyllCollector`. A Collector task executes corresponding [single project task](#single-project-builds) for each subproject (for example, -`dokkaHtml`), and merges all outputs into a single virtual project. +`dokkaHtml`), and merges all outputs into a single virtual project. Resulting documentation will look as if you have a single project build that contains all declarations from the subprojects. > Use `dokkaJavadocCollector` task if you need to create Javadoc documentation for your multi-project build. -> +> {type="tip"} #### Collector results @@ -219,8 +227,9 @@ for more details. ## Building javadoc.jar -In order to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API reference -documentation. +In order to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API +reference +documentation. Dokka's Gradle plugin does not provide any way to do this out of the box, but it can be achieved with custom Gradle tasks, one for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: @@ -262,16 +271,16 @@ tasks.register('dokkaJavadocJar', Jar.class) { -> If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to +> If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to > host of your library's API documentation for free and without any setup - it will take documentation pages straight -> from the artifact. It works with both HTML and Javadoc formats as demonstrated by +> from the artifact. It works with both HTML and Javadoc formats as demonstrated by > [this example](https://javadoc.io/doc/com.trib3/server/latest/index.html). -> +> {type="tip"} ## Configuration -You can configure tasks/formats individually +You can configure tasks/formats individually: @@ -292,16 +301,6 @@ tasks.dokkaHtmlPartial { } ``` -If you applied Dokka with the [buildscript block](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application): - -```kotlin -import org.jetbrains.dokka.gradle.DokkaTask - -tasks.named("dokkaHtml") { - outputDirectory.set(buildDir.resolve("documentation/html")) -} -``` - @@ -323,8 +322,8 @@ dokkaHtmlPartial { -Alternatively, you can configure all tasks/formats at once, including [MultiModule](#multi-project-builds), -[Partial](#partial-tasks) and [Collector](#collector-tasks) tasks as well. This is often the simplest solution. +Alternatively, you can configure all tasks/formats at once, including [MultiModule](#multi-project-builds), +[Partial](#partial-tasks) and [Collector](#collector-tasks) tasks: @@ -334,7 +333,8 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial import org.jetbrains.dokka.DokkaConfiguration.Visibility -// configure all dokka tasks, including multimodule, partial and collector +// configure all dokka tasks, including multimodule, +// partial and collector ones tasks.withType().configureEach { dokkaSourceSets.configureEach { documentedVisibilities.set( @@ -367,7 +367,8 @@ tasks.withType(DokkaTaskPartial::class).configureEach { import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial -// configure all dokka tasks, including multimodule, partial and collector +// configure all dokka tasks, including multimodule, +// partial and collector ones tasks.withType(DokkaTask.class) { dokkaSourceSets.configureEach { documentedVisibilities.set([ @@ -394,9 +395,667 @@ tasks.withType(DokkaTaskPartial.class) { -### Full configuration +## Configuration options + +Dokka has many configuration options to tailor your and your reader's experience. + +Below you will find examples and descriptions for each configuration section. You can also find an example with +[all configuration options](#complete-configuration) applied at once at the very bottom. + +### General configuration + +General configuration of any Dokka task, regardless of source set and package: + + + + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType().configureEach { + moduleName.set(project.name) + moduleVersion.set(project.version.toString()) + outputDirectory.set(buildDir.resolve("dokka/$name")) + failOnWarning.set(false) + suppressObviousFunctions.set(true) + suppressInheritedMembers.set(false) + offlineMode.set(false) + + // .. + // source set configuration section + // .. +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType(DokkaTask.class) { + moduleName.set(project.name) + moduleVersion.set(project.version.toString()) + outputDirectory.set(file("build/dokka/$name")) + failOnWarning.set(false) + suppressObviousFunctions.set(true) + suppressInheritedMembers.set(false) + offlineMode.set(false) + + // .. + // source set configuration section + // .. +} +``` + + + + + + +

    Display name used to refer to the module. Used for ToC, navigation, logging, etc.

    +

    If set for a single-project build or a MultiModule task, will be used as project name.

    +

    Default is Gradle project name.

    +
    + +

    + Module version. If set for a single-project build or a MultiModule task, will be used as project version + by the versioning plugin. +

    +

    Default is Gradle project version.

    +
    + +

    Directory to which documentation will be generated, regardless of format. Can be set on per-task basis.

    +

    + Default is project/buildDir/format, where format is the task name with + removed "dokka" prefix. For task dokkaHtmlMultiModule it will be + project/buildDir/htmlMultiModule +

    +
    + +

    + Whether to fail documentation generation if Dokka has emitted a warning or an error. + Will wait until all errors and warnings have been emitted first. +

    +

    This setting works well with reportUndocumented

    +

    Default is false.

    +
    + +

    Whether to suppress obvious functions.

    +

    + A function is considered to be obvious if it is: + +

  • + Inherited from kotlin.Any, Kotlin.Enum, java.lang.Object or + java.lang.Enum, such as equals, hashCode, toString. +
  • +
  • + Synthetic (generated by the compiler) and does not have any documentation, such as + dataClass.componentN or dataClass.copy. +
  • + +

    +

    Default is true.

    +
    + +

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    +

    + Note: this can suppress functions such as equals / hashCode / toString, + but cannot suppress synthetic functions such as dataClass.componentN and + dataClass.copy. Use suppressObviousFunctions + for that. +

    +

    Default is false.

    +
    + +

    Whether to resolve remote files/links over network.

    +

    + This includes package-lists used for generating external documentation links: + for instance, to make classes from standard library clickable. +

    +

    + Setting this to true can significantly speed up build times in certain cases, + but can also worsen documentation quality and user experience, for instance by + not resolving some dependency's class/member links. +

    +

    + Note: you can cache fetched files locally and provide them to + Dokka as local paths. See externalDocumentationLinks section. +

    +

    Default is false.

    +
    +
    + +### Source set configuration + +Configuration of Kotlin [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). + + + + +```kotlin +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.Platform +import java.net.URL + +tasks.withType().configureEach { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + suppress.set(false) + displayName.set(name) + documentedVisibilities.set(setOf(Visibility.PUBLIC)) + reportUndocumented.set(false) + skipEmptyPackages.set(true) + skipDeprecated.set(false) + suppressGeneratedFiles.set(true) + jdkVersion.set(8) + languageVersion.set("1.7") + apiVersion.set("1.7") + noStdlibLink.set(false) + noJdkLink.set(false) + noAndroidSdkLink.set(false) + includes.from(project.files(), "packages.md", "extra.md") + platform.set(Platform.DEFAULT) + sourceRoots.from(file("src")) + classpath.from(project.files(), file("libs/dependency.jar")) + samples.from(project.files(), "samples/Basic.kt", "samples/Advanced.kt") + + sourceLink { + // Source link section + } + externalDocumentationLink { + // External documentation link section + } + perPackageOption { + // Package options section + } + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.dokka.Platform +import java.net.URL + +tasks.withType(DokkaTask.class) { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + suppress.set(false) + displayName.set(name) + documentedVisibilities.set([Visibility.PUBLIC]) + reportUndocumented.set(false) + skipEmptyPackages.set(true) + skipDeprecated.set(false) + suppressGeneratedFiles.set(true) + jdkVersion.set(8) + languageVersion.set("1.7") + apiVersion.set("1.7") + noStdlibLink.set(false) + noJdkLink.set(false) + noAndroidSdkLink.set(false) + includes.from(project.files(), "packages.md", "extra.md") + platform.set(Platform.DEFAULT) + sourceRoots.from(file("src")) + classpath.from(project.files(), file("libs/dependency.jar")) + samples.from(project.files(), "samples/Basic.kt", "samples/Advanced.kt") + + sourceLink { + // Source link section + } + externalDocumentationLink { + // External documentation link section + } + perPackageOption { + // Package options section + } + } +} +``` + + + + + + +

    Whether this source set should be skipped when generating documentation.

    +

    Default is false.

    +
    + +

    Display name used to refer to the source set.

    +

    + The name will be used both externally (for example, as source set name visible to documentation readers) and + internally (for example, for logging messages of reportUndocumented). +

    +

    By default, the value is deduced from information provided by the Kotlin Gradle plugin.

    +
    + +

    Set of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations, + as well as if you want to exclude public declarations and only document internal API. +

    +

    Can be configured on per-package basis.

    +

    Default is DokkaConfiguration.Visibility.PUBLIC.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning. Can be overridden for a specific package.

    +

    Default is false.

    +
    + +

    + Whether to skip packages that contain no visible declarations after + various filters have been applied. +

    +

    + For instance, if skipDeprecated is set to true and your package contains only + deprecated declarations, it will be considered to be empty. +

    +

    Default is true.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be overridden on package level.

    +

    Default is false.

    +
    + +

    Whether to document/analyze generated files.

    +

    + Generated files are expected to be present under {project}/{buildDir}/generated directory. + If set to true, it effectively adds all files from that directory to + suppressedFiles option, so you can configure it manually. +

    +

    Default is true.

    +
    + +

    JDK version to use when generating external documentation links for Java types.

    +

    + For instance, if you use java.util.UUID from JDK in some public declaration signature, + and this property is set to 8, Dokka will generate an external documentation link + to JDK 8 Javadocs for it. +

    +

    Default is JDK 8.

    +
    + +

    + Kotlin language version + used for setting up analysis and @sample + environment. +

    +

    By default, the latest language version available to Dokka's embedded compiler will be used.

    +
    + +

    + Kotlin API version + used for setting up analysis and @sample + environment. +

    +

    By default, it will be deduced from languageVersion.

    +
    + +

    + Whether to generate external documentation links that lead to API reference + documentation for Kotlin's standard library when declarations from it are used. +

    +

    Default is false, meaning links will be generated.

    +
    + +

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    +

    The version of JDK Javadocs is determined by jdkVersion property.

    +

    Default is false, meaning links will be generated.

    +
    + +

    + Whether to generate external documentation links for Android SDK API reference + when declarations from it are used. +

    +

    Only relevant in Android projects, ignored otherwise.

    +

    Default is false, meaning links will be generated.

    +
    + +

    + List of Markdown files that contain + module and package documentation. +

    +

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +

    + See Dokka gradle example + for an example of how to use it and what it will look like. +

    +
    + +

    + Platform to be used for setting up code analysis and + @sample environment. +

    +

    The default value is deduced from information provided by the Kotlin Gradle plugin.

    +
    + +

    + Source code roots to be analyzed and documented. + Accepts directories and individual .kt / .java files. +

    +

    By default, source roots are deduced from information provided by the Kotlin Gradle plugin.

    +
    + +

    Classpath for analysis and interactive samples.

    +

    + Useful if some types that come from dependencies are not resolved/picked up automatically. + Property accepts both .jar and .klib files. +

    +

    By default, classpath is deduced from information provided by the Kotlin Gradle plugin.

    +
    + +

    + List of directories or files that contain sample functions which are referenced via + @sample KDoc tag. +

    +
    +
    + +### Source link configuration + +Configuration block that allows adding a `source` link to each signature +which leads to `remoteUrl` with a specific line number (configurable by setting `remoteLineSuffix`), +letting documentation readers find source code for each declaration. + +For an example, see documentation for +[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function from `kotlinx.coroutines`. + + + + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask +import java.net.URL + +tasks.withType().configureEach { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + sourceLink { + localDirectory.set(projectDir.resolve("src")) + remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteLineSuffix.set("#L") + } + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask +import java.net.URL + +tasks.withType(DokkaTask.class) { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + sourceLink { + localDirectory.set(file("src")) + remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteLineSuffix.set("#L") + } + } +} +``` + + + + + + +

    + Path to the local source directory. The path must be relative to the root of + current project. +

    +
    + +

    + URL of source code hosting service that can be accessed by documentation readers, + like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + source code links of declarations. +

    +
    + +

    + Suffix used to append source code line number to the URL. This will help readers navigate + not only to the file, but to the specific line number of the declaration. +

    +

    + The number itself will be appended to the specified suffix. For instance, + if this property is set to #L and the line number is 10, resulting URL suffix + will be #L10. +

    +

    + Suffixes used by popular services: + +

  • GitHub: #L
  • +
  • GitLab: #L
  • +
  • Bitbucket: #lines-
  • + +

    +

    Default is #L.

    +
    +
    + +### Package options + +Configuration block that allows setting some options for specific packages matched by `matchingRegex`. + + + + +```kotlin +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType().configureEach { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + perPackageOption { + matchingRegex.set(".*api.*") + suppress.set(false) + skipDeprecated.set(false) + reportUndocumented.set(false) + documentedVisibilities.set(setOf(Visibility.PUBLIC)) + } + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.DokkaConfiguration.Visibility +import org.jetbrains.dokka.gradle.DokkaTask + +tasks.withType(DokkaTask.class) { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + perPackageOption { + matchingRegex.set(".*api.*") + suppress.set(false) + skipDeprecated.set(false) + reportUndocumented.set(false) + documentedVisibilities.set([Visibility.PUBLIC]) + } + } +} +``` + + + + + + +

    Regular expression that is used to match the package.

    +

    Default is any string: .*.

    +
    + +

    Whether this package should be skipped when generating documentation.

    +

    Default is false.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be configured on source set level.

    +

    Default is false.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations from + this package and without KDocs, after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning.

    +

    Can be configured on source set level.

    +

    Default is false.

    +
    + +

    Set of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations within a + specific package, as well as if you want to exclude public declarations and only document internal API. +

    +

    Can be configured on source set level.

    +

    Default is DokkaConfiguration.Visibility.PUBLIC.

    +
    +
    + +### External documentation links configuration + +Configuration block that allows creating links leading to externally hosted documentation of your dependencies. + +For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your +documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is +[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external +documentation links for it, allowing Dokka to generate links for used types, making them clickable +and appear resolved. + + + + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTask +import java.net.URL + +tasks.withType().configureEach { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + externalDocumentationLink { + url.set(URL("https://kotlinlang.org/api/kotlinx.serialization/")) + packageListUrl.set( + rootProject.projectDir.resolve("serialization.package.list").toURL() + ) + } + } +} +``` + + + + +```groovy +import org.jetbrains.dokka.gradle.DokkaTask +import java.net.URL + +tasks.withType(DokkaTask.class) { + // .. + // general configuration section + // .. + + dokkaSourceSets.configureEach { + // .. + // source set configuration section + // .. + + externalDocumentationLink { + url.set(new URL("https://kotlinlang.org/api/kotlinx.serialization/")) + packageListUrl.set( + file("serialization.package.list").toURL() + ) + } + } +} +``` + + + -TODO add descriptions for each setting as a separate entry in a table + + +

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    + Dokka will do its best to automatically find package-list for the given URL, + and link declarations together. +

    +

    + If automatic resolution fails or if you want to use locally cached files instead, + consider providing packageListUrl. +

    +
    + +

    + Specifies the exact location of a package-list instead of relying on Dokka + automatically resolving it. Can also be a locally cached file to avoid network calls. +

    +
    +
    + +### Complete configuration + +Below you can see all possible configuration options applied at once. diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index c578ebb310..a571090c19 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -7,6 +7,9 @@ To generate documentation for Maven-based projects, you can use [Dokka Maven plu > {type="note"} +You can play around with Dokka and see how it can be configured for a Maven project by visiting +[Maven example](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/maven) project. + ## Applying the plugin To apply the plugin, you need to add it to the plugins section of your POM: @@ -81,7 +84,7 @@ You can learn more about Dokka plugins in [a separate topic](plugins_introductio ## Building javadoc.jar -Unlike [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin comes with ready-to-use `dokka:javadocJar` goal. +Unlike the [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin comes with ready-to-use `dokka:javadocJar` goal. By default, it will generate documentation in [Javadoc](javadoc.md) format under `target` folder. If you are not satisfied with the built-in goal or want to customize the output (for instance, you want to generate @@ -115,7 +118,7 @@ Maven jar plugin with the following configuration: ``` -The documentation and the archive for it can then be generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: +The documentation and the `.jar` archive for it can then be generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: ```Bash mvn dokka:dokka jar:jar@dokka-jar @@ -125,8 +128,7 @@ mvn dokka:dokka jar:jar@dokka-jar Maven's plugin configuration block can be used to configure Dokka. -Below you will find basic configuration that only changes output location of documentation. See -[all configuration elements](#all-configuration-elements) section to find out what else is possible. +Example of basic configuration that only changes output location of documentation: ```xml @@ -139,15 +141,20 @@ Below you will find basic configuration that only changes output location of doc ``` -### All configuration elements +## Configuration options + +Dokka has many configuration options to tailor your experience. -TODO add descriptions for each setting as a separate entry in a table +Below you will find examples and descriptions for each configuration section. You can also find an example with +[all configuration options](#complete-configuration) applied at once at the very bottom. + +### General configuration ```xml org.jetbrains.dokka dokka-maven-plugin - ... + false ${project.artifactId} @@ -156,12 +163,400 @@ TODO add descriptions for each setting as a separate entry in a table true false false + + ${project.basedir}/src/main/kotlin + + + PUBLIC + PROTECTED + + false + false + true + + /path/to/dir + /path/to/file + + 8 + 1.7 + 1.7 + false + false + + packages.md + extra.md + + ${project.compileClasspathElements} + + ${project.basedir}/samples + + + + + + + + + + + + +``` + + + +

    Whether to skip documentation generation.

    +

    Default is false.

    +
    + +

    Display name used to refer to the project/module. Used for ToC, navigation, logging, etc.

    +

    Default is {project.artifactId}.

    +
    + +

    Directory to which documentation will be generated.

    +

    Default is {project.basedir}/target/dokka.

    +
    + +

    + Whether to fail documentation generation if Dokka has emitted a warning or an error. Will wait until + all errors and warnings have been emitted first. +

    +

    This setting works well with reportUndocumented.

    +

    Default is false.

    +
    + +

    Whether to suppress obvious functions.

    +

    + A function is considered to be obvious if it is: + +

  • + Inherited from kotlin.Any, Kotlin.Enum, java.lang.Object or + java.lang.Enum, such as equals, hashCode, toString`. +
  • +
  • + Synthetic (generated by the compiler) and does not have any documentation, such as + dataClass.componentN or dataClass.copy. +
  • + +

    +

    Default is true

    +
    + +

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    +

    + Note: this can suppress functions such as equals/hashCode/toString, + but cannot suppress synthetic functions such as dataClass.componentN and + dataClass.copy. Use suppressObviousFunctions for that. +

    +

    Default is false.

    +
    + +

    Whether to resolve remote files/links over network.

    +

    + This includes package-lists used for generating external documentation links: + for instance, to make classes from standard library clickable. +

    +

    + Setting this to true can significantly speed up build times in certain cases, + but can also worsen documentation quality and user experience, for instance by + not resolving some dependency's class/member links. +

    +

    + When using offline mode, you can cache fetched files locally and provide them to + Dokka as local paths, see externalDocumentationLinks section. +

    +

    Default is false.

    +
    + +

    + Source code roots to be analyzed and documented. + Accepts directories and individual .kt / .java files. +

    +

    Default is {project.compileSourceRoots}.

    +
    + +

    Set of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations, + as well as if you want to exclude public declarations and only document internal API. +

    +

    Can be configured on per-package basis.

    +

    Default is PUBLIC.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning.

    +

    Can be overridden on package level.

    +

    Default is false.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be overridden on package level.

    +

    Default is false.

    +
    + +

    Whether to skip packages that contain no visible declarations after various filters have been applied.

    +

    + For instance, if skipDeprecated is set to true and your package contains only + deprecated declarations, it will be considered to be empty.

    +

    Default is true.

    +
    + +

    + Directories or individual files that should be suppressed, meaning declarations from them + will be not documented. +

    +
    + +

    JDK version to use when generating external documentation links for Java types.

    +

    + For instance, if you use java.util.UUID from JDK in some public declaration signature, + and this property is set to 8, Dokka will generate an external documentation link + to JDK 8 Javadocs for it. +

    +

    Default is JDK 8.

    +
    + +

    + Kotlin language version + used for setting up analysis and @sample + environment. +

    +

    By default, the latest language version available to Dokka's embedded compiler will be used.

    +
    + +

    + Kotlin API version + used for setting up analysis and @sample + environment. +

    +

    By default, it will be deduced from languageVersion.

    +
    + +

    + Whether to generate external documentation links that lead to API reference + documentation for Kotlin's standard library when declarations from it are used. +

    +

    Default is false, meaning links will be generated.

    +
    + +

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    +

    The version of JDK Javadocs is determined by jdkVersion property.

    +

    Default is false, meaning links will be generated.

    +
    + +

    + List of Markdown files that contain + module and package documentation +

    +

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +
    + +

    Classpath for analysis and interactive samples.

    +

    + Useful if some types that come from dependencies are not resolved/picked up automatically. + Property accepts both .jar and .klib files. +

    +

    Default is {project.compileClasspathElements}.

    +
    + +

    + List of directories or files that contain sample functions which are referenced via + @sample KDoc tag. +

    +
    +
    + +### Source link configuration + +Configuration block that allows adding a `source` link to each signature which leads to `path` with a specific line +number (configurable by setting `lineSuffix`), letting documentation readers find source code for each +declaration. + +For an example, see documentation for +[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function from `kotlinx.coroutines`. - JVM +```xml + + org.jetbrains.dokka + dokka-maven-plugin + + + + + ${project.basedir}/src/main/kotlin + https://github.com/kotlin/dokka/tree/master/src/main/kotlin + #L + + + + +``` + + + +

    + Path to the local source directory. The path must be relative to the root of + current module. +

    +
    + +

    + URL of source code hosting service that can be accessed by documentation readers, like GitHub, GitLab, + Bitbucket, etc. This URL will be used to generate source code links of declarations. +

    +
    + +

    + Suffix used to append source code line number to the URL. This will help readers navigate not only + to the file, but to the specific line number of the declaration. +

    +

    + The number itself will be appended to the specified suffix. For instance, if this property is set + to #L and the line number is 10, resulting URL suffix will be #L10. +

    +

    + Suffixes used by popular services: + +

  • GitHub: #L
  • +
  • GitLab: #L
  • +
  • Bitbucket: #lines-
  • + +

    +
    +
    + +#### External documentation links configuration + +Configuration block that allows creating links leading to externally hosted documentation of your dependencies. + +For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your +documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is +[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external +documentation links for it, allowing Dokka to generate links for used types, making them clickable +and appear resolved. + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + + + + + https://kotlinlang.org/api/kotlinx.serialization/ + file:/${project.basedir}/serialization.package.list + + + + +``` + + + +

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    + Dokka will do its best to automatically find package-list for the given URL, + and link declarations together. +

    +

    + It automatic resolution fails or if you want to use locally cached files instead, + consider providing packageListUrl. +

    +
    + +

    + Specifies the exact location of a package-list instead of relying on Dokka + automatically resolving it. Can also be a locally cached file to avoid network calls. +

    +
    +
    + +### Package options + +Configuration block that allows setting some options for specific packages matched by `matchingRegex`. + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + + + + + .*api.* + false + false + false + + PUBLIC + PRIVATE + PROTECTED + INTERNAL + PACKAGE + + + + + +``` + + + +

    Regular expression that is used to match the package.

    +

    Default is any string: .*.

    +
    + +

    Whether this package should be skipped when generating documentation.

    +

    Default is false.

    +
    + +

    List of visibility modifiers that should be documented.

    +

    + This can be used if you want to document protected/internal/private declarations within a + specific package, as well as if you want to exclude public declarations and only document internal API. +

    +

    Default is PUBLIC.

    +
    + +

    Whether to document declarations annotated with @Deprecated.

    +

    Can be set on project/module level.

    +

    Default is false.

    +
    + +

    + Whether to emit warnings about visible undocumented declarations, that is declarations from + this package and without KDocs, after they have been filtered by documentedVisibilities. +

    +

    This setting works well with failOnWarning.

    +

    Default is false.

    +
    +
    + +### Complete configuration + +Below you can see all possible configuration options applied at once. + +```xml + + org.jetbrains.dokka + dokka-maven-plugin + + + false + ${project.artifactId} + ${project.basedir}/target/documentation + false + true + false + false ${project.basedir}/src/main/kotlin - JVM PUBLIC PRIVATE @@ -185,13 +580,6 @@ TODO add descriptions for each setting as a separate entry in a table packages.md extra.md - JVM - - - src/main/kotlin - JVM - - ${project.compileClasspathElements} ${project.basedir}/samples diff --git a/runners/cli/api/cli.api b/runners/cli/api/cli.api index cdd051ccbe..74769272a2 100644 --- a/runners/cli/api/cli.api +++ b/runners/cli/api/cli.api @@ -62,7 +62,8 @@ public final class org/jetbrains/dokka/ArgTypeVisibility : kotlinx/cli/ArgType { public final class org/jetbrains/dokka/GlobalArguments : org/jetbrains/dokka/DokkaConfiguration { public fun ([Ljava/lang/String;)V - public fun getCacheRoot ()Ljava/io/File; + public synthetic fun getCacheRoot ()Ljava/io/File; + public fun getCacheRoot ()Ljava/lang/Void; public fun getDelayTemplateSubstitution ()Z public fun getFailOnWarning ()Z public fun getFinalizeCoroutines ()Z @@ -88,10 +89,13 @@ public final class org/jetbrains/dokka/GlobalArguments : org/jetbrains/dokka/Dok public fun getSuppressObviousFunctions ()Z } -public final class org/jetbrains/dokka/MainKt { +public final class org/jetbrains/dokka/LinkMapperKt { public static final fun defaultLinks (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/List; + public static final fun parseLinks (Ljava/util/List;)Ljava/util/List; +} + +public final class org/jetbrains/dokka/MainKt { public static final fun initializeConfiguration (Lorg/jetbrains/dokka/GlobalArguments;)Lorg/jetbrains/dokka/DokkaConfiguration; public static final fun main ([Ljava/lang/String;)V - public static final fun parseLinks (Ljava/util/List;)Ljava/util/List; } diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt new file mode 100644 index 0000000000..f52f72fd0c --- /dev/null +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt @@ -0,0 +1,91 @@ +package org.jetbrains.dokka + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.CLIEntity +import org.jetbrains.dokka.utilities.LoggingLevel +import java.io.File +import java.nio.file.Paths + + +object ArgTypeFile : ArgType(true) { + override fun convert(value: kotlin.String, name: kotlin.String): File = Paths.get(value).toRealPath().toFile() + override val description: kotlin.String + get() = "{ String that represents a directory / file path }" +} + +object ArgTypePlatform : ArgType(true) { + override fun convert(value: kotlin.String, name: kotlin.String): Platform = Platform.fromString(value) + override val description: kotlin.String + get() = "{ String that represents a Kotlin platform. Possible values: jvm/js/native/common/android }" +} + +object ArgTypeVisibility : ArgType(true) { + override fun convert(value: kotlin.String, name: kotlin.String) = DokkaConfiguration.Visibility.fromString(value) + override val description: kotlin.String + get() = "{ String that represents a visibility modifier. Possible values: ${getPossibleVisibilityValues()}" + + private fun getPossibleVisibilityValues(): kotlin.String = + DokkaConfiguration.Visibility.values().joinToString(separator = ", ") +} + +object ArgTypePlugin : ArgType(true) { + override fun convert( + value: kotlin.String, + name: kotlin.String + ): DokkaConfiguration.PluginConfiguration { + return value.split("=").let { + PluginConfigurationImpl( + fqPluginName = it[0], + serializationFormat = DokkaConfiguration.SerializationFormat.JSON, + values = it[1] + ) + } + } + + override val description: kotlin.String + get() = "{ String that represents plugin configuration. " + + "Format is {fullyQualifiedPluginName}={jsonConfiguration}. " + + "Quotation marks (`\"`) inside json must be escaped. }" +} + +object ArgTypeSourceLinkDefinition : ArgType(true) { + override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.SourceLinkDefinition { + return if (value.isNotEmpty() && value.contains("=")) + SourceLinkDefinitionImpl.parseSourceLinkDefinition(value) + else { + throw IllegalArgumentException( + "Warning: Invalid -srcLink syntax. " + + "Expected: =[#lineSuffix]. No source links will be generated." + ) + } + } + + override val description: kotlin.String + get() = "{ String that represent source links. Format: {srcPath}={remotePath#lineSuffix} }" +} + +data class ArgTypeArgument(val moduleName: CLIEntity) : + ArgType(true) { + override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.DokkaSourceSet = + (if (moduleName.valueOrigin != ArgParser.ValueOrigin.UNSET && moduleName.valueOrigin != ArgParser.ValueOrigin.UNDEFINED) { + moduleName.value + } else { + DokkaDefaults.moduleName + }).let { moduleNameOrDefault -> + parseSourceSet(moduleNameOrDefault, value.split(" ").filter { it.isNotBlank() }.toTypedArray()) + } + + override val description: kotlin.String + get() = "" +} + +// Workaround for printing nested parsers help +data class ArgTypeHelpSourceSet(val moduleName: CLIEntity) : ArgType(false) { + override fun convert(value: kotlin.String, name: kotlin.String): Any = Any().also { + parseSourceSet(moduleName.value, arrayOf("-h")) + } + + override val description: kotlin.String + get() = "" +} diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt new file mode 100644 index 0000000000..2bda8d79eb --- /dev/null +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt @@ -0,0 +1,164 @@ +package org.jetbrains.dokka + +import kotlinx.cli.* +import org.jetbrains.dokka.utilities.DokkaConsoleLogger +import org.jetbrains.dokka.utilities.DokkaLogger +import org.jetbrains.dokka.utilities.LoggingLevel +import org.jetbrains.dokka.utilities.cast +import java.io.File + +class GlobalArguments(args: Array) : DokkaConfiguration { + + val parser = ArgParser("dokka-cli", prefixStyle = ArgParser.OptionPrefixStyle.JVM) + + val json: String? by parser.argument(ArgType.String, description = "JSON configuration file path").optional() + + private val _moduleName = parser.option( + ArgType.String, + description = "Name of the project/module", + fullName = "moduleName" + ).default(DokkaDefaults.moduleName) + + override val moduleName: String by _moduleName + + override val moduleVersion by parser.option( + ArgType.String, + description = "Documented version", + fullName = "moduleVersion" + ) + + override val outputDir by parser.option(ArgTypeFile, description = "Output directory path, ./dokka by default") + .default(DokkaDefaults.outputDir) + + override val cacheRoot = null + + override val sourceSets by parser.option( + ArgTypeArgument(_moduleName), + description = "Configuration for a Dokka source set. Contains nested configuration.", + fullName = "sourceSet" + ).multiple() + + override val pluginsConfiguration by parser.option( + ArgTypePlugin, + description = "Configuration for Dokka plugins. Accepts multiple values separated by `^^`." + ).delimiter("^^") + + override val pluginsClasspath by parser.option( + ArgTypeFile, + fullName = "pluginsClasspath", + description = "List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons" + ).delimiter(";") + + override val offlineMode by parser.option( + ArgType.Boolean, + description = "Whether to resolve remote files/links over network" + ).default(DokkaDefaults.offlineMode) + + override val failOnWarning by parser.option( + ArgType.Boolean, + description = "Whether to fail documentation generation if Dokka has emitted a warning or an error" + ).default(DokkaDefaults.failOnWarning) + + override val delayTemplateSubstitution by parser.option( + ArgType.Boolean, + description = "Delay substitution of some elements. Used in incremental builds of multimodule projects" + ).default(DokkaDefaults.delayTemplateSubstitution) + + val noSuppressObviousFunctions: Boolean by parser.option( + ArgType.Boolean, + description = "Whether to suppress obvious functions such as inherited from `kotlin.Any` and `java.lang.Object`" + ).default(!DokkaDefaults.suppressObviousFunctions) + + override val suppressObviousFunctions: Boolean by lazy { !noSuppressObviousFunctions } + + private val _includes by parser.option( + ArgTypeFile, + fullName = "includes", + description = "Markdown files that contain module and package documentation. " + + "Accepts multiple values separated by semicolons" + ).delimiter(";") + + override val includes: Set by lazy { _includes.toSet() } + + override val suppressInheritedMembers: Boolean by parser.option( + ArgType.Boolean, + description = "Whether to suppress inherited members that aren't explicitly overridden in a given class" + ).default(DokkaDefaults.suppressInheritedMembers) + + override val finalizeCoroutines: Boolean = true + + val globalPackageOptions by parser.option( + ArgType.String, + description = "Global list of package configurations in format " + + "\"matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...\". " + + "Accepts multiple values separated by semicolons. " + ).delimiter(";") + + val globalLinks by parser.option( + ArgType.String, + description = "Global external documentation links in format {url}^{packageListUrl}. " + + "Accepts multiple values separated by `^^`" + ).delimiter("^^") + + val globalSrcLink by parser.option( + ArgType.String, + description = "Global mapping between a source directory and a Web service for browsing the code. " + + "Accepts multiple paths separated by semicolons" + ).delimiter(";") + + val helpSourceSet by parser.option( + ArgTypeHelpSourceSet(_moduleName), + description = "Prints help for nested -sourceSet configuration" + ) + + val loggingLevel by parser.option( + ArgType.Choice(toVariant = { + when (it.toUpperCase().trim()) { + "DEBUG", "" -> LoggingLevel.DEBUG + "PROGRESS" -> LoggingLevel.PROGRESS + "INFO" -> LoggingLevel.INFO + "WARN" -> LoggingLevel.WARN + "ERROR" -> LoggingLevel.ERROR + else -> { + println("""Failed to deserialize logging level, got $it expected one of + |"DEBUG", "PROGRESS", "INFO", "WARN", "ERROR", falling back to DEBUG""".trimMargin()) + LoggingLevel.DEBUG + } + } + }, toString = { it.toString() } + )).default(LoggingLevel.DEBUG) + + override val modules: List = emptyList() + + val logger: DokkaLogger by lazy { + DokkaConsoleLogger(loggingLevel) + } + + init { + parser.parse(args) + + sourceSets.forEach { + it.perPackageOptions.cast>() + .addAll(parsePerPackageOptions(globalPackageOptions)) + } + + sourceSets.forEach { + it.externalDocumentationLinks.cast>().addAll(parseLinks(globalLinks)) + } + + globalSrcLink.forEach { + if (it.isNotEmpty() && it.contains("=")) + sourceSets.all { sourceSet -> + sourceSet.sourceLinks.cast>() + .add(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it)) + } + else { + logger.warn("Invalid -srcLink syntax. Expected: =[#lineSuffix]. No source links will be generated.") + } + } + + sourceSets.forEach { + it.externalDocumentationLinks.cast>().addAll(defaultLinks(it)) + } + } +} diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt new file mode 100644 index 0000000000..191d5067f4 --- /dev/null +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt @@ -0,0 +1,37 @@ +package org.jetbrains.dokka + +import java.io.File +import java.net.MalformedURLException +import java.net.URL + +@OptIn(ExperimentalStdlibApi::class) // for buildList +fun defaultLinks(config: DokkaConfiguration.DokkaSourceSet): MutableList = + buildList { + if (!config.noJdkLink) { + add(DokkaConfiguration.ExternalDocumentationLink.jdk(config.jdkVersion)) + } + + if (!config.noStdlibLink) { + add(DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()) + } + }.toMutableList() + + +fun parseLinks(links: List): List { + val (parsedLinks, parsedOfflineLinks) = links + .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } } + .filter { it.isNotEmpty() } + .partition { it.size == 1 } + + return parsedLinks.map { (root) -> ExternalDocumentationLink(root) } + + parsedOfflineLinks.map { (root, packageList) -> + val rootUrl = URL(root) + val packageListUrl = + try { + URL(packageList) + } catch (ex: MalformedURLException) { + File(packageList).toURI().toURL() + } + ExternalDocumentationLink(rootUrl, packageListUrl) + } +} diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt new file mode 100644 index 0000000000..1b9a3c5698 --- /dev/null +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt @@ -0,0 +1,34 @@ +package org.jetbrains.dokka + +internal fun parsePerPackageOptions(args: List): List = args.map { it.split(",") }.map { + val matchingRegex = it.first() + + val options = it.subList(1, it.size) + + val deprecated = options.find { it.endsWith("skipDeprecated") }?.startsWith("+") + ?: DokkaDefaults.skipDeprecated + + val reportUndocumented = options.find { it.endsWith("reportUndocumented") }?.startsWith("+") + ?: DokkaDefaults.reportUndocumented + + val privateApi = options.find { it.endsWith("includeNonPublic") }?.startsWith("+") + ?: DokkaDefaults.includeNonPublic + + val suppress = options.find { it.endsWith("suppress") }?.startsWith("+") + ?: DokkaDefaults.suppress + + val documentedVisibilities = options + .filter { it.matches(Regex("\\+visibility:.+")) } // matches '+visibility:' with at least one symbol after the semicolon + .map { DokkaConfiguration.Visibility.fromString(it.split(":")[1]) } + .toSet() + .ifEmpty { DokkaDefaults.documentedVisibilities } + + PackageOptionsImpl( + matchingRegex, + includeNonPublic = privateApi, + documentedVisibilities = documentedVisibilities, + reportUndocumented = reportUndocumented, + skipDeprecated = !deprecated, + suppress = suppress + ) +} diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt new file mode 100644 index 0000000000..49e8f2ae05 --- /dev/null +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt @@ -0,0 +1,155 @@ +package org.jetbrains.dokka + +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.default +import kotlinx.cli.delimiter + +internal fun parseSourceSet(moduleName: String, args: Array): DokkaConfiguration.DokkaSourceSet { + + val parser = ArgParser("sourceSet", prefixStyle = ArgParser.OptionPrefixStyle.JVM) + + val sourceSetName by parser.option( + ArgType.String, + description = "Name of the source set" + ).default("main") + + val displayName by parser.option( + ArgType.String, + description = "Display name of the source set, used both internally and externally" + ).default(DokkaDefaults.sourceSetDisplayName) + + val classpath by parser.option( + ArgTypeFile, + description = "Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons" + ).delimiter(";") + + val sourceRoots by parser.option( + ArgTypeFile, + description = "Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons", + fullName = "src" + ).delimiter(";") + + val dependentSourceSets by parser.option( + ArgType.String, + description = "Names of dependent source sets in format \"moduleName/sourceSetName\". " + + "Accepts multiple paths separated by semicolons" + ).delimiter(";") + + val samples by parser.option( + ArgTypeFile, + description = "List of directories or files that contain sample functions. " + + "Accepts multiple paths separated by semicolons" + ).delimiter(";") + + val includes by parser.option( + ArgTypeFile, + description = "Markdown files that contain module and package documentation. " + + "Accepts multiple paths separated by semicolons" + ).delimiter(";") + + val includeNonPublic: Boolean by parser.option( + ArgType.Boolean, + description = "Deprecated, use documentedVisibilities") + .default(DokkaDefaults.includeNonPublic) + + val documentedVisibilities by parser.option( + ArgTypeVisibility, + description = "Visibilities to be documented. Accepts multiple values separated by semicolons" + ).delimiter(";") + + val reportUndocumented by parser.option(ArgType.Boolean, description = "Whether to report undocumented declarations") + .default(DokkaDefaults.reportUndocumented) + + val noSkipEmptyPackages by parser.option( + ArgType.Boolean, + description = "Whether to create pages for empty packages" + ).default(!DokkaDefaults.skipEmptyPackages) + + val skipEmptyPackages by lazy { !noSkipEmptyPackages } + + val skipDeprecated by parser.option(ArgType.Boolean, description = "Whether to skip deprecated declarations") + .default(DokkaDefaults.skipDeprecated) + + val jdkVersion by parser.option( + ArgType.Int, + description = "Version of JDK to use for linking to JDK Javadocs" + ).default(DokkaDefaults.jdkVersion) + + val languageVersion by parser.option( + ArgType.String, + description = "Language version used for setting up analysis and samples" + ) + + val apiVersion by parser.option( + ArgType.String, + description = "Kotlin API version used for setting up analysis and samples" + ) + + val noStdlibLink by parser.option(ArgType.Boolean, description = "Whether to generate links to Standard library") + .default(DokkaDefaults.noStdlibLink) + + val noJdkLink by parser.option(ArgType.Boolean, description = "Whether to generate links to JDK Javadocs") + .default(DokkaDefaults.noJdkLink) + + val suppressedFiles by parser.option( + ArgTypeFile, + description = "Paths to files to be suppressed. Accepts multiple paths separated by semicolons." + ).delimiter(";") + + val analysisPlatform: Platform by parser.option( + ArgTypePlatform, + description = "Platform used for setting up analysis" + ).default(DokkaDefaults.analysisPlatform) + + val perPackageOptions by parser.option( + ArgType.String, + description = "List of package source set configuration in format " + + "\"matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...\". " + + "Accepts multiple values separated by semicolons. " + ).delimiter(";") + + val externalDocumentationLinks by parser.option( + ArgType.String, + description = "External documentation links in format {url}^{packageListUrl}. " + + "Accepts multiple values separated by `^^`" + ).delimiter("^^") + + val sourceLinks by parser.option( + ArgTypeSourceLinkDefinition, + description = "Mapping between a source directory and a Web service for browsing the code. " + + "Accepts multiple paths separated by semicolons", + fullName = "srcLink" + ).delimiter(";") + + parser.parse(args) + + return object : DokkaConfiguration.DokkaSourceSet { + override val displayName = displayName + override val sourceSetID = DokkaSourceSetID(moduleName, sourceSetName) + override val classpath = classpath.toMutableList() + override val sourceRoots = sourceRoots.toMutableSet() + override val dependentSourceSets = dependentSourceSets + .map { dependentSourceSetName -> dependentSourceSetName.split('/').let { DokkaSourceSetID(it[0], it[1]) } } + .toMutableSet() + override val samples = samples.toMutableSet() + override val includes = includes.toMutableSet() + @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities") + override val includeNonPublic = includeNonPublic + override val reportUndocumented = reportUndocumented + override val skipEmptyPackages = skipEmptyPackages + override val skipDeprecated = skipDeprecated + override val jdkVersion = jdkVersion + override val sourceLinks = sourceLinks.toMutableSet() + override val analysisPlatform = analysisPlatform + override val perPackageOptions = parsePerPackageOptions(perPackageOptions).toMutableList() + override val externalDocumentationLinks = parseLinks(externalDocumentationLinks).toMutableSet() + override val languageVersion = languageVersion + override val apiVersion = apiVersion + override val noStdlibLink = noStdlibLink + override val noJdkLink = noJdkLink + override val suppressedFiles = suppressedFiles.toMutableSet() + override val documentedVisibilities: Set = documentedVisibilities.toSet() + .ifEmpty { DokkaDefaults.documentedVisibilities } + } +} diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt index 7fe782a9eb..99813f62de 100644 --- a/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt +++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt @@ -1,429 +1,28 @@ package org.jetbrains.dokka -import kotlinx.cli.* import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink import org.jetbrains.dokka.utilities.* -import java.io.* -import java.net.MalformedURLException -import java.net.URL import java.nio.file.Paths -class GlobalArguments(args: Array) : DokkaConfiguration { - - val parser = ArgParser("globalArguments", prefixStyle = ArgParser.OptionPrefixStyle.JVM) - - val json: String? by parser.argument(ArgType.String, description = "Json file name").optional() - - private val _moduleName = parser.option( - ArgType.String, - description = "Name of the documentation module", - fullName = "moduleName" - ).default(DokkaDefaults.moduleName) - - override val moduleName: String by _moduleName - - override val moduleVersion by parser.option( - ArgType.String, - description = "Documentation version", - fullName = "moduleVersion" - ) - - override val outputDir by parser.option(ArgTypeFile, description = "Output directory path") - .default(DokkaDefaults.outputDir) - - override val cacheRoot by parser.option( - ArgTypeFile, - description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled" - ) - - override val sourceSets by parser.option( - ArgTypeArgument(_moduleName), - description = "Single dokka source set", - fullName = "sourceSet" - ).multiple() - - override val pluginsConfiguration by parser.option( - ArgTypePlugin, - description = "Configuration for plugins in format fqPluginName=json^^fqPluginName=json..." - ).delimiter("^^") - - override val pluginsClasspath by parser.option( - ArgTypeFile, - fullName = "pluginsClasspath", - description = "List of jars with dokka plugins (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - override val offlineMode by parser.option( - ArgType.Boolean, - description = "Offline mode (do not download package lists from the Internet)" - ).default(DokkaDefaults.offlineMode) - - override val failOnWarning by parser.option( - ArgType.Boolean, - description = "Throw an exception if the generation exited with warnings" - ).default(DokkaDefaults.failOnWarning) - - override val delayTemplateSubstitution by parser.option( - ArgType.Boolean, - description = "Delay substitution of some elements (usefull for incremental builds of multimodule projects)" - ).default(DokkaDefaults.delayTemplateSubstitution) - - val noSuppressObviousFunctions: Boolean by parser.option( - ArgType.Boolean, - description = "Document generated or obvious functions like default `toString` or `equals`" - ).default(!DokkaDefaults.suppressObviousFunctions) - - override val suppressObviousFunctions: Boolean by lazy { !noSuppressObviousFunctions } - - private val _includes by parser.option( - ArgTypeFile, - fullName = "includes", - description = "Markdown files that would be displayed in multi-module page separated by the semicolon `;`)" - ).delimiter(";") - - override val includes: Set by lazy { _includes.toSet() } - - override val suppressInheritedMembers: Boolean by parser.option( - ArgType.Boolean, - description = "Suppress members inherited from other classes" - ).default(DokkaDefaults.suppressInheritedMembers) - - override val finalizeCoroutines: Boolean = true - - val globalPackageOptions by parser.option( - ArgType.String, - description = "List of package source sets in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" " - ).delimiter(";") - - val globalLinks by parser.option( - ArgType.String, - description = "External documentation links in format url^packageListUrl^^url2..." - ).delimiter("^^") - - val globalSrcLink by parser.option( - ArgType.String, - description = "Mapping between a source directory and a Web site for browsing the code (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val helpSourceSet by parser.option( - ArgTypeHelpSourceSet(_moduleName), - description = "Prints help for single -sourceSet" - ) - - val loggingLevel by parser.option( - ArgType.Choice(toVariant = { - when (it.toUpperCase().trim()) { - "DEBUG", "" -> LoggingLevel.DEBUG - "PROGRESS" -> LoggingLevel.PROGRESS - "INFO" -> LoggingLevel.INFO - "WARN" -> LoggingLevel.WARN - "ERROR" -> LoggingLevel.ERROR - else -> { - println("""Failed to deserialize logging level, got $it expected one of "DEBUG", "PROGRESS", "INFO", "WARN", "ERROR", falling back to DEBUG""") - LoggingLevel.DEBUG - } - } - }, toString = { it.toString() } - )).default(LoggingLevel.DEBUG) - - override val modules: List = emptyList() - - val logger: DokkaLogger by lazy { - DokkaConsoleLogger(loggingLevel) - } - - init { - parser.parse(args) - - sourceSets.forEach { - it.perPackageOptions.cast>() - .addAll(parsePerPackageOptions(globalPackageOptions)) - } - - sourceSets.forEach { - it.externalDocumentationLinks.cast>().addAll(parseLinks(globalLinks)) - } - - globalSrcLink.forEach { - if (it.isNotEmpty() && it.contains("=")) - sourceSets.all { sourceSet -> - sourceSet.sourceLinks.cast>() - .add(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it)) - } - else { - logger.warn("Invalid -srcLink syntax. Expected: =[#lineSuffix]. No source links will be generated.") - } - } - - sourceSets.forEach { - it.externalDocumentationLinks.cast>().addAll(defaultLinks(it)) - } - } -} - -private fun parseSourceSet(moduleName: String, args: Array): DokkaConfiguration.DokkaSourceSet { - - val parser = ArgParser("sourceSet", prefixStyle = ArgParser.OptionPrefixStyle.JVM) - - val sourceSetName by parser.option( - ArgType.String, - description = "Name of the source set" - ).default("main") - - val displayName by parser.option( - ArgType.String, - description = "Displayed name of the source set" - ).default(DokkaDefaults.sourceSetDisplayName) - - val classpath by parser.option( - ArgTypeFile, - description = "Classpath for symbol resolution (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val sourceRoots by parser.option( - ArgTypeFile, - description = "Source file or directory (allows many paths separated by the semicolon `;`)", - fullName = "src" - ).delimiter(";") - - val dependentSourceSets by parser.option( - ArgType.String, - description = "Names of dependent source sets in format \"moduleName/sourceSetName\" (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val samples by parser.option( - ArgTypeFile, - description = "Source root for samples (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val includes by parser.option( - ArgTypeFile, - description = "Markdown files to load (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val includeNonPublic: Boolean by parser.option(ArgType.Boolean, description = "Include non public") - .default(DokkaDefaults.includeNonPublic) - - val documentedVisibilities by parser.option( - ArgTypeVisibility, - description = "Visibilities to be documented (allows multiple values separated by the semicolon `;`)" - ).delimiter(";") - - val reportUndocumented by parser.option(ArgType.Boolean, description = "Report undocumented members") - .default(DokkaDefaults.reportUndocumented) - - val noSkipEmptyPackages by parser.option( - ArgType.Boolean, - description = "Create index pages for empty packages" - ).default(!DokkaDefaults.skipEmptyPackages) - - val skipEmptyPackages by lazy { !noSkipEmptyPackages } - - val skipDeprecated by parser.option(ArgType.Boolean, description = "Do not output deprecated members") - .default(DokkaDefaults.skipDeprecated) - - val jdkVersion by parser.option( - ArgType.Int, - description = "Version of JDK to use for linking to JDK JavaDoc" - ).default(DokkaDefaults.jdkVersion) - - val languageVersion by parser.option( - ArgType.String, - description = "Language Version to pass to Kotlin analysis" - ) - - val apiVersion by parser.option( - ArgType.String, - description = "Kotlin Api Version to pass to Kotlin analysis" - ) - - val noStdlibLink by parser.option(ArgType.Boolean, description = "Disable documentation link to stdlib") - .default(DokkaDefaults.noStdlibLink) - - val noJdkLink by parser.option(ArgType.Boolean, description = "Disable documentation link to JDK") - .default(DokkaDefaults.noJdkLink) - - val suppressedFiles by parser.option( - ArgTypeFile, - description = "Paths to files to be suppressed (allows many paths separated by the semicolon `;`)" - ).delimiter(";") - - val analysisPlatform: Platform by parser.option( - ArgTypePlatform, - description = "Platform for analysis" - ).default(DokkaDefaults.analysisPlatform) - - val perPackageOptions by parser.option( - ArgType.String, - description = "List of package source set configuration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" " - ).delimiter(";") - - val externalDocumentationLinks by parser.option( - ArgType.String, - description = "External documentation links in format url^packageListUrl^^url2..." - ).delimiter("^^") - - val sourceLinks by parser.option( - ArgTypeSourceLinkDefinition, - description = "Mapping between a source directory and a Web site for browsing the code (allows many paths separated by the semicolon `;`)", - fullName = "srcLink" - ).delimiter(";") - - parser.parse(args) - - return object : DokkaConfiguration.DokkaSourceSet { - override val displayName = displayName - override val sourceSetID = DokkaSourceSetID(moduleName, sourceSetName) - override val classpath = classpath.toMutableList() - override val sourceRoots = sourceRoots.toMutableSet() - override val dependentSourceSets = dependentSourceSets - .map { dependentSourceSetName -> dependentSourceSetName.split('/').let { DokkaSourceSetID(it[0], it[1]) } } - .toMutableSet() - override val samples = samples.toMutableSet() - override val includes = includes.toMutableSet() - @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities") - override val includeNonPublic = includeNonPublic - override val reportUndocumented = reportUndocumented - override val skipEmptyPackages = skipEmptyPackages - override val skipDeprecated = skipDeprecated - override val jdkVersion = jdkVersion - override val sourceLinks = sourceLinks.toMutableSet() - override val analysisPlatform = analysisPlatform - override val perPackageOptions = parsePerPackageOptions(perPackageOptions).toMutableList() - override val externalDocumentationLinks = parseLinks(externalDocumentationLinks).toMutableSet() - override val languageVersion = languageVersion - override val apiVersion = apiVersion - override val noStdlibLink = noStdlibLink - override val noJdkLink = noJdkLink - override val suppressedFiles = suppressedFiles.toMutableSet() - override val documentedVisibilities: Set = documentedVisibilities.toSet() - .ifEmpty { DokkaDefaults.documentedVisibilities } - } -} - -object ArgTypeFile : ArgType(true) { - override fun convert(value: kotlin.String, name: kotlin.String): File = Paths.get(value).toRealPath().toFile() - override val description: kotlin.String - get() = "{ String that points to file path }" -} - -object ArgTypePlatform : ArgType(true) { - override fun convert(value: kotlin.String, name: kotlin.String): Platform = Platform.fromString(value) - override val description: kotlin.String - get() = "{ String that represents platform }" -} - -object ArgTypeVisibility : ArgType(true) { - override fun convert(value: kotlin.String, name: kotlin.String) = DokkaConfiguration.Visibility.fromString(value) - override val description: kotlin.String - get() = "{ String that represents a visibility modifier. " + - "Possible values: ${DokkaConfiguration.Visibility.values().joinToString(separator = ", ")} }" -} - -object ArgTypePlugin : ArgType(true) { - override fun convert( - value: kotlin.String, - name: kotlin.String - ): DokkaConfiguration.PluginConfiguration { - return value.split("=").let { - PluginConfigurationImpl( - fqPluginName = it[0], - serializationFormat = DokkaConfiguration.SerializationFormat.JSON, - values = it[1] - ) - } - } - - override val description: kotlin.String - get() = "{ String fqName=json, remember to escape `\"` inside json }" -} - -object ArgTypeSourceLinkDefinition : ArgType(true) { - override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.SourceLinkDefinition = - if (value.isNotEmpty() && value.contains("=")) - SourceLinkDefinitionImpl.parseSourceLinkDefinition(value) - else { - throw IllegalArgumentException("Warning: Invalid -srcLink syntax. Expected: =[#lineSuffix]. No source links will be generated.") - } - - override val description: kotlin.String - get() = "{ String that represent source links }" -} - -data class ArgTypeArgument(val moduleName: CLIEntity) : - ArgType(true) { - override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.DokkaSourceSet = - (if (moduleName.valueOrigin != ArgParser.ValueOrigin.UNSET && moduleName.valueOrigin != ArgParser.ValueOrigin.UNDEFINED) { - moduleName.value - } else { - DokkaDefaults.moduleName - }).let { moduleNameOrDefault -> - parseSourceSet(moduleNameOrDefault, value.split(" ").filter { it.isNotBlank() }.toTypedArray()) - } - - override val description: kotlin.String - get() = "" -} - -// Workaround for printing nested parsers help -data class ArgTypeHelpSourceSet(val moduleName: CLIEntity) : ArgType(false) { - override fun convert(value: kotlin.String, name: kotlin.String): Any = Any().also { - parseSourceSet(moduleName.value, arrayOf("-h")) - } - - override val description: kotlin.String - get() = "" +fun main(args: Array) { + val globalArguments = GlobalArguments(args) + val configuration = initializeConfiguration(globalArguments) + DokkaGenerator(configuration, globalArguments.logger).generate() } -@OptIn(ExperimentalStdlibApi::class) -fun defaultLinks(config: DokkaConfiguration.DokkaSourceSet): MutableList = - buildList { - if (!config.noJdkLink) { - add(ExternalDocumentationLink.jdk(config.jdkVersion)) - } +fun initializeConfiguration(globalArguments: GlobalArguments): DokkaConfiguration { + return if (globalArguments.json != null) { + val jsonContent = Paths.get(checkNotNull(globalArguments.json)).toFile().readText() + val globals = GlobalDokkaConfiguration(jsonContent) + val dokkaConfigurationImpl = DokkaConfigurationImpl(jsonContent) - if (!config.noStdlibLink) { - add(ExternalDocumentationLink.kotlinStdlib()) - } - }.toMutableList() - - -fun parseLinks(links: List): List { - val (parsedLinks, parsedOfflineLinks) = links - .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } } - .filter { it.isNotEmpty() } - .partition { it.size == 1 } - - return parsedLinks.map { (root) -> ExternalDocumentationLink(root) } + - parsedOfflineLinks.map { (root, packageList) -> - val rootUrl = URL(root) - val packageListUrl = - try { - URL(packageList) - } catch (ex: MalformedURLException) { - File(packageList).toURI().toURL() - } - ExternalDocumentationLink(rootUrl, packageListUrl) + dokkaConfigurationImpl.apply(globals).apply { + sourceSets.forEach { + it.externalDocumentationLinks.cast>().addAll(defaultLinks(it)) } -} - -fun initializeConfiguration(globalArguments: GlobalArguments): DokkaConfiguration = if (globalArguments.json != null) { - val jsonContent = Paths.get(checkNotNull(globalArguments.json)).toFile().readText() - val globals = GlobalDokkaConfiguration(jsonContent) - val dokkaConfigurationImpl = DokkaConfigurationImpl(jsonContent) - - dokkaConfigurationImpl.apply(globals).apply { - sourceSets.forEach { - it.externalDocumentationLinks.cast>().addAll(defaultLinks(it)) } + } else { + globalArguments } -} else { - globalArguments -} - -fun main(args: Array) { - val globalArguments = GlobalArguments(args) - val configuration = initializeConfiguration(globalArguments) - DokkaGenerator(configuration, globalArguments.logger).generate() } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt index 2c761eef98..0fb62b3086 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt @@ -23,48 +23,160 @@ import kotlin.reflect.full.createInstance @DisableCachingByDefault(because = "Abstract super-class, not to be instantiated directly") abstract class AbstractDokkaTask : DefaultTask() { + /** + * Display name used to refer to the module. Used for ToC, navigation, logging, etc. + * + * If set for a single-project build or a MultiModule task, will be used as project name. + * + * Default is Gradle project name. + */ @Input val moduleName: Property = project.objects.safeProperty() .safeConvention(project.name) + /** + * Module version. + * + * If set for a single-project build or a MultiModule task, will be used + * as project version by the versioning plugin. + * + * Default is Gradle project version. + */ @Input val moduleVersion: Property = project.objects.safeProperty() .safeConvention(project.version.toString()) + /** + * Directory to which documentation will be generated, regardless of format. + * Can be set on per-task basis. + * + * Default is `project/buildDir/taskName.removePrefix("dokka").decapitalize()`, so + * for `dokkaHtmlMultiModule` task it will be `project/buildDir/htmlMultiModule` + */ @OutputDirectory val outputDirectory: Property = project.objects.safeProperty() .safeConvention(project.provider { defaultDokkaOutputDirectory() }) - @Optional - @InputDirectory - @PathSensitive(PathSensitivity.RELATIVE) - val cacheRoot: Property = project.objects.safeProperty() + /** + * Configuration for Dokka plugins. This property is not expected to be used directly - if possible, use + * [pluginConfiguration] blocks (preferred) or [pluginsMapConfiguration] instead. + */ + @Input + val pluginsConfiguration: ListProperty = project.objects.listProperty() + /** + * JSON configuration of Dokka plugins. + * + * Key is fully qualified Dokka plugin name, value is its configuration in JSON. + * + * Example: + * + * ```kotlin + * tasks.dokkaHtml { + * val dokkaBaseConfiguration = """ + * { + * "customAssets": ["${file("assets/my-image.png")}"], + * "customStyleSheets": ["${file("assets/my-styles.css")}"], + * "footerMessage": "(c) 2022 MyOrg" + * } + * """ + * pluginsMapConfiguration.set( + * mapOf("org.jetbrains.dokka.base.DokkaBase" to dokkaBaseConfiguration) + * ) + * } + * ``` + */ @Input - val failOnWarning: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.failOnWarning) + val pluginsMapConfiguration: MapProperty = project.objects.mapProperty() + /** + * Whether to suppress obvious functions. + * + * A function is considered to be obvious if it is: + * - Inherited from `kotlin.Any`, `Kotlin.Enum`, `java.lang.Object` or `java.lang.Enum`, + * such as `equals`, `hashCode`, `toString`. + * - Synthetic (generated by the compiler) and does not have any documentation, such as + * `dataClass.componentN` or `dataClass.copy`. + * + * Default is `true` + */ @Input val suppressObviousFunctions: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.suppressObviousFunctions) + /** + * Whether to suppress inherited members that aren't explicitly overridden in a given class. + * + * Note: this can suppress functions such as `equals`/`hashCode`/`toString`, but cannot suppress + * synthetic functions such as `dataClass.componentN` and `dataClass.copy`. Use [suppressObviousFunctions] + * for that. + * + * Default is `false`. + */ @Input val suppressInheritedMembers: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.suppressInheritedMembers) + /** + * Whether to resolve remote files/links over network. + * + * This includes package-lists used for generating external documentation links: + * for instance, to make classes from standard library clickable. + * + * Setting this to `true` can significantly speed up build times in certain cases, + * but can also worsen documentation quality and user experience, for instance by + * not resolving some dependency's class/member links. + * + * When using offline mode, you can cache fetched files locally and provide them to + * Dokka as local paths. For instance, see [GradleExternalDocumentationLinkBuilder]. + * + * Default is `false`. + */ @Input val offlineMode: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.offlineMode) - @Input - val pluginsConfiguration: ListProperty = project.objects.listProperty() - /** - * Used to keep compatibility with gradle using Kotlin lower than 1.3.50 + * Whether to fail documentation generation if Dokka has emitted a warning or an error. + * Will wait until all errors and warnings have been emitted first. + * + * This setting works well with [GradleDokkaSourceSetBuilder.reportUndocumented] + * + * Default is `false`. */ @Input - val pluginsMapConfiguration: MapProperty = project.objects.mapProperty() + val failOnWarning: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.failOnWarning) + @Optional + @InputDirectory + @PathSensitive(PathSensitivity.RELATIVE) + val cacheRoot: Property = project.objects.safeProperty() + + /** + * Type-safe configuration for a Dokka plugin. + * + * Note: this is available in Kotlin DSL only, if Dokka Gradle plugin was applied through `plugins` block + * and the configured plugin can be found on classpath, which may require adding a classpath dependency + * to `buildscript` block in case of external plugins. Some Dokka plugins, such as + * [org.jetbrains.dokka.base.DokkaBase], are on classpath by default. + * + * Example: + * + * ```kotlin + * import org.jetbrains.dokka.base.DokkaBase + * import org.jetbrains.dokka.base.DokkaBaseConfiguration + * + * tasks.dokkaHtml { + * pluginConfiguration { + * footerMessage = "Test" + * } + * } + * ``` + * + * @param P Plugin class that extends [DokkaPlugin] + * @param T Plugin configuration class that extends [ConfigurableBlock] + */ inline fun pluginConfiguration(block: T.() -> Unit) { val instance = T::class.createInstance().apply(block) val pluginConfiguration = PluginConfigurationImpl( diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt index 76213f14eb..c930bc5048 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt @@ -16,6 +16,33 @@ private typealias TaskPath = String @CacheableTask abstract class DokkaMultiModuleTask : AbstractDokkaParentTask() { + + /** + * List of Markdown files that contain + * [module and package documentation](https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation). + * + * Contents of specified files will be parsed and embedded into documentation as module and package descriptions. + * + * Example of such a file: + * + * ```markdown + * # Module kotlin-demo + * + * The module shows the Dokka usage. + * + * # Package org.jetbrains.kotlin.demo + * + * Contains assorted useful stuff. + * + * ## Level 2 heading + * + * Text after this heading is also part of documentation for `org.jetbrains.kotlin.demo` + * + * # Package org.jetbrains.kotlin.demo2 + * + * Useful stuff in another package. + * ``` + */ @InputFiles @Optional @PathSensitive(PathSensitivity.RELATIVE) diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetMapper.kt similarity index 100% rename from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt rename to runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetMapper.kt diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt index 717527d205..6390336ac0 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt @@ -13,6 +13,29 @@ import org.jetbrains.dokka.* import java.io.File import java.net.URL +/** + * [Source set](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) level configuration. + * + * Can be configured in the following way with Gradle Kotlin DSL: + * + * ```kotlin + * import org.jetbrains.dokka.gradle.DokkaTask + * + * tasks.dokkaHtml { + * dokkaSourceSets { + * // configure individual source set by name + * named("customSourceSet") { + * suppress.set(true) + * } + * + * // configure all source sets at once + * configureEach { + * reportUndocumented.set(true) + * } + * } + * } + * ``` + */ open class GradleDokkaSourceSetBuilder( @Transient @get:Input val name: String, @Transient @get:Internal internal val project: Project, @@ -22,177 +45,423 @@ open class GradleDokkaSourceSetBuilder( @Input val sourceSetID: DokkaSourceSetID = sourceSetIdFactory.create(name) + /** + * Whether this source set should be skipped when generating documentation. + * + * Default is `false`. + */ @Input val suppress: Property = project.objects.safeProperty() .safeConvention(false) - @Classpath - @Optional - val classpath: ConfigurableFileCollection = project.files() - + /** + * Display name used to refer to the source set. + * + * The name will be used both externally (for example, source set name visible to documentation readers) and + * internally (for example, for logging messages of [reportUndocumented]). + * + * By default, the value is deduced from information provided by the Kotlin Gradle plugin. + */ @Input @Optional val displayName: Property = project.objects.safeProperty() + /** + * List of Markdown files that contain + * [module and package documentation](https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation). + * + * Contents of specified files will be parsed and embedded into documentation as module and package descriptions. + * + * Example of such a file: + * + * ```markdown + * # Module kotlin-demo + * + * The module shows the Dokka usage. + * + * # Package org.jetbrains.kotlin.demo + * + * Contains assorted useful stuff. + * + * ## Level 2 heading + * + * Text after this heading is also part of documentation for `org.jetbrains.kotlin.demo` + * + * # Package org.jetbrains.kotlin.demo2 + * + * Useful stuff in another package. + * ``` + */ @InputFiles + @Optional @PathSensitive(PathSensitivity.RELATIVE) - val sourceRoots: ConfigurableFileCollection = project.objects.fileCollection() + val includes: ConfigurableFileCollection = project.files() + + /** + * Set of visibility modifiers that should be documented. + * + * This can be used if you want to document protected/internal/private declarations, + * as well as if you want to exclude public declarations and only document internal API. + * + * Can be configured on per-package basis, see [GradlePackageOptionsBuilder.documentedVisibilities]. + * + * Default is [DokkaConfiguration.Visibility.PUBLIC]. + */ + @Input + val documentedVisibilities: SetProperty = project.objects.setProperty() + .convention(DokkaDefaults.documentedVisibilities) + /** + * Specifies source sets that current source set depends on. + * + * Among other things, this information is needed to resolve + * [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html) declarations. + * + * Prefer using [dependsOn] function to append dependent source sets to this list. + * + * By default, the values are deduced from information provided by the Kotlin Gradle plugin. + */ @Input val dependentSourceSets: SetProperty = project.objects.setProperty() .convention(emptySet()) - @InputFiles + /** + * Classpath for analysis and interactive samples. + * + * Useful if some types that come from dependencies are not resolved/picked up automatically. + * Property accepts both `.jar` and `.klib` files. + * + * By default, classpath is deduced from information provided by the Kotlin Gradle plugin. + */ + @Classpath @Optional + val classpath: ConfigurableFileCollection = project.files() + + /** + * Source code roots to be analyzed and documented. + * Accepts directories and individual `.kt` / `.java` files. + * + * Prefer using [sourceRoot] function to append source roots to this list. + * + * By default, source roots are deduced from information provided by the Kotlin Gradle plugin. + */ + @InputFiles @PathSensitive(PathSensitivity.RELATIVE) - val samples: ConfigurableFileCollection = project.files() + val sourceRoots: ConfigurableFileCollection = project.objects.fileCollection() + /** + * List of directories or files that contain sample functions which are referenced via + * [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) KDoc tag. + */ @InputFiles @Optional @PathSensitive(PathSensitivity.RELATIVE) - val includes: ConfigurableFileCollection = project.files() - - @Input - val includeNonPublic: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.includeNonPublic) - - @Input - val documentedVisibilities: SetProperty = project.objects.setProperty() - .convention(DokkaDefaults.documentedVisibilities) + val samples: ConfigurableFileCollection = project.files() + /** + * Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + * after they have been filtered by [documentedVisibilities]. + * + * This setting works well with [AbstractDokkaTask.failOnWarning]. + * + * Can be overridden for a specific package by setting [GradlePackageOptionsBuilder.reportUndocumented]. + * + * Default is `false`. + */ @Input val reportUndocumented: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.reportUndocumented) - @Input - val skipEmptyPackages: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.skipEmptyPackages) - - @Input - val skipDeprecated: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.skipDeprecated) - - @Input - val suppressGeneratedFiles: Property = project.objects.safeProperty() - .safeConvention(true) - - @Input - val jdkVersion: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.jdkVersion) - + /** + * Specifies the location of the project source code on the Web. If provided, Dokka generates + * "source" links for each declaration. See [GradleSourceLinkBuilder] for more details. + * + * Prefer using [sourceLink] action/closure for adding source links. + */ @Nested val sourceLinks: SetProperty = project.objects.setProperty() .convention(emptySet()) + /** + * Allows to customize documentation generation options on a per-package basis. + * + * @see GradlePackageOptionsBuilder for details + */ @Nested val perPackageOptions: ListProperty = project.objects.listProperty() .convention(emptyList()) + /** + * Allows linking to Dokka/Javadoc documentation of the project's dependencies. + * + * Prefer using [externalDocumentationLink] action/closure for adding links. + */ @Nested val externalDocumentationLinks: SetProperty = project.objects.setProperty() .convention(emptySet()) + /** + * Platform to be used for setting up code analysis and samples. + * + * The default value is deduced from information provided by the Kotlin Gradle plugin. + */ @Input @Optional - val languageVersion: Property = project.objects.safeProperty() + val platform: Property = project.objects.safeProperty() + .safeConvention(Platform.DEFAULT) + /** + * Whether to skip packages that contain no visible declarations after + * various filters have been applied. + * + * For instance, if [skipDeprecated] is set to `true` and your package contains only + * deprecated declarations, it will be considered to be empty. + * + * Default is `true`. + */ @Input - @Optional - val apiVersion: Property = project.objects.safeProperty() + val skipEmptyPackages: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.skipEmptyPackages) + /** + * Whether to document declarations annotated with [Deprecated]. + * + * Can be overridden on package level by setting [GradlePackageOptionsBuilder.skipDeprecated]. + * + * Default is `false`. + */ + @Input + val skipDeprecated: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.skipDeprecated) + + /** + * Directories or individual files that should be suppressed, meaning declarations from them + * will be not documented. + * + * Will be concatenated with generated files if [suppressGeneratedFiles] is set to `false`. + */ + @InputFiles + @PathSensitive(PathSensitivity.RELATIVE) + val suppressedFiles: ConfigurableFileCollection = project.files() + + /** + * Whether to document/analyze generated files. + * + * Generated files are expected to be present under `{project}/{buildDir}/generated` directory. + * If set to `true`, it effectively adds all files from that directory to [suppressedFiles], so + * you can configure it manually. + * + * Default is `true`. + */ + @Input + val suppressGeneratedFiles: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.suppressGeneratedFiles) + + /** + * Whether to generate external documentation links that lead to API reference + * documentation for Kotlin's standard library when declarations from it are used. + * + * Default is `false`, meaning links will be generated. + */ @Input val noStdlibLink: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.noStdlibLink) + /** + * Whether to generate external documentation links to JDK's Javadocs + * when declarations from it are used. + * + * The version of JDK Javadocs is determined by [jdkVersion] property. + * + * Default is `false`, meaning links will be generated. + */ @Input val noJdkLink: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.noJdkLink) + /** + * Whether to generate external documentation links for Android SDK API reference + * when declarations from it are used. + * + * Only relevant in Android projects, ignored otherwise. + * + * Default is `false`, meaning links will be generated. + */ @Input val noAndroidSdkLink: Property = project.objects.safeProperty() - .safeConvention(false) - - @InputFiles - @PathSensitive(PathSensitivity.RELATIVE) - val suppressedFiles: ConfigurableFileCollection = project.files() + .safeConvention(DokkaDefaults.noAndroidSdkLink) + + /** + * [Kotlin language version](https://kotlinlang.org/docs/compatibility-modes.html) + * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) + * environment. + * + * By default, the latest language version available to Dokka's embedded compiler will be used. + */ + @Input + @Optional + val languageVersion: Property = project.objects.safeProperty() + /** + * [Kotlin API version](https://kotlinlang.org/docs/compatibility-modes.html) + * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) + * environment. + * + * By default, it will be deduced from [languageVersion]. + */ @Input @Optional - val platform: Property = project.objects.safeProperty() - .safeConvention(Platform.DEFAULT) + val apiVersion: Property = project.objects.safeProperty() + + /** + * JDK version to use when generating external documentation links for Java types. + * + * For instance, if you use [java.util.UUID] from JDK in some public declaration signature, + * and this property is set to `8`, Dokka will generate an external documentation link + * to [JDK 8 Javadocs](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) for it. + * + * Default is JDK 8. + */ + @Input + val jdkVersion: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.jdkVersion) + + /** + * Deprecated. Use [documentedVisibilities] instead. + */ + @Input + val includeNonPublic: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.includeNonPublic) fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID = sourceSetIdFactory.create(sourceSetName) + /** + * Convenient override to **append** source sets to [dependentSourceSets] + */ fun dependsOn(sourceSet: SourceSet) { dependsOn(DokkaSourceSetID(sourceSet.name)) } + /** + * Convenient override to **append** source sets to [dependentSourceSets] + */ fun dependsOn(sourceSet: GradleDokkaSourceSetBuilder) { dependsOn(sourceSet.sourceSetID) } + /** + * Convenient override to **append** source sets to [dependentSourceSets] + */ fun dependsOn(sourceSet: DokkaConfiguration.DokkaSourceSet) { dependsOn(sourceSet.sourceSetID) } + /** + * Convenient override to **append** source sets to [dependentSourceSets] + */ fun dependsOn(sourceSetName: String) { dependsOn(DokkaSourceSetID(sourceSetName)) } + /** + * Convenient override to **append** source sets to [dependentSourceSets] + */ fun dependsOn(sourceSetID: DokkaSourceSetID) { dependentSourceSets.add(sourceSetID) } + /** + * Convenient override to **append** source roots to [sourceRoots] + */ fun sourceRoot(file: File) { sourceRoots.from(file) } + /** + * Convenient override to **append** source roots to [sourceRoots] + */ fun sourceRoot(path: String) { sourceRoot(project.file(path)) } + /** + * Closure for configuring source links, appending to [sourceLinks]. + * + * @see [GradleSourceLinkBuilder] for details. + */ @Suppress("DEPRECATION") // TODO [beresnev] ConfigureUtil will be removed in Gradle 8 fun sourceLink(c: Closure) { val configured = org.gradle.util.ConfigureUtil.configure(c, GradleSourceLinkBuilder(project)) sourceLinks.add(configured) } + /** + * Action for configuring source links, appending to [sourceLinks]. + * + * @see [GradleSourceLinkBuilder] for details. + */ fun sourceLink(action: Action) { val sourceLink = GradleSourceLinkBuilder(project) action.execute(sourceLink) sourceLinks.add(sourceLink) } + /** + * Closure for configuring package options, appending to [perPackageOptions]. + * + * @see [GradlePackageOptionsBuilder] for details. + */ @Suppress("DEPRECATION") // TODO [beresnev] ConfigureUtil will be removed in Gradle 8 fun perPackageOption(c: Closure) { val configured = org.gradle.util.ConfigureUtil.configure(c, GradlePackageOptionsBuilder(project)) perPackageOptions.add(configured) } + /** + * Action for configuring package options, appending to [perPackageOptions]. + * + * @see [GradlePackageOptionsBuilder] for details. + */ fun perPackageOption(action: Action) { val option = GradlePackageOptionsBuilder(project) action.execute(option) perPackageOptions.add(option) } + /** + * Closure for configuring external documentation links, appending to [externalDocumentationLinks]. + * + * @see [GradleExternalDocumentationLinkBuilder] for details. + */ @Suppress("DEPRECATION") // TODO [beresnev] ConfigureUtil will be removed in Gradle 8 fun externalDocumentationLink(c: Closure) { val link = org.gradle.util.ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder(project)) externalDocumentationLinks.add(link) } + /** + * Action for configuring external documentation links, appending to [externalDocumentationLinks]. + * + * See [GradleExternalDocumentationLinkBuilder] for details. + */ fun externalDocumentationLink(action: Action) { val link = GradleExternalDocumentationLinkBuilder(project) action.execute(link) externalDocumentationLinks.add(link) } + /** + * Convenient override to **append** external documentation links to [externalDocumentationLinks]. + */ fun externalDocumentationLink(url: String, packageListUrl: String? = null) { externalDocumentationLink(URL(url), packageListUrl = packageListUrl?.let(::URL)) } + /** + * Convenient override to **append** external documentation links to [externalDocumentationLinks]. + */ fun externalDocumentationLink(url: URL, packageListUrl: URL? = null) { externalDocumentationLinks.add( GradleExternalDocumentationLinkBuilder(project).apply { diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderExtensions.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderExtensions.kt index c5c7428f28..5c7c523b93 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderExtensions.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilderExtensions.kt @@ -3,14 +3,23 @@ package org.jetbrains.dokka.gradle import com.android.build.gradle.api.AndroidSourceSet import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +/** + * Convenient override to **append** source sets to [GradleDokkaSourceSetBuilder.dependentSourceSets] + */ fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinSourceSet) { dependsOn(DokkaSourceSetID(sourceSet.name)) } +/** + * Convenient override to **append** source sets to [GradleDokkaSourceSetBuilder.dependentSourceSets] + */ fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: AndroidSourceSet) { dependsOn(DokkaSourceSetID(sourceSet.name)) } +/** + * Extension allowing configuration of Dokka source sets via Kotlin Gradle plugin source sets. + */ fun GradleDokkaSourceSetBuilder.kotlinSourceSet(kotlinSourceSet: KotlinSourceSet) { configureWithKotlinSourceSet(kotlinSourceSet) } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt index 19d150c338..36e4f81d31 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt @@ -10,12 +10,60 @@ import org.jetbrains.dokka.ExternalDocumentationLink import org.jetbrains.dokka.ExternalDocumentationLinkImpl import java.net.URL +/** + * Configuration builder that allows creating links leading to externally hosted + * documentation of your dependencies. + * + * For instance, if you are using types from `kotlinx.serialization`, by default + * they will be unclickable in your documentation, as if unresolved. However, + * since API reference for `kotlinx.serialization` is also built by Dokka and is + * [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), + * you can configure external documentation links for it, allowing Dokka to generate + * documentation links for used types, making them clickable and appear resolved. + * + * Example in Gradle Kotlin DSL: + * + * ```kotlin + * externalDocumentationLink { + * url.set(URL("https://kotlinlang.org/api/kotlinx.serialization/")) + * packageListUrl.set( + * rootProject.projectDir.resolve("serialization.package.list").toURL() + * ) + * } + * ``` + */ class GradleExternalDocumentationLinkBuilder( @Transient @get:Internal internal val project: Project ) : DokkaConfigurationBuilder { + + /** + * Root URL of documentation to link with. **Must** contain a trailing slash. + * + * Dokka will do its best to automatically find `package-list` for the given URL, and link + * declarations together. + * + * It automatic resolution fails or if you want to use locally cached files instead, + * consider providing [packageListUrl]. + * + * Example: + * + * ```kotlin + * java.net.URL("https://kotlinlang.org/api/kotlinx.serialization/") + * ``` + */ @Input val url: Property = project.objects.safeProperty() + /** + * Specifies the exact location of a `package-list` instead of relying on Dokka + * automatically resolving it. Can also be a locally cached file to avoid network calls. + * + * Example: + * + * ```kotlin + * rootProject.projectDir.resolve("serialization.package.list").toURL() + * ``` + */ @Optional @Input val packageListUrl: Property = project.objects.safeProperty() diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt index f15a6462ac..4e53cf8117 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt @@ -13,33 +13,91 @@ import org.jetbrains.dokka.DokkaConfigurationBuilder import org.jetbrains.dokka.DokkaDefaults import org.jetbrains.dokka.PackageOptionsImpl - +/** + * Configuration builder that allows setting some options for specific packages + * matched by [matchingRegex]. + * + * Example in Gradle Kotlin DSL: + * + * ```kotlin + * tasks.dokkaHtml { + * dokkaSourceSets.configureEach { + * perPackageOption { + * matchingRegex.set(".*internal.*") + * suppress.set(true) + * } + * } + * } + * ``` + */ class GradlePackageOptionsBuilder( @Transient @get:Internal internal val project: Project ) : DokkaConfigurationBuilder { + + /** + * Regular expression that is used to match the package. + * + * Default is any string: `.*`. + */ @Input val matchingRegex: Property = project.objects.safeProperty() .safeConvention(".*") + /** + * Whether this package should be skipped when generating documentation. + * + * Default is `false`. + */ @Input - val includeNonPublic: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.includeNonPublic) + val suppress: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.suppress) + /** + * Set of visibility modifiers that should be documented. + * + * This can be used if you want to document protected/internal/private declarations within a + * specific package, as well as if you want to exclude public declarations and only document internal API. + * + * Can be configured for a whole source set, see [GradleDokkaSourceSetBuilder.documentedVisibilities]. + * + * Default is [DokkaConfiguration.Visibility.PUBLIC]. + */ @Input val documentedVisibilities: SetProperty = project.objects.setProperty() .convention(DokkaDefaults.documentedVisibilities) + /** + * Whether to document declarations annotated with [Deprecated]. + * + * Can be overridden on source set level by setting [GradleDokkaSourceSetBuilder.skipDeprecated]. + * + * Default is `false`. + */ + @Input + val skipDeprecated: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.skipDeprecated) + + /** + * Whether to emit warnings about visible undocumented declarations, that is declarations from + * this package and without KDocs, after they have been filtered by [documentedVisibilities]. + * + * This setting works well with [AbstractDokkaTask.failOnWarning]. + * + * Can be overridden on source set level by setting [GradleDokkaSourceSetBuilder.reportUndocumented]. + * + * Default is `false`. + */ @Input val reportUndocumented: Property = project.objects.safeProperty() .safeConvention(DokkaDefaults.reportUndocumented) + /** + * Deprecated. Use [documentedVisibilities] instead. + */ @Input - val skipDeprecated: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.skipDeprecated) + val includeNonPublic: Property = project.objects.safeProperty() + .safeConvention(DokkaDefaults.includeNonPublic) - @Input - val suppress: Property = project.objects.safeProperty() - .safeConvention(DokkaDefaults.suppress) override fun build(): PackageOptionsImpl = PackageOptionsImpl( matchingRegex = checkNotNull(matchingRegex.getSafe()) { "prefix not specified" }, diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt index 2ddd8056d5..8e118767b2 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt @@ -8,17 +8,67 @@ import org.jetbrains.dokka.SourceLinkDefinitionImpl import java.io.File import java.net.URL +/** + * Configuration builder that allows adding a `source` link to each signature + * which leads to [remoteUrl] with a specific line number (configurable by setting [remoteLineSuffix]), + * letting documentation readers find source code for each declaration. + * + * Example in Gradle Kotlin DSL: + * + * ```kotlin + * sourceLink { + * localDirectory.set(projectDir.resolve("src")) + * remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + * remoteLineSuffix.set("#L") + * } + * ``` + */ class GradleSourceLinkBuilder( @Transient @get:Internal internal val project: Project ) : DokkaConfigurationBuilder { + /** + * Path to the local source directory. The path must be relative to the root of current project. + * + * Example: + * + * ```kotlin + * projectDir.resolve("src") + * ``` + */ @InputDirectory @PathSensitive(PathSensitivity.RELATIVE) val localDirectory: Property = project.objects.safeProperty() + /** + * URL of source code hosting service that can be accessed by documentation readers, + * like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + * source code links of declarations. + * + * Example: + * + * ```kotlin + * java.net.URL("https://github.com/username/projectname/tree/master/src/main/kotlin")) + * ``` + */ @Input val remoteUrl: Property = project.objects.safeProperty() + /** + * Suffix used to append source code line number to the URL. This will help readers navigate + * not only to the file, but to the specific line number of the declaration. + * + * The number itself will be appended to the specified suffix. For instance, + * if this property is set to `#L` and the line number is 10, resulting URL suffix + * will be `#L10` + * + * Suffixes used by popular services: + * - GitHub: `#L` + * - GitLab: `#L` + * - Bitbucket: `#lines-` + * + * Default is `#L`. + */ @Optional @Input val remoteLineSuffix: Property = project.objects.safeProperty() diff --git a/runners/maven-plugin/api/maven-plugin.api b/runners/maven-plugin/api/maven-plugin.api index 3b4ace568f..28d96bd3b6 100644 --- a/runners/maven-plugin/api/maven-plugin.api +++ b/runners/maven-plugin/api/maven-plugin.api @@ -66,22 +66,6 @@ public abstract class org/jetbrains/dokka/maven/AbstractDokkaMojo : org/apache/m public final fun setSuppressedFiles (Ljava/util/List;)V } -public final class org/jetbrains/dokka/maven/AbstractDokkaMojo$PackageOptions : org/jetbrains/dokka/DokkaConfiguration$PackageOptions { - public fun ()V - public fun getDocumentedVisibilities ()Ljava/util/Set; - public fun getIncludeNonPublic ()Z - public fun getMatchingRegex ()Ljava/lang/String; - public fun getReportUndocumented ()Ljava/lang/Boolean; - public fun getSkipDeprecated ()Z - public fun getSuppress ()Z - public fun setDocumentedVisibilities (Ljava/util/Set;)V - public fun setIncludeNonPublic (Z)V - public fun setMatchingRegex (Ljava/lang/String;)V - public fun setReportUndocumented (Z)V - public fun setSkipDeprecated (Z)V - public fun setSuppress (Z)V -} - public final class org/jetbrains/dokka/maven/DokkaJavadocJarMojo : org/jetbrains/dokka/maven/AbstractDokkaMojo { public fun ()V public fun execute ()V @@ -124,6 +108,22 @@ public final class org/jetbrains/dokka/maven/MavenDokkaLogger : org/jetbrains/do public fun warn (Ljava/lang/String;)V } +public final class org/jetbrains/dokka/maven/PackageOptions : org/jetbrains/dokka/DokkaConfiguration$PackageOptions { + public fun ()V + public fun getDocumentedVisibilities ()Ljava/util/Set; + public fun getIncludeNonPublic ()Z + public fun getMatchingRegex ()Ljava/lang/String; + public fun getReportUndocumented ()Ljava/lang/Boolean; + public fun getSkipDeprecated ()Z + public fun getSuppress ()Z + public fun setDocumentedVisibilities (Ljava/util/Set;)V + public fun setIncludeNonPublic (Z)V + public fun setMatchingRegex (Ljava/lang/String;)V + public fun setReportUndocumented (Z)V + public fun setSkipDeprecated (Z)V + public fun setSuppress (Z)V +} + public final class org/jetbrains/dokka/maven/SourceLinkMapItem { public fun ()V public final fun getLineSuffix ()Ljava/lang/String; diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index 581d4c9e61..92ab97548f 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -24,28 +24,6 @@ import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink import java.io.File import java.net.URL -class SourceLinkMapItem { - @Parameter(name = "path", required = true) - var path: String = "" - - @Parameter(name = "url", required = true) - var url: String = "" - - @Parameter(name = "lineSuffix") - var lineSuffix: String? = null -} - -class ExternalDocumentationLinkBuilder { - - @Parameter(name = "url", required = true) - var url: URL? = null - - @Parameter(name = "packageListUrl", required = true) - var packageListUrl: URL? = null - - fun build() = ExternalDocumentationLink(url, packageListUrl) -} - abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List) : AbstractMojo() { @Parameter(defaultValue = "\${project}", readonly = true, required = true) @@ -64,118 +42,303 @@ abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List = DokkaDefaults.documentedVisibilities - } + @Parameter(defaultValue = "JVM") + var displayName: String = "JVM" @Parameter var sourceSetName: String = "JVM" + /** + * Source code roots to be analyzed and documented. + * Accepts directories and individual `.kt` / `.java` files. + * + * Default is `{project.compileSourceRoots}`. + */ @Parameter(required = true, defaultValue = "\${project.compileSourceRoots}") var sourceDirectories: List = emptyList() + /** + * List of directories or files that contain sample functions which are referenced via + * [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) KDoc tag. + */ @Parameter var samples: List = emptyList() + /** + * List of Markdown files that contain + * [module and package documentation](https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation). + * + * Contents of specified files will be parsed and embedded into documentation as module and package descriptions. + * + * Example of such a file: + * + * ```markdown + * # Module kotlin-demo + * + * The module shows the Dokka usage. + * + * # Package org.jetbrains.kotlin.demo + * + * Contains assorted useful stuff. + * + * ## Level 2 heading + * + * Text after this heading is also part of documentation for `org.jetbrains.kotlin.demo` + * + * # Package org.jetbrains.kotlin.demo2 + * + * Useful stuff in another package. + * ``` + */ @Parameter var includes: List = emptyList() + /** + * Classpath for analysis and interactive samples. + * + * Useful if some types that come from dependencies are not resolved/picked up automatically. + * Property accepts both `.jar` and `.klib` files. + * + * Default is `{project.compileClasspathElements}`. + */ @Parameter(required = true, defaultValue = "\${project.compileClasspathElements}") var classpath: List = emptyList() + /** + * Specifies the location of the project source code on the Web. If provided, Dokka generates + * "source" links for each declaration. See [SourceLinkMapItem] for more details. + */ @Parameter var sourceLinks: List = emptyList() + /** + * Display name used to refer to the project/module. Used for ToC, navigation, logging, etc. + * + * Default is `{project.artifactId}`. + */ @Parameter(required = true, defaultValue = "\${project.artifactId}") var moduleName: String = "" + /** + * Whether to skip documentation generation. + * + * Default is `false`. + */ @Parameter(required = false, defaultValue = "false") var skip: Boolean = false + /** + * JDK version to use when generating external documentation links for Java types. + * + * For instance, if you use [java.util.UUID] from JDK in some public declaration signature, + * and this property is set to `8`, Dokka will generate an external documentation link + * to [JDK 8 Javadocs](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) for it. + * + * Default is JDK 8. + */ @Parameter(required = false, defaultValue = "${DokkaDefaults.jdkVersion}") var jdkVersion: Int = DokkaDefaults.jdkVersion + /** + * Whether to document declarations annotated with [Deprecated]. + * + * Can be overridden on package level by setting [PackageOptions.skipDeprecated]. + * + * Default is `false`. + */ @Parameter var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated + /** + * Whether to skip packages that contain no visible declarations after + * various filters have been applied. + * + * For instance, if [skipDeprecated] is set to `true` and your package contains only + * deprecated declarations, it will be considered to be empty. + * + * Default is `true`. + */ @Parameter var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages + /** + * Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + * after they have been filtered by [documentedVisibilities]. + * + * This setting works well with [failOnWarning]. + * + * Can be overridden for a specific package by setting [PackageOptions.reportUndocumented]. + * + * Default is `false`. + */ @Parameter var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented + /** + * Allows to customize documentation generation options on a per-package basis. + * + * @see PackageOptions for details + */ @Parameter var perPackageOptions: List = emptyList() + /** + * Allows linking to Dokka/Javadoc documentation of the project's dependencies. + * + * @see ExternalDocumentationLinkBuilder for details + */ @Parameter var externalDocumentationLinks: List = emptyList() + /** + * Whether to generate external documentation links that lead to API reference + * documentation for Kotlin's standard library when declarations from it are used. + * + * Default is `false`, meaning links will be generated. + */ @Parameter(defaultValue = "${DokkaDefaults.noStdlibLink}") var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink + /** + * Whether to generate external documentation links to JDK's Javadocs + * when declarations from it are used. + * + * The version of JDK Javadocs is determined by [jdkVersion] property. + * + * Default is `false`, meaning links will be generated. + */ @Parameter(defaultValue = "${DokkaDefaults.noJdkLink}") var noJdkLink: Boolean = DokkaDefaults.noJdkLink - @Parameter - var cacheRoot: String? = null - - @Parameter(defaultValue = "JVM") - var displayName: String = "JVM" - + /** + * Whether to resolve remote files/links over network. + * + * This includes package-lists used for generating external documentation links: + * for instance, to make classes from standard library clickable. + * + * Setting this to `true` can significantly speed up build times in certain cases, + * but can also worsen documentation quality and user experience, for instance by + * not resolving some dependency's class/member links. + * + * When using offline mode, you can cache fetched files locally and provide them to + * Dokka as local paths. For instance, see [ExternalDocumentationLinkBuilder]. + * + * Default is `false`. + */ @Parameter(defaultValue = "${DokkaDefaults.offlineMode}") var offlineMode: Boolean = DokkaDefaults.offlineMode + /** + * [Kotlin language version](https://kotlinlang.org/docs/compatibility-modes.html) + * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) + * environment. + * + * By default, the latest language version available to Dokka's embedded compiler will be used. + */ @Parameter var languageVersion: String? = null + /** + * [Kotlin API version](https://kotlinlang.org/docs/compatibility-modes.html) + * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) + * environment. + * + * By default, it will be deduced from [languageVersion]. + */ @Parameter var apiVersion: String? = null + /** + * Directories or individual files that should be suppressed, meaning declarations from them + * will be not documented. + */ @Parameter var suppressedFiles: List = emptyList() - @Parameter - var platform: String = "" - - @Parameter - var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic - + /** + * Set of visibility modifiers that should be documented. + * + * This can be used if you want to document protected/internal/private declarations, + * as well as if you want to exclude public declarations and only document internal API. + * + * Can be configured on per-package basis, see [PackageOptions.documentedVisibilities]. + * + * Default is [DokkaConfiguration.Visibility.PUBLIC]. + */ @Parameter(property = "visibility") var documentedVisibilities: Set = DokkaDefaults.documentedVisibilities // hack to set the default value for lists, didn't find any other safe way // maven seems to overwrite Kotlin's default initialization value, so it doesn't matter what you put there get() = field.ifEmpty { DokkaDefaults.documentedVisibilities } + /** + * Whether to fail documentation generation if Dokka has emitted a warning or an error. + * Will wait until all errors and warnings have been emitted first. + * + * This setting works well with [reportUndocumented] + * + * Default is `false`. + */ @Parameter var failOnWarning: Boolean = DokkaDefaults.failOnWarning + /** + * Whether to suppress obvious functions. + * + * A function is considered to be obvious if it is: + * - Inherited from `kotlin.Any`, `Kotlin.Enum`, `java.lang.Object` or `java.lang.Enum`, + * such as `equals`, `hashCode`, `toString`. + * - Synthetic (generated by the compiler) and does not have any documentation, such as + * `dataClass.componentN` or `dataClass.copy`. + * + * Default is `true` + */ @Parameter(defaultValue = "${DokkaDefaults.suppressObviousFunctions}") var suppressObviousFunctions: Boolean = DokkaDefaults.suppressObviousFunctions + /** + * Whether to suppress inherited members that aren't explicitly overridden in a given class. + * + * Note: this can suppress functions such as `equals`/`hashCode`/`toString`, but cannot suppress + * synthetic functions such as `dataClass.componentN` and `dataClass.copy`. Use [suppressObviousFunctions] + * for that. + * + * Default is `false`. + */ @Parameter(defaultValue = "${DokkaDefaults.suppressInheritedMembers}") var suppressInheritedMembers: Boolean = DokkaDefaults.suppressInheritedMembers + /** + * Dokka plugins to be using during documentation generation. + * + * Example: + * + * ```xml + * + * + * org.jetbrains.dokka + * gfm-plugin + * 1.7.20 + * + * + * ``` + */ @Parameter var dokkaPlugins: List = emptyList() get() = field + defaultDokkaPlugins + @Parameter + var cacheRoot: String? = null + + @Parameter + var platform: String = "" + + /** + * Deprecated. Use [documentedVisibilities] instead. + */ + @Parameter + var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic + protected abstract fun getOutDir(): String override fun execute() { @@ -320,6 +483,12 @@ abstract class AbstractDokkaMojo(private val defaultDokkaPlugins: List + * + * https://kotlinlang.org/api/latest/jvm/stdlib/ + * file:/${project.basedir}/stdlib.package.list + * + * + * ``` + */ +class ExternalDocumentationLinkBuilder { + + /** + * Root URL of documentation to link with. **Must** contain a trailing slash. + * + * Dokka will do its best to automatically find `package-list` for the given URL, and link + * declarations together. + * + * It automatic resolution fails or if you want to use locally cached files instead, + * consider providing [packageListUrl]. + * + * Example: + * + * ```xml + * https://kotlinlang.org/api/latest/jvm/stdlib/ + * ``` + */ + @Parameter(name = "url", required = true) + var url: URL? = null + + /** + * Specifies the exact location of a `package-list` instead of relying on Dokka + * automatically resolving it. Can also be a locally cached file to avoid network calls. + * + * Example: + * + * ```xml + * file:/${project.basedir}/stdlib.package.list + * ``` + */ + @Parameter(name = "packageListUrl", required = true) + var packageListUrl: URL? = null + + fun build() = ExternalDocumentationLink(url, packageListUrl) +} diff --git a/runners/maven-plugin/src/main/kotlin/PackageOptions.kt b/runners/maven-plugin/src/main/kotlin/PackageOptions.kt new file mode 100644 index 0000000000..af67876956 --- /dev/null +++ b/runners/maven-plugin/src/main/kotlin/PackageOptions.kt @@ -0,0 +1,85 @@ +package org.jetbrains.dokka.maven + +import org.apache.maven.plugins.annotations.Parameter +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.DokkaDefaults + +/** + * Configuration block that allows setting some options for specific packages + * matched by [matchingRegex]. + * + * Example: + * + * ```xml + * + * + * + * .*api.* + * false + * false + * false + * + * PUBLIC + * PROTECTED + * + * + * + * + * ``` + */ +class PackageOptions : DokkaConfiguration.PackageOptions { + + /** + * Regular expression that is used to match the package. + * + * If multiple packages match the same `matchingRegex`, the longest `matchingRegex` will be used. + * + * Default is any string: `.*`. + */ + @Parameter + override var matchingRegex: String = ".*" + + /** + * Whether this package should be skipped when generating documentation. + * + * Default is `false`. + */ + @Parameter + override var suppress: Boolean = DokkaDefaults.suppress + + /** + * List of visibility modifiers that should be documented. + * + * This can be used if you want to document protected/internal/private declarations within a + * specific package, as well as if you want to exclude public declarations and only document internal API. + * + * Default is [DokkaConfiguration.Visibility.PUBLIC]. + */ + @Parameter(property = "visibility") + override var documentedVisibilities: Set = DokkaDefaults.documentedVisibilities + + /** + * Whether to document declarations annotated with [Deprecated]. + * + * Can be set on project level with [AbstractDokkaMojo.skipDeprecated]. + * + * Default is `false`. + */ + @Parameter + override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated + + /** + * Whether to emit warnings about visible undocumented declarations, that is declarations from + * this package and without KDocs, after they have been filtered by [documentedVisibilities]. + * + * This setting works well with [AbstractDokkaMojo.failOnWarning]. + * + * Default is `false`. + */ + @Parameter + override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented + + @Parameter + @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities") + override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic +} diff --git a/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt b/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt new file mode 100644 index 0000000000..bd6d3baee5 --- /dev/null +++ b/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt @@ -0,0 +1,65 @@ +package org.jetbrains.dokka.maven + +import org.apache.maven.plugins.annotations.Parameter + +/** + * Configuration block that allows adding a `source` link to each signature + * which leads to [path] with a specific line number (configurable by setting [lineSuffix]), + * letting documentation readers find source code for each declaration. + * + * Example: + * + * ```xml + * + * + * ${project.basedir}/src/main/kotlin + * https://github.com/kotlin/dokka/tree/master/src/main/kotlin + * #L + * + * + * ``` + */ +class SourceLinkMapItem { + + /** + * Path to the local source directory. The path must be relative to the root of current project. + * + * Example: + * + * ```xml + * ${project.basedir}/src/main/kotlin + * ``` + */ + @Parameter(name = "path", required = true) + var path: String = "" + + /** + * URL of source code hosting service that can be accessed by documentation readers, + * like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + * source code links of declarations. + * + * Example: + * + * ```xml + * https://github.com/username/projectname/tree/master/src/main/kotlin + * ``` + */ + @Parameter(name = "url", required = true) + var url: String = "" + + /** + * Suffix used to append source code line number to the URL. This will help readers navigate + * not only to the file, but to the specific line number of the declaration. + * + * The number itself will be appended to the specified suffix. For instance, + * if this property is set to `#L` and the line number is 10, resulting URL suffix + * will be `#L10` + * + * Suffixes used by popular services: + * - GitHub: `#L` + * - GitLab: `#L` + * - Bitbucket: `#lines-` + */ + @Parameter(name = "lineSuffix") + var lineSuffix: String? = null +} From c16f6f6b0426a48dbb64ef0d1fcee639909a800e Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 16 Nov 2022 04:16:30 +0100 Subject: [PATCH 05/14] Update API dump --- core/api/core.api | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/api/core.api b/core/api/core.api index f466ed71e0..c85a33477c 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -208,7 +208,6 @@ public final class org/jetbrains/dokka/DokkaDefaults { public static final field INSTANCE Lorg/jetbrains/dokka/DokkaDefaults; public static final field delayTemplateSubstitution Z public static final field failOnWarning Z - public static final field format Ljava/lang/String; public static final field includeNonPublic Z public static final field jdkVersion I public static final field noAndroidSdkLink Z @@ -363,7 +362,6 @@ public final class org/jetbrains/dokka/GlobalDokkaConfiguration { public final class org/jetbrains/dokka/PackageOptionsImpl : org/jetbrains/dokka/DokkaConfiguration$PackageOptions { public fun (Ljava/lang/String;ZLjava/lang/Boolean;ZZLjava/util/Set;)V - public synthetic fun (Ljava/lang/String;ZLjava/lang/Boolean;ZZLjava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Z public final fun component3 ()Ljava/lang/Boolean; From ba31f35f8d12fcfc29a490fb741147bf80fcbca5 Mon Sep 17 00:00:00 2001 From: Sarah Haggarty Date: Wed, 14 Dec 2022 18:06:09 +0100 Subject: [PATCH 06/14] technical writer review --- docs/README.md | 38 ++- docs/topics/formats/html.md | 123 ++++---- docs/topics/formats/javadoc.md | 46 +-- docs/topics/formats/markdown.md | 46 +-- docs/topics/overview.md | 46 +-- docs/topics/plugins/plugins_introduction.md | 62 ++-- docs/topics/plugins/versioning.md | 83 +++--- docs/topics/runners/cli.md | 248 ++++++++-------- docs/topics/runners/gradle.md | 295 ++++++++++---------- docs/topics/runners/maven.md | 184 ++++++------ 10 files changed, 594 insertions(+), 577 deletions(-) diff --git a/docs/README.md b/docs/README.md index 52e982d7c2..0683b80748 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,30 +1,36 @@ -# docs +# Dokka documentation -This module contains documentation for Dokka that is deployed to [kotlinlang.org](https://kotlinlang.org/) +This folder contains the Dokka documentation that is available on [kotlinlang.org](https://kotlinlang.org/). -Documentation format is basically markdown with some DSL that is used internally at JetBrains. +Our documentation is written in Markdown format with some domain specific language (DSL) that is used at JetBrains. ## Project structure -* `dokka.tree` represents Table of Contents -* `vars.list` contains variables that you can use throughout documentation -* `topics` directory contains documentation topics themselves +This project contains: +* A `topics` directory, which contains our documentation in Markdown format. +* A `dokka.tree` file, that describes the site navigation structure. +* A `vars.list` file, that contains a list of variables that you can use throughout documentation. -## DSL +## DSL guide + +This section explains what DSL you can use to create different document elements. ### Title -Each page must have a title. By default, this title is used in ToC as well. +To declare the title of your document: ```text [//]: # (title: Name of topic) ``` -Note that title is basically a level 1 header, and it has to be the only one. So all other headers within topics must -be at least level 2, otherwise sidebar navigation may not work as expected. +Every document must have a title. By default, this title is used in the side menu. + +As the title is a level 1 header, it must be the only level 1 header in your document. All other headers within your document must be at least level 2, otherwise the side menu may not work as expected. ### Notes +To add a note: + ```text > This is a simple note > @@ -33,6 +39,8 @@ be at least level 2, otherwise sidebar navigation may not work as expected. ### Tips +To add a tip: + ```text > This is a useful tip > @@ -41,6 +49,8 @@ be at least level 2, otherwise sidebar navigation may not work as expected. ### Warning +To add a warning: + ```text > This is a warning > @@ -49,9 +59,9 @@ be at least level 2, otherwise sidebar navigation may not work as expected. ### Tabs -Tabs can be used to give instructions that are specific to a build system or something else. +Tabs can be used to save space in your document, allowing you to show different text in the same space depending on the tab chosen. -Content inside tabs is not limited to just text - it can be code blocks, tips, etc. +Content within tabs isn't limited to text. You can also add code blocks, tips, etc. ```text @@ -75,9 +85,7 @@ Instructions specific to CLI ``` -Notice the use of `group-key` - this groups all tabs on the page, and when the user switches to a tab - it switches to -all tabs with this key throughout the whole page. This is convenient for the user, since if they switched to Groovy tab, -they probably want other tabs to be of that value as well. +You can use the `group-key` parameter to link tabs in a document together. Grouping tabs like this means that if your reader selects a particular tab, e.g. "Groovy", then other tabbed sections in your document will also show the tab for "Groovy" first. ## Documentation preview diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index 2d0c6f6774..4b1e1d8a26 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -1,15 +1,14 @@ [//]: # (title: HTML) -HTML is Dokka's default and recommended format. You can see it in action by browsing documentation +HTML is Dokka's default and recommended output format. You can see an example of the final result by browsing documentation for [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/). ## Generating HTML documentation -This format comes standard in all runners: - +HTML as an output format is supported by all runners. To generate HTML documentation, follow these steps depending on your runner: * For [Gradle](gradle.md#generating-documentation), run `dokkaHtml` or `dokkaHtmlMultiModule` tasks. -* For [Maven](maven.md#generating-documentation), run `dokka:dokka` goal. -* For [CLI runner](cli.md), run it with [HTML dependencies](cli.md#generating-documentation). +* For [Maven](maven.md#generating-documentation), run the `dokka:dokka` goal. +* For [CLI runner](cli.md#generating-documentation), run with HTML dependencies set. > HTML pages generated by this format require a web server in order to render everything correctly. > @@ -161,47 +160,48 @@ Via [JSON configuration](cli.md#running-with-json-configuration):
    -For more details, see [configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins) topic. - ### Configuration options -| **Option** | **Description** | -|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `customAssets` | List of paths for image assets to be bundled with documentation. Can have any extension. See [modifying assets](#customizing-assets) section for details. | -| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. See [modifying styles](#customizing-styles) section for details. | -| `footerMessage` | Text displayed in the footer. | -| `separateInheritedMembers` | Boolean property. If set to `true`, Dokka will render properties/functions and inherited properties/inherited functions separately. Disabled by default. | -| `templatesDir` | Path to the directory with custom HTML templates. See [templates](#templates) section for more details. | -| `mergeImplicitExpectActualDeclarations` | Boolean property. If set to true, Dokka will merge declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. Can be useful in legacy codebases. Disabled by default. | +The table below contains all of the possible configuration options and their purpose. + +| **Option** | **Description** | +|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `customAssets` | List of paths for image assets to be bundled with documentation. The image assets can have any file extension. For more information, see [Customizing assets](#customizing-assets). | +| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. For more information, see [Customizing styles](#customizing-styles). | +| `templatesDir` | Path to the directory containing custom HTML templates. For more information, see [Templates](#templates). | +| `footerMessage` | The text displayed in the footer. | +| `separateInheritedMembers` | This is a boolean property. If set to `true`, Dokka renders properties/functions and inherited properties/inherited functions separately. This is disabled by default. | +| `mergeImplicitExpectActualDeclarations` | This is a boolean property. If set to true, Dokka merges declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. This can be useful for legacy codebases. This is disabled by default. | +For more information about configuring Dokka plugins, see [Configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins). ## Customization -HTML format provides a number of customization options. +To help you add your own look and feel to your documentation, the HTML format supports a number of customization options. ### Customizing styles -You can provide your own stylesheets by setting `customStyleSheets` -[configuration property](#configuration). These files will be applied to every page. +You can use your own stylesheets by using the `customStyleSheets` +[configuration option](#configuration). These are applied to every page. -Files with the same name will be overwritten, so it is possible to override stylesheets that Dokka uses: +It's also possible to override Dokka's stylesheets by using files with the same name: -| **Stylesheet name** | **Description** | -|----------------------|---------------------------------------------------------------| -| `style.css` | Main stylesheet, contains most styles used across all pages | -| `logo-styles.css` | Header logo styling | -| `prism.css` | Styles for [PrismJS](https://prismjs.com/) syntax highlighter | -| `jetbrains-mono.css` | Font styling | +| **Stylesheet name** | **Description** | +|----------------------|--------------------------------------------------------------------| +| `style.css` | Main stylesheet, contains most of the styles used across all pages | +| `logo-styles.css` | Header logo styling | +| `prism.css` | Styles for [PrismJS](https://prismjs.com/) syntax highlighter | +| `jetbrains-mono.css` | Font styling | -Source code for all of the used styles is +The source code for all of Dokka's stylesheets is [available on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/styles). ### Customizing assets -You can provide your own images to be bundled with documentation by setting `customAssets` -[configuration property](#configuration). These files will be copied to `/images` directory. +You can provide your own images to be bundled with documentation by using the `customAssets` +[configuration option](#configuration). These files are copied to the `/images` directory. -Files with the same name will be overwritten, so it is possible to override images and icons that Dokka uses. The most +It's possible to override Dokka's images and icons by using files with the same name. The most useful and relevant one being `logo-icon.svg`, which is the image that's used in the header. The rest is mostly icons. You can find all images used by Dokka on @@ -209,18 +209,17 @@ You can find all images used by Dokka on ### Changing the logo -To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. If your -image has similar size, it should not look out of place. +To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. For the best results, use an image of a similar size. -However, if your image has different dimensions or you want to use a `.png` image instead of the default `.svg` file, -you can [override `logo-styles.css` stylesheet](#customizing-styles) and make it fit. +However, if your image has different dimensions or you want to use a `.png` file instead of the default `.svg` file, +you can [override the `logo-styles.css` stylesheet](#customizing-styles) to make it fit. -For an example of how to do it, see +For an example of how to do this, see our [custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). -### Modifying footer +### Modifying the footer -You can modify the footer message by setting `footerMessage` [configuration property](#configuration). +You can modify text in the footer by using the `footerMessage` [configuration option](#configuration). ### Templates @@ -231,35 +230,35 @@ You can change the header completely, add your own banners/menus/search, load an Dokka uses the following templates: -| **Template** | **Description** | -|-----------------------------------|-------------------------------------------------------------------------------------------------------------------| -| `base.ftl` | Defines general design of all pages to be rendered. | -| `includes/header.ft` | Page header that by default contains the logo, version, source set selector, light/dark theme switch and search. | -| `includes/footer.ft` | Page footer that contains `footerMessage` [configuration property](#configuration) and copyright. | -| `includes/page_metadata.ft` | Metadata used within `` container. | -| `includes/source_set_selector.ft` | [Source set](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) selector in the header. | +| **Template** | **Description** | +|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------| +| `base.ftl` | Defines the general design of all pages to be rendered. | +| `includes/header.ft` | The page header that by default contains the logo, version, source set selector, light/dark theme switch, and search. | +| `includes/footer.ft` | The page footer that contains the `footerMessage` [configuration option](#configuration) and copyright. | +| `includes/page_metadata.ft` | Metadata used within `` container. | +| `includes/source_set_selector.ft` | [The source set](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) selector in the header. | -`base.ftl` template is the base template and it includes all the other ones. You can find source code for all templates +The base template is `base.ftl` and it includes all of the remaining listed templates. You can find the source code for all of Dokka's templates [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/templates). -You can override any template by setting `templatesDir` [configuration property](#configuration). Dokka will look -for the exact template names within given directory. If it fails to find user-defined templates, it will use the -default ones. +You can override any template by using the `templatesDir` [configuration option](#configuration). Dokka searches +for the exact template names within the given directory. If it fails to find user-defined templates, it uses the +default templates. #### Variables -Following variables are available inside all templates: +The following variables are available inside all templates: -| **Variable** | **Description** | -|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `${pageName}` | Page name | -| `${footerMessage}` | Text which is set by the `footerMessage` [configuration property](#configuration) | -| `${sourceSets}` | Nullable list of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for multi-platform pages. Each item has `name`, `platform` and `filter` properties. | -| `${projectName}` | Project name. Available only within `template_cmd` directive. | -| `${pathToRoot}` | Path to root from current page. Useful for locating assets. Available only within `template_cmd` directive. | +| **Variable** | **Description** | +|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `${pageName}` | The page name | +| `${footerMessage}` | The text which is set by the `footerMessage` [configuration option](#configuration) | +| `${sourceSets}` | A nullable list of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for multi-platform pages. Each item has `name`, `platform`, and `filter` properties. | +| `${projectName}` | The project name. It's available only within the `template_cmd` directive. | +| `${pathToRoot}` | The path to root from the current page. It's useful for locating assets and is available only within the `template_cmd` directive. | -Variables `projectName` and `pathToRoot` are available only within `@template_cmd` directive as they require more -context and thus need to be resolved at later stages by the [MultiModule](gradle.md#multi-project-builds) task: +Variables `projectName` and `pathToRoot` are available only within the `template_cmd` directive as they require more +context and thus they need to be resolved at later stages by the [MultiModule](gradle.md#multi-project-builds) task: ```html <@template_cmd name="projectName"> @@ -271,9 +270,9 @@ context and thus need to be resolved at later stages by the [MultiModule](gradle You can also use the following Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html): -| **Variable** | **Description** | -|-----------------|----------------------------------------------------------------------------------------------------------------------------------------| -| `<@content/>` | Main page content. | -| `<@resources/>` | Resources such as scripts and stylesheets. | -| `<@version/>` | Module version taken from configuration. If [versioning plugin](versioning.md) is applied, it will be replaced with version navigator. | +| **Variable** | **Description** | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `<@content/>` | The main page content. | +| `<@resources/>` | Resources such as scripts and stylesheets. | +| `<@version/>` | The module version taken from configuration. If the [versioning plugin](versioning.md) is applied, it is replaced with a version navigator. | diff --git a/docs/topics/formats/javadoc.md b/docs/topics/formats/javadoc.md index a319d38a5d..d85cb680ab 100644 --- a/docs/topics/formats/javadoc.md +++ b/docs/topics/formats/javadoc.md @@ -1,49 +1,49 @@ [//]: # (title: Javadoc) -> Javadoc output format is still in Alpha, use at your own risk, expect bugs and migration issues. Correct -> integration with tools that accept Java's Javadoc HTML as input is not guaranteed. +> The Javadoc output format is still in Alpha so you may find bugs and experience migration issues when using it. **You use it at your own risk.** +> Successful integration with tools that accept Java's Javadoc HTML as input is not guaranteed. > {type="warning"} -Dokka's Javadoc output format is a lookalike of Java's +Dokka's Javadoc output format is similar to Java's [Javadoc HTML format](https://docs.oracle.com/en/java/javase/19/docs/api/index.html). -It tries to visually mimic HTML pages generated by the Javadoc tool, but it's not a direct implementation -and it's not an exact copy. +It tries to visually mimic HTML pages generated by the Javadoc tool, but it's not a direct implementation +or an exact copy. ![Screenshot of javadoc output format](javadoc-format-example.png){height=750} -All Kotlin code and signatures are rendered as seen from Java's perspective, this is achieved with +All Kotlin code and signatures are rendered as seen from Java's perspective. This is achieved with our [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and applied by default for this format. -Javadoc output format is a rendering [Dokka plugin](plugins_introduction.md), maintained by the Dokka team. -It is [open source](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). +The Javadoc output format is generated by our [Dokka plugin](plugins_introduction.md), which we actively maintain. +It is open source and you can find the source code on [GitHub](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). -## Geneatring Javadoc documentation +## Generating Javadoc documentation -> Javadoc format does not support multiplatform projects. +> The Javadoc format is not supported for multiplatform projects. > -{type="note"} +{type="warning"} -Dokka's [Gradle plugin](gradle.md) ships with Javadoc format included, you can use the following tasks: +Dokka's [Gradle plugin](gradle.md) comes with the Javadoc output format included. You can use the following tasks: -| **Task** | **Description** | -|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaJavadoc` | Generates Javadoc documentation for a single project. | -| `dokkaJavadocCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJavadoc` | Generates Javadoc documentation for a single project. | +| `dokkaJavadocCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | -`javadoc.jar` [can be built separately](gradle.md#building-javadoc-jar). +The `javadoc.jar` file can be generated separately. For more information, see [Building `javadoc.jar`](gradle.md#building-javadoc-jar). -Dokka's [Maven plugin](maven.md) ships with Javadoc format built in, you can generate documentation -with the following goals: +Dokka's [Maven plugin](maven.md) comes with the Javadoc output format built in. You can generate documentation +by using the following goals: | **Goal** | **Description** | |--------------------|------------------------------------------------------------------------------| @@ -54,10 +54,10 @@ with the following goals: -Since Javadoc format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the -[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). +Since the Javadoc output format is generated by a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the plugin as a +[JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). -Javadoc format has two dependencies that you will need to provide as jar files as well: +The Javadoc output format has two dependencies that you need to provide as additional JAR files: * [kotlin-as-java plugin](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-as-java-plugin/%dokkaVersion%) * [korte-jvm](https://mvnrepository.com/artifact/com.soywiz.korlibs.korte/korte-jvm/3.3.0) @@ -86,7 +86,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. +For more information, see [Other output formats](cli.md#other-output-formats) in the CLI runner documentation. diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/markdown.md index 42ed18cf64..690cfbb156 100644 --- a/docs/topics/formats/markdown.md +++ b/docs/topics/formats/markdown.md @@ -1,6 +1,6 @@ [//]: # (title: Markdown) -> Markdown output formats are still in Alpha, use at your own risk, expect bugs and migration issues. +> The Markdown output formats are still in Alpha so you may find bugs and experience migration issues when using them. **You use them at your own risk.** > {type="warning"} @@ -15,18 +15,18 @@ they are open source. ## GFM -GFM format generates documentation in [GitHub Flavored Markdown](https://github.github.com/gfm/). +The GFM output format generates documentation in [GitHub Flavored Markdown](https://github.github.com/gfm/). -Dokka's [Gradle plugin](gradle.md) ships with GFM format included, you can use the following tasks: +Dokka's [Gradle plugin](gradle.md) comes with the GFM output format included. You can use the following tasks with it: -| **Task** | **Description** | -|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaGfm` | Generates GFM documentation for a single project. | -| `dokkaGfmMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. Generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaGfmCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaGfm` | Generates GFM documentation for a single project. | +| `dokkaGfmMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaGfmCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | @@ -51,9 +51,9 @@ dependency: ``` -After that, running `dokka:dokka` goal should produce documentation in GFM format. +After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see [other output formats](maven.md#other-output-formats) section for the Maven plugin. +For more information, see the Mavin plugin documentation for [Other output formats](maven.md#other-output-formats). @@ -84,27 +84,27 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. +For more information, see the CLI runner documentation for [Other output formats](cli.md#other-output-formats). -You can find sources [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/gfm). +You can find the source code [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/gfm). ## Jekyll -Jekyll format generates documentation in [Jekyll](https://jekyllrb.com/) compatible Markdown. +The Jekyll output format generates documentation in [Jekyll](https://jekyllrb.com/) compatible Markdown. -Dokka's [Gradle plugin](gradle.md) ships with Jekyll format included, you can use the following tasks: +Dokka's [Gradle plugin](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: -| **Task** | **Description** | -|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaJekyll` | Generates Jekyll documentation for a single project. | -| `dokkaJekyllMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. Generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaJekyllCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. Calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJekyll` | Generates Jekyll documentation for a single project. | +| `dokkaJekyllMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaJekyllCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | @@ -129,9 +129,9 @@ dependency: ``` -After that, running `dokka:dokka` goal should produce documentation in GFM format. +After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see [other output formats](maven.md#other-output-formats) section for the Maven plugin. +For more information, see the Maven plugin documentation for [Other output formats](maven.md#other-output-formats). @@ -164,9 +164,9 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see [other output formats](cli.md#other-output-formats) section for the CLI runner. +For more information, see the CLI runner documentation for [Other output formats](cli.md#other-output-formats). -You can find sources [on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/jekyll). +You can find the source code on [GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/jekyll). diff --git a/docs/topics/overview.md b/docs/topics/overview.md index f88a9d884a..8321fe2028 100644 --- a/docs/topics/overview.md +++ b/docs/topics/overview.md @@ -2,14 +2,14 @@ Dokka is an API documentation engine for Kotlin. -Just like Kotlin itself, Dokka supports mixed-language projects: it understands Kotlin's +Just like Kotlin itself, Dokka supports mixed-language projects. It understands Kotlin's [KDoc comments](https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax) and Java's [Javadoc comments](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html). -Dokka can generate documentation in multiple formats, including its own and modern [HTML format](html.md), -multiple flavours of [Markdown](markdown.md) and Java's [Javadoc HTML](javadoc.md). +Dokka can generate documentation in multiple formats, including its own modern [HTML format](html.md), +multiple flavors of [Markdown](markdown.md), and Java's [Javadoc HTML](javadoc.md). -Libraries that use Dokka for API reference docs: +There are already a number of libraries that use Dokka for their API reference documentation: * [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/) * [Bitmovin](https://cdn.bitmovin.com/player/android/3/docs/index.html) @@ -17,7 +17,7 @@ Libraries that use Dokka for API reference docs: * [Ktor](https://api.ktor.io/) * [OkHttp](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) (Markdown) -Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or [command line](cli.md). It is also +Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or on the [command line](cli.md). It is also [highly pluggable](plugins_introduction.md). ## Quickstart @@ -25,7 +25,7 @@ Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or [command line](cl -Apply Dokka Gradle plugin in the root project: +Apply the Dokka Gradle plugin in the root of your project: ```kotlin plugins { @@ -33,7 +33,7 @@ plugins { } ``` -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well: +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well: ```kotlin subprojects { @@ -41,19 +41,19 @@ subprojects { } ``` -To generate documentation run the following Gradle tasks: +To generate documentation, run the following Gradle tasks: -* `dokkaHtml` for single-project builds. -* `dokkaHtmlMultiModule` for multi-module builds. +* `dokkaHtml` for single-project builds +* `dokkaHtmlMultiModule` for multi-module builds -By default, output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. +By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -Learn more about Gradle configuration in a separate [topic dedicated to Gradle](gradle.md). +To learn more about Gradle configuration, see [Gradle](gradle.md). -Apply Dokka Gradle plugin in the root project: +Apply the Dokka Gradle plugin in the root of your project: ```groovy plugins { @@ -61,7 +61,7 @@ plugins { } ``` -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well: +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well: ```groovy subprojects { @@ -69,19 +69,19 @@ subprojects { } ``` -To generate documentation run the following Gradle tasks: +To generate documentation, run the following Gradle tasks: -* `dokkaHtml` for single-project builds. -* `dokkaHtmlMultiModule` for multi-module builds. +* `dokkaHtml` for single-project builds +* `dokkaHtmlMultiModule` for multi-module builds By default, output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -Learn more about Gradle configuration in a separate [topic dedicated to Gradle](gradle.md). +To learn more about Gradle configuration, see [Gradle](gradle.md). -Add Dokka Maven plugin to the plugins section of your POM: +Add the Dokka Maven plugin to the plugins section of your POM file: ```xml @@ -103,11 +103,11 @@ Add Dokka Maven plugin to the plugins section of your POM: ``` -To generate documentation run `dokka:dokka` goal. +To generate documentation, run the `dokka:dokka` goal. -By default, output directory is set to `target/dokka`. +By default, the output directory is set to `target/dokka`. -Learn more about Maven configuration in a separate [topic dedicated to Maven](maven.md). +To learn more about Maven configuration, see [Maven](maven.md). @@ -115,4 +115,4 @@ Learn more about Maven configuration in a separate [topic dedicated to Maven](ma ## Community Dokka has a dedicated `#dokka` channel in [Kotlin Community Slack](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up) -where you can chat about Dokka itself, its plugins and how to develop them, and get in touch with maintainers. +where you can chat about Dokka, its plugins and how to develop them, as well as get in touch with maintainers. diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/plugins/plugins_introduction.md index 3b162e0c3e..bee4c02729 100644 --- a/docs/topics/plugins/plugins_introduction.md +++ b/docs/topics/plugins/plugins_introduction.md @@ -14,13 +14,13 @@ If you want to learn how to create Dokka plugins, see ## Applying Dokka plugins Dokka plugins are published as separate artifacts, so to apply a Dokka plugin you only need to add it as a dependency. -From there, the plugin will extend Dokka by itself - no extra actions needed. +From there, the plugin extends Dokka by itself - no further action is needed. > Plugins that use the same extension points or work in a similar way can interfere with each other. > This may lead to visual bugs, general undefined behaviour or even failed builds. However, it should not lead to > concurrency issues since Dokka does not expose any mutable data structures or objects. -> -> If you notice any problems of such nature, it's a good idea to check which plugins are applied and what they do. +> +> If you notice problems like this, it's a good idea to check which plugins are applied and what they do. > {type="note"} @@ -30,23 +30,23 @@ to your project: -Gradle plugin creates convenient dependency configurations that allow you to apply plugins universally or +The Gradle plugin creates convenient dependency configurations that allow you to apply plugins universally or for a specific output format only. ```kotlin dependencies { - // will be applied universally + // Is applied universally dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:%dokkaVersion%") - - // will be applied for single-module dokkaHtml task only + + // Is applied for the single-module dokkaHtml task only dokkaHtmlPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%") - // will be applied for html format in multi-project builds + // Is applied for HTML format in multi-project builds dokkaHtmlPartialPlugin("org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%") } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins in +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within > subprojects as well as in their parent project. > {type="note"} @@ -54,23 +54,23 @@ dependencies { -Gradle plugin creates convenient dependency configurations that allow you to apply Dokka plugins universally or +The Gradle plugin creates convenient dependency configurations that allow you to apply Dokka plugins universally or for a specific output format only. ```groovy dependencies { - // will be applied universally + // Is applied universally dokkaPlugin 'org.jetbrains.dokka:mathjax-plugin:%dokkaVersion%' - // will be applied for single-module dokkaHtml task only + // Is applied for the single-module dokkaHtml task only dokkaHtmlPlugin 'org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%' - // will be applied for html format in multi-project builds + // Is applied for HTML format in multi-project builds dokkaHtmlPartialPlugin 'org.jetbrains.dokka:kotlin-as-java-plugin:%dokkaVersion%' } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins in +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within > subprojects as well as in their parent project. > {type="note"} @@ -127,18 +127,18 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), D ## Configuring Dokka plugins -Dokka plugins can also have configuration options of their own. Consult used plugin's documentation to see which +Dokka plugins can also have configuration options of their own. Consult each plugin's documentation to see which options are available. -Let's have a look at how you can configure `DokkaBase` plugin, which is responsible for generating [HTML](html.md) -documentation, by adding a custom image to assets (`customAssets` option), by adding custom style sheets -(`customStyleSheets` option) and by modifying the footer message (`footerMessage` option): +Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](html.md) +documentation, by adding a custom image to assets (`customAssets` option), by adding custom style sheets +(`customStyleSheets` option), and by modifying the footer message (`footerMessage` option): Gradle's Kotlin DSL allows for type-safe plugin configuration. This is achievable by adding plugin's artifact to classpath -dependencies in `buildscript` block, and then importing plugin and configuration classes: +dependencies in the `buildscript` block, and then importing plugin and configuration classes: ```kotlin import org.jetbrains.dokka.base.DokkaBase @@ -160,7 +160,7 @@ tasks.withType().configureEach { } ``` -Alternatively, plugins can be configured via JSON. This way no additional dependencies are needed. +Alternatively, plugins can be configured via JSON. With this method, no additional dependencies are needed. ```kotlin import org.jetbrains.dokka.gradle.DokkaTask @@ -233,7 +233,7 @@ tasks.withType(DokkaTask.class) { If you are using the [CLI](cli.md) runner with [command line arguments](cli.md#running-with-command-line-arguments), -use `-pluginsConfiguration` argument that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. +use the `-pluginsConfiguration` argument that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. If you need to configure multiple plugins, you can pass multiple values separated by `^^`. @@ -243,8 +243,8 @@ java -jar dokka-cli-%dokkaVersion%.jar \ -pluginsConfiguration "org.jetbrains.dokka.base.DokkaBase={\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg CLI\"}" ``` -If you are using [JSON configuration](cli.md#running-with-json-configuration), there exists a similar -`pluginsConfiguration` array that accepts JSON as values. +If you are using [JSON configuration](cli.md#running-with-json-configuration), there exists a similar +`pluginsConfiguration` array that accepts JSON as `values`. ```json { @@ -264,10 +264,12 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), t ## Notable plugins -| **Name** | **Description** | -|-----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| [Android documentation plugin](https://github.com/Kotlin/dokka/tree/master/plugins/android-documentation) | Improves documentation experience on Android platform | -| [Versioning plugin](versioning.md) | Adds version selector and helps organize documentation for different version of your application/library | -| [MermaidJS HTML plugin](https://github.com/glureau/dokka-mermaid) | Renders [MermaidJS](https://mermaid-js.github.io/mermaid/#/) diagrams and visualizations found in KDocs | -| [Mathjax HTML plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) | Pretty prints mathematics found in KDocs | -| [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | +For a list of popular Dokka plugins, see the table below. + +| **Name** | **Description** | +|-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| +| [Android documentation plugin](https://github.com/Kotlin/dokka/tree/master/plugins/android-documentation) | Improves the documentation experience on Android | +| [Versioning plugin](versioning.md) | Adds version selector and helps to organize documentation for different versions of your application/library | +| [MermaidJS HTML plugin](https://github.com/glureau/dokka-mermaid) | Renders [MermaidJS](https://mermaid-js.github.io/mermaid/#/) diagrams and visualizations found in KDocs | +| [Mathjax HTML plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) | Pretty prints mathematics found in KDocs | +| [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | diff --git a/docs/topics/plugins/versioning.md b/docs/topics/plugins/versioning.md index 9cdbeebfb3..f0d4be0a7d 100644 --- a/docs/topics/plugins/versioning.md +++ b/docs/topics/plugins/versioning.md @@ -1,16 +1,16 @@ [//]: # (title: Versioning plugin) -Versioning plugin aims to provide the ability to host documentation for multiple versions of your library/application -with seamless switching between them. This, in turn, provides better experience for your users. +The versioning plugin provides the ability to host documentation for multiple versions of your library/application +with seamless switching between them. This, in turn, provides a better experience for your users. ![Screenshot of documentation version dropdown](versioning-plugin-example.png){height=350} -> Versioning plugin only works with [HTML](html.md) format. +> The versioning plugin only works with [HTML](html.md) format. > {type="note"} -Visit [versioning plugin example project](https://github.com/Kotlin/dokka/tree/1.7.20/examples/gradle/dokka-versioning-multimodule-example) -to see it in action as well as how it can be configured. +Visit the [versioning plugin example project](https://github.com/Kotlin/dokka/tree/1.7.20/examples/gradle/dokka-versioning-multimodule-example) +to see an example of it in action and how it can be configured. ## Applying the plugin @@ -25,7 +25,7 @@ dependencies { } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply versioning plugin in +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the versioning plugin within > subprojects as well as in their parent project. > {type="note"} @@ -39,7 +39,7 @@ dependencies { } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply versioning plugin in +> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the versioning plugin within > subprojects as well as in their parent project. > {type="note"} @@ -67,10 +67,10 @@ dependencies { -You can find versioning plugin's artifact on +You can find the versioning plugin's artifact on [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/versioning-plugin/%dokkaVersion%) or by browsing -[maven central repository](https://repo1.maven.org/maven2/org/jetbrains/dokka/versioning-plugin/%dokkaVersion%/) -directly, and pass it to `pliginsClasspath`. +[maven central repository](https://repo1.maven.org/maven2/org/jetbrains/dokka/versioning-plugin/%dokkaVersion%/) +directly, and pass it to `pluginsClasspath`. Via [command line arguments](cli.md#running-with-command-line-arguments): @@ -101,19 +101,19 @@ Via [JSON configuration](cli.md#running-with-json-configuration): ### Configuration options -Versioning plugin has a number of optional configuration properties: +The table below contains all the possible configuration options for the versioning plugin and their purpose. -| **Property** | **Description** | -|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `version` | Version of your application/library for which documentation is going to be generated. This will be the version in the dropdown menu. | -| `versionsOrdering` | Optional list of strings that represents the order in which versions should appear in the dropdown menu. Must match versions string exactly. First item of the list is the topmost in the dropdown. | -| `olderVersionsDir` | Optional path to a parent folder that contains other documentation versions. Requires a certain [directory structure](#directory-structure). | -| `olderVersions` | Optional list of paths to other documentation versions. Must point to Dokka's outputs directly. Useful if different versions are scattered and cannot be put into a single directory. | -| `renderVersionsNavigationOnAllPages` | Optional boolean indicating whether to render navigation dropdown on all pages. True by default. | +| **Option** | **Description** | +|--------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `version` | The version of your application/library that documentation is going to be generated for. This will be the version shown in the dropdown menu. | +| `versionsOrdering` | An optional list of strings that represents the order that versions should appear in the dropdown menu. Must match versions string exactly. The first item in the list is at the top of the dropdown. | +| `olderVersionsDir` | An optional path to a parent folder that contains other documentation versions. It requires a specific directory structure. For more information, see [Directory structure](#directory-structure). | +| `olderVersions` | An optional list of paths to other documentation versions. It must point to Dokka's outputs directly. This is useful if different versions can't all be in the same directory. | +| `renderVersionsNavigationOnAllPages` | An optional boolean value indicating whether to render the navigation dropdown on all pages. Set to true by default. | #### Directory structure -Note that the directory passed to `olderVersionsDir` requires a specific structure: +Note that the directory passed to `olderVersionsDir` needs to follow a specific structure: ```text . @@ -253,31 +253,30 @@ Alternatively, via JSON configuration: ## Generating versioned documentation -With versioning plugin applied and configured, no other steps are needed: documentation can be built the usual way. +With the versioning plugin applied and configured, no other steps are needed. Documentation can be built in the usual way. -Among other things, versioning plugin will add a `version.json` file to the output folder. This file will be used by the +Among other things, the versioning plugin adds a `version.json` file to the output folder. This file is used by the plugin to match versions and generate version navigation. If your previously generated documentation does not have that -file, you will need to re-generate documentation for such versions -- adding just the file will not work. +file, you will need to re-generate documentation for such versions. Just adding the file will not work. -Versioning plugin will also bundle all other documentation versions that have been passed through `olderVersionsDir` -and `olderVersions` configuration properties by putting them inside `older` directory. +The versioning plugin also bundles all other documentation versions that have been passed through `olderVersionsDir` +and `olderVersions` configuration options by putting them inside the `older` directory. ## Usage example -There is no single correct way to configure the plugin, it can be tailored to your liking and needs. However, +There is no single correct way to configure the plugin, it can be tailored to your needs. However, it can be a bit overwhelming when starting out. Below you will find one of the ways it can be configured so that you -can begin publishing versioned documentation right away. +can begin publishing versioned documentation straight away. The main idea behind it is the following: -1. One directory will contain all versions of your documentation. For instance, `documentation/version/{doc_version}`. - This is your archive, you will need to preserve it for future builds. -2. Output directory of all new builds will be set to that directory as well, under `documentation/version/{new_version}` -3. When new builds are executed, the plugin will look for previous versions of documentation in the archive directory. -4. Once new documentation has been generated, it needs to be **copied** to some place accessible by the user: - GitHub pages, nginx static directories, and so on. It needs to be copied and not moved because Dokka will still need - this version for future builds, otherwise there will be a gap in the archive. -5. Once it has been safely copied away, you can remove `older` directory from the newly generated and archived version. +1. One directory contains all versions of your documentation. For example, `documentation/version/{doc_version}`. + This is your archive which is needed for future builds. +2. The output directory of all new builds is set to that directory as well, under `documentation/version/{new_version}`. +3. When new builds are executed, the plugin looks for previous versions of documentation in the archive directory. +4. Once new documentation has been generated, it needs to be **copied** to somewhere accessible by the user. + For example, GitHub pages or nginx static directories. It needs to be **copied**, not moved, because Dokka needs +5. Once it has been safely copied, you can remove the `older` directory from the newly generated and archived version. This helps reduce the overhead of each version bundling all previous versions, as these files are effectively duplicates. ```kotlin @@ -295,15 +294,15 @@ dependencies { } tasks.dokkaHtml { - // can be any persistent folder where + // This can be any persistent folder where // you store documentation by version val docVersionsDir = projectDir.resolve("documentation/version") - // version for which you are currently generating docs + // The version for which you are currently generating docs val currentVersion = "1.3" - // set output to folder with all other versions - // as you'll need current version for future builds + // Set the output to a folder with all other versions + // as you'll need the current version for future builds val currentDocsDir = docVersionsDir.resolve(currentVersion) outputDirectory.set(currentDocsDir) @@ -313,15 +312,15 @@ tasks.dokkaHtml { } doLast { - // this folder will contain latest documentation with all + // This folder contains the latest documentation with all // previous versions included, so it's ready to be published. - // make sure it's copied and not moved - you'll still need this + // Make sure it's copied and not moved - you'll still need this // version for future builds currentDocsDir.copyTo(file("/my/hosting")) - // only once current documentation has been safely moved, + // Only once current documentation has been safely moved, // remove previous versions bundled in it. They will not - // be needed in future builds, it's just overhead + // be needed in future builds, it's just overhead. currentDocsDir.resolve("older").deleteRecursively() } } diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index 59999ee34f..cb7c72ca9d 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -1,18 +1,18 @@ [//]: # (title: CLI runner) If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) plugins, Dokka has -a command line runner for generating documentation without any build tools. +a command line (CLI) runner for generating documentation without any build tools. -In comparison, it has the same, if not more, capabilities as the Gradle plugin, although it is considerably more +In comparison, it has the same, if not more, capabilities as the Gradle plugin. Although it is considerably more difficult to set up as there is no autoconfiguration, especially in multiplatform and multimodule environments. -CLI runner is published as a separate artifact to Maven Central under `org.jetbrains.dokka:dokka-cli`, so you can +The CLI runner is published as a separate artifact to Maven Central under `org.jetbrains.dokka:dokka-cli`, so you can find it on [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-cli) or by browsing [maven central repository directories](https://repo1.maven.org/maven2/org/jetbrains/dokka/dokka-cli/) directly. ## Getting started -With `dokka-cli-%dokkaVersion%.jar` file on your computer, you can run it with `-help` to see available arguments and their description: +With the `dokka-cli-%dokkaVersion%.jar` file saved on your computer, run it with the `-help` option to see all available arguments and their description: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -help @@ -26,11 +26,11 @@ java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help ## Generating documentation -### Pre-requisites +### Prerequisites -Since there is no build tool to manage dependencies, you will have to provide dependency `.jar` files yourself. +Since there is no build tool to manage dependencies, you have to provide dependency `.jar` files yourself. -Dependencies you will need for any format: +Listed below are the dependencies that you need for any output format: | **Group** | **Artifact** | **Version** | **Link** | |-----------------------|----------------------------|----------------|-----------------------------------------------------------------------------------------------------------------| @@ -39,7 +39,7 @@ Dependencies you will need for any format: | `org.jetbrains.dokka` | `kotlin-analysis-compiler` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-compiler/%dokkaVersion%) | | `org.jetbrains.dokka` | `kotlin-analysis-intellij` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-intellij/%dokkaVersion%) | -Additional dependencies for [HTML](html.md) format: +Below are the additional dependencies that you need for [HTML](html.md) output format: | **Group** | **Artifact** | **Version** | **Link** | |-------------------------|--------------------|-------------|--------------------------------------------------------------------------------------------------| @@ -51,10 +51,10 @@ Additional dependencies for [HTML](html.md) format: You can pass command line arguments to configure the CLI runner. -At the very least you would need to provide the following arguments: +At the very least you need to provide the following arguments: * `-pluginsClasspath` - a list of absolute/relative paths to downloaded dependencies, separated by semi-colons `;` -* `-sourceSet` - an absolute path to code sources for which to generate documentation -* `-outputDir` - an absolute/relative path of documentation output directory +* `-sourceSet` - an absolute path to code sources to generate documentation for +* `-outputDir` - an absolute/relative path of the documentation output directory ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -63,25 +63,25 @@ java -jar dokka-cli-%dokkaVersion%.jar \ -outputDir "./dokka/html" ``` -> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`, -> otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. +> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`. +> Otherwise you may see obscure exceptions, such as `NoSuchFieldError`. > {type="note"} -Executing the given example should generate documentation in [HTML](html.md) format. +Executing the given example generates documentation in [HTML](html.md) output format. -See [command line arguments](#command-line-arguments) for more configuration details. +See [Command line arguments](#command-line-arguments) for more configuration details. ### Running with JSON configuration -It is possible to configure the CLI runner with JSON. In this case, you will need to provide an -absolute/relative path to the JSON configuration file, and all other configuration options will be parsed from it. +It's possible to configure the CLI runner with JSON. In this case, you need to provide an +absolute/relative path to the JSON configuration file. All other configuration options are parsed from it. ```Bash java -jar dokka-cli-%dokkaVersion%.jar dokka-configuration.json ``` -At the very least, you would need the following configuration: +At the very least, you need the following configuration: ```json { "outputDir": "./dokka/html", @@ -107,8 +107,8 @@ At the very least, you would need the following configuration: } ``` -> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`, -> otherwise it can lead to obscure exceptions such as `NoSuchFieldError`. +> Due to an internal class conflict, first pass `kotlin-analysis-intellij` and only then `kotlin-analysis-compiler`. +> Otherwise you may see obscure exceptions, such as `NoSuchFieldError`. > {type="note"} @@ -116,14 +116,14 @@ See [JSON configuration options](#json-configuration) for more details. ### Other output formats -By default, `dokka-base` artifact contains stable [HTML](html.md) format only. +By default, the `dokka-base` artifact contains the [HTML](html.md) output format only. -All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use them, you have to put it -on plugins classpath. +All other output formats come as part of [Dokka plugins](plugins_introduction.md). In order to use them, you have to put them +in the plugins classpath. -For example, if you want to generate documentation in experimental [GFM](markdown.md#gfm) format, you have to download and -pass [gfm-plugin's jar](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into -`pluginsClasspath` configuration option. +For example, if you want to generate documentation in the experimental [GFM](markdown.md#gfm) output format, you need to download and +pass [gfm-plugin's JAR](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into +the `pluginsClasspath` configuration option. Via command line arguments: @@ -147,14 +147,14 @@ Via JSON configuration: } ``` -With GFM plugin on classpath, CLI runner should generate documentation in GFM format, no extra actions -needed. +With the GFM plugin in the `pluginsClasspath`, the CLI runner generates documentation in GFM output format. +No further action is needed. -For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#geneatring-javadoc-documentation) topics. +For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#generating-javadoc-documentation). ## Command line arguments -You can see short descriptions for command line arguments by running: +To see a list of all possible command line arguments for the nested `-sourceSet` configuration, run: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -help @@ -230,8 +230,8 @@ Summary: ## JSON configuration -Below you will find examples and detailed descriptions for each configuration section. You can also find an example -with [all configuration options](#complete-configuration) applied at once at the very bottom. +Below are some examples and detailed descriptions for each configuration section. You can also find an example +with [all configuration options](#complete-configuration) applied. ### General configuration @@ -272,24 +272,24 @@ with [all configuration options](#complete-configuration) applied at once at the -

    Display name used to refer to the module. Used for ToC, navigation, logging, etc.

    -

    Default is root.

    +

    The display name used to refer to the module. Used in the table of contents, navigation, logging, etc.

    +

    Default: root.

    Module version.

    -

    Default is empty.

    +

    Default: empty.

    -

    Directory to which documentation will be generated, regardless of format.

    -

    Default is ./dokka

    +

    The directory to where documentation is generated, regardless of output format.

    +

    Default: ./dokka

    - Whether to fail documentation generation if Dokka has emitted a warning or an error. - Will wait until all errors and warnings have been emitted first. + Whether to fail documentation generation if Dokka emits a warning or an error. + The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented

    -

    Default is false.

    +

    Default: false.

    Whether to suppress obvious functions.

    @@ -306,42 +306,44 @@ with [all configuration options](#complete-configuration) applied at once at the

    -

    Default is true.

    +

    Default: true.

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    - Note: this can suppress functions such as equals / hashCode / toString, + Note: this can suppress functions such as equals / hashCode / +toString, but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default is false.

    +

    Default: false.

    Whether to resolve remote files/links over network.

    - This includes package-lists used for generating external documentation links: - for instance, to make classes from standard library clickable. + This includes package-lists used for generating external documentation links. + For example, to make classes from standard library clickable.

    Setting this to true can significantly speed up build times in certain cases, - but can also worsen documentation quality and user experience, for instance by + but can also worsen documentation quality and user experience. For example, by not resolving some dependency's class/member links.

    Note: you can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks.

    -

    Default is false.

    +

    Default: false.

    - List of Markdown files that contain + A list of Markdown files that contain module and package documentation.

    -

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    -

    Can be configured on per-package basis.

    +

    The contents of specified files are parsed and embedded into documentation as module and package +descriptions.

    +

    This can be configured on per-package basis.

    @@ -351,26 +353,26 @@ with [all configuration options](#complete-configuration) applied at once at the

    For a list of possible options, see source set configuration.

    -

    Global configuration of source links that will be applied for all source sets.

    +

    The global configuration of source links that are applied for all source sets.

    For a list of possible options, see source link configuration.

    -

    Global configuration of matched packages, regardless of the source set they are in.

    +

    The global configuration of matched packages, regardless of the source set they are in.

    For a list of possible options, see per-package configuration.

    -

    Global configuration of external documentation links, regardless of the source set they are used in.

    +

    The global configuration of external documentation links, regardless of the source set they are used in.

    For a list of possible options, see external documentation configuration.

    -

    List of jars with Dokka plugins and their dependencies.

    +

    A list of JAR files with Dokka plugins and their dependencies.

    ### Source set configuration -Configuration of Kotlin -[source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). +How to configure Kotlin +[source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets): ```json { @@ -429,23 +431,23 @@ Configuration of Kotlin -

    Display name used to refer to the source set.

    +

    The display name used to refer to the source set.

    - The name will be used both externally (for example, as source set name visible to documentation readers) and + The name is used both externally (for example, the source set name is visible to documentation readers) and internally (for example, for logging messages of reportUndocumented).

    -

    Platform name could be used if you don't have a better alternative.

    +

    The platform name can be used if you don't have a better alternative.

    -

    Technical ID of the source set

    +

    The technical ID of the source set

    -

    Set of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations, as well as if you want to exclude public declarations and only document internal API.

    -

    Can be configured on per-package basis.

    +

    This can be configured on per-package basis.

    Possible values: @@ -456,15 +458,15 @@ Configuration of Kotlin

  • PACKAGE
  • -

    Default is PUBLIC.

    +

    Default: PUBLIC.

    Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs after they have been filtered by documentedVisibilities.

    -

    This setting works well with failOnWarning. Can be overridden for a specific package

    -

    Default is false.

    +

    This setting works well with failOnWarning. It can be overridden for a specific package

    +

    Default: false.

    @@ -472,34 +474,34 @@ Configuration of Kotlin various filters have been applied.

    - For instance, if skipDeprecated is set to true and your package contains only - deprecated declarations, it will be considered to be empty. + For example, if skipDeprecated is set to true and your package contains only + deprecated declarations, it is considered to be empty.

    Default for CLI runner is false.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be overridden on package level.

    -

    Default is false.

    +

    It can be overridden at package level.

    +

    Default: false.

    -

    JDK version to use when generating external documentation links for Java types.

    +

    The JDK version to use when generating external documentation links for Java types.

    - For instance, if you use java.util.UUID from JDK in some public declaration signature, - and this property is set to 8, Dokka will generate an external documentation link + For example, if you use java.util.UUID from JDK in some public declaration signature, + and this property is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    - Kotlin language version + The Kotlin language version used for setting up analysis and @sample environment.

    - Kotlin API version + The Kotlin API version used for setting up analysis and @sample environment.

    @@ -509,19 +511,21 @@ Configuration of Kotlin Whether to generate external documentation links that lead to API reference documentation for Kotlin's standard library when declarations from it are used.

    -

    Default is false, meaning links will be generated.

    +

    Links are generated when `noStdLibLink` is set to false.

    +

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    +

    Links are generated when `noJdkLink` is set to false.

    The version of JDK Javadocs is determined by jdkVersion property.

    -

    Default is false, meaning links will be generated.

    +

    Default: false.

    - List of Markdown files that contain + A list of Markdown files that contain module and package documentation.

    -

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +

    The contents of the specified files are parsed and embedded into documentation as module and package descriptions.

    @@ -541,51 +545,51 @@ Configuration of Kotlin

    - Source code roots to be analyzed and documented. - Accepts directories and individual .kt / .java files. + The source code roots to be analyzed and documented. + It accepts directories and individual .kt / .java files.

    - Classpath for analysis and interactive samples. If you use a declaration from a dependency, + The classpath for analysis and interactive samples. If you use a declaration from a dependency, it should be present on the classpath to be resolved.

    Property accepts both .jar and .klib files.

    - List of directories or files that contain sample functions which are referenced via + A list of directories or files that contain sample functions which are referenced via @sample KDoc tag.

    -

    Files to be suppressed when generating documentation.

    +

    The files to be suppressed when generating documentation.

    -

    Configuration of source links that will be applied only for this source set.

    +

    A set of parameters for source links that are applied only for this source set.

    For a list of possible options, see source link configuration.

    -

    Configuration specific to matched packages within this source set.

    +

    A set of parameters specific to matched packages within this source set.

    For a list of possible options, see per-package configuration.

    -

    Configuration of external documentation links that will be applied only for this source set.

    +

    A set of parameters for external documentation links that are applied only for this source set.

    For a list of possible options, see external documentation configuration.

    ### Source link configuration -Configuration block that allows adding a `source` link to each signature -which leads to `remoteUrl` with a specific line number (configurable by setting `remoteLineSuffix`), -letting documentation readers find source code for each declaration. +The `sourceLinks` configuration block is where you can add a `source` link to each signature +that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +This helps readers to find the source code for each declaration. -For an example, see documentation for -[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) -function from `kotlinx.coroutines`. +For an example, see the documentation for the +[`count()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function in `kotlinx.coroutines`. -Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) +You can configure source sets together at the same time, or [individually](#source-set-configuration): ```json { @@ -605,20 +609,20 @@ Configurable for all source sets at once, or [for each source set individually](

    - URL of source code hosting service that can be accessed by documentation readers, - like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + The URL of the source code hosting service that can be accessed by documentation readers, + like GitHub, GitLab, Bitbucket, etc. This URL is used to generate source code links of declarations.

    - Suffix used to append source code line number to the URL. This will help readers navigate + The suffix used to append source code line number to the URL. This helps readers navigate not only to the file, but to the specific line number of the declaration.

    - The number itself will be appended to the specified suffix. For instance, - if this property is set to #L and the line number is 10, resulting URL suffix - will be #L10. + The number itself is appended to the specified suffix. For example, + if this property is set to #L and the line number is 10, the resulting URL suffix + is #L10.

    Suffixes used by popular services: @@ -628,15 +632,15 @@ Configurable for all source sets at once, or [for each source set individually](

  • Bitbucket: #lines-
  • -

    Default is empty (no suffix).

    +

    Default: empty (no suffix).

    ### Per-package configuration -Configuration block that allows setting some options for specific packages matched by `matchingRegex`. +The `perPackageOptions` configuration block allows you to set some options for specific packages matched by `matchingRegex`. -Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) +You can configure source sets together at the same time, or [individually](#source-set-configuration): ```json { @@ -654,16 +658,16 @@ Configurable for all source sets at once, or [for each source set individually]( -

    Regular expression that is used to match the package.

    +

    The regular expression that is used to match the package.

    Whether this package should be skipped when generating documentation.

    -

    Default is false.

    +

    Default: false.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be set on project/module level.

    -

    Default is false.

    +

    This can be set on project/module level.

    +

    Default: false.

    @@ -671,31 +675,31 @@ Configurable for all source sets at once, or [for each source set individually]( this package and without KDocs, after they have been filtered by documentedVisibilities.

    This setting works well with failOnWarning.

    -

    Can be configured on source set level.

    -

    Default is false.

    +

    This can be configured on source set level.

    +

    Default: false.

    -

    Set of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations within a specific package, as well as if you want to exclude public declarations and only document internal API.

    Can be configured on source set level.

    -

    Default is PUBLIC.

    +

    Default: PUBLIC.

    ### External documentation configuration -Configuration block that allows creating links leading to externally hosted documentation of your dependencies. +The `externalDocumentationLinks` configuration block allows you to add links that lead to the externally hosted documentation of your dependencies. -For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your -documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is +For example, if you are using types from `kotlinx.serialization`, by default they are unclickable in your +documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it, allowing Dokka to generate links for used types, making them clickable -and appear resolved. +documentation links for it. Thus allowing Dokka to generate links for types, making them clickable +and resolve successfully. -Configurable for all source sets at once, or [for each source set individually](#source-set-configuration) +You can configure source sets together all at once, or [individually](#source-set-configuration): ```json { @@ -710,27 +714,27 @@ Configurable for all source sets at once, or [for each source set individually]( -

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    The root URL of documentation to link with. It **must** contain a trailing slash.

    - Dokka will do its best to automatically find package-list for the given URL, + Dokka does its best to automatically find package-list for the given URL and link declarations together.

    If automatic resolution fails or if you want to use locally cached files instead, - consider providing packageListUrl. + consider providing the packageListUrl.

    - Specifies the exact location of a package-list instead of relying on Dokka - automatically resolving it. Can also be a locally cached file to avoid network calls. + The exact location of a package-list. This is an alternative to relying on Dokka + automatically resolving it. This can also be a locally cached file to avoid network calls.

    ### Complete configuration -Below you can see all possible configuration options applied at once. +Below you can see all the possible configuration options applied at the same time. ```json { diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md index 78b2b75943..9f05e58f1c 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/gradle.md @@ -1,12 +1,12 @@ [//]: # (title: Gradle plugin) -To generate documentation for a Gradle-based project, you can use [Dokka Gradle plugin](#applying-the-plugin). +To generate documentation for a Gradle-based project, you can use the [Dokka Gradle plugin](#applying-the-plugin). It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient [Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of [configuration options](#configuration) to customize output. -You can play around with Dokka and see how it can be configured for various projects by visiting +You can play around with Dokka and see how it can be configured for various projects by visiting our [Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). ## Applying the plugin @@ -35,7 +35,7 @@ plugins {
    -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka in subprojects as well. +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well. You can use `allprojects {}` and `subprojects {}` Gradle configurations to achieve that: @@ -59,17 +59,17 @@ subprojects {
    -> Under the hood, Dokka uses [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform +> Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform > autoconfiguration -> of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for which documentation -> should be generated, so make sure Kotlin Gradle Plugin is applied as well, or +> of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for documentation +> to be generated. Make sure to apply Kotlin Gradle Plugin or > [configure source sets](#source-set-configuration) manually. > {type="note"} > If you are using Dokka in a > [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), -> you will have to add [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) as a dependency in order for +> you need to add the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) as a dependency in order for > it to work properly: > > @@ -91,14 +91,14 @@ subprojects { > {type="note"} -If you cannot use plugins DSL for some reason, you can use +If you cannot use the plugin DSL for some reason, you can use [the legacy method](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application) of applying plugins. ## Generating documentation -Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) formats built in, -and adds a number of tasks for generating documentation, both for [single](#single-project-builds) +Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats built in. +It adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. ### Single project builds @@ -119,13 +119,13 @@ Use the following tasks to build documentation for simple, single project applic | `dokkaJavadoc` | Generates documentation in [Javadoc](javadoc.md) format. | | `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | -By default, you will find generated documentation under `build/dokka/{format}` directory of your project. -Output location, among other things, can be [configured](#configuration) separately. +By default, generated documentation is stored in the `build/dokka/{format}` directory of your project. +The output location, among other things, can be [configured](#configuration) separately. ### Multi-project builds For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), make sure -you apply the Dokka plugin in subprojects that you want to generate documentation for, as well as in their parent project. +that you apply the Dokka plugin within subprojects that you want to generate documentation for, as well as in their parent project. #### MultiModule tasks @@ -137,23 +137,23 @@ Dokka creates the following tasks for **parent** projects automatically: #### Stable formats -| **Task** | **Description** | -|--------------------------|--------------------------------------------------------------------------------------------------| -| `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](html.md) format. | +| **Task** | **Description** | +|--------------------------|------------------------------------------------------------------------| +| `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](html.md) output format. | #### Experimental formats -| **Task** | **Description** | -|--------------------------|--------------------------------------------------------------------------------------------------| -| `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | -| `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | +| **Task** | **Description** | +|--------------------------|---------------------------------------------------------------------------------------------------------| +| `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) output format. | +| `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) output format. | -> [Javadoc](javadoc.md) output format does not have a MultiModule task, but a [Collector](#collector-tasks) task can +> The [Javadoc](javadoc.md) output format does not have a MultiModule task, but a [Collector](#collector-tasks) task can > be used instead. > {type="note"} -By default, you will find ready-to-use documentation under `{parentProject}/build/dokka/{format}MultiModule` directory. +By default, you can find ready-to-use documentation under `{parentProject}/build/dokka/{format}MultiModule` directory. #### MultiModule task example @@ -169,16 +169,17 @@ parentProject ├── ChildProjectBClass ``` -You will see these pages generated after running `dokkaHtmlMultiModule`: +These pages are generated after running `dokkaHtmlMultiModule`: ![Screenshot for output of dokkaHtmlMultiModule task](dokkaHtmlMultiModule-example.png){width=600} -Visit [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +See our [multi-module project example](https://github. +com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) for more details. #### Partial tasks -Each subproject will have _partial_ tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, +Each subproject has _partial_ tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, and `dokkaJekyllPartial`. These tasks are not intended to be used independently and exist only to be called by the parent's @@ -187,20 +188,21 @@ These tasks are not intended to be used independently and exist only to be calle Output generated by partial tasks contains non-displayable formatting along with unresolved templates and references. > If you want to generate documentation for a single subproject only, use -> [single project tasks](#single-project-builds). For instance, `:subproject:dokkaHtml`. +> [single project tasks](#single-project-builds). For example, `:subproject:dokkaHtml`. #### Collector tasks -Similar to MultiModule tasks, _Collector_ tasks will be created for each parent project: `dokkaHtmlCollector`, +Similar to MultiModule tasks, _Collector_ tasks are created for each parent project: `dokkaHtmlCollector`, `dokkaGfmCollector`, `dokkaJavadocCollector` and `dokkaJekyllCollector`. -A Collector task executes corresponding [single project task](#single-project-builds) for each subproject (for example, +A Collector task executes the corresponding [single project task](#single-project-builds) for each subproject (for +example, `dokkaHtml`), and merges all outputs into a single virtual project. -Resulting documentation will look as if you have a single project +The resulting documentation looks as if you have a single project build that contains all declarations from the subprojects. -> Use `dokkaJavadocCollector` task if you need to create Javadoc documentation for your multi-project build. +> Use the `dokkaJavadocCollector` task if you need to create Javadoc documentation for your multi-project build. > {type="tip"} @@ -218,21 +220,21 @@ parentProject ├── ChildProjectBClass ``` -You will see these pages generated after running `dokkaHtmlCollector`: +These pages are generated after running `dokkaHtmlCollector`: ![Screenshot for output of dokkaHtmlCollector task](dokkaHtmlCollector-example.png){width=800} -Visit [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +See our [multi-module project example](https://github. +com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) for more details. ## Building javadoc.jar In order to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API -reference -documentation. +reference documentation. Dokka's Gradle plugin does not provide any way to do this out of the box, but it can be achieved with custom Gradle -tasks, one for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: +tasks. One for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: @@ -272,20 +274,20 @@ tasks.register('dokkaJavadocJar', Jar.class) { > If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to -> host of your library's API documentation for free and without any setup - it will take documentation pages straight -> from the artifact. It works with both HTML and Javadoc formats as demonstrated by +> host your library's API documentation for free and without any setup. It takes documentation pages straight +> from the artifact. It works with both HTML and Javadoc formats as demonstrated in > [this example](https://javadoc.io/doc/com.trib3/server/latest/index.html). > {type="tip"} ## Configuration -You can configure tasks/formats individually: +You can configure tasks and output formats individually: -If you applied Dokka via [plugins DSL](#applying-the-plugin) block: +Applying the Dokka plugin via the [plugins DSL](#applying-the-plugin) block: ```kotlin tasks.dokkaHtml { @@ -322,7 +324,7 @@ dokkaHtmlPartial { -Alternatively, you can configure all tasks/formats at once, including [MultiModule](#multi-project-builds), +Alternatively, you can configure all tasks and output formats at the same time, including [MultiModule](#multi-project-builds), [Partial](#partial-tasks) and [Collector](#collector-tasks) tasks: @@ -351,8 +353,8 @@ tasks.withType().configureEach { } } -// configure partial tasks of all output formats, -// these can have subproject-specific settings +// Configure partial tasks of all output formats. +// These can have subproject-specific settings. tasks.withType(DokkaTaskPartial::class).configureEach { dokkaSourceSets.configureEach { includes.from("README.md") @@ -367,8 +369,8 @@ tasks.withType(DokkaTaskPartial::class).configureEach { import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial -// configure all dokka tasks, including multimodule, -// partial and collector ones +// Configure all Dokka tasks, including multimodule, +// partial and collector tasks tasks.withType(DokkaTask.class) { dokkaSourceSets.configureEach { documentedVisibilities.set([ @@ -383,8 +385,8 @@ tasks.withType(DokkaTask.class) { } } -// configure partial tasks of all output formats, -// these can have subproject-specific settings +// Configure partial tasks of all output formats. +// These can have subproject-specific settings. tasks.withType(DokkaTaskPartial.class) { dokkaSourceSets.configureEach { includes.from("README.md") @@ -399,12 +401,12 @@ tasks.withType(DokkaTaskPartial.class) { Dokka has many configuration options to tailor your and your reader's experience. -Below you will find examples and descriptions for each configuration section. You can also find an example with -[all configuration options](#complete-configuration) applied at once at the very bottom. +Below are some examples and detailed descriptions for each configuration section. You can also find an example +with [all configuration options](#complete-configuration) applied. ### General configuration -General configuration of any Dokka task, regardless of source set and package: +Here is an example of general configuration of any Dokka task, regardless of source set or package: @@ -453,32 +455,32 @@ tasks.withType(DokkaTask.class) { -

    Display name used to refer to the module. Used for ToC, navigation, logging, etc.

    -

    If set for a single-project build or a MultiModule task, will be used as project name.

    -

    Default is Gradle project name.

    +

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    +

    If set for a single-project build or a MultiModule task, it is used as the project name.

    +

    The default is the Gradle project name.

    - Module version. If set for a single-project build or a MultiModule task, will be used as project version + The module version. If set for a single-project build or a MultiModule task, it is used as the project version by the versioning plugin.

    -

    Default is Gradle project version.

    +

    Default: Gradle project version.

    -

    Directory to which documentation will be generated, regardless of format. Can be set on per-task basis.

    +

    The directory where documentation is generated, regardless of format. It can be set on a per-task basis.

    - Default is project/buildDir/format, where format is the task name with - removed "dokka" prefix. For task dokkaHtmlMultiModule it will be - project/buildDir/htmlMultiModule + The default is project/buildDir/format, where format is the task name with + the "dokka" prefix removed. For the dokkaHtmlMultiModule task, it is + project/buildDir/htmlMultiModule.

    Whether to fail documentation generation if Dokka has emitted a warning or an error. - Will wait until all errors and warnings have been emitted first. + The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented

    -

    Default is false.

    +

    Default: false.

    Whether to suppress obvious functions.

    @@ -495,7 +497,7 @@ tasks.withType(DokkaTask.class) {

    -

    Default is true.

    +

    Default: true.

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    @@ -505,30 +507,30 @@ tasks.withType(DokkaTask.class) { dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default is false.

    +

    Default: false.

    -

    Whether to resolve remote files/links over network.

    +

    Whether to resolve remote files/links over your network.

    - This includes package-lists used for generating external documentation links: - for instance, to make classes from standard library clickable. + This includes package-lists used for generating external documentation links. + For example, to make classes from standard library clickable.

    Setting this to true can significantly speed up build times in certain cases, - but can also worsen documentation quality and user experience, for instance by + but can also worsen documentation quality and user experience. For example, by not resolving some dependency's class/member links.

    Note: you can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    -

    Default is false.

    +

    Default: false.

    ### Source set configuration -Configuration of Kotlin [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). +Here is an example of how to configure Kotlin [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). @@ -630,32 +632,32 @@ tasks.withType(DokkaTask.class) {

    Whether this source set should be skipped when generating documentation.

    -

    Default is false.

    +

    Default: false.

    -

    Display name used to refer to the source set.

    +

    The display name used to refer to the source set.

    - The name will be used both externally (for example, as source set name visible to documentation readers) and + The name is used both externally (for example, as source set name visible to documentation readers) and internally (for example, for logging messages of reportUndocumented).

    By default, the value is deduced from information provided by the Kotlin Gradle plugin.

    -

    Set of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations, as well as if you want to exclude public declarations and only document internal API.

    Can be configured on per-package basis.

    -

    Default is DokkaConfiguration.Visibility.PUBLIC.

    +

    Default: DokkaConfiguration.Visibility.PUBLIC.

    Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs after they have been filtered by documentedVisibilities.

    -

    This setting works well with failOnWarning. Can be overridden for a specific package.

    -

    Default is false.

    +

    This setting works well with failOnWarning. It can be overridden for a specific package.

    +

    Default: false.

    @@ -663,106 +665,109 @@ tasks.withType(DokkaTask.class) { various filters have been applied.

    - For instance, if skipDeprecated is set to true and your package contains only - deprecated declarations, it will be considered to be empty. + For example, if skipDeprecated is set to true and your package contains only + deprecated declarations, it is considered to be empty.

    -

    Default is true.

    +

    Default: true.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be overridden on package level.

    -

    Default is false.

    +

    It can be overridden at package level.

    +

    Default: false.

    Whether to document/analyze generated files.

    - Generated files are expected to be present under {project}/{buildDir}/generated directory. - If set to true, it effectively adds all files from that directory to + Generated files are expected to be present under the {project}/{buildDir}/generated directory. + If set to true, it effectively adds all files from that directory to the suppressedFiles option, so you can configure it manually.

    -

    Default is true.

    +

    Default: true.

    -

    JDK version to use when generating external documentation links for Java types.

    +

    The JDK version to use when generating external documentation links for Java types.

    - For instance, if you use java.util.UUID from JDK in some public declaration signature, - and this property is set to 8, Dokka will generate an external documentation link + For example, if you use java.util.UUID from the JDK in some public declaration signature, + and this property is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    -

    Default is JDK 8.

    +

    Default: JDK 8.

    - Kotlin language version + The Kotlin language version used for setting up analysis and @sample environment.

    -

    By default, the latest language version available to Dokka's embedded compiler will be used.

    +

    By default, the latest language version available to Dokka's embedded compiler is used.

    - Kotlin API version + The Kotlin API version used for setting up analysis and @sample environment.

    -

    By default, it will be deduced from languageVersion.

    +

    By default, it is deduced from languageVersion.

    Whether to generate external documentation links that lead to API reference documentation for Kotlin's standard library when declarations from it are used.

    -

    Default is false, meaning links will be generated.

    +

    Links are generated when `noStdLibLink` is set to false.

    +

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    -

    The version of JDK Javadocs is determined by jdkVersion property.

    -

    Default is false, meaning links will be generated.

    +

    The version of JDK Javadocs is determined by the jdkVersion property.

    +

    Links are generated when `noJdkLink` is set to false.

    +

    Default: false.

    Whether to generate external documentation links for Android SDK API reference when declarations from it are used.

    -

    Only relevant in Android projects, ignored otherwise.

    -

    Default is false, meaning links will be generated.

    +

    This is only relevant in Android projects, ignored otherwise.

    +

    Links are generated when `noAndroidSdkLink` is set to false.

    +

    Default: false.

    - List of Markdown files that contain + A list of Markdown files that contain module and package documentation.

    -

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +

    The contents of the specified files are parsed and embedded into documentation as module and package descriptions.

    See Dokka gradle example - for an example of how to use it and what it will look like. + for an example of how to use it and what it looks like.

    - Platform to be used for setting up code analysis and + The platform to be used for setting up code analysis and @sample environment.

    The default value is deduced from information provided by the Kotlin Gradle plugin.

    - Source code roots to be analyzed and documented. - Accepts directories and individual .kt / .java files. + The source code roots to be analyzed and documented. + Acceptable formats are directories and individual .kt / .java files.

    By default, source roots are deduced from information provided by the Kotlin Gradle plugin.

    -

    Classpath for analysis and interactive samples.

    +

    The classpath for analysis and interactive samples.

    - Useful if some types that come from dependencies are not resolved/picked up automatically. - Property accepts both .jar and .klib files. + This iu Useful if some types that come from dependencies are not resolved/picked up automatically. + The property accepts both .jar and .klib files.

    By default, classpath is deduced from information provided by the Kotlin Gradle plugin.

    - List of directories or files that contain sample functions which are referenced via + A list of directories or files that contain sample functions which are referenced via @sample KDoc tag.

    @@ -770,13 +775,13 @@ tasks.withType(DokkaTask.class) { ### Source link configuration -Configuration block that allows adding a `source` link to each signature -which leads to `remoteUrl` with a specific line number (configurable by setting `remoteLineSuffix`), -letting documentation readers find source code for each declaration. +The `sourceLinks` configuration block is where you can add a `source` link to each signature +that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +This helps readers to find the source code for each declaration. -For an example, see documentation for -[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) -function from `kotlinx.coroutines`. +For an example, see the documentation for the +[`count()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function in `kotlinx.coroutines`. @@ -836,26 +841,26 @@ tasks.withType(DokkaTask.class) {

    - Path to the local source directory. The path must be relative to the root of - current project. + The path to the local source directory. The path must be relative to the root of + the current project.

    - URL of source code hosting service that can be accessed by documentation readers, - like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate + The URL of the source code hosting service that can be accessed by documentation readers, + like GitHub, GitLab, Bitbucket, etc. This URL is used to generate source code links of declarations.

    - Suffix used to append source code line number to the URL. This will help readers navigate + The suffix used to append the source code line number to the URL. This helps readers navigate not only to the file, but to the specific line number of the declaration.

    - The number itself will be appended to the specified suffix. For instance, - if this property is set to #L and the line number is 10, resulting URL suffix - will be #L10. + The number itself is appended to the specified suffix. For example, + if this property is set to #L and the line number is 10, the resulting URL suffix + is #L10.

    Suffixes used by popular services: @@ -865,13 +870,13 @@ tasks.withType(DokkaTask.class) {

  • Bitbucket: #lines-
  • -

    Default is #L.

    +

    Default: #L.

    ### Package options -Configuration block that allows setting some options for specific packages matched by `matchingRegex`. +Here is an example of a configuration block that allows setting some options for specific packages matched by `matchingRegex`. @@ -910,12 +915,12 @@ import org.jetbrains.dokka.gradle.DokkaTask tasks.withType(DokkaTask.class) { // .. - // general configuration section + // General configuration section // .. dokkaSourceSets.configureEach { // .. - // source set configuration section + // Source set configuration section // .. perPackageOption { @@ -934,47 +939,47 @@ tasks.withType(DokkaTask.class) { -

    Regular expression that is used to match the package.

    -

    Default is any string: .*.

    +

    The regular expression that is used to match the package.

    +

    Default: any string: .*.

    Whether this package should be skipped when generating documentation.

    -

    Default is false.

    +

    Default: false.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be configured on source set level.

    -

    Default is false.

    +

    This can be configured on source set level.

    +

    Default: false.

    - Whether to emit warnings about visible undocumented declarations, that is declarations from + Whether to emit warnings about visible undocumented declarations. That is declarations from this package and without KDocs, after they have been filtered by documentedVisibilities.

    This setting works well with failOnWarning.

    -

    Can be configured on source set level.

    -

    Default is false.

    +

    This can be configured on source set level.

    +

    Default: false.

    -

    Set of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations within a specific package, as well as if you want to exclude public declarations and only document internal API.

    -

    Can be configured on source set level.

    -

    Default is DokkaConfiguration.Visibility.PUBLIC.

    +

    This can be configured on source set level.

    +

    Default: DokkaConfiguration.Visibility.PUBLIC.

    ### External documentation links configuration -Configuration block that allows creating links leading to externally hosted documentation of your dependencies. +The externalDocumentationLink` block allows the creation of links that lead to the externally hosted documentation of your dependencies. -For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your -documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is -[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it, allowing Dokka to generate links for used types, making them clickable -and appear resolved. +For example, if you are using types from `kotlinx.serialization`, by default they are unclickable in your +documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is +[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external +documentation links for it. Thus allowing Dokka to generate links for types, making them clickable +and resolve successfully. @@ -1035,9 +1040,9 @@ tasks.withType(DokkaTask.class) { -

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    The root URL of documentation to link with. It **must** contain a trailing slash.

    - Dokka will do its best to automatically find package-list for the given URL, + Dokka does its best to automatically find package-list for the given URL, and link declarations together.

    @@ -1048,14 +1053,14 @@ tasks.withType(DokkaTask.class) {

    Specifies the exact location of a package-list instead of relying on Dokka - automatically resolving it. Can also be a locally cached file to avoid network calls. + automatically resolving it. It can also be a locally cached file to avoid network calls.

    ### Complete configuration -Below you can see all possible configuration options applied at once. +Below you can see all possible configuration options applied at the same time. diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index a571090c19..7ba7dcea44 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -1,18 +1,18 @@ [//]: # (title: Maven plugin) -To generate documentation for Maven-based projects, you can use [Dokka Maven plugin](#applying-the-plugin). +To generate documentation for Maven-based projects, you can use the [Dokka Maven plugin](#applying-the-plugin). -> Compared to the [Gradle plugin](gradle.md), Maven plugin has only basic features and +> Compared to the [Gradle plugin](gradle.md), the Maven plugin has only basic features and > does not provide support for multimodule builds out of the box. > {type="note"} You can play around with Dokka and see how it can be configured for a Maven project by visiting -[Maven example](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/maven) project. +our [Maven example](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/maven) project. ## Applying the plugin -To apply the plugin, you need to add it to the plugins section of your POM: +To apply the plugin, you need to add it to the plugins section of your POM file: ```xml @@ -36,7 +36,7 @@ To apply the plugin, you need to add it to the plugins section of your POM: ## Generating documentation -Following goals are provided by the plugin: +The following goals are provided by the plugin: ### Stable @@ -53,13 +53,11 @@ Following goals are provided by the plugin: ### Other output formats -By default, Maven plugin will build documentation in [HTML](html.md) format. +By default, the Maven plugin builds documentation in [HTML](html.md) output format. -All other output formats come as [Dokka plugins](plugins_introduction.md). In order to use it, you have to apply -it as a dependency. +All other output formats come as part of [Dokka plugins](plugins_introduction.md). In order to use them, you have to apply -For example, to use experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in -the following way: +For example, to use the experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in ```xml @@ -78,18 +76,18 @@ the following way: ``` -After that, running `dokka:dokka` goal should produce documentation in GFM format. +With this configuration, running the `dokka:dokka` goal produces documentation in GFM format. -You can learn more about Dokka plugins in [a separate topic](plugins_introduction.md). +To learn more about Dokka plugins, see [Dokka plugins](plugins_introduction.md). ## Building javadoc.jar -Unlike the [Gradle plugin](gradle.md#building-javadoc-jar), Maven plugin comes with ready-to-use `dokka:javadocJar` goal. -By default, it will generate documentation in [Javadoc](javadoc.md) format under `target` folder. +Unlike the [Gradle plugin](gradle.md#building-javadoc-jar), the Maven plugin comes with a ready-to-use `dokka:javadocJar` goal. +By default, it generates documentation in [Javadoc](javadoc.md) output format in the`target` folder. If you are not satisfied with the built-in goal or want to customize the output (for instance, you want to generate -documentation in [HTML](html.md) format instead of Javadoc), similar behaviour can be achieved by adding the -Maven jar plugin with the following configuration: +documentation in [HTML](html.md) format instead of Javadoc), similar behavior can be achieved by adding the +Maven JAR plugin with the following configuration: ```xml @@ -118,7 +116,7 @@ Maven jar plugin with the following configuration: ``` -The documentation and the `.jar` archive for it can then be generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: +The documentation and the `.jar` archive for it is then generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: ```Bash mvn dokka:dokka jar:jar@dokka-jar @@ -128,7 +126,7 @@ mvn dokka:dokka jar:jar@dokka-jar Maven's plugin configuration block can be used to configure Dokka. -Example of basic configuration that only changes output location of documentation: +Here is an example of a basic configuration that only changes the output location of your documentation: ```xml @@ -145,8 +143,8 @@ Example of basic configuration that only changes output location of documentatio Dokka has many configuration options to tailor your experience. -Below you will find examples and descriptions for each configuration section. You can also find an example with -[all configuration options](#complete-configuration) applied at once at the very bottom. +Below are some examples and detailed descriptions for each configuration section. You can also find an example +with [all configuration options](#complete-configuration) applied. ### General configuration @@ -206,23 +204,23 @@ Below you will find examples and descriptions for each configuration section. Yo

    Whether to skip documentation generation.

    -

    Default is false.

    +

    Default: false.

    -

    Display name used to refer to the project/module. Used for ToC, navigation, logging, etc.

    -

    Default is {project.artifactId}.

    +

    The display name used to refer to the project/module. It's used for the table of contents, navigation, logging, etc.

    +

    Default: {project.artifactId}.

    -

    Directory to which documentation will be generated.

    -

    Default is {project.basedir}/target/dokka.

    +

    The directory where documentation is generated.

    +

    Default: {project.basedir}/target/dokka.

    - Whether to fail documentation generation if Dokka has emitted a warning or an error. Will wait until + Whether to fail documentation generation if Dokka has emitted a warning or an error. The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented.

    -

    Default is false.

    +

    Default: false.

    Whether to suppress obvious functions.

    @@ -239,7 +237,7 @@ Below you will find examples and descriptions for each configuration section. Yo

    -

    Default is true

    +

    Default: true

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    @@ -248,7 +246,7 @@ Below you will find examples and descriptions for each configuration section. Yo but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default is false.

    +

    Default: false.

    Whether to resolve remote files/links over network.

    @@ -258,30 +256,30 @@ Below you will find examples and descriptions for each configuration section. Yo

    Setting this to true can significantly speed up build times in certain cases, - but can also worsen documentation quality and user experience, for instance by + but can also worsen documentation quality and user experience, for example by not resolving some dependency's class/member links.

    When using offline mode, you can cache fetched files locally and provide them to Dokka as local paths, see externalDocumentationLinks section.

    -

    Default is false.

    +

    Default: false.

    - Source code roots to be analyzed and documented. - Accepts directories and individual .kt / .java files. + The source code roots to be analyzed and documented. + Acceptable inputs are directories and individual .kt / .java files.

    -

    Default is {project.compileSourceRoots}.

    +

    Default: {project.compileSourceRoots}.

    -

    Set of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations, as well as if you want to exclude public declarations and only document internal API.

    Can be configured on per-package basis.

    -

    Default is PUBLIC.

    +

    Default: PUBLIC.

    @@ -289,82 +287,84 @@ Below you will find examples and descriptions for each configuration section. Yo after they have been filtered by documentedVisibilities.

    This setting works well with failOnWarning.

    -

    Can be overridden on package level.

    -

    Default is false.

    +

    This can be overridden at package level.

    +

    Default: false.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be overridden on package level.

    -

    Default is false.

    +

    This can be overridden at package level.

    +

    Default: false.

    Whether to skip packages that contain no visible declarations after various filters have been applied.

    - For instance, if skipDeprecated is set to true and your package contains only - deprecated declarations, it will be considered to be empty.

    -

    Default is true.

    + For example, if skipDeprecated is set to true and your package contains only + deprecated declarations, it is considered empty.

    +

    Default: true.

    - Directories or individual files that should be suppressed, meaning declarations from them - will be not documented. + The directories or individual files that should be suppressed, meaning that declarations from them + are not documented.

    -

    JDK version to use when generating external documentation links for Java types.

    +

    The JDK version to use when generating external documentation links for Java types.

    - For instance, if you use java.util.UUID from JDK in some public declaration signature, - and this property is set to 8, Dokka will generate an external documentation link + For example, if you use java.util.UUID from JDK in some public declaration signature, + and this property is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    -

    Default is JDK 8.

    +

    Default: JDK 8.

    - Kotlin language version + The Kotlin language version used for setting up analysis and @sample environment.

    -

    By default, the latest language version available to Dokka's embedded compiler will be used.

    +

    By default, the latest language version available to Dokka's embedded compiler is used.

    - Kotlin API version + The Kotlin API version used for setting up analysis and @sample environment.

    -

    By default, it will be deduced from languageVersion.

    +

    By default, it is deduced from languageVersion.

    Whether to generate external documentation links that lead to API reference documentation for Kotlin's standard library when declarations from it are used.

    -

    Default is false, meaning links will be generated.

    +

    Links are generated when `noStdLibLink` is set to false.

    +

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    The version of JDK Javadocs is determined by jdkVersion property.

    -

    Default is false, meaning links will be generated.

    +

    Links are generated when `noJdkLink` is set to false.

    +

    Default: false

    - List of Markdown files that contain + A list of Markdown files that contain module and package documentation

    -

    Contents of specified files will be parsed and embedded into documentation as module and package descriptions.

    +

    The contents of specified files are parsed and embedded into documentation as module and package descriptions.

    -

    Classpath for analysis and interactive samples.

    +

    The classpath for analysis and interactive samples.

    - Useful if some types that come from dependencies are not resolved/picked up automatically. - Property accepts both .jar and .klib files. + This is useful if some types that come from dependencies are not resolved/picked up automatically. + The property accepts both .jar and .klib files.

    -

    Default is {project.compileClasspathElements}.

    +

    Default: {project.compileClasspathElements}.

    - List of directories or files that contain sample functions which are referenced via + A list of directories or files that contain sample functions which are referenced via @sample KDoc tag.

    @@ -372,9 +372,9 @@ Below you will find examples and descriptions for each configuration section. Yo ### Source link configuration -Configuration block that allows adding a `source` link to each signature which leads to `path` with a specific line -number (configurable by setting `lineSuffix`), letting documentation readers find source code for each -declaration. +The `sourceLinks` configuration block is where you can add a `source` link to each signature +that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +This helps readers to find the source code for each declaration. For an example, see documentation for [count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) @@ -400,24 +400,24 @@ function from `kotlinx.coroutines`.

    - Path to the local source directory. The path must be relative to the root of + The path to the local source directory. The path must be relative to the root of the current module.

    - URL of source code hosting service that can be accessed by documentation readers, like GitHub, GitLab, - Bitbucket, etc. This URL will be used to generate source code links of declarations. + The URL of the source code hosting service that can be accessed by documentation readers, like GitHub, GitLab, + Bitbucket, etc. This URL is used to generate source code links of declarations.

    - Suffix used to append source code line number to the URL. This will help readers navigate not only + The suffix used to append source code line number to the URL. This helps readers navigate not only to the file, but to the specific line number of the declaration.

    - The number itself will be appended to the specified suffix. For instance, if this property is set - to #L and the line number is 10, resulting URL suffix will be #L10. + The number itself is appended to the specified suffix. For example, if this property is set + to #L and the line number is 10, the resulting URL suffix is #L10.

    Suffixes used by popular services: @@ -432,13 +432,13 @@ function from `kotlinx.coroutines`. #### External documentation links configuration -Configuration block that allows creating links leading to externally hosted documentation of your dependencies. +The `externalDocumentationLinks` block allows the creation of links that lead to the externally hosted documentation of your dependencies. -For instance, if you are using types from `kotlinx.serialization`, by default they will be unclickable in your -documentation, as if unresolved. However, since API reference for `kotlinx.serialization` is also built by Dokka and is +For example, if you are using types from `kotlinx.serialization`, by default they are be unclickable in your +documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it, allowing Dokka to generate links for used types, making them clickable -and appear resolved. +documentation links for it. Thus allowing Dokka to generate links for types, making them clickable +and resolve successfully. ```xml @@ -458,27 +458,27 @@ and appear resolved. -

    Root URL of documentation to link with. Must contain a trailing slash.

    +

    The root URL of documentation to link with. It **must** contain a trailing slash.

    - Dokka will do its best to automatically find package-list for the given URL, + Dokka does its best to automatically find the package-list for the given URL and link declarations together.

    - It automatic resolution fails or if you want to use locally cached files instead, - consider providing packageListUrl. + If automatic resolution fails or if you want to use locally cached files instead, + consider providing the packageListUrl.

    - Specifies the exact location of a package-list instead of relying on Dokka - automatically resolving it. Can also be a locally cached file to avoid network calls. + The exact location of a package-list. This is an alternative to relying on Dokka + automatically resolving it. This can also be a locally cached file to avoid network calls.

    ### Package options -Configuration block that allows setting some options for specific packages matched by `matchingRegex`. +The `packageOptions` configuration block allows you to set some options for specific packages matched by `matchingRegex`. ```xml @@ -507,25 +507,25 @@ Configuration block that allows setting some options for specific packages match -

    Regular expression that is used to match the package.

    -

    Default is any string: .*.

    +

    The regular expression that is used to match the package.

    +

    Default: any string: .*.

    Whether this package should be skipped when generating documentation.

    -

    Default is false.

    +

    Default: false.

    -

    List of visibility modifiers that should be documented.

    +

    A list of visibility modifiers that should be documented.

    This can be used if you want to document protected/internal/private declarations within a specific package, as well as if you want to exclude public declarations and only document internal API.

    -

    Default is PUBLIC.

    +

    Default: PUBLIC.

    Whether to document declarations annotated with @Deprecated.

    -

    Can be set on project/module level.

    -

    Default is false.

    +

    This can be set on project/module level.

    +

    Default: false.

    @@ -533,13 +533,13 @@ Configuration block that allows setting some options for specific packages match this package and without KDocs, after they have been filtered by documentedVisibilities.

    This setting works well with failOnWarning.

    -

    Default is false.

    +

    Default: false.

    ### Complete configuration -Below you can see all possible configuration options applied at once. +Below you can see all the possible configuration options applied at the same time. ```xml From 2c17ae0e0af4106df89411fefd3c85904684d1c7 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Thu, 22 Dec 2022 05:57:51 +0100 Subject: [PATCH 07/14] Fix review comments and proofread documentation once more --- CONTRIBUTING.md | 2 +- docs/README.md | 95 +---- docs/dokka.tree | 8 +- ...ugins_introduction.md => dokka_plugins.md} | 26 +- docs/topics/formats/html.md | 45 +-- docs/topics/formats/javadoc.md | 18 +- docs/topics/formats/markdown.md | 26 +- docs/topics/get_started.md | 95 +++++ docs/topics/overview.md | 98 +----- docs/topics/plugins/versioning.md | 327 ------------------ docs/topics/runners/cli.md | 200 ++++++----- docs/topics/runners/gradle.md | 271 ++++++++------- docs/topics/runners/maven.md | 168 +++++---- examples/maven/pom.xml | 2 +- .../dokka/gradle/GradleSourceLinkBuilder.kt | 4 +- .../src/main/kotlin/SourceLinkMapItem.kt | 8 +- 16 files changed, 528 insertions(+), 865 deletions(-) rename docs/topics/{plugins/plugins_introduction.md => dokka_plugins.md} (88%) create mode 100644 docs/topics/get_started.md delete mode 100644 docs/topics/plugins/versioning.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92bc91051f..ca58ff4de0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Here's how to import and configure Dokka in IntelliJ IDEA: If you want to use/test your locally built Dokka in a project, do the following: 1. Change `dokka_version` in `gradle.properties` to something that you will use later on as the dependency version. - For instance, you can set it to something like `1.7.20-my-fix-SNAPSHOT`. + For example, you can set it to something like `1.7.20-my-fix-SNAPSHOT`. 2. Publish it to maven local (`./gradlew publishToMavenLocal`) 3. In the project you want to generate documentation for, add maven local as a plugin/dependency repository (`mavenLocal()`) diff --git a/docs/README.md b/docs/README.md index 0683b80748..686c95bd30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,95 +2,8 @@ This folder contains the Dokka documentation that is available on [kotlinlang.org](https://kotlinlang.org/). -Our documentation is written in Markdown format with some domain specific language (DSL) that is used at JetBrains. +Our documentation is written in Markdown format with some domain specific language (DSL) constructs that are used at +JetBrains. -## Project structure - -This project contains: -* A `topics` directory, which contains our documentation in Markdown format. -* A `dokka.tree` file, that describes the site navigation structure. -* A `vars.list` file, that contains a list of variables that you can use throughout documentation. - -## DSL guide - -This section explains what DSL you can use to create different document elements. - -### Title - -To declare the title of your document: - -```text -[//]: # (title: Name of topic) -``` - -Every document must have a title. By default, this title is used in the side menu. - -As the title is a level 1 header, it must be the only level 1 header in your document. All other headers within your document must be at least level 2, otherwise the side menu may not work as expected. - -### Notes - -To add a note: - -```text -> This is a simple note -> -{type="note"} -``` - -### Tips - -To add a tip: - -```text -> This is a useful tip -> -{type="tip"} -``` - -### Warning - -To add a warning: - -```text -> This is a warning -> -{type="warning"} -``` - -### Tabs - -Tabs can be used to save space in your document, allowing you to show different text in the same space depending on the tab chosen. - -Content within tabs isn't limited to text. You can also add code blocks, tips, etc. - -```text - - - -Instructions specific to Kotlin - - - -Instructions specific to Groovy - - - -Instructions specific to Maven - - - -Instructions specific to CLI - - - -``` - -You can use the `group-key` parameter to link tabs in a document together. Grouping tabs like this means that if your reader selects a particular tab, e.g. "Groovy", then other tabbed sections in your document will also show the tab for "Groovy" first. - -## Documentation preview - -Unfortunately, at the moment, to properly preview documentation you need to be a JetBrains employee -or have access to internal infrastructure. - -If you do have access, download `Stardust` plugin (ask around for instructions), and on the right sidebar you'll see -`Stardust Article Preview` tab, open it. +If you wish to contribute to the documentation, please read through +[Kotlin documentation guidelines](https://docs.google.com/document/d/1mUuxK4xwzs3jtDGoJ5_zwYLaSEl13g_SuhODdFuh2Dc/edit). diff --git a/docs/dokka.tree b/docs/dokka.tree index eb1da12d24..db1a933e9a 100644 --- a/docs/dokka.tree +++ b/docs/dokka.tree @@ -7,7 +7,8 @@ start-page="quickstart.md"> - + + @@ -17,8 +18,5 @@ - - - - + diff --git a/docs/topics/plugins/plugins_introduction.md b/docs/topics/dokka_plugins.md similarity index 88% rename from docs/topics/plugins/plugins_introduction.md rename to docs/topics/dokka_plugins.md index bee4c02729..06dbcdf03c 100644 --- a/docs/topics/plugins/plugins_introduction.md +++ b/docs/topics/dokka_plugins.md @@ -30,7 +30,7 @@ to your project: -The Gradle plugin creates convenient dependency configurations that allow you to apply plugins universally or +The Dokka Gradle runner creates convenient dependency configurations that allow you to apply plugins universally or for a specific output format only. ```kotlin @@ -54,7 +54,7 @@ dependencies { -The Gradle plugin creates convenient dependency configurations that allow you to apply Dokka plugins universally or +The Dokka Gradle runner creates convenient dependency configurations that allow you to apply Dokka plugins universally or for a specific output format only. ```groovy @@ -98,7 +98,7 @@ dependencies { -If you are using the [CLI](cli.md) runner with [command line arguments](cli.md#running-with-command-line-arguments), +If you are using the [CLI](cli.md) runner with [command line options](cli.md#running-with-command-line-options), Dokka plugins should be passed as `.jar` files to `-pluginsClasspath`: ```Shell @@ -127,18 +127,18 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), D ## Configuring Dokka plugins -Dokka plugins can also have configuration options of their own. Consult each plugin's documentation to see which -options are available. +Dokka plugins can also have configuration options of their own. To see which options are available, consult +documentation of the plugin you want to configure. Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](html.md) -documentation, by adding a custom image to assets (`customAssets` option), by adding custom style sheets +documentation, by adding a custom image to the assets (`customAssets` option), by adding custom style sheets (`customStyleSheets` option), and by modifying the footer message (`footerMessage` option): -Gradle's Kotlin DSL allows for type-safe plugin configuration. This is achievable by adding plugin's artifact to classpath -dependencies in the `buildscript` block, and then importing plugin and configuration classes: +Gradle's Kotlin DSL allows for type-safe plugin configuration. This is achievable by adding the plugin's artifact to +the classpath dependencies in the `buildscript` block, and then importing plugin and configuration classes: ```kotlin import org.jetbrains.dokka.base.DokkaBase @@ -232,8 +232,8 @@ tasks.withType(DokkaTask.class) { -If you are using the [CLI](cli.md) runner with [command line arguments](cli.md#running-with-command-line-arguments), -use the `-pluginsConfiguration` argument that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. +If you are using the [CLI](cli.md) runner with [command line options](cli.md#running-with-command-line-options), +use the `-pluginsConfiguration` option that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. If you need to configure multiple plugins, you can pass multiple values separated by `^^`. @@ -244,7 +244,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ ``` If you are using [JSON configuration](cli.md#running-with-json-configuration), there exists a similar -`pluginsConfiguration` array that accepts JSON as `values`. +`pluginsConfiguration` array that accepts JSON configuration in `values`. ```json { @@ -264,12 +264,10 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), t ## Notable plugins -For a list of popular Dokka plugins, see the table below. - | **Name** | **Description** | |-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | [Android documentation plugin](https://github.com/Kotlin/dokka/tree/master/plugins/android-documentation) | Improves the documentation experience on Android | -| [Versioning plugin](versioning.md) | Adds version selector and helps to organize documentation for different versions of your application/library | +| [Versioning plugin](https://github.com/Kotlin/dokka/tree/master/plugins/versioning) | Adds version selector and helps to organize documentation for different versions of your application/library | | [MermaidJS HTML plugin](https://github.com/glureau/dokka-mermaid) | Renders [MermaidJS](https://mermaid-js.github.io/mermaid/#/) diagrams and visualizations found in KDocs | | [Mathjax HTML plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) | Pretty prints mathematics found in KDocs | | [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index 4b1e1d8a26..f4fbdb2c9d 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -10,7 +10,7 @@ HTML as an output format is supported by all runners. To generate HTML documenta * For [Maven](maven.md#generating-documentation), run the `dokka:dokka` goal. * For [CLI runner](cli.md#generating-documentation), run with HTML dependencies set. -> HTML pages generated by this format require a web server in order to render everything correctly. +> HTML pages generated by this format need to be hosted on a web server in order to render everything correctly. > > You can use any free static site hosting service, such as > [GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages). @@ -133,7 +133,7 @@ tasks.withType(DokkaTask.class) { -Via [command line arguments](cli.md#running-with-command-line-arguments): +Via [command line options](cli.md#running-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -164,16 +164,16 @@ Via [JSON configuration](cli.md#running-with-json-configuration): The table below contains all of the possible configuration options and their purpose. -| **Option** | **Description** | -|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `customAssets` | List of paths for image assets to be bundled with documentation. The image assets can have any file extension. For more information, see [Customizing assets](#customizing-assets). | -| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. For more information, see [Customizing styles](#customizing-styles). | -| `templatesDir` | Path to the directory containing custom HTML templates. For more information, see [Templates](#templates). | -| `footerMessage` | The text displayed in the footer. | -| `separateInheritedMembers` | This is a boolean property. If set to `true`, Dokka renders properties/functions and inherited properties/inherited functions separately. This is disabled by default. | -| `mergeImplicitExpectActualDeclarations` | This is a boolean property. If set to true, Dokka merges declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. This can be useful for legacy codebases. This is disabled by default. | +| **Option** | **Description** | +|-----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `customAssets` | List of paths for image assets to be bundled with documentation. The image assets can have any file extension. For more information, see [Customizing assets](#customizing-assets). | +| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. For more information, see [Customizing styles](#customizing-styles). | +| `templatesDir` | Path to the directory containing custom HTML templates. For more information, see [Templates](#templates). | +| `footerMessage` | The text displayed in the footer. | +| `separateInheritedMembers` | This is a boolean option. If set to `true`, Dokka renders properties/functions and inherited properties/inherited functions separately. This is disabled by default. | +| `mergeImplicitExpectActualDeclarations` | This is a boolean option. If set to `true`, Dokka merges declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. This can be useful for legacy codebases. This is disabled by default. | -For more information about configuring Dokka plugins, see [Configuring Dokka plugins](plugins_introduction.md#configuring-dokka-plugins). +For more information about configuring Dokka plugins, see [Configuring Dokka plugins](dokka_plugins.md#configuring-dokka-plugins). ## Customization @@ -184,7 +184,7 @@ To help you add your own look and feel to your documentation, the HTML format su You can use your own stylesheets by using the `customStyleSheets` [configuration option](#configuration). These are applied to every page. -It's also possible to override Dokka's stylesheets by using files with the same name: +It's also possible to override Dokka's default stylesheets by providing files with the same name: | **Stylesheet name** | **Description** | |----------------------|--------------------------------------------------------------------| @@ -199,9 +199,11 @@ The source code for all of Dokka's stylesheets is ### Customizing assets You can provide your own images to be bundled with documentation by using the `customAssets` -[configuration option](#configuration). These files are copied to the `/images` directory. +[configuration option](#configuration). -It's possible to override Dokka's images and icons by using files with the same name. The most +These files are copied to the `/images` directory. + +It's possible to override Dokka's images and icons by providing files with the same name. The most useful and relevant one being `logo-icon.svg`, which is the image that's used in the header. The rest is mostly icons. You can find all images used by Dokka on @@ -209,10 +211,11 @@ You can find all images used by Dokka on ### Changing the logo -To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. For the best results, use an image of a similar size. +To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. +If your image has similar size, it should not look out of place. However, if your image has different dimensions or you want to use a `.png` file instead of the default `.svg` file, -you can [override the `logo-styles.css` stylesheet](#customizing-styles) to make it fit. +you can [override the `logo-styles.css` stylesheet](#customizing-styles) and make it fit. For an example of how to do this, see our [custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). @@ -270,9 +273,9 @@ context and thus they need to be resolved at later stages by the [MultiModule](g You can also use the following Dokka-defined [directives](https://freemarker.apache.org/docs/ref_directive_userDefined.html): -| **Variable** | **Description** | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------| -| `<@content/>` | The main page content. | -| `<@resources/>` | Resources such as scripts and stylesheets. | -| `<@version/>` | The module version taken from configuration. If the [versioning plugin](versioning.md) is applied, it is replaced with a version navigator. | +| **Variable** | **Description** | +|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `<@content/>` | The main page content. | +| `<@resources/>` | Resources such as scripts and stylesheets. | +| `<@version/>` | The module version taken from configuration. If the [versioning plugin](https://github.com/Kotlin/dokka/tree/master/plugins/versioning) is applied, it is replaced with a version navigator. | diff --git a/docs/topics/formats/javadoc.md b/docs/topics/formats/javadoc.md index d85cb680ab..a5e6116d5d 100644 --- a/docs/topics/formats/javadoc.md +++ b/docs/topics/formats/javadoc.md @@ -5,7 +5,7 @@ > {type="warning"} -Dokka's Javadoc output format is similar to Java's +Dokka's Javadoc output format is a lookalike of Java's [Javadoc HTML format](https://docs.oracle.com/en/java/javase/19/docs/api/index.html). It tries to visually mimic HTML pages generated by the Javadoc tool, but it's not a direct implementation @@ -14,15 +14,15 @@ or an exact copy. ![Screenshot of javadoc output format](javadoc-format-example.png){height=750} All Kotlin code and signatures are rendered as seen from Java's perspective. This is achieved with our -[Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and +[Kotlin as Java Dokka plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and applied by default for this format. -The Javadoc output format is generated by our [Dokka plugin](plugins_introduction.md), which we actively maintain. +The Javadoc output format itself is a [Dokka plugin](dokka_plugins.md), and it is maintained by the Dokka team. It is open source and you can find the source code on [GitHub](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). ## Generating Javadoc documentation -> The Javadoc format is not supported for multiplatform projects. +> The Javadoc format does not support multiplatform projects. > {type="warning"} @@ -30,7 +30,7 @@ It is open source and you can find the source code on [GitHub](https://github.co -Dokka's [Gradle plugin](gradle.md) comes with the Javadoc output format included. You can use the following tasks: +Dokka's [Gradle runner](gradle.md) comes with the Javadoc output format included. You can use the following tasks: | **Task** | **Description** | |-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -42,7 +42,7 @@ The `javadoc.jar` file can be generated separately. For more information, see [B -Dokka's [Maven plugin](maven.md) comes with the Javadoc output format built in. You can generate documentation +Dokka's [Maven runner](maven.md) comes with the Javadoc output format built in. You can generate documentation by using the following goals: | **Goal** | **Description** | @@ -54,15 +54,15 @@ by using the following goals: -Since the Javadoc output format is generated by a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the plugin as a -[JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). +Since the Javadoc output format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to +download the plugin's [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). The Javadoc output format has two dependencies that you need to provide as additional JAR files: * [kotlin-as-java plugin](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-as-java-plugin/%dokkaVersion%) * [korte-jvm](https://mvnrepository.com/artifact/com.soywiz.korlibs.korte/korte-jvm/3.3.0) -Via [command line arguments](cli.md#running-with-command-line-arguments): +Via [command line options](cli.md#running-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/markdown.md index 690cfbb156..fb7ed094ca 100644 --- a/docs/topics/formats/markdown.md +++ b/docs/topics/formats/markdown.md @@ -10,7 +10,7 @@ These formats give you more freedom in terms of hosting documentation as the out documentation website. For example, see [OkHttp's API reference](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) pages. -Markdown output formats are rendering [Dokka plugins](plugins_introduction.md), maintained by the Dokka team, and +Markdown output formats are rendering [Dokka plugins](dokka_plugins.md), maintained by the Dokka team, and they are open source. ## GFM @@ -20,7 +20,7 @@ The GFM output format generates documentation in [GitHub Flavored Markdown](http -Dokka's [Gradle plugin](gradle.md) comes with the GFM output format included. You can use the following tasks with it: +Dokka's [Gradle runner](gradle.md) comes with the GFM output format included. You can use the following tasks with it: | **Task** | **Description** | |-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -31,7 +31,7 @@ Dokka's [Gradle plugin](gradle.md) comes with the GFM output format included. Yo -Since GFM format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to apply it as a plugin +Since GFM format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -58,11 +58,11 @@ For more information, see the Mavin plugin documentation for [Other output forma -Since GFM format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the -[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) and pass it to +Since GFM format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +[JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) and pass it to `pluginsClasspath`. -Via [command line arguments](cli.md#running-with-command-line-arguments): +Via [command line options](cli.md#running-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -98,7 +98,7 @@ The Jekyll output format generates documentation in [Jekyll](https://jekyllrb.co -Dokka's [Gradle plugin](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: +Dokka's [Gradle runner](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: | **Task** | **Description** | |--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -109,7 +109,7 @@ Dokka's [Gradle plugin](gradle.md) comes with the Jekyll output format included. -Since Jekyll format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to apply it as a plugin +Since Jekyll format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -131,17 +131,17 @@ dependency: After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see the Maven plugin documentation for [Other output formats](maven.md#other-output-formats). +For more information, see the Maven runner documentation for [Other output formats](maven.md#other-output-formats). -Since Jekyll format is a [Dokka plugin](plugins_introduction.md#applying-dokka-plugins), you need to download the -[jar file](https://mvnrepository.com/artifact/org.jetbrains.dokka/jekyll-plugin/%dokkaVersion%). This format is also -based on [GFM](#gfm) format, so you need to provide it as a dependency as well. Both jars need to be passed to +Since Jekyll format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +[JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/jekyll-plugin/%dokkaVersion%). This format is also +based on [GFM](#gfm) format, so you need to provide it as a dependency as well. Both JARs need to be passed to `pluginsClasspath`: -Via [command line arguments](cli.md#running-with-command-line-arguments): +Via [command line options](cli.md#running-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ diff --git a/docs/topics/get_started.md b/docs/topics/get_started.md new file mode 100644 index 0000000000..1eb743a5d0 --- /dev/null +++ b/docs/topics/get_started.md @@ -0,0 +1,95 @@ +[//]: # (title: Get started) + +TODO add an introduction of some sort? + + + + +Apply the Dokka Gradle plugin in the root build script of your project: + +```kotlin +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} +``` + +When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need +to apply the Dokka Gradle plugin within subprojects as well: + +```kotlin +subprojects { + apply(plugin = "org.jetbrains.dokka") +} +``` + +To generate documentation, run the following Gradle tasks: + +* `dokkaHtml` for single-project builds +* `dokkaHtmlMultiModule` for multi-project builds + +By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. + +To learn more about Gradle configuration, see [Gradle](gradle.md). + + + + +Apply the Dokka Gradle plugin in the root build script of your project: + +```groovy +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} +``` + +When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need +to apply the Dokka Gradle plugin within subprojects as well: + +```groovy +subprojects { + apply plugin: 'org.jetbrains.dokka' +} +``` + +To generate documentation, run the following Gradle tasks: + +* `dokkaHtml` for single-project builds +* `dokkaHtmlMultiModule` for multi-project builds + +By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. + +To learn more about Gradle configuration, see [Gradle](gradle.md). + + + + +Add the Dokka Maven plugin to the `plugins` section of your POM file: + +```xml + + + + org.jetbrains.dokka + dokka-maven-plugin + %dokkaVersion% + + + pre-site + + dokka + + + + + + +``` + +To generate documentation, run the `dokka:dokka` goal. + +By default, the output directory is set to `target/dokka`. + +To learn more about Maven configuration, see [Maven](maven.md). + + + diff --git a/docs/topics/overview.md b/docs/topics/overview.md index 8321fe2028..d52a636e92 100644 --- a/docs/topics/overview.md +++ b/docs/topics/overview.md @@ -9,7 +9,7 @@ Just like Kotlin itself, Dokka supports mixed-language projects. It understands Dokka can generate documentation in multiple formats, including its own modern [HTML format](html.md), multiple flavors of [Markdown](markdown.md), and Java's [Javadoc HTML](javadoc.md). -There are already a number of libraries that use Dokka for their API reference documentation: +Some libraries that use Dokka for their API reference documentation: * [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/) * [Bitmovin](https://cdn.bitmovin.com/player/android/3/docs/index.html) @@ -17,100 +17,8 @@ There are already a number of libraries that use Dokka for their API reference d * [Ktor](https://api.ktor.io/) * [OkHttp](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) (Markdown) -Dokka can be run via [Gradle](gradle.md), [Maven](maven.md) or on the [command line](cli.md). It is also -[highly pluggable](plugins_introduction.md). - -## Quickstart - - - - -Apply the Dokka Gradle plugin in the root of your project: - -```kotlin -plugins { - id("org.jetbrains.dokka") version "%dokkaVersion%" -} -``` - -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well: - -```kotlin -subprojects { - apply(plugin = "org.jetbrains.dokka") -} -``` - -To generate documentation, run the following Gradle tasks: - -* `dokkaHtml` for single-project builds -* `dokkaHtmlMultiModule` for multi-module builds - -By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. - -To learn more about Gradle configuration, see [Gradle](gradle.md). - - - - -Apply the Dokka Gradle plugin in the root of your project: - -```groovy -plugins { - id 'org.jetbrains.dokka' version '%dokkaVersion%' -} -``` - -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well: - -```groovy -subprojects { - apply plugin: 'org.jetbrains.dokka' -} -``` - -To generate documentation, run the following Gradle tasks: - -* `dokkaHtml` for single-project builds -* `dokkaHtmlMultiModule` for multi-module builds - -By default, output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. - -To learn more about Gradle configuration, see [Gradle](gradle.md). - - - - -Add the Dokka Maven plugin to the plugins section of your POM file: - -```xml - - - - org.jetbrains.dokka - dokka-maven-plugin - %dokkaVersion% - - - pre-site - - dokka - - - - - - -``` - -To generate documentation, run the `dokka:dokka` goal. - -By default, the output directory is set to `target/dokka`. - -To learn more about Maven configuration, see [Maven](maven.md). - - - +You can run Dokka using [Gradle](gradle.md), [Maven](maven.md) or from the [command line](cli.md). It is also +[highly pluggable](dokka_plugins.md). ## Community diff --git a/docs/topics/plugins/versioning.md b/docs/topics/plugins/versioning.md deleted file mode 100644 index f0d4be0a7d..0000000000 --- a/docs/topics/plugins/versioning.md +++ /dev/null @@ -1,327 +0,0 @@ -[//]: # (title: Versioning plugin) - -The versioning plugin provides the ability to host documentation for multiple versions of your library/application -with seamless switching between them. This, in turn, provides a better experience for your users. - -![Screenshot of documentation version dropdown](versioning-plugin-example.png){height=350} - -> The versioning plugin only works with [HTML](html.md) format. -> -{type="note"} - -Visit the [versioning plugin example project](https://github.com/Kotlin/dokka/tree/1.7.20/examples/gradle/dokka-versioning-multimodule-example) -to see an example of it in action and how it can be configured. - -## Applying the plugin - -You can apply the versioning plugin the same way as other [Dokka plugins](plugins_introduction.md#applying-dokka-plugins): - - - - -```kotlin -dependencies { - dokkaHtmlPlugin("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") -} -``` - -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the versioning plugin within -> subprojects as well as in their parent project. -> -{type="note"} - - - - -```groovy -dependencies { - dokkaHtmlPlugin 'org.jetbrains.dokka:versioning-plugin:%dokkaVersion%' -} -``` - -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the versioning plugin within -> subprojects as well as in their parent project. -> -{type="note"} - - - - -```xml - - org.jetbrains.dokka - dokka-maven-plugin - ... - - - - org.jetbrains.dokka - versioning-plugin - %dokkaVersion% - - - - -``` - - - - -You can find the versioning plugin's artifact on -[mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/versioning-plugin/%dokkaVersion%) or by browsing -[maven central repository](https://repo1.maven.org/maven2/org/jetbrains/dokka/versioning-plugin/%dokkaVersion%/) -directly, and pass it to `pluginsClasspath`. - -Via [command line arguments](cli.md#running-with-command-line-arguments): - -```Bash -java -jar dokka-cli-%dokkaVersion%.jar \ - -pluginsClasspath "./dokka-base-%dokkaVersion%.jar;...;./versioning-plugin-%dokkaVersion%.jar" \ - ... -``` - -Via [JSON configuration](cli.md#running-with-json-configuration): - -```json -{ - ... - "pluginsClasspath": [ - "./dokka-base-%dokkaVersion%.jar", - "...", - "./versioning-plugin-%dokkaVersion%.jar" - ], - ... -} -``` - - - - -## Configuration - -### Configuration options - -The table below contains all the possible configuration options for the versioning plugin and their purpose. - -| **Option** | **Description** | -|--------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `version` | The version of your application/library that documentation is going to be generated for. This will be the version shown in the dropdown menu. | -| `versionsOrdering` | An optional list of strings that represents the order that versions should appear in the dropdown menu. Must match versions string exactly. The first item in the list is at the top of the dropdown. | -| `olderVersionsDir` | An optional path to a parent folder that contains other documentation versions. It requires a specific directory structure. For more information, see [Directory structure](#directory-structure). | -| `olderVersions` | An optional list of paths to other documentation versions. It must point to Dokka's outputs directly. This is useful if different versions can't all be in the same directory. | -| `renderVersionsNavigationOnAllPages` | An optional boolean value indicating whether to render the navigation dropdown on all pages. Set to true by default. | - -#### Directory structure - -Note that the directory passed to `olderVersionsDir` needs to follow a specific structure: - -```text -. -└── olderVersionsDir - └── 1.7.10 - ├── - └── 1.7.20 - ├── -... -``` - -### Configuration example - - - - -```kotlin -import org.jetbrains.dokka.versioning.VersioningPlugin -import org.jetbrains.dokka.versioning.VersioningConfiguration - -buildscript { - dependencies { - classpath("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") - } -} - -tasks.dokkaHtml { - pluginConfiguration { - version = "1.5" - versionsOrdering = listOf("1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1") - olderVersionsDir = file("documentation/version") - olderVersions = listOf(file("documentation/alpha/alpha-2"), file("documentation/alpha/alpha-1")) - renderVersionsNavigationOnAllPages = true - } -} -``` - -Alternatively, you can configure it via JSON: - -```kotlin - val versioningConfiguration = """ - { - "version": "1.5", - "versionsOrdering": ["1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1"], - "olderVersionsDir": "documentation/version", - "olderVersions": ["documentation/alpha/alpha-2", "documentation/alpha/alpha-1"], - "renderVersionsNavigationOnAllPages": true - } - """ - pluginsMapConfiguration.set( - mapOf( - "org.jetbrains.dokka.versioning.VersioningPlugin" to versioningConfiguration - ) - ) -``` - - - - -```groovy -dokkaHtml { - String versioningConfiguration = """ - { - "version": "1.5", - "versionsOrdering": ["1.5", "1.4", "1.3", "1.2", "1.1", "alpha-2", "alpha-1"], - "olderVersionsDir": "documentation/version", - "olderVersions": ["documentation/alpha/alpha-2", "documentation/alpha/alpha-1"], - "renderVersionsNavigationOnAllPages": true - } - """ - pluginsMapConfiguration.set( - ["org.jetbrains.dokka.versioning.VersioningPlugin": versioningConfiguration] - ) -} -``` - - - - -```xml - - org.jetbrains.dokka - dokka-maven-plugin - ... - - - - 1.5 - - 1.5 - 1.4 - 1.3 - 1.2 - 1.1 - alpha-2 - alpha-1 - - ${project.basedir}/documentation/version - - ${project.basedir}/documentation/alpha/alpha-2 - ${project.basedir}/documentation/alpha/alpha-1 - - true - - - - -``` - - - - -```Bash -java -jar dokka-cli-%dokkaVersion%.jar \ - ... - -pluginsConfiguration "org.jetbrains.dokka.versioning.VersioningPlugin={\"version\": \"1.5\", \"versionsOrdering\": [\"1.5\", \"1.4\", \"1.3\", \"1.2\", \"1.1\", \"alpha-2\", \"alpha-1\"], \"olderVersionsDir\": \"documentation/version\", \"olderVersions\": [\"documentation/alpha/alpha-2\", \"documentation/alpha/alpha-1\"], \"renderVersionsNavigationOnAllPages\": true}" - -``` - -Alternatively, via JSON configuration: -```json -{ - "moduleName": "Dokka Example", - ... - "pluginsConfiguration": [ - { - "fqPluginName": "org.jetbrains.dokka.versioning.VersioningPlugin", - "serializationFormat": "JSON", - "values": "{\"version\": \"1.5\", \"versionsOrdering\": [\"1.5\", \"1.4\", \"1.3\", \"1.2\", \"1.1\", \"alpha-2\", \"alpha-1\"], \"olderVersionsDir\": \"documentation/version\", \"olderVersions\": [\"documentation/alpha/alpha-2\", \"documentation/alpha/alpha-1\"], \"renderVersionsNavigationOnAllPages\": true}" - } - ] -} -``` - - - - -## Generating versioned documentation - -With the versioning plugin applied and configured, no other steps are needed. Documentation can be built in the usual way. - -Among other things, the versioning plugin adds a `version.json` file to the output folder. This file is used by the -plugin to match versions and generate version navigation. If your previously generated documentation does not have that -file, you will need to re-generate documentation for such versions. Just adding the file will not work. - -The versioning plugin also bundles all other documentation versions that have been passed through `olderVersionsDir` -and `olderVersions` configuration options by putting them inside the `older` directory. - -## Usage example - -There is no single correct way to configure the plugin, it can be tailored to your needs. However, -it can be a bit overwhelming when starting out. Below you will find one of the ways it can be configured so that you -can begin publishing versioned documentation straight away. - -The main idea behind it is the following: - -1. One directory contains all versions of your documentation. For example, `documentation/version/{doc_version}`. - This is your archive which is needed for future builds. -2. The output directory of all new builds is set to that directory as well, under `documentation/version/{new_version}`. -3. When new builds are executed, the plugin looks for previous versions of documentation in the archive directory. -4. Once new documentation has been generated, it needs to be **copied** to somewhere accessible by the user. - For example, GitHub pages or nginx static directories. It needs to be **copied**, not moved, because Dokka needs -5. Once it has been safely copied, you can remove the `older` directory from the newly generated and archived version. - This helps reduce the overhead of each version bundling all previous versions, as these files are effectively duplicates. - -```kotlin -import org.jetbrains.dokka.versioning.VersioningPlugin -import org.jetbrains.dokka.versioning.VersioningConfiguration - -buildscript { - dependencies { - classpath("org.jetbrains.dokka:versioning-plugin:%dokkaVersion%") - } -} - -dependencies { - dokkaPlugin("org.jetbrains.dokka:versioning-plugin:$dokkaVersion") -} - -tasks.dokkaHtml { - // This can be any persistent folder where - // you store documentation by version - val docVersionsDir = projectDir.resolve("documentation/version") - - // The version for which you are currently generating docs - val currentVersion = "1.3" - - // Set the output to a folder with all other versions - // as you'll need the current version for future builds - val currentDocsDir = docVersionsDir.resolve(currentVersion) - outputDirectory.set(currentDocsDir) - - pluginConfiguration { - olderVersionsDir = docVersionsDir - version = currentVersion - } - - doLast { - // This folder contains the latest documentation with all - // previous versions included, so it's ready to be published. - // Make sure it's copied and not moved - you'll still need this - // version for future builds - currentDocsDir.copyTo(file("/my/hosting")) - - // Only once current documentation has been safely moved, - // remove previous versions bundled in it. They will not - // be needed in future builds, it's just overhead. - currentDocsDir.resolve("older").deleteRecursively() - } -} -``` diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index cb7c72ca9d..e0ef7d3208 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -1,24 +1,26 @@ -[//]: # (title: CLI runner) +[//]: # (title: CLI) -If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) plugins, Dokka has -a command line (CLI) runner for generating documentation without any build tools. +If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) build tools, Dokka has +a command line (CLI) runner for generating documentation. -In comparison, it has the same, if not more, capabilities as the Gradle plugin. Although it is considerably more -difficult to set up as there is no autoconfiguration, especially in multiplatform and multimodule environments. - -The CLI runner is published as a separate artifact to Maven Central under `org.jetbrains.dokka:dokka-cli`, so you can -find it on [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-cli) or by browsing -[maven central repository directories](https://repo1.maven.org/maven2/org/jetbrains/dokka/dokka-cli/) directly. +In comparison, it has the same, if not more, capabilities as the Gradle runner. Although it is considerably more +difficult to set up as there is no autoconfiguration, especially in multiplatform and multi-module environments. ## Getting started -With the `dokka-cli-%dokkaVersion%.jar` file saved on your computer, run it with the `-help` option to see all available arguments and their description: +The CLI runner is published to Maven Central as a separate runnable artifact. + +You can find it on [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/dokka-cli/%dokkaVersion%) or by browsing +[maven central repository directories](https://repo1.maven.org/maven2/org/jetbrains/dokka/dokka-cli/%dokkaVersion%) directly. + +With the `dokka-cli-%dokkaVersion%.jar` file saved on your computer, run it with the `-help` option to see all +available configuration options and their description: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -help ``` -It also works for some nested arguments, such as `-sourceSet`: +It also works for some nested options, such as `-sourceSet`: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help @@ -47,11 +49,12 @@ Below are the additional dependencies that you need for [HTML](html.md) output f | `org.freemarker` | `freemarker` | 2.3.31 | [mvnrepository](https://mvnrepository.com/artifact/org.freemarker/freemarker/2.3.31) | -### Running with command line arguments +### Running with command line options -You can pass command line arguments to configure the CLI runner. +You can pass command line options to configure the CLI runner. + +At the very least you need to provide the following options: -At the very least you need to provide the following arguments: * `-pluginsClasspath` - a list of absolute/relative paths to downloaded dependencies, separated by semi-colons `;` * `-sourceSet` - an absolute path to code sources to generate documentation for * `-outputDir` - an absolute/relative path of the documentation output directory @@ -70,18 +73,19 @@ java -jar dokka-cli-%dokkaVersion%.jar \ Executing the given example generates documentation in [HTML](html.md) output format. -See [Command line arguments](#command-line-arguments) for more configuration details. +See [Command line options](#command-line-options) for more configuration details. ### Running with JSON configuration It's possible to configure the CLI runner with JSON. In this case, you need to provide an -absolute/relative path to the JSON configuration file. All other configuration options are parsed from it. +absolute/relative path to the JSON configuration file as the first and only argument. +All other configuration options are parsed from it. ```Bash java -jar dokka-cli-%dokkaVersion%.jar dokka-configuration.json ``` -At the very least, you need the following configuration: +At the very least, you need the following JSON configuration file: ```json { "outputDir": "./dokka/html", @@ -118,14 +122,14 @@ See [JSON configuration options](#json-configuration) for more details. By default, the `dokka-base` artifact contains the [HTML](html.md) output format only. -All other output formats come as part of [Dokka plugins](plugins_introduction.md). In order to use them, you have to put them -in the plugins classpath. +All other output formats come as [Dokka plugins](dokka_plugins.md). In order to use them, you have to put them +on the plugins classpath. For example, if you want to generate documentation in the experimental [GFM](markdown.md#gfm) output format, you need to download and pass [gfm-plugin's JAR](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into the `pluginsClasspath` configuration option. -Via command line arguments: +Via command line options: ```Shell java -jar dokka-cli-%dokkaVersion%.jar \ @@ -147,51 +151,50 @@ Via JSON configuration: } ``` -With the GFM plugin in the `pluginsClasspath`, the CLI runner generates documentation in GFM output format. -No further action is needed. +With the GFM plugin passed to `pluginsClasspath`, the CLI runner generates documentation in the GFM output format. For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#generating-javadoc-documentation). -## Command line arguments +## Command line options -To see a list of all possible command line arguments for the nested `-sourceSet` configuration, run: +To see the list of all possible command line options and their detailed description, run: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -help ``` -Summary: +Short summary: - `-moduleName` -> Name of the project/module. - `-moduleVersion` -> Documented version. - `-outputDir` -> Output directory path, `./dokka` by default. -- `-sourceSet` -> Configuration for a Dokka source set. Contains nested configuration. +- `-sourceSet` -> Configuration for a Dokka source set. Contains nested configuration options. - `-pluginsConfiguration` -> Configuration for Dokka plugins. - `-pluginsClasspath` -> List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons. - `-offlineMode` -> Whether to resolve remote files/links over network. - `-failOnWarning` -> Whether to fail documentation generation if Dokka has emitted a warning or an error. -- `-delayTemplateSubstitution` -> Delay substitution of some elements. Used in incremental builds of - multimodule projects. -- `-noSuppressObviousFunctions` -> Whether to suppress obvious functions such as inherited from `kotlin.Any` +- `-delayTemplateSubstitution` -> Whether to delay substitution of some elements. Used in incremental builds of + multi-module projects. +- `-noSuppressObviousFunctions` -> Whether to suppress obvious functions such as those inherited from `kotlin.Any` and `java.lang.Object`. - `-includes` -> Markdown files that contain module and package documentation. Accepts multiple values separated by semicolons. - `-suppressInheritedMembers` -> Whether to suppress inherited members that aren't explicitly overridden in a given class. -- `-globalPackageOptions` -> Global list of package configurations in format +- `-globalPackageOptions` -> Global list of package configuration options in format `"matchingRegex,-deprecated,-privateApi,+warnUndocumented,+suppress;+visibility:PUBLIC;..."`. Accepts multiple values separated by semicolons. - `-globalLinks` -> Global external documentation links in format `{url}^{packageListUrl}`. Accepts multiple values separated by `^^`. - `-globalSrcLink` -> Global mapping between a source directory and a Web service for browsing the code. Accepts multiple paths separated by semicolons. -- `-helpSourceSet` -> Prints help for nested `-sourceSet` configuration. +- `-helpSourceSet` -> Prints help for the nested `-sourceSet` configuration. - `-loggingLevel` -> Logging level, possible values: `DEBUG, PROGRESS, INFO, WARN, ERROR`. - `-help, -h` -> Usage info. -#### Source set arguments +#### Source set options -You can also see short descriptions for nested `-sourceSet` configuration: +To see the list of command line options for the nested `-sourceSet` configuration, run: ```Bash java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help @@ -203,24 +206,23 @@ Summary: - `-displayName` -> Display name of the source set, used both internally and externally. - `-classpath` -> Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons. - `-src` -> Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons. -- `-dependentSourceSets` -> Names of dependent source sets in format `moduleName/sourceSetName`. +- `-dependentSourceSets` -> Names of the dependent source sets in format `moduleName/sourceSetName`. Accepts multiple paths separated by semicolons. - `-samples` -> List of directories or files that contain sample functions. Accepts multiple paths separated by semicolons. - `-includes` -> Markdown files that contain module and package documentation. Accepts multiple paths separated by semicolons. -- `-includeNonPublic` -> Deprecated, use `documentedVisibilities`. - Possible values: `PUBLIC`, `PRIVATE`, `PROTECTED`, `INTERNAL`, `PACKAGE`. - `-documentedVisibilities` -> Visibilities to be documented. Accepts multiple values separated by semicolons. + Possible values: `PUBLIC`, `PRIVATE`, `PROTECTED`, `INTERNAL`, `PACKAGE`. - `-reportUndocumented` -> Whether to report undocumented declarations. - `-noSkipEmptyPackages` -> Whether to create pages for empty packages. - `-skipDeprecated` -> Whether to skip deprecated declarations. - `-jdkVersion` -> Version of JDK to use for linking to JDK Javadocs. - `-languageVersion` -> Language version used for setting up analysis and samples. - `-apiVersion` -> Kotlin API version used for setting up analysis and samples. -- `-noStdlibLink` -> Whether to generate links to Standard library. +- `-noStdlibLink` -> Whether to generate links to the Kotlin standard library. - `-noJdkLink` -> Whether to generate links to JDK Javadocs. - `-suppressedFiles` -> Paths to files to be suppressed. Accepts multiple paths separated by semicolons. - `-analysisPlatform` -> Platform used for setting up analysis. -- `-perPackageOptions` -> List of package source set configuration in format +- `-perPackageOptions` -> List of package source set configurations in format `matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...`. Accepts multiple values separated by semicolons. - `-externalDocumentationLinks` -> External documentation links in format `{url}^{packageListUrl}`. Accepts multiple values separated by `^^`. @@ -272,11 +274,11 @@ with [all configuration options](#complete-configuration) applied. -

    The display name used to refer to the module. Used in the table of contents, navigation, logging, etc.

    +

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    Default: root.

    -

    Module version.

    +

    The module version.

    Default: empty.

    @@ -285,7 +287,7 @@ with [all configuration options](#complete-configuration) applied.

    - Whether to fail documentation generation if Dokka emits a warning or an error. + Whether to fail documentation generation if Dokka has emitted a warning or an error. The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented

    @@ -311,8 +313,7 @@ with [all configuration options](#complete-configuration) applied.

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    - Note: this can suppress functions such as equals / hashCode / -toString, + Note: this can suppress functions such as equals / hashCode / toString, but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that. @@ -320,19 +321,19 @@ with [all configuration options](#complete-configuration) applied.

    Default: false.

    -

    Whether to resolve remote files/links over network.

    +

    Whether to resolve remote files/links over your network.

    - This includes package-lists used for generating external documentation links. - For example, to make classes from standard library clickable. + This includes package-lists used for generating external documentation links. + For example, to make classes from the standard library clickable.

    Setting this to true can significantly speed up build times in certain cases, but can also worsen documentation quality and user experience. For example, by - not resolving some dependency's class/member links. + not resolving class/member links from your dependencies, including the standard library.

    Note: you can cache fetched files locally and provide them to - Dokka as local paths. See externalDocumentationLinks. + Dokka as local paths. See externalDocumentationLinks section.

    Default: false.

    @@ -341,8 +342,7 @@ with [all configuration options](#complete-configuration) applied. A list of Markdown files that contain module and package documentation.

    -

    The contents of specified files are parsed and embedded into documentation as module and package -descriptions.

    +

    The contents of specified files are parsed and embedded into documentation as module and package descriptions.

    This can be configured on per-package basis.

    @@ -353,7 +353,7 @@ descriptions.

    For a list of possible options, see source set configuration.

    -

    The global configuration of source links that are applied for all source sets.

    +

    The global configuration of source links that is applied for all source sets.

    For a list of possible options, see source link configuration.

    @@ -431,7 +431,7 @@ How to configure Kotlin -

    The display name used to refer to the source set.

    +

    The display name used to refer to this source set.

    The name is used both externally (for example, the source set name is visible to documentation readers) and internally (for example, for logging messages of reportUndocumented). @@ -463,9 +463,10 @@ How to configure Kotlin

    Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs - after they have been filtered by documentedVisibilities. + after they have been filtered by documentedVisibilities and other filters.

    -

    This setting works well with failOnWarning. It can be overridden for a specific package

    +

    This setting works well with failOnWarning.

    +

    This can be configured on per-package basis.

    Default: false.

    @@ -481,14 +482,14 @@ How to configure Kotlin

    Whether to document declarations annotated with @Deprecated.

    -

    It can be overridden at package level.

    +

    This can be configured on per-package basis.

    Default: false.

    The JDK version to use when generating external documentation links for Java types.

    - For example, if you use java.util.UUID from JDK in some public declaration signature, - and this property is set to 8, Dokka generates an external documentation link + For example, if you use java.util.UUID in some public declaration signature, + and this option is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    @@ -508,16 +509,16 @@ How to configure Kotlin

    - Whether to generate external documentation links that lead to API reference - documentation for Kotlin's standard library when declarations from it are used. + Whether to generate external documentation links that lead to the API reference + documentation of Kotlin's standard library.

    -

    Links are generated when `noStdLibLink` is set to false.

    +

    Note: links are generated when noStdLibLink is set to false.

    Default: false.

    -

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    -

    Links are generated when `noJdkLink` is set to false.

    -

    The version of JDK Javadocs is determined by jdkVersion property.

    +

    Whether to generate external documentation links to JDK's Javadocs.

    +

    The version of JDK Javadocs is determined by the jdkVersion option.

    +

    Note: links are generated when noJdkLink is set to false.

    Default: false.

    @@ -532,7 +533,6 @@ How to configure Kotlin Platform to be used for setting up code analysis and @sample environment.

    -

    The default value is deduced from information provided by the Kotlin Gradle plugin.

    Possible values: @@ -546,19 +546,17 @@ How to configure Kotlin

    The source code roots to be analyzed and documented. - It accepts directories and individual .kt / .java files. + Acceptable inputs are directories and individual .kt / .java files.

    -

    - The classpath for analysis and interactive samples. If you use a declaration from a dependency, - it should be present on the classpath to be resolved. -

    -

    Property accepts both .jar and .klib files.

    +

    The classpath for analysis and interactive samples.

    +

    This is useful if some types that come from dependencies are not resolved/picked up automatically.

    +

    This option accepts both .jar and .klib files.

    - A list of directories or files that contain sample functions which are referenced via + A list of directories or files that contain sample functions which are referenced via the @sample KDoc tag.

    @@ -566,7 +564,7 @@ How to configure Kotlin

    The files to be suppressed when generating documentation.

    -

    A set of parameters for source links that are applied only for this source set.

    +

    A set of parameters for source links that is applied only for this source set.

    For a list of possible options, see source link configuration.

    @@ -574,22 +572,24 @@ How to configure Kotlin

    For a list of possible options, see per-package configuration.

    -

    A set of parameters for external documentation links that are applied only for this source set.

    +

    A set of parameters for external documentation links that is applied only for this source set.

    For a list of possible options, see external documentation configuration.

    ### Source link configuration -The `sourceLinks` configuration block is where you can add a `source` link to each signature -that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +The `sourceLinks` configuration block allows you to add a `source` link to each signature +that leads to the `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). + This helps readers to find the source code for each declaration. For an example, see the documentation for the [`count()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) function in `kotlinx.coroutines`. -You can configure source sets together at the same time, or [individually](#source-set-configuration): +You can configure source links for all source sets together at the same time, or +[individually](#source-set-configuration): ```json { @@ -605,7 +605,7 @@ You can configure source sets together at the same time, or [individually](#sour -

    Path to the local source directory.

    +

    The path to the local source directory.

    @@ -616,12 +616,12 @@ You can configure source sets together at the same time, or [individually](#sour

    - The suffix used to append source code line number to the URL. This helps readers navigate + The suffix used to append the source code line number to the URL. This helps readers navigate not only to the file, but to the specific line number of the declaration.

    The number itself is appended to the specified suffix. For example, - if this property is set to #L and the line number is 10, the resulting URL suffix + if this option is set to #L and the line number is 10, the resulting URL suffix is #L10.

    @@ -638,9 +638,10 @@ You can configure source sets together at the same time, or [individually](#sour ### Per-package configuration -The `perPackageOptions` configuration block allows you to set some options for specific packages matched by `matchingRegex`. +The `perPackageOptions` configuration block allows setting some options for specific packages matched by `matchingRegex`. -You can configure source sets together at the same time, or [individually](#source-set-configuration): +You can add package configurations for all source sets together at the same time, or +[individually](#source-set-configuration): ```json { @@ -671,8 +672,8 @@ You can configure source sets together at the same time, or [individually](#sour

    - Whether to emit warnings about visible undocumented declarations, that is declarations from - this package and without KDocs, after they have been filtered by documentedVisibilities. + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities and other filters.

    This setting works well with failOnWarning.

    This can be configured on source set level.

    @@ -681,8 +682,8 @@ You can configure source sets together at the same time, or [individually](#sour

    The set of visibility modifiers that should be documented.

    - This can be used if you want to document protected/internal/private declarations within a - specific package, as well as if you want to exclude public declarations and only document internal API. + This can be used if you want to document protected/internal/private declarations within this package, + as well as if you want to exclude public declarations and only document internal API.

    Can be configured on source set level.

    Default: PUBLIC.

    @@ -691,15 +692,17 @@ You can configure source sets together at the same time, or [individually](#sour ### External documentation configuration -The `externalDocumentationLinks` configuration block allows you to add links that lead to the externally hosted documentation of your dependencies. +The `externalDocumentationLink` block allows the creation of links that lead to the externally hosted documentation of +your dependencies. For example, if you are using types from `kotlinx.serialization`, by default they are unclickable in your -documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is -[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it. Thus allowing Dokka to generate links for types, making them clickable -and resolve successfully. +documentation, as if they are unresolved. However, since the API reference documentation for `kotlinx.serialization` +is built by Dokka and is [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can +configure external documentation links for it. Thus allowing Dokka to generate links for types from the library, making +them resolve successfully and clickable. -You can configure source sets together all at once, or [individually](#source-set-configuration): +You can configure external documentation links for all source sets together at the same time, or +[individually](#source-set-configuration): ```json { @@ -714,27 +717,32 @@ You can configure source sets together all at once, or [individually](#source-se -

    The root URL of documentation to link with. It **must** contain a trailing slash.

    +

    The root URL of documentation to link to. It must contain a trailing slash.

    - Dokka does its best to automatically find package-list for the given URL + Dokka does its best to automatically find package-list for the given URL, and link declarations together.

    If automatic resolution fails or if you want to use locally cached files instead, - consider providing the packageListUrl. + consider setting the packageListUrl option.

    The exact location of a package-list. This is an alternative to relying on Dokka - automatically resolving it. This can also be a locally cached file to avoid network calls. + automatically resolving it. +

    +

    + Package lists contain information about the documentation and the project itself, + such as module and package names.

    +

    This can also be a locally cached file to avoid network calls.

    ### Complete configuration -Below you can see all the possible configuration options applied at the same time. +Below you can see all possible configuration options applied at the same time. ```json { diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md index 9f05e58f1c..37fcde4e7e 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/gradle.md @@ -1,17 +1,18 @@ -[//]: # (title: Gradle plugin) +[//]: # (title: Gradle) -To generate documentation for a Gradle-based project, you can use the [Dokka Gradle plugin](#applying-the-plugin). +To generate documentation for a Gradle-based project, you can use the +[Dokka Gradle plugin](https://plugins.gradle.org/plugin/org.jetbrains.dokka). It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient [Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of -[configuration options](#configuration) to customize output. +[configuration options](#configuration) to customize the output. You can play around with Dokka and see how it can be configured for various projects by visiting our [Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). -## Applying the plugin +## Applying Dokka -The recommended way of applying the plugin is via +The recommended way of applying the Dokka Gradle plugin is with the [plugins DSL](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block): @@ -35,8 +36,8 @@ plugins {
    -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka plugin within subprojects as well. -You can use `allprojects {}` and `subprojects {}` Gradle configurations to achieve that: +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka Gradle plugin +within subprojects as well. You can use `allprojects {}` or `subprojects {}` Gradle configurations to achieve that: @@ -60,9 +61,8 @@ subprojects { > Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform -> autoconfiguration -> of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for documentation -> to be generated. Make sure to apply Kotlin Gradle Plugin or +> autoconfiguration of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for +> which documentation is to be generated. Make sure to apply the Kotlin Gradle Plugin or > [configure source sets](#source-set-configuration) manually. > {type="note"} @@ -91,13 +91,13 @@ subprojects { > {type="note"} -If you cannot use the plugin DSL for some reason, you can use +If you cannot use the plugins DSL for some reason, you can use [the legacy method](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application) of applying plugins. ## Generating documentation -Dokka's Gradle plugin comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats built in. +Dokka's Gradle runner comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats built in. It adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. @@ -119,17 +119,18 @@ Use the following tasks to build documentation for simple, single project applic | `dokkaJavadoc` | Generates documentation in [Javadoc](javadoc.md) format. | | `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | -By default, generated documentation is stored in the `build/dokka/{format}` directory of your project. -The output location, among other things, can be [configured](#configuration) separately. +By default, generated documentation is located in the `build/dokka/{format}` directory of your project. +The output location, among other things, can be [configured](#configuration). ### Multi-project builds For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), make sure -that you apply the Dokka plugin within subprojects that you want to generate documentation for, as well as in their parent project. +that you [apply the Dokka Gradle plugin](#applying-dokka) within subprojects that you want to generate documentation +for, as well as in their parent project. #### MultiModule tasks -`MultiModule` tasks generate documentation for each subproject individually via [partial](#partial-tasks) tasks, +`MultiModule` tasks generate documentation for each subproject individually via [Partial](#partial-tasks) tasks, collect and process all outputs, and produce complete documentation with a common table of contents and resolved cross-project references. @@ -148,14 +149,14 @@ Dokka creates the following tasks for **parent** projects automatically: | `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) output format. | | `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) output format. | -> The [Javadoc](javadoc.md) output format does not have a MultiModule task, but a [Collector](#collector-tasks) task can +> The [Javadoc](javadoc.md) output format does not have a `MultiModule` task, but a [Collector](#collector-tasks) task can > be used instead. > {type="note"} By default, you can find ready-to-use documentation under `{parentProject}/build/dokka/{format}MultiModule` directory. -#### MultiModule task example +#### MultiModule results Given a project with the following structure: @@ -173,29 +174,15 @@ These pages are generated after running `dokkaHtmlMultiModule`: ![Screenshot for output of dokkaHtmlMultiModule task](dokkaHtmlMultiModule-example.png){width=600} -See our [multi-module project example](https://github. -com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +See our [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) for more details. -#### Partial tasks - -Each subproject has _partial_ tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, -and `dokkaJekyllPartial`. - -These tasks are not intended to be used independently and exist only to be called by the parent's -[MultiModule](#multimodule-tasks) task. - -Output generated by partial tasks contains non-displayable formatting along with unresolved templates and references. - -> If you want to generate documentation for a single subproject only, use -> [single project tasks](#single-project-builds). For example, `:subproject:dokkaHtml`. - #### Collector tasks -Similar to MultiModule tasks, _Collector_ tasks are created for each parent project: `dokkaHtmlCollector`, +Similar to `MultiModule` tasks, `Collector` tasks are created for each parent project: `dokkaHtmlCollector`, `dokkaGfmCollector`, `dokkaJavadocCollector` and `dokkaJekyllCollector`. -A Collector task executes the corresponding [single project task](#single-project-builds) for each subproject (for +A `Collector` task executes the corresponding [single project task](#single-project-builds) for each subproject (for example, `dokkaHtml`), and merges all outputs into a single virtual project. @@ -224,16 +211,37 @@ These pages are generated after running `dokkaHtmlCollector`: ![Screenshot for output of dokkaHtmlCollector task](dokkaHtmlCollector-example.png){width=800} -See our [multi-module project example](https://github. -com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) +See our [multi-module project example](https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-multimodule-example) for more details. +#### Partial tasks + +Each subproject has `Partial` tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, +and `dokkaJekyllPartial`. + +These tasks are not intended to be used independently and exist only to be called by the parent's +[MultiModule](#multimodule-tasks) task. + +Output generated by `Partial` tasks contains unresolved HTML templates and references, so it cannot be used +on its own without post-processing done by the `MultiModule` task. + +However, you can [configure](#configuration) `Partial` tasks to customize Dokka on a per-project basis. +For example, your subprojects can have different configurations of documented visibilities, where one of +the subprojects allows documenting `protected` declarations, while others do not. + +> If you want to generate documentation for a single subproject only, use +> [single project tasks](#single-project-builds). For example, `:subprojectName:dokkaHtml`. + ## Building javadoc.jar -In order to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API -reference documentation. +If you want to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains +API reference documentation of your library. + +For example, if you want to publish to [Maven Central](https://central.sonatype.org/), you +[must](https://central.sonatype.org/publish/requirements/) supply a `javadoc.jar` alongside your project. However, +not all repositories have that rule. -Dokka's Gradle plugin does not provide any way to do this out of the box, but it can be achieved with custom Gradle +Dokka's Gradle runner does not provide any way to do this out of the box, but it can be achieved with custom Gradle tasks. One for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: @@ -275,7 +283,7 @@ tasks.register('dokkaJavadocJar', Jar.class) { > If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to > host your library's API documentation for free and without any setup. It takes documentation pages straight -> from the artifact. It works with both HTML and Javadoc formats as demonstrated in +> from the `javadoc.jar`. It works well with the HTML format as demonstrated in > [this example](https://javadoc.io/doc/com.trib3/server/latest/index.html). > {type="tip"} @@ -287,8 +295,6 @@ You can configure tasks and output formats individually: -Applying the Dokka plugin via the [plugins DSL](#applying-the-plugin) block: - ```kotlin tasks.dokkaHtml { outputDirectory.set(buildDir.resolve("documentation/html")) @@ -298,6 +304,7 @@ tasks.dokkaGfm { outputDirectory.set(buildDir.resolve("documentation/markdown")) } +// only within a subproject: tasks.dokkaHtmlPartial { outputDirectory.set(buildDir.resolve("docs/partial")) } @@ -316,6 +323,7 @@ dokkaGfm { outputDirectory.set(file("build/documentation/markdown")) } +// only within a subproject: dokkaHtmlPartial { outputDirectory.set(file("build/docs/partial")) } @@ -335,8 +343,8 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial import org.jetbrains.dokka.DokkaConfiguration.Visibility -// configure all dokka tasks, including multimodule, -// partial and collector ones +// Configure all single-project Dokka tasks at the same time, +// such as dokkaHtml, dokkaJavadoc and dokkaGfm. tasks.withType().configureEach { dokkaSourceSets.configureEach { documentedVisibilities.set( @@ -353,11 +361,16 @@ tasks.withType().configureEach { } } -// Configure partial tasks of all output formats. +// Configure all Partial tasks found in multi-project builds, +// such as dokkaHtmlPartial, dokkaJavadocPartial and dokkaGfmPartial. // These can have subproject-specific settings. -tasks.withType(DokkaTaskPartial::class).configureEach { - dokkaSourceSets.configureEach { - includes.from("README.md") +subprojects { + apply(plugin = "org.jetbrains.dokka") + + tasks.withType().configureEach { + dokkaSourceSets.configureEach { + includes.from("README.md") + } } } ``` @@ -369,8 +382,8 @@ tasks.withType(DokkaTaskPartial::class).configureEach { import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial -// Configure all Dokka tasks, including multimodule, -// partial and collector tasks +// Configure all single-project Dokka tasks at the same time, +// such as dokkaHtml, dokkaJavadoc and dokkaGfm. tasks.withType(DokkaTask.class) { dokkaSourceSets.configureEach { documentedVisibilities.set([ @@ -385,11 +398,15 @@ tasks.withType(DokkaTask.class) { } } -// Configure partial tasks of all output formats. +// Configure all Partial tasks found in multi-project builds. // These can have subproject-specific settings. -tasks.withType(DokkaTaskPartial.class) { - dokkaSourceSets.configureEach { - includes.from("README.md") +subprojects { + apply plugin: 'org.jetbrains.dokka' + + tasks.withType(DokkaTaskPartial.class) { + dokkaSourceSets.configureEach { + includes.from("README.md") + } } } ``` @@ -456,20 +473,20 @@ tasks.withType(DokkaTask.class) {

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    -

    If set for a single-project build or a MultiModule task, it is used as the project name.

    -

    The default is the Gradle project name.

    +

    If set for a single-project build or a MultiModule task, it is used as the project name.

    +

    Default: Gradle project name.

    - The module version. If set for a single-project build or a MultiModule task, it is used as the project version - by the versioning plugin. + The module version. If set for a single-project build or a MultiModule task, it is used as the + project version.

    Default: Gradle project version.

    -

    The directory where documentation is generated, regardless of format. It can be set on a per-task basis.

    +

    The directory to where documentation is generated, regardless of format. It can be set on a per-task basis.

    - The default is project/buildDir/format, where format is the task name with + The default is {project}/{buildDir}/{format}, where {format} is the task name with the "dokka" prefix removed. For the dokkaHtmlMultiModule task, it is project/buildDir/htmlMultiModule.

    @@ -479,7 +496,7 @@ tasks.withType(DokkaTask.class) { Whether to fail documentation generation if Dokka has emitted a warning or an error. The process waits until all errors and warnings have been emitted first.

    -

    This setting works well with reportUndocumented

    +

    This setting works well with reportUndocumented.

    Default: false.

    @@ -513,12 +530,12 @@ tasks.withType(DokkaTask.class) {

    Whether to resolve remote files/links over your network.

    This includes package-lists used for generating external documentation links. - For example, to make classes from standard library clickable. + For example, to make classes from the standard library clickable.

    Setting this to true can significantly speed up build times in certain cases, but can also worsen documentation quality and user experience. For example, by - not resolving some dependency's class/member links. + not resolving class/member links from your dependencies, including the standard library.

    Note: you can cache fetched files locally and provide them to @@ -530,7 +547,8 @@ tasks.withType(DokkaTask.class) { ### Source set configuration -Here is an example of how to configure Kotlin [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets). +Dokka allows configuring some options for +[Kotlin source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets): @@ -545,6 +563,12 @@ tasks.withType().configureEach { // .. // general configuration section // .. + + // configuration exclusive to the 'linux' source set + named("linux") { + dependsOn("native") + sourceRoots.from(file("linux/src")) + } dokkaSourceSets.configureEach { suppress.set(false) @@ -593,6 +617,12 @@ tasks.withType(DokkaTask.class) { // general configuration section // .. + // configuration exclusive to the 'linux' source set + named("linux") { + dependsOn("native") + sourceRoots.from(file("linux/src")) + } + dokkaSourceSets.configureEach { suppress.set(false) displayName.set(name) @@ -635,7 +665,7 @@ tasks.withType(DokkaTask.class) {

    Default: false.

    -

    The display name used to refer to the source set.

    +

    The display name used to refer to this source set.

    The name is used both externally (for example, as source set name visible to documentation readers) and internally (for example, for logging messages of reportUndocumented). @@ -648,15 +678,16 @@ tasks.withType(DokkaTask.class) { This can be used if you want to document protected/internal/private declarations, as well as if you want to exclude public declarations and only document internal API.

    -

    Can be configured on per-package basis.

    +

    This can be configured on per-package basis.

    Default: DokkaConfiguration.Visibility.PUBLIC.

    Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs - after they have been filtered by documentedVisibilities. + after they have been filtered by documentedVisibilities and other filters.

    -

    This setting works well with failOnWarning. It can be overridden for a specific package.

    +

    This setting works well with failOnWarning.

    +

    This can be configured on per-package basis.

    Default: false.

    @@ -672,13 +703,15 @@ tasks.withType(DokkaTask.class) {

    Whether to document declarations annotated with @Deprecated.

    -

    It can be overridden at package level.

    +

    This can be configured on per-package basis.

    Default: false.

    Whether to document/analyze generated files.

    Generated files are expected to be present under the {project}/{buildDir}/generated directory. +

    +

    If set to true, it effectively adds all files from that directory to the suppressedFiles option, so you can configure it manually.

    @@ -687,8 +720,8 @@ tasks.withType(DokkaTask.class) {

    The JDK version to use when generating external documentation links for Java types.

    - For example, if you use java.util.UUID from the JDK in some public declaration signature, - and this property is set to 8, Dokka generates an external documentation link + For example, if you use java.util.UUID in some public declaration signature, + and this option is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    Default: JDK 8.

    @@ -711,25 +744,22 @@ tasks.withType(DokkaTask.class) {

    - Whether to generate external documentation links that lead to API reference - documentation for Kotlin's standard library when declarations from it are used. + Whether to generate external documentation links that lead to the API reference + documentation of Kotlin's standard library.

    -

    Links are generated when `noStdLibLink` is set to false.

    +

    Note: links are generated when noStdLibLink is set to false.

    Default: false.

    -

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    -

    The version of JDK Javadocs is determined by the jdkVersion property.

    -

    Links are generated when `noJdkLink` is set to false.

    +

    Whether to generate external documentation links to JDK's Javadocs.

    +

    The version of JDK Javadocs is determined by the jdkVersion option.

    +

    Note: links are generated when noJdkLink is set to false.

    Default: false.

    -

    - Whether to generate external documentation links for Android SDK API reference - when declarations from it are used. -

    +

    Whether to generate external documentation links to the Android SDK API reference

    This is only relevant in Android projects, ignored otherwise.

    -

    Links are generated when `noAndroidSdkLink` is set to false.

    +

    Note: links are generated when noAndroidSdkLink is set to false.

    Default: false.

    @@ -740,7 +770,7 @@ tasks.withType(DokkaTask.class) {

    The contents of the specified files are parsed and embedded into documentation as module and package descriptions.

    See Dokka gradle example - for an example of how to use it and what it looks like. + for an example of what it looks like and how to use it.

    @@ -753,21 +783,19 @@ tasks.withType(DokkaTask.class) {

    The source code roots to be analyzed and documented. - Acceptable formats are directories and individual .kt / .java files. + Acceptable inputs are directories and individual .kt / .java files.

    By default, source roots are deduced from information provided by the Kotlin Gradle plugin.

    The classpath for analysis and interactive samples.

    -

    - This iu Useful if some types that come from dependencies are not resolved/picked up automatically. - The property accepts both .jar and .klib files. -

    +

    This is useful if some types that come from dependencies are not resolved/picked up automatically.

    +

    This option accepts both .jar and .klib files.

    By default, classpath is deduced from information provided by the Kotlin Gradle plugin.

    - A list of directories or files that contain sample functions which are referenced via + A list of directories or files that contain sample functions which are referenced via the @sample KDoc tag.

    @@ -775,8 +803,9 @@ tasks.withType(DokkaTask.class) { ### Source link configuration -The `sourceLinks` configuration block is where you can add a `source` link to each signature -that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +The `sourceLinks` configuration block allows you to add a `source` link to each signature +that leads to the `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). + This helps readers to find the source code for each declaration. For an example, see the documentation for the @@ -802,7 +831,7 @@ tasks.withType().configureEach { sourceLink { localDirectory.set(projectDir.resolve("src")) - remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src")) remoteLineSuffix.set("#L") } } @@ -828,7 +857,7 @@ tasks.withType(DokkaTask.class) { sourceLink { localDirectory.set(file("src")) - remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src")) remoteLineSuffix.set("#L") } } @@ -859,7 +888,7 @@ tasks.withType(DokkaTask.class) {

    The number itself is appended to the specified suffix. For example, - if this property is set to #L and the line number is 10, the resulting URL suffix + if this option is set to #L and the line number is 10, the resulting URL suffix is #L10.

    @@ -876,7 +905,7 @@ tasks.withType(DokkaTask.class) { ### Package options -Here is an example of a configuration block that allows setting some options for specific packages matched by `matchingRegex`. +The `perPackageOption` configuration block allows setting some options for specific packages matched by `matchingRegex`. @@ -940,7 +969,7 @@ tasks.withType(DokkaTask.class) {

    The regular expression that is used to match the package.

    -

    Default: any string: .*.

    +

    Default: .*.

    Whether this package should be skipped when generating documentation.

    @@ -953,8 +982,8 @@ tasks.withType(DokkaTask.class) {

    - Whether to emit warnings about visible undocumented declarations. That is declarations from - this package and without KDocs, after they have been filtered by documentedVisibilities. + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities and other filters.

    This setting works well with failOnWarning.

    This can be configured on source set level.

    @@ -963,8 +992,8 @@ tasks.withType(DokkaTask.class) {

    The set of visibility modifiers that should be documented.

    - This can be used if you want to document protected/internal/private declarations within a - specific package, as well as if you want to exclude public declarations and only document internal API. + This can be used if you want to document protected/internal/private declarations within this package, + as well as if you want to exclude public declarations and only document internal API.

    This can be configured on source set level.

    Default: DokkaConfiguration.Visibility.PUBLIC.

    @@ -973,13 +1002,16 @@ tasks.withType(DokkaTask.class) { ### External documentation links configuration -The externalDocumentationLink` block allows the creation of links that lead to the externally hosted documentation of your dependencies. +The `externalDocumentationLink` block allows the creation of links that lead to the externally hosted documentation of +your dependencies. For example, if you are using types from `kotlinx.serialization`, by default they are unclickable in your -documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is -[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it. Thus allowing Dokka to generate links for types, making them clickable -and resolve successfully. +documentation, as if they are unresolved. However, since the API reference documentation for `kotlinx.serialization` +is built by Dokka and is [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can +configure external documentation links for it. Thus allowing Dokka to generate links for types from the library, making +them resolve successfully and clickable. + +By default, external documentation links for Kotlin standard library, JDK, Android SDK and AndroidX are configured. @@ -1040,21 +1072,26 @@ tasks.withType(DokkaTask.class) { -

    The root URL of documentation to link with. It **must** contain a trailing slash.

    +

    The root URL of documentation to link to. It must contain a trailing slash.

    Dokka does its best to automatically find package-list for the given URL, and link declarations together.

    If automatic resolution fails or if you want to use locally cached files instead, - consider providing packageListUrl. + consider setting the packageListUrl option.

    - Specifies the exact location of a package-list instead of relying on Dokka - automatically resolving it. It can also be a locally cached file to avoid network calls. + The exact location of a package-list. This is an alternative to relying on Dokka + automatically resolving it. +

    +

    + Package lists contain information about the documentation and the project itself, + such as module and package names.

    +

    This can also be a locally cached file to avoid network calls.

    @@ -1081,8 +1118,9 @@ tasks.withType().configureEach { offlineMode.set(false) dokkaSourceSets { - named("customSourceSet") { - dependsOn("sourceSetDependency") + named("linux") { + dependsOn("native") + sourceRoots.from(file("linux/src")) } configureEach { suppress.set(false) @@ -1106,7 +1144,7 @@ tasks.withType().configureEach { sourceLink { localDirectory.set(projectDir.resolve("src")) - remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src")) remoteLineSuffix.set("#L") } @@ -1156,8 +1194,9 @@ tasks.withType(DokkaTask.class) { offlineMode.set(false) dokkaSourceSets { - named("customSourceSet") { - dependsOn("sourceSetDependency") + named("linux") { + dependsOn("native") + sourceRoots.from(file("linux/src")) } configureEach { suppress.set(false) @@ -1181,7 +1220,7 @@ tasks.withType(DokkaTask.class) { sourceLink { localDirectory.set(file("src")) - remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + remoteUrl.set(new URL("https://github.com/kotlin/dokka/tree/master/src")) remoteLineSuffix.set("#L") } diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index 7ba7dcea44..40bb9306f8 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -1,18 +1,18 @@ -[//]: # (title: Maven plugin) +[//]: # (title: Maven) -To generate documentation for Maven-based projects, you can use the [Dokka Maven plugin](#applying-the-plugin). +To generate documentation for a Maven-based project, you can use the [Dokka Maven plugin](#applying-dokka). -> Compared to the [Gradle plugin](gradle.md), the Maven plugin has only basic features and -> does not provide support for multimodule builds out of the box. +> Compared to the [Gradle runner](gradle.md), the Maven runner has only basic features and +> does not provide support for multi-module builds. > {type="note"} You can play around with Dokka and see how it can be configured for a Maven project by visiting our [Maven example](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/maven) project. -## Applying the plugin +## Applying Dokka -To apply the plugin, you need to add it to the plugins section of your POM file: +To apply Dokka, you need to add `dokka-maven-plugin` to the `plugins` section of your POM file: ```xml @@ -53,11 +53,11 @@ The following goals are provided by the plugin: ### Other output formats -By default, the Maven plugin builds documentation in [HTML](html.md) output format. +By default, the Maven runner builds documentation in [HTML](html.md) output format. -All other output formats come as part of [Dokka plugins](plugins_introduction.md). In order to use them, you have to apply +All other output formats come as [Dokka plugins](dokka_plugins.md). In order to use them, you have to apply TODO -For example, to use the experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in +For example, to use the experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in TODO ```xml @@ -78,14 +78,21 @@ For example, to use the experimental [GFM](markdown.md#gfm) format, you have to With this configuration, running the `dokka:dokka` goal produces documentation in GFM format. -To learn more about Dokka plugins, see [Dokka plugins](plugins_introduction.md). +To learn more about Dokka plugins, see [Dokka plugins](dokka_plugins.md). ## Building javadoc.jar -Unlike the [Gradle plugin](gradle.md#building-javadoc-jar), the Maven plugin comes with a ready-to-use `dokka:javadocJar` goal. -By default, it generates documentation in [Javadoc](javadoc.md) output format in the`target` folder. +If you want to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains +API reference documentation of your library. -If you are not satisfied with the built-in goal or want to customize the output (for instance, you want to generate +For example, if you want to publish to [Maven Central](https://central.sonatype.org/), you +[must](https://central.sonatype.org/publish/requirements/) supply a `javadoc.jar` alongside your project. However, +not all repositories have that rule. + +Unlike the [Gradle runner](gradle.md#building-javadoc-jar), the Maven runner comes with a ready-to-use `dokka:javadocJar` +goal. By default, it generates documentation in [Javadoc](javadoc.md) output format in the`target` folder. + +If you are not satisfied with the built-in goal or want to customize the output (for example, you want to generate documentation in [HTML](html.md) format instead of Javadoc), similar behavior can be achieved by adding the Maven JAR plugin with the following configuration: @@ -116,12 +123,19 @@ Maven JAR plugin with the following configuration: ``` -The documentation and the `.jar` archive for it is then generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: +The documentation and the `.jar` archive for it are then generated by running `dokka:dokka` and `jar:jar@dokka-jar` goals: ```Bash mvn dokka:dokka jar:jar@dokka-jar ``` +> If you publish your library to Maven Central, you can use services like [javadoc.io](https://javadoc.io/) to +> host your library's API documentation for free and without any setup. It takes documentation pages straight +> from the `javadoc.jar`. It works well with the HTML format as demonstrated in +> [this example](https://javadoc.io/doc/com.trib3/server/latest/index.html). +> +{type="tip"} + ## Configuration Maven's plugin configuration block can be used to configure Dokka. @@ -141,7 +155,7 @@ Here is an example of a basic configuration that only changes the output locatio ## Configuration options -Dokka has many configuration options to tailor your experience. +Dokka has many configuration options to tailor your and your reader's experience. Below are some examples and detailed descriptions for each configuration section. You can also find an example with [all configuration options](#complete-configuration) applied. @@ -162,7 +176,7 @@ with [all configuration options](#complete-configuration) applied. false false - ${project.basedir}/src/main/kotlin + ${project.basedir}/src PUBLIC @@ -211,7 +225,7 @@ with [all configuration options](#complete-configuration) applied.

    Default: {project.artifactId}.

    -

    The directory where documentation is generated.

    +

    The directory to where documentation is generated, regardless of format.

    Default: {project.basedir}/target/dokka.

    @@ -229,7 +243,7 @@ with [all configuration options](#complete-configuration) applied.
  • Inherited from kotlin.Any, Kotlin.Enum, java.lang.Object or - java.lang.Enum, such as equals, hashCode, toString`. + java.lang.Enum, such as equals, hashCode, toString.
  • Synthetic (generated by the compiler) and does not have any documentation, such as @@ -249,19 +263,19 @@ with [all configuration options](#complete-configuration) applied.

    Default: false.

    -

    Whether to resolve remote files/links over network.

    +

    Whether to resolve remote files/links over your network.

    - This includes package-lists used for generating external documentation links: - for instance, to make classes from standard library clickable. + This includes package-lists used for generating external documentation links. + For example, to make classes from the standard library clickable.

    Setting this to true can significantly speed up build times in certain cases, - but can also worsen documentation quality and user experience, for example by - not resolving some dependency's class/member links. + but can also worsen documentation quality and user experience. For example, by + not resolving class/member links from your dependencies, including the standard library.

    - When using offline mode, you can cache fetched files locally and provide them to - Dokka as local paths, see externalDocumentationLinks section. + Note: you can cache fetched files locally and provide them to + Dokka as local paths. See externalDocumentationLinks section.

    Default: false.

    @@ -283,8 +297,8 @@ with [all configuration options](#complete-configuration) applied.

    - Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs - after they have been filtered by documentedVisibilities. + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities and other filters.

    This setting works well with failOnWarning.

    This can be overridden at package level.

    @@ -296,10 +310,14 @@ with [all configuration options](#complete-configuration) applied.

    Default: false.

    -

    Whether to skip packages that contain no visible declarations after various filters have been applied.

    - For example, if skipDeprecated is set to true and your package contains only - deprecated declarations, it is considered empty.

    + Whether to skip packages that contain no visible declarations after + various filters have been applied. +

    +

    + For example, if skipDeprecated is set to true and your package contains only + deprecated declarations, it is considered to be empty. +

    Default: true.

    @@ -311,8 +329,8 @@ with [all configuration options](#complete-configuration) applied.

    The JDK version to use when generating external documentation links for Java types.

    - For example, if you use java.util.UUID from JDK in some public declaration signature, - and this property is set to 8, Dokka generates an external documentation link + For example, if you use java.util.UUID in some public declaration signature, + and this option is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    Default: JDK 8.

    @@ -335,16 +353,16 @@ with [all configuration options](#complete-configuration) applied.

    - Whether to generate external documentation links that lead to API reference - documentation for Kotlin's standard library when declarations from it are used. + Whether to generate external documentation links that lead to the API reference + documentation of Kotlin's standard library.

    -

    Links are generated when `noStdLibLink` is set to false.

    +

    Note: links are generated when noStdLibLink is set to false.

    Default: false.

    -

    Whether to generate external documentation links to JDK's Javadocs when declarations from it are used.

    -

    The version of JDK Javadocs is determined by jdkVersion property.

    -

    Links are generated when `noJdkLink` is set to false.

    +

    Whether to generate external documentation links to JDK's Javadocs.

    +

    The version of JDK Javadocs is determined by the jdkVersion option.

    +

    Note: links are generated when noJdkLink is set to false.

    Default: false

    @@ -358,7 +376,7 @@ with [all configuration options](#complete-configuration) applied.

    The classpath for analysis and interactive samples.

    This is useful if some types that come from dependencies are not resolved/picked up automatically. - The property accepts both .jar and .klib files. + This option accepts both .jar and .klib files.

    Default: {project.compileClasspathElements}.

    @@ -372,13 +390,14 @@ with [all configuration options](#complete-configuration) applied. ### Source link configuration -The `sourceLinks` configuration block is where you can add a `source` link to each signature -that leads to a `remoteUrl` with a specific line number. (The line number is configurable by setting `remoteLineSuffix`). +The `sourceLinks` configuration block allows you to add a `source` link to each signature +that leads to the `url` with a specific line number. (The line number is configurable by setting `lineSuffix`). + This helps readers to find the source code for each declaration. -For an example, see documentation for -[count](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) -function from `kotlinx.coroutines`. +For an example, see the documentation for the +[`count()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/count.html) +function in `kotlinx.coroutines`. ```xml @@ -388,8 +407,8 @@ function from `kotlinx.coroutines`. - ${project.basedir}/src/main/kotlin - https://github.com/kotlin/dokka/tree/master/src/main/kotlin + ${project.basedir}/src + https://github.com/kotlin/dokka/tree/master/src #L @@ -406,8 +425,9 @@ function from `kotlinx.coroutines`.

    - The URL of the source code hosting service that can be accessed by documentation readers, like GitHub, GitLab, - Bitbucket, etc. This URL is used to generate source code links of declarations. + The URL of the source code hosting service that can be accessed by documentation readers, + like GitHub, GitLab, Bitbucket, etc. This URL is used to generate + source code links of declarations.

    @@ -416,7 +436,7 @@ function from `kotlinx.coroutines`. to the file, but to the specific line number of the declaration.

    - The number itself is appended to the specified suffix. For example, if this property is set + The number itself is appended to the specified suffix. For example, if this option is set to #L and the line number is 10, the resulting URL suffix is #L10.

    @@ -432,13 +452,16 @@ function from `kotlinx.coroutines`. #### External documentation links configuration -The `externalDocumentationLinks` block allows the creation of links that lead to the externally hosted documentation of your dependencies. +The `externalDocumentationLink` block allows the creation of links that lead to the externally hosted documentation of +your dependencies. -For example, if you are using types from `kotlinx.serialization`, by default they are be unclickable in your -documentation, as if they are unresolved. However, since the API reference for `kotlinx.serialization` is also built by Dokka and is -[published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can configure external -documentation links for it. Thus allowing Dokka to generate links for types, making them clickable -and resolve successfully. +For example, if you are using types from `kotlinx.serialization`, by default they are unclickable in your +documentation, as if they are unresolved. However, since the API reference documentation for `kotlinx.serialization` +is built by Dokka and is [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/), you can +configure external documentation links for it. Thus allowing Dokka to generate links for types from the library, making +them resolve successfully and clickable. + +By default, external documentation links for Kotlin standard library and JDK are configured. ```xml @@ -458,27 +481,32 @@ and resolve successfully. -

    The root URL of documentation to link with. It **must** contain a trailing slash.

    +

    The root URL of documentation to link to. It must contain a trailing slash.

    - Dokka does its best to automatically find the package-list for the given URL + Dokka does its best to automatically find the package-list for the given URL, and link declarations together.

    If automatic resolution fails or if you want to use locally cached files instead, - consider providing the packageListUrl. + consider setting the packageListUrl option.

    The exact location of a package-list. This is an alternative to relying on Dokka - automatically resolving it. This can also be a locally cached file to avoid network calls. + automatically resolving it. +

    +

    + Package lists contain information about the documentation and the project itself, + such as module and package names.

    +

    This can also be a locally cached file to avoid network calls.

    ### Package options -The `packageOptions` configuration block allows you to set some options for specific packages matched by `matchingRegex`. +The `perPackageOptions` configuration block allows setting some options for specific packages matched by `matchingRegex`. ```xml @@ -508,17 +536,17 @@ The `packageOptions` configuration block allows you to set some options for spec

    The regular expression that is used to match the package.

    -

    Default: any string: .*.

    -
    +

    Default: .*.

    +

    Whether this package should be skipped when generating documentation.

    Default: false.

    -

    A list of visibility modifiers that should be documented.

    +

    The set of visibility modifiers that should be documented.

    - This can be used if you want to document protected/internal/private declarations within a - specific package, as well as if you want to exclude public declarations and only document internal API. + This can be used if you want to document protected/internal/private declarations within this package, + as well as if you want to exclude public declarations and only document internal API.

    Default: PUBLIC.

    @@ -529,8 +557,8 @@ The `packageOptions` configuration block allows you to set some options for spec

    - Whether to emit warnings about visible undocumented declarations, that is declarations from - this package and without KDocs, after they have been filtered by documentedVisibilities. + Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs + after they have been filtered by documentedVisibilities and other filters.

    This setting works well with failOnWarning.

    Default: false.

    @@ -555,7 +583,7 @@ Below you can see all the possible configuration options applied at the same tim false false - ${project.basedir}/src/main/kotlin + ${project.basedir}/src PUBLIC @@ -586,8 +614,8 @@ Below you can see all the possible configuration options applied at the same tim - ${project.basedir}/src/main/kotlin - https://github.com/kotlin/dokka/tree/master/src/main/kotlin + ${project.basedir}/src + https://github.com/kotlin/dokka/tree/master/src #L diff --git a/examples/maven/pom.xml b/examples/maven/pom.xml index 40525fdbf6..74675d6d01 100644 --- a/examples/maven/pom.xml +++ b/examples/maven/pom.xml @@ -21,7 +21,7 @@ - ${project.basedir}/src/main/kotlin + ${project.basedir}/src diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt index 8e118767b2..4a0c133379 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt @@ -18,7 +18,7 @@ import java.net.URL * ```kotlin * sourceLink { * localDirectory.set(projectDir.resolve("src")) - * remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src/main/kotlin")) + * remoteUrl.set(URL("https://github.com/kotlin/dokka/tree/master/src")) * remoteLineSuffix.set("#L") * } * ``` @@ -48,7 +48,7 @@ class GradleSourceLinkBuilder( * Example: * * ```kotlin - * java.net.URL("https://github.com/username/projectname/tree/master/src/main/kotlin")) + * java.net.URL("https://github.com/username/projectname/tree/master/src")) * ``` */ @Input diff --git a/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt b/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt index bd6d3baee5..621b38d85c 100644 --- a/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt +++ b/runners/maven-plugin/src/main/kotlin/SourceLinkMapItem.kt @@ -12,8 +12,8 @@ import org.apache.maven.plugins.annotations.Parameter * ```xml * * - * ${project.basedir}/src/main/kotlin - * https://github.com/kotlin/dokka/tree/master/src/main/kotlin + * ${project.basedir}/src + * https://github.com/kotlin/dokka/tree/master/src * #L * * @@ -27,7 +27,7 @@ class SourceLinkMapItem { * Example: * * ```xml - * ${project.basedir}/src/main/kotlin + * ${project.basedir}/src * ``` */ @Parameter(name = "path", required = true) @@ -41,7 +41,7 @@ class SourceLinkMapItem { * Example: * * ```xml - * https://github.com/username/projectname/tree/master/src/main/kotlin + * https://github.com/username/projectname/tree/master/src * ``` */ @Parameter(name = "url", required = true) From a4da9d5a55948c7cfe724766926b1a2eae71c10a Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Thu, 22 Dec 2022 06:31:50 +0100 Subject: [PATCH 08/14] Update project configuration for docs --- docs/cfg/build-script.xml | 10 --------- docs/cfg/buildprofiles.xml | 42 +++++------------------------------- docs/dokka.tree | 34 +++++++++++++++-------------- docs/project.ihp | 8 +++++-- docs/topics/get_started.md | 8 +++---- docs/topics/overview.md | 2 ++ docs/topics/runners/maven.md | 5 +++-- 7 files changed, 38 insertions(+), 71 deletions(-) delete mode 100644 docs/cfg/build-script.xml diff --git a/docs/cfg/build-script.xml b/docs/cfg/build-script.xml deleted file mode 100644 index 8911c1e087..0000000000 --- a/docs/cfg/build-script.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/docs/cfg/buildprofiles.xml b/docs/cfg/buildprofiles.xml index 614e57fe7d..86c3ad592b 100644 --- a/docs/cfg/buildprofiles.xml +++ b/docs/cfg/buildprofiles.xml @@ -2,41 +2,9 @@ - blue_romb_blt.png - seealso_blt.gif - topic.gif - folder.gif - note.gif - notice_purple.gif - tip.gif - mark.gif - iconpdf.png - moveUp.gif - hr.gif - bg_idea_big.jpg - IDEA.gif - images - printable.png - css - blt_pdf.png - http://www.jetbrains.com/idea/ - Developer Community:http://www.jetbrains.net/devnet/community/idea/kb - - 2 - jetbrains - true - true - true - null - https://support.jetbrains.com - webmaster@jetbrains.com - true - https://www.jetbrains.com/search/json/ + true + https://github.com/Kotlin/dokka/edit/master/docs/ + true - - - - topic.web.new.xsl - - - \ No newline at end of file + + diff --git a/docs/dokka.tree b/docs/dokka.tree index db1a933e9a..a27733515f 100644 --- a/docs/dokka.tree +++ b/docs/dokka.tree @@ -2,21 +2,23 @@ - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/docs/project.ihp b/docs/project.ihp index b60dede74d..f9ab9b9edb 100644 --- a/docs/project.ihp +++ b/docs/project.ihp @@ -2,9 +2,13 @@ - + + - + + + + diff --git a/docs/topics/get_started.md b/docs/topics/get_started.md index 1eb743a5d0..b8efb33f9b 100644 --- a/docs/topics/get_started.md +++ b/docs/topics/get_started.md @@ -1,6 +1,6 @@ [//]: # (title: Get started) -TODO add an introduction of some sort? +Below you can find simple instructions to help you get started with Dokka. @@ -29,7 +29,7 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about Gradle configuration, see [Gradle](gradle.md). +To learn more about the Gradle runner, see [Gradle](gradle.md). @@ -58,7 +58,7 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about Gradle configuration, see [Gradle](gradle.md). +To learn more about the Gradle runner, see [Gradle](gradle.md). @@ -89,7 +89,7 @@ To generate documentation, run the `dokka:dokka` goal. By default, the output directory is set to `target/dokka`. -To learn more about Maven configuration, see [Maven](maven.md). +To learn more about the Maven runner, see [Maven](maven.md). diff --git a/docs/topics/overview.md b/docs/topics/overview.md index d52a636e92..b254aa87ed 100644 --- a/docs/topics/overview.md +++ b/docs/topics/overview.md @@ -20,6 +20,8 @@ Some libraries that use Dokka for their API reference documentation: You can run Dokka using [Gradle](gradle.md), [Maven](maven.md) or from the [command line](cli.md). It is also [highly pluggable](dokka_plugins.md). +See [Get started](get_started.md) to take the first steps in using Dokka. + ## Community Dokka has a dedicated `#dokka` channel in [Kotlin Community Slack](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up) diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index 40bb9306f8..3b65a77e3f 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -55,9 +55,10 @@ The following goals are provided by the plugin: By default, the Maven runner builds documentation in [HTML](html.md) output format. -All other output formats come as [Dokka plugins](dokka_plugins.md). In order to use them, you have to apply TODO +All other output formats come as [Dokka plugins](dokka_plugins.md). In order to generate documentation in the desired +format, you have to add it as a Dokka plugin to the configuration. -For example, to use the experimental [GFM](markdown.md#gfm) format, you have to apply `org.jetbrains.dokka:gfm-plugin` in TODO +For example, to use the experimental [GFM](markdown.md#gfm) format, you have to add `gfm-plugin` artifact: ```xml From 317dea25b0a797a99c4eda334899f7cd63f6dd66 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Wed, 4 Jan 2023 09:37:55 +0100 Subject: [PATCH 09/14] Fix review comments --- docs/dokka.tree | 4 +- docs/topics/dokka_plugins.md | 13 +- docs/topics/formats/html.md | 9 +- docs/topics/formats/javadoc.md | 19 +-- docs/topics/formats/markdown.md | 40 +++--- docs/topics/get_started.md | 16 +-- docs/topics/{overview.md => introduction.md} | 6 +- docs/topics/runners/cli.md | 127 ++++++++---------- docs/topics/runners/gradle.md | 72 +++++----- docs/topics/runners/maven.md | 34 ++--- .../org/jetbrains/dokka/gfm/GfmPlugin.kt | 5 +- .../jetbrains/dokka/javadoc/JavadocPlugin.kt | 6 +- .../jekyll/src/main/kotlin/JekyllPlugin.kt | 5 +- 13 files changed, 182 insertions(+), 174 deletions(-) rename docs/topics/{overview.md => introduction.md} (87%) diff --git a/docs/dokka.tree b/docs/dokka.tree index a27733515f..bf5501eed0 100644 --- a/docs/dokka.tree +++ b/docs/dokka.tree @@ -4,10 +4,10 @@ + start-page="introduction.md"> - + diff --git a/docs/topics/dokka_plugins.md b/docs/topics/dokka_plugins.md index 06dbcdf03c..dbac9e9381 100644 --- a/docs/topics/dokka_plugins.md +++ b/docs/topics/dokka_plugins.md @@ -30,7 +30,7 @@ to your project: -The Dokka Gradle runner creates convenient dependency configurations that allow you to apply plugins universally or +The Gradle plugin for Dokka creates convenient dependency configurations that allow you to apply plugins universally or for a specific output format only. ```kotlin @@ -54,7 +54,7 @@ dependencies { -The Dokka Gradle runner creates convenient dependency configurations that allow you to apply Dokka plugins universally or +The Gradle plugin for Dokka creates convenient dependency configurations that allow you to apply Dokka plugins universally or for a specific output format only. ```groovy @@ -127,8 +127,8 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), D ## Configuring Dokka plugins -Dokka plugins can also have configuration options of their own. To see which options are available, consult -documentation of the plugin you want to configure. +Dokka plugins can also have configuration options of their own. To see which options are available, consult documentation +of the plugins you are using. Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](html.md) documentation, by adding a custom image to the assets (`customAssets` option), by adding custom style sheets @@ -264,6 +264,8 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), t ## Notable plugins +Here are some notable Dokka plugins that you might find useful: + | **Name** | **Description** | |-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | [Android documentation plugin](https://github.com/Kotlin/dokka/tree/master/plugins/android-documentation) | Improves the documentation experience on Android | @@ -271,3 +273,6 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), t | [MermaidJS HTML plugin](https://github.com/glureau/dokka-mermaid) | Renders [MermaidJS](https://mermaid-js.github.io/mermaid/#/) diagrams and visualizations found in KDocs | | [Mathjax HTML plugin](https://github.com/Kotlin/dokka/tree/master/plugins/mathjax) | Pretty prints mathematics found in KDocs | | [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | + +If you are a Dokka plugin author and would like to add your plugin to this list, get in touch with maintainers +via [Slack](introduction.md#community) or [GitHub](https://github.com/Kotlin/dokka/). \ No newline at end of file diff --git a/docs/topics/formats/html.md b/docs/topics/formats/html.md index f4fbdb2c9d..d7ed9fcdda 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/html.md @@ -5,7 +5,9 @@ for [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/). ## Generating HTML documentation -HTML as an output format is supported by all runners. To generate HTML documentation, follow these steps depending on your runner: +HTML as an output format is supported by all runners. To generate HTML documentation, follow these steps depending on +your build tool or runner: + * For [Gradle](gradle.md#generating-documentation), run `dokkaHtml` or `dokkaHtmlMultiModule` tasks. * For [Maven](maven.md#generating-documentation), run the `dokka:dokka` goal. * For [CLI runner](cli.md#generating-documentation), run with HTML dependencies set. @@ -212,10 +214,9 @@ You can find all images used by Dokka on ### Changing the logo To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. -If your image has similar size, it should not look out of place. -However, if your image has different dimensions or you want to use a `.png` file instead of the default `.svg` file, -you can [override the `logo-styles.css` stylesheet](#customizing-styles) and make it fit. +If you don't like how it looks, or you want to use a `.png` file instead of the default `.svg` file, +you can [override the `logo-styles.css` stylesheet](#customizing-styles) to customize it. For an example of how to do this, see our [custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). diff --git a/docs/topics/formats/javadoc.md b/docs/topics/formats/javadoc.md index a5e6116d5d..2f11fb21e1 100644 --- a/docs/topics/formats/javadoc.md +++ b/docs/topics/formats/javadoc.md @@ -1,7 +1,8 @@ [//]: # (title: Javadoc) -> The Javadoc output format is still in Alpha so you may find bugs and experience migration issues when using it. **You use it at your own risk.** +> The Javadoc output format is still in Alpha so you may find bugs and experience migration issues when using it. > Successful integration with tools that accept Java's Javadoc HTML as input is not guaranteed. +> **You use it at your own risk.** > {type="warning"} @@ -17,7 +18,7 @@ All Kotlin code and signatures are rendered as seen from Java's perspective. Thi [Kotlin as Java Dokka plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and applied by default for this format. -The Javadoc output format itself is a [Dokka plugin](dokka_plugins.md), and it is maintained by the Dokka team. +The Javadoc output format is implemented as a [Dokka plugin](dokka_plugins.md), and it is maintained by the Dokka team. It is open source and you can find the source code on [GitHub](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). ## Generating Javadoc documentation @@ -30,19 +31,19 @@ It is open source and you can find the source code on [GitHub](https://github.co -Dokka's [Gradle runner](gradle.md) comes with the Javadoc output format included. You can use the following tasks: +The [Gradle plugin for Dokka](gradle.md) comes with the Javadoc output format included. You can use the following tasks: -| **Task** | **Description** | -|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaJavadoc` | Generates Javadoc documentation for a single project. | -| `dokkaJavadocCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJavadoc` | Generates Javadoc documentation for a single project. | +| `dokkaJavadocCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | The `javadoc.jar` file can be generated separately. For more information, see [Building `javadoc.jar`](gradle.md#building-javadoc-jar). -Dokka's [Maven runner](maven.md) comes with the Javadoc output format built in. You can generate documentation +The [Maven plugin for Dokka](maven.md) comes with the Javadoc output format built in. You can generate documentation by using the following goals: | **Goal** | **Description** | @@ -86,7 +87,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see [Other output formats](cli.md#other-output-formats) in the CLI runner documentation. +For more information, see [Other output formats](cli.md#other-output-formats) in the CLI runner's documentation. diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/markdown.md index fb7ed094ca..b0d215472c 100644 --- a/docs/topics/formats/markdown.md +++ b/docs/topics/formats/markdown.md @@ -10,7 +10,7 @@ These formats give you more freedom in terms of hosting documentation as the out documentation website. For example, see [OkHttp's API reference](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) pages. -Markdown output formats are rendering [Dokka plugins](dokka_plugins.md), maintained by the Dokka team, and +Markdown output formats are implemented as [Dokka plugins](dokka_plugins.md), maintained by the Dokka team, and they are open source. ## GFM @@ -20,18 +20,18 @@ The GFM output format generates documentation in [GitHub Flavored Markdown](http -Dokka's [Gradle runner](gradle.md) comes with the GFM output format included. You can use the following tasks with it: +The [Gradle plugin for Dokka](gradle.md) comes with the GFM output format included. You can use the following tasks with it: -| **Task** | **Description** | -|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaGfm` | Generates GFM documentation for a single project. | -| `dokkaGfmMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaGfmCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaGfm` | Generates GFM documentation for a single project. | +| `dokkaGfmMultiModule` | A [`MultiModule`](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaGfmCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | -Since GFM format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin +Since GFM format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -58,7 +58,7 @@ For more information, see the Mavin plugin documentation for [Other output forma -Since GFM format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +Since GFM format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) and pass it to `pluginsClasspath`. @@ -84,7 +84,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see the CLI runner documentation for [Other output formats](cli.md#other-output-formats). +For more information, see the CLI runner's documentation for [Other output formats](cli.md#other-output-formats). @@ -98,18 +98,18 @@ The Jekyll output format generates documentation in [Jekyll](https://jekyllrb.co -Dokka's [Gradle runner](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: +The [Gradle plugin for Dokka](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: -| **Task** | **Description** | -|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dokkaJekyll` | Generates Jekyll documentation for a single project. | -| `dokkaJekyllMultiModule` | A [MultiModule](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaJekyllCollector` | A [Collector](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | +| **Task** | **Description** | +|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dokkaJekyll` | Generates Jekyll documentation for a single project. | +| `dokkaJekyllMultiModule` | A [`MultiModule`](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaJekyllCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | -Since Jekyll format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin +Since Jekyll format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -131,12 +131,12 @@ dependency: After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see the Maven runner documentation for [Other output formats](maven.md#other-output-formats). +For more information, see the Maven plugin's documentation for [Other output formats](maven.md#other-output-formats). -Since Jekyll format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +Since Jekyll format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/jekyll-plugin/%dokkaVersion%). This format is also based on [GFM](#gfm) format, so you need to provide it as a dependency as well. Both JARs need to be passed to `pluginsClasspath`: @@ -164,7 +164,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see the CLI runner documentation for [Other output formats](cli.md#other-output-formats). +For more information, see the CLI runner's documentation for [Other output formats](cli.md#other-output-formats). diff --git a/docs/topics/get_started.md b/docs/topics/get_started.md index b8efb33f9b..35525ac57e 100644 --- a/docs/topics/get_started.md +++ b/docs/topics/get_started.md @@ -5,7 +5,7 @@ Below you can find simple instructions to help you get started with Dokka. -Apply the Dokka Gradle plugin in the root build script of your project: +Apply the Gradle plugin for Dokka in the root build script of your project: ```kotlin plugins { @@ -14,7 +14,7 @@ plugins { ``` When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need -to apply the Dokka Gradle plugin within subprojects as well: +to apply the Gradle plugin within subprojects as well: ```kotlin subprojects { @@ -29,12 +29,12 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about the Gradle runner, see [Gradle](gradle.md). +To learn more about using Dokka with Gradle, see [Gradle](gradle.md). -Apply the Dokka Gradle plugin in the root build script of your project: +Apply the Gradle plugin for Dokka in the root build script of your project: ```groovy plugins { @@ -43,7 +43,7 @@ plugins { ``` When documenting [multi-project](https://docs.gradle.org/current/userguide/multi_project_builds.html) builds, you need -to apply the Dokka Gradle plugin within subprojects as well: +to apply the Gradle plugin within subprojects as well: ```groovy subprojects { @@ -58,12 +58,12 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about the Gradle runner, see [Gradle](gradle.md). +To learn more about using Dokka with Gradle, see [Gradle](gradle.md). -Add the Dokka Maven plugin to the `plugins` section of your POM file: +Add the Maven plugin for Dokka to the `plugins` section of your POM file: ```xml @@ -89,7 +89,7 @@ To generate documentation, run the `dokka:dokka` goal. By default, the output directory is set to `target/dokka`. -To learn more about the Maven runner, see [Maven](maven.md). +To learn more about using Dokka with Maven, see [Maven](maven.md). diff --git a/docs/topics/overview.md b/docs/topics/introduction.md similarity index 87% rename from docs/topics/overview.md rename to docs/topics/introduction.md index b254aa87ed..d6f8c3f9ad 100644 --- a/docs/topics/overview.md +++ b/docs/topics/introduction.md @@ -1,4 +1,4 @@ -[//]: # (title: Overview) +[//]: # (title: Introduction) Dokka is an API documentation engine for Kotlin. @@ -9,7 +9,7 @@ Just like Kotlin itself, Dokka supports mixed-language projects. It understands Dokka can generate documentation in multiple formats, including its own modern [HTML format](html.md), multiple flavors of [Markdown](markdown.md), and Java's [Javadoc HTML](javadoc.md). -Some libraries that use Dokka for their API reference documentation: +Here are some libraries that use Dokka for their API reference documentation: * [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/) * [Bitmovin](https://cdn.bitmovin.com/player/android/3/docs/index.html) @@ -20,7 +20,7 @@ Some libraries that use Dokka for their API reference documentation: You can run Dokka using [Gradle](gradle.md), [Maven](maven.md) or from the [command line](cli.md). It is also [highly pluggable](dokka_plugins.md). -See [Get started](get_started.md) to take the first steps in using Dokka. +See [Get started](get_started.md) to take your first steps in using Dokka. ## Community diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/cli.md index e0ef7d3208..183498eda9 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/cli.md @@ -3,7 +3,7 @@ If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) build tools, Dokka has a command line (CLI) runner for generating documentation. -In comparison, it has the same, if not more, capabilities as the Gradle runner. Although it is considerably more +In comparison, it has the same, if not more, capabilities as the Gradle plugin for Dokka. Although it is considerably more difficult to set up as there is no autoconfiguration, especially in multiplatform and multi-module environments. ## Getting started @@ -86,6 +86,7 @@ java -jar dokka-cli-%dokkaVersion%.jar dokka-configuration.json ``` At the very least, you need the following JSON configuration file: + ```json { "outputDir": "./dokka/html", @@ -122,7 +123,7 @@ See [JSON configuration options](#json-configuration) for more details. By default, the `dokka-base` artifact contains the [HTML](html.md) output format only. -All other output formats come as [Dokka plugins](dokka_plugins.md). In order to use them, you have to put them +All other output formats are implemented as [Dokka plugins](dokka_plugins.md). In order to use them, you have to put them on the plugins classpath. For example, if you want to generate documentation in the experimental [GFM](markdown.md#gfm) output format, you need to download and @@ -153,7 +154,7 @@ Via JSON configuration: With the GFM plugin passed to `pluginsClasspath`, the CLI runner generates documentation in the GFM output format. -For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#generating-javadoc-documentation). +For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#generating-javadoc-documentation) pages. ## Command line options @@ -165,32 +166,26 @@ java -jar dokka-cli-%dokkaVersion%.jar -help Short summary: -- `-moduleName` -> Name of the project/module. -- `-moduleVersion` -> Documented version. -- `-outputDir` -> Output directory path, `./dokka` by default. -- `-sourceSet` -> Configuration for a Dokka source set. Contains nested configuration options. -- `-pluginsConfiguration` -> Configuration for Dokka plugins. -- `-pluginsClasspath` -> List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons. -- `-offlineMode` -> Whether to resolve remote files/links over network. -- `-failOnWarning` -> Whether to fail documentation generation if Dokka has emitted a warning or an error. -- `-delayTemplateSubstitution` -> Whether to delay substitution of some elements. Used in incremental builds of - multi-module projects. -- `-noSuppressObviousFunctions` -> Whether to suppress obvious functions such as those inherited from `kotlin.Any` - and `java.lang.Object`. -- `-includes` -> Markdown files that contain module and package documentation. Accepts multiple values separated by - semicolons. -- `-suppressInheritedMembers` -> Whether to suppress inherited members that aren't explicitly overridden in a - given class. -- `-globalPackageOptions` -> Global list of package configuration options in format - `"matchingRegex,-deprecated,-privateApi,+warnUndocumented,+suppress;+visibility:PUBLIC;..."`. - Accepts multiple values separated by semicolons. -- `-globalLinks` -> Global external documentation links in format `{url}^{packageListUrl}`. - Accepts multiple values separated by `^^`. -- `-globalSrcLink` -> Global mapping between a source directory and a Web service for browsing the code. - Accepts multiple paths separated by semicolons. -- `-helpSourceSet` -> Prints help for the nested `-sourceSet` configuration. -- `-loggingLevel` -> Logging level, possible values: `DEBUG, PROGRESS, INFO, WARN, ERROR`. -- `-help, -h` -> Usage info. +| Option | Description | +|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `moduleName` | Name of the project/module. | +| `moduleVersion` | Documented version. | +| `outputDir` | Output directory path, `./dokka` by default. | +| `sourceSet` | Configuration for a Dokka source set. Contains nested configuration options. | +| `pluginsConfiguration` | Configuration for Dokka plugins. | +| `pluginsClasspath` | List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons. | +| `offlineMode` | Whether to resolve remote files/links over network. | +| `failOnWarning` | Whether to fail documentation generation if Dokka has emitted a warning or an error. | +| `delayTemplateSubstitution` | Whether to delay substitution of some elements. Used in incremental builds of multi-module projects. | +| `noSuppressObviousFunctions` | Whether to suppress obvious functions such as those inherited from `kotlin.Any` and `java.lang.Object`. | +| `includes` | Markdown files that contain module and package documentation. Accepts multiple values separated by semicolons. | +| `suppressInheritedMembers` | Whether to suppress inherited members that aren't explicitly overridden in a given class. | +| `globalPackageOptions` | Global list of package configuration options in format `"matchingRegex,-deprecated,-privateApi,+warnUndocumented,+suppress;+visibility:PUBLIC;..."`. Accepts multiple values separated by semicolons. | +| `globalLinks` | Global external documentation links in format `{url}^{packageListUrl}`. Accepts multiple values separated by `^^`. | +| `globalSrcLink` | Global mapping between a source directory and a Web service for browsing the code. Accepts multiple paths separated by semicolons. | +| `helpSourceSet` | Prints help for the nested `-sourceSet` configuration. | +| `loggingLevel` | Logging level, possible values: `DEBUG, PROGRESS, INFO, WARN, ERROR`. | +| `help, h` | Usage info. | #### Source set options @@ -200,40 +195,36 @@ To see the list of command line options for the nested `-sourceSet` configuratio java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help ``` -Summary: - -- `-sourceSetName` -> Name of the source set. -- `-displayName` -> Display name of the source set, used both internally and externally. -- `-classpath` -> Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons. -- `-src` -> Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons. -- `-dependentSourceSets` -> Names of the dependent source sets in format `moduleName/sourceSetName`. - Accepts multiple paths separated by semicolons. -- `-samples` -> List of directories or files that contain sample functions. Accepts multiple paths separated by semicolons. -- `-includes` -> Markdown files that contain module and package documentation. Accepts multiple paths separated by semicolons. -- `-documentedVisibilities` -> Visibilities to be documented. Accepts multiple values separated by semicolons. - Possible values: `PUBLIC`, `PRIVATE`, `PROTECTED`, `INTERNAL`, `PACKAGE`. -- `-reportUndocumented` -> Whether to report undocumented declarations. -- `-noSkipEmptyPackages` -> Whether to create pages for empty packages. -- `-skipDeprecated` -> Whether to skip deprecated declarations. -- `-jdkVersion` -> Version of JDK to use for linking to JDK Javadocs. -- `-languageVersion` -> Language version used for setting up analysis and samples. -- `-apiVersion` -> Kotlin API version used for setting up analysis and samples. -- `-noStdlibLink` -> Whether to generate links to the Kotlin standard library. -- `-noJdkLink` -> Whether to generate links to JDK Javadocs. -- `-suppressedFiles` -> Paths to files to be suppressed. Accepts multiple paths separated by semicolons. -- `-analysisPlatform` -> Platform used for setting up analysis. -- `-perPackageOptions` -> List of package source set configurations in format - `matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...`. Accepts multiple values separated by semicolons. -- `-externalDocumentationLinks` -> External documentation links in format `{url}^{packageListUrl}`. - Accepts multiple values separated by `^^`. -- `-srcLink` -> Mapping between a source directory and a Web service for browsing the code. - Accepts multiple paths separated by semicolons. -- `-help`, `-h` -> Usage info +Short summary: + +| Option | Description | +|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `sourceSetName` | Name of the source set. | +| `displayName` | Display name of the source set, used both internally and externally. | +| `classpath` | Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons. | +| `src` | Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons. | +| `dependentSourceSets` | Names of the dependent source sets in format `moduleName/sourceSetName`. Accepts multiple paths separated by semicolons. | +| `samples` | List of directories or files that contain sample functions. Accepts multiple paths separated by semicolons. | +| `includes` | Markdown files that contain module and package documentation. Accepts multiple paths separated by semicolons. | +| `documentedVisibilities` | Visibilities to be documented. Accepts multiple values separated by semicolons. Possible values: `PUBLIC`, `PRIVATE`, `PROTECTED`, `INTERNAL`, `PACKAGE`. | +| `reportUndocumented` | Whether to report undocumented declarations. | +| `noSkipEmptyPackages` | Whether to create pages for empty packages. | +| `skipDeprecated` | Whether to skip deprecated declarations. | +| `jdkVersion` | Version of JDK to use for linking to JDK Javadocs. | +| `languageVersion` | Language version used for setting up analysis and samples. | +| `apiVersion` | Kotlin API version used for setting up analysis and samples. | +| `noStdlibLink` | Whether to generate links to the Kotlin standard library. | +| `noJdkLink` | Whether to generate links to JDK Javadocs. | +| `suppressedFiles` | Paths to files to be suppressed. Accepts multiple paths separated by semicolons. | +| `analysisPlatform` | Platform used for setting up analysis. | +| `perPackageOptions` | List of package source set configurations in format `matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...`. Accepts multiple values separated by semicolons. | +| `externalDocumentationLinks` | External documentation links in format `{url}^{packageListUrl}`. Accepts multiple values separated by `^^`. | +| `srcLink` | Mapping between a source directory and a Web service for browsing the code. Accepts multiple paths separated by semicolons. | ## JSON configuration Below are some examples and detailed descriptions for each configuration section. You can also find an example -with [all configuration options](#complete-configuration) applied. +with [all configuration options](#complete-configuration) applied at the bottom of the page. ### General configuration @@ -272,7 +263,7 @@ with [all configuration options](#complete-configuration) applied. } ``` - +

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    Default: root.

    @@ -313,7 +304,7 @@ with [all configuration options](#complete-configuration) applied.

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    - Note: this can suppress functions such as equals / hashCode / toString, + Note: This can suppress functions such as equals / hashCode / toString, but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that. @@ -332,7 +323,7 @@ with [all configuration options](#complete-configuration) applied. not resolving class/member links from your dependencies, including the standard library.

    - Note: you can cache fetched files locally and provide them to + Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    Default: false.

    @@ -429,7 +420,7 @@ How to configure Kotlin } ``` - +

    The display name used to refer to this source set.

    @@ -512,13 +503,13 @@ How to configure Kotlin Whether to generate external documentation links that lead to the API reference documentation of Kotlin's standard library.

    -

    Note: links are generated when noStdLibLink is set to false.

    +

    Note: Links are generated when noStdLibLink is set to false.

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs.

    The version of JDK Javadocs is determined by the jdkVersion option.

    -

    Note: links are generated when noJdkLink is set to false.

    +

    Note: Links are generated when noJdkLink is set to false.

    Default: false.

    @@ -603,7 +594,7 @@ You can configure source links for all source sets together at the same time, or } ``` - +

    The path to the local source directory.

    @@ -657,7 +648,7 @@ You can add package configurations for all source sets together at the same time } ``` - +

    The regular expression that is used to match the package.

    @@ -715,7 +706,7 @@ You can configure external documentation links for all source sets together at t } ``` - +

    The root URL of documentation to link to. It must contain a trailing slash.

    diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/gradle.md index 37fcde4e7e..ab11605775 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/gradle.md @@ -1,18 +1,18 @@ [//]: # (title: Gradle) To generate documentation for a Gradle-based project, you can use the -[Dokka Gradle plugin](https://plugins.gradle.org/plugin/org.jetbrains.dokka). +[Gradle plugin for Dokka](https://plugins.gradle.org/plugin/org.jetbrains.dokka). It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient [Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of -[configuration options](#configuration) to customize the output. +[configuration options](#configuration-example) to customize the output. You can play around with Dokka and see how it can be configured for various projects by visiting our [Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). ## Applying Dokka -The recommended way of applying the Dokka Gradle plugin is with the +The recommended way of applying the Gradle plugin for Dokka is with the [plugins DSL](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block): @@ -36,7 +36,7 @@ plugins { -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Dokka Gradle plugin +When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Gradle plugin for Dokka within subprojects as well. You can use `allprojects {}` or `subprojects {}` Gradle configurations to achieve that: @@ -60,17 +60,17 @@ subprojects { -> Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) to perform -> autoconfiguration of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) for -> which documentation is to be generated. Make sure to apply the Kotlin Gradle Plugin or +> Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin) +> to perform autoconfiguration of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) +> for which documentation is to be generated. Make sure to apply the Kotlin Gradle Plugin or > [configure source sets](#source-set-configuration) manually. > {type="note"} > If you are using Dokka in a > [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), -> you need to add the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle.html) as a dependency in order for -> it to work properly: +> you need to add the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin) +> as a dependency in order for it to work properly: > > > @@ -97,13 +97,13 @@ plugins. ## Generating documentation -Dokka's Gradle runner comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats built in. -It adds a number of tasks for generating documentation, both for [single](#single-project-builds) +The Gradle plugin for Dokka comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats +built in. It adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. -### Single project builds +### Single-project builds -Use the following tasks to build documentation for simple, single project applications and libraries: +Use the following tasks to build documentation for simple, single-project applications and libraries: #### Stable formats @@ -120,17 +120,17 @@ Use the following tasks to build documentation for simple, single project applic | `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | By default, generated documentation is located in the `build/dokka/{format}` directory of your project. -The output location, among other things, can be [configured](#configuration). +The output location, among other things, can be [configured](#configuration-example). ### Multi-project builds For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), make sure -that you [apply the Dokka Gradle plugin](#applying-dokka) within subprojects that you want to generate documentation +that you [apply the Gradle plugin for Dokka](#applying-dokka) within subprojects that you want to generate documentation for, as well as in their parent project. #### MultiModule tasks -`MultiModule` tasks generate documentation for each subproject individually via [Partial](#partial-tasks) tasks, +`MultiModule` tasks generate documentation for each subproject individually via [`Partial`](#partial-tasks) tasks, collect and process all outputs, and produce complete documentation with a common table of contents and resolved cross-project references. @@ -149,7 +149,7 @@ Dokka creates the following tasks for **parent** projects automatically: | `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) output format. | | `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) output format. | -> The [Javadoc](javadoc.md) output format does not have a `MultiModule` task, but a [Collector](#collector-tasks) task can +> The [Javadoc](javadoc.md) output format does not have a `MultiModule` task, but a [`Collector`](#collector-tasks) task can > be used instead. > {type="note"} @@ -182,11 +182,11 @@ for more details. Similar to `MultiModule` tasks, `Collector` tasks are created for each parent project: `dokkaHtmlCollector`, `dokkaGfmCollector`, `dokkaJavadocCollector` and `dokkaJekyllCollector`. -A `Collector` task executes the corresponding [single project task](#single-project-builds) for each subproject (for +A `Collector` task executes the corresponding [single-project task](#single-project-builds) for each subproject (for example, `dokkaHtml`), and merges all outputs into a single virtual project. -The resulting documentation looks as if you have a single project +The resulting documentation looks as if you have a single-project build that contains all declarations from the subprojects. > Use the `dokkaJavadocCollector` task if you need to create Javadoc documentation for your multi-project build. @@ -225,12 +225,12 @@ These tasks are not intended to be used independently and exist only to be calle Output generated by `Partial` tasks contains unresolved HTML templates and references, so it cannot be used on its own without post-processing done by the `MultiModule` task. -However, you can [configure](#configuration) `Partial` tasks to customize Dokka on a per-project basis. +However, you can [configure](#configuration-example) `Partial` tasks to customize Dokka on a per-project basis. For example, your subprojects can have different configurations of documented visibilities, where one of the subprojects allows documenting `protected` declarations, while others do not. > If you want to generate documentation for a single subproject only, use -> [single project tasks](#single-project-builds). For example, `:subprojectName:dokkaHtml`. +> [single-project tasks](#single-project-builds). For example, `:subprojectName:dokkaHtml`. ## Building javadoc.jar @@ -241,7 +241,7 @@ For example, if you want to publish to [Maven Central](https://central.sonatype. [must](https://central.sonatype.org/publish/requirements/) supply a `javadoc.jar` alongside your project. However, not all repositories have that rule. -Dokka's Gradle runner does not provide any way to do this out of the box, but it can be achieved with custom Gradle +The Gradle plugin for Dokka does not provide any way to do this out of the box, but it can be achieved with custom Gradle tasks. One for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: @@ -288,7 +288,7 @@ tasks.register('dokkaJavadocJar', Jar.class) { > {type="tip"} -## Configuration +## Configuration example You can configure tasks and output formats individually: @@ -332,8 +332,8 @@ dokkaHtmlPartial { -Alternatively, you can configure all tasks and output formats at the same time, including [MultiModule](#multi-project-builds), -[Partial](#partial-tasks) and [Collector](#collector-tasks) tasks: +Alternatively, you can configure all tasks and output formats at the same time, including [`MultiModule`](#multi-project-builds), +[`Partial`](#partial-tasks) and [`Collector`](#collector-tasks) tasks: @@ -419,7 +419,7 @@ subprojects { Dokka has many configuration options to tailor your and your reader's experience. Below are some examples and detailed descriptions for each configuration section. You can also find an example -with [all configuration options](#complete-configuration) applied. +with [all configuration options](#complete-configuration) applied at the bottom of the page. ### General configuration @@ -470,7 +470,7 @@ tasks.withType(DokkaTask.class) { - +

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    If set for a single-project build or a MultiModule task, it is used as the project name.

    @@ -519,7 +519,7 @@ tasks.withType(DokkaTask.class) {

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    - Note: this can suppress functions such as equals / hashCode / toString, + Note: This can suppress functions such as equals / hashCode / toString, but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that. @@ -538,7 +538,7 @@ tasks.withType(DokkaTask.class) { not resolving class/member links from your dependencies, including the standard library.

    - Note: you can cache fetched files locally and provide them to + Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    Default: false.

    @@ -659,7 +659,7 @@ tasks.withType(DokkaTask.class) {
    - +

    Whether this source set should be skipped when generating documentation.

    Default: false.

    @@ -747,19 +747,19 @@ tasks.withType(DokkaTask.class) { Whether to generate external documentation links that lead to the API reference documentation of Kotlin's standard library.

    -

    Note: links are generated when noStdLibLink is set to false.

    +

    Note: Links are generated when noStdLibLink is set to false.

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs.

    The version of JDK Javadocs is determined by the jdkVersion option.

    -

    Note: links are generated when noJdkLink is set to false.

    +

    Note: Links are generated when noJdkLink is set to false.

    Default: false.

    Whether to generate external documentation links to the Android SDK API reference

    This is only relevant in Android projects, ignored otherwise.

    -

    Note: links are generated when noAndroidSdkLink is set to false.

    +

    Note: Links are generated when noAndroidSdkLink is set to false.

    Default: false.

    @@ -867,7 +867,7 @@ tasks.withType(DokkaTask.class) { - +

    The path to the local source directory. The path must be relative to the root of @@ -966,7 +966,7 @@ tasks.withType(DokkaTask.class) { - +

    The regular expression that is used to match the package.

    Default: .*.

    @@ -1070,7 +1070,7 @@ tasks.withType(DokkaTask.class) { - +

    The root URL of documentation to link to. It must contain a trailing slash.

    diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/maven.md index 3b65a77e3f..e97d57ceda 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/maven.md @@ -1,8 +1,8 @@ [//]: # (title: Maven) -To generate documentation for a Maven-based project, you can use the [Dokka Maven plugin](#applying-dokka). +To generate documentation for a Maven-based project, you can use the Maven plugin for Dokka. -> Compared to the [Gradle runner](gradle.md), the Maven runner has only basic features and +> Compared to the [Gradle plugin for Dokka](gradle.md), the Maven plugin has only basic features and > does not provide support for multi-module builds. > {type="note"} @@ -36,7 +36,7 @@ To apply Dokka, you need to add `dokka-maven-plugin` to the `plugins` section of ## Generating documentation -The following goals are provided by the plugin: +The following goals are provided by the Maven plugin: ### Stable @@ -53,10 +53,10 @@ The following goals are provided by the plugin: ### Other output formats -By default, the Maven runner builds documentation in [HTML](html.md) output format. +By default, the Maven plugin for Dokka builds documentation in [HTML](html.md) output format. -All other output formats come as [Dokka plugins](dokka_plugins.md). In order to generate documentation in the desired -format, you have to add it as a Dokka plugin to the configuration. +All other output formats are implemented as [Dokka plugins](dokka_plugins.md). In order to generate documentation in the +desired format, you have to add it as a Dokka plugin to the configuration. For example, to use the experimental [GFM](markdown.md#gfm) format, you have to add `gfm-plugin` artifact: @@ -90,7 +90,7 @@ For example, if you want to publish to [Maven Central](https://central.sonatype. [must](https://central.sonatype.org/publish/requirements/) supply a `javadoc.jar` alongside your project. However, not all repositories have that rule. -Unlike the [Gradle runner](gradle.md#building-javadoc-jar), the Maven runner comes with a ready-to-use `dokka:javadocJar` +Unlike the [Gradle plugin for Dokka](gradle.md#building-javadoc-jar), the Maven plugin comes with a ready-to-use `dokka:javadocJar` goal. By default, it generates documentation in [Javadoc](javadoc.md) output format in the`target` folder. If you are not satisfied with the built-in goal or want to customize the output (for example, you want to generate @@ -137,7 +137,7 @@ mvn dokka:dokka jar:jar@dokka-jar > {type="tip"} -## Configuration +## Configuration example Maven's plugin configuration block can be used to configure Dokka. @@ -159,7 +159,7 @@ Here is an example of a basic configuration that only changes the output locatio Dokka has many configuration options to tailor your and your reader's experience. Below are some examples and detailed descriptions for each configuration section. You can also find an example -with [all configuration options](#complete-configuration) applied. +with [all configuration options](#complete-configuration) applied at the bottom of the page. ### General configuration @@ -216,7 +216,7 @@ with [all configuration options](#complete-configuration) applied. ``` - +

    Whether to skip documentation generation.

    Default: false.

    @@ -257,7 +257,7 @@ with [all configuration options](#complete-configuration) applied.

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    - Note: this can suppress functions such as equals/hashCode/toString, + Note: This can suppress functions such as equals/hashCode/toString, but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that.

    @@ -275,7 +275,7 @@ with [all configuration options](#complete-configuration) applied. not resolving class/member links from your dependencies, including the standard library.

    - Note: you can cache fetched files locally and provide them to + Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    Default: false.

    @@ -357,13 +357,13 @@ with [all configuration options](#complete-configuration) applied. Whether to generate external documentation links that lead to the API reference documentation of Kotlin's standard library.

    -

    Note: links are generated when noStdLibLink is set to false.

    +

    Note: Links are generated when noStdLibLink is set to false.

    Default: false.

    Whether to generate external documentation links to JDK's Javadocs.

    The version of JDK Javadocs is determined by the jdkVersion option.

    -

    Note: links are generated when noJdkLink is set to false.

    +

    Note: Links are generated when noJdkLink is set to false.

    Default: false

    @@ -417,7 +417,7 @@ function in `kotlinx.coroutines`.
    ``` - +

    The path to the local source directory. The path must be relative to the root of the @@ -480,7 +480,7 @@ By default, external documentation links for Kotlin standard library and JDK are ``` - +

    The root URL of documentation to link to. It must contain a trailing slash.

    @@ -534,7 +534,7 @@ The `perPackageOptions` configuration block allows setting some options for spec ``` - +

    The regular expression that is used to match the package.

    Default: .*.

    diff --git a/plugins/gfm/src/main/kotlin/org/jetbrains/dokka/gfm/GfmPlugin.kt b/plugins/gfm/src/main/kotlin/org/jetbrains/dokka/gfm/GfmPlugin.kt index b3610809ca..b382a4627b 100644 --- a/plugins/gfm/src/main/kotlin/org/jetbrains/dokka/gfm/GfmPlugin.kt +++ b/plugins/gfm/src/main/kotlin/org/jetbrains/dokka/gfm/GfmPlugin.kt @@ -43,7 +43,10 @@ class GfmPlugin : DokkaPlugin() { internal val alphaVersionNotifier by extending { CoreExtensions.postActions providing { ctx -> PostAction { - ctx.logger.info("GFM output format is in Alpha version, use at your own risk, expect bugs and migration issues") + ctx.logger.info( + "The GFM output format is still in Alpha so you may find bugs and experience migration " + + "issues when using it. You use it at your own risk." + ) } } } diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPlugin.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPlugin.kt index 19dfb5c0e3..358e4ca384 100644 --- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPlugin.kt +++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/JavadocPlugin.kt @@ -86,7 +86,11 @@ class JavadocPlugin : DokkaPlugin() { internal val alphaVersionNotifier by extending { CoreExtensions.postActions providing { ctx -> PostAction { - ctx.logger.info("Javadoc output format is in Alpha version, use at your own risk, expect bugs and migration issues") + ctx.logger.info( + "The Javadoc output format is still in Alpha so you may find bugs and experience migration " + + "issues when using it. Successful integration with tools that accept Java's Javadoc " + + "HTML as input is not guaranteed. You use it at your own risk." + ) } } } diff --git a/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt b/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt index a6cc6cba8d..1ae8803523 100644 --- a/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt +++ b/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt @@ -52,7 +52,10 @@ class JekyllPlugin : DokkaPlugin() { internal val alphaVersionNotifier by extending { CoreExtensions.postActions providing { ctx -> PostAction { - ctx.logger.info("Jekyll output format is in Alpha version, use at your own risk, expect bugs and migration issues") + ctx.logger.info( + "The Jekyll output format is still in Alpha so you may find bugs and experience migration " + + "issues when using it. You use it at your own risk." + ) } } } From a4baa433226470dad176cc0bdffaf50c2491b078 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Mon, 9 Jan 2023 11:58:51 +0100 Subject: [PATCH 10/14] Rename `*ing` headers and add `dokka` prefix to file names --- docs/dokka.tree | 20 +++++----- .../{get_started.md => dokka-get-started.md} | 6 +-- ...{introduction.md => dokka-introduction.md} | 10 ++--- .../{dokka_plugins.md => dokka-plugins.md} | 20 +++++----- .../topics/formats/{html.md => dokka-html.md} | 32 ++++++++-------- .../formats/{javadoc.md => dokka-javadoc.md} | 20 +++++----- .../{markdown.md => dokka-markdown.md} | 38 +++++++++---------- docs/topics/runners/{cli.md => dokka-cli.md} | 22 +++++------ .../runners/{gradle.md => dokka-gradle.md} | 32 ++++++++-------- .../runners/{maven.md => dokka-maven.md} | 28 +++++++------- 10 files changed, 114 insertions(+), 114 deletions(-) rename docs/topics/{get_started.md => dokka-get-started.md} (91%) rename docs/topics/{introduction.md => dokka-introduction.md} (73%) rename docs/topics/{dokka_plugins.md => dokka-plugins.md} (91%) rename docs/topics/formats/{html.md => dokka-html.md} (94%) rename docs/topics/formats/{javadoc.md => dokka-javadoc.md} (76%) rename docs/topics/formats/{markdown.md => dokka-markdown.md} (70%) rename docs/topics/runners/{cli.md => dokka-cli.md} (98%) rename docs/topics/runners/{gradle.md => dokka-gradle.md} (96%) rename docs/topics/runners/{maven.md => dokka-maven.md} (96%) diff --git a/docs/dokka.tree b/docs/dokka.tree index bf5501eed0..1825b6bcb6 100644 --- a/docs/dokka.tree +++ b/docs/dokka.tree @@ -4,21 +4,21 @@ + start-page="dokka-introduction.md"> - - + + - - - + + + - - - + + + - + diff --git a/docs/topics/get_started.md b/docs/topics/dokka-get-started.md similarity index 91% rename from docs/topics/get_started.md rename to docs/topics/dokka-get-started.md index 35525ac57e..df4ab7e567 100644 --- a/docs/topics/get_started.md +++ b/docs/topics/dokka-get-started.md @@ -29,7 +29,7 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about using Dokka with Gradle, see [Gradle](gradle.md). +To learn more about using Dokka with Gradle, see [Gradle](dokka-gradle.md). @@ -58,7 +58,7 @@ To generate documentation, run the following Gradle tasks: By default, the output directory is set to `/build/dokka/html` and `/build/dokka/htmlMultiModule`. -To learn more about using Dokka with Gradle, see [Gradle](gradle.md). +To learn more about using Dokka with Gradle, see [Gradle](dokka-gradle.md). @@ -89,7 +89,7 @@ To generate documentation, run the `dokka:dokka` goal. By default, the output directory is set to `target/dokka`. -To learn more about using Dokka with Maven, see [Maven](maven.md). +To learn more about using Dokka with Maven, see [Maven](dokka-maven.md). diff --git a/docs/topics/introduction.md b/docs/topics/dokka-introduction.md similarity index 73% rename from docs/topics/introduction.md rename to docs/topics/dokka-introduction.md index d6f8c3f9ad..cc5cef78c1 100644 --- a/docs/topics/introduction.md +++ b/docs/topics/dokka-introduction.md @@ -6,8 +6,8 @@ Just like Kotlin itself, Dokka supports mixed-language projects. It understands [KDoc comments](https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax) and Java's [Javadoc comments](https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html). -Dokka can generate documentation in multiple formats, including its own modern [HTML format](html.md), -multiple flavors of [Markdown](markdown.md), and Java's [Javadoc HTML](javadoc.md). +Dokka can generate documentation in multiple formats, including its own modern [HTML format](dokka-html.md), +multiple flavors of [Markdown](dokka-markdown.md), and Java's [Javadoc HTML](dokka-javadoc.md). Here are some libraries that use Dokka for their API reference documentation: @@ -17,10 +17,10 @@ Here are some libraries that use Dokka for their API reference documentation: * [Ktor](https://api.ktor.io/) * [OkHttp](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) (Markdown) -You can run Dokka using [Gradle](gradle.md), [Maven](maven.md) or from the [command line](cli.md). It is also -[highly pluggable](dokka_plugins.md). +You can run Dokka using [Gradle](dokka-gradle.md), [Maven](dokka-maven.md) or from the [command line](dokka-cli.md). It is also +[highly pluggable](dokka-plugins.md). -See [Get started](get_started.md) to take your first steps in using Dokka. +See [Get started](dokka-get-started.md) to take your first steps in using Dokka. ## Community diff --git a/docs/topics/dokka_plugins.md b/docs/topics/dokka-plugins.md similarity index 91% rename from docs/topics/dokka_plugins.md rename to docs/topics/dokka-plugins.md index dbac9e9381..36e3aa9c14 100644 --- a/docs/topics/dokka_plugins.md +++ b/docs/topics/dokka-plugins.md @@ -11,7 +11,7 @@ with other tools and so much more. If you want to learn how to create Dokka plugins, see [Developer guides](https://kotlin.github.io/dokka/%dokkaVersion%/developer_guide/introduction/). -## Applying Dokka plugins +## Apply Dokka plugins Dokka plugins are published as separate artifacts, so to apply a Dokka plugin you only need to add it as a dependency. From there, the plugin extends Dokka by itself - no further action is needed. @@ -46,7 +46,7 @@ dependencies { } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within +> When documenting [multi-project](dokka-gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within > subprojects as well as in their parent project. > {type="note"} @@ -70,7 +70,7 @@ dependencies { } ``` -> When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within +> When documenting [multi-project](dokka-gradle.md#multi-project-builds) builds, you need to apply Dokka plugins within > subprojects as well as in their parent project. > {type="note"} @@ -98,7 +98,7 @@ dependencies { -If you are using the [CLI](cli.md) runner with [command line options](cli.md#running-with-command-line-options), +If you are using the [CLI](dokka-cli.md) runner with [command line options](dokka-cli.md#run-with-command-line-options), Dokka plugins should be passed as `.jar` files to `-pluginsClasspath`: ```Shell @@ -107,7 +107,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ ... ``` -If you are using [JSON configuration](cli.md#running-with-json-configuration), Dokka plugins should be specified under +If you are using [JSON configuration](dokka-cli.md#run-with-json-configuration), Dokka plugins should be specified under `pluginsClasspath`. ```json @@ -125,12 +125,12 @@ If you are using [JSON configuration](cli.md#running-with-json-configuration), D -## Configuring Dokka plugins +## Configure Dokka plugins Dokka plugins can also have configuration options of their own. To see which options are available, consult documentation of the plugins you are using. -Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](html.md) +Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](dokka-html.md) documentation, by adding a custom image to the assets (`customAssets` option), by adding custom style sheets (`customStyleSheets` option), and by modifying the footer message (`footerMessage` option): @@ -232,7 +232,7 @@ tasks.withType(DokkaTask.class) { -If you are using the [CLI](cli.md) runner with [command line options](cli.md#running-with-command-line-options), +If you are using the [CLI](dokka-cli.md) runner with [command line options](dokka-cli.md#run-with-command-line-options), use the `-pluginsConfiguration` option that accepts JSON configuration in the form of `fullyQualifiedPluginName=json`. If you need to configure multiple plugins, you can pass multiple values separated by `^^`. @@ -243,7 +243,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ -pluginsConfiguration "org.jetbrains.dokka.base.DokkaBase={\"customAssets\": [\"my-image.png\"], \"customStyleSheets\": [\"my-styles.css\"], \"footerMessage\": \"(c) 2022 MyOrg CLI\"}" ``` -If you are using [JSON configuration](cli.md#running-with-json-configuration), there exists a similar +If you are using [JSON configuration](dokka-cli.md#run-with-json-configuration), there exists a similar `pluginsConfiguration` array that accepts JSON configuration in `values`. ```json @@ -275,4 +275,4 @@ Here are some notable Dokka plugins that you might find useful: | [Kotlin as Java plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java) | Renders Kotlin signatures as seen from Java's perspective | If you are a Dokka plugin author and would like to add your plugin to this list, get in touch with maintainers -via [Slack](introduction.md#community) or [GitHub](https://github.com/Kotlin/dokka/). \ No newline at end of file +via [Slack](dokka-introduction.md#community) or [GitHub](https://github.com/Kotlin/dokka/). \ No newline at end of file diff --git a/docs/topics/formats/html.md b/docs/topics/formats/dokka-html.md similarity index 94% rename from docs/topics/formats/html.md rename to docs/topics/formats/dokka-html.md index d7ed9fcdda..dd81b2d902 100644 --- a/docs/topics/formats/html.md +++ b/docs/topics/formats/dokka-html.md @@ -3,14 +3,14 @@ HTML is Dokka's default and recommended output format. You can see an example of the final result by browsing documentation for [kotlinx.coroutines](https://kotlinlang.org/api/kotlinx.coroutines/). -## Generating HTML documentation +## Generate HTML documentation HTML as an output format is supported by all runners. To generate HTML documentation, follow these steps depending on your build tool or runner: -* For [Gradle](gradle.md#generating-documentation), run `dokkaHtml` or `dokkaHtmlMultiModule` tasks. -* For [Maven](maven.md#generating-documentation), run the `dokka:dokka` goal. -* For [CLI runner](cli.md#generating-documentation), run with HTML dependencies set. +* For [Gradle](dokka-gradle.md#generate-documentation), run `dokkaHtml` or `dokkaHtmlMultiModule` tasks. +* For [Maven](dokka-maven.md#generate-documentation), run the `dokka:dokka` goal. +* For [CLI runner](dokka-cli.md#generate-documentation), run with HTML dependencies set. > HTML pages generated by this format need to be hosted on a web server in order to render everything correctly. > @@ -135,7 +135,7 @@ tasks.withType(DokkaTask.class) { -Via [command line options](cli.md#running-with-command-line-options): +Via [command line options](dokka-cli.md#run-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -144,7 +144,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ " ``` -Via [JSON configuration](cli.md#running-with-json-configuration): +Via [JSON configuration](dokka-cli.md#run-with-json-configuration): ```json { @@ -168,20 +168,20 @@ The table below contains all of the possible configuration options and their pur | **Option** | **Description** | |-----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `customAssets` | List of paths for image assets to be bundled with documentation. The image assets can have any file extension. For more information, see [Customizing assets](#customizing-assets). | -| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. For more information, see [Customizing styles](#customizing-styles). | +| `customAssets` | List of paths for image assets to be bundled with documentation. The image assets can have any file extension. For more information, see [Customizing assets](#customize-assets). | +| `customStyleSheets` | List of paths for `.css` stylesheets to be bundled with documentation and used for rendering. For more information, see [Customizing styles](#customize-styles). | | `templatesDir` | Path to the directory containing custom HTML templates. For more information, see [Templates](#templates). | | `footerMessage` | The text displayed in the footer. | | `separateInheritedMembers` | This is a boolean option. If set to `true`, Dokka renders properties/functions and inherited properties/inherited functions separately. This is disabled by default. | | `mergeImplicitExpectActualDeclarations` | This is a boolean option. If set to `true`, Dokka merges declarations that are not declared as [expect/actual](https://kotlinlang.org/docs/multiplatform-connect-to-apis.html), but have the same fully qualified name. This can be useful for legacy codebases. This is disabled by default. | -For more information about configuring Dokka plugins, see [Configuring Dokka plugins](dokka_plugins.md#configuring-dokka-plugins). +For more information about configuring Dokka plugins, see [Configuring Dokka plugins](dokka-plugins.md#configure-dokka-plugins). ## Customization To help you add your own look and feel to your documentation, the HTML format supports a number of customization options. -### Customizing styles +### Customize styles You can use your own stylesheets by using the `customStyleSheets` [configuration option](#configuration). These are applied to every page. @@ -198,7 +198,7 @@ It's also possible to override Dokka's default stylesheets by providing files wi The source code for all of Dokka's stylesheets is [available on GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/styles). -### Customizing assets +### Customize assets You can provide your own images to be bundled with documentation by using the `customAssets` [configuration option](#configuration). @@ -211,17 +211,17 @@ useful and relevant one being `logo-icon.svg`, which is the image that's used in You can find all images used by Dokka on [GitHub](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/plugins/base/src/main/resources/dokka/images). -### Changing the logo +### Change the logo -To customize the logo, you can begin by [providing your own asset](#customizing-assets) for `logo-icon.svg`. +To customize the logo, you can begin by [providing your own asset](#customize-assets) for `logo-icon.svg`. If you don't like how it looks, or you want to use a `.png` file instead of the default `.svg` file, -you can [override the `logo-styles.css` stylesheet](#customizing-styles) to customize it. +you can [override the `logo-styles.css` stylesheet](#customize-styles) to customize it. For an example of how to do this, see our [custom format example project](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle/dokka-customFormat-example). -### Modifying the footer +### Modify the footer You can modify text in the footer by using the `footerMessage` [configuration option](#configuration). @@ -262,7 +262,7 @@ The following variables are available inside all templates: | `${pathToRoot}` | The path to root from the current page. It's useful for locating assets and is available only within the `template_cmd` directive. | Variables `projectName` and `pathToRoot` are available only within the `template_cmd` directive as they require more -context and thus they need to be resolved at later stages by the [MultiModule](gradle.md#multi-project-builds) task: +context and thus they need to be resolved at later stages by the [MultiModule](dokka-gradle.md#multi-project-builds) task: ```html <@template_cmd name="projectName"> diff --git a/docs/topics/formats/javadoc.md b/docs/topics/formats/dokka-javadoc.md similarity index 76% rename from docs/topics/formats/javadoc.md rename to docs/topics/formats/dokka-javadoc.md index 2f11fb21e1..4781afcb61 100644 --- a/docs/topics/formats/javadoc.md +++ b/docs/topics/formats/dokka-javadoc.md @@ -18,10 +18,10 @@ All Kotlin code and signatures are rendered as seen from Java's perspective. Thi [Kotlin as Java Dokka plugin](https://github.com/Kotlin/dokka/tree/master/plugins/kotlin-as-java), which comes bundled and applied by default for this format. -The Javadoc output format is implemented as a [Dokka plugin](dokka_plugins.md), and it is maintained by the Dokka team. +The Javadoc output format is implemented as a [Dokka plugin](dokka-plugins.md), and it is maintained by the Dokka team. It is open source and you can find the source code on [GitHub](https://github.com/Kotlin/dokka/tree/master/plugins/javadoc). -## Generating Javadoc documentation +## Generate Javadoc documentation > The Javadoc format does not support multiplatform projects. > @@ -31,19 +31,19 @@ It is open source and you can find the source code on [GitHub](https://github.co -The [Gradle plugin for Dokka](gradle.md) comes with the Javadoc output format included. You can use the following tasks: +The [Gradle plugin for Dokka](dokka-gradle.md) comes with the Javadoc output format included. You can use the following tasks: | **Task** | **Description** | |-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `dokkaJavadoc` | Generates Javadoc documentation for a single project. | -| `dokkaJavadocCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | +| `dokkaJavadocCollector` | A [`Collector`](dokka-gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJavadoc` for every subproject and merges all outputs into a single virtual project. | -The `javadoc.jar` file can be generated separately. For more information, see [Building `javadoc.jar`](gradle.md#building-javadoc-jar). +The `javadoc.jar` file can be generated separately. For more information, see [Building `javadoc.jar`](dokka-gradle.md#build-javadoc-jar). -The [Maven plugin for Dokka](maven.md) comes with the Javadoc output format built in. You can generate documentation +The [Maven plugin for Dokka](dokka-maven.md) comes with the Javadoc output format built in. You can generate documentation by using the following goals: | **Goal** | **Description** | @@ -55,7 +55,7 @@ by using the following goals: -Since the Javadoc output format is a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to +Since the Javadoc output format is a [Dokka plugin](dokka-plugins.md#apply-dokka-plugins), you need to download the plugin's [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/javadoc-plugin/%dokkaVersion%). The Javadoc output format has two dependencies that you need to provide as additional JAR files: @@ -63,7 +63,7 @@ The Javadoc output format has two dependencies that you need to provide as addit * [kotlin-as-java plugin](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-as-java-plugin/%dokkaVersion%) * [korte-jvm](https://mvnrepository.com/artifact/com.soywiz.korlibs.korte/korte-jvm/3.3.0) -Via [command line options](cli.md#running-with-command-line-options): +Via [command line options](dokka-cli.md#run-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -71,7 +71,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ ... ``` -Via [JSON configuration](cli.md#running-with-json-configuration): +Via [JSON configuration](dokka-cli.md#run-with-json-configuration): ```json { @@ -87,7 +87,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see [Other output formats](cli.md#other-output-formats) in the CLI runner's documentation. +For more information, see [Other output formats](dokka-cli.md#other-output-formats) in the CLI runner's documentation. diff --git a/docs/topics/formats/markdown.md b/docs/topics/formats/dokka-markdown.md similarity index 70% rename from docs/topics/formats/markdown.md rename to docs/topics/formats/dokka-markdown.md index b0d215472c..d4919a5c3c 100644 --- a/docs/topics/formats/markdown.md +++ b/docs/topics/formats/dokka-markdown.md @@ -10,7 +10,7 @@ These formats give you more freedom in terms of hosting documentation as the out documentation website. For example, see [OkHttp's API reference](https://square.github.io/okhttp/4.x/okhttp/okhttp3/) pages. -Markdown output formats are implemented as [Dokka plugins](dokka_plugins.md), maintained by the Dokka team, and +Markdown output formats are implemented as [Dokka plugins](dokka-plugins.md), maintained by the Dokka team, and they are open source. ## GFM @@ -20,18 +20,18 @@ The GFM output format generates documentation in [GitHub Flavored Markdown](http -The [Gradle plugin for Dokka](gradle.md) comes with the GFM output format included. You can use the following tasks with it: +The [Gradle plugin for Dokka](dokka-gradle.md) comes with the GFM output format included. You can use the following tasks with it: | **Task** | **Description** | |-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `dokkaGfm` | Generates GFM documentation for a single project. | -| `dokkaGfmMultiModule` | A [`MultiModule`](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaGfmCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | +| `dokkaGfmMultiModule` | A [`MultiModule`](dokka-gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaGfmCollector` | A [`Collector`](dokka-gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaGfm` for every subproject and merges all outputs into a single virtual project. | -Since GFM format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin +Since GFM format is implemented as a [Dokka plugin](dokka-plugins.md#apply-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -53,16 +53,16 @@ dependency: After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see the Mavin plugin documentation for [Other output formats](maven.md#other-output-formats). +For more information, see the Mavin plugin documentation for [Other output formats](dokka-maven.md#other-output-formats). -Since GFM format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +Since GFM format is implemented as a [Dokka plugin](dokka-plugins.md#apply-dokka-plugins), you need to download the [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) and pass it to `pluginsClasspath`. -Via [command line options](cli.md#running-with-command-line-options): +Via [command line options](dokka-cli.md#run-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -70,7 +70,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ ... ``` -Via [JSON configuration](cli.md#running-with-json-configuration): +Via [JSON configuration](dokka-cli.md#run-with-json-configuration): ```json { @@ -84,7 +84,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see the CLI runner's documentation for [Other output formats](cli.md#other-output-formats). +For more information, see the CLI runner's documentation for [Other output formats](dokka-cli.md#other-output-formats). @@ -98,18 +98,18 @@ The Jekyll output format generates documentation in [Jekyll](https://jekyllrb.co -The [Gradle plugin for Dokka](gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: +The [Gradle plugin for Dokka](dokka-gradle.md) comes with the Jekyll output format included. You can use the following tasks with it: | **Task** | **Description** | |--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `dokkaJekyll` | Generates Jekyll documentation for a single project. | -| `dokkaJekyllMultiModule` | A [`MultiModule`](gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | -| `dokkaJekyllCollector` | A [`Collector`](gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | +| `dokkaJekyllMultiModule` | A [`MultiModule`](dokka-gradle.md#multi-project-builds) task created only for parent projects in multi-project builds. It generates documentation for subprojects and collects all outputs in a single place with a common table of contents. | +| `dokkaJekyllCollector` | A [`Collector`](dokka-gradle.md#collector-tasks) task created only for parent projects in multi-project builds. It calls `dokkaJekyll` for every subproject and merges all outputs into a single virtual project. | -Since Jekyll format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to apply it as a plugin +Since Jekyll format is implemented as a [Dokka plugin](dokka-plugins.md#apply-dokka-plugins), you need to apply it as a plugin dependency: ```xml @@ -131,17 +131,17 @@ dependency: After configuring this, running the `dokka:dokka` goal produces documentation in GFM format. -For more information, see the Maven plugin's documentation for [Other output formats](maven.md#other-output-formats). +For more information, see the Maven plugin's documentation for [Other output formats](dokka-maven.md#other-output-formats). -Since Jekyll format is implemented as a [Dokka plugin](dokka_plugins.md#applying-dokka-plugins), you need to download the +Since Jekyll format is implemented as a [Dokka plugin](dokka-plugins.md#apply-dokka-plugins), you need to download the [JAR file](https://mvnrepository.com/artifact/org.jetbrains.dokka/jekyll-plugin/%dokkaVersion%). This format is also based on [GFM](#gfm) format, so you need to provide it as a dependency as well. Both JARs need to be passed to `pluginsClasspath`: -Via [command line options](cli.md#running-with-command-line-options): +Via [command line options](dokka-cli.md#run-with-command-line-options): ```Bash java -jar dokka-cli-%dokkaVersion%.jar \ @@ -149,7 +149,7 @@ java -jar dokka-cli-%dokkaVersion%.jar \ ... ``` -Via [JSON configuration](cli.md#running-with-json-configuration): +Via [JSON configuration](dokka-cli.md#run-with-json-configuration): ```json { @@ -164,7 +164,7 @@ Via [JSON configuration](cli.md#running-with-json-configuration): } ``` -For more information, see the CLI runner's documentation for [Other output formats](cli.md#other-output-formats). +For more information, see the CLI runner's documentation for [Other output formats](dokka-cli.md#other-output-formats). diff --git a/docs/topics/runners/cli.md b/docs/topics/runners/dokka-cli.md similarity index 98% rename from docs/topics/runners/cli.md rename to docs/topics/runners/dokka-cli.md index 183498eda9..485372d888 100644 --- a/docs/topics/runners/cli.md +++ b/docs/topics/runners/dokka-cli.md @@ -1,12 +1,12 @@ [//]: # (title: CLI) -If for some reason you cannot use [Gradle](gradle.md) or [Maven](maven.md) build tools, Dokka has +If for some reason you cannot use [Gradle](dokka-gradle.md) or [Maven](dokka-maven.md) build tools, Dokka has a command line (CLI) runner for generating documentation. In comparison, it has the same, if not more, capabilities as the Gradle plugin for Dokka. Although it is considerably more difficult to set up as there is no autoconfiguration, especially in multiplatform and multi-module environments. -## Getting started +## Get started The CLI runner is published to Maven Central as a separate runnable artifact. @@ -26,7 +26,7 @@ It also works for some nested options, such as `-sourceSet`: java -jar dokka-cli-%dokkaVersion%.jar -sourceSet -help ``` -## Generating documentation +## Generate documentation ### Prerequisites @@ -41,7 +41,7 @@ Listed below are the dependencies that you need for any output format: | `org.jetbrains.dokka` | `kotlin-analysis-compiler` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-compiler/%dokkaVersion%) | | `org.jetbrains.dokka` | `kotlin-analysis-intellij` | %dokkaVersion% | [mvnrepository](https://mvnrepository.com/artifact/org.jetbrains.dokka/kotlin-analysis-intellij/%dokkaVersion%) | -Below are the additional dependencies that you need for [HTML](html.md) output format: +Below are the additional dependencies that you need for [HTML](dokka-html.md) output format: | **Group** | **Artifact** | **Version** | **Link** | |-------------------------|--------------------|-------------|--------------------------------------------------------------------------------------------------| @@ -49,7 +49,7 @@ Below are the additional dependencies that you need for [HTML](html.md) output f | `org.freemarker` | `freemarker` | 2.3.31 | [mvnrepository](https://mvnrepository.com/artifact/org.freemarker/freemarker/2.3.31) | -### Running with command line options +### Run with command line options You can pass command line options to configure the CLI runner. @@ -71,11 +71,11 @@ java -jar dokka-cli-%dokkaVersion%.jar \ > {type="note"} -Executing the given example generates documentation in [HTML](html.md) output format. +Executing the given example generates documentation in [HTML](dokka-html.md) output format. See [Command line options](#command-line-options) for more configuration details. -### Running with JSON configuration +### Run with JSON configuration It's possible to configure the CLI runner with JSON. In this case, you need to provide an absolute/relative path to the JSON configuration file as the first and only argument. @@ -121,12 +121,12 @@ See [JSON configuration options](#json-configuration) for more details. ### Other output formats -By default, the `dokka-base` artifact contains the [HTML](html.md) output format only. +By default, the `dokka-base` artifact contains the [HTML](dokka-html.md) output format only. -All other output formats are implemented as [Dokka plugins](dokka_plugins.md). In order to use them, you have to put them +All other output formats are implemented as [Dokka plugins](dokka-plugins.md). In order to use them, you have to put them on the plugins classpath. -For example, if you want to generate documentation in the experimental [GFM](markdown.md#gfm) output format, you need to download and +For example, if you want to generate documentation in the experimental [GFM](dokka-markdown.md#gfm) output format, you need to download and pass [gfm-plugin's JAR](https://mvnrepository.com/artifact/org.jetbrains.dokka/gfm-plugin/%dokkaVersion%) into the `pluginsClasspath` configuration option. @@ -154,7 +154,7 @@ Via JSON configuration: With the GFM plugin passed to `pluginsClasspath`, the CLI runner generates documentation in the GFM output format. -For more information, see [Markdown](markdown.md) and [Javadoc](javadoc.md#generating-javadoc-documentation) pages. +For more information, see [Markdown](dokka-markdown.md) and [Javadoc](dokka-javadoc.md#generate-javadoc-documentation) pages. ## Command line options diff --git a/docs/topics/runners/gradle.md b/docs/topics/runners/dokka-gradle.md similarity index 96% rename from docs/topics/runners/gradle.md rename to docs/topics/runners/dokka-gradle.md index ab11605775..3973804768 100644 --- a/docs/topics/runners/gradle.md +++ b/docs/topics/runners/dokka-gradle.md @@ -4,13 +4,13 @@ To generate documentation for a Gradle-based project, you can use the [Gradle plugin for Dokka](https://plugins.gradle.org/plugin/org.jetbrains.dokka). It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient -[Gradle tasks](#generating-documentation) for generating documentation, and provides a great deal of +[Gradle tasks](#generate-documentation) for generating documentation, and provides a great deal of [configuration options](#configuration-example) to customize the output. You can play around with Dokka and see how it can be configured for various projects by visiting our [Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). -## Applying Dokka +## Apply Dokka The recommended way of applying the Gradle plugin for Dokka is with the [plugins DSL](https://docs.gradle.org/current/userguide/plugins.html#sec:plugins_block): @@ -36,7 +36,7 @@ plugins { -When documenting [multi-project](gradle.md#multi-project-builds) builds, you need to apply the Gradle plugin for Dokka +When documenting [multi-project](dokka-gradle.md#multi-project-builds) builds, you need to apply the Gradle plugin for Dokka within subprojects as well. You can use `allprojects {}` or `subprojects {}` Gradle configurations to achieve that: @@ -95,9 +95,9 @@ If you cannot use the plugins DSL for some reason, you can use [the legacy method](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application) of applying plugins. -## Generating documentation +## Generate documentation -The Gradle plugin for Dokka comes with [HTML](html.md), [Markdown](markdown.md) and [Javadoc](javadoc.md) output formats +The Gradle plugin for Dokka comes with [HTML](dokka-html.md), [Markdown](dokka-markdown.md) and [Javadoc](dokka-javadoc.md) output formats built in. It adds a number of tasks for generating documentation, both for [single](#single-project-builds) and [multi-project](#multi-project-builds) builds. @@ -109,15 +109,15 @@ Use the following tasks to build documentation for simple, single-project applic | **Task** | **Description** | |----------------|-------------------------------------------------------------------------------------| -| `dokkaHtml` | Generates documentation in [HTML](html.md) format. | +| `dokkaHtml` | Generates documentation in [HTML](dokka-html.md) format. | #### Experimental formats | **Task** | **Description** | |----------------|-------------------------------------------------------------------------------------| -| `dokkaGfm` | Generates documentation in [GitHub Flavored Markdown](markdown.md#gfm) format. | -| `dokkaJavadoc` | Generates documentation in [Javadoc](javadoc.md) format. | -| `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](markdown.md#jekyll) format. | +| `dokkaGfm` | Generates documentation in [GitHub Flavored Markdown](dokka-markdown.md#gfm) format. | +| `dokkaJavadoc` | Generates documentation in [Javadoc](dokka-javadoc.md) format. | +| `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](dokka-markdown.md#jekyll) format. | By default, generated documentation is located in the `build/dokka/{format}` directory of your project. The output location, among other things, can be [configured](#configuration-example). @@ -125,7 +125,7 @@ The output location, among other things, can be [configured](#configuration-exam ### Multi-project builds For documenting [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html), make sure -that you [apply the Gradle plugin for Dokka](#applying-dokka) within subprojects that you want to generate documentation +that you [apply the Gradle plugin for Dokka](#apply-dokka) within subprojects that you want to generate documentation for, as well as in their parent project. #### MultiModule tasks @@ -140,16 +140,16 @@ Dokka creates the following tasks for **parent** projects automatically: | **Task** | **Description** | |--------------------------|------------------------------------------------------------------------| -| `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](html.md) output format. | +| `dokkaHtmlMultiModule` | Generates multi-module documentation in [HTML](dokka-html.md) output format. | #### Experimental formats | **Task** | **Description** | |--------------------------|---------------------------------------------------------------------------------------------------------| -| `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](markdown.md#gfm) output format. | -| `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](markdown.md#jekyll) output format. | +| `dokkaGfmMultiModule` | Generates multi-module documentation in [GitHub Flavored Markdown](dokka-markdown.md#gfm) output format. | +| `dokkaJekyllMultiModule` | Generates multi-module documentation in [Jekyll compatible Markdown](dokka-markdown.md#jekyll) output format. | -> The [Javadoc](javadoc.md) output format does not have a `MultiModule` task, but a [`Collector`](#collector-tasks) task can +> The [Javadoc](dokka-javadoc.md) output format does not have a `MultiModule` task, but a [`Collector`](#collector-tasks) task can > be used instead. > {type="note"} @@ -232,7 +232,7 @@ the subprojects allows documenting `protected` declarations, while others do not > If you want to generate documentation for a single subproject only, use > [single-project tasks](#single-project-builds). For example, `:subprojectName:dokkaHtml`. -## Building javadoc.jar +## Build javadoc.jar If you want to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API reference documentation of your library. @@ -242,7 +242,7 @@ For example, if you want to publish to [Maven Central](https://central.sonatype. not all repositories have that rule. The Gradle plugin for Dokka does not provide any way to do this out of the box, but it can be achieved with custom Gradle -tasks. One for generating documentation in [HTML](html.md) format and another one for [Javadoc](javadoc.md) format: +tasks. One for generating documentation in [HTML](dokka-html.md) format and another one for [Javadoc](dokka-javadoc.md) format: diff --git a/docs/topics/runners/maven.md b/docs/topics/runners/dokka-maven.md similarity index 96% rename from docs/topics/runners/maven.md rename to docs/topics/runners/dokka-maven.md index e97d57ceda..7c8889939d 100644 --- a/docs/topics/runners/maven.md +++ b/docs/topics/runners/dokka-maven.md @@ -2,7 +2,7 @@ To generate documentation for a Maven-based project, you can use the Maven plugin for Dokka. -> Compared to the [Gradle plugin for Dokka](gradle.md), the Maven plugin has only basic features and +> Compared to the [Gradle plugin for Dokka](dokka-gradle.md), the Maven plugin has only basic features and > does not provide support for multi-module builds. > {type="note"} @@ -10,7 +10,7 @@ To generate documentation for a Maven-based project, you can use the Maven plugi You can play around with Dokka and see how it can be configured for a Maven project by visiting our [Maven example](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/maven) project. -## Applying Dokka +## Apply Dokka To apply Dokka, you need to add `dokka-maven-plugin` to the `plugins` section of your POM file: @@ -34,7 +34,7 @@ To apply Dokka, you need to add `dokka-maven-plugin` to the `plugins` section of
    ``` -## Generating documentation +## Generate documentation The following goals are provided by the Maven plugin: @@ -42,23 +42,23 @@ The following goals are provided by the Maven plugin: | **Goal** | **Description** | |---------------|----------------------------------------------------------------------------------------| -| `dokka:dokka` | Generates documentation with Dokka plugins applied. [HTML](html.md) format by default. | +| `dokka:dokka` | Generates documentation with Dokka plugins applied. [HTML](dokka-html.md) format by default. | ### Experimental | **Goal** | **Description** | |--------------------|---------------------------------------------------------------------------------------------| -| `dokka:javadoc` | Generates documentation in [Javadoc](javadoc.md) format. | -| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in [Javadoc](javadoc.md) format. | +| `dokka:javadoc` | Generates documentation in [Javadoc](dokka-javadoc.md) format. | +| `dokka:javadocJar` | Generates a `javadoc.jar` file that contains documentation in [Javadoc](dokka-javadoc.md) format. | ### Other output formats -By default, the Maven plugin for Dokka builds documentation in [HTML](html.md) output format. +By default, the Maven plugin for Dokka builds documentation in [HTML](dokka-html.md) output format. -All other output formats are implemented as [Dokka plugins](dokka_plugins.md). In order to generate documentation in the +All other output formats are implemented as [Dokka plugins](dokka-plugins.md). In order to generate documentation in the desired format, you have to add it as a Dokka plugin to the configuration. -For example, to use the experimental [GFM](markdown.md#gfm) format, you have to add `gfm-plugin` artifact: +For example, to use the experimental [GFM](dokka-markdown.md#gfm) format, you have to add `gfm-plugin` artifact: ```xml @@ -79,9 +79,9 @@ For example, to use the experimental [GFM](markdown.md#gfm) format, you have to With this configuration, running the `dokka:dokka` goal produces documentation in GFM format. -To learn more about Dokka plugins, see [Dokka plugins](dokka_plugins.md). +To learn more about Dokka plugins, see [Dokka plugins](dokka-plugins.md). -## Building javadoc.jar +## Build javadoc.jar If you want to publish your library to a repository, you may need to provide a `javadoc.jar` file that contains API reference documentation of your library. @@ -90,11 +90,11 @@ For example, if you want to publish to [Maven Central](https://central.sonatype. [must](https://central.sonatype.org/publish/requirements/) supply a `javadoc.jar` alongside your project. However, not all repositories have that rule. -Unlike the [Gradle plugin for Dokka](gradle.md#building-javadoc-jar), the Maven plugin comes with a ready-to-use `dokka:javadocJar` -goal. By default, it generates documentation in [Javadoc](javadoc.md) output format in the`target` folder. +Unlike the [Gradle plugin for Dokka](dokka-gradle.md#build-javadoc-jar), the Maven plugin comes with a ready-to-use `dokka:javadocJar` +goal. By default, it generates documentation in [Javadoc](dokka-javadoc.md) output format in the`target` folder. If you are not satisfied with the built-in goal or want to customize the output (for example, you want to generate -documentation in [HTML](html.md) format instead of Javadoc), similar behavior can be achieved by adding the +documentation in [HTML](dokka-html.md) format instead of Javadoc), similar behavior can be achieved by adding the Maven JAR plugin with the following configuration: ```xml From 5e64da52d5fea4fbeb449f399d88ef16ef2cd0e6 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Mon, 9 Jan 2023 15:37:04 +0100 Subject: [PATCH 11/14] Add more examples and details to multi-project build configuration --- docs/topics/runners/dokka-gradle.md | 388 +++++++++++++++++++++++++--- 1 file changed, 349 insertions(+), 39 deletions(-) diff --git a/docs/topics/runners/dokka-gradle.md b/docs/topics/runners/dokka-gradle.md index 3973804768..362ab20267 100644 --- a/docs/topics/runners/dokka-gradle.md +++ b/docs/topics/runners/dokka-gradle.md @@ -3,9 +3,9 @@ To generate documentation for a Gradle-based project, you can use the [Gradle plugin for Dokka](https://plugins.gradle.org/plugin/org.jetbrains.dokka). -It comes with basic autoconfiguration (including multi-project and multiplatform builds), has convenient -[Gradle tasks](#generate-documentation) for generating documentation, and provides a great deal of -[configuration options](#configuration-example) to customize the output. +It comes with basic autoconfiguration for your project, has convenient [Gradle tasks](#generate-documentation) for +generating documentation, and provides a great deal of [configuration options](#configuration-example) to +customize the output. You can play around with Dokka and see how it can be configured for various projects by visiting our [Gradle example projects](https://github.com/Kotlin/dokka/tree/%dokkaVersion%/examples/gradle). @@ -60,6 +60,8 @@ subprojects { +See [Configuration example](#configuration-example) if you are not sure where to apply Dokka. + > Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin) > to perform autoconfiguration of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) > for which documentation is to be generated. Make sure to apply the Kotlin Gradle Plugin or @@ -70,7 +72,7 @@ subprojects { > If you are using Dokka in a > [precompiled script plugin](https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins), > you need to add the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin) -> as a dependency in order for it to work properly: +> as a dependency for it to work properly: > > > @@ -219,18 +221,20 @@ for more details. Each subproject has `Partial` tasks created for it: `dokkaHtmlPartial`,`dokkaGfmPartial`, and `dokkaJekyllPartial`. -These tasks are not intended to be used independently and exist only to be called by the parent's +These tasks are not intended to be run independently, they are called by the parent's [MultiModule](#multimodule-tasks) task. -Output generated by `Partial` tasks contains unresolved HTML templates and references, so it cannot be used -on its own without post-processing done by the `MultiModule` task. +However, you can [configure](#subproject-configuration) `Partial` tasks to customize Dokka for your subprojects. -However, you can [configure](#configuration-example) `Partial` tasks to customize Dokka on a per-project basis. -For example, your subprojects can have different configurations of documented visibilities, where one of -the subprojects allows documenting `protected` declarations, while others do not. +> Output generated by `Partial` tasks contains unresolved HTML templates and references, so it cannot be used +> on its own without post-processing done by the parent's [`MultiModule`](#multimodule-tasks) task. +> +{type="warning"} > If you want to generate documentation for a single subproject only, use > [single-project tasks](#single-project-builds). For example, `:subprojectName:dokkaHtml`. +> +{type="note"} ## Build javadoc.jar @@ -290,12 +294,99 @@ tasks.register('dokkaJavadocJar', Jar.class) { ## Configuration example +Depending on the type of project that you have, the way you apply and configure Dokka differs slightly. However, +[configuration options](#configuration-options) themselves are the same, regardless of the type of your project. + +For simple and flat projects with a single `build.gradle.kts` or `build.gradle` file found in the root of your project, +see [Single-project configuration](#single-project-configuration). + +For a more complex build with subprojects and multiple nested `build.gradle.kts` or `build.gradle` files, +see [Multi-project configuration](#multi-project-configuration). + +### Single-project configuration + +Single-project builds usually have only one `build.gradle.kts` or `build.gradle` file in the root of the project, +and typically have the following structure: + + + + +Single platform: + +```text +. +├── build.gradle.kts +└── src + └── main + └── kotlin + └── HelloWorld.kt +``` + +Multiplatform: + +```text +. +├── build.gradle.kts +└── src + └── commonMain + └── kotlin + └── Common.kt + └── jvmMain + └── kotlin + └── JvmUtils.kt + └── nativeMain + └── kotlin + └── NativeUtils.kt +``` + + + + +Single platform: + +```text +. +├── build.gradle +└── src + └── main + └── kotlin + └── HelloWorld.kt +``` + +Multiplatform: + +```text +. +├── build.gradle +└── src + └── commonMain + └── kotlin + └── Common.kt + └── jvmMain + └── kotlin + └── JvmUtils.kt + └── nativeMain + └── kotlin + └── NativeUtils.kt +``` + + + + +In such projects, you need to apply Dokka and its configuration in the root `build.gradle.kts` or `build.gradle` file. + You can configure tasks and output formats individually: +Inside `./build.gradle.kts`: + ```kotlin +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} + tasks.dokkaHtml { outputDirectory.set(buildDir.resolve("documentation/html")) } @@ -303,17 +394,17 @@ tasks.dokkaHtml { tasks.dokkaGfm { outputDirectory.set(buildDir.resolve("documentation/markdown")) } - -// only within a subproject: -tasks.dokkaHtmlPartial { - outputDirectory.set(buildDir.resolve("docs/partial")) -} ``` +Inside `./build.gradle`: + ```groovy +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} dokkaHtml { outputDirectory.set(file("build/documentation/html")) @@ -322,27 +413,27 @@ dokkaHtml { dokkaGfm { outputDirectory.set(file("build/documentation/markdown")) } - -// only within a subproject: -dokkaHtmlPartial { - outputDirectory.set(file("build/docs/partial")) -} ``` -Alternatively, you can configure all tasks and output formats at the same time, including [`MultiModule`](#multi-project-builds), -[`Partial`](#partial-tasks) and [`Collector`](#collector-tasks) tasks: +Or you can configure all tasks and output formats at the same time: +Inside `./build.gradle.kts`: + ```kotlin import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial import org.jetbrains.dokka.DokkaConfiguration.Visibility +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} + // Configure all single-project Dokka tasks at the same time, // such as dokkaHtml, dokkaJavadoc and dokkaGfm. tasks.withType().configureEach { @@ -360,27 +451,21 @@ tasks.withType().configureEach { } } } - -// Configure all Partial tasks found in multi-project builds, -// such as dokkaHtmlPartial, dokkaJavadocPartial and dokkaGfmPartial. -// These can have subproject-specific settings. -subprojects { - apply(plugin = "org.jetbrains.dokka") - - tasks.withType().configureEach { - dokkaSourceSets.configureEach { - includes.from("README.md") - } - } -} ``` +Inside `./build.gradle`: + ```groovy import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTaskPartial +import org.jetbrains.dokka.DokkaConfiguration.Visibility + +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} // Configure all single-project Dokka tasks at the same time, // such as dokkaHtml, dokkaJavadoc and dokkaGfm. @@ -397,12 +482,121 @@ tasks.withType(DokkaTask.class) { } } } +``` + + + + +### Multi-project configuration + +Gradle's [multi-project builds](https://docs.gradle.org/current/userguide/multi_project_builds.html) are more complex +in structure and configuration. They usually have multiple nested `build.gradle.kts` or `build.gradle` files, and +typically have the following structure: + + + + +```text +. +├── build.gradle.kts +├── settings.gradle.kts +├── subproject-A + └── build.gradle.kts + └── src + └── main + └── kotlin + └── HelloFromA.kt +├── subproject-B + └── build.gradle.kts + └── src + └── main + └── kotlin + └── HelloFromB.kt +``` + + + + +```text +. +├── build.gradle +├── settings.gradle +├── subproject-A + └── build.gradle + └── src + └── main + └── kotlin + └── HelloFromA.kt +├── subproject-B + └── build.gradle + └── src + └── main + └── kotlin + └── HelloFromB.kt +``` + + + + +In this case, there are multiple ways of applying and configuring Dokka. + +#### Subproject configuration + +To configure subprojects in a multi-module build, you need to configure [`Partial`](#partial-tasks) tasks. + +You can configure all subprojects at the same time in the root `build.gradle.kts` or `build.gradle` file, +using Gradle's `allprojects {}` or `subprojects {}` configuration blocks: + + + + +In the root `./build.gradle.kts`: + +```kotlin +import org.jetbrains.dokka.gradle.DokkaTaskPartial + +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} + +subprojects { + apply(plugin = "org.jetbrains.dokka") + + // configure only the HTML task + tasks.dokkaHtmlPartial { + outputDirectory.set(buildDir.resolve("docs/partial")) + } + + // configure all format tasks at once + tasks.withType().configureEach { + dokkaSourceSets.configureEach { + includes.from("README.md") + } + } +} +``` + + + + +In the root `./build.gradle`: + +```groovy +import org.jetbrains.dokka.gradle.DokkaTaskPartial + +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} -// Configure all Partial tasks found in multi-project builds. -// These can have subproject-specific settings. subprojects { apply plugin: 'org.jetbrains.dokka' - + + // configure only the HTML task + dokkaHtmlPartial { + outputDirectory.set(file("build/docs/partial")) + } + + // configure all format tasks at once tasks.withType(DokkaTaskPartial.class) { dokkaSourceSets.configureEach { includes.from("README.md") @@ -414,6 +608,84 @@ subprojects { +Alternatively, you can apply and configure Dokka within subprojects individually. + +For example, to have specific settings for the `subproject-A` subproject only, you need to apply the following code +inside `./subproject-A/build.gradle.kts`: + + + + +Inside `./subproject-A/build.gradle.kts`: + +```kotlin +apply(plugin = "org.jetbrains.dokka") + +// configuration for subproject-A only. +tasks.dokkaHtmlPartial { + outputDirectory.set(buildDir.resolve("docs/partial")) +} +``` + + + + +Inside `./subproject-A/build.gradle`: + +```groovy +apply plugin: 'org.jetbrains.dokka' + +// configuration for subproject-A only. +dokkaHtmlPartial { + outputDirectory.set(file("build/docs/partial")) +} +``` + + + + +#### Parent project configuration + +If you want to configure something which is universal across all documentation and does not belong to the +subprojects - in other words, it's a property of the parent project - you need to configure the +[`MultiModule`](#multimodule-tasks) tasks. + +For example, if you want to change the name of your project which is used in the header of the HTML documentation, +you need to apply the following inside the root `build.gradle.kts` or `build.gradle` file: + + + + +In the root `./build.gradle.kts` file: + +```kotlin +plugins { + id("org.jetbrains.dokka") version "%dokkaVersion%" +} + +tasks.dokkaHtmlMultiModule { + moduleName.set("WHOLE PROJECT NAME USED IN THE HEADER") +} +``` + + + + +In the root `./build.gradle` file: + +```groovy +plugins { + id 'org.jetbrains.dokka' version '%dokkaVersion%' +} + +dokkaHtmlMultiModule { + moduleName.set("WHOLE PROJECT NAME USED IN THE HEADER") +} +``` + + + + ## Configuration options Dokka has many configuration options to tailor your and your reader's experience. @@ -421,6 +693,8 @@ Dokka has many configuration options to tailor your and your reader's experience Below are some examples and detailed descriptions for each configuration section. You can also find an example with [all configuration options](#complete-configuration) applied at the bottom of the page. +See [Configuration example](#configuration-example) for more details on where to apply configuration blocks and how. + ### General configuration Here is an example of general configuration of any Dokka task, regardless of source set or package: @@ -431,6 +705,9 @@ Here is an example of general configuration of any Dokka task, regardless of sou ```kotlin import org.jetbrains.dokka.gradle.DokkaTask +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { moduleName.set(project.name) moduleVersion.set(project.version.toString()) @@ -452,6 +729,9 @@ tasks.withType().configureEach { ```groovy import org.jetbrains.dokka.gradle.DokkaTask +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { moduleName.set(project.name) moduleVersion.set(project.version.toString()) @@ -559,6 +839,9 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.Platform import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { // .. // general configuration section @@ -612,6 +895,9 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.Platform import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { // .. // general configuration section @@ -819,6 +1105,9 @@ function in `kotlinx.coroutines`. import org.jetbrains.dokka.gradle.DokkaTask import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { // .. // general configuration section @@ -845,6 +1134,9 @@ tasks.withType().configureEach { import org.jetbrains.dokka.gradle.DokkaTask import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { // .. // general configuration section @@ -914,6 +1206,9 @@ The `perPackageOption` configuration block allows setting some options for speci import org.jetbrains.dokka.DokkaConfiguration.Visibility import org.jetbrains.dokka.gradle.DokkaTask +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { // .. // general configuration section @@ -942,9 +1237,12 @@ tasks.withType().configureEach { import org.jetbrains.dokka.DokkaConfiguration.Visibility import org.jetbrains.dokka.gradle.DokkaTask +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { // .. - // General configuration section + // general configuration section // .. dokkaSourceSets.configureEach { @@ -1020,6 +1318,9 @@ By default, external documentation links for Kotlin standard library, JDK, Andro import org.jetbrains.dokka.gradle.DokkaTask import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { // .. // general configuration section @@ -1047,6 +1348,9 @@ tasks.withType().configureEach { import org.jetbrains.dokka.gradle.DokkaTask import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { // .. // general configuration section @@ -1108,6 +1412,9 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.Platform import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType().configureEach { moduleName.set(project.name) moduleVersion.set(project.version.toString()) @@ -1184,6 +1491,9 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.Platform import java.net.URL +// Note: To configure multi-project builds, you need +// to configure Partial tasks of the subprojects. +// See "Configuration example" section of documentation. tasks.withType(DokkaTask.class) { moduleName.set(project.name) moduleVersion.set(project.version.toString()) From 9c7a381f739859ce3f9256521c7b27b86d3fe40a Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Mon, 9 Jan 2023 15:50:28 +0100 Subject: [PATCH 12/14] Remove periods for default statements --- docs/topics/runners/dokka-cli.md | 32 ++++++++++----------- docs/topics/runners/dokka-gradle.md | 44 ++++++++++++++--------------- docs/topics/runners/dokka-maven.md | 38 ++++++++++++------------- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/docs/topics/runners/dokka-cli.md b/docs/topics/runners/dokka-cli.md index 485372d888..fa8fa459c8 100644 --- a/docs/topics/runners/dokka-cli.md +++ b/docs/topics/runners/dokka-cli.md @@ -266,11 +266,11 @@ with [all configuration options](#complete-configuration) applied at the bottom

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    -

    Default: root.

    +

    Default: root

    The module version.

    -

    Default: empty.

    +

    Default: empty

    The directory to where documentation is generated, regardless of output format.

    @@ -282,7 +282,7 @@ with [all configuration options](#complete-configuration) applied at the bottom The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented

    -

    Default: false.

    +

    Default: false

    Whether to suppress obvious functions.

    @@ -299,7 +299,7 @@ with [all configuration options](#complete-configuration) applied at the bottom
  • -

    Default: true.

    +

    Default: true

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    @@ -309,7 +309,7 @@ with [all configuration options](#complete-configuration) applied at the bottom dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default: false.

    +

    Default: false

    Whether to resolve remote files/links over your network.

    @@ -326,7 +326,7 @@ with [all configuration options](#complete-configuration) applied at the bottom Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    -

    Default: false.

    +

    Default: false

    @@ -449,7 +449,7 @@ How to configure Kotlin

  • PACKAGE
  • -

    Default: PUBLIC.

    +

    Default: PUBLIC

    @@ -458,7 +458,7 @@ How to configure Kotlin

    This setting works well with failOnWarning.

    This can be configured on per-package basis.

    -

    Default: false.

    +

    Default: false

    @@ -474,7 +474,7 @@ How to configure Kotlin

    Whether to document declarations annotated with @Deprecated.

    This can be configured on per-package basis.

    -

    Default: false.

    +

    Default: false

    The JDK version to use when generating external documentation links for Java types.

    @@ -504,13 +504,13 @@ How to configure Kotlin documentation of Kotlin's standard library.

    Note: Links are generated when noStdLibLink is set to false.

    -

    Default: false.

    +

    Default: false

    Whether to generate external documentation links to JDK's Javadocs.

    The version of JDK Javadocs is determined by the jdkVersion option.

    Note: Links are generated when noJdkLink is set to false.

    -

    Default: false.

    +

    Default: false

    @@ -623,7 +623,7 @@ You can configure source links for all source sets together at the same time, or

  • Bitbucket: #lines-
  • -

    Default: empty (no suffix).

    +

    Default: empty (no suffix)

    @@ -654,12 +654,12 @@ You can add package configurations for all source sets together at the same time

    Whether this package should be skipped when generating documentation.

    -

    Default: false.

    +

    Default: false

    Whether to document declarations annotated with @Deprecated.

    This can be set on project/module level.

    -

    Default: false.

    +

    Default: false

    @@ -668,7 +668,7 @@ You can add package configurations for all source sets together at the same time

    This setting works well with failOnWarning.

    This can be configured on source set level.

    -

    Default: false.

    +

    Default: false

    The set of visibility modifiers that should be documented.

    @@ -677,7 +677,7 @@ You can add package configurations for all source sets together at the same time as well as if you want to exclude public declarations and only document internal API.

    Can be configured on source set level.

    -

    Default: PUBLIC.

    +

    Default: PUBLIC

    diff --git a/docs/topics/runners/dokka-gradle.md b/docs/topics/runners/dokka-gradle.md index 362ab20267..aff8b680a0 100644 --- a/docs/topics/runners/dokka-gradle.md +++ b/docs/topics/runners/dokka-gradle.md @@ -754,14 +754,14 @@ tasks.withType(DokkaTask.class) {

    The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc.

    If set for a single-project build or a MultiModule task, it is used as the project name.

    -

    Default: Gradle project name.

    +

    Default: Gradle project name

    The module version. If set for a single-project build or a MultiModule task, it is used as the project version.

    -

    Default: Gradle project version.

    +

    Default: Gradle project version

    The directory to where documentation is generated, regardless of format. It can be set on a per-task basis.

    @@ -777,7 +777,7 @@ tasks.withType(DokkaTask.class) { The process waits until all errors and warnings have been emitted first.

    This setting works well with reportUndocumented.

    -

    Default: false.

    +

    Default: false

    Whether to suppress obvious functions.

    @@ -794,7 +794,7 @@ tasks.withType(DokkaTask.class) {

    -

    Default: true.

    +

    Default: true

    Whether to suppress inherited members that aren't explicitly overridden in a given class.

    @@ -804,7 +804,7 @@ tasks.withType(DokkaTask.class) { dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default: false.

    +

    Default: false

    Whether to resolve remote files/links over your network.

    @@ -821,7 +821,7 @@ tasks.withType(DokkaTask.class) { Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    -

    Default: false.

    +

    Default: false

    @@ -948,7 +948,7 @@ tasks.withType(DokkaTask.class) {

    Whether this source set should be skipped when generating documentation.

    -

    Default: false.

    +

    Default: false

    The display name used to refer to this source set.

    @@ -965,7 +965,7 @@ tasks.withType(DokkaTask.class) { as well as if you want to exclude public declarations and only document internal API.

    This can be configured on per-package basis.

    -

    Default: DokkaConfiguration.Visibility.PUBLIC.

    +

    Default: DokkaConfiguration.Visibility.PUBLIC

    @@ -974,7 +974,7 @@ tasks.withType(DokkaTask.class) {

    This setting works well with failOnWarning.

    This can be configured on per-package basis.

    -

    Default: false.

    +

    Default: false

    @@ -985,12 +985,12 @@ tasks.withType(DokkaTask.class) { For example, if skipDeprecated is set to true and your package contains only deprecated declarations, it is considered to be empty.

    -

    Default: true.

    +

    Default: true

    Whether to document declarations annotated with @Deprecated.

    This can be configured on per-package basis.

    -

    Default: false.

    +

    Default: false

    Whether to document/analyze generated files.

    @@ -1001,7 +1001,7 @@ tasks.withType(DokkaTask.class) { If set to true, it effectively adds all files from that directory to the suppressedFiles option, so you can configure it manually.

    -

    Default: true.

    +

    Default: true

    The JDK version to use when generating external documentation links for Java types.

    @@ -1010,7 +1010,7 @@ tasks.withType(DokkaTask.class) { and this option is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    -

    Default: JDK 8.

    +

    Default: JDK 8

    @@ -1034,19 +1034,19 @@ tasks.withType(DokkaTask.class) { documentation of Kotlin's standard library.

    Note: Links are generated when noStdLibLink is set to false.

    -

    Default: false.

    +

    Default: false

    Whether to generate external documentation links to JDK's Javadocs.

    The version of JDK Javadocs is determined by the jdkVersion option.

    Note: Links are generated when noJdkLink is set to false.

    -

    Default: false.

    +

    Default: false

    Whether to generate external documentation links to the Android SDK API reference

    This is only relevant in Android projects, ignored otherwise.

    Note: Links are generated when noAndroidSdkLink is set to false.

    -

    Default: false.

    +

    Default: false

    @@ -1191,7 +1191,7 @@ tasks.withType(DokkaTask.class) {

  • Bitbucket: #lines-
  • -

    Default: #L.

    +

    Default: #L

    @@ -1267,16 +1267,16 @@ tasks.withType(DokkaTask.class) {

    The regular expression that is used to match the package.

    -

    Default: .*.

    +

    Default: .*

    Whether this package should be skipped when generating documentation.

    -

    Default: false.

    +

    Default: false

    Whether to document declarations annotated with @Deprecated.

    This can be configured on source set level.

    -

    Default: false.

    +

    Default: false

    @@ -1285,7 +1285,7 @@ tasks.withType(DokkaTask.class) {

    This setting works well with failOnWarning.

    This can be configured on source set level.

    -

    Default: false.

    +

    Default: false

    The set of visibility modifiers that should be documented.

    @@ -1294,7 +1294,7 @@ tasks.withType(DokkaTask.class) { as well as if you want to exclude public declarations and only document internal API.

    This can be configured on source set level.

    -

    Default: DokkaConfiguration.Visibility.PUBLIC.

    +

    Default: DokkaConfiguration.Visibility.PUBLIC

    diff --git a/docs/topics/runners/dokka-maven.md b/docs/topics/runners/dokka-maven.md index 7c8889939d..9bedc5174c 100644 --- a/docs/topics/runners/dokka-maven.md +++ b/docs/topics/runners/dokka-maven.md @@ -219,15 +219,15 @@ with [all configuration options](#complete-configuration) applied at the bottom

    Whether to skip documentation generation.

    -

    Default: false.

    +

    Default: false

    The display name used to refer to the project/module. It's used for the table of contents, navigation, logging, etc.

    -

    Default: {project.artifactId}.

    +

    Default: {project.artifactId}

    The directory to where documentation is generated, regardless of format.

    -

    Default: {project.basedir}/target/dokka.

    +

    Default: {project.basedir}/target/dokka

    @@ -235,7 +235,7 @@ with [all configuration options](#complete-configuration) applied at the bottom all errors and warnings have been emitted first.

    This setting works well with reportUndocumented.

    -

    Default: false.

    +

    Default: false

    Whether to suppress obvious functions.

    @@ -261,7 +261,7 @@ with [all configuration options](#complete-configuration) applied at the bottom but cannot suppress synthetic functions such as dataClass.componentN and dataClass.copy. Use suppressObviousFunctions for that.

    -

    Default: false.

    +

    Default: false

    Whether to resolve remote files/links over your network.

    @@ -278,14 +278,14 @@ with [all configuration options](#complete-configuration) applied at the bottom Note: You can cache fetched files locally and provide them to Dokka as local paths. See externalDocumentationLinks section.

    -

    Default: false.

    +

    Default: false

    The source code roots to be analyzed and documented. Acceptable inputs are directories and individual .kt / .java files.

    -

    Default: {project.compileSourceRoots}.

    +

    Default: {project.compileSourceRoots}

    The set of visibility modifiers that should be documented.

    @@ -294,7 +294,7 @@ with [all configuration options](#complete-configuration) applied at the bottom as well as if you want to exclude public declarations and only document internal API.

    Can be configured on per-package basis.

    -

    Default: PUBLIC.

    +

    Default: PUBLIC

    @@ -303,12 +303,12 @@ with [all configuration options](#complete-configuration) applied at the bottom

    This setting works well with failOnWarning.

    This can be overridden at package level.

    -

    Default: false.

    +

    Default: false

    Whether to document declarations annotated with @Deprecated.

    This can be overridden at package level.

    -

    Default: false.

    +

    Default: false

    @@ -319,7 +319,7 @@ with [all configuration options](#complete-configuration) applied at the bottom For example, if skipDeprecated is set to true and your package contains only deprecated declarations, it is considered to be empty.

    -

    Default: true.

    +

    Default: true

    @@ -334,7 +334,7 @@ with [all configuration options](#complete-configuration) applied at the bottom and this option is set to 8, Dokka generates an external documentation link to JDK 8 Javadocs for it.

    -

    Default: JDK 8.

    +

    Default: JDK 8

    @@ -358,7 +358,7 @@ with [all configuration options](#complete-configuration) applied at the bottom documentation of Kotlin's standard library.

    Note: Links are generated when noStdLibLink is set to false.

    -

    Default: false.

    +

    Default: false

    Whether to generate external documentation links to JDK's Javadocs.

    @@ -379,7 +379,7 @@ with [all configuration options](#complete-configuration) applied at the bottom This is useful if some types that come from dependencies are not resolved/picked up automatically. This option accepts both .jar and .klib files.

    -

    Default: {project.compileClasspathElements}.

    +

    Default: {project.compileClasspathElements}

    @@ -537,11 +537,11 @@ The `perPackageOptions` configuration block allows setting some options for spec

    The regular expression that is used to match the package.

    -

    Default: .*.

    +

    Default: .*

    Whether this package should be skipped when generating documentation.

    -

    Default: false.

    +

    Default: false

    The set of visibility modifiers that should be documented.

    @@ -549,12 +549,12 @@ The `perPackageOptions` configuration block allows setting some options for spec This can be used if you want to document protected/internal/private declarations within this package, as well as if you want to exclude public declarations and only document internal API.

    -

    Default: PUBLIC.

    +

    Default: PUBLIC

    Whether to document declarations annotated with @Deprecated.

    This can be set on project/module level.

    -

    Default: false.

    +

    Default: false

    @@ -562,7 +562,7 @@ The `perPackageOptions` configuration block allows setting some options for spec after they have been filtered by documentedVisibilities and other filters.

    This setting works well with failOnWarning.

    -

    Default: false.

    +

    Default: false

    From 2722784ec6f8fbf4b6725c8d97415c32737b3502 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Mon, 9 Jan 2023 18:50:15 +0100 Subject: [PATCH 13/14] Address review comments --- docs/dokka.tree | 2 +- docs/topics/runners/dokka-gradle.md | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/dokka.tree b/docs/dokka.tree index 1825b6bcb6..73ac277eb1 100644 --- a/docs/dokka.tree +++ b/docs/dokka.tree @@ -9,7 +9,7 @@ - + diff --git a/docs/topics/runners/dokka-gradle.md b/docs/topics/runners/dokka-gradle.md index aff8b680a0..21a4232216 100644 --- a/docs/topics/runners/dokka-gradle.md +++ b/docs/topics/runners/dokka-gradle.md @@ -4,7 +4,7 @@ To generate documentation for a Gradle-based project, you can use the [Gradle plugin for Dokka](https://plugins.gradle.org/plugin/org.jetbrains.dokka). It comes with basic autoconfiguration for your project, has convenient [Gradle tasks](#generate-documentation) for -generating documentation, and provides a great deal of [configuration options](#configuration-example) to +generating documentation, and provides a great deal of [configuration options](#configuration-options) to customize the output. You can play around with Dokka and see how it can be configured for various projects by visiting our @@ -60,7 +60,7 @@ subprojects {
    -See [Configuration example](#configuration-example) if you are not sure where to apply Dokka. +See [Configuration examples](#configuration-examples) if you are not sure where to apply Dokka. > Under the hood, Dokka uses the [Kotlin Gradle plugin](https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin) > to perform autoconfiguration of [source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets) @@ -122,7 +122,7 @@ Use the following tasks to build documentation for simple, single-project applic | `dokkaJekyll` | Generates documentation in [Jekyll compatible Markdown](dokka-markdown.md#jekyll) format. | By default, generated documentation is located in the `build/dokka/{format}` directory of your project. -The output location, among other things, can be [configured](#configuration-example). +The output location, among other things, can be [configured](#configuration-examples). ### Multi-project builds @@ -292,7 +292,7 @@ tasks.register('dokkaJavadocJar', Jar.class) { > {type="tip"} -## Configuration example +## Configuration examples Depending on the type of project that you have, the way you apply and configure Dokka differs slightly. However, [configuration options](#configuration-options) themselves are the same, regardless of the type of your project. @@ -542,7 +542,7 @@ In this case, there are multiple ways of applying and configuring Dokka. #### Subproject configuration -To configure subprojects in a multi-module build, you need to configure [`Partial`](#partial-tasks) tasks. +To configure subprojects in a multi-project build, you need to configure [`Partial`](#partial-tasks) tasks. You can configure all subprojects at the same time in the root `build.gradle.kts` or `build.gradle` file, using Gradle's `allprojects {}` or `subprojects {}` configuration blocks: @@ -693,7 +693,7 @@ Dokka has many configuration options to tailor your and your reader's experience Below are some examples and detailed descriptions for each configuration section. You can also find an example with [all configuration options](#complete-configuration) applied at the bottom of the page. -See [Configuration example](#configuration-example) for more details on where to apply configuration blocks and how. +See [Configuration examples](#configuration-examples) for more details on where to apply configuration blocks and how. ### General configuration From 3df247b34a1b4be7983d3387ded11b064b994677 Mon Sep 17 00:00:00 2001 From: IgnatBeresnev Date: Tue, 10 Jan 2023 12:57:20 +0100 Subject: [PATCH 14/14] Add missing "the" --- docs/topics/dokka-plugins.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/topics/dokka-plugins.md b/docs/topics/dokka-plugins.md index 36e3aa9c14..5d3501acf9 100644 --- a/docs/topics/dokka-plugins.md +++ b/docs/topics/dokka-plugins.md @@ -127,8 +127,8 @@ If you are using [JSON configuration](dokka-cli.md#run-with-json-configuration), ## Configure Dokka plugins -Dokka plugins can also have configuration options of their own. To see which options are available, consult documentation -of the plugins you are using. +Dokka plugins can also have configuration options of their own. To see which options are available, consult +the documentation of the plugins you are using. Let's have a look at how you can configure the `DokkaBase` plugin, which is responsible for generating [HTML](dokka-html.md) documentation, by adding a custom image to the assets (`customAssets` option), by adding custom style sheets

    + List of Markdown files that contain + module and package documentation. +