Enhanced Markdown rendering for Bitbucket Data Center: Mermaid diagrams, PlantUML diagrams, and LaTeX math (KaTeX) — right inside the file browser, pull request diffs, commits, and READMEs.
- Mermaid diagrams — 20+ diagram types (flowcharts, sequence, class, state, ER, Gantt, pie, git-graph, mindmap, timeline, C4, Sankey, XY, etc.). Rendered client-side, loaded lazily.
- PlantUML diagrams — 15+ UML and non-UML diagram types. Rendered server-side to SVG.
- LaTeX math — block (
```math) and inline ($…$,$$…$$) formulas via KaTeX. - Mermaid themes — default / dark / forest / neutral, selectable in plugin admin.
All features run everywhere rendered Markdown appears: file view, file browser, pull request descriptions and diffs, commits, and compare views.
- Bitbucket Data Center 8.19+ (tested on 8.19, targets 9.x and 10.x — see Compatibility below)
- Java 11+ (runtime, provided by Bitbucket)
- Download the latest
markdown-extra-*.jarfrom Releases. - In Bitbucket: Administration → Manage apps → Upload app.
- Upload the JAR. That's it — all features are active.
Use markdown-extra-<version>.jar on Bitbucket 8.x/9.x and markdown-extra-<version>-bb10.jar on Bitbucket 10.x.
Bitbucket 10.x: UPM only installs signed apps. Builds from the Atlassian Marketplace are signed by Atlassian; a JAR from GitHub Releases is not, and upload fails with "Signature check failed!". Install from the Marketplace, or on a test instance start Bitbucket with
-Datlassian.upm.signature.check.disabled=true.
Just write regular Markdown:
```mermaid
sequenceDiagram
Alice->>Bob: Hi
Bob-->>Alice: Hi!
```
```plantuml
@startuml
Alice -> Bob : Authentication Request
Bob --> Alice : Authentication Response
@enduml
```
```math
E = mc^2
```
Inline math: $a^2 + b^2 = c^2$.Diagrams render automatically when the file is viewed in Bitbucket.
cd frontend && npm install && npm run build && cd ..
export JAVA_HOME=/path/to/jdk21
mvn package -DskipTestsmvn package also runs the unit tests (drop -DskipTests). The resulting JARs are written to target/markdown-extra-<version>.jar (Bitbucket 8.x/9.x) and target/markdown-extra-<version>-bb10.jar (Bitbucket 10.x).
After building, upload the JAR to a running Bitbucket via the UPM REST API:
./deploy.sh [BITBUCKET_URL] [USERNAME] [PASSWORD]
# defaults: http://localhost:7990 admin adminOr start a clean Bitbucket 8.19 in Docker:
cd docker
docker compose up -d
./deploy-plugin.sh admin admin # deploys target/*.jar to localhost:7990For Bitbucket 10.x use docker-compose.10x.yml and deploy-plugin-10x.sh (runs on localhost:7991).
| Layer | Files |
|---|---|
| Plugin descriptor | src/main/resources/atlassian-plugin.xml |
| Spring scan config | src/main/resources/META-INF/spring/plugin-context.xml |
| REST (settings, PlantUML) | src/main/java/com/plainward/bitbucket/markdownx/rest/ |
| Services (settings, PlantUML render) | src/main/java/com/plainward/bitbucket/markdownx/service/ |
| Admin page (servlet, SYS_ADMIN only) | src/main/java/com/plainward/bitbucket/markdownx/servlet/, src/main/resources/templates/admin.html |
| Frontend orchestrator | frontend/src/markdown-enhancer.js |
| Mermaid (iframe + Shadow DOM) | frontend/src/mermaid-enhancer.js |
| PlantUML (REST → SVG) | frontend/src/plantuml-enhancer.js |
| LaTeX (KaTeX) | frontend/src/katex-enhancer.js |
| MutationObserver | frontend/src/utils/dom-observer.js |
Two non-obvious choices are worth calling out:
- Mermaid renders inside a hidden
<iframe>, then mounts into a Shadow DOM. Bitbucket loads different CSS bundles per page context (filebrowservsfileContent), and the page CSS corrupts Mermaid'sgetBBox()text measurements if it renders in an offscreen container on the host page. An iframe gives it a clean document. - Rendering is locked down against stored XSS. Anyone who can push Markdown controls the diagram source, so Mermaid runs with
securityLevel: 'strict', KaTeX withtrust: false, and PlantUML SVG is passed through DOMPurify before insertion. PlantUML runs server-side in itsSANDBOXsecurity profile (no file or URL includes), with a render timeout and a bounded worker pool. - Built JS is named
*-min.jsto bypass the AMPS YUI Compressor. The compressor is ES3-only and silently destroys the ES6+ output from Vite; AMPS skips any filename with the-minsuffix.
cd docker
docker compose up -d # Bitbucket 8.19 on http://localhost:7990
# or
docker compose -f docker-compose.10x.yml up -d # Bitbucket 10.x on :7991Default credentials after first-run setup: admin / admin (configure during Bitbucket onboarding). Edit docker/.env to pick a different Bitbucket patch version.
localStorage.setItem('markdownx-debug', '1'); // enable, then reload
localStorage.removeItem('markdownx-debug'); // disable- File browser:
http://localhost:7990/projects/TEST/repos/test-markdown/browse?at=main - File view:
http://localhost:7990/projects/TEST/repos/test-markdown/browse/README.md?at=main - Admin: Bitbucket Administration → Add-ons → MarkdownX Admin (or open
http://localhost:7990/plugins/servlet/markdownx/admindirectly, or click Configure in Manage apps)
| Bitbucket DC | Status |
|---|---|
| 8.x (8.19+) | Tested — default JAR |
| 9.x | Tested on 9.6 — default JAR |
| 10.x | Tested on 10.2 — -bb10 JAR |
See docker/COMPAT-TESTING.md for the verification matrix.
Contributions welcome — see CONTRIBUTING.md.
Please report vulnerabilities privately — see SECURITY.md.
Apache License 2.0. See LICENSE.
Bundled third-party libraries: PlantUML (plantuml-asl, Apache-2.0), Mermaid (MIT), KaTeX (MIT), DOMPurify (Apache-2.0 / MPL-2.0).