[READ-ONLY] a fast, modern browser for the npm registry

feat: generate sprite for file view (#1347)

authored by

Alex Savelyev and committed by
GitHub
e7670f8d 6c1083fa

+418 -286
+1
.gitignore
··· 39 39 40 40 # generated files 41 41 shared/types/lexicons 42 + file-tree-sprite.svg 42 43 43 44 **/__screenshots__/** 44 45
+20 -7
app/components/Code/DirectoryListing.vue
··· 1 1 <script setup lang="ts"> 2 2 import type { PackageFileTree } from '#shared/types' 3 3 import type { RouteLocationRaw } from 'vue-router' 4 - import { getFileIcon } from '~/utils/file-icons' 4 + import { ADDITIONAL_ICONS, getFileIcon } from '~/utils/file-icons' 5 5 6 6 const props = defineProps<{ 7 7 tree: PackageFileTree[] ··· 80 80 :to="getCodeRoute(parentPath || undefined)" 81 81 class="py-2 px-4 font-mono text-sm w-full" 82 82 no-underline 83 - classicon="i-carbon:folder text-yellow-600" 84 83 > 84 + <svg 85 + class="size-[1em] me-1 shrink-0 text-yellow-600" 86 + viewBox="0 0 16 16" 87 + fill="currentColor" 88 + aria-hidden="true" 89 + > 90 + <use :href="`/file-tree-sprite.svg#${ADDITIONAL_ICONS['folder']}`" /> 91 + </svg> 85 92 <span class="w-full flex justify-self-stretch items-center gap-2"> .. </span> 86 93 </LinkBase> 87 94 </td> ··· 98 105 :to="getCodeRoute(node.path)" 99 106 class="py-2 px-4 font-mono text-sm w-full" 100 107 no-underline 101 - :classicon=" 102 - node.type === 'directory' 103 - ? 'i-carbon:folder text-yellow-600' 104 - : getFileIcon(node.name) 105 - " 106 108 > 109 + <svg 110 + class="size-[1em] me-1 shrink-0" 111 + viewBox="0 0 16 16" 112 + fill="currentColor" 113 + :class="node.type === 'directory' ? 'text-yellow-600' : undefined" 114 + aria-hidden="true" 115 + > 116 + <use 117 + :href="`/file-tree-sprite.svg#${node.type === 'directory' ? ADDITIONAL_ICONS['folder'] : getFileIcon(node.name)}`" 118 + /> 119 + </svg> 107 120 <span class="w-full flex justify-self-stretch items-center gap-2"> 108 121 <span class="flex-1">{{ node.name }}</span> 109 122 <span
+20 -10
app/components/Code/FileTree.vue
··· 1 1 <script setup lang="ts"> 2 2 import type { PackageFileTree } from '#shared/types' 3 3 import type { RouteLocationRaw } from 'vue-router' 4 - import { getFileIcon } from '~/utils/file-icons' 4 + import { ADDITIONAL_ICONS, getFileIcon } from '~/utils/file-icons' 5 5 6 6 const props = defineProps<{ 7 7 tree: PackageFileTree[] ··· 57 57 @click="toggleDir(node.path)" 58 58 :classicon="isExpanded(node.path) ? 'i-carbon:chevron-down' : 'i-carbon:chevron-right'" 59 59 > 60 - <span 61 - class="w-4 h-4 shrink-0" 62 - :class=" 63 - isExpanded(node.path) 64 - ? 'i-carbon:folder-open text-yellow-500' 65 - : 'i-carbon:folder text-yellow-600' 66 - " 67 - /> 60 + <svg 61 + class="size-[1em] me-1 shrink-0" 62 + :class="isExpanded(node.path) ? 'text-yellow-500' : 'text-yellow-600'" 63 + viewBox="0 0 16 16" 64 + fill="currentColor" 65 + aria-hidden="true" 66 + > 67 + <use 68 + :href="`/file-tree-sprite.svg#${isExpanded(node.path) ? ADDITIONAL_ICONS['folder-open'] : ADDITIONAL_ICONS['folder']}`" 69 + /> 70 + </svg> 68 71 <span class="truncate">{{ node.name }}</span> 69 72 </ButtonBase> 70 73 <CodeFileTree ··· 86 89 class="w-full justify-start! rounded-none! border-none!" 87 90 block 88 91 :style="{ paddingLeft: `${depth * 12 + 32}px` }" 89 - :classicon="getFileIcon(node.name)" 90 92 > 93 + <svg 94 + class="size-[1em] me-1 shrink-0" 95 + viewBox="0 0 16 16" 96 + fill="currentColor" 97 + aria-hidden="true" 98 + > 99 + <use :href="`/file-tree-sprite.svg#${getFileIcon(node.name)}`" /> 100 + </svg> 91 101 <span class="truncate">{{ node.name }}</span> 92 102 </LinkBase> 93 103 </template>
+253 -245
app/utils/file-icons.ts
··· 1 1 /** 2 2 * Get icon class for a file based on its name/extension. 3 3 * Uses vscode-icons and carbon icons. 4 + * 5 + * Based on this file, a sprite file (<ORIGIN_URL>/file-tree-sprite.svg) is generated on postinstall 6 + * @see /scripts/generate-file-tree-sprite.ts 4 7 */ 5 8 6 9 // Extension to icon mapping 7 10 // @unocss-include 8 - const EXTENSION_ICONS: Record<string, string> = { 11 + export const EXTENSION_ICONS: Record<string, string> = { 9 12 // JavaScript/TypeScript 10 - 'js': 'i-vscode-icons-file-type-js-official', 11 - 'mjs': 'i-vscode-icons-file-type-js-official', 12 - 'cjs': 'i-vscode-icons-file-type-js-official', 13 - 'ts': 'i-vscode-icons-file-type-typescript-official', 14 - 'mts': 'i-vscode-icons-file-type-typescript-official', 15 - 'cts': 'i-vscode-icons-file-type-typescript-official', 16 - 'jsx': 'i-vscode-icons-file-type-reactjs', 17 - 'tsx': 'i-vscode-icons-file-type-reactts', 13 + 'js': 'vscode-icons-file-type-js-official', 14 + 'mjs': 'vscode-icons-file-type-js-official', 15 + 'cjs': 'vscode-icons-file-type-js-official', 16 + 'ts': 'vscode-icons-file-type-typescript-official', 17 + 'mts': 'vscode-icons-file-type-typescript-official', 18 + 'cts': 'vscode-icons-file-type-typescript-official', 19 + 'jsx': 'vscode-icons-file-type-reactjs', 20 + 'tsx': 'vscode-icons-file-type-reactts', 18 21 19 22 // Web 20 - 'html': 'i-vscode-icons-file-type-html', 21 - 'htm': 'i-vscode-icons-file-type-html', 22 - 'css': 'i-vscode-icons-file-type-css', 23 - 'scss': 'i-vscode-icons-file-type-scss', 24 - 'sass': 'i-vscode-icons-file-type-sass', 25 - 'less': 'i-vscode-icons-file-type-less', 26 - 'styl': 'i-vscode-icons-file-type-stylus', 27 - 'vue': 'i-vscode-icons-file-type-vue', 28 - 'svelte': 'i-vscode-icons-file-type-svelte', 29 - 'astro': 'i-vscode-icons-file-type-astro', 30 - 'gjs': 'i-vscode-icons-file-type-glimmer', 31 - 'gts': 'i-vscode-icons-file-type-glimmer', 23 + 'html': 'vscode-icons-file-type-html', 24 + 'htm': 'vscode-icons-file-type-html', 25 + 'css': 'vscode-icons-file-type-css', 26 + 'scss': 'vscode-icons-file-type-scss', 27 + 'sass': 'vscode-icons-file-type-sass', 28 + 'less': 'vscode-icons-file-type-less', 29 + 'styl': 'vscode-icons-file-type-stylus', 30 + 'vue': 'vscode-icons-file-type-vue', 31 + 'svelte': 'vscode-icons-file-type-svelte', 32 + 'astro': 'vscode-icons-file-type-astro', 33 + 'gjs': 'vscode-icons-file-type-glimmer', 34 + 'gts': 'vscode-icons-file-type-glimmer', 32 35 33 36 // Config/Data 34 - 'json': 'i-vscode-icons-file-type-json', 35 - 'jsonc': 'i-vscode-icons-file-type-json', 36 - 'json5': 'i-vscode-icons-file-type-json5', 37 - 'yaml': 'i-vscode-icons-file-type-yaml', 38 - 'yml': 'i-vscode-icons-file-type-yaml', 39 - 'toml': 'i-vscode-icons-file-type-toml', 40 - 'xml': 'i-vscode-icons-file-type-xml', 41 - 'svg': 'i-vscode-icons-file-type-svg', 42 - 'graphql': 'i-vscode-icons-file-type-graphql', 43 - 'gql': 'i-vscode-icons-file-type-graphql', 44 - 'prisma': 'i-vscode-icons-file-type-prisma', 37 + 'json': 'vscode-icons-file-type-json', 38 + 'jsonc': 'vscode-icons-file-type-json', 39 + 'json5': 'vscode-icons-file-type-json5', 40 + 'yaml': 'vscode-icons-file-type-yaml', 41 + 'yml': 'vscode-icons-file-type-yaml', 42 + 'toml': 'vscode-icons-file-type-toml', 43 + 'xml': 'vscode-icons-file-type-xml', 44 + 'svg': 'vscode-icons-file-type-svg', 45 + 'graphql': 'vscode-icons-file-type-graphql', 46 + 'gql': 'vscode-icons-file-type-graphql', 47 + 'prisma': 'vscode-icons-file-type-prisma', 45 48 46 49 // Documentation 47 - 'md': 'i-vscode-icons-file-type-markdown', 48 - 'mdx': 'i-vscode-icons-file-type-mdx', 49 - 'txt': 'i-vscode-icons-file-type-text', 50 - 'rst': 'i-vscode-icons-file-type-text', 51 - 'pdf': 'i-vscode-icons-file-type-pdf2', 50 + 'md': 'vscode-icons-file-type-markdown', 51 + 'mdx': 'vscode-icons-file-type-mdx', 52 + 'txt': 'vscode-icons-file-type-text', 53 + 'rst': 'vscode-icons-file-type-text', 54 + 'pdf': 'vscode-icons-file-type-pdf2', 52 55 53 56 // Shell/Scripts 54 - 'sh': 'i-vscode-icons-file-type-shell', 55 - 'bash': 'i-vscode-icons-file-type-shell', 56 - 'zsh': 'i-vscode-icons-file-type-shell', 57 - 'fish': 'i-vscode-icons-file-type-shell', 58 - 'ps1': 'i-vscode-icons-file-type-powershell', 59 - 'bat': 'i-vscode-icons-file-type-bat', 60 - 'cmd': 'i-vscode-icons-file-type-bat', 57 + 'sh': 'vscode-icons-file-type-shell', 58 + 'bash': 'vscode-icons-file-type-shell', 59 + 'zsh': 'vscode-icons-file-type-shell', 60 + 'fish': 'vscode-icons-file-type-shell', 61 + 'ps1': 'vscode-icons-file-type-powershell', 62 + 'bat': 'vscode-icons-file-type-bat', 63 + 'cmd': 'vscode-icons-file-type-bat', 61 64 62 65 // Programming languages 63 - 'py': 'i-vscode-icons-file-type-python', 64 - 'pyi': 'i-vscode-icons-file-type-python', 65 - 'rb': 'i-vscode-icons-file-type-ruby', 66 - 'go': 'i-vscode-icons-file-type-go', 67 - 'rs': 'i-vscode-icons-file-type-rust', 68 - 'java': 'i-vscode-icons-file-type-java', 69 - 'kt': 'i-vscode-icons-file-type-kotlin', 70 - 'swift': 'i-vscode-icons-file-type-swift', 71 - 'c': 'i-vscode-icons-file-type-c', 72 - 'cpp': 'i-vscode-icons-file-type-cpp', 73 - 'h': 'i-vscode-icons-file-type-cheader', 74 - 'hpp': 'i-vscode-icons-file-type-cppheader', 75 - 'cs': 'i-vscode-icons-file-type-csharp', 76 - 'php': 'i-vscode-icons-file-type-php', 77 - 'lua': 'i-vscode-icons-file-type-lua', 78 - 'r': 'i-vscode-icons-file-type-r', 79 - 'sql': 'i-vscode-icons-file-type-sql', 80 - 'pl': 'i-vscode-icons-file-type-perl', 81 - 'ex': 'i-vscode-icons-file-type-elixir', 82 - 'exs': 'i-vscode-icons-file-type-elixir', 83 - 'erl': 'i-vscode-icons-file-type-erlang', 84 - 'hs': 'i-vscode-icons-file-type-haskell', 85 - 'clj': 'i-vscode-icons-file-type-clojure', 86 - 'scala': 'i-vscode-icons-file-type-scala', 87 - 'zig': 'i-vscode-icons-file-type-zig', 88 - 'nim': 'i-vscode-icons-file-type-nim', 89 - 'v': 'i-vscode-icons-file-type-vlang', 90 - 'wasm': 'i-vscode-icons-file-type-wasm', 66 + 'py': 'vscode-icons-file-type-python', 67 + 'pyi': 'vscode-icons-file-type-python', 68 + 'rb': 'vscode-icons-file-type-ruby', 69 + 'go': 'vscode-icons-file-type-go', 70 + 'rs': 'vscode-icons-file-type-rust', 71 + 'java': 'vscode-icons-file-type-java', 72 + 'kt': 'vscode-icons-file-type-kotlin', 73 + 'swift': 'vscode-icons-file-type-swift', 74 + 'c': 'vscode-icons-file-type-c', 75 + 'cpp': 'vscode-icons-file-type-cpp', 76 + 'h': 'vscode-icons-file-type-cheader', 77 + 'hpp': 'vscode-icons-file-type-cppheader', 78 + 'cs': 'vscode-icons-file-type-csharp', 79 + 'php': 'vscode-icons-file-type-php', 80 + 'lua': 'vscode-icons-file-type-lua', 81 + 'r': 'vscode-icons-file-type-r', 82 + 'sql': 'vscode-icons-file-type-sql', 83 + 'pl': 'vscode-icons-file-type-perl', 84 + 'ex': 'vscode-icons-file-type-elixir', 85 + 'exs': 'vscode-icons-file-type-elixir', 86 + 'erl': 'vscode-icons-file-type-erlang', 87 + 'hs': 'vscode-icons-file-type-haskell', 88 + 'clj': 'vscode-icons-file-type-clojure', 89 + 'scala': 'vscode-icons-file-type-scala', 90 + 'zig': 'vscode-icons-file-type-zig', 91 + 'nim': 'vscode-icons-file-type-nim', 92 + 'v': 'vscode-icons-file-type-vlang', 93 + 'wasm': 'vscode-icons-file-type-wasm', 91 94 92 95 // Images 93 - 'png': 'i-vscode-icons-file-type-image', 94 - 'jpg': 'i-vscode-icons-file-type-image', 95 - 'jpeg': 'i-vscode-icons-file-type-image', 96 - 'gif': 'i-vscode-icons-file-type-image', 97 - 'webp': 'i-vscode-icons-file-type-image', 98 - 'ico': 'i-vscode-icons-file-type-image', 99 - 'bmp': 'i-vscode-icons-file-type-image', 96 + 'png': 'vscode-icons-file-type-image', 97 + 'jpg': 'vscode-icons-file-type-image', 98 + 'jpeg': 'vscode-icons-file-type-image', 99 + 'gif': 'vscode-icons-file-type-image', 100 + 'webp': 'vscode-icons-file-type-image', 101 + 'ico': 'vscode-icons-file-type-image', 102 + 'bmp': 'vscode-icons-file-type-image', 100 103 101 104 // Fonts 102 - 'woff': 'i-vscode-icons-file-type-font', 103 - 'woff2': 'i-vscode-icons-file-type-font', 104 - 'ttf': 'i-vscode-icons-file-type-font', 105 - 'otf': 'i-vscode-icons-file-type-font', 106 - 'eot': 'i-vscode-icons-file-type-font', 105 + 'woff': 'vscode-icons-file-type-font', 106 + 'woff2': 'vscode-icons-file-type-font', 107 + 'ttf': 'vscode-icons-file-type-font', 108 + 'otf': 'vscode-icons-file-type-font', 109 + 'eot': 'vscode-icons-file-type-font', 107 110 108 111 // Archives 109 - 'zip': 'i-vscode-icons-file-type-zip', 110 - 'tar': 'i-vscode-icons-file-type-zip', 111 - 'gz': 'i-vscode-icons-file-type-zip', 112 - 'tgz': 'i-vscode-icons-file-type-zip', 113 - 'bz2': 'i-vscode-icons-file-type-zip', 114 - '7z': 'i-vscode-icons-file-type-zip', 115 - 'rar': 'i-vscode-icons-file-type-zip', 112 + 'zip': 'vscode-icons-file-type-zip', 113 + 'tar': 'vscode-icons-file-type-zip', 114 + 'gz': 'vscode-icons-file-type-zip', 115 + 'tgz': 'vscode-icons-file-type-zip', 116 + 'bz2': 'vscode-icons-file-type-zip', 117 + '7z': 'vscode-icons-file-type-zip', 118 + 'rar': 'vscode-icons-file-type-zip', 116 119 117 120 // Certificates/Keys 118 - 'pem': 'i-vscode-icons-file-type-cert', 119 - 'crt': 'i-vscode-icons-file-type-cert', 120 - 'key': 'i-vscode-icons-file-type-key', 121 + 'pem': 'vscode-icons-file-type-cert', 122 + 'crt': 'vscode-icons-file-type-cert', 123 + 'key': 'vscode-icons-file-type-key', 121 124 122 125 // Diff/Patch 123 - 'diff': 'i-vscode-icons-file-type-diff', 124 - 'patch': 'i-vscode-icons-file-type-diff', 126 + 'diff': 'vscode-icons-file-type-diff', 127 + 'patch': 'vscode-icons-file-type-diff', 125 128 126 129 // Other 127 - 'log': 'i-vscode-icons-file-type-log', 128 - 'lock': 'i-vscode-icons-file-type-json', 129 - 'map': 'i-vscode-icons-file-type-map', 130 - 'wrl': 'i-vscode-icons-file-type-binary', 131 - 'bin': 'i-vscode-icons-file-type-binary', 132 - 'node': 'i-vscode-icons-file-type-node', 130 + 'log': 'vscode-icons-file-type-log', 131 + 'lock': 'vscode-icons-file-type-json', 132 + 'map': 'vscode-icons-file-type-map', 133 + 'wrl': 'vscode-icons-file-type-binary', 134 + 'bin': 'vscode-icons-file-type-binary', 135 + 'node': 'vscode-icons-file-type-node', 133 136 } 134 137 135 138 // Special filenames that have specific icons 136 - const FILENAME_ICONS: Record<string, string> = { 139 + export const FILENAME_ICONS: Record<string, string> = { 137 140 // Package managers 138 - 'package.json': 'i-vscode-icons-file-type-npm', 139 - 'package-lock.json': 'i-vscode-icons-file-type-npm', 140 - 'pnpm-lock.yaml': 'i-vscode-icons-file-type-pnpm', 141 - 'pnpm-workspace.yaml': 'i-vscode-icons-file-type-pnpm', 142 - 'yarn.lock': 'i-vscode-icons-file-type-yarn', 143 - '.yarnrc': 'i-vscode-icons-file-type-yarn', 144 - '.yarnrc.yml': 'i-vscode-icons-file-type-yarn', 145 - 'bun.lockb': 'i-vscode-icons-file-type-bun', 146 - 'bunfig.toml': 'i-vscode-icons-file-type-bun', 147 - 'deno.json': 'i-vscode-icons-file-type-deno', 148 - 'deno.jsonc': 'i-vscode-icons-file-type-deno', 141 + 'package.json': 'vscode-icons-file-type-npm', 142 + 'package-lock.json': 'vscode-icons-file-type-npm', 143 + 'pnpm-lock.yaml': 'vscode-icons-file-type-pnpm', 144 + 'pnpm-workspace.yaml': 'vscode-icons-file-type-pnpm', 145 + 'yarn.lock': 'vscode-icons-file-type-yarn', 146 + '.yarnrc': 'vscode-icons-file-type-yarn', 147 + '.yarnrc.yml': 'vscode-icons-file-type-yarn', 148 + 'bun.lockb': 'vscode-icons-file-type-bun', 149 + 'bunfig.toml': 'vscode-icons-file-type-bun', 150 + 'deno.json': 'vscode-icons-file-type-deno', 151 + 'deno.jsonc': 'vscode-icons-file-type-deno', 149 152 150 153 // TypeScript configs 151 - 'tsconfig.json': 'i-vscode-icons-file-type-tsconfig', 152 - 'tsconfig.base.json': 'i-vscode-icons-file-type-tsconfig', 153 - 'tsconfig.build.json': 'i-vscode-icons-file-type-tsconfig', 154 - 'tsconfig.node.json': 'i-vscode-icons-file-type-tsconfig', 155 - 'jsconfig.json': 'i-vscode-icons-file-type-jsconfig', 154 + 'tsconfig.json': 'vscode-icons-file-type-tsconfig', 155 + 'tsconfig.base.json': 'vscode-icons-file-type-tsconfig', 156 + 'tsconfig.build.json': 'vscode-icons-file-type-tsconfig', 157 + 'tsconfig.node.json': 'vscode-icons-file-type-tsconfig', 158 + 'jsconfig.json': 'vscode-icons-file-type-jsconfig', 156 159 157 160 // Build tools 158 - 'vite.config.ts': 'i-vscode-icons-file-type-vite', 159 - 'vite.config.js': 'i-vscode-icons-file-type-vite', 160 - 'vite.config.mts': 'i-vscode-icons-file-type-vite', 161 - 'vite.config.mjs': 'i-vscode-icons-file-type-vite', 162 - 'webpack.config.js': 'i-vscode-icons-file-type-webpack', 163 - 'webpack.config.ts': 'i-vscode-icons-file-type-webpack', 164 - 'rollup.config.js': 'i-vscode-icons-file-type-rollup', 165 - 'rollup.config.ts': 'i-vscode-icons-file-type-rollup', 166 - 'rollup.config.mjs': 'i-vscode-icons-file-type-rollup', 167 - 'esbuild.config.js': 'i-vscode-icons-file-type-esbuild', 168 - 'turbo.json': 'i-vscode-icons-file-type-turbo', 169 - 'nx.json': 'i-vscode-icons-file-type-nx', 161 + 'vite.config.ts': 'vscode-icons-file-type-vite', 162 + 'vite.config.js': 'vscode-icons-file-type-vite', 163 + 'vite.config.mts': 'vscode-icons-file-type-vite', 164 + 'vite.config.mjs': 'vscode-icons-file-type-vite', 165 + 'webpack.config.js': 'vscode-icons-file-type-webpack', 166 + 'webpack.config.ts': 'vscode-icons-file-type-webpack', 167 + 'rollup.config.js': 'vscode-icons-file-type-rollup', 168 + 'rollup.config.ts': 'vscode-icons-file-type-rollup', 169 + 'rollup.config.mjs': 'vscode-icons-file-type-rollup', 170 + 'esbuild.config.js': 'vscode-icons-file-type-esbuild', 171 + 'turbo.json': 'vscode-icons-file-type-turbo', 172 + 'nx.json': 'vscode-icons-file-type-nx', 170 173 171 174 // Framework configs 172 - 'nuxt.config.ts': 'i-vscode-icons-file-type-nuxt', 173 - 'nuxt.config.js': 'i-vscode-icons-file-type-nuxt', 174 - 'next.config.js': 'i-vscode-icons-file-type-next', 175 - 'next.config.mjs': 'i-vscode-icons-file-type-next', 176 - 'next.config.ts': 'i-vscode-icons-file-type-next', 177 - 'svelte.config.js': 'i-vscode-icons-file-type-svelte', 178 - 'astro.config.mjs': 'i-vscode-icons-file-type-astro', 179 - 'astro.config.ts': 'i-vscode-icons-file-type-astro', 180 - 'remix.config.js': 'i-vscode-icons-file-type-js-official', 181 - 'angular.json': 'i-vscode-icons-file-type-angular', 182 - 'nest-cli.json': 'i-vscode-icons-file-type-nestjs', 175 + 'nuxt.config.ts': 'vscode-icons-file-type-nuxt', 176 + 'nuxt.config.js': 'vscode-icons-file-type-nuxt', 177 + 'next.config.js': 'vscode-icons-file-type-next', 178 + 'next.config.mjs': 'vscode-icons-file-type-next', 179 + 'next.config.ts': 'vscode-icons-file-type-next', 180 + 'svelte.config.js': 'vscode-icons-file-type-svelte', 181 + 'astro.config.mjs': 'vscode-icons-file-type-astro', 182 + 'astro.config.ts': 'vscode-icons-file-type-astro', 183 + 'remix.config.js': 'vscode-icons-file-type-js-official', 184 + 'angular.json': 'vscode-icons-file-type-angular', 185 + 'nest-cli.json': 'vscode-icons-file-type-nestjs', 183 186 184 187 // Linting/Formatting 185 - '.eslintrc': 'i-vscode-icons-file-type-eslint', 186 - '.eslintrc.js': 'i-vscode-icons-file-type-eslint', 187 - '.eslintrc.cjs': 'i-vscode-icons-file-type-eslint', 188 - '.eslintrc.json': 'i-vscode-icons-file-type-eslint', 189 - '.eslintrc.yml': 'i-vscode-icons-file-type-eslint', 190 - 'eslint.config.js': 'i-vscode-icons-file-type-eslint', 191 - 'eslint.config.mjs': 'i-vscode-icons-file-type-eslint', 192 - 'eslint.config.ts': 'i-vscode-icons-file-type-eslint', 193 - '.prettierrc': 'i-vscode-icons-file-type-prettier', 194 - '.prettierrc.js': 'i-vscode-icons-file-type-prettier', 195 - '.prettierrc.json': 'i-vscode-icons-file-type-prettier', 196 - 'prettier.config.js': 'i-vscode-icons-file-type-prettier', 197 - 'prettier.config.mjs': 'i-vscode-icons-file-type-prettier', 198 - '.prettierignore': 'i-vscode-icons-file-type-prettier', 199 - 'biome.json': 'i-vscode-icons-file-type-biome', 200 - '.stylelintrc': 'i-vscode-icons-file-type-stylelint', 201 - '.stylelintrc.json': 'i-vscode-icons-file-type-stylelint', 188 + '.eslintrc': 'vscode-icons-file-type-eslint', 189 + '.eslintrc.js': 'vscode-icons-file-type-eslint', 190 + '.eslintrc.cjs': 'vscode-icons-file-type-eslint', 191 + '.eslintrc.json': 'vscode-icons-file-type-eslint', 192 + '.eslintrc.yml': 'vscode-icons-file-type-eslint', 193 + 'eslint.config.js': 'vscode-icons-file-type-eslint', 194 + 'eslint.config.mjs': 'vscode-icons-file-type-eslint', 195 + 'eslint.config.ts': 'vscode-icons-file-type-eslint', 196 + '.prettierrc': 'vscode-icons-file-type-prettier', 197 + '.prettierrc.js': 'vscode-icons-file-type-prettier', 198 + '.prettierrc.json': 'vscode-icons-file-type-prettier', 199 + 'prettier.config.js': 'vscode-icons-file-type-prettier', 200 + 'prettier.config.mjs': 'vscode-icons-file-type-prettier', 201 + '.prettierignore': 'vscode-icons-file-type-prettier', 202 + 'biome.json': 'vscode-icons-file-type-biome', 203 + '.stylelintrc': 'vscode-icons-file-type-stylelint', 204 + '.stylelintrc.json': 'vscode-icons-file-type-stylelint', 202 205 203 206 // Testing 204 - 'jest.config.js': 'i-vscode-icons-file-type-jest', 205 - 'jest.config.ts': 'i-vscode-icons-file-type-jest', 206 - 'vitest.config.ts': 'i-vscode-icons-file-type-vitest', 207 - 'vitest.config.js': 'i-vscode-icons-file-type-vitest', 208 - 'vitest.config.mts': 'i-vscode-icons-file-type-vitest', 209 - 'playwright.config.ts': 'i-vscode-icons-file-type-playwright', 210 - 'playwright.config.js': 'i-vscode-icons-file-type-playwright', 211 - 'cypress.config.ts': 'i-vscode-icons-file-type-cypress', 212 - 'cypress.config.js': 'i-vscode-icons-file-type-cypress', 207 + 'jest.config.js': 'vscode-icons-file-type-jest', 208 + 'jest.config.ts': 'vscode-icons-file-type-jest', 209 + 'vitest.config.ts': 'vscode-icons-file-type-vitest', 210 + 'vitest.config.js': 'vscode-icons-file-type-vitest', 211 + 'vitest.config.mts': 'vscode-icons-file-type-vitest', 212 + 'playwright.config.ts': 'vscode-icons-file-type-playwright', 213 + 'playwright.config.js': 'vscode-icons-file-type-playwright', 214 + 'cypress.config.ts': 'vscode-icons-file-type-cypress', 215 + 'cypress.config.js': 'vscode-icons-file-type-cypress', 213 216 214 217 // Git 215 - '.gitignore': 'i-vscode-icons-file-type-git', 216 - '.gitattributes': 'i-vscode-icons-file-type-git', 217 - '.gitmodules': 'i-vscode-icons-file-type-git', 218 - '.gitkeep': 'i-vscode-icons-file-type-git', 218 + '.gitignore': 'vscode-icons-file-type-git', 219 + '.gitattributes': 'vscode-icons-file-type-git', 220 + '.gitmodules': 'vscode-icons-file-type-git', 221 + '.gitkeep': 'vscode-icons-file-type-git', 219 222 220 223 // CI/CD 221 - '.travis.yml': 'i-vscode-icons-file-type-travis', 222 - '.gitlab-ci.yml': 'i-vscode-icons-file-type-gitlab', 223 - 'Jenkinsfile': 'i-vscode-icons-file-type-jenkins', 224 - 'azure-pipelines.yml': 'i-vscode-icons-file-type-azurepipelines', 225 - 'cloudbuild.yaml': 'i-vscode-icons-file-type-yaml', 226 - 'vercel.json': 'i-vscode-icons-file-type-vercel', 227 - 'netlify.toml': 'i-vscode-icons-file-type-netlify', 224 + '.travis.yml': 'vscode-icons-file-type-travis', 225 + '.gitlab-ci.yml': 'vscode-icons-file-type-gitlab', 226 + 'Jenkinsfile': 'vscode-icons-file-type-jenkins', 227 + 'azure-pipelines.yml': 'vscode-icons-file-type-azurepipelines', 228 + 'cloudbuild.yaml': 'vscode-icons-file-type-yaml', 229 + 'vercel.json': 'vscode-icons-file-type-vercel', 230 + 'netlify.toml': 'vscode-icons-file-type-netlify', 228 231 229 232 // Docker 230 - 'Dockerfile': 'i-vscode-icons-file-type-docker', 231 - 'docker-compose.yml': 'i-vscode-icons-file-type-docker', 232 - 'docker-compose.yaml': 'i-vscode-icons-file-type-docker', 233 - '.dockerignore': 'i-vscode-icons-file-type-docker', 233 + 'Dockerfile': 'vscode-icons-file-type-docker', 234 + 'docker-compose.yml': 'vscode-icons-file-type-docker', 235 + 'docker-compose.yaml': 'vscode-icons-file-type-docker', 236 + '.dockerignore': 'vscode-icons-file-type-docker', 234 237 235 238 // Environment 236 - '.env': 'i-vscode-icons-file-type-dotenv', 237 - '.env.local': 'i-vscode-icons-file-type-dotenv', 238 - '.env.development': 'i-vscode-icons-file-type-dotenv', 239 - '.env.production': 'i-vscode-icons-file-type-dotenv', 240 - '.env.test': 'i-vscode-icons-file-type-dotenv', 241 - '.env.example': 'i-vscode-icons-file-type-dotenv', 239 + '.env': 'vscode-icons-file-type-dotenv', 240 + '.env.local': 'vscode-icons-file-type-dotenv', 241 + '.env.development': 'vscode-icons-file-type-dotenv', 242 + '.env.production': 'vscode-icons-file-type-dotenv', 243 + '.env.test': 'vscode-icons-file-type-dotenv', 244 + '.env.example': 'vscode-icons-file-type-dotenv', 242 245 243 246 // Editor configs 244 - '.editorconfig': 'i-vscode-icons-file-type-editorconfig', 245 - '.vscode': 'i-vscode-icons-file-type-vscode', 246 - 'settings.json': 'i-vscode-icons-file-type-vscode', 247 - 'launch.json': 'i-vscode-icons-file-type-vscode', 248 - 'extensions.json': 'i-vscode-icons-file-type-vscode', 247 + '.editorconfig': 'vscode-icons-file-type-editorconfig', 248 + '.vscode': 'vscode-icons-file-type-vscode', 249 + 'settings.json': 'vscode-icons-file-type-vscode', 250 + 'launch.json': 'vscode-icons-file-type-vscode', 251 + 'extensions.json': 'vscode-icons-file-type-vscode', 249 252 250 253 // Documentation 251 - 'README': 'i-vscode-icons-file-type-markdown', 252 - 'README.md': 'i-vscode-icons-file-type-markdown', 253 - 'readme.md': 'i-vscode-icons-file-type-markdown', 254 - 'README.markdown': 'i-vscode-icons-file-type-markdown', 255 - 'readme.markdown': 'i-vscode-icons-file-type-markdown', 256 - 'CHANGELOG': 'i-vscode-icons-file-type-markdown', 257 - 'CHANGELOG.md': 'i-vscode-icons-file-type-markdown', 258 - 'changelog.md': 'i-vscode-icons-file-type-markdown', 259 - 'CONTRIBUTING.md': 'i-vscode-icons-file-type-markdown', 260 - 'contributing.md': 'i-vscode-icons-file-type-markdown', 261 - 'CODE_OF_CONDUCT.md': 'i-vscode-icons-file-type-markdown', 262 - 'LICENSE': 'i-vscode-icons-file-type-license', 263 - 'LICENSE.md': 'i-vscode-icons-file-type-license', 264 - 'LICENSE.txt': 'i-vscode-icons-file-type-license', 265 - 'license': 'i-vscode-icons-file-type-license', 266 - 'license.md': 'i-vscode-icons-file-type-license', 267 - 'license.txt': 'i-vscode-icons-file-type-license', 254 + 'README': 'vscode-icons-file-type-markdown', 255 + 'README.md': 'vscode-icons-file-type-markdown', 256 + 'readme.md': 'vscode-icons-file-type-markdown', 257 + 'README.markdown': 'vscode-icons-file-type-markdown', 258 + 'readme.markdown': 'vscode-icons-file-type-markdown', 259 + 'CHANGELOG': 'vscode-icons-file-type-markdown', 260 + 'CHANGELOG.md': 'vscode-icons-file-type-markdown', 261 + 'changelog.md': 'vscode-icons-file-type-markdown', 262 + 'CONTRIBUTING.md': 'vscode-icons-file-type-markdown', 263 + 'contributing.md': 'vscode-icons-file-type-markdown', 264 + 'CODE_OF_CONDUCT.md': 'vscode-icons-file-type-markdown', 265 + 'LICENSE': 'vscode-icons-file-type-license', 266 + 'LICENSE.md': 'vscode-icons-file-type-license', 267 + 'LICENSE.txt': 'vscode-icons-file-type-license', 268 + 'license': 'vscode-icons-file-type-license', 269 + 'license.md': 'vscode-icons-file-type-license', 270 + 'license.txt': 'vscode-icons-file-type-license', 268 271 269 272 // Node 270 - '.npmrc': 'i-vscode-icons-file-type-npm', 271 - '.npmignore': 'i-vscode-icons-file-type-npm', 272 - '.nvmrc': 'i-vscode-icons-file-type-node', 273 - '.node-version': 'i-vscode-icons-file-type-node', 273 + '.npmrc': 'vscode-icons-file-type-npm', 274 + '.npmignore': 'vscode-icons-file-type-npm', 275 + '.nvmrc': 'vscode-icons-file-type-node', 276 + '.node-version': 'vscode-icons-file-type-node', 274 277 275 278 // Misc 276 - 'Makefile': 'i-vscode-icons-file-type-makefile', 277 - '.browserslistrc': 'i-vscode-icons-file-type-browserslist', 278 - 'browserslist': 'i-vscode-icons-file-type-browserslist', 279 - '.babelrc': 'i-vscode-icons-file-type-babel', 280 - 'babel.config.js': 'i-vscode-icons-file-type-babel', 281 - 'tailwind.config.js': 'i-vscode-icons-file-type-tailwind', 282 - 'tailwind.config.ts': 'i-vscode-icons-file-type-tailwind', 283 - 'postcss.config.js': 'i-vscode-icons-file-type-postcss', 284 - 'postcss.config.cjs': 'i-vscode-icons-file-type-postcss', 285 - 'uno.config.ts': 'i-vscode-icons-file-type-unocss', 286 - 'unocss.config.ts': 'i-vscode-icons-file-type-unocss', 279 + 'Makefile': 'vscode-icons-file-type-makefile', 280 + '.browserslistrc': 'vscode-icons-file-type-browserslist', 281 + 'browserslist': 'vscode-icons-file-type-browserslist', 282 + '.babelrc': 'vscode-icons-file-type-babel', 283 + 'babel.config.js': 'vscode-icons-file-type-babel', 284 + 'tailwind.config.js': 'vscode-icons-file-type-tailwind', 285 + 'tailwind.config.ts': 'vscode-icons-file-type-tailwind', 286 + 'postcss.config.js': 'vscode-icons-file-type-postcss', 287 + 'postcss.config.cjs': 'vscode-icons-file-type-postcss', 288 + 'uno.config.ts': 'vscode-icons-file-type-unocss', 289 + 'unocss.config.ts': 'vscode-icons-file-type-unocss', 287 290 } 288 291 289 292 // Patterns for .d.ts and similar compound extensions 290 - const COMPOUND_EXTENSIONS: Record<string, string> = { 291 - '.d.ts': 'i-vscode-icons-file-type-typescriptdef', 292 - '.d.mts': 'i-vscode-icons-file-type-typescriptdef', 293 - '.d.cts': 'i-vscode-icons-file-type-typescriptdef', 294 - '.test.ts': 'i-vscode-icons-file-type-testts', 295 - '.test.js': 'i-vscode-icons-file-type-testjs', 296 - '.spec.ts': 'i-vscode-icons-file-type-testts', 297 - '.spec.js': 'i-vscode-icons-file-type-testjs', 298 - '.test.tsx': 'i-vscode-icons-file-type-testts', 299 - '.test.jsx': 'i-vscode-icons-file-type-testjs', 300 - '.spec.tsx': 'i-vscode-icons-file-type-testts', 301 - '.spec.jsx': 'i-vscode-icons-file-type-testjs', 302 - '.stories.tsx': 'i-vscode-icons-file-type-storybook', 303 - '.stories.ts': 'i-vscode-icons-file-type-storybook', 304 - '.stories.jsx': 'i-vscode-icons-file-type-storybook', 305 - '.stories.js': 'i-vscode-icons-file-type-storybook', 306 - '.min.js': 'i-vscode-icons-file-type-js-official', 307 - '.min.css': 'i-vscode-icons-file-type-css', 293 + export const COMPOUND_EXTENSIONS: Record<string, string> = { 294 + '.d.ts': 'vscode-icons-file-type-typescriptdef', 295 + '.d.mts': 'vscode-icons-file-type-typescriptdef', 296 + '.d.cts': 'vscode-icons-file-type-typescriptdef', 297 + '.test.ts': 'vscode-icons-file-type-testts', 298 + '.test.js': 'vscode-icons-file-type-testjs', 299 + '.spec.ts': 'vscode-icons-file-type-testts', 300 + '.spec.js': 'vscode-icons-file-type-testjs', 301 + '.test.tsx': 'vscode-icons-file-type-testts', 302 + '.test.jsx': 'vscode-icons-file-type-testjs', 303 + '.spec.tsx': 'vscode-icons-file-type-testts', 304 + '.spec.jsx': 'vscode-icons-file-type-testjs', 305 + '.stories.tsx': 'vscode-icons-file-type-storybook', 306 + '.stories.ts': 'vscode-icons-file-type-storybook', 307 + '.stories.jsx': 'vscode-icons-file-type-storybook', 308 + '.stories.js': 'vscode-icons-file-type-storybook', 309 + '.min.js': 'vscode-icons-file-type-js-official', 310 + '.min.css': 'vscode-icons-file-type-css', 308 311 } 309 312 310 313 // Default icon for unknown files 311 - const DEFAULT_ICON = 'i-vscode-icons-default-file' 314 + export const DEFAULT_ICON = 'vscode-icons-default-file' 315 + 316 + export const ADDITIONAL_ICONS = { 317 + 'folder': 'carbon-folder', 318 + 'folder-open': 'carbon-folder-open', 319 + } 312 320 313 321 /** 314 322 * Get the icon class for a file based on its name
+2 -1
package.json
··· 29 29 "npmx-connector": "pnpm --filter npmx-connector dev", 30 30 "generate-pwa-icons": "pwa-assets-generator", 31 31 "preview": "nuxt preview", 32 - "postinstall": "pnpm rebuild @resvg/resvg-js && pnpm generate:lexicons && nuxt prepare && simple-git-hooks", 32 + "postinstall": "pnpm rebuild @resvg/resvg-js && pnpm generate:lexicons && pnpm generate:sprite && nuxt prepare && simple-git-hooks", 33 + "generate:sprite": "node scripts/generate-file-tree-sprite.ts", 33 34 "generate:fixtures": "node scripts/generate-fixtures.ts", 34 35 "generate:lexicons": "lex build --lexicons lexicons --out shared/types/lexicons --clear", 35 36 "test": "vite test",
+99
scripts/generate-file-tree-sprite.ts
··· 1 + import type { IconifyJSON } from '@iconify-json/carbon' 2 + import { promises as fs } from 'node:fs' 3 + import { fileURLToPath } from 'node:url' 4 + import path from 'node:path' 5 + import { 6 + ADDITIONAL_ICONS, 7 + EXTENSION_ICONS, 8 + FILENAME_ICONS, 9 + COMPOUND_EXTENSIONS, 10 + DEFAULT_ICON, 11 + } from '../app/utils/file-icons.ts' 12 + 13 + const rootDir = process.cwd() 14 + const outputDevPath = path.join(rootDir, 'public', 'file-tree-sprite.svg') 15 + const outputStagePath = path.join(rootDir, 'public-dev', 'file-tree-sprite.svg') 16 + const outputProdPath = path.join(rootDir, 'public-prod', 'file-tree-sprite.svg') 17 + 18 + const COLLECTION_NAMES = ['carbon', 'lucide', 'simple-icons', 'svg-spinners', 'vscode-icons'] 19 + 20 + const COLLECTION_REGEXP = new RegExp(`^(${COLLECTION_NAMES.join('|')})-(.+)$`) 21 + 22 + async function loadCollections() { 23 + const collections: { [key: string]: IconifyJSON } = {} 24 + for (const name of COLLECTION_NAMES) { 25 + const filePathUrl = import.meta.resolve(`@iconify-json/${name}/icons.json`) 26 + const filePath = fileURLToPath(filePathUrl) 27 + const raw = await fs.readFile(filePath, 'utf8') 28 + collections[name] = JSON.parse(raw) 29 + } 30 + return collections 31 + } 32 + 33 + function groupByCollection(iconNames: string[]) { 34 + const grouped: { [key: string]: string[] } = {} 35 + for (const name of iconNames) { 36 + const [, group, iconName] = name.match(COLLECTION_REGEXP) || [] 37 + if (group && iconName) { 38 + grouped[group] ||= [] 39 + grouped[group].push(iconName) 40 + } 41 + } 42 + return grouped 43 + } 44 + 45 + function buildSprite( 46 + grouped: { [key: string]: string[] }, 47 + collections: { [key: string]: IconifyJSON }, 48 + ) { 49 + let symbols = '' 50 + Object.entries(grouped).forEach(([prefix, iconNames]) => { 51 + const collection = collections[prefix] 52 + 53 + if (!collection?.icons) return 54 + 55 + const defaultWidth = collection.width ?? 16 56 + const defaultHeight = collection.height ?? 16 57 + 58 + iconNames.forEach(name => { 59 + const icon = collection.icons[name] 60 + 61 + if (!icon?.body) return 62 + 63 + const width = icon.width ?? defaultWidth 64 + const height = icon.height ?? defaultHeight 65 + const viewBox = `0 0 ${width} ${height}` 66 + const id = `${collection.prefix}-${name}` 67 + symbols += `<symbol id="${id}" viewBox="${viewBox}">${icon.body}</symbol>` 68 + }) 69 + }) 70 + return `<svg xmlns="http://www.w3.org/2000/svg" style="display:none">${symbols}</svg>\n` 71 + } 72 + 73 + async function main() { 74 + const collections = await loadCollections() 75 + const iconNames = [ 76 + ...Object.values(EXTENSION_ICONS), 77 + ...Object.values(FILENAME_ICONS), 78 + ...Object.values(COMPOUND_EXTENSIONS), 79 + ...Object.values(ADDITIONAL_ICONS), 80 + DEFAULT_ICON, 81 + ] 82 + const grouped = groupByCollection(iconNames) 83 + const sprite = buildSprite(grouped, collections) 84 + await Promise.all([ 85 + fs.mkdir(path.dirname(outputDevPath), { recursive: true }), 86 + fs.mkdir(path.dirname(outputStagePath), { recursive: true }), 87 + fs.mkdir(path.dirname(outputProdPath), { recursive: true }), 88 + ]) 89 + await Promise.all([ 90 + fs.writeFile(outputDevPath, sprite, 'utf8'), 91 + fs.writeFile(outputStagePath, sprite, 'utf8'), 92 + fs.writeFile(outputProdPath, sprite, 'utf8'), 93 + ]) 94 + } 95 + 96 + main().catch(error => { 97 + console.error(error) 98 + process.exitCode = 1 99 + })
+23 -23
test/unit/app/utils/file-icons.spec.ts
··· 3 3 4 4 describe('getFileIcon', () => { 5 5 it('returns correct icons for exact filename matches', () => { 6 - expect(getFileIcon('package.json')).toBe('i-vscode-icons-file-type-npm') 7 - expect(getFileIcon('Dockerfile')).toBe('i-vscode-icons-file-type-docker') 8 - expect(getFileIcon('.gitignore')).toBe('i-vscode-icons-file-type-git') 9 - expect(getFileIcon('eslint.config.js')).toBe('i-vscode-icons-file-type-eslint') 10 - expect(getFileIcon('vitest.config.ts')).toBe('i-vscode-icons-file-type-vitest') 11 - expect(getFileIcon('.env')).toBe('i-vscode-icons-file-type-dotenv') 6 + expect(getFileIcon('package.json')).toBe('vscode-icons-file-type-npm') 7 + expect(getFileIcon('Dockerfile')).toBe('vscode-icons-file-type-docker') 8 + expect(getFileIcon('.gitignore')).toBe('vscode-icons-file-type-git') 9 + expect(getFileIcon('eslint.config.js')).toBe('vscode-icons-file-type-eslint') 10 + expect(getFileIcon('vitest.config.ts')).toBe('vscode-icons-file-type-vitest') 11 + expect(getFileIcon('.env')).toBe('vscode-icons-file-type-dotenv') 12 12 }) 13 13 14 14 it('returns correct icons for compound extensions', () => { 15 - expect(getFileIcon('types.d.ts')).toBe('i-vscode-icons-file-type-typescriptdef') 16 - expect(getFileIcon('utils.test.ts')).toBe('i-vscode-icons-file-type-testts') 17 - expect(getFileIcon('utils.spec.js')).toBe('i-vscode-icons-file-type-testjs') 18 - expect(getFileIcon('Button.stories.tsx')).toBe('i-vscode-icons-file-type-storybook') 15 + expect(getFileIcon('types.d.ts')).toBe('vscode-icons-file-type-typescriptdef') 16 + expect(getFileIcon('utils.test.ts')).toBe('vscode-icons-file-type-testts') 17 + expect(getFileIcon('utils.spec.js')).toBe('vscode-icons-file-type-testjs') 18 + expect(getFileIcon('Button.stories.tsx')).toBe('vscode-icons-file-type-storybook') 19 19 }) 20 20 21 21 it('returns correct icons for simple extensions', () => { 22 - expect(getFileIcon('index.js')).toBe('i-vscode-icons-file-type-js-official') 23 - expect(getFileIcon('main.ts')).toBe('i-vscode-icons-file-type-typescript-official') 24 - expect(getFileIcon('App.vue')).toBe('i-vscode-icons-file-type-vue') 25 - expect(getFileIcon('data.json')).toBe('i-vscode-icons-file-type-json') 26 - expect(getFileIcon('build.sh')).toBe('i-vscode-icons-file-type-shell') 27 - expect(getFileIcon('script.py')).toBe('i-vscode-icons-file-type-python') 28 - expect(getFileIcon('lib.rs')).toBe('i-vscode-icons-file-type-rust') 29 - expect(getFileIcon('logo.png')).toBe('i-vscode-icons-file-type-image') 30 - expect(getFileIcon('archive.tar')).toBe('i-vscode-icons-file-type-zip') 22 + expect(getFileIcon('index.js')).toBe('vscode-icons-file-type-js-official') 23 + expect(getFileIcon('main.ts')).toBe('vscode-icons-file-type-typescript-official') 24 + expect(getFileIcon('App.vue')).toBe('vscode-icons-file-type-vue') 25 + expect(getFileIcon('data.json')).toBe('vscode-icons-file-type-json') 26 + expect(getFileIcon('build.sh')).toBe('vscode-icons-file-type-shell') 27 + expect(getFileIcon('script.py')).toBe('vscode-icons-file-type-python') 28 + expect(getFileIcon('lib.rs')).toBe('vscode-icons-file-type-rust') 29 + expect(getFileIcon('logo.png')).toBe('vscode-icons-file-type-image') 30 + expect(getFileIcon('archive.tar')).toBe('vscode-icons-file-type-zip') 31 31 }) 32 32 33 33 it('returns default icon for unknown files', () => { 34 - expect(getFileIcon('file.xyz')).toBe('i-vscode-icons-default-file') 35 - expect(getFileIcon('unknownfile')).toBe('i-vscode-icons-default-file') 34 + expect(getFileIcon('file.xyz')).toBe('vscode-icons-default-file') 35 + expect(getFileIcon('unknownfile')).toBe('vscode-icons-default-file') 36 36 }) 37 37 38 38 it('prefers exact filename over extension, and compound over simple', () => { 39 - expect(getFileIcon('package.json')).toBe('i-vscode-icons-file-type-npm') 40 - expect(getFileIcon('foo.test.ts')).toBe('i-vscode-icons-file-type-testts') 39 + expect(getFileIcon('package.json')).toBe('vscode-icons-file-type-npm') 40 + expect(getFileIcon('foo.test.ts')).toBe('vscode-icons-file-type-testts') 41 41 }) 42 42 })