UNPKG

2.49 kBJavaScriptView Raw
1import { HTML_JS_REGEX } from './util';
2const { parse } = require('es-module-lexer');
3function spliceString(source, withSlice, start, end) {
4 return source.slice(0, start) + (withSlice || '') + source.slice(end);
5}
6export async function scanCodeImportsExports(code) {
7 const [imports] = await parse(code);
8 return imports.filter((imp) => {
9 //imp.d = -2 = import.meta.url = we can skip this for now
10 if (imp.d === -2) {
11 return false;
12 }
13 // imp.d > -1 === dynamic import
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}
22export 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}
39async 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 // Only transform a script element if it contains inlined code / is not empty.
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}
52export 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}