A Gradle plugin that converts your Javadoc comments into Docusaurus-ready Markdown files.
Each public class, interface, enum, and record gets its own .md file, organized by package. Fields, constructors, and methods are all documented, including their modifiers, parameter tables, return values, throws tables, and deprecation notices. Inline tags like {@link} and {@code} are converted to Markdown links and code spans. HTML in your Javadoc (lists, tables, bold, <pre> blocks) is converted as well.
- Java 21 or later
- Gradle 8 or later
DocletMD is published via JitPack. Add the JitPack repository and a resolution rule to your settings.gradle (or settings.gradle.kts) so Gradle knows where to find the plugin:
settings.gradle
pluginManagement {
repositories {
maven { url 'https://jitpack.io' }
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'me.stringdotjar.docletmd') {
useModule('com.github.flixelgdx.DocletMD:docletmd:0.1.1')
}
}
}
}Replace
0.1.1with any released tag from the releases page, or use a full commit hash for a snapshot build.
Then apply the plugin alongside the java plugin in your build.gradle:
build.gradle
plugins {
id 'java'
id 'me.stringdotjar.docletmd' version '0.1.1'
}If you prefer the legacy approach, skip the pluginManagement block and use a buildscript classpath instead:
build.gradle
buildscript {
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.github.flixelgdx.DocletMD:docletmd:0.1.1'
}
}
apply plugin: 'java'
apply plugin: 'me.stringdotjar.docletmd'All settings are optional. Add a docletmd {} block to build.gradle to override the defaults:
docletmd {
// Where the generated Markdown files are written.
// Default: build/docletmd
outputDir = file("docs/api")
// Set to true to also document private and package-private members.
// Default: false
includePrivate = false
// Set to true to skip members that have no Javadoc comment at all.
// Default: false
skipEmptyDocs = false
}Run the generateDocletMD task:
./gradlew generateDocletMDThe task is also available in the documentation group in the Gradle task list.
Each class produces one .md file, placed under outputDir in a directory tree that mirrors the package structure. For example, a class com.example.MyService produces:
build/docletmd/
com/
example/
MyService.md
Every file contains:
- A YAML frontmatter block with
titleandsidebar_label(compatible with Docusaurus). - An H1 heading with the class name.
- The full qualified name as an inline code span.
- An optional
:::caution Deprecatedadmonition when the class is deprecated. - The Javadoc description, including inline
{@link}and{@code}tags. @sinceand@seemeta-tags.- Sections for Constructors, Fields, and Methods, each with:
- The full signature (modifiers, return type, parameters, constant value for
finalfields). - The Javadoc description.
- Parameter table (
@paramtags). - Return value (
@returntag). - Throws table (
@throws/@exceptiontags).
- The full signature (modifiers, return type, parameters, constant value for
Every member heading (field, constructor, method) is preceded by an HTML comment that identifies its kind:
<!-- docletmd:field -->
<!-- docletmd:field:static -->
<!-- docletmd:field:constant -->
<!-- docletmd:constructor -->
<!-- docletmd:method -->
<!-- docletmd:method:static -->
field:constant is emitted for static final fields that have a compile-time constant value (primitives and String).
These comments are invisible in all standard Markdown renderers and Docusaurus itself, so generated pages look correct with or without any additional tooling. A Docusaurus remark plugin can read the markers and apply styling -- for example, color-coding headings by member kind -- without modifying the plugin or the generated files.
The markers appear in the raw Markdown AST as html nodes immediately before each heading node of depth 3. A minimal remark plugin that processes them looks like this:
// remark-docletmd-colors.js
export default function remarkDocletmdColors() {
return (tree) => {
const { visit } = require('unist-util-visit');
visit(tree, 'html', (node, index, parent) => {
const match = node.value.match(/^<!-- docletmd:(\S+) -->$/);
if (!match || !parent) return;
const kind = match[1]; // e.g. "method", "field:static", "constructor"
const next = parent.children[index + 1];
if (next?.type === 'heading' && next.depth === 3) {
next.data ??= {};
next.data.hProperties ??= {};
next.data.hProperties.className = `docletmd-${kind.replace(':', '-')}`;
}
});
};
}Then add CSS that targets those classes to apply per-kind colors.
Point Docusaurus at the output directory by adding it as a docs directory or a plugin source in your docusaurus.config.js. Because each file has valid frontmatter, Docusaurus picks up the title and sidebar_label automatically.
// docusaurus.config.js (example)
const config = {
// ...
presets: [
[
'classic',
{
docs: {
path: 'docs',
// If your outputDir points inside docs/, nothing extra is needed.
},
},
],
],
};If your outputDir is outside the Docusaurus docs/ folder, copy or symlink the output after running generateDocletMD, or wire the two Gradle tasks together:
tasks.named('generateDocletMD').configure {
finalizedBy(tasks.named('copyApiDocs'))
}
tasks.register('copyApiDocs', Copy) {
from docletmd.outputDir
into 'path/to/docusaurus/docs/api'
dependsOn generateDocletMD
}MIT