-
Notifications
You must be signed in to change notification settings - Fork 1
/
LiquidParser.cs
126 lines (113 loc) · 4.5 KB
/
LiquidParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// <copyright file="LiquidParser.cs">
// Licensed under the open source Apache License, Version 2.0.
// Project: AzureLiquid
// Created: 2022-10-18 07:48
// </copyright>
using System.Dynamic;
using System.Xml;
using AzureLiquid.Exceptions;
using AzureLiquid.Formatting;
using DotLiquid;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
namespace AzureLiquid
{
/// <summary>
/// Parses liquid templates using a JSON string, an object or an XML document.
/// </summary>
public class LiquidParser
{
private Hash? _data;
private Template? _template;
/// <summary>
/// Parses the specified template.
/// </summary>
/// <param name="template">The template.</param>
/// <returns>The current instance to use for method chaining.</returns>
public LiquidParser Parse(string? template)
{
_template = Template.Parse(template);
return this;
}
/// <summary>
/// Sets content using an object. Data will be available using the 'content' variable and the serialized object as JSON.
/// </summary>
/// <param name="instance">The object instance.</param>
/// <param name="forceCamelCase">if set to <c>true</c> to force camel case in serialized output.</param>
/// <returns>
/// The current instance to use for method chaining.
/// </returns>
public LiquidParser SetContent(object? instance, bool forceCamelCase = false)
{
var settings = new JsonSerializerSettings();
if (forceCamelCase)
{
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
return SetContentJson(JsonConvert.SerializeObject(instance, settings));
}
/// <summary>
/// Sets the content JSON. Data will be available using the 'content' variable.
/// </summary>
/// <param name="json">The JSON data.</param>
/// <returns>
/// The current instance to use for method chaining.
/// </returns>
public LiquidParser SetContentJson(string json)
{
var content = "{ \"content\": " + json + " }";
dynamic? expando = JsonConvert.DeserializeObject<ExpandoObject>(content, new PreserveCaseDeserializer(),
new ExpandoObjectConverter());
_data = Hash.FromDictionary(new Dictionary<string, object>(expando));
return this;
}
/// <summary>
/// Sets the content JSON using XML text data as source. Data will be available using the 'content' variable.
/// </summary>
/// <param name="xml">The XML data as string.</param>
/// <returns>The current instance to use for method chaining.</returns>
public LiquidParser SetContentXml(string xml)
{
var document = new XmlDocument();
document.LoadXml(xml);
return SetContentXml(document);
}
/// <summary>
/// Sets the content JSON using an XML document as source. Data will be available using the 'content' variable.
/// </summary>
/// <param name="document">The XML document.</param>
/// <returns>The current instance to use for method chaining.</returns>
public LiquidParser SetContentXml(XmlDocument document) =>
SetContentJson(JsonConvert.SerializeXmlNode(document));
/// <summary>
/// Renders this instance using the parsed template and loaded data content.
/// </summary>
/// <returns>The output result.</returns>
public string Render()
{
GuardRender();
return _template!.Render(_data);
}
/// <summary>
/// Guards rendering for bad inputs.
/// </summary>
/// <returns></returns>
/// <exception cref="LiquidParserException">
/// No data loaded. Call the SetContent* methods before calling Render.
/// or
/// No template loaded. Call the Parse method before calling Render.
/// </exception>
private void GuardRender()
{
if (_data is null)
{
throw new LiquidParserException("No data loaded. Call the SetContent* methods before calling Render.");
}
if (_template is null)
{
throw new LiquidParserException("No template loaded. Call the Parse method before calling Render.");
}
}
}
}