/
html.d
156 lines (139 loc) · 3.64 KB
/
html.d
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
/**
HTML character entity escaping.
Copyright: © 2012 RejectedSoftware e.K.
License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
Authors: Sönke Ludwig
*/
module vibe.textfilter.html;
import std.array;
import std.conv;
import std.range;
/** Returns the HTML escaped version of a given string.
*/
string htmlEscape(string str)
{
if( __ctfe ){ // appender is a performance/memory hog in ctfe
StringAppender dst;
filterHtmlEscape(dst, str);
return dst.data;
} else {
auto dst = appender!string();
filterHtmlEscape(dst, str);
return dst.data;
}
}
/** Writes the HTML escaped version of a given string to an output range.
*/
void filterHtmlEscape(R)(ref R dst, string str)
{
foreach( dchar ch; str )
filterHtmlEscape(dst, ch, HtmlEscapeFlags.escapeNewline);
}
/** Returns the HTML escaped version of a given string (also escapes double quotes).
*/
string htmlAttribEscape(string str)
{
if( __ctfe ){ // appender is a performance/memory hog in ctfe
StringAppender dst;
filterHtmlAttribEscape(dst, str);
return dst.data;
} else {
auto dst = appender!string();
filterHtmlAttribEscape(dst, str);
return dst.data;
}
}
/** Writes the HTML escaped version of a given string to an output range (also escapes double quotes).
*/
void filterHtmlAttribEscape(R)(ref R dst, string str)
{
foreach( dchar ch; str )
filterHtmlEscape(dst, ch, HtmlEscapeFlags.escapeNewline|HtmlEscapeFlags.escapeQuotes);
}
/** Returns the HTML escaped version of a given string (escapes every character).
*/
string htmlAllEscape()(string str)
{
if( __ctfe ){ // appender is a performance/memory hog in ctfe
StringAppender dst;
filterHtmlAllEscape(dst, str);
return dst.data;
} else {
auto dst = appender!string();
filterHtmlAllEscape(dst, str);
return dst.data;
}
}
/** Writes the HTML escaped version of a given string to an output range (escapes every character).
*/
void filterHtmlAllEscape(R)(ref R dst, string str)
{
foreach( dchar ch; str ){
dst.put("&#");
dst.put(to!string(cast(int)ch));
dst.put(';');
}
}
/**
Minimally escapes a text so that no HTML tags appear in it.
*/
string htmlEscapeMin(string str)
{
auto dst = appender!string();
foreach( dchar ch; str )
filterHtmlEscape(dst, ch, HtmlEscapeFlags.escapeMinimal);
return dst.data();
}
/**
Writes the HTML escaped version of a character to an output range.
*/
void filterHtmlEscape(R)(ref R dst, dchar ch, HtmlEscapeFlags flags = HtmlEscapeFlags.escapeNewline )
{
switch(ch){
default:
if( flags & HtmlEscapeFlags.escapeUnknown ){
dst.put("&#");
dst.put(to!string(cast(int)ch));
dst.put(';');
} else dst.put(ch);
break;
case '"':
if( flags & HtmlEscapeFlags.escapeQuotes ) dst.put(""");
else dst.put('"');
break;
case '\r', '\n':
if( flags & HtmlEscapeFlags.escapeNewline ){
dst.put("&#");
dst.put(to!string(cast(int)ch));
dst.put(';');
} else dst.put(ch);
break;
case 'a': .. case 'z': goto case;
case 'A': .. case 'Z': goto case;
case '0': .. case '9': goto case;
case ' ', '\t', '-', '_', '.', ':', ',', ';',
'#', '+', '*', '?', '=', '(', ')', '/', '!',
'%' , '{', '}', '[', ']', '`', '´', '$', '^', '~':
dst.put(cast(char)ch);
break;
case '<': dst.put("<"); break;
case '>': dst.put(">"); break;
case '&': dst.put("&"); break;
}
}
enum HtmlEscapeFlags {
escapeMinimal = 0,
escapeQuotes = 1<<0,
escapeNewline = 1<<1,
escapeUnknown = 1<<2
}
private struct StringAppender {
string data;
void put(string s) { data ~= s; }
void put(char ch) { data ~= ch; }
void put(dchar ch) {
import std.utf;
char[4] dst;
data ~= dst[0 .. encode(dst, ch)];
}
}