diff --git a/.github/needs_more_info.yml b/.github/needs_more_info.yml
new file mode 100644
index 00000000000..934e98898d4
--- /dev/null
+++ b/.github/needs_more_info.yml
@@ -0,0 +1,6 @@
+{
+ daysUntilClose: 7,
+ needsMoreInfoLabel: 'needs more info',
+ perform: true,
+ closeComment: 'This issue has been closed automatically because it needs more information and has not had recent activity. Please refer to our [guidelines](https://github.com/Microsoft/vscode/blob/master/CONTRIBUTING.md) for filing issues. Thank you for your contributions.'
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 7e923598730..39b72b995a8 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,34 +1,6 @@
{
"version": "0.1.0",
"configurations": [
- {
- "type": "node",
- "request": "launch",
- "name": "Unit Tests",
- "protocol": "legacy",
- "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
- "runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
- "windows": {
- "runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.exe"
- },
- "linux": {
- "runtimeExecutable": "${workspaceRoot}/.build/electron/code-oss"
- },
- "stopOnEntry": false,
- "args": [
- "--timeout",
- "2000"
- ],
- "cwd": "${workspaceRoot}",
- "env": {
- "ELECTRON_RUN_AS_NODE": "true"
- },
- "sourceMaps": true,
- "outFiles": [
- "${workspaceRoot}/out/**/*.js"
- ],
- "preLaunchTask": "electron"
- },
{
"type": "node",
"request": "launch",
@@ -46,7 +18,6 @@
"name": "Attach to Extension Host",
"protocol": "legacy",
"port": 5870,
- "sourceMaps": true,
"restart": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
@@ -58,7 +29,6 @@
"name": "Attach to Shared Process",
"protocol": "legacy",
"port": 5871,
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -69,7 +39,6 @@
"protocol": "legacy",
"name": "Attach to Search process",
"port": 7890,
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -80,7 +49,6 @@
"name": "Attach to CLI Process",
"protocol": "legacy",
"port": 5874,
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -91,7 +59,6 @@
"name": "Attach to Main Process",
"protocol": "legacy",
"port": 5875,
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -106,7 +73,6 @@
"--extensionDevelopmentPath=${workspaceRoot}/extensions/vscode-api-tests",
"--extensionTestsPath=${workspaceRoot}/extensions/vscode-api-tests/out"
],
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -121,7 +87,6 @@
"--extensionDevelopmentPath=${workspaceRoot}/extensions/vscode-colorize-tests",
"--extensionTestsPath=${workspaceRoot}/extensions/vscode-colorize-tests/out"
],
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
]
@@ -159,10 +124,45 @@
"program": "${workspaceRoot}/extensions/git/node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"cwd": "${workspaceRoot}/extensions/git",
- "sourceMaps": true,
"outFiles": [
"${workspaceRoot}/extensions/git/out/**/*.js"
]
+ },
+ {
+ "name": "Attach to TS Server",
+ "type": "node",
+ "request": "attach",
+ "port": 5859,
+ "protocol": "legacy",
+ "outFiles": [
+ "${workspaceRoot}/extensions/node_modules/typescript/lib/**/*.js"
+ ]
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Unit Tests",
+ "protocol": "legacy",
+ "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
+ "runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
+ "windows": {
+ "runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.exe"
+ },
+ "linux": {
+ "runtimeExecutable": "${workspaceRoot}/.build/electron/code-oss"
+ },
+ "stopOnEntry": false,
+ "args": [
+ "--timeout",
+ "2000"
+ ],
+ "cwd": "${workspaceRoot}",
+ "env": {
+ "ELECTRON_RUN_AS_NODE": "true"
+ },
+ "outFiles": [
+ "${workspaceRoot}/out/**/*.js"
+ ]
}
],
"compounds": [
diff --git a/.vscode/settings.json b/.vscode/settings.json
index ee2a86a54f5..ed5e39baa7f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -6,7 +6,9 @@
".git": true,
".build": true,
"**/.DS_Store": true,
- "build/**/*.js": { "when": "$(basename).ts" }
+ "build/**/*.js": {
+ "when": "$(basename).ts"
+ }
},
"search.exclude": {
"**/node_modules": true,
@@ -17,7 +19,6 @@
"extensions/**/out/**": true
},
"tslint.enable": true,
- "tslint.rulesDirectory": "build/lib/tslint",
"lcov.path": [
"./.build/coverage/lcov.info",
"./.build/coverage-single/lcov.info"
@@ -31,4 +32,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js
index 480077c58cf..1c716b56f99 100644
--- a/build/gulpfile.hygiene.js
+++ b/build/gulpfile.hygiene.js
@@ -40,13 +40,17 @@ const eolFilter = [
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot}',
'!build/{lib,tslintRules}/**/*.js',
'!build/monaco/**',
- '!build/win32/**'
+ '!build/win32/**',
+ '!build/**/*.sh',
+ '!build/tfs/**/*.js',
+ '!**/Dockerfile'
];
const indentationFilter = [
'**',
'!ThirdPartyNotices.txt',
'!**/*.md',
+ '!**/*.ps1',
'!**/*.template',
'!**/*.yml',
'!**/lib/**',
diff --git a/build/gulpfile.js b/build/gulpfile.js
deleted file mode 100644
index c0a5700ec1f..00000000000
--- a/build/gulpfile.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-var gulp = require('gulp');
-var tsb = require('gulp-tsb');
-var util = require('./lib/util');
-var watcher = require('./lib/watch');
-var assign = require('object-assign');
-
-var compilation = tsb.create(assign({ verbose: true }, require('./tsconfig.json').compilerOptions));
-
-gulp.task('compile', function() {
- return gulp.src('**/*.ts', { base: '.' })
- .pipe(compilation())
- .pipe(gulp.dest(''));
-});
-
-gulp.task('watch', function() {
- var src = gulp.src('**/*.ts', { base: '.' });
-
- return watcher('**/*.ts', { base: '.' })
- .pipe(util.incremental(compilation, src))
- .pipe(gulp.dest(''));
-});
-
-gulp.task('default', ['compile']);
diff --git a/build/gulpfile.mixin.js b/build/gulpfile.mixin.js
index 0a80a8a0337..abf3ce4a90c 100644
--- a/build/gulpfile.mixin.js
+++ b/build/gulpfile.mixin.js
@@ -48,32 +48,16 @@ gulp.task('mixin', function () {
.pipe(util.rebase(1));
if (quality) {
- const build = all.pipe(filter('build/**'));
const productJsonFilter = filter('product.json', { restore: true });
- const arch = process.env.VSCODE_ELECTRON_PLATFORM || process.arch;
-
- const vsdaFilter = (function () {
- const filter = [];
- if (process.platform !== 'win32') { filter.push('!**/vsda_win32.node'); }
- if (process.platform !== 'darwin') { filter.push('!**/vsda_darwin.node'); }
- if (process.platform !== 'linux' || arch !== 'x64') { filter.push('!**/vsda_linux64.node'); }
- if (process.platform !== 'linux' || arch === 'x64') { filter.push('!**/vsda_linux32.node'); }
-
- return filter;
- })();
-
const mixin = all
- .pipe(filter(['quality/' + quality + '/**'].concat(vsdaFilter)))
+ .pipe(filter(['quality/' + quality + '/**']))
.pipe(util.rebase(2))
.pipe(productJsonFilter)
.pipe(buffer())
- .pipe(json(function (patch) {
- const original = require('../product.json');
- return assign(original, patch);
- }))
+ .pipe(json(o => assign({}, require('../product.json'), o)))
.pipe(productJsonFilter.restore);
- all = es.merge(build, mixin);
+ all = es.merge(mixin);
}
return all
diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js
index 08a775ce6e6..e73e03c311d 100644
--- a/build/gulpfile.vscode.js
+++ b/build/gulpfile.vscode.js
@@ -31,8 +31,9 @@ const shrinkwrap = require('../npm-shrinkwrap.json');
const crypto = require('crypto');
const i18n = require('./lib/i18n');
+const productDependencies = Object.keys(product.dependencies || {});
const dependencies = Object.keys(shrinkwrap.dependencies)
- .concat(Array.isArray(product.extraNodeModules) ? product.extraNodeModules : []); // additional dependencies from our product configuration
+ .concat(productDependencies); // additional dependencies from our product configuration
const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n));
const nodeModules = ['electron', 'original-fs']
.concat(dependencies)
@@ -41,8 +42,8 @@ const nodeModules = ['electron', 'original-fs']
// Build
const builtInExtensions = [
- { name: 'ms-vscode.node-debug', version: '1.12.14' },
- { name: 'ms-vscode.node-debug2', version: '1.12.4' }
+ { name: 'ms-vscode.node-debug', version: '1.13.7' },
+ { name: 'ms-vscode.node-debug2', version: '1.13.0' }
];
const vscodeEntryPoints = _.flatten([
@@ -59,13 +60,13 @@ const vscodeResources = [
'out-build/bootstrap-amd.js',
'out-build/paths.js',
'out-build/vs/**/*.{svg,png,cur,html}',
+ 'out-build/vs/base/node/startupTimers.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/electron-browser/bootstrap/**',
'out-build/vs/workbench/parts/debug/**/*.json',
'out-build/vs/workbench/parts/execution/**/*.scpt',
- 'out-build/vs/workbench/parts/git/**/*.sh',
'out-build/vs/workbench/parts/html/browser/webview-pre.js',
'out-build/vs/**/markdown.css',
'out-build/vs/workbench/parts/tasks/**/*.json',
@@ -120,7 +121,7 @@ const config = {
name: product.nameLong + ' document',
role: 'Editor',
ostypes: ["TEXT", "utxt", "TUTX", "****"],
- extensions: ["ascx", "asp", "aspx", "bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "bat", "bowerrc", "c", "cc", "clj", "cljs", "cljx", "clojure", "cmd", "coffee", "config", "cpp", "cs", "cshtml", "csproj", "css", "csx", "ctp", "cxx", "dockerfile", "dot", "dtd", "editorconfig", "edn", "eyaml", "eyml", "fs", "fsi", "fsscript", "fsx", "gemspec", "gitattributes", "gitconfig", "gitignore", "go", "h", "handlebars", "hbs", "hh", "hpp", "htm", "html", "hxx", "ini", "jade", "jav", "java", "js", "jscsrc", "jshintrc", "jshtm", "json", "jsp", "less", "lua", "m", "makefile", "markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn", "ml", "mli", "php", "phtml", "pl", "pl6", "pm", "pm6", "pod", "pp", "profile", "properties", "ps1", "psd1", "psgi", "psm1", "py", "r", "rb", "rhistory", "rprofile", "rs", "rt", "scss", "sh", "shtml", "sql", "svg", "svgz", "t", "ts", "txt", "vb", "wxi", "wxl", "wxs", "xaml", "xml", "yaml", "yml", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"],
+ extensions: ["ascx", "asp", "aspx", "bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "bat", "bowerrc", "c", "cc", "clj", "cljs", "cljx", "clojure", "cmd", "coffee", "config", "cpp", "cs", "cshtml", "csproj", "css", "csx", "ctp", "cxx", "dockerfile", "dot", "dtd", "editorconfig", "edn", "eyaml", "eyml", "fs", "fsi", "fsscript", "fsx", "gemspec", "gitattributes", "gitconfig", "gitignore", "go", "h", "handlebars", "hbs", "hh", "hpp", "htm", "html", "hxx", "ini", "jade", "jav", "java", "js", "jscsrc", "jshintrc", "jshtm", "json", "jsp", "less", "lua", "m", "makefile", "markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn", "ml", "mli", "php", "phtml", "pl", "pl6", "pm", "pm6", "pod", "pp", "profile", "properties", "ps1", "psd1", "psgi", "psm1", "py", "r", "rb", "rhistory", "rprofile", "rs", "rt", "scss", "sh", "shtml", "sql", "svg", "svgz", "t", "ts", "txt", "vb", "wxi", "wxl", "wxs", "xaml", "xcodeproj", "xcworkspace", "xml", "yaml", "yml", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"],
iconFile: 'resources/darwin/code_file.icns'
}],
darwinBundleURLTypes: [{
@@ -131,25 +132,33 @@ const config = {
darwinCredits: darwinCreditsTemplate ? new Buffer(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
- token: process.env['GITHUB_TOKEN'] || void 0
+ token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
+ repo: product.electronRepository || void 0
};
+function getElectron(arch) {
+ return () => {
+ const electronOpts = _.extend({}, config, {
+ platform: process.platform,
+ arch,
+ ffmpegChromium: true,
+ keepDefaultApp: true
+ });
+
+ return gulp.src('package.json')
+ .pipe(json({ name: product.nameShort }))
+ .pipe(electron(electronOpts))
+ .pipe(filter(['**', '!**/app/package.json']))
+ .pipe(vfs.dest('.build/electron'));
+ };
+}
+
gulp.task('clean-electron', util.rimraf('.build/electron'));
+gulp.task('electron', ['clean-electron'], getElectron(process.arch));
+gulp.task('electron-ia32', ['clean-electron'], getElectron('ia32'));
+gulp.task('electron-x64', ['clean-electron'], getElectron('x64'));
-gulp.task('electron', ['clean-electron'], () => {
- const platform = process.platform;
- const arch = process.env.VSCODE_ELECTRON_PLATFORM || (platform === 'win32' ? 'ia32' : process.arch);
- const opts = _.extend({}, config, { platform, arch, ffmpegChromium: true, keepDefaultApp: true });
- const name = product.nameShort;
-
- return gulp.src('package.json')
- .pipe(json({ name }))
- .pipe(electron(opts))
- .pipe(filter(['**', '!**/app/package.json']))
- .pipe(vfs.dest('.build/electron'));
-});
-
-const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
+const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita', 'ptb'];
/**
* Compute checksums for some files.
@@ -190,7 +199,6 @@ function packageTask(platform, arch, opts) {
const destination = path.join(path.dirname(root), 'VSCode') + (platform ? '-' + platform : '') + (arch ? '-' + arch : '');
platform = platform || process.platform;
- arch = platform === 'win32' ? 'ia32' : arch;
return () => {
const out = opts.minified ? 'out-vscode-min' : 'out-vscode';
@@ -273,7 +281,8 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('v8-profiler', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
- .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/**']));
+ .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/**']))
+ .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']));
let all = es.merge(
packageJsonStream,
@@ -323,19 +332,22 @@ function packageTask(platform, arch, opts) {
const buildRoot = path.dirname(root);
-gulp.task('clean-vscode-win32', util.rimraf(path.join(buildRoot, 'VSCode-win32')));
+gulp.task('clean-vscode-win32-ia32', util.rimraf(path.join(buildRoot, 'VSCode-win32-ia32')));
+gulp.task('clean-vscode-win32-x64', util.rimraf(path.join(buildRoot, 'VSCode-win32-x64')));
gulp.task('clean-vscode-darwin', util.rimraf(path.join(buildRoot, 'VSCode-darwin')));
gulp.task('clean-vscode-linux-ia32', util.rimraf(path.join(buildRoot, 'VSCode-linux-ia32')));
gulp.task('clean-vscode-linux-x64', util.rimraf(path.join(buildRoot, 'VSCode-linux-x64')));
gulp.task('clean-vscode-linux-arm', util.rimraf(path.join(buildRoot, 'VSCode-linux-arm')));
-gulp.task('vscode-win32', ['optimize-vscode', 'clean-vscode-win32'], packageTask('win32'));
+gulp.task('vscode-win32-ia32', ['optimize-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32'));
+gulp.task('vscode-win32-x64', ['optimize-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64'));
gulp.task('vscode-darwin', ['optimize-vscode', 'clean-vscode-darwin'], packageTask('darwin'));
gulp.task('vscode-linux-ia32', ['optimize-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32'));
gulp.task('vscode-linux-x64', ['optimize-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64'));
gulp.task('vscode-linux-arm', ['optimize-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm'));
-gulp.task('vscode-win32-min', ['minify-vscode', 'clean-vscode-win32'], packageTask('win32', null, { minified: true }));
+gulp.task('vscode-win32-ia32-min', ['minify-vscode', 'clean-vscode-win32-ia32'], packageTask('win32', 'ia32', { minified: true }));
+gulp.task('vscode-win32-x64-min', ['minify-vscode', 'clean-vscode-win32-x64'], packageTask('win32', 'x64', { minified: true }));
gulp.task('vscode-darwin-min', ['minify-vscode', 'clean-vscode-darwin'], packageTask('darwin', null, { minified: true }));
gulp.task('vscode-linux-ia32-min', ['minify-vscode', 'clean-vscode-linux-ia32'], packageTask('linux', 'ia32', { minified: true }));
gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], packageTask('linux', 'x64', { minified: true }));
@@ -351,7 +363,8 @@ const vscodeLanguages = [
'fr',
'es',
'ru',
- 'it'
+ 'it',
+ 'pt-br'
];
const setupDefaultLanguages = [
'zh-hans',
@@ -363,7 +376,7 @@ const apiHostname = process.env.TRANSIFEX_API_URL;
const apiName = process.env.TRANSIFEX_API_NAME;
const apiToken = process.env.TRANSIFEX_API_TOKEN;
-gulp.task('vscode-translations-push', ['optimize-vscode'], function() {
+gulp.task('vscode-translations-push', ['optimize-vscode'], function () {
const pathToMetadata = './out-vscode/nls.metadata.json';
const pathToExtensions = './extensions/**/*.nls.json';
const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
@@ -375,7 +388,7 @@ gulp.task('vscode-translations-push', ['optimize-vscode'], function() {
).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken));
});
-gulp.task('vscode-translations-pull', function() {
+gulp.task('vscode-translations-pull', function () {
return es.merge(
i18n.pullXlfFiles('vscode-editor', apiHostname, apiName, apiToken, vscodeLanguages),
i18n.pullXlfFiles('vscode-workbench', apiHostname, apiName, apiToken, vscodeLanguages),
@@ -384,7 +397,7 @@ gulp.task('vscode-translations-pull', function() {
).pipe(vfs.dest('../vscode-localization'));
});
-gulp.task('vscode-translations-import', function() {
+gulp.task('vscode-translations-import', function () {
return gulp.src('../vscode-localization/**/*.xlf').pipe(i18n.prepareJsonFiles()).pipe(vfs.dest('./i18n'));
});
diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js
index cc8f75a0c9c..54c73a538c2 100644
--- a/build/gulpfile.vscode.linux.js
+++ b/build/gulpfile.vscode.linux.js
@@ -259,20 +259,16 @@ gulp.task('clean-vscode-linux-ia32-rpm', util.rimraf('.build/linux/rpm/i386'));
gulp.task('clean-vscode-linux-x64-rpm', util.rimraf('.build/linux/rpm/x86_64'));
gulp.task('clean-vscode-linux-arm-rpm', util.rimraf('.build/linux/rpm/armhf'));
-// TODO@joao TODO@daniel
-// commented out the dependencies to the actual building of VS Code
-// we gotta make sure those targets run before these run, in our TFS builds
-
-gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'/*, 'vscode-linux-ia32-min'*/], prepareDebPackage('ia32'));
-gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'/*, 'vscode-linux-x64-min'*/], prepareDebPackage('x64'));
-gulp.task('vscode-linux-arm-prepare-deb', ['clean-vscode-linux-arm-deb'/*, 'vscode-linux-arm-min'*/], prepareDebPackage('arm'));
+gulp.task('vscode-linux-ia32-prepare-deb', ['clean-vscode-linux-ia32-deb'], prepareDebPackage('ia32'));
+gulp.task('vscode-linux-x64-prepare-deb', ['clean-vscode-linux-x64-deb'], prepareDebPackage('x64'));
+gulp.task('vscode-linux-arm-prepare-deb', ['clean-vscode-linux-arm-deb'], prepareDebPackage('arm'));
gulp.task('vscode-linux-ia32-build-deb', ['vscode-linux-ia32-prepare-deb'], buildDebPackage('ia32'));
gulp.task('vscode-linux-x64-build-deb', ['vscode-linux-x64-prepare-deb'], buildDebPackage('x64'));
gulp.task('vscode-linux-arm-build-deb', ['vscode-linux-arm-prepare-deb'], buildDebPackage('arm'));
-gulp.task('vscode-linux-ia32-prepare-rpm', ['clean-vscode-linux-ia32-rpm'/*, 'vscode-linux-ia32-min'*/], prepareRpmPackage('ia32'));
-gulp.task('vscode-linux-x64-prepare-rpm', ['clean-vscode-linux-x64-rpm'/*, 'vscode-linux-x64-min'*/], prepareRpmPackage('x64'));
-gulp.task('vscode-linux-arm-prepare-rpm', ['clean-vscode-linux-arm-rpm'/*, 'vscode-linux-arm-min'*/], prepareRpmPackage('arm'));
+gulp.task('vscode-linux-ia32-prepare-rpm', ['clean-vscode-linux-ia32-rpm'], prepareRpmPackage('ia32'));
+gulp.task('vscode-linux-x64-prepare-rpm', ['clean-vscode-linux-x64-rpm'], prepareRpmPackage('x64'));
+gulp.task('vscode-linux-arm-prepare-rpm', ['clean-vscode-linux-arm-rpm'], prepareRpmPackage('arm'));
gulp.task('vscode-linux-ia32-build-rpm', ['vscode-linux-ia32-prepare-rpm'], buildRpmPackage('ia32'));
gulp.task('vscode-linux-x64-build-rpm', ['vscode-linux-x64-prepare-rpm'], buildRpmPackage('x64'));
gulp.task('vscode-linux-arm-build-rpm', ['vscode-linux-arm-prepare-rpm'], buildRpmPackage('arm'));
@@ -281,9 +277,9 @@ gulp.task('clean-vscode-linux-ia32-flatpak', util.rimraf('.build/linux/flatpak/i
gulp.task('clean-vscode-linux-x64-flatpak', util.rimraf('.build/linux/flatpak/x86_64'));
gulp.task('clean-vscode-linux-arm-flatpak', util.rimraf('.build/linux/flatpak/arm'));
-gulp.task('vscode-linux-ia32-prepare-flatpak', ['clean-vscode-linux-ia32-flatpak'/*, 'vscode-linux-ia32-min'*/], prepareFlatpak('ia32'));
-gulp.task('vscode-linux-x64-prepare-flatpak', ['clean-vscode-linux-x64-flatpak'/*, 'vscode-linux-x64-min'*/], prepareFlatpak('x64'));
-gulp.task('vscode-linux-arm-prepare-flatpak', ['clean-vscode-linux-arm-flatpak'/*, 'vscode-linux-arm-min'*/], prepareFlatpak('arm'));
+gulp.task('vscode-linux-ia32-prepare-flatpak', ['clean-vscode-linux-ia32-flatpak'], prepareFlatpak('ia32'));
+gulp.task('vscode-linux-x64-prepare-flatpak', ['clean-vscode-linux-x64-flatpak'], prepareFlatpak('x64'));
+gulp.task('vscode-linux-arm-prepare-flatpak', ['clean-vscode-linux-arm-flatpak'], prepareFlatpak('arm'));
gulp.task('vscode-linux-ia32-flatpak', ['vscode-linux-ia32-prepare-flatpak'], buildFlatpak('ia32'));
gulp.task('vscode-linux-x64-flatpak', ['vscode-linux-x64-prepare-flatpak'], buildFlatpak('x64'));
diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js
index 427e4e52538..a4ebd283ee0 100644
--- a/build/gulpfile.vscode.win32.js
+++ b/build/gulpfile.vscode.win32.js
@@ -9,12 +9,16 @@ const gulp = require('gulp');
const path = require('path');
const assert = require('assert');
const cp = require('child_process');
+const _7z = require('7zip')['7z'];
const util = require('./lib/util');
const pkg = require('../package.json');
const product = require('../product.json');
const repoPath = path.dirname(__dirname);
-const buildPath = path.join(path.dirname(repoPath), 'VSCode-win32');
+const buildPath = arch => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`);
+const zipDir = arch => path.join(repoPath, '.build', `win32-${arch}`, 'archive');
+const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`);
+const setupDir = arch => path.join(repoPath, '.build', `win32-${arch}`, 'setup');
const issPath = path.join(__dirname, 'win32', 'code.iss');
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
@@ -24,9 +28,9 @@ function packageInnoSetup(iss, options, cb) {
const definitions = options.definitions || {};
const keys = Object.keys(definitions);
- keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${ key }' in Inno Setup package step`));
+ keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${key}' in Inno Setup package step`));
- const defs = keys.map(key => `/d${ key }=${ definitions[key] }`);
+ const defs = keys.map(key => `/d${key}=${definitions[key]}`);
const args = [iss].concat(defs);
cp.spawn(innoSetupPath, args, { stdio: 'inherit' })
@@ -34,26 +38,48 @@ function packageInnoSetup(iss, options, cb) {
.on('exit', () => cb(null));
}
-function buildWin32Setup(cb) {
- const definitions = {
- NameLong: product.nameLong,
- NameShort: product.nameShort,
- DirName: product.win32DirName,
- Version: pkg.version,
- RawVersion: pkg.version.replace(/-\w+$/, ''),
- NameVersion: product.win32NameVersion,
- ExeBasename: product.nameShort,
- RegValueName: product.win32RegValueName,
- ShellNameShort: product.win32ShellNameShort,
- AppMutex: product.win32MutexName,
- AppId: product.win32AppId,
- AppUserId: product.win32AppUserModelId,
- SourceDir: buildPath,
- RepoDir: repoPath
- };
+function buildWin32Setup(arch) {
+ return cb => {
+ const definitions = {
+ NameLong: product.nameLong,
+ NameShort: product.nameShort,
+ DirName: product.win32DirName,
+ Version: pkg.version,
+ RawVersion: pkg.version.replace(/-\w+$/, ''),
+ NameVersion: product.win32NameVersion,
+ ExeBasename: product.nameShort,
+ RegValueName: product.win32RegValueName,
+ ShellNameShort: product.win32ShellNameShort,
+ AppMutex: product.win32MutexName,
+ AppId: product.win32AppId,
+ AppUserId: product.win32AppUserModelId,
+ SourceDir: buildPath(arch),
+ RepoDir: repoPath,
+ OutputDir: setupDir(arch)
+ };
- packageInnoSetup(issPath, { definitions }, cb);
+ packageInnoSetup(issPath, { definitions }, cb);
+ };
}
-gulp.task('clean-vscode-win32-setup', util.rimraf('.build/win32/setup'));
-gulp.task('vscode-win32-setup', ['clean-vscode-win32-setup'], buildWin32Setup);
+gulp.task('clean-vscode-win32-ia32-setup', util.rimraf(setupDir('ia32')));
+gulp.task('vscode-win32-ia32-setup', ['clean-vscode-win32-ia32-setup'], buildWin32Setup('ia32'));
+
+gulp.task('clean-vscode-win32-x64-setup', util.rimraf(setupDir('x64')));
+gulp.task('vscode-win32-x64-setup', ['clean-vscode-win32-x64-setup'], buildWin32Setup('x64'));
+
+function archiveWin32Setup(arch) {
+ return cb => {
+ const args = ['a', '-tzip', zipPath(arch), buildPath(arch), '-r'];
+
+ cp.spawn(_7z, args, { stdio: 'inherit' })
+ .on('error', cb)
+ .on('exit', () => cb(null));
+ };
+}
+
+gulp.task('clean-vscode-win32-ia32-archive', util.rimraf(zipDir('ia32')));
+gulp.task('vscode-win32-ia32-archive', ['clean-vscode-win32-ia32-archive'], archiveWin32Setup('ia32'));
+
+gulp.task('clean-vscode-win32-x64-archive', util.rimraf(zipDir('x64')));
+gulp.task('vscode-win32-x64-archive', ['clean-vscode-win32-x64-archive'], archiveWin32Setup('x64'));
diff --git a/build/lib/bundle.js b/build/lib/bundle.js
index 8914c89c919..5a51bde2156 100644
--- a/build/lib/bundle.js
+++ b/build/lib/bundle.js
@@ -1,453 +1,453 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var fs = require("fs");
-var path = require("path");
-var vm = require("vm");
-/**
- * Bundle `entryPoints` given config `config`.
- */
-function bundle(entryPoints, config, callback) {
- var entryPointsMap = {};
- entryPoints.forEach(function (module) {
- entryPointsMap[module.name] = module;
- });
- var allMentionedModulesMap = {};
- entryPoints.forEach(function (module) {
- allMentionedModulesMap[module.name] = true;
- (module.include || []).forEach(function (includedModule) {
- allMentionedModulesMap[includedModule] = true;
- });
- (module.exclude || []).forEach(function (excludedModule) {
- allMentionedModulesMap[excludedModule] = true;
- });
- });
- var code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
- var r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
- var loaderModule = { exports: {} };
- r.call({}, require, loaderModule, loaderModule.exports);
- var loader = loaderModule.exports;
- config.isBuild = true;
- loader.config(config);
- loader(['require'], function (localRequire) {
- var resolvePath = function (path) {
- var r = localRequire.toUrl(path);
- if (!/\.js/.test(r)) {
- return r + '.js';
- }
- return r;
- };
- for (var moduleId in entryPointsMap) {
- var entryPoint = entryPointsMap[moduleId];
- if (entryPoint.append) {
- entryPoint.append = entryPoint.append.map(resolvePath);
- }
- if (entryPoint.prepend) {
- entryPoint.prepend = entryPoint.prepend.map(resolvePath);
- }
- }
- });
- loader(Object.keys(allMentionedModulesMap), function () {
- var modules = loader.getBuildInfo();
- var partialResult = emitEntryPoints(modules, entryPointsMap);
- var cssInlinedResources = loader('vs/css').getInlinedResources();
- callback(null, {
- files: partialResult.files,
- cssInlinedResources: cssInlinedResources,
- bundleData: partialResult.bundleData
- });
- }, function (err) { return callback(err, null); });
-}
-exports.bundle = bundle;
-function emitEntryPoints(modules, entryPoints) {
- var modulesMap = {};
- modules.forEach(function (m) {
- modulesMap[m.id] = m;
- });
- var modulesGraph = {};
- modules.forEach(function (m) {
- modulesGraph[m.id] = m.dependencies;
- });
- var sortedModules = topologicalSort(modulesGraph);
- var result = [];
- var usedPlugins = {};
- var bundleData = {
- graph: modulesGraph,
- bundles: {}
- };
- Object.keys(entryPoints).forEach(function (moduleToBundle) {
- var info = entryPoints[moduleToBundle];
- var rootNodes = [moduleToBundle].concat(info.include || []);
- var allDependencies = visit(rootNodes, modulesGraph);
- var excludes = ['require', 'exports', 'module'].concat(info.exclude || []);
- excludes.forEach(function (excludeRoot) {
- var allExcludes = visit([excludeRoot], modulesGraph);
- Object.keys(allExcludes).forEach(function (exclude) {
- delete allDependencies[exclude];
- });
- });
- var includedModules = sortedModules.filter(function (module) {
- return allDependencies[module];
- });
- bundleData.bundles[moduleToBundle] = includedModules;
- var res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend, info.append, info.dest);
- result = result.concat(res.files);
- for (var pluginName in res.usedPlugins) {
- usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
- }
- });
- Object.keys(usedPlugins).forEach(function (pluginName) {
- var plugin = usedPlugins[pluginName];
- if (typeof plugin.finishBuild === 'function') {
- var write = function (filename, contents) {
- result.push({
- dest: filename,
- sources: [{
- path: null,
- contents: contents
- }]
- });
- };
- plugin.finishBuild(write);
- }
- });
- return {
- // TODO@TS 2.1.2
- files: extractStrings(removeDuplicateTSBoilerplate(result)),
- bundleData: bundleData
- };
-}
-function extractStrings(destFiles) {
- var parseDefineCall = function (moduleMatch, depsMatch) {
- var module = moduleMatch.replace(/^"|"$/g, '');
- var deps = depsMatch.split(',');
- deps = deps.map(function (dep) {
- dep = dep.trim();
- dep = dep.replace(/^"|"$/g, '');
- dep = dep.replace(/^'|'$/g, '');
- var prefix = null;
- var _path = null;
- var pieces = dep.split('!');
- if (pieces.length > 1) {
- prefix = pieces[0] + '!';
- _path = pieces[1];
- }
- else {
- prefix = '';
- _path = pieces[0];
- }
- if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
- var res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
- return prefix + res;
- }
- return prefix + _path;
- });
- return {
- module: module,
- deps: deps
- };
- };
- destFiles.forEach(function (destFile, index) {
- if (!/\.js$/.test(destFile.dest)) {
- return;
- }
- if (/\.nls\.js$/.test(destFile.dest)) {
- return;
- }
- // Do one pass to record the usage counts for each module id
- var useCounts = {};
- destFile.sources.forEach(function (source) {
- var matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
- if (!matches) {
- return;
- }
- var defineCall = parseDefineCall(matches[1], matches[2]);
- useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
- defineCall.deps.forEach(function (dep) {
- useCounts[dep] = (useCounts[dep] || 0) + 1;
- });
- });
- var sortedByUseModules = Object.keys(useCounts);
- sortedByUseModules.sort(function (a, b) {
- return useCounts[b] - useCounts[a];
- });
- var replacementMap = {};
- sortedByUseModules.forEach(function (module, index) {
- replacementMap[module] = index;
- });
- destFile.sources.forEach(function (source) {
- source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, function (_, moduleMatch, depsMatch) {
- var defineCall = parseDefineCall(moduleMatch, depsMatch);
- return "define(__m[" + replacementMap[defineCall.module] + "/*" + defineCall.module + "*/], __M([" + defineCall.deps.map(function (dep) { return replacementMap[dep] + '/*' + dep + '*/'; }).join(',') + "])";
- });
- });
- destFile.sources.unshift({
- path: null,
- contents: [
- '(function() {',
- "var __m = " + JSON.stringify(sortedByUseModules) + ";",
- "var __M = function(deps) {",
- " var result = [];",
- " for (var i = 0, len = deps.length; i < len; i++) {",
- " result[i] = __m[deps[i]];",
- " }",
- " return result;",
- "};"
- ].join('\n')
- });
- destFile.sources.push({
- path: null,
- contents: '}).call(this);'
- });
- });
- return destFiles;
-}
-function removeDuplicateTSBoilerplate(destFiles) {
- // Taken from typescript compiler => emitFiles
- var BOILERPLATE = [
- { start: /^var __extends/, end: /^}\)\(\);$/ },
- { start: /^var __assign/, end: /^};$/ },
- { start: /^var __decorate/, end: /^};$/ },
- { start: /^var __metadata/, end: /^};$/ },
- { start: /^var __param/, end: /^};$/ },
- { start: /^var __awaiter/, end: /^};$/ },
- ];
- destFiles.forEach(function (destFile) {
- var SEEN_BOILERPLATE = [];
- destFile.sources.forEach(function (source) {
- var lines = source.contents.split(/\r\n|\n|\r/);
- var newLines = [];
- var IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- if (IS_REMOVING_BOILERPLATE) {
- newLines.push('');
- if (END_BOILERPLATE.test(line)) {
- IS_REMOVING_BOILERPLATE = false;
- }
- }
- else {
- for (var j = 0; j < BOILERPLATE.length; j++) {
- var boilerplate = BOILERPLATE[j];
- if (boilerplate.start.test(line)) {
- if (SEEN_BOILERPLATE[j]) {
- IS_REMOVING_BOILERPLATE = true;
- END_BOILERPLATE = boilerplate.end;
- }
- else {
- SEEN_BOILERPLATE[j] = true;
- }
- }
- }
- if (IS_REMOVING_BOILERPLATE) {
- newLines.push('');
- }
- else {
- newLines.push(line);
- }
- }
- }
- source.contents = newLines.join('\n');
- });
- });
- return destFiles;
-}
-function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend, append, dest) {
- if (!dest) {
- dest = entryPoint + '.js';
- }
- var mainResult = {
- sources: [],
- dest: dest
- }, results = [mainResult];
- var usedPlugins = {};
- var getLoaderPlugin = function (pluginName) {
- if (!usedPlugins[pluginName]) {
- usedPlugins[pluginName] = modulesMap[pluginName].exports;
- }
- return usedPlugins[pluginName];
- };
- includedModules.forEach(function (c) {
- var bangIndex = c.indexOf('!');
- if (bangIndex >= 0) {
- var pluginName = c.substr(0, bangIndex);
- var plugin = getLoaderPlugin(pluginName);
- mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
- return;
- }
- var module = modulesMap[c];
- if (module.path === 'empty:') {
- return;
- }
- var contents = readFileAndRemoveBOM(module.path);
- if (module.shim) {
- mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
- }
- else {
- mainResult.sources.push(emitNamedModule(c, deps[c], module.defineLocation, module.path, contents));
- }
- });
- Object.keys(usedPlugins).forEach(function (pluginName) {
- var plugin = usedPlugins[pluginName];
- if (typeof plugin.writeFile === 'function') {
- var req = (function () {
- throw new Error('no-no!');
- });
- req.toUrl = function (something) { return something; };
- var write = function (filename, contents) {
- results.push({
- dest: filename,
- sources: [{
- path: null,
- contents: contents
- }]
- });
- };
- plugin.writeFile(pluginName, entryPoint, req, write, {});
- }
- });
- var toIFile = function (path) {
- var contents = readFileAndRemoveBOM(path);
- return {
- path: path,
- contents: contents
- };
- };
- var toPrepend = (prepend || []).map(toIFile);
- var toAppend = (append || []).map(toIFile);
- mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
- return {
- files: results,
- usedPlugins: usedPlugins
- };
-}
-function readFileAndRemoveBOM(path) {
- var BOM_CHAR_CODE = 65279;
- var contents = fs.readFileSync(path, 'utf8');
- // Remove BOM
- if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
- contents = contents.substring(1);
- }
- return contents;
-}
-function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
- var result = '';
- if (typeof plugin.write === 'function') {
- var write = (function (what) {
- result += what;
- });
- write.getEntryPoint = function () {
- return entryPoint;
- };
- write.asModule = function (moduleId, code) {
- code = code.replace(/^define\(/, 'define("' + moduleId + '",');
- result += code;
- };
- plugin.write(pluginName, moduleName, write);
- }
- return {
- path: null,
- contents: result
- };
-}
-function emitNamedModule(moduleId, myDeps, defineCallPosition, path, contents) {
- // `defineCallPosition` is the position in code: |define()
- var defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
- // `parensOffset` is the position in code: define|()
- var parensOffset = contents.indexOf('(', defineCallOffset);
- var insertStr = '"' + moduleId + '", ';
- return {
- path: path,
- contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1)
- };
-}
-function emitShimmedModule(moduleId, myDeps, factory, path, contents) {
- var strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
- var strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
- return {
- path: path,
- contents: contents + '\n;\n' + strDefine
- };
-}
-/**
- * Convert a position (line:col) to (offset) in string `str`
- */
-function positionToOffset(str, desiredLine, desiredCol) {
- if (desiredLine === 1) {
- return desiredCol - 1;
- }
- var line = 1, lastNewLineOffset = -1;
- do {
- if (desiredLine === line) {
- return lastNewLineOffset + 1 + desiredCol - 1;
- }
- lastNewLineOffset = str.indexOf('\n', lastNewLineOffset + 1);
- line++;
- } while (lastNewLineOffset >= 0);
- return -1;
-}
-/**
- * Return a set of reachable nodes in `graph` starting from `rootNodes`
- */
-function visit(rootNodes, graph) {
- var result = {}, queue = rootNodes;
- rootNodes.forEach(function (node) {
- result[node] = true;
- });
- while (queue.length > 0) {
- var el = queue.shift();
- var myEdges = graph[el] || [];
- myEdges.forEach(function (toNode) {
- if (!result[toNode]) {
- result[toNode] = true;
- queue.push(toNode);
- }
- });
- }
- return result;
-}
-/**
- * Perform a topological sort on `graph`
- */
-function topologicalSort(graph) {
- var allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {};
- Object.keys(graph).forEach(function (fromNode) {
- allNodes[fromNode] = true;
- outgoingEdgeCount[fromNode] = graph[fromNode].length;
- graph[fromNode].forEach(function (toNode) {
- allNodes[toNode] = true;
- outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0;
- inverseEdges[toNode] = inverseEdges[toNode] || [];
- inverseEdges[toNode].push(fromNode);
- });
- });
- // https://en.wikipedia.org/wiki/Topological_sorting
- var S = [], L = [];
- Object.keys(allNodes).forEach(function (node) {
- if (outgoingEdgeCount[node] === 0) {
- delete outgoingEdgeCount[node];
- S.push(node);
- }
- });
- while (S.length > 0) {
- // Ensure the exact same order all the time with the same inputs
- S.sort();
- var n = S.shift();
- L.push(n);
- var myInverseEdges = inverseEdges[n] || [];
- myInverseEdges.forEach(function (m) {
- outgoingEdgeCount[m]--;
- if (outgoingEdgeCount[m] === 0) {
- delete outgoingEdgeCount[m];
- S.push(m);
- }
- });
- }
- if (Object.keys(outgoingEdgeCount).length > 0) {
- throw new Error('Cannot do topological sort on cyclic graph, remaining nodes: ' + Object.keys(outgoingEdgeCount));
- }
- return L;
-}
+"use strict";
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+Object.defineProperty(exports, "__esModule", { value: true });
+var fs = require("fs");
+var path = require("path");
+var vm = require("vm");
+/**
+ * Bundle `entryPoints` given config `config`.
+ */
+function bundle(entryPoints, config, callback) {
+ var entryPointsMap = {};
+ entryPoints.forEach(function (module) {
+ entryPointsMap[module.name] = module;
+ });
+ var allMentionedModulesMap = {};
+ entryPoints.forEach(function (module) {
+ allMentionedModulesMap[module.name] = true;
+ (module.include || []).forEach(function (includedModule) {
+ allMentionedModulesMap[includedModule] = true;
+ });
+ (module.exclude || []).forEach(function (excludedModule) {
+ allMentionedModulesMap[excludedModule] = true;
+ });
+ });
+ var code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
+ var r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
+ var loaderModule = { exports: {} };
+ r.call({}, require, loaderModule, loaderModule.exports);
+ var loader = loaderModule.exports;
+ config.isBuild = true;
+ loader.config(config);
+ loader(['require'], function (localRequire) {
+ var resolvePath = function (path) {
+ var r = localRequire.toUrl(path);
+ if (!/\.js/.test(r)) {
+ return r + '.js';
+ }
+ return r;
+ };
+ for (var moduleId in entryPointsMap) {
+ var entryPoint = entryPointsMap[moduleId];
+ if (entryPoint.append) {
+ entryPoint.append = entryPoint.append.map(resolvePath);
+ }
+ if (entryPoint.prepend) {
+ entryPoint.prepend = entryPoint.prepend.map(resolvePath);
+ }
+ }
+ });
+ loader(Object.keys(allMentionedModulesMap), function () {
+ var modules = loader.getBuildInfo();
+ var partialResult = emitEntryPoints(modules, entryPointsMap);
+ var cssInlinedResources = loader('vs/css').getInlinedResources();
+ callback(null, {
+ files: partialResult.files,
+ cssInlinedResources: cssInlinedResources,
+ bundleData: partialResult.bundleData
+ });
+ }, function (err) { return callback(err, null); });
+}
+exports.bundle = bundle;
+function emitEntryPoints(modules, entryPoints) {
+ var modulesMap = {};
+ modules.forEach(function (m) {
+ modulesMap[m.id] = m;
+ });
+ var modulesGraph = {};
+ modules.forEach(function (m) {
+ modulesGraph[m.id] = m.dependencies;
+ });
+ var sortedModules = topologicalSort(modulesGraph);
+ var result = [];
+ var usedPlugins = {};
+ var bundleData = {
+ graph: modulesGraph,
+ bundles: {}
+ };
+ Object.keys(entryPoints).forEach(function (moduleToBundle) {
+ var info = entryPoints[moduleToBundle];
+ var rootNodes = [moduleToBundle].concat(info.include || []);
+ var allDependencies = visit(rootNodes, modulesGraph);
+ var excludes = ['require', 'exports', 'module'].concat(info.exclude || []);
+ excludes.forEach(function (excludeRoot) {
+ var allExcludes = visit([excludeRoot], modulesGraph);
+ Object.keys(allExcludes).forEach(function (exclude) {
+ delete allDependencies[exclude];
+ });
+ });
+ var includedModules = sortedModules.filter(function (module) {
+ return allDependencies[module];
+ });
+ bundleData.bundles[moduleToBundle] = includedModules;
+ var res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend, info.append, info.dest);
+ result = result.concat(res.files);
+ for (var pluginName in res.usedPlugins) {
+ usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
+ }
+ });
+ Object.keys(usedPlugins).forEach(function (pluginName) {
+ var plugin = usedPlugins[pluginName];
+ if (typeof plugin.finishBuild === 'function') {
+ var write = function (filename, contents) {
+ result.push({
+ dest: filename,
+ sources: [{
+ path: null,
+ contents: contents
+ }]
+ });
+ };
+ plugin.finishBuild(write);
+ }
+ });
+ return {
+ // TODO@TS 2.1.2
+ files: extractStrings(removeDuplicateTSBoilerplate(result)),
+ bundleData: bundleData
+ };
+}
+function extractStrings(destFiles) {
+ var parseDefineCall = function (moduleMatch, depsMatch) {
+ var module = moduleMatch.replace(/^"|"$/g, '');
+ var deps = depsMatch.split(',');
+ deps = deps.map(function (dep) {
+ dep = dep.trim();
+ dep = dep.replace(/^"|"$/g, '');
+ dep = dep.replace(/^'|'$/g, '');
+ var prefix = null;
+ var _path = null;
+ var pieces = dep.split('!');
+ if (pieces.length > 1) {
+ prefix = pieces[0] + '!';
+ _path = pieces[1];
+ }
+ else {
+ prefix = '';
+ _path = pieces[0];
+ }
+ if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
+ var res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
+ return prefix + res;
+ }
+ return prefix + _path;
+ });
+ return {
+ module: module,
+ deps: deps
+ };
+ };
+ destFiles.forEach(function (destFile, index) {
+ if (!/\.js$/.test(destFile.dest)) {
+ return;
+ }
+ if (/\.nls\.js$/.test(destFile.dest)) {
+ return;
+ }
+ // Do one pass to record the usage counts for each module id
+ var useCounts = {};
+ destFile.sources.forEach(function (source) {
+ var matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
+ if (!matches) {
+ return;
+ }
+ var defineCall = parseDefineCall(matches[1], matches[2]);
+ useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
+ defineCall.deps.forEach(function (dep) {
+ useCounts[dep] = (useCounts[dep] || 0) + 1;
+ });
+ });
+ var sortedByUseModules = Object.keys(useCounts);
+ sortedByUseModules.sort(function (a, b) {
+ return useCounts[b] - useCounts[a];
+ });
+ var replacementMap = {};
+ sortedByUseModules.forEach(function (module, index) {
+ replacementMap[module] = index;
+ });
+ destFile.sources.forEach(function (source) {
+ source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, function (_, moduleMatch, depsMatch) {
+ var defineCall = parseDefineCall(moduleMatch, depsMatch);
+ return "define(__m[" + replacementMap[defineCall.module] + "/*" + defineCall.module + "*/], __M([" + defineCall.deps.map(function (dep) { return replacementMap[dep] + '/*' + dep + '*/'; }).join(',') + "])";
+ });
+ });
+ destFile.sources.unshift({
+ path: null,
+ contents: [
+ '(function() {',
+ "var __m = " + JSON.stringify(sortedByUseModules) + ";",
+ "var __M = function(deps) {",
+ " var result = [];",
+ " for (var i = 0, len = deps.length; i < len; i++) {",
+ " result[i] = __m[deps[i]];",
+ " }",
+ " return result;",
+ "};"
+ ].join('\n')
+ });
+ destFile.sources.push({
+ path: null,
+ contents: '}).call(this);'
+ });
+ });
+ return destFiles;
+}
+function removeDuplicateTSBoilerplate(destFiles) {
+ // Taken from typescript compiler => emitFiles
+ var BOILERPLATE = [
+ { start: /^var __extends/, end: /^}\)\(\);$/ },
+ { start: /^var __assign/, end: /^};$/ },
+ { start: /^var __decorate/, end: /^};$/ },
+ { start: /^var __metadata/, end: /^};$/ },
+ { start: /^var __param/, end: /^};$/ },
+ { start: /^var __awaiter/, end: /^};$/ },
+ ];
+ destFiles.forEach(function (destFile) {
+ var SEEN_BOILERPLATE = [];
+ destFile.sources.forEach(function (source) {
+ var lines = source.contents.split(/\r\n|\n|\r/);
+ var newLines = [];
+ var IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+ if (IS_REMOVING_BOILERPLATE) {
+ newLines.push('');
+ if (END_BOILERPLATE.test(line)) {
+ IS_REMOVING_BOILERPLATE = false;
+ }
+ }
+ else {
+ for (var j = 0; j < BOILERPLATE.length; j++) {
+ var boilerplate = BOILERPLATE[j];
+ if (boilerplate.start.test(line)) {
+ if (SEEN_BOILERPLATE[j]) {
+ IS_REMOVING_BOILERPLATE = true;
+ END_BOILERPLATE = boilerplate.end;
+ }
+ else {
+ SEEN_BOILERPLATE[j] = true;
+ }
+ }
+ }
+ if (IS_REMOVING_BOILERPLATE) {
+ newLines.push('');
+ }
+ else {
+ newLines.push(line);
+ }
+ }
+ }
+ source.contents = newLines.join('\n');
+ });
+ });
+ return destFiles;
+}
+function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend, append, dest) {
+ if (!dest) {
+ dest = entryPoint + '.js';
+ }
+ var mainResult = {
+ sources: [],
+ dest: dest
+ }, results = [mainResult];
+ var usedPlugins = {};
+ var getLoaderPlugin = function (pluginName) {
+ if (!usedPlugins[pluginName]) {
+ usedPlugins[pluginName] = modulesMap[pluginName].exports;
+ }
+ return usedPlugins[pluginName];
+ };
+ includedModules.forEach(function (c) {
+ var bangIndex = c.indexOf('!');
+ if (bangIndex >= 0) {
+ var pluginName = c.substr(0, bangIndex);
+ var plugin = getLoaderPlugin(pluginName);
+ mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
+ return;
+ }
+ var module = modulesMap[c];
+ if (module.path === 'empty:') {
+ return;
+ }
+ var contents = readFileAndRemoveBOM(module.path);
+ if (module.shim) {
+ mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
+ }
+ else {
+ mainResult.sources.push(emitNamedModule(c, deps[c], module.defineLocation, module.path, contents));
+ }
+ });
+ Object.keys(usedPlugins).forEach(function (pluginName) {
+ var plugin = usedPlugins[pluginName];
+ if (typeof plugin.writeFile === 'function') {
+ var req = (function () {
+ throw new Error('no-no!');
+ });
+ req.toUrl = function (something) { return something; };
+ var write = function (filename, contents) {
+ results.push({
+ dest: filename,
+ sources: [{
+ path: null,
+ contents: contents
+ }]
+ });
+ };
+ plugin.writeFile(pluginName, entryPoint, req, write, {});
+ }
+ });
+ var toIFile = function (path) {
+ var contents = readFileAndRemoveBOM(path);
+ return {
+ path: path,
+ contents: contents
+ };
+ };
+ var toPrepend = (prepend || []).map(toIFile);
+ var toAppend = (append || []).map(toIFile);
+ mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
+ return {
+ files: results,
+ usedPlugins: usedPlugins
+ };
+}
+function readFileAndRemoveBOM(path) {
+ var BOM_CHAR_CODE = 65279;
+ var contents = fs.readFileSync(path, 'utf8');
+ // Remove BOM
+ if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
+ contents = contents.substring(1);
+ }
+ return contents;
+}
+function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
+ var result = '';
+ if (typeof plugin.write === 'function') {
+ var write = (function (what) {
+ result += what;
+ });
+ write.getEntryPoint = function () {
+ return entryPoint;
+ };
+ write.asModule = function (moduleId, code) {
+ code = code.replace(/^define\(/, 'define("' + moduleId + '",');
+ result += code;
+ };
+ plugin.write(pluginName, moduleName, write);
+ }
+ return {
+ path: null,
+ contents: result
+ };
+}
+function emitNamedModule(moduleId, myDeps, defineCallPosition, path, contents) {
+ // `defineCallPosition` is the position in code: |define()
+ var defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
+ // `parensOffset` is the position in code: define|()
+ var parensOffset = contents.indexOf('(', defineCallOffset);
+ var insertStr = '"' + moduleId + '", ';
+ return {
+ path: path,
+ contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1)
+ };
+}
+function emitShimmedModule(moduleId, myDeps, factory, path, contents) {
+ var strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
+ var strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
+ return {
+ path: path,
+ contents: contents + '\n;\n' + strDefine
+ };
+}
+/**
+ * Convert a position (line:col) to (offset) in string `str`
+ */
+function positionToOffset(str, desiredLine, desiredCol) {
+ if (desiredLine === 1) {
+ return desiredCol - 1;
+ }
+ var line = 1, lastNewLineOffset = -1;
+ do {
+ if (desiredLine === line) {
+ return lastNewLineOffset + 1 + desiredCol - 1;
+ }
+ lastNewLineOffset = str.indexOf('\n', lastNewLineOffset + 1);
+ line++;
+ } while (lastNewLineOffset >= 0);
+ return -1;
+}
+/**
+ * Return a set of reachable nodes in `graph` starting from `rootNodes`
+ */
+function visit(rootNodes, graph) {
+ var result = {}, queue = rootNodes;
+ rootNodes.forEach(function (node) {
+ result[node] = true;
+ });
+ while (queue.length > 0) {
+ var el = queue.shift();
+ var myEdges = graph[el] || [];
+ myEdges.forEach(function (toNode) {
+ if (!result[toNode]) {
+ result[toNode] = true;
+ queue.push(toNode);
+ }
+ });
+ }
+ return result;
+}
+/**
+ * Perform a topological sort on `graph`
+ */
+function topologicalSort(graph) {
+ var allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {};
+ Object.keys(graph).forEach(function (fromNode) {
+ allNodes[fromNode] = true;
+ outgoingEdgeCount[fromNode] = graph[fromNode].length;
+ graph[fromNode].forEach(function (toNode) {
+ allNodes[toNode] = true;
+ outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0;
+ inverseEdges[toNode] = inverseEdges[toNode] || [];
+ inverseEdges[toNode].push(fromNode);
+ });
+ });
+ // https://en.wikipedia.org/wiki/Topological_sorting
+ var S = [], L = [];
+ Object.keys(allNodes).forEach(function (node) {
+ if (outgoingEdgeCount[node] === 0) {
+ delete outgoingEdgeCount[node];
+ S.push(node);
+ }
+ });
+ while (S.length > 0) {
+ // Ensure the exact same order all the time with the same inputs
+ S.sort();
+ var n = S.shift();
+ L.push(n);
+ var myInverseEdges = inverseEdges[n] || [];
+ myInverseEdges.forEach(function (m) {
+ outgoingEdgeCount[m]--;
+ if (outgoingEdgeCount[m] === 0) {
+ delete outgoingEdgeCount[m];
+ S.push(m);
+ }
+ });
+ }
+ if (Object.keys(outgoingEdgeCount).length > 0) {
+ throw new Error('Cannot do topological sort on cyclic graph, remaining nodes: ' + Object.keys(outgoingEdgeCount));
+ }
+ return L;
+}
diff --git a/build/lib/compilation.js b/build/lib/compilation.js
index e49862b4778..d9691ebc1d2 100644
--- a/build/lib/compilation.js
+++ b/build/lib/compilation.js
@@ -1,171 +1,171 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-'use strict';
-Object.defineProperty(exports, "__esModule", { value: true });
-var gulp = require("gulp");
-var tsb = require("gulp-tsb");
-var es = require("event-stream");
-var watch = require('./watch');
-var nls = require("./nls");
-var util = require("./util");
-var reporter_1 = require("./reporter");
-var path = require("path");
-var bom = require("gulp-bom");
-var sourcemaps = require("gulp-sourcemaps");
-var _ = require("underscore");
-var monacodts = require("../monaco/api");
-var fs = require("fs");
-var reporter = reporter_1.createReporter();
-var rootDir = path.join(__dirname, '../../src');
-var options = require('../../src/tsconfig.json').compilerOptions;
-options.verbose = false;
-options.sourceMap = true;
-options.rootDir = rootDir;
-options.sourceRoot = util.toFileUri(rootDir);
-function createCompile(build, emitError) {
- var opts = _.clone(options);
- opts.inlineSources = !!build;
- opts.noFilesystemLookup = true;
- var ts = tsb.create(opts, null, null, function (err) { return reporter(err.toString()); });
- return function (token) {
- var utf8Filter = util.filter(function (data) { return /(\/|\\)test(\/|\\).*utf8/.test(data.path); });
- var tsFilter = util.filter(function (data) { return /\.ts$/.test(data.path); });
- var noDeclarationsFilter = util.filter(function (data) { return !(/\.d\.ts$/.test(data.path)); });
- var input = es.through();
- var output = input
- .pipe(utf8Filter)
- .pipe(bom())
- .pipe(utf8Filter.restore)
- .pipe(tsFilter)
- .pipe(util.loadSourcemaps())
- .pipe(ts(token))
- .pipe(build ? reloadTypeScriptNodeModule() : es.through())
- .pipe(noDeclarationsFilter)
- .pipe(build ? nls() : es.through())
- .pipe(noDeclarationsFilter.restore)
- .pipe(sourcemaps.write('.', {
- addComment: false,
- includeContent: !!build,
- sourceRoot: options.sourceRoot
- }))
- .pipe(tsFilter.restore)
- .pipe(reporter.end(emitError));
- return es.duplex(input, output);
- };
-}
-function compileTask(out, build) {
- return function () {
- var compile = createCompile(build, true);
- var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src('node_modules/@types/**/index.d.ts'));
- return src
- .pipe(compile())
- .pipe(gulp.dest(out))
- .pipe(monacodtsTask(out, false));
- };
-}
-exports.compileTask = compileTask;
-function watchTask(out, build) {
- return function () {
- var compile = createCompile(build);
- var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src('node_modules/@types/**/index.d.ts'));
- var watchSrc = watch('src/**', { base: 'src' });
- return watchSrc
- .pipe(util.incremental(compile, src, true))
- .pipe(gulp.dest(out))
- .pipe(monacodtsTask(out, true));
- };
-}
-exports.watchTask = watchTask;
-function reloadTypeScriptNodeModule() {
- var util = require('gulp-util');
- function log(message) {
- var rest = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- rest[_i - 1] = arguments[_i];
- }
- util.log.apply(util, [util.colors.cyan('[memory watch dog]'), message].concat(rest));
- }
- function heapUsed() {
- return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
- }
- return es.through(function (data) {
- this.emit('data', data);
- }, function () {
- log('memory usage after compilation finished: ' + heapUsed());
- // It appears we are running into some variant of
- // https://bugs.chromium.org/p/v8/issues/detail?id=2073
- //
- // Even though all references are dropped, some
- // optimized methods in the TS compiler end up holding references
- // to the entire TypeScript language host (>600MB)
- //
- // The idea is to force v8 to drop references to these
- // optimized methods, by "reloading" the typescript node module
- log('Reloading typescript node module...');
- var resolvedName = require.resolve('typescript');
- var originalModule = require.cache[resolvedName];
- delete require.cache[resolvedName];
- var newExports = require('typescript');
- require.cache[resolvedName] = originalModule;
- for (var prop in newExports) {
- if (newExports.hasOwnProperty(prop)) {
- originalModule.exports[prop] = newExports[prop];
- }
- }
- log('typescript node module reloaded.');
- this.emit('end');
- });
-}
-function monacodtsTask(out, isWatch) {
- var neededFiles = {};
- monacodts.getFilesToWatch(out).forEach(function (filePath) {
- filePath = path.normalize(filePath);
- neededFiles[filePath] = true;
- });
- var inputFiles = {};
- for (var filePath in neededFiles) {
- if (/\bsrc(\/|\\)vs\b/.test(filePath)) {
- // This file is needed from source => simply read it now
- inputFiles[filePath] = fs.readFileSync(filePath).toString();
- }
- }
- var setInputFile = function (filePath, contents) {
- if (inputFiles[filePath] === contents) {
- // no change
- return;
- }
- inputFiles[filePath] = contents;
- var neededInputFilesCount = Object.keys(neededFiles).length;
- var availableInputFilesCount = Object.keys(inputFiles).length;
- if (neededInputFilesCount === availableInputFilesCount) {
- run();
- }
- };
- var run = function () {
- var result = monacodts.run(out, inputFiles);
- if (!result.isTheSame) {
- if (isWatch) {
- fs.writeFileSync(result.filePath, result.content);
- }
- else {
- resultStream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
- }
- }
- };
- var resultStream;
- if (isWatch) {
- watch('build/monaco/*').pipe(es.through(function () {
- run();
- }));
- }
- resultStream = es.through(function (data) {
- var filePath = path.normalize(data.path);
- if (neededFiles[filePath]) {
- setInputFile(filePath, data.contents.toString());
- }
- this.emit('data', data);
- });
- return resultStream;
-}
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+Object.defineProperty(exports, "__esModule", { value: true });
+var gulp = require("gulp");
+var tsb = require("gulp-tsb");
+var es = require("event-stream");
+var watch = require('./watch');
+var nls = require("./nls");
+var util = require("./util");
+var reporter_1 = require("./reporter");
+var path = require("path");
+var bom = require("gulp-bom");
+var sourcemaps = require("gulp-sourcemaps");
+var _ = require("underscore");
+var monacodts = require("../monaco/api");
+var fs = require("fs");
+var reporter = reporter_1.createReporter();
+var rootDir = path.join(__dirname, '../../src');
+var options = require('../../src/tsconfig.json').compilerOptions;
+options.verbose = false;
+options.sourceMap = true;
+options.rootDir = rootDir;
+options.sourceRoot = util.toFileUri(rootDir);
+function createCompile(build, emitError) {
+ var opts = _.clone(options);
+ opts.inlineSources = !!build;
+ opts.noFilesystemLookup = true;
+ var ts = tsb.create(opts, null, null, function (err) { return reporter(err.toString()); });
+ return function (token) {
+ var utf8Filter = util.filter(function (data) { return /(\/|\\)test(\/|\\).*utf8/.test(data.path); });
+ var tsFilter = util.filter(function (data) { return /\.ts$/.test(data.path); });
+ var noDeclarationsFilter = util.filter(function (data) { return !(/\.d\.ts$/.test(data.path)); });
+ var input = es.through();
+ var output = input
+ .pipe(utf8Filter)
+ .pipe(bom())
+ .pipe(utf8Filter.restore)
+ .pipe(tsFilter)
+ .pipe(util.loadSourcemaps())
+ .pipe(ts(token))
+ .pipe(build ? reloadTypeScriptNodeModule() : es.through())
+ .pipe(noDeclarationsFilter)
+ .pipe(build ? nls() : es.through())
+ .pipe(noDeclarationsFilter.restore)
+ .pipe(sourcemaps.write('.', {
+ addComment: false,
+ includeContent: !!build,
+ sourceRoot: options.sourceRoot
+ }))
+ .pipe(tsFilter.restore)
+ .pipe(reporter.end(emitError));
+ return es.duplex(input, output);
+ };
+}
+function compileTask(out, build) {
+ return function () {
+ var compile = createCompile(build, true);
+ var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src('node_modules/@types/**/index.d.ts'));
+ return src
+ .pipe(compile())
+ .pipe(gulp.dest(out))
+ .pipe(monacodtsTask(out, false));
+ };
+}
+exports.compileTask = compileTask;
+function watchTask(out, build) {
+ return function () {
+ var compile = createCompile(build);
+ var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'), gulp.src('node_modules/@types/**/index.d.ts'));
+ var watchSrc = watch('src/**', { base: 'src' });
+ return watchSrc
+ .pipe(util.incremental(compile, src, true))
+ .pipe(gulp.dest(out))
+ .pipe(monacodtsTask(out, true));
+ };
+}
+exports.watchTask = watchTask;
+function reloadTypeScriptNodeModule() {
+ var util = require('gulp-util');
+ function log(message) {
+ var rest = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ rest[_i - 1] = arguments[_i];
+ }
+ util.log.apply(util, [util.colors.cyan('[memory watch dog]'), message].concat(rest));
+ }
+ function heapUsed() {
+ return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
+ }
+ return es.through(function (data) {
+ this.emit('data', data);
+ }, function () {
+ log('memory usage after compilation finished: ' + heapUsed());
+ // It appears we are running into some variant of
+ // https://bugs.chromium.org/p/v8/issues/detail?id=2073
+ //
+ // Even though all references are dropped, some
+ // optimized methods in the TS compiler end up holding references
+ // to the entire TypeScript language host (>600MB)
+ //
+ // The idea is to force v8 to drop references to these
+ // optimized methods, by "reloading" the typescript node module
+ log('Reloading typescript node module...');
+ var resolvedName = require.resolve('typescript');
+ var originalModule = require.cache[resolvedName];
+ delete require.cache[resolvedName];
+ var newExports = require('typescript');
+ require.cache[resolvedName] = originalModule;
+ for (var prop in newExports) {
+ if (newExports.hasOwnProperty(prop)) {
+ originalModule.exports[prop] = newExports[prop];
+ }
+ }
+ log('typescript node module reloaded.');
+ this.emit('end');
+ });
+}
+function monacodtsTask(out, isWatch) {
+ var neededFiles = {};
+ monacodts.getFilesToWatch(out).forEach(function (filePath) {
+ filePath = path.normalize(filePath);
+ neededFiles[filePath] = true;
+ });
+ var inputFiles = {};
+ for (var filePath in neededFiles) {
+ if (/\bsrc(\/|\\)vs\b/.test(filePath)) {
+ // This file is needed from source => simply read it now
+ inputFiles[filePath] = fs.readFileSync(filePath).toString();
+ }
+ }
+ var setInputFile = function (filePath, contents) {
+ if (inputFiles[filePath] === contents) {
+ // no change
+ return;
+ }
+ inputFiles[filePath] = contents;
+ var neededInputFilesCount = Object.keys(neededFiles).length;
+ var availableInputFilesCount = Object.keys(inputFiles).length;
+ if (neededInputFilesCount === availableInputFilesCount) {
+ run();
+ }
+ };
+ var run = function () {
+ var result = monacodts.run(out, inputFiles);
+ if (!result.isTheSame) {
+ if (isWatch) {
+ fs.writeFileSync(result.filePath, result.content);
+ }
+ else {
+ resultStream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
+ }
+ }
+ };
+ var resultStream;
+ if (isWatch) {
+ watch('build/monaco/*').pipe(es.through(function () {
+ run();
+ }));
+ }
+ resultStream = es.through(function (data) {
+ var filePath = path.normalize(data.path);
+ if (neededFiles[filePath]) {
+ setInputFile(filePath, data.contents.toString());
+ }
+ this.emit('data', data);
+ });
+ return resultStream;
+}
diff --git a/build/lib/extensions.js b/build/lib/extensions.js
index e0a0d727883..b1b354abcff 100644
--- a/build/lib/extensions.js
+++ b/build/lib/extensions.js
@@ -1,96 +1,96 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var event_stream_1 = require("event-stream");
-var assign = require("object-assign");
-var remote = require("gulp-remote-src");
-var flatmap = require('gulp-flatmap');
-var vzip = require('gulp-vinyl-zip');
-var filter = require('gulp-filter');
-var rename = require('gulp-rename');
-var util = require('gulp-util');
-var buffer = require('gulp-buffer');
-var json = require('gulp-json-editor');
-function error(err) {
- var result = event_stream_1.through();
- setTimeout(function () { return result.emit('error', err); });
- return result;
-}
-var baseHeaders = {
- 'X-Market-Client-Id': 'VSCode Build',
- 'User-Agent': 'VSCode Build',
-};
-function src(extensionName, version) {
- var filterType = 7;
- var value = extensionName;
- var criterium = { filterType: filterType, value: value };
- var criteria = [criterium];
- var pageNumber = 1;
- var pageSize = 1;
- var sortBy = 0;
- var sortOrder = 0;
- var flags = 0x1 | 0x2 | 0x80;
- var assetTypes = ['Microsoft.VisualStudio.Services.VSIXPackage'];
- var filters = [{ criteria: criteria, pageNumber: pageNumber, pageSize: pageSize, sortBy: sortBy, sortOrder: sortOrder }];
- var body = JSON.stringify({ filters: filters, assetTypes: assetTypes, flags: flags });
- var headers = assign({}, baseHeaders, {
- 'Content-Type': 'application/json',
- 'Accept': 'application/json;api-version=3.0-preview.1',
- 'Content-Length': body.length
- });
- var options = {
- base: 'https://marketplace.visualstudio.com/_apis/public/gallery',
- requestOptions: {
- method: 'POST',
- gzip: true,
- headers: headers,
- body: body
- }
- };
- return remote('/extensionquery', options)
- .pipe(flatmap(function (stream, f) {
- var rawResult = f.contents.toString('utf8');
- var result = JSON.parse(rawResult);
- var extension = result.results[0].extensions[0];
- if (!extension) {
- return error("No such extension: " + extension);
- }
- var metadata = {
- id: extension.extensionId,
- publisherId: extension.publisher,
- publisherDisplayName: extension.publisher.displayName
- };
- var extensionVersion = extension.versions.filter(function (v) { return v.version === version; })[0];
- if (!extensionVersion) {
- return error("No such extension version: " + extensionName + " @ " + version);
- }
- var asset = extensionVersion.files.filter(function (f) { return f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage'; })[0];
- if (!asset) {
- return error("No VSIX found for extension version: " + extensionName + " @ " + version);
- }
- util.log('Downloading extension:', util.colors.yellow(extensionName + "@" + version), '...');
- var options = {
- base: asset.source,
- requestOptions: {
- gzip: true,
- headers: baseHeaders
- }
- };
- return remote('', options)
- .pipe(flatmap(function (stream) {
- var packageJsonFilter = filter('package.json', { restore: true });
- return stream
- .pipe(vzip.src())
- .pipe(filter('extension/**'))
- .pipe(rename(function (p) { return p.dirname = p.dirname.replace(/^extension\/?/, ''); }))
- .pipe(packageJsonFilter)
- .pipe(buffer())
- .pipe(json({ __metadata: metadata }))
- .pipe(packageJsonFilter.restore);
- }));
- }));
-}
-exports.src = src;
+"use strict";
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+Object.defineProperty(exports, "__esModule", { value: true });
+var event_stream_1 = require("event-stream");
+var assign = require("object-assign");
+var remote = require("gulp-remote-src");
+var flatmap = require('gulp-flatmap');
+var vzip = require('gulp-vinyl-zip');
+var filter = require('gulp-filter');
+var rename = require('gulp-rename');
+var util = require('gulp-util');
+var buffer = require('gulp-buffer');
+var json = require('gulp-json-editor');
+function error(err) {
+ var result = event_stream_1.through();
+ setTimeout(function () { return result.emit('error', err); });
+ return result;
+}
+var baseHeaders = {
+ 'X-Market-Client-Id': 'VSCode Build',
+ 'User-Agent': 'VSCode Build',
+};
+function src(extensionName, version) {
+ var filterType = 7;
+ var value = extensionName;
+ var criterium = { filterType: filterType, value: value };
+ var criteria = [criterium];
+ var pageNumber = 1;
+ var pageSize = 1;
+ var sortBy = 0;
+ var sortOrder = 0;
+ var flags = 0x1 | 0x2 | 0x80;
+ var assetTypes = ['Microsoft.VisualStudio.Services.VSIXPackage'];
+ var filters = [{ criteria: criteria, pageNumber: pageNumber, pageSize: pageSize, sortBy: sortBy, sortOrder: sortOrder }];
+ var body = JSON.stringify({ filters: filters, assetTypes: assetTypes, flags: flags });
+ var headers = assign({}, baseHeaders, {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json;api-version=3.0-preview.1',
+ 'Content-Length': body.length
+ });
+ var options = {
+ base: 'https://marketplace.visualstudio.com/_apis/public/gallery',
+ requestOptions: {
+ method: 'POST',
+ gzip: true,
+ headers: headers,
+ body: body
+ }
+ };
+ return remote('/extensionquery', options)
+ .pipe(flatmap(function (stream, f) {
+ var rawResult = f.contents.toString('utf8');
+ var result = JSON.parse(rawResult);
+ var extension = result.results[0].extensions[0];
+ if (!extension) {
+ return error("No such extension: " + extension);
+ }
+ var metadata = {
+ id: extension.extensionId,
+ publisherId: extension.publisher,
+ publisherDisplayName: extension.publisher.displayName
+ };
+ var extensionVersion = extension.versions.filter(function (v) { return v.version === version; })[0];
+ if (!extensionVersion) {
+ return error("No such extension version: " + extensionName + " @ " + version);
+ }
+ var asset = extensionVersion.files.filter(function (f) { return f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage'; })[0];
+ if (!asset) {
+ return error("No VSIX found for extension version: " + extensionName + " @ " + version);
+ }
+ util.log('Downloading extension:', util.colors.yellow(extensionName + "@" + version), '...');
+ var options = {
+ base: asset.source,
+ requestOptions: {
+ gzip: true,
+ headers: baseHeaders
+ }
+ };
+ return remote('', options)
+ .pipe(flatmap(function (stream) {
+ var packageJsonFilter = filter('package.json', { restore: true });
+ return stream
+ .pipe(vzip.src())
+ .pipe(filter('extension/**'))
+ .pipe(rename(function (p) { return p.dirname = p.dirname.replace(/^extension\/?/, ''); }))
+ .pipe(packageJsonFilter)
+ .pipe(buffer())
+ .pipe(json({ __metadata: metadata }))
+ .pipe(packageJsonFilter.restore);
+ }));
+ }));
+}
+exports.src = src;
diff --git a/build/lib/git.js b/build/lib/git.js
index 8b31b9a2e0f..e9a571b7c9b 100644
--- a/build/lib/git.js
+++ b/build/lib/git.js
@@ -1,53 +1,53 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-'use strict';
-Object.defineProperty(exports, "__esModule", { value: true });
-var path = require("path");
-var fs = require("fs");
-/**
- * Returns the sha1 commit version of a repository or undefined in case of failure.
- */
-function getVersion(repo) {
- var git = path.join(repo, '.git');
- var headPath = path.join(git, 'HEAD');
- var head;
- try {
- head = fs.readFileSync(headPath, 'utf8').trim();
- }
- catch (e) {
- return void 0;
- }
- if (/^[0-9a-f]{40}$/i.test(head)) {
- return head;
- }
- var refMatch = /^ref: (.*)$/.exec(head);
- if (!refMatch) {
- return void 0;
- }
- var ref = refMatch[1];
- var refPath = path.join(git, ref);
- try {
- return fs.readFileSync(refPath, 'utf8').trim();
- }
- catch (e) {
- // noop
- }
- var packedRefsPath = path.join(git, 'packed-refs');
- var refsRaw;
- try {
- refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
- }
- catch (e) {
- return void 0;
- }
- var refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
- var refsMatch;
- var refs = {};
- while (refsMatch = refsRegex.exec(refsRaw)) {
- refs[refsMatch[2]] = refsMatch[1];
- }
- return refs[ref];
-}
-exports.getVersion = getVersion;
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+Object.defineProperty(exports, "__esModule", { value: true });
+var path = require("path");
+var fs = require("fs");
+/**
+ * Returns the sha1 commit version of a repository or undefined in case of failure.
+ */
+function getVersion(repo) {
+ var git = path.join(repo, '.git');
+ var headPath = path.join(git, 'HEAD');
+ var head;
+ try {
+ head = fs.readFileSync(headPath, 'utf8').trim();
+ }
+ catch (e) {
+ return void 0;
+ }
+ if (/^[0-9a-f]{40}$/i.test(head)) {
+ return head;
+ }
+ var refMatch = /^ref: (.*)$/.exec(head);
+ if (!refMatch) {
+ return void 0;
+ }
+ var ref = refMatch[1];
+ var refPath = path.join(git, ref);
+ try {
+ return fs.readFileSync(refPath, 'utf8').trim();
+ }
+ catch (e) {
+ // noop
+ }
+ var packedRefsPath = path.join(git, 'packed-refs');
+ var refsRaw;
+ try {
+ refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
+ }
+ catch (e) {
+ return void 0;
+ }
+ var refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
+ var refsMatch;
+ var refs = {};
+ while (refsMatch = refsRegex.exec(refsRaw)) {
+ refs[refsMatch[2]] = refsMatch[1];
+ }
+ return refs[ref];
+}
+exports.getVersion = getVersion;
diff --git a/build/lib/i18n.js b/build/lib/i18n.js
index e0bfbe4b987..3f16ccc97f1 100644
--- a/build/lib/i18n.js
+++ b/build/lib/i18n.js
@@ -1,1049 +1,1049 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var path = require("path");
-var fs = require("fs");
-var event_stream_1 = require("event-stream");
-var File = require("vinyl");
-var Is = require("is");
-var xml2js = require("xml2js");
-var glob = require("glob");
-var http = require("http");
-var util = require('gulp-util');
-var iconv = require('iconv-lite');
-function log(message) {
- var rest = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- rest[_i - 1] = arguments[_i];
- }
- util.log.apply(util, [util.colors.green('[i18n]'), message].concat(rest));
-}
-var LocalizeInfo;
-(function (LocalizeInfo) {
- function is(value) {
- var candidate = value;
- return Is.defined(candidate) && Is.string(candidate.key) && (Is.undef(candidate.comment) || (Is.array(candidate.comment) && candidate.comment.every(function (element) { return Is.string(element); })));
- }
- LocalizeInfo.is = is;
-})(LocalizeInfo || (LocalizeInfo = {}));
-var BundledFormat;
-(function (BundledFormat) {
- function is(value) {
- if (Is.undef(value)) {
- return false;
- }
- var candidate = value;
- var length = Object.keys(value).length;
- return length === 3 && Is.defined(candidate.keys) && Is.defined(candidate.messages) && Is.defined(candidate.bundles);
- }
- BundledFormat.is = is;
-})(BundledFormat || (BundledFormat = {}));
-var PackageJsonFormat;
-(function (PackageJsonFormat) {
- function is(value) {
- if (Is.undef(value) || !Is.object(value)) {
- return false;
- }
- return Object.keys(value).every(function (key) {
- var element = value[key];
- return Is.string(element) || (Is.object(element) && Is.defined(element.message) && Is.defined(element.comment));
- });
- }
- PackageJsonFormat.is = is;
-})(PackageJsonFormat || (PackageJsonFormat = {}));
-var ModuleJsonFormat;
-(function (ModuleJsonFormat) {
- function is(value) {
- var candidate = value;
- return Is.defined(candidate)
- && Is.array(candidate.messages) && candidate.messages.every(function (message) { return Is.string(message); })
- && Is.array(candidate.keys) && candidate.keys.every(function (key) { return Is.string(key) || LocalizeInfo.is(key); });
- }
- ModuleJsonFormat.is = is;
-})(ModuleJsonFormat || (ModuleJsonFormat = {}));
-var Line = (function () {
- function Line(indent) {
- if (indent === void 0) { indent = 0; }
- this.indent = indent;
- this.buffer = [];
- if (indent > 0) {
- this.buffer.push(new Array(indent + 1).join(' '));
- }
- }
- Line.prototype.append = function (value) {
- this.buffer.push(value);
- return this;
- };
- Line.prototype.toString = function () {
- return this.buffer.join('');
- };
- return Line;
-}());
-exports.Line = Line;
-var TextModel = (function () {
- function TextModel(contents) {
- this._lines = contents.split(/\r\n|\r|\n/);
- }
- Object.defineProperty(TextModel.prototype, "lines", {
- get: function () {
- return this._lines;
- },
- enumerable: true,
- configurable: true
- });
- return TextModel;
-}());
-var XLF = (function () {
- function XLF(project) {
- this.project = project;
- this.buffer = [];
- this.files = Object.create(null);
- }
- XLF.prototype.toString = function () {
- this.appendHeader();
- for (var file in this.files) {
- this.appendNewLine("", 2);
- for (var _i = 0, _a = this.files[file]; _i < _a.length; _i++) {
- var item = _a[_i];
- this.addStringItem(item);
- }
- this.appendNewLine('', 2);
- }
- this.appendFooter();
- return this.buffer.join('\r\n');
- };
- XLF.prototype.addFile = function (original, keys, messages) {
- this.files[original] = [];
- var existingKeys = [];
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
- var key = keys_1[_i];
- // Ignore duplicate keys because Transifex does not populate those with translated values.
- if (existingKeys.indexOf(key) !== -1) {
- continue;
- }
- existingKeys.push(key);
- var message = encodeEntities(messages[keys.indexOf(key)]);
- var comment = undefined;
- // Check if the message contains description (if so, it becomes an object type in JSON)
- if (Is.string(key)) {
- this.files[original].push({ id: key, message: message, comment: comment });
- }
- else {
- if (key['comment'] && key['comment'].length > 0) {
- comment = key['comment'].map(function (comment) { return encodeEntities(comment); }).join('\r\n');
- }
- this.files[original].push({ id: key['key'], message: message, comment: comment });
- }
- }
- };
- XLF.prototype.addStringItem = function (item) {
- if (!item.id || !item.message) {
- throw new Error('No item ID or value specified.');
- }
- this.appendNewLine("", 4);
- this.appendNewLine("" + item.message + "", 6);
- if (item.comment) {
- this.appendNewLine("" + item.comment + "", 6);
- }
- this.appendNewLine('', 4);
- };
- XLF.prototype.appendHeader = function () {
- this.appendNewLine('', 0);
- this.appendNewLine('', 0);
- };
- XLF.prototype.appendFooter = function () {
- this.appendNewLine('', 0);
- };
- XLF.prototype.appendNewLine = function (content, indent) {
- var line = new Line(indent);
- line.append(content);
- this.buffer.push(line.toString());
- };
- return XLF;
-}());
-XLF.parse = function (xlfString) {
- return new Promise(function (resolve, reject) {
- var parser = new xml2js.Parser();
- var files = [];
- parser.parseString(xlfString, function (err, result) {
- if (err) {
- reject("Failed to parse XLIFF string. " + err);
- }
- var fileNodes = result['xliff']['file'];
- if (!fileNodes) {
- reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.');
- }
- fileNodes.forEach(function (file) {
- var originalFilePath = file.$.original;
- if (!originalFilePath) {
- reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.');
- }
- var language = file.$['target-language'].toLowerCase();
- if (!language) {
- reject('XLIFF file node does not contain target-language attribute to determine translated language.');
- }
- var messages = {};
- var transUnits = file.body[0]['trans-unit'];
- transUnits.forEach(function (unit) {
- var key = unit.$.id;
- if (!unit.target) {
- return; // No translation available
- }
- var val = unit.target.toString();
- if (key && val) {
- messages[key] = decodeEntities(val);
- }
- else {
- reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.');
- }
- });
- files.push({ messages: messages, originalFilePath: originalFilePath, language: language });
- });
- resolve(files);
- });
- });
-};
-exports.XLF = XLF;
-var vscodeLanguages = [
- 'chs',
- 'cht',
- 'jpn',
- 'kor',
- 'deu',
- 'fra',
- 'esn',
- 'rus',
- 'ita'
-];
-var iso639_3_to_2 = {
- 'chs': 'zh-cn',
- 'cht': 'zh-tw',
- 'csy': 'cs-cz',
- 'deu': 'de',
- 'enu': 'en',
- 'esn': 'es',
- 'fra': 'fr',
- 'hun': 'hu',
- 'ita': 'it',
- 'jpn': 'ja',
- 'kor': 'ko',
- 'nld': 'nl',
- 'plk': 'pl',
- 'ptb': 'pt-br',
- 'ptg': 'pt',
- 'rus': 'ru',
- 'sve': 'sv-se',
- 'trk': 'tr'
-};
-/**
- * Used to map Transifex to VS Code language code representation.
- */
-var iso639_2_to_3 = {
- 'zh-hans': 'chs',
- 'zh-hant': 'cht',
- 'cs-cz': 'csy',
- 'de': 'deu',
- 'en': 'enu',
- 'es': 'esn',
- 'fr': 'fra',
- 'hu': 'hun',
- 'it': 'ita',
- 'ja': 'jpn',
- 'ko': 'kor',
- 'nl': 'nld',
- 'pl': 'plk',
- 'pt-br': 'ptb',
- 'pt': 'ptg',
- 'ru': 'rus',
- 'sv-se': 'sve',
- 'tr': 'trk'
-};
-function sortLanguages(directoryNames) {
- return directoryNames.map(function (dirName) {
- var lower = dirName.toLowerCase();
- return {
- name: lower,
- iso639_2: iso639_3_to_2[lower]
- };
- }).sort(function (a, b) {
- if (!a.iso639_2 && !b.iso639_2) {
- return 0;
- }
- if (!a.iso639_2) {
- return -1;
- }
- if (!b.iso639_2) {
- return 1;
- }
- return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0);
- });
-}
-function stripComments(content) {
- /**
- * First capturing group matches double quoted string
- * Second matches single quotes string
- * Third matches block comments
- * Fourth matches line comments
- */
- var regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
- var result = content.replace(regexp, function (match, m1, m2, m3, m4) {
- // Only one of m1, m2, m3, m4 matches
- if (m3) {
- // A block comment. Replace with nothing
- return '';
- }
- else if (m4) {
- // A line comment. If it ends in \r?\n then keep it.
- var length_1 = m4.length;
- if (length_1 > 2 && m4[length_1 - 1] === '\n') {
- return m4[length_1 - 2] === '\r' ? '\r\n' : '\n';
- }
- else {
- return '';
- }
- }
- else {
- // We match a string
- return match;
- }
- });
- return result;
-}
-function escapeCharacters(value) {
- var result = [];
- for (var i = 0; i < value.length; i++) {
- var ch = value.charAt(i);
- switch (ch) {
- case '\'':
- result.push('\\\'');
- break;
- case '"':
- result.push('\\"');
- break;
- case '\\':
- result.push('\\\\');
- break;
- case '\n':
- result.push('\\n');
- break;
- case '\r':
- result.push('\\r');
- break;
- case '\t':
- result.push('\\t');
- break;
- case '\b':
- result.push('\\b');
- break;
- case '\f':
- result.push('\\f');
- break;
- default:
- result.push(ch);
- }
- }
- return result.join('');
-}
-function processCoreBundleFormat(fileHeader, json, emitter) {
- var keysSection = json.keys;
- var messageSection = json.messages;
- var bundleSection = json.bundles;
- var statistics = Object.create(null);
- var total = 0;
- var defaultMessages = Object.create(null);
- var modules = Object.keys(keysSection);
- modules.forEach(function (module) {
- var keys = keysSection[module];
- var messages = messageSection[module];
- if (!messages || keys.length !== messages.length) {
- emitter.emit('error', "Message for module " + module + " corrupted. Mismatch in number of keys and messages.");
- return;
- }
- var messageMap = Object.create(null);
- defaultMessages[module] = messageMap;
- keys.map(function (key, i) {
- total++;
- if (Is.string(key)) {
- messageMap[key] = messages[i];
- }
- else {
- messageMap[key.key] = messages[i];
- }
- });
- });
- var languageDirectory = path.join(__dirname, '..', '..', 'i18n');
- var languages = sortLanguages(fs.readdirSync(languageDirectory).filter(function (item) { return fs.statSync(path.join(languageDirectory, item)).isDirectory(); }));
- languages.forEach(function (language) {
- if (!language.iso639_2) {
- return;
- }
- if (process.env['VSCODE_BUILD_VERBOSE']) {
- log("Generating nls bundles for: " + language.iso639_2);
- }
- statistics[language.iso639_2] = 0;
- var localizedModules = Object.create(null);
- var cwd = path.join(languageDirectory, language.name, 'src');
- modules.forEach(function (module) {
- var order = keysSection[module];
- var i18nFile = path.join(cwd, module) + '.i18n.json';
- var messages = null;
- if (fs.existsSync(i18nFile)) {
- var content = stripComments(fs.readFileSync(i18nFile, 'utf8'));
- messages = JSON.parse(content);
- }
- else {
- if (process.env['VSCODE_BUILD_VERBOSE']) {
- log("No localized messages found for module " + module + ". Using default messages.");
- }
- messages = defaultMessages[module];
- statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length;
- }
- var localizedMessages = [];
- order.forEach(function (keyInfo) {
- var key = null;
- if (Is.string(keyInfo)) {
- key = keyInfo;
- }
- else {
- key = keyInfo.key;
- }
- var message = messages[key];
- if (!message) {
- if (process.env['VSCODE_BUILD_VERBOSE']) {
- log("No localized message found for key " + key + " in module " + module + ". Using default message.");
- }
- message = defaultMessages[module][key];
- statistics[language.iso639_2] = statistics[language.iso639_2] + 1;
- }
- localizedMessages.push(message);
- });
- localizedModules[module] = localizedMessages;
- });
- Object.keys(bundleSection).forEach(function (bundle) {
- var modules = bundleSection[bundle];
- var contents = [
- fileHeader,
- "define(\"" + bundle + ".nls." + language.iso639_2 + "\", {"
- ];
- modules.forEach(function (module, index) {
- contents.push("\t\"" + module + "\": [");
- var messages = localizedModules[module];
- if (!messages) {
- emitter.emit('error', "Didn't find messages for module " + module + ".");
- return;
- }
- messages.forEach(function (message, index) {
- contents.push("\t\t\"" + escapeCharacters(message) + (index < messages.length ? '",' : '"'));
- });
- contents.push(index < modules.length - 1 ? '\t],' : '\t]');
- });
- contents.push('});');
- emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') }));
- });
- });
- Object.keys(statistics).forEach(function (key) {
- var value = statistics[key];
- log(key + " has " + value + " untranslated strings.");
- });
- vscodeLanguages.forEach(function (language) {
- var iso639_2 = iso639_3_to_2[language];
- if (!iso639_2) {
- log("\tCouldn't find iso639 2 mapping for language " + language + ". Using default language instead.");
- }
- else {
- var stats = statistics[iso639_2];
- if (Is.undef(stats)) {
- log("\tNo translations found for language " + language + ". Using default language instead.");
- }
- }
- });
-}
-function processNlsFiles(opts) {
- return event_stream_1.through(function (file) {
- var fileName = path.basename(file.path);
- if (fileName === 'nls.metadata.json') {
- var json = null;
- if (file.isBuffer()) {
- json = JSON.parse(file.contents.toString('utf8'));
- }
- else {
- this.emit('error', "Failed to read component file: " + file.relative);
- }
- if (BundledFormat.is(json)) {
- processCoreBundleFormat(opts.fileHeader, json, this);
- }
- }
- this.emit('data', file);
- });
-}
-exports.processNlsFiles = processNlsFiles;
-function prepareXlfFiles(projectName, extensionName) {
- return event_stream_1.through(function (file) {
- if (!file.isBuffer()) {
- throw new Error("Failed to read component file: " + file.relative);
- }
- var extension = path.extname(file.path);
- if (extension === '.json') {
- var json = JSON.parse(file.contents.toString('utf8'));
- if (BundledFormat.is(json)) {
- importBundleJson(file, json, this);
- }
- else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) {
- importModuleOrPackageJson(file, json, projectName, this, extensionName);
- }
- else {
- throw new Error("JSON format cannot be deduced for " + file.relative + ".");
- }
- }
- else if (extension === '.isl') {
- importIsl(file, this);
- }
- });
-}
-exports.prepareXlfFiles = prepareXlfFiles;
-var editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup';
-/**
- * Ensure to update those arrays when new resources are pushed to Transifex.
- * Used because Transifex does not have API method to pull all project resources.
- */
-var editorResources = [
- { name: 'vs/platform', project: editorProject },
- { name: 'vs/editor/contrib', project: editorProject },
- { name: 'vs/editor', project: editorProject },
- { name: 'vs/base', project: editorProject }
-];
-var workbenchResources = [
- { name: 'vs/code', project: workbenchProject },
- { name: 'vs/workbench', project: workbenchProject },
- { name: 'vs/workbench/parts/cli', project: workbenchProject },
- { name: 'vs/workbench/parts/codeEditor', project: workbenchProject },
- { name: 'vs/workbench/parts/debug', project: workbenchProject },
- { name: 'vs/workbench/parts/emmet', project: workbenchProject },
- { name: 'vs/workbench/parts/execution', project: workbenchProject },
- { name: 'vs/workbench/parts/explorers', project: workbenchProject },
- { name: 'vs/workbench/parts/extensions', project: workbenchProject },
- { name: 'vs/workbench/parts/feedback', project: workbenchProject },
- { name: 'vs/workbench/parts/files', project: workbenchProject },
- { name: 'vs/workbench/parts/git', project: workbenchProject },
- { name: 'vs/workbench/parts/html', project: workbenchProject },
- { name: 'vs/workbench/parts/markers', project: workbenchProject },
- { name: 'vs/workbench/parts/nps', project: workbenchProject },
- { name: 'vs/workbench/parts/output', project: workbenchProject },
- { name: 'vs/workbench/parts/performance', project: workbenchProject },
- { name: 'vs/workbench/parts/preferences', project: workbenchProject },
- { name: 'vs/workbench/parts/quickopen', project: workbenchProject },
- { name: 'vs/workbench/parts/scm', project: workbenchProject },
- { name: 'vs/workbench/parts/search', project: workbenchProject },
- { name: 'vs/workbench/parts/snippets', project: workbenchProject },
- { name: 'vs/workbench/parts/tasks', project: workbenchProject },
- { name: 'vs/workbench/parts/terminal', project: workbenchProject },
- { name: 'vs/workbench/parts/themes', project: workbenchProject },
- { name: 'vs/workbench/parts/trust', project: workbenchProject },
- { name: 'vs/workbench/parts/update', project: workbenchProject },
- { name: 'vs/workbench/parts/watermark', project: workbenchProject },
- { name: 'vs/workbench/parts/welcome', project: workbenchProject },
- { name: 'vs/workbench/services/configuration', project: workbenchProject },
- { name: 'vs/workbench/services/editor', project: workbenchProject },
- { name: 'vs/workbench/services/files', project: workbenchProject },
- { name: 'vs/workbench/services/keybinding', project: workbenchProject },
- { name: 'vs/workbench/services/message', project: workbenchProject },
- { name: 'vs/workbench/services/mode', project: workbenchProject },
- { name: 'vs/workbench/services/textfile', project: workbenchProject },
- { name: 'vs/workbench/services/themes', project: workbenchProject },
- { name: 'setup_messages', project: workbenchProject }
-];
-function getResource(sourceFile) {
- var resource;
- if (sourceFile.startsWith('vs/platform')) {
- return { name: 'vs/platform', project: editorProject };
- }
- else if (sourceFile.startsWith('vs/editor/contrib')) {
- return { name: 'vs/editor/contrib', project: editorProject };
- }
- else if (sourceFile.startsWith('vs/editor')) {
- return { name: 'vs/editor', project: editorProject };
- }
- else if (sourceFile.startsWith('vs/base')) {
- return { name: 'vs/base', project: editorProject };
- }
- else if (sourceFile.startsWith('vs/code')) {
- return { name: 'vs/code', project: workbenchProject };
- }
- else if (sourceFile.startsWith('vs/workbench/parts')) {
- resource = sourceFile.split('/', 4).join('/');
- return { name: resource, project: workbenchProject };
- }
- else if (sourceFile.startsWith('vs/workbench/services')) {
- resource = sourceFile.split('/', 4).join('/');
- return { name: resource, project: workbenchProject };
- }
- else if (sourceFile.startsWith('vs/workbench')) {
- return { name: 'vs/workbench', project: workbenchProject };
- }
- throw new Error("Could not identify the XLF bundle for " + sourceFile);
-}
-exports.getResource = getResource;
-function importBundleJson(file, json, stream) {
- var bundleXlfs = Object.create(null);
- for (var source in json.keys) {
- var projectResource = getResource(source);
- var resource = projectResource.name;
- var project = projectResource.project;
- var keys = json.keys[source];
- var messages = json.messages[source];
- if (keys.length !== messages.length) {
- throw new Error("There is a mismatch between keys and messages in " + file.relative);
- }
- var xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project);
- xlf.addFile('src/' + source, keys, messages);
- }
- for (var resource in bundleXlfs) {
- var newFilePath = bundleXlfs[resource].project + "/" + resource.replace(/\//g, '_') + ".xlf";
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-// Keeps existing XLF instances and a state of how many files were already processed for faster file emission
-var extensions = Object.create(null);
-function importModuleOrPackageJson(file, json, projectName, stream, extensionName) {
- if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) {
- throw new Error("There is a mismatch between keys and messages in " + file.relative);
- }
- // Prepare the source path for attribute in XLF & extract messages from JSON
- var formattedSourcePath = file.relative.replace(/\\/g, '/');
- var messages = Object.keys(json).map(function (key) { return json[key].toString(); });
- // Stores the amount of localization files to be transformed to XLF before the emission
- var localizationFilesCount, originalFilePath;
- // If preparing XLF for external extension, then use different glob pattern and source path
- if (extensionName) {
- localizationFilesCount = glob.sync('**/*.nls.json').length;
- originalFilePath = "" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
- }
- else {
- // Used for vscode/extensions folder
- extensionName = formattedSourcePath.split('/')[0];
- localizationFilesCount = glob.sync("./extensions/" + extensionName + "/**/*.nls.json").length;
- originalFilePath = "extensions/" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
- }
- var extension = extensions[extensionName] ?
- extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 };
- if (ModuleJsonFormat.is(json)) {
- extension.xlf.addFile(originalFilePath, json['keys'], json['messages']);
- }
- else {
- extension.xlf.addFile(originalFilePath, Object.keys(json), messages);
- }
- // Check if XLF is populated with file nodes to emit it
- if (++extensions[extensionName].processed === localizationFilesCount) {
- var newFilePath = path.join(projectName, extensionName + '.xlf');
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-function importIsl(file, stream) {
- var projectName, resourceFile;
- if (path.basename(file.path) === 'Default.isl') {
- projectName = setupProject;
- resourceFile = 'setup_default.xlf';
- }
- else {
- projectName = workbenchProject;
- resourceFile = 'setup_messages.xlf';
- }
- var xlf = new XLF(projectName), keys = [], messages = [];
- var model = new TextModel(file.contents.toString());
- var inMessageSection = false;
- model.lines.forEach(function (line) {
- if (line.length === 0) {
- return;
- }
- var firstChar = line.charAt(0);
- switch (firstChar) {
- case ';':
- // Comment line;
- return;
- case '[':
- inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
- return;
- }
- if (!inMessageSection) {
- return;
- }
- var sections = line.split('=');
- if (sections.length !== 2) {
- throw new Error("Badly formatted message found: " + line);
- }
- else {
- var key = sections[0];
- var value = sections[1];
- if (key.length > 0 && value.length > 0) {
- keys.push(key);
- messages.push(value);
- }
- }
- });
- var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
- xlf.addFile(originalPath, keys, messages);
- // Emit only upon all ISL files combined into single XLF instance
- var newFilePath = path.join(projectName, resourceFile);
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
-}
-function pushXlfFiles(apiHostname, username, password) {
- var tryGetPromises = [];
- var updateCreatePromises = [];
- return event_stream_1.through(function (file) {
- var project = path.dirname(file.relative);
- var fileName = path.basename(file.path);
- var slug = fileName.substr(0, fileName.length - '.xlf'.length);
- var credentials = username + ":" + password;
- // Check if resource already exists, if not, then create it.
- var promise = tryGetResource(project, slug, apiHostname, credentials);
- tryGetPromises.push(promise);
- promise.then(function (exists) {
- if (exists) {
- promise = updateResource(project, slug, file, apiHostname, credentials);
- }
- else {
- promise = createResource(project, slug, file, apiHostname, credentials);
- }
- updateCreatePromises.push(promise);
- });
- }, function () {
- var _this = this;
- // End the pipe only after all the communication with Transifex API happened
- Promise.all(tryGetPromises).then(function () {
- Promise.all(updateCreatePromises).then(function () {
- _this.emit('end');
- }).catch(function (reason) { throw new Error(reason); });
- }).catch(function (reason) { throw new Error(reason); });
- });
-}
-exports.pushXlfFiles = pushXlfFiles;
-function tryGetResource(project, slug, apiHostname, credentials) {
- return new Promise(function (resolve, reject) {
- var options = {
- hostname: apiHostname,
- path: "/api/2/project/" + project + "/resource/" + slug + "/?details",
- auth: credentials,
- method: 'GET'
- };
- var request = http.request(options, function (response) {
- if (response.statusCode === 404) {
- resolve(false);
- }
- else if (response.statusCode === 200) {
- resolve(true);
- }
- else {
- reject("Failed to query resource " + project + "/" + slug + ". Response: " + response.statusCode + " " + response.statusMessage);
- }
- });
- request.on('error', function (err) {
- reject("Failed to get " + project + "/" + slug + " on Transifex: " + err);
- });
- request.end();
- });
-}
-function createResource(project, slug, xlfFile, apiHostname, credentials) {
- return new Promise(function (resolve, reject) {
- var data = JSON.stringify({
- 'content': xlfFile.contents.toString(),
- 'name': slug,
- 'slug': slug,
- 'i18n_type': 'XLIFF'
- });
- var options = {
- hostname: apiHostname,
- path: "/api/2/project/" + project + "/resources",
- headers: {
- 'Content-Type': 'application/json',
- 'Content-Length': Buffer.byteLength(data)
- },
- auth: credentials,
- method: 'POST'
- };
- var request = http.request(options, function (res) {
- if (res.statusCode === 201) {
- log("Resource " + project + "/" + slug + " successfully created on Transifex.");
- }
- else {
- reject("Something went wrong in the request creating " + slug + " in " + project + ". " + res.statusCode);
- }
- });
- request.on('error', function (err) {
- reject("Failed to create " + project + "/" + slug + " on Transifex: " + err);
- });
- request.write(data);
- request.end();
- });
-}
-/**
- * The following link provides information about how Transifex handles updates of a resource file:
- * https://dev.befoolish.co/tx-docs/public/projects/updating-content#what-happens-when-you-update-files
- */
-function updateResource(project, slug, xlfFile, apiHostname, credentials) {
- return new Promise(function (resolve, reject) {
- var data = JSON.stringify({ content: xlfFile.contents.toString() });
- var options = {
- hostname: apiHostname,
- path: "/api/2/project/" + project + "/resource/" + slug + "/content",
- headers: {
- 'Content-Type': 'application/json',
- 'Content-Length': Buffer.byteLength(data)
- },
- auth: credentials,
- method: 'PUT'
- };
- var request = http.request(options, function (res) {
- if (res.statusCode === 200) {
- res.setEncoding('utf8');
- var responseBuffer_1 = '';
- res.on('data', function (chunk) {
- responseBuffer_1 += chunk;
- });
- res.on('end', function () {
- var response = JSON.parse(responseBuffer_1);
- log("Resource " + project + "/" + slug + " successfully updated on Transifex. Strings added: " + response.strings_added + ", updated: " + response.strings_added + ", deleted: " + response.strings_added);
- resolve();
- });
- }
- else {
- reject("Something went wrong in the request updating " + slug + " in " + project + ". " + res.statusCode);
- }
- });
- request.on('error', function (err) {
- reject("Failed to update " + project + "/" + slug + " on Transifex: " + err);
- });
- request.write(data);
- request.end();
- });
-}
-function obtainProjectResources(projectName) {
- var resources = [];
- if (projectName === editorProject) {
- resources = editorResources;
- }
- else if (projectName === workbenchProject) {
- resources = workbenchResources;
- }
- else if (projectName === extensionsProject) {
- var extensionsToLocalize = glob.sync('./extensions/**/*.nls.json').map(function (extension) { return extension.split('/')[2]; });
- var resourcesToPull_1 = [];
- extensionsToLocalize.forEach(function (extension) {
- if (resourcesToPull_1.indexOf(extension) === -1) {
- resourcesToPull_1.push(extension);
- resources.push({ name: extension, project: projectName });
- }
- });
- }
- else if (projectName === setupProject) {
- resources.push({ name: 'setup_default', project: setupProject });
- }
- return resources;
-}
-function pullXlfFiles(projectName, apiHostname, username, password, languages, resources) {
- if (!resources) {
- resources = obtainProjectResources(projectName);
- }
- if (!resources) {
- throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.');
- }
- var credentials = username + ":" + password;
- var expectedTranslationsCount = languages.length * resources.length;
- var translationsRetrieved = 0, called = false;
- return event_stream_1.readable(function (count, callback) {
- // Mark end of stream when all resources were retrieved
- if (translationsRetrieved === expectedTranslationsCount) {
- return this.emit('end');
- }
- if (!called) {
- called = true;
- var stream_1 = this;
- // Retrieve XLF files from main projects
- languages.map(function (language) {
- resources.map(function (resource) {
- retrieveResource(language, resource, apiHostname, credentials).then(function (file) {
- stream_1.emit('data', file);
- translationsRetrieved++;
- }).catch(function (error) { throw new Error(error); });
- });
- });
- }
- callback();
- });
-}
-exports.pullXlfFiles = pullXlfFiles;
-function retrieveResource(language, resource, apiHostname, credentials) {
- return new Promise(function (resolve, reject) {
- var slug = resource.name.replace(/\//g, '_');
- var project = resource.project;
- var iso639 = language.toLowerCase();
- var options = {
- hostname: apiHostname,
- path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + iso639 + "?file&mode=onlyreviewed",
- auth: credentials,
- method: 'GET'
- };
- var request = http.request(options, function (res) {
- var xlfBuffer = [];
- res.on('data', function (chunk) { return xlfBuffer.push(chunk); });
- res.on('end', function () {
- if (res.statusCode === 200) {
- resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + iso639_2_to_3[language] + "/" + slug + ".xlf" }));
- }
- reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + ".");
- });
- });
- request.on('error', function (err) {
- reject("Failed to query resource " + slug + " with the following error: " + err);
- });
- request.end();
- });
-}
-function prepareJsonFiles() {
- var parsePromises = [];
- return event_stream_1.through(function (xlf) {
- var stream = this;
- var parsePromise = XLF.parse(xlf.contents.toString());
- parsePromises.push(parsePromise);
- parsePromise.then(function (resolvedFiles) {
- resolvedFiles.forEach(function (file) {
- var messages = file.messages, translatedFile;
- // ISL file path always starts with 'build/'
- if (file.originalFilePath.startsWith('build/')) {
- var defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true };
- if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) {
- return;
- }
- translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]);
- }
- else {
- translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages);
- }
- stream.emit('data', translatedFile);
- });
- }, function (rejectReason) {
- throw new Error("XLF parsing error: " + rejectReason);
- });
- }, function () {
- var _this = this;
- Promise.all(parsePromises)
- .then(function () { _this.emit('end'); })
- .catch(function (reason) { throw new Error(reason); });
- });
-}
-exports.prepareJsonFiles = prepareJsonFiles;
-function createI18nFile(base, originalFilePath, messages) {
- var content = [
- '/*---------------------------------------------------------------------------------------------',
- ' * Copyright (c) Microsoft Corporation. All rights reserved.',
- ' * Licensed under the MIT License. See License.txt in the project root for license information.',
- ' *--------------------------------------------------------------------------------------------*/',
- '// Do not edit this file. It is machine generated.'
- ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n');
- return new File({
- path: path.join(base, originalFilePath + '.i18n.json'),
- contents: new Buffer(content, 'utf8')
- });
-}
-var languageNames = {
- 'chs': 'Simplified Chinese',
- 'cht': 'Traditional Chinese',
- 'kor': 'Korean'
-};
-var languageIds = {
- 'chs': '$0804',
- 'cht': '$0404',
- 'kor': '$0412'
-};
-var encodings = {
- 'chs': 'CP936',
- 'cht': 'CP950',
- 'jpn': 'CP932',
- 'kor': 'CP949',
- 'deu': 'CP1252',
- 'fra': 'CP1252',
- 'esn': 'CP1252',
- 'rus': 'CP1251',
- 'ita': 'CP1252'
-};
-function createIslFile(base, originalFilePath, messages, language) {
- var content = [];
- var originalContent;
- if (path.basename(originalFilePath) === 'Default') {
- originalContent = new TextModel(fs.readFileSync(originalFilePath + '.isl', 'utf8'));
- }
- else {
- originalContent = new TextModel(fs.readFileSync(originalFilePath + '.en.isl', 'utf8'));
- }
- originalContent.lines.forEach(function (line) {
- if (line.length > 0) {
- var firstChar = line.charAt(0);
- if (firstChar === '[' || firstChar === ';') {
- if (line === '; *** Inno Setup version 5.5.3+ English messages ***') {
- content.push("; *** Inno Setup version 5.5.3+ " + languageNames[language] + " messages ***");
- }
- else {
- content.push(line);
- }
- }
- else {
- var sections = line.split('=');
- var key = sections[0];
- var translated = line;
- if (key) {
- if (key === 'LanguageName') {
- translated = key + "=" + languageNames[language];
- }
- else if (key === 'LanguageID') {
- translated = key + "=" + languageIds[language];
- }
- else if (key === 'LanguageCodePage') {
- translated = key + "=" + encodings[language].substr(2);
- }
- else {
- var translatedMessage = messages[key];
- if (translatedMessage) {
- translated = key + "=" + translatedMessage;
- }
- }
- }
- content.push(translated);
- }
- }
- });
- var tag = iso639_3_to_2[language];
- var basename = path.basename(originalFilePath);
- var filePath = path.join(base, path.dirname(originalFilePath), basename) + "." + tag + ".isl";
- return new File({
- path: filePath,
- contents: iconv.encode(new Buffer(content.join('\r\n'), 'utf8'), encodings[language])
- });
-}
-function encodeEntities(value) {
- var result = [];
- for (var i = 0; i < value.length; i++) {
- var ch = value[i];
- switch (ch) {
- case '<':
- result.push('<');
- break;
- case '>':
- result.push('>');
- break;
- case '&':
- result.push('&');
- break;
- default:
- result.push(ch);
- }
- }
- return result.join('');
-}
-function decodeEntities(value) {
- return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
-}
+"use strict";
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+Object.defineProperty(exports, "__esModule", { value: true });
+var path = require("path");
+var fs = require("fs");
+var event_stream_1 = require("event-stream");
+var File = require("vinyl");
+var Is = require("is");
+var xml2js = require("xml2js");
+var glob = require("glob");
+var http = require("http");
+var util = require('gulp-util');
+var iconv = require('iconv-lite');
+function log(message) {
+ var rest = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ rest[_i - 1] = arguments[_i];
+ }
+ util.log.apply(util, [util.colors.green('[i18n]'), message].concat(rest));
+}
+var LocalizeInfo;
+(function (LocalizeInfo) {
+ function is(value) {
+ var candidate = value;
+ return Is.defined(candidate) && Is.string(candidate.key) && (Is.undef(candidate.comment) || (Is.array(candidate.comment) && candidate.comment.every(function (element) { return Is.string(element); })));
+ }
+ LocalizeInfo.is = is;
+})(LocalizeInfo || (LocalizeInfo = {}));
+var BundledFormat;
+(function (BundledFormat) {
+ function is(value) {
+ if (Is.undef(value)) {
+ return false;
+ }
+ var candidate = value;
+ var length = Object.keys(value).length;
+ return length === 3 && Is.defined(candidate.keys) && Is.defined(candidate.messages) && Is.defined(candidate.bundles);
+ }
+ BundledFormat.is = is;
+})(BundledFormat || (BundledFormat = {}));
+var PackageJsonFormat;
+(function (PackageJsonFormat) {
+ function is(value) {
+ if (Is.undef(value) || !Is.object(value)) {
+ return false;
+ }
+ return Object.keys(value).every(function (key) {
+ var element = value[key];
+ return Is.string(element) || (Is.object(element) && Is.defined(element.message) && Is.defined(element.comment));
+ });
+ }
+ PackageJsonFormat.is = is;
+})(PackageJsonFormat || (PackageJsonFormat = {}));
+var ModuleJsonFormat;
+(function (ModuleJsonFormat) {
+ function is(value) {
+ var candidate = value;
+ return Is.defined(candidate)
+ && Is.array(candidate.messages) && candidate.messages.every(function (message) { return Is.string(message); })
+ && Is.array(candidate.keys) && candidate.keys.every(function (key) { return Is.string(key) || LocalizeInfo.is(key); });
+ }
+ ModuleJsonFormat.is = is;
+})(ModuleJsonFormat || (ModuleJsonFormat = {}));
+var Line = (function () {
+ function Line(indent) {
+ if (indent === void 0) { indent = 0; }
+ this.indent = indent;
+ this.buffer = [];
+ if (indent > 0) {
+ this.buffer.push(new Array(indent + 1).join(' '));
+ }
+ }
+ Line.prototype.append = function (value) {
+ this.buffer.push(value);
+ return this;
+ };
+ Line.prototype.toString = function () {
+ return this.buffer.join('');
+ };
+ return Line;
+}());
+exports.Line = Line;
+var TextModel = (function () {
+ function TextModel(contents) {
+ this._lines = contents.split(/\r\n|\r|\n/);
+ }
+ Object.defineProperty(TextModel.prototype, "lines", {
+ get: function () {
+ return this._lines;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ return TextModel;
+}());
+var XLF = (function () {
+ function XLF(project) {
+ this.project = project;
+ this.buffer = [];
+ this.files = Object.create(null);
+ }
+ XLF.prototype.toString = function () {
+ this.appendHeader();
+ for (var file in this.files) {
+ this.appendNewLine("", 2);
+ for (var _i = 0, _a = this.files[file]; _i < _a.length; _i++) {
+ var item = _a[_i];
+ this.addStringItem(item);
+ }
+ this.appendNewLine('', 2);
+ }
+ this.appendFooter();
+ return this.buffer.join('\r\n');
+ };
+ XLF.prototype.addFile = function (original, keys, messages) {
+ this.files[original] = [];
+ var existingKeys = [];
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
+ var key = keys_1[_i];
+ // Ignore duplicate keys because Transifex does not populate those with translated values.
+ if (existingKeys.indexOf(key) !== -1) {
+ continue;
+ }
+ existingKeys.push(key);
+ var message = encodeEntities(messages[keys.indexOf(key)]);
+ var comment = undefined;
+ // Check if the message contains description (if so, it becomes an object type in JSON)
+ if (Is.string(key)) {
+ this.files[original].push({ id: key, message: message, comment: comment });
+ }
+ else {
+ if (key['comment'] && key['comment'].length > 0) {
+ comment = key['comment'].map(function (comment) { return encodeEntities(comment); }).join('\r\n');
+ }
+ this.files[original].push({ id: key['key'], message: message, comment: comment });
+ }
+ }
+ };
+ XLF.prototype.addStringItem = function (item) {
+ if (!item.id || !item.message) {
+ throw new Error('No item ID or value specified.');
+ }
+ this.appendNewLine("", 4);
+ this.appendNewLine("" + item.message + "", 6);
+ if (item.comment) {
+ this.appendNewLine("" + item.comment + "", 6);
+ }
+ this.appendNewLine('', 4);
+ };
+ XLF.prototype.appendHeader = function () {
+ this.appendNewLine('', 0);
+ this.appendNewLine('', 0);
+ };
+ XLF.prototype.appendFooter = function () {
+ this.appendNewLine('', 0);
+ };
+ XLF.prototype.appendNewLine = function (content, indent) {
+ var line = new Line(indent);
+ line.append(content);
+ this.buffer.push(line.toString());
+ };
+ return XLF;
+}());
+XLF.parse = function (xlfString) {
+ return new Promise(function (resolve, reject) {
+ var parser = new xml2js.Parser();
+ var files = [];
+ parser.parseString(xlfString, function (err, result) {
+ if (err) {
+ reject("Failed to parse XLIFF string. " + err);
+ }
+ var fileNodes = result['xliff']['file'];
+ if (!fileNodes) {
+ reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.');
+ }
+ fileNodes.forEach(function (file) {
+ var originalFilePath = file.$.original;
+ if (!originalFilePath) {
+ reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.');
+ }
+ var language = file.$['target-language'].toLowerCase();
+ if (!language) {
+ reject('XLIFF file node does not contain target-language attribute to determine translated language.');
+ }
+ var messages = {};
+ var transUnits = file.body[0]['trans-unit'];
+ transUnits.forEach(function (unit) {
+ var key = unit.$.id;
+ if (!unit.target) {
+ return; // No translation available
+ }
+ var val = unit.target.toString();
+ if (key && val) {
+ messages[key] = decodeEntities(val);
+ }
+ else {
+ reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.');
+ }
+ });
+ files.push({ messages: messages, originalFilePath: originalFilePath, language: language });
+ });
+ resolve(files);
+ });
+ });
+};
+exports.XLF = XLF;
+var vscodeLanguages = [
+ 'chs',
+ 'cht',
+ 'jpn',
+ 'kor',
+ 'deu',
+ 'fra',
+ 'esn',
+ 'rus',
+ 'ita'
+];
+var iso639_3_to_2 = {
+ 'chs': 'zh-cn',
+ 'cht': 'zh-tw',
+ 'csy': 'cs-cz',
+ 'deu': 'de',
+ 'enu': 'en',
+ 'esn': 'es',
+ 'fra': 'fr',
+ 'hun': 'hu',
+ 'ita': 'it',
+ 'jpn': 'ja',
+ 'kor': 'ko',
+ 'nld': 'nl',
+ 'plk': 'pl',
+ 'ptb': 'pt-br',
+ 'ptg': 'pt',
+ 'rus': 'ru',
+ 'sve': 'sv-se',
+ 'trk': 'tr'
+};
+/**
+ * Used to map Transifex to VS Code language code representation.
+ */
+var iso639_2_to_3 = {
+ 'zh-hans': 'chs',
+ 'zh-hant': 'cht',
+ 'cs-cz': 'csy',
+ 'de': 'deu',
+ 'en': 'enu',
+ 'es': 'esn',
+ 'fr': 'fra',
+ 'hu': 'hun',
+ 'it': 'ita',
+ 'ja': 'jpn',
+ 'ko': 'kor',
+ 'nl': 'nld',
+ 'pl': 'plk',
+ 'pt-br': 'ptb',
+ 'pt': 'ptg',
+ 'ru': 'rus',
+ 'sv-se': 'sve',
+ 'tr': 'trk'
+};
+function sortLanguages(directoryNames) {
+ return directoryNames.map(function (dirName) {
+ var lower = dirName.toLowerCase();
+ return {
+ name: lower,
+ iso639_2: iso639_3_to_2[lower]
+ };
+ }).sort(function (a, b) {
+ if (!a.iso639_2 && !b.iso639_2) {
+ return 0;
+ }
+ if (!a.iso639_2) {
+ return -1;
+ }
+ if (!b.iso639_2) {
+ return 1;
+ }
+ return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0);
+ });
+}
+function stripComments(content) {
+ /**
+ * First capturing group matches double quoted string
+ * Second matches single quotes string
+ * Third matches block comments
+ * Fourth matches line comments
+ */
+ var regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
+ var result = content.replace(regexp, function (match, m1, m2, m3, m4) {
+ // Only one of m1, m2, m3, m4 matches
+ if (m3) {
+ // A block comment. Replace with nothing
+ return '';
+ }
+ else if (m4) {
+ // A line comment. If it ends in \r?\n then keep it.
+ var length_1 = m4.length;
+ if (length_1 > 2 && m4[length_1 - 1] === '\n') {
+ return m4[length_1 - 2] === '\r' ? '\r\n' : '\n';
+ }
+ else {
+ return '';
+ }
+ }
+ else {
+ // We match a string
+ return match;
+ }
+ });
+ return result;
+}
+function escapeCharacters(value) {
+ var result = [];
+ for (var i = 0; i < value.length; i++) {
+ var ch = value.charAt(i);
+ switch (ch) {
+ case '\'':
+ result.push('\\\'');
+ break;
+ case '"':
+ result.push('\\"');
+ break;
+ case '\\':
+ result.push('\\\\');
+ break;
+ case '\n':
+ result.push('\\n');
+ break;
+ case '\r':
+ result.push('\\r');
+ break;
+ case '\t':
+ result.push('\\t');
+ break;
+ case '\b':
+ result.push('\\b');
+ break;
+ case '\f':
+ result.push('\\f');
+ break;
+ default:
+ result.push(ch);
+ }
+ }
+ return result.join('');
+}
+function processCoreBundleFormat(fileHeader, json, emitter) {
+ var keysSection = json.keys;
+ var messageSection = json.messages;
+ var bundleSection = json.bundles;
+ var statistics = Object.create(null);
+ var total = 0;
+ var defaultMessages = Object.create(null);
+ var modules = Object.keys(keysSection);
+ modules.forEach(function (module) {
+ var keys = keysSection[module];
+ var messages = messageSection[module];
+ if (!messages || keys.length !== messages.length) {
+ emitter.emit('error', "Message for module " + module + " corrupted. Mismatch in number of keys and messages.");
+ return;
+ }
+ var messageMap = Object.create(null);
+ defaultMessages[module] = messageMap;
+ keys.map(function (key, i) {
+ total++;
+ if (Is.string(key)) {
+ messageMap[key] = messages[i];
+ }
+ else {
+ messageMap[key.key] = messages[i];
+ }
+ });
+ });
+ var languageDirectory = path.join(__dirname, '..', '..', 'i18n');
+ var languages = sortLanguages(fs.readdirSync(languageDirectory).filter(function (item) { return fs.statSync(path.join(languageDirectory, item)).isDirectory(); }));
+ languages.forEach(function (language) {
+ if (!language.iso639_2) {
+ return;
+ }
+ if (process.env['VSCODE_BUILD_VERBOSE']) {
+ log("Generating nls bundles for: " + language.iso639_2);
+ }
+ statistics[language.iso639_2] = 0;
+ var localizedModules = Object.create(null);
+ var cwd = path.join(languageDirectory, language.name, 'src');
+ modules.forEach(function (module) {
+ var order = keysSection[module];
+ var i18nFile = path.join(cwd, module) + '.i18n.json';
+ var messages = null;
+ if (fs.existsSync(i18nFile)) {
+ var content = stripComments(fs.readFileSync(i18nFile, 'utf8'));
+ messages = JSON.parse(content);
+ }
+ else {
+ if (process.env['VSCODE_BUILD_VERBOSE']) {
+ log("No localized messages found for module " + module + ". Using default messages.");
+ }
+ messages = defaultMessages[module];
+ statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length;
+ }
+ var localizedMessages = [];
+ order.forEach(function (keyInfo) {
+ var key = null;
+ if (Is.string(keyInfo)) {
+ key = keyInfo;
+ }
+ else {
+ key = keyInfo.key;
+ }
+ var message = messages[key];
+ if (!message) {
+ if (process.env['VSCODE_BUILD_VERBOSE']) {
+ log("No localized message found for key " + key + " in module " + module + ". Using default message.");
+ }
+ message = defaultMessages[module][key];
+ statistics[language.iso639_2] = statistics[language.iso639_2] + 1;
+ }
+ localizedMessages.push(message);
+ });
+ localizedModules[module] = localizedMessages;
+ });
+ Object.keys(bundleSection).forEach(function (bundle) {
+ var modules = bundleSection[bundle];
+ var contents = [
+ fileHeader,
+ "define(\"" + bundle + ".nls." + language.iso639_2 + "\", {"
+ ];
+ modules.forEach(function (module, index) {
+ contents.push("\t\"" + module + "\": [");
+ var messages = localizedModules[module];
+ if (!messages) {
+ emitter.emit('error', "Didn't find messages for module " + module + ".");
+ return;
+ }
+ messages.forEach(function (message, index) {
+ contents.push("\t\t\"" + escapeCharacters(message) + (index < messages.length ? '",' : '"'));
+ });
+ contents.push(index < modules.length - 1 ? '\t],' : '\t]');
+ });
+ contents.push('});');
+ emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') }));
+ });
+ });
+ Object.keys(statistics).forEach(function (key) {
+ var value = statistics[key];
+ log(key + " has " + value + " untranslated strings.");
+ });
+ vscodeLanguages.forEach(function (language) {
+ var iso639_2 = iso639_3_to_2[language];
+ if (!iso639_2) {
+ log("\tCouldn't find iso639 2 mapping for language " + language + ". Using default language instead.");
+ }
+ else {
+ var stats = statistics[iso639_2];
+ if (Is.undef(stats)) {
+ log("\tNo translations found for language " + language + ". Using default language instead.");
+ }
+ }
+ });
+}
+function processNlsFiles(opts) {
+ return event_stream_1.through(function (file) {
+ var fileName = path.basename(file.path);
+ if (fileName === 'nls.metadata.json') {
+ var json = null;
+ if (file.isBuffer()) {
+ json = JSON.parse(file.contents.toString('utf8'));
+ }
+ else {
+ this.emit('error', "Failed to read component file: " + file.relative);
+ }
+ if (BundledFormat.is(json)) {
+ processCoreBundleFormat(opts.fileHeader, json, this);
+ }
+ }
+ this.emit('data', file);
+ });
+}
+exports.processNlsFiles = processNlsFiles;
+function prepareXlfFiles(projectName, extensionName) {
+ return event_stream_1.through(function (file) {
+ if (!file.isBuffer()) {
+ throw new Error("Failed to read component file: " + file.relative);
+ }
+ var extension = path.extname(file.path);
+ if (extension === '.json') {
+ var json = JSON.parse(file.contents.toString('utf8'));
+ if (BundledFormat.is(json)) {
+ importBundleJson(file, json, this);
+ }
+ else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) {
+ importModuleOrPackageJson(file, json, projectName, this, extensionName);
+ }
+ else {
+ throw new Error("JSON format cannot be deduced for " + file.relative + ".");
+ }
+ }
+ else if (extension === '.isl') {
+ importIsl(file, this);
+ }
+ });
+}
+exports.prepareXlfFiles = prepareXlfFiles;
+var editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup';
+/**
+ * Ensure to update those arrays when new resources are pushed to Transifex.
+ * Used because Transifex does not have API method to pull all project resources.
+ */
+var editorResources = [
+ { name: 'vs/platform', project: editorProject },
+ { name: 'vs/editor/contrib', project: editorProject },
+ { name: 'vs/editor', project: editorProject },
+ { name: 'vs/base', project: editorProject }
+];
+var workbenchResources = [
+ { name: 'vs/code', project: workbenchProject },
+ { name: 'vs/workbench', project: workbenchProject },
+ { name: 'vs/workbench/parts/cli', project: workbenchProject },
+ { name: 'vs/workbench/parts/codeEditor', project: workbenchProject },
+ { name: 'vs/workbench/parts/debug', project: workbenchProject },
+ { name: 'vs/workbench/parts/emmet', project: workbenchProject },
+ { name: 'vs/workbench/parts/execution', project: workbenchProject },
+ { name: 'vs/workbench/parts/explorers', project: workbenchProject },
+ { name: 'vs/workbench/parts/extensions', project: workbenchProject },
+ { name: 'vs/workbench/parts/feedback', project: workbenchProject },
+ { name: 'vs/workbench/parts/files', project: workbenchProject },
+ { name: 'vs/workbench/parts/html', project: workbenchProject },
+ { name: 'vs/workbench/parts/markers', project: workbenchProject },
+ { name: 'vs/workbench/parts/nps', project: workbenchProject },
+ { name: 'vs/workbench/parts/output', project: workbenchProject },
+ { name: 'vs/workbench/parts/performance', project: workbenchProject },
+ { name: 'vs/workbench/parts/preferences', project: workbenchProject },
+ { name: 'vs/workbench/parts/quickopen', project: workbenchProject },
+ { name: 'vs/workbench/parts/scm', project: workbenchProject },
+ { name: 'vs/workbench/parts/search', project: workbenchProject },
+ { name: 'vs/workbench/parts/snippets', project: workbenchProject },
+ { name: 'vs/workbench/parts/tasks', project: workbenchProject },
+ { name: 'vs/workbench/parts/terminal', project: workbenchProject },
+ { name: 'vs/workbench/parts/themes', project: workbenchProject },
+ { name: 'vs/workbench/parts/trust', project: workbenchProject },
+ { name: 'vs/workbench/parts/update', project: workbenchProject },
+ { name: 'vs/workbench/parts/watermark', project: workbenchProject },
+ { name: 'vs/workbench/parts/welcome', project: workbenchProject },
+ { name: 'vs/workbench/services/configuration', project: workbenchProject },
+ { name: 'vs/workbench/services/editor', project: workbenchProject },
+ { name: 'vs/workbench/services/files', project: workbenchProject },
+ { name: 'vs/workbench/services/keybinding', project: workbenchProject },
+ { name: 'vs/workbench/services/message', project: workbenchProject },
+ { name: 'vs/workbench/services/mode', project: workbenchProject },
+ { name: 'vs/workbench/services/textfile', project: workbenchProject },
+ { name: 'vs/workbench/services/themes', project: workbenchProject },
+ { name: 'setup_messages', project: workbenchProject }
+];
+function getResource(sourceFile) {
+ var resource;
+ if (/^vs\/platform/.test(sourceFile)) {
+ return { name: 'vs/platform', project: editorProject };
+ }
+ else if (/^vs\/editor\/contrib/.test(sourceFile)) {
+ return { name: 'vs/editor/contrib', project: editorProject };
+ }
+ else if (/^vs\/editor/.test(sourceFile)) {
+ return { name: 'vs/editor', project: editorProject };
+ }
+ else if (/^vs\/base/.test(sourceFile)) {
+ return { name: 'vs/base', project: editorProject };
+ }
+ else if (/^vs\/code/.test(sourceFile)) {
+ return { name: 'vs/code', project: workbenchProject };
+ }
+ else if (/^vs\/workbench\/parts/.test(sourceFile)) {
+ resource = sourceFile.split('/', 4).join('/');
+ return { name: resource, project: workbenchProject };
+ }
+ else if (/^vs\/workbench\/services/.test(sourceFile)) {
+ resource = sourceFile.split('/', 4).join('/');
+ return { name: resource, project: workbenchProject };
+ }
+ else if (/^vs\/workbench/.test(sourceFile)) {
+ return { name: 'vs/workbench', project: workbenchProject };
+ }
+ throw new Error("Could not identify the XLF bundle for " + sourceFile);
+}
+exports.getResource = getResource;
+function importBundleJson(file, json, stream) {
+ var bundleXlfs = Object.create(null);
+ for (var source in json.keys) {
+ var projectResource = getResource(source);
+ var resource = projectResource.name;
+ var project = projectResource.project;
+ var keys = json.keys[source];
+ var messages = json.messages[source];
+ if (keys.length !== messages.length) {
+ throw new Error("There is a mismatch between keys and messages in " + file.relative);
+ }
+ var xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project);
+ xlf.addFile('src/' + source, keys, messages);
+ }
+ for (var resource in bundleXlfs) {
+ var newFilePath = bundleXlfs[resource].project + "/" + resource.replace(/\//g, '_') + ".xlf";
+ var xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') });
+ stream.emit('data', xlfFile);
+ }
+}
+// Keeps existing XLF instances and a state of how many files were already processed for faster file emission
+var extensions = Object.create(null);
+function importModuleOrPackageJson(file, json, projectName, stream, extensionName) {
+ if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) {
+ throw new Error("There is a mismatch between keys and messages in " + file.relative);
+ }
+ // Prepare the source path for attribute in XLF & extract messages from JSON
+ var formattedSourcePath = file.relative.replace(/\\/g, '/');
+ var messages = Object.keys(json).map(function (key) { return json[key].toString(); });
+ // Stores the amount of localization files to be transformed to XLF before the emission
+ var localizationFilesCount, originalFilePath;
+ // If preparing XLF for external extension, then use different glob pattern and source path
+ if (extensionName) {
+ localizationFilesCount = glob.sync('**/*.nls.json').length;
+ originalFilePath = "" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
+ }
+ else {
+ // Used for vscode/extensions folder
+ extensionName = formattedSourcePath.split('/')[0];
+ localizationFilesCount = glob.sync("./extensions/" + extensionName + "/**/*.nls.json").length;
+ originalFilePath = "extensions/" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
+ }
+ var extension = extensions[extensionName] ?
+ extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 };
+ if (ModuleJsonFormat.is(json)) {
+ extension.xlf.addFile(originalFilePath, json['keys'], json['messages']);
+ }
+ else {
+ extension.xlf.addFile(originalFilePath, Object.keys(json), messages);
+ }
+ // Check if XLF is populated with file nodes to emit it
+ if (++extensions[extensionName].processed === localizationFilesCount) {
+ var newFilePath = path.join(projectName, extensionName + '.xlf');
+ var xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') });
+ stream.emit('data', xlfFile);
+ }
+}
+function importIsl(file, stream) {
+ var projectName, resourceFile;
+ if (path.basename(file.path) === 'Default.isl') {
+ projectName = setupProject;
+ resourceFile = 'setup_default.xlf';
+ }
+ else {
+ projectName = workbenchProject;
+ resourceFile = 'setup_messages.xlf';
+ }
+ var xlf = new XLF(projectName), keys = [], messages = [];
+ var model = new TextModel(file.contents.toString());
+ var inMessageSection = false;
+ model.lines.forEach(function (line) {
+ if (line.length === 0) {
+ return;
+ }
+ var firstChar = line.charAt(0);
+ switch (firstChar) {
+ case ';':
+ // Comment line;
+ return;
+ case '[':
+ inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
+ return;
+ }
+ if (!inMessageSection) {
+ return;
+ }
+ var sections = line.split('=');
+ if (sections.length !== 2) {
+ throw new Error("Badly formatted message found: " + line);
+ }
+ else {
+ var key = sections[0];
+ var value = sections[1];
+ if (key.length > 0 && value.length > 0) {
+ keys.push(key);
+ messages.push(value);
+ }
+ }
+ });
+ var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
+ xlf.addFile(originalPath, keys, messages);
+ // Emit only upon all ISL files combined into single XLF instance
+ var newFilePath = path.join(projectName, resourceFile);
+ var xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') });
+ stream.emit('data', xlfFile);
+}
+function pushXlfFiles(apiHostname, username, password) {
+ var tryGetPromises = [];
+ var updateCreatePromises = [];
+ return event_stream_1.through(function (file) {
+ var project = path.dirname(file.relative);
+ var fileName = path.basename(file.path);
+ var slug = fileName.substr(0, fileName.length - '.xlf'.length);
+ var credentials = username + ":" + password;
+ // Check if resource already exists, if not, then create it.
+ var promise = tryGetResource(project, slug, apiHostname, credentials);
+ tryGetPromises.push(promise);
+ promise.then(function (exists) {
+ if (exists) {
+ promise = updateResource(project, slug, file, apiHostname, credentials);
+ }
+ else {
+ promise = createResource(project, slug, file, apiHostname, credentials);
+ }
+ updateCreatePromises.push(promise);
+ });
+ }, function () {
+ var _this = this;
+ // End the pipe only after all the communication with Transifex API happened
+ Promise.all(tryGetPromises).then(function () {
+ Promise.all(updateCreatePromises).then(function () {
+ _this.emit('end');
+ }).catch(function (reason) { throw new Error(reason); });
+ }).catch(function (reason) { throw new Error(reason); });
+ });
+}
+exports.pushXlfFiles = pushXlfFiles;
+function tryGetResource(project, slug, apiHostname, credentials) {
+ return new Promise(function (resolve, reject) {
+ var options = {
+ hostname: apiHostname,
+ path: "/api/2/project/" + project + "/resource/" + slug + "/?details",
+ auth: credentials,
+ method: 'GET'
+ };
+ var request = http.request(options, function (response) {
+ if (response.statusCode === 404) {
+ resolve(false);
+ }
+ else if (response.statusCode === 200) {
+ resolve(true);
+ }
+ else {
+ reject("Failed to query resource " + project + "/" + slug + ". Response: " + response.statusCode + " " + response.statusMessage);
+ }
+ });
+ request.on('error', function (err) {
+ reject("Failed to get " + project + "/" + slug + " on Transifex: " + err);
+ });
+ request.end();
+ });
+}
+function createResource(project, slug, xlfFile, apiHostname, credentials) {
+ return new Promise(function (resolve, reject) {
+ var data = JSON.stringify({
+ 'content': xlfFile.contents.toString(),
+ 'name': slug,
+ 'slug': slug,
+ 'i18n_type': 'XLIFF'
+ });
+ var options = {
+ hostname: apiHostname,
+ path: "/api/2/project/" + project + "/resources",
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Content-Length': Buffer.byteLength(data)
+ },
+ auth: credentials,
+ method: 'POST'
+ };
+ var request = http.request(options, function (res) {
+ if (res.statusCode === 201) {
+ log("Resource " + project + "/" + slug + " successfully created on Transifex.");
+ }
+ else {
+ reject("Something went wrong in the request creating " + slug + " in " + project + ". " + res.statusCode);
+ }
+ });
+ request.on('error', function (err) {
+ reject("Failed to create " + project + "/" + slug + " on Transifex: " + err);
+ });
+ request.write(data);
+ request.end();
+ });
+}
+/**
+ * The following link provides information about how Transifex handles updates of a resource file:
+ * https://dev.befoolish.co/tx-docs/public/projects/updating-content#what-happens-when-you-update-files
+ */
+function updateResource(project, slug, xlfFile, apiHostname, credentials) {
+ return new Promise(function (resolve, reject) {
+ var data = JSON.stringify({ content: xlfFile.contents.toString() });
+ var options = {
+ hostname: apiHostname,
+ path: "/api/2/project/" + project + "/resource/" + slug + "/content",
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Content-Length': Buffer.byteLength(data)
+ },
+ auth: credentials,
+ method: 'PUT'
+ };
+ var request = http.request(options, function (res) {
+ if (res.statusCode === 200) {
+ res.setEncoding('utf8');
+ var responseBuffer_1 = '';
+ res.on('data', function (chunk) {
+ responseBuffer_1 += chunk;
+ });
+ res.on('end', function () {
+ var response = JSON.parse(responseBuffer_1);
+ log("Resource " + project + "/" + slug + " successfully updated on Transifex. Strings added: " + response.strings_added + ", updated: " + response.strings_added + ", deleted: " + response.strings_added);
+ resolve();
+ });
+ }
+ else {
+ reject("Something went wrong in the request updating " + slug + " in " + project + ". " + res.statusCode);
+ }
+ });
+ request.on('error', function (err) {
+ reject("Failed to update " + project + "/" + slug + " on Transifex: " + err);
+ });
+ request.write(data);
+ request.end();
+ });
+}
+function obtainProjectResources(projectName) {
+ var resources = [];
+ if (projectName === editorProject) {
+ resources = editorResources;
+ }
+ else if (projectName === workbenchProject) {
+ resources = workbenchResources;
+ }
+ else if (projectName === extensionsProject) {
+ var extensionsToLocalize = glob.sync('./extensions/**/*.nls.json').map(function (extension) { return extension.split('/')[2]; });
+ var resourcesToPull_1 = [];
+ extensionsToLocalize.forEach(function (extension) {
+ if (resourcesToPull_1.indexOf(extension) === -1) {
+ resourcesToPull_1.push(extension);
+ resources.push({ name: extension, project: projectName });
+ }
+ });
+ }
+ else if (projectName === setupProject) {
+ resources.push({ name: 'setup_default', project: setupProject });
+ }
+ return resources;
+}
+function pullXlfFiles(projectName, apiHostname, username, password, languages, resources) {
+ if (!resources) {
+ resources = obtainProjectResources(projectName);
+ }
+ if (!resources) {
+ throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.');
+ }
+ var credentials = username + ":" + password;
+ var expectedTranslationsCount = languages.length * resources.length;
+ var translationsRetrieved = 0, called = false;
+ return event_stream_1.readable(function (count, callback) {
+ // Mark end of stream when all resources were retrieved
+ if (translationsRetrieved === expectedTranslationsCount) {
+ return this.emit('end');
+ }
+ if (!called) {
+ called = true;
+ var stream_1 = this;
+ // Retrieve XLF files from main projects
+ languages.map(function (language) {
+ resources.map(function (resource) {
+ retrieveResource(language, resource, apiHostname, credentials).then(function (file) {
+ stream_1.emit('data', file);
+ translationsRetrieved++;
+ }).catch(function (error) { throw new Error(error); });
+ });
+ });
+ }
+ callback();
+ });
+}
+exports.pullXlfFiles = pullXlfFiles;
+function retrieveResource(language, resource, apiHostname, credentials) {
+ return new Promise(function (resolve, reject) {
+ var slug = resource.name.replace(/\//g, '_');
+ var project = resource.project;
+ var iso639 = language.toLowerCase();
+ var options = {
+ hostname: apiHostname,
+ path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + iso639 + "?file&mode=onlyreviewed",
+ auth: credentials,
+ method: 'GET'
+ };
+ var request = http.request(options, function (res) {
+ var xlfBuffer = [];
+ res.on('data', function (chunk) { return xlfBuffer.push(chunk); });
+ res.on('end', function () {
+ if (res.statusCode === 200) {
+ resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + iso639_2_to_3[language] + "/" + slug + ".xlf" }));
+ }
+ reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + ".");
+ });
+ });
+ request.on('error', function (err) {
+ reject("Failed to query resource " + slug + " with the following error: " + err);
+ });
+ request.end();
+ });
+}
+function prepareJsonFiles() {
+ var parsePromises = [];
+ return event_stream_1.through(function (xlf) {
+ var stream = this;
+ var parsePromise = XLF.parse(xlf.contents.toString());
+ parsePromises.push(parsePromise);
+ parsePromise.then(function (resolvedFiles) {
+ resolvedFiles.forEach(function (file) {
+ var messages = file.messages, translatedFile;
+ // ISL file path always starts with 'build/'
+ if (/^build\//.test(file.originalFilePath)) {
+ var defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true };
+ if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) {
+ return;
+ }
+ translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]);
+ }
+ else {
+ translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages);
+ }
+ stream.emit('data', translatedFile);
+ });
+ }, function (rejectReason) {
+ throw new Error("XLF parsing error: " + rejectReason);
+ });
+ }, function () {
+ var _this = this;
+ Promise.all(parsePromises)
+ .then(function () { _this.emit('end'); })
+ .catch(function (reason) { throw new Error(reason); });
+ });
+}
+exports.prepareJsonFiles = prepareJsonFiles;
+function createI18nFile(base, originalFilePath, messages) {
+ var content = [
+ '/*---------------------------------------------------------------------------------------------',
+ ' * Copyright (c) Microsoft Corporation. All rights reserved.',
+ ' * Licensed under the MIT License. See License.txt in the project root for license information.',
+ ' *--------------------------------------------------------------------------------------------*/',
+ '// Do not edit this file. It is machine generated.'
+ ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n');
+ return new File({
+ path: path.join(base, originalFilePath + '.i18n.json'),
+ contents: new Buffer(content, 'utf8')
+ });
+}
+var languageNames = {
+ 'chs': 'Simplified Chinese',
+ 'cht': 'Traditional Chinese',
+ 'kor': 'Korean'
+};
+var languageIds = {
+ 'chs': '$0804',
+ 'cht': '$0404',
+ 'kor': '$0412'
+};
+var encodings = {
+ 'chs': 'CP936',
+ 'cht': 'CP950',
+ 'jpn': 'CP932',
+ 'kor': 'CP949',
+ 'deu': 'CP1252',
+ 'fra': 'CP1252',
+ 'esn': 'CP1252',
+ 'rus': 'CP1251',
+ 'ita': 'CP1252',
+ 'ptb': 'CP1252'
+};
+function createIslFile(base, originalFilePath, messages, language) {
+ var content = [];
+ var originalContent;
+ if (path.basename(originalFilePath) === 'Default') {
+ originalContent = new TextModel(fs.readFileSync(originalFilePath + '.isl', 'utf8'));
+ }
+ else {
+ originalContent = new TextModel(fs.readFileSync(originalFilePath + '.en.isl', 'utf8'));
+ }
+ originalContent.lines.forEach(function (line) {
+ if (line.length > 0) {
+ var firstChar = line.charAt(0);
+ if (firstChar === '[' || firstChar === ';') {
+ if (line === '; *** Inno Setup version 5.5.3+ English messages ***') {
+ content.push("; *** Inno Setup version 5.5.3+ " + languageNames[language] + " messages ***");
+ }
+ else {
+ content.push(line);
+ }
+ }
+ else {
+ var sections = line.split('=');
+ var key = sections[0];
+ var translated = line;
+ if (key) {
+ if (key === 'LanguageName') {
+ translated = key + "=" + languageNames[language];
+ }
+ else if (key === 'LanguageID') {
+ translated = key + "=" + languageIds[language];
+ }
+ else if (key === 'LanguageCodePage') {
+ translated = key + "=" + encodings[language].substr(2);
+ }
+ else {
+ var translatedMessage = messages[key];
+ if (translatedMessage) {
+ translated = key + "=" + translatedMessage;
+ }
+ }
+ }
+ content.push(translated);
+ }
+ }
+ });
+ var tag = iso639_3_to_2[language];
+ var basename = path.basename(originalFilePath);
+ var filePath = path.join(base, path.dirname(originalFilePath), basename) + "." + tag + ".isl";
+ return new File({
+ path: filePath,
+ contents: iconv.encode(new Buffer(content.join('\r\n'), 'utf8'), encodings[language])
+ });
+}
+function encodeEntities(value) {
+ var result = [];
+ for (var i = 0; i < value.length; i++) {
+ var ch = value[i];
+ switch (ch) {
+ case '<':
+ result.push('<');
+ break;
+ case '>':
+ result.push('>');
+ break;
+ case '&':
+ result.push('&');
+ break;
+ default:
+ result.push(ch);
+ }
+ }
+ return result.join('');
+}
+function decodeEntities(value) {
+ return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
+}
diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts
index 434d3301752..9667b01fa2f 100644
--- a/build/lib/i18n.ts
+++ b/build/lib/i18n.ts
@@ -140,23 +140,23 @@ class TextModel {
}
export class XLF {
- private buffer: string[];
+ private buffer: string[];
private files: Map- ;
- constructor(public project: string) {
- this.buffer = [];
+ constructor(public project: string) {
+ this.buffer = [];
this.files = Object.create(null);
}
- public toString(): string {
- this.appendHeader();
+ public toString(): string {
+ this.appendHeader();
for (let file in this.files) {
this.appendNewLine(``, 2);
for (let item of this.files[file]) {
this.addStringItem(item);
}
- this.appendNewLine('', 2);
+ this.appendNewLine('