Templating: TEXT mit w= für zentrierte und rechtsbündige Zeilen
CI / build-and-test (push) Canceled after 0s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Sonnet 5.5 committed 2026-10-07 23:04:46 +02:00
1 parent 98c5f9eba0
commit d1f3dd5148
4 files changed
+52 -2

No files matched your search

@@ -197,6 +197,25 @@ public sealed class TemplatingTests : IDisposable
|| issue.Message.Contains("keine Zahl", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void LayoutParser_LiestTextBreiteFuerZentrierung()
{
var layout = new LayoutParser().Parse("PAGE 210 297 mm\nTEXT 0 20 \"Titel $Name\" w=210 align=center");
var text = Assert.IsType<TextElement>(Assert.Single(layout.Elements));
Assert.Equal("210", text.Attributes["w"]);
}
[Theory]
[InlineData("w=0")]
[InlineData("w=-5")]
[InlineData("w=abc")]
public void LayoutParser_LehntUngueltigeTextBreiteAb(string attribute)
{
Assert.Throws<TemplateValidationException>(() =>
new LayoutParser().Parse($"PAGE 210 297 mm\nTEXT 0 20 \"Titel\" {attribute}"));
}
[Fact]
public void LayoutParser_MeldetAlleSyntaxfehlerMitZeilen()
{
+3 -1
View File
@@ -123,9 +123,11 @@ public sealed class LayoutParser
Require(tokens, flowText ? 2 : 4);
var textContent = tokens[flowText ? 1 : 3];
var textRef = Reference(textContent);
var textAttributes = Attributes(tokens, flowText ? 2 : 4);
if (textAttributes.ContainsKey("w")) RequiredPositiveNumber(textAttributes, "w");
parsedElement = new TextElement(lineNumber, flowText ? 0 : Number(tokens[1]),
flowText ? 0 : Number(tokens[2]), textContent, textRef.Name, textRef.Format,
Attributes(tokens, flowText ? 2 : 4)); break;
textAttributes); break;
case "TEXTBOX":
var flowBox = currentFlowName is not null;
Require(tokens, flowBox ? 2 : 6);
@@ -321,9 +321,13 @@ public sealed class QuestTemplateRenderer : ITemplateRenderer, ITemplatePreviewR
Position(root, image, unit, imageScale).Image(GetAsset(template, image.Path)).FitArea();
break;
case TextElement text:
// w= begrenzt die Zeile auf eine feste Breite, damit align=center/right darin wirkt.
var textWidth = text.Attributes.ContainsKey("w")
? ParseFloat(text.Attributes, "w", 0)
: Math.Max(0, template.Layout.Width - text.X);
var textContainer = root.TranslateX(UnitConverter.Points(text.X, unit))
.TranslateY(UnitConverter.Points(text.Y, unit))
.Width(UnitConverter.Points(Math.Max(0, template.Layout.Width - text.X), unit))
.Width(UnitConverter.Points(textWidth, unit))
.Height(QuestTemplateRenderer.ParseFloat(text.Attributes, "size", 11) * 1.8f);
RenderResolvedText(textContainer, text.Content, text.Placeholder, text.Format,
values, template.Manifest, text.Attributes);
+25
View File
@@ -116,6 +116,31 @@ Login-, Bearer-Token-, Guthaben- und Abrechnungsmechanismus wie die übrigen KI-
Passwort wird vom eigenständigen Designer nicht gespeichert. Tabellen-/Chart-Erkennung und die
automatische Rekonstruktion mehrseitiger Vorlagen sind bewusst nicht Teil von v1.
## Zentrierte und rechtsbündige Zeilen
`TEXT` richtet `align=center` bzw. `align=right` innerhalb seiner Zeilenbreite aus. Ohne Angabe
reicht diese von `x` bis zum rechten Seitenrand, sodass Zentrierung nicht auf der Seitenmitte liegt.
Mit `w=` wird die Breite explizit gesetzt; Variablen im Text verschieben die Mitte dann nicht:
```text
PAGE 210 297 mm
TEXT 0 20 "Elternbrief $Group.Name" w=210 align=center size=16 bold=true
TEXT 20 30 "Klasse $Group.Name" w=170 align=center
```
`x=0 w=<Seitenbreite>` zentriert auf der Seite, `x=<Rand> w=<Seitenbreite − 2·Rand>` innerhalb der
Ränder. In einem `content-flow` ist `w` nicht nötig: dort gilt die Breite des Flows.
Weitere Hinweise:
- `w` muss eine positive Zahl in der Einheit des Layouts sein; andernfalls meldet der Parser einen Fehler.
- `w` gilt nur für `TEXT`. `TEXTBOX` und `FLOWBOX` besitzen bereits eine Breite und richten
`align=left|center|right` darin aus.
- `align` und `w` wirken auch bei Systemvariablen (`"Seite $$curPage von $$maxPageNum"`) und bei
Platzhaltern mit Format (`$Datum|dd.MM.yyyy`).
- Der Koordinateneditor des Designers kennt `w` bei `TEXT` nicht; das Attribut wird beim Verschieben
erhalten, aber nur in der DSL-Zeile bearbeitet.
## Mehrseitiger Fließtext
`TEXTBOX` bleibt ein absolut positionierter Bereich mit fester Höhe. Für Texte unbekannter Länge