1 module elemi.internal;
2 
3 import std.conv;
4 import std.string;
5 import std.algorithm;
6 
7 pure @safe:
8 
9 static if (__traits(compiles, { import core.interpolation; })) {
10     public import core.interpolation;
11     enum withInterpolation = true;
12     
13     enum isInterpolation(size_t index, Ts...)
14         =  is(Ts[index] == InterpolationHeader)
15         || is(Ts[index] == InterpolationFooter)
16         || is(Ts[index] == InterpolatedLiteral!text, string text)
17         || is(Ts[index] == InterpolatedExpression!text, string text)
18         || (index > 0 && is(Ts[index-1] == InterpolatedExpression!text, string text));
19 
20 }
21 else {
22     enum withInterpolation = false;
23     enum isInterpolation(size_t index, Ts...) = false;
24 }
25 
26 /// Escape HTML elements.
27 ///
28 /// Package level: input sanitization is done automatically by the library.
29 package string escapeHTML(const string text) {
30 
31     // substitute doesn't work in CTFE for some reason
32     if (__ctfe) {
33 
34         return text
35             .map!(ch => ch.predSwitch(
36                 '<', "&lt;",
37                 '>', "&gt;",
38                 '&', "&amp;",
39                 '"', "&quot;",
40                 '\'', "&#39;",
41                 .text(ch),
42             ))
43             .join;
44 
45     }
46 
47     else return text.substitute!(
48         `<`, "&lt;",
49         `>`, "&gt;",
50         `&`, "&amp;",
51         `"`, "&quot;",
52         `'`, "&#39;",
53     ).to!string;
54 
55 }
56 
57 /// Serialize attributes
58 package string serializeAttributes(string[string] attributes) {
59 
60     // Generate attribute text
61     string attrHTML;
62     foreach (key, value; attributes) {
63 
64         attrHTML ~= format!` %s="%s"`(key, value.escapeHTML);
65 
66     }
67 
68     return attrHTML;
69 
70 }
71 
72 package string minifyAttributes(string attrHTML) {
73 
74     const ret = attrHTML.splitter("\n")
75         .map!q{ a.strip }
76         .filter!q{ a.length }
77         .join(" ");
78 
79     return ret.length
80         ? " " ~ ret
81         : null;
82 
83 }