@jsenv/core 38.2.11 → 38.3.0
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/jsenv_core.js +1376 -1371
- package/package.json +1 -1
- package/src/dev/file_service.js +1 -1
- package/src/kitchen/url_graph/references.js +2 -2
- package/src/kitchen/url_graph/url_graph.js +14 -4
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +10 -2
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +493 -310
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +0 -205
package/dist/jsenv_core.js
CHANGED
|
@@ -13,7 +13,7 @@ import http from "node:http";
|
|
|
13
13
|
import { Readable, Stream, Writable } from "node:stream";
|
|
14
14
|
import { Http2ServerResponse } from "node:http2";
|
|
15
15
|
import { lookup } from "node:dns";
|
|
16
|
-
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtmlString, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn,
|
|
16
|
+
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtmlString, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getUrlForContentInsideHtml, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls, parseJsUrls, getUrlForContentInsideJs, analyzeLinkNode, findHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
|
|
17
17
|
import { sourcemapConverter, createMagicSource, composeTwoSourcemaps, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import { systemJsClientFileUrlDefault, convertJsModuleToJsClassic } from "@jsenv/js-module-fallback";
|
|
@@ -11814,12 +11814,12 @@ const createReference = ({
|
|
|
11814
11814
|
ownerUrlInfo.context.finalizeReference(reference);
|
|
11815
11815
|
};
|
|
11816
11816
|
|
|
11817
|
-
// "
|
|
11817
|
+
// "formatReference" can be async BUT this is an exception
|
|
11818
11818
|
// for most cases it will be sync. We want to favor the sync signature to keep things simpler
|
|
11819
11819
|
// The only case where it needs to be async is when
|
|
11820
11820
|
// the specifier is a `data:*` url
|
|
11821
11821
|
// in this case we'll wait for the promise returned by
|
|
11822
|
-
// "
|
|
11822
|
+
// "formatReference"
|
|
11823
11823
|
reference.readGeneratedSpecifier = () => {
|
|
11824
11824
|
if (reference.generatedSpecifier.then) {
|
|
11825
11825
|
return reference.generatedSpecifier.then((value) => {
|
|
@@ -12398,6 +12398,9 @@ const createUrlInfo = (url, context) => {
|
|
|
12398
12398
|
continue;
|
|
12399
12399
|
}
|
|
12400
12400
|
if (ref.gotInlined()) {
|
|
12401
|
+
if (ref.ownerUrlInfo.isUsed()) {
|
|
12402
|
+
return true;
|
|
12403
|
+
}
|
|
12401
12404
|
// the url info was inlined, an other reference is required
|
|
12402
12405
|
// to consider the non-inlined urlInfo as used
|
|
12403
12406
|
continue;
|
|
@@ -12497,7 +12500,7 @@ const createUrlInfo = (url, context) => {
|
|
|
12497
12500
|
};
|
|
12498
12501
|
urlInfo.onModified = ({ modifiedTimestamp = Date.now() } = {}) => {
|
|
12499
12502
|
const visitedSet = new Set();
|
|
12500
|
-
const
|
|
12503
|
+
const considerModified = (urlInfo) => {
|
|
12501
12504
|
if (visitedSet.has(urlInfo)) {
|
|
12502
12505
|
return;
|
|
12503
12506
|
}
|
|
@@ -12507,14 +12510,21 @@ const createUrlInfo = (url, context) => {
|
|
|
12507
12510
|
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
12508
12511
|
const referencedUrlInfo = referenceToOther.urlInfo;
|
|
12509
12512
|
if (referencedUrlInfo.isInline) {
|
|
12510
|
-
|
|
12513
|
+
considerModified(referencedUrlInfo);
|
|
12514
|
+
}
|
|
12515
|
+
}
|
|
12516
|
+
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
12517
|
+
if (referenceFromOther.gotInlined()) {
|
|
12518
|
+
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
12519
|
+
considerModified(urlInfoReferencingThisOne);
|
|
12511
12520
|
}
|
|
12512
12521
|
}
|
|
12513
12522
|
for (const searchParamVariant of urlInfo.searchParamVariantSet) {
|
|
12514
|
-
|
|
12523
|
+
considerModified(searchParamVariant);
|
|
12515
12524
|
}
|
|
12516
12525
|
};
|
|
12517
|
-
|
|
12526
|
+
considerModified(urlInfo);
|
|
12527
|
+
visitedSet.clear();
|
|
12518
12528
|
};
|
|
12519
12529
|
urlInfo.onDereferenced = (lastReferenceFromOther) => {
|
|
12520
12530
|
urlInfo.dereferencedTimestamp = Date.now();
|
|
@@ -15011,922 +15021,228 @@ const base64ToString = (base64String) =>
|
|
|
15011
15021
|
Buffer.from(base64String, "base64").toString("utf8");
|
|
15012
15022
|
const dataToBase64 = (data) => Buffer.from(data).toString("base64");
|
|
15013
15023
|
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
}) => {
|
|
15018
|
-
return {
|
|
15019
|
-
name: "jsenv:html_reference_analysis",
|
|
15020
|
-
appliesDuring: "*",
|
|
15021
|
-
transformUrlContent: {
|
|
15022
|
-
html: (urlInfo) =>
|
|
15023
|
-
parseAndTransformHtmlReferences(urlInfo, {
|
|
15024
|
-
inlineContent,
|
|
15025
|
-
inlineConvertedScript,
|
|
15026
|
-
}),
|
|
15027
|
-
},
|
|
15028
|
-
};
|
|
15029
|
-
};
|
|
15024
|
+
// duplicated from @jsenv/log to avoid the dependency
|
|
15025
|
+
const createDetailedMessage = (message, details = {}) => {
|
|
15026
|
+
let string = `${message}`;
|
|
15030
15027
|
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15028
|
+
Object.keys(details).forEach((key) => {
|
|
15029
|
+
const value = details[key];
|
|
15030
|
+
string += `
|
|
15031
|
+
--- ${key} ---
|
|
15032
|
+
${
|
|
15033
|
+
Array.isArray(value)
|
|
15034
|
+
? value.join(`
|
|
15035
|
+
`)
|
|
15036
|
+
: value
|
|
15037
|
+
}`;
|
|
15038
|
+
});
|
|
15037
15039
|
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
const finalizeCallbacks = [];
|
|
15040
|
+
return string
|
|
15041
|
+
};
|
|
15041
15042
|
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
|
|
15046
|
-
{ type, subtype, expectedType, ...rest },
|
|
15047
|
-
) => {
|
|
15048
|
-
let position;
|
|
15049
|
-
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
15050
|
-
// when generated from inline content,
|
|
15051
|
-
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
15052
|
-
position = getHtmlNodePosition(node);
|
|
15053
|
-
} else {
|
|
15054
|
-
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
15055
|
-
}
|
|
15056
|
-
const {
|
|
15057
|
-
line,
|
|
15058
|
-
column,
|
|
15059
|
-
// originalLine, originalColumn
|
|
15060
|
-
} = position;
|
|
15061
|
-
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15062
|
-
|
|
15063
|
-
const { crossorigin, integrity } = readFetchMetas(node);
|
|
15064
|
-
const isResourceHint = [
|
|
15065
|
-
"preconnect",
|
|
15066
|
-
"dns-prefetch",
|
|
15067
|
-
"prefetch",
|
|
15068
|
-
"preload",
|
|
15069
|
-
"modulepreload",
|
|
15070
|
-
].includes(subtype);
|
|
15071
|
-
let attributeLocation = node.sourceCodeLocation.attrs[attributeName];
|
|
15072
|
-
if (
|
|
15073
|
-
!attributeLocation &&
|
|
15074
|
-
attributeName === "href" &&
|
|
15075
|
-
(node.tagName === "use" || node.tagName === "image")
|
|
15076
|
-
) {
|
|
15077
|
-
attributeLocation = node.sourceCodeLocation.attrs["xlink:href"];
|
|
15078
|
-
}
|
|
15079
|
-
const attributeStart = attributeLocation.startOffset;
|
|
15080
|
-
const attributeValueStart = urlInfo.content.indexOf(
|
|
15081
|
-
attributeValue,
|
|
15082
|
-
attributeStart + `${attributeName}=`.length,
|
|
15083
|
-
);
|
|
15084
|
-
const attributeValueEnd = attributeValueStart + attributeValue.length;
|
|
15085
|
-
const reference = urlInfo.dependencies.found({
|
|
15086
|
-
type,
|
|
15087
|
-
subtype,
|
|
15088
|
-
expectedType,
|
|
15089
|
-
specifier: attributeValue,
|
|
15090
|
-
specifierLine: line,
|
|
15091
|
-
specifierColumn: column,
|
|
15092
|
-
specifierStart: attributeValueStart,
|
|
15093
|
-
specifierEnd: attributeValueEnd,
|
|
15094
|
-
isResourceHint,
|
|
15095
|
-
isWeak: isResourceHint,
|
|
15096
|
-
crossorigin,
|
|
15097
|
-
integrity,
|
|
15098
|
-
debug,
|
|
15099
|
-
astInfo: { node, attributeName },
|
|
15100
|
-
...rest,
|
|
15101
|
-
});
|
|
15102
|
-
actions.push(async () => {
|
|
15103
|
-
await reference.readGeneratedSpecifier();
|
|
15104
|
-
mutations.push(() => {
|
|
15105
|
-
setHtmlNodeAttributes(node, {
|
|
15106
|
-
[attributeName]: reference.generatedSpecifier,
|
|
15107
|
-
});
|
|
15108
|
-
});
|
|
15109
|
-
});
|
|
15110
|
-
return reference;
|
|
15111
|
-
};
|
|
15112
|
-
const visitHref = (node, referenceProps) => {
|
|
15113
|
-
const href = getHtmlNodeAttribute(node, "href");
|
|
15114
|
-
if (href) {
|
|
15115
|
-
return createExternalReference(node, "href", href, referenceProps);
|
|
15116
|
-
}
|
|
15117
|
-
return null;
|
|
15118
|
-
};
|
|
15119
|
-
const visitSrc = (node, referenceProps) => {
|
|
15120
|
-
const src = getHtmlNodeAttribute(node, "src");
|
|
15121
|
-
if (src) {
|
|
15122
|
-
return createExternalReference(node, "src", src, referenceProps);
|
|
15123
|
-
}
|
|
15124
|
-
return null;
|
|
15125
|
-
};
|
|
15126
|
-
const visitSrcset = (node, referenceProps) => {
|
|
15127
|
-
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
15128
|
-
if (srcset) {
|
|
15129
|
-
const srcCandidates = parseSrcSet(srcset);
|
|
15130
|
-
return srcCandidates.map((srcCandidate) => {
|
|
15131
|
-
return createExternalReference(
|
|
15132
|
-
node,
|
|
15133
|
-
"srcset",
|
|
15134
|
-
srcCandidate.specifier,
|
|
15135
|
-
referenceProps,
|
|
15136
|
-
);
|
|
15137
|
-
});
|
|
15138
|
-
}
|
|
15139
|
-
return null;
|
|
15140
|
-
};
|
|
15043
|
+
const assertImportMap = (value) => {
|
|
15044
|
+
if (value === null) {
|
|
15045
|
+
throw new TypeError(`an importMap must be an object, got null`)
|
|
15046
|
+
}
|
|
15141
15047
|
|
|
15142
|
-
const
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
) => {
|
|
15147
|
-
const hotAccept = getHtmlNodeAttribute(node, "hot-accept") !== undefined;
|
|
15148
|
-
const { line, column, isOriginal } = getHtmlNodePosition(node, {
|
|
15149
|
-
preferOriginal: true,
|
|
15150
|
-
});
|
|
15151
|
-
const inlineContentUrl = getUrlForContentInsideHtml(node, {
|
|
15152
|
-
htmlUrl: urlInfo.url,
|
|
15153
|
-
});
|
|
15154
|
-
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15155
|
-
const inlineReference = urlInfo.dependencies.foundInline({
|
|
15156
|
-
type,
|
|
15157
|
-
expectedType,
|
|
15158
|
-
isOriginalPosition: isOriginal,
|
|
15159
|
-
// we remove 1 to the line because imagine the following html:
|
|
15160
|
-
// <style>body { color: red; }</style>
|
|
15161
|
-
// -> content starts same line as <style> (same for <script>)
|
|
15162
|
-
specifierLine: line - 1,
|
|
15163
|
-
specifierColumn: column,
|
|
15164
|
-
specifier: inlineContentUrl,
|
|
15165
|
-
contentType,
|
|
15166
|
-
content: inlineContent,
|
|
15167
|
-
debug,
|
|
15168
|
-
astInfo: { node },
|
|
15169
|
-
});
|
|
15048
|
+
const type = typeof value;
|
|
15049
|
+
if (type !== "object") {
|
|
15050
|
+
throw new TypeError(`an importMap must be an object, received ${value}`)
|
|
15051
|
+
}
|
|
15170
15052
|
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
15178
|
-
});
|
|
15179
|
-
} else {
|
|
15180
|
-
setHtmlNodeText(node, inlineReference.urlInfo.content, {
|
|
15181
|
-
indentation: false, // indentation would decrease stack trace precision
|
|
15182
|
-
});
|
|
15183
|
-
setHtmlNodeAttributes(node, {
|
|
15184
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
15185
|
-
});
|
|
15186
|
-
}
|
|
15187
|
-
});
|
|
15188
|
-
});
|
|
15189
|
-
return inlineReference;
|
|
15190
|
-
};
|
|
15191
|
-
const visitTextContent = (
|
|
15192
|
-
node,
|
|
15193
|
-
{ type, subtype, expectedType, contentType },
|
|
15194
|
-
) => {
|
|
15195
|
-
const inlineContent = getHtmlNodeText(node);
|
|
15196
|
-
if (!inlineContent) {
|
|
15197
|
-
return null;
|
|
15198
|
-
}
|
|
15199
|
-
return createInlineReference(node, inlineContent, {
|
|
15200
|
-
type,
|
|
15201
|
-
subtype,
|
|
15202
|
-
expectedType,
|
|
15203
|
-
contentType,
|
|
15204
|
-
});
|
|
15205
|
-
};
|
|
15053
|
+
if (Array.isArray(value)) {
|
|
15054
|
+
throw new TypeError(
|
|
15055
|
+
`an importMap must be an object, received array ${value}`,
|
|
15056
|
+
)
|
|
15057
|
+
}
|
|
15058
|
+
};
|
|
15206
15059
|
|
|
15207
|
-
|
|
15208
|
-
|
|
15209
|
-
|
|
15210
|
-
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
15211
|
-
const ref = visitHref(linkNode, {
|
|
15212
|
-
type: "link_href",
|
|
15213
|
-
subtype: rel,
|
|
15214
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
15215
|
-
expectedContentType: type,
|
|
15216
|
-
});
|
|
15217
|
-
if (ref) {
|
|
15218
|
-
finalizeCallbacks.push(() => {
|
|
15219
|
-
if (ref.expectedType) ; else {
|
|
15220
|
-
ref.expectedType = decideLinkExpectedType(ref, urlInfo);
|
|
15221
|
-
}
|
|
15222
|
-
});
|
|
15223
|
-
}
|
|
15224
|
-
},
|
|
15225
|
-
style: inlineContent
|
|
15226
|
-
? (styleNode) => {
|
|
15227
|
-
visitTextContent(styleNode, {
|
|
15228
|
-
type: "style",
|
|
15229
|
-
expectedType: "css",
|
|
15230
|
-
contentType: "text/css",
|
|
15231
|
-
});
|
|
15232
|
-
}
|
|
15233
|
-
: null,
|
|
15234
|
-
script: (scriptNode) => {
|
|
15235
|
-
// during build the importmap is inlined
|
|
15236
|
-
// and shoud not be considered as a dependency anymore
|
|
15237
|
-
if (
|
|
15238
|
-
getHtmlNodeAttribute(scriptNode, "jsenv-inlined-by") ===
|
|
15239
|
-
"jsenv:importmap"
|
|
15240
|
-
) {
|
|
15241
|
-
return;
|
|
15242
|
-
}
|
|
15060
|
+
const hasScheme = (string) => {
|
|
15061
|
+
return /^[a-zA-Z]{2,}:/.test(string)
|
|
15062
|
+
};
|
|
15243
15063
|
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
const externalRef = visitSrc(scriptNode, {
|
|
15250
|
-
type: "script",
|
|
15251
|
-
subtype: type,
|
|
15252
|
-
expectedType: type,
|
|
15253
|
-
});
|
|
15254
|
-
if (externalRef) {
|
|
15255
|
-
return;
|
|
15256
|
-
}
|
|
15257
|
-
}
|
|
15064
|
+
const urlToScheme = (urlString) => {
|
|
15065
|
+
const colonIndex = urlString.indexOf(":");
|
|
15066
|
+
if (colonIndex === -1) return ""
|
|
15067
|
+
return urlString.slice(0, colonIndex)
|
|
15068
|
+
};
|
|
15258
15069
|
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
}
|
|
15263
|
-
// If the inline script was already handled by an other plugin, ignore it
|
|
15264
|
-
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
15265
|
-
// - we want to avoid cooking twice a script during build
|
|
15266
|
-
if (
|
|
15267
|
-
!inlineConvertedScript &&
|
|
15268
|
-
getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") ===
|
|
15269
|
-
"jsenv:js_module_fallback"
|
|
15270
|
-
) {
|
|
15271
|
-
return;
|
|
15272
|
-
}
|
|
15070
|
+
const urlToPathname = (urlString) => {
|
|
15071
|
+
return ressourceToPathname(urlToRessource(urlString))
|
|
15072
|
+
};
|
|
15273
15073
|
|
|
15274
|
-
|
|
15275
|
-
|
|
15276
|
-
subtype,
|
|
15277
|
-
expectedType: type,
|
|
15278
|
-
contentType,
|
|
15279
|
-
});
|
|
15280
|
-
if (inlineRef) {
|
|
15281
|
-
// 1. <script type="jsx"> becomes <script>
|
|
15282
|
-
if (type === "js_classic" && extension !== ".js") {
|
|
15283
|
-
mutations.push(() => {
|
|
15284
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
15285
|
-
type: undefined,
|
|
15286
|
-
});
|
|
15287
|
-
});
|
|
15288
|
-
}
|
|
15289
|
-
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
15290
|
-
if (type === "js_module" && extension !== ".js") {
|
|
15291
|
-
mutations.push(() => {
|
|
15292
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
15293
|
-
type: "module",
|
|
15294
|
-
});
|
|
15295
|
-
});
|
|
15296
|
-
}
|
|
15297
|
-
}
|
|
15298
|
-
},
|
|
15299
|
-
a: (aNode) => {
|
|
15300
|
-
visitHref(aNode, {
|
|
15301
|
-
type: "a_href",
|
|
15302
|
-
});
|
|
15303
|
-
},
|
|
15304
|
-
iframe: (iframeNode) => {
|
|
15305
|
-
visitSrc(iframeNode, {
|
|
15306
|
-
type: "iframe_src",
|
|
15307
|
-
});
|
|
15308
|
-
},
|
|
15309
|
-
img: (imgNode) => {
|
|
15310
|
-
visitSrc(imgNode, {
|
|
15311
|
-
type: "img_src",
|
|
15312
|
-
});
|
|
15313
|
-
visitSrcset(imgNode, {
|
|
15314
|
-
type: "img_srcset",
|
|
15315
|
-
});
|
|
15316
|
-
},
|
|
15317
|
-
source: (sourceNode) => {
|
|
15318
|
-
visitSrc(sourceNode, {
|
|
15319
|
-
type: "source_src",
|
|
15320
|
-
});
|
|
15321
|
-
visitSrcset(sourceNode, {
|
|
15322
|
-
type: "source_srcset",
|
|
15323
|
-
});
|
|
15324
|
-
},
|
|
15325
|
-
// svg <image> tag
|
|
15326
|
-
image: (imageNode) => {
|
|
15327
|
-
visitHref(imageNode, {
|
|
15328
|
-
type: "image_href",
|
|
15329
|
-
});
|
|
15330
|
-
},
|
|
15331
|
-
use: (useNode) => {
|
|
15332
|
-
visitHref(useNode, {
|
|
15333
|
-
type: "use_href",
|
|
15334
|
-
});
|
|
15335
|
-
},
|
|
15336
|
-
});
|
|
15337
|
-
finalizeCallbacks.forEach((finalizeCallback) => {
|
|
15338
|
-
finalizeCallback();
|
|
15339
|
-
});
|
|
15074
|
+
const urlToRessource = (urlString) => {
|
|
15075
|
+
const scheme = urlToScheme(urlString);
|
|
15340
15076
|
|
|
15341
|
-
if (
|
|
15342
|
-
|
|
15077
|
+
if (scheme === "file") {
|
|
15078
|
+
return urlString.slice("file://".length)
|
|
15343
15079
|
}
|
|
15344
|
-
|
|
15345
|
-
|
|
15080
|
+
|
|
15081
|
+
if (scheme === "https" || scheme === "http") {
|
|
15082
|
+
// remove origin
|
|
15083
|
+
const afterProtocol = urlString.slice(scheme.length + "://".length);
|
|
15084
|
+
const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
|
|
15085
|
+
return afterProtocol.slice(pathnameSlashIndex)
|
|
15346
15086
|
}
|
|
15347
|
-
|
|
15348
|
-
return
|
|
15087
|
+
|
|
15088
|
+
return urlString.slice(scheme.length + 1)
|
|
15349
15089
|
};
|
|
15350
15090
|
|
|
15351
|
-
const
|
|
15352
|
-
const
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
const crossorigin = getHtmlNodeAttribute(node, "crossorigin") !== undefined;
|
|
15357
|
-
meta.crossorigin = crossorigin;
|
|
15358
|
-
}
|
|
15359
|
-
if (integrityCompatibleTagNames.includes(node.nodeName)) {
|
|
15360
|
-
const integrity = getHtmlNodeAttribute(node, "integrity");
|
|
15361
|
-
meta.integrity = integrity;
|
|
15362
|
-
}
|
|
15363
|
-
return meta;
|
|
15091
|
+
const ressourceToPathname = (ressource) => {
|
|
15092
|
+
const searchSeparatorIndex = ressource.indexOf("?");
|
|
15093
|
+
return searchSeparatorIndex === -1
|
|
15094
|
+
? ressource
|
|
15095
|
+
: ressource.slice(0, searchSeparatorIndex)
|
|
15364
15096
|
};
|
|
15365
15097
|
|
|
15366
|
-
const
|
|
15367
|
-
const
|
|
15368
|
-
|
|
15369
|
-
|
|
15098
|
+
const urlToOrigin = (urlString) => {
|
|
15099
|
+
const scheme = urlToScheme(urlString);
|
|
15100
|
+
|
|
15101
|
+
if (scheme === "file") {
|
|
15102
|
+
return "file://"
|
|
15370
15103
|
}
|
|
15371
|
-
|
|
15372
|
-
|
|
15104
|
+
|
|
15105
|
+
if (scheme === "http" || scheme === "https") {
|
|
15106
|
+
const secondProtocolSlashIndex = scheme.length + "://".length;
|
|
15107
|
+
const pathnameSlashIndex = urlString.indexOf("/", secondProtocolSlashIndex);
|
|
15108
|
+
|
|
15109
|
+
if (pathnameSlashIndex === -1) return urlString
|
|
15110
|
+
return urlString.slice(0, pathnameSlashIndex)
|
|
15373
15111
|
}
|
|
15374
|
-
|
|
15375
|
-
|
|
15112
|
+
|
|
15113
|
+
return urlString.slice(0, scheme.length + 1)
|
|
15114
|
+
};
|
|
15115
|
+
|
|
15116
|
+
const pathnameToParentPathname = (pathname) => {
|
|
15117
|
+
const slashLastIndex = pathname.lastIndexOf("/");
|
|
15118
|
+
if (slashLastIndex === -1) {
|
|
15119
|
+
return "/"
|
|
15376
15120
|
}
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15121
|
+
|
|
15122
|
+
return pathname.slice(0, slashLastIndex + 1)
|
|
15123
|
+
};
|
|
15124
|
+
|
|
15125
|
+
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
|
|
15126
|
+
|
|
15127
|
+
|
|
15128
|
+
const resolveUrl = (specifier, baseUrl) => {
|
|
15129
|
+
if (baseUrl) {
|
|
15130
|
+
if (typeof baseUrl !== "string") {
|
|
15131
|
+
throw new TypeError(writeBaseUrlMustBeAString({ baseUrl, specifier }))
|
|
15382
15132
|
}
|
|
15383
|
-
if (
|
|
15384
|
-
|
|
15385
|
-
}
|
|
15386
|
-
if (as === "script") {
|
|
15387
|
-
for (const referenceToOther of htmlUrlInfo.referenceToOthersSet) {
|
|
15388
|
-
if (referenceToOther.url !== linkReference.url) {
|
|
15389
|
-
continue;
|
|
15390
|
-
}
|
|
15391
|
-
if (referenceToOther.type !== "script") {
|
|
15392
|
-
continue;
|
|
15393
|
-
}
|
|
15394
|
-
return referenceToOther.expectedType;
|
|
15395
|
-
}
|
|
15396
|
-
return undefined;
|
|
15133
|
+
if (!hasScheme(baseUrl)) {
|
|
15134
|
+
throw new Error(writeBaseUrlMustBeAbsolute({ baseUrl, specifier }))
|
|
15397
15135
|
}
|
|
15398
15136
|
}
|
|
15399
|
-
return undefined;
|
|
15400
|
-
};
|
|
15401
15137
|
|
|
15402
|
-
|
|
15403
|
-
|
|
15404
|
-
|
|
15405
|
-
// }
|
|
15406
|
-
// return new URL(url, baseUrl).href;
|
|
15407
|
-
// };
|
|
15138
|
+
if (hasScheme(specifier)) {
|
|
15139
|
+
return specifier
|
|
15140
|
+
}
|
|
15408
15141
|
|
|
15409
|
-
|
|
15142
|
+
if (!baseUrl) {
|
|
15143
|
+
throw new Error(writeBaseUrlRequired({ baseUrl, specifier }))
|
|
15144
|
+
}
|
|
15410
15145
|
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
transformUrlContent: {
|
|
15416
|
-
webmanifest: parseAndTransformWebmanifestUrls,
|
|
15417
|
-
},
|
|
15418
|
-
};
|
|
15419
|
-
};
|
|
15146
|
+
// scheme relative
|
|
15147
|
+
if (specifier.slice(0, 2) === "//") {
|
|
15148
|
+
return `${urlToScheme(baseUrl)}:${specifier}`
|
|
15149
|
+
}
|
|
15420
15150
|
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
const { icons = [] } = manifest;
|
|
15426
|
-
icons.forEach((icon) => {
|
|
15427
|
-
const iconReference = urlInfo.dependencies.found({
|
|
15428
|
-
type: "webmanifest_icon_src",
|
|
15429
|
-
specifier: icon.src,
|
|
15430
|
-
});
|
|
15431
|
-
actions.push(async () => {
|
|
15432
|
-
await iconReference.readGeneratedSpecifier();
|
|
15433
|
-
icon.src = iconReference.generatedSpecifier;
|
|
15434
|
-
});
|
|
15435
|
-
});
|
|
15151
|
+
// origin relative
|
|
15152
|
+
if (specifier[0] === "/") {
|
|
15153
|
+
return `${urlToOrigin(baseUrl)}${specifier}`
|
|
15154
|
+
}
|
|
15436
15155
|
|
|
15437
|
-
|
|
15438
|
-
|
|
15156
|
+
const baseOrigin = urlToOrigin(baseUrl);
|
|
15157
|
+
const basePathname = urlToPathname(baseUrl);
|
|
15158
|
+
|
|
15159
|
+
if (specifier === ".") {
|
|
15160
|
+
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
15161
|
+
return `${baseOrigin}${baseDirectoryPathname}`
|
|
15439
15162
|
}
|
|
15440
|
-
await Promise.all(actions.map((action) => action()));
|
|
15441
|
-
return JSON.stringify(manifest, null, " ");
|
|
15442
|
-
};
|
|
15443
15163
|
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
|
|
15164
|
+
// pathname relative inside
|
|
15165
|
+
if (specifier.slice(0, 2) === "./") {
|
|
15166
|
+
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
15167
|
+
return `${baseOrigin}${baseDirectoryPathname}${specifier.slice(2)}`
|
|
15168
|
+
}
|
|
15447
15169
|
|
|
15170
|
+
// pathname relative outside
|
|
15171
|
+
if (specifier.slice(0, 3) === "../") {
|
|
15172
|
+
let unresolvedPathname = specifier;
|
|
15173
|
+
const importerFolders = basePathname.split("/");
|
|
15174
|
+
importerFolders.pop();
|
|
15448
15175
|
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
};
|
|
15176
|
+
while (unresolvedPathname.slice(0, 3) === "../") {
|
|
15177
|
+
unresolvedPathname = unresolvedPathname.slice(3);
|
|
15178
|
+
// when there is no folder left to resolved
|
|
15179
|
+
// we just ignore '../'
|
|
15180
|
+
if (importerFolders.length) {
|
|
15181
|
+
importerFolders.pop();
|
|
15182
|
+
}
|
|
15183
|
+
}
|
|
15458
15184
|
|
|
15459
|
-
const
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
});
|
|
15464
|
-
const actions = [];
|
|
15465
|
-
const magicSource = createMagicSource(urlInfo.content);
|
|
15466
|
-
for (const cssUrl of cssUrls) {
|
|
15467
|
-
const reference = urlInfo.dependencies.found({
|
|
15468
|
-
type: cssUrl.type,
|
|
15469
|
-
specifier: cssUrl.specifier,
|
|
15470
|
-
specifierStart: cssUrl.start,
|
|
15471
|
-
specifierEnd: cssUrl.end,
|
|
15472
|
-
specifierLine: cssUrl.line,
|
|
15473
|
-
specifierColumn: cssUrl.column,
|
|
15474
|
-
});
|
|
15475
|
-
actions.push(async () => {
|
|
15476
|
-
await reference.readGeneratedSpecifier();
|
|
15477
|
-
const replacement = reference.generatedSpecifier;
|
|
15478
|
-
magicSource.replace({
|
|
15479
|
-
start: cssUrl.start,
|
|
15480
|
-
end: cssUrl.end,
|
|
15481
|
-
replacement,
|
|
15482
|
-
});
|
|
15483
|
-
});
|
|
15185
|
+
const resolvedPathname = `${importerFolders.join(
|
|
15186
|
+
"/",
|
|
15187
|
+
)}/${unresolvedPathname}`;
|
|
15188
|
+
return `${baseOrigin}${resolvedPathname}`
|
|
15484
15189
|
}
|
|
15485
|
-
|
|
15486
|
-
|
|
15190
|
+
|
|
15191
|
+
// bare
|
|
15192
|
+
if (basePathname === "") {
|
|
15193
|
+
return `${baseOrigin}/${specifier}`
|
|
15487
15194
|
}
|
|
15488
|
-
|
|
15195
|
+
if (basePathname[basePathname.length] === "/") {
|
|
15196
|
+
return `${baseOrigin}${basePathname}${specifier}`
|
|
15197
|
+
}
|
|
15198
|
+
return `${baseOrigin}${pathnameToParentPathname(basePathname)}${specifier}`
|
|
15489
15199
|
};
|
|
15490
15200
|
|
|
15491
|
-
const
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15510
|
-
|
|
15511
|
-
|
|
15201
|
+
const writeBaseUrlMustBeAString = ({
|
|
15202
|
+
baseUrl,
|
|
15203
|
+
specifier,
|
|
15204
|
+
}) => `baseUrl must be a string.
|
|
15205
|
+
--- base url ---
|
|
15206
|
+
${baseUrl}
|
|
15207
|
+
--- specifier ---
|
|
15208
|
+
${specifier}`;
|
|
15209
|
+
|
|
15210
|
+
const writeBaseUrlMustBeAbsolute = ({
|
|
15211
|
+
baseUrl,
|
|
15212
|
+
specifier,
|
|
15213
|
+
}) => `baseUrl must be absolute.
|
|
15214
|
+
--- base url ---
|
|
15215
|
+
${baseUrl}
|
|
15216
|
+
--- specifier ---
|
|
15217
|
+
${specifier}`;
|
|
15218
|
+
|
|
15219
|
+
const writeBaseUrlRequired = ({
|
|
15220
|
+
baseUrl,
|
|
15221
|
+
specifier,
|
|
15222
|
+
}) => `baseUrl required to resolve relative specifier.
|
|
15223
|
+
--- base url ---
|
|
15224
|
+
${baseUrl}
|
|
15225
|
+
--- specifier ---
|
|
15226
|
+
${specifier}`;
|
|
15227
|
+
|
|
15228
|
+
const tryUrlResolution = (string, url) => {
|
|
15229
|
+
const result = resolveUrl(string, url);
|
|
15230
|
+
return hasScheme(result) ? result : null
|
|
15512
15231
|
};
|
|
15513
15232
|
|
|
15514
|
-
const
|
|
15515
|
-
|
|
15516
|
-
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15520
|
-
|
|
15521
|
-
|
|
15522
|
-
|
|
15233
|
+
const resolveSpecifier = (specifier, importer) => {
|
|
15234
|
+
if (
|
|
15235
|
+
specifier === "." ||
|
|
15236
|
+
specifier[0] === "/" ||
|
|
15237
|
+
specifier.startsWith("./") ||
|
|
15238
|
+
specifier.startsWith("../")
|
|
15239
|
+
) {
|
|
15240
|
+
return resolveUrl(specifier, importer)
|
|
15241
|
+
}
|
|
15523
15242
|
|
|
15524
|
-
|
|
15525
|
-
|
|
15526
|
-
|
|
15527
|
-
});
|
|
15528
|
-
let { quote } = inlineReferenceInfo;
|
|
15529
|
-
if (quote === "`" && !canUseTemplateLiterals) {
|
|
15530
|
-
// if quote is "`" and template literals are not supported
|
|
15531
|
-
// we'll use a regular string (single or double quote)
|
|
15532
|
-
// when rendering the string
|
|
15533
|
-
quote = JS_QUOTES.pickBest(inlineReferenceInfo.content);
|
|
15534
|
-
}
|
|
15535
|
-
const inlineReference = urlInfo.dependencies.foundInline({
|
|
15536
|
-
type: "js_inline_content",
|
|
15537
|
-
subtype: inlineReferenceInfo.type, // "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
15538
|
-
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
15539
|
-
specifierLine: inlineReferenceInfo.line,
|
|
15540
|
-
specifierColumn: inlineReferenceInfo.column,
|
|
15541
|
-
specifier: inlineUrl,
|
|
15542
|
-
contentType: inlineReferenceInfo.contentType,
|
|
15543
|
-
content: inlineReferenceInfo.content,
|
|
15544
|
-
});
|
|
15545
|
-
const inlineUrlInfo = inlineReference.urlInfo;
|
|
15546
|
-
inlineUrlInfo.jsQuote = quote;
|
|
15547
|
-
inlineReference.escape = (value) => {
|
|
15548
|
-
return JS_QUOTES.escapeSpecialChars(value.slice(1, -1), { quote });
|
|
15549
|
-
};
|
|
15550
|
-
|
|
15551
|
-
sequentialActions.push(async () => {
|
|
15552
|
-
await inlineUrlInfo.cook();
|
|
15553
|
-
const replacement = JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
15554
|
-
quote,
|
|
15555
|
-
});
|
|
15556
|
-
magicSource.replace({
|
|
15557
|
-
start: inlineReferenceInfo.start,
|
|
15558
|
-
end: inlineReferenceInfo.end,
|
|
15559
|
-
replacement,
|
|
15560
|
-
});
|
|
15561
|
-
});
|
|
15562
|
-
};
|
|
15563
|
-
const onExternalReference = (externalReferenceInfo) => {
|
|
15564
|
-
if (
|
|
15565
|
-
externalReferenceInfo.subtype === "import_static" ||
|
|
15566
|
-
externalReferenceInfo.subtype === "import_dynamic"
|
|
15567
|
-
) {
|
|
15568
|
-
urlInfo.data.usesImport = true;
|
|
15569
|
-
}
|
|
15570
|
-
if (
|
|
15571
|
-
isNodeJs &&
|
|
15572
|
-
externalReferenceInfo.type === "js_url" &&
|
|
15573
|
-
externalReferenceInfo.expectedSubtype === "worker" &&
|
|
15574
|
-
externalReferenceInfo.expectedType === "js_classic" &&
|
|
15575
|
-
// TODO: it's true also if closest package.json
|
|
15576
|
-
// is type: module
|
|
15577
|
-
urlToExtension$1(
|
|
15578
|
-
new URL(externalReferenceInfo.specifier, urlInfo.url).href,
|
|
15579
|
-
) === ".mjs"
|
|
15580
|
-
) {
|
|
15581
|
-
externalReferenceInfo.expectedType = "js_module";
|
|
15582
|
-
}
|
|
15583
|
-
const reference = urlInfo.dependencies.found({
|
|
15584
|
-
type: externalReferenceInfo.type,
|
|
15585
|
-
subtype: externalReferenceInfo.subtype,
|
|
15586
|
-
expectedType: externalReferenceInfo.expectedType,
|
|
15587
|
-
expectedSubtype: externalReferenceInfo.expectedSubtype || urlInfo.subtype,
|
|
15588
|
-
specifier: externalReferenceInfo.specifier,
|
|
15589
|
-
specifierStart: externalReferenceInfo.start,
|
|
15590
|
-
specifierEnd: externalReferenceInfo.end,
|
|
15591
|
-
specifierLine: externalReferenceInfo.line,
|
|
15592
|
-
specifierColumn: externalReferenceInfo.column,
|
|
15593
|
-
data: externalReferenceInfo.data,
|
|
15594
|
-
baseUrl: {
|
|
15595
|
-
"StringLiteral": externalReferenceInfo.baseUrl,
|
|
15596
|
-
"window.location": urlInfo.url,
|
|
15597
|
-
"window.origin": urlInfo.context.rootDirectoryUrl,
|
|
15598
|
-
"import.meta.url": urlInfo.url,
|
|
15599
|
-
"context.meta.url": urlInfo.url,
|
|
15600
|
-
"document.currentScript.src": urlInfo.url,
|
|
15601
|
-
}[externalReferenceInfo.baseUrlType],
|
|
15602
|
-
importAttributes: externalReferenceInfo.importAttributes,
|
|
15603
|
-
astInfo: externalReferenceInfo.astInfo,
|
|
15604
|
-
});
|
|
15605
|
-
parallelActions.push(async () => {
|
|
15606
|
-
await reference.readGeneratedSpecifier();
|
|
15607
|
-
const replacement = reference.generatedSpecifier;
|
|
15608
|
-
magicSource.replace({
|
|
15609
|
-
start: externalReferenceInfo.start,
|
|
15610
|
-
end: externalReferenceInfo.end,
|
|
15611
|
-
replacement,
|
|
15612
|
-
});
|
|
15613
|
-
if (reference.mutation) {
|
|
15614
|
-
reference.mutation(magicSource, urlInfo);
|
|
15615
|
-
}
|
|
15616
|
-
});
|
|
15617
|
-
};
|
|
15618
|
-
const jsReferenceInfos = parseJsUrls({
|
|
15619
|
-
js: urlInfo.content,
|
|
15620
|
-
url: urlInfo.originalUrl,
|
|
15621
|
-
ast: urlInfo.contentAst,
|
|
15622
|
-
isJsModule: urlInfo.type === "js_module",
|
|
15623
|
-
isWebWorker: isWebWorkerUrlInfo(urlInfo),
|
|
15624
|
-
inlineContent,
|
|
15625
|
-
isNodeJs,
|
|
15626
|
-
});
|
|
15627
|
-
for (const jsReferenceInfo of jsReferenceInfos) {
|
|
15628
|
-
if (jsReferenceInfo.isInline) {
|
|
15629
|
-
onInlineReference(jsReferenceInfo);
|
|
15630
|
-
} else {
|
|
15631
|
-
onExternalReference(jsReferenceInfo);
|
|
15632
|
-
}
|
|
15633
|
-
}
|
|
15634
|
-
if (parallelActions.length > 0) {
|
|
15635
|
-
await Promise.all(parallelActions.map((action) => action()));
|
|
15636
|
-
}
|
|
15637
|
-
if (sequentialActions.length > 0) {
|
|
15638
|
-
await sequentialActions.reduce(async (previous, action) => {
|
|
15639
|
-
await previous;
|
|
15640
|
-
await action();
|
|
15641
|
-
}, Promise.resolve());
|
|
15642
|
-
}
|
|
15643
|
-
|
|
15644
|
-
const { content, sourcemap } = magicSource.toContentAndSourcemap();
|
|
15645
|
-
return { content, sourcemap };
|
|
15646
|
-
};
|
|
15647
|
-
|
|
15648
|
-
const jsenvPluginReferenceAnalysis = ({
|
|
15649
|
-
inlineContent = true,
|
|
15650
|
-
inlineConvertedScript = false,
|
|
15651
|
-
fetchInlineUrls = true,
|
|
15652
|
-
}) => {
|
|
15653
|
-
return [
|
|
15654
|
-
jsenvPluginDirectoryReferenceAnalysis(),
|
|
15655
|
-
jsenvPluginHtmlReferenceAnalysis({
|
|
15656
|
-
inlineContent,
|
|
15657
|
-
inlineConvertedScript,
|
|
15658
|
-
}),
|
|
15659
|
-
jsenvPluginWebmanifestReferenceAnalysis(),
|
|
15660
|
-
jsenvPluginCssReferenceAnalysis(),
|
|
15661
|
-
jsenvPluginJsReferenceAnalysis({
|
|
15662
|
-
inlineContent,
|
|
15663
|
-
}),
|
|
15664
|
-
...(inlineContent ? [jsenvPluginDataUrlsAnalysis()] : []),
|
|
15665
|
-
...(inlineContent && fetchInlineUrls
|
|
15666
|
-
? [jsenvPluginInlineContentFetcher()]
|
|
15667
|
-
: []),
|
|
15668
|
-
jsenvPluginReferenceExpectedTypes(),
|
|
15669
|
-
];
|
|
15670
|
-
};
|
|
15671
|
-
|
|
15672
|
-
const jsenvPluginInlineContentFetcher = () => {
|
|
15673
|
-
return {
|
|
15674
|
-
name: "jsenv:inline_content_fetcher",
|
|
15675
|
-
appliesDuring: "*",
|
|
15676
|
-
fetchUrlContent: async (urlInfo) => {
|
|
15677
|
-
if (!urlInfo.isInline) {
|
|
15678
|
-
return null;
|
|
15679
|
-
}
|
|
15680
|
-
// - we must use last reference because
|
|
15681
|
-
// when updating the file, first reference is the previous version
|
|
15682
|
-
// - we cannot use urlInfo.lastReference because it can be the reference created by "http_request"
|
|
15683
|
-
let lastInlineReference;
|
|
15684
|
-
for (const reference of urlInfo.referenceFromOthersSet) {
|
|
15685
|
-
if (reference.isInline) {
|
|
15686
|
-
lastInlineReference = reference;
|
|
15687
|
-
}
|
|
15688
|
-
}
|
|
15689
|
-
const { prev } = lastInlineReference;
|
|
15690
|
-
if (prev && !prev.isInline) {
|
|
15691
|
-
// got inlined, cook original url
|
|
15692
|
-
if (lastInlineReference.content === undefined) {
|
|
15693
|
-
const originalUrlInfo = prev.urlInfo;
|
|
15694
|
-
await originalUrlInfo.cook();
|
|
15695
|
-
lastInlineReference.content = originalUrlInfo.content;
|
|
15696
|
-
lastInlineReference.contentType = originalUrlInfo.contentType;
|
|
15697
|
-
}
|
|
15698
|
-
}
|
|
15699
|
-
return {
|
|
15700
|
-
originalContent: urlInfo.originalContent,
|
|
15701
|
-
content: lastInlineReference.content,
|
|
15702
|
-
contentType: lastInlineReference.contentType,
|
|
15703
|
-
};
|
|
15704
|
-
},
|
|
15705
|
-
};
|
|
15706
|
-
};
|
|
15707
|
-
|
|
15708
|
-
// duplicated from @jsenv/log to avoid the dependency
|
|
15709
|
-
const createDetailedMessage = (message, details = {}) => {
|
|
15710
|
-
let string = `${message}`;
|
|
15711
|
-
|
|
15712
|
-
Object.keys(details).forEach((key) => {
|
|
15713
|
-
const value = details[key];
|
|
15714
|
-
string += `
|
|
15715
|
-
--- ${key} ---
|
|
15716
|
-
${
|
|
15717
|
-
Array.isArray(value)
|
|
15718
|
-
? value.join(`
|
|
15719
|
-
`)
|
|
15720
|
-
: value
|
|
15721
|
-
}`;
|
|
15722
|
-
});
|
|
15723
|
-
|
|
15724
|
-
return string
|
|
15725
|
-
};
|
|
15726
|
-
|
|
15727
|
-
const assertImportMap = (value) => {
|
|
15728
|
-
if (value === null) {
|
|
15729
|
-
throw new TypeError(`an importMap must be an object, got null`)
|
|
15730
|
-
}
|
|
15731
|
-
|
|
15732
|
-
const type = typeof value;
|
|
15733
|
-
if (type !== "object") {
|
|
15734
|
-
throw new TypeError(`an importMap must be an object, received ${value}`)
|
|
15735
|
-
}
|
|
15736
|
-
|
|
15737
|
-
if (Array.isArray(value)) {
|
|
15738
|
-
throw new TypeError(
|
|
15739
|
-
`an importMap must be an object, received array ${value}`,
|
|
15740
|
-
)
|
|
15741
|
-
}
|
|
15742
|
-
};
|
|
15743
|
-
|
|
15744
|
-
const hasScheme = (string) => {
|
|
15745
|
-
return /^[a-zA-Z]{2,}:/.test(string)
|
|
15746
|
-
};
|
|
15747
|
-
|
|
15748
|
-
const urlToScheme = (urlString) => {
|
|
15749
|
-
const colonIndex = urlString.indexOf(":");
|
|
15750
|
-
if (colonIndex === -1) return ""
|
|
15751
|
-
return urlString.slice(0, colonIndex)
|
|
15752
|
-
};
|
|
15753
|
-
|
|
15754
|
-
const urlToPathname = (urlString) => {
|
|
15755
|
-
return ressourceToPathname(urlToRessource(urlString))
|
|
15756
|
-
};
|
|
15757
|
-
|
|
15758
|
-
const urlToRessource = (urlString) => {
|
|
15759
|
-
const scheme = urlToScheme(urlString);
|
|
15760
|
-
|
|
15761
|
-
if (scheme === "file") {
|
|
15762
|
-
return urlString.slice("file://".length)
|
|
15763
|
-
}
|
|
15764
|
-
|
|
15765
|
-
if (scheme === "https" || scheme === "http") {
|
|
15766
|
-
// remove origin
|
|
15767
|
-
const afterProtocol = urlString.slice(scheme.length + "://".length);
|
|
15768
|
-
const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
|
|
15769
|
-
return afterProtocol.slice(pathnameSlashIndex)
|
|
15770
|
-
}
|
|
15771
|
-
|
|
15772
|
-
return urlString.slice(scheme.length + 1)
|
|
15773
|
-
};
|
|
15774
|
-
|
|
15775
|
-
const ressourceToPathname = (ressource) => {
|
|
15776
|
-
const searchSeparatorIndex = ressource.indexOf("?");
|
|
15777
|
-
return searchSeparatorIndex === -1
|
|
15778
|
-
? ressource
|
|
15779
|
-
: ressource.slice(0, searchSeparatorIndex)
|
|
15780
|
-
};
|
|
15781
|
-
|
|
15782
|
-
const urlToOrigin = (urlString) => {
|
|
15783
|
-
const scheme = urlToScheme(urlString);
|
|
15784
|
-
|
|
15785
|
-
if (scheme === "file") {
|
|
15786
|
-
return "file://"
|
|
15787
|
-
}
|
|
15788
|
-
|
|
15789
|
-
if (scheme === "http" || scheme === "https") {
|
|
15790
|
-
const secondProtocolSlashIndex = scheme.length + "://".length;
|
|
15791
|
-
const pathnameSlashIndex = urlString.indexOf("/", secondProtocolSlashIndex);
|
|
15792
|
-
|
|
15793
|
-
if (pathnameSlashIndex === -1) return urlString
|
|
15794
|
-
return urlString.slice(0, pathnameSlashIndex)
|
|
15795
|
-
}
|
|
15796
|
-
|
|
15797
|
-
return urlString.slice(0, scheme.length + 1)
|
|
15798
|
-
};
|
|
15799
|
-
|
|
15800
|
-
const pathnameToParentPathname = (pathname) => {
|
|
15801
|
-
const slashLastIndex = pathname.lastIndexOf("/");
|
|
15802
|
-
if (slashLastIndex === -1) {
|
|
15803
|
-
return "/"
|
|
15804
|
-
}
|
|
15805
|
-
|
|
15806
|
-
return pathname.slice(0, slashLastIndex + 1)
|
|
15807
|
-
};
|
|
15808
|
-
|
|
15809
|
-
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
const resolveUrl = (specifier, baseUrl) => {
|
|
15813
|
-
if (baseUrl) {
|
|
15814
|
-
if (typeof baseUrl !== "string") {
|
|
15815
|
-
throw new TypeError(writeBaseUrlMustBeAString({ baseUrl, specifier }))
|
|
15816
|
-
}
|
|
15817
|
-
if (!hasScheme(baseUrl)) {
|
|
15818
|
-
throw new Error(writeBaseUrlMustBeAbsolute({ baseUrl, specifier }))
|
|
15819
|
-
}
|
|
15820
|
-
}
|
|
15821
|
-
|
|
15822
|
-
if (hasScheme(specifier)) {
|
|
15823
|
-
return specifier
|
|
15824
|
-
}
|
|
15825
|
-
|
|
15826
|
-
if (!baseUrl) {
|
|
15827
|
-
throw new Error(writeBaseUrlRequired({ baseUrl, specifier }))
|
|
15828
|
-
}
|
|
15829
|
-
|
|
15830
|
-
// scheme relative
|
|
15831
|
-
if (specifier.slice(0, 2) === "//") {
|
|
15832
|
-
return `${urlToScheme(baseUrl)}:${specifier}`
|
|
15833
|
-
}
|
|
15834
|
-
|
|
15835
|
-
// origin relative
|
|
15836
|
-
if (specifier[0] === "/") {
|
|
15837
|
-
return `${urlToOrigin(baseUrl)}${specifier}`
|
|
15838
|
-
}
|
|
15839
|
-
|
|
15840
|
-
const baseOrigin = urlToOrigin(baseUrl);
|
|
15841
|
-
const basePathname = urlToPathname(baseUrl);
|
|
15842
|
-
|
|
15843
|
-
if (specifier === ".") {
|
|
15844
|
-
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
15845
|
-
return `${baseOrigin}${baseDirectoryPathname}`
|
|
15846
|
-
}
|
|
15847
|
-
|
|
15848
|
-
// pathname relative inside
|
|
15849
|
-
if (specifier.slice(0, 2) === "./") {
|
|
15850
|
-
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
15851
|
-
return `${baseOrigin}${baseDirectoryPathname}${specifier.slice(2)}`
|
|
15852
|
-
}
|
|
15853
|
-
|
|
15854
|
-
// pathname relative outside
|
|
15855
|
-
if (specifier.slice(0, 3) === "../") {
|
|
15856
|
-
let unresolvedPathname = specifier;
|
|
15857
|
-
const importerFolders = basePathname.split("/");
|
|
15858
|
-
importerFolders.pop();
|
|
15859
|
-
|
|
15860
|
-
while (unresolvedPathname.slice(0, 3) === "../") {
|
|
15861
|
-
unresolvedPathname = unresolvedPathname.slice(3);
|
|
15862
|
-
// when there is no folder left to resolved
|
|
15863
|
-
// we just ignore '../'
|
|
15864
|
-
if (importerFolders.length) {
|
|
15865
|
-
importerFolders.pop();
|
|
15866
|
-
}
|
|
15867
|
-
}
|
|
15868
|
-
|
|
15869
|
-
const resolvedPathname = `${importerFolders.join(
|
|
15870
|
-
"/",
|
|
15871
|
-
)}/${unresolvedPathname}`;
|
|
15872
|
-
return `${baseOrigin}${resolvedPathname}`
|
|
15873
|
-
}
|
|
15874
|
-
|
|
15875
|
-
// bare
|
|
15876
|
-
if (basePathname === "") {
|
|
15877
|
-
return `${baseOrigin}/${specifier}`
|
|
15878
|
-
}
|
|
15879
|
-
if (basePathname[basePathname.length] === "/") {
|
|
15880
|
-
return `${baseOrigin}${basePathname}${specifier}`
|
|
15881
|
-
}
|
|
15882
|
-
return `${baseOrigin}${pathnameToParentPathname(basePathname)}${specifier}`
|
|
15883
|
-
};
|
|
15884
|
-
|
|
15885
|
-
const writeBaseUrlMustBeAString = ({
|
|
15886
|
-
baseUrl,
|
|
15887
|
-
specifier,
|
|
15888
|
-
}) => `baseUrl must be a string.
|
|
15889
|
-
--- base url ---
|
|
15890
|
-
${baseUrl}
|
|
15891
|
-
--- specifier ---
|
|
15892
|
-
${specifier}`;
|
|
15893
|
-
|
|
15894
|
-
const writeBaseUrlMustBeAbsolute = ({
|
|
15895
|
-
baseUrl,
|
|
15896
|
-
specifier,
|
|
15897
|
-
}) => `baseUrl must be absolute.
|
|
15898
|
-
--- base url ---
|
|
15899
|
-
${baseUrl}
|
|
15900
|
-
--- specifier ---
|
|
15901
|
-
${specifier}`;
|
|
15902
|
-
|
|
15903
|
-
const writeBaseUrlRequired = ({
|
|
15904
|
-
baseUrl,
|
|
15905
|
-
specifier,
|
|
15906
|
-
}) => `baseUrl required to resolve relative specifier.
|
|
15907
|
-
--- base url ---
|
|
15908
|
-
${baseUrl}
|
|
15909
|
-
--- specifier ---
|
|
15910
|
-
${specifier}`;
|
|
15911
|
-
|
|
15912
|
-
const tryUrlResolution = (string, url) => {
|
|
15913
|
-
const result = resolveUrl(string, url);
|
|
15914
|
-
return hasScheme(result) ? result : null
|
|
15915
|
-
};
|
|
15916
|
-
|
|
15917
|
-
const resolveSpecifier = (specifier, importer) => {
|
|
15918
|
-
if (
|
|
15919
|
-
specifier === "." ||
|
|
15920
|
-
specifier[0] === "/" ||
|
|
15921
|
-
specifier.startsWith("./") ||
|
|
15922
|
-
specifier.startsWith("../")
|
|
15923
|
-
) {
|
|
15924
|
-
return resolveUrl(specifier, importer)
|
|
15925
|
-
}
|
|
15926
|
-
|
|
15927
|
-
if (hasScheme(specifier)) {
|
|
15928
|
-
return specifier
|
|
15929
|
-
}
|
|
15243
|
+
if (hasScheme(specifier)) {
|
|
15244
|
+
return specifier
|
|
15245
|
+
}
|
|
15930
15246
|
|
|
15931
15247
|
return null
|
|
15932
15248
|
};
|
|
@@ -16048,561 +15364,1243 @@ const applyMappings = (
|
|
|
16048
15364
|
const afterSpecifier = specifierNormalized.slice(
|
|
16049
15365
|
specifierCandidate.length,
|
|
16050
15366
|
);
|
|
16051
|
-
const addressFinal = tryUrlResolution(afterSpecifier, address);
|
|
16052
|
-
onImportMapping({
|
|
16053
|
-
scope,
|
|
16054
|
-
from: specifierCandidate,
|
|
16055
|
-
to: address,
|
|
16056
|
-
before: specifierNormalized,
|
|
16057
|
-
after: addressFinal,
|
|
16058
|
-
});
|
|
16059
|
-
return addressFinal
|
|
15367
|
+
const addressFinal = tryUrlResolution(afterSpecifier, address);
|
|
15368
|
+
onImportMapping({
|
|
15369
|
+
scope,
|
|
15370
|
+
from: specifierCandidate,
|
|
15371
|
+
to: address,
|
|
15372
|
+
before: specifierNormalized,
|
|
15373
|
+
after: addressFinal,
|
|
15374
|
+
});
|
|
15375
|
+
return addressFinal
|
|
15376
|
+
}
|
|
15377
|
+
}
|
|
15378
|
+
|
|
15379
|
+
return null
|
|
15380
|
+
};
|
|
15381
|
+
|
|
15382
|
+
const specifierIsPrefixOf = (specifierHref, href) => {
|
|
15383
|
+
return (
|
|
15384
|
+
specifierHref[specifierHref.length - 1] === "/" &&
|
|
15385
|
+
href.startsWith(specifierHref)
|
|
15386
|
+
)
|
|
15387
|
+
};
|
|
15388
|
+
|
|
15389
|
+
// https://github.com/systemjs/systemjs/blob/89391f92dfeac33919b0223bbf834a1f4eea5750/src/common.js#L136
|
|
15390
|
+
|
|
15391
|
+
const composeTwoImportMaps = (leftImportMap, rightImportMap) => {
|
|
15392
|
+
assertImportMap(leftImportMap);
|
|
15393
|
+
assertImportMap(rightImportMap);
|
|
15394
|
+
|
|
15395
|
+
const importMap = {};
|
|
15396
|
+
|
|
15397
|
+
const leftImports = leftImportMap.imports;
|
|
15398
|
+
const rightImports = rightImportMap.imports;
|
|
15399
|
+
const leftHasImports = Boolean(leftImports);
|
|
15400
|
+
const rightHasImports = Boolean(rightImports);
|
|
15401
|
+
if (leftHasImports && rightHasImports) {
|
|
15402
|
+
importMap.imports = composeTwoMappings(leftImports, rightImports);
|
|
15403
|
+
} else if (leftHasImports) {
|
|
15404
|
+
importMap.imports = { ...leftImports };
|
|
15405
|
+
} else if (rightHasImports) {
|
|
15406
|
+
importMap.imports = { ...rightImports };
|
|
15407
|
+
}
|
|
15408
|
+
|
|
15409
|
+
const leftScopes = leftImportMap.scopes;
|
|
15410
|
+
const rightScopes = rightImportMap.scopes;
|
|
15411
|
+
const leftHasScopes = Boolean(leftScopes);
|
|
15412
|
+
const rightHasScopes = Boolean(rightScopes);
|
|
15413
|
+
if (leftHasScopes && rightHasScopes) {
|
|
15414
|
+
importMap.scopes = composeTwoScopes(
|
|
15415
|
+
leftScopes,
|
|
15416
|
+
rightScopes,
|
|
15417
|
+
importMap.imports || {},
|
|
15418
|
+
);
|
|
15419
|
+
} else if (leftHasScopes) {
|
|
15420
|
+
importMap.scopes = { ...leftScopes };
|
|
15421
|
+
} else if (rightHasScopes) {
|
|
15422
|
+
importMap.scopes = { ...rightScopes };
|
|
15423
|
+
}
|
|
15424
|
+
|
|
15425
|
+
return importMap
|
|
15426
|
+
};
|
|
15427
|
+
|
|
15428
|
+
const composeTwoMappings = (leftMappings, rightMappings) => {
|
|
15429
|
+
const mappings = {};
|
|
15430
|
+
|
|
15431
|
+
Object.keys(leftMappings).forEach((leftSpecifier) => {
|
|
15432
|
+
if (objectHasKey(rightMappings, leftSpecifier)) {
|
|
15433
|
+
// will be overidden
|
|
15434
|
+
return
|
|
15435
|
+
}
|
|
15436
|
+
const leftAddress = leftMappings[leftSpecifier];
|
|
15437
|
+
const rightSpecifier = Object.keys(rightMappings).find((rightSpecifier) => {
|
|
15438
|
+
return compareAddressAndSpecifier(leftAddress, rightSpecifier)
|
|
15439
|
+
});
|
|
15440
|
+
mappings[leftSpecifier] = rightSpecifier
|
|
15441
|
+
? rightMappings[rightSpecifier]
|
|
15442
|
+
: leftAddress;
|
|
15443
|
+
});
|
|
15444
|
+
|
|
15445
|
+
Object.keys(rightMappings).forEach((rightSpecifier) => {
|
|
15446
|
+
mappings[rightSpecifier] = rightMappings[rightSpecifier];
|
|
15447
|
+
});
|
|
15448
|
+
|
|
15449
|
+
return mappings
|
|
15450
|
+
};
|
|
15451
|
+
|
|
15452
|
+
const objectHasKey = (object, key) =>
|
|
15453
|
+
Object.prototype.hasOwnProperty.call(object, key);
|
|
15454
|
+
|
|
15455
|
+
const compareAddressAndSpecifier = (address, specifier) => {
|
|
15456
|
+
const addressUrl = resolveUrl(address, "file:///");
|
|
15457
|
+
const specifierUrl = resolveUrl(specifier, "file:///");
|
|
15458
|
+
return addressUrl === specifierUrl
|
|
15459
|
+
};
|
|
15460
|
+
|
|
15461
|
+
const composeTwoScopes = (leftScopes, rightScopes, imports) => {
|
|
15462
|
+
const scopes = {};
|
|
15463
|
+
|
|
15464
|
+
Object.keys(leftScopes).forEach((leftScopeKey) => {
|
|
15465
|
+
if (objectHasKey(rightScopes, leftScopeKey)) {
|
|
15466
|
+
// will be merged
|
|
15467
|
+
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
15468
|
+
return
|
|
15469
|
+
}
|
|
15470
|
+
const topLevelSpecifier = Object.keys(imports).find(
|
|
15471
|
+
(topLevelSpecifierCandidate) => {
|
|
15472
|
+
return compareAddressAndSpecifier(
|
|
15473
|
+
leftScopeKey,
|
|
15474
|
+
topLevelSpecifierCandidate,
|
|
15475
|
+
)
|
|
15476
|
+
},
|
|
15477
|
+
);
|
|
15478
|
+
if (topLevelSpecifier) {
|
|
15479
|
+
scopes[imports[topLevelSpecifier]] = leftScopes[leftScopeKey];
|
|
15480
|
+
} else {
|
|
15481
|
+
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
15482
|
+
}
|
|
15483
|
+
});
|
|
15484
|
+
|
|
15485
|
+
Object.keys(rightScopes).forEach((rightScopeKey) => {
|
|
15486
|
+
if (objectHasKey(scopes, rightScopeKey)) {
|
|
15487
|
+
scopes[rightScopeKey] = composeTwoMappings(
|
|
15488
|
+
scopes[rightScopeKey],
|
|
15489
|
+
rightScopes[rightScopeKey],
|
|
15490
|
+
);
|
|
15491
|
+
} else {
|
|
15492
|
+
scopes[rightScopeKey] = {
|
|
15493
|
+
...rightScopes[rightScopeKey],
|
|
15494
|
+
};
|
|
15495
|
+
}
|
|
15496
|
+
});
|
|
15497
|
+
|
|
15498
|
+
return scopes
|
|
15499
|
+
};
|
|
15500
|
+
|
|
15501
|
+
const sortImports = (imports) => {
|
|
15502
|
+
const mappingsSorted = {};
|
|
15503
|
+
|
|
15504
|
+
Object.keys(imports)
|
|
15505
|
+
.sort(compareLengthOrLocaleCompare)
|
|
15506
|
+
.forEach((name) => {
|
|
15507
|
+
mappingsSorted[name] = imports[name];
|
|
15508
|
+
});
|
|
15509
|
+
|
|
15510
|
+
return mappingsSorted
|
|
15511
|
+
};
|
|
15512
|
+
|
|
15513
|
+
const sortScopes = (scopes) => {
|
|
15514
|
+
const scopesSorted = {};
|
|
15515
|
+
|
|
15516
|
+
Object.keys(scopes)
|
|
15517
|
+
.sort(compareLengthOrLocaleCompare)
|
|
15518
|
+
.forEach((scopeSpecifier) => {
|
|
15519
|
+
scopesSorted[scopeSpecifier] = sortImports(scopes[scopeSpecifier]);
|
|
15520
|
+
});
|
|
15521
|
+
|
|
15522
|
+
return scopesSorted
|
|
15523
|
+
};
|
|
15524
|
+
|
|
15525
|
+
const compareLengthOrLocaleCompare = (a, b) => {
|
|
15526
|
+
return b.length - a.length || a.localeCompare(b)
|
|
15527
|
+
};
|
|
15528
|
+
|
|
15529
|
+
const normalizeImportMap = (importMap, baseUrl) => {
|
|
15530
|
+
assertImportMap(importMap);
|
|
15531
|
+
|
|
15532
|
+
if (!isStringOrUrl(baseUrl)) {
|
|
15533
|
+
throw new TypeError(formulateBaseUrlMustBeStringOrUrl({ baseUrl }))
|
|
15534
|
+
}
|
|
15535
|
+
|
|
15536
|
+
const { imports, scopes } = importMap;
|
|
15537
|
+
|
|
15538
|
+
return {
|
|
15539
|
+
imports: imports ? normalizeMappings(imports, baseUrl) : undefined,
|
|
15540
|
+
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
|
|
15541
|
+
}
|
|
15542
|
+
};
|
|
15543
|
+
|
|
15544
|
+
const isStringOrUrl = (value) => {
|
|
15545
|
+
if (typeof value === "string") {
|
|
15546
|
+
return true
|
|
15547
|
+
}
|
|
15548
|
+
|
|
15549
|
+
if (typeof URL === "function" && value instanceof URL) {
|
|
15550
|
+
return true
|
|
15551
|
+
}
|
|
15552
|
+
|
|
15553
|
+
return false
|
|
15554
|
+
};
|
|
15555
|
+
|
|
15556
|
+
const normalizeMappings = (mappings, baseUrl) => {
|
|
15557
|
+
const mappingsNormalized = {};
|
|
15558
|
+
|
|
15559
|
+
Object.keys(mappings).forEach((specifier) => {
|
|
15560
|
+
const address = mappings[specifier];
|
|
15561
|
+
|
|
15562
|
+
if (typeof address !== "string") {
|
|
15563
|
+
console.warn(
|
|
15564
|
+
formulateAddressMustBeAString({
|
|
15565
|
+
address,
|
|
15566
|
+
specifier,
|
|
15567
|
+
}),
|
|
15568
|
+
);
|
|
15569
|
+
return
|
|
15570
|
+
}
|
|
15571
|
+
|
|
15572
|
+
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier;
|
|
15573
|
+
|
|
15574
|
+
const addressUrl = tryUrlResolution(address, baseUrl);
|
|
15575
|
+
if (addressUrl === null) {
|
|
15576
|
+
console.warn(
|
|
15577
|
+
formulateAdressResolutionFailed({
|
|
15578
|
+
address,
|
|
15579
|
+
baseUrl,
|
|
15580
|
+
specifier,
|
|
15581
|
+
}),
|
|
15582
|
+
);
|
|
15583
|
+
return
|
|
15584
|
+
}
|
|
15585
|
+
|
|
15586
|
+
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
|
|
15587
|
+
console.warn(
|
|
15588
|
+
formulateAddressUrlRequiresTrailingSlash({
|
|
15589
|
+
addressUrl,
|
|
15590
|
+
address,
|
|
15591
|
+
specifier,
|
|
15592
|
+
}),
|
|
15593
|
+
);
|
|
15594
|
+
return
|
|
16060
15595
|
}
|
|
16061
|
-
|
|
15596
|
+
mappingsNormalized[specifierResolved] = addressUrl;
|
|
15597
|
+
});
|
|
16062
15598
|
|
|
16063
|
-
return
|
|
15599
|
+
return sortImports(mappingsNormalized)
|
|
16064
15600
|
};
|
|
16065
15601
|
|
|
16066
|
-
const
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16070
|
-
|
|
15602
|
+
const normalizeScopes = (scopes, baseUrl) => {
|
|
15603
|
+
const scopesNormalized = {};
|
|
15604
|
+
|
|
15605
|
+
Object.keys(scopes).forEach((scopeSpecifier) => {
|
|
15606
|
+
const scopeMappings = scopes[scopeSpecifier];
|
|
15607
|
+
const scopeUrl = tryUrlResolution(scopeSpecifier, baseUrl);
|
|
15608
|
+
if (scopeUrl === null) {
|
|
15609
|
+
console.warn(
|
|
15610
|
+
formulateScopeResolutionFailed({
|
|
15611
|
+
scope: scopeSpecifier,
|
|
15612
|
+
baseUrl,
|
|
15613
|
+
}),
|
|
15614
|
+
);
|
|
15615
|
+
return
|
|
15616
|
+
}
|
|
15617
|
+
const scopeValueNormalized = normalizeMappings(scopeMappings, baseUrl);
|
|
15618
|
+
scopesNormalized[scopeUrl] = scopeValueNormalized;
|
|
15619
|
+
});
|
|
15620
|
+
|
|
15621
|
+
return sortScopes(scopesNormalized)
|
|
16071
15622
|
};
|
|
16072
15623
|
|
|
16073
|
-
|
|
15624
|
+
const formulateBaseUrlMustBeStringOrUrl = ({
|
|
15625
|
+
baseUrl,
|
|
15626
|
+
}) => `baseUrl must be a string or an url.
|
|
15627
|
+
--- base url ---
|
|
15628
|
+
${baseUrl}`;
|
|
16074
15629
|
|
|
16075
|
-
const
|
|
16076
|
-
|
|
16077
|
-
|
|
15630
|
+
const formulateAddressMustBeAString = ({
|
|
15631
|
+
specifier,
|
|
15632
|
+
address,
|
|
15633
|
+
}) => `Address must be a string.
|
|
15634
|
+
--- address ---
|
|
15635
|
+
${address}
|
|
15636
|
+
--- specifier ---
|
|
15637
|
+
${specifier}`;
|
|
16078
15638
|
|
|
16079
|
-
|
|
15639
|
+
const formulateAdressResolutionFailed = ({
|
|
15640
|
+
address,
|
|
15641
|
+
baseUrl,
|
|
15642
|
+
specifier,
|
|
15643
|
+
}) => `Address url resolution failed.
|
|
15644
|
+
--- address ---
|
|
15645
|
+
${address}
|
|
15646
|
+
--- base url ---
|
|
15647
|
+
${baseUrl}
|
|
15648
|
+
--- specifier ---
|
|
15649
|
+
${specifier}`;
|
|
16080
15650
|
|
|
16081
|
-
|
|
16082
|
-
|
|
16083
|
-
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
15651
|
+
const formulateAddressUrlRequiresTrailingSlash = ({
|
|
15652
|
+
addressURL,
|
|
15653
|
+
address,
|
|
15654
|
+
specifier,
|
|
15655
|
+
}) => `Address must end with /.
|
|
15656
|
+
--- address url ---
|
|
15657
|
+
${addressURL}
|
|
15658
|
+
--- address ---
|
|
15659
|
+
${address}
|
|
15660
|
+
--- specifier ---
|
|
15661
|
+
${specifier}`;
|
|
16092
15662
|
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
importMap.scopes = { ...rightScopes };
|
|
15663
|
+
const formulateScopeResolutionFailed = ({
|
|
15664
|
+
scope,
|
|
15665
|
+
baseUrl,
|
|
15666
|
+
}) => `Scope url resolution failed.
|
|
15667
|
+
--- scope ---
|
|
15668
|
+
${scope}
|
|
15669
|
+
--- base url ---
|
|
15670
|
+
${baseUrl}`;
|
|
15671
|
+
|
|
15672
|
+
const pathnameToExtension = (pathname) => {
|
|
15673
|
+
const slashLastIndex = pathname.lastIndexOf("/");
|
|
15674
|
+
if (slashLastIndex !== -1) {
|
|
15675
|
+
pathname = pathname.slice(slashLastIndex + 1);
|
|
16107
15676
|
}
|
|
16108
15677
|
|
|
16109
|
-
|
|
15678
|
+
const dotLastIndex = pathname.lastIndexOf(".");
|
|
15679
|
+
if (dotLastIndex === -1) return ""
|
|
15680
|
+
// if (dotLastIndex === pathname.length - 1) return ""
|
|
15681
|
+
return pathname.slice(dotLastIndex)
|
|
16110
15682
|
};
|
|
16111
15683
|
|
|
16112
|
-
const
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
15684
|
+
const resolveImport = ({
|
|
15685
|
+
specifier,
|
|
15686
|
+
importer,
|
|
15687
|
+
importMap,
|
|
15688
|
+
defaultExtension = false,
|
|
15689
|
+
createBareSpecifierError,
|
|
15690
|
+
onImportMapping = () => {},
|
|
15691
|
+
}) => {
|
|
15692
|
+
let url;
|
|
15693
|
+
if (importMap) {
|
|
15694
|
+
url = applyImportMap({
|
|
15695
|
+
importMap,
|
|
15696
|
+
specifier,
|
|
15697
|
+
importer,
|
|
15698
|
+
createBareSpecifierError,
|
|
15699
|
+
onImportMapping,
|
|
16123
15700
|
});
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
16127
|
-
});
|
|
15701
|
+
} else {
|
|
15702
|
+
url = resolveUrl(specifier, importer);
|
|
15703
|
+
}
|
|
16128
15704
|
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
}
|
|
15705
|
+
if (defaultExtension) {
|
|
15706
|
+
url = applyDefaultExtension({ url, importer, defaultExtension });
|
|
15707
|
+
}
|
|
16132
15708
|
|
|
16133
|
-
return
|
|
15709
|
+
return url
|
|
16134
15710
|
};
|
|
16135
15711
|
|
|
16136
|
-
const
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
const addressUrl = resolveUrl(address, "file:///");
|
|
16141
|
-
const specifierUrl = resolveUrl(specifier, "file:///");
|
|
16142
|
-
return addressUrl === specifierUrl
|
|
16143
|
-
};
|
|
15712
|
+
const applyDefaultExtension = ({ url, importer, defaultExtension }) => {
|
|
15713
|
+
if (urlToPathname(url).endsWith("/")) {
|
|
15714
|
+
return url
|
|
15715
|
+
}
|
|
16144
15716
|
|
|
16145
|
-
|
|
16146
|
-
|
|
15717
|
+
if (typeof defaultExtension === "string") {
|
|
15718
|
+
const extension = pathnameToExtension(url);
|
|
15719
|
+
if (extension === "") {
|
|
15720
|
+
return `${url}${defaultExtension}`
|
|
15721
|
+
}
|
|
15722
|
+
return url
|
|
15723
|
+
}
|
|
16147
15724
|
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
15725
|
+
if (defaultExtension === true) {
|
|
15726
|
+
const extension = pathnameToExtension(url);
|
|
15727
|
+
if (extension === "" && importer) {
|
|
15728
|
+
const importerPathname = urlToPathname(importer);
|
|
15729
|
+
const importerExtension = pathnameToExtension(importerPathname);
|
|
15730
|
+
return `${url}${importerExtension}`
|
|
16153
15731
|
}
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
15732
|
+
}
|
|
15733
|
+
|
|
15734
|
+
return url
|
|
15735
|
+
};
|
|
15736
|
+
|
|
15737
|
+
const jsenvPluginHtmlReferenceAnalysis = ({
|
|
15738
|
+
inlineContent,
|
|
15739
|
+
inlineConvertedScript,
|
|
15740
|
+
}) => {
|
|
15741
|
+
/*
|
|
15742
|
+
* About importmap found in HTML files:
|
|
15743
|
+
* - feeds importmap files to jsenv kitchen
|
|
15744
|
+
* - use importmap to resolve import (when there is one + fallback to other resolution mecanism)
|
|
15745
|
+
* - inline importmap with [src=""]
|
|
15746
|
+
*
|
|
15747
|
+
* A correct importmap resolution should scope importmap resolution per html file.
|
|
15748
|
+
* It would be doable by adding ?html_id to each js file in order to track
|
|
15749
|
+
* the html file importing it.
|
|
15750
|
+
* Considering it happens only when all the following conditions are met:
|
|
15751
|
+
* - 2+ html files are using an importmap
|
|
15752
|
+
* - the importmap used is not the same
|
|
15753
|
+
* - the importmap contain conflicting mappings
|
|
15754
|
+
* - these html files are both executed during the same scenario (dev, test, build)
|
|
15755
|
+
* And that it would be ugly to see ?html_id all over the place
|
|
15756
|
+
* -> The importmap resolution implemented here takes a shortcut and does the following:
|
|
15757
|
+
* - All importmap found are merged into a single one that is applied to every import specifiers
|
|
15758
|
+
*/
|
|
15759
|
+
|
|
15760
|
+
let globalImportmap = null;
|
|
15761
|
+
const importmaps = {};
|
|
15762
|
+
const onImportmapParsed = (htmlUrl, importmap) => {
|
|
15763
|
+
if (importmap) {
|
|
15764
|
+
importmaps[htmlUrl] = normalizeImportMap(importmap, htmlUrl);
|
|
16164
15765
|
} else {
|
|
16165
|
-
|
|
15766
|
+
importmaps[htmlUrl] = null;
|
|
16166
15767
|
}
|
|
16167
|
-
|
|
15768
|
+
globalImportmap = Object.keys(importmaps).reduce((previous, url) => {
|
|
15769
|
+
const importmap = importmaps[url];
|
|
15770
|
+
if (!previous) {
|
|
15771
|
+
return importmap;
|
|
15772
|
+
}
|
|
15773
|
+
if (!importmap) {
|
|
15774
|
+
return previous;
|
|
15775
|
+
}
|
|
15776
|
+
return composeTwoImportMaps(previous, importmap);
|
|
15777
|
+
}, null);
|
|
15778
|
+
};
|
|
15779
|
+
|
|
15780
|
+
return {
|
|
15781
|
+
name: "jsenv:html_reference_analysis",
|
|
15782
|
+
appliesDuring: "*",
|
|
15783
|
+
resolveReference: {
|
|
15784
|
+
js_import: (reference) => {
|
|
15785
|
+
if (!globalImportmap) {
|
|
15786
|
+
return null;
|
|
15787
|
+
}
|
|
15788
|
+
try {
|
|
15789
|
+
let fromMapping = false;
|
|
15790
|
+
const result = resolveImport({
|
|
15791
|
+
specifier: reference.specifier,
|
|
15792
|
+
importer: reference.ownerUrlInfo.url,
|
|
15793
|
+
importMap: globalImportmap,
|
|
15794
|
+
onImportMapping: () => {
|
|
15795
|
+
fromMapping = true;
|
|
15796
|
+
},
|
|
15797
|
+
});
|
|
15798
|
+
if (fromMapping) {
|
|
15799
|
+
return result;
|
|
15800
|
+
}
|
|
15801
|
+
return null;
|
|
15802
|
+
} catch (e) {
|
|
15803
|
+
if (e.message.includes("bare specifier")) {
|
|
15804
|
+
// in theory we should throw to be compliant with web behaviour
|
|
15805
|
+
// but for now it's simpler to return null
|
|
15806
|
+
// and let a chance to other plugins to handle the bare specifier
|
|
15807
|
+
// (node esm resolution)
|
|
15808
|
+
// and we want importmap to be prio over node esm so we cannot put this plugin after
|
|
15809
|
+
return null;
|
|
15810
|
+
}
|
|
15811
|
+
throw e;
|
|
15812
|
+
}
|
|
15813
|
+
},
|
|
15814
|
+
},
|
|
15815
|
+
transformUrlContent: {
|
|
15816
|
+
html: async (urlInfo) => {
|
|
15817
|
+
let importmapFound = false;
|
|
15818
|
+
let importmapParsedCallbackSet = new Set();
|
|
15819
|
+
const onImportmapReady = (importmap) => {
|
|
15820
|
+
onImportmapParsed(urlInfo.url, importmap);
|
|
15821
|
+
importmapParsedCallbackSet.forEach((callback) => {
|
|
15822
|
+
callback();
|
|
15823
|
+
});
|
|
15824
|
+
importmapParsedCallbackSet.clear();
|
|
15825
|
+
};
|
|
16168
15826
|
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
scopes[rightScopeKey] = composeTwoMappings(
|
|
16172
|
-
scopes[rightScopeKey],
|
|
16173
|
-
rightScopes[rightScopeKey],
|
|
16174
|
-
);
|
|
16175
|
-
} else {
|
|
16176
|
-
scopes[rightScopeKey] = {
|
|
16177
|
-
...rightScopes[rightScopeKey],
|
|
16178
|
-
};
|
|
16179
|
-
}
|
|
16180
|
-
});
|
|
15827
|
+
const content = urlInfo.content;
|
|
15828
|
+
const htmlAst = parseHtmlString(content);
|
|
16181
15829
|
|
|
16182
|
-
|
|
16183
|
-
|
|
15830
|
+
const mutations = [];
|
|
15831
|
+
const actions = [];
|
|
15832
|
+
const finalizeCallbacks = [];
|
|
16184
15833
|
|
|
16185
|
-
const
|
|
16186
|
-
|
|
15834
|
+
const createExternalReference = (
|
|
15835
|
+
node,
|
|
15836
|
+
attributeName,
|
|
15837
|
+
attributeValue,
|
|
15838
|
+
{ type, subtype, expectedType, ...rest },
|
|
15839
|
+
) => {
|
|
15840
|
+
let position;
|
|
15841
|
+
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
15842
|
+
// when generated from inline content,
|
|
15843
|
+
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
15844
|
+
position = getHtmlNodePosition(node);
|
|
15845
|
+
} else {
|
|
15846
|
+
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
15847
|
+
}
|
|
15848
|
+
const {
|
|
15849
|
+
line,
|
|
15850
|
+
column,
|
|
15851
|
+
// originalLine, originalColumn
|
|
15852
|
+
} = position;
|
|
15853
|
+
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15854
|
+
|
|
15855
|
+
const { crossorigin, integrity } = readFetchMetas(node);
|
|
15856
|
+
const isResourceHint = [
|
|
15857
|
+
"preconnect",
|
|
15858
|
+
"dns-prefetch",
|
|
15859
|
+
"prefetch",
|
|
15860
|
+
"preload",
|
|
15861
|
+
"modulepreload",
|
|
15862
|
+
].includes(subtype);
|
|
15863
|
+
let attributeLocation = node.sourceCodeLocation.attrs[attributeName];
|
|
15864
|
+
if (
|
|
15865
|
+
!attributeLocation &&
|
|
15866
|
+
attributeName === "href" &&
|
|
15867
|
+
(node.tagName === "use" || node.tagName === "image")
|
|
15868
|
+
) {
|
|
15869
|
+
attributeLocation = node.sourceCodeLocation.attrs["xlink:href"];
|
|
15870
|
+
}
|
|
15871
|
+
const attributeStart = attributeLocation.startOffset;
|
|
15872
|
+
const attributeValueStart = urlInfo.content.indexOf(
|
|
15873
|
+
attributeValue,
|
|
15874
|
+
attributeStart + `${attributeName}=`.length,
|
|
15875
|
+
);
|
|
15876
|
+
const attributeValueEnd = attributeValueStart + attributeValue.length;
|
|
15877
|
+
const reference = urlInfo.dependencies.found({
|
|
15878
|
+
type,
|
|
15879
|
+
subtype,
|
|
15880
|
+
expectedType,
|
|
15881
|
+
specifier: attributeValue,
|
|
15882
|
+
specifierLine: line,
|
|
15883
|
+
specifierColumn: column,
|
|
15884
|
+
specifierStart: attributeValueStart,
|
|
15885
|
+
specifierEnd: attributeValueEnd,
|
|
15886
|
+
isResourceHint,
|
|
15887
|
+
isWeak: isResourceHint,
|
|
15888
|
+
crossorigin,
|
|
15889
|
+
integrity,
|
|
15890
|
+
debug,
|
|
15891
|
+
astInfo: { node, attributeName },
|
|
15892
|
+
...rest,
|
|
15893
|
+
});
|
|
15894
|
+
actions.push(async () => {
|
|
15895
|
+
await reference.readGeneratedSpecifier();
|
|
15896
|
+
mutations.push(() => {
|
|
15897
|
+
setHtmlNodeAttributes(node, {
|
|
15898
|
+
[attributeName]: reference.generatedSpecifier,
|
|
15899
|
+
});
|
|
15900
|
+
});
|
|
15901
|
+
});
|
|
15902
|
+
return reference;
|
|
15903
|
+
};
|
|
15904
|
+
const visitHref = (node, referenceProps) => {
|
|
15905
|
+
const href = getHtmlNodeAttribute(node, "href");
|
|
15906
|
+
if (href) {
|
|
15907
|
+
return createExternalReference(node, "href", href, referenceProps);
|
|
15908
|
+
}
|
|
15909
|
+
return null;
|
|
15910
|
+
};
|
|
15911
|
+
const visitSrc = (node, referenceProps) => {
|
|
15912
|
+
const src = getHtmlNodeAttribute(node, "src");
|
|
15913
|
+
if (src) {
|
|
15914
|
+
return createExternalReference(node, "src", src, referenceProps);
|
|
15915
|
+
}
|
|
15916
|
+
return null;
|
|
15917
|
+
};
|
|
15918
|
+
const visitSrcset = (node, referenceProps) => {
|
|
15919
|
+
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
15920
|
+
if (srcset) {
|
|
15921
|
+
const srcCandidates = parseSrcSet(srcset);
|
|
15922
|
+
return srcCandidates.map((srcCandidate) => {
|
|
15923
|
+
return createExternalReference(
|
|
15924
|
+
node,
|
|
15925
|
+
"srcset",
|
|
15926
|
+
srcCandidate.specifier,
|
|
15927
|
+
referenceProps,
|
|
15928
|
+
);
|
|
15929
|
+
});
|
|
15930
|
+
}
|
|
15931
|
+
return null;
|
|
15932
|
+
};
|
|
16187
15933
|
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
15934
|
+
const createInlineReference = (
|
|
15935
|
+
node,
|
|
15936
|
+
inlineContent,
|
|
15937
|
+
{ type, expectedType, contentType },
|
|
15938
|
+
) => {
|
|
15939
|
+
const hotAccept =
|
|
15940
|
+
getHtmlNodeAttribute(node, "hot-accept") !== undefined;
|
|
15941
|
+
const { line, column, isOriginal } = getHtmlNodePosition(node, {
|
|
15942
|
+
preferOriginal: true,
|
|
15943
|
+
});
|
|
15944
|
+
const inlineContentUrl = getUrlForContentInsideHtml(node, {
|
|
15945
|
+
htmlUrl: urlInfo.url,
|
|
15946
|
+
});
|
|
15947
|
+
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15948
|
+
const inlineReference = urlInfo.dependencies.foundInline({
|
|
15949
|
+
type,
|
|
15950
|
+
expectedType,
|
|
15951
|
+
isOriginalPosition: isOriginal,
|
|
15952
|
+
// we remove 1 to the line because imagine the following html:
|
|
15953
|
+
// <style>body { color: red; }</style>
|
|
15954
|
+
// -> content starts same line as <style> (same for <script>)
|
|
15955
|
+
specifierLine: line - 1,
|
|
15956
|
+
specifierColumn: column,
|
|
15957
|
+
specifier: inlineContentUrl,
|
|
15958
|
+
contentType,
|
|
15959
|
+
content: inlineContent,
|
|
15960
|
+
debug,
|
|
15961
|
+
astInfo: { node },
|
|
15962
|
+
});
|
|
16193
15963
|
|
|
16194
|
-
|
|
16195
|
-
|
|
15964
|
+
actions.push(async () => {
|
|
15965
|
+
if (expectedType === "js_module" && importmapFound) {
|
|
15966
|
+
await new Promise((resolve) => {
|
|
15967
|
+
importmapParsedCallbackSet.add(resolve);
|
|
15968
|
+
});
|
|
15969
|
+
}
|
|
15970
|
+
await inlineReference.urlInfo.cook();
|
|
15971
|
+
mutations.push(() => {
|
|
15972
|
+
if (hotAccept) {
|
|
15973
|
+
removeHtmlNodeText(node);
|
|
15974
|
+
setHtmlNodeAttributes(node, {
|
|
15975
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
15976
|
+
});
|
|
15977
|
+
} else {
|
|
15978
|
+
setHtmlNodeText(node, inlineReference.urlInfo.content, {
|
|
15979
|
+
indentation: false, // indentation would decrease stack trace precision
|
|
15980
|
+
});
|
|
15981
|
+
setHtmlNodeAttributes(node, {
|
|
15982
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
15983
|
+
});
|
|
15984
|
+
}
|
|
15985
|
+
});
|
|
15986
|
+
});
|
|
15987
|
+
return inlineReference;
|
|
15988
|
+
};
|
|
15989
|
+
const visitTextContent = (
|
|
15990
|
+
node,
|
|
15991
|
+
{ type, subtype, expectedType, contentType },
|
|
15992
|
+
) => {
|
|
15993
|
+
const inlineContent = getHtmlNodeText(node);
|
|
15994
|
+
if (!inlineContent) {
|
|
15995
|
+
return null;
|
|
15996
|
+
}
|
|
15997
|
+
return createInlineReference(node, inlineContent, {
|
|
15998
|
+
type,
|
|
15999
|
+
subtype,
|
|
16000
|
+
expectedType,
|
|
16001
|
+
contentType,
|
|
16002
|
+
});
|
|
16003
|
+
};
|
|
16196
16004
|
|
|
16197
|
-
|
|
16198
|
-
|
|
16005
|
+
visitHtmlNodes(htmlAst, {
|
|
16006
|
+
link: (linkNode) => {
|
|
16007
|
+
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
16008
|
+
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
16009
|
+
const ref = visitHref(linkNode, {
|
|
16010
|
+
type: "link_href",
|
|
16011
|
+
subtype: rel,
|
|
16012
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
16013
|
+
expectedContentType: type,
|
|
16014
|
+
});
|
|
16015
|
+
if (ref) {
|
|
16016
|
+
finalizeCallbacks.push(() => {
|
|
16017
|
+
if (ref.expectedType) ; else {
|
|
16018
|
+
ref.expectedType = decideLinkExpectedType(ref, urlInfo);
|
|
16019
|
+
}
|
|
16020
|
+
});
|
|
16021
|
+
}
|
|
16022
|
+
},
|
|
16023
|
+
style: inlineContent
|
|
16024
|
+
? (styleNode) => {
|
|
16025
|
+
visitTextContent(styleNode, {
|
|
16026
|
+
type: "style",
|
|
16027
|
+
expectedType: "css",
|
|
16028
|
+
contentType: "text/css",
|
|
16029
|
+
});
|
|
16030
|
+
}
|
|
16031
|
+
: null,
|
|
16032
|
+
script: (scriptNode) => {
|
|
16033
|
+
const { type, subtype, contentType, extension } =
|
|
16034
|
+
analyzeScriptNode(scriptNode);
|
|
16035
|
+
if (type === "text") {
|
|
16036
|
+
// ignore <script type="whatever">foobar</script>
|
|
16037
|
+
// per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
|
|
16038
|
+
return;
|
|
16039
|
+
}
|
|
16040
|
+
if (type === "importmap") {
|
|
16041
|
+
importmapFound = true;
|
|
16042
|
+
|
|
16043
|
+
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
16044
|
+
if (src) {
|
|
16045
|
+
// Browser would throw on remote importmap
|
|
16046
|
+
// and won't sent a request to the server for it
|
|
16047
|
+
// We must precook the importmap to know its content and inline it into the HTML
|
|
16048
|
+
const importmapReference = createExternalReference(
|
|
16049
|
+
scriptNode,
|
|
16050
|
+
"src",
|
|
16051
|
+
src,
|
|
16052
|
+
{
|
|
16053
|
+
type: "script",
|
|
16054
|
+
subtype: "importmap",
|
|
16055
|
+
expectedType: "importmap",
|
|
16056
|
+
},
|
|
16057
|
+
);
|
|
16058
|
+
const { line, column, isOriginal } = getHtmlNodePosition(
|
|
16059
|
+
scriptNode,
|
|
16060
|
+
{
|
|
16061
|
+
preferOriginal: true,
|
|
16062
|
+
},
|
|
16063
|
+
);
|
|
16064
|
+
const importmapInlineUrl = getUrlForContentInsideHtml(
|
|
16065
|
+
scriptNode,
|
|
16066
|
+
{
|
|
16067
|
+
htmlUrl: urlInfo.url,
|
|
16068
|
+
},
|
|
16069
|
+
);
|
|
16070
|
+
const importmapReferenceInlined = importmapReference.inline({
|
|
16071
|
+
line: line - 1,
|
|
16072
|
+
column,
|
|
16073
|
+
isOriginal,
|
|
16074
|
+
specifier: importmapInlineUrl,
|
|
16075
|
+
contentType: "application/importmap+json",
|
|
16076
|
+
});
|
|
16077
|
+
const importmapInlineUrlInfo =
|
|
16078
|
+
importmapReferenceInlined.urlInfo;
|
|
16079
|
+
actions.push(async () => {
|
|
16080
|
+
await importmapInlineUrlInfo.cook();
|
|
16081
|
+
onImportmapReady(JSON.parse(importmapInlineUrlInfo.content));
|
|
16082
|
+
mutations.push(() => {
|
|
16083
|
+
setHtmlNodeText(
|
|
16084
|
+
scriptNode,
|
|
16085
|
+
importmapInlineUrlInfo.content,
|
|
16086
|
+
{
|
|
16087
|
+
indentation: "auto",
|
|
16088
|
+
},
|
|
16089
|
+
);
|
|
16090
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16091
|
+
"src": undefined,
|
|
16092
|
+
"jsenv-inlined-by": "jsenv:html_reference_analysis",
|
|
16093
|
+
"inlined-from-src": src,
|
|
16094
|
+
});
|
|
16095
|
+
});
|
|
16096
|
+
});
|
|
16097
|
+
} else {
|
|
16098
|
+
const htmlNodeText = getHtmlNodeText(scriptNode);
|
|
16099
|
+
if (htmlNodeText) {
|
|
16100
|
+
const importmapReference = createInlineReference(
|
|
16101
|
+
scriptNode,
|
|
16102
|
+
htmlNodeText,
|
|
16103
|
+
{
|
|
16104
|
+
type: "script",
|
|
16105
|
+
expectedType: "importmap",
|
|
16106
|
+
contentType: "application/importmap+json",
|
|
16107
|
+
},
|
|
16108
|
+
);
|
|
16109
|
+
const inlineImportmapUrlInfo = importmapReference.urlInfo;
|
|
16110
|
+
actions.push(async () => {
|
|
16111
|
+
await inlineImportmapUrlInfo.cook();
|
|
16112
|
+
onImportmapReady(
|
|
16113
|
+
JSON.parse(inlineImportmapUrlInfo.content),
|
|
16114
|
+
);
|
|
16115
|
+
mutations.push(() => {
|
|
16116
|
+
setHtmlNodeText(
|
|
16117
|
+
scriptNode,
|
|
16118
|
+
inlineImportmapUrlInfo.content,
|
|
16119
|
+
{
|
|
16120
|
+
indentation: "auto",
|
|
16121
|
+
},
|
|
16122
|
+
);
|
|
16123
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16124
|
+
"jsenv-cooked-by": "jsenv:html_reference_analysis",
|
|
16125
|
+
});
|
|
16126
|
+
});
|
|
16127
|
+
});
|
|
16128
|
+
}
|
|
16129
|
+
}
|
|
16130
|
+
// once this plugin knows the importmap, it will use it
|
|
16131
|
+
// to map imports. These import specifiers will be normalized
|
|
16132
|
+
// by "formatReference" making the importmap presence useless.
|
|
16133
|
+
// In dev/test we keep importmap into the HTML to see it even if useless
|
|
16134
|
+
// Duing build we get rid of it
|
|
16135
|
+
if (urlInfo.context.build) {
|
|
16136
|
+
mutations.push(() => {
|
|
16137
|
+
removeHtmlNode(scriptNode);
|
|
16138
|
+
});
|
|
16139
|
+
}
|
|
16140
|
+
return;
|
|
16141
|
+
}
|
|
16142
|
+
const externalRef = visitSrc(scriptNode, {
|
|
16143
|
+
type: "script",
|
|
16144
|
+
subtype: type,
|
|
16145
|
+
expectedType: type,
|
|
16146
|
+
});
|
|
16147
|
+
if (externalRef) {
|
|
16148
|
+
return;
|
|
16149
|
+
}
|
|
16199
16150
|
|
|
16200
|
-
|
|
16201
|
-
|
|
16202
|
-
|
|
16203
|
-
|
|
16204
|
-
|
|
16151
|
+
// now visit the content, if any
|
|
16152
|
+
if (!inlineContent) {
|
|
16153
|
+
return;
|
|
16154
|
+
}
|
|
16155
|
+
// If the inline script was already handled by an other plugin, ignore it
|
|
16156
|
+
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
16157
|
+
// - we want to avoid cooking twice a script during build
|
|
16158
|
+
if (
|
|
16159
|
+
!inlineConvertedScript &&
|
|
16160
|
+
getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") ===
|
|
16161
|
+
"jsenv:js_module_fallback"
|
|
16162
|
+
) {
|
|
16163
|
+
return;
|
|
16164
|
+
}
|
|
16205
16165
|
|
|
16206
|
-
|
|
16207
|
-
|
|
16166
|
+
const inlineRef = visitTextContent(scriptNode, {
|
|
16167
|
+
type: "script",
|
|
16168
|
+
subtype,
|
|
16169
|
+
expectedType: type,
|
|
16170
|
+
contentType,
|
|
16171
|
+
});
|
|
16172
|
+
if (inlineRef) {
|
|
16173
|
+
// 1. <script type="jsx"> becomes <script>
|
|
16174
|
+
if (type === "js_classic" && extension !== ".js") {
|
|
16175
|
+
mutations.push(() => {
|
|
16176
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16177
|
+
type: undefined,
|
|
16178
|
+
});
|
|
16179
|
+
});
|
|
16180
|
+
}
|
|
16181
|
+
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
16182
|
+
if (type === "js_module" && extension !== ".js") {
|
|
16183
|
+
mutations.push(() => {
|
|
16184
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16185
|
+
type: "module",
|
|
16186
|
+
});
|
|
16187
|
+
});
|
|
16188
|
+
}
|
|
16189
|
+
}
|
|
16190
|
+
},
|
|
16191
|
+
a: (aNode) => {
|
|
16192
|
+
visitHref(aNode, {
|
|
16193
|
+
type: "a_href",
|
|
16194
|
+
});
|
|
16195
|
+
},
|
|
16196
|
+
iframe: (iframeNode) => {
|
|
16197
|
+
visitSrc(iframeNode, {
|
|
16198
|
+
type: "iframe_src",
|
|
16199
|
+
});
|
|
16200
|
+
},
|
|
16201
|
+
img: (imgNode) => {
|
|
16202
|
+
visitSrc(imgNode, {
|
|
16203
|
+
type: "img_src",
|
|
16204
|
+
});
|
|
16205
|
+
visitSrcset(imgNode, {
|
|
16206
|
+
type: "img_srcset",
|
|
16207
|
+
});
|
|
16208
|
+
},
|
|
16209
|
+
source: (sourceNode) => {
|
|
16210
|
+
visitSrc(sourceNode, {
|
|
16211
|
+
type: "source_src",
|
|
16212
|
+
});
|
|
16213
|
+
visitSrcset(sourceNode, {
|
|
16214
|
+
type: "source_srcset",
|
|
16215
|
+
});
|
|
16216
|
+
},
|
|
16217
|
+
// svg <image> tag
|
|
16218
|
+
image: (imageNode) => {
|
|
16219
|
+
visitHref(imageNode, {
|
|
16220
|
+
type: "image_href",
|
|
16221
|
+
});
|
|
16222
|
+
},
|
|
16223
|
+
use: (useNode) => {
|
|
16224
|
+
visitHref(useNode, {
|
|
16225
|
+
type: "use_href",
|
|
16226
|
+
});
|
|
16227
|
+
},
|
|
16228
|
+
});
|
|
16229
|
+
if (!importmapFound) {
|
|
16230
|
+
onImportmapReady();
|
|
16231
|
+
}
|
|
16232
|
+
finalizeCallbacks.forEach((finalizeCallback) => {
|
|
16233
|
+
finalizeCallback();
|
|
16234
|
+
});
|
|
16208
16235
|
|
|
16209
|
-
|
|
16210
|
-
|
|
16236
|
+
if (actions.length > 0) {
|
|
16237
|
+
await Promise.all(actions.map((action) => action()));
|
|
16238
|
+
actions.length = 0;
|
|
16239
|
+
}
|
|
16240
|
+
if (mutations.length === 0) {
|
|
16241
|
+
return null;
|
|
16242
|
+
}
|
|
16243
|
+
mutations.forEach((mutation) => mutation());
|
|
16244
|
+
mutations.length = 0;
|
|
16245
|
+
return stringifyHtmlAst(htmlAst);
|
|
16246
|
+
},
|
|
16247
|
+
},
|
|
16248
|
+
};
|
|
16211
16249
|
};
|
|
16212
16250
|
|
|
16213
|
-
const
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
|
|
16251
|
+
const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
|
|
16252
|
+
const integrityCompatibleTagNames = ["script", "link", "img", "source"];
|
|
16253
|
+
const readFetchMetas = (node) => {
|
|
16254
|
+
const meta = {};
|
|
16255
|
+
if (crossOriginCompatibleTagNames.includes(node.nodeName)) {
|
|
16256
|
+
const crossorigin = getHtmlNodeAttribute(node, "crossorigin") !== undefined;
|
|
16257
|
+
meta.crossorigin = crossorigin;
|
|
16218
16258
|
}
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
return {
|
|
16223
|
-
imports: imports ? normalizeMappings(imports, baseUrl) : undefined,
|
|
16224
|
-
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
|
|
16259
|
+
if (integrityCompatibleTagNames.includes(node.nodeName)) {
|
|
16260
|
+
const integrity = getHtmlNodeAttribute(node, "integrity");
|
|
16261
|
+
meta.integrity = integrity;
|
|
16225
16262
|
}
|
|
16263
|
+
return meta;
|
|
16226
16264
|
};
|
|
16227
16265
|
|
|
16228
|
-
const
|
|
16229
|
-
|
|
16230
|
-
|
|
16266
|
+
const decideLinkExpectedType = (linkReference, htmlUrlInfo) => {
|
|
16267
|
+
const rel = getHtmlNodeAttribute(linkReference.astInfo.node, "rel");
|
|
16268
|
+
if (rel === "webmanifest") {
|
|
16269
|
+
return "webmanifest";
|
|
16231
16270
|
}
|
|
16232
|
-
|
|
16233
|
-
|
|
16234
|
-
return true
|
|
16271
|
+
if (rel === "modulepreload") {
|
|
16272
|
+
return "js_module";
|
|
16235
16273
|
}
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
}
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
|
|
16243
|
-
|
|
16244
|
-
const address = mappings[specifier];
|
|
16245
|
-
|
|
16246
|
-
if (typeof address !== "string") {
|
|
16247
|
-
console.warn(
|
|
16248
|
-
formulateAddressMustBeAString({
|
|
16249
|
-
address,
|
|
16250
|
-
specifier,
|
|
16251
|
-
}),
|
|
16252
|
-
);
|
|
16253
|
-
return
|
|
16254
|
-
}
|
|
16255
|
-
|
|
16256
|
-
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier;
|
|
16257
|
-
|
|
16258
|
-
const addressUrl = tryUrlResolution(address, baseUrl);
|
|
16259
|
-
if (addressUrl === null) {
|
|
16260
|
-
console.warn(
|
|
16261
|
-
formulateAdressResolutionFailed({
|
|
16262
|
-
address,
|
|
16263
|
-
baseUrl,
|
|
16264
|
-
specifier,
|
|
16265
|
-
}),
|
|
16266
|
-
);
|
|
16267
|
-
return
|
|
16274
|
+
if (rel === "stylesheet") {
|
|
16275
|
+
return "css";
|
|
16276
|
+
}
|
|
16277
|
+
if (rel === "preload") {
|
|
16278
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#what_types_of_content_can_be_preloaded
|
|
16279
|
+
const as = getHtmlNodeAttribute(linkReference.astInfo.node, "as");
|
|
16280
|
+
if (as === "document") {
|
|
16281
|
+
return "html";
|
|
16268
16282
|
}
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
console.warn(
|
|
16272
|
-
formulateAddressUrlRequiresTrailingSlash({
|
|
16273
|
-
addressUrl,
|
|
16274
|
-
address,
|
|
16275
|
-
specifier,
|
|
16276
|
-
}),
|
|
16277
|
-
);
|
|
16278
|
-
return
|
|
16283
|
+
if (as === "style") {
|
|
16284
|
+
return "css";
|
|
16279
16285
|
}
|
|
16280
|
-
|
|
16281
|
-
|
|
16282
|
-
|
|
16283
|
-
|
|
16286
|
+
if (as === "script") {
|
|
16287
|
+
for (const referenceToOther of htmlUrlInfo.referenceToOthersSet) {
|
|
16288
|
+
if (referenceToOther.url !== linkReference.url) {
|
|
16289
|
+
continue;
|
|
16290
|
+
}
|
|
16291
|
+
if (referenceToOther.type !== "script") {
|
|
16292
|
+
continue;
|
|
16293
|
+
}
|
|
16294
|
+
return referenceToOther.expectedType;
|
|
16295
|
+
}
|
|
16296
|
+
return undefined;
|
|
16297
|
+
}
|
|
16298
|
+
}
|
|
16299
|
+
return undefined;
|
|
16284
16300
|
};
|
|
16285
16301
|
|
|
16286
|
-
const
|
|
16287
|
-
|
|
16302
|
+
// const applyWebUrlResolution = (url, baseUrl) => {
|
|
16303
|
+
// if (url[0] === "/") {
|
|
16304
|
+
// return new URL(url.slice(1), baseUrl).href;
|
|
16305
|
+
// }
|
|
16306
|
+
// return new URL(url, baseUrl).href;
|
|
16307
|
+
// };
|
|
16288
16308
|
|
|
16289
|
-
|
|
16290
|
-
const scopeMappings = scopes[scopeSpecifier];
|
|
16291
|
-
const scopeUrl = tryUrlResolution(scopeSpecifier, baseUrl);
|
|
16292
|
-
if (scopeUrl === null) {
|
|
16293
|
-
console.warn(
|
|
16294
|
-
formulateScopeResolutionFailed({
|
|
16295
|
-
scope: scopeSpecifier,
|
|
16296
|
-
baseUrl,
|
|
16297
|
-
}),
|
|
16298
|
-
);
|
|
16299
|
-
return
|
|
16300
|
-
}
|
|
16301
|
-
const scopeValueNormalized = normalizeMappings(scopeMappings, baseUrl);
|
|
16302
|
-
scopesNormalized[scopeUrl] = scopeValueNormalized;
|
|
16303
|
-
});
|
|
16309
|
+
// css: parseAndTransformCssUrls,
|
|
16304
16310
|
|
|
16305
|
-
|
|
16311
|
+
const jsenvPluginWebmanifestReferenceAnalysis = () => {
|
|
16312
|
+
return {
|
|
16313
|
+
name: "jsenv:webmanifest_reference_analysis",
|
|
16314
|
+
appliesDuring: "*",
|
|
16315
|
+
transformUrlContent: {
|
|
16316
|
+
webmanifest: parseAndTransformWebmanifestUrls,
|
|
16317
|
+
},
|
|
16318
|
+
};
|
|
16306
16319
|
};
|
|
16307
16320
|
|
|
16308
|
-
const
|
|
16309
|
-
|
|
16310
|
-
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
|
|
16314
|
-
const
|
|
16315
|
-
|
|
16316
|
-
|
|
16317
|
-
})
|
|
16318
|
-
|
|
16319
|
-
|
|
16320
|
-
|
|
16321
|
-
|
|
16322
|
-
|
|
16323
|
-
const formulateAdressResolutionFailed = ({
|
|
16324
|
-
address,
|
|
16325
|
-
baseUrl,
|
|
16326
|
-
specifier,
|
|
16327
|
-
}) => `Address url resolution failed.
|
|
16328
|
-
--- address ---
|
|
16329
|
-
${address}
|
|
16330
|
-
--- base url ---
|
|
16331
|
-
${baseUrl}
|
|
16332
|
-
--- specifier ---
|
|
16333
|
-
${specifier}`;
|
|
16321
|
+
const parseAndTransformWebmanifestUrls = async (urlInfo) => {
|
|
16322
|
+
const content = urlInfo.content;
|
|
16323
|
+
const manifest = JSON.parse(content);
|
|
16324
|
+
const actions = [];
|
|
16325
|
+
const { icons = [] } = manifest;
|
|
16326
|
+
icons.forEach((icon) => {
|
|
16327
|
+
const iconReference = urlInfo.dependencies.found({
|
|
16328
|
+
type: "webmanifest_icon_src",
|
|
16329
|
+
specifier: icon.src,
|
|
16330
|
+
});
|
|
16331
|
+
actions.push(async () => {
|
|
16332
|
+
await iconReference.readGeneratedSpecifier();
|
|
16333
|
+
icon.src = iconReference.generatedSpecifier;
|
|
16334
|
+
});
|
|
16335
|
+
});
|
|
16334
16336
|
|
|
16335
|
-
|
|
16336
|
-
|
|
16337
|
-
|
|
16338
|
-
|
|
16339
|
-
|
|
16340
|
-
|
|
16341
|
-
${addressURL}
|
|
16342
|
-
--- address ---
|
|
16343
|
-
${address}
|
|
16344
|
-
--- specifier ---
|
|
16345
|
-
${specifier}`;
|
|
16337
|
+
if (actions.length === 0) {
|
|
16338
|
+
return null;
|
|
16339
|
+
}
|
|
16340
|
+
await Promise.all(actions.map((action) => action()));
|
|
16341
|
+
return JSON.stringify(manifest, null, " ");
|
|
16342
|
+
};
|
|
16346
16343
|
|
|
16347
|
-
|
|
16348
|
-
|
|
16349
|
-
|
|
16350
|
-
}) => `Scope url resolution failed.
|
|
16351
|
-
--- scope ---
|
|
16352
|
-
${scope}
|
|
16353
|
-
--- base url ---
|
|
16354
|
-
${baseUrl}`;
|
|
16344
|
+
/*
|
|
16345
|
+
* https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/css/src/CSSTransformer.js
|
|
16346
|
+
*/
|
|
16355
16347
|
|
|
16356
|
-
const pathnameToExtension = (pathname) => {
|
|
16357
|
-
const slashLastIndex = pathname.lastIndexOf("/");
|
|
16358
|
-
if (slashLastIndex !== -1) {
|
|
16359
|
-
pathname = pathname.slice(slashLastIndex + 1);
|
|
16360
|
-
}
|
|
16361
16348
|
|
|
16362
|
-
|
|
16363
|
-
|
|
16364
|
-
|
|
16365
|
-
|
|
16349
|
+
const jsenvPluginCssReferenceAnalysis = () => {
|
|
16350
|
+
return {
|
|
16351
|
+
name: "jsenv:css_reference_analysis",
|
|
16352
|
+
appliesDuring: "*",
|
|
16353
|
+
transformUrlContent: {
|
|
16354
|
+
css: parseAndTransformCssUrls,
|
|
16355
|
+
},
|
|
16356
|
+
};
|
|
16366
16357
|
};
|
|
16367
16358
|
|
|
16368
|
-
const
|
|
16369
|
-
|
|
16370
|
-
|
|
16371
|
-
|
|
16372
|
-
|
|
16373
|
-
|
|
16374
|
-
|
|
16375
|
-
|
|
16376
|
-
|
|
16377
|
-
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16359
|
+
const parseAndTransformCssUrls = async (urlInfo) => {
|
|
16360
|
+
const cssUrls = await parseCssUrls({
|
|
16361
|
+
css: urlInfo.content,
|
|
16362
|
+
url: urlInfo.originalUrl,
|
|
16363
|
+
});
|
|
16364
|
+
const actions = [];
|
|
16365
|
+
const magicSource = createMagicSource(urlInfo.content);
|
|
16366
|
+
for (const cssUrl of cssUrls) {
|
|
16367
|
+
const reference = urlInfo.dependencies.found({
|
|
16368
|
+
type: cssUrl.type,
|
|
16369
|
+
specifier: cssUrl.specifier,
|
|
16370
|
+
specifierStart: cssUrl.start,
|
|
16371
|
+
specifierEnd: cssUrl.end,
|
|
16372
|
+
specifierLine: cssUrl.line,
|
|
16373
|
+
specifierColumn: cssUrl.column,
|
|
16374
|
+
});
|
|
16375
|
+
actions.push(async () => {
|
|
16376
|
+
await reference.readGeneratedSpecifier();
|
|
16377
|
+
const replacement = reference.generatedSpecifier;
|
|
16378
|
+
magicSource.replace({
|
|
16379
|
+
start: cssUrl.start,
|
|
16380
|
+
end: cssUrl.end,
|
|
16381
|
+
replacement,
|
|
16382
|
+
});
|
|
16384
16383
|
});
|
|
16385
|
-
} else {
|
|
16386
|
-
url = resolveUrl(specifier, importer);
|
|
16387
16384
|
}
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
url = applyDefaultExtension({ url, importer, defaultExtension });
|
|
16385
|
+
if (actions.length > 0) {
|
|
16386
|
+
await Promise.all(actions.map((action) => action()));
|
|
16391
16387
|
}
|
|
16388
|
+
return magicSource.toContentAndSourcemap();
|
|
16389
|
+
};
|
|
16392
16390
|
|
|
16393
|
-
|
|
16391
|
+
const jsenvPluginJsReferenceAnalysis = ({ inlineContent }) => {
|
|
16392
|
+
return [
|
|
16393
|
+
{
|
|
16394
|
+
name: "jsenv:js_reference_analysis",
|
|
16395
|
+
appliesDuring: "*",
|
|
16396
|
+
transformUrlContent: {
|
|
16397
|
+
js_classic: (urlInfo) =>
|
|
16398
|
+
parseAndTransformJsReferences(urlInfo, {
|
|
16399
|
+
inlineContent,
|
|
16400
|
+
canUseTemplateLiterals:
|
|
16401
|
+
urlInfo.context.isSupportedOnCurrentClients("template_literals"),
|
|
16402
|
+
}),
|
|
16403
|
+
js_module: (urlInfo) =>
|
|
16404
|
+
parseAndTransformJsReferences(urlInfo, {
|
|
16405
|
+
inlineContent,
|
|
16406
|
+
canUseTemplateLiterals:
|
|
16407
|
+
urlInfo.context.isSupportedOnCurrentClients("template_literals"),
|
|
16408
|
+
}),
|
|
16409
|
+
},
|
|
16410
|
+
},
|
|
16411
|
+
];
|
|
16394
16412
|
};
|
|
16395
16413
|
|
|
16396
|
-
const
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16414
|
+
const parseAndTransformJsReferences = async (
|
|
16415
|
+
urlInfo,
|
|
16416
|
+
{ inlineContent, canUseTemplateLiterals },
|
|
16417
|
+
) => {
|
|
16418
|
+
const magicSource = createMagicSource(urlInfo.content);
|
|
16419
|
+
const parallelActions = [];
|
|
16420
|
+
const sequentialActions = [];
|
|
16421
|
+
const isNodeJs =
|
|
16422
|
+
Object.keys(urlInfo.context.runtimeCompat).toString() === "node";
|
|
16423
|
+
|
|
16424
|
+
const onInlineReference = (inlineReferenceInfo) => {
|
|
16425
|
+
const inlineUrl = getUrlForContentInsideJs(inlineReferenceInfo, {
|
|
16426
|
+
url: urlInfo.url,
|
|
16427
|
+
});
|
|
16428
|
+
let { quote } = inlineReferenceInfo;
|
|
16429
|
+
if (quote === "`" && !canUseTemplateLiterals) {
|
|
16430
|
+
// if quote is "`" and template literals are not supported
|
|
16431
|
+
// we'll use a regular string (single or double quote)
|
|
16432
|
+
// when rendering the string
|
|
16433
|
+
quote = JS_QUOTES.pickBest(inlineReferenceInfo.content);
|
|
16434
|
+
}
|
|
16435
|
+
const inlineReference = urlInfo.dependencies.foundInline({
|
|
16436
|
+
type: "js_inline_content",
|
|
16437
|
+
subtype: inlineReferenceInfo.type, // "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
16438
|
+
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
16439
|
+
specifierLine: inlineReferenceInfo.line,
|
|
16440
|
+
specifierColumn: inlineReferenceInfo.column,
|
|
16441
|
+
specifier: inlineUrl,
|
|
16442
|
+
contentType: inlineReferenceInfo.contentType,
|
|
16443
|
+
content: inlineReferenceInfo.content,
|
|
16444
|
+
});
|
|
16445
|
+
const inlineUrlInfo = inlineReference.urlInfo;
|
|
16446
|
+
inlineUrlInfo.jsQuote = quote;
|
|
16447
|
+
inlineReference.escape = (value) => {
|
|
16448
|
+
return JS_QUOTES.escapeSpecialChars(value.slice(1, -1), { quote });
|
|
16449
|
+
};
|
|
16400
16450
|
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16451
|
+
sequentialActions.push(async () => {
|
|
16452
|
+
await inlineUrlInfo.cook();
|
|
16453
|
+
const replacement = JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
16454
|
+
quote,
|
|
16455
|
+
});
|
|
16456
|
+
magicSource.replace({
|
|
16457
|
+
start: inlineReferenceInfo.start,
|
|
16458
|
+
end: inlineReferenceInfo.end,
|
|
16459
|
+
replacement,
|
|
16460
|
+
});
|
|
16461
|
+
});
|
|
16462
|
+
};
|
|
16463
|
+
const onExternalReference = (externalReferenceInfo) => {
|
|
16464
|
+
if (
|
|
16465
|
+
externalReferenceInfo.subtype === "import_static" ||
|
|
16466
|
+
externalReferenceInfo.subtype === "import_dynamic"
|
|
16467
|
+
) {
|
|
16468
|
+
urlInfo.data.usesImport = true;
|
|
16405
16469
|
}
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16470
|
+
if (
|
|
16471
|
+
isNodeJs &&
|
|
16472
|
+
externalReferenceInfo.type === "js_url" &&
|
|
16473
|
+
externalReferenceInfo.expectedSubtype === "worker" &&
|
|
16474
|
+
externalReferenceInfo.expectedType === "js_classic" &&
|
|
16475
|
+
// TODO: it's true also if closest package.json
|
|
16476
|
+
// is type: module
|
|
16477
|
+
urlToExtension$1(
|
|
16478
|
+
new URL(externalReferenceInfo.specifier, urlInfo.url).href,
|
|
16479
|
+
) === ".mjs"
|
|
16480
|
+
) {
|
|
16481
|
+
externalReferenceInfo.expectedType = "js_module";
|
|
16482
|
+
}
|
|
16483
|
+
const reference = urlInfo.dependencies.found({
|
|
16484
|
+
type: externalReferenceInfo.type,
|
|
16485
|
+
subtype: externalReferenceInfo.subtype,
|
|
16486
|
+
expectedType: externalReferenceInfo.expectedType,
|
|
16487
|
+
expectedSubtype: externalReferenceInfo.expectedSubtype || urlInfo.subtype,
|
|
16488
|
+
specifier: externalReferenceInfo.specifier,
|
|
16489
|
+
specifierStart: externalReferenceInfo.start,
|
|
16490
|
+
specifierEnd: externalReferenceInfo.end,
|
|
16491
|
+
specifierLine: externalReferenceInfo.line,
|
|
16492
|
+
specifierColumn: externalReferenceInfo.column,
|
|
16493
|
+
data: externalReferenceInfo.data,
|
|
16494
|
+
baseUrl: {
|
|
16495
|
+
"StringLiteral": externalReferenceInfo.baseUrl,
|
|
16496
|
+
"window.location": urlInfo.url,
|
|
16497
|
+
"window.origin": urlInfo.context.rootDirectoryUrl,
|
|
16498
|
+
"import.meta.url": urlInfo.url,
|
|
16499
|
+
"context.meta.url": urlInfo.url,
|
|
16500
|
+
"document.currentScript.src": urlInfo.url,
|
|
16501
|
+
}[externalReferenceInfo.baseUrlType],
|
|
16502
|
+
importAttributes: externalReferenceInfo.importAttributes,
|
|
16503
|
+
astInfo: externalReferenceInfo.astInfo,
|
|
16504
|
+
});
|
|
16505
|
+
parallelActions.push(async () => {
|
|
16506
|
+
await reference.readGeneratedSpecifier();
|
|
16507
|
+
const replacement = reference.generatedSpecifier;
|
|
16508
|
+
magicSource.replace({
|
|
16509
|
+
start: externalReferenceInfo.start,
|
|
16510
|
+
end: externalReferenceInfo.end,
|
|
16511
|
+
replacement,
|
|
16512
|
+
});
|
|
16513
|
+
if (reference.mutation) {
|
|
16514
|
+
reference.mutation(magicSource, urlInfo);
|
|
16515
|
+
}
|
|
16516
|
+
});
|
|
16517
|
+
};
|
|
16518
|
+
const jsReferenceInfos = parseJsUrls({
|
|
16519
|
+
js: urlInfo.content,
|
|
16520
|
+
url: urlInfo.originalUrl,
|
|
16521
|
+
ast: urlInfo.contentAst,
|
|
16522
|
+
isJsModule: urlInfo.type === "js_module",
|
|
16523
|
+
isWebWorker: isWebWorkerUrlInfo(urlInfo),
|
|
16524
|
+
inlineContent,
|
|
16525
|
+
isNodeJs,
|
|
16526
|
+
});
|
|
16527
|
+
for (const jsReferenceInfo of jsReferenceInfos) {
|
|
16528
|
+
if (jsReferenceInfo.isInline) {
|
|
16529
|
+
onInlineReference(jsReferenceInfo);
|
|
16530
|
+
} else {
|
|
16531
|
+
onExternalReference(jsReferenceInfo);
|
|
16415
16532
|
}
|
|
16416
16533
|
}
|
|
16534
|
+
if (parallelActions.length > 0) {
|
|
16535
|
+
await Promise.all(parallelActions.map((action) => action()));
|
|
16536
|
+
}
|
|
16537
|
+
if (sequentialActions.length > 0) {
|
|
16538
|
+
await sequentialActions.reduce(async (previous, action) => {
|
|
16539
|
+
await previous;
|
|
16540
|
+
await action();
|
|
16541
|
+
}, Promise.resolve());
|
|
16542
|
+
}
|
|
16417
16543
|
|
|
16418
|
-
|
|
16544
|
+
const { content, sourcemap } = magicSource.toContentAndSourcemap();
|
|
16545
|
+
return { content, sourcemap };
|
|
16419
16546
|
};
|
|
16420
16547
|
|
|
16421
|
-
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
16427
|
-
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16439
|
-
|
|
16440
|
-
|
|
16441
|
-
|
|
16442
|
-
|
|
16443
|
-
|
|
16444
|
-
const onHtmlImportmapParsed = (importmap, htmlUrl) => {
|
|
16445
|
-
importmaps[htmlUrl] = importmap
|
|
16446
|
-
? normalizeImportMap(importmap, htmlUrl)
|
|
16447
|
-
: null;
|
|
16448
|
-
finalImportmap = Object.keys(importmaps).reduce((previous, url) => {
|
|
16449
|
-
const importmap = importmaps[url];
|
|
16450
|
-
if (!previous) {
|
|
16451
|
-
return importmap;
|
|
16452
|
-
}
|
|
16453
|
-
if (!importmap) {
|
|
16454
|
-
return previous;
|
|
16455
|
-
}
|
|
16456
|
-
return composeTwoImportMaps(previous, importmap);
|
|
16457
|
-
}, null);
|
|
16458
|
-
};
|
|
16548
|
+
const jsenvPluginReferenceAnalysis = ({
|
|
16549
|
+
inlineContent = true,
|
|
16550
|
+
inlineConvertedScript = false,
|
|
16551
|
+
fetchInlineUrls = true,
|
|
16552
|
+
}) => {
|
|
16553
|
+
return [
|
|
16554
|
+
jsenvPluginDirectoryReferenceAnalysis(),
|
|
16555
|
+
jsenvPluginHtmlReferenceAnalysis({
|
|
16556
|
+
inlineContent,
|
|
16557
|
+
inlineConvertedScript,
|
|
16558
|
+
}),
|
|
16559
|
+
jsenvPluginWebmanifestReferenceAnalysis(),
|
|
16560
|
+
jsenvPluginCssReferenceAnalysis(),
|
|
16561
|
+
jsenvPluginJsReferenceAnalysis({
|
|
16562
|
+
inlineContent,
|
|
16563
|
+
}),
|
|
16564
|
+
...(inlineContent ? [jsenvPluginDataUrlsAnalysis()] : []),
|
|
16565
|
+
...(inlineContent && fetchInlineUrls
|
|
16566
|
+
? [jsenvPluginInlineContentFetcher()]
|
|
16567
|
+
: []),
|
|
16568
|
+
jsenvPluginReferenceExpectedTypes(),
|
|
16569
|
+
];
|
|
16570
|
+
};
|
|
16459
16571
|
|
|
16572
|
+
const jsenvPluginInlineContentFetcher = () => {
|
|
16460
16573
|
return {
|
|
16461
|
-
name: "jsenv:
|
|
16574
|
+
name: "jsenv:inline_content_fetcher",
|
|
16462
16575
|
appliesDuring: "*",
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
|
|
16474
|
-
onImportMapping: () => {
|
|
16475
|
-
fromMapping = true;
|
|
16476
|
-
},
|
|
16477
|
-
});
|
|
16478
|
-
if (fromMapping) {
|
|
16479
|
-
return result;
|
|
16480
|
-
}
|
|
16481
|
-
return null;
|
|
16482
|
-
} catch (e) {
|
|
16483
|
-
if (e.message.includes("bare specifier")) {
|
|
16484
|
-
// in theory we should throw to be compliant with web behaviour
|
|
16485
|
-
// but for now it's simpler to return null
|
|
16486
|
-
// and let a chance to other plugins to handle the bare specifier
|
|
16487
|
-
// (node esm resolution)
|
|
16488
|
-
// and we want importmap to be prio over node esm so we cannot put this plugin after
|
|
16489
|
-
return null;
|
|
16490
|
-
}
|
|
16491
|
-
throw e;
|
|
16492
|
-
}
|
|
16493
|
-
},
|
|
16494
|
-
},
|
|
16495
|
-
transformUrlContent: {
|
|
16496
|
-
html: async (htmlUrlInfo) => {
|
|
16497
|
-
const htmlAst = parseHtmlString(htmlUrlInfo.content);
|
|
16498
|
-
const importmap = findHtmlNode(htmlAst, (node) => {
|
|
16499
|
-
if (node.nodeName !== "script") {
|
|
16500
|
-
return false;
|
|
16501
|
-
}
|
|
16502
|
-
const type = getHtmlNodeAttribute(node, "type");
|
|
16503
|
-
if (type === undefined || type !== "importmap") {
|
|
16504
|
-
return false;
|
|
16505
|
-
}
|
|
16506
|
-
return true;
|
|
16507
|
-
});
|
|
16508
|
-
if (!importmap) {
|
|
16509
|
-
onHtmlImportmapParsed(null, htmlUrlInfo.url);
|
|
16510
|
-
return null;
|
|
16511
|
-
}
|
|
16512
|
-
const handleInlineImportmap = async (importmap, htmlNodeText) => {
|
|
16513
|
-
const { line, column, isOriginal } = getHtmlNodePosition(importmap, {
|
|
16514
|
-
preferOriginal: true,
|
|
16515
|
-
});
|
|
16516
|
-
const inlineImportmapUrl = getUrlForContentInsideHtml(importmap, {
|
|
16517
|
-
htmlUrl: htmlUrlInfo.url,
|
|
16518
|
-
});
|
|
16519
|
-
const inlineImportmapReference = htmlUrlInfo.dependencies.foundInline(
|
|
16520
|
-
{
|
|
16521
|
-
type: "script",
|
|
16522
|
-
isOriginalPosition: isOriginal,
|
|
16523
|
-
specifierLine: line - 1,
|
|
16524
|
-
specifierColumn: column,
|
|
16525
|
-
specifier: inlineImportmapUrl,
|
|
16526
|
-
contentType: "application/importmap+json",
|
|
16527
|
-
content: htmlNodeText,
|
|
16528
|
-
},
|
|
16529
|
-
);
|
|
16530
|
-
const inlineImportmapUrlInfo = inlineImportmapReference.urlInfo;
|
|
16531
|
-
await inlineImportmapUrlInfo.cook();
|
|
16532
|
-
setHtmlNodeText(importmap, inlineImportmapUrlInfo.content, {
|
|
16533
|
-
indentation: "auto",
|
|
16534
|
-
});
|
|
16535
|
-
setHtmlNodeAttributes(importmap, {
|
|
16536
|
-
"jsenv-cooked-by": "jsenv:importmap",
|
|
16537
|
-
});
|
|
16538
|
-
onHtmlImportmapParsed(
|
|
16539
|
-
JSON.parse(inlineImportmapUrlInfo.content),
|
|
16540
|
-
htmlUrlInfo.url,
|
|
16541
|
-
);
|
|
16542
|
-
};
|
|
16543
|
-
const handleImportmapWithSrc = async (importmap, src) => {
|
|
16544
|
-
// Browser would throw on remote importmap
|
|
16545
|
-
// and won't sent a request to the server for it
|
|
16546
|
-
// We must precook the importmap to know its content and inline it into the HTML
|
|
16547
|
-
// In this situation the ref to the importmap was already discovered
|
|
16548
|
-
// when parsing the HTML
|
|
16549
|
-
let importmapReference = null;
|
|
16550
|
-
for (const referenceToOther of htmlUrlInfo.referenceToOthersSet) {
|
|
16551
|
-
if (referenceToOther.generatedSpecifier === src) {
|
|
16552
|
-
importmapReference = referenceToOther;
|
|
16553
|
-
break;
|
|
16554
|
-
}
|
|
16555
|
-
}
|
|
16556
|
-
const { line, column, isOriginal } = getHtmlNodePosition(importmap, {
|
|
16557
|
-
preferOriginal: true,
|
|
16558
|
-
});
|
|
16559
|
-
const importmapInlineUrl = getUrlForContentInsideHtml(importmap, {
|
|
16560
|
-
htmlUrl: htmlUrlInfo.url,
|
|
16561
|
-
});
|
|
16562
|
-
const importmapReferenceInlined = importmapReference.inline({
|
|
16563
|
-
line: line - 1,
|
|
16564
|
-
column,
|
|
16565
|
-
isOriginal,
|
|
16566
|
-
specifier: importmapInlineUrl,
|
|
16567
|
-
contentType: "application/importmap+json",
|
|
16568
|
-
});
|
|
16569
|
-
const importmapInlineUrlInfo = importmapReferenceInlined.urlInfo;
|
|
16570
|
-
await importmapInlineUrlInfo.cook();
|
|
16571
|
-
onHtmlImportmapParsed(
|
|
16572
|
-
JSON.parse(importmapInlineUrlInfo.content),
|
|
16573
|
-
htmlUrlInfo.url,
|
|
16574
|
-
);
|
|
16575
|
-
setHtmlNodeText(importmap, importmapInlineUrlInfo.content, {
|
|
16576
|
-
indentation: "auto",
|
|
16577
|
-
});
|
|
16578
|
-
setHtmlNodeAttributes(importmap, {
|
|
16579
|
-
"src": undefined,
|
|
16580
|
-
"jsenv-inlined-by": "jsenv:importmap",
|
|
16581
|
-
"inlined-from-src": src,
|
|
16582
|
-
});
|
|
16583
|
-
};
|
|
16584
|
-
|
|
16585
|
-
const src = getHtmlNodeAttribute(importmap, "src");
|
|
16586
|
-
if (src) {
|
|
16587
|
-
await handleImportmapWithSrc(importmap, src);
|
|
16588
|
-
} else {
|
|
16589
|
-
const htmlNodeText = getHtmlNodeText(importmap);
|
|
16590
|
-
if (htmlNodeText) {
|
|
16591
|
-
await handleInlineImportmap(importmap, htmlNodeText);
|
|
16592
|
-
}
|
|
16576
|
+
fetchUrlContent: async (urlInfo) => {
|
|
16577
|
+
if (!urlInfo.isInline) {
|
|
16578
|
+
return null;
|
|
16579
|
+
}
|
|
16580
|
+
// - we must use last reference because
|
|
16581
|
+
// when updating the file, first reference is the previous version
|
|
16582
|
+
// - we cannot use urlInfo.lastReference because it can be the reference created by "http_request"
|
|
16583
|
+
let lastInlineReference;
|
|
16584
|
+
for (const reference of urlInfo.referenceFromOthersSet) {
|
|
16585
|
+
if (reference.isInline) {
|
|
16586
|
+
lastInlineReference = reference;
|
|
16593
16587
|
}
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16597
|
-
//
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16588
|
+
}
|
|
16589
|
+
const { prev } = lastInlineReference;
|
|
16590
|
+
if (prev && !prev.isInline) {
|
|
16591
|
+
// got inlined, cook original url
|
|
16592
|
+
if (lastInlineReference.content === undefined) {
|
|
16593
|
+
const originalUrlInfo = prev.urlInfo;
|
|
16594
|
+
await originalUrlInfo.cook();
|
|
16595
|
+
lastInlineReference.content = originalUrlInfo.content;
|
|
16596
|
+
lastInlineReference.contentType = originalUrlInfo.contentType;
|
|
16601
16597
|
}
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16598
|
+
}
|
|
16599
|
+
return {
|
|
16600
|
+
originalContent: urlInfo.originalContent,
|
|
16601
|
+
content: lastInlineReference.content,
|
|
16602
|
+
contentType: lastInlineReference.contentType,
|
|
16603
|
+
};
|
|
16606
16604
|
},
|
|
16607
16605
|
};
|
|
16608
16606
|
};
|
|
@@ -19478,14 +19476,22 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
19478
19476
|
return iterateMemoized(firstUrlInfo, []);
|
|
19479
19477
|
};
|
|
19480
19478
|
|
|
19481
|
-
|
|
19479
|
+
let propagationResult = propagateUpdate(firstUrlInfo);
|
|
19482
19480
|
const seen = new Set();
|
|
19483
19481
|
const invalidateImporters = (urlInfo) => {
|
|
19484
19482
|
// to indicate this urlInfo should be modified
|
|
19485
19483
|
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
19486
19484
|
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
19487
|
-
const { hotAcceptDependencies = [] } =
|
|
19485
|
+
const { hotDecline, hotAcceptDependencies = [] } =
|
|
19488
19486
|
urlInfoReferencingThisOne.data;
|
|
19487
|
+
if (hotDecline) {
|
|
19488
|
+
propagationResult = {
|
|
19489
|
+
declined: true,
|
|
19490
|
+
reason: `file declines hot reload`,
|
|
19491
|
+
declinedBy: formatUrlForClient(urlInfoReferencingThisOne.url),
|
|
19492
|
+
};
|
|
19493
|
+
return;
|
|
19494
|
+
}
|
|
19489
19495
|
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
19490
19496
|
continue;
|
|
19491
19497
|
}
|
|
@@ -19764,7 +19770,7 @@ const jsenvPluginRibbon = ({
|
|
|
19764
19770
|
null,
|
|
19765
19771
|
" ",
|
|
19766
19772
|
);
|
|
19767
|
-
|
|
19773
|
+
injectHtmlNodeAsEarlyAsPossible(
|
|
19768
19774
|
htmlAst,
|
|
19769
19775
|
createHtmlNode({
|
|
19770
19776
|
tagName: "script",
|
|
@@ -19829,7 +19835,6 @@ const getCorePlugins = ({
|
|
|
19829
19835
|
jsenvPluginReferenceAnalysis(referenceAnalysis),
|
|
19830
19836
|
...(injections ? [jsenvPluginInjections(injections)] : []),
|
|
19831
19837
|
jsenvPluginTranspilation(transpilation),
|
|
19832
|
-
jsenvPluginImportmap(),
|
|
19833
19838
|
...(inlining ? [jsenvPluginInlining()] : []),
|
|
19834
19839
|
...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []), // after inline as it needs inline script to be cooked
|
|
19835
19840
|
|
|
@@ -22279,7 +22284,7 @@ const createFileService = ({
|
|
|
22279
22284
|
associations: watchAssociations,
|
|
22280
22285
|
});
|
|
22281
22286
|
urlInfoCreated.isWatched = watch;
|
|
22282
|
-
//
|
|
22287
|
+
// when an url depends on many others, we check all these (like package.json)
|
|
22283
22288
|
urlInfoCreated.isValid = () => {
|
|
22284
22289
|
if (!urlInfoCreated.url.startsWith("file:")) {
|
|
22285
22290
|
return false;
|