website
git clone https://git.pyrossh.dev/website
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
src/_helpers/fileIcons.js
import iconSet from "@iconify-json/vscode-icons/icons.json" with { type: "json" };
// The old Astro version resolved per-extension file/folder icons from the
// full vscode-icons manifest (see git history at 7325531^:src/utils/files.ts).
// That manifest is itself a large VS Code extension repo installed as a git
// dependency — overkill for a static build. This is a curated subset of the
// same @iconify-json/vscode-icons icon set (already used to render both),
// covering the extensions that actually show up in these repos, with a
// generic fallback for anything else.
const FILENAME_TO_ICON = {
"cargo.toml": "file-type-cargo",
"cargo.lock": "file-type-cargo",
"license": "file-type-license",
"license.md": "file-type-license",
".gitignore": "file-type-git",
".gitattributes": "file-type-git",
".npmignore": "file-type-npm",
"package.json": "file-type-npm",
"package-lock.json": "file-type-npm",
"bun.lock": "file-type-npm",
"tsconfig.json": "file-type-typescript",
};
const EXT_TO_ICON = {
rs: "file-type-rust",
toml: "file-type-toml",
json: "file-type-json",
jsonc: "file-type-json",
md: "file-type-markdown",
mdx: "file-type-mdx",
css: "file-type-css",
html: "file-type-html",
js: "file-type-js",
mjs: "file-type-js",
jsx: "file-type-reactjs",
ts: "file-type-typescript",
tsx: "file-type-reactts",
zig: "file-type-zig",
svg: "file-type-svg",
png: "file-type-image",
jpg: "file-type-image",
jpeg: "file-type-image",
gif: "file-type-image",
webp: "file-type-webp",
pdf: "file-type-pdf2",
txt: "file-type-text",
sh: "file-type-shell",
py: "file-type-python",
kt: "file-type-kotlin",
java: "file-type-java",
go: "file-type-go",
c: "file-type-c",
h: "file-type-cheader",
yml: "file-type-yaml",
yaml: "file-type-yaml",
};
const FOLDER_TO_ICON = {
src: "folder-type-src",
test: "folder-type-test",
tests: "folder-type-test",
public: "folder-type-public",
images: "folder-type-images",
docs: "folder-type-docs",
dist: "folder-type-dist",
".github": "folder-type-github",
node_modules: "folder-type-node",
};
// Every icon id this module can ever emit, deduped — used to build the
// sprite once rather than guessing which subset a given page needs.
const ICON_NAMES = new Set([
...Object.values(FILENAME_TO_ICON),
...Object.values(EXT_TO_ICON),
...Object.values(FOLDER_TO_ICON),
"default-file",
"default-folder",
]);
/**
* A <svg><symbol> sprite holding every file/folder icon this repo browser
* can use, written once to assets/icons/sprite.svg (see eleventy.config.js)
* rather than inlined per page. fileIcon()/folderIcon() emit a tiny <use>
* that points at that shared file, so the ~30 icon bodies are fetched
* (and cached by the browser) once for the whole site instead of being
* duplicated in every one of the thousands of generated repo pages.
*/
export const iconSpriteDefs = () => {
const symbols = [...ICON_NAMES]
.map((name) => {
const icon = iconSet.icons[name];
return `<symbol id="icon-${name}" viewBox="0 0 ${iconSet.width} ${iconSet.height}">${icon.body}</symbol>`;
})
.join("");
return `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">${symbols}</svg>`;
};
const useIcon = (name) => `<svg width="16" height="16"><use href="/assets/icons/sprite.svg#icon-${name}"></use></svg>`;
export const fileIcon = (filename, ext) => {
const key = FILENAME_TO_ICON[filename.toLowerCase()] ?? EXT_TO_ICON[ext] ?? "default-file";
return useIcon(key);
};
export const folderIcon = (foldername) => {
const key = FOLDER_TO_ICON[foldername.toLowerCase()] ?? "default-folder";
return useIcon(key);
};