1 module uim.html.apps.layout; 2 3 import uim.html; 4 5 /// Page layout 6 class DH5AppLayout : DH5AppObj { 7 this() { super(); 8 _lang = "en"; } 9 this(DH5App anApp) { this().app(anApp); } 10 11 string[] _headClasses; 12 string[string] _headAttributes; 13 string[] _bodyClasses; 14 string[string] _bodyAttributes; 15 16 mixin(XString!("preHead")); 17 mixin(XString!("postHead")); 18 mixin(XString!("preContent")); 19 mixin(XString!("postContent")); 20 mixin(XStringArray!("requires")); 21 22 mixin(OString!("lang")); 23 mixin(OString!("title")); 24 25 mixin(OProperty!("DH5Html", "html")); 26 27 protected DH5Meta[] _metas; 28 DH5Meta[] metas() { return _metas; } 29 O metas(this O)(string[string] value, string[string][] addMetas...) { this.metas([value]~addMetas); return cast(O)this;} 30 O metas(this O)(string[string][] addMetas) { foreach(meta; addMetas) this.metas(H5Meta(meta)); return cast(O)this; } 31 32 O metas(this O)(DH5Meta[] addMetas...) { this.metas(addMetas); return cast(O)this; } 33 O metas(this O)(DH5Meta[] addMetas) { _metas ~= addMetas; return cast(O)this;} 34 35 O clearMetas(this O)() { _metas = null; return cast(O)this; } 36 unittest { 37 assert(uim.html.elements.meta.toString(H5AppLayout.metas(["a":"b"]).metas) == `<meta a="b">`); 38 assert(uim.html.elements.meta.toString(H5AppLayout.metas([["a":"b"]]).metas) == `<meta a="b">`); 39 assert(uim.html.elements.meta.toString(H5AppLayout.metas(H5Meta(["a":"b"])).metas) == `<meta a="b">`); 40 assert(uim.html.elements.meta.toString(H5AppLayout.metas([H5Meta(["a":"b"])]).metas) == `<meta a="b">`); 41 } 42 43 DH5Link[] _links; 44 DH5Link[] links() { return _links; } 45 O links(this O)(string[string] link, string[string][] links...) { this.links([link]~links); return cast(O)this;} 46 O links(this O)(string[string][] links) { foreach(link; links) _links ~= H5Link(link); return cast(O)this;} 47 48 O links(this O)(DH5Link[] links...) { this.links(links); return cast(O)this;} 49 O links(this O)(DH5Link[] links) { _links ~= links; return cast(O)this;} 50 51 O clearLinks(this O)() { _links = null; return cast(O)this; } 52 unittest { 53 /// TODO 54 } 55 56 DH5Style[] _styles; 57 DH5Style[] styles() { return _styles; } 58 O styles(this O)(string content, string[] contents...) { this.styles([content]~contents); return cast(O)this; } // <style>...</style> 59 O styles(this O)(string[] links) { foreach(link; links) _styles ~= H5Style(content); return cast(O)this;} 60 61 O styles(this O)(string[string] link, string[string][] links...) { this.links([link]~links); return cast(O)this;} 62 O styles(this O)(string[string][] links) { foreach(link; links) _links ~= H5Link(link); return cast(O)this;} 63 64 O styles(this O)(DH5Style[] styles...) { this.styles(styles); return cast(O)this;} 65 O styles(this O)(DH5Style[] styles) { _styles ~= styles; return cast(O)this;} 66 O styles(this O)(DH5Link[] links...) { this.styles(links); return cast(O)this;} 67 O styles(this O)(DH5Link[] links) { _styles ~= links; return cast(O)this;} 68 69 O clearStyles(this O)() { _styles = null; return cast(O)this; } 70 unittest { 71 /// TODO 72 } 73 74 DH5Script[] _scripts; 75 DH5Script[] scripts() { return _scripts; } 76 O scripts(this O)(string lib, string[] libs...) { this.scripts([lib]~libs); return cast(O)this;} 77 O scripts(this O)(string[] libs) { foreach(lib; libs) _scripts ~= H5Script(["src":lib]); return cast(O)this;} 78 79 O scripts(this O)(string[string] lib, string[string][] libs...) { this.scripts([lib]~libs); return cast(O)this;} 80 O scripts(this O)(string[string][] libs) { foreach(lib; libs) _scripts ~= H5Script(lib); return cast(O)this;} 81 82 O scripts(this O)(DH5Script[] libs...) { this.scripts(libs); return cast(O)this;} 83 O scripts(this O)(DH5Script[] libs) { _scripts ~= libs; return cast(O)this;} 84 85 O clearScripts(this O)() { _scripts = null; return cast(O)this; } 86 unittest { 87 // assert(H5AppLayout.) 88 } 89 90 mixin(XString!("headPart")); 91 mixin(XString!("bodyPart")); 92 93 /// central layout for page 94 DH5AppLayout _layout; 95 auto layout() { if (_layout) return _layout; return null; } 96 O layout(this O)(DH5AppLayout newlayout) { _layout = newlayout.app(this.app); return cast(O)this; } 97 unittest { 98 /// TODO 99 } 100 101 string opCall() { return toString(); } 102 string opCall(DH5AppPage page, string[string] parameters = null) { return toString(page, parameters); } 103 string opCall(string content, string[string] parameters = null) { return toString(content, parameters); } 104 105 override string toString() { return toString("", null); } 106 string toString(DH5AppPage page, string[string] someParameters = null) { 107 return toString(page, page.content, someParameters); 108 } 109 110 string toString(DH5AppPage page, string content, string[string] someParameters = null) { 111 // layout override app, page override layout, parameters override page 112 string[string] newParameters; 113 114 if (app) newParameters = app.parameters.dup; 115 // Layout overrides app 116 foreach(k,v; this.parameters) newParameters[k] = v; 117 // page overrides layout & app 118 foreach(k,v; page.parameters) newParameters[k] = v; 119 // parameters overrides App & layout & page 120 foreach(k,v; someParameters) newParameters[k] = v; 121 122 DH5Meta[] newMetas; 123 if (app) newMetas ~= app.metas; 124 newMetas ~= this.metas; 125 newMetas ~= page.metas; 126 127 DH5Link[] newLinks; 128 // if (app) newLinks = app.links; 129 newLinks ~= this.links; 130 newLinks ~= page.links; 131 132 DH5Style[] newStyles; 133 if (app) newStyles ~= app.styles; 134 newStyles ~= this.styles; 135 newStyles ~= page.styles; 136 137 DH5Script[] newScripts; 138 if (app) newScripts ~= app.scripts; 139 newScripts ~= this.scripts; 140 newScripts ~= page.scripts; 141 142 return htmlDocument(content, newMetas, newLinks, newStyles, newScripts, newParameters); 143 } 144 145 string toString(string content, string[string] someParameters = null) { 146 // layout override app, parameters override layout 147 string[string] newParameters; 148 149 if (app) newParameters = app.parameters.dup; 150 // Layout overrides app 151 foreach(k,v; this.parameters) newParameters[k] = v; 152 // parameters overrides App & layout & page 153 foreach(k,v; someParameters) newParameters[k] = v; 154 155 DH5Meta[] newMetas; 156 if (app) newMetas = app.metas; 157 newMetas ~= this.metas; 158 159 DH5Link[] newLinks; 160 // if (app) newLinks = app.links; 161 newLinks ~= this.links; 162 163 DH5Style[] newStyles; 164 if (app) newStyles = app.styles; 165 newStyles ~= this.styles; 166 167 DH5Script[] newScripts; 168 if (app) newScripts ~= app.scripts; 169 newScripts ~= this.scripts; 170 171 return htmlDocument(content, newMetas, newLinks, newStyles, newScripts, newParameters); 172 } 173 174 auto htmlDocument(string content, DH5Meta[] newMetas, DH5Link[] newLinks, DH5Style[] newStyles, DH5Script[] newScripts, string[string] parameters = null) { 175 auto finalLang = parameters.get("lang", this.lang); // if lang !in parameters use this.lang 176 auto finalTitle = parameters.get("title", this.title); // if title !in parameters use this.title 177 178 // creating HTML page 179 _html = H5Html 180 .attributes("lang", finalLang).attributes("dir", parameters.get("dir", "ltr")) 181 // Head part of HTML 182 .head(_headClasses) 183 .head(_headAttributes) 184 .head(finalTitle.length > 0 ? "<title>" ~ finalTitle ~ "</title>":"") 185 .head(newMetas.asString~parameters.get("metas", "")) 186 .head(newLinks.asString~parameters.get("links", "")) 187 .head(newStyles.asString~parameters.get("styles", "")) 188 .head("style" in parameters ? H5Style(parameters["style"]).toString : "") 189 // Body part of HTML 190 .body_(_bodyClasses) 191 .body_(_bodyAttributes) 192 .body_(this.layout ? this.layout.toString(content, parameters) : content) 193 .body_(newScripts.asString~parameters.get("scripts", "")) 194 .body_("script" in parameters ? H5Script(parameters["script"]).toString : ""); 195 196 return _html.toString; 197 } 198 unittest { 199 // writeln(H5AppLayout); 200 assert(H5AppLayout == `<!doctype html><html dir="ltr" lang="en"><head></head><body></body></html>`); 201 assert(H5AppLayout()("xxx") == `<!doctype html><html dir="ltr" lang="en"><head></head><body>xxx</body></html>`); 202 } 203 } 204 auto H5AppLayout() { return new DH5AppLayout(); } 205 206 unittest { 207 208 }