@jsenv/core 25.1.0 → 25.3.0-alpha.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.
Files changed (58) hide show
  1. package/dist/browser_runtime/browser_runtime_91c5a3b8.js.map +2 -2
  2. package/dist/build_manifest.js +4 -4
  3. package/dist/compile_proxy/asset-manifest.json +2 -2
  4. package/dist/compile_proxy/{compile_proxy_e3b0c442_809f35f7.js.map → compile_proxy.html__inline__20_809f35f7.js.map} +0 -0
  5. package/dist/compile_proxy/{compile_proxy_7ad5faa6.html → compile_proxy_8dfaee51.html} +3 -4
  6. package/dist/redirector/asset-manifest.json +2 -2
  7. package/dist/redirector/{redirector_e3b0c442_e391410e.js.map → redirector.html__inline__15_e391410e.js.map} +0 -0
  8. package/dist/redirector/{redirector_eb92e8a7.html → redirector_3e9a97b9.html} +3 -4
  9. package/dist/toolbar/asset-manifest.json +1 -1
  10. package/dist/toolbar/{toolbar_f7b8a263.html → toolbar_361afb84.html} +2 -3
  11. package/dist/toolbar_injector/asset-manifest.json +2 -2
  12. package/dist/toolbar_injector/{toolbar_injector_49e4756e.js → toolbar_injector_fac1e995.js} +2 -2
  13. package/dist/toolbar_injector/{toolbar_injector_49e4756e.js.map → toolbar_injector_fac1e995.js.map} +2 -2
  14. package/package.json +13 -9
  15. package/readme.md +75 -76
  16. package/src/buildProject.js +21 -13
  17. package/src/commonJsToJavaScriptModule.js +8 -7
  18. package/src/dev_server.js +2 -0
  19. package/src/execute.js +2 -0
  20. package/src/executeTestPlan.js +14 -0
  21. package/src/internal/building/buildUsingRollup.js +4 -2
  22. package/src/internal/building/build_stats.js +3 -0
  23. package/src/internal/building/build_url_generator.js +153 -0
  24. package/src/internal/building/css/parseCssRessource.js +32 -26
  25. package/src/internal/building/html/parseHtmlRessource.js +110 -91
  26. package/src/internal/building/js/parseJsRessource.js +4 -7
  27. package/src/internal/building/parseRessource.js +3 -0
  28. package/src/internal/building/ressource_builder.js +64 -62
  29. package/src/internal/building/ressource_builder_util.js +17 -5
  30. package/src/internal/building/rollup_plugin_jsenv.js +259 -189
  31. package/src/internal/building/url_fetcher.js +16 -7
  32. package/src/internal/building/url_loader.js +1 -5
  33. package/src/internal/building/url_versioning.js +0 -173
  34. package/src/internal/compiling/babel_plugin_import_metadata.js +7 -11
  35. package/src/internal/compiling/babel_plugin_proxy_external_imports.js +31 -0
  36. package/src/internal/compiling/compile-directory/compile-asset.js +8 -4
  37. package/src/internal/compiling/compile-directory/getOrGenerateCompiledFile.js +43 -8
  38. package/src/internal/compiling/compile-directory/updateMeta.js +4 -8
  39. package/src/internal/compiling/compile-directory/validateCache.js +1 -2
  40. package/src/internal/compiling/compileFile.js +22 -10
  41. package/src/internal/compiling/compileHtml.js +15 -28
  42. package/src/internal/compiling/createCompiledFileService.js +22 -24
  43. package/src/internal/compiling/html_source_file_service.js +18 -19
  44. package/src/internal/compiling/js-compilation-service/babelHelper.js +10 -13
  45. package/src/internal/compiling/js-compilation-service/babel_plugin_babel_helpers_as_jsenv_imports.js +4 -2
  46. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +16 -7
  47. package/src/internal/compiling/js-compilation-service/transformJs.js +9 -5
  48. package/src/internal/compiling/jsenvCompilerForHtml.js +231 -195
  49. package/src/internal/compiling/jsenvCompilerForJavaScript.js +15 -11
  50. package/src/internal/compiling/startCompileServer.js +79 -19
  51. package/src/internal/compiling/transformResultToCompilationResult.js +47 -25
  52. package/src/internal/executing/executePlan.js +2 -0
  53. package/src/internal/fetchUrl.js +3 -2
  54. package/src/internal/jsenv_remote_directory.js +156 -0
  55. package/src/internal/origin_directory_converter.js +62 -0
  56. package/src/internal/response_validation.js +11 -24
  57. package/src/internal/sourceMappingURLUtils.js +10 -0
  58. package/src/internal/url_conversion.js +1 -0
@@ -17,6 +17,8 @@ Or be sure to also reference this url somewhere in the html file like
17
17
  */
18
18
 
19
19
  import { urlToFilename, urlToRelativeUrl, resolveUrl } from "@jsenv/filesystem"
20
+ import { applyAlgoToRepresentationData } from "@jsenv/integrity"
21
+
20
22
 
21
23
  import {
22
24
  parseHtmlString,
@@ -24,7 +26,7 @@ import {
24
26
  replaceHtmlNode,
25
27
  getHtmlNodeAttributeByName,
26
28
  stringifyHtmlAst,
27
- getUniqueNameForInlineHtmlNode,
29
+ getIdForInlineHtmlNode,
28
30
  removeHtmlNodeAttribute,
29
31
  setHtmlNodeText,
30
32
  getHtmlNodeTextNode,
@@ -32,6 +34,7 @@ import {
32
34
  stringifySrcset,
33
35
  getHtmlNodeLocation,
34
36
  removeHtmlNode,
37
+ addHtmlNodeAttribute,
35
38
  } from "@jsenv/core/src/internal/compiling/compileHtml.js"
36
39
  import {
37
40
  getJavaScriptSourceMappingUrl,
@@ -172,20 +175,21 @@ const regularScriptSrcVisitor = (
172
175
  if (!srcAttribute) {
173
176
  return null
174
177
  }
175
-
178
+ const integrityAttribute = getHtmlNodeAttributeByName(script, "integrity")
179
+ const integrity = integrityAttribute ? integrityAttribute.value : ""
176
180
  const remoteScriptReference = notifyReferenceFound({
177
181
  referenceLabel: "html script",
178
182
  contentTypeExpected: "application/javascript",
179
183
  ressourceSpecifier: srcAttribute.value,
184
+ integrity,
185
+ ...crossoriginFromHtmlNode(script),
180
186
  ...referenceLocationFromHtmlNode(script, "src"),
181
187
  })
182
188
  return ({ getUrlRelativeToImporter }) => {
183
189
  const ressource = remoteScriptReference.ressource
184
-
185
190
  if (ressource.isExternal) {
186
191
  return
187
192
  }
188
-
189
193
  if (shouldInline({ ressource, htmlNode: script })) {
190
194
  removeHtmlNodeAttribute(script, srcAttribute)
191
195
  const { bufferAfterBuild } = ressource
@@ -200,14 +204,19 @@ const regularScriptSrcVisitor = (
200
204
  const sourcemapInlineUrl = urlToRelativeUrl(sourcemapBuildUrl, htmlUrl)
201
205
  jsString = setJavaScriptSourceMappingUrl(jsString, sourcemapInlineUrl)
202
206
  }
203
-
204
207
  setHtmlNodeText(script, jsString)
205
208
  remoteScriptReference.inlinedCallback()
206
209
  return
207
210
  }
208
-
209
211
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
210
212
  srcAttribute.value = urlRelativeToImporter
213
+ if (integrityAttribute) {
214
+ const base64Value = applyAlgoToRepresentationData(
215
+ "sha256",
216
+ ressource.bufferAfterBuild,
217
+ )
218
+ integrityAttribute.value = `sha256-${base64Value}`
219
+ }
211
220
  }
212
221
  }
213
222
 
@@ -233,12 +242,10 @@ const regularScriptTextNodeVisitor = (
233
242
  if (!textNode) {
234
243
  return null
235
244
  }
236
-
237
- const ressourceSpecifier = getUniqueNameForInlineHtmlNode(
238
- script,
239
- scripts,
240
- `${urlToFilename(htmlRessource.url)}__inline__[id].js`,
241
- )
245
+ const scriptId = getIdForInlineHtmlNode(script, scripts)
246
+ const ressourceSpecifier = `${urlToFilename(
247
+ htmlRessource.url,
248
+ )}__inline__${scriptId}.js`
242
249
  const jsReference = notifyReferenceFound({
243
250
  referenceLabel: "html inline script",
244
251
  contentTypeExpected: "application/javascript",
@@ -266,25 +273,25 @@ const moduleScriptSrcVisitor = (script, { format, notifyReferenceFound }) => {
266
273
  if (!srcAttribute) {
267
274
  return null
268
275
  }
269
-
276
+ const integrityAttribute = getHtmlNodeAttributeByName(script, "integrity")
277
+ const integrity = integrityAttribute ? integrityAttribute.value : ""
270
278
  const remoteScriptReference = notifyReferenceFound({
271
279
  referenceLabel: "html module script",
272
280
  contentTypeExpected: "application/javascript",
273
281
  ressourceSpecifier: srcAttribute.value,
282
+ integrity,
283
+ ...crossoriginFromHtmlNode(script),
274
284
  ...referenceLocationFromHtmlNode(script, "src"),
275
285
  isJsModule: true,
276
286
  })
277
287
  return ({ getUrlRelativeToImporter }) => {
278
288
  const { ressource } = remoteScriptReference
279
-
280
289
  if (format === "systemjs") {
281
290
  removeHtmlNodeAttribute(script, typeAttribute)
282
291
  }
283
-
284
292
  if (ressource.isExternal) {
285
293
  return
286
294
  }
287
-
288
295
  if (shouldInline({ ressource, htmlNode: script })) {
289
296
  // here put a warning if we cannot inline importmap because it would mess
290
297
  // the remapping (note that it's feasible) but not yet supported
@@ -299,15 +306,20 @@ const moduleScriptSrcVisitor = (script, { format, notifyReferenceFound }) => {
299
306
  // with these assumptions we can force the sourcemap url
300
307
  const sourcemapUrl = `${ressource.buildRelativeUrl}.map`
301
308
  jsString = setJavaScriptSourceMappingUrl(jsString, sourcemapUrl)
302
-
303
309
  setHtmlNodeText(script, jsString)
304
310
  remoteScriptReference.inlinedCallback()
305
311
  return
306
312
  }
307
-
308
313
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
309
314
  const relativeUrlNotation = ensureRelativeUrlNotation(urlRelativeToImporter)
310
315
  srcAttribute.value = relativeUrlNotation
316
+ if (integrityAttribute) {
317
+ const base64Value = applyAlgoToRepresentationData(
318
+ "sha256",
319
+ ressource.bufferAfterBuild,
320
+ )
321
+ integrityAttribute.value = `sha256-${base64Value}`
322
+ }
311
323
  }
312
324
  }
313
325
 
@@ -332,12 +344,10 @@ const moduleScriptTextNodeVisitor = (
332
344
  if (!textNode) {
333
345
  return null
334
346
  }
335
-
336
- const ressourceSpecifier = getUniqueNameForInlineHtmlNode(
337
- script,
338
- scripts,
339
- `${urlToFilename(htmlRessource.url)}__inline__[id].js`,
340
- )
347
+ const scriptId = getIdForInlineHtmlNode(script, scripts)
348
+ const ressourceSpecifier = `${urlToFilename(
349
+ htmlRessource.url,
350
+ )}__inline__${scriptId}.js`
341
351
  const jsReference = notifyReferenceFound({
342
352
  referenceLabel: "html inline module script",
343
353
  contentTypeExpected: "application/javascript",
@@ -373,24 +383,24 @@ const importmapScriptSrcVisitor = (
373
383
  if (!srcAttribute) {
374
384
  return null
375
385
  }
376
-
386
+ const integrityAttribute = getHtmlNodeAttributeByName(script, "integrity")
387
+ const integrity = integrityAttribute ? integrityAttribute.value : ""
377
388
  const importmapReference = notifyReferenceFound({
378
389
  referenceLabel: "html importmap",
379
390
  contentTypeExpected: "application/importmap+json",
380
391
  ressourceSpecifier: srcAttribute.value,
392
+ integrity,
393
+ ...crossoriginFromHtmlNode(script),
381
394
  ...referenceLocationFromHtmlNode(script, "src"),
382
395
  })
383
396
  return ({ getUrlRelativeToImporter }) => {
384
397
  const { ressource } = importmapReference
385
-
386
398
  if (format === "systemjs") {
387
399
  typeAttribute.value = "systemjs-importmap"
388
400
  }
389
-
390
401
  if (ressource.isExternal) {
391
402
  return
392
403
  }
393
-
394
404
  if (
395
405
  // for esmodule we always inline the importmap
396
406
  // as it's the only thing supported by Chrome
@@ -404,22 +414,22 @@ const importmapScriptSrcVisitor = (
404
414
  // here put a warning if we cannot inline importmap because it would mess
405
415
  // the remapping (note that it's feasible) but not yet supported
406
416
  const { bufferAfterBuild } = ressource
407
-
408
417
  const importmapString = String(bufferAfterBuild)
409
- replaceHtmlNode(
410
- script,
411
- `<script>
412
- ${importmapString}</script>`,
413
- {
414
- attributesToIgnore: ["src"],
415
- },
416
- )
418
+ removeHtmlNodeAttribute(script, srcAttribute)
419
+ setHtmlNodeText(script, importmapString)
420
+ removeHtmlNodeAttribute(script, integrityAttribute)
417
421
  importmapReference.inlinedCallback()
418
422
  return
419
423
  }
420
-
421
424
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
422
425
  srcAttribute.value = urlRelativeToImporter
426
+ if (integrityAttribute) {
427
+ const base64Value = applyAlgoToRepresentationData(
428
+ "sha256",
429
+ ressource.bufferAfterBuild,
430
+ )
431
+ integrityAttribute.value = `sha256-${base64Value}`
432
+ }
423
433
  }
424
434
  }
425
435
 
@@ -444,17 +454,14 @@ const importmapScriptTextNodeVisitor = (
444
454
  if (!textNode) {
445
455
  return null
446
456
  }
447
-
457
+ const importmapScriptId = getIdForInlineHtmlNode(script, scripts)
448
458
  const importmapReference = notifyReferenceFound({
449
459
  referenceLabel: "html inline importmap",
450
460
  contentTypeExpected: "application/importmap+json",
451
- ressourceSpecifier: getUniqueNameForInlineHtmlNode(
452
- script,
453
- scripts,
454
- `${urlToFilename(htmlRessource.url)}__inline__[id].importmap`,
455
- ),
461
+ ressourceSpecifier: `${urlToFilename(
462
+ htmlRessource.url,
463
+ )}__inline__${importmapScriptId}.importmap`,
456
464
  ...referenceLocationFromHtmlNode(script),
457
-
458
465
  contentType: "application/importmap+json",
459
466
  bufferBeforeBuild: Buffer.from(textNode.value),
460
467
  isInline: true,
@@ -463,7 +470,6 @@ const importmapScriptTextNodeVisitor = (
463
470
  if (format === "systemjs") {
464
471
  typeAttribute.value = "systemjs-importmap"
465
472
  }
466
-
467
473
  const { bufferAfterBuild } = importmapReference.ressource
468
474
  textNode.value = bufferAfterBuild
469
475
  }
@@ -485,38 +491,34 @@ const linkStylesheetHrefVisitor = (
485
491
  if (relAttribute.value !== "stylesheet") {
486
492
  return null
487
493
  }
488
-
494
+ const integrityAttribute = getHtmlNodeAttributeByName(link, "integrity")
495
+ const integrity = integrityAttribute ? integrityAttribute.value : ""
489
496
  const cssReference = notifyReferenceFound({
490
497
  referenceLabel: "html stylesheet link",
491
498
  contentTypeExpected: "text/css",
492
499
  ressourceSpecifier: hrefAttribute.value,
500
+ integrity,
501
+ ...crossoriginFromHtmlNode(link),
493
502
  ...referenceLocationFromHtmlNode(link, "href"),
494
503
  })
495
- return async ({
496
- getUrlRelativeToImporter,
497
- precomputeBuildRelativeUrl,
498
- buildDirectoryUrl,
499
- }) => {
504
+ return async ({ getUrlRelativeToImporter, buildDirectoryUrl }) => {
500
505
  const { ressource } = cssReference
501
-
502
506
  if (ressource.isExternal) {
503
507
  return
504
508
  }
505
-
506
509
  if (shouldInline({ ressource, htmlNode: link })) {
507
510
  const { bufferAfterBuild } = ressource
508
511
  let code = String(bufferAfterBuild)
509
512
  const { buildRelativeUrl } = ressource
510
513
  const cssBuildUrl = resolveUrl(buildRelativeUrl, buildDirectoryUrl)
511
- const htmlUrl = resolveUrl(
512
- precomputeBuildRelativeUrl(htmlRessource),
514
+ const htmlBuildUrl = resolveUrl(
515
+ htmlRessource.buildRelativeUrlWithoutHash,
513
516
  buildDirectoryUrl,
514
517
  )
515
-
516
518
  const moveResult = await moveCssUrls({
517
519
  code,
518
520
  from: cssBuildUrl,
519
- to: htmlUrl,
521
+ to: htmlBuildUrl,
520
522
  // moveCssUrls will change the css source code
521
523
  // Ideally we should update the sourcemap referenced by css
522
524
  // to target the one after css urls are moved.
@@ -527,24 +529,38 @@ const linkStylesheetHrefVisitor = (
527
529
  sourcemapMethod: null,
528
530
  })
529
531
  code = moveResult.code
530
-
531
532
  const sourcemapRelativeUrl = getCssSourceMappingUrl(code)
532
533
  if (sourcemapRelativeUrl) {
533
534
  const cssBuildUrl = resolveUrl(buildRelativeUrl, buildDirectoryUrl)
534
535
  const sourcemapBuildUrl = resolveUrl(sourcemapRelativeUrl, cssBuildUrl)
535
- const sourcemapInlineUrl = urlToRelativeUrl(sourcemapBuildUrl, htmlUrl)
536
+ const sourcemapInlineUrl = urlToRelativeUrl(
537
+ sourcemapBuildUrl,
538
+ htmlBuildUrl,
539
+ )
536
540
  code = setCssSourceMappingUrl(code, sourcemapInlineUrl)
537
541
  }
538
-
539
542
  replaceHtmlNode(link, `<style>${code}</style>`, {
540
- attributesToIgnore: ["href", "rel", "as", "crossorigin", "type"],
543
+ attributesToIgnore: [
544
+ "href",
545
+ "rel",
546
+ "as",
547
+ "crossorigin",
548
+ "type",
549
+ "integrity",
550
+ ],
541
551
  })
542
552
  cssReference.inlinedCallback()
543
553
  return
544
554
  }
545
-
546
555
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
547
556
  hrefAttribute.value = urlRelativeToImporter
557
+ if (integrityAttribute) {
558
+ const base64Value = applyAlgoToRepresentationData(
559
+ "sha256",
560
+ ressource.bufferAfterBuild,
561
+ )
562
+ integrityAttribute.value = `sha256-${base64Value}`
563
+ }
548
564
  }
549
565
  }
550
566
 
@@ -556,7 +572,6 @@ const linkHrefVisitor = (
556
572
  if (!hrefAttribute) {
557
573
  return null
558
574
  }
559
-
560
575
  const href = hrefAttribute.value
561
576
  const relAttribute = getHtmlNodeAttributeByName(link, "rel")
562
577
  const rel = relAttribute ? relAttribute.value : undefined
@@ -567,7 +582,6 @@ const linkHrefVisitor = (
567
582
  "preload",
568
583
  "modulepreload",
569
584
  ].includes(rel)
570
-
571
585
  let contentTypeExpected
572
586
  const typeAttribute = getHtmlNodeAttributeByName(link, "type")
573
587
  const type = typeAttribute ? typeAttribute.value : ""
@@ -580,19 +594,21 @@ const linkHrefVisitor = (
580
594
  contentTypeExpected = "application/javascript"
581
595
  isJsModule = true
582
596
  }
583
-
597
+ const integrityAttribute = getHtmlNodeAttributeByName(link, "integrity")
598
+ const integrity = integrityAttribute ? integrityAttribute.value : ""
584
599
  const linkReference = notifyReferenceFound({
585
600
  referenceLabel: rel ? `html ${rel} link href` : `html link href`,
586
601
  isRessourceHint,
587
602
  contentTypeExpected,
588
603
  ressourceSpecifier: href,
604
+ integrity,
605
+ ...crossoriginFromHtmlNode(link),
589
606
  ...referenceLocationFromHtmlNode(link, "href"),
590
607
  urlVersioningDisabled: contentTypeExpected === "application/manifest+json",
591
608
  isJsModule,
592
609
  })
593
610
  return ({ getUrlRelativeToImporter }) => {
594
611
  const { ressource } = linkReference
595
-
596
612
  if (isRessourceHint) {
597
613
  if (isReferencedOnlyByRessourceHint(ressource)) {
598
614
  ressourceHintNeverUsedCallback({
@@ -604,36 +620,34 @@ const linkHrefVisitor = (
604
620
  // we could remove the HTML node but better keep it untouched and let user decide what to do
605
621
  return
606
622
  }
607
-
608
623
  ressource.inlinedCallbacks.push(() => {
609
624
  removeHtmlNode(link)
610
625
  })
611
626
  }
612
-
613
627
  if (ressource.isExternal) {
614
628
  return
615
629
  }
616
-
617
630
  if (format === "systemjs" && rel === "modulepreload") {
618
631
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
619
- replaceHtmlNode(
620
- link,
621
- `<link rel="preload" href="${urlRelativeToImporter}" as="script" />`,
622
- )
632
+ relAttribute.value = "preload"
633
+ hrefAttribute.value = urlRelativeToImporter
634
+ addHtmlNodeAttribute(link, { name: "as", value: "script" })
623
635
  return
624
636
  }
625
-
626
637
  if (shouldInline({ ressource, htmlNode: link })) {
627
- replaceHtmlNode(
628
- link,
629
- `<link href="${getRessourceAsBase64Url(ressource)}" />`,
630
- )
638
+ removeHtmlNode(link)
631
639
  linkReference.inlinedCallback()
632
640
  return
633
641
  }
634
-
635
642
  const urlRelativeToImporter = getUrlRelativeToImporter(ressource)
636
643
  hrefAttribute.value = urlRelativeToImporter
644
+ if (integrityAttribute) {
645
+ const base64Value = applyAlgoToRepresentationData(
646
+ "sha256",
647
+ ressource.bufferAfterBuild,
648
+ )
649
+ integrityAttribute.value = `sha256-${base64Value}`
650
+ }
637
651
  }
638
652
  }
639
653
 
@@ -647,17 +661,14 @@ const styleTextNodeVisitor = (
647
661
  if (!textNode) {
648
662
  return null
649
663
  }
650
-
664
+ const styleId = getIdForInlineHtmlNode(style, styles)
651
665
  const inlineStyleReference = notifyReferenceFound({
652
666
  referenceLabel: "html style",
653
667
  contentTypeExpected: "text/css",
654
- ressourceSpecifier: getUniqueNameForInlineHtmlNode(
655
- style,
656
- styles,
657
- `${urlToFilename(htmlRessource.url)}__inline__[id].css`,
658
- ),
668
+ ressourceSpecifier: `${urlToFilename(
669
+ htmlRessource.url,
670
+ )}__inline__${styleId}.css`,
659
671
  ...referenceLocationFromHtmlNode(style),
660
-
661
672
  contentType: "text/css",
662
673
  bufferBeforeBuild: Buffer.from(textNode.value),
663
674
  isInline: true,
@@ -673,10 +684,10 @@ const imgSrcVisitor = (img, { notifyReferenceFound }) => {
673
684
  if (!srcAttribute) {
674
685
  return null
675
686
  }
676
-
677
687
  const srcReference = notifyReferenceFound({
678
688
  referenceLabel: "html img src",
679
689
  ressourceSpecifier: srcAttribute.value,
690
+ ...crossoriginFromHtmlNode(img),
680
691
  ...referenceLocationFromHtmlNode(img, "src"),
681
692
  })
682
693
  return ({ getUrlRelativeToImporter }) => {
@@ -694,19 +705,18 @@ const srcsetVisitor = (htmlNode, { notifyReferenceFound }) => {
694
705
  if (!srcsetAttribute) {
695
706
  return null
696
707
  }
697
-
698
708
  const srcsetParts = parseSrcset(srcsetAttribute.value)
699
709
  const srcsetPartsReferences = srcsetParts.map(({ specifier }, index) =>
700
710
  notifyReferenceFound({
701
711
  referenceLabel: `html srcset ${index}`,
702
712
  ressourceSpecifier: specifier,
713
+ ...crossoriginFromHtmlNode(htmlNode),
703
714
  ...referenceLocationFromHtmlNode(htmlNode, "srcset"),
704
715
  }),
705
716
  )
706
717
  if (srcsetParts.length === 0) {
707
718
  return null
708
719
  }
709
-
710
720
  return ({ getUrlRelativeToImporter }) => {
711
721
  srcsetParts.forEach((srcsetPart, index) => {
712
722
  const reference = srcsetPartsReferences[index]
@@ -727,12 +737,12 @@ const sourceSrcVisitor = (source, { notifyReferenceFound }) => {
727
737
  if (!srcAttribute) {
728
738
  return null
729
739
  }
730
-
731
740
  const typeAttribute = getHtmlNodeAttributeByName(source, "type")
732
741
  const srcReference = notifyReferenceFound({
733
742
  referenceLabel: "html source",
734
743
  contentTypeExpected: typeAttribute ? typeAttribute.value : undefined,
735
744
  ressourceSpecifier: srcAttribute.value,
745
+ ...crossoriginFromHtmlNode(source),
736
746
  ...referenceLocationFromHtmlNode(source, "src"),
737
747
  })
738
748
  return ({ getUrlRelativeToImporter }) => {
@@ -757,6 +767,15 @@ const referenceToUrl = ({ reference, htmlNode, getUrlRelativeToImporter }) => {
757
767
  return getUrlRelativeToImporter(ressource)
758
768
  }
759
769
 
770
+ const crossoriginFromHtmlNode = (htmlNode) => {
771
+ const crossOriginAttribute = getHtmlNodeAttributeByName(
772
+ htmlNode,
773
+ "crossorigin",
774
+ )
775
+ const crossorigin = crossOriginAttribute ? crossOriginAttribute.value : ""
776
+ return { crossorigin }
777
+ }
778
+
760
779
  const referenceLocationFromHtmlNode = (htmlNode, htmlAttributeName) => {
761
780
  const locInfo = getHtmlNodeLocation(htmlNode, htmlAttributeName)
762
781
  return locInfo
@@ -1,6 +1,7 @@
1
1
  import { urlToFilename, resolveUrl, urlToRelativeUrl } from "@jsenv/filesystem"
2
2
 
3
3
  import {
4
+ generateSourcemapUrl,
4
5
  getJavaScriptSourceMappingUrl,
5
6
  setJavaScriptSourceMappingUrl,
6
7
  } from "@jsenv/core/src/internal/sourceMappingURLUtils.js"
@@ -32,7 +33,7 @@ export const parseJsRessource = async (
32
33
  sourcemapReference = notifyReferenceFound({
33
34
  referenceLabel: "js sourcemapping comment",
34
35
  contentType: "application/octet-stream",
35
- ressourceSpecifier: `${urlToFilename(jsUrl)}.map`,
36
+ ressourceSpecifier: urlToRelativeUrl(generateSourcemapUrl(jsUrl), jsUrl),
36
37
  isPlaceholder: true,
37
38
  isSourcemap: true,
38
39
  })
@@ -40,7 +41,6 @@ export const parseJsRessource = async (
40
41
 
41
42
  return async ({ buildDirectoryUrl }) => {
42
43
  const sourcemapRessource = sourcemapReference.ressource
43
-
44
44
  let code
45
45
  let map
46
46
  if (!sourcemapRessource.isPlaceholder) {
@@ -92,15 +92,12 @@ export const parseJsRessource = async (
92
92
  jsRessource.buildRelativeUrl,
93
93
  buildDirectoryUrl,
94
94
  )
95
- const sourcemapPrecomputedBuildUrl = resolveUrl(
96
- `${urlToFilename(jsBuildUrl)}.map`,
97
- jsBuildUrl,
98
- )
95
+ const sourcemapPrecomputedBuildUrl = generateSourcemapUrl(jsBuildUrl)
99
96
  map.file = urlToFilename(jsBuildUrl)
100
97
  if (map.sources) {
101
98
  map.sources = map.sources.map((source) => {
102
99
  const sourceUrl = resolveUrl(source, jsUrl)
103
- const sourceOriginalUrl = asOriginalUrl(sourceUrl)
100
+ const sourceOriginalUrl = asOriginalUrl(sourceUrl) || sourceUrl
104
101
  const sourceUrlRelativeToSourceMap = urlToRelativeUrl(
105
102
  sourceOriginalUrl,
106
103
  sourcemapPrecomputedBuildUrl,
@@ -27,6 +27,7 @@ export const parseRessource = async (
27
27
  notifiers,
28
28
  {
29
29
  projectDirectoryUrl,
30
+ jsenvRemoteDirectory,
30
31
  format,
31
32
  systemJsUrl,
32
33
  asProjectUrl,
@@ -125,6 +126,7 @@ export const parseRessource = async (
125
126
 
126
127
  if (contentType === "text/css") {
127
128
  return parseCssRessource(ressource, notifiers, {
129
+ jsenvRemoteDirectory,
128
130
  asProjectUrl,
129
131
  asOriginalUrl,
130
132
  asOriginalServerUrl,
@@ -156,6 +158,7 @@ export const parseRessource = async (
156
158
  ) {
157
159
  return parseJsRessource(ressource, notifiers, {
158
160
  projectDirectoryUrl,
161
+ jsenvRemoteDirectory,
159
162
  asProjectUrl,
160
163
  asOriginalUrl,
161
164
  asOriginalServerUrl,