Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dokka-integration-tests/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# while integration test projects aren't published,
# the version here should be in sync with other versions,
# because it's used to resolve dependencies
version=2.1.0-SNAPSHOT
version=3.0.0-KDP

org.jetbrains.dokka.javaToolchain.mainCompiler=8
org.jetbrains.dokka.javaToolchain.testLauncher=8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ buildscript {
}
}

version = "2.1.0-SNAPSHOT"
version = "3.0.0-KDP"

dependencies {
testImplementation(kotlin("test-junit"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ buildscript {
}
}

version = "2.1.0-SNAPSHOT"
version = "3.0.0-KDP"

tasks.withType<DokkaTask> {
moduleName.set("Configuration Test Project")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class BasicGradleIntegrationTest : AbstractGradleIntegrationTest() {
val indexFile = File(this, "index.html")
assertTrue(indexFile.isFile, "Missing index.html")
assertTrue(
"""<title>Basic Project 2.1.0-SNAPSHOT API </title>""" in indexFile.readText(),
"""<title>Basic Project 3.0.0-KDP API </title>""" in indexFile.readText(),
"Header with version number not present in index.html"
)

Expand Down
51 changes: 51 additions & 0 deletions dokka-ir-to-html-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# dokka-ir-to-html-generator

A small CLI that renders a static HTML page from a Dokka IR JSON input using a React/TypeScript frontend that is server‑side rendered via GraalJS.

## How to build and run

Prerequisites:
- JDK 8+ (the project targets Java 8 toolchain)
- Gradle wrapper (use `./gradlew`)

1) Build a fat JAR (shadow JAR)
- From the project root, run:
```bash
./gradlew :dokka-ir-to-html-generator:shadowJar
```
- The task bundles all dependencies and also builds the frontend bundle. The resulting JAR will be at:
- `dokka-ir-to-html-generator/build/libs/docgen.jar`

2) Run it against any input.json
- Provide a path to a JSON file that contains the page data (an example `input.json` is in this module’s directory):
```bash
java -jar build/libs/docgen.jar input.json
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is how to run it

```

3) Inspect the result
- The program produces `output.html` in the current working directory.
- It also prints the raw rendered HTML to stdout for convenience.

## What this module consists of

This module has two main parts:

1. Kotlin CLI (server‑side rendering bridge)
- `src/main/kotlin/Main.kt`
- Entry point that reads the JSON input file.
- Starts a GraalJS context and evaluates the webpacked server bundle (`server-bundle.js`).
- Calls the exported `SSR.render` function to produce HTML string.
- Injects the HTML and the serialized page data into an HTML template and writes `output.html`.
- Resources
- `src/main/resources/index.html` (copied from `src/frontend/public/index.html` by Gradle) — the HTML template containing placeholders for app markup and serialized data.

2. React/TypeScript frontend (rendered on the server via GraalJS)
- Location: `src/frontend`
- Client entry: `src/frontend/src/client/index.tsx` (hydration/runtime on the client if needed).
- Server entry: `src/frontend/src/server/index.tsx` (exports `SSR.render(data)` used by Kotlin).
- Shared app code: `src/frontend/src/shared/App.tsx`.
- Polyfills for the server bundle: `src/frontend/src/server/polyfills.ts`.
- Static HTML template: `src/frontend/public/index.html`.
- Webpack configs: `src/frontend/webpack.config.js` (and `webpack.client.config.js` if present).
- Build
- Gradle runs `npm install` and `npm run build` under `src/frontend`, then copies the produced `server-bundle.js` and `index.html` into the JVM resources so they are packaged inside `docgen.jar`.
82 changes: 82 additions & 0 deletions dokka-ir-to-html-generator/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
kotlin("jvm")
application
id("com.github.johnrengelman.shadow") version "8.1.1" // Plugin to build a fat JAR
}

repositories {
mavenCentral()
}

dependencies {
// new versions of GraalJS require Java 17+.
// For Java 8 use older versions (the last one supporting Java 8 is 21.0.0.2)
implementation("org.graalvm.sdk:graal-sdk:21.0.0.2")
implementation("org.graalvm.js:js:21.0.0.2")

// Library for convenient JSON handling in CLI (optional, but useful for reading input.json)
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.0")
}

application {
mainClass.set("MainKt")
}

// Configure the toolchain so Gradle uses Java 8 for compilation
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
}


// --- 1. Frontend build configuration ---

// Task to run npm install
val npmInstall by tasks.registering(Exec::class) {
workingDir = file("src/frontend")
// OS check to call the correct command
val npmCmd = if (System.getProperty("os.name").lowercase().contains("win")) "npm.cmd" else "npm"
commandLine(npmCmd, "install")
// So the task won't run every time if node_modules already exists
inputs.file("src/frontend/package.json")
outputs.dir("src/frontend/node_modules")
}

// Task to run npm run build
val npmBuild by tasks.registering(Exec::class) {
dependsOn(npmInstall)
workingDir = file("src/frontend")
val npmCmd = if (System.getProperty("os.name").lowercase().contains("win")) "npm.cmd" else "npm"
commandLine(npmCmd, "run", "build")

inputs.dir("src/frontend/src")
inputs.file("src/frontend/webpack.config.js")
// The webpack result is our bundle
outputs.file("src/main/resources/server-bundle.js")
}

// Make resource processing depend on the JS build
tasks.processResources {
dependsOn(npmBuild)
from("src/frontend/public/index.html")
}

tasks.named<JavaExec>("run") {
// Pass the path to the file as an argument.
// The input.json file should be in the project root (next to build.gradle.kts)
args = listOf("input.json")
}


// --- 2. JAR build configuration ---

tasks.withType<ShadowJar> {
archiveFileName.set("docgen.jar") // Name of the output JAR
mergeServiceFiles() // Important for GraalJS so services are included
manifest {
attributes["Main-Class"] = "MainKt"
}
}
8 changes: 8 additions & 0 deletions dokka-ir-to-html-generator/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"title": "Test Page from GraalVM",
"items": [
"Class A",
"Function B",
"Property C"
]
}
21 changes: 21 additions & 0 deletions dokka-ir-to-html-generator/output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documentation</title>
<!-- Webpack will include styles here if you use MiniCssExtractPlugin -->
<!-- Or you can also replace this with a placeholder if paths change -->
</head>
<body>
<!-- Kotlin will insert the renderToString result here -->
<div id="root"><div class="dokka-page"><h1>Test Page from GraalVM</h1><ul><li>Class A</li><li>Function B</li><li>Property C</li></ul><footer>Generated by GraalJS</footer></div></div>

<!-- Kotlin should insert the JSON data here -->
<script>
window.__INITIAL_DATA__ = {"title":"Test Page from GraalVM","items":["Class A","Function B","Property C"]};
</script>

<!-- Link to the JS bundle that Webpack builds from src/client/index.tsx -->
<script src="client.js"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions dokka-ir-to-html-generator/src/frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
Loading
Loading