-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathfile-system-loader.ts
77 lines (61 loc) · 2.15 KB
/
file-system-loader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* this file is forked from https://raw.githubusercontent.com/css-modules/css-modules-loader-core/master/src/file-system-loader.js */
import Core from 'css-modules-loader-core'
import * as fs from 'fs'
import * as path from 'path'
import * as util from 'util'
import { Plugin } from "postcss";
type Dictionary<T> = {
[key: string]: T | undefined;
};
const readFile = util.promisify(fs.readFile);
export default class FileSystemLoader {
private root: string;
private sources: Dictionary<string>;
private importNr: number;
private core: Core;
public tokensByFile: Dictionary<Core.ExportTokens>;
constructor( root: string, plugins?: Array<Plugin<any>> ) {
this.root = root;
this.sources = {};
this.importNr = 0;
//@ts-ignore
this.core = new Core(plugins );
this.tokensByFile = {};
}
public async fetch(_newPath: string, relativeTo: string, _trace?: string, initialContents?: string): Promise<Core.ExportTokens> {
const newPath = _newPath.replace(/^["']|["']$/g, "");
const trace = _trace || String.fromCharCode(this.importNr++);
const relativeDir = path.dirname(relativeTo);
const rootRelativePath = path.resolve(relativeDir, newPath);
let fileRelativePath = path.resolve(path.join(this.root, relativeDir), newPath);
// if the path is not relative or absolute, try to resolve it in node_modules
if (newPath[0] !== '.' && newPath[0] !== '/') {
try {
fileRelativePath = require.resolve(newPath);
}
catch (e) {}
}
let source: string;
if (!initialContents) {
const tokens = this.tokensByFile[fileRelativePath]
if (tokens) {
return tokens;
}
try {
source = await readFile(fileRelativePath, "utf-8");
}
catch (error) {
if (relativeTo && relativeTo !== '/') {
return {};
}
throw error;
}
} else {
source = initialContents;
}
const { injectableSource, exportTokens } = await this.core.load(source, rootRelativePath, trace, this.fetch.bind(this));
this.sources[trace] = injectableSource;
this.tokensByFile[fileRelativePath] = exportTokens;
return exportTokens;
}
}