@jsenv/core 27.0.0-alpha.5 → 27.0.0-alpha.50

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 (146) hide show
  1. package/dist/event_source_client.js +545 -0
  2. package/dist/event_source_client.js.map +187 -0
  3. package/dist/html_supervisor_installer.js +1236 -0
  4. package/dist/html_supervisor_installer.js.map +337 -0
  5. package/dist/html_supervisor_setup.js +95 -0
  6. package/dist/html_supervisor_setup.js.map +57 -0
  7. package/dist/import_meta_hot.js +86 -0
  8. package/dist/import_meta_hot.js.map +42 -0
  9. package/main.js +8 -1
  10. package/package.json +22 -21
  11. package/readme.md +4 -12
  12. package/src/build/build.js +749 -437
  13. package/src/build/build_urls_generator.js +56 -22
  14. package/src/build/graph_utils.js +31 -0
  15. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  16. package/src/build/inject_service_worker_urls.js +79 -0
  17. package/src/build/resync_ressource_hints.js +68 -0
  18. package/src/build/start_build_server.js +255 -0
  19. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  20. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  21. package/src/dev/start_dev_server.js +136 -30
  22. package/src/execute/execute.js +31 -6
  23. package/src/execute/run.js +19 -56
  24. package/src/execute/runtimes/browsers/from_playwright.js +201 -147
  25. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  26. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  27. package/src/execute/runtimes/node/node_process.js +280 -39
  28. package/src/jsenv_root_directory_url.js +1 -0
  29. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  30. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  31. package/src/omega/compat/runtime_compat.js +50 -0
  32. package/src/omega/errors.js +51 -58
  33. package/src/omega/fetched_content_compliance.js +24 -0
  34. package/src/omega/file_url_converter.js +8 -50
  35. package/src/omega/kitchen.js +482 -292
  36. package/src/omega/omega_server.js +2 -3
  37. package/src/omega/server/file_service.js +38 -25
  38. package/src/omega/server/user_agent.js +4 -2
  39. package/src/omega/url_graph/url_graph_load.js +14 -7
  40. package/src/omega/url_graph/url_graph_report.js +17 -15
  41. package/src/omega/url_graph/url_info_transformations.js +26 -9
  42. package/src/omega/url_graph.js +91 -16
  43. package/src/omega/web_workers.js +42 -0
  44. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  45. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  46. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  47. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  48. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
  49. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +204 -0
  50. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
  51. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  52. package/src/plugins/bundling/css/bundle_css.js +21 -0
  53. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  54. package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +150 -79
  55. package/src/plugins/bundling/jsenv_plugin_bundling.js +54 -0
  56. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
  57. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  58. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
  59. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  60. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  61. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +242 -0
  62. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +79 -0
  63. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  64. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  65. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +83 -58
  66. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  67. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  68. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  69. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  70. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +105 -0
  71. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
  72. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  73. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  74. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +39 -33
  75. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
  76. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  77. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  78. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +65 -44
  79. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  80. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  81. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
  82. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  83. package/src/plugins/minification/css/minify_css.js +9 -0
  84. package/src/plugins/minification/html/minify_html.js +15 -0
  85. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  86. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  87. package/src/plugins/minification/json/minify_json.js +8 -0
  88. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
  89. package/src/{omega → plugins}/plugin_controller.js +42 -11
  90. package/src/plugins/plugins.js +91 -0
  91. package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
  92. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  93. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  94. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  95. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
  96. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
  97. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +55 -0
  98. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  100. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
  101. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
  102. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  103. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
  104. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  105. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  106. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  107. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  108. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  109. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  110. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  111. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +181 -0
  112. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
  113. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  114. package/src/plugins/url_analysis/css/css_urls.js +42 -0
  115. package/src/plugins/url_analysis/html/html_urls.js +273 -0
  116. package/src/plugins/url_analysis/js/js_urls.js +67 -0
  117. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +18 -0
  118. package/src/plugins/url_analysis/webmanifest/webmanifest_urls.js +17 -0
  119. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  120. package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
  121. package/src/test/execute_plan.js +30 -18
  122. package/src/test/execute_test_plan.js +23 -8
  123. package/src/test/logs_file_execution.js +8 -7
  124. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  125. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  126. package/src/dev/plugins/autoreload/jsenv_plugin_autoreload.js +0 -374
  127. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  128. package/src/execute/runtimes/node/controlled_process.js +0 -316
  129. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  130. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_installer.js +0 -168
  131. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_setup.js +0 -77
  132. package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
  133. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  134. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  135. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  136. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  137. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  138. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  139. package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
  140. package/src/omega/core_plugins.js +0 -39
  141. package/src/omega/runtime_support/runtime_support.js +0 -20
  142. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  143. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  144. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  145. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  146. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -30,8 +30,7 @@ import {
30
30
  getHtmlNodeAttributeByName,
31
31
  htmlNodePosition,
32
32
  removeHtmlNodeAttributeByName,
33
- setHtmlNodeText,
34
- assignHtmlNodeAttributes,
33
+ setHtmlNodeGeneratedText,
35
34
  getHtmlNodeTextNode,
36
35
  removeHtmlNode,
37
36
  } from "@jsenv/utils/html_ast/html_ast.js"
@@ -59,16 +58,16 @@ export const jsenvPluginImportmap = () => {
59
58
  return {
60
59
  name: "jsenv:importmap",
61
60
  appliesDuring: "*",
62
- resolve: {
63
- js_import_export: ({ parentUrl, specifier }) => {
61
+ resolveUrl: {
62
+ js_import_export: (reference) => {
64
63
  if (!finalImportmap) {
65
64
  return null
66
65
  }
67
66
  try {
68
67
  let fromMapping = false
69
68
  const result = resolveImport({
70
- specifier,
71
- importer: parentUrl,
69
+ specifier: reference.specifier,
70
+ importer: reference.parentUrl,
72
71
  importMap: finalImportmap,
73
72
  onImportMapping: () => {
74
73
  fromMapping = true
@@ -91,12 +90,9 @@ export const jsenvPluginImportmap = () => {
91
90
  }
92
91
  },
93
92
  },
94
- transform: {
95
- html: async (
96
- { url, content, references },
97
- { scenario, cook, urlGraph, referenceUtils },
98
- ) => {
99
- const htmlAst = parseHtmlString(content)
93
+ transformUrlContent: {
94
+ html: async (htmlUrlInfo, context) => {
95
+ const htmlAst = parseHtmlString(htmlUrlInfo.content)
100
96
  const importmap = findNode(htmlAst, (node) => {
101
97
  if (node.nodeName !== "script") {
102
98
  return false
@@ -108,7 +104,7 @@ export const jsenvPluginImportmap = () => {
108
104
  return true
109
105
  })
110
106
  if (!importmap) {
111
- onHtmlImportmapParsed(null, url)
107
+ onHtmlImportmapParsed(null, htmlUrlInfo.url)
112
108
  return null
113
109
  }
114
110
  const handleInlineImportmap = async (importmap, textNode) => {
@@ -117,7 +113,7 @@ export const jsenvPluginImportmap = () => {
117
113
  preferOriginal: true,
118
114
  })
119
115
  const inlineImportmapUrl = generateInlineContentUrl({
120
- url,
116
+ url: htmlUrlInfo.url,
121
117
  extension: ".importmap",
122
118
  line,
123
119
  column,
@@ -125,21 +121,27 @@ export const jsenvPluginImportmap = () => {
125
121
  columnEnd,
126
122
  })
127
123
  const [inlineImportmapReference, inlineImportmapUrlInfo] =
128
- referenceUtils.foundInline({
124
+ context.referenceUtils.foundInline({
129
125
  type: "script_src",
130
- line: line - 1,
131
- column,
132
- isOriginal,
126
+ isOriginalPosition: isOriginal,
127
+ specifierLine: line - 1,
128
+ specifierColumn: column,
133
129
  specifier: inlineImportmapUrl,
134
130
  contentType: "application/importmap+json",
135
131
  content: textNode.value,
136
132
  })
137
- await cook({
133
+ await context.cook({
138
134
  reference: inlineImportmapReference,
139
135
  urlInfo: inlineImportmapUrlInfo,
140
136
  })
141
- setHtmlNodeText(importmap, inlineImportmapUrlInfo.content)
142
- onHtmlImportmapParsed(JSON.parse(inlineImportmapUrlInfo.content), url)
137
+ setHtmlNodeGeneratedText(importmap, {
138
+ generatedText: inlineImportmapUrlInfo.content,
139
+ generatedBy: "jsenv:importmap",
140
+ })
141
+ onHtmlImportmapParsed(
142
+ JSON.parse(inlineImportmapUrlInfo.content),
143
+ htmlUrlInfo.url,
144
+ )
143
145
  }
144
146
  const handleImportmapWithSrc = async (importmap, src) => {
145
147
  // Browser would throw on remote importmap
@@ -147,35 +149,39 @@ export const jsenvPluginImportmap = () => {
147
149
  // We must precook the importmap to know its content and inline it into the HTML
148
150
  // In this situation the ref to the importmap was already discovered
149
151
  // when parsing the HTML
150
- const importmapReference = references.find(
151
- (reference) => reference.url === src,
152
+ const importmapReference =
153
+ context.referenceUtils.findByGeneratedSpecifier(src)
154
+ const importmapUrlInfo = context.urlGraph.getUrlInfo(
155
+ importmapReference.url,
152
156
  )
153
- const importmapUrlInfo = urlGraph.getUrlInfo(importmapReference.url)
154
- await cook({
157
+ await context.cook({
155
158
  reference: importmapReference,
156
159
  urlInfo: importmapUrlInfo,
157
160
  })
158
- onHtmlImportmapParsed(JSON.parse(importmapUrlInfo.content), url)
161
+ onHtmlImportmapParsed(
162
+ JSON.parse(importmapUrlInfo.content),
163
+ htmlUrlInfo.url,
164
+ )
159
165
  removeHtmlNodeAttributeByName(importmap, "src")
160
- assignHtmlNodeAttributes(importmap, {
161
- "content-src": src,
162
- "inlined-by": "jsenv:importmap",
166
+ setHtmlNodeGeneratedText(importmap, {
167
+ generatedText: importmapUrlInfo.content,
168
+ generatedBy: "jsenv:importmap",
169
+ generatedFromSrc: src,
163
170
  })
164
- setHtmlNodeText(importmap, importmapUrlInfo.content)
165
171
 
166
172
  const { line, column, lineEnd, columnEnd, isOriginal } =
167
173
  htmlNodePosition.readNodePosition(importmap, {
168
174
  preferOriginal: true,
169
175
  })
170
176
  const inlineImportmapUrl = generateInlineContentUrl({
171
- url,
177
+ url: htmlUrlInfo.url,
172
178
  extension: ".importmap",
173
179
  line,
174
180
  column,
175
181
  lineEnd,
176
182
  columnEnd,
177
183
  })
178
- referenceUtils.becomesInline(importmapReference, {
184
+ context.referenceUtils.becomesInline(importmapReference, {
179
185
  line: line - 1,
180
186
  column,
181
187
  isOriginal,
@@ -200,7 +206,7 @@ export const jsenvPluginImportmap = () => {
200
206
  // by "formatReferencedUrl" making the importmap presence useless.
201
207
  // In dev/test we keep importmap into the HTML to see it even if useless
202
208
  // Duing build we get rid of it
203
- if (scenario === "build") {
209
+ if (context.scenario === "build") {
204
210
  removeHtmlNode(importmap)
205
211
  }
206
212
  return {
@@ -0,0 +1,67 @@
1
+ import {
2
+ parseHtmlString,
3
+ injectScriptAsEarlyAsPossible,
4
+ createHtmlNode,
5
+ stringifyHtmlAst,
6
+ } from "@jsenv/utils/html_ast/html_ast.js"
7
+ import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
8
+ import { isWebWorkerUrlInfo } from "@jsenv/core/src/omega/web_workers.js"
9
+
10
+ export const jsenvPluginInjectGlobals = (globals = {}) => {
11
+ if (Object.keys(globals).length === 0) {
12
+ return []
13
+ }
14
+
15
+ const globalInjectorOnHtmlEntryPoint = (urlInfo) => {
16
+ if (!urlInfo.data.isEntryPoint) {
17
+ return null
18
+ }
19
+ // ideally we would inject an importmap but browser support is too low
20
+ // (even worse for worker/service worker)
21
+ // so for now we inject code into entry points
22
+ const htmlAst = parseHtmlString(urlInfo.content, {
23
+ storeOriginalPositions: false,
24
+ })
25
+ injectScriptAsEarlyAsPossible(
26
+ htmlAst,
27
+ createHtmlNode({
28
+ "tagName": "script",
29
+ "textContent": generateClientCodeForGlobals({
30
+ globals,
31
+ isWebWorker: false,
32
+ }),
33
+ "injected-by": "jsenv:inject_globals",
34
+ }),
35
+ )
36
+ return stringifyHtmlAst(htmlAst)
37
+ }
38
+
39
+ const globalsInjectorOnJsEntryPoints = (urlInfo) => {
40
+ if (!urlInfo.data.isEntryPoint && !urlInfo.data.isWebWorkerEntryPoint) {
41
+ return null
42
+ }
43
+ const magicSource = createMagicSource(urlInfo.content)
44
+ magicSource.append(
45
+ generateClientCodeForGlobals({
46
+ globals,
47
+ isWebWorker: isWebWorkerUrlInfo(urlInfo),
48
+ }),
49
+ )
50
+ return magicSource.toContentAndSourcemap()
51
+ }
52
+
53
+ return {
54
+ name: "jsenv:inject_globals",
55
+ appliesDuring: "*",
56
+ transformUrlContent: {
57
+ html: globalInjectorOnHtmlEntryPoint,
58
+ js_classic: globalsInjectorOnJsEntryPoints,
59
+ js_module: globalsInjectorOnJsEntryPoints,
60
+ },
61
+ }
62
+ }
63
+
64
+ const generateClientCodeForGlobals = ({ isWebWorker = false, globals }) => {
65
+ const globalName = isWebWorker ? "self" : "window"
66
+ return `Object.assign(${globalName}, ${JSON.stringify(globals, null, " ")});`
67
+ }
@@ -1,42 +1,46 @@
1
1
  import { DataUrl } from "@jsenv/utils/urls/data_url.js"
2
- import { ContentType } from "@jsenv/utils/src/content_type.js"
2
+ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
3
3
 
4
4
  export const jsenvPluginDataUrls = () => {
5
5
  return {
6
6
  name: "jsenv:data_urls",
7
7
  appliesDuring: "*",
8
- resolve: ({ specifier }) => {
9
- if (!specifier.startsWith("data:")) {
8
+ resolveUrl: (reference) => {
9
+ if (!reference.specifier.startsWith("data:")) {
10
10
  return null
11
11
  }
12
- return specifier
12
+ return reference.specifier
13
13
  },
14
- load: ({ url, data }) => {
15
- if (!url.startsWith("data:")) {
14
+ fetchUrlContent: (urlInfo) => {
15
+ if (!urlInfo.url.startsWith("data:")) {
16
16
  return null
17
17
  }
18
- const { contentType, base64Flag, data: urlData } = DataUrl.parse(url)
19
- data.base64Flag = base64Flag
18
+ const {
19
+ contentType,
20
+ base64Flag,
21
+ data: urlData,
22
+ } = DataUrl.parse(urlInfo.url)
23
+ urlInfo.data.base64Flag = base64Flag
20
24
  return {
21
25
  contentType,
22
26
  content: contentFromUrlData({ contentType, base64Flag, urlData }),
23
27
  }
24
28
  },
25
- formatReferencedUrl: (reference, { urlGraph, cook }) => {
26
- if (!reference.url.startsWith("data:")) {
29
+ formatUrl: (reference, context) => {
30
+ if (!reference.generatedUrl.startsWith("data:")) {
27
31
  return null
28
32
  }
29
33
  if (reference.type === "sourcemap_comment") {
30
34
  return null
31
35
  }
32
36
  return (async () => {
33
- const urlInfo = urlGraph.getUrlInfo(reference.url)
34
- await cook({
37
+ const urlInfo = context.urlGraph.getUrlInfo(reference.url)
38
+ await context.cook({
35
39
  reference,
36
40
  urlInfo,
37
41
  })
38
42
  if (urlInfo.originalContent === urlInfo.content) {
39
- return reference.url
43
+ return reference.generatedUrl
40
44
  }
41
45
  const specifier = DataUrl.stringify({
42
46
  contentType: urlInfo.contentType,
@@ -52,7 +56,7 @@ export const jsenvPluginDataUrls = () => {
52
56
  }
53
57
 
54
58
  const contentFromUrlData = ({ contentType, base64Flag, urlData }) => {
55
- if (ContentType.isTextual(contentType)) {
59
+ if (CONTENT_TYPE.isTextual(contentType)) {
56
60
  if (base64Flag) {
57
61
  return base64ToString(urlData)
58
62
  }
@@ -5,19 +5,19 @@ import {
5
5
  getHtmlNodeTextNode,
6
6
  htmlNodePosition,
7
7
  parseScriptNode,
8
- setHtmlNodeText,
8
+ setHtmlNodeGeneratedText,
9
9
  getHtmlNodeAttributeByName,
10
10
  } from "@jsenv/utils/html_ast/html_ast.js"
11
- import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
12
11
  import { generateInlineContentUrl } from "@jsenv/utils/urls/inline_content_url_generator.js"
12
+ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
13
13
 
14
- export const jsenvPluginJsAndCssInsideHtml = () => {
14
+ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
15
15
  return {
16
- name: "jsenv:js_and_css_inside_html",
16
+ name: "jsenv:html_inline_content",
17
17
  appliesDuring: "*",
18
- transform: {
19
- html: async ({ url, content }, { cook, referenceUtils }) => {
20
- const htmlAst = parseHtmlString(content)
18
+ transformUrlContent: {
19
+ html: async (urlInfo, context) => {
20
+ const htmlAst = parseHtmlString(urlInfo.content)
21
21
  const actions = []
22
22
  const handleInlineStyle = (node) => {
23
23
  if (node.nodeName !== "style") {
@@ -33,7 +33,7 @@ export const jsenvPluginJsAndCssInsideHtml = () => {
33
33
  preferOriginal: true,
34
34
  })
35
35
  const inlineStyleUrl = generateInlineContentUrl({
36
- url,
36
+ url: urlInfo.url,
37
37
  extension: ".css",
38
38
  line,
39
39
  column,
@@ -41,23 +41,27 @@ export const jsenvPluginJsAndCssInsideHtml = () => {
41
41
  columnEnd,
42
42
  })
43
43
  const [inlineStyleReference, inlineStyleUrlInfo] =
44
- referenceUtils.foundInline({
44
+ context.referenceUtils.foundInline({
45
45
  type: "link_href",
46
+ expectedType: "css",
47
+ isOriginalPosition: isOriginal,
46
48
  // we remove 1 to the line because imagine the following html:
47
49
  // <style>body { color: red; }</style>
48
50
  // -> content starts same line as <style>
49
- line: line - 1,
50
- column,
51
- isOriginal,
51
+ specifierLine: line - 1,
52
+ specifierColumn: column,
52
53
  specifier: inlineStyleUrl,
53
54
  contentType: "text/css",
54
55
  content: textNode.value,
55
56
  })
56
- await cook({
57
+ await context.cook({
57
58
  reference: inlineStyleReference,
58
59
  urlInfo: inlineStyleUrlInfo,
59
60
  })
60
- setHtmlNodeText(node, inlineStyleUrlInfo.content)
61
+ setHtmlNodeGeneratedText(node, {
62
+ generatedText: inlineStyleUrlInfo.content,
63
+ generatedBy: "jsenv:html_inline_content",
64
+ })
61
65
  })
62
66
  }
63
67
  const handleInlineScript = (node) => {
@@ -68,14 +72,19 @@ export const jsenvPluginJsAndCssInsideHtml = () => {
68
72
  if (!textNode) {
69
73
  return
70
74
  }
71
- const contentSrc = getHtmlNodeAttributeByName(node, "content-src")
72
- if (contentSrc) {
73
- // it's inline but there is a corresponding "src" somewhere
74
- // - for instance the importmap was inlined by importmap plugin
75
- // in that case the content is already cooked and can be kept as it is
76
- // - any other logic that would turn a remote script into some content
77
- // but don't want to cook the content
78
- return
75
+ // If the inline script was already handled by an other plugin, ignore it
76
+ // - we want to preserve inline scripts generated by html supervisor during dev
77
+ // - we want to avoid cooking twice a script during build
78
+ const generatedBy = getHtmlNodeAttributeByName(node, "generated-by")
79
+ if (generatedBy) {
80
+ if (generatedBy.value === "jsenv:script_type_module_as_classic") {
81
+ if (!analyzeConvertedScripts) {
82
+ return
83
+ }
84
+ }
85
+ if (generatedBy.value === "jsenv:html_supervisor") {
86
+ return
87
+ }
79
88
  }
80
89
  actions.push(async () => {
81
90
  const scriptCategory = parseScriptNode(node)
@@ -83,41 +92,57 @@ export const jsenvPluginJsAndCssInsideHtml = () => {
83
92
  htmlNodePosition.readNodePosition(node, {
84
93
  preferOriginal: true,
85
94
  })
95
+ // from MDN about [type] attribute:
96
+ // "Any other value: The embedded content is treated as a data block
97
+ // which won't be processed by the browser. Developers must use a valid MIME type
98
+ // that is not a JavaScript MIME type to denote data blocks.
99
+ // The src attribute will be ignored."
100
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
101
+ const isJs =
102
+ scriptCategory === "classic" || scriptCategory === "module"
103
+ const isImportmap = scriptCategory === "importmap"
104
+ const contentType = isJs
105
+ ? "text/javascript"
106
+ : isImportmap
107
+ ? "application/importmap+json"
108
+ : scriptCategory
109
+
86
110
  let inlineScriptUrl = generateInlineContentUrl({
87
- url,
88
- extension: scriptCategory === "importmap" ? ".importmap" : ".js",
111
+ url: urlInfo.url,
112
+ extension: CONTENT_TYPE.asFileExtension(contentType),
89
113
  line,
90
114
  column,
91
115
  lineEnd,
92
116
  columnEnd,
93
117
  })
94
- if (scriptCategory === "classic") {
95
- inlineScriptUrl = injectQueryParams(inlineScriptUrl, {
96
- js_classic: "",
97
- })
98
- }
99
118
  const [inlineScriptReference, inlineScriptUrlInfo] =
100
- referenceUtils.foundInline({
119
+ context.referenceUtils.foundInline({
101
120
  node,
102
121
  type: "script_src",
122
+ expectedType: {
123
+ classic: "js_classic",
124
+ module: "js_module",
125
+ importmap: "importmap",
126
+ }[scriptCategory],
103
127
  // we remove 1 to the line because imagine the following html:
104
128
  // <script>console.log('ok')</script>
105
129
  // -> content starts same line as <script>
106
- line: line - 1,
107
- column,
108
- isOriginal,
130
+ specifierLine: line - 1,
131
+ specifierColumn: column,
132
+ isOriginalPosition: isOriginal,
109
133
  specifier: inlineScriptUrl,
110
- contentType:
111
- scriptCategory === "importmap"
112
- ? "application/importmap+json"
113
- : "application/javascript",
134
+ contentType,
114
135
  content: textNode.value,
115
136
  })
116
- await cook({
137
+
138
+ await context.cook({
117
139
  reference: inlineScriptReference,
118
140
  urlInfo: inlineScriptUrlInfo,
119
141
  })
120
- setHtmlNodeText(node, inlineScriptUrlInfo.content)
142
+ setHtmlNodeGeneratedText(node, {
143
+ generatedText: inlineScriptUrlInfo.content,
144
+ generatedBy: "jsenv:html_inline_content",
145
+ })
121
146
  })
122
147
  }
123
148
  visitHtmlAst(htmlAst, (node) => {
@@ -127,11 +152,7 @@ export const jsenvPluginJsAndCssInsideHtml = () => {
127
152
  if (actions.length === 0) {
128
153
  return null
129
154
  }
130
- await Promise.all(
131
- actions.map(async (action) => {
132
- await action()
133
- }),
134
- )
155
+ await Promise.all(actions.map((action) => action()))
135
156
  const htmlModified = stringifyHtmlAst(htmlAst)
136
157
  return {
137
158
  content: htmlModified,
@@ -0,0 +1,36 @@
1
+ import { jsenvPluginHtmlInlineContent } from "./jsenv_plugin_html_inline_content.js"
2
+ import { jsenvPluginJsInlineContent } from "./jsenv_plugin_js_inline_content.js"
3
+ import { jsenvPluginDataUrls } from "./jsenv_plugin_data_urls.js"
4
+ import { jsenvPluginInlineQueryParam } from "./jsenv_plugin_inline_query_param.js"
5
+
6
+ export const jsenvPluginInline = ({
7
+ fetchInlineUrls = true,
8
+ analyzeConvertedScripts = false,
9
+ allowEscapeForVersioning = false,
10
+ } = {}) => {
11
+ return [
12
+ ...(fetchInlineUrls ? [jsenvPluginInlineUrls()] : []),
13
+ jsenvPluginHtmlInlineContent({ analyzeConvertedScripts }),
14
+ jsenvPluginJsInlineContent({ allowEscapeForVersioning }),
15
+ jsenvPluginDataUrls(),
16
+ jsenvPluginInlineQueryParam(),
17
+ ]
18
+ }
19
+
20
+ const jsenvPluginInlineUrls = () => {
21
+ return {
22
+ name: "jsenv:inline_urls",
23
+ appliesDuring: "*",
24
+ fetchUrlContent: (urlInfo) => {
25
+ if (!urlInfo.isInline) {
26
+ return null
27
+ }
28
+ return {
29
+ contentType: urlInfo.contentType,
30
+ // we want to fetch the original content otherwise we might re-cook
31
+ // content already cooked
32
+ content: urlInfo.originalContent,
33
+ }
34
+ },
35
+ }
36
+ }
@@ -4,7 +4,7 @@ export const jsenvPluginInlineQueryParam = () => {
4
4
  return {
5
5
  name: "jsenv:inline_query_param",
6
6
  appliesDuring: "*",
7
- formatReferencedUrl: {
7
+ formatUrl: {
8
8
  // <link> and <script> can be inlined in the html
9
9
  // this should be done during dev and postbuild but not build
10
10
  // so that the bundled file gets inlined and not the entry point
@@ -15,17 +15,17 @@ export const jsenvPluginInlineQueryParam = () => {
15
15
  // but maybe we should rather use ?object_url
16
16
  // or people could do this:
17
17
  // import workerText from './worker.js?text'
18
- // const blob = new Blob(workerText, { type: 'application/javascript' })
18
+ // const blob = new Blob(workerText, { type: 'text/javascript' })
19
19
  // window.URL.createObjectURL(blob)
20
20
  // in any case the recommended way is to use an url
21
21
  // to benefit from shared worker and reuse worker between tabs
22
- "*": (reference, { urlGraph, cook }) => {
23
- if (!new URL(reference.url).searchParams.has("inline")) {
22
+ "*": (reference, context) => {
23
+ if (!reference.searchParams.has("inline")) {
24
24
  return null
25
25
  }
26
26
  return (async () => {
27
- const urlInfo = urlGraph.getUrlInfo(reference.url)
28
- await cook({
27
+ const urlInfo = context.urlGraph.getUrlInfo(reference.url)
28
+ await context.cook({
29
29
  reference,
30
30
  urlInfo,
31
31
  })