2024-08-04
Preparing For Release
Series: Creating A Compose Multiplatform UI Library
Table of Contents
• Introduction
• TLDR
• Prepping your project for release
• Adding an open-source License
• Adding the README.md files
• The root README.md
• The segmented-display README.md
• The composeApp README.md
• Automated reference documentation
• Adding the Dokka Gradle Plugin
• Adding KDoc comments
• Generating the reference documentation site locally
• Improving the look of your reference documentation
• Configuring Gradle to publish our library
• Including the maven-publish plugin
• Initial configuration of the maven-publish plugin
• Testing by publishing locally
• Inspecting the output of publishing locally
• Adding the javadoc.jar file
• Conclusion
Now that we have a useful bit of multiplatform UI, it's time to share that code with the world. This is article 5 in the series about creating a Compose Multiplatform UI library. The previous article was the final article in the series that focused on improving the look of the segmented display. In this article, we'll perform the less-glamorous task of preparing our library for release in a way that can be easily consumed. In the next article, we will actually release our library to Maven Central.
At the end of this article, you will have:
Even though you may feel that your code is totally self-explanatory and that it should be obvious to the rest of the world how to get the code and use it and what the implications are if they were to use your software.
The world of open-source licenses is quite complex. I'm not a lawyer, and I cannot provide legal advice. In this article, we'll use Apache-2.0, but that is not meant to influence your decision on what license to use. If you're looking for a starting place to research licenses, Wikipedia has a comparison of software licenses. The simplest way to download this license is to curl it. In a command prompt, navigate to the root directory of the project and run the following:
$ curl -o LICENSE https://www.apache.org/licenses/LICENSE-2.0.txt
Now that we have the license file, let's take care of helping visitors to our repository successfully navigate our project. The README.md file is the first thing that visitors to your repository will see. It should contain a brief description of the project, how to get the code, how to use the code, and how to contribute to the project.
This file should be seen as the front page of your project, and often, many people will not look further at your project. Let's get started by creating a README.md that just has a screenshot added to the top.
First, run your project on one of the platforms (I chose web):
./gradlew :composeApp:wasmJsBrowserRun
Then take a screenshot of the output. I called the screenshot readme_headline.png
. Now put the file in the docs/images
directory of your project (if the directory doesn't exist already, create it).
Now create the README.md
file in the root of your project (if it doesn't exist). and add the following:
# segmented-display

The line # segmented-display
above should actually be the name of your project.
If the README.md
file already exists, just delete the contents and add the above.
Now you'll want to describe your repository and it's main offering.
Segmented displays are ubiquitous in the world of electronics. They are used in everything from digital clocks to thermostats to calculators to microwave ovens. This library provides a Composable function that can be used to create and style a segmented display in your Compose Multiplatform application.
Next, we'll want to describe the supported platforms:
## Supported Platforms
Because this library is a [Compose Multiplatform](https://www.jetbrains.com/lp/compose-multiplatform/) library, the following platforms are supported:
* Android
* iOS
* Desktop (via JVM)
* Web (via WASM)
Finally, we'll explain the project structure:
## Project Structure
There are two modules in this project:
* [segmented-display](segmented-display/README.md), the library module that you can depend upon in your Compose Multiplatform project
* [composeApp](composeApp/README.md), a demo application that shows the main library features
It may be wise to add a gif that will help you demonstrate the library in action somewhere on the root README.md file. You can see this article I previously wrote regarding how you can make such a gif.
After we've actually published our library, we'll add a section on how to get the library from Maven Central, add version badges, etc. Next, we'll add the README.md files for the segmented-display
module and the composeApp
module.
This README.md should be the landing spot for people who are interested in using, extending or reading your library code. While this should not be the reference documentation, it should point to some of the important parts of the code, such as the main composable functions. It should also give some advice regarding usage and extension.
Create the README.md
file in the segmented-display
directory of your project (if it doesn't exist) and add the following:
# segmented-display
This library provides the following Composable functions that can be used to create a segmented
display:
* [Rect7SegmentDisplay](src/commonMain/kotlin/com/fsryan/ui/segments/Rect7Segment.kt)
* [Hexagonal7SegmentDisplay](src/commonMain/kotlin/com/fsryan/ui/segments/Hexagonal7Segment.kt)
Of these, the one you'll most likely want to use is [Classic7SegmentDisplay](src/commonMain/kotlin/com/fsryan/ui/segments/Classic7SegmentDisplay.kt) because the rectangular version is visually unappealing.
## Usage
The most basic usage of the `Classic7SegmentDisplay` composable function is as follows:
```kotlin
Classic7SegmentDisplay(
modifier = Modifier.fillMaxWidth().aspectRatio(0.5F),
text = "01234567"
)
```
However, you can also style the display in a number of ways:
```kotlin
Classic7SegmentDisplay(
modifier = Modifier.fillMaxWidth().aspectRatio(0.5F),
text = "01234567",
shearPct = 0.18F,
topAreaPercentage = 0.45F,
thicknessMultiplier = 0.75F,
gapSizeMultiplier = 1.25F,
activatedColor = Color.Red,
debuggingEnabled = true,
angledSegmentEndsOf = ::createAsymmetricAngled7SegmentEndsFun
)
```
## Developing your own segmented display
If you want to develop your own segmented display, you can use the more-generic [SingleLineSegmentedDisplay](src/commonMain/kotlin/com/fsryan/ui/segments/SingleLineSegmentedDisplay.kt) composable function as a starting point and then implement your own `renderCharOnCanvas` function. As for how to implement your `renderCharOnCanvas` function, you could use the [drawRect7SegmentChar](src/commonMain/kotlin/com/fsryan/ui/segments/Rect7SegmentDisplay.kt#L57) and [drawClassic7SegmentChar](src/commonMain/kotlin/com/fsryan/ui/segments/Classic7SegmentDisplay.kt#L61) functions as examples.
Then you can pass your new function to the `SingleLineSegmentedDisplay` composable function as the `renderCharOnCanvas` parameter as below:
```kotlin
SingleLineSegmentedDisplay(
modifier = Modifier.fillMaxWidth().aspectRatio(0.5F),
text = "01234567",
shearPct = 0.15F,
renderCharOnCanvas = { idx: Int, char: Char, offset: Offset, charWidth: Float, charHeight: Float ->
// your implementation that draws a vertical segmented display character here
}
)
```
As you can see above, some basic hints about usage, extension and some links to relevant code are provided.
For the sample app, the most importatnt point is to show how the app can be run on the various platforms.
# FS Segmented Display Sample App
This app is intended to enable basic manipulation of some of the properties you can style.
## Running
* in a browser: `./gradlew :app:wasmJsBrowserRun`
* In a desktop window: `./gradlew :app:desktopRun -DmainClass=MainKt`
* On an Android device: `./gradlew :app:installDebug && adb shell am start -n com.fsryan.ui/.MainActivity`
* On an iOS device: it's just best to use Android Studio plus the [Kotlin Multiplatform plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform)
Now that we've created a very basic tour of our library for visitors of our repository, we should provide more comprehensive documentation for developers who want to use our library. It's important to not skip this, as, if we publish it correctly, we'll have our versioned reference documentation available for us via javadoc.io. Moreover, Maven Central forces you to provide a javadoc.jar file. In the next article, we'll package up our reference documentation in a javadoc.jar and publish it with our library.
Dokka is the tool we'll use to generate our reference documentation website. To add Dokka to your project, first declare the plugin dependency in your gradle/libs.versions.toml
file:
[versions]
# other versions
dokka = "1.9.20"
[libraries]
# libraries
[plugins]
# other plugins
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
Then we must apply the dokka plugin to our segmented-display
module. Add the following to the plugins
block of the segmented-display/build.gradle.kts
file:
plugins {
// other plugins
id("org.jetbrains.dokka") version versions["dokka"]
}
Finally, sync the project, and you now should be able to generate your reference documentation website.
In contrast to typical javadocs, Kotlin uses KDoc comments. These comments are similar to javadocs, but they are written in markdown. You should add KDoc comments to all public references in your library. For example, on our transformCharToActiveSegments
function:
/**
* A basic transformation function that translates a character to the active
* segments that can be used for determining the segments of a 7-segment
* display that are active. The active segments are described withing the 7
* least significant bits of the returned integer and are mapped as follows
* (where the number shown be low is the index of the bit from least to most
* significant):
*
* ```
* 1111
* 2 3
* 2 3
* 2 3
* 4444
* 5 6
* 5 6
* 5 6
* 7777
* ```
*
* > [!NOTE]
* > If the character is not in 0-9a-zA-Z\-, then 0 will be returned
*
* > [!NOTE]
* > Capitalization does nto make a difference
*
* @param char the character to translate
* @return the active segments for the character
* @author fsryan
*/
fun transformCharToActiveSegments(char: Char): Int = when (char) {
/* ... */
}
Here we've added a KDoc comment that explains what the function does, what the function returns, and what the function does in the case of an invalid character. Additionally, using @param
and @return
, we've described the inputs and outputs. We've also documented the author of the function using the @author
marker. Writing good KDoc comments is often difficult. Here's a list of things to avoid:
Here are some things to consider as you write your KDocs:
@param
marker and outputs use the @return
marker; there is no specific marker for edge cases)@throws
)@see
to link to another identifier's KDoc or you can add markdown links.I'm not going to go through every identifier here, but you should add KDoc comments to all public identifiers in your library.
Let's take a look at our documentation site. To generate the reference documentation page with gradle:
./gradlew :segmented-display:dokkaHtml
This will generate the documentation in the segmented-display/build/dokka
directory. Open the index.html
file in your browser to see the documentation. On OSX, you can open the reference documentation in your browser by:
open segmented-display/build/dokka/index.html
As you can see, however, our documentation page looks a little sparse:
But if we click on the one package name and then on the "Functions" tab, we can see the documentation we've added.
Another thing you'll notice is that our documentation page is cluttered with the Compose preview functions and helper functions we added for the previews. These functions obscure the public identifiers we want our consumers to use and understand. Because Dokka, by default, only generates documentation for public identifiers, we can fix that by changing the visibility modifier of those preview functions to internal
. So for all the compose preview functions we've written, just change fun
to internal fun
.
Now, regenerating the documentation, we have only the identifiers we want our consumers to know about.
For a tool that helps create documentation, it's ironic, but Dokka does not document its features well. However, you can style your documentation site and add to it. Let's start by adding some content for the segmented-display
module. To see how it works, create a file called segmented-display/MODULE.md
, and add the following:
#Module segmented-display
This is a Compose Multiplatform library that targets Android, desktop, iOS, and WASM JS.
Then include this markdown file in the dokka configuration of your segmented-display/build.gradle.kts
file:
tasks.withType<DokkaTask> {
dokkaSourceSets.configureEach {
includes.from("MODULE.md")
}
}
Now, if you regenerate your documentation site, you should have the following:
You can add anything you want to this markdown file, as long as the content is markdown. You can link to external or bundled images, link to your company's website, etc. Below, we'll do the following:
docs/images/readme_headline.png
image with the documentation siteMODULE.md
file#Module segmented-display
This is a Compose Multiplatform library that targets Android, desktop, iOS, and WASM JS.

Notice above that we changed the module name and that we referenced the image with a relative path. Now we need to tell dokka both to bundle the image, to change the module name, and to add a custom footer message:
In the segmented-display/build.gradle.kts
file, add the following:
tasks.withType<DokkaTask> {
val dokkaBaseConfiguration = buildString {
append("{\"customAssets\": [\"")
append(rootProject.file("docs/images/readme_headline.png"))
append("\"],")
append("\"customStyleSheets\": [],")
append("\"footerMessage\": \"(c) 2024 FS Ryan Software\"")
append("}")
}
pluginsMapConfiguration.set(
mapOf("org.jetbrains.dokka.base.DokkaBase" to dokkaBaseConfiguration)
)
dokkaSourceSets.configureEach {
reportUndocumented.set(true)
includes.from("MODULE.md")
}
}
That will result in something like the following after regenerating the documentation page:
You can customize the look of your documentation site in many more ways, however, We'll stop here for now. See the Dokka HTML documentation for more information.
"POM" stands for "Project Object Model." In other words, a pom file is a document that describes your project. You can learn more about it from the apache maven website. It's a very mature description of a project that is ubiquitous throughout the Java/Kotlin ecosystem. After we include the maven-publish
plugin in our project, we'll need to configure the pom file to provide information about our project.
To include the maven-publish
plugin, add the following to the plugins
block of the segmented-display/build.gradle.kts
file:
plugins {
// other plugins
`maven-publish`
}
This will give you access to the MavenPublication
class in your segmented-display/build.gradle.kts
file. Sync the gradle project to enable code completion.
Multiplatform publishing is only slightly more complicated than single-platform publishing. The biggest difference is that we need to configure many different publications--not just one. Therefore, adding an extension on top of MavenPublication
that configures each publication will help us maintain uniformity among each publication. Add the following at the top level of the segmented-display/build.gradle.kts
file:
// A function that will configure the maven publishing for a publication
fun MavenPublication.configureMultiplatformPublishing(project: Project) {
val publicationName = name
with(pom) {
description.set("$publicationName target of the Compose Multiplatform FS Ryan library for rendering segmented displays")
inceptionYear.set("2024")
url.set("https://github.com/fsryan-org/segmented-display")
issueManagement {
url.set("https://github.com/fsryan-org/segmented-display/issues")
system.set("GitHub Issues")
}
licenses {
license {
name.set("The Apache Software License, Version 2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
distribution.set("repo")
}
}
developers {
developer {
id.set("ryan")
name.set("Ryan Scott")
email.set("ryan@fsryan.com")
organization.set("FS Ryan")
organizationUrl.set("https://www.fsryan.com")
}
}
scm {
url.set("https://github.com/fsryan-org/segmented-display.git")
developerConnection.set("scm:git:git@github.com:fsryan-org/segmented-display.git")
}
}
}
There's a lot here, so lets break it down:
The val publicationName = name
line is there because both the MavenPom
class (which is the default receiver of all calls inside the with
block) has a Property<String>
getter function called getName
, which clashes with MavenPublication.name
, which is a String
. Inside of the with
block, we're configuring the various parts of the pom file. The issueManagement
, licenses
, developers
, and scm
blocks will be used by Maven Central to direct users who are looking at our library to our repository page on GitHub as well as provide a point of contact for the developer who produced the library. The licenses block is also important in that it communicates the open source license we used to license our library.
Then, also in the segmented-display/build.gradle.kts
file, add the following to the publishing
block:
publishing {
publications.withType(MavenPublication::class.java) {
configureMultiplatformPublishing(project)
}
publications.whenObjectAdded {
(this as? MavenPublication)?.configureMultiplatformPublishing(project)
}
}
We're actually publishing seven publications: common (which is unmarked), android, iosArm64, iosSimulatorArm64, iosX64, jvm, and wasm-js.
Each publication has its target marked with an indicator at the end of the name. For example, the wasm-js publication is called segmented-display-wasm-js
.
Why do we need to add the publications.whenObjectAdded
call? The Android Gradle plugin defers creation of the android release publication. This block allows us to catch these deferred publications and configure them in the same way we configured the other publications.
Here, you can stop and check that you have all the correct publishing tasks:
./gradlew :segmented-display:tasks --group=publishing
The output should look like this:
------------------------------------------------------------
Tasks runnable from project ':segmented-display'
------------------------------------------------------------
Publishing tasks
----------------
generateMetadataFileForIosArm64Publication - Generates the Gradle metadata file for publication 'iosArm64'.
generateMetadataFileForIosSimulatorArm64Publication - Generates the Gradle metadata file for publication 'iosSimulatorArm64'.
generateMetadataFileForIosX64Publication - Generates the Gradle metadata file for publication 'iosX64'.
generateMetadataFileForJvmPublication - Generates the Gradle metadata file for publication 'jvm'.
generateMetadataFileForKotlinMultiplatformPublication - Generates the Gradle metadata file for publication 'kotlinMultiplatform'.
generateMetadataFileForWasmJsPublication - Generates the Gradle metadata file for publication 'wasmJs'.
generatePomFileForIosArm64Publication - Generates the Maven POM file for publication 'iosArm64'.
generatePomFileForIosSimulatorArm64Publication - Generates the Maven POM file for publication 'iosSimulatorArm64'.
generatePomFileForIosX64Publication - Generates the Maven POM file for publication 'iosX64'.
generatePomFileForJvmPublication - Generates the Maven POM file for publication 'jvm'.
generatePomFileForKotlinMultiplatformPublication - Generates the Maven POM file for publication 'kotlinMultiplatform'.
generatePomFileForWasmJsPublication - Generates the Maven POM file for publication 'wasmJs'.
publish - Publishes all publications produced by this project.
publishIosArm64PublicationToMavenLocal - Publishes Maven publication 'iosArm64' to the local Maven repository.
publishIosSimulatorArm64PublicationToMavenLocal - Publishes Maven publication 'iosSimulatorArm64' to the local Maven repository.
publishIosX64PublicationToMavenLocal - Publishes Maven publication 'iosX64' to the local Maven repository.
publishJvmPublicationToMavenLocal - Publishes Maven publication 'jvm' to the local Maven repository.
publishKotlinMultiplatformPublicationToMavenLocal - Publishes Maven publication 'kotlinMultiplatform' to the local Maven repository.
publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.
publishWasmJsPublicationToMavenLocal - Publishes Maven publication 'wasmJs' to the local Maven repository.
Notably, we don't see any publishing tasks for our Android release publication. Let's fix that. In the segmented-display/build.gradle.kts
file's kotlin
block, we configure the androidTarget
target. Add the following line to that block:
androidTarget {
publishLibraryVariants("release")
/* ... */
}
Now when we run:
./gradlew :segmented-display:tasks --group=publishing
We should see:
------------------------------------------------------------
Tasks runnable from project ':segmented-display'
------------------------------------------------------------
Publishing tasks
----------------
generateMetadataFileForAndroidReleasePublication - Generates the Gradle metadata file for publication 'androidRelease'.
generateMetadataFileForIosArm64Publication - Generates the Gradle metadata file for publication 'iosArm64'.
generateMetadataFileForIosSimulatorArm64Publication - Generates the Gradle metadata file for publication 'iosSimulatorArm64'.
generateMetadataFileForIosX64Publication - Generates the Gradle metadata file for publication 'iosX64'.
generateMetadataFileForJvmPublication - Generates the Gradle metadata file for publication 'jvm'.
generateMetadataFileForKotlinMultiplatformPublication - Generates the Gradle metadata file for publication 'kotlinMultiplatform'.
generateMetadataFileForWasmJsPublication - Generates the Gradle metadata file for publication 'wasmJs'.
generatePomFileForAndroidReleasePublication - Generates the Maven POM file for publication 'androidRelease'.
generatePomFileForIosArm64Publication - Generates the Maven POM file for publication 'iosArm64'.
generatePomFileForIosSimulatorArm64Publication - Generates the Maven POM file for publication 'iosSimulatorArm64'.
generatePomFileForIosX64Publication - Generates the Maven POM file for publication 'iosX64'.
generatePomFileForJvmPublication - Generates the Maven POM file for publication 'jvm'.
generatePomFileForKotlinMultiplatformPublication - Generates the Maven POM file for publication 'kotlinMultiplatform'.
generatePomFileForWasmJsPublication - Generates the Maven POM file for publication 'wasmJs'.
publish - Publishes all publications produced by this project.
publishAndroidReleasePublicationToMavenLocal - Publishes Maven publication 'androidRelease' to the local Maven repository.
publishIosArm64PublicationToMavenLocal - Publishes Maven publication 'iosArm64' to the local Maven repository.
publishIosSimulatorArm64PublicationToMavenLocal - Publishes Maven publication 'iosSimulatorArm64' to the local Maven repository.
publishIosX64PublicationToMavenLocal - Publishes Maven publication 'iosX64' to the local Maven repository.
publishJvmPublicationToMavenLocal - Publishes Maven publication 'jvm' to the local Maven repository.
publishKotlinMultiplatformPublicationToMavenLocal - Publishes Maven publication 'kotlinMultiplatform' to the local Maven repository.
publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.
publishWasmJsPublicationToMavenLocal - Publishes Maven publication 'wasmJs' to the local Maven repository.
Notice the android release publication.
In the above output, you may have seen a publishToMavenLocal
task. That's the task we'll use to test our publishing configuration. The maven local repository is just a directory on your system (usually ~/.m2/repository
). Test by running this task:
./gradlew clean :segmented-display:publishToMavenLocal
I included the clean
task just to make sure that there were no lingering files on my system that got packaged. Generally, when publishing, it's a good idea to start from a clean state.
If you now inspect your ~/.m2/repository directory, however, you'll not find your nice group name and artifact name following the typical structure with a version. You'll actually just see a directory that has your root project name and a directory inside it with your module name. To remedy this, we should configure the group name and version. In your root build.gradle.kts
file, add the following:
allprojects {
group = "com.fsryan.ui"
version = "0.0.3"
}
Use your own group--not mine.
I used version 0.0.3 because I had already published 0.0.1 and 0.0.2
Now run the publishToMavenLocal
task again. You should see the group name and version in the directory structure of your local maven repository.
$ ls -1 ~/.m2/repository/com/fsryan/ui
segmented-display
segmented-display-android
segmented-display-iosarm64
segmented-display-iossimulatorarm64
segmented-display-iosx64
segmented-display-jvm
segmented-display-wasm-js
The com/fsryan/ui
part of the path came from the group name. The segmented-display
part is the artifact name. In multiplatform publishing, the artifact that lacks a target indicator is the common artifact. The other artifacts are the platform-specific artifacts, as marked by the target indicator.
Let's also inspect one of those directories:
$ ls ~/.m2/repository/com/fsryan/ui/segmented-display-jvm/
0.0.3 maven-metadata-local.xml
Here, we have a directory that contains the files for the version 0.0.3. If we were to publish another version, then there would be another directory with the version number.
Additionally, maven-metadata-local.xml
is just an XML file that contains some metadata about segmented-display-jvm
on the whole, describing things like when versions were published, etc. You don't really need to do anything with this file.
In contrast to our local environment, this file will be called maven-metadata.xml
when we publish to Maven Central.
Finally, let's look inside the 0.0.3 directory to see what it contains. These are the files that will get published to Maven Central.
$ ls -1 ~/.m2/repository/com/fsryan/ui/segmented-display-jvm/0.0.3
segmented-display-jvm-0.0.3-sources.jar
segmented-display-jvm-0.0.3.jar
segmented-display-jvm-0.0.3.module
segmented-display-jvm-0.0.3.pom
Notice that while the maven-publish plugin is automatically creating the sources jar, it's not automatically creating the javadoc.jar.
To add the javadoc.jar file, we need to:
dokkaHtml
task into a jar fileMavenPublication
publishToMavenLocal
taskLet's register the task that bundles the output of the dokkaHtml
into a jar file. In segmented-display/build.gradle.kts
:
tasks.register<Jar>("dokkaHtmlJar") {
dependsOn(tasks.dokkaHtml)
from(tasks.dokkaHtml.flatMap { it.outputDirectory })
archiveClassifier.set("javadoc")
}
In line order, the dependsOn
function sets the new dokkaHtmlJar
task dependent upon the dokkaHtml
task. The from
function tells the dokkaHtmlJar
task to include the output of the dokkaHtml
task in the jar file. And finally, the archiveClassifier
function sets the classifier of the jar file to "javadoc". It's important to set this archive classifier because consuming applications will know to look for this.
Now we'll add the output of dokkaHtmlJar
as an artifact of each MavenPublication
. If you go back to where we created the configureMultiplatformPublishing
extension function on MavenPublication
, add the following to the bottom of that function:
if (name != "androidRelease") {
artifact(project.tasks.withType<Jar>().first { it.name == "dokkaHtmlJar" })
}
I couldn't figure out why adding the javadoc jar to the androidRelease publication wasn't working. Having tried many things, I had to admit defeat and move on. Maven Central did not reject my library when I published it.
Rerun the segmented-display:publishToMavenLocal
task and check the contents of segmented-display-jvm
again. You should see that the javadoc.jar was added:
$ ls -1 ~/.m2/repository/com/fsryan/ui/segmented-display-jvm/0.0.3/
segmented-display-jvm-0.0.3-javadoc.jar
segmented-display-jvm-0.0.3-sources.jar
segmented-display-jvm-0.0.3.jar
segmented-display-jvm-0.0.3.module
segmented-display-jvm-0.0.3.pom
So you see now that the javadoc.jar got generated. Lets look at the files inside the javadoc.jar to ensure that our website was added:
$ jar -tf ~/.m2/repository/com/fsryan/ui/segmented-display-jvm/0.0.3/segmented-display-jvm-0.0.3-javadoc.jar
ryan[MyUILibrary] (main)$ jar -tf ~/.m2/repository/com/fsryan/ui/segmented-display-jvm/0.0.3/segmented-display-jvm-0.0.3-javadoc.jar
META-INF/
META-INF/MANIFEST.MF
segmented-display/
segmented-display/com.fsryan.ui.segments/
segmented-display/com.fsryan.ui.segments/create-symmetric-angled7-segment-ends-fun.html
segmented-display/com.fsryan.ui.segments/symmetric-even-angled-segment-ends.html
segmented-display/com.fsryan.ui.segments/index.html
segmented-display/com.fsryan.ui.segments/-rect7-segment-display.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends.html
segmented-display/com.fsryan.ui.segments/-classic7-segment-display.html
segmented-display/com.fsryan.ui.segments/draw-rect7-segment-char.html
segmented-display/com.fsryan.ui.segments/draw-classic7-segment-char.html
segmented-display/com.fsryan.ui.segments/-single-line-segmented-display.html
segmented-display/com.fsryan.ui.segments/transform-char-to-active-segments.html
segmented-display/com.fsryan.ui.segments/create-asymmetric-angled7-segment-ends-fun.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/outer-edge-left-area.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/right-intersection-pct.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/index.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/-companion/
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/-companion/index.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/-companion/-e-v-e-n.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/inner-edge-right-area.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/left-intersection-pct.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/inner-edge-left-area.html
segmented-display/com.fsryan.ui.segments/-angled-segment-ends/outer-edge-right-area.html
segmented-display/package-list
index.html
images/
images/copy-icon.svg
images/footer-go-to-link.svg
images/logo-icon.svg
images/nav-icons/
images/nav-icons/function.svg
images/nav-icons/interface.svg
images/nav-icons/enum.svg
images/nav-icons/typealias-kotlin.svg
images/nav-icons/field-value.svg
images/nav-icons/abstract-class.svg
images/nav-icons/class-kotlin.svg
images/nav-icons/class.svg
images/nav-icons/exception-class.svg
images/nav-icons/annotation-kotlin.svg
images/nav-icons/field-variable.svg
images/nav-icons/abstract-class-kotlin.svg
images/nav-icons/enum-kotlin.svg
images/nav-icons/object.svg
images/nav-icons/interface-kotlin.svg
images/nav-icons/annotation.svg
images/burger.svg
images/go-to-top-icon.svg
images/arrow_down.svg
images/copy-successful-icon.svg
images/homepage.svg
images/theme-toggle.svg
images/anchor-copy-button.svg
images/readme_headline.png
styles/
styles/font-jb-sans-auto.css
styles/main.css
styles/prism.css
styles/style.css
styles/logo-styles.css
scripts/
scripts/prism.js
scripts/platform-content-handler.js
scripts/symbol-parameters-wrapper_deferred.js
scripts/navigation-loader.js
scripts/main.js
scripts/clipboard.js
scripts/sourceset_dependencies.js
scripts/pages.json
navigation.html
You can see that the javadoc.jar contains the entire documentation site. This is what will be published to Maven Central and then picked up by javadoc.io.
Finally, let's inspect the contents of the segmented-display-jvm-0.0.3.pom
file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<groupId>com.fsryan.ui</groupId>
<artifactId>segmented-display-jvm</artifactId>
<version>0.0.3</version>
<description>jvm target of the Compose Multiplatform FS Ryan library for rendering segmented displays</description>
<url>https://github.com/fsryan-org/segmented-display</url>
<inceptionYear>2024</inceptionYear>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>ryan</id>
<name>Ryan Scott</name>
<email>ryan@fsryan.com</email>
<organization>FS Ryan</organization>
<organizationUrl>https://www.fsryan.com</organizationUrl>
</developer>
</developers>
<scm>
<developerConnection>scm:git:git@github.com:fsryan-org/segmented-display.git</developerConnection>
<url>https://github.com/fsryan-org/segmented-display.git</url>
</scm>
<issueManagement>
<system>GitHub Issues</system>
<url>https://github.com/fsryan-org/segmented-display/issues</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.compose.foundation</groupId>
<artifactId>foundation-desktop</artifactId>
<version>1.6.11</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.compose.ui</groupId>
<artifactId>ui-desktop</artifactId>
<version>1.6.11</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
As you can see, the full text of the pom file describes the project and its dependencies. This is what will be used by Maven Central to describe our project and direct users to our project source, etc. It's also what will be used by gradle to perform transitive dependency resolution. Notice that the properties we configured when we initially configured the maven publish plugin appear here as well.
In contrast to previous articles, this article was less exciting, but it was necessary. The additions to our project in this article makes our code more accessible to others while simultaneously adding the features that make our library more discoverable and usable. In the next article, we'll configure signing for our library and publish it to Maven Central. We'll then add some instructions to our README.md file about how to consume the library via binary dependency, and test it out ourselves.