
Search.pudu
Pudu52 lines2.0 KB
1/** @Docgen.Site.Search — the searchable text of published pages */2module PuduLangDocgen.Site.Search34import Std.Json as Json5import PuduLangDocgen as Docgen6import PuduLangDocgen.Meta as Meta789const TEXT_LIMIT: Int = 8000101112const HIDDEN: Array[Str] = ["script", "style", "button"]13141516export fn index(pages: &Array[Docgen.Page]) -> Str {17 var entries: Array[Json.Json] = []18 for page in *pages {19 if page.kind == "redirect" || Meta.flag(&page.meta, "_noindex") { continue }20 let text = plainText(page.body)21 entries = entries.push(Json.object(&[("href", Json.Text(page.path)), ("title", Json.Text(page.title)), ("summary", Json.Text(page.summary)), ("text", Json.Text(text.take(TEXT_LIMIT)))]))22 }23 Json.encode(&Json.list(&entries))24}252627export fn plainText(html: Str) -> Str {28 let cs = html.chars()29 var pieces: Array[Str] = []30 var cursor = 031 var hidden = ""32 while cursor < cs.length() {33 let character = cs[cursor]34 if character == '<' {35 var end = cursor + 136 while end < cs.length() && cs[end] != '>' { end = end + 1 }37 var tag: Array[Str] = []38 for position in (cursor + 1)..end { tag = tag.push(cs[position].toText()) }39 let name = tag.join("").split(" ")[0].toLower()40 if hidden.isEmpty() && HIDDEN.contains(name) { hidden = name }41 else if !hidden.isEmpty() && name == "/" + hidden { hidden = "" }42 pieces = pieces.push(" ")43 cursor = end + 144 } else {45 if hidden.isEmpty() { pieces = pieces.push(character.toText()) }46 cursor = cursor + 147 }48 }49 let text = pieces.join("").replace("<", "<").replace(">", ">").replace(""", "\"").replace("'", "'").replace("&", "&")50 text.replace("\n", " ").replace("\t", " ").split(" ").filter(|word: Str| !word.isEmpty()).join(" ")51}52