aboutsummaryrefslogtreecommitdiff
path: root/frontend/main.ts
blob: b74f539e704e9f737cb2fe2c3f67a04959539cc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/// <reference lib="dom" />

interface Bangs { [key: string]: string }
let bangs: Bangs = {}
let status_el: HTMLElement

globalThis.addEventListener("hashchange", () => process_url())
globalThis.addEventListener("load", async () => {
    status_el = document.createElement("p")
    document.body.append(status_el)

    const bangs_res = await fetch("/bangs.json")
    if (!bangs_res.ok) document.writeln("error: could not download bangs.json")
    bangs = await bangs_res.json()
    process_url()
})

function setup_page(engine?: string) {
    document.getElementById("content")?.remove()
    const section = document.createElement("section")
    section.id = "content"

    if (engine) {
        if (document.getElementById("search-link")) {
            // <link /> is already present, we need reload because browser wont notice otherwise
            window.location.reload()
        }
        const link = document.createElement("link")
        link.rel = "search"
        link.id = "search-link"
        link.type = "application/opensearchdescription+xml"
        link.href = `/search.xml?default=${encodeURIComponent(engine)}`
        link.title = `Laufente (defaults engine: ${engine})`
        document.head.append(link)

        const heading = document.createElement("h1")
        heading.textContent = engine

        const input = document.createElement("input")
        input.type = "input"
        input.addEventListener("keydown", ev => {
            if (ev.code == "Enter") process_query(engine, input.value ?? "")
        })

        const submit = document.createElement("button")
        submit.textContent = "Search"
        submit.addEventListener("click", () => {
            process_query(engine, input.value ?? "")
        })

        const info = document.createElement("p")
        info.textContent = `To install this as the default search engine, select "Add <name>" in the context-menu of the URL-bar.`

        section.append(heading, input, submit, info)
    } else {
        const info = document.createElement("p")
        info.textContent = `todo`
        section.append(info)
    }
    document.body.append(section)
}


function status(text: string, color?: string) {
    status_el.textContent = text
    if (color) status_el.style.color = color
}

function process_url() {
    if (document.location.hash.length != 0) {
        const input = document.location.hash.substring(1)
        const [default_engine, query_encoded] = input.split("#")
        if (!query_encoded) return setup_page(default_engine)
        const query = decodeURIComponent(query_encoded)
        process_query(default_engine, query)
    } else {
        setup_page()
    }
}

function process_query(default_engine: string, query: string) {
    const bang_prefix = "!"
    let url = ""
    if (query.startsWith(bang_prefix)) {
        const [engine, ...query_parts] = query.substring(bang_prefix.length).split(" ")
        url = search_url(engine, query_parts.join(" "))
    } else {
        url = search_url(default_engine, query)
    }

    status(`Forwarding to ${url}`, "green")
    setTimeout(() => document.location.href = url, 0)
}

function search_url(engine: string, query: string) {
    return bangs[engine].replace("{{{s}}}", encodeURIComponent(query).replaceAll("%20", "+"))
}