MatchHighlight
Marks where the words of a search appear in a text, in any case, every time they do.
Demo
- Deploying a Quillo app to Fly.io
- Toronto, Ontario
- No match here
Quillo renders components on the server, then resumes them in the browser from the state the server sent, so a page shows at once and reacts as soon as it is touched.
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/match_highlight.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/match_highlight.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/match_highlight.qwe
let match_highlight_demo_text = "Quillo renders components on the server, then resumes them in the browser from the state the server sent, so a page shows at once and reacts as soon as it is touched."component MatchHighlightDemoLive() { state q = "server state" <div.demo-stack> <SearchInput name="mh-q" label="Find in the text" value={q} on_input={(t) => { q = t }}/> <p.demo-note.mh-demo-out><MatchHighlight text={match_highlight_demo_text} query={q}/></p> </div>}view MatchHighlightDemo() = <div.demo-stack> <ul.demo-stack.mh-demo-list style="margin: 0; padding-left: 18px"> <li><MatchHighlight text="Deploying a Quillo app to Fly.io" query="quillo deploy"/></li> <li><MatchHighlight text="Toronto, Ontario" query="to"/></li> <li><MatchHighlight text="No match here" query="zebra"/></li> </ul> <MatchHighlightDemoLive/> </div>Source
ui/match_highlight.qwe
// MatchHighlight: a text with the parts that match a search marked, as <mark>, in// any case and wherever they are; each word of the query is looked for on its own.// A view: it needs no script, and components (SearchList) use it as they filter.//// <MatchHighlight text="Deploying a Quillo app to Fly.io" query="quillo deploy"/>// <p>{for r in results => <MatchHighlight text={r.title} query={q}/>}</p>//// text: what to show. query: what was searched; split into words at spaces, and// each found in every place (so "to" marks both of "Toronto"). An empty query// marks nothing. class: added to the wrapping <span>.// match_highlight_parts(text, query) gives the pieces as [{ text, hit }], to mark// them some other way.let match_highlight_css = css`.ui-mh-mark { padding: 0 1px; border-radius: 3px; background: color-mix(in srgb, var(--ui-warning) 26%, transparent); color: inherit;}@media (forced-colors: active) { .ui-mh-mark { background: Mark; color: MarkText; } }`// The words of a query in lower case, without repeats: "Rust web" is ["rust", "web"].fn match_highlight_words(query: str) -> list = re.split(lower(trim(query)), "\\s+") | filter((w) => w != "") | unique// The text in pieces: [{ text, hit }], hit where a word of the query is.fn match_highlight_parts(text: str, query: str) -> list { let words = match_highlight_words(query) | map((w) => split(w, "")) let cs = split(text, "") let low = split(lower(text), "") let n = len(cs) if len(words) == 0 || n == 0 || len(low) != n { return [{ text, hit: false }] } let parts = [] let run = "" let run_hit = false let reach = 0 let i = 0 while i < n { let k = 0 while k < len(words) { let w = words[k] let lw = len(w) if i + lw > reach && i + lw <= n { let j = 0 while j < lw && low[i + j] == w[j] { j += 1 } if j == lw { reach = i + lw } } k += 1 } let hit = i < reach if hit != run_hit && run != "" { parts = parts | push({ text: run, hit: run_hit }) run = "" } run_hit = hit run = run + cs[i] i += 1 } parts | push({ text: run, hit: run_hit })}view MatchHighlight(text: str, query: str = "", class: str? = null) { style global match_highlight_css <span class={class}>{for p in match_highlight_parts(text, query) => p.hit ? <mark.ui-mh-mark>{p.text}</mark> : p.text}</span>}Related
MarkHighlighted text in tones, as a real <mark>, filled or underlined.4 views · 9 downloadsCodeBlockCode in a <pre> with a file name, line numbers, highlighted lines and a Copy button.5 views · 6 downloadsDataGridSort, search, filter by a column's values, pick rows and page through them, in one table.5 views · 9 downloadsJsonTableJSON as a table: open nested objects and arrays in place or as the table, search at every depth, export as JSON or CSV, thousands of lines kept fast.9 views · 8 downloadsLogExplorerReads raw logs in logfmt, JSON lines or plain text, keeps traces together, and searches them like level:error status:5xx "timeout".3 views · 6 downloadsLogViewerLog lines with each level in its colour, buttons to show or hide levels, a search that marks matches, wrapping and following the end.8 views · 7 downloads
Thread
Thread 0 posts
On MatchHighlight: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.