!7 sclass SmoothHTMLTemplater { // input S template; // internal LS tok; L commentRanges; LS comments; srecord Replacement(S exampleValue, S actualValue) { S replaceIn(S text) { ret replace(text, exampleValue, actualValue); } } S render() { tok = htmlTok(template); commentRanges = charRangesOfHTMLComments(template); comments = map(commentRanges, r -> htmlCommentContents(substring(template, r))); new Matches m; new LPair replacements; for i over comments: { S comment = comments.get(i); if (match("start * block", comment)) { S type = $1; S endPat = format3("end * block", type); int j = indexOfMatches(endPat, comments, i+1); if (j < 0) continue with warn("End of block comment not found: " + endPat); LL entries = getEntries(type); IntRange r1 = commentRanges.get(i), r2 = commentRanges.get(j); S contents = substring(template, r1.end, r2.start); addPair(replacements, intRange(r1.end, r2.start), lines(map(entries, entry -> rewriteEntry(contents, entry)))); i = j; } } pnl(map htmlCommentContents(map(r -> substring(template, r), ))); } // TODO: avoid multi-replacements S rewriteEntry(S text, L entry) { fOr (Replacement r : entry) text = r.replaceIn(text); ret text; } LL getEntries(S type) { null; } } cmodule TemplaterTest > DynPrintLogAndWeb { set flag NoNanoHTTPD. !include #1029545 // API for Eleu S html(IWebRequest req) { S template = loadPage("https://pays5.com/text/2559"); ret template; } }