@stylable/core
Version:
CSS for Components
106 lines (92 loc) • 2.97 kB
text/typescript
import { dirname } from 'path';
const deindent = require('deindent');
import { MinimalFS } from './cached-process-file';
export interface File {
content: string;
mtime?: Date;
}
export interface MinimalFSSetup {
files: { [absolutePath: string]: File };
trimWS?: boolean;
}
export function createMinimalFS({ files, trimWS }: MinimalFSSetup) {
const creationDate = new Date();
const filePaths = new Map<string, { content: string; mtime: Date }>(
Object.entries(files).map(([filePath, { content, mtime = creationDate }]) => [
filePath,
{ content, mtime },
])
);
const directoryPaths = new Set<string>();
for (const filePath of filePaths.keys()) {
for (const directoryPath of getParentPaths(dirname(filePath))) {
directoryPaths.add(directoryPath);
}
}
const fs: MinimalFS = {
readFileSync(path: string) {
if (!files[path]) {
throw new Error('Cannot find file: ' + path);
}
if (trimWS) {
return deindent(files[path].content).trim();
}
return files[path].content;
},
statSync(path: string) {
const isDirectory = directoryPaths.has(path);
const fileEntry = filePaths.get(path);
if (!fileEntry && !isDirectory) {
throw new Error(`ENOENT: no such file or directory, stat ${path}`);
}
return {
isDirectory() {
return isDirectory;
},
isFile() {
return !!fileEntry;
},
mtime: fileEntry ? fileEntry.mtime : new Date(),
};
},
readlinkSync() {
throw new Error(`not implemented`);
},
};
const requireModule = function require(id: string): any {
const _module = {
id,
exports: {},
};
try {
if (!id.match(/\.js$/)) {
id += '.js';
}
// eslint-disable-next-line @typescript-eslint/no-implied-eval
const fn = new Function('module', 'exports', 'require', files[id].content);
fn(_module, _module.exports, requireModule);
} catch (e) {
throw new Error('Cannot require file: ' + id);
}
return _module.exports;
};
function resolvePath(_ctx: string, path: string) {
return path;
}
return {
fs,
requireModule,
resolvePath,
};
}
function getParentPaths(initialDirectoryPath: string) {
const parentPaths: string[] = [];
let currentPath = initialDirectoryPath;
let lastPath: string | undefined;
while (currentPath !== lastPath) {
parentPaths.push(currentPath);
lastPath = currentPath;
currentPath = dirname(currentPath);
}
return parentPaths;
}