-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
110 lines (96 loc) · 4.61 KB
/
index.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
104
105
106
107
108
109
110
import MagicString from "magic-string"
import {minimatch} from "minimatch"
export default function importSideEffectPlugin (options) {
const jsIdentifierRegex = new RegExp(/^[A-Za-z_][A-Za-z0-9_]*$/)
if (options.defNames === undefined) {
throw new Error("importSideEffectPlugin: You must provide defNames option. See docs. Use an empty array if you don't want any.")
} else if (!(options.defNames instanceof Array)) {
throw new Error(`importSideEffectPlugin: defNames option expects an array of strings, you provided a single \`${typeof options.defNames}\` instead. See docs.`)
} else {
options.defNames.forEach(defName => {
if (typeof defName !== "string") {
throw new Error(`importSideEffectPlugin: defNames option expects an array of strings, you provided an array with \`${typeof defName}\` instead. See docs.`)
}
if (!jsIdentifierRegex.test(defName)) {
throw new Error(`importSideEffectPlugin: the provided defName \`${defName}\` is not valid. Must match RegExp(/^[A-Za-z_][A-Za-z0-9_]*$/).`)
}
})
}
if (options.rewriteModuleIds === undefined) {
throw new Error("importSideEffectPlugin: You must provide importModuleIds option. See docs. Disable the plugin if you don't want any.")
} else if (!(options.rewriteModuleIds instanceof Array)) {
throw new Error(`importSideEffectPlugin: importModuleIds option expects an array of strings (glob patterns), you provided a single \`${typeof options.rewriteModuleIds}\` instead. See docs.`)
} else {
options.rewriteModuleIds.forEach(moduleIdPattern => {
if (typeof moduleIdPattern !== "string") {
throw new Error(`importSideEffectPlugin: importModuleIds option expects an array of strings, you provided an array with \`${typeof moduleIdPattern}\` instead. See docs.`)
}
})
}
options.verbose = !!options.verbose
if (!options.sourceMapOptions) {
// See https://github.com/rich-harris/magic-string#sgeneratemap-options-
options.sourceMapOptions = {}
}
if (options.sourceMapOptions.hires === undefined) {
options.sourceMapOptions.hires = true // high resolution source maps by default
}
const defNamesObjRepr = '{' + options.defNames.map(defName => `${defName}: function () {}`).join(', ') + '}'
return {
name: '@raquo/vite-plugin-import-side-effect',
transform (code, id) {
const {moduleId, querySuffix} = splitModuleId(id);
const comment = "// import below modified by @raquo/vite-plugin-import-side-effect"
// #TODO We only want to process JS files generated by scala.js,
// processing any other files is a waste of CPU cycles.
// #TODO Consider first finding the index of "var $linkingInfo"
// in the file, and only looking at the file contents prior to
// that. This is where scala.js imports live. I'm just not sure
// if this assumption is universally true (e.g. module splitting?)
if (moduleId.endsWith(".js") && !moduleId.includes("node_modules")) {
const str = new MagicString(code)
const p = new RegExp(/^\s*import \S+ as (\$i_[\w$]+) from "(.+)";?\s*$/, 'gm')
const sideEffectImports = []
let match = null;
while ((match = p.exec(code)) !== null) {
const importedAlias = match[1]
const moduleId = match[2]
let shouldRewrite = false
options.rewriteModuleIds.forEach(rewriteModuleIdPattern => {
if (!shouldRewrite && minimatch(moduleId, rewriteModuleIdPattern)) {
shouldRewrite = true
}
})
if (shouldRewrite) {
sideEffectImports.push(" - " + moduleId)
const replacement = `${comment}\nconst ${importedAlias} = ${defNamesObjRepr};\nimport "${moduleId}";`
str.overwrite(match.index, match.index + match[0].length, replacement)
}
}
if (options.verbose) {
console.log(`\n@raquo/import-side-effect -- ${id}:\n${sideEffectImports.join("\n")}`)
}
return {
code: str.toString(),
map: str.generateMap(options.sourceMapOptions)
};
} else {
return null;
}
}
};
}
/** Helper to split e.g. "foo.css?used" into "foo" and "?used" */
export function splitModuleId (id) {
const indexOfQuery = id.lastIndexOf("?");
let moduleId = id;
let querySuffix = ""
if (indexOfQuery !== -1) {
moduleId = id.substring(0, indexOfQuery)
querySuffix = id.substring(indexOfQuery)
}
return {
moduleId, // anything before the last "?", or the whole module id if there is no query
querySuffix // everything after and including "?", or an empty string if there is no query
}
}