!7 static new L data; concept Para { S text; L split; bool ok; } p { db(); parasFromText(); data.clear(); for (Para p) { if (p.split == null) { p.split = splitIntoSentences_v1(p.text); p.change(); } S sp; if (l(p.split) == 1 && eq(first(p.split), p.text)) sp = "-"; else //sp = htmlEncode_nlToBr(lines(p.split)); sp = ul(htmlEncodeAll(p.split)); data.add(litorderedmap( "Original Paragraph" := htmlencode(p.text), "Split" := sp, "OK" := hcheckbox("ok_" + p.id, p.ok, "class" := "chkbox"))); } data = sortByCalculatedField(data, func(Map m) { comparableList( neq(m.get("Split"), "-"), m.get("Original Paragraph")) }); serveHttpOpenBrowser(4000); } static synchronized NanoHTTPD.Response serve(S uri, NanoHTTPD.Method method, Map header, Map parms, Map files) { Set toCheck = asSet(map(f toLong, keysDeprefixNemptyValue(parms, "ok_"))); for (Para p) cset(p, ok := toCheck.contains(p.id)); S title = "Splitting paragraphs into sentences"; ret serveHTML(hhtml( hhead(htitle(title) + loadJQuery() + hCheckBoxMultiSelect()) + hbody(h3(title) + hform(htable_noEncode(data) + p(hsubmit()))))); } svoid parasFromText { S text = loadSnippet(#1008407); for (S line : toLinesFullTrim(text)) { if (line.startsWith("#")) continue; uniq(Para, text := line); } }