How to Configure Theme Bundling and Offline Asset Distribution in Quarkdown HTML
Quarkdown HTML bundles every runtime dependency—including third-party libraries and theme assets—into a self-contained build/install/ directory via Gradle tasks defined in quarkdown-html/build.gradle.kts, enabling completely offline document rendering.
Quarkdown HTML generates standalone documents that require no internet connectivity by compiling SCSS themes, bundling JavaScript dependencies, and assembling all assets into a local distribution. When you configure theme bundling and offline asset distribution in Quarkdown HTML, you control how custom styles and external libraries are packaged alongside the compiled output, ensuring self-contained deployments.
The Gradle-Driven Build Pipeline
The entire bundling process is orchestrated through quarkdown-html/build.gradle.kts, which defines specialized tasks for theme compilation, asset collection, and library distribution. Each stage transforms source files into the final offline-ready structure under build/install/.
SCSS Compilation and Theme Discovery
The build begins by discovering and compiling theme sources located in src/main/scss/. The discoverThemeNames function (lines 32-38) scans the directory structure for layout/, color/, and locale/ subdirectories, excluding partials (files prefixed with _) to identify valid theme entries.
The compileSass task (lines 25-33) then compiles all discovered SCSS files—global styles, layout variants, color schemes, and locale-specific formatting—into flat CSS files. These compiled styles serve as the foundation for the theme assembly process.
Asset Assembly via Manifest Processing
Once SCSS compilation completes, the assembleThemes task (lines 42-93) reorganizes the flat CSS output into a hierarchical directory structure at build/install/theme/<kind>/<name>/. This task also processes optional theme manifests: any <theme>.json file placed alongside an SCSS source can declare an exports array listing additional assets (fonts, images, or other static files) that must ship with the theme.
The readThemeExports helper (lines 22-26) validates these manifests at build time, failing early if declared files are missing from node_modules or source directories. This ensures that every theme package is complete before the distribution is finalized.
Third-Party Library Bundling
Runtime JavaScript dependencies are handled by two distinct tasks. The bundleHighlightJs task (lines 78-103) creates a single IIFE bundle (highlightjs.min.js) from the modular highlight.js npm package, as the standard distribution lacks a pre-bundled browser version.
The bundleThirdParty task (lines 95-115) processes the librariesToBundle list—an array of LibrarySpec objects defined around lines 58-95. Each LibrarySpec specifies the target folder name, the source path within node_modules, and the specific files to copy into build/install/lib/<target>/. The TypeScript bundler marks these libraries as external (--external:<target>), ensuring that quarkdown.min.js references the runtime files rather than inlining them.
Adding Custom Themes with Asset Exports
Creating a new theme requires placing SCSS source files in the appropriate category directory and optionally declaring additional assets through a JSON manifest.
-
Create the SCSS source in the appropriate subdirectory:
// quarkdown-html/src/main/scss/color/sunset.scss $primary-color: #ff6b35; $secondary-color: #f7c59f; // ... additional variable definitions -
(Optional) Declare exported assets by creating a manifest with the same base name:
{ "exports": [ "node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2" ] } -
Execute the build to generate the distribution:
./gradlew clean installDist
After compilation, the theme appears at build/install/theme/color/sunset/sunset.css, with exported fonts or images copied into the same directory. The HTML runtime loads these assets relative to the theme path without network requests.
Bundling External JavaScript Libraries
To include additional runtime dependencies such as clipboard.js or other npm packages, extend the library specifications and install the package.
First, install the dependency via npm:
npm install clipboard --save
Then add a LibrarySpec entry in build.gradle.kts:
LibrarySpec(
"clipboard",
"clipboard/dist",
listOf("clipboard.min.js")
),
Reference the library from the TypeScript entry point (quarkdown-html/src/main/typescript/index.ts):
import "clipboard";
The build system automatically copies the specified files into build/install/lib/clipboard/ and configures the bundler to treat the import as an external dependency. The final installDist output includes the library in the lib/ directory alongside quarkdown.min.js and all theme assets.
Customizing Existing Theme Exports
You can extend existing themes without modifying Gradle configuration by editing their JSON manifests. To add a custom SVG logo to a layout theme:
Update the manifest at src/main/scss/layout/mylayout.json:
{
"exports": [
"node_modules/@my-icons/logo.svg"
]
}
The assembleThemes task automatically validates the path and copies logo.svg into build/install/theme/layout/mylayout/logo.svg during the next build. This manifest-driven approach requires no changes to the core build logic, allowing per-theme customization of distributed assets.
Summary
- Gradle orchestrates the entire pipeline through
quarkdown-html/build.gradle.kts, handling SCSS compilation, theme assembly, and library bundling. - Themes are discovered automatically from
src/main/scss/subdirectories, with compilation handled bytasks.compileSassand assembly byassembleThemes. - Asset exports are manifest-driven—JSON files declare additional resources that
readThemeExportsvalidates andassembleThemespackages intobuild/install/theme/. - Third-party libraries use
LibrarySpecdefinitions to copy files fromnode_modulesintobuild/install/lib/, with the TypeScript bundler treating them as external runtime dependencies. - The final distribution produced by
./gradlew installDistis completely self-contained, loading all resources from locallib/andtheme/directories without network connectivity.
Frequently Asked Questions
How does Quarkdown HTML handle the highlight.js dependency differently from other libraries?
Highlight.js ships as ES modules rather than pre-bundled browser code, so the bundleHighlightJs task (lines 78-103) uses esbuild to create a single highlightjs.min.js IIFE bundle specifically for the distribution. Other libraries listed in librariesToBundle are copied directly from node_modules without additional transformation.
Where are theme assets loaded from when the HTML runs offline?
The HTML runtime uses InstallDirectoryResolver.kt from the quarkdown-install-layout-navigator module to locate the lib/ and theme/ directories relative to the executed document. References to lib/<name>/ and theme/<kind>/<name>/ resolve to the local filesystem, ensuring all CSS, fonts, and JavaScript load without internet access.
Can I bundle assets that are not located in node_modules?
Yes. The exports array in theme JSON manifests accepts relative paths from the project root. While the examples commonly reference node_modules/, you can specify paths to any file within the repository structure, such as src/main/resources/custom-fonts/ or assets/images/, and assembleThemes will copy them into the theme directory.
What happens if I declare an export that does not exist in the manifest?
The readThemeExports function validates all paths during the Gradle configuration phase. If a declared file is missing, the build fails immediately with an error indicating which theme manifest references the non-existent path, preventing incomplete or broken distributions from being generated.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →