2024-09-11 02:37:36 +00:00
"use strict" ;
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Copyright ( c ) Microsoft Corporation . All rights reserved .
* Licensed under the MIT License . See License . txt in the project root for license information .
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
2025-03-01 02:01:53 +00:00
var _ _createBinding = ( this && this . _ _createBinding ) || ( Object . create ? ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
var desc = Object . getOwnPropertyDescriptor ( m , k ) ;
if ( ! desc || ( "get" in desc ? ! m . _ _esModule : desc . writable || desc . configurable ) ) {
desc = { enumerable : true , get : function ( ) { return m [ k ] ; } } ;
}
Object . defineProperty ( o , k2 , desc ) ;
} ) : ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
o [ k2 ] = m [ k ] ;
} ) ) ;
var _ _setModuleDefault = ( this && this . _ _setModuleDefault ) || ( Object . create ? ( function ( o , v ) {
Object . defineProperty ( o , "default" , { enumerable : true , value : v } ) ;
} ) : function ( o , v ) {
o [ "default" ] = v ;
} ) ;
var _ _importStar = ( this && this . _ _importStar ) || ( function ( ) {
var ownKeys = function ( o ) {
ownKeys = Object . getOwnPropertyNames || function ( o ) {
var ar = [ ] ;
for ( var k in o ) if ( Object . prototype . hasOwnProperty . call ( o , k ) ) ar [ ar . length ] = k ;
return ar ;
} ;
return ownKeys ( o ) ;
} ;
return function ( mod ) {
if ( mod && mod . _ _esModule ) return mod ;
var result = { } ;
if ( mod != null ) for ( var k = ownKeys ( mod ) , i = 0 ; i < k . length ; i ++ ) if ( k [ i ] !== "default" ) _ _createBinding ( result , mod , k [ i ] ) ;
_ _setModuleDefault ( result , mod ) ;
return result ;
} ;
} ) ( ) ;
var _ _importDefault = ( this && this . _ _importDefault ) || function ( mod ) {
return ( mod && mod . _ _esModule ) ? mod : { "default" : mod } ;
} ;
2024-09-11 02:37:36 +00:00
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
exports . fromMarketplace = fromMarketplace ;
2025-03-01 02:01:53 +00:00
exports . fromVsix = fromVsix ;
2024-09-11 02:37:36 +00:00
exports . fromGithub = fromGithub ;
2025-03-01 02:01:53 +00:00
exports . packageNonNativeLocalExtensionsStream = packageNonNativeLocalExtensionsStream ;
exports . packageNativeLocalExtensionsStream = packageNativeLocalExtensionsStream ;
exports . packageAllLocalExtensionsStream = packageAllLocalExtensionsStream ;
2024-09-11 02:37:36 +00:00
exports . packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream ;
exports . scanBuiltinExtensions = scanBuiltinExtensions ;
exports . translatePackageJSON = translatePackageJSON ;
exports . webpackExtensions = webpackExtensions ;
exports . buildExtensionMedia = buildExtensionMedia ;
2025-03-01 02:01:53 +00:00
const event _stream _1 = _ _importDefault ( require ( "event-stream" ) ) ;
const fs _1 = _ _importDefault ( require ( "fs" ) ) ;
const child _process _1 = _ _importDefault ( require ( "child_process" ) ) ;
const glob _1 = _ _importDefault ( require ( "glob" ) ) ;
const gulp _1 = _ _importDefault ( require ( "gulp" ) ) ;
const path _1 = _ _importDefault ( require ( "path" ) ) ;
const crypto _1 = _ _importDefault ( require ( "crypto" ) ) ;
const vinyl _1 = _ _importDefault ( require ( "vinyl" ) ) ;
2024-09-11 02:37:36 +00:00
const stats _1 = require ( "./stats" ) ;
2025-03-01 02:01:53 +00:00
const util2 = _ _importStar ( require ( "./util" ) ) ;
2024-09-11 02:37:36 +00:00
const vzip = require ( 'gulp-vinyl-zip' ) ;
2025-03-01 02:01:53 +00:00
const gulp _filter _1 = _ _importDefault ( require ( "gulp-filter" ) ) ;
const gulp _rename _1 = _ _importDefault ( require ( "gulp-rename" ) ) ;
const fancy _log _1 = _ _importDefault ( require ( "fancy-log" ) ) ;
const ansi _colors _1 = _ _importDefault ( require ( "ansi-colors" ) ) ;
const gulp _buffer _1 = _ _importDefault ( require ( "gulp-buffer" ) ) ;
const jsoncParser = _ _importStar ( require ( "jsonc-parser" ) ) ;
2024-09-11 02:37:36 +00:00
const dependencies _1 = require ( "./dependencies" ) ;
const builtInExtensions _1 = require ( "./builtInExtensions" ) ;
const getVersion _1 = require ( "./getVersion" ) ;
const fetch _1 = require ( "./fetch" ) ;
2025-03-01 02:01:53 +00:00
const root = path _1 . default . dirname ( path _1 . default . dirname ( _ _dirname ) ) ;
2024-09-11 02:37:36 +00:00
const commit = ( 0 , getVersion _1 . getVersion ) ( root ) ;
const sourceMappingURLBase = ` https://main.vscode-cdn.net/sourcemaps/ ${ commit } ` ;
function minifyExtensionResources ( input ) {
2025-03-01 02:01:53 +00:00
const jsonFilter = ( 0 , gulp _filter _1 . default ) ( [ '**/*.json' , '**/*.code-snippets' ] , { restore : true } ) ;
2024-09-11 02:37:36 +00:00
return input
. pipe ( jsonFilter )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
. pipe ( event _stream _1 . default . mapSync ( ( f ) => {
2024-09-11 02:37:36 +00:00
const errors = [ ] ;
const value = jsoncParser . parse ( f . contents . toString ( 'utf8' ) , errors , { allowTrailingComma : true } ) ;
if ( errors . length === 0 ) {
// file parsed OK => just stringify to drop whitespace and comments
f . contents = Buffer . from ( JSON . stringify ( value ) ) ;
}
return f ;
} ) )
. pipe ( jsonFilter . restore ) ;
}
function updateExtensionPackageJSON ( input , update ) {
2025-03-01 02:01:53 +00:00
const packageJsonFilter = ( 0 , gulp _filter _1 . default ) ( 'extensions/*/package.json' , { restore : true } ) ;
2024-09-11 02:37:36 +00:00
return input
. pipe ( packageJsonFilter )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
. pipe ( event _stream _1 . default . mapSync ( ( f ) => {
2024-09-11 02:37:36 +00:00
const data = JSON . parse ( f . contents . toString ( 'utf8' ) ) ;
f . contents = Buffer . from ( JSON . stringify ( update ( data ) ) ) ;
return f ;
} ) )
. pipe ( packageJsonFilter . restore ) ;
}
function fromLocal ( extensionPath , forWeb , disableMangle ) {
const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js' ;
2025-03-01 02:01:53 +00:00
const isWebPacked = fs _1 . default . existsSync ( path _1 . default . join ( extensionPath , webpackConfigFileName ) ) ;
2024-09-11 02:37:36 +00:00
let input = isWebPacked
? fromLocalWebpack ( extensionPath , webpackConfigFileName , disableMangle )
: fromLocalNormal ( extensionPath ) ;
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 input ;
}
function fromLocalWebpack ( extensionPath , webpackConfigFileName , disableMangle ) {
const vsce = require ( '@vscode/vsce' ) ;
const webpack = require ( 'webpack' ) ;
const webpackGulp = require ( 'webpack-stream' ) ;
2025-03-01 02:01:53 +00:00
const result = event _stream _1 . default . through ( ) ;
2024-09-11 02:37:36 +00:00
const packagedDependencies = [ ] ;
2025-03-01 02:01:53 +00:00
const packageJsonConfig = require ( path _1 . default . join ( extensionPath , 'package.json' ) ) ;
2024-09-11 02:37:36 +00:00
if ( packageJsonConfig . dependencies ) {
2025-03-01 02:01:53 +00:00
const webpackRootConfig = require ( path _1 . default . join ( extensionPath , webpackConfigFileName ) ) ;
2024-09-11 02:37:36 +00:00
for ( const key in webpackRootConfig . externals ) {
if ( key in packageJsonConfig . dependencies ) {
packagedDependencies . push ( key ) ;
}
}
}
2024-09-06 13:18:02 +00:00
// TODO: add prune support based on packagedDependencies to vsce.PackageManager.Npm similar
// to vsce.PackageManager.Yarn.
// A static analysis showed there are no webpack externals that are dependencies of the current
// local extensions so we can use the vsce.PackageManager.None config to ignore dependencies list
// as a temporary workaround.
vsce . listFiles ( { cwd : extensionPath , packageManager : vsce . PackageManager . None , packagedDependencies } ) . then ( fileNames => {
2024-09-11 02:37:36 +00:00
const files = fileNames
2025-03-01 02:01:53 +00:00
. map ( fileName => path _1 . default . join ( extensionPath , fileName ) )
. map ( filePath => new vinyl _1 . default ( {
2024-09-11 02:37:36 +00:00
path : filePath ,
2025-03-01 02:01:53 +00:00
stat : fs _1 . default . statSync ( filePath ) ,
2024-09-11 02:37:36 +00:00
base : extensionPath ,
2025-03-01 02:01:53 +00:00
contents : fs _1 . default . createReadStream ( filePath )
2024-09-11 02:37:36 +00:00
} ) ) ;
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
2025-03-01 02:01:53 +00:00
const webpackConfigLocations = glob _1 . default . sync ( path _1 . default . join ( extensionPath , '**' , webpackConfigFileName ) , { ignore : [ '**/node_modules' ] } ) ;
2024-09-11 02:37:36 +00:00
const webpackStreams = webpackConfigLocations . flatMap ( webpackConfigPath => {
const webpackDone = ( err , stats ) => {
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( ` Bundled extension: ${ ansi _colors _1 . default . yellow ( path _1 . default . join ( path _1 . default . basename ( extensionPath ) , path _1 . default . relative ( extensionPath , webpackConfigPath ) ) ) } ... ` ) ;
2024-09-11 02:37:36 +00:00
if ( err ) {
result . emit ( 'error' , err ) ;
}
const { compilation } = stats ;
if ( compilation . errors . length > 0 ) {
result . emit ( 'error' , compilation . errors . join ( '\n' ) ) ;
}
if ( compilation . warnings . length > 0 ) {
result . emit ( 'error' , compilation . warnings . join ( '\n' ) ) ;
}
} ;
const exportedConfig = require ( webpackConfigPath ) ;
return ( Array . isArray ( exportedConfig ) ? exportedConfig : [ exportedConfig ] ) . map ( config => {
const webpackConfig = {
... config ,
... { mode : 'production' }
} ;
if ( disableMangle ) {
if ( Array . isArray ( config . module . rules ) ) {
for ( const rule of config . module . rules ) {
if ( Array . isArray ( rule . use ) ) {
for ( const use of rule . use ) {
if ( String ( use . loader ) . endsWith ( 'mangle-loader.js' ) ) {
use . options . disabled = true ;
}
}
}
}
}
}
2025-03-01 02:01:53 +00:00
const relativeOutputPath = path _1 . default . relative ( extensionPath , webpackConfig . output . path ) ;
2024-09-11 02:37:36 +00:00
return webpackGulp ( webpackConfig , webpack , webpackDone )
2025-03-01 02:01:53 +00:00
. pipe ( event _stream _1 . default . through ( function ( data ) {
2024-09-11 02:37:36 +00:00
data . stat = data . stat || { } ;
data . base = extensionPath ;
this . emit ( 'data' , data ) ;
} ) )
2025-03-01 02:01:53 +00:00
. pipe ( event _stream _1 . default . through ( function ( data ) {
2024-09-11 02:37:36 +00:00
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
2025-03-01 02:01:53 +00:00
if ( path _1 . default . extname ( data . basename ) === '.js' ) {
const contents = data . contents . toString ( 'utf8' ) ;
data . contents = Buffer . from ( contents . replace ( /\n\/\/# sourceMappingURL=(.*)$/gm , function ( _m , g1 ) {
return ` \n //# sourceMappingURL= ${ sourceMappingURLBase } /extensions/ ${ path _1 . default . basename ( extensionPath ) } / ${ relativeOutputPath } / ${ g1 } ` ;
} ) , 'utf8' ) ;
}
2024-09-11 02:37:36 +00:00
this . emit ( 'data' , data ) ;
} ) ) ;
} ) ;
} ) ;
2025-03-01 02:01:53 +00:00
event _stream _1 . default . merge ( ... webpackStreams , event _stream _1 . default . readArray ( files ) )
2024-09-11 02:37:36 +00:00
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
. pipe ( result ) ;
} ) . catch ( err => {
console . error ( extensionPath ) ;
console . error ( packagedDependencies ) ;
result . emit ( 'error' , err ) ;
} ) ;
2025-03-01 02:01:53 +00:00
return result . pipe ( ( 0 , stats _1 . createStatsStream ) ( path _1 . default . basename ( extensionPath ) ) ) ;
2024-09-11 02:37:36 +00:00
}
function fromLocalNormal ( extensionPath ) {
const vsce = require ( '@vscode/vsce' ) ;
2025-03-01 02:01:53 +00:00
const result = event _stream _1 . default . through ( ) ;
2024-09-06 13:18:02 +00:00
vsce . listFiles ( { cwd : extensionPath , packageManager : vsce . PackageManager . Npm } )
2024-09-11 02:37:36 +00:00
. then ( fileNames => {
const files = fileNames
2025-03-01 02:01:53 +00:00
. map ( fileName => path _1 . default . join ( extensionPath , fileName ) )
. map ( filePath => new vinyl _1 . default ( {
2024-09-11 02:37:36 +00:00
path : filePath ,
2025-03-01 02:01:53 +00:00
stat : fs _1 . default . statSync ( filePath ) ,
2024-09-11 02:37:36 +00:00
base : extensionPath ,
2025-03-01 02:01:53 +00:00
contents : fs _1 . default . createReadStream ( filePath )
2024-09-11 02:37:36 +00:00
} ) ) ;
2025-03-01 02:01:53 +00:00
event _stream _1 . default . readArray ( files ) . pipe ( result ) ;
2024-09-11 02:37:36 +00:00
} )
. catch ( err => result . emit ( 'error' , err ) ) ;
2025-03-01 02:01:53 +00:00
return result . pipe ( ( 0 , stats _1 . createStatsStream ) ( path _1 . default . basename ( extensionPath ) ) ) ;
2024-09-11 02:37:36 +00:00
}
const userAgent = 'VSCode Build' ;
const baseHeaders = {
'X-Market-Client-Id' : 'VSCode Build' ,
'User-Agent' : userAgent ,
'X-Market-User-Id' : '291C1CD0-051A-4123-9B4B-30D60EF52EE2' ,
} ;
function fromMarketplace ( serviceUrl , { name : extensionName , version , sha256 , metadata } ) {
const json = require ( 'gulp-json-editor' ) ;
const [ publisher , name ] = extensionName . split ( '.' ) ;
const url = ` ${ serviceUrl } /publishers/ ${ publisher } /vsextensions/ ${ name } / ${ version } /vspackage ` ;
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( 'Downloading extension:' , ansi _colors _1 . default . yellow ( ` ${ extensionName } @ ${ version } ` ) , '...' ) ;
const packageJsonFilter = ( 0 , gulp _filter _1 . default ) ( 'package.json' , { restore : true } ) ;
2024-09-11 02:37:36 +00:00
return ( 0 , fetch _1 . fetchUrls ) ( '' , {
base : url ,
nodeFetchOptions : {
headers : baseHeaders
} ,
checksumSha256 : sha256
} )
. pipe ( vzip . src ( ) )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _filter _1 . default ) ( 'extension/**' ) )
. pipe ( ( 0 , gulp _rename _1 . default ) ( p => p . dirname = p . dirname . replace ( /^extension\/?/ , '' ) ) )
. pipe ( packageJsonFilter )
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
. pipe ( json ( { _ _metadata : metadata } ) )
. pipe ( packageJsonFilter . restore ) ;
}
function fromVsix ( vsixPath , { name : extensionName , version , sha256 , metadata } ) {
const json = require ( 'gulp-json-editor' ) ;
( 0 , fancy _log _1 . default ) ( 'Using local VSIX for extension:' , ansi _colors _1 . default . yellow ( ` ${ extensionName } @ ${ version } ` ) , '...' ) ;
const packageJsonFilter = ( 0 , gulp _filter _1 . default ) ( 'package.json' , { restore : true } ) ;
return gulp _1 . default . src ( vsixPath )
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
. pipe ( event _stream _1 . default . mapSync ( ( f ) => {
const hash = crypto _1 . default . createHash ( 'sha256' ) ;
hash . update ( f . contents ) ;
const checksum = hash . digest ( 'hex' ) ;
if ( checksum !== sha256 ) {
throw new Error ( ` Checksum mismatch for ${ vsixPath } (expected ${ sha256 } , actual ${ checksum } )) ` ) ;
}
return f ;
} ) )
. pipe ( vzip . src ( ) )
. pipe ( ( 0 , gulp _filter _1 . default ) ( 'extension/**' ) )
. pipe ( ( 0 , gulp _rename _1 . default ) ( p => p . dirname = p . dirname . replace ( /^extension\/?/ , '' ) ) )
2024-09-11 02:37:36 +00:00
. pipe ( packageJsonFilter )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
2024-09-11 02:37:36 +00:00
. pipe ( json ( { _ _metadata : metadata } ) )
. pipe ( packageJsonFilter . restore ) ;
}
function fromGithub ( { name , version , repo , sha256 , metadata } ) {
const json = require ( 'gulp-json-editor' ) ;
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( 'Downloading extension from GH:' , ansi _colors _1 . default . yellow ( ` ${ name } @ ${ version } ` ) , '...' ) ;
const packageJsonFilter = ( 0 , gulp _filter _1 . default ) ( 'package.json' , { restore : true } ) ;
2024-09-11 02:37:36 +00:00
return ( 0 , fetch _1 . fetchGithub ) ( new URL ( repo ) . pathname , {
version ,
name : name => name . endsWith ( '.vsix' ) ,
checksumSha256 : sha256
} )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
2024-09-11 02:37:36 +00:00
. pipe ( vzip . src ( ) )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _filter _1 . default ) ( 'extension/**' ) )
. pipe ( ( 0 , gulp _rename _1 . default ) ( p => p . dirname = p . dirname . replace ( /^extension\/?/ , '' ) ) )
2024-09-11 02:37:36 +00:00
. pipe ( packageJsonFilter )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _buffer _1 . default ) ( ) )
2024-09-11 02:37:36 +00:00
. pipe ( json ( { _ _metadata : metadata } ) )
. pipe ( packageJsonFilter . restore ) ;
}
2025-03-01 02:01:53 +00:00
/ * *
* All extensions that are known to have some native component and thus must be built on the
* platform that is being built .
* /
const nativeExtensions = [
'microsoft-authentication' ,
] ;
2024-09-11 02:37:36 +00:00
const excludedExtensions = [
'vscode-api-tests' ,
'vscode-colorize-tests' ,
2025-03-01 02:01:53 +00:00
'vscode-colorize-perf-tests' ,
2024-09-11 02:37:36 +00:00
'vscode-test-resolver' ,
'ms-vscode.node-debug' ,
'ms-vscode.node-debug2' ,
] ;
const marketplaceWebExtensionsExclude = new Set ( [
'ms-vscode.node-debug' ,
'ms-vscode.node-debug2' ,
'ms-vscode.js-debug-companion' ,
'ms-vscode.js-debug' ,
'ms-vscode.vscode-js-profile-table'
] ) ;
2025-03-01 02:01:53 +00:00
const productJson = JSON . parse ( fs _1 . default . readFileSync ( path _1 . default . join ( _ _dirname , '../../product.json' ) , 'utf8' ) ) ;
2024-09-11 02:37:36 +00:00
const builtInExtensions = productJson . builtInExtensions || [ ] ;
const webBuiltInExtensions = productJson . webBuiltInExtensions || [ ] ;
/ * *
* Loosely based on ` getExtensionKind ` from ` src/vs/workbench/services/extensions/common/extensionManifestPropertiesService.ts `
* /
function isWebExtension ( manifest ) {
if ( Boolean ( manifest . browser ) ) {
return true ;
}
if ( Boolean ( manifest . main ) ) {
return false ;
}
// neither browser nor main
if ( typeof manifest . extensionKind !== 'undefined' ) {
const extensionKind = Array . isArray ( manifest . extensionKind ) ? manifest . extensionKind : [ manifest . extensionKind ] ;
if ( extensionKind . indexOf ( 'web' ) >= 0 ) {
return true ;
}
}
if ( typeof manifest . contributes !== 'undefined' ) {
for ( const id of [ 'debuggers' , 'terminal' , 'typescriptServerPlugins' ] ) {
if ( manifest . contributes . hasOwnProperty ( id ) ) {
return false ;
}
}
}
return true ;
}
2025-03-01 02:01:53 +00:00
/ * *
* Package local extensions that are known to not have native dependencies . Mutually exclusive to { @ link packageNativeLocalExtensionsStream } .
* @ param forWeb build the extensions that have web targets
* @ param disableMangle disable the mangler
* @ returns a stream
* /
function packageNonNativeLocalExtensionsStream ( forWeb , disableMangle ) {
return doPackageLocalExtensionsStream ( forWeb , disableMangle , false ) ;
}
/ * *
* Package local extensions that are known to have native dependencies . Mutually exclusive to { @ link packageNonNativeLocalExtensionsStream } .
* @ note it ' s possible that the extension does not have native dependencies for the current platform , especially if building for the web ,
* but we simplify the logic here by having a flat list of extensions ( See { @ link nativeExtensions } ) that are known to have native
* dependencies on some platform and thus should be packaged on the platform that they are building for .
* @ param forWeb build the extensions that have web targets
* @ param disableMangle disable the mangler
* @ returns a stream
* /
function packageNativeLocalExtensionsStream ( forWeb , disableMangle ) {
return doPackageLocalExtensionsStream ( forWeb , disableMangle , true ) ;
}
/ * *
* Package all the local extensions ... both those that are known to have native dependencies and those that are not .
* @ param forWeb build the extensions that have web targets
* @ param disableMangle disable the mangler
* @ returns a stream
* /
function packageAllLocalExtensionsStream ( forWeb , disableMangle ) {
return event _stream _1 . default . merge ( [
packageNonNativeLocalExtensionsStream ( forWeb , disableMangle ) ,
packageNativeLocalExtensionsStream ( forWeb , disableMangle )
] ) ;
}
/ * *
* @ param forWeb build the extensions that have web targets
* @ param disableMangle disable the mangler
* @ param native build the extensions that are marked as having native dependencies
* /
function doPackageLocalExtensionsStream ( forWeb , disableMangle , native ) {
const nativeExtensionsSet = new Set ( nativeExtensions ) ;
const localExtensionsDescriptions = ( glob _1 . default . sync ( 'extensions/*/package.json' )
2024-09-11 02:37:36 +00:00
. map ( manifestPath => {
2025-03-01 02:01:53 +00:00
const absoluteManifestPath = path _1 . default . join ( root , manifestPath ) ;
const extensionPath = path _1 . default . dirname ( path _1 . default . join ( root , manifestPath ) ) ;
const extensionName = path _1 . default . basename ( extensionPath ) ;
2024-09-11 02:37:36 +00:00
return { name : extensionName , path : extensionPath , manifestPath : absoluteManifestPath } ;
} )
2025-03-01 02:01:53 +00:00
. filter ( ( { name } ) => native ? nativeExtensionsSet . has ( name ) : ! nativeExtensionsSet . has ( name ) )
2024-09-11 02:37:36 +00:00
. filter ( ( { name } ) => excludedExtensions . indexOf ( name ) === - 1 )
. filter ( ( { name } ) => builtInExtensions . every ( b => b . name !== name ) )
. filter ( ( { manifestPath } ) => ( forWeb ? isWebExtension ( require ( manifestPath ) ) : true ) ) ) ;
2025-03-01 02:01:53 +00:00
const localExtensionsStream = minifyExtensionResources ( event _stream _1 . default . merge ( ... localExtensionsDescriptions . map ( extension => {
2024-09-11 02:37:36 +00:00
return fromLocal ( extension . path , forWeb , disableMangle )
2025-03-01 02:01:53 +00:00
. pipe ( ( 0 , gulp _rename _1 . default ) ( p => p . dirname = ` extensions/ ${ extension . name } / ${ p . dirname } ` ) ) ;
2024-09-11 02:37:36 +00:00
} ) ) ) ;
let result ;
if ( forWeb ) {
result = localExtensionsStream ;
}
else {
// also include shared production node modules
const productionDependencies = ( 0 , dependencies _1 . getProductionDependencies ) ( 'extensions/' ) ;
2025-03-01 02:01:53 +00:00
const dependenciesSrc = productionDependencies . map ( d => path _1 . default . relative ( root , d ) ) . map ( d => [ ` ${ d } /** ` , ` ! ${ d } /**/{test,tests}/** ` ] ) . flat ( ) ;
result = event _stream _1 . default . merge ( localExtensionsStream , gulp _1 . default . src ( dependenciesSrc , { base : '.' } )
. pipe ( util2 . cleanNodeModules ( path _1 . default . join ( root , 'build' , '.moduleignore' ) ) )
. pipe ( util2 . cleanNodeModules ( path _1 . default . join ( root , 'build' , ` .moduleignore. ${ process . platform } ` ) ) ) ) ;
2024-09-11 02:37:36 +00:00
}
return ( result
. pipe ( util2 . setExecutableBit ( [ '**/*.sh' ] ) ) ) ;
}
function packageMarketplaceExtensionsStream ( forWeb ) {
const marketplaceExtensionsDescriptions = [
... builtInExtensions . filter ( ( { name } ) => ( forWeb ? ! marketplaceWebExtensionsExclude . has ( name ) : true ) ) ,
... ( forWeb ? webBuiltInExtensions : [ ] )
] ;
2025-03-01 02:01:53 +00:00
const marketplaceExtensionsStream = minifyExtensionResources ( event _stream _1 . default . merge ( ... marketplaceExtensionsDescriptions
2024-09-11 02:37:36 +00:00
. map ( extension => {
2025-03-01 02:01:53 +00:00
const src = ( 0 , builtInExtensions _1 . getExtensionStream ) ( extension ) . pipe ( ( 0 , gulp _rename _1 . default ) ( p => p . dirname = ` extensions/ ${ p . dirname } ` ) ) ;
2024-09-11 02:37:36 +00:00
return updateExtensionPackageJSON ( src , ( data ) => {
delete data . scripts ;
delete data . dependencies ;
delete data . devDependencies ;
return data ;
} ) ;
} ) ) ) ;
return ( marketplaceExtensionsStream
. pipe ( util2 . setExecutableBit ( [ '**/*.sh' ] ) ) ) ;
}
function scanBuiltinExtensions ( extensionsRoot , exclude = [ ] ) {
const scannedExtensions = [ ] ;
try {
2025-03-01 02:01:53 +00:00
const extensionsFolders = fs _1 . default . readdirSync ( extensionsRoot ) ;
2024-09-11 02:37:36 +00:00
for ( const extensionFolder of extensionsFolders ) {
if ( exclude . indexOf ( extensionFolder ) >= 0 ) {
continue ;
}
2025-03-01 02:01:53 +00:00
const packageJSONPath = path _1 . default . join ( extensionsRoot , extensionFolder , 'package.json' ) ;
if ( ! fs _1 . default . existsSync ( packageJSONPath ) ) {
2024-09-11 02:37:36 +00:00
continue ;
}
2025-03-01 02:01:53 +00:00
const packageJSON = JSON . parse ( fs _1 . default . readFileSync ( packageJSONPath ) . toString ( 'utf8' ) ) ;
2024-09-11 02:37:36 +00:00
if ( ! isWebExtension ( packageJSON ) ) {
continue ;
}
2025-03-01 02:01:53 +00:00
const children = fs _1 . default . readdirSync ( path _1 . default . join ( extensionsRoot , extensionFolder ) ) ;
2024-09-11 02:37:36 +00:00
const packageNLSPath = children . filter ( child => child === 'package.nls.json' ) [ 0 ] ;
2025-03-01 02:01:53 +00:00
const packageNLS = packageNLSPath ? JSON . parse ( fs _1 . default . readFileSync ( path _1 . default . join ( extensionsRoot , extensionFolder , packageNLSPath ) ) . toString ( ) ) : undefined ;
2024-09-11 02:37:36 +00:00
const readme = children . filter ( child => / ^ readme ( \ . txt | \ . md | ) $ / i . test ( child ) ) [ 0 ] ;
const changelog = children . filter ( child => / ^ changelog ( \ . txt | \ . md | ) $ / i . test ( child ) ) [ 0 ] ;
scannedExtensions . push ( {
extensionPath : extensionFolder ,
packageJSON ,
packageNLS ,
2025-03-01 02:01:53 +00:00
readmePath : readme ? path _1 . default . join ( extensionFolder , readme ) : undefined ,
changelogPath : changelog ? path _1 . default . join ( extensionFolder , changelog ) : undefined ,
2024-09-11 02:37:36 +00:00
} ) ;
}
return scannedExtensions ;
}
catch ( ex ) {
return scannedExtensions ;
}
}
function translatePackageJSON ( packageJSON , packageNLSPath ) {
const CharCode _PC = '%' . charCodeAt ( 0 ) ;
2025-03-01 02:01:53 +00:00
const packageNls = JSON . parse ( fs _1 . default . readFileSync ( packageNLSPath ) . toString ( ) ) ;
2024-09-11 02:37:36 +00:00
const translate = ( obj ) => {
for ( const key in obj ) {
const val = obj [ key ] ;
if ( Array . isArray ( val ) ) {
val . forEach ( translate ) ;
}
else if ( val && typeof val === 'object' ) {
translate ( val ) ;
}
else if ( typeof val === 'string' && val . charCodeAt ( 0 ) === CharCode _PC && val . charCodeAt ( val . length - 1 ) === CharCode _PC ) {
const translated = packageNls [ val . substr ( 1 , val . length - 2 ) ] ;
if ( translated ) {
obj [ key ] = typeof translated === 'string' ? translated : ( typeof translated . message === 'string' ? translated . message : val ) ;
}
}
}
} ;
translate ( packageJSON ) ;
return packageJSON ;
}
2025-03-01 02:01:53 +00:00
const extensionsPath = path _1 . default . join ( root , 'extensions' ) ;
2024-09-11 02:37:36 +00:00
// Additional projects to run esbuild on. These typically build code for webviews
const esbuildMediaScripts = [
'markdown-language-features/esbuild-notebook.js' ,
'markdown-language-features/esbuild-preview.js' ,
'markdown-math/esbuild.js' ,
'notebook-renderers/esbuild.js' ,
'ipynb/esbuild.js' ,
'simple-browser/esbuild-preview.js' ,
] ;
async function webpackExtensions ( taskName , isWatch , webpackConfigLocations ) {
const webpack = require ( 'webpack' ) ;
const webpackConfigs = [ ] ;
for ( const { configPath , outputRoot } of webpackConfigLocations ) {
const configOrFnOrArray = require ( configPath ) ;
function addConfig ( configOrFnOrArray ) {
for ( const configOrFn of Array . isArray ( configOrFnOrArray ) ? configOrFnOrArray : [ configOrFnOrArray ] ) {
const config = typeof configOrFn === 'function' ? configOrFn ( { } , { } ) : configOrFn ;
if ( outputRoot ) {
2025-03-01 02:01:53 +00:00
config . output . path = path _1 . default . join ( outputRoot , path _1 . default . relative ( path _1 . default . dirname ( configPath ) , config . output . path ) ) ;
2024-09-11 02:37:36 +00:00
}
webpackConfigs . push ( config ) ;
}
}
addConfig ( configOrFnOrArray ) ;
}
function reporter ( fullStats ) {
if ( Array . isArray ( fullStats . children ) ) {
for ( const stats of fullStats . children ) {
const outputPath = stats . outputPath ;
if ( outputPath ) {
2025-03-01 02:01:53 +00:00
const relativePath = path _1 . default . relative ( extensionsPath , outputPath ) . replace ( /\\/g , '/' ) ;
2024-09-11 02:37:36 +00:00
const match = relativePath . match ( /[^\/]+(\/server|\/client)?/ ) ;
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( ` Finished ${ ansi _colors _1 . default . green ( taskName ) } ${ ansi _colors _1 . default . cyan ( match [ 0 ] ) } with ${ stats . errors . length } errors. ` ) ;
2024-09-11 02:37:36 +00:00
}
if ( Array . isArray ( stats . errors ) ) {
stats . errors . forEach ( ( error ) => {
2025-03-01 02:01:53 +00:00
fancy _log _1 . default . error ( error ) ;
2024-09-11 02:37:36 +00:00
} ) ;
}
if ( Array . isArray ( stats . warnings ) ) {
stats . warnings . forEach ( ( warning ) => {
2025-03-01 02:01:53 +00:00
fancy _log _1 . default . warn ( warning ) ;
2024-09-11 02:37:36 +00:00
} ) ;
}
}
}
}
return new Promise ( ( resolve , reject ) => {
if ( isWatch ) {
webpack ( webpackConfigs ) . watch ( { } , ( err , stats ) => {
if ( err ) {
reject ( ) ;
}
else {
reporter ( stats ? . toJson ( ) ) ;
}
} ) ;
}
else {
webpack ( webpackConfigs ) . run ( ( err , stats ) => {
if ( err ) {
2025-03-01 02:01:53 +00:00
fancy _log _1 . default . error ( err ) ;
2024-09-11 02:37:36 +00:00
reject ( ) ;
}
else {
reporter ( stats ? . toJson ( ) ) ;
resolve ( ) ;
}
} ) ;
}
} ) ;
}
async function esbuildExtensions ( taskName , isWatch , scripts ) {
function reporter ( stdError , script ) {
const matches = ( stdError || '' ) . match ( /\> (.+): error: (.+)?/g ) ;
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( ` Finished ${ ansi _colors _1 . default . green ( taskName ) } ${ script } with ${ matches ? matches . length : 0 } errors. ` ) ;
2024-09-11 02:37:36 +00:00
for ( const match of matches || [ ] ) {
2025-03-01 02:01:53 +00:00
fancy _log _1 . default . error ( match ) ;
2024-09-11 02:37:36 +00:00
}
}
const tasks = scripts . map ( ( { script , outputRoot } ) => {
return new Promise ( ( resolve , reject ) => {
const args = [ script ] ;
if ( isWatch ) {
args . push ( '--watch' ) ;
}
if ( outputRoot ) {
args . push ( '--outputRoot' , outputRoot ) ;
}
2025-03-01 02:01:53 +00:00
const proc = child _process _1 . default . execFile ( process . argv [ 0 ] , args , { } , ( error , _stdout , stderr ) => {
2024-09-11 02:37:36 +00:00
if ( error ) {
return reject ( error ) ;
}
reporter ( stderr , script ) ;
return resolve ( ) ;
} ) ;
proc . stdout . on ( 'data' , ( data ) => {
2025-03-01 02:01:53 +00:00
( 0 , fancy _log _1 . default ) ( ` ${ ansi _colors _1 . default . green ( taskName ) } : ${ data . toString ( 'utf8' ) } ` ) ;
2024-09-11 02:37:36 +00:00
} ) ;
} ) ;
} ) ;
return Promise . all ( tasks ) ;
}
async function buildExtensionMedia ( isWatch , outputRoot ) {
return esbuildExtensions ( 'esbuilding extension media' , isWatch , esbuildMediaScripts . map ( p => ( {
2025-03-01 02:01:53 +00:00
script : path _1 . default . join ( extensionsPath , p ) ,
outputRoot : outputRoot ? path _1 . default . join ( root , outputRoot , path _1 . default . dirname ( p ) ) : undefined
2024-09-11 02:37:36 +00:00
} ) ) ) ;
}
//# sourceMappingURL=extensions.js.map