@jsenv/core 27.0.0-alpha.4 → 27.0.0-alpha.40
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/event_source_client.js +549 -0
- package/dist/event_source_client.js.map +188 -0
- package/dist/html_supervisor_installer.js +1145 -0
- package/dist/html_supervisor_installer.js.map +322 -0
- package/dist/html_supervisor_setup.js +92 -0
- package/dist/html_supervisor_setup.js.map +57 -0
- package/main.js +8 -1
- package/package.json +22 -21
- package/readme.md +4 -12
- package/src/build/build.js +731 -433
- package/src/build/build_urls_generator.js +55 -21
- package/src/build/graph_utils.js +31 -0
- package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
- package/src/build/inject_service_worker_urls.js +79 -0
- package/src/build/resync_ressource_hints.js +68 -0
- package/src/build/start_build_server.js +205 -0
- package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
- package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
- package/src/dev/start_dev_server.js +58 -26
- package/src/execute/execute.js +30 -4
- package/src/execute/run.js +19 -56
- package/src/execute/runtimes/browsers/from_playwright.js +201 -147
- package/src/execute/runtimes/node/controllable_file.mjs +26 -10
- package/src/execute/runtimes/node/node_execution_performance.js +67 -0
- package/src/execute/runtimes/node/node_process.js +280 -39
- package/src/jsenv_root_directory_url.js +1 -0
- package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
- package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
- package/src/omega/compat/runtime_compat.js +50 -0
- package/src/omega/errors.js +51 -58
- package/src/omega/fetched_content_compliance.js +24 -0
- package/src/omega/file_url_converter.js +8 -50
- package/src/omega/kitchen.js +414 -285
- package/src/omega/server/file_service.js +21 -22
- package/src/omega/url_graph/url_graph_load.js +14 -7
- package/src/omega/url_graph/url_graph_report.js +17 -15
- package/src/omega/url_graph/url_info_transformations.js +17 -5
- package/src/omega/url_graph.js +33 -10
- package/src/omega/web_workers.js +42 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
- package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +31 -172
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
- package/src/plugins/bundling/css/bundle_css.js +21 -0
- package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
- package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +120 -79
- package/src/plugins/bundling/jsenv_plugin_bundling.js +51 -0
- package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
- package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_installer.js +3 -2
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_setup.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +52 -55
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +101 -0
- package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
- package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
- package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
- package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +37 -31
- package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
- package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
- package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +61 -40
- package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
- package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
- package/src/plugins/minification/css/minify_css.js +9 -0
- package/src/plugins/minification/html/minify_html.js +15 -0
- package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
- package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
- package/src/plugins/minification/json/minify_json.js +8 -0
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
- package/src/{omega → plugins}/plugin_controller.js +39 -11
- package/src/plugins/plugins.js +89 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
- package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
- package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +93 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
- package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
- package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +200 -0
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
- package/src/plugins/url_references/css/css_urls.js +49 -0
- package/src/plugins/url_references/html/html_urls.js +273 -0
- package/src/plugins/url_references/js/js_urls.js +43 -0
- package/src/plugins/url_references/jsenv_plugin_imports_analysis.js +46 -0
- package/src/plugins/url_references/jsenv_plugin_url_analysis.js +18 -0
- package/src/plugins/url_references/jsenv_plugin_url_references.js +6 -0
- package/src/plugins/url_references/webmanifest/webmanifest_urls.js +17 -0
- package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
- package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
- package/src/test/execute_plan.js +28 -11
- package/src/test/execute_test_plan.js +23 -8
- package/src/test/logs_file_execution.js +8 -7
- package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
- package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
- package/src/dev/plugins/autoreload/sse_service.js +0 -149
- package/src/execute/runtimes/node/controlled_process.js +0 -316
- package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
- package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
- package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
- package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
- package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
- package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
- package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
- package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
- package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
- package/src/omega/core_plugins.js +0 -39
- package/src/omega/runtime_support/runtime_support.js +0 -20
- package/src/omega/url_mentions/css_url_mentions.js +0 -63
- package/src/omega/url_mentions/html_url_mentions.js +0 -185
- package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
- package/src/omega/url_mentions/parse_url_mentions.js +0 -37
- package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
|
@@ -12,18 +12,22 @@
|
|
|
12
12
|
import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
|
|
13
13
|
import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
|
|
14
14
|
|
|
15
|
-
import { collectProgramImportMetas } from "@jsenv/utils/js_ast/program_import_metas.js"
|
|
16
|
-
|
|
17
15
|
export const jsenvPluginImportMetaScenarios = () => {
|
|
18
16
|
return {
|
|
19
17
|
name: "jsenv:import_meta_scenario",
|
|
20
18
|
appliesDuring: "*",
|
|
21
|
-
|
|
22
|
-
js_module: async (
|
|
19
|
+
transformUrlContent: {
|
|
20
|
+
js_module: async (urlInfo, { scenario }) => {
|
|
21
|
+
if (
|
|
22
|
+
!urlInfo.content.includes("import.meta.dev") &&
|
|
23
|
+
!urlInfo.content.includes("import.meta.test") &&
|
|
24
|
+
!urlInfo.content.includes("import.meta.build")
|
|
25
|
+
) {
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
23
28
|
const { metadata } = await applyBabelPlugins({
|
|
24
29
|
babelPlugins: [babelPluginMetadataImportMetaScenarios],
|
|
25
|
-
|
|
26
|
-
content,
|
|
30
|
+
urlInfo,
|
|
27
31
|
})
|
|
28
32
|
const { dev = [], test = [], build = [] } = metadata.importMetaScenarios
|
|
29
33
|
const replacements = []
|
|
@@ -59,7 +63,7 @@ export const jsenvPluginImportMetaScenarios = () => {
|
|
|
59
63
|
replace(path, "true")
|
|
60
64
|
})
|
|
61
65
|
}
|
|
62
|
-
const magicSource = createMagicSource(content)
|
|
66
|
+
const magicSource = createMagicSource(urlInfo.content)
|
|
63
67
|
replacements.forEach(({ path, value }) => {
|
|
64
68
|
magicSource.replace({
|
|
65
69
|
start: path.node.start,
|
|
@@ -78,7 +82,28 @@ const babelPluginMetadataImportMetaScenarios = () => {
|
|
|
78
82
|
name: "metadata-import-meta-scenarios",
|
|
79
83
|
visitor: {
|
|
80
84
|
Program(programPath, state) {
|
|
81
|
-
const importMetas =
|
|
85
|
+
const importMetas = {}
|
|
86
|
+
programPath.traverse({
|
|
87
|
+
MemberExpression(path) {
|
|
88
|
+
const { node } = path
|
|
89
|
+
const { object } = node
|
|
90
|
+
if (object.type !== "MetaProperty") {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
const { property: objectProperty } = object
|
|
94
|
+
if (objectProperty.name !== "meta") {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
const { property } = node
|
|
98
|
+
const { name } = property
|
|
99
|
+
const importMetaPaths = importMetas[name]
|
|
100
|
+
if (importMetaPaths) {
|
|
101
|
+
importMetaPaths.push(path)
|
|
102
|
+
} else {
|
|
103
|
+
importMetas[name] = [path]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
})
|
|
82
107
|
state.file.metadata.importMetaScenarios = {
|
|
83
108
|
dev: importMetas.dev,
|
|
84
109
|
test: importMetas.test,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const getCurrentScriptSrc = () => {
|
|
2
|
+
const { currentScript } = document
|
|
3
|
+
if (currentScript) return currentScript.src
|
|
4
|
+
|
|
5
|
+
// https://github.com/amiller-gh/currentScript-polyfill
|
|
6
|
+
|
|
7
|
+
const scripts = Array.prototype.slice.call(
|
|
8
|
+
document.getElementsByTagName("script"),
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
const readyScript = scripts.find((script) => {
|
|
12
|
+
return script.readyState === "interactive"
|
|
13
|
+
})
|
|
14
|
+
if (readyScript) return readyScript
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
throw new Error()
|
|
18
|
+
} catch (err) {
|
|
19
|
+
// Find the second match for the "at" string to get file src url from stack.
|
|
20
|
+
// Specifically works with the format of stack traces in IE.
|
|
21
|
+
const stackDetails = /.*at [^(]*\((.*):(.+):(.+)\)$/gi.exec(err.stack)
|
|
22
|
+
const scriptLocation = (stackDetails || [false])[1]
|
|
23
|
+
const line = (stackDetails || [false])[2]
|
|
24
|
+
const currentLocation = document.location.href.replace(
|
|
25
|
+
document.location.hash,
|
|
26
|
+
"",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if (scriptLocation === currentLocation) {
|
|
30
|
+
const source = document.documentElement.outerHTML
|
|
31
|
+
const codeRegExp = new RegExp(
|
|
32
|
+
`(?:[^\\n]+?\\n){0,${
|
|
33
|
+
line - 2
|
|
34
|
+
}}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*`,
|
|
35
|
+
"i",
|
|
36
|
+
)
|
|
37
|
+
const code = source.replace(codeRegExp, "$1").trim()
|
|
38
|
+
|
|
39
|
+
return scripts.find((script) => {
|
|
40
|
+
return script.innerHTML && script.innerHTML.trim() === code
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return scripts.find((script) => {
|
|
45
|
+
return script.src === scriptLocation
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const url = getCurrentScriptSrc()
|
|
51
|
+
|
|
52
|
+
export default url
|
|
@@ -30,8 +30,7 @@ import {
|
|
|
30
30
|
getHtmlNodeAttributeByName,
|
|
31
31
|
htmlNodePosition,
|
|
32
32
|
removeHtmlNodeAttributeByName,
|
|
33
|
-
|
|
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
|
-
|
|
63
|
-
js_import_export: (
|
|
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
|
-
|
|
95
|
-
html: async (
|
|
96
|
-
|
|
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
126
|
line: line - 1,
|
|
131
127
|
column,
|
|
132
|
-
isOriginal,
|
|
128
|
+
isOriginalPosition: isOriginal,
|
|
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
|
-
|
|
142
|
-
|
|
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 =
|
|
151
|
-
(
|
|
152
|
+
const importmapReference =
|
|
153
|
+
context.referenceUtils.findByGeneratedSpecifier(src)
|
|
154
|
+
const importmapUrlInfo = context.urlGraph.getUrlInfo(
|
|
155
|
+
importmapReference.url,
|
|
152
156
|
)
|
|
153
|
-
|
|
154
|
-
await cook({
|
|
157
|
+
await context.cook({
|
|
155
158
|
reference: importmapReference,
|
|
156
159
|
urlInfo: importmapUrlInfo,
|
|
157
160
|
})
|
|
158
|
-
onHtmlImportmapParsed(
|
|
161
|
+
onHtmlImportmapParsed(
|
|
162
|
+
JSON.parse(importmapUrlInfo.content),
|
|
163
|
+
htmlUrlInfo.url,
|
|
164
|
+
)
|
|
159
165
|
removeHtmlNodeAttributeByName(importmap, "src")
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
+
}
|
|
File without changes
|
|
@@ -1,42 +1,46 @@
|
|
|
1
1
|
import { DataUrl } from "@jsenv/utils/urls/data_url.js"
|
|
2
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
if (!url.startsWith("data:")) {
|
|
14
|
+
fetchUrlContent: (urlInfo) => {
|
|
15
|
+
if (!urlInfo.url.startsWith("data:")) {
|
|
16
16
|
return null
|
|
17
17
|
}
|
|
18
|
-
const {
|
|
19
|
-
|
|
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
|
-
|
|
26
|
-
if (!reference.
|
|
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.
|
|
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 (
|
|
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
|
-
|
|
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
|
|
14
|
+
export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
|
|
15
15
|
return {
|
|
16
|
-
name: "jsenv:
|
|
16
|
+
name: "jsenv:html_inline_content",
|
|
17
17
|
appliesDuring: "*",
|
|
18
|
-
|
|
19
|
-
html: async (
|
|
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",
|
|
46
47
|
// we remove 1 to the line because imagine the following html:
|
|
47
48
|
// <style>body { color: red; }</style>
|
|
48
49
|
// -> content starts same line as <style>
|
|
49
50
|
line: line - 1,
|
|
50
51
|
column,
|
|
51
|
-
isOriginal,
|
|
52
|
+
isOriginalPosition: isOriginal,
|
|
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
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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:
|
|
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
130
|
line: line - 1,
|
|
107
131
|
column,
|
|
108
|
-
isOriginal,
|
|
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
|
-
|
|
137
|
+
|
|
138
|
+
await context.cook({
|
|
117
139
|
reference: inlineScriptReference,
|
|
118
140
|
urlInfo: inlineScriptUrlInfo,
|
|
119
141
|
})
|
|
120
|
-
|
|
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
|
-
|
|
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: '
|
|
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,
|
|
23
|
-
if (!
|
|
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
|
})
|