feat: Labels brechen balanciert um, ID-Zeile über dem Titel, Falt-Chip — D64

Lange Knotentitel brechen bei ~40 Zeichen um, gleichmäßig auf die Zeilen
verteilt — vom Renderer (wrapLabel, headless getestet) statt text-wrap:balance,
damit der Kasten auf die längste balancierte Zeile schrumpft. Der
23-px-Abzweig ankert an der ersten Zeile; der Optional-Kreis sitzt fest auf
der Abzweighöhe. Der Grafikexport misst die gerenderten Zeilen (labelLines)
und gibt je Zeile ein <text> aus. Dazu: die eingeblendete ID (D56) steht in
einer eigenen Zeile über dem Titel, und das Falt-Zeichen ist ein gerahmter
19×16-px-Chip mit gedeckelter Höhe. Plan: #ed.render.wrap, #ed.render M→L
(D62-Prüfung schlug korrekt an).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-24 17:45:11 +02:00
co-authored by Claude Fable 5
parent 1debb7d9da
commit 52232f2c20
10 changed files with 318 additions and 32 deletions
+7 -5
View File
@@ -143,8 +143,10 @@ describe('renderTreeHtml — data-line je Knoten (D25)', () => {
});
/* Knoten-IDs im Diagramm (D56). Als Renderer-Option gebaut und nicht per CSS
versteckt — nur so folgt der Grafikexport, der den Knotentext ausliest. */
describe('showIds — die ID vor dem Titel, geschrieben wie im Text', () => {
versteckt — nur so folgt der Grafikexport, der den Knotentext ausliest.
Seit D64 steht die ID in einer eigenen Zeile ÜBER dem Titel (Trenner ist
der Umbruch, nicht mehr der Doppelpunkt). */
describe('showIds — die ID in einer eigenen Zeile über dem Titel', () => {
const ids = (text, showIds) => renderTreeHtml(parse(text).roots,
{t, showDiscarded: false, cheapPath: false, cheapSet: new Set(), showIds}).html;
@@ -154,9 +156,9 @@ describe('showIds — die ID vor dem Titel, geschrieben wie im Text', () => {
expect(html).not.toContain('nid');
});
it('stellt die ID mit Doppelpunkt und Leerzeichen davor', () => {
it('stellt die ID in eine eigene Zeile über den Titel', () => {
expect(ids('#auth: Backend', true))
.toContain('<span class="nid" aria-hidden="true">#auth:</span> Backend');
.toContain('<span class="nid" aria-hidden="true">#auth</span>\nBackend');
});
it('lässt Knoten ohne ID unangetastet', () => {
@@ -176,7 +178,7 @@ describe('showIds — die ID vor dem Titel, geschrieben wie im Text', () => {
genau das: `#a<b` ergibt die ID `a`, der Rest bleibt (escaped) im Label. */
it('endet an einem Zeichen außerhalb der ID-Zeichenmenge', () => {
const html = ids('#a<b: X', true);
expect(html).toContain('<span class="nid" aria-hidden="true">#a:</span>');
expect(html).toContain('<span class="nid" aria-hidden="true">#a</span>');
expect(html).toContain('&lt;b: X');
});
});