"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getImports = getImports; exports.renderImports = renderImports; exports.sourceHasUseStrict = sourceHasUseStrict; var _path = _interopRequireDefault(require("path")); var _stripComments = _interopRequireDefault(require("strip-comments")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const matchRelativePath = /^\.\.?[/\\]/; function isAbsolutePath(str) { return _path.default.posix.isAbsolute(str) || _path.default.win32.isAbsolute(str); } function isRelativePath(str) { return matchRelativePath.test(str); } // TODO simplify for the next major release function stringifyRequest(loaderContext, request) { if (typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function") { return JSON.stringify(loaderContext.utils.contextify(loaderContext.context, request)); } const splitted = request.split("!"); const { context } = loaderContext; return JSON.stringify(splitted.map(part => { // First, separate singlePath from query, because the query might contain paths again const splittedPart = part.match(/^(.*?)(\?.*)/); const query = splittedPart ? splittedPart[2] : ""; let singlePath = splittedPart ? splittedPart[1] : part; if (isAbsolutePath(singlePath) && context) { singlePath = _path.default.relative(context, singlePath); if (isAbsolutePath(singlePath)) { // If singlePath still matches an absolute path, singlePath was on a different drive than context. // In this case, we leave the path platform-specific without replacing any separators. // @see https://github.com/webpack/loader-utils/pull/14 return singlePath + query; } if (isRelativePath(singlePath) === false) { // Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules). singlePath = `./${singlePath}`; } } return singlePath.replace(/\\/g, "/") + query; }).join("!")); } function forError(item) { return typeof item === "string" ? item : `\n${JSON.stringify(item, null, " ")}\n`; } function sourceHasUseStrict(source) { const str = (0, _stripComments.default)(source).trim(); return str.startsWith("'use strict'") || str.startsWith('"use strict"'); } function splitCommand(command) { const result = command.split("|").map(item => item.split(" ")).reduce((acc, val) => acc.concat(val), []); for (const item of result) { if (!item) { throw new Error(`Invalid command "${item}" in "${command}" for imports. There must be only one separator: " ", or "|"`); } } return result; } function resolveImports(type, item) { const defaultSyntax = type === "module" ? "default" : "single"; let result; if (typeof item === "string") { const noWhitespaceItem = item.trim(); if (noWhitespaceItem.length === 0) { throw new Error(`Invalid "${item}" value for import`); } const splittedItem = splitCommand(noWhitespaceItem); if (splittedItem.length > 4) { throw new Error(`Invalid "${item}" value for import`); } if (splittedItem.length === 1) { result = { syntax: defaultSyntax, moduleName: splittedItem[0], name: splittedItem[0], // eslint-disable-next-line no-undefined alias: undefined }; } else { result = { syntax: splittedItem[0], moduleName: splittedItem[1], name: splittedItem[2], // eslint-disable-next-line no-undefined alias: splittedItem[3] ? splittedItem[3] : undefined }; } } else { result = { syntax: defaultSyntax, ...item }; } if (result.syntax === defaultSyntax && typeof result.name === "undefined") { result.name = result.moduleName; } if (["default", "side-effects", "single", "pure"].includes(result.syntax) && typeof result.alias !== "undefined") { throw new Error(`The "${result.syntax}" syntax does not support "${result.alias}" alias in "${forError(item)}" value`); } if (["side-effects", "pure"].includes(result.syntax) && typeof result.name !== "undefined") { throw new Error(`The "${result.syntax}" syntax does not support "${result.name}" name in "${forError(item)}" value`); } if (["default", "namespace", "named", "side-effects"].includes(result.syntax) && type === "commonjs") { throw new Error(`The "${type}" type does not support the "${result.syntax}" syntax in "${forError(item)}" value`); } if (["single", "multiple", "pure"].includes(result.syntax) && type === "module") { throw new Error(`The "${type}" format does not support the "${result.syntax}" syntax in "${forError(item)}" value`); } if (["namespace", "named", "multiple"].includes(result.syntax) && typeof result.name === "undefined") { throw new Error(`The "${result.syntax}" syntax needs the "name" option in "${forError(item)}" value`); } return result; } function getIdentifiers(array) { return array.reduce((accumulator, item) => { if (typeof item.alias !== "undefined") { accumulator.push({ type: "alias", value: item.alias }); return accumulator; } if (typeof item.name !== "undefined") { accumulator.push({ type: "name", value: item.name }); } return accumulator; }, []); } function duplicateBy(array, key) { return array.filter((a, aIndex) => array.filter((b, bIndex) => b[key] === a[key] && aIndex !== bIndex).length > 0); } function getImports(type, imports) { let result; const importItems = typeof imports === "string" && imports.includes(",") ? imports.split(",") : imports; if (typeof importItems === "string") { result = [resolveImports(type, importItems)]; } else { result = [].concat(importItems).map(item => resolveImports(type, item)); } const identifiers = getIdentifiers(result); const duplicates = duplicateBy(identifiers, "value"); if (duplicates.length > 0) { throw new Error(`Duplicate ${duplicates.map(identifier => `"${identifier.value}" (as "${identifier.type}")`).join(", ")} identifiers found in "\n${JSON.stringify(importItems, null, " ")}\n" value`); } const sortedResults = Object.create(null); for (const item of result) { const { moduleName } = item; if (!sortedResults[moduleName]) { sortedResults[moduleName] = []; } const { syntax, name, alias } = item; sortedResults[moduleName].push({ syntax, name, alias }); } return sortedResults; } function renderImports(loaderContext, type, moduleName, imports) { let code = ""; if (type === "commonjs") { const pure = imports.filter(({ syntax }) => syntax === "pure"); // Pure if (pure.length > 0) { pure.forEach((_, i) => { const needNewline = i < pure.length - 1 ? "\n" : ""; code += `require(${stringifyRequest(loaderContext, moduleName)});${needNewline}`; }); } const singleImports = imports.filter(({ syntax }) => syntax === "single"); // Single if (singleImports.length > 0) { code += pure.length > 0 ? "\n" : ""; singleImports.forEach((singleImport, i) => { const { name } = singleImport; const needNewline = i < singleImports.length - 1 ? "\n" : ""; code += `var ${name} = require(${stringifyRequest(loaderContext, moduleName)});${needNewline}`; }); } const multipleImports = imports.filter(({ syntax }) => syntax === "multiple"); // Multiple if (multipleImports.length > 0) { code += pure.length > 0 || singleImports.length > 0 ? "\n" : ""; code += `var { `; multipleImports.forEach((multipleImport, i) => { const needComma = i > 0 ? ", " : ""; const { name, alias } = multipleImport; const separator = ": "; code += alias ? `${needComma}${name}${separator}${alias}` : `${needComma}${name}`; }); code += ` } = require(${stringifyRequest(loaderContext, moduleName)});`; } return code; } const sideEffectsImports = imports.filter(({ syntax }) => syntax === "side-effects"); // Side-effects if (sideEffectsImports.length > 0) { sideEffectsImports.forEach((_, i) => { const needNewline = i < sideEffectsImports.length - 1 ? "\n" : ""; code += `import ${stringifyRequest(loaderContext, moduleName)};${needNewline}`; }); return code; } const defaultImports = imports.filter(({ syntax }) => syntax === "default"); const namedImports = imports.filter(({ syntax }) => syntax === "named"); const namespaceImports = imports.filter(({ syntax }) => syntax === "namespace"); // Default if (defaultImports.length > 0) { defaultImports.forEach((defaultImport, i) => { const { name } = defaultImport; const needNewline = i < defaultImports.length - 1 ? "\n" : ""; code += `import ${name} from ${stringifyRequest(loaderContext, moduleName)};${needNewline}`; }); } // Named if (namedImports.length > 0) { code += defaultImports.length > 0 ? "\n" : ""; code += "import { "; namedImports.forEach((namedImport, i) => { const needComma = i > 0 ? ", " : ""; const { name, alias } = namedImport; const separator = " as "; code += alias ? `${needComma}${name}${separator}${alias}` : `${needComma}${name}`; }); code += ` } from ${stringifyRequest(loaderContext, moduleName)};`; } // Namespace if (namespaceImports.length > 0) { code += defaultImports.length > 0 || namedImports.length > 0 ? "\n" : ""; namespaceImports.forEach((namespaceImport, i) => { const { name } = namespaceImport; const needNewline = i < namespaceImports.length - 1 ? "\n" : ""; code += `import * as ${name} from ${stringifyRequest(loaderContext, moduleName)};${needNewline}`; }); } return code; }