'use strict'; Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const path = require('crosspath'); const fs = require('fs'); const minimatch = require('minimatch'); const resolveModule = require('resolve'); const SCRIPT_EXTENSIONS = [".js", ".mjs", ".cjs"]; /** * Creates a Custom Importer for sass/scss with support for Node Module Resolution and path mapping/aliasing */ function createImporter(options) { return (p, parent) => resolve(p, { ...options, parentDir: path.dirname(parent) }); } /** * Resolves sass/scss files with support for Node Module Resolution and path mapping/aliasing */ function resolve(p, options) { const sanitizedOptions = sanitizeOptions(options); const useNodeModuleResolution = p.startsWith(sanitizedOptions.nodeModuleResolutionPrefix); const { baseDir, paths } = resolveMaybeAliasedPath(path.normalize(useNodeModuleResolution ? p.slice(sanitizedOptions.nodeModuleResolutionPrefix.length) : p), sanitizedOptions); const internalOptions = { ...sanitizedOptions, baseDir }; for (const sanitizedPath of paths) { const resolved = useNodeModuleResolution ? nodeModuleResolutionStrategy(sanitizedPath, internalOptions) : sassStrategy(sanitizedPath, internalOptions); if (resolved != null) return resolved; } return null; } function sanitizeOptions(options) { const { fileSystem = fs, nodeModuleResolutionPrefix = "~", extensions = [".scss", ".sass", ".css"], paths = {}, cwd = process.cwd(), parentDir } = options !== null && options !== void 0 ? options : {}; return { fileSystem, nodeModuleResolutionPrefix, extensions, paths, cwd, parentDir }; } function resolveMaybeAliasedPath(p, options) { for (const key of Object.keys(options.paths)) { // Replace single asterisks with multiple ones const normalizedKey = key.replace(/(? path.join(value.replace(/(\\|\/)+\*$/gi, ""), pFromAsterisk)); return { paths, // Resolve mapped paths from the cwd baseDir: options.cwd }; } return { paths: [p], baseDir: options.parentDir == null ? options.cwd : options.parentDir }; } function nodeModuleResolutionStrategy(p, options) { try { const resolvedFile = resolveModule.sync(p, { basedir: options.cwd, extensions: [...options.extensions, ...SCRIPT_EXTENSIONS], readFileSync: file => options.fileSystem.readFileSync(file).toString(), isFile: file => isFileSync(file, options.fileSystem), isDirectory: file => isDirectorySync(file, options.fileSystem), // We can use the main property as a pointer to where in the package to look for a .scss/.sass/.css file with an equivalent name pathFilter: (_, currentPath) => { var _a, _b; const mainExtname = path.extname(currentPath); // If the main property already has a supported extension, leave it be if (options.extensions.some(extension => mainExtname === extension)) { return currentPath; } // Remove the extension from the path and see if a related .scss, .sass, or .css file can be resolved return (_b = (_a = sassStrategy(replaceScriptExtension(currentPath, ""), options)) === null || _a === void 0 ? void 0 : _a.file) !== null && _b !== void 0 ? _b : currentPath; } }); return { file: path.native.normalize(resolvedFile), contents: options.fileSystem.readFileSync(path.native.normalize(resolvedFile), "utf-8") }; } catch (ex) { return undefined; } } function sassStrategy(p, options) { let resolvedFile; // If the path has a specific extension, we might skip a lot of work and just be able to resolve that file directly. // Note that it may still not be able to resolve a file, for example if p is 'foo.bar', then '.bar' is technically an extension, // but no such file may exist, and we might still be able to resolve a file such as 'foo.bar.scss' if (path.extname(p) !== "") { resolvedFile = exactlyOne(tryPathSync(p, options)); } if (resolvedFile == null) { resolvedFile = exactlyOne(tryPathWithExtensionsSync(p, options)); } if (resolvedFile == null) return undefined; return { file: path.native.normalize(resolvedFile), contents: options.fileSystem.readFileSync(path.native.normalize(resolvedFile), "utf-8") }; } /** * Like tryPath, but checks for all possible extensions */ function tryPathWithExtensionsSync(p, options) { return options.extensions.map(extension => [tryPathSync(`${p}${extension}`, options), tryPathSync(path.join(p, `index${extension}`), options)]).flat(2); } /** * Returns the path and/or the partial with the same name, if either or both exists */ function tryPathSync(p, options) { const absolutePath = path.isAbsolute(p) ? p : path.join(options.baseDir, p); const absolutePartial = path.join(path.dirname(absolutePath), `_${path.basename(absolutePath)}`); return [...(isFileSync(absolutePartial, options.fileSystem) ? [absolutePartial] : []), ...(isFileSync(absolutePath, options.fileSystem) ? [absolutePath] : [])]; } function isFileSync(p, fileSystem) { var _a, _b; return (_b = (_a = safeStatSync(p, fileSystem)) === null || _a === void 0 ? void 0 : _a.isFile()) !== null && _b !== void 0 ? _b : false; } function isDirectorySync(p, fileSystem) { var _a, _b; return (_b = (_a = safeStatSync(p, fileSystem)) === null || _a === void 0 ? void 0 : _a.isDirectory()) !== null && _b !== void 0 ? _b : false; } function safeStatSync(p, fileSystem) { try { return fileSystem.statSync(path.native.normalize(p)); } catch { return undefined; } } /** * If paths contains exactly one path, return that path. * If it contains no paths, return undefined. If it contains more than one, * throw an exception */ function exactlyOne(paths) { const [head, ...tail] = paths; if (head == null) return undefined; if (tail.length > 0) { throw new ReferenceError("It's not clear which file to import. Found:\n" + paths.map(p => ` ${p}`).join("\n")); } return head; } function ensureArray(item) { return Array.isArray(item) ? item : [item]; } /** * Sets the given extension for the given file */ function replaceScriptExtension(file, extension) { return path.normalize(`${removeScriptExtension(file)}${extension}`); } /** * Strips the extension from a file */ function removeScriptExtension(file) { let currentExtname; for (const extName of SCRIPT_EXTENSIONS) { if (file.endsWith(extName)) { currentExtname = extName; break; } } if (currentExtname == null) return file; return file.slice(0, file.lastIndexOf(currentExtname)); } exports.createImporter = createImporter; exports.resolve = resolve; //# sourceMappingURL=index.cjs.map