abstract sclass HAbstractRenderable { S baseLink = ""; MakeFrame makeFrame = (title, contents) -> h1_title(title) + contents; sinterface MakeFrame { S makeFrame(S title, S contents); } *() {} *(S *baseLink) {} HAbstractRenderable makeFrame(MakeFrame makeFrame) { this.makeFrame = makeFrame; this; } S baseLinkPlus(S uri) { ret nempty(uri) ? appendSlash(baseLink) + uri : baseLink; } // title is in HTML S frame(S title, S contents) { ret makeFrame.makeFrame(title, contents); } S refreshWithMsgs(S... msgs) { ret refreshWithMsgs(asList(msgs)); } S refreshWithMsgs(LS msgs, O... _) { optPar S anchor; optPar SS params; ret hrefresh(addAnchorToURL(appendQueryToURL(baseLink, mapPlus(params, msg := htmlEncode_nlToBr(lines_rtrim(msgs)))), anchor)); } S renderMsgs(SS params) { ret pUnlessEmpty(params.get("msg")); } }