Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/gulpfile.editor.ts
5250 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 gulp from 'gulp';
7
import path from 'path';
8
import * as util from './lib/util.ts';
9
import { getVersion } from './lib/getVersion.ts';
10
import * as task from './lib/task.ts';
11
import es from 'event-stream';
12
import File from 'vinyl';
13
import * as i18n from './lib/i18n.ts';
14
import * as standalone from './lib/standalone.ts';
15
import * as cp from 'child_process';
16
import * as compilation from './lib/compilation.ts';
17
import * as monacoapi from './lib/monaco-api.ts';
18
import * as fs from 'fs';
19
import filter from 'gulp-filter';
20
import { createReporter } from './lib/reporter.ts';
21
import monacoPackage from './monaco/package.json' with { type: 'json' };
22
23
const root = path.dirname(import.meta.dirname);
24
const sha1 = getVersion(root);
25
const semver = monacoPackage.version;
26
const headerVersion = semver + '(' + sha1 + ')';
27
28
const BUNDLED_FILE_HEADER = [
29
'/*!-----------------------------------------------------------',
30
' * Copyright (c) Microsoft Corporation. All rights reserved.',
31
' * Version: ' + headerVersion,
32
' * Released under the MIT license',
33
' * https://github.com/microsoft/vscode/blob/main/LICENSE.txt',
34
' *-----------------------------------------------------------*/',
35
''
36
].join('\n');
37
38
const extractEditorSrcTask = task.define('extract-editor-src', () => {
39
// Ensure codicon.ttf is copied from node_modules (needed when node_modules is cached and postinstall doesn't run)
40
const codiconSource = path.join(root, 'node_modules', '@vscode', 'codicons', 'dist', 'codicon.ttf');
41
const codiconDest = path.join(root, 'src', 'vs', 'base', 'browser', 'ui', 'codicons', 'codicon', 'codicon.ttf');
42
if (fs.existsSync(codiconSource)) {
43
fs.mkdirSync(path.dirname(codiconDest), { recursive: true });
44
fs.copyFileSync(codiconSource, codiconDest);
45
}
46
47
const apiusages = monacoapi.execute().usageContent;
48
const extrausages = fs.readFileSync(path.join(root, 'build', 'monaco', 'monaco.usage.recipe')).toString();
49
standalone.extractEditor({
50
sourcesRoot: path.join(root, 'src'),
51
entryPoints: [
52
'vs/editor/editor.main.ts',
53
'vs/editor/editor.worker.start.ts',
54
'vs/editor/common/services/editorWebWorkerMain.ts',
55
],
56
inlineEntryPoints: [
57
apiusages,
58
extrausages
59
],
60
typings: [],
61
additionalFilesToCopyOut: [
62
'vs/base/browser/dompurify/dompurify.js',
63
'vs/base/common/marked/marked.js',
64
],
65
shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers
66
importIgnorePattern: /\.css$/,
67
destRoot: path.join(root, 'out-editor-src'),
68
tsOutDir: '../out-monaco-editor-core/esm/vs',
69
});
70
});
71
72
const compileEditorESMTask = task.define('compile-editor-esm', () => {
73
74
const src = 'out-editor-src';
75
const out = 'out-monaco-editor-core/esm';
76
77
const compile = compilation.createCompile(src, { build: true, emitError: true, transpileOnly: false, preserveEnglish: true });
78
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
79
80
return (
81
srcPipe
82
.pipe(compile())
83
.pipe(i18n.processNlsFiles({
84
out,
85
fileHeader: BUNDLED_FILE_HEADER,
86
languages: [...i18n.defaultLanguages, ...i18n.extraLanguages],
87
}))
88
.pipe(filter(['**', '!**/inlineEntryPoint*', '!**/tsconfig.json']))
89
.pipe(gulp.dest(out))
90
);
91
});
92
93
function toExternalDTS(contents: string) {
94
const lines = contents.split(/\r\n|\r|\n/);
95
let killNextCloseCurlyBrace = false;
96
for (let i = 0; i < lines.length; i++) {
97
const line = lines[i];
98
99
if (killNextCloseCurlyBrace) {
100
if ('}' === line) {
101
lines[i] = '';
102
killNextCloseCurlyBrace = false;
103
continue;
104
}
105
106
if (line.indexOf(' ') === 0) {
107
lines[i] = line.substr(4);
108
} else if (line.charAt(0) === '\t') {
109
lines[i] = line.substr(1);
110
}
111
112
continue;
113
}
114
115
if ('declare namespace monaco {' === line) {
116
lines[i] = '';
117
killNextCloseCurlyBrace = true;
118
continue;
119
}
120
121
if (line.indexOf('declare namespace monaco.') === 0) {
122
lines[i] = line.replace('declare namespace monaco.', 'export namespace ');
123
}
124
125
if (line.indexOf('declare var MonacoEnvironment') === 0) {
126
lines[i] = `declare global {\n var MonacoEnvironment: Environment | undefined;\n}`;
127
}
128
}
129
return lines.join('\n').replace(/\n\n\n+/g, '\n\n');
130
}
131
132
const finalEditorResourcesTask = task.define('final-editor-resources', () => {
133
return es.merge(
134
// other assets
135
es.merge(
136
gulp.src('build/monaco/LICENSE'),
137
gulp.src('build/monaco/ThirdPartyNotices.txt'),
138
gulp.src('src/vs/monaco.d.ts')
139
).pipe(gulp.dest('out-monaco-editor-core')),
140
141
// place the .d.ts in the esm folder
142
gulp.src('src/vs/monaco.d.ts')
143
.pipe(es.through(function (data) {
144
this.emit('data', new File({
145
path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'),
146
base: data.base,
147
contents: Buffer.from(toExternalDTS(data.contents.toString()))
148
}));
149
}))
150
.pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')),
151
152
// package.json
153
gulp.src('build/monaco/package.json')
154
.pipe(es.through(function (data) {
155
const json = JSON.parse(data.contents.toString());
156
json.private = false;
157
158
let markedVersion;
159
let dompurifyVersion;
160
try {
161
const markedManifestPath = path.join(root, 'src/vs/base/common/marked/cgmanifest.json');
162
const dompurifyManifestPath = path.join(root, 'src/vs/base/browser/dompurify/cgmanifest.json');
163
164
const markedManifest = JSON.parse(fs.readFileSync(markedManifestPath, 'utf8'));
165
const dompurifyManifest = JSON.parse(fs.readFileSync(dompurifyManifestPath, 'utf8'));
166
167
markedVersion = markedManifest.registrations[0].version;
168
dompurifyVersion = dompurifyManifest.registrations[0].version;
169
170
if (!markedVersion || !dompurifyVersion) {
171
throw new Error('Unable to read versions from cgmanifest.json files');
172
}
173
} catch (error) {
174
throw new Error(`Failed to read cgmanifest.json files for monaco-editor-core dependencies: ${error.message}`);
175
}
176
177
setUnsetField(json, 'dependencies', {
178
'marked': markedVersion,
179
'dompurify': dompurifyVersion
180
});
181
182
data.contents = Buffer.from(JSON.stringify(json, null, ' '));
183
this.emit('data', data);
184
}))
185
.pipe(gulp.dest('out-monaco-editor-core')),
186
187
// version.txt
188
gulp.src('build/monaco/version.txt')
189
.pipe(es.through(function (data) {
190
data.contents = Buffer.from(`monaco-editor-core: https://github.com/microsoft/vscode/tree/${sha1}`);
191
this.emit('data', data);
192
}))
193
.pipe(gulp.dest('out-monaco-editor-core')),
194
195
// README.md
196
gulp.src('build/monaco/README-npm.md')
197
.pipe(es.through(function (data) {
198
this.emit('data', new File({
199
path: data.path.replace(/README-npm\.md/, 'README.md'),
200
base: data.base,
201
contents: data.contents
202
}));
203
}))
204
.pipe(gulp.dest('out-monaco-editor-core')),
205
);
206
});
207
208
gulp.task('extract-editor-src',
209
task.series(
210
util.rimraf('out-editor-src'),
211
extractEditorSrcTask
212
)
213
);
214
215
gulp.task('editor-distro',
216
task.series(
217
task.parallel(
218
util.rimraf('out-editor-src'),
219
util.rimraf('out-monaco-editor-core'),
220
),
221
extractEditorSrcTask,
222
compileEditorESMTask,
223
finalEditorResourcesTask
224
)
225
);
226
227
gulp.task('monacodts', task.define('monacodts', () => {
228
const result = monacoapi.execute();
229
fs.writeFileSync(result.filePath, result.content);
230
fs.writeFileSync(path.join(root, 'src/vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
231
return Promise.resolve(true);
232
}));
233
234
//#region monaco type checking
235
236
function createTscCompileTask(watch: boolean) {
237
return () => {
238
return new Promise((resolve, reject) => {
239
const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit'];
240
if (watch) {
241
args.push('-w');
242
}
243
const child = cp.spawn(`node`, args, {
244
cwd: path.join(import.meta.dirname, '..'),
245
// stdio: [null, 'pipe', 'inherit']
246
});
247
const errors: string[] = [];
248
const reporter = createReporter('monaco');
249
250
let report: NodeJS.ReadWriteStream | undefined;
251
const magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
252
253
child.stdout.on('data', data => {
254
let str = String(data);
255
str = str.replace(magic, '').trim();
256
if (str.indexOf('Starting compilation') >= 0 || str.indexOf('File change detected') >= 0) {
257
errors.length = 0;
258
report = reporter.end(false);
259
260
} else if (str.indexOf('Compilation complete') >= 0) {
261
// @ts-ignore
262
report.end();
263
264
} else if (str) {
265
const match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(str);
266
if (match) {
267
// trying to massage the message so that it matches the gulp-tsb error messages
268
// e.g. src/vs/base/common/strings.ts(663,5): error TS2322: Type '1234' is not assignable to type 'string'.
269
const fullpath = path.join(root, match[1]);
270
const message = match[3];
271
reporter(fullpath + message);
272
} else {
273
reporter(str);
274
}
275
}
276
});
277
child.on('exit', resolve);
278
child.on('error', reject);
279
});
280
};
281
}
282
283
export const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true));
284
285
export const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false));
286
287
//#endregion
288
/**
289
* Sets a field on an object only if it's not already set, otherwise throws an error
290
* @param obj The object to modify
291
* @param field The field name to set
292
* @param value The value to set
293
*/
294
function setUnsetField(obj: Record<string, unknown>, field: string, value: unknown) {
295
if (obj[field] !== undefined) {
296
throw new Error(`Field "${field}" is already set (but was expected to not be).`);
297
}
298
obj[field] = value;
299
}
300
301