Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/vite/vite.config.ts
4770 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { createLogger, defineConfig, Plugin } from 'vite';
7
import path, { join } from 'path';
8
/// @ts-ignore
9
import { urlToEsmPlugin } from './rollup-url-to-module-plugin/index.mjs';
10
import { statSync } from 'fs';
11
import { pathToFileURL } from 'url';
12
13
function injectBuiltinExtensionsPlugin(): Plugin {
14
let builtinExtensionsCache: unknown[] | null = null;
15
16
function replaceAllOccurrences(str: string, search: string, replace: string): string {
17
return str.split(search).join(replace);
18
}
19
20
async function loadBuiltinExtensions() {
21
if (!builtinExtensionsCache) {
22
builtinExtensionsCache = await getScannedBuiltinExtensions(path.resolve(__dirname, '../../'));
23
console.log(`Found ${builtinExtensionsCache!.length} built-in extensions.`);
24
}
25
return builtinExtensionsCache;
26
}
27
28
function asJSON(value: unknown): string {
29
return escapeHtmlByReplacingCharacters(JSON.stringify(value));
30
}
31
32
function escapeHtmlByReplacingCharacters(str: string) {
33
if (typeof str !== 'string') {
34
return '';
35
}
36
37
const escapeCharacter = (match: string) => {
38
switch (match) {
39
case '&': return '&';
40
case '<': return '&lt;';
41
case '>': return '&gt;';
42
case '"': return '&quot;';
43
case '\'': return '&#039;';
44
case '`': return '&#096;';
45
default: return match;
46
}
47
};
48
49
return str.replace(/[&<>"'`]/g, escapeCharacter);
50
}
51
52
const prebuiltExtensionsLocation = '.build/builtInExtensions';
53
async function getScannedBuiltinExtensions(vsCodeDevLocation: string) {
54
// use the build utility as to not duplicate the code
55
const extensionsUtil = await import(pathToFileURL(path.join(vsCodeDevLocation, 'build', 'lib', 'extensions.js')).toString());
56
const localExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, 'extensions'));
57
const prebuiltExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, prebuiltExtensionsLocation));
58
for (const ext of localExtensions) {
59
let browserMain = ext.packageJSON.browser;
60
if (browserMain) {
61
if (!browserMain.endsWith('.js')) {
62
browserMain = browserMain + '.js';
63
}
64
const browserMainLocation = path.join(vsCodeDevLocation, 'extensions', ext.extensionPath, browserMain);
65
if (!fileExists(browserMainLocation)) {
66
console.log(`${browserMainLocation} not found. Make sure all extensions are compiled (use 'yarn watch-web').`);
67
}
68
}
69
}
70
return localExtensions.concat(prebuiltExtensions);
71
}
72
73
function fileExists(path: string): boolean {
74
try {
75
return statSync(path).isFile();
76
} catch (err) {
77
return false;
78
}
79
}
80
81
return {
82
name: 'inject-builtin-extensions',
83
transformIndexHtml: {
84
order: 'pre',
85
async handler(html) {
86
const search = '{{WORKBENCH_BUILTIN_EXTENSIONS}}';
87
if (html.indexOf(search) === -1) {
88
return html;
89
}
90
91
const extensions = await loadBuiltinExtensions();
92
const h = replaceAllOccurrences(html, search, asJSON(extensions));
93
return h;
94
}
95
}
96
};
97
}
98
99
function createHotClassSupport(): Plugin {
100
return {
101
name: 'createHotClassSupport',
102
transform: {
103
order: 'pre',
104
handler: (code, id) => {
105
if (id.endsWith('.ts')) {
106
let needsHMRAccept = false;
107
const hasCreateHotClass = code.includes('createHotClass');
108
const hasDomWidget = code.includes('DomWidget');
109
110
if (!hasCreateHotClass && !hasDomWidget) {
111
return undefined;
112
}
113
114
if (hasCreateHotClass) {
115
needsHMRAccept = true;
116
}
117
118
if (hasDomWidget) {
119
const matches = code.matchAll(/class\s+([a-zA-Z0-9_]+)\s+extends\s+DomWidget/g);
120
/// @ts-ignore
121
for (const match of matches) {
122
const className = match[1];
123
code = code + `\n${className}.registerWidgetHotReplacement(${JSON.stringify(id + '#' + className)});`;
124
needsHMRAccept = true;
125
}
126
}
127
128
if (needsHMRAccept) {
129
code = code + `\n
130
if (import.meta.hot) {
131
import.meta.hot.accept();
132
}`;
133
}
134
return code;
135
}
136
return undefined;
137
},
138
}
139
};
140
}
141
142
const logger = createLogger();
143
const loggerWarn = logger.warn;
144
145
logger.warn = (msg, options) => {
146
// amdX and the baseUrl code cannot be analyzed by vite.
147
// However, they are not needed, so it is okay to silence the warning.
148
if (msg.indexOf('vs/amdX.ts') !== -1) {
149
return;
150
}
151
if (msg.indexOf('await import(new URL(`vs/workbench/workbench.desktop.main.js`, baseUrl).href)') !== -1) {
152
return;
153
}
154
if (msg.indexOf('const result2 = await import(workbenchUrl);') !== -1) {
155
return;
156
}
157
158
// See https://github.com/microsoft/vscode/issues/278153
159
if (msg.indexOf('marked.esm.js.map') !== -1 || msg.indexOf('purify.es.mjs.map') !== -1) {
160
return;
161
}
162
163
loggerWarn(msg, options);
164
};
165
166
export default defineConfig({
167
plugins: [
168
urlToEsmPlugin(),
169
injectBuiltinExtensionsPlugin(),
170
createHotClassSupport()
171
],
172
customLogger: logger,
173
esbuild: {
174
tsconfigRaw: {
175
compilerOptions: {
176
experimentalDecorators: true,
177
}
178
}
179
},
180
root: '../..', // To support /out/... paths
181
server: {
182
cors: true,
183
port: 5199,
184
origin: 'http://localhost:5199',
185
fs: {
186
allow: [
187
// To allow loading from sources, not needed when loading monaco-editor from npm package
188
/// @ts-ignore
189
join(import.meta.dirname, '../../../')
190
]
191
}
192
}
193
});
194
195