A fast, local-first "redirection engine" for !bang users with a few extra features ^-^

feat: minify favicon and remove inter dependency

dunkirk.sh ef4081ab 247d99b6

verified
+11 -11
bun.lock
···
"": {
"name": "unduck",
"dependencies": {
-
"@fontsource/inter": "^5.2.5",
+
"caniuse-lite": "^1.0.30001750",
},
"devDependencies": {
-
"@types/bun": "^1.2.4",
-
"typescript": "~5.7.2",
-
"vite": "^6.1.0",
-
"vite-plugin-pwa": "^0.21.1",
+
"@types/bun": "^1.2.20",
+
"typescript": "~5.7.3",
+
"vite": "^6.3.5",
+
"vite-plugin-pwa": "^0.21.2",
},
},
},
···
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="],
-
"@fontsource/inter": ["@fontsource/inter@5.2.6", "", {}, "sha512-CZs9S1CrjD0jPwsNy9W6j0BhsmRSQrgwlTNkgQXTsAeDRM42LBRLo3eo9gCzfH4GvV7zpyf78Ozfl773826csw=="],
-
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
···
"@surma/rollup-plugin-off-main-thread": ["@surma/rollup-plugin-off-main-thread@2.2.3", "", { "dependencies": { "ejs": "^3.1.6", "json5": "^2.2.0", "magic-string": "^0.25.0", "string.prototype.matchall": "^4.0.6" } }, "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ=="],
-
"@types/bun": ["@types/bun@1.2.20", "", { "dependencies": { "bun-types": "1.2.20" } }, "sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA=="],
+
"@types/bun": ["@types/bun@1.3.0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
···
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
-
"bun-types": ["bun-types@1.2.20", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA=="],
+
"bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
···
"call-bound": ["call-bound@1.0.3", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "get-intrinsic": "^1.2.6" } }, "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA=="],
-
"caniuse-lite": ["caniuse-lite@1.0.30001701", "", {}, "sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw=="],
+
"caniuse-lite": ["caniuse-lite@1.0.30001750", "", {}, "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
···
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
-
"vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
+
"vite": ["vite@6.3.6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA=="],
"vite-plugin-pwa": ["vite-plugin-pwa@0.21.2", "", { "dependencies": { "debug": "^4.3.6", "pretty-bytes": "^6.1.1", "tinyglobby": "^0.2.10", "workbox-build": "^7.3.0", "workbox-window": "^7.3.0" }, "peerDependencies": { "@vite-pwa/assets-generator": "^0.2.6", "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@vite-pwa/assets-generator"] }, "sha512-vFhH6Waw8itNu37hWUJxL50q+CBbNcMVzsKaYHQVrfxTt3ihk3PeLO22SbiP1UNWzcEPaTQv+YVxe4G0KOjAkg=="],
···
"@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"@rollup/pluginutils/rollup": ["rollup@2.79.2", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ=="],
+
+
"browserslist/caniuse-lite": ["caniuse-lite@1.0.30001701", "", {}, "sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw=="],
"filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
+47 -1
index.html
···
href="/opensearch.xml"
/>
<style>
+
/* Font fallback that closely matches Inter metrics */
+
@font-face {
+
font-family: "Inter Fallback";
+
size-adjust: 107%;
+
ascent-override: 90%;
+
src: local("Arial");
+
font-display: swap;
+
}
+
:root {
+
font-family:
+
Inter,
+
"Inter Fallback",
+
system-ui,
+
-apple-system,
+
BlinkMacSystemFont,
+
"Segoe UI",
+
Roboto,
+
Oxygen,
+
Ubuntu,
+
Cantarell,
+
"Open Sans",
+
"Helvetica Neue",
+
sans-serif;
+
font-synthesis: none;
+
text-rendering: optimizeLegibility;
+
-webkit-font-smoothing: antialiased;
+
-moz-osx-font-smoothing: grayscale;
+
/* Light mode colors */
--text-color: #1a1a1a;
--text-color-secondary: #666;
···
--bg-color-secondary: #f5f5f5;
--bg-color-hover: #f0f0f0;
--bg-color-active: #e5e5e5;
+
--bg-color-danger: #e9808a;
--border-color: #ddd;
}
···
--bg-color-secondary: #1e1e1e;
--bg-color-hover: #2a2a2a;
--bg-color-active: #333;
+
--bg-color-danger: #f15f6d;
--border-color: #444;
}
}
···
margin: 0;
padding: 0;
box-sizing: border-box;
+
outline: none;
+
}
+
*:focus {
+
outline: 2px solid var(--text-color-secondary);
+
}
+
+
html, body {
+
height: 100%;
+
width: 100%;
}
body {
-
font-family: system-ui, sans-serif;
line-height: 1.5;
+
font-weight: 400;
+
font-size: 16px;
color: var(--text-color);
background-color: var(--bg-color);
}
+
#app {
+
min-height: 100vh;
+
background-color: var(--bg-color);
+
}
+
input {
+
margin: 2px 0px !important;
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 4px;
+20 -20
package.json
···
{
-
"name": "unduck",
-
"private": true,
-
"version": "0.0.0",
-
"type": "module",
-
"scripts": {
-
"dev": "bunx --bun vite",
-
"build": "bunx --bun vite build",
-
"preview": "bunx --bun vite preview",
-
"hash": "bun run src/bangs/hashbanggen.ts",
-
"check": "bun run src/bangs/test-bangs.ts"
-
},
-
"devDependencies": {
-
"typescript": "~5.7.3",
-
"vite": "^6.3.5",
-
"@types/bun": "^1.2.20",
-
"vite-plugin-pwa": "^0.21.2"
-
},
-
"dependencies": {
-
"@fontsource/inter": "^5.2.6"
-
}
+
"name": "unduckified",
+
"private": true,
+
"version": "0.3.0",
+
"type": "module",
+
"scripts": {
+
"dev": "bunx --bun vite",
+
"build": "bunx --bun vite build",
+
"preview": "bunx --bun vite preview",
+
"hash": "bun run src/bangs/hashbanggen.ts",
+
"check": "bun run src/bangs/test-bangs.ts"
+
},
+
"devDependencies": {
+
"typescript": "~5.7.3",
+
"vite": "^6.3.6",
+
"@types/bun": "^1.3.0",
+
"vite-plugin-pwa": "^0.21.2"
+
},
+
"dependencies": {
+
"caniuse-lite": "^1.0.30001750"
+
}
}
public/goose.gif

This is a binary file and will not be displayed.

-11
src/global.css
···
-
/* Font fallback that closely matches Inter metrics */
-
@font-face {
-
font-family: "Inter Fallback";
-
size-adjust: 107%;
-
ascent-override: 90%;
-
src: local("Arial");
-
}
-
:root {
font-family:
-
Inter,
-
"Inter Fallback",
system-ui,
-apple-system,
BlinkMacSystemFont,
···
Oxygen,
Ubuntu,
Cantarell,
-
"Open Sans",
"Helvetica Neue",
sans-serif;
font-synthesis: none;
+24 -23
src/main.ts
···
+
import "./global.css";
import { bangs } from "./bangs/hashbang.ts";
import {
addToSearchHistory,
···
storage,
} from "./libs.ts";
-
import "@fontsource/inter/latin-400.css";
-
import "@fontsource/inter/latin-500.css";
-
import "@fontsource/inter/latin-600.css";
-
import "@fontsource/inter/latin-700.css";
-
import "./global.css";
import notFoundPageRender from "./404.ts";
export const CONSTANTS = {
···
return null;
}
-
const count = (
-
Number.parseInt(
-
storage.get(CONSTANTS.LOCAL_STORAGE_KEYS.SEARCH_COUNT) || "0",
-
) + 1
-
).toString();
-
storage.set(CONSTANTS.LOCAL_STORAGE_KEYS.SEARCH_COUNT, count);
-
const match = query.toLowerCase().match(/^!(\S+)|!(\S+)$/i);
const selectedBang = match
? customBangs[match[1] || match[2]] || bangs[match[1] || match[2]]
···
return ensureProtocol(selectedBang.d);
}
-
if (
-
storage.get(CONSTANTS.LOCAL_STORAGE_KEYS.HISTORY_ENABLED) === "true"
-
) {
-
addToSearchHistory(cleanQuery, {
-
bang: selectedBang?.t || "",
-
name: selectedBang?.s || "",
-
url: selectedBang?.u || "",
-
});
-
}
-
-
return selectedBang?.u.replace(
+
const redirectUrl = selectedBang?.u.replace(
"{{{s}}}",
encodeURIComponent(cleanQuery).replace(/%2F/g, "/"),
);
+
+
// Do these operations after determining redirect URL to minimize delay
+
setTimeout(() => {
+
const count = (
+
Number.parseInt(
+
storage.get(CONSTANTS.LOCAL_STORAGE_KEYS.SEARCH_COUNT) || "0",
+
) + 1
+
).toString();
+
storage.set(CONSTANTS.LOCAL_STORAGE_KEYS.SEARCH_COUNT, count);
+
+
if (
+
storage.get(CONSTANTS.LOCAL_STORAGE_KEYS.HISTORY_ENABLED) === "true"
+
) {
+
addToSearchHistory(cleanQuery, {
+
bang: selectedBang?.t || "",
+
name: selectedBang?.s || "",
+
url: selectedBang?.u || "",
+
});
+
}
+
}, 0);
+
+
return redirectUrl;
}
default:
notFoundPageRender();
+1 -1
vite.config.ts
···
VitePWA({
registerType: "autoUpdate",
workbox: {
-
globPatterns: ["**/*.{js,css,html}", "assets/inter*.woff2"],
+
globPatterns: ["**/*.{js,css,html}"],
maximumFileSizeToCacheInBytes: 3 * 1048576,
},
}),