UNPKG

fuse-box

Version:

Fuse-Box a bundler that does it right

103 lines (91 loc) 3.21 kB
import * as path from "path"; import * as fs from "fs"; export interface ICSSDependencyExtractorOptions { paths: string[]; extensions: string[], content: string; sassStyle?: boolean; importer?: { (f: string, prev: any, done: { (info: { file: string }): void }): string } } export class CSSDependencyExtractor { private dependencies: string[] = []; constructor(public opts: ICSSDependencyExtractorOptions) { this.extractDepsFromString(opts.content); } private extractDepsFromString(input: string) { const re = /@import\s+("|')([^"']+)/g; let match; while (match = re.exec(input)) { let target = this.findTarget(match[2]); if (target) { this.readFile(target); this.dependencies.push(target); } } } private readFile(fileName: string) { let contents = fs.readFileSync(fileName).toString(); this.extractDepsFromString(contents) } public getDependencies() { return this.dependencies; } private tryFile(filePath: string): string { // restrict node_module // we don't want to detect stuff from there if (filePath.indexOf("node_modules") > -1) { return; } let fname = path.basename(filePath); // if a filename doesn't have _ we need to try it with _ for sass cases if (this.opts.sassStyle && !/^_/.test(fname)) { const pathWithUnderScore = path.join(path.dirname(filePath), "_" + fname); if (fs.existsSync(pathWithUnderScore)) { return pathWithUnderScore; } } if (fs.existsSync(filePath)) { return filePath; } } private getPath(suggested: string, fileName: string) { let target = fileName; if (this.opts.importer) { fileName = this.opts.importer(fileName, null, info => { target = info.file; }); } if (path.isAbsolute(target)) { return target; } return path.join(suggested, target); } private findTarget(fileName: string): string { let targetFile: any; let extName = path.extname(fileName); if (!extName) { for (let p = 0; p < this.opts.paths.length; p++) { for (let e = 0; e < this.opts.extensions.length; e++) { let filePath = this.getPath(this.opts.paths[p], fileName + "." + this.opts.extensions[e]); filePath = this.tryFile(filePath); if (filePath) { return filePath; } } } } else { for (let p = 0; p < this.opts.paths.length; p++) { let filePath = this.getPath(this.opts.paths[p], fileName); filePath = this.tryFile(filePath); if (filePath) { return filePath; } } } return targetFile; } public static init(opts: ICSSDependencyExtractorOptions) { return new CSSDependencyExtractor(opts); } // }