Files
Projektwissen/werkzeuge/vorschau/vorschau.html
T
DanielandClaude Opus 5.5 19947a845f BPMN-Vorschau im Browser, offline, auf Basis von bpmn-js
- werkzeuge/vorschau/vorschau.html: Anzeige per Drag & Drop oder
  Dateiauswahl, Zoom, Einpassen, Fehlermeldungen; funktioniert ohne
  Python direkt aus dem Dateisystem.
- scripts/vorschau.py: erzeugt aus .bpmn oder Arbeitsschritt-.md eine
  in sich geschlossene Seite und öffnet sie; --stdin als Filter, etwa
  für einen Gitea-Renderer. Diagramm wird mit maskiertem '<' eingebettet,
  die Bibliothek unverändert und nur auf <script/</script geprüft.
- bpmn-js 18.29.1 (navigated viewer + CSS + LICENSE) lokal eingebettet,
  npm-Integrität geprüft; lädt nichts aus dem Netz. Wasserzeichen bleibt
  laut Lizenzauflage sichtbar.
- tests/test_vorschau.py: 11 Tests; Skill sn-bpmn, Anleitung, AGENTS.md,
  README, Leitfäden, Fallstricke und STATUS ergänzt.
- Tests: python -m pytest -q -> 55 bestanden. Darstellung mit Edge
  headless geprüft (beide Beispiele, leere Seite, kaputte Datei).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 13:32:14 +02:00

130 lines
5.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BPMN-Vorschau</title>
<!-- bpmn-js (bpmn.io), lokal eingebettet – siehe README.md. Nichts wird aus dem Netz geladen. -->
<link rel="stylesheet" href="bpmn-js/diagram-js.css">
<link rel="stylesheet" href="bpmn-js/bpmn-js.css">
<style>
:root {
--hintergrund: #ffffff;
--leiste: #f3f5f7;
--rand: #d0d7de;
--text: #1f2328;
--gedaempft: #59636e;
--akzent: #0b6bcb;
--fehler: #b42318;
--warnung: #9a6700;
}
html, body { height: 100%; margin: 0; }
body {
display: flex; flex-direction: column;
font-family: "Segoe UI", system-ui, sans-serif; font-size: 14px;
color: var(--text); background: var(--hintergrund);
}
header {
display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
padding: 8px 16px; background: var(--leiste); border-bottom: 1px solid var(--rand);
}
header h1 { font-size: 15px; font-weight: 600; margin: 0 12px 0 0; }
button, label.knopf {
font: inherit; padding: 4px 10px; border: 1px solid var(--rand); border-radius: 6px;
background: #fff; color: var(--text); cursor: pointer;
}
button:hover, label.knopf:hover { border-color: var(--akzent); }
button:disabled { opacity: .5; cursor: default; }
#datei { display: none; }
#dateiname { color: var(--gedaempft); overflow-wrap: anywhere; }
#meldung { flex-basis: 100%; margin: 0; }
#meldung:empty { display: none; }
#meldung.fehler { color: var(--fehler); }
#meldung.warnung { color: var(--warnung); }
/* Zeichenfläche: das bpmn.io-Wasserzeichen unten rechts muss laut Lizenz sichtbar und unverdeckt bleiben. */
main { position: relative; flex: 1; min-height: 0; }
#flaeche { position: absolute; inset: 0; }
#hinweis {
position: absolute; inset: 24px 24px 64px 24px; display: flex; align-items: center; justify-content: center;
text-align: center; color: var(--gedaempft); border: 2px dashed var(--rand); border-radius: 12px;
padding: 16px; pointer-events: none;
}
main.ziehen #hinweis { border-color: var(--akzent); color: var(--akzent); }
main.geladen #hinweis { display: none; }
</style>
</head>
<body>
<header>
<h1>BPMN-Vorschau</h1>
<label class="knopf" for="datei">Datei öffnen …</label>
<input type="file" id="datei" accept=".bpmn,.xml">
<button type="button" id="einpassen" disabled>Einpassen</button>
<button type="button" id="groesser" disabled title="Vergrößern">+</button>
<button type="button" id="kleiner" disabled title="Verkleinern">−</button>
<span id="dateiname"></span>
<p id="meldung" role="status"></p>
</header>
<main id="bereich">
<div id="flaeche"></div>
<div id="hinweis">.bpmn-Datei hierher ziehen oder über „Datei öffnen …“ wählen.<br>
Die Datei wird nur in diesem Browser angezeigt und nirgendwohin übertragen.</div>
</main>
<script src="bpmn-js/bpmn-navigated-viewer.production.min.js"></script>
<script>
// Wird von scripts/vorschau.py durch den Inhalt einer .bpmn und ihren Namen ersetzt.
const EINGEBETTET = null;
const DATEINAME = null;
const bereich = document.getElementById('bereich');
const meldung = document.getElementById('meldung');
const knoepfe = ['einpassen', 'groesser', 'kleiner'].map(id => document.getElementById(id));
const viewer = new BpmnJS({ container: '#flaeche' });
const canvas = () => viewer.get('canvas');
function melde(text, art) {
meldung.textContent = text || '';
meldung.className = art || '';
}
async function zeige(xml, name) {
melde('');
try {
const { warnings } = await viewer.importXML(xml);
canvas().zoom('fit-viewport', 'auto');
bereich.classList.add('geladen');
knoepfe.forEach(k => { k.disabled = false; });
document.getElementById('dateiname').textContent = name || '';
document.title = name ? `${name} – BPMN-Vorschau` : 'BPMN-Vorschau';
if (warnings.length) {
melde(`${warnings.length} Warnung(en) beim Einlesen: ` + warnings.map(w => w.message).join(' | '), 'warnung');
}
} catch (fehler) {
bereich.classList.remove('geladen');
knoepfe.forEach(k => { k.disabled = true; });
melde(`Die Datei ${name || ''} lässt sich nicht als BPMN lesen: ${fehler.message}`, 'fehler');
}
}
function lies(datei) {
if (!datei) return;
datei.text().then(xml => zeige(xml, datei.name));
}
document.getElementById('datei').addEventListener('change', e => lies(e.target.files[0]));
document.getElementById('einpassen').addEventListener('click', () => canvas().zoom('fit-viewport', 'auto'));
document.getElementById('groesser').addEventListener('click', () => canvas().zoom(canvas().zoom() * 1.25));
document.getElementById('kleiner').addEventListener('click', () => canvas().zoom(canvas().zoom() / 1.25));
['dragenter', 'dragover'].forEach(art => document.addEventListener(art, e => {
e.preventDefault(); bereich.classList.add('ziehen');
}));
['dragleave', 'drop'].forEach(art => document.addEventListener(art, e => {
e.preventDefault(); bereich.classList.remove('ziehen');
}));
document.addEventListener('drop', e => lies(e.dataTransfer.files[0]));
if (EINGEBETTET) zeige(EINGEBETTET, DATEINAME);
</script>
</body>
</html>