Utilities

ReadingTime

"4 min read", worked out from a text or a word count, with the wording and the reading speed yours to set.

#utility#text#time#typography#no-js

Demo

Preview
4 min read7 min readUnder a minute12 minutes to read

The first is a text of 800 words at 200 a minute.

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/reading_time.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/reading_time.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/reading_time.qwe
let reading_time_demo_text = repeat("The quick brown fox jumps over the lazy dog and keeps running through the long afternoon. ", 50)view ReadingTimeDemo() =    <div.demo-stack>        <div.demo-row style="gap: 24px">            <ReadingTime id="reading-time-demo-text" text={reading_time_demo_text}/>            <ReadingTime id="reading-time-demo-words" words={1850} wpm={250} icon={false}/>            <ReadingTime id="reading-time-demo-short" text="Just a note." less="Under a minute" size="sm"/>            <ReadingTime id="reading-time-demo-format" words={2400} format="{n} minutes to read"/>        </div>        <p.demo-note>The first is a text of {reading_time_words(reading_time_demo_text)} words at 200 a minute.</p>    </div>

Source

ui/reading_time.qwe
// ReadingTime: "4 min read", worked out from a text (or a word count), for the// top of an article.////   <ReadingTime text={post.body}/>//   <ReadingTime words={1850} wpm={250} icon={false}/>//   <ReadingTime text={post.body} format="{n} minutes" less="Under a minute"/>//// text: the article (Markdown or plain; tags and marks count as words, close// enough). words: the count, when known, instead of text. wpm: words read a// minute (200). format: what it says, with {n} for the minutes ("{n} min read").// less: what it says under a minute ("1 min read"). icon: a small clock before// it (true). size: "sm" or "md" (default). reading_time_minutes(text, wpm) and// reading_time_words(text) give the numbers for your own markup.import ui/theme.qwe use ui_clslet reading_time_css = css`.ui-readtime { display: inline-flex; align-items: center; gap: 5px; vertical-align: middle; font: 13px/1.4 var(--ui-font); color: var(--ui-muted);  white-space: nowrap; }.ui-readtime svg { flex: none; width: 14px; height: 14px; }.ui-readtime-sm { font-size: 12px; }.ui-readtime-sm svg { width: 12px; height: 12px; }`// How many words a text has: runs of characters that are not spaces.fn reading_time_words(text: str) -> int = len(re.find_all(text, "\\S+"))// Whole minutes to read `words` words at `wpm`, at least 1.fn reading_time_minutes(words: int, wpm: int = 200) -> int = max([1, round(words / (wpm < 1 ? 200 : wpm))])view ReadingTime(text: str? = null, words: int? = null, wpm: int = 200, format: str = "{n} min read", less: str? = null,                 icon: bool = true, size: str = "md", id: str? = null, class: str? = null) {    style global reading_time_css    let count = words ?? reading_time_words(text ?? "")    let mins = reading_time_minutes(count, wpm)    let under = count < wpm && less != null    let said = under ? less : replace(format, "{n}", str(mins))    <span class={ui_cls(["ui-readtime", size != "md" && `ui-readtime-${size}`, class])} id={id}          title={`${count} words`}>        {icon && <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"                      stroke-linejoin="round" aria-hidden="true"><circle cx="8" cy="8" r="6"/><path d="M8 4.8V8l2.2 1.5"/></svg>}        <span>{said}</span>    </span>}
Thread
68Useful? Like it, or add to its thread below.

Thread 0 posts

On ReadingTime: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.