@jsenv/core 35.0.5 → 36.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/js/inline_content.js +5 -4
- package/dist/jsenv_core.js +1127 -1497
- package/package.json +8 -8
- package/src/build/build.js +49 -41
- package/src/dev/file_service.js +7 -17
- package/src/dev/start_dev_server.js +12 -7
- package/src/kitchen/kitchen.js +38 -19
- package/src/kitchen/url_graph.js +1 -1
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +2 -2
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +4 -4
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +1 -1
- package/src/plugins/importmap/jsenv_plugin_importmap.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +13 -2
- package/src/plugins/plugin_controller.js +19 -10
- package/src/plugins/plugins.js +21 -25
- package/src/plugins/{url_analysis/css/css_urls.js → reference_analysis/css/jsenv_plugin_css_reference_analysis.js} +11 -1
- package/src/plugins/{inline_content_analysis/jsenv_plugin_data_urls.js → reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js} +19 -19
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +51 -0
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +429 -0
- package/src/plugins/reference_analysis/inline_content.js +7 -0
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +161 -0
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +120 -0
- package/src/plugins/{url_analysis → reference_analysis}/jsenv_plugin_reference_expected_types.js +19 -12
- package/src/plugins/{url_analysis/webmanifest/webmanifest_urls.js → reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js} +13 -1
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +74 -0
- package/src/plugins/{url_resolution → resolution_node_esm}/node_esm_resolver.js +8 -0
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +45 -0
- package/src/plugins/transpilation/as_js_module/jsenv_plugin_as_js_module.js +1 -1
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_conversion.js +1 -1
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +1 -1
- package/src/plugins/url_type_from_reference.js +13 -0
- package/src/plugins/{url_version/jsenv_plugin_url_version.js → version_search_param/jsenv_plugin_version_search_param.js} +4 -4
- package/dist/html/explorer.html +0 -559
- package/dist/other/jsenv.png +0 -0
- package/src/plugins/explorer/client/explorer.html +0 -608
- package/src/plugins/explorer/client/jsenv.png +0 -0
- package/src/plugins/explorer/jsenv_plugin_explorer.js +0 -86
- package/src/plugins/inline_content_analysis/client/inline_content.js +0 -6
- package/src/plugins/inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js +0 -206
- package/src/plugins/inline_content_analysis/jsenv_plugin_inline_content_analysis.js +0 -34
- package/src/plugins/inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js +0 -314
- package/src/plugins/url_analysis/html/html_urls.js +0 -313
- package/src/plugins/url_analysis/js/js_urls.js +0 -65
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +0 -116
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +0 -140
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
parseHtmlString,
|
|
3
|
-
visitHtmlNodes,
|
|
4
|
-
getHtmlNodeAttribute,
|
|
5
|
-
getHtmlNodePosition,
|
|
6
|
-
setHtmlNodeAttributes,
|
|
7
|
-
getHtmlNodeAttributePosition,
|
|
8
|
-
analyzeScriptNode,
|
|
9
|
-
parseSrcSet,
|
|
10
|
-
stringifyHtmlAst,
|
|
11
|
-
} from "@jsenv/ast";
|
|
12
|
-
|
|
13
|
-
export const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
14
|
-
const url = urlInfo.originalUrl;
|
|
15
|
-
const content = urlInfo.content;
|
|
16
|
-
const htmlAst = parseHtmlString(content, {
|
|
17
|
-
storeOriginalPositions: context.dev,
|
|
18
|
-
});
|
|
19
|
-
const mentions = visitHtmlUrls({
|
|
20
|
-
url,
|
|
21
|
-
htmlAst,
|
|
22
|
-
});
|
|
23
|
-
const mutations = [];
|
|
24
|
-
const actions = [];
|
|
25
|
-
for (const mention of mentions) {
|
|
26
|
-
const {
|
|
27
|
-
type,
|
|
28
|
-
subtype,
|
|
29
|
-
expectedType,
|
|
30
|
-
line,
|
|
31
|
-
column,
|
|
32
|
-
originalLine,
|
|
33
|
-
originalColumn,
|
|
34
|
-
node,
|
|
35
|
-
attributeName,
|
|
36
|
-
debug,
|
|
37
|
-
specifier,
|
|
38
|
-
} = mention;
|
|
39
|
-
const { crossorigin, integrity } = readFetchMetas(node);
|
|
40
|
-
const isResourceHint = [
|
|
41
|
-
"preconnect",
|
|
42
|
-
"dns-prefetch",
|
|
43
|
-
"prefetch",
|
|
44
|
-
"preload",
|
|
45
|
-
"modulepreload",
|
|
46
|
-
].includes(subtype);
|
|
47
|
-
const [reference] = context.referenceUtils.found({
|
|
48
|
-
type,
|
|
49
|
-
subtype,
|
|
50
|
-
expectedType,
|
|
51
|
-
originalLine,
|
|
52
|
-
originalColumn,
|
|
53
|
-
specifier,
|
|
54
|
-
specifierLine: line,
|
|
55
|
-
specifierColumn: column,
|
|
56
|
-
isResourceHint,
|
|
57
|
-
crossorigin,
|
|
58
|
-
integrity,
|
|
59
|
-
debug,
|
|
60
|
-
});
|
|
61
|
-
actions.push(async () => {
|
|
62
|
-
await context.referenceUtils.readGeneratedSpecifier(reference);
|
|
63
|
-
mutations.push(() => {
|
|
64
|
-
setHtmlNodeAttributes(node, {
|
|
65
|
-
[attributeName]: reference.generatedSpecifier,
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
if (actions.length > 0) {
|
|
71
|
-
await Promise.all(actions.map((action) => action()));
|
|
72
|
-
}
|
|
73
|
-
if (mutations.length === 0) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
mutations.forEach((mutation) => mutation());
|
|
77
|
-
return stringifyHtmlAst(htmlAst);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
|
|
81
|
-
const integrityCompatibleTagNames = ["script", "link", "img", "source"];
|
|
82
|
-
const readFetchMetas = (node) => {
|
|
83
|
-
const meta = {};
|
|
84
|
-
if (crossOriginCompatibleTagNames.includes(node.nodeName)) {
|
|
85
|
-
const crossorigin = getHtmlNodeAttribute(node, "crossorigin") !== undefined;
|
|
86
|
-
meta.crossorigin = crossorigin;
|
|
87
|
-
}
|
|
88
|
-
if (integrityCompatibleTagNames.includes(node.nodeName)) {
|
|
89
|
-
const integrity = getHtmlNodeAttribute(node, "integrity");
|
|
90
|
-
meta.integrity = integrity;
|
|
91
|
-
}
|
|
92
|
-
return meta;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const visitHtmlUrls = ({ url, htmlAst }) => {
|
|
96
|
-
const mentions = [];
|
|
97
|
-
const finalizeCallbacks = [];
|
|
98
|
-
const addMention = ({
|
|
99
|
-
type,
|
|
100
|
-
subtype,
|
|
101
|
-
expectedType,
|
|
102
|
-
node,
|
|
103
|
-
attributeName,
|
|
104
|
-
specifier,
|
|
105
|
-
}) => {
|
|
106
|
-
let position;
|
|
107
|
-
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
108
|
-
// when generated from inline content,
|
|
109
|
-
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
110
|
-
position = getHtmlNodePosition(node);
|
|
111
|
-
} else {
|
|
112
|
-
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
113
|
-
}
|
|
114
|
-
const {
|
|
115
|
-
line,
|
|
116
|
-
column,
|
|
117
|
-
// originalLine, originalColumn
|
|
118
|
-
} = position;
|
|
119
|
-
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
120
|
-
const mention = {
|
|
121
|
-
type,
|
|
122
|
-
subtype,
|
|
123
|
-
expectedType,
|
|
124
|
-
line,
|
|
125
|
-
column,
|
|
126
|
-
// originalLine, originalColumn
|
|
127
|
-
specifier,
|
|
128
|
-
node,
|
|
129
|
-
attributeName,
|
|
130
|
-
debug,
|
|
131
|
-
};
|
|
132
|
-
mentions.push(mention);
|
|
133
|
-
return mention;
|
|
134
|
-
};
|
|
135
|
-
const visitAttributeAsUrlSpecifier = ({ node, attributeName, ...rest }) => {
|
|
136
|
-
const value = getHtmlNodeAttribute(node, attributeName);
|
|
137
|
-
if (value) {
|
|
138
|
-
if (
|
|
139
|
-
getHtmlNodeAttribute(node, "jsenv-inlined-by") === "jsenv:importmap"
|
|
140
|
-
) {
|
|
141
|
-
// during build the importmap is inlined
|
|
142
|
-
// and shoud not be considered as a dependency anymore
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return addMention({
|
|
146
|
-
...rest,
|
|
147
|
-
node,
|
|
148
|
-
attributeName,
|
|
149
|
-
specifier:
|
|
150
|
-
attributeName === "inlined-from-src" ||
|
|
151
|
-
attributeName === "inlined-from-href"
|
|
152
|
-
? new URL(value, url).href
|
|
153
|
-
: value,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
if (attributeName === "src") {
|
|
157
|
-
return visitAttributeAsUrlSpecifier({
|
|
158
|
-
...rest,
|
|
159
|
-
node,
|
|
160
|
-
attributeName: "inlined-from-src",
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (attributeName === "href") {
|
|
164
|
-
return visitAttributeAsUrlSpecifier({
|
|
165
|
-
...rest,
|
|
166
|
-
node,
|
|
167
|
-
attributeName: "inlined-from-href",
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
return null;
|
|
171
|
-
};
|
|
172
|
-
const visitSrcset = ({ type, node }) => {
|
|
173
|
-
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
174
|
-
if (srcset) {
|
|
175
|
-
const srcCandidates = parseSrcSet(srcset);
|
|
176
|
-
srcCandidates.forEach((srcCandidate) => {
|
|
177
|
-
addMention({
|
|
178
|
-
type,
|
|
179
|
-
node,
|
|
180
|
-
attributeName: "srcset",
|
|
181
|
-
specifier: srcCandidate.specifier,
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
visitHtmlNodes(htmlAst, {
|
|
187
|
-
link: (node) => {
|
|
188
|
-
const rel = getHtmlNodeAttribute(node, "rel");
|
|
189
|
-
const type = getHtmlNodeAttribute(node, "type");
|
|
190
|
-
const mention = visitAttributeAsUrlSpecifier({
|
|
191
|
-
type: "link_href",
|
|
192
|
-
subtype: rel,
|
|
193
|
-
node,
|
|
194
|
-
attributeName: "href",
|
|
195
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
196
|
-
expectedContentType: type,
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
if (mention) {
|
|
200
|
-
finalizeCallbacks.push(() => {
|
|
201
|
-
mention.expectedType = decideLinkExpectedType(mention, mentions);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
// style: () => {},
|
|
206
|
-
script: (node) => {
|
|
207
|
-
const { type } = analyzeScriptNode(node);
|
|
208
|
-
if (type === "text") {
|
|
209
|
-
// ignore <script type="whatever" src="./file.js">
|
|
210
|
-
// per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
|
|
211
|
-
// this will be handled by jsenv_plugin_html_inline_content_analysis
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
visitAttributeAsUrlSpecifier({
|
|
215
|
-
type: "script",
|
|
216
|
-
subtype: type,
|
|
217
|
-
expectedType: type,
|
|
218
|
-
node,
|
|
219
|
-
attributeName: "src",
|
|
220
|
-
});
|
|
221
|
-
},
|
|
222
|
-
a: (node) => {
|
|
223
|
-
visitAttributeAsUrlSpecifier({
|
|
224
|
-
type: "a_href",
|
|
225
|
-
node,
|
|
226
|
-
attributeName: "href",
|
|
227
|
-
});
|
|
228
|
-
},
|
|
229
|
-
iframe: (node) => {
|
|
230
|
-
visitAttributeAsUrlSpecifier({
|
|
231
|
-
type: "iframe_src",
|
|
232
|
-
node,
|
|
233
|
-
attributeName: "src",
|
|
234
|
-
});
|
|
235
|
-
},
|
|
236
|
-
img: (node) => {
|
|
237
|
-
visitAttributeAsUrlSpecifier({
|
|
238
|
-
type: "img_src",
|
|
239
|
-
node,
|
|
240
|
-
attributeName: "src",
|
|
241
|
-
});
|
|
242
|
-
visitSrcset({
|
|
243
|
-
type: "img_srcset",
|
|
244
|
-
node,
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
source: (node) => {
|
|
248
|
-
visitAttributeAsUrlSpecifier({
|
|
249
|
-
type: "source_src",
|
|
250
|
-
node,
|
|
251
|
-
attributeName: "src",
|
|
252
|
-
});
|
|
253
|
-
visitSrcset({
|
|
254
|
-
type: "source_srcset",
|
|
255
|
-
node,
|
|
256
|
-
});
|
|
257
|
-
},
|
|
258
|
-
// svg <image> tag
|
|
259
|
-
image: (node) => {
|
|
260
|
-
visitAttributeAsUrlSpecifier({
|
|
261
|
-
type: "image_href",
|
|
262
|
-
node,
|
|
263
|
-
attributeName: "href",
|
|
264
|
-
});
|
|
265
|
-
},
|
|
266
|
-
use: (node) => {
|
|
267
|
-
visitAttributeAsUrlSpecifier({
|
|
268
|
-
type: "use_href",
|
|
269
|
-
node,
|
|
270
|
-
attributeName: "href",
|
|
271
|
-
});
|
|
272
|
-
},
|
|
273
|
-
});
|
|
274
|
-
finalizeCallbacks.forEach((finalizeCallback) => {
|
|
275
|
-
finalizeCallback();
|
|
276
|
-
});
|
|
277
|
-
return mentions;
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
const decideLinkExpectedType = (linkMention, mentions) => {
|
|
281
|
-
const rel = getHtmlNodeAttribute(linkMention.node, "rel");
|
|
282
|
-
if (rel === "webmanifest") {
|
|
283
|
-
return "webmanifest";
|
|
284
|
-
}
|
|
285
|
-
if (rel === "modulepreload") {
|
|
286
|
-
return "js_module";
|
|
287
|
-
}
|
|
288
|
-
if (rel === "stylesheet") {
|
|
289
|
-
return "css";
|
|
290
|
-
}
|
|
291
|
-
if (rel === "preload") {
|
|
292
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#what_types_of_content_can_be_preloaded
|
|
293
|
-
const as = getHtmlNodeAttribute(linkMention.node, "as");
|
|
294
|
-
if (as === "document") {
|
|
295
|
-
return "html";
|
|
296
|
-
}
|
|
297
|
-
if (as === "style") {
|
|
298
|
-
return "css";
|
|
299
|
-
}
|
|
300
|
-
if (as === "script") {
|
|
301
|
-
const firstScriptOnThisUrl = mentions.find(
|
|
302
|
-
(mentionCandidate) =>
|
|
303
|
-
mentionCandidate.url === linkMention.url &&
|
|
304
|
-
mentionCandidate.type === "script",
|
|
305
|
-
);
|
|
306
|
-
if (firstScriptOnThisUrl) {
|
|
307
|
-
return firstScriptOnThisUrl.expectedType;
|
|
308
|
-
}
|
|
309
|
-
return undefined;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return undefined;
|
|
313
|
-
};
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { createMagicSource } from "@jsenv/sourcemap";
|
|
2
|
-
import { parseJsUrls } from "@jsenv/ast";
|
|
3
|
-
|
|
4
|
-
import { isWebWorkerUrlInfo } from "@jsenv/core/src/kitchen/web_workers.js";
|
|
5
|
-
|
|
6
|
-
export const parseAndTransformJsUrls = async (urlInfo, context) => {
|
|
7
|
-
const jsMentions = await parseJsUrls({
|
|
8
|
-
js: urlInfo.content,
|
|
9
|
-
url: urlInfo.originalUrl,
|
|
10
|
-
isJsModule: urlInfo.type === "js_module",
|
|
11
|
-
isWebWorker: isWebWorkerUrlInfo(urlInfo),
|
|
12
|
-
});
|
|
13
|
-
const actions = [];
|
|
14
|
-
const magicSource = createMagicSource(urlInfo.content);
|
|
15
|
-
for (const jsMention of jsMentions) {
|
|
16
|
-
if (
|
|
17
|
-
jsMention.subtype === "import_static" ||
|
|
18
|
-
jsMention.subtype === "import_dynamic"
|
|
19
|
-
) {
|
|
20
|
-
urlInfo.data.usesImport = true;
|
|
21
|
-
}
|
|
22
|
-
const [reference] = context.referenceUtils.found({
|
|
23
|
-
node: jsMention.node,
|
|
24
|
-
type: jsMention.type,
|
|
25
|
-
subtype: jsMention.subtype,
|
|
26
|
-
expectedType: jsMention.expectedType,
|
|
27
|
-
expectedSubtype: jsMention.expectedSubtype || urlInfo.subtype,
|
|
28
|
-
specifier: jsMention.specifier,
|
|
29
|
-
specifierStart: jsMention.start,
|
|
30
|
-
specifierEnd: jsMention.end,
|
|
31
|
-
specifierLine: jsMention.line,
|
|
32
|
-
specifierColumn: jsMention.column,
|
|
33
|
-
data: jsMention.data,
|
|
34
|
-
baseUrl: {
|
|
35
|
-
"StringLiteral": jsMention.baseUrl,
|
|
36
|
-
"window.location": urlInfo.url,
|
|
37
|
-
"window.origin": context.rootDirectoryUrl,
|
|
38
|
-
"import.meta.url": urlInfo.url,
|
|
39
|
-
"context.meta.url": urlInfo.url,
|
|
40
|
-
"document.currentScript.src": urlInfo.url,
|
|
41
|
-
}[jsMention.baseUrlType],
|
|
42
|
-
assert: jsMention.assert,
|
|
43
|
-
assertNode: jsMention.assertNode,
|
|
44
|
-
typePropertyNode: jsMention.typePropertyNode,
|
|
45
|
-
});
|
|
46
|
-
actions.push(async () => {
|
|
47
|
-
const replacement = await context.referenceUtils.readGeneratedSpecifier(
|
|
48
|
-
reference,
|
|
49
|
-
);
|
|
50
|
-
magicSource.replace({
|
|
51
|
-
start: jsMention.start,
|
|
52
|
-
end: jsMention.end,
|
|
53
|
-
replacement,
|
|
54
|
-
});
|
|
55
|
-
if (reference.mutation) {
|
|
56
|
-
reference.mutation(magicSource);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if (actions.length > 0) {
|
|
61
|
-
await Promise.all(actions.map((action) => action()));
|
|
62
|
-
}
|
|
63
|
-
const { content, sourcemap } = magicSource.toContentAndSourcemap();
|
|
64
|
-
return { content, sourcemap };
|
|
65
|
-
};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { URL_META } from "@jsenv/url-meta";
|
|
2
|
-
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
3
|
-
|
|
4
|
-
import { jsenvPluginReferenceExpectedTypes } from "./jsenv_plugin_reference_expected_types.js";
|
|
5
|
-
import { parseAndTransformHtmlUrls } from "./html/html_urls.js";
|
|
6
|
-
import { parseAndTransformCssUrls } from "./css/css_urls.js";
|
|
7
|
-
import { parseAndTransformJsUrls } from "./js/js_urls.js";
|
|
8
|
-
import { parseAndTransformWebmanifestUrls } from "./webmanifest/webmanifest_urls.js";
|
|
9
|
-
|
|
10
|
-
export const jsenvPluginUrlAnalysis = ({
|
|
11
|
-
rootDirectoryUrl,
|
|
12
|
-
include,
|
|
13
|
-
supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
|
|
14
|
-
}) => {
|
|
15
|
-
// eslint-disable-next-line no-unused-vars
|
|
16
|
-
let getIncludeInfo = (url) => undefined;
|
|
17
|
-
if (include) {
|
|
18
|
-
const associations = URL_META.resolveAssociations(
|
|
19
|
-
{ include },
|
|
20
|
-
rootDirectoryUrl,
|
|
21
|
-
);
|
|
22
|
-
getIncludeInfo = (url) => {
|
|
23
|
-
const { include } = URL_META.applyAssociations({ url, associations });
|
|
24
|
-
return include;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return [
|
|
29
|
-
{
|
|
30
|
-
name: "jsenv:url_analysis",
|
|
31
|
-
appliesDuring: "*",
|
|
32
|
-
redirectUrl: (reference) => {
|
|
33
|
-
if (reference.shouldHandle !== undefined) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (
|
|
37
|
-
reference.specifier[0] === "#" &&
|
|
38
|
-
// For Html, css and in general "#" refer to a resource in the page
|
|
39
|
-
// so that urls must be kept intact
|
|
40
|
-
// However for js import specifiers they have a different meaning and we want
|
|
41
|
-
// to resolve them (https://nodejs.org/api/packages.html#imports for instance)
|
|
42
|
-
reference.type !== "js_import"
|
|
43
|
-
) {
|
|
44
|
-
reference.shouldHandle = false;
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const includeInfo = getIncludeInfo(reference.url);
|
|
48
|
-
if (includeInfo === true) {
|
|
49
|
-
reference.shouldHandle = true;
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (includeInfo === false) {
|
|
53
|
-
reference.shouldHandle = false;
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const { protocol } = new URL(reference.url);
|
|
57
|
-
const protocolIsSupported = supportedProtocols.some(
|
|
58
|
-
(supportedProtocol) => protocol === supportedProtocol,
|
|
59
|
-
);
|
|
60
|
-
if (protocolIsSupported) {
|
|
61
|
-
reference.shouldHandle = true;
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
transformUrlContent: {
|
|
65
|
-
html: parseAndTransformHtmlUrls,
|
|
66
|
-
css: parseAndTransformCssUrls,
|
|
67
|
-
js_classic: parseAndTransformJsUrls,
|
|
68
|
-
js_module: parseAndTransformJsUrls,
|
|
69
|
-
webmanifest: parseAndTransformWebmanifestUrls,
|
|
70
|
-
directory: (urlInfo, context) => {
|
|
71
|
-
const originalDirectoryReference = findOriginalDirectoryReference(
|
|
72
|
-
urlInfo,
|
|
73
|
-
context,
|
|
74
|
-
);
|
|
75
|
-
const directoryRelativeUrl = urlToRelativeUrl(
|
|
76
|
-
urlInfo.url,
|
|
77
|
-
context.rootDirectoryUrl,
|
|
78
|
-
);
|
|
79
|
-
JSON.parse(urlInfo.content).forEach((directoryEntryName) => {
|
|
80
|
-
context.referenceUtils.found({
|
|
81
|
-
type: "filesystem",
|
|
82
|
-
subtype: "directory_entry",
|
|
83
|
-
specifier: directoryEntryName,
|
|
84
|
-
trace: {
|
|
85
|
-
message: `"${directoryRelativeUrl}${directoryEntryName}" entry in directory referenced by ${originalDirectoryReference.trace.message}`,
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
jsenvPluginReferenceExpectedTypes(),
|
|
93
|
-
];
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const findOriginalDirectoryReference = (urlInfo, context) => {
|
|
97
|
-
const findNonFileSystemAncestor = (urlInfo) => {
|
|
98
|
-
for (const dependentUrl of urlInfo.dependents) {
|
|
99
|
-
const dependentUrlInfo = context.urlGraph.getUrlInfo(dependentUrl);
|
|
100
|
-
if (dependentUrlInfo.type !== "directory") {
|
|
101
|
-
return [dependentUrlInfo, urlInfo];
|
|
102
|
-
}
|
|
103
|
-
const found = findNonFileSystemAncestor(dependentUrlInfo);
|
|
104
|
-
if (found) {
|
|
105
|
-
return found;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return [];
|
|
109
|
-
};
|
|
110
|
-
const [ancestor, child] = findNonFileSystemAncestor(urlInfo);
|
|
111
|
-
if (!ancestor) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
const ref = ancestor.references.find((ref) => ref.url === child.url);
|
|
115
|
-
return ref;
|
|
116
|
-
};
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This plugin is responsible to resolve urls except for a few cases:
|
|
3
|
-
* - A custom plugin implements a resolveUrl hook returning something
|
|
4
|
-
* - The reference.type is "filesystem" -> it is handled by jsenv_plugin_file_urls.js
|
|
5
|
-
*
|
|
6
|
-
* By default node esm resolution applies inside js modules
|
|
7
|
-
* and the rest uses the web standard url resolution (new URL):
|
|
8
|
-
* - "http_request"
|
|
9
|
-
* - "entry_point"
|
|
10
|
-
* - "link_href"
|
|
11
|
-
* - "style"
|
|
12
|
-
* - "script"
|
|
13
|
-
* - "a_href"
|
|
14
|
-
* - "iframe_src
|
|
15
|
-
* - "img_src"
|
|
16
|
-
* - "img_srcset"
|
|
17
|
-
* - "source_src"
|
|
18
|
-
* - "source_srcset"
|
|
19
|
-
* - "image_href"
|
|
20
|
-
* - "use_href"
|
|
21
|
-
* - "css_@import"
|
|
22
|
-
* - "css_url"
|
|
23
|
-
* - "js_import"
|
|
24
|
-
* - "js_import_script"
|
|
25
|
-
* - "js_url"
|
|
26
|
-
* - "js_inline_content"
|
|
27
|
-
* - "sourcemap_comment"
|
|
28
|
-
* - "webmanifest_icon_src"
|
|
29
|
-
* - "package_json"
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import { createNodeEsmResolver } from "./node_esm_resolver.js";
|
|
33
|
-
|
|
34
|
-
export const jsenvPluginUrlResolution = ({
|
|
35
|
-
runtimeCompat,
|
|
36
|
-
defaultFileUrl,
|
|
37
|
-
urlResolution,
|
|
38
|
-
}) => {
|
|
39
|
-
const resolveUrlUsingWebResolution = (reference) => {
|
|
40
|
-
return new URL(
|
|
41
|
-
reference.specifier,
|
|
42
|
-
// baseUrl happens second argument to new URL() is different from
|
|
43
|
-
// import.meta.url or document.currentScript.src
|
|
44
|
-
reference.baseUrl || reference.parentUrl,
|
|
45
|
-
).href;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const resolvers = {};
|
|
49
|
-
Object.keys(urlResolution).forEach((urlType) => {
|
|
50
|
-
const resolver = urlResolution[urlType];
|
|
51
|
-
if (typeof resolver !== "object") {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`urlResolution values must be objects, got ${resolver} on "${urlType}"`,
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
let { web, node_esm, ...rest } = resolver;
|
|
57
|
-
const unexpectedKeys = Object.keys(rest);
|
|
58
|
-
if (unexpectedKeys.length) {
|
|
59
|
-
throw new TypeError(
|
|
60
|
-
`${unexpectedKeys.join(
|
|
61
|
-
",",
|
|
62
|
-
)}: there is no such configuration on "${urlType}"`,
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
if (node_esm === undefined) {
|
|
66
|
-
node_esm = urlType === "js_import";
|
|
67
|
-
}
|
|
68
|
-
if (web === undefined) {
|
|
69
|
-
web = true;
|
|
70
|
-
}
|
|
71
|
-
if (node_esm) {
|
|
72
|
-
if (node_esm === true) node_esm = {};
|
|
73
|
-
const { packageConditions, preservesSymlink } = node_esm;
|
|
74
|
-
resolvers[urlType] = createNodeEsmResolver({
|
|
75
|
-
runtimeCompat,
|
|
76
|
-
packageConditions,
|
|
77
|
-
preservesSymlink,
|
|
78
|
-
});
|
|
79
|
-
} else if (web) {
|
|
80
|
-
resolvers[urlType] = resolveUrlUsingWebResolution;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const nodeEsmResolverDefault = createNodeEsmResolver({
|
|
85
|
-
runtimeCompat,
|
|
86
|
-
preservesSymlink: true,
|
|
87
|
-
});
|
|
88
|
-
if (!resolvers.js_module) {
|
|
89
|
-
resolvers.js_module = nodeEsmResolverDefault;
|
|
90
|
-
}
|
|
91
|
-
if (!resolvers.js_classic) {
|
|
92
|
-
resolvers.js_classic = (reference, context) => {
|
|
93
|
-
if (reference.subtype === "self_import_scripts_arg") {
|
|
94
|
-
return nodeEsmResolverDefault(reference, context);
|
|
95
|
-
}
|
|
96
|
-
return resolveUrlUsingWebResolution(reference, context);
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
if (!resolvers["*"]) {
|
|
100
|
-
resolvers["*"] = resolveUrlUsingWebResolution;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
name: "jsenv:url_resolution",
|
|
105
|
-
appliesDuring: "*",
|
|
106
|
-
resolveUrl: (reference, context) => {
|
|
107
|
-
if (reference.specifier === "/") {
|
|
108
|
-
return String(defaultFileUrl);
|
|
109
|
-
}
|
|
110
|
-
if (reference.specifier[0] === "/") {
|
|
111
|
-
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl)
|
|
112
|
-
.href;
|
|
113
|
-
}
|
|
114
|
-
if (reference.type === "sourcemap_comment") {
|
|
115
|
-
return resolveUrlUsingWebResolution(reference, context);
|
|
116
|
-
}
|
|
117
|
-
let urlType;
|
|
118
|
-
if (reference.injected) {
|
|
119
|
-
urlType = reference.expectedType;
|
|
120
|
-
} else {
|
|
121
|
-
const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl);
|
|
122
|
-
urlType = parentUrlInfo ? parentUrlInfo.type : "entry_point";
|
|
123
|
-
}
|
|
124
|
-
const resolver = resolvers[urlType] || resolvers["*"];
|
|
125
|
-
return resolver(reference, context);
|
|
126
|
-
},
|
|
127
|
-
// when specifier is prefixed by "file:///@ignore/"
|
|
128
|
-
// we return an empty js module (used by node esm)
|
|
129
|
-
fetchUrlContent: (urlInfo) => {
|
|
130
|
-
if (urlInfo.url.startsWith("file:///@ignore/")) {
|
|
131
|
-
return {
|
|
132
|
-
content: "export default {}",
|
|
133
|
-
contentType: "text/javascript",
|
|
134
|
-
type: "js_module",
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return null;
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
};
|