UNPKG

fuse-box

Version:

Fuse-Box a bundler that does it right

167 lines (147 loc) 6.15 kB
import { FileAbstraction } from "../FileAbstraction"; import * as path from "path"; import { joinFuseBoxPath } from "../../../Utils"; import { acornParse } from "../../../analysis/FileAnalysis"; function isString(node: any): boolean { return node.type === "Literal" || node.type === "StringLiteral"; } export class RequireStatement { public functionName: string; public value: string; public isNodeModule: boolean; public isComputed = false; public nodeModuleName: string; public nodeModulePartialRequire: string; public usedNames = new Set<string>(); public identifiedStatementsAst: any; public identifier: string; public localReferences = 0; private resolvedAbstraction: FileAbstraction; private resolved = false; constructor(public file: FileAbstraction, public ast: any, public parentAst?: any) { ast.arguments = ast.arguments || []; const arg1 = ast.arguments[0]; this.functionName = ast.callee.name; const producer = file.packageAbstraction.bundleAbstraction.producerAbstraction; const customComputedStatementPaths = producer.opts.customComputedStatementPaths; // if it's a string if (ast.arguments.length === 1 && isString(arg1)) { this.value = ast.arguments[0].value; let moduleValues = this.value.match(/^([a-z@](?!:).*)$/); this.isNodeModule = moduleValues !== null && moduleValues !== undefined; if (moduleValues) { const moduleValue = moduleValues[0]; if (moduleValue.charAt(0) === '@') { // matching @angular/animations/browser // where package name is @angular/animations let matched = moduleValue.match(/(@[\w_-]+\/[\w_-]+)\/?(.*)/i); if (matched) { this.nodeModuleName = matched[1] this.nodeModulePartialRequire = matched[2] } } else { const [moduleName, ...partialRequire] = moduleValue.split("/"); this.nodeModuleName = moduleName; this.nodeModulePartialRequire = partialRequire.join("/"); } } } else { this.isComputed = true; // limit it to require if (this.functionName === "require") { let showWarning = true; let matched = false; // notify producer customComputedStatementPaths.forEach((regexp, path) => { if (regexp.test(file.getFuseBoxFullPath())) { matched = true; showWarning = false; } }); //if (!matched) { //producer.useComputedRequireStatements = true; //producer.useNumbers = false; //} // we assume it's a dynamic import if (showWarning) { producer.addWarning(`Computed statement warning in ${this.file.packageAbstraction.name}/${this.file.fuseBoxPath}`); } } } } public removeWithIdentifier() { const declarator = this.parentAst; const declaration = declarator.$parent; const index = declaration.declarations.indexOf(declarator); declaration.declarations.splice(index, 1); if (declaration.declarations.length === 0) { const body = declaration.$parent; const prop = declaration.$prop; if (Array.isArray(body[prop]) && declaration.$idx !== undefined) { const arrayIndex = body[prop].indexOf(declaration); if (arrayIndex > -1) { body[prop].splice(arrayIndex, 1); } } } } public setFunctionName(name: string) { this.ast.callee.name = name; } public bindID(id: any) { this.ast.callee.name += `.bind({id:${JSON.stringify(id)}})` } public isCSSRequested() { return this.value && path.extname(this.value) === ".css"; } public isRemoteURL() { return this.value && /^http(s):/.test(this.value); } public isJSONRequested() { return this.value && path.extname(this.value) === ".json"; } public setValue(str: string) { this.ast.arguments[0].value = str; } public setExpression(raw: string) { const astStatemet = acornParse​​(raw); if (astStatemet.body[0].expression) { this.ast.arguments = [astStatemet.body[0].expression]; } } public getValue(): string { return this.ast.arguments[0].value; } public resolve(): FileAbstraction { return this.resolveAbstraction(); } private resolveAbstraction(): FileAbstraction { let resolved: FileAbstraction; if (!this.resolved) { this.resolved = true; // cannot resolve dynamic imports if (this.isComputed) { return; } const pkgName = !this.isNodeModule ? this.file.packageAbstraction.name : this.nodeModuleName; let resolvedName; const producerAbstraction = this.file.packageAbstraction.bundleAbstraction.producerAbstraction; if (!this.isNodeModule) { if (/^~\//.test(this.value)) { resolvedName = this.value.slice(2) } else { resolvedName = joinFuseBoxPath(path.dirname(this.file.fuseBoxPath), this.value); } resolved = producerAbstraction.findFileAbstraction(pkgName, resolvedName); } else { resolved = producerAbstraction.findFileAbstraction(pkgName, this.nodeModulePartialRequire); } if (resolved) { // register dependency this.file.addDependency(resolved, this); } this.resolvedAbstraction = resolved; } return this.resolvedAbstraction; } }