diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js index 6f7a9e678b4..6ae72e4cf06 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.js @@ -165,8 +165,8 @@ gulp.task(compileExtensionsBuildLegacyTask); const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions')); const compileExtensionsBuildTask = task.define('compile-extensions-build', task.series( cleanExtensionsBuildTask, - task.define('bundle-extensions-build', () => ext.packageLocalExtensionsStream().pipe(gulp.dest('.build'))), - task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream().pipe(gulp.dest('.build'))), + task.define('bundle-extensions-build', () => ext.packageLocalExtensionsStream(false).pipe(gulp.dest('.build'))), + task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream(false).pipe(gulp.dest('.build'))), )); gulp.task(compileExtensionsBuildTask); diff --git a/build/lib/extensions.js b/build/lib/extensions.js index 3726563cede..58596187e49 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -4,7 +4,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); -exports.translatePackageJSON = exports.scanBuiltinExtensions = exports.packageMarketplaceWebExtensionsStream = exports.packageMarketplaceExtensionsStream = exports.packageLocalWebExtensionsStream = exports.packageLocalExtensionsStream = exports.fromMarketplace = void 0; +exports.translatePackageJSON = exports.scanBuiltinExtensions = exports.packageMarketplaceExtensionsStream = exports.packageLocalExtensionsStream = exports.fromMarketplace = void 0; const es = require("event-stream"); const fs = require("fs"); const glob = require("glob"); @@ -200,68 +200,66 @@ const excludedExtensions = [ 'ms-vscode.node-debug2', 'vscode-notebook-tests' ]; +const marketplaceWebExtensions = [ + 'ms-vscode.references-view' +]; const builtInExtensions = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')).builtInExtensions; -function packageLocalExtensionsStream() { - const localExtensionDescriptions = glob.sync('extensions/*/package.json') +/** + * Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionsUtil.ts` + */ +function isWebExtension(manifest) { + if (typeof manifest.extensionKind !== 'undefined') { + const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind]; + return (extensionKind.indexOf('web') >= 0); + } + return (!Boolean(manifest.main) || Boolean(manifest.browser)); +} +function packageLocalExtensionsStream(forWeb) { + const localExtensionsDescriptions = (glob.sync('extensions/*/package.json') .map(manifestPath => { + const absoluteManifestPath = path.join(root, manifestPath); const extensionPath = path.dirname(path.join(root, manifestPath)); const extensionName = path.basename(extensionPath); - return { name: extensionName, path: extensionPath }; + return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath }; }) .filter(({ name }) => excludedExtensions.indexOf(name) === -1) - .filter(({ name }) => builtInExtensions.every(b => b.name !== name)); - const localExtensions = localExtensionDescriptions.map(extension => { - return fromLocal(extension.path, false) + .filter(({ name }) => builtInExtensions.every(b => b.name !== name)) + .filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true))); + const localExtensionsStream = minifyExtensionResources(es.merge(...localExtensionsDescriptions.map(extension => { + return fromLocal(extension.path, forWeb) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - }); - const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); - return minifyExtensionResources(es.merge(nodeModules, ...localExtensions) + }))); + let result; + if (forWeb) { + result = localExtensionsStream; + } + else { + // also include shared node modules + result = es.merge(localExtensionsStream, gulp.src('extensions/node_modules/**', { base: '.' })); + } + return (result .pipe(util2.setExecutableBit(['**/*.sh']))); } exports.packageLocalExtensionsStream = packageLocalExtensionsStream; -function packageLocalWebExtensionsStream() { - const localExtensionDescriptions = glob.sync('extensions/*/package.json') - .filter(manifestPath => { - const packageJsonConfig = require(path.join(root, manifestPath)); - return !packageJsonConfig.main || packageJsonConfig.browser; - }) - .map(manifestPath => { - const extensionPath = path.dirname(path.join(root, manifestPath)); - const extensionName = path.basename(extensionPath); - return { name: extensionName, path: extensionPath }; - }); - 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() { - const extensions = builtInExtensions.map(extension => { - return fromMarketplace(extension.name, extension.version, extension.metadata) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - }); - return minifyExtensionResources(es.merge(extensions) - .pipe(util2.setExecutableBit(['**/*.sh']))); -} -exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream; -function packageMarketplaceWebExtensionsStream(builtInExtensions) { - const extensions = builtInExtensions +function packageMarketplaceExtensionsStream(forWeb) { + const marketplaceExtensionsDescriptions = (builtInExtensions + .filter(({ name }) => (forWeb ? marketplaceWebExtensions.indexOf(name) >= 0 : true))); + const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions .map(extension => { const input = fromMarketplace(extension.name, extension.version, extension.metadata) .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); return updateExtensionPackageJSON(input, (data) => { - if (data.main) { - data.browser = data.main; - } - data.extensionKind = ['web']; + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; return data; }); - }); - return minifyExtensionResources(es.merge(extensions)); + }))); + return (marketplaceExtensionsStream + .pipe(util2.setExecutableBit(['**/*.sh']))); } -exports.packageMarketplaceWebExtensionsStream = packageMarketplaceWebExtensionsStream; -function scanBuiltinExtensions(extensionsRoot, forWeb) { +exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream; +function scanBuiltinExtensions(extensionsRoot) { const scannedExtensions = []; const extensionsFolders = fs.readdirSync(extensionsRoot); for (const extensionFolder of extensionsFolders) { @@ -270,10 +268,6 @@ function scanBuiltinExtensions(extensionsRoot, forWeb) { continue; } let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8')); - const extensionKind = packageJSON['extensionKind'] || []; - if (forWeb && extensionKind.indexOf('web') === -1) { - continue; - } const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder)); const packageNLS = children.filter(child => child === 'package.nls.json')[0]; const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; diff --git a/build/lib/extensions.ts b/build/lib/extensions.ts index 2efa0947b7b..c54de2b3160 100644 --- a/build/lib/extensions.ts +++ b/build/lib/extensions.ts @@ -235,6 +235,10 @@ const excludedExtensions = [ 'vscode-notebook-tests' ]; +const marketplaceWebExtensions = [ + 'ms-vscode.references-view' +]; + interface IBuiltInExtension { name: string; version: string; @@ -244,76 +248,83 @@ interface IBuiltInExtension { const builtInExtensions: IBuiltInExtension[] = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8')).builtInExtensions; -export function packageLocalExtensionsStream(): Stream { - const localExtensionDescriptions = (glob.sync('extensions/*/package.json')) - .map(manifestPath => { - const extensionPath = path.dirname(path.join(root, manifestPath)); - const extensionName = path.basename(extensionPath); - return { name: extensionName, path: extensionPath }; - }) - .filter(({ name }) => excludedExtensions.indexOf(name) === -1) - .filter(({ name }) => builtInExtensions.every(b => b.name !== name)); +type ExtensionKind = 'ui' | 'workspace' | 'web'; +interface IExtensionManifest { + main: string; + browser: string; + extensionKind?: ExtensionKind | ExtensionKind[]; +} +/** + * Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionsUtil.ts` + */ +function isWebExtension(manifest: IExtensionManifest): boolean { + if (typeof manifest.extensionKind !== 'undefined') { + const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind]; + return (extensionKind.indexOf('web') >= 0); + } + return (!Boolean(manifest.main) || Boolean(manifest.browser)); +} +export function packageLocalExtensionsStream(forWeb: boolean): Stream { + const localExtensionsDescriptions = ( + (glob.sync('extensions/*/package.json')) + .map(manifestPath => { + const absoluteManifestPath = path.join(root, manifestPath); + const extensionPath = path.dirname(path.join(root, manifestPath)); + const extensionName = path.basename(extensionPath); + return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath }; + }) + .filter(({ name }) => excludedExtensions.indexOf(name) === -1) + .filter(({ name }) => builtInExtensions.every(b => b.name !== name)) + .filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true)) + ); + const localExtensionsStream = minifyExtensionResources( + es.merge( + ...localExtensionsDescriptions.map(extension => { + return fromLocal(extension.path, forWeb) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + }) + ) + ); - const localExtensions = localExtensionDescriptions.map(extension => { - return fromLocal(extension.path, false) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - }); + let result: Stream; + if (forWeb) { + result = localExtensionsStream; + } else { + // also include shared node modules + result = es.merge(localExtensionsStream, gulp.src('extensions/node_modules/**', { base: '.' })); + } - const nodeModules = gulp.src('extensions/node_modules/**', { base: '.' }); - return minifyExtensionResources( - es.merge(nodeModules, ...localExtensions) - .pipe(util2.setExecutableBit(['**/*.sh'])) + return ( + result + .pipe(util2.setExecutableBit(['**/*.sh'])) ); } -export function packageLocalWebExtensionsStream(): Stream { - const localExtensionDescriptions = (glob.sync('extensions/*/package.json')) - .filter(manifestPath => { - const packageJsonConfig = require(path.join(root, manifestPath)); - return !packageJsonConfig.main || packageJsonConfig.browser; - }) - .map(manifestPath => { - const extensionPath = path.dirname(path.join(root, manifestPath)); - const extensionName = path.basename(extensionPath); - return { name: extensionName, path: extensionPath }; - }); - - 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(forWeb: boolean): Stream { + const marketplaceExtensionsDescriptions = ( + builtInExtensions + .filter(({ name }) => (forWeb ? marketplaceWebExtensions.indexOf(name) >= 0 : true)) ); -} - -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 minifyExtensionResources( - es.merge(extensions) - .pipe(util2.setExecutableBit(['**/*.sh'])) + const marketplaceExtensionsStream = minifyExtensionResources( + es.merge( + ...marketplaceExtensionsDescriptions + .map(extension => { + const input = fromMarketplace(extension.name, extension.version, extension.metadata) + .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); + return updateExtensionPackageJSON(input, (data: any) => { + delete data.scripts; + delete data.dependencies; + delete data.devDependencies; + return data; + }); + }) + ) ); -} -export function packageMarketplaceWebExtensionsStream(builtInExtensions: IBuiltInExtension[]): Stream { - const extensions = builtInExtensions - .map(extension => { - const input = fromMarketplace(extension.name, extension.version, extension.metadata) - .pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`)); - return updateExtensionPackageJSON(input, (data: any) => { - if (data.main) { - data.browser = data.main; - } - data.extensionKind = ['web']; - return data; - }); - }); - return minifyExtensionResources( - es.merge(extensions) + return ( + marketplaceExtensionsStream + .pipe(util2.setExecutableBit(['**/*.sh'])) ); } @@ -325,7 +336,7 @@ export interface IScannedBuiltinExtension { changelogPath?: string, } -export function scanBuiltinExtensions(extensionsRoot: string, forWeb: boolean): IScannedBuiltinExtension[] { +export function scanBuiltinExtensions(extensionsRoot: string): IScannedBuiltinExtension[] { const scannedExtensions: IScannedBuiltinExtension[] = []; const extensionsFolders = fs.readdirSync(extensionsRoot); for (const extensionFolder of extensionsFolders) { @@ -334,10 +345,6 @@ export function scanBuiltinExtensions(extensionsRoot: string, forWeb: boolean): continue; } let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8')); - const extensionKind: string[] = packageJSON['extensionKind'] || []; - if (forWeb && extensionKind.indexOf('web') === -1) { - continue; - } const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder)); const packageNLS = children.filter(child => child === 'package.nls.json')[0]; const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];