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 `\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",