diff --git a/docs/SPEC.md b/docs/SPEC.md index b7eb9b3..052de3a 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -140,9 +140,12 @@ kopierbar (grafisches Format, in Dokumente/Chats einfügbar): - Das gerenderte Diagramm wird aus der Live-Geometrie in ein eigenständiges SVG (nur Formen + Text, keine externen Ressourcen) nachgezeichnet und als - **PNG** (`image/png`) in die Zwischenablage gelegt. Fällt der Bild-Clipboard - aus (fehlende `ClipboardItem`-Unterstützung), wird der **SVG-Quelltext** - kopiert (ebenfalls ein Grafikformat). + **PNG** in die Zwischenablage gelegt. Es werden zwei Flavors geschrieben: + `image/png` (das eigentliche Bild) und `text/html` mit eingebettetem PNG + (``) — Office-Programme wie LibreOffice Writer + bevorzugen den HTML-Flavor und betten das Bild dann korrekt ein. Fällt der + Bild-Clipboard ganz aus (fehlende `ClipboardItem`-Unterstützung), wird der + **SVG-Quelltext** kopiert (ebenfalls ein Grafikformat). - Übernommen werden Knotenfarben (Status §4), Größen-Badge, Tags und der Geister-Knoten; die Verbindungslinien werden je Gate neu gezogen (und = durchgezogen Tinte, oder = gestrichelt Grau) und treffen die Knoten diff --git a/frontend/index.html b/frontend/index.html index de06453..e43c5d5 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -564,7 +564,7 @@ - @@ -825,7 +825,7 @@ function diagramToSvg(){ const svg = `${parts.join('')}`; return {svg, W, H}; } -function svgToPngBlob(svg, W, H, scale){ +function svgToPng(svg, W, H, scale){ return new Promise(resolve => { const img = new Image(); img.onload = () => { @@ -834,20 +834,28 @@ function svgToPngBlob(svg, W, H, scale){ const ctx = c.getContext('2d'); ctx.scale(scale, scale); ctx.drawImage(img, 0, 0); - c.toBlob(b => resolve(b), 'image/png'); + c.toBlob(b => resolve({blob:b, dataUrl:c.toDataURL('image/png')}), 'image/png'); }; img.onerror = () => resolve(null); img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg); }); } +/* Kopiert das Diagramm als PNG-Bild. Zusätzlich wird eine text/html-Variante + mit eingebettetem PNG mitgegeben — Office-Programme wie LibreOffice Writer + bevorzugen den HTML-Flavor und betten das Bild dann korrekt ein. */ async function copyDiagramImage(){ const {svg, W, H} = diagramToSvg(); - const blob = await svgToPngBlob(svg, W, H, 2); - if(blob && navigator.clipboard && window.ClipboardItem){ + const png = await svgToPng(svg, W, H, 2); + if(png && png.blob && navigator.clipboard && window.ClipboardItem){ + const html = new Blob( + [`Werkbaum-Diagramm`], + {type:'text/html'}); try{ - await navigator.clipboard.write([new ClipboardItem({'image/png': blob})]); + await navigator.clipboard.write([new ClipboardItem({'image/png':png.blob, 'text/html':html})]); return; - }catch(_){} + }catch(_){ + try{ await navigator.clipboard.write([new ClipboardItem({'image/png':png.blob})]); return; }catch(_){} + } } await writeClipboard(svg); /* Fallback: SVG-Quelltext (ebenfalls Grafik) */ } @@ -1028,7 +1036,7 @@ const I18N = { brandTooltip:"„Werkbaum“ bedeutet so viel wie ‚Werk-Baum‘ — der Baum des Projektstrukturplans (WBS).", editorTitle:"Struktur (Text)", diagramTitle:"Diagramm", copy:"kopieren", copyDone:"kopiert ✓", copyTooltip:"Text in die Zwischenablage kopieren", - copyDiagramTooltip:"Diagramm als Bild kopieren", + copyDiagramTooltip:"Diagramm als PNG-Bild in die Zwischenablage kopieren", minimize:"minimieren", normal:"normal", maximize:"maximieren", agenda:"Agenda", discarded:"verworfene", modeHorizontal:"Horizontal – Organigramm, Diagramm über dem Editor", @@ -1057,7 +1065,7 @@ const I18N = { brandTooltip:"“Werkbaum” means roughly ‘work tree’ — the tree of the work breakdown structure (WBS).", editorTitle:"Structure (text)", diagramTitle:"Diagram", copy:"copy", copyDone:"copied ✓", copyTooltip:"Copy text to clipboard", - copyDiagramTooltip:"Copy diagram as an image", + copyDiagramTooltip:"Copy diagram as a PNG image to the clipboard", minimize:"minimize", normal:"normal", maximize:"maximize", agenda:"Legend", discarded:"discarded", modeHorizontal:"Horizontal – org chart, diagram above the editor", @@ -1086,7 +1094,7 @@ const I18N = { brandTooltip:"«Werkbaum» significa algo así como ‘árbol de trabajo’ — el árbol de la estructura de desglose del trabajo (EDT).", editorTitle:"Estructura (texto)", diagramTitle:"Diagrama", copy:"copiar", copyDone:"copiado ✓", copyTooltip:"Copiar el texto al portapapeles", - copyDiagramTooltip:"Copiar el diagrama como imagen", + copyDiagramTooltip:"Copiar el diagrama como imagen PNG al portapapeles", minimize:"minimizar", normal:"normal", maximize:"maximizar", agenda:"Leyenda", discarded:"descartados", modeHorizontal:"Horizontal – organigrama, diagrama sobre el editor", @@ -1115,7 +1123,7 @@ const I18N = { brandTooltip:"« Werkbaum » signifie à peu près « arbre de travail » — l’arbre de l’organigramme des tâches (WBS).", editorTitle:"Structure (texte)", diagramTitle:"Diagramme", copy:"copier", copyDone:"copié ✓", copyTooltip:"Copier le texte dans le presse-papiers", - copyDiagramTooltip:"Copier le diagramme comme image", + copyDiagramTooltip:"Copier le diagramme comme image PNG dans le presse-papiers", minimize:"réduire", normal:"normal", maximize:"agrandir", agenda:"Légende", discarded:"abandonnés", modeHorizontal:"Horizontal – organigramme, diagramme au-dessus de l'éditeur", @@ -1144,7 +1152,7 @@ const I18N = { brandTooltip:"„Werkbaum” znaczy mniej więcej ‚drzewo pracy’ — drzewo struktury podziału pracy (WBS).", editorTitle:"Struktura (tekst)", diagramTitle:"Diagram", copy:"kopiuj", copyDone:"skopiowano ✓", copyTooltip:"Kopiuj tekst do schowka", - copyDiagramTooltip:"Kopiuj diagram jako obraz", + copyDiagramTooltip:"Kopiuj diagram jako obraz PNG do schowka", minimize:"minimalizuj", normal:"normalny", maximize:"maksymalizuj", agenda:"Legenda", discarded:"odrzucone", modeHorizontal:"Poziomo – schemat organizacyjny, diagram nad edytorem", @@ -1173,7 +1181,7 @@ const I18N = { brandTooltip:"«Werkbaum» примерно означает ‚дерево работ’ — дерево структуры декомпозиции работ (СДР).", editorTitle:"Структура (текст)", diagramTitle:"Диаграмма", copy:"копировать", copyDone:"скопировано ✓", copyTooltip:"Скопировать текст в буфер обмена", - copyDiagramTooltip:"Скопировать диаграмму как изображение", + copyDiagramTooltip:"Скопировать диаграмму как изображение PNG в буфер обмена", minimize:"свернуть", normal:"обычный", maximize:"развернуть", agenda:"Легенда", discarded:"отклонённые", modeHorizontal:"Горизонтально – оргсхема, диаграмма над редактором", @@ -1202,7 +1210,7 @@ const I18N = { brandTooltip:"„Werkbaum“ का अर्थ लगभग ‚कार्य-वृक्ष‘ है — कार्य विभाजन संरचना (WBS) का वृक्ष।", editorTitle:"संरचना (टेक्स्ट)", diagramTitle:"आरेख", copy:"कॉपी करें", copyDone:"कॉपी हो गया ✓", copyTooltip:"टेक्स्ट को क्लिपबोर्ड पर कॉपी करें", - copyDiagramTooltip:"आरेख को छवि के रूप में कॉपी करें", + copyDiagramTooltip:"आरेख को PNG छवि के रूप में क्लिपबोर्ड पर कॉपी करें", minimize:"छोटा करें", normal:"सामान्य", maximize:"बड़ा करें", agenda:"लेजेंड", discarded:"अस्वीकृत", modeHorizontal:"क्षैतिज – संगठन-चार्ट, संपादक के ऊपर आरेख",