|
|
@ -8,7 +8,12 @@ interface Dependency {
|
|
|
|
source: string;
|
|
|
|
source: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const wrappers = { es, amd, cjs, iife, umd, eval: expr };
|
|
|
|
const wrappers = { esm, cjs, eval: expr };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Export = {
|
|
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
|
|
as: string;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default function wrapModule(
|
|
|
|
export default function wrapModule(
|
|
|
|
code: string,
|
|
|
|
code: string,
|
|
|
@ -19,60 +24,20 @@ export default function wrapModule(
|
|
|
|
sharedPath: string,
|
|
|
|
sharedPath: string,
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
imports: Node[],
|
|
|
|
imports: Node[],
|
|
|
|
module_exports: string[],
|
|
|
|
module_exports: Export[],
|
|
|
|
source: string
|
|
|
|
source: string
|
|
|
|
): string {
|
|
|
|
): string {
|
|
|
|
if (format === 'es') {
|
|
|
|
if (format === 'esm') {
|
|
|
|
return es(code, name, options, banner, sharedPath, helpers, imports, module_exports, source);
|
|
|
|
return esm(code, name, options, banner, sharedPath, helpers, imports, module_exports, source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const dependencies = imports.map((declaration, i) => {
|
|
|
|
if (format === 'cjs') return cjs(code, name, banner, sharedPath, helpers, imports, module_exports);
|
|
|
|
const defaultImport = declaration.specifiers.find(
|
|
|
|
if (format === 'eval') return expr(code, name, options, banner, imports);
|
|
|
|
(x: Node) =>
|
|
|
|
|
|
|
|
x.type === 'ImportDefaultSpecifier' ||
|
|
|
|
|
|
|
|
(x.type === 'ImportSpecifier' && x.imported.name === 'default')
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const namespaceImport = declaration.specifiers.find(
|
|
|
|
|
|
|
|
(x: Node) => x.type === 'ImportNamespaceSpecifier'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const namedImports = declaration.specifiers.filter(
|
|
|
|
|
|
|
|
(x: Node) =>
|
|
|
|
|
|
|
|
x.type === 'ImportSpecifier' && x.imported.name !== 'default'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const name = defaultImport || namespaceImport
|
|
|
|
|
|
|
|
? (defaultImport || namespaceImport).local.name
|
|
|
|
|
|
|
|
: `__import${i}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const statements: string[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namedImports.forEach((specifier: Node) => {
|
|
|
|
|
|
|
|
statements.push(
|
|
|
|
|
|
|
|
`var ${specifier.local.name} = ${name}.${specifier.imported.name};`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (defaultImport) {
|
|
|
|
|
|
|
|
statements.push(
|
|
|
|
|
|
|
|
`${name} = (${name} && ${name}.__esModule) ? ${name}["default"] : ${name};`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { name, statements, source: declaration.source.value };
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (format === 'amd') return amd(code, name, options, banner, dependencies);
|
|
|
|
|
|
|
|
if (format === 'cjs') return cjs(code, name, options, banner, sharedPath, helpers, dependencies);
|
|
|
|
|
|
|
|
if (format === 'iife') return iife(code, name, options, banner, dependencies);
|
|
|
|
|
|
|
|
if (format === 'umd') return umd(code, name, options, banner, dependencies);
|
|
|
|
|
|
|
|
if (format === 'eval') return expr(code, name, options, banner, dependencies);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`);
|
|
|
|
throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function es(
|
|
|
|
function esm(
|
|
|
|
code: string,
|
|
|
|
code: string,
|
|
|
|
name: string,
|
|
|
|
name: string,
|
|
|
|
options: CompileOptions,
|
|
|
|
options: CompileOptions,
|
|
|
@ -80,7 +45,7 @@ function es(
|
|
|
|
sharedPath: string,
|
|
|
|
sharedPath: string,
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
imports: Node[],
|
|
|
|
imports: Node[],
|
|
|
|
module_exports: string[],
|
|
|
|
module_exports: Export[],
|
|
|
|
source: string
|
|
|
|
source: string
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
const importHelpers = helpers.length > 0 && (
|
|
|
|
const importHelpers = helpers.length > 0 && (
|
|
|
@ -103,47 +68,45 @@ function es(
|
|
|
|
${module_exports.length > 0 && `export { ${module_exports.join(', ')} };`}`;
|
|
|
|
${module_exports.length > 0 && `export { ${module_exports.join(', ')} };`}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function amd(
|
|
|
|
|
|
|
|
code: string,
|
|
|
|
|
|
|
|
name: string,
|
|
|
|
|
|
|
|
options: CompileOptions,
|
|
|
|
|
|
|
|
banner: string,
|
|
|
|
|
|
|
|
dependencies: Dependency[]
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
const sourceString = dependencies.length
|
|
|
|
|
|
|
|
? `[${dependencies.map(d => `"${removeExtension(d.source)}"`).join(', ')}], `
|
|
|
|
|
|
|
|
: '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const id = options.amd && options.amd.id;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return deindent`
|
|
|
|
|
|
|
|
define(${id ? `"${id}", ` : ''}${sourceString}function(${paramString(dependencies)}) { "use strict";
|
|
|
|
|
|
|
|
${getCompatibilityStatements(dependencies)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
${code}
|
|
|
|
|
|
|
|
return ${name};
|
|
|
|
|
|
|
|
});`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function cjs(
|
|
|
|
function cjs(
|
|
|
|
code: string,
|
|
|
|
code: string,
|
|
|
|
name: string,
|
|
|
|
name: string,
|
|
|
|
options: CompileOptions,
|
|
|
|
|
|
|
|
banner: string,
|
|
|
|
banner: string,
|
|
|
|
sharedPath: string,
|
|
|
|
sharedPath: string,
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
helpers: { name: string, alias: string }[],
|
|
|
|
dependencies: Dependency[]
|
|
|
|
imports: Node[],
|
|
|
|
|
|
|
|
module_exports: Export[]
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
const helperDeclarations = helpers.map(h => `${h.alias === h.name ? h.name : `${h.name}: ${h.alias}`}`).join(', ');
|
|
|
|
const helperDeclarations = helpers.map(h => `${h.alias === h.name ? h.name : `${h.name}: ${h.alias}`}`).join(', ');
|
|
|
|
|
|
|
|
|
|
|
|
const helperBlock = helpers.length > 0 && (
|
|
|
|
const helperBlock = helpers.length > 0 && (
|
|
|
|
`var { ${helperDeclarations} } = require(${JSON.stringify(sharedPath)});\n`
|
|
|
|
`const { ${helperDeclarations} } = require(${JSON.stringify(sharedPath)});\n`
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const requireBlock = dependencies.length > 0 && (
|
|
|
|
const requires = imports.map(node => {
|
|
|
|
dependencies
|
|
|
|
let lhs;
|
|
|
|
.map(d => `var ${d.name} = require("${d.source}");`)
|
|
|
|
|
|
|
|
.join('\n\n')
|
|
|
|
if (node.specifiers[0].type === 'ImportNamespaceSpecifier') {
|
|
|
|
|
|
|
|
lhs = node.specifiers[0].local.name;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const properties = node.specifiers.map(s => {
|
|
|
|
|
|
|
|
if (s.type === 'ImportDefaultSpecifier') {
|
|
|
|
|
|
|
|
return `default: ${s.local.name}`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return s.local.name === s.imported.name
|
|
|
|
|
|
|
|
? s.local.name
|
|
|
|
|
|
|
|
: `${s.imported.name}: ${s.local.name}`;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lhs = `{ ${properties.join(', ')} }`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return `const ${lhs} = require("${node.source.value}");`
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const exports = [`exports.default = ${name};`].concat(
|
|
|
|
|
|
|
|
module_exports.map(x => `exports.${x.as} = ${x.name};`)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return deindent`
|
|
|
|
return deindent`
|
|
|
@ -151,84 +114,57 @@ function cjs(
|
|
|
|
"use strict";
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
|
|
${helperBlock}
|
|
|
|
${helperBlock}
|
|
|
|
${requireBlock}
|
|
|
|
${requires}
|
|
|
|
${getCompatibilityStatements(dependencies)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
${code}
|
|
|
|
${code}
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = ${name};`
|
|
|
|
${exports}`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function iife(
|
|
|
|
function expr(
|
|
|
|
code: string,
|
|
|
|
|
|
|
|
name: string,
|
|
|
|
|
|
|
|
options: CompileOptions,
|
|
|
|
|
|
|
|
banner: string,
|
|
|
|
|
|
|
|
dependencies: Dependency[]
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if (!options.name) {
|
|
|
|
|
|
|
|
throw new Error(`Missing required 'name' option for IIFE export`);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const globals = getGlobals(dependencies, options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return deindent`
|
|
|
|
|
|
|
|
${banner}
|
|
|
|
|
|
|
|
var ${options.name} = (function(${paramString(dependencies)}) { "use strict";
|
|
|
|
|
|
|
|
${getCompatibilityStatements(dependencies)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
${code}
|
|
|
|
|
|
|
|
return ${name};
|
|
|
|
|
|
|
|
}(${globals.join(', ')}));`;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function umd(
|
|
|
|
|
|
|
|
code: string,
|
|
|
|
code: string,
|
|
|
|
name: string,
|
|
|
|
name: string,
|
|
|
|
options: CompileOptions,
|
|
|
|
options: CompileOptions,
|
|
|
|
banner: string,
|
|
|
|
banner: string,
|
|
|
|
dependencies: Dependency[]
|
|
|
|
imports: Node[]
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
if (!options.name) {
|
|
|
|
const dependencies = imports.map((declaration, i) => {
|
|
|
|
throw new Error(`Missing required 'name' option for UMD export`);
|
|
|
|
const defaultImport = declaration.specifiers.find(
|
|
|
|
}
|
|
|
|
(x: Node) =>
|
|
|
|
|
|
|
|
x.type === 'ImportDefaultSpecifier' ||
|
|
|
|
const amdId = options.amd && options.amd.id ? `'${options.amd.id}', ` : '';
|
|
|
|
(x.type === 'ImportSpecifier' && x.imported.name === 'default')
|
|
|
|
|
|
|
|
);
|
|
|
|
const amdDeps = dependencies.length
|
|
|
|
|
|
|
|
? `[${dependencies.map(d => `"${removeExtension(d.source)}"`).join(', ')}], `
|
|
|
|
|
|
|
|
: '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cjsDeps = dependencies
|
|
|
|
const namespaceImport = declaration.specifiers.find(
|
|
|
|
.map(d => `require("${d.source}")`)
|
|
|
|
(x: Node) => x.type === 'ImportNamespaceSpecifier'
|
|
|
|
.join(', ');
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const globals = getGlobals(dependencies, options);
|
|
|
|
const namedImports = declaration.specifiers.filter(
|
|
|
|
|
|
|
|
(x: Node) =>
|
|
|
|
|
|
|
|
x.type === 'ImportSpecifier' && x.imported.name !== 'default'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return deindent`
|
|
|
|
const name = defaultImport || namespaceImport
|
|
|
|
${banner}
|
|
|
|
? (defaultImport || namespaceImport).local.name
|
|
|
|
(function(global, factory) {
|
|
|
|
: `__import${i}`;
|
|
|
|
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory(${cjsDeps}) :
|
|
|
|
|
|
|
|
typeof define === "function" && define.amd ? define(${amdId}${amdDeps}factory) :
|
|
|
|
|
|
|
|
(global.${options.name} = factory(${globals.join(', ')}));
|
|
|
|
|
|
|
|
}(this, (function (${paramString(dependencies)}) { "use strict";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
${getCompatibilityStatements(dependencies)}
|
|
|
|
const statements: string[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
${code}
|
|
|
|
namedImports.forEach((specifier: Node) => {
|
|
|
|
|
|
|
|
statements.push(
|
|
|
|
|
|
|
|
`var ${specifier.local.name} = ${name}.${specifier.imported.name};`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return ${name};
|
|
|
|
if (defaultImport) {
|
|
|
|
|
|
|
|
statements.push(
|
|
|
|
|
|
|
|
`${name} = (${name} && ${name}.__esModule) ? ${name}["default"] : ${name};`
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
})));`;
|
|
|
|
return { name, statements, source: declaration.source.value };
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function expr(
|
|
|
|
|
|
|
|
code: string,
|
|
|
|
|
|
|
|
name: string,
|
|
|
|
|
|
|
|
options: CompileOptions,
|
|
|
|
|
|
|
|
banner: string,
|
|
|
|
|
|
|
|
dependencies: Dependency[]
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
const globals = getGlobals(dependencies, options);
|
|
|
|
const globals = getGlobals(dependencies, options);
|
|
|
|
|
|
|
|
|
|
|
|
return deindent`
|
|
|
|
return deindent`
|
|
|
@ -247,11 +183,6 @@ function paramString(dependencies: Dependency[]) {
|
|
|
|
return dependencies.map(dep => dep.name).join(', ');
|
|
|
|
return dependencies.map(dep => dep.name).join(', ');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function removeExtension(file: string) {
|
|
|
|
|
|
|
|
const index = file.lastIndexOf('.');
|
|
|
|
|
|
|
|
return ~index ? file.slice(0, index) : file;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getCompatibilityStatements(dependencies: Dependency[]) {
|
|
|
|
function getCompatibilityStatements(dependencies: Dependency[]) {
|
|
|
|
if (!dependencies.length) return null;
|
|
|
|
if (!dependencies.length) return null;
|
|
|
|
|
|
|
|
|
|
|
|