#pragma once #include "concat_strings.h" #include #include #include #include extern Y_POD_THREAD(IOutputStream*) HtmlOutputStreamPtr; static IOutputStream& HtmlOutputStream() { Y_ABORT_UNLESS(!!HtmlOutputStreamPtr); return *HtmlOutputStreamPtr; } struct THtmlOutputStreamPushPop { IOutputStream* const Prev; THtmlOutputStreamPushPop(IOutputStream* outputStream) : Prev(HtmlOutputStreamPtr) { HtmlOutputStreamPtr = outputStream; } ~THtmlOutputStreamPushPop() { HtmlOutputStreamPtr = Prev; } }; struct TChars { TString Text; bool NeedEscape; TChars(TStringBuf text) : Text(text) , NeedEscape(true) { } TChars(TStringBuf text, bool escape) : Text(text) , NeedEscape(escape) { } TChars(const char* text) : Text(text) , NeedEscape(true) { } TChars(const char* text, bool escape) : Text(text) , NeedEscape(escape) { } TString Escape() { if (NeedEscape) { return EncodeHtmlPcdata(Text); } else { return Text; } } }; struct TAttr { TString Name; TString Value; TAttr(TStringBuf name, TStringBuf value) : Name(name) , Value(value) { } TAttr() { } bool operator!() const { return !Name; } }; static inline void Doctype() { HtmlOutputStream() << "\n"; } static inline void Nl() { HtmlOutputStream() << "\n"; } static inline void Sp() { HtmlOutputStream() << " "; } static inline void Text(TStringBuf text) { HtmlOutputStream() << EncodeHtmlPcdata(text); } static inline void Line(TStringBuf text) { Text(text); Nl(); } static inline void WriteAttr(TAttr a) { if (!!a) { HtmlOutputStream() << " " << a.Name << "='" << EncodeHtmlPcdata(a.Value) << "'"; } } static inline void Open(TStringBuf tag, TAttr a1 = TAttr(), TAttr a2 = TAttr(), TAttr a3 = TAttr(), TAttr a4 = TAttr()) { HtmlOutputStream() << "<" << tag; WriteAttr(a1); WriteAttr(a2); WriteAttr(a3); WriteAttr(a4); HtmlOutputStream() << ">"; } static inline void Open(TStringBuf tag, TStringBuf cssClass, TStringBuf id = "") { Open(tag, TAttr("class", cssClass), !!id ? TAttr("id", id) : TAttr()); } static inline void OpenBlock(TStringBuf tag, TStringBuf cssClass = "") { Open(tag, cssClass); Nl(); } static inline void Close(TStringBuf tag) { HtmlOutputStream() << "\n"; } static inline void CloseBlock(TStringBuf tag) { Close(tag); Nl(); } static inline void TagWithContent(TStringBuf tag, TChars content) { HtmlOutputStream() << "<" << tag << ">" << content.Escape() << ""; } static inline void BlockTagWithContent(TStringBuf tag, TStringBuf content) { TagWithContent(tag, content); Nl(); } static inline void TagWithClass(TStringBuf tag, TStringBuf cssClass) { Open(tag, cssClass); Close(tag); } static inline void Hn(unsigned n, TStringBuf title) { BlockTagWithContent(ConcatStrings("h", n), title); } static inline void Small(TStringBuf text) { TagWithContent("small", text); } static inline void HnWithSmall(unsigned n, TStringBuf title, TStringBuf small) { TString tagName = ConcatStrings("h", n); Open(tagName); HtmlOutputStream() << title; Sp(); Small(small); Close(tagName); } static inline void H1(TStringBuf title) { Hn(1, title); } static inline void H2(TStringBuf title) { Hn(2, title); } static inline void H3(TStringBuf title) { Hn(3, title); } static inline void H4(TStringBuf title) { Hn(4, title); } static inline void H5(TStringBuf title) { Hn(5, title); } static inline void H6(TStringBuf title) { Hn(6, title); } static inline void Pre(TStringBuf content) { HtmlOutputStream() << "
" << EncodeHtmlPcdata(content) << "
\n"; } static inline void Li(TStringBuf content) { BlockTagWithContent("li", content); } static inline void LiWithClass(TStringBuf cssClass, TStringBuf content) { Open("li", cssClass); Text(content); Close("li"); } static inline void OpenA(TStringBuf href) { Open("a", TAttr("href", href)); } static inline void A(TStringBuf href, TStringBuf text) { OpenA(href); Text(text); Close("a"); } static inline void Td(TStringBuf content) { TagWithContent("td", content); } static inline void Th(TStringBuf content, TStringBuf cssClass = "") { OpenBlock("th", cssClass); Text(content); CloseBlock("th"); } static inline void DivWithClassAndContent(TStringBuf cssClass, TStringBuf content) { Open("div", cssClass); Text(content); Close("div"); } static inline void BootstrapError(TStringBuf text) { DivWithClassAndContent("alert alert-danger", text); } static inline void BootstrapInfo(TStringBuf text) { DivWithClassAndContent("alert alert-info", text); } static inline void ScriptHref(TStringBuf href) { Open("script", TAttr("language", "javascript"), TAttr("type", "text/javascript"), TAttr("src", href)); Close("script"); Nl(); } static inline void LinkStylesheet(TStringBuf href) { Open("link", TAttr("rel", "stylesheet"), TAttr("href", href)); Close("link"); Nl(); } static inline void LinkFavicon(TStringBuf href) { Open("link", TAttr("rel", "shortcut icon"), TAttr("href", href)); Close("link"); Nl(); } static inline void Title(TChars title) { TagWithContent("title", title); Nl(); } static inline void Code(TStringBuf content) { TagWithContent("code", content); } struct TTagGuard { const TString TagName; TTagGuard(TStringBuf tagName, TStringBuf cssClass, TStringBuf id = "") : TagName(tagName) { Open(TagName, cssClass, id); } TTagGuard(TStringBuf tagName, TAttr a1 = TAttr(), TAttr a2 = TAttr(), TAttr a3 = TAttr(), TAttr a4 = TAttr()) : TagName(tagName) { Open(tagName, a1, a2, a3, a4); } ~TTagGuard() { Close(TagName); } }; struct TDivGuard: public TTagGuard { TDivGuard(TStringBuf cssClass, TStringBuf id = "") : TTagGuard("div", cssClass, id) { } TDivGuard(TAttr a1 = TAttr(), TAttr a2 = TAttr(), TAttr a3 = TAttr()) : TTagGuard("div", a1, a2, a3) { } }; struct TAGuard { TAGuard(TStringBuf href) { OpenA(href); } ~TAGuard() { Close("a"); } }; struct TScriptFunctionGuard { TTagGuard Script; TScriptFunctionGuard() : Script("script") { Line("$(function() {"); } ~TScriptFunctionGuard() { Line("});"); } };