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 '<', "<", 28 '>', ">", 29 '&', "&", 30 '"', """, 31 '\'', "'", 32 .text(ch), 33 )) 34 .join; 35 36 } 37 38 else return text.substitute!( 39 `<`, "<", 40 `>`, ">", 41 `&`, "&", 42 `"`, """, 43 `'`, "'", 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 }