1 | import { HTML_JS_REGEX } from './util';
|
2 | const { parse } = require('es-module-lexer');
|
3 | function spliceString(source, withSlice, start, end) {
|
4 | return source.slice(0, start) + (withSlice || '') + source.slice(end);
|
5 | }
|
6 | export async function scanCodeImportsExports(code) {
|
7 | const [imports] = await parse(code);
|
8 | return imports.filter((imp) => {
|
9 |
|
10 | if (imp.d === -2) {
|
11 | return false;
|
12 | }
|
13 |
|
14 | if (imp.d > -1) {
|
15 | const importStatement = code.substring(imp.s, imp.e);
|
16 | const importSpecifierMatch = importStatement.match(/^\s*['"](.*)['"]\s*$/m);
|
17 | return !!importSpecifierMatch;
|
18 | }
|
19 | return true;
|
20 | });
|
21 | }
|
22 | export async function transformEsmImports(_code, replaceImport) {
|
23 | const imports = await scanCodeImportsExports(_code);
|
24 | let rewrittenCode = _code;
|
25 | for (const imp of imports.reverse()) {
|
26 | let spec = rewrittenCode.substring(imp.s, imp.e);
|
27 | if (imp.d > -1) {
|
28 | const importSpecifierMatch = spec.match(/^\s*['"](.*)['"]\s*$/m);
|
29 | spec = importSpecifierMatch[1];
|
30 | }
|
31 | let rewrittenImport = replaceImport(spec);
|
32 | if (imp.d > -1) {
|
33 | rewrittenImport = JSON.stringify(rewrittenImport);
|
34 | }
|
35 | rewrittenCode = spliceString(rewrittenCode, rewrittenImport, imp.s, imp.e);
|
36 | }
|
37 | return rewrittenCode;
|
38 | }
|
39 | async function transformHtmlImports(code, replaceImport) {
|
40 | let rewrittenCode = code;
|
41 | let match;
|
42 | const importRegex = new RegExp(HTML_JS_REGEX);
|
43 | while ((match = importRegex.exec(rewrittenCode))) {
|
44 | const [, scriptTag, scriptCode] = match;
|
45 |
|
46 | if (scriptCode.trim()) {
|
47 | rewrittenCode = spliceString(rewrittenCode, await transformEsmImports(scriptCode, replaceImport), match.index + scriptTag.length, match.index + scriptTag.length + scriptCode.length);
|
48 | }
|
49 | }
|
50 | return rewrittenCode;
|
51 | }
|
52 | export async function transformFileImports({ baseExt, code }, replaceImport) {
|
53 | if (baseExt === '.js') {
|
54 | return transformEsmImports(code, replaceImport);
|
55 | }
|
56 | if (baseExt === '.html') {
|
57 | return transformHtmlImports(code, replaceImport);
|
58 | }
|
59 | throw new Error(`Incompatible filetype: cannot scan ${baseExt} files for ESM imports. This is most likely an error within Snowpack.`);
|
60 | }
|