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 else {
14     enum withInterpolation = false;
15 }
16 
17 /// Escape HTML elements.
18 ///
19 /// Package level: input sanitization is done automatically by the library.
20 package string escapeHTML(const string text) {
21 
22     // substitute doesn't work in CTFE for some reason
23     if (__ctfe) {
24 
25         return text
26             .map!(ch => ch.predSwitch(
27                 '<', "&lt;",
28                 '>', "&gt;",
29                 '&', "&amp;",
30                 '"', "&quot;",
31                 '\'', "&#39;",
32                 .text(ch),
33             ))
34             .join;
35 
36     }
37 
38     else return text.substitute!(
39         `<`, "&lt;",
40         `>`, "&gt;",
41         `&`, "&amp;",
42         `"`, "&quot;",
43         `'`, "&#39;",
44     ).to!string;
45 
46 }
47 
48 /// Serialize attributes
49 package string serializeAttributes(string[string] attributes) {
50 
51     // Generate attribute text
52     string attrHTML;
53     foreach (key, value; attributes) {
54 
55         attrHTML ~= format!` %s="%s"`(key, value.escapeHTML);
56 
57     }
58 
59     return attrHTML;
60 
61 }
62 
63 package string minifyAttributes(string attrHTML) {
64 
65     const ret = attrHTML.splitter("\n")
66         .map!q{ a.strip }
67         .filter!q{ a.length }
68         .join(" ");
69 
70     return ret.length
71         ? " " ~ ret
72         : null;
73 
74 }