-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathimportGlob.js
103 lines (97 loc) · 2.47 KB
/
importGlob.js
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import path from 'path';
import glob from 'fast-glob';
function lexGlobPattern(code, pos) {
let state = 0;
let pattern = '';
let i = code.indexOf(`(`, pos) + 1;
outer: for (; i < code.length; i++) {
const char = code.charAt(i);
switch (state) {
case 0:
if (char === `'`) {
state = 1;
} else if (char === `"`) {
state = 2;
} else if (char === '`') {
state = 4;
} else if (/\s/.test(char)) {
continue;
} else {
error(i);
}
break;
case 1:
if (char === `'`) {
break outer;
} else {
pattern += char;
}
break;
case 2:
if (char === `"`) {
break outer;
} else {
pattern += char;
}
break;
case 4:
if (char === '`') {
break outer;
} else {
pattern += char;
}
break;
default:
throw new Error('unknown import.meta.glob lexer state');
}
}
return [pattern, code.indexOf(`)`, i) + 1];
}
export async function transformImportGlob(source, pos, importer, importIndex) {
const err = msg => {
const e = new Error(`Invalid glob import syntax: ${msg}`);
e.pos = pos;
return e;
};
const importerBasename = path.basename(importer);
let [pattern, endIndex] = lexGlobPattern(source, pos);
if (!pattern.startsWith('.')) {
throw err(`pattern must start with "." (relative to project root)`);
}
let base;
let parentDepth = 0;
base = path.dirname(importer);
while (pattern.startsWith('../')) {
pattern = pattern.slice(3);
base = path.resolve(base, '../');
parentDepth++;
}
if (pattern.startsWith('./')) {
pattern = pattern.slice(2);
}
const files = glob.sync(pattern, {
cwd: base,
ignore: ['**/node_modules/**'],
});
const imports = [];
let importsString = ``;
let entries = ``;
for (let i = 0; i < files.length; i++) {
// skip importer itself
if (files[i] === importerBasename) continue;
const file = parentDepth ? `${'../'.repeat(parentDepth)}${files[i]}` : `./${files[i]}`;
let importee = file;
imports.push(importee);
const identifier = `__glob_${importIndex}_${i}`;
importsString += `import * as ${identifier} from ${JSON.stringify(importee)};`;
entries += ` ${JSON.stringify(file)}: ${identifier},`;
}
return {
imports,
importsString,
exp: `{${entries}}`,
endIndex,
pattern,
base,
};
}