@jsenv/core 25.0.1 → 25.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser_runtime/browser_runtime_91c5a3b8.js.map +2 -2
- package/dist/build_manifest.js +4 -4
- package/dist/compile_proxy/asset-manifest.json +2 -2
- package/dist/compile_proxy/{compile_proxy_e3b0c442_809f35f7.js.map → compile_proxy.html__inline__20_809f35f7.js.map} +0 -0
- package/dist/compile_proxy/{compile_proxy_7ad5faa6.html → compile_proxy_8dfaee51.html} +3 -4
- package/dist/redirector/asset-manifest.json +2 -2
- package/dist/redirector/{redirector_e3b0c442_e391410e.js.map → redirector.html__inline__15_e391410e.js.map} +0 -0
- package/dist/redirector/{redirector_eb92e8a7.html → redirector_3e9a97b9.html} +3 -4
- package/dist/toolbar/asset-manifest.json +1 -1
- package/dist/toolbar/{toolbar_f7b8a263.html → toolbar_361afb84.html} +2 -3
- package/dist/toolbar_injector/asset-manifest.json +2 -2
- package/dist/toolbar_injector/{toolbar_injector_49e4756e.js → toolbar_injector_fac1e995.js} +2 -2
- package/dist/toolbar_injector/{toolbar_injector_49e4756e.js.map → toolbar_injector_fac1e995.js.map} +2 -2
- package/package.json +9 -10
- package/readme.md +60 -51
- package/src/buildProject.js +21 -13
- package/src/commonJsToJavaScriptModule.js +8 -7
- package/src/dev_server.js +2 -0
- package/src/execute.js +2 -0
- package/src/executeTestPlan.js +14 -0
- package/src/internal/building/buildUsingRollup.js +4 -2
- package/src/internal/building/build_stats.js +3 -0
- package/src/internal/building/build_url_generator.js +153 -0
- package/src/internal/building/css/parseCssRessource.js +32 -26
- package/src/internal/building/html/parseHtmlRessource.js +109 -91
- package/src/internal/building/js/parseJsRessource.js +5 -13
- package/src/internal/building/parseRessource.js +3 -0
- package/src/internal/building/ressource_builder.js +72 -64
- package/src/internal/building/ressource_builder_util.js +17 -5
- package/src/internal/building/rollup_plugin_jsenv.js +262 -189
- package/src/internal/building/url_fetcher.js +16 -7
- package/src/internal/building/url_loader.js +1 -5
- package/src/internal/building/url_versioning.js +0 -173
- package/src/internal/compiling/babel_plugin_import_metadata.js +7 -11
- package/src/internal/compiling/babel_plugin_proxy_external_imports.js +31 -0
- package/src/internal/compiling/compile-directory/compile-asset.js +8 -4
- package/src/internal/compiling/compile-directory/getOrGenerateCompiledFile.js +43 -8
- package/src/internal/compiling/compile-directory/updateMeta.js +4 -8
- package/src/internal/compiling/compile-directory/validateCache.js +1 -2
- package/src/internal/compiling/compileFile.js +22 -10
- package/src/internal/compiling/compileHtml.js +15 -28
- package/src/internal/compiling/createCompiledFileService.js +22 -24
- package/src/internal/compiling/html_source_file_service.js +18 -19
- package/src/internal/compiling/js-compilation-service/babelHelper.js +10 -13
- package/src/internal/compiling/js-compilation-service/babel_plugin_babel_helpers_as_jsenv_imports.js +4 -2
- package/src/internal/compiling/js-compilation-service/jsenvTransform.js +16 -7
- package/src/internal/compiling/js-compilation-service/transformJs.js +9 -5
- package/src/internal/compiling/jsenvCompilerForHtml.js +536 -262
- package/src/internal/compiling/jsenvCompilerForJavaScript.js +15 -11
- package/src/internal/compiling/startCompileServer.js +83 -20
- package/src/internal/compiling/transformResultToCompilationResult.js +47 -25
- package/src/internal/executing/executePlan.js +2 -0
- package/src/internal/fetchUrl.js +3 -2
- package/src/internal/integrity/integrity_algorithms.js +26 -0
- package/src/internal/integrity/integrity_parsing.js +50 -0
- package/src/internal/integrity/integrity_update.js +23 -0
- package/src/internal/integrity/integrity_validation.js +49 -0
- package/src/internal/jsenvCoreDirectoryUrl.js +2 -0
- package/src/internal/jsenv_remote_directory.js +156 -0
- package/src/internal/origin_directory_converter.js +62 -0
- package/src/internal/response_validation.js +11 -24
- package/src/internal/sourceMappingURLUtils.js +10 -0
- package/src/internal/url_conversion.js +1 -0
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
resolveUrl,
|
|
3
|
+
urlToFilename,
|
|
4
|
+
urlToRelativeUrl,
|
|
5
|
+
urlIsInsideOf,
|
|
6
|
+
} from "@jsenv/filesystem"
|
|
2
7
|
import { moveImportMap, composeTwoImportMaps } from "@jsenv/importmap"
|
|
3
8
|
import { createDetailedMessage } from "@jsenv/logger"
|
|
4
9
|
|
|
10
|
+
import { jsenvDistDirectoryUrl } from "@jsenv/core/src/internal/jsenvCoreDirectoryUrl.js"
|
|
5
11
|
import {
|
|
6
12
|
BROWSER_RUNTIME_BUILD_URL,
|
|
7
13
|
EVENT_SOURCE_CLIENT_BUILD_URL,
|
|
@@ -11,6 +17,7 @@ import { fetchUrl } from "@jsenv/core/src/internal/fetchUrl.js"
|
|
|
11
17
|
import { getDefaultImportmap } from "@jsenv/core/src/internal/import-resolution/importmap_default.js"
|
|
12
18
|
|
|
13
19
|
import {
|
|
20
|
+
generateSourcemapUrl,
|
|
14
21
|
setJavaScriptSourceMappingUrl,
|
|
15
22
|
sourcemapToBase64Url,
|
|
16
23
|
} from "../sourceMappingURLUtils.js"
|
|
@@ -23,47 +30,46 @@ import {
|
|
|
23
30
|
stringifyHtmlAst,
|
|
24
31
|
getHtmlNodeAttributeByName,
|
|
25
32
|
getHtmlNodeTextNode,
|
|
26
|
-
|
|
33
|
+
getIdForInlineHtmlNode,
|
|
27
34
|
removeHtmlNodeAttribute,
|
|
28
35
|
setHtmlNodeText,
|
|
29
36
|
visitHtmlAst,
|
|
30
|
-
|
|
37
|
+
addHtmlNodeAttribute,
|
|
31
38
|
} from "./compileHtml.js"
|
|
32
|
-
import {
|
|
39
|
+
import { generateCompilationAssetUrl } from "./compile-directory/compile-asset.js"
|
|
33
40
|
|
|
34
41
|
export const compileHtml = async ({
|
|
35
42
|
// cancellationToken,
|
|
36
43
|
logger,
|
|
37
|
-
// request,
|
|
38
|
-
code,
|
|
39
44
|
url,
|
|
40
45
|
compiledUrl,
|
|
41
46
|
projectDirectoryUrl,
|
|
47
|
+
jsenvRemoteDirectory,
|
|
48
|
+
compileServerOrigin,
|
|
42
49
|
outDirectoryRelativeUrl,
|
|
43
|
-
compileId,
|
|
44
50
|
|
|
51
|
+
compileId,
|
|
45
52
|
babelPluginMap,
|
|
46
53
|
moduleOutFormat,
|
|
47
54
|
importMetaFormat,
|
|
48
55
|
topLevelAwait,
|
|
49
|
-
|
|
50
|
-
sourcemapMethod,
|
|
51
|
-
|
|
52
56
|
jsenvScriptInjection = true,
|
|
53
57
|
jsenvEventSourceClientInjection,
|
|
54
58
|
jsenvToolbarInjection,
|
|
55
59
|
onHtmlImportmapInfo,
|
|
60
|
+
|
|
61
|
+
sourcemapMethod,
|
|
62
|
+
code,
|
|
56
63
|
}) => {
|
|
64
|
+
const compileDirectoryUrl = `${projectDirectoryUrl}${outDirectoryRelativeUrl}${compileId}/`
|
|
57
65
|
const browserRuntimeBuildUrlRelativeToProject = urlToRelativeUrl(
|
|
58
66
|
BROWSER_RUNTIME_BUILD_URL,
|
|
59
67
|
projectDirectoryUrl,
|
|
60
68
|
)
|
|
61
|
-
|
|
62
69
|
const eventSourceClientBuildRelativeUrlForProject = urlToRelativeUrl(
|
|
63
70
|
EVENT_SOURCE_CLIENT_BUILD_URL,
|
|
64
71
|
projectDirectoryUrl,
|
|
65
72
|
)
|
|
66
|
-
|
|
67
73
|
const toolbarInjectorBuildRelativeUrlForProject = urlToRelativeUrl(
|
|
68
74
|
TOOLBAR_INJECTOR_BUILD_URL,
|
|
69
75
|
projectDirectoryUrl,
|
|
@@ -71,11 +77,6 @@ export const compileHtml = async ({
|
|
|
71
77
|
|
|
72
78
|
// ideally we should try/catch html syntax error
|
|
73
79
|
const htmlAst = parseHtmlString(code)
|
|
74
|
-
|
|
75
|
-
if (moduleOutFormat !== "esmodule") {
|
|
76
|
-
await mutateRessourceHints(htmlAst)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
80
|
manipulateHtmlAst(htmlAst, {
|
|
80
81
|
scriptInjections: [
|
|
81
82
|
...(jsenvScriptInjection
|
|
@@ -104,255 +105,562 @@ export const compileHtml = async ({
|
|
|
104
105
|
],
|
|
105
106
|
})
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
const sources = []
|
|
109
|
+
const sourcesContent = []
|
|
110
|
+
const assets = []
|
|
111
|
+
const assetsContent = []
|
|
112
|
+
|
|
113
|
+
const addHtmlSourceFile = ({ url, content }) => {
|
|
114
|
+
sources.push(url)
|
|
115
|
+
sourcesContent.push(content)
|
|
116
|
+
}
|
|
117
|
+
addHtmlSourceFile({ url, content: code })
|
|
118
|
+
|
|
109
119
|
const { scripts } = parseHtmlAstRessources(htmlAst)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
120
|
+
const htmlDependencies = collectHtmlDependenciesFromAst(htmlAst)
|
|
121
|
+
|
|
122
|
+
const htmlAssetGenerators = []
|
|
123
|
+
const htmlMutations = []
|
|
124
|
+
const addHtmlAssetGenerator = (htmlAssetGenerator) => {
|
|
125
|
+
htmlAssetGenerators.push(htmlAssetGenerator)
|
|
126
|
+
}
|
|
127
|
+
const addHtmlMutation = (htmlMutation) => {
|
|
128
|
+
htmlMutations.push(htmlMutation)
|
|
129
|
+
}
|
|
130
|
+
const addHtmlDependency = ({ htmlNode, specifier }) => {
|
|
131
|
+
htmlDependencies.push({
|
|
132
|
+
htmlNode,
|
|
133
|
+
specifier,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
if (moduleOutFormat !== "esmodule") {
|
|
137
|
+
const ressourceHints = collectRessourceHints(htmlAst)
|
|
138
|
+
await visitRessourceHints({
|
|
139
|
+
ressourceHints,
|
|
140
|
+
addHtmlMutation,
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
await visitImportmapScript({
|
|
144
|
+
htmlAst,
|
|
145
|
+
logger,
|
|
146
|
+
url,
|
|
147
|
+
compiledUrl,
|
|
148
|
+
projectDirectoryUrl,
|
|
149
|
+
compileDirectoryUrl,
|
|
150
|
+
moduleOutFormat,
|
|
151
|
+
scripts,
|
|
152
|
+
addHtmlMutation,
|
|
153
|
+
addHtmlSourceFile,
|
|
154
|
+
onHtmlImportmapInfo,
|
|
155
|
+
})
|
|
156
|
+
await visitScripts({
|
|
157
|
+
logger,
|
|
158
|
+
projectDirectoryUrl,
|
|
159
|
+
jsenvRemoteDirectory,
|
|
160
|
+
compileServerOrigin,
|
|
161
|
+
url,
|
|
162
|
+
compiledUrl,
|
|
163
|
+
|
|
164
|
+
babelPluginMap,
|
|
165
|
+
moduleOutFormat,
|
|
166
|
+
importMetaFormat,
|
|
167
|
+
topLevelAwait,
|
|
168
|
+
sourcemapMethod,
|
|
169
|
+
|
|
170
|
+
scripts,
|
|
171
|
+
addHtmlSourceFile,
|
|
172
|
+
addHtmlAssetGenerator,
|
|
173
|
+
addHtmlMutation,
|
|
174
|
+
addHtmlDependency,
|
|
175
|
+
})
|
|
176
|
+
await Promise.all(
|
|
177
|
+
htmlAssetGenerators.map(async (htmlAssetGenerator) => {
|
|
178
|
+
const assetInfos = await htmlAssetGenerator()
|
|
179
|
+
assetInfos.forEach((assetInfo) => {
|
|
180
|
+
assets.push(assetInfo.url)
|
|
181
|
+
assetsContent.push(assetInfo.content)
|
|
182
|
+
})
|
|
183
|
+
}),
|
|
184
|
+
)
|
|
185
|
+
htmlAssetGenerators.length = 0
|
|
186
|
+
htmlMutations.forEach((htmlMutation) => {
|
|
187
|
+
htmlMutation()
|
|
188
|
+
})
|
|
189
|
+
htmlMutations.length = 0
|
|
190
|
+
const htmlAfterTransformation = stringifyHtmlAst(htmlAst)
|
|
191
|
+
return {
|
|
192
|
+
contentType: "text/html",
|
|
193
|
+
compiledSource: htmlAfterTransformation,
|
|
194
|
+
sources,
|
|
195
|
+
sourcesContent,
|
|
196
|
+
assets,
|
|
197
|
+
assetsContent,
|
|
198
|
+
dependencies: htmlDependencies.map(({ specifier }) => {
|
|
199
|
+
return specifier
|
|
200
|
+
}),
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// transform <link type="modulepreload"> into <link type="preload">
|
|
205
|
+
// also remove integrity attributes because we don't know in advance
|
|
206
|
+
// the result of the file compilation
|
|
207
|
+
const visitRessourceHints = async ({ ressourceHints, addHtmlMutation }) => {
|
|
208
|
+
await Promise.all(
|
|
209
|
+
ressourceHints.map(async (ressourceHint) => {
|
|
210
|
+
const hrefAttribute = getHtmlNodeAttributeByName(ressourceHint, "href")
|
|
211
|
+
const href = hrefAttribute ? hrefAttribute.value : ""
|
|
212
|
+
if (!href) {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
const integrityAttribute = getHtmlNodeAttributeByName(
|
|
216
|
+
ressourceHint,
|
|
217
|
+
"integrity",
|
|
218
|
+
)
|
|
219
|
+
if (integrityAttribute) {
|
|
220
|
+
addHtmlMutation(() => {
|
|
221
|
+
removeHtmlNodeAttribute(ressourceHint, integrityAttribute)
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
const relAttribute = getHtmlNodeAttributeByName(ressourceHint, "rel")
|
|
225
|
+
const asAttribute = getHtmlNodeAttributeByName(ressourceHint, "as")
|
|
226
|
+
// - "modulepreload" -> "preload" because it's now regular js script
|
|
227
|
+
if (ressourceHint.rel === "modulepreload") {
|
|
228
|
+
addHtmlMutation(() => {
|
|
229
|
+
relAttribute.value = "preload"
|
|
230
|
+
if (asAttribute) {
|
|
231
|
+
asAttribute.value = "script"
|
|
232
|
+
} else {
|
|
233
|
+
addHtmlNodeAttribute(ressourceHint, { name: "as", value: "script" })
|
|
169
234
|
}
|
|
170
|
-
}
|
|
235
|
+
})
|
|
236
|
+
return
|
|
171
237
|
}
|
|
172
|
-
|
|
238
|
+
// if (asAttribute && asAttribute.value === "script") {
|
|
239
|
+
// addHtmlMutation(() => {
|
|
240
|
+
// replaceHtmlNode(htmlNode, `<link as="script" />`)
|
|
241
|
+
// })
|
|
242
|
+
// return
|
|
243
|
+
// }
|
|
244
|
+
}),
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const visitImportmapScript = async ({
|
|
249
|
+
htmlAst,
|
|
250
|
+
logger,
|
|
251
|
+
url,
|
|
252
|
+
compiledUrl,
|
|
253
|
+
projectDirectoryUrl,
|
|
254
|
+
compileDirectoryUrl,
|
|
255
|
+
moduleOutFormat,
|
|
256
|
+
scripts,
|
|
257
|
+
addHtmlMutation,
|
|
258
|
+
addHtmlSourceFile,
|
|
259
|
+
onHtmlImportmapInfo,
|
|
260
|
+
}) => {
|
|
261
|
+
const importmapScripts = scripts.filter((script) => {
|
|
262
|
+
const typeAttribute = getHtmlNodeAttributeByName(script, "type")
|
|
263
|
+
const type = typeAttribute ? typeAttribute.value : "application/javascript"
|
|
264
|
+
return type === "importmap"
|
|
173
265
|
})
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
replaceHtmlNode(
|
|
178
|
-
importmapInfo.script,
|
|
179
|
-
`<script type="${
|
|
180
|
-
moduleOutFormat === "systemjs" ? "systemjs-importmap" : "importmap"
|
|
181
|
-
}">${importmapAsText}</script>`,
|
|
182
|
-
{
|
|
183
|
-
attributesToIgnore: ["src"],
|
|
184
|
-
},
|
|
185
|
-
)
|
|
186
|
-
importmapInfo.inlinedFrom = importmapInfo.url
|
|
187
|
-
importmapInfo.text = importmapAsText
|
|
188
|
-
} else {
|
|
266
|
+
// in case there is no importmap, force the presence
|
|
267
|
+
// so that '@jsenv/core/' are still remapped
|
|
268
|
+
if (importmapScripts.length === 0) {
|
|
189
269
|
const defaultImportMap = getDefaultImportmap(compiledUrl, {
|
|
190
270
|
projectDirectoryUrl,
|
|
191
|
-
compileDirectoryUrl
|
|
271
|
+
compileDirectoryUrl,
|
|
192
272
|
})
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
scriptInjections: [
|
|
196
|
-
{
|
|
197
|
-
type:
|
|
198
|
-
moduleOutFormat === "systemjs" ? "systemjs-importmap" : "importmap",
|
|
199
|
-
// in case there is no importmap, force the presence
|
|
200
|
-
// so that '@jsenv/core/' are still remapped
|
|
201
|
-
text: importmapAsText,
|
|
202
|
-
},
|
|
203
|
-
],
|
|
204
|
-
})
|
|
205
|
-
importmapInfo = {
|
|
273
|
+
const defaultImportMapAsText = JSON.stringify(defaultImportMap, null, " ")
|
|
274
|
+
onHtmlImportmapInfo({
|
|
206
275
|
url: compiledUrl,
|
|
207
|
-
text:
|
|
276
|
+
text: defaultImportMapAsText,
|
|
277
|
+
})
|
|
278
|
+
addHtmlMutation(() => {
|
|
279
|
+
manipulateHtmlAst(htmlAst, {
|
|
280
|
+
scriptInjections: [
|
|
281
|
+
{
|
|
282
|
+
type:
|
|
283
|
+
moduleOutFormat === "systemjs"
|
|
284
|
+
? "systemjs-importmap"
|
|
285
|
+
: "importmap",
|
|
286
|
+
text: defaultImportMapAsText,
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
return
|
|
292
|
+
}
|
|
293
|
+
if (importmapScripts.length > 1) {
|
|
294
|
+
logger.error("HTML file must contain max 1 importmap")
|
|
295
|
+
}
|
|
296
|
+
const firstImportmapScript = importmapScripts[0]
|
|
297
|
+
const srcAttribute = getHtmlNodeAttributeByName(firstImportmapScript, "src")
|
|
298
|
+
const src = srcAttribute ? srcAttribute.value : ""
|
|
299
|
+
if (src) {
|
|
300
|
+
const importmapUrl = resolveUrl(src, url)
|
|
301
|
+
const importMapResponse = await fetchUrl(importmapUrl)
|
|
302
|
+
let importmap
|
|
303
|
+
if (importMapResponse.status === 200) {
|
|
304
|
+
const importmapAsText = await importMapResponse.text()
|
|
305
|
+
addHtmlSourceFile({
|
|
306
|
+
url: importmapUrl,
|
|
307
|
+
content: importmapAsText,
|
|
308
|
+
})
|
|
309
|
+
let htmlImportmap = JSON.parse(importmapAsText)
|
|
310
|
+
importmap = moveImportMap(htmlImportmap, importmapUrl, url)
|
|
311
|
+
} else {
|
|
312
|
+
logger.warn(
|
|
313
|
+
createDetailedMessage(
|
|
314
|
+
importMapResponse.status === 404
|
|
315
|
+
? `importmap script file cannot be found.`
|
|
316
|
+
: `importmap script file unexpected response status (${importMapResponse.status}).`,
|
|
317
|
+
{
|
|
318
|
+
"importmap url": importmapUrl,
|
|
319
|
+
"html url": url,
|
|
320
|
+
},
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
importmap = {}
|
|
208
324
|
}
|
|
325
|
+
const importmapAsText = JSON.stringify(importmap, null, " ")
|
|
326
|
+
onHtmlImportmapInfo({
|
|
327
|
+
url: importmapUrl,
|
|
328
|
+
text: importmapAsText,
|
|
329
|
+
})
|
|
330
|
+
addHtmlMutation(() => {
|
|
331
|
+
removeHtmlNodeAttribute(firstImportmapScript, srcAttribute)
|
|
332
|
+
setHtmlNodeText(firstImportmapScript, importmapAsText)
|
|
333
|
+
if (moduleOutFormat === "systemjs") {
|
|
334
|
+
const typeAttribute = getHtmlNodeAttributeByName(
|
|
335
|
+
firstImportmapScript,
|
|
336
|
+
"type",
|
|
337
|
+
)
|
|
338
|
+
typeAttribute.value = "systemjs-importmap"
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
return
|
|
209
342
|
}
|
|
343
|
+
|
|
344
|
+
const jsenvImportmap = getDefaultImportmap(compiledUrl, {
|
|
345
|
+
projectDirectoryUrl,
|
|
346
|
+
compileDirectoryUrl,
|
|
347
|
+
})
|
|
348
|
+
const htmlImportmap = JSON.parse(
|
|
349
|
+
getHtmlNodeTextNode(firstImportmapScript).value,
|
|
350
|
+
)
|
|
351
|
+
const importmap = composeTwoImportMaps(jsenvImportmap, htmlImportmap)
|
|
352
|
+
const importmapAsText = JSON.stringify(importmap, null, " ")
|
|
210
353
|
onHtmlImportmapInfo({
|
|
211
|
-
|
|
212
|
-
|
|
354
|
+
url: compiledUrl,
|
|
355
|
+
text: importmapAsText,
|
|
356
|
+
})
|
|
357
|
+
addHtmlMutation(() => {
|
|
358
|
+
removeHtmlNodeAttribute(firstImportmapScript, srcAttribute)
|
|
359
|
+
setHtmlNodeText(firstImportmapScript, importmapAsText)
|
|
360
|
+
if (moduleOutFormat === "systemjs") {
|
|
361
|
+
const typeAttribute = getHtmlNodeAttributeByName(
|
|
362
|
+
firstImportmapScript,
|
|
363
|
+
"type",
|
|
364
|
+
)
|
|
365
|
+
typeAttribute.value = "systemjs-importmap"
|
|
366
|
+
}
|
|
213
367
|
})
|
|
368
|
+
return
|
|
369
|
+
}
|
|
214
370
|
|
|
215
|
-
|
|
216
|
-
|
|
371
|
+
const visitScripts = async ({
|
|
372
|
+
logger,
|
|
373
|
+
projectDirectoryUrl,
|
|
374
|
+
compileServerOrigin,
|
|
375
|
+
jsenvRemoteDirectory,
|
|
376
|
+
url,
|
|
377
|
+
compiledUrl,
|
|
378
|
+
|
|
379
|
+
babelPluginMap,
|
|
380
|
+
moduleOutFormat,
|
|
381
|
+
importMetaFormat,
|
|
382
|
+
topLevelAwait,
|
|
383
|
+
sourcemapMethod,
|
|
384
|
+
|
|
385
|
+
scripts,
|
|
386
|
+
addHtmlSourceFile,
|
|
387
|
+
addHtmlAssetGenerator,
|
|
388
|
+
addHtmlMutation,
|
|
389
|
+
addHtmlDependency,
|
|
390
|
+
}) => {
|
|
217
391
|
scripts.forEach((script) => {
|
|
218
392
|
const typeAttribute = getHtmlNodeAttributeByName(script, "type")
|
|
393
|
+
const type = typeAttribute ? typeAttribute.value : "application/javascript"
|
|
219
394
|
const srcAttribute = getHtmlNodeAttributeByName(script, "src")
|
|
220
395
|
const src = srcAttribute ? srcAttribute.value : ""
|
|
221
|
-
|
|
222
|
-
if (typeAttribute && typeAttribute.value === "module" && src) {
|
|
223
|
-
if (moduleOutFormat === "systemjs") {
|
|
224
|
-
removeHtmlNodeAttribute(script, typeAttribute)
|
|
225
|
-
}
|
|
226
|
-
removeHtmlNodeAttribute(script, srcAttribute)
|
|
227
|
-
const jsenvMethod =
|
|
228
|
-
moduleOutFormat === "systemjs"
|
|
229
|
-
? "executeFileUsingSystemJs"
|
|
230
|
-
: "executeFileUsingDynamicImport"
|
|
231
|
-
setHtmlNodeText(
|
|
232
|
-
script,
|
|
233
|
-
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(src)})`,
|
|
234
|
-
)
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// inline module script
|
|
396
|
+
const integrityAttribute = getHtmlNodeAttributeByName(script, "integrity")
|
|
239
397
|
const textNode = getHtmlNodeTextNode(script)
|
|
240
|
-
if (
|
|
241
|
-
if (
|
|
242
|
-
|
|
398
|
+
if (type === "module") {
|
|
399
|
+
if (src) {
|
|
400
|
+
addHtmlMutation(() => {
|
|
401
|
+
if (moduleOutFormat === "systemjs") {
|
|
402
|
+
removeHtmlNodeAttribute(script, typeAttribute)
|
|
403
|
+
}
|
|
404
|
+
if (integrityAttribute) {
|
|
405
|
+
removeHtmlNodeAttribute(script, integrityAttribute)
|
|
406
|
+
}
|
|
407
|
+
removeHtmlNodeAttribute(script, srcAttribute)
|
|
408
|
+
const jsenvMethod =
|
|
409
|
+
moduleOutFormat === "systemjs"
|
|
410
|
+
? "executeFileUsingSystemJs"
|
|
411
|
+
: "executeFileUsingDynamicImport"
|
|
412
|
+
let specifier
|
|
413
|
+
if (
|
|
414
|
+
jsenvRemoteDirectory.isRemoteUrl(src) &&
|
|
415
|
+
!jsenvRemoteDirectory.isPreservedUrl(src)
|
|
416
|
+
) {
|
|
417
|
+
const fileUrl = jsenvRemoteDirectory.fileUrlFromRemoteUrl(src)
|
|
418
|
+
const fileUrlRelativeToHtml = urlToRelativeUrl(fileUrl, url)
|
|
419
|
+
specifier = `./${fileUrlRelativeToHtml}`
|
|
420
|
+
} else {
|
|
421
|
+
specifier = src
|
|
422
|
+
}
|
|
423
|
+
setHtmlNodeText(
|
|
424
|
+
script,
|
|
425
|
+
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
426
|
+
)
|
|
427
|
+
})
|
|
428
|
+
return
|
|
243
429
|
}
|
|
244
|
-
|
|
245
|
-
const
|
|
430
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
431
|
+
const inlineScriptName = `${scriptId}.js`
|
|
432
|
+
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
433
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
246
434
|
compiledUrl,
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
const specifier = `./${urlToRelativeUrl(scriptAssetUrl, compiledUrl)}`
|
|
250
|
-
inlineScriptsContentMap[specifier] = textNode.value
|
|
251
|
-
const jsenvMethod =
|
|
252
|
-
moduleOutFormat === "systemjs"
|
|
253
|
-
? "executeFileUsingSystemJs"
|
|
254
|
-
: "executeFileUsingDynamicImport"
|
|
255
|
-
setHtmlNodeText(
|
|
256
|
-
script,
|
|
257
|
-
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
435
|
+
inlineScriptName,
|
|
258
436
|
)
|
|
259
|
-
|
|
437
|
+
addHtmlAssetGenerator(async () => {
|
|
438
|
+
return transformHtmlScript({
|
|
439
|
+
projectDirectoryUrl,
|
|
440
|
+
jsenvRemoteDirectory,
|
|
441
|
+
url: scriptOriginalUrl,
|
|
442
|
+
compiledUrl: scriptCompiledUrl,
|
|
443
|
+
|
|
444
|
+
type: "module",
|
|
445
|
+
babelPluginMap,
|
|
446
|
+
moduleOutFormat,
|
|
447
|
+
importMetaFormat,
|
|
448
|
+
topLevelAwait,
|
|
449
|
+
|
|
450
|
+
sourcemapMethod,
|
|
451
|
+
code: textNode.value,
|
|
452
|
+
})
|
|
453
|
+
})
|
|
454
|
+
const specifier = `./${urlToRelativeUrl(scriptCompiledUrl, compiledUrl)}`
|
|
455
|
+
addHtmlMutation(() => {
|
|
456
|
+
if (moduleOutFormat === "systemjs") {
|
|
457
|
+
removeHtmlNodeAttribute(script, typeAttribute)
|
|
458
|
+
}
|
|
459
|
+
removeHtmlNodeAttribute(script, srcAttribute)
|
|
460
|
+
const jsenvMethod =
|
|
461
|
+
moduleOutFormat === "systemjs"
|
|
462
|
+
? "executeFileUsingSystemJs"
|
|
463
|
+
: "executeFileUsingDynamicImport"
|
|
464
|
+
setHtmlNodeText(
|
|
465
|
+
script,
|
|
466
|
+
`window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
|
|
467
|
+
)
|
|
468
|
+
})
|
|
469
|
+
addHtmlDependency({
|
|
260
470
|
htmlNode: script,
|
|
261
471
|
specifier,
|
|
262
472
|
})
|
|
263
473
|
return
|
|
264
474
|
}
|
|
265
|
-
|
|
266
|
-
|
|
475
|
+
if (type === "application/javascript" || type === "text/javascript") {
|
|
476
|
+
if (src) {
|
|
477
|
+
const htmlServerUrl = url.replace(
|
|
478
|
+
projectDirectoryUrl,
|
|
479
|
+
`${compileServerOrigin}/`,
|
|
480
|
+
)
|
|
481
|
+
const scriptOriginalServerUrl = resolveUrl(src, htmlServerUrl)
|
|
482
|
+
const scriptOriginalUrl = scriptOriginalServerUrl.replace(
|
|
483
|
+
`${compileServerOrigin}/`,
|
|
484
|
+
projectDirectoryUrl,
|
|
485
|
+
)
|
|
486
|
+
const fileIsInsideJsenvDistDirectory = urlIsInsideOf(
|
|
487
|
+
scriptOriginalUrl,
|
|
488
|
+
jsenvDistDirectoryUrl,
|
|
489
|
+
)
|
|
490
|
+
if (fileIsInsideJsenvDistDirectory) {
|
|
491
|
+
return
|
|
492
|
+
}
|
|
493
|
+
const isRemoteUrl = jsenvRemoteDirectory.isRemoteUrl(src)
|
|
494
|
+
if (isRemoteUrl && jsenvRemoteDirectory.isPreservedUrl(src)) {
|
|
495
|
+
return
|
|
496
|
+
}
|
|
497
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
498
|
+
compiledUrl,
|
|
499
|
+
urlToFilename(scriptOriginalUrl),
|
|
500
|
+
)
|
|
501
|
+
addHtmlAssetGenerator(async () => {
|
|
502
|
+
// we fetch scriptOriginalUrl on purpose because we do
|
|
503
|
+
// the transformation here and not in compile server
|
|
504
|
+
// (because compile server would think it's a module script
|
|
505
|
+
// and add things like systemjs)
|
|
506
|
+
// we could take into account the integrity her
|
|
507
|
+
const scriptResponse = await fetchUrl(scriptOriginalUrl)
|
|
508
|
+
if (scriptResponse.status !== 200) {
|
|
509
|
+
logger.warn(
|
|
510
|
+
createDetailedMessage(
|
|
511
|
+
scriptResponse.status === 404
|
|
512
|
+
? `script file cannot be found.`
|
|
513
|
+
: `script file unexpected response status (${scriptResponse.status}).`,
|
|
514
|
+
{
|
|
515
|
+
"script url": script.url,
|
|
516
|
+
"html url": url,
|
|
517
|
+
},
|
|
518
|
+
),
|
|
519
|
+
)
|
|
520
|
+
return []
|
|
521
|
+
}
|
|
522
|
+
const scriptAsText = await scriptResponse.text()
|
|
523
|
+
addHtmlSourceFile({
|
|
524
|
+
url: scriptOriginalUrl,
|
|
525
|
+
content: scriptAsText,
|
|
526
|
+
})
|
|
527
|
+
return transformHtmlScript({
|
|
528
|
+
projectDirectoryUrl,
|
|
529
|
+
jsenvRemoteDirectory,
|
|
530
|
+
url: scriptOriginalUrl,
|
|
531
|
+
compiledUrl: scriptCompiledUrl,
|
|
267
532
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const scriptBasename = urlToRelativeUrl(scriptAssetUrl, compiledUrl)
|
|
274
|
-
const scriptOriginalFileUrl = resolveUrl(scriptBasename, url)
|
|
275
|
-
const scriptCompiledFileUrl = resolveUrl(scriptBasename, compiledUrl)
|
|
533
|
+
type: "classic",
|
|
534
|
+
babelPluginMap,
|
|
535
|
+
moduleOutFormat,
|
|
536
|
+
importMetaFormat,
|
|
537
|
+
topLevelAwait,
|
|
276
538
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
539
|
+
sourcemapMethod,
|
|
540
|
+
code: scriptAsText,
|
|
541
|
+
})
|
|
542
|
+
})
|
|
543
|
+
addHtmlMutation(() => {
|
|
544
|
+
if (integrityAttribute) {
|
|
545
|
+
removeHtmlNodeAttribute(script, integrityAttribute)
|
|
546
|
+
}
|
|
547
|
+
srcAttribute.value = `./${urlToRelativeUrl(
|
|
548
|
+
scriptCompiledUrl,
|
|
549
|
+
compiledUrl,
|
|
550
|
+
)}`
|
|
551
|
+
})
|
|
552
|
+
return
|
|
553
|
+
}
|
|
554
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
555
|
+
const inlineScriptName = `${scriptId}.js`
|
|
556
|
+
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
557
|
+
const scriptCompiledUrl = generateCompilationAssetUrl(
|
|
558
|
+
compiledUrl,
|
|
559
|
+
inlineScriptName,
|
|
560
|
+
)
|
|
561
|
+
addHtmlAssetGenerator(async () => {
|
|
562
|
+
const htmlAssets = await transformHtmlScript({
|
|
284
563
|
projectDirectoryUrl,
|
|
564
|
+
jsenvRemoteDirectory,
|
|
565
|
+
url: scriptOriginalUrl,
|
|
566
|
+
compiledUrl: scriptCompiledUrl,
|
|
285
567
|
|
|
568
|
+
type: "classic",
|
|
286
569
|
babelPluginMap,
|
|
287
570
|
moduleOutFormat,
|
|
288
571
|
importMetaFormat,
|
|
289
572
|
topLevelAwait,
|
|
573
|
+
|
|
574
|
+
code: textNode.value,
|
|
575
|
+
sourcemapMethod,
|
|
290
576
|
})
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const code = scriptBeforeCompilation
|
|
301
|
-
assets = [...assets, scriptAssetUrl]
|
|
302
|
-
assetsContent = [...assetsContent, code]
|
|
303
|
-
return
|
|
304
|
-
}
|
|
305
|
-
throw e
|
|
306
|
-
}
|
|
307
|
-
const sourcemapFileUrl = resolveUrl(
|
|
308
|
-
`${scriptBasename}.map`,
|
|
309
|
-
scriptCompiledFileUrl,
|
|
310
|
-
)
|
|
577
|
+
addHtmlMutation(() => {
|
|
578
|
+
setHtmlNodeText(script, htmlAssets[0].content)
|
|
579
|
+
})
|
|
580
|
+
return htmlAssets
|
|
581
|
+
})
|
|
582
|
+
return
|
|
583
|
+
}
|
|
584
|
+
})
|
|
585
|
+
}
|
|
311
586
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
587
|
+
const transformHtmlScript = async ({
|
|
588
|
+
projectDirectoryUrl,
|
|
589
|
+
jsenvRemoteDirectory,
|
|
590
|
+
url,
|
|
591
|
+
compiledUrl,
|
|
317
592
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
code,
|
|
324
|
-
sourcemapFileRelativePathForModule,
|
|
325
|
-
)
|
|
326
|
-
assets = [...assets, scriptAssetUrl, sourcemapFileUrl]
|
|
327
|
-
assetsContent = [
|
|
328
|
-
...assetsContent,
|
|
329
|
-
code,
|
|
330
|
-
JSON.stringify(map, null, " "),
|
|
331
|
-
]
|
|
332
|
-
}
|
|
333
|
-
}),
|
|
334
|
-
)
|
|
335
|
-
sources.push(url)
|
|
336
|
-
sourcesContent.push(code)
|
|
593
|
+
type,
|
|
594
|
+
babelPluginMap,
|
|
595
|
+
moduleOutFormat,
|
|
596
|
+
importMetaFormat,
|
|
597
|
+
topLevelAwait,
|
|
337
598
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
599
|
+
code,
|
|
600
|
+
sourcemapMethod,
|
|
601
|
+
}) => {
|
|
602
|
+
let transformResult
|
|
603
|
+
try {
|
|
604
|
+
transformResult = await transformJs({
|
|
605
|
+
projectDirectoryUrl,
|
|
606
|
+
jsenvRemoteDirectory,
|
|
607
|
+
url,
|
|
608
|
+
compiledUrl,
|
|
609
|
+
|
|
610
|
+
babelPluginMap,
|
|
611
|
+
moduleOutFormat: type === "module" ? moduleOutFormat : "global",
|
|
612
|
+
importMetaFormat,
|
|
613
|
+
topLevelAwait: type === "module" ? topLevelAwait : false,
|
|
614
|
+
babelHelpersInjectionAsImport: type === "module" ? undefined : false,
|
|
615
|
+
|
|
616
|
+
code,
|
|
617
|
+
})
|
|
618
|
+
} catch (e) {
|
|
619
|
+
// If there is a syntax error in inline script
|
|
620
|
+
// we put the raw script without transformation.
|
|
621
|
+
// when systemjs will try to instantiate to script it
|
|
622
|
+
// will re-throw this syntax error.
|
|
623
|
+
// Thanks to this we see the syntax error in the
|
|
624
|
+
// document and livereloading still works
|
|
625
|
+
// because we gracefully handle this error
|
|
626
|
+
if (e.code === "PARSE_ERROR") {
|
|
627
|
+
return [{ url, content: code }]
|
|
628
|
+
}
|
|
629
|
+
throw e
|
|
348
630
|
}
|
|
631
|
+
|
|
632
|
+
code = transformResult.code
|
|
633
|
+
let map = transformResult.map
|
|
634
|
+
const sourcemapUrl = generateSourcemapUrl(compiledUrl)
|
|
635
|
+
if (sourcemapMethod === "inline") {
|
|
636
|
+
code = setJavaScriptSourceMappingUrl(code, sourcemapToBase64Url(map))
|
|
637
|
+
return [
|
|
638
|
+
{
|
|
639
|
+
url: compiledUrl,
|
|
640
|
+
content: code,
|
|
641
|
+
},
|
|
642
|
+
]
|
|
643
|
+
}
|
|
644
|
+
const sourcemapSpecifier = urlToRelativeUrl(sourcemapUrl, compiledUrl)
|
|
645
|
+
code = setJavaScriptSourceMappingUrl(code, sourcemapSpecifier)
|
|
646
|
+
return [
|
|
647
|
+
{
|
|
648
|
+
url: compiledUrl,
|
|
649
|
+
content: code,
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
url: sourcemapUrl,
|
|
653
|
+
content: JSON.stringify(map, null, " "),
|
|
654
|
+
},
|
|
655
|
+
]
|
|
349
656
|
}
|
|
350
657
|
|
|
351
|
-
|
|
352
|
-
const mutateRessourceHints = async (htmlAst) => {
|
|
658
|
+
const collectRessourceHints = (htmlAst) => {
|
|
353
659
|
const ressourceHints = []
|
|
354
660
|
visitHtmlAst(htmlAst, (htmlNode) => {
|
|
355
|
-
if (htmlNode.nodeName !== "link")
|
|
661
|
+
if (htmlNode.nodeName !== "link") {
|
|
662
|
+
return
|
|
663
|
+
}
|
|
356
664
|
const relAttribute = getHtmlNodeAttributeByName(htmlNode, "rel")
|
|
357
665
|
const rel = relAttribute ? relAttribute.value : ""
|
|
358
666
|
const isRessourceHint = [
|
|
@@ -362,44 +670,10 @@ const mutateRessourceHints = async (htmlAst) => {
|
|
|
362
670
|
"preload",
|
|
363
671
|
"modulepreload",
|
|
364
672
|
].includes(rel)
|
|
365
|
-
if (!isRessourceHint)
|
|
366
|
-
|
|
367
|
-
|
|
673
|
+
if (!isRessourceHint) {
|
|
674
|
+
return
|
|
675
|
+
}
|
|
676
|
+
ressourceHints.push(htmlNode)
|
|
368
677
|
})
|
|
369
|
-
|
|
370
|
-
const mutations = []
|
|
371
|
-
await Promise.all(
|
|
372
|
-
ressourceHints.map(async (ressourceHint) => {
|
|
373
|
-
const hrefAttribute = getHtmlNodeAttributeByName(
|
|
374
|
-
ressourceHint.htmlNode,
|
|
375
|
-
"href",
|
|
376
|
-
)
|
|
377
|
-
const href = hrefAttribute ? hrefAttribute.value : ""
|
|
378
|
-
if (!href) return
|
|
379
|
-
|
|
380
|
-
// - "modulepreload" -> "preload" because it's now regular js script
|
|
381
|
-
const asAttribute = getHtmlNodeAttributeByName(
|
|
382
|
-
ressourceHint.htmlNode,
|
|
383
|
-
"as",
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
if (ressourceHint.rel === "modulepreload") {
|
|
387
|
-
mutations.push(() => {
|
|
388
|
-
replaceHtmlNode(
|
|
389
|
-
ressourceHint.htmlNode,
|
|
390
|
-
`<link rel="preload" as="script" />`,
|
|
391
|
-
)
|
|
392
|
-
})
|
|
393
|
-
return
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (asAttribute && asAttribute.value === "script") {
|
|
397
|
-
mutations.push(() => {
|
|
398
|
-
replaceHtmlNode(ressourceHint.htmlNode, `<link as="script" />`)
|
|
399
|
-
})
|
|
400
|
-
return
|
|
401
|
-
}
|
|
402
|
-
}),
|
|
403
|
-
)
|
|
404
|
-
mutations.forEach((mutation) => mutation())
|
|
678
|
+
return ressourceHints
|
|
405
679
|
}
|