Skip to content

Commit b5183c1

Browse files
committed
feat: add method to get field names from templates
1 parent da3b8c2 commit b5183c1

4 files changed

Lines changed: 61 additions & 12 deletions

File tree

src/Template/Services/HandlebarsTemplateService.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ namespace Avolutions.Baf.Core.Template.Services;
44

55
public class HandlebarsTemplateService : TemplateService<string, string>
66
{
7-
protected override Task<string> ApplyValuesToTemplateAsync(string template, IDictionary<string, string> values, CancellationToken ct)
7+
public override IReadOnlyList<string> ExtractFieldNames(Stream template)
8+
{
9+
throw new NotImplementedException();
10+
}
11+
12+
public override Task<string> ApplyValuesToTemplateAsync(string template, IDictionary<string, string> values, CancellationToken ct)
813
{
914
var compiledTemplate = Handlebars.Compile(template);
1015
var result = compiledTemplate(values);

src/Template/Services/PdfTemplateService.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ public PdfTemplateService()
1818
_fontsConfigured = true;
1919
}
2020
}
21-
22-
protected override Task<byte[]> ApplyValuesToTemplateAsync(Stream template, IDictionary<string, string> values, CancellationToken ct)
21+
22+
public override IReadOnlyList<string> ExtractFieldNames(Stream template)
23+
{
24+
throw new NotImplementedException();
25+
}
26+
27+
public override Task<byte[]> ApplyValuesToTemplateAsync(Stream template, IDictionary<string, string> values, CancellationToken ct)
2328
{
2429
using var templateBuffer = new MemoryStream();
2530
template.CopyTo(templateBuffer);

src/Template/Services/TemplateService.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@ public Task<TResult> ApplyModelToTemplateAsync(TTemplate template, object model,
1515

1616
return ApplyValuesToTemplateAsync(template, values, ct);
1717
}
18-
19-
protected abstract Task<TResult> ApplyValuesToTemplateAsync(
18+
19+
public abstract IReadOnlyList<string> ExtractFieldNames(Stream template);
20+
21+
public abstract Task<TResult> ApplyValuesToTemplateAsync(
2022
TTemplate template,
2123
IDictionary<string, string> values,
2224
CancellationToken ct);
2325

24-
protected Dictionary<string, string> BuildValueDictionary(object model)
26+
protected virtual Dictionary<string, string> BuildValueDictionary(object model)
2527
{
26-
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
2728
var type = model.GetType();
29+
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
30+
var result = new Dictionary<string, string>(properties.Length, StringComparer.OrdinalIgnoreCase);
2831

29-
foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
32+
foreach (var property in properties)
3033
{
3134
if (!property.CanRead)
3235
{

src/Template/Services/WordTemplateService.cs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,48 @@ namespace Avolutions.Baf.Core.Template.Services;
66

77
public class WordTemplateService : TemplateService<Stream, byte[]>
88
{
9-
protected override Task<byte[]> ApplyValuesToTemplateAsync(Stream template, IDictionary<string, string> values, CancellationToken ct)
9+
public override IReadOnlyList<string> ExtractFieldNames(Stream template)
10+
{
11+
var fieldNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
12+
13+
using var document = WordprocessingDocument.Open(template, false);
14+
15+
var body = document.MainDocumentPart?.Document.Body;
16+
if (body != null)
17+
{
18+
ExtractMergeFieldNames(body, fieldNames);
19+
}
20+
21+
return fieldNames.ToList();
22+
}
23+
24+
private static void ExtractMergeFieldNames(OpenXmlElement root, HashSet<string> fieldNames)
25+
{
26+
foreach (var fieldCode in root.Descendants<FieldCode>())
27+
{
28+
var instruction = fieldCode.Text;
29+
if (string.IsNullOrWhiteSpace(instruction))
30+
{
31+
continue;
32+
}
33+
34+
if (!instruction.Contains("MERGEFIELD", StringComparison.OrdinalIgnoreCase))
35+
{
36+
continue;
37+
}
38+
39+
var fieldName = ExtractMergeFieldName(instruction);
40+
if (fieldName != null)
41+
{
42+
fieldNames.Add(fieldName);
43+
}
44+
}
45+
}
46+
47+
public override Task<byte[]> ApplyValuesToTemplateAsync(Stream template, IDictionary<string, string> values, CancellationToken ct)
1048
{
1149
// Copy to a writable, seekable stream
12-
var output = new MemoryStream();
50+
using var output = new MemoryStream();
1351
template.CopyTo(output);
1452
output.Position = 0;
1553

@@ -21,8 +59,6 @@ protected override Task<byte[]> ApplyValuesToTemplateAsync(Stream template, IDic
2159
ReplaceMergeFields(body, values);
2260
}
2361
}
24-
25-
output.Position = 0;
2662

2763
return Task.FromResult(output.ToArray());
2864
}

0 commit comments

Comments
 (0)