| .gitignore | ||
| compose.yaml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
README: Markmap-API mit Docker Compose testen
Diese Anleitung beschreibt ein minimales Setup für einen Docker-Compose-Dienst, der Markdown per HTTP annimmt und als Markmap-HTML rendert. markmap-lib ist das offizielle Paket zur Transformation von Markdown in die Datenstruktur für Markmap.[1][2][3]
Voraussetzungen
- Docker Engine und Docker Compose Plugin sind installiert.[4][5][6]
- Ein freier TCP-Port, im Beispiel
3000.[7][4] - Eine funktionierende
server.js,Dockerfileunddocker-compose.ymlim selben Projektordner.[6]
Projektstruktur
markmap-api/
├── docker-compose.yml
├── Dockerfile
├── package.json
└── server.js
Dieses Layout entspricht dem üblichen Aufbau einer kleinen Node/Express-App mit Docker Compose.[4][6]
package.json automatisch erzeugen
Die package.json kann automatisch mit npm init -y erzeugt werden; npm erstellt dabei eine Standarddatei im aktuellen Verzeichnis.[8][9][10]
mkdir -p markmap-api
cd markmap-api
npm init -y
npm install express markmap-lib
Nach der Installation trägt npm die Abhängigkeiten automatisch in package.json ein.[11][8]
Beispiel-Dateien
package.json
{
"name": "markmap-api",
"version": "1.0.0",
"private": true,
"type": "commonjs",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.21.2",
"markmap-lib": "^0.18.12"
}
}
Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package.json ./
RUN npm install --omit=dev
COPY server.js ./
EXPOSE 3000
CMD ["npm", "start"]
Dieses Container-Muster ist ein übliches Setup für kleine Node-Services in Docker.[5][7][4]
docker-compose.yml
services:
markmap-api:
build: .
container_name: markmap-api
restart: unless-stopped
ports:
- "3000:3000"
environment:
PORT: 3000
Docker Compose veröffentlicht damit den Container-Port 3000 auf dem Host-Port 3000.[6][7][4]
server.js
const express = require('express');
const { Transformer } = require('markmap-lib');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json({ limit: '1mb' }));
app.get('/health', (req, res) => {
res.json({ ok: true });
});
app.post('/api/markmap', (req, res) => {
const markdown = req.body?.markdown;
if (!markdown || typeof markdown !== 'string') {
return res.status(400).json({ error: 'markdown fehlt oder ist ungültig' });
}
try {
const transformer = new Transformer();
const { root, features } = transformer.transform(markdown);
const assets = transformer.getUsedAssets(features);
const css = (assets.styles || [])
.map((href) => `<link rel="stylesheet" href="${href}">`)
.join('\n');
const js = (assets.scripts || [])
.map((src) => `<script src="${src}"></script>`)
.join('\n');
const html = `<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>markmap</title>
<style>
html, body { margin: 0; height: 100%; background: #fff; }
#mindmap { width: 100vw; height: 100vh; }
</style>
${css}
</head>
<body>
<svg id="mindmap"></svg>
<script>
window.__MARKMAP_DATA__ = ${JSON.stringify(root)};
</script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://cdn.jsdelivr.net/npm/markmap-view"></script>
${js}
<script>
const { Markmap } = window.markmap;
Markmap.create('#mindmap', null, window.__MARKMAP_DATA__);
</script>
</body>
</html>`;
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.send(html);
} catch (err) {
res.status(500).json({ error: 'Rendering fehlgeschlagen', details: err.message });
}
});
app.listen(port, '0.0.0.0', () => {
console.log(`markmap-api läuft auf Port ${port}`);
});
markmap-lib stellt die Transformation und die benötigten Assets für die aktiv genutzten Features bereit.[2][3][1]
Häufiger Syntaxfehler
Wenn in server.js eine Zeile wie console.log(\...`)steht, wurde meist ein Backtick falsch escaped. Template Literals müssen mit echten Backticks geschrieben werden, also z.B.console.log(markmap-api läuft auf Port ${port});`.[12][13]
Container starten
docker compose up --build -d
Mit --build wird das Image neu gebaut, was sinnvoll ist, wenn server.js oder package.json geändert wurden.[5][4][6]
Logs prüfen
docker compose logs -f
Wenn alles korrekt ist, sollte der Dienst nach dem Start auf Port 3000 lauschen.[4][6]
Healthcheck testen
curl http://localhost:3000/health
Erwartete Antwort:
{"ok":true}
API testen
Der Endpoint /api/markmap erwartet JSON mit einem Feld markdown.[1][2]
curl -X POST http://localhost:3000/api/markmap \
-H 'Content-Type: application/json' \
-d '{"markdown":"# Projekt\n## Idee A\n## Idee B"}' \
-o test.html
Die Datei test.html enthält eine renderbare HTML-Seite mit der Markmap und kann im Browser geöffnet werden.[14][1]
Test im Browser
Alternativ kann der Request auch direkt aus einem Tool oder Skript erfolgen; die Antwort ist HTML und nicht JSON.[2][1]
Beispiel mit curl und Header-Anzeige:
curl -i -X POST http://localhost:3000/api/markmap \
-H 'Content-Type: application/json' \
-d '{"markdown":"# Demo\n## Alpha\n## Beta"}' | head
Die Response sollte Content-Type: text/html; charset=utf-8 enthalten.[1]
Mit iOS Kurzbefehlen testen
Die Kurzbefehle-App auf iPhone und iPad kann HTTP-Requests an Web-APIs senden, darunter auch POST mit JSON-Body.[15][16]
Empfohlener Shortcut-Ablauf:
- Markdown aus Zwischenablage oder Share Sheet holen.[15]
- Aktion „Inhalt von URL abrufen“ mit
POSTaufhttps://dein-server/api/markmapkonfigurieren.[16][15] - Als Body JSON senden, z.B.
{ "markdown": "<dein Text>" }.[15] - Die HTML-Antwort in Safari oder Quick Look öffnen.[15]
Fehlerbehebung
SyntaxError: Invalid or unexpected token: meist falsch kopierte Backticks, typografische Anführungszeichen oder beschädigte Zeichen inserver.js.[13][17][18]- Container startet neu:
docker compose logs -fprüfen und Syntax inserver.jsgegenchecken.[6][4] - Leere Seite im Browser: prüfen, ob CDN-Zugriff auf
d3undmarkmap-viewfunktioniert und ob das HTML vollständig ausgeliefert wird.[19][14] - Port schon belegt: Host-Port in
docker-compose.ymländern, z.B.3001:3000.[7][4]
Nächste sinnvolle Schritte
- Reverse Proxy mit HTTPS davor setzen, z.B. Nginx oder Traefik.[7][4]
- Optional Basic Auth aktivieren, wenn der Endpoint öffentlich erreichbar ist.[4]
- Statt HTML eine URL oder gespeicherte SVG/HTML-Datei zurückgeben, wenn der iOS-Workflow sauberer werden soll.[1][15]
Quellen [1] markmap-lib https://markmap.js.org/docs/packages--markmap-lib [2] markmap-lib https://markmap.js.org/api/modules/markmap-lib.html [3] markmap-lib - NPM https://www.npmjs.com/package/markmap-lib [4] An enterprise-style Node.js REST API setup with Docker ... https://codewithhugo.com/node-postgres-express-docker-compose/ [5] Using Docker Compose for NodeJS Development https://www.cloudbees.com/blog/using-docker-compose-for-nodejs-development [6] GitHub - nickjj/docker-node-example: An example Node / Express app that's using Docker and Docker Compose. https://github.com/nickjj/docker-node-example [7] Docker Compose: Node.js Express and MongoDB example https://www.bezkoder.com/docker-compose-nodejs-mongodb/ [8] Creating a package.json file - npm Docs https://docs.npmjs.com/creating-a-package-json-file/ [9] Using npm init with -y flag explained - sebhastian https://sebhastian.com/npm-init-y/ [10] Creating a package.json file https://runebook.dev/en/docs/npm/creating-a-package-json-file [11] So verwenden Sie Node.js-Module mit npm und package.json https://www.digitalocean.com/community/tutorials/how-to-use-node-js-modules-with-npm-and-package-json-de [12] Template-Literale (Template-Zeichenketten) - JavaScript | MDN https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Template_literals [13] SyntaxError: Unerwartetes Token - JavaScript - MDN Web Docs https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Errors/Unexpected_token [14] Try markmap https://markmap.js.org/repl [15] Request your first API in Shortcuts on iPhone or iPad https://support.apple.com/en-il/guide/shortcuts/apd58d46713f/ios [16] Request your first API in Shortcuts on iPhone or iPad https://support.apple.com/en-ae/guide/shortcuts/apd58d46713f/ios [17] SyntaxError: Unexpected token - JavaScript - MDN Web Docs https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_token [18] console.log error showing Uncaught SyntaxError - Stack Overflow https://stackoverflow.com/questions/44661360/console-log-error-showing-uncaught-syntaxerror-invalid-or-unexpected-token [19] markmap https://markmap.js.org/api/