@jsenv/core 37.1.4 → 38.0.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/js/autoreload.js +2 -2
- package/dist/jsenv_core.js +3221 -2483
- package/package.json +16 -15
- package/src/build/build.js +246 -1028
- package/src/build/build_specifier_manager.js +1200 -0
- package/src/build/build_urls_generator.js +40 -18
- package/src/build/version_mappings_injection.js +14 -16
- package/src/dev/file_service.js +0 -10
- package/src/dev/start_dev_server.js +0 -2
- package/src/kitchen/kitchen.js +54 -37
- package/src/kitchen/url_graph/references.js +84 -93
- package/src/kitchen/url_graph/url_graph.js +16 -6
- package/src/kitchen/url_graph/url_info_transformations.js +124 -55
- package/src/plugins/autoreload/client/autoreload.js +6 -2
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +20 -16
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +1 -1
- package/src/plugins/cache_control/jsenv_plugin_cache_control.js +2 -2
- package/src/plugins/clean_html/jsenv_plugin_clean_html.js +16 -0
- package/src/plugins/importmap/jsenv_plugin_importmap.js +11 -23
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +16 -1
- package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +14 -24
- package/src/plugins/plugin_controller.js +37 -25
- package/src/plugins/plugins.js +2 -0
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +31 -16
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +12 -6
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +33 -54
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +2 -9
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +15 -8
- package/src/build/build_versions_manager.js +0 -492
|
@@ -56,7 +56,10 @@ export const createUrlGraph = ({
|
|
|
56
56
|
addUrlInfo(referencedUrlInfo);
|
|
57
57
|
urlInfoCreatedEventEmitter.emit(referencedUrlInfo);
|
|
58
58
|
}
|
|
59
|
-
if (
|
|
59
|
+
if (
|
|
60
|
+
referencedUrlInfo.searchParams.size > 0 &&
|
|
61
|
+
kitchen.context.buildStep !== "shape"
|
|
62
|
+
) {
|
|
60
63
|
// A resource is represented by a url.
|
|
61
64
|
// Variations of a resource are represented by url search params
|
|
62
65
|
// Each representation of the resource is given a dedicated url info
|
|
@@ -187,6 +190,8 @@ const createUrlInfo = (url, context) => {
|
|
|
187
190
|
referenceToOthersSet: new Set(),
|
|
188
191
|
referenceFromOthersSet: new Set(),
|
|
189
192
|
firstReference: null, // first reference from an other url to this one
|
|
193
|
+
lastReference: null,
|
|
194
|
+
remapReference: null, // used solely during build for rollup
|
|
190
195
|
implicitUrlSet: new Set(),
|
|
191
196
|
searchParamVariantSet: new Set(),
|
|
192
197
|
|
|
@@ -197,7 +202,6 @@ const createUrlInfo = (url, context) => {
|
|
|
197
202
|
contentType: "", // "text/html", "text/css", "text/javascript", "application/json", ...
|
|
198
203
|
url: null,
|
|
199
204
|
originalUrl: undefined,
|
|
200
|
-
filename: "",
|
|
201
205
|
isEntryPoint: false,
|
|
202
206
|
originalContent: undefined,
|
|
203
207
|
originalContentAst: undefined,
|
|
@@ -211,6 +215,8 @@ const createUrlInfo = (url, context) => {
|
|
|
211
215
|
|
|
212
216
|
generatedUrl: null,
|
|
213
217
|
sourcemapGeneratedUrl: null,
|
|
218
|
+
filenameHint: "",
|
|
219
|
+
dirnameHint: "",
|
|
214
220
|
injected: false,
|
|
215
221
|
|
|
216
222
|
isInline: false,
|
|
@@ -238,16 +244,20 @@ const createUrlInfo = (url, context) => {
|
|
|
238
244
|
if (referenceFromOther.urlInfo !== urlInfo) {
|
|
239
245
|
continue;
|
|
240
246
|
}
|
|
241
|
-
if (referenceFromOther.
|
|
247
|
+
if (referenceFromOther.ownerUrlInfo.isRoot) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
const ref = referenceFromOther.original || referenceFromOther;
|
|
251
|
+
if (ref.isWeak) {
|
|
242
252
|
// weak reference don't count as using the url
|
|
243
253
|
continue;
|
|
244
254
|
}
|
|
245
|
-
if (
|
|
255
|
+
if (ref.gotInlined()) {
|
|
246
256
|
// the url info was inlined, an other reference is required
|
|
247
257
|
// to consider the non-inlined urlInfo as used
|
|
248
258
|
continue;
|
|
249
259
|
}
|
|
250
|
-
return
|
|
260
|
+
return ref.ownerUrlInfo.isUsed();
|
|
251
261
|
}
|
|
252
262
|
// nothing uses this url anymore
|
|
253
263
|
// - versioning update inline content
|
|
@@ -328,7 +338,7 @@ const createUrlInfo = (url, context) => {
|
|
|
328
338
|
data: { ...reference.data },
|
|
329
339
|
specifier: newSpecifier,
|
|
330
340
|
isWeak: true,
|
|
331
|
-
isInline:
|
|
341
|
+
isInline: reference.isInline,
|
|
332
342
|
original: reference.original || reference,
|
|
333
343
|
prev: reference,
|
|
334
344
|
// urlInfo: null,
|
|
@@ -15,19 +15,29 @@ import {
|
|
|
15
15
|
export const createUrlInfoTransformer = ({
|
|
16
16
|
logger,
|
|
17
17
|
sourcemaps,
|
|
18
|
+
sourcemapsComment,
|
|
19
|
+
sourcemapsSources,
|
|
18
20
|
sourcemapsSourcesProtocol,
|
|
19
21
|
sourcemapsSourcesContent,
|
|
20
|
-
sourcemapsSourcesRelative,
|
|
21
22
|
outDirectoryUrl,
|
|
22
23
|
supervisor,
|
|
23
24
|
}) => {
|
|
24
|
-
if (sourcemapsSourcesProtocol === undefined) {
|
|
25
|
-
sourcemapsSourcesProtocol = "file:///";
|
|
26
|
-
}
|
|
27
25
|
if (sourcemapsSourcesContent === undefined) {
|
|
28
26
|
sourcemapsSourcesContent = true;
|
|
29
27
|
}
|
|
30
28
|
|
|
29
|
+
const formatSourcemapSource =
|
|
30
|
+
typeof sourcemapsSources === "function"
|
|
31
|
+
? (source, urlInfo) => {
|
|
32
|
+
return sourcemapsSources(source, urlInfo);
|
|
33
|
+
}
|
|
34
|
+
: sourcemapsSources === "relative"
|
|
35
|
+
? (source, urlInfo) => {
|
|
36
|
+
const sourceRelative = urlToRelativeUrl(source, urlInfo.url);
|
|
37
|
+
return sourceRelative || ".";
|
|
38
|
+
}
|
|
39
|
+
: null;
|
|
40
|
+
|
|
31
41
|
const normalizeSourcemap = (urlInfo, sourcemap) => {
|
|
32
42
|
let { sources } = sourcemap;
|
|
33
43
|
if (sources) {
|
|
@@ -76,6 +86,21 @@ export const createUrlInfoTransformer = ({
|
|
|
76
86
|
urlInfo.sourcemapIsWrong = null;
|
|
77
87
|
};
|
|
78
88
|
|
|
89
|
+
const setContentProperties = (
|
|
90
|
+
urlInfo,
|
|
91
|
+
{ content, contentAst, contentEtag, contentLength },
|
|
92
|
+
) => {
|
|
93
|
+
if (content === urlInfo.content) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
urlInfo.contentAst = contentAst;
|
|
97
|
+
urlInfo.contentEtag = contentEtag;
|
|
98
|
+
urlInfo.contentLength = contentLength;
|
|
99
|
+
urlInfo.content = content;
|
|
100
|
+
defineGettersOnPropertiesDerivedFromContent(urlInfo);
|
|
101
|
+
return true;
|
|
102
|
+
};
|
|
103
|
+
|
|
79
104
|
const setContent = async (
|
|
80
105
|
urlInfo,
|
|
81
106
|
content,
|
|
@@ -96,14 +121,22 @@ export const createUrlInfoTransformer = ({
|
|
|
96
121
|
}
|
|
97
122
|
defineGettersOnPropertiesDerivedFromOriginalContent(urlInfo);
|
|
98
123
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
124
|
+
let may = mayHaveSourcemap(urlInfo);
|
|
125
|
+
let shouldHandle = shouldHandleSourcemap(urlInfo);
|
|
126
|
+
if (may && !shouldHandle) {
|
|
127
|
+
content = SOURCEMAP.removeComment({
|
|
128
|
+
contentType: urlInfo.contentType,
|
|
129
|
+
content,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
setContentProperties(urlInfo, {
|
|
133
|
+
content,
|
|
134
|
+
contentAst,
|
|
135
|
+
contentEtag,
|
|
136
|
+
contentLength,
|
|
137
|
+
});
|
|
105
138
|
urlInfo.sourcemap = sourcemap;
|
|
106
|
-
if (!
|
|
139
|
+
if (!may || !shouldHandle) {
|
|
107
140
|
return;
|
|
108
141
|
}
|
|
109
142
|
// sourcemap is a special kind of reference:
|
|
@@ -176,18 +209,22 @@ export const createUrlInfoTransformer = ({
|
|
|
176
209
|
if (contentType) {
|
|
177
210
|
urlInfo.contentType = contentType;
|
|
178
211
|
}
|
|
179
|
-
const contentModified =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
212
|
+
const contentModified = setContentProperties(urlInfo, {
|
|
213
|
+
content,
|
|
214
|
+
contentAst,
|
|
215
|
+
contentEtag,
|
|
216
|
+
contentLength,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (
|
|
220
|
+
sourcemap &&
|
|
221
|
+
mayHaveSourcemap(urlInfo) &&
|
|
222
|
+
shouldHandleSourcemap(urlInfo)
|
|
223
|
+
) {
|
|
188
224
|
const sourcemapNormalized = normalizeSourcemap(urlInfo, sourcemap);
|
|
225
|
+
let currentSourcemap = urlInfo.sourcemap;
|
|
189
226
|
const finalSourcemap = composeTwoSourcemaps(
|
|
190
|
-
|
|
227
|
+
currentSourcemap,
|
|
191
228
|
sourcemapNormalized,
|
|
192
229
|
);
|
|
193
230
|
const finalSourcemapNormalized = normalizeSourcemap(
|
|
@@ -259,7 +296,10 @@ export const createUrlInfoTransformer = ({
|
|
|
259
296
|
}
|
|
260
297
|
};
|
|
261
298
|
|
|
262
|
-
const applySourcemapOnContent = (
|
|
299
|
+
const applySourcemapOnContent = (
|
|
300
|
+
urlInfo,
|
|
301
|
+
formatSource = formatSourcemapSource,
|
|
302
|
+
) => {
|
|
263
303
|
if (!urlInfo.sourcemap || !shouldHandleSourcemap(urlInfo)) {
|
|
264
304
|
return;
|
|
265
305
|
}
|
|
@@ -291,40 +331,54 @@ export const createUrlInfoTransformer = ({
|
|
|
291
331
|
});
|
|
292
332
|
}
|
|
293
333
|
const sourcemapUrlInfo = sourcemapReference.urlInfo;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
334
|
+
// It's possible urlInfo content to be modified after being finalized
|
|
335
|
+
// In that case we'll recompose sourcemaps (and re-append it to file content)
|
|
336
|
+
// Recomposition is done on urlInfo.sourcemap and must be done with absolute urls inside .sources
|
|
337
|
+
// (so we can detect if sources are identical)
|
|
338
|
+
// For this reason we must not mutate urlInfo.sourcemap.sources
|
|
339
|
+
const sourcemapGenerated = {
|
|
340
|
+
...urlInfo.sourcemap,
|
|
341
|
+
sources: urlInfo.sourcemap.sources.map((source) => {
|
|
342
|
+
const sourceFormatted = formatSource
|
|
343
|
+
? formatSource(source, urlInfo)
|
|
344
|
+
: source;
|
|
345
|
+
if (sourcemapsSourcesProtocol) {
|
|
346
|
+
if (sourceFormatted.startsWith("file:///")) {
|
|
347
|
+
return `${sourcemapsSourcesProtocol}${sourceFormatted.slice(
|
|
348
|
+
"file:///".length,
|
|
349
|
+
)}`;
|
|
350
|
+
}
|
|
308
351
|
}
|
|
309
|
-
return
|
|
310
|
-
})
|
|
311
|
-
}
|
|
352
|
+
return sourceFormatted;
|
|
353
|
+
}),
|
|
354
|
+
};
|
|
355
|
+
sourcemapUrlInfo.type = "sourcemap";
|
|
312
356
|
sourcemapUrlInfo.contentType = "application/json";
|
|
313
|
-
sourcemapUrlInfo
|
|
357
|
+
setContentProperties(sourcemapUrlInfo, {
|
|
358
|
+
content: JSON.stringify(sourcemapGenerated, null, " "),
|
|
359
|
+
});
|
|
314
360
|
|
|
315
361
|
if (!urlInfo.sourcemapIsWrong) {
|
|
316
362
|
if (sourcemaps === "inline") {
|
|
317
363
|
sourcemapReference.generatedSpecifier =
|
|
318
|
-
generateSourcemapDataUrl(
|
|
364
|
+
generateSourcemapDataUrl(sourcemapGenerated);
|
|
319
365
|
}
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
366
|
+
if (shouldUpdateSourcemapComment(urlInfo, sourcemaps)) {
|
|
367
|
+
let specifier;
|
|
368
|
+
if (sourcemaps === "file" && sourcemapsComment === "relative") {
|
|
369
|
+
specifier = urlToRelativeUrl(
|
|
370
|
+
sourcemapReference.generatedUrl,
|
|
371
|
+
urlInfo.generatedUrl,
|
|
372
|
+
);
|
|
373
|
+
} else {
|
|
374
|
+
specifier = sourcemapReference.generatedSpecifier;
|
|
375
|
+
}
|
|
376
|
+
setContentProperties(urlInfo, {
|
|
377
|
+
content: SOURCEMAP.writeComment({
|
|
378
|
+
contentType: urlInfo.contentType,
|
|
379
|
+
content: urlInfo.content,
|
|
380
|
+
specifier,
|
|
381
|
+
}),
|
|
328
382
|
});
|
|
329
383
|
}
|
|
330
384
|
}
|
|
@@ -342,10 +396,31 @@ export const createUrlInfoTransformer = ({
|
|
|
342
396
|
resetContent,
|
|
343
397
|
setContent,
|
|
344
398
|
applyTransformations,
|
|
399
|
+
applySourcemapOnContent,
|
|
345
400
|
endTransformations,
|
|
346
401
|
};
|
|
347
402
|
};
|
|
348
403
|
|
|
404
|
+
const shouldUpdateSourcemapComment = (urlInfo, sourcemaps) => {
|
|
405
|
+
if (urlInfo.context.buildStep === "shape") {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
if (sourcemaps === "file" || sourcemaps === "inline") {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
return false;
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const mayHaveSourcemap = (urlInfo) => {
|
|
415
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
return true;
|
|
422
|
+
};
|
|
423
|
+
|
|
349
424
|
const shouldHandleSourcemap = (urlInfo) => {
|
|
350
425
|
const { sourcemaps } = urlInfo.context;
|
|
351
426
|
if (
|
|
@@ -355,11 +430,5 @@ const shouldHandleSourcemap = (urlInfo) => {
|
|
|
355
430
|
) {
|
|
356
431
|
return false;
|
|
357
432
|
}
|
|
358
|
-
if (urlInfo.url.startsWith("data:")) {
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
362
|
-
return false;
|
|
363
|
-
}
|
|
364
433
|
return true;
|
|
365
434
|
};
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getDOMNodesUsingUrl,
|
|
7
7
|
} from "./reload.js";
|
|
8
8
|
|
|
9
|
+
let debug = false;
|
|
9
10
|
const reloader = {
|
|
10
11
|
urlHotMetas,
|
|
11
12
|
status: {
|
|
@@ -34,7 +35,9 @@ const reloader = {
|
|
|
34
35
|
value: [],
|
|
35
36
|
onchange: () => {},
|
|
36
37
|
add: (reloadMessage) => {
|
|
37
|
-
|
|
38
|
+
if (debug) {
|
|
39
|
+
console.debug("received reload message", reloadMessage);
|
|
40
|
+
}
|
|
38
41
|
reloader.changes.value.push(reloadMessage);
|
|
39
42
|
reloader.changes.onchange();
|
|
40
43
|
if (reloader.autoreload.enabled) {
|
|
@@ -127,11 +130,12 @@ const dequeue = async () => {
|
|
|
127
130
|
}
|
|
128
131
|
};
|
|
129
132
|
|
|
130
|
-
const applyHotReload = async ({ cause,
|
|
133
|
+
const applyHotReload = async ({ cause, hotInstructions }) => {
|
|
131
134
|
await hotInstructions.reduce(
|
|
132
135
|
async (previous, { type, boundary, acceptedBy }) => {
|
|
133
136
|
await previous;
|
|
134
137
|
|
|
138
|
+
const hot = Date.now();
|
|
135
139
|
const urlToFetch = new URL(boundary, `${window.location.origin}/`).href;
|
|
136
140
|
const urlHotMeta = urlHotMetas[urlToFetch];
|
|
137
141
|
// there is no url hot meta when:
|
|
@@ -39,7 +39,12 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
39
39
|
const instructions = [];
|
|
40
40
|
for (const referenceFromOther of urlInfo.referenceFromOthersSet) {
|
|
41
41
|
if (referenceFromOther.isImplicit && referenceFromOther.isWeak) {
|
|
42
|
-
|
|
42
|
+
if (!referenceFromOther.original) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (referenceFromOther.original.isWeak) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
const urlInfoReferencingThisOne = referenceFromOther.ownerUrlInfo;
|
|
45
50
|
if (urlInfoReferencingThisOne.data.hotDecline) {
|
|
@@ -148,7 +153,6 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
148
153
|
cause: `${relativeUrl} ${event}`,
|
|
149
154
|
type: "hot",
|
|
150
155
|
typeReason: hotUpdate.reason,
|
|
151
|
-
hot: changedUrlInfo.modifiedTimestamp,
|
|
152
156
|
hotInstructions: instructions,
|
|
153
157
|
};
|
|
154
158
|
}
|
|
@@ -207,7 +211,6 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
207
211
|
cause,
|
|
208
212
|
type: "hot",
|
|
209
213
|
typeReason: ownerHotUpdate.reason,
|
|
210
|
-
hot: prunedUrlInfo.prunedTimestamp,
|
|
211
214
|
hotInstructions: [pruneInstruction],
|
|
212
215
|
};
|
|
213
216
|
}
|
|
@@ -220,20 +223,21 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
220
223
|
|
|
221
224
|
clientFileChangeEventEmitter.on(({ url, event }) => {
|
|
222
225
|
const changedUrlInfo = serverEventInfo.kitchen.graph.getUrlInfo(url);
|
|
223
|
-
if (changedUrlInfo) {
|
|
224
|
-
|
|
225
|
-
type: "change",
|
|
226
|
-
changedUrlInfo,
|
|
227
|
-
event,
|
|
228
|
-
});
|
|
229
|
-
for (const searchParamVariant of changedUrlInfo.searchParamVariantSet) {
|
|
230
|
-
delayAction({
|
|
231
|
-
type: "change",
|
|
232
|
-
changedUrlInfo: searchParamVariant,
|
|
233
|
-
event,
|
|
234
|
-
});
|
|
235
|
-
}
|
|
226
|
+
if (!changedUrlInfo) {
|
|
227
|
+
return;
|
|
236
228
|
}
|
|
229
|
+
delayAction({
|
|
230
|
+
type: "change",
|
|
231
|
+
changedUrlInfo,
|
|
232
|
+
event,
|
|
233
|
+
});
|
|
234
|
+
// for (const searchParamVariant of changedUrlInfo.searchParamVariantSet) {
|
|
235
|
+
// delayAction({
|
|
236
|
+
// type: "change",
|
|
237
|
+
// changedUrlInfo: searchParamVariant,
|
|
238
|
+
// event,
|
|
239
|
+
// });
|
|
240
|
+
// }
|
|
237
241
|
});
|
|
238
242
|
clientFileDereferencedEventEmitter.on(
|
|
239
243
|
(prunedUrlInfo, lastReferenceFromOther) => {
|
|
@@ -53,7 +53,7 @@ export const jsenvPluginHotSearchParam = () => {
|
|
|
53
53
|
// that could prevent re-execution of js code
|
|
54
54
|
// In order to achieve this, this plugin inject ?hot=timestamp
|
|
55
55
|
// - The browser will likely not have it in cache
|
|
56
|
-
// and refetch
|
|
56
|
+
// and refetch latest version from server + re-execute it
|
|
57
57
|
// - If the browser have it in cache, he will not get it from server
|
|
58
58
|
// We use the latest timestamp to ensure it's fresh
|
|
59
59
|
// The dereferencedTimestamp is needed because when a js module is re-referenced
|
|
@@ -8,8 +8,8 @@ export const jsenvPluginCacheControl = ({
|
|
|
8
8
|
augmentResponse: ({ reference }) => {
|
|
9
9
|
if (
|
|
10
10
|
versionedUrls &&
|
|
11
|
-
reference.
|
|
12
|
-
!reference.
|
|
11
|
+
reference.generatedSearchParams.has("v") &&
|
|
12
|
+
!reference.generatedSearchParams.has("hot")
|
|
13
13
|
) {
|
|
14
14
|
return {
|
|
15
15
|
headers: {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseHtmlString, stringifyHtmlAst } from "@jsenv/ast";
|
|
2
|
+
|
|
3
|
+
export const jsenvPluginCleanHTML = () => {
|
|
4
|
+
return {
|
|
5
|
+
name: "jsenv:cleanup_html_during_dev",
|
|
6
|
+
appliesDuring: "dev",
|
|
7
|
+
finalizeUrlContent: {
|
|
8
|
+
html: (urlInfo) => {
|
|
9
|
+
const htmlAst = parseHtmlString(urlInfo.content);
|
|
10
|
+
return stringifyHtmlAst(htmlAst, {
|
|
11
|
+
cleanupPositionAttributes: true,
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
composeTwoImportMaps,
|
|
23
23
|
normalizeImportMap,
|
|
24
24
|
} from "@jsenv/importmap";
|
|
25
|
-
import { generateInlineContentUrl } from "@jsenv/urls";
|
|
26
25
|
import {
|
|
27
26
|
parseHtmlString,
|
|
28
27
|
stringifyHtmlAst,
|
|
@@ -33,6 +32,7 @@ import {
|
|
|
33
32
|
getHtmlNodeText,
|
|
34
33
|
setHtmlNodeText,
|
|
35
34
|
removeHtmlNode,
|
|
35
|
+
getUrlForContentInsideHtml,
|
|
36
36
|
} from "@jsenv/ast";
|
|
37
37
|
|
|
38
38
|
export const jsenvPluginImportmap = () => {
|
|
@@ -107,17 +107,11 @@ export const jsenvPluginImportmap = () => {
|
|
|
107
107
|
return null;
|
|
108
108
|
}
|
|
109
109
|
const handleInlineImportmap = async (importmap, htmlNodeText) => {
|
|
110
|
-
const { line, column,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
url: htmlUrlInfo.url,
|
|
116
|
-
extension: ".importmap",
|
|
117
|
-
line,
|
|
118
|
-
column,
|
|
119
|
-
lineEnd,
|
|
120
|
-
columnEnd,
|
|
110
|
+
const { line, column, isOriginal } = getHtmlNodePosition(importmap, {
|
|
111
|
+
preferOriginal: true,
|
|
112
|
+
});
|
|
113
|
+
const inlineImportmapUrl = getUrlForContentInsideHtml(importmap, {
|
|
114
|
+
htmlUrl: htmlUrlInfo.url,
|
|
121
115
|
});
|
|
122
116
|
const inlineImportmapReference = htmlUrlInfo.dependencies.foundInline(
|
|
123
117
|
{
|
|
@@ -156,17 +150,11 @@ export const jsenvPluginImportmap = () => {
|
|
|
156
150
|
break;
|
|
157
151
|
}
|
|
158
152
|
}
|
|
159
|
-
const { line, column,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
url: htmlUrlInfo.url,
|
|
165
|
-
extension: ".importmap",
|
|
166
|
-
line,
|
|
167
|
-
column,
|
|
168
|
-
lineEnd,
|
|
169
|
-
columnEnd,
|
|
153
|
+
const { line, column, isOriginal } = getHtmlNodePosition(importmap, {
|
|
154
|
+
preferOriginal: true,
|
|
155
|
+
});
|
|
156
|
+
const importmapInlineUrl = getUrlForContentInsideHtml(importmap, {
|
|
157
|
+
htmlUrl: htmlUrlInfo.url,
|
|
170
158
|
});
|
|
171
159
|
const importmapReferenceInlined = importmapReference.inline({
|
|
172
160
|
line: line - 1,
|
|
@@ -17,6 +17,21 @@ export const jsenvPluginInliningAsDataUrl = () => {
|
|
|
17
17
|
if (!reference.searchParams.has("inline")) {
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
|
+
if (reference.isInline) {
|
|
21
|
+
// happens when inlining file content into js
|
|
22
|
+
// (for instance import "style.css" with { type: "css" } )
|
|
23
|
+
// In that case the code generated look as follow
|
|
24
|
+
// new InlineContent(/* content of style.css */, { type: "text/css", inlinedFromUrl: "style.css" }).
|
|
25
|
+
// and during code analysis an inline reference is generated
|
|
26
|
+
// with the url "style.css?inline"
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// when search param is injected, it will be removed later
|
|
30
|
+
// by "getWithoutSearchParam". We don't want to redirect again
|
|
31
|
+
// (would create infinite recursion)
|
|
32
|
+
if (reference.prev && reference.prev.searchParams.has("inline")) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
20
35
|
if (reference.type === "sourcemap_comment") {
|
|
21
36
|
return null;
|
|
22
37
|
}
|
|
@@ -39,7 +54,7 @@ export const jsenvPluginInliningAsDataUrl = () => {
|
|
|
39
54
|
}
|
|
40
55
|
const specifierWithBase64Param = injectQueryParamsIntoSpecifier(
|
|
41
56
|
reference.specifier,
|
|
42
|
-
{ as_base_64: ""
|
|
57
|
+
{ as_base_64: "" },
|
|
43
58
|
);
|
|
44
59
|
const referenceInlined = reference.inline({
|
|
45
60
|
line: reference.line,
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
setHtmlNodeAttributes,
|
|
9
9
|
setHtmlNodeText,
|
|
10
10
|
getHtmlNodePosition,
|
|
11
|
+
getUrlForContentInsideHtml,
|
|
11
12
|
} from "@jsenv/ast";
|
|
12
|
-
import { generateInlineContentUrl, urlToExtension } from "@jsenv/urls";
|
|
13
13
|
|
|
14
14
|
export const jsenvPluginInliningIntoHtml = () => {
|
|
15
15
|
return {
|
|
@@ -21,7 +21,7 @@ export const jsenvPluginInliningIntoHtml = () => {
|
|
|
21
21
|
const mutations = [];
|
|
22
22
|
const actions = [];
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const onLinkRelStyleSheet = (linkNode, { href }) => {
|
|
25
25
|
let linkReference = null;
|
|
26
26
|
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
27
27
|
if (
|
|
@@ -36,17 +36,12 @@ export const jsenvPluginInliningIntoHtml = () => {
|
|
|
36
36
|
if (!linkReference.searchParams.has("inline")) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
const { line, column,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
const { line, column, isOriginal } = getHtmlNodePosition(linkNode, {
|
|
40
|
+
preferOriginal: true,
|
|
41
|
+
});
|
|
42
|
+
const linkInlineUrl = getUrlForContentInsideHtml(linkNode, {
|
|
43
|
+
htmlUrl: urlInfo.url,
|
|
44
44
|
url: linkReference.url,
|
|
45
|
-
extension: urlToExtension(linkReference.url),
|
|
46
|
-
line,
|
|
47
|
-
column,
|
|
48
|
-
lineEnd,
|
|
49
|
-
columnEnd,
|
|
50
45
|
});
|
|
51
46
|
const linkReferenceInlined = linkReference.inline({
|
|
52
47
|
line: line - 1,
|
|
@@ -62,7 +57,7 @@ export const jsenvPluginInliningIntoHtml = () => {
|
|
|
62
57
|
await linkUrlInfoInlined.cook();
|
|
63
58
|
mutations.push(() => {
|
|
64
59
|
setHtmlNodeAttributes(linkNode, {
|
|
65
|
-
"inlined-from-href":
|
|
60
|
+
"inlined-from-href": linkReference.url,
|
|
66
61
|
"href": undefined,
|
|
67
62
|
"rel": undefined,
|
|
68
63
|
"type": undefined,
|
|
@@ -93,17 +88,12 @@ export const jsenvPluginInliningIntoHtml = () => {
|
|
|
93
88
|
if (!scriptReference.searchParams.has("inline")) {
|
|
94
89
|
return;
|
|
95
90
|
}
|
|
96
|
-
const { line, column,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
const { line, column, isOriginal } = getHtmlNodePosition(scriptNode, {
|
|
92
|
+
preferOriginal: true,
|
|
93
|
+
});
|
|
94
|
+
const scriptInlineUrl = getUrlForContentInsideHtml(scriptNode, {
|
|
95
|
+
htmlUrl: urlInfo.url,
|
|
101
96
|
url: scriptReference.url,
|
|
102
|
-
extension: urlToExtension(scriptReference.url),
|
|
103
|
-
line,
|
|
104
|
-
column,
|
|
105
|
-
lineEnd,
|
|
106
|
-
columnEnd,
|
|
107
97
|
});
|
|
108
98
|
const scriptReferenceInlined = scriptReference.inline({
|
|
109
99
|
line: line - 1,
|
|
@@ -142,7 +132,7 @@ export const jsenvPluginInliningIntoHtml = () => {
|
|
|
142
132
|
if (!href) {
|
|
143
133
|
return;
|
|
144
134
|
}
|
|
145
|
-
|
|
135
|
+
onLinkRelStyleSheet(linkNode, { href });
|
|
146
136
|
},
|
|
147
137
|
script: (scriptNode) => {
|
|
148
138
|
const { type } = analyzeScriptNode(scriptNode);
|