History

Add workspace file browser and preview panel (#3087)

Julius Marminge committed 4 months agov0.0.28-nightly.20260615.565

Commit de8bdc11 parent 477795662 files · +2850 −9551Browse files

Showing the changes to scripts (1 of 62 files). Show all

Unified · Split

scripts/sync-vscode-icons.mjs+0−153
@@ -1,153 +0,0 @@
1#!/usr/bin/env node
2
3import fs from "node:fs/promises";
4import os from "node:os";
5import path from "node:path";
6import vm from "node:vm";
7import { execFile } from "node:child_process";
8import { promisify } from "node:util";
9
10const execFileAsync = promisify(execFile);
11
12const VERSION = process.argv[2] ?? "12.17.0";
13const VERSION_TAG = `v${VERSION}`;
14const VSIX_URL = `https://open-vsx.org/api/vscode-icons-team/vscode-icons/${VERSION}/file/vscode-icons-team.vscode-icons-${VERSION}.vsix`;
15const LANGUAGES_URL = `https://raw.githubusercontent.com/vscode-icons/vscode-icons/${VERSION_TAG}/src/iconsManifest/languages.ts`;
16
17const REPO_ROOT = process.cwd();
18const MANIFEST_PATH = path.join(REPO_ROOT, "apps/web/src/vscode-icons-manifest.json");
19const ASSOCIATIONS_PATH = path.join(
20 REPO_ROOT,
21 "apps/web/src/vscode-icons-language-associations.json",
22);
23
24function normalizeExtension(value) {
25 return value.trim().toLowerCase().replace(/^\./, "");
26}
27
28function normalizeFileName(value) {
29 return value.trim().toLowerCase();
30}
31
32function putIfAbsent(target, key, value) {
33 if (!(key in target)) {
34 target[key] = value;
35 }
36}
37
38async function downloadVsix(tmpDir) {
39 const vsixPath = path.join(tmpDir, `vscode-icons-${VERSION}.vsix`);
40 const response = await fetch(VSIX_URL);
41 if (!response.ok) {
42 throw new Error(`Failed to download VSIX: ${response.status} ${response.statusText}`);
43 }
44 const bytes = Buffer.from(await response.arrayBuffer());
45 await fs.writeFile(vsixPath, bytes);
46 return vsixPath;
47}
48
49async function extractManifestFromVsix(vsixPath) {
50 const { stdout } = await execFileAsync("unzip", [
51 "-p",
52 vsixPath,
53 "extension/dist/src/vsicons-icon-theme.json",
54 ]);
55 if (!stdout || stdout.trim().length === 0) {
56 throw new Error("Could not extract vsicons-icon-theme.json from VSIX");
57 }
58 return JSON.parse(stdout);
59}
60
61async function loadLanguagesCollection() {
62 const response = await fetch(LANGUAGES_URL);
63 if (!response.ok) {
64 throw new Error(`Failed to fetch languages.ts: ${response.status} ${response.statusText}`);
65 }
66 const rawSource = await response.text();
67 const source = rawSource
68 .replace(/^import[^;]+;\s*/gm, "")
69 .replace(/export const languages(?:\s*:\s*[^=]+)?\s*=/, "const languages =")
70 .replace(/\}\s*satisfies\s*Record<[^;]+>;/, "};");
71
72 const context = {};
73 vm.createContext(context);
74 vm.runInContext(`${source}\n;globalThis.__languages = languages;`, context);
75 const languages = context.__languages;
76 if (!languages || typeof languages !== "object") {
77 throw new Error("Failed to parse languages.ts into a collection");
78 }
79 return languages;
80}
81
82function buildLanguageAssociations(manifest, languages) {
83 const availableLanguageIds = new Set(Object.keys(manifest.languageIds ?? {}));
84 const extensionToLanguageId = {};
85 const fileNameToLanguageId = {};
86
87 for (const entry of Object.values(languages)) {
88 if (!entry || typeof entry !== "object") continue;
89 const idsRaw = entry.ids;
90 const ids = Array.isArray(idsRaw) ? idsRaw : [idsRaw];
91 const knownExtensions = Array.isArray(entry.knownExtensions) ? entry.knownExtensions : [];
92 const knownFilenames = Array.isArray(entry.knownFilenames) ? entry.knownFilenames : [];
93
94 for (const idValue of ids) {
95 if (typeof idValue !== "string") continue;
96 const languageId = idValue.trim();
97 if (languageId.length === 0) continue;
98 if (!availableLanguageIds.has(languageId)) continue;
99
100 for (const extensionValue of knownExtensions) {
101 if (typeof extensionValue !== "string") continue;
102 const extension = normalizeExtension(extensionValue);
103 if (extension.length === 0) continue;
104 putIfAbsent(extensionToLanguageId, extension, languageId);
105 }
106
107 for (const fileNameValue of knownFilenames) {
108 if (typeof fileNameValue !== "string") continue;
109 const fileName = normalizeFileName(fileNameValue);
110 if (fileName.length === 0) continue;
111 putIfAbsent(fileNameToLanguageId, fileName, languageId);
112 }
113 }
114 }
115
116 return {
117 version: VERSION,
118 source: LANGUAGES_URL,
119 generatedAt: new Date().toISOString(),
120 extensionToLanguageId,
121 fileNameToLanguageId,
122 };
123}
124
125async function main() {
126 const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "t3-vscode-icons-sync-"));
127 try {
128 const vsixPath = await downloadVsix(tmpDir);
129 const manifest = await extractManifestFromVsix(vsixPath);
130 const languages = await loadLanguagesCollection();
131 const associations = buildLanguageAssociations(manifest, languages);
132
133 await fs.writeFile(MANIFEST_PATH, `${JSON.stringify(manifest)}\n`, "utf8");
134 await fs.writeFile(ASSOCIATIONS_PATH, `${JSON.stringify(associations)}\n`, "utf8");
135
136 process.stdout.write(
137 [
138 `Synced vscode-icons ${VERSION}`,
139 `manifest: ${MANIFEST_PATH}`,
140 `language associations: ${ASSOCIATIONS_PATH}`,
141 `extension mappings: ${Object.keys(associations.extensionToLanguageId).length}`,
142 `filename mappings: ${Object.keys(associations.fileNameToLanguageId).length}`,
143 ].join("\n") + "\n",
144 );
145 } finally {
146 await fs.rm(tmpDir, { recursive: true, force: true });
147 }
148}
149
150main().catch((error) => {
151 process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
152 process.exit(1);
153});