From aa1c25ccb1fad7f598bdbf43446e4f5c1db841bc Mon Sep 17 00:00:00 2001 From: Vordgi Date: Tue, 10 Feb 2026 18:36:56 +0000 Subject: [PATCH 1/5] feat: generate sprite for file view --- .gitignore | 1 + app/components/Code/DirectoryListing.vue | 25 +- app/components/Code/FileTree.vue | 28 +- app/utils/file-icons.ts | 495 ++++++++++++----------- generate-file-tree-sprite.ts | 99 +++++ package.json | 3 +- 6 files changed, 390 insertions(+), 261 deletions(-) create mode 100644 generate-file-tree-sprite.ts diff --git a/.gitignore b/.gitignore index 0b1d74f52..99e727c21 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ test-results/ # generated files shared/types/lexicons +file-tree-sprite.svg **/__screenshots__/** diff --git a/app/components/Code/DirectoryListing.vue b/app/components/Code/DirectoryListing.vue index 95e894a1e..bd69f3c99 100644 --- a/app/components/Code/DirectoryListing.vue +++ b/app/components/Code/DirectoryListing.vue @@ -80,8 +80,15 @@ const bytesFormatter = useBytesFormatter() :to="getCodeRoute(parentPath || undefined)" class="py-2 px-4 font-mono text-sm w-full" no-underline - classicon="i-carbon:folder text-yellow-600" > + .. @@ -98,12 +105,18 @@ const bytesFormatter = useBytesFormatter() :to="getCodeRoute(node.path)" class="py-2 px-4 font-mono text-sm w-full" no-underline - :classicon=" - node.type === 'directory' - ? 'i-carbon:folder text-yellow-600' - : getFileIcon(node.name) - " > + {{ node.name }} - + {{ node.name }} + {{ node.name }} diff --git a/app/utils/file-icons.ts b/app/utils/file-icons.ts index 0c465c4ed..9377cdd92 100644 --- a/app/utils/file-icons.ts +++ b/app/utils/file-icons.ts @@ -5,310 +5,315 @@ // Extension to icon mapping // @unocss-include -const EXTENSION_ICONS: Record = { +export const EXTENSION_ICONS: Record = { // JavaScript/TypeScript - 'js': 'i-vscode-icons-file-type-js-official', - 'mjs': 'i-vscode-icons-file-type-js-official', - 'cjs': 'i-vscode-icons-file-type-js-official', - 'ts': 'i-vscode-icons-file-type-typescript-official', - 'mts': 'i-vscode-icons-file-type-typescript-official', - 'cts': 'i-vscode-icons-file-type-typescript-official', - 'jsx': 'i-vscode-icons-file-type-reactjs', - 'tsx': 'i-vscode-icons-file-type-reactts', + 'js': 'vscode-icons-file-type-js-official', + 'mjs': 'vscode-icons-file-type-js-official', + 'cjs': 'vscode-icons-file-type-js-official', + 'ts': 'vscode-icons-file-type-typescript-official', + 'mts': 'vscode-icons-file-type-typescript-official', + 'cts': 'vscode-icons-file-type-typescript-official', + 'jsx': 'vscode-icons-file-type-reactjs', + 'tsx': 'vscode-icons-file-type-reactts', // Web - 'html': 'i-vscode-icons-file-type-html', - 'htm': 'i-vscode-icons-file-type-html', - 'css': 'i-vscode-icons-file-type-css', - 'scss': 'i-vscode-icons-file-type-scss', - 'sass': 'i-vscode-icons-file-type-sass', - 'less': 'i-vscode-icons-file-type-less', - 'styl': 'i-vscode-icons-file-type-stylus', - 'vue': 'i-vscode-icons-file-type-vue', - 'svelte': 'i-vscode-icons-file-type-svelte', - 'astro': 'i-vscode-icons-file-type-astro', - 'gjs': 'i-vscode-icons-file-type-glimmer', - 'gts': 'i-vscode-icons-file-type-glimmer', + 'html': 'vscode-icons-file-type-html', + 'htm': 'vscode-icons-file-type-html', + 'css': 'vscode-icons-file-type-css', + 'scss': 'vscode-icons-file-type-scss', + 'sass': 'vscode-icons-file-type-sass', + 'less': 'vscode-icons-file-type-less', + 'styl': 'vscode-icons-file-type-stylus', + 'vue': 'vscode-icons-file-type-vue', + 'svelte': 'vscode-icons-file-type-svelte', + 'astro': 'vscode-icons-file-type-astro', + 'gjs': 'vscode-icons-file-type-glimmer', + 'gts': 'vscode-icons-file-type-glimmer', // Config/Data - 'json': 'i-vscode-icons-file-type-json', - 'jsonc': 'i-vscode-icons-file-type-json', - 'json5': 'i-vscode-icons-file-type-json5', - 'yaml': 'i-vscode-icons-file-type-yaml', - 'yml': 'i-vscode-icons-file-type-yaml', - 'toml': 'i-vscode-icons-file-type-toml', - 'xml': 'i-vscode-icons-file-type-xml', - 'svg': 'i-vscode-icons-file-type-svg', - 'graphql': 'i-vscode-icons-file-type-graphql', - 'gql': 'i-vscode-icons-file-type-graphql', - 'prisma': 'i-vscode-icons-file-type-prisma', + 'json': 'vscode-icons-file-type-json', + 'jsonc': 'vscode-icons-file-type-json', + 'json5': 'vscode-icons-file-type-json5', + 'yaml': 'vscode-icons-file-type-yaml', + 'yml': 'vscode-icons-file-type-yaml', + 'toml': 'vscode-icons-file-type-toml', + 'xml': 'vscode-icons-file-type-xml', + 'svg': 'vscode-icons-file-type-svg', + 'graphql': 'vscode-icons-file-type-graphql', + 'gql': 'vscode-icons-file-type-graphql', + 'prisma': 'vscode-icons-file-type-prisma', // Documentation - 'md': 'i-vscode-icons-file-type-markdown', - 'mdx': 'i-vscode-icons-file-type-mdx', - 'txt': 'i-vscode-icons-file-type-text', - 'rst': 'i-vscode-icons-file-type-text', - 'pdf': 'i-vscode-icons-file-type-pdf2', + 'md': 'vscode-icons-file-type-markdown', + 'mdx': 'vscode-icons-file-type-mdx', + 'txt': 'vscode-icons-file-type-text', + 'rst': 'vscode-icons-file-type-text', + 'pdf': 'vscode-icons-file-type-pdf2', // Shell/Scripts - 'sh': 'i-vscode-icons-file-type-shell', - 'bash': 'i-vscode-icons-file-type-shell', - 'zsh': 'i-vscode-icons-file-type-shell', - 'fish': 'i-vscode-icons-file-type-shell', - 'ps1': 'i-vscode-icons-file-type-powershell', - 'bat': 'i-vscode-icons-file-type-bat', - 'cmd': 'i-vscode-icons-file-type-bat', + 'sh': 'vscode-icons-file-type-shell', + 'bash': 'vscode-icons-file-type-shell', + 'zsh': 'vscode-icons-file-type-shell', + 'fish': 'vscode-icons-file-type-shell', + 'ps1': 'vscode-icons-file-type-powershell', + 'bat': 'vscode-icons-file-type-bat', + 'cmd': 'vscode-icons-file-type-bat', // Programming languages - 'py': 'i-vscode-icons-file-type-python', - 'pyi': 'i-vscode-icons-file-type-python', - 'rb': 'i-vscode-icons-file-type-ruby', - 'go': 'i-vscode-icons-file-type-go', - 'rs': 'i-vscode-icons-file-type-rust', - 'java': 'i-vscode-icons-file-type-java', - 'kt': 'i-vscode-icons-file-type-kotlin', - 'swift': 'i-vscode-icons-file-type-swift', - 'c': 'i-vscode-icons-file-type-c', - 'cpp': 'i-vscode-icons-file-type-cpp', - 'h': 'i-vscode-icons-file-type-cheader', - 'hpp': 'i-vscode-icons-file-type-cppheader', - 'cs': 'i-vscode-icons-file-type-csharp', - 'php': 'i-vscode-icons-file-type-php', - 'lua': 'i-vscode-icons-file-type-lua', - 'r': 'i-vscode-icons-file-type-r', - 'sql': 'i-vscode-icons-file-type-sql', - 'pl': 'i-vscode-icons-file-type-perl', - 'ex': 'i-vscode-icons-file-type-elixir', - 'exs': 'i-vscode-icons-file-type-elixir', - 'erl': 'i-vscode-icons-file-type-erlang', - 'hs': 'i-vscode-icons-file-type-haskell', - 'clj': 'i-vscode-icons-file-type-clojure', - 'scala': 'i-vscode-icons-file-type-scala', - 'zig': 'i-vscode-icons-file-type-zig', - 'nim': 'i-vscode-icons-file-type-nim', - 'v': 'i-vscode-icons-file-type-vlang', - 'wasm': 'i-vscode-icons-file-type-wasm', + 'py': 'vscode-icons-file-type-python', + 'pyi': 'vscode-icons-file-type-python', + 'rb': 'vscode-icons-file-type-ruby', + 'go': 'vscode-icons-file-type-go', + 'rs': 'vscode-icons-file-type-rust', + 'java': 'vscode-icons-file-type-java', + 'kt': 'vscode-icons-file-type-kotlin', + 'swift': 'vscode-icons-file-type-swift', + 'c': 'vscode-icons-file-type-c', + 'cpp': 'vscode-icons-file-type-cpp', + 'h': 'vscode-icons-file-type-cheader', + 'hpp': 'vscode-icons-file-type-cppheader', + 'cs': 'vscode-icons-file-type-csharp', + 'php': 'vscode-icons-file-type-php', + 'lua': 'vscode-icons-file-type-lua', + 'r': 'vscode-icons-file-type-r', + 'sql': 'vscode-icons-file-type-sql', + 'pl': 'vscode-icons-file-type-perl', + 'ex': 'vscode-icons-file-type-elixir', + 'exs': 'vscode-icons-file-type-elixir', + 'erl': 'vscode-icons-file-type-erlang', + 'hs': 'vscode-icons-file-type-haskell', + 'clj': 'vscode-icons-file-type-clojure', + 'scala': 'vscode-icons-file-type-scala', + 'zig': 'vscode-icons-file-type-zig', + 'nim': 'vscode-icons-file-type-nim', + 'v': 'vscode-icons-file-type-vlang', + 'wasm': 'vscode-icons-file-type-wasm', // Images - 'png': 'i-vscode-icons-file-type-image', - 'jpg': 'i-vscode-icons-file-type-image', - 'jpeg': 'i-vscode-icons-file-type-image', - 'gif': 'i-vscode-icons-file-type-image', - 'webp': 'i-vscode-icons-file-type-image', - 'ico': 'i-vscode-icons-file-type-image', - 'bmp': 'i-vscode-icons-file-type-image', + 'png': 'vscode-icons-file-type-image', + 'jpg': 'vscode-icons-file-type-image', + 'jpeg': 'vscode-icons-file-type-image', + 'gif': 'vscode-icons-file-type-image', + 'webp': 'vscode-icons-file-type-image', + 'ico': 'vscode-icons-file-type-image', + 'bmp': 'vscode-icons-file-type-image', // Fonts - 'woff': 'i-vscode-icons-file-type-font', - 'woff2': 'i-vscode-icons-file-type-font', - 'ttf': 'i-vscode-icons-file-type-font', - 'otf': 'i-vscode-icons-file-type-font', - 'eot': 'i-vscode-icons-file-type-font', + 'woff': 'vscode-icons-file-type-font', + 'woff2': 'vscode-icons-file-type-font', + 'ttf': 'vscode-icons-file-type-font', + 'otf': 'vscode-icons-file-type-font', + 'eot': 'vscode-icons-file-type-font', // Archives - 'zip': 'i-vscode-icons-file-type-zip', - 'tar': 'i-vscode-icons-file-type-zip', - 'gz': 'i-vscode-icons-file-type-zip', - 'tgz': 'i-vscode-icons-file-type-zip', - 'bz2': 'i-vscode-icons-file-type-zip', - '7z': 'i-vscode-icons-file-type-zip', - 'rar': 'i-vscode-icons-file-type-zip', + 'zip': 'vscode-icons-file-type-zip', + 'tar': 'vscode-icons-file-type-zip', + 'gz': 'vscode-icons-file-type-zip', + 'tgz': 'vscode-icons-file-type-zip', + 'bz2': 'vscode-icons-file-type-zip', + '7z': 'vscode-icons-file-type-zip', + 'rar': 'vscode-icons-file-type-zip', // Certificates/Keys - 'pem': 'i-vscode-icons-file-type-cert', - 'crt': 'i-vscode-icons-file-type-cert', - 'key': 'i-vscode-icons-file-type-key', + 'pem': 'vscode-icons-file-type-cert', + 'crt': 'vscode-icons-file-type-cert', + 'key': 'vscode-icons-file-type-key', // Diff/Patch - 'diff': 'i-vscode-icons-file-type-diff', - 'patch': 'i-vscode-icons-file-type-diff', + 'diff': 'vscode-icons-file-type-diff', + 'patch': 'vscode-icons-file-type-diff', // Other - 'log': 'i-vscode-icons-file-type-log', - 'lock': 'i-vscode-icons-file-type-json', - 'map': 'i-vscode-icons-file-type-map', - 'wrl': 'i-vscode-icons-file-type-binary', - 'bin': 'i-vscode-icons-file-type-binary', - 'node': 'i-vscode-icons-file-type-node', + 'log': 'vscode-icons-file-type-log', + 'lock': 'vscode-icons-file-type-json', + 'map': 'vscode-icons-file-type-map', + 'wrl': 'vscode-icons-file-type-binary', + 'bin': 'vscode-icons-file-type-binary', + 'node': 'vscode-icons-file-type-node', } // Special filenames that have specific icons -const FILENAME_ICONS: Record = { +export const FILENAME_ICONS: Record = { // Package managers - 'package.json': 'i-vscode-icons-file-type-npm', - 'package-lock.json': 'i-vscode-icons-file-type-npm', - 'pnpm-lock.yaml': 'i-vscode-icons-file-type-pnpm', - 'pnpm-workspace.yaml': 'i-vscode-icons-file-type-pnpm', - 'yarn.lock': 'i-vscode-icons-file-type-yarn', - '.yarnrc': 'i-vscode-icons-file-type-yarn', - '.yarnrc.yml': 'i-vscode-icons-file-type-yarn', - 'bun.lockb': 'i-vscode-icons-file-type-bun', - 'bunfig.toml': 'i-vscode-icons-file-type-bun', - 'deno.json': 'i-vscode-icons-file-type-deno', - 'deno.jsonc': 'i-vscode-icons-file-type-deno', + 'package.json': 'vscode-icons-file-type-npm', + 'package-lock.json': 'vscode-icons-file-type-npm', + 'pnpm-lock.yaml': 'vscode-icons-file-type-pnpm', + 'pnpm-workspace.yaml': 'vscode-icons-file-type-pnpm', + 'yarn.lock': 'vscode-icons-file-type-yarn', + '.yarnrc': 'vscode-icons-file-type-yarn', + '.yarnrc.yml': 'vscode-icons-file-type-yarn', + 'bun.lockb': 'vscode-icons-file-type-bun', + 'bunfig.toml': 'vscode-icons-file-type-bun', + 'deno.json': 'vscode-icons-file-type-deno', + 'deno.jsonc': 'vscode-icons-file-type-deno', // TypeScript configs - 'tsconfig.json': 'i-vscode-icons-file-type-tsconfig', - 'tsconfig.base.json': 'i-vscode-icons-file-type-tsconfig', - 'tsconfig.build.json': 'i-vscode-icons-file-type-tsconfig', - 'tsconfig.node.json': 'i-vscode-icons-file-type-tsconfig', - 'jsconfig.json': 'i-vscode-icons-file-type-jsconfig', + 'tsconfig.json': 'vscode-icons-file-type-tsconfig', + 'tsconfig.base.json': 'vscode-icons-file-type-tsconfig', + 'tsconfig.build.json': 'vscode-icons-file-type-tsconfig', + 'tsconfig.node.json': 'vscode-icons-file-type-tsconfig', + 'jsconfig.json': 'vscode-icons-file-type-jsconfig', // Build tools - 'vite.config.ts': 'i-vscode-icons-file-type-vite', - 'vite.config.js': 'i-vscode-icons-file-type-vite', - 'vite.config.mts': 'i-vscode-icons-file-type-vite', - 'vite.config.mjs': 'i-vscode-icons-file-type-vite', - 'webpack.config.js': 'i-vscode-icons-file-type-webpack', - 'webpack.config.ts': 'i-vscode-icons-file-type-webpack', - 'rollup.config.js': 'i-vscode-icons-file-type-rollup', - 'rollup.config.ts': 'i-vscode-icons-file-type-rollup', - 'rollup.config.mjs': 'i-vscode-icons-file-type-rollup', - 'esbuild.config.js': 'i-vscode-icons-file-type-esbuild', - 'turbo.json': 'i-vscode-icons-file-type-turbo', - 'nx.json': 'i-vscode-icons-file-type-nx', + 'vite.config.ts': 'vscode-icons-file-type-vite', + 'vite.config.js': 'vscode-icons-file-type-vite', + 'vite.config.mts': 'vscode-icons-file-type-vite', + 'vite.config.mjs': 'vscode-icons-file-type-vite', + 'webpack.config.js': 'vscode-icons-file-type-webpack', + 'webpack.config.ts': 'vscode-icons-file-type-webpack', + 'rollup.config.js': 'vscode-icons-file-type-rollup', + 'rollup.config.ts': 'vscode-icons-file-type-rollup', + 'rollup.config.mjs': 'vscode-icons-file-type-rollup', + 'esbuild.config.js': 'vscode-icons-file-type-esbuild', + 'turbo.json': 'vscode-icons-file-type-turbo', + 'nx.json': 'vscode-icons-file-type-nx', // Framework configs - 'nuxt.config.ts': 'i-vscode-icons-file-type-nuxt', - 'nuxt.config.js': 'i-vscode-icons-file-type-nuxt', - 'next.config.js': 'i-vscode-icons-file-type-next', - 'next.config.mjs': 'i-vscode-icons-file-type-next', - 'next.config.ts': 'i-vscode-icons-file-type-next', - 'svelte.config.js': 'i-vscode-icons-file-type-svelte', - 'astro.config.mjs': 'i-vscode-icons-file-type-astro', - 'astro.config.ts': 'i-vscode-icons-file-type-astro', - 'remix.config.js': 'i-vscode-icons-file-type-js-official', - 'angular.json': 'i-vscode-icons-file-type-angular', - 'nest-cli.json': 'i-vscode-icons-file-type-nestjs', + 'nuxt.config.ts': 'vscode-icons-file-type-nuxt', + 'nuxt.config.js': 'vscode-icons-file-type-nuxt', + 'next.config.js': 'vscode-icons-file-type-next', + 'next.config.mjs': 'vscode-icons-file-type-next', + 'next.config.ts': 'vscode-icons-file-type-next', + 'svelte.config.js': 'vscode-icons-file-type-svelte', + 'astro.config.mjs': 'vscode-icons-file-type-astro', + 'astro.config.ts': 'vscode-icons-file-type-astro', + 'remix.config.js': 'vscode-icons-file-type-js-official', + 'angular.json': 'vscode-icons-file-type-angular', + 'nest-cli.json': 'vscode-icons-file-type-nestjs', // Linting/Formatting - '.eslintrc': 'i-vscode-icons-file-type-eslint', - '.eslintrc.js': 'i-vscode-icons-file-type-eslint', - '.eslintrc.cjs': 'i-vscode-icons-file-type-eslint', - '.eslintrc.json': 'i-vscode-icons-file-type-eslint', - '.eslintrc.yml': 'i-vscode-icons-file-type-eslint', - 'eslint.config.js': 'i-vscode-icons-file-type-eslint', - 'eslint.config.mjs': 'i-vscode-icons-file-type-eslint', - 'eslint.config.ts': 'i-vscode-icons-file-type-eslint', - '.prettierrc': 'i-vscode-icons-file-type-prettier', - '.prettierrc.js': 'i-vscode-icons-file-type-prettier', - '.prettierrc.json': 'i-vscode-icons-file-type-prettier', - 'prettier.config.js': 'i-vscode-icons-file-type-prettier', - 'prettier.config.mjs': 'i-vscode-icons-file-type-prettier', - '.prettierignore': 'i-vscode-icons-file-type-prettier', - 'biome.json': 'i-vscode-icons-file-type-biome', - '.stylelintrc': 'i-vscode-icons-file-type-stylelint', - '.stylelintrc.json': 'i-vscode-icons-file-type-stylelint', + '.eslintrc': 'vscode-icons-file-type-eslint', + '.eslintrc.js': 'vscode-icons-file-type-eslint', + '.eslintrc.cjs': 'vscode-icons-file-type-eslint', + '.eslintrc.json': 'vscode-icons-file-type-eslint', + '.eslintrc.yml': 'vscode-icons-file-type-eslint', + 'eslint.config.js': 'vscode-icons-file-type-eslint', + 'eslint.config.mjs': 'vscode-icons-file-type-eslint', + 'eslint.config.ts': 'vscode-icons-file-type-eslint', + '.prettierrc': 'vscode-icons-file-type-prettier', + '.prettierrc.js': 'vscode-icons-file-type-prettier', + '.prettierrc.json': 'vscode-icons-file-type-prettier', + 'prettier.config.js': 'vscode-icons-file-type-prettier', + 'prettier.config.mjs': 'vscode-icons-file-type-prettier', + '.prettierignore': 'vscode-icons-file-type-prettier', + 'biome.json': 'vscode-icons-file-type-biome', + '.stylelintrc': 'vscode-icons-file-type-stylelint', + '.stylelintrc.json': 'vscode-icons-file-type-stylelint', // Testing - 'jest.config.js': 'i-vscode-icons-file-type-jest', - 'jest.config.ts': 'i-vscode-icons-file-type-jest', - 'vitest.config.ts': 'i-vscode-icons-file-type-vitest', - 'vitest.config.js': 'i-vscode-icons-file-type-vitest', - 'vitest.config.mts': 'i-vscode-icons-file-type-vitest', - 'playwright.config.ts': 'i-vscode-icons-file-type-playwright', - 'playwright.config.js': 'i-vscode-icons-file-type-playwright', - 'cypress.config.ts': 'i-vscode-icons-file-type-cypress', - 'cypress.config.js': 'i-vscode-icons-file-type-cypress', + 'jest.config.js': 'vscode-icons-file-type-jest', + 'jest.config.ts': 'vscode-icons-file-type-jest', + 'vitest.config.ts': 'vscode-icons-file-type-vitest', + 'vitest.config.js': 'vscode-icons-file-type-vitest', + 'vitest.config.mts': 'vscode-icons-file-type-vitest', + 'playwright.config.ts': 'vscode-icons-file-type-playwright', + 'playwright.config.js': 'vscode-icons-file-type-playwright', + 'cypress.config.ts': 'vscode-icons-file-type-cypress', + 'cypress.config.js': 'vscode-icons-file-type-cypress', // Git - '.gitignore': 'i-vscode-icons-file-type-git', - '.gitattributes': 'i-vscode-icons-file-type-git', - '.gitmodules': 'i-vscode-icons-file-type-git', - '.gitkeep': 'i-vscode-icons-file-type-git', + '.gitignore': 'vscode-icons-file-type-git', + '.gitattributes': 'vscode-icons-file-type-git', + '.gitmodules': 'vscode-icons-file-type-git', + '.gitkeep': 'vscode-icons-file-type-git', // CI/CD - '.travis.yml': 'i-vscode-icons-file-type-travis', - '.gitlab-ci.yml': 'i-vscode-icons-file-type-gitlab', - 'Jenkinsfile': 'i-vscode-icons-file-type-jenkins', - 'azure-pipelines.yml': 'i-vscode-icons-file-type-azurepipelines', - 'cloudbuild.yaml': 'i-vscode-icons-file-type-yaml', - 'vercel.json': 'i-vscode-icons-file-type-vercel', - 'netlify.toml': 'i-vscode-icons-file-type-netlify', + '.travis.yml': 'vscode-icons-file-type-travis', + '.gitlab-ci.yml': 'vscode-icons-file-type-gitlab', + 'Jenkinsfile': 'vscode-icons-file-type-jenkins', + 'azure-pipelines.yml': 'vscode-icons-file-type-azurepipelines', + 'cloudbuild.yaml': 'vscode-icons-file-type-yaml', + 'vercel.json': 'vscode-icons-file-type-vercel', + 'netlify.toml': 'vscode-icons-file-type-netlify', // Docker - 'Dockerfile': 'i-vscode-icons-file-type-docker', - 'docker-compose.yml': 'i-vscode-icons-file-type-docker', - 'docker-compose.yaml': 'i-vscode-icons-file-type-docker', - '.dockerignore': 'i-vscode-icons-file-type-docker', + 'Dockerfile': 'vscode-icons-file-type-docker', + 'docker-compose.yml': 'vscode-icons-file-type-docker', + 'docker-compose.yaml': 'vscode-icons-file-type-docker', + '.dockerignore': 'vscode-icons-file-type-docker', // Environment - '.env': 'i-vscode-icons-file-type-dotenv', - '.env.local': 'i-vscode-icons-file-type-dotenv', - '.env.development': 'i-vscode-icons-file-type-dotenv', - '.env.production': 'i-vscode-icons-file-type-dotenv', - '.env.test': 'i-vscode-icons-file-type-dotenv', - '.env.example': 'i-vscode-icons-file-type-dotenv', + '.env': 'vscode-icons-file-type-dotenv', + '.env.local': 'vscode-icons-file-type-dotenv', + '.env.development': 'vscode-icons-file-type-dotenv', + '.env.production': 'vscode-icons-file-type-dotenv', + '.env.test': 'vscode-icons-file-type-dotenv', + '.env.example': 'vscode-icons-file-type-dotenv', // Editor configs - '.editorconfig': 'i-vscode-icons-file-type-editorconfig', - '.vscode': 'i-vscode-icons-file-type-vscode', - 'settings.json': 'i-vscode-icons-file-type-vscode', - 'launch.json': 'i-vscode-icons-file-type-vscode', - 'extensions.json': 'i-vscode-icons-file-type-vscode', + '.editorconfig': 'vscode-icons-file-type-editorconfig', + '.vscode': 'vscode-icons-file-type-vscode', + 'settings.json': 'vscode-icons-file-type-vscode', + 'launch.json': 'vscode-icons-file-type-vscode', + 'extensions.json': 'vscode-icons-file-type-vscode', // Documentation - 'README': 'i-vscode-icons-file-type-markdown', - 'README.md': 'i-vscode-icons-file-type-markdown', - 'readme.md': 'i-vscode-icons-file-type-markdown', - 'README.markdown': 'i-vscode-icons-file-type-markdown', - 'readme.markdown': 'i-vscode-icons-file-type-markdown', - 'CHANGELOG': 'i-vscode-icons-file-type-markdown', - 'CHANGELOG.md': 'i-vscode-icons-file-type-markdown', - 'changelog.md': 'i-vscode-icons-file-type-markdown', - 'CONTRIBUTING.md': 'i-vscode-icons-file-type-markdown', - 'contributing.md': 'i-vscode-icons-file-type-markdown', - 'CODE_OF_CONDUCT.md': 'i-vscode-icons-file-type-markdown', - 'LICENSE': 'i-vscode-icons-file-type-license', - 'LICENSE.md': 'i-vscode-icons-file-type-license', - 'LICENSE.txt': 'i-vscode-icons-file-type-license', - 'license': 'i-vscode-icons-file-type-license', - 'license.md': 'i-vscode-icons-file-type-license', - 'license.txt': 'i-vscode-icons-file-type-license', + 'README': 'vscode-icons-file-type-markdown', + 'README.md': 'vscode-icons-file-type-markdown', + 'readme.md': 'vscode-icons-file-type-markdown', + 'README.markdown': 'vscode-icons-file-type-markdown', + 'readme.markdown': 'vscode-icons-file-type-markdown', + 'CHANGELOG': 'vscode-icons-file-type-markdown', + 'CHANGELOG.md': 'vscode-icons-file-type-markdown', + 'changelog.md': 'vscode-icons-file-type-markdown', + 'CONTRIBUTING.md': 'vscode-icons-file-type-markdown', + 'contributing.md': 'vscode-icons-file-type-markdown', + 'CODE_OF_CONDUCT.md': 'vscode-icons-file-type-markdown', + 'LICENSE': 'vscode-icons-file-type-license', + 'LICENSE.md': 'vscode-icons-file-type-license', + 'LICENSE.txt': 'vscode-icons-file-type-license', + 'license': 'vscode-icons-file-type-license', + 'license.md': 'vscode-icons-file-type-license', + 'license.txt': 'vscode-icons-file-type-license', // Node - '.npmrc': 'i-vscode-icons-file-type-npm', - '.npmignore': 'i-vscode-icons-file-type-npm', - '.nvmrc': 'i-vscode-icons-file-type-node', - '.node-version': 'i-vscode-icons-file-type-node', + '.npmrc': 'vscode-icons-file-type-npm', + '.npmignore': 'vscode-icons-file-type-npm', + '.nvmrc': 'vscode-icons-file-type-node', + '.node-version': 'vscode-icons-file-type-node', // Misc - 'Makefile': 'i-vscode-icons-file-type-makefile', - '.browserslistrc': 'i-vscode-icons-file-type-browserslist', - 'browserslist': 'i-vscode-icons-file-type-browserslist', - '.babelrc': 'i-vscode-icons-file-type-babel', - 'babel.config.js': 'i-vscode-icons-file-type-babel', - 'tailwind.config.js': 'i-vscode-icons-file-type-tailwind', - 'tailwind.config.ts': 'i-vscode-icons-file-type-tailwind', - 'postcss.config.js': 'i-vscode-icons-file-type-postcss', - 'postcss.config.cjs': 'i-vscode-icons-file-type-postcss', - 'uno.config.ts': 'i-vscode-icons-file-type-unocss', - 'unocss.config.ts': 'i-vscode-icons-file-type-unocss', + 'Makefile': 'vscode-icons-file-type-makefile', + '.browserslistrc': 'vscode-icons-file-type-browserslist', + 'browserslist': 'vscode-icons-file-type-browserslist', + '.babelrc': 'vscode-icons-file-type-babel', + 'babel.config.js': 'vscode-icons-file-type-babel', + 'tailwind.config.js': 'vscode-icons-file-type-tailwind', + 'tailwind.config.ts': 'vscode-icons-file-type-tailwind', + 'postcss.config.js': 'vscode-icons-file-type-postcss', + 'postcss.config.cjs': 'vscode-icons-file-type-postcss', + 'uno.config.ts': 'vscode-icons-file-type-unocss', + 'unocss.config.ts': 'vscode-icons-file-type-unocss', } // Patterns for .d.ts and similar compound extensions -const COMPOUND_EXTENSIONS: Record = { - '.d.ts': 'i-vscode-icons-file-type-typescriptdef', - '.d.mts': 'i-vscode-icons-file-type-typescriptdef', - '.d.cts': 'i-vscode-icons-file-type-typescriptdef', - '.test.ts': 'i-vscode-icons-file-type-testts', - '.test.js': 'i-vscode-icons-file-type-testjs', - '.spec.ts': 'i-vscode-icons-file-type-testts', - '.spec.js': 'i-vscode-icons-file-type-testjs', - '.test.tsx': 'i-vscode-icons-file-type-testts', - '.test.jsx': 'i-vscode-icons-file-type-testjs', - '.spec.tsx': 'i-vscode-icons-file-type-testts', - '.spec.jsx': 'i-vscode-icons-file-type-testjs', - '.stories.tsx': 'i-vscode-icons-file-type-storybook', - '.stories.ts': 'i-vscode-icons-file-type-storybook', - '.stories.jsx': 'i-vscode-icons-file-type-storybook', - '.stories.js': 'i-vscode-icons-file-type-storybook', - '.min.js': 'i-vscode-icons-file-type-js-official', - '.min.css': 'i-vscode-icons-file-type-css', +export const COMPOUND_EXTENSIONS: Record = { + '.d.ts': 'vscode-icons-file-type-typescriptdef', + '.d.mts': 'vscode-icons-file-type-typescriptdef', + '.d.cts': 'vscode-icons-file-type-typescriptdef', + '.test.ts': 'vscode-icons-file-type-testts', + '.test.js': 'vscode-icons-file-type-testjs', + '.spec.ts': 'vscode-icons-file-type-testts', + '.spec.js': 'vscode-icons-file-type-testjs', + '.test.tsx': 'vscode-icons-file-type-testts', + '.test.jsx': 'vscode-icons-file-type-testjs', + '.spec.tsx': 'vscode-icons-file-type-testts', + '.spec.jsx': 'vscode-icons-file-type-testjs', + '.stories.tsx': 'vscode-icons-file-type-storybook', + '.stories.ts': 'vscode-icons-file-type-storybook', + '.stories.jsx': 'vscode-icons-file-type-storybook', + '.stories.js': 'vscode-icons-file-type-storybook', + '.min.js': 'vscode-icons-file-type-js-official', + '.min.css': 'vscode-icons-file-type-css', } // Default icon for unknown files -const DEFAULT_ICON = 'i-vscode-icons-default-file' +export const DEFAULT_ICON = 'vscode-icons-default-file' + +export const ADDITIONAL_ICONS = { + 'folder': 'carbon-folder', + 'folder-open': 'carbon-folder-open', +} /** * Get the icon class for a file based on its name diff --git a/generate-file-tree-sprite.ts b/generate-file-tree-sprite.ts new file mode 100644 index 000000000..26857b084 --- /dev/null +++ b/generate-file-tree-sprite.ts @@ -0,0 +1,99 @@ +import { promises as fs } from 'node:fs' +import path from 'node:path' +import type { IconifyJSON } from '@iconify-json/carbon' +import { fileURLToPath } from 'node:url' +import { + ADDITIONAL_ICONS, + EXTENSION_ICONS, + FILENAME_ICONS, + COMPOUND_EXTENSIONS, + DEFAULT_ICON, +} from './app/utils/file-icons.ts' + +const rootDir = process.cwd() +const outputDevPath = path.join(rootDir, 'public', 'file-tree-sprite.svg') +const outputStagePath = path.join(rootDir, 'public-dev', 'file-tree-sprite.svg') +const outputProdPath = path.join(rootDir, 'public-prod', 'file-tree-sprite.svg') + +const COLLECTION_NAMES = ['carbon', 'lucide', 'simple-icons', 'svg-spinners', 'vscode-icons'] + +const COLLECTION_REGEXP = new RegExp(`^(${COLLECTION_NAMES.join('|')})-(.+)$`) + +async function loadCollections() { + const collections: { [key: string]: IconifyJSON } = {} + for (const name of COLLECTION_NAMES) { + const filePathUrl = import.meta.resolve(`@iconify-json/${name}/icons.json`) + const filePath = fileURLToPath(filePathUrl) + const raw = await fs.readFile(filePath, 'utf8') + collections[name] = JSON.parse(raw) + } + return collections +} + +function groupByCollection(iconNames: string[]) { + const grouped: { [key: string]: string[] } = {} + for (const name of iconNames) { + const [, group, iconName] = name.match(COLLECTION_REGEXP) || [] + if (group && iconName) { + grouped[group] ||= [] + grouped[group].push(iconName) + } + } + return grouped +} + +function buildSprite( + grouped: { [key: string]: string[] }, + collections: { [key: string]: IconifyJSON }, +) { + let symbols = '' + Object.entries(grouped).forEach(([prefix, iconNames]) => { + const collection = collections[prefix] + + if (!collection?.icons) return + + const defaultWidth = collection.width ?? 16 + const defaultHeight = collection.height ?? 16 + + iconNames.forEach(name => { + const icon = collection.icons[name] + + if (!icon?.body) return + + const width = icon.width ?? defaultWidth + const height = icon.height ?? defaultHeight + const viewBox = `0 0 ${width} ${height}` + const id = `${collection.prefix}-${name}` + symbols += `${icon.body}` + }) + }) + return `${symbols}\n` +} + +async function main() { + const collections = await loadCollections() + const iconNames = [ + ...Object.values(EXTENSION_ICONS), + ...Object.values(FILENAME_ICONS), + ...Object.values(COMPOUND_EXTENSIONS), + ...Object.values(ADDITIONAL_ICONS), + DEFAULT_ICON, + ] + const grouped = groupByCollection(iconNames) + const sprite = buildSprite(grouped, collections) + await Promise.all([ + fs.mkdir(path.dirname(outputDevPath), { recursive: true }), + fs.mkdir(path.dirname(outputStagePath), { recursive: true }), + fs.mkdir(path.dirname(outputProdPath), { recursive: true }), + ]) + await Promise.all([ + fs.writeFile(outputDevPath, sprite, 'utf8'), + fs.writeFile(outputStagePath, sprite, 'utf8'), + fs.writeFile(outputProdPath, sprite, 'utf8'), + ]) +} + +main().catch(error => { + console.error(error) + process.exitCode = 1 +}) diff --git a/package.json b/package.json index 410564a85..b990cdf8b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "npmx-connector": "pnpm --filter npmx-connector dev", "generate-pwa-icons": "pwa-assets-generator", "preview": "nuxt preview", - "postinstall": "pnpm rebuild @resvg/resvg-js && pnpm generate:lexicons && nuxt prepare && simple-git-hooks", + "postinstall": "pnpm rebuild @resvg/resvg-js && pnpm generate:lexicons && pnpm generate:sprite && nuxt prepare && simple-git-hooks", + "generate:sprite": "node generate-file-tree-sprite.ts", "generate:fixtures": "node scripts/generate-fixtures.ts", "generate:lexicons": "lex build --lexicons lexicons --out shared/types/lexicons --clear", "test": "vite test", From febdd8d80b413a729415dfde0b4235648761b6f9 Mon Sep 17 00:00:00 2001 From: Vordgi Date: Tue, 10 Feb 2026 18:43:40 +0000 Subject: [PATCH 2/5] feat: restore icons size in file-view --- app/components/Code/DirectoryListing.vue | 4 ++-- app/components/Code/FileTree.vue | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/Code/DirectoryListing.vue b/app/components/Code/DirectoryListing.vue index bd69f3c99..67384d7e9 100644 --- a/app/components/Code/DirectoryListing.vue +++ b/app/components/Code/DirectoryListing.vue @@ -82,7 +82,7 @@ const bytesFormatter = useBytesFormatter() no-underline >