-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathHandlebarsHelpers.cs
165 lines (143 loc) · 5.27 KB
/
HandlebarsHelpers.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using HandlebarsDotNet;
using Newtonsoft.Json;
namespace Seq.App.EmailPlus
{
static class HandlebarsHelpers
{
public static void Register()
{
Handlebars.RegisterHelper("pretty", PrettyPrintHelper);
Handlebars.RegisterHelper("if_eq", IfEqHelper);
Handlebars.RegisterHelper("substring", SubstringHelper);
Handlebars.RegisterHelper("datetime", DateTimeHelper);
}
static void PrettyPrintHelper(EncodedTextWriter output, Context context, Arguments arguments)
{
var value = arguments.FirstOrDefault();
if (value == null)
output.WriteSafeString("null");
else if (value is IEnumerable<object> || value is IEnumerable<KeyValuePair<string, object>>)
output.Write(JsonConvert.SerializeObject(FromDynamic(value)));
else
{
var str = value.ToString();
if (string.IsNullOrWhiteSpace(str))
{
output.WriteSafeString(" ");
}
else
{
output.Write(str);
}
}
}
static void IfEqHelper(EncodedTextWriter output, BlockHelperOptions options, Context context, Arguments arguments)
{
if (arguments.Length != 2)
{
options.Inverse(output, context);
return;
}
var lhs = (arguments[0]?.ToString() ?? "").Trim();
var rhs = (arguments[1]?.ToString() ?? "").Trim();
if (lhs.Equals(rhs, StringComparison.Ordinal))
{
options.Template(output, context);
}
else
{
options.Inverse(output, context);
}
}
static object FromDynamic(object o)
{
if (o is IEnumerable<KeyValuePair<string, object>> dictionary)
{
return dictionary.ToDictionary(kvp => kvp.Key, kvp => FromDynamic(kvp.Value));
}
if (o is IEnumerable<object> enumerable)
{
return enumerable.Select(FromDynamic).ToArray();
}
return o;
}
static object SubstringHelper(Context context, Arguments arguments)
{
//{{ substring value 0 30 }}
var value = arguments.FirstOrDefault();
var toString = value?.ToString();
if (toString == null)
return value;
if (arguments.Length < 2)
{
// No start or length arguments provided
return value;
}
int start;
if (arguments.Length < 3)
{
// just a start position provided
if (!int.TryParse(arguments[1].ToString(), out start) || start > toString.Length)
{
// start of substring after end of string.
return "";
}
return toString.Substring(start);
}
// Start & length provided.
int.TryParse(arguments[1].ToString(), out start);
int.TryParse(arguments[2].ToString(), out var end);
if (start > toString.Length)
{
// start of substring after end of string.
return "";
}
// ensure the length is still in the string to avoid ArgumentOutOfRangeException
if (end > toString.Length - start)
{
end = toString.Length - start;
}
return toString.Substring(start, end);
}
static object DateTimeHelper(Context context, Arguments arguments)
{
if (arguments.Length < 1)
return null;
// Using `DateTimeOffset` avoids ending up with `DateTimeKind.Unspecified` after time zone conversion.
DateTimeOffset dt;
if (arguments[0] is DateTimeOffset dto)
{
dt = dto;
}
else if (arguments[0] is DateTime rdt)
{
dt = rdt.Kind == DateTimeKind.Unspecified ? new DateTime(rdt.Ticks, DateTimeKind.Utc) : rdt;
}
else if (arguments[0] is not string str || !DateTimeOffset.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
{
return null;
}
string format = null;
if (arguments.Length >= 2 && arguments[1] is string f)
{
format = f;
}
if (arguments.Length >= 3 && arguments[2] is string timeZoneId)
{
var tzi = PortableTimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
dt = TimeZoneInfo.ConvertTime(dt, tzi);
}
if (dt.Offset == TimeSpan.Zero)
{
// Use the idiomatic trailing `Z` formatting for ISO-8601 in UTC.
return dt.UtcDateTime.ToString(format);
}
return dt.ToString(format);
}
}
}