1 /// Holds the [Attribute] type which can be passed to [elemi.elem|elem] to add attributes to 2 /// XML and HTML elements. 3 module elemi.attribute; 4 5 /// 6 unittest { 7 import elemi.xml; 8 9 // Create new attributes with `attr` 10 auto a = attr("key") = "value"; 11 assert(a == `key="value"`); 12 13 // And pass them to elements 14 assert(elem!"div"(a) == `<div key="value"></div>`); 15 16 assert(elem!"div"( 17 attr("key") = "value", 18 attr("class") = "one two three", 19 ) == `<div key="value" class="one two three"></div>`); 20 } 21 22 import std.string; 23 24 import elemi.internal; 25 26 pure @safe: 27 28 29 /// Represents an XML/HTML attribute. It can be easily created with the [attr] function. 30 struct Attribute { 31 32 pure: 33 34 /// Name of the attribute. 35 string name; 36 37 /// Value assigned to the attribute. 38 string value; 39 40 /// Assign a new value to this attribute. Retains the original key. 41 /// Params: 42 /// newValue = Value assigned to the attribute. i-strings are supported. 43 /// The value can also be passed as an array of strings, in which case they will be 44 /// joined with a space. That comes handy for CSS classes. 45 /// Returns: 46 /// The attribute. 47 Attribute opAssign(string newValue) { 48 49 value = newValue; 50 return this; 51 52 } 53 54 /// ditto 55 Attribute opAssign(string[] newValue) { 56 57 value = newValue.join(" "); 58 return this; 59 60 } 61 62 static if (withInterpolation) { 63 /// ditto 64 Attribute opAssign(Ts...)(InterpolationHeader, Ts values, InterpolationFooter) { 65 import std.conv : text; 66 value = text(values); 67 return this; 68 } 69 70 /// 71 pure @safe unittest { 72 auto a = Attribute("name"); 73 a = i"1+2 is $(1+2)"; 74 assert(a == `name="1+2 is 3"`); 75 } 76 } 77 78 string toString() { 79 80 return format!q{%s="%s"}(name, value.escapeHTML); 81 82 } 83 84 alias toString this; 85 86 } 87 88 /// Create an XML/HTML attribute. 89 /// 90 /// Params: 91 /// name = Name for the attribute. 92 /// value = Value for the attribute. 93 Attribute attr(string name) { 94 95 return Attribute(name); 96 97 } 98 99 /// ditto 100 Attribute attr(string name)() { 101 102 return Attribute(name); 103 104 } 105 106 /// ditto 107 Attribute attr(string name, string value) { 108 109 return Attribute(name, value); 110 111 } 112 113 /// ditto 114 Attribute attr(string name)(string value) { 115 116 return Attribute(name, value); 117 118 } 119 120 /// 121 pure unittest { 122 auto a = attr("key") = "value"; 123 auto b = attr("key", "value"); 124 125 assert(a == `key="value"`); 126 assert(a == b); 127 } 128 129 /// 130 pure unittest { 131 import elemi.html; 132 133 assert(elem!"div"( 134 attr("id") = "name", 135 attr("class") = ["hello", "world"], 136 ) == `<div id="name" class="hello world"></div>`); 137 } 138 139 /// 140 static if (withInterpolation) 141 pure unittest { 142 import elemi.html; 143 144 assert(elem!"div"( 145 attr("class") = i"interpolate-$(123)-<unsafe>" 146 ) == `<div class="interpolate-123-<unsafe>"></div>`); 147 }