@jsenv/core 24.2.2 → 24.4.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 (156) hide show
  1. package/dist/browser_runtime/browser_runtime-fbd309a1.js +5137 -0
  2. package/dist/browser_runtime/browser_runtime-fbd309a1.js.map +1064 -0
  3. package/dist/{jsenv_browser_system.js → browser_system/browser_system-29eda202.js} +12 -12
  4. package/dist/{jsenv_browser_system.js.map → browser_system/browser_system-29eda202.js.map} +64 -64
  5. package/dist/build_manifest.js +12 -0
  6. package/dist/compile_proxy/assets/s.js-749702e8.map +242 -0
  7. package/dist/compile_proxy/compile_proxy-405777e6.html +2074 -0
  8. package/dist/compile_proxy/compile_proxy.html__inline__20-39c0801c.js.map +385 -0
  9. package/dist/{jsenv_event_source_client.js → event_source_client/event_source_client-9f14c8b9.js} +39 -21
  10. package/dist/event_source_client/event_source_client-9f14c8b9.js.map +127 -0
  11. package/dist/redirector/assets/s.js-749702e8.map +242 -0
  12. package/dist/redirector/redirector-237cd168.html +2118 -0
  13. package/dist/redirector/redirector.html__inline__15-33acb0b9.js.map +390 -0
  14. package/dist/toolbar/assets/compilation.css-209d68b4.map +12 -0
  15. package/dist/toolbar/assets/eventsource.css-38cd0a36.map +12 -0
  16. package/dist/toolbar/assets/execution.css-0ebe522f.map +12 -0
  17. package/dist/toolbar/assets/focus.css-3f9c156d.map +12 -0
  18. package/dist/toolbar/assets/light-theme.css-78b19a80.map +12 -0
  19. package/dist/toolbar/assets/overflow-menu.css-d9688a1c.map +12 -0
  20. package/dist/toolbar/assets/s.js-749702e8.map +242 -0
  21. package/dist/toolbar/assets/settings.css-2b81b245.map +12 -0
  22. package/dist/toolbar/assets/toolbar.main.css-846920e9.map +28 -0
  23. package/dist/toolbar/assets/tooltip.css-03395ee6.map +12 -0
  24. package/dist/toolbar/toolbar-29e91dcd.html +4779 -0
  25. package/dist/toolbar/toolbar.main-53e1ab2b.js.map +795 -0
  26. package/dist/toolbar_injector/assets/jsenv-logo-188b9ca6.svg +95 -0
  27. package/dist/{jsenv_toolbar_injector.js → toolbar_injector/toolbar_injector-0af91b43.js} +87 -65
  28. package/dist/toolbar_injector/toolbar_injector-0af91b43.js.map +294 -0
  29. package/main.js +0 -1
  30. package/package.json +2 -1
  31. package/readme.md +10 -7
  32. package/src/buildProject.js +6 -2
  33. package/src/dev_server.js +22 -130
  34. package/src/execute.js +7 -10
  35. package/src/executeTestPlan.js +7 -1
  36. package/src/importUsingChildProcess.js +1 -1
  37. package/src/internal/{runtime/detectBrowser/detectBrowser.js → browser_detection/browser_detection.js} +0 -0
  38. package/src/internal/{runtime/detectBrowser → browser_detection}/detectAndroid.js +0 -0
  39. package/src/internal/{runtime/detectBrowser → browser_detection}/detectChrome.js +0 -0
  40. package/src/internal/{runtime/detectBrowser → browser_detection}/detectEdge.js +0 -0
  41. package/src/internal/{runtime/detectBrowser → browser_detection}/detectElectron.js +0 -0
  42. package/src/internal/{runtime/detectBrowser → browser_detection}/detectFirefox.js +0 -0
  43. package/src/internal/{runtime/detectBrowser → browser_detection}/detectIOS.js +0 -0
  44. package/src/internal/{runtime/detectBrowser → browser_detection}/detectInternetExplorer.js +0 -0
  45. package/src/internal/{runtime/detectBrowser → browser_detection}/detectOpera.js +0 -0
  46. package/src/internal/{runtime/detectBrowser → browser_detection}/detectSafari.js +0 -0
  47. package/src/internal/{runtime/detectBrowser → browser_detection}/util.js +0 -0
  48. package/src/internal/{runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js → browser_feature_detection/browser_feature_detection.js} +116 -81
  49. package/src/internal/browser_feature_detection/compile_proxy.html +27 -0
  50. package/src/internal/browser_launcher/browser_runtime_report.js +75 -0
  51. package/src/internal/{browser-launcher → browser_launcher}/executeHtmlFile.js +13 -16
  52. package/src/internal/browser_launcher/from_playwright.js +314 -0
  53. package/src/internal/{browser-launcher → browser_launcher}/trackPageToNotify.js +0 -0
  54. package/src/internal/{browser-launcher/jsenv-browser-system.js → browser_runtime/browser_runtime.js} +4 -4
  55. package/src/internal/{runtime/createBrowserRuntime/createBrowserSystem.js → browser_runtime/browser_system.js} +3 -2
  56. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/createBrowserRuntime.js +7 -5
  57. package/src/internal/{browser-launcher → browser_runtime}/displayErrorInDocument.js +0 -0
  58. package/src/internal/{browser-launcher → browser_runtime}/displayErrorNotification.js +2 -4
  59. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/evalSource.js +2 -0
  60. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/makeNamespaceTransferable.js +0 -0
  61. package/src/internal/{browser-utils → browser_utils}/fetch-browser.js +2 -0
  62. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingFetch.js +3 -0
  63. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingScript.js +2 -0
  64. package/src/internal/{browser-utils → browser_utils}/fetchJson.js +0 -0
  65. package/src/internal/{browser-utils → browser_utils}/fetchUsingXHR.js +4 -4
  66. package/src/internal/building/buildUsingRollup.js +4 -0
  67. package/src/internal/building/createJsenvRollupPlugin.js +19 -9
  68. package/src/internal/building/css/applyPostCss.js +19 -8
  69. package/src/internal/building/css/moveCssUrls.js +44 -0
  70. package/src/internal/building/css/parseCssRessource.js +67 -17
  71. package/src/internal/building/css/parseCssUrls.js +29 -23
  72. package/src/internal/building/css/postcss_plugin_url_visitor.js +11 -20
  73. package/src/internal/building/css/replaceCssUrls.js +38 -19
  74. package/src/internal/building/css_module.js +6 -10
  75. package/src/internal/building/html/parseHtmlRessource.js +37 -11
  76. package/src/internal/building/parseRessource.js +3 -0
  77. package/src/internal/building/ressource_builder.js +12 -3
  78. package/src/internal/compiling/babel_plugin_import_assertions.js +1 -2
  79. package/src/internal/compiling/html_source_file_service.js +23 -21
  80. package/src/internal/compiling/jsenvCompilerForHtml.js +15 -22
  81. package/src/internal/compiling/startCompileServer.js +37 -32
  82. package/src/internal/dev_server/event_source_client/event_source_connection.js +28 -19
  83. package/src/internal/dev_server/exploring/exploring.html +7 -2
  84. package/src/internal/dev_server/exploring/fetchExploringJson.js +4 -9
  85. package/src/internal/dev_server/redirector/redirector.html +37 -2
  86. package/src/internal/dev_server/toolbar/compilation/toolbar.compilation.js +4 -7
  87. package/src/internal/dev_server/toolbar/eventsource/toolbar.eventsource.js +2 -2
  88. package/src/internal/dev_server/toolbar/notification/toolbar.notification.js +75 -44
  89. package/src/internal/dev_server/toolbar/toolbar.html +31 -5
  90. package/src/internal/dev_server/toolbar/toolbar.injector.js +55 -36
  91. package/src/internal/dev_server/toolbar/toolbar.main.js +45 -31
  92. package/src/internal/dev_server/toolbar/util/fetching.js +1 -1
  93. package/src/internal/executing/executeConcurrently.js +15 -11
  94. package/src/internal/executing/executePlan.js +3 -2
  95. package/src/internal/generateGroupMap/one_runtime_compat.js +1 -1
  96. package/src/internal/generateGroupMap/runtime_compat_composition.js +1 -1
  97. package/src/internal/generateGroupMap/runtime_support.js +1 -1
  98. package/src/internal/jsenvInternalFiles.js +0 -26
  99. package/src/internal/jsenv_builds.js +19 -0
  100. package/src/internal/{runtime/node-feature-detect/feature-detect-dynamic-import.mjs → node_feature_detection/feature_detect_dynamic_import.mjs} +0 -0
  101. package/src/internal/{runtime/node-feature-detect/feature-detect-top-level-await.mjs → node_feature_detection/feature_detect_top_level_await.mjs} +0 -0
  102. package/src/internal/{runtime/node-feature-detect → node_feature_detection}/nodeSupportsDynamicImport.js +0 -0
  103. package/src/internal/node_feature_detection/nodeSupportsTopLevelAwait.js +16 -0
  104. package/src/internal/{runtime/createNodeRuntime/scanNodeRuntimeFeatures.js → node_feature_detection/node_feature_detection.js} +12 -13
  105. package/src/internal/{node-launcher → node_launcher}/createChildProcessOptions.js +0 -0
  106. package/src/internal/{node-launcher → node_launcher}/createControllableNodeProcess.js +9 -14
  107. package/src/internal/{node-launcher → node_launcher}/kill_process_tree.js +0 -0
  108. package/src/internal/node_launcher/node_runtime_report.js +71 -0
  109. package/src/internal/{node-launcher → node_launcher}/processOptions.js +0 -0
  110. package/src/internal/{runtime/detectNode → node_runtime}/detectNode.js +0 -0
  111. package/src/internal/{runtime/createNodeRuntime → node_runtime}/evalSource.js +1 -1
  112. package/src/internal/{runtime/createNodeRuntime → node_runtime}/fetchSource.js +1 -1
  113. package/src/internal/{node-launcher → node_runtime}/nodeControllableFile.mjs +14 -11
  114. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithDynamicImport.js → node_runtime/node_execution_dynamic_import.js} +34 -6
  115. package/src/internal/node_runtime/node_execution_performance.js +67 -0
  116. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithSystemJs.js → node_runtime/node_execution_systemjs.js} +38 -24
  117. package/src/internal/{runtime/createNodeRuntime/createNodeSystem.js → node_runtime/node_system.js} +4 -4
  118. package/src/internal/runtime/computeCompileIdFromGroupId.js +1 -0
  119. package/src/internal/runtime/resolveGroup.js +1 -1
  120. package/src/internal/runtime/resolveRuntimeGroup.js +2 -2
  121. package/src/internal/{semantic-versioning → semantic_versioning}/findHighestVersion.js +0 -0
  122. package/src/internal/{semantic-versioning → semantic_versioning}/findLowestVersion.js +0 -0
  123. package/src/internal/{semantic-versioning → semantic_versioning}/index.js +0 -0
  124. package/src/internal/{semantic-versioning → semantic_versioning}/valueToVersion.js +0 -0
  125. package/src/internal/{semantic-versioning → semantic_versioning}/versionCompare.js +0 -0
  126. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsAbove.js +0 -0
  127. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsBelow.js +0 -0
  128. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsEqual.js +0 -0
  129. package/src/launchBrowser.js +33 -492
  130. package/src/launchNode.js +36 -7
  131. package/src/requireUsingChildProcess.js +1 -1
  132. package/dist/jsenv_compile_proxy.js +0 -1339
  133. package/dist/jsenv_compile_proxy.js.map +0 -378
  134. package/dist/jsenv_event_source_client.js.map +0 -126
  135. package/dist/jsenv_exploring_index.js +0 -1092
  136. package/dist/jsenv_exploring_index.js.map +0 -353
  137. package/dist/jsenv_exploring_redirector.js +0 -1386
  138. package/dist/jsenv_exploring_redirector.js.map +0 -384
  139. package/dist/jsenv_redirector.js +0 -1388
  140. package/dist/jsenv_redirector.js.map +0 -384
  141. package/dist/jsenv_toolbar.js +0 -2880
  142. package/dist/jsenv_toolbar.js.map +0 -771
  143. package/dist/jsenv_toolbar_injector.js.map +0 -301
  144. package/src/internal/browser-launcher/createSharing.js +0 -70
  145. package/src/internal/browser-launcher/jsenv_compile_proxy.html +0 -13
  146. package/src/internal/browser-launcher/jsenv_compile_proxy.js +0 -5
  147. package/src/internal/dev_server/event_source_client/event_source_client_file_info.js +0 -17
  148. package/src/internal/dev_server/exploring/exploring_file_info.js +0 -21
  149. package/src/internal/dev_server/redirector/redirector.js +0 -30
  150. package/src/internal/dev_server/redirector/redirector_file_info.js +0 -24
  151. package/src/internal/dev_server/toolbar/backtolist/toolbar.backtolist.js +0 -33
  152. package/src/internal/dev_server/toolbar/toolbar_file_info.js +0 -37
  153. package/src/internal/node-launcher/node-js-file.js +0 -110
  154. package/src/internal/runtime/createNodeRuntime/createNodeRuntime.js +0 -32
  155. package/src/internal/runtime/node-feature-detect/nodeSupportsTopLevelAwait.js +0 -18
  156. package/src/nodeRuntime.js +0 -5
@@ -1,23 +1,35 @@
1
1
  import { urlToFileSystemPath } from "@jsenv/filesystem"
2
2
 
3
- export const applyPostCss = async (
4
- cssString,
5
- cssUrl,
3
+ export const applyPostCss = async ({
4
+ code,
5
+ url,
6
+ map,
7
+ sourcemapMethod = "comment",
6
8
  plugins,
7
9
  // https://github.com/postcss/postcss#options
8
10
  options = {},
9
- ) => {
11
+ }) => {
10
12
  const { default: postcss } = await import("postcss")
11
13
 
12
- let result
13
14
  try {
14
- const cssFileUrl = urlToFileUrl(cssUrl)
15
- result = await postcss(plugins).process(cssString, {
15
+ const cssFileUrl = urlToFileUrl(url)
16
+ const result = await postcss(plugins).process(code, {
16
17
  collectUrls: true,
17
18
  from: urlToFileSystemPath(cssFileUrl),
18
19
  to: urlToFileSystemPath(cssFileUrl),
20
+ map: {
21
+ annotation: sourcemapMethod === "comment",
22
+ inline: sourcemapMethod === "inline",
23
+ // https://postcss.org/api/#sourcemapoptions
24
+ ...(map ? { prev: JSON.stringify(map) } : {}),
25
+ },
19
26
  ...options,
20
27
  })
28
+ return {
29
+ code: result.css,
30
+ map: result.map.toJSON(),
31
+ postCssMessages: result.messages,
32
+ }
21
33
  } catch (error) {
22
34
  if (error.name === "CssSyntaxError") {
23
35
  console.error(String(error))
@@ -25,7 +37,6 @@ export const applyPostCss = async (
25
37
  }
26
38
  throw error
27
39
  }
28
- return result
29
40
  }
30
41
 
31
42
  // the goal of this function is to take an url that is likely an http url
@@ -0,0 +1,44 @@
1
+ import { urlToRelativeUrl } from "@jsenv/filesystem"
2
+
3
+ import { applyPostCss } from "./applyPostCss.js"
4
+ import { postCssPluginUrlVisitor } from "./postcss_plugin_url_visitor.js"
5
+
6
+ export const moveCssUrls = async ({
7
+ code,
8
+ from,
9
+ to,
10
+ map,
11
+ sourcemapMethod,
12
+ } = {}) => {
13
+ const fromDirectoryUrl = new URL("./", from).href
14
+ const toDirectoryUrl = new URL("./", to).href
15
+ // same directory, nothing to do
16
+ if (fromDirectoryUrl === toDirectoryUrl) {
17
+ return { code, map }
18
+ }
19
+
20
+ const result = await applyPostCss({
21
+ code,
22
+ url: from,
23
+ map,
24
+ sourcemapMethod,
25
+ plugins: [
26
+ postCssPluginUrlVisitor({
27
+ urlVisitor: ({ specifier }) => {
28
+ if (specifier[0] === "#") {
29
+ return null
30
+ }
31
+ const url = new URL(specifier, fromDirectoryUrl).href
32
+ const relativeUrl = urlToRelativeUrl(url, toDirectoryUrl)
33
+ return relativeUrl
34
+ },
35
+ }),
36
+ ],
37
+ })
38
+ code = result.code
39
+ map = result.map
40
+ return {
41
+ code,
42
+ map,
43
+ }
44
+ }
@@ -1,4 +1,9 @@
1
- import { urlToFilename, urlToRelativeUrl, resolveUrl } from "@jsenv/filesystem"
1
+ import {
2
+ urlToFilename,
3
+ urlToRelativeUrl,
4
+ resolveUrl,
5
+ fileSystemPathToUrl,
6
+ } from "@jsenv/filesystem"
2
7
 
3
8
  import {
4
9
  getCssSourceMappingUrl,
@@ -7,14 +12,18 @@ import {
7
12
  import { getRessourceAsBase64Url } from "../ressource_builder_util.js"
8
13
  import { parseCssUrls } from "./parseCssUrls.js"
9
14
  import { replaceCssUrls } from "./replaceCssUrls.js"
15
+ import { moveCssUrls } from "./moveCssUrls.js"
10
16
 
11
17
  export const parseCssRessource = async (
12
18
  cssRessource,
13
19
  { notifyReferenceFound },
14
- { asProjectUrl, asOriginalUrl, minify, minifyCssOptions },
20
+ { asProjectUrl, asOriginalUrl, minify, minifyCssOptions, cssConcatenation },
15
21
  ) => {
16
22
  const cssString = String(cssRessource.bufferBeforeBuild)
17
23
  const cssSourcemapUrl = getCssSourceMappingUrl(cssString)
24
+ const url = cssRessource.url
25
+ let code = cssString
26
+ let map
18
27
  let sourcemapReference
19
28
  if (cssSourcemapUrl) {
20
29
  sourcemapReference = notifyReferenceFound({
@@ -26,6 +35,8 @@ export const parseCssRessource = async (
26
35
  referenceColumn: 0,
27
36
  isSourcemap: true,
28
37
  })
38
+ await sourcemapReference.ressource.getBufferAvailablePromise()
39
+ map = JSON.parse(String(sourcemapReference.ressource.bufferBeforeBuild))
29
40
  } else {
30
41
  sourcemapReference = notifyReferenceFound({
31
42
  contentType: "application/octet-stream",
@@ -35,20 +46,25 @@ export const parseCssRessource = async (
35
46
  })
36
47
  }
37
48
 
38
- const { atImports, urlDeclarations } = await parseCssUrls(
39
- cssString,
40
- cssRessource.url,
41
- )
42
-
49
+ const { atImports, urlDeclarations } = await parseCssUrls({
50
+ code,
51
+ url,
52
+ })
43
53
  const urlNodeReferenceMapping = new Map()
54
+ const atImportReferences = []
44
55
  atImports.forEach((atImport) => {
45
56
  const importReference = notifyReferenceFound({
46
57
  ressourceSpecifier: atImport.specifier,
47
58
  ...cssNodeToReferenceLocation(atImport.urlDeclarationNode),
48
59
  })
49
60
  urlNodeReferenceMapping.set(atImport.urlNode, importReference)
61
+ atImportReferences.push(importReference)
50
62
  })
51
63
  urlDeclarations.forEach((urlDeclaration) => {
64
+ if (urlDeclaration.specifier[0] === "#") {
65
+ return
66
+ }
67
+
52
68
  const urlReference = notifyReferenceFound({
53
69
  ressourceSpecifier: urlDeclaration.specifier,
54
70
  ...cssNodeToReferenceLocation(urlDeclaration.urlDeclarationNode),
@@ -56,22 +72,20 @@ export const parseCssRessource = async (
56
72
  urlNodeReferenceMapping.set(urlDeclaration.urlNode, urlReference)
57
73
  })
58
74
 
59
- return async ({ getUrlRelativeToImporter, buildDirectoryUrl }) => {
75
+ return async ({
76
+ getUrlRelativeToImporter,
77
+ precomputeBuildRelativeUrl,
78
+ buildDirectoryUrl,
79
+ }) => {
60
80
  const sourcemapRessource = sourcemapReference.ressource
61
-
62
- let code = cssString
63
- let map = sourcemapRessource.isPlaceholder
64
- ? undefined
65
- : JSON.parse(String(sourcemapRessource.bufferBeforeBuild))
66
-
67
81
  const cssCompiledUrl = cssRessource.url
68
82
  const cssOriginalUrl = asOriginalUrl(cssCompiledUrl)
69
83
 
70
84
  const replaceCssResult = await replaceCssUrls({
71
- url: map ? asProjectUrl(cssCompiledUrl) : cssOriginalUrl,
72
- code: cssString,
85
+ url: asProjectUrl(cssCompiledUrl),
86
+ code,
73
87
  map,
74
- getUrlReplacementValue: ({ urlNode }) => {
88
+ urlVisitor: ({ urlNode }) => {
75
89
  const nodeCandidates = Array.from(urlNodeReferenceMapping.keys())
76
90
  const urlNodeFound = nodeCandidates.find((urlNodeCandidate) =>
77
91
  isSameCssDocumentUrlNode(urlNodeCandidate, urlNode),
@@ -95,6 +109,42 @@ export const parseCssRessource = async (
95
109
  }
96
110
  return getUrlRelativeToImporter(cssUrlRessource)
97
111
  },
112
+ cssConcatenation,
113
+ loadCssImport: async (path) => {
114
+ // const cssFileUrl = asProjectUrl(url)
115
+ const importedCssFileUrl = fileSystemPathToUrl(path)
116
+ const atImportReference = atImportReferences.find(
117
+ (atImportReference) => {
118
+ return (
119
+ asProjectUrl(atImportReference.ressource.url) ===
120
+ importedCssFileUrl
121
+ )
122
+ },
123
+ )
124
+ atImportReference.inlinedCallback()
125
+ let code = String(atImportReference.ressource.bufferAfterBuild)
126
+ const moveResult = await moveCssUrls({
127
+ code,
128
+ from: resolveUrl(
129
+ atImportReference.ressource.buildRelativeUrl,
130
+ buildDirectoryUrl,
131
+ ),
132
+ to: resolveUrl(
133
+ precomputeBuildRelativeUrl(cssRessource),
134
+ buildDirectoryUrl,
135
+ ),
136
+ // moveCssUrls will change the css source code
137
+ // Ideally we should update the sourcemap referenced by css
138
+ // to target the one after css urls are moved.
139
+ // It means we should force sourcemap ressource to the new one
140
+ // until it's supported we prevent postcss from updating the
141
+ // sourcemap comment, othwise css would reference a sourcemap
142
+ // that won't by in the build directory
143
+ sourcemapMethod: null,
144
+ })
145
+ code = moveResult.code
146
+ return code
147
+ },
98
148
  cssMinification: minify,
99
149
  cssMinificationOptions: minifyCssOptions,
100
150
  })
@@ -1,32 +1,38 @@
1
1
  import { applyPostCss } from "./applyPostCss.js"
2
2
  import { postCssPluginUrlVisitor } from "./postcss_plugin_url_visitor.js"
3
3
 
4
- export const parseCssUrls = async (css, cssUrl = "file:///file.css") => {
4
+ export const parseCssUrls = async ({ code, url = "file:///file.css" }) => {
5
5
  const atImports = []
6
6
  const urlDeclarations = []
7
-
8
- const postCssPlugins = [postCssPluginUrlVisitor]
9
- const postCssOptions = { collectUrls: true }
10
- const result = await applyPostCss(css, cssUrl, postCssPlugins, postCssOptions)
11
-
12
- result.messages.forEach(
13
- ({ type, specifier, atImportNode, declarationNode, urlNode }) => {
14
- if (type === "import") {
15
- atImports.push({
7
+ await applyPostCss({
8
+ code,
9
+ url,
10
+ plugins: [
11
+ postCssPluginUrlVisitor({
12
+ urlVisitor: ({
13
+ type,
16
14
  specifier,
15
+ atImportNode,
16
+ declarationNode,
17
17
  urlNode,
18
- urlDeclarationNode: atImportNode,
19
- })
20
- }
21
- if (type === "asset") {
22
- urlDeclarations.push({
23
- specifier,
24
- urlNode,
25
- urlDeclarationNode: declarationNode,
26
- })
27
- }
28
- },
29
- )
30
-
18
+ }) => {
19
+ if (type === "import") {
20
+ atImports.push({
21
+ specifier,
22
+ urlNode,
23
+ urlDeclarationNode: atImportNode,
24
+ })
25
+ }
26
+ if (type === "asset") {
27
+ urlDeclarations.push({
28
+ specifier,
29
+ urlNode,
30
+ urlDeclarationNode: declarationNode,
31
+ })
32
+ }
33
+ },
34
+ }),
35
+ ],
36
+ })
31
37
  return { atImports, urlDeclarations }
32
38
  }
@@ -14,18 +14,14 @@ hence sourcemap cannot point the original source location
14
14
  import { fileSystemPathToUrl, resolveUrl } from "@jsenv/filesystem"
15
15
  import { require } from "@jsenv/core/src/internal/require.js"
16
16
 
17
- export const postCssPluginUrlVisitor = () => {
17
+ export const postCssPluginUrlVisitor = ({ urlVisitor = () => null }) => {
18
18
  const parseCssValue = require("postcss-value-parser")
19
19
  const stringifyCssNodes = parseCssValue.stringify
20
20
 
21
21
  return {
22
22
  postcssPlugin: "url_visitor",
23
23
  prepare: (result) => {
24
- const {
25
- from,
26
- collectUrls = false,
27
- getUrlReplacementValue = () => undefined,
28
- } = result.opts
24
+ const { from } = result.opts
29
25
  const fromUrl = fileSystemPathToUrl(from)
30
26
  const mutations = []
31
27
  return {
@@ -109,9 +105,12 @@ export const postCssPluginUrlVisitor = () => {
109
105
  atImportNode,
110
106
  urlNode,
111
107
  }
112
- const urlNewValue = getUrlReplacementValue(urlReference)
113
- if (urlNewValue && urlNewValue !== urlNode.value) {
114
- urlNode.value = urlNewValue
108
+ const urlVisitorReturnValue = urlVisitor(urlReference)
109
+ if (
110
+ urlVisitorReturnValue &&
111
+ urlVisitorReturnValue !== urlNode.value
112
+ ) {
113
+ urlNode.value = urlVisitorReturnValue
115
114
  const newParams = parsed.toString()
116
115
  const newAtImportRule = new AtRule({
117
116
  name: "import",
@@ -120,10 +119,6 @@ export const postCssPluginUrlVisitor = () => {
120
119
  })
121
120
  atImportNode.replaceWith(newAtImportRule)
122
121
  }
123
-
124
- if (collectUrls) {
125
- result.messages.push(urlReference)
126
- }
127
122
  },
128
123
  },
129
124
  Declaration: (declarationNode) => {
@@ -158,14 +153,10 @@ export const postCssPluginUrlVisitor = () => {
158
153
  urlNode,
159
154
  }
160
155
 
161
- if (collectUrls) {
162
- result.messages.push(urlReference)
163
- }
164
-
165
- const urlNewValue = getUrlReplacementValue(urlReference)
166
- if (urlNewValue) {
156
+ const urlVisitorReturnValue = urlVisitor(urlReference)
157
+ if (urlVisitorReturnValue) {
167
158
  urlMutations.push(() => {
168
- urlNode.value = urlNewValue
159
+ urlNode.value = urlVisitorReturnValue
169
160
  })
170
161
  }
171
162
  },
@@ -1,3 +1,8 @@
1
+ import {
2
+ assertAndNormalizeDirectoryUrl,
3
+ urlToFileSystemPath,
4
+ } from "@jsenv/filesystem"
5
+
1
6
  import { require } from "@jsenv/core/src/internal/require.js"
2
7
  import { applyPostCss } from "./applyPostCss.js"
3
8
  import { postCssPluginUrlVisitor } from "./postcss_plugin_url_visitor.js"
@@ -6,32 +11,46 @@ export const replaceCssUrls = async ({
6
11
  url,
7
12
  code,
8
13
  map,
9
- getUrlReplacementValue,
14
+ urlVisitor,
15
+ cssConcatenation = false,
16
+ loadCssImport,
10
17
  cssMinification = false,
11
18
  cssMinificationOptions,
12
19
  } = {}) => {
13
- const postcssPlugins = [
14
- postCssPluginUrlVisitor,
15
- ...(cssMinification
16
- ? [await getCssMinificationPlugin(cssMinificationOptions)]
17
- : []),
18
- ]
19
- const postcssOptions = {
20
- getUrlReplacementValue,
21
- map: {
22
- inline: false,
23
- // https://postcss.org/api/#sourcemapoptions
24
- ...(map ? { prev: JSON.stringify(map) } : {}),
25
- },
26
- }
27
- const result = await applyPostCss(code, url, postcssPlugins, postcssOptions)
28
-
20
+ const result = await applyPostCss({
21
+ code,
22
+ url,
23
+ plugins: [
24
+ postCssPluginUrlVisitor({ urlVisitor }),
25
+ ...(cssConcatenation
26
+ ? [await getCssConcatenationPlugin({ url, loadCssImport })]
27
+ : []),
28
+ ...(cssMinification
29
+ ? [await getCssMinificationPlugin(cssMinificationOptions)]
30
+ : []),
31
+ ],
32
+ })
33
+ code = result.code
34
+ map = result.map
29
35
  return {
30
- code: result.css,
31
- map: result.map.toJSON(),
36
+ code,
37
+ map,
32
38
  }
33
39
  }
34
40
 
41
+ const getCssConcatenationPlugin = async ({ loadCssImport }) => {
42
+ const postcssImport = require("postcss-import")
43
+ return postcssImport({
44
+ resolve: (id, basedir) => {
45
+ const url = new URL(id, assertAndNormalizeDirectoryUrl(basedir)).href
46
+ return urlToFileSystemPath(url)
47
+ },
48
+ load: (id) => {
49
+ return loadCssImport(id)
50
+ },
51
+ })
52
+ }
53
+
35
54
  const getCssMinificationPlugin = async (cssMinificationOptions = {}) => {
36
55
  const cssnano = require("cssnano")
37
56
  const cssnanoDefaultPreset = require("cssnano-preset-default")
@@ -1,6 +1,6 @@
1
1
  import { resolveUrl, urlToRelativeUrl } from "@jsenv/filesystem"
2
2
 
3
- import { replaceCssUrls } from "@jsenv/core/src/internal/building/css/replaceCssUrls.js"
3
+ import { moveCssUrls } from "@jsenv/core/src/internal/building/css/moveCssUrls.js"
4
4
  import { escapeTemplateStringSpecialCharacters } from "@jsenv/core/src/internal/escapeTemplateStringSpecialCharacters.js"
5
5
  import {
6
6
  getCssSourceMappingUrl,
@@ -16,18 +16,14 @@ export const convertCssTextToJavascriptModule = async ({
16
16
  const directoryUrl = resolveUrl("./", cssUrl)
17
17
  const jsDirectoryUrl = resolveUrl("./", jsUrl)
18
18
  if (directoryUrl !== jsDirectoryUrl) {
19
- const cssUrlReplaceResult = await replaceCssUrls({
20
- url: cssUrl,
19
+ const moveUrlResult = await moveCssUrls({
20
+ from: cssUrl,
21
+ to: jsUrl,
21
22
  code,
22
23
  map,
23
- getUrlReplacementValue: ({ specifier }) => {
24
- const urlForCss = resolveUrl(specifier, cssUrl)
25
- const urlForJs = urlToRelativeUrl(urlForCss, jsUrl)
26
- return urlForJs
27
- },
28
24
  })
29
- code = cssUrlReplaceResult.code
30
- map = cssUrlReplaceResult.map
25
+ code = moveUrlResult.code
26
+ map = moveUrlResult.map
31
27
  const sourcemapUrlSpecifier = getCssSourceMappingUrl(code)
32
28
  const sourcemapUrlForCss = resolveUrl(sourcemapUrlSpecifier, cssUrl)
33
29
  const sourcemapUrlForJs = urlToRelativeUrl(sourcemapUrlForCss, jsUrl)
@@ -51,6 +51,7 @@ import {
51
51
  import { collectNodesMutations } from "../parsing.utils.js"
52
52
 
53
53
  import { collectSvgMutations } from "../svg/parseSvgRessource.js"
54
+ import { moveCssUrls } from "../css/moveCssUrls.js"
54
55
 
55
56
  export const parseHtmlRessource = async (
56
57
  htmlRessource,
@@ -144,11 +145,12 @@ export const parseHtmlRessource = async (
144
145
  ]
145
146
 
146
147
  return async (params) => {
147
- htmlMutations.forEach((mutationCallback) => {
148
- mutationCallback({
148
+ await htmlMutations.reduce(async (previous, mutationCallback) => {
149
+ await previous
150
+ await mutationCallback({
149
151
  ...params,
150
152
  })
151
- })
153
+ }, Promise.resolve())
152
154
 
153
155
  const htmlAfterTransformation = htmlAstToHtmlString(htmlAst)
154
156
  const html = minify
@@ -507,7 +509,11 @@ const linkStylesheetHrefVisitor = (
507
509
  ressourceSpecifier: hrefAttribute.value,
508
510
  ...referenceLocationFromHtmlNode(link, "href"),
509
511
  })
510
- return ({ getUrlRelativeToImporter }) => {
512
+ return async ({
513
+ getUrlRelativeToImporter,
514
+ precomputeBuildRelativeUrl,
515
+ buildDirectoryUrl,
516
+ }) => {
511
517
  const { ressource } = cssReference
512
518
 
513
519
  if (ressource.isExternal) {
@@ -516,18 +522,38 @@ const linkStylesheetHrefVisitor = (
516
522
 
517
523
  if (shouldInline({ ressource, htmlNode: link })) {
518
524
  const { bufferAfterBuild } = ressource
519
- let cssString = String(bufferAfterBuild)
520
- const sourcemapRelativeUrl = getCssSourceMappingUrl(cssString)
525
+ let code = String(bufferAfterBuild)
526
+ const { buildRelativeUrl } = ressource
527
+ const cssBuildUrl = resolveUrl(buildRelativeUrl, buildDirectoryUrl)
528
+ const htmlUrl = resolveUrl(
529
+ precomputeBuildRelativeUrl(htmlRessource),
530
+ buildDirectoryUrl,
531
+ )
532
+
533
+ const moveResult = await moveCssUrls({
534
+ code,
535
+ from: cssBuildUrl,
536
+ to: htmlUrl,
537
+ // moveCssUrls will change the css source code
538
+ // Ideally we should update the sourcemap referenced by css
539
+ // to target the one after css urls are moved.
540
+ // It means we should force sourcemap ressource to the new one
541
+ // until it's supported we prevent postcss from updating the
542
+ // sourcemap comment, othwise css would reference a sourcemap
543
+ // that won't by in the build directory
544
+ sourcemapMethod: null,
545
+ })
546
+ code = moveResult.code
547
+
548
+ const sourcemapRelativeUrl = getCssSourceMappingUrl(code)
521
549
  if (sourcemapRelativeUrl) {
522
- const { buildRelativeUrl } = ressource
523
- const cssBuildUrl = resolveUrl(buildRelativeUrl, "file:///")
550
+ const cssBuildUrl = resolveUrl(buildRelativeUrl, buildDirectoryUrl)
524
551
  const sourcemapBuildUrl = resolveUrl(sourcemapRelativeUrl, cssBuildUrl)
525
- const htmlUrl = resolveUrl(htmlRessource.fileNamePattern, "file:///")
526
552
  const sourcemapInlineUrl = urlToRelativeUrl(sourcemapBuildUrl, htmlUrl)
527
- cssString = setCssSourceMappingUrl(cssString, sourcemapInlineUrl)
553
+ code = setCssSourceMappingUrl(code, sourcemapInlineUrl)
528
554
  }
529
555
 
530
- replaceHtmlNode(link, `<style>${cssString}</style>`, {
556
+ replaceHtmlNode(link, `<style>${code}</style>`, {
531
557
  attributesToIgnore: ["href", "rel", "as", "crossorigin", "type"],
532
558
  })
533
559
  cssReference.inlinedCallback()
@@ -39,6 +39,7 @@ export const parseRessource = (
39
39
  minifyJs,
40
40
  minifyHtml,
41
41
  minifyCssOptions,
42
+ cssConcatenation,
42
43
  },
43
44
  ) => {
44
45
  const { contentType } = ressource
@@ -124,10 +125,12 @@ export const parseRessource = (
124
125
 
125
126
  if (contentType === "text/css") {
126
127
  return parseCssRessource(ressource, notifiers, {
128
+ asProjectUrl,
127
129
  asOriginalUrl,
128
130
  asOriginalServerUrl,
129
131
  minify,
130
132
  minifyCssOptions,
133
+ cssConcatenation,
131
134
  })
132
135
  }
133
136
 
@@ -49,6 +49,7 @@ export const createRessourceBuilder = (
49
49
  entryUrl,
50
50
  entryBuffer,
51
51
  entryBuildRelativeUrl,
52
+ urlVersionningForEntryPoints,
52
53
  }) => {
53
54
  // The entry point is conceptually referenced by code passing "entryPointMap"
54
55
  // to buildProject. So we analyse stack trace to put this function caller
@@ -68,8 +69,12 @@ export const createRessourceBuilder = (
68
69
  isEntryPoint: true,
69
70
 
70
71
  // don't hash asset entry points
71
- urlVersioningDisabled: true,
72
- fileNamePattern: entryBuildRelativeUrl,
72
+ ...(urlVersionningForEntryPoints
73
+ ? {}
74
+ : {
75
+ urlVersioningDisabled: true,
76
+ fileNamePattern: entryBuildRelativeUrl,
77
+ }),
73
78
  })
74
79
  entryReference.isProgrammatic = true
75
80
 
@@ -567,6 +572,10 @@ export const createRessourceBuilder = (
567
572
  )
568
573
  await transform({
569
574
  buildDirectoryUrl,
575
+ precomputeBuildRelativeUrl: (ressource) =>
576
+ precomputeBuildRelativeUrlForRessource(ressource, {
577
+ lineBreakNormalization,
578
+ }),
570
579
  getUrlRelativeToImporter: (referencedRessource) => {
571
580
  const ressourceImporter = ressource
572
581
 
@@ -1021,7 +1030,7 @@ const isEmitChunkNeeded = ({ ressource, reference }) => {
1021
1030
  *
1022
1031
  * see also:
1023
1032
  * - https://rollupjs.org/guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string
1024
- * -https://github.com/rollup/rollup/issues/2872
1033
+ * - https://github.com/rollup/rollup/issues/2872
1025
1034
  */
1026
1035
  const referenceShouldBeIgnoredWarning = ({
1027
1036
  isJsModule,
@@ -10,8 +10,7 @@ export const babelPluginImportAssertions = (
10
10
  return {
11
11
  ...babelPluginImportVisitor(
12
12
  babel,
13
- // During the build we throw when for import call expression where
14
- // sepcifier or type is dynamic.
13
+ // During build we throw on import call expression where "specifier" or "type" is dynamic
15
14
  // Here there is no strong need to throw because keeping the source code intact
16
15
  // will throw an error when browser will execute the code
17
16
  ({ importPath, specifierPath }) => {