-
Notifications
You must be signed in to change notification settings - Fork 1
/
HTMLUtil.cs
143 lines (125 loc) · 4.72 KB
/
HTMLUtil.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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DotStd
{
/// <summary>
/// Helper functions for formatting HTML.
/// compliment Encode, Decode
/// In some ways HTML can be treated like XML except for some exceptions. (some non closed tags, literals, some encoding)
/// Use WebUtility.HtmlEncode() to encode a string to proper HTML.
/// NOTE: FormUrlEncodedContent is for URL args. NOT the same.
/// NOTE: Use select2 for option lists with icons.
/// </summary>
public static class HTMLUtil
{
public const string kNBSP = " "; // HTML non breaking space
public const string kGT = ">"; //
public const string kLT = "<"; //
public const string kCommentOpen = "<!--";
public const string kCommentClose = "-->";
// List of known/common entities. https://www.w3schools.com/html/html_entities.asp
public static readonly Dictionary<string, char> kEntities = new Dictionary<string, char>
{
{kNBSP, ' '},
{"©", '©'},
{"®", '®'},
{"é", 'é'},
{"™", '™'},
{"&", '&'},
{kGT, '>'},
{kLT, '<'},
{""", '"'},
{"'", '\''},
};
public static char GetEntityChar(string entity)
{
// TODO handle " " ??
char value;
if (kEntities.TryGetValue(entity, out value))
{
return value;
}
return '\0';
}
public static string? GetEntityName(string src, int startIndex)
{
// assume any entity name starts with & and ends with ;
if (src[startIndex] != '&')
return null;
int j = src.IndexOf(';', startIndex + 1);
if (j <= startIndex + 1)
return null;
int length = (j - startIndex) + 1;
if (length > 10)
return null;
return src.Substring(startIndex, length);
}
public static string DecodeEntities2(string src)
{
// replace Non standard entities with chars. HTML is not the same as XML.
// Replacing " " with " " since " " is not XML standard
// NOTE: XmlReader is vulnerable to attacks from entity creation. XSS. OK in .Net 4.0+ but use DtdProcessing.Prohibit !!
for (int i = 0; i < src.Length; i++)
{
string? entityName = GetEntityName(src, i);
if (entityName == null)
continue;
char ch = GetEntityChar(entityName);
if (ch == '\0')
continue;
src = string.Concat(src.Substring(0, i), ch, src.Substring(i + entityName.Length));
}
return src;
}
public const string kSelected = "selected ";
public static string GetOpt(string value, string? desc, bool selected = false, string? extra = null)
{
// construct HTML option for <select>
// construct HTML "<option value='1'>Main</option>");
// like TupleKeyValue
if (selected)
{
extra = string.Concat(kSelected, extra);
}
return string.Concat("<option ", extra, "value='", value, "'>", desc ?? value, "</option>");
}
public static string GetOpt(int value, string? desc, bool selected = false)
{
// construct HTML option for <select>
return GetOpt(value.ToString(), desc, selected);
}
public static string GetOpt(TupleIdValue n, bool selected = false)
{
// construct HTML option for <select>
return GetOpt(n.Id, n.Value, selected);
}
public static string GetOpt(Enum n, bool selected = false)
{
// construct HTML option for <select>
// Get a value from enum to populate a HTML select list option.
return GetOpt(n.ToInt(), n.ToDescription(), selected);
}
public static bool IsCommentLine(string s)
{
s = s.Trim();
return s.StartsWith(kCommentOpen) && s.EndsWith(kCommentClose);
}
public static string GetList(IEnumerable<string> a)
{
if (!a.Any())
return "";
var sb = new StringBuilder();
sb.Append("<ul>");
foreach (var s in a)
{
sb.Append("<li>");
sb.Append(s);
sb.Append("</li>");
}
sb.Append("</ul>");
return sb.ToString();
}
}
}