feat: add flowing templates and PDF import pipeline
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
2026-08-31 19:56:25 +02:00
parent 95e3f677e4
commit 3e5f197bdb
19 changed files with 920 additions and 44 deletions
+37 -7
View File
@@ -32,6 +32,7 @@ public sealed class QuestTemplateRenderer : ITemplateRenderer, ITemplatePreviewR
private static IDocument BuildDocument(LoadedTemplate template,
IReadOnlyDictionary<string, PlaceholderValue> values) => Document.Create(document =>
{
var flowBox = template.Layout.Elements.OfType<FlowBoxElement>().SingleOrDefault();
document.Page(page =>
{
page.Size(UnitConverter.Points(template.Layout.Width, template.Layout.Unit),
@@ -39,17 +40,44 @@ public sealed class QuestTemplateRenderer : ITemplateRenderer, ITemplatePreviewR
page.Margin(0);
page.Content().Layers(layers =>
{
layers.PrimaryLayer().Width(UnitConverter.Points(template.Layout.Width, template.Layout.Unit))
.Height(UnitConverter.Points(template.Layout.Height, template.Layout.Unit)).Background(Colors.White);
foreach (var element in template.Layout.Elements)
{
var current = element;
layers.Layer().Element(container => RenderElement(container, current, template, values));
}
if (flowBox is null)
layers.PrimaryLayer().Width(UnitConverter.Points(template.Layout.Width, template.Layout.Unit))
.Height(UnitConverter.Points(template.Layout.Height, template.Layout.Unit)).Background(Colors.White);
else
RenderFlowBox(layers.PrimaryLayer(), flowBox, template, values);
RenderStaticLayers(layers, template.Layout, template, values,
template.ContinuationLayout is null ? null : static container => container.ShowOnce());
if (template.ContinuationLayout is { } continuation)
RenderStaticLayers(layers, continuation, template, values, static container => container.SkipOnce());
});
});
});
private static void RenderStaticLayers(LayersDescriptor layers, TemplateLayout layout, LoadedTemplate template,
IReadOnlyDictionary<string, PlaceholderValue> values, Func<IContainer, IContainer>? visibility)
{
foreach (var element in layout.Elements.Where(x => x is not FlowBoxElement))
{
var current = element;
layers.Layer().Element(container => RenderElement(
visibility is null ? container : visibility(container), current, template, values));
}
}
private static void RenderFlowBox(IContainer container, FlowBoxElement box, LoadedTemplate template,
IReadOnlyDictionary<string, PlaceholderValue> values)
{
var unit = template.Layout.Unit;
container
.PaddingLeft(UnitConverter.Points(box.X, unit))
.PaddingTop(UnitConverter.Points(box.Y, unit))
.PaddingRight(UnitConverter.Points(Math.Max(0, template.Layout.Width - box.X - box.Width), unit))
.PaddingBottom(UnitConverter.Points(Math.Max(0, template.Layout.Height - box.Y - box.Height), unit))
.Element(content => RenderResolvedText(content, box.Content, box.Placeholder, box.Format,
values, template.Manifest, box.Attributes));
}
private static void RenderElement(IContainer root, TemplateElement element, LoadedTemplate template,
IReadOnlyDictionary<string, PlaceholderValue> values)
{
@@ -78,6 +106,8 @@ public sealed class QuestTemplateRenderer : ITemplateRenderer, ITemplatePreviewR
RenderResolvedText(Position(root, box, unit).Shrink(), box.Content, box.Placeholder, box.Format,
values, template.Manifest, box.Attributes);
break;
case FlowBoxElement:
break;
case TableElement table:
if (values.GetValueOrDefault(table.Placeholder) is TableValue tableValue)
TableElementRenderer.Render(Position(root, table, unit), tableValue, table.Attributes);