diff --git a/error.html b/error.html index 350f0625..914a19c2 100644 --- a/error.html +++ b/error.html @@ -47,6 +47,8 @@ background: var(--panel); border: 1px solid var(--line); color: var(--acid); font-family: ui-monospace, monospace; font-size: 12.5px; text-decoration: none; cursor: pointer; } .suggest a:hover { border-color: rgb(from var(--acid) r g b / .55); filter: brightness(1.05); } + .suggest a.search { font-family: inherit; color: var(--ink); } + .suggest a.search:hover { color: var(--acid); } .actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 1.3rem; } .btn { font-family: inherit; font-size: 13.5px; padding: 9px 16px; border-radius: 9px; border: 1px solid var(--line); background: var(--panel2); color: var(--ink); @@ -270,13 +272,16 @@ actionsBox.appendChild(b); } - // "Did you mean" — two sources, merged into one row: + // "Did you mean" — two sources, merged into one row, plus a search chip: // • BCNR warm shared index (Levenshtein ≤ 2, same TLD) — for a BCDN name // typo like "games.x" → "game.x". Local index; works offline. // • ICANN alternative-TLD swaps + history base-name matches — a DNS // failure on my.mynymbox.com surfaces my.mynymbox.io, .net, .org, …, // and any related host the user has visited. Local too. - // Clicking a suggestion retries at that host, preserving the original path. + // • A trailing "Search ''" chip that defers to the default + // search engine when none of the URL alternatives looks right. + // Clicking a URL chip retries at that host (keeps the original path); + // clicking the search chip opens a search for the host text. if ((kind === "name-not-registered" || kind === "name-unreachable") && host) { let origPath = "/"; try { const u = new URL(url); origPath = u.pathname + u.search + u.hash; } catch {} @@ -292,7 +297,6 @@ seen.add(name); matches.push(name); if (matches.length >= 4) break; } - if (!matches.length) return; const row = $("suggestRow"); for (const name of matches) { const a = el("a", null, name); @@ -303,6 +307,23 @@ }); row.appendChild(a); } + // Search chip. Shown whenever we have a host, even when no URL match + // surfaced — "search for it on your default engine" is the universal + // fallback for a DNS miss. + const s = el("a", "search", "🔎 Search '" + host + "'"); + s.href = "#"; + s.title = "Open your default search engine with this as the query"; + s.addEventListener("click", (ev) => { + ev.preventDefault(); + window.errorpage.searchFor(host); + }); + row.appendChild(s); + // Replace the row's "Did you mean" label with a softer one when the + // only chip is the search fallback — nothing to actually suggest. + if (!matches.length) { + const lbl = $("suggest").querySelector(".lbl"); + if (lbl) lbl.textContent = "Not sure what you were after?"; + } $("suggest").hidden = false; }).catch(() => {}); } diff --git a/package.json b/package.json index 2ef56bf1..43458281 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "theseus-navigator", - "version": "0.3.122", + "version": "0.3.123", "license": "MPL-2.0", "description": "Theseus Navigator — a browser that follows the thread. By Silent Mode, a Deviant project.", "author": "Silent Mode",