diff --git a/build/lib/extensions.js b/build/lib/extensions.js index d289ccf9107..0a4434bf4e3 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -22,22 +22,28 @@ const fancyLog = require("fancy-log"); const ansiColors = require("ansi-colors"); const buffer = require('gulp-buffer'); const json = require("gulp-json-editor"); +const jsoncParser = require("jsonc-parser"); const webpack = require('webpack'); const webpackGulp = require('webpack-stream'); const util = require('./util'); const root = path.dirname(path.dirname(__dirname)); const commit = util.getVersion(root); const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; -function minimizeLanguageJSON(input) { - const tmLanguageJsonFilter = filter('**/*.tmLanguage.json', { restore: true }); +function minifyExtensionResources(input) { + const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true }); return input - .pipe(tmLanguageJsonFilter) + .pipe(jsonFilter) .pipe(buffer()) .pipe(es.mapSync((f) => { - f.contents = Buffer.from(JSON.stringify(JSON.parse(f.contents.toString('utf8')))); + const errors = []; + const value = jsoncParser.parse(f.contents.toString('utf8'), errors); + if (errors.length === 0) { + // file parsed OK => just stringify to drop whitespace and comments + f.contents = Buffer.from(JSON.stringify(value)); + } return f; })) - .pipe(tmLanguageJsonFilter.restore); + .pipe(jsonFilter.restore); } function updateExtensionPackageJSON(input, update) { const packageJsonFilter = filter('extensions/*/package.json', { restore: true }); @@ -59,6 +65,9 @@ function fromLocal(extensionPath, forWeb) { : fromLocalNormal(extensionPath); if (forWeb) { input = updateExtensionPackageJSON(input, (data) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; if (data.browser) { data.main = data.browser; } @@ -68,13 +77,16 @@ function fromLocal(extensionPath, forWeb) { } else if (isWebPacked) { input = updateExtensionPackageJSON(input, (data) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; if (data.main) { data.main = data.main.replace('/out/', /dist/); } return data; }); } - return minimizeLanguageJSON(input); + return input; } function fromLocalWebpack(extensionPath, webpackConfigFileName) { const result = es.through(); @@ -215,8 +227,8 @@ function packageLocalExtensionsStream() { .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); }); const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); - return es.merge(nodeModules, ...localExtensions) - .pipe(util2.setExecutableBit(['**/*.sh'])); + return minifyExtensionResources(es.merge(nodeModules, ...localExtensions) + .pipe(util2.setExecutableBit(['**/*.sh']))); } exports.packageLocalExtensionsStream = packageLocalExtensionsStream; function packageLocalWebExtensionsStream() { @@ -230,10 +242,10 @@ function packageLocalWebExtensionsStream() { const extensionName = path.basename(extensionPath); return { name: extensionName, path: extensionPath }; }); - return es.merge(...localExtensionDescriptions.map(extension => { + return minifyExtensionResources(es.merge(...localExtensionDescriptions.map(extension => { return fromLocal(extension.path, true) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - })); + }))); } exports.packageLocalWebExtensionsStream = packageLocalWebExtensionsStream; function packageMarketplaceExtensionsStream() { @@ -241,8 +253,8 @@ function packageMarketplaceExtensionsStream() { return fromMarketplace(extension.name, extension.version, extension.metadata) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); }); - return es.merge(extensions) - .pipe(util2.setExecutableBit(['**/*.sh'])); + return minifyExtensionResources(es.merge(extensions) + .pipe(util2.setExecutableBit(['**/*.sh']))); } exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream; function packageMarketplaceWebExtensionsStream(builtInExtensions) { @@ -258,7 +270,7 @@ function packageMarketplaceWebExtensionsStream(builtInExtensions) { return data; }); }); - return es.merge(extensions); + return minifyExtensionResources(es.merge(extensions)); } exports.packageMarketplaceWebExtensionsStream = packageMarketplaceWebExtensionsStream; function scanBuiltinExtensions(extensionsRoot, forWeb) { diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 3810723d7d4..e41cc473e3c 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -21,6 +21,7 @@ import * as fancyLog from 'fancy-log'; import * as ansiColors from 'ansi-colors'; const buffer = require('gulp-buffer'); import json = require('gulp-json-editor'); +import * as jsoncParser from 'jsonc-parser'; const webpack = require('webpack'); const webpackGulp = require('webpack-stream'); const util = require('./util'); @@ -28,16 +29,21 @@ const root = path.dirname(path.dirname(__dirname)); const commit = util.getVersion(root); const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`; -function minimizeLanguageJSON(input: Stream): Stream { - const tmLanguageJsonFilter = filter('**/*.tmLanguage.json', { restore: true }); +function minifyExtensionResources(input: Stream): Stream { + const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true }); return input - .pipe(tmLanguageJsonFilter) + .pipe(jsonFilter) .pipe(buffer()) .pipe(es.mapSync((f: File) => { - f.contents = Buffer.from(JSON.stringify(JSON.parse(f.contents.toString('utf8')))); + const errors: jsoncParser.ParseError[] = []; + const value = jsoncParser.parse(f.contents.toString('utf8'), errors); + if (errors.length === 0) { + // file parsed OK => just stringify to drop whitespace and comments + f.contents = Buffer.from(JSON.stringify(value)); + } return f; })) - .pipe(tmLanguageJsonFilter.restore); + .pipe(jsonFilter.restore); } function updateExtensionPackageJSON(input: Stream, update: (data: any) => any): Stream { @@ -63,6 +69,9 @@ function fromLocal(extensionPath: string, forWeb: boolean): Stream { if (forWeb) { input = updateExtensionPackageJSON(input, (data: any) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; if (data.browser) { data.main = data.browser; } @@ -71,6 +80,9 @@ function fromLocal(extensionPath: string, forWeb: boolean): Stream { }); } else if (isWebPacked) { input = updateExtensionPackageJSON(input, (data: any) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; if (data.main) { data.main = data.main.replace('/out/', /dist/); } @@ -78,7 +90,7 @@ function fromLocal(extensionPath: string, forWeb: boolean): Stream { }); } - return minimizeLanguageJSON(input); + return input; } @@ -243,7 +255,7 @@ interface IBuiltInExtension { const builtInExtensions: IBuiltInExtension[] = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')).builtInExtensions; -export function packageLocalExtensionsStream(): NodeJS.ReadWriteStream { +export function packageLocalExtensionsStream(): Stream { const localExtensionDescriptions = (glob.sync('extensions/*/package.json')) .map(manifestPath => { const extensionPath = path.dirname(path.join(root, manifestPath)); @@ -260,11 +272,13 @@ export function packageLocalExtensionsStream(): NodeJS.ReadWriteStream { }); const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); - return es.merge(nodeModules, ...localExtensions) - .pipe(util2.setExecutableBit(['**/*.sh'])); + return minifyExtensionResources( + es.merge(nodeModules, ...localExtensions) + .pipe(util2.setExecutableBit(['**/*.sh'])) + ); } -export function packageLocalWebExtensionsStream(): NodeJS.ReadWriteStream { +export function packageLocalWebExtensionsStream(): Stream { const localExtensionDescriptions = (glob.sync('extensions/*/package.json')) .filter(manifestPath => { const packageJsonConfig = require(path.join(root, manifestPath)); @@ -276,23 +290,27 @@ export function packageLocalWebExtensionsStream(): NodeJS.ReadWriteStream { return { name: extensionName, path: extensionPath }; }); - return es.merge(...localExtensionDescriptions.map(extension => { - return fromLocal(extension.path, true) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - })); + return minifyExtensionResources( + es.merge(...localExtensionDescriptions.map(extension => { + return fromLocal(extension.path, true) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + })) + ); } -export function packageMarketplaceExtensionsStream(): NodeJS.ReadWriteStream { +export function packageMarketplaceExtensionsStream(): Stream { const extensions = builtInExtensions.map(extension => { return fromMarketplace(extension.name, extension.version, extension.metadata) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); }); - return es.merge(extensions) - .pipe(util2.setExecutableBit(['**/*.sh'])); + return minifyExtensionResources( + es.merge(extensions) + .pipe(util2.setExecutableBit(['**/*.sh'])) + ); } -export function packageMarketplaceWebExtensionsStream(builtInExtensions: IBuiltInExtension[]): NodeJS.ReadWriteStream { +export function packageMarketplaceWebExtensionsStream(builtInExtensions: IBuiltInExtension[]): Stream { const extensions = builtInExtensions .map(extension => { const input = fromMarketplace(extension.name, extension.version, extension.metadata) @@ -305,7 +323,9 @@ export function packageMarketplaceWebExtensionsStream(builtInExtensions: IBuiltI return data; }); }); - return es.merge(extensions); + return minifyExtensionResources( + es.merge(extensions) + ); } export interface IScannedBuiltinExtension { @@ -336,7 +356,7 @@ export function scanBuiltinExtensions(extensionsRoot: string, forWeb: boolean): if (packageNLS) { // temporary - packageJSON = translatePackageJSON(packageJSON, path.join(extensionsRoot, extensionFolder, packageNLS)) + packageJSON = translatePackageJSON(packageJSON, path.join(extensionsRoot, extensionFolder, packageNLS)); } scannedExtensions.push({ extensionPath: extensionFolder, diff --git a/build/package.json b/build/package.json index 22206229ffb..5cf6fe5202b 100644 --- a/build/package.json +++ b/build/package.json @@ -39,6 +39,7 @@ "gulp-sourcemaps": "^1.11.0", "gulp-uglify": "^3.0.0", "iconv-lite-umd": "0.6.8", + "jsonc-parser": "^2.3.0", "mime": "^1.3.4", "minimatch": "3.0.4", "minimist": "^1.2.3", diff --git a/build/yarn.lock b/build/yarn.lock index 79909133c5b..94529f13ba0 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -1600,6 +1600,11 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +jsonc-parser@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee" + integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"