@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
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
|
|
2
|
+
import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
|
|
3
|
+
import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
|
|
4
|
+
import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
|
|
5
|
+
import { generateInlineContentUrl } from "@jsenv/utils/urls/inline_content_url_generator.js"
|
|
6
|
+
|
|
7
|
+
export const jsenvPluginJsInlineContent = ({ allowEscapeForVersioning }) => {
|
|
8
|
+
const parseAndTransformInlineContentCalls = async (urlInfo, context) => {
|
|
9
|
+
const inlineContentInfos = await parseJsInlineContentInfos({
|
|
10
|
+
js: urlInfo.content,
|
|
11
|
+
url: (urlInfo.data && urlInfo.data.rawUrl) || urlInfo.url,
|
|
12
|
+
isJsModule: urlInfo.type === "js_module",
|
|
13
|
+
})
|
|
14
|
+
if (inlineContentInfos.length === 0) {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
const magicSource = createMagicSource(urlInfo.content)
|
|
18
|
+
await inlineContentInfos.reduce(async (previous, inlineContentInfo) => {
|
|
19
|
+
await previous
|
|
20
|
+
const inlineUrl = generateInlineContentUrl({
|
|
21
|
+
url: urlInfo.url,
|
|
22
|
+
extension: CONTENT_TYPE.asFileExtension(inlineContentInfo.contentType),
|
|
23
|
+
line: inlineContentInfo.line,
|
|
24
|
+
column: inlineContentInfo.column,
|
|
25
|
+
lineEnd: inlineContentInfo.lineEnd,
|
|
26
|
+
columnEnd: inlineContentInfo.columnEnd,
|
|
27
|
+
})
|
|
28
|
+
let { quote } = inlineContentInfo
|
|
29
|
+
if (
|
|
30
|
+
quote === "`" &&
|
|
31
|
+
!context.isSupportedOnCurrentClients("template_literals")
|
|
32
|
+
) {
|
|
33
|
+
// if quote is "`" and template literals are not supported
|
|
34
|
+
// we'll use a regular string (single or double quote)
|
|
35
|
+
// when rendering the string
|
|
36
|
+
quote = JS_QUOTES.pickBest(inlineContentInfo.content)
|
|
37
|
+
}
|
|
38
|
+
const [inlineReference, inlineUrlInfo] =
|
|
39
|
+
context.referenceUtils.foundInline({
|
|
40
|
+
type: "js_inline_content",
|
|
41
|
+
subtype: inlineContentInfo.type, // "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
42
|
+
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
43
|
+
line: inlineContentInfo.line,
|
|
44
|
+
column: inlineContentInfo.column,
|
|
45
|
+
specifier: inlineUrl,
|
|
46
|
+
contentType: inlineContentInfo.contentType,
|
|
47
|
+
content: inlineContentInfo.content,
|
|
48
|
+
})
|
|
49
|
+
inlineUrlInfo.jsQuote = quote
|
|
50
|
+
inlineReference.escape = (value) =>
|
|
51
|
+
JS_QUOTES.escapeSpecialChars(value.slice(1, -1), { quote })
|
|
52
|
+
await context.cook({
|
|
53
|
+
reference: inlineReference,
|
|
54
|
+
urlInfo: inlineUrlInfo,
|
|
55
|
+
})
|
|
56
|
+
magicSource.replace({
|
|
57
|
+
start: inlineContentInfo.start,
|
|
58
|
+
end: inlineContentInfo.end,
|
|
59
|
+
replacement: JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
60
|
+
quote,
|
|
61
|
+
allowEscapeForVersioning,
|
|
62
|
+
}),
|
|
63
|
+
})
|
|
64
|
+
}, Promise.resolve())
|
|
65
|
+
return magicSource.toContentAndSourcemap()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
name: "jsenv:js_inline_content",
|
|
70
|
+
appliesDuring: "*",
|
|
71
|
+
transformUrlContent: {
|
|
72
|
+
js_classic: parseAndTransformInlineContentCalls,
|
|
73
|
+
js_module: parseAndTransformInlineContentCalls,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const parseJsInlineContentInfos = async ({ js, url, isJsModule }) => {
|
|
79
|
+
if (
|
|
80
|
+
!js.includes("InlineContent") &&
|
|
81
|
+
!js.includes("new Blob(") &&
|
|
82
|
+
!js.includes("JSON.parse(")
|
|
83
|
+
) {
|
|
84
|
+
return []
|
|
85
|
+
}
|
|
86
|
+
const { metadata } = await applyBabelPlugins({
|
|
87
|
+
babelPlugins: [babelPluginMetadataInlineContents],
|
|
88
|
+
urlInfo: {
|
|
89
|
+
url,
|
|
90
|
+
type: isJsModule ? "js_module" : "js_classic",
|
|
91
|
+
content: js,
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
return metadata.inlineContentInfos
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const babelPluginMetadataInlineContents = () => {
|
|
98
|
+
return {
|
|
99
|
+
name: "metadata-inline-contents",
|
|
100
|
+
visitor: {
|
|
101
|
+
Program: (programPath, state) => {
|
|
102
|
+
const inlineContentInfos = []
|
|
103
|
+
const onInlineContentInfo = (inlineContentInfo) => {
|
|
104
|
+
inlineContentInfos.push(inlineContentInfo)
|
|
105
|
+
}
|
|
106
|
+
programPath.traverse({
|
|
107
|
+
NewExpression: (path) => {
|
|
108
|
+
if (isNewInlineContentCall(path)) {
|
|
109
|
+
analyzeNewInlineContentCall(path.node, {
|
|
110
|
+
onInlineContentInfo,
|
|
111
|
+
})
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
if (isNewBlobCall(path.node)) {
|
|
115
|
+
analyzeNewBlobCall(path.node, {
|
|
116
|
+
onInlineContentInfo,
|
|
117
|
+
})
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
CallExpression: (path) => {
|
|
122
|
+
const node = path.node
|
|
123
|
+
if (isJSONParseCall(node)) {
|
|
124
|
+
analyzeJsonParseCall(node, {
|
|
125
|
+
onInlineContentInfo,
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
state.file.metadata.inlineContentInfos = inlineContentInfos
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const isNewInlineContentCall = (path) => {
|
|
137
|
+
const node = path.node
|
|
138
|
+
if (node.callee.type === "Identifier") {
|
|
139
|
+
// terser rename import to use a shorter name
|
|
140
|
+
const name = getOriginalName(path, node.callee.name)
|
|
141
|
+
return name === "InlineContent"
|
|
142
|
+
}
|
|
143
|
+
if (node.callee.id && node.callee.id.type === "Identifier") {
|
|
144
|
+
const name = getOriginalName(path, node.callee.id.name)
|
|
145
|
+
return name === "InlineContent"
|
|
146
|
+
}
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
const analyzeNewInlineContentCall = (node, { onInlineContentInfo }) => {
|
|
150
|
+
analyzeArguments({
|
|
151
|
+
node,
|
|
152
|
+
onInlineContentInfo,
|
|
153
|
+
nodeHoldingContent: node.arguments[0],
|
|
154
|
+
type: "new_inline_content_first_arg",
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const isNewBlobCall = (node) => {
|
|
159
|
+
return node.callee.type === "Identifier" && node.callee.name === "Blob"
|
|
160
|
+
}
|
|
161
|
+
const analyzeNewBlobCall = (node, { onInlineContentInfo }) => {
|
|
162
|
+
const firstArg = node.arguments[0]
|
|
163
|
+
if (firstArg.type !== "ArrayExpression") {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
if (firstArg.elements.length !== 1) {
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
analyzeArguments({
|
|
170
|
+
node,
|
|
171
|
+
onInlineContentInfo,
|
|
172
|
+
nodeHoldingContent: firstArg.elements[0],
|
|
173
|
+
type: "new_blob_first_arg",
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const analyzeArguments = ({
|
|
178
|
+
node,
|
|
179
|
+
onInlineContentInfo,
|
|
180
|
+
nodeHoldingContent,
|
|
181
|
+
type,
|
|
182
|
+
}) => {
|
|
183
|
+
if (node.arguments.length !== 2) {
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
const [, secondArg] = node.arguments
|
|
187
|
+
const typePropertyNode = getTypePropertyNode(secondArg)
|
|
188
|
+
if (!typePropertyNode) {
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
const typePropertyValueNode = typePropertyNode.value
|
|
192
|
+
if (typePropertyValueNode.type !== "StringLiteral") {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
const contentType = typePropertyValueNode.value
|
|
196
|
+
const contentDetails = extractContentDetails(nodeHoldingContent)
|
|
197
|
+
if (contentDetails) {
|
|
198
|
+
onInlineContentInfo({
|
|
199
|
+
node: nodeHoldingContent,
|
|
200
|
+
...getNodePosition(nodeHoldingContent),
|
|
201
|
+
type,
|
|
202
|
+
contentType,
|
|
203
|
+
...contentDetails,
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const extractContentDetails = (node) => {
|
|
208
|
+
if (node.type === "StringLiteral") {
|
|
209
|
+
return {
|
|
210
|
+
nodeType: "StringLiteral",
|
|
211
|
+
quote: node.extra.raw[0],
|
|
212
|
+
content: node.value,
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (node.type === "TemplateLiteral") {
|
|
216
|
+
const quasis = node.quasis
|
|
217
|
+
if (quasis.length !== 1) {
|
|
218
|
+
return null
|
|
219
|
+
}
|
|
220
|
+
const templateElementNode = quasis[0]
|
|
221
|
+
return {
|
|
222
|
+
nodeType: "TemplateLiteral",
|
|
223
|
+
quote: "`",
|
|
224
|
+
content: templateElementNode.value.cooked,
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return null
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const isJSONParseCall = (node) => {
|
|
231
|
+
const callee = node.callee
|
|
232
|
+
return (
|
|
233
|
+
callee.type === "MemberExpression" &&
|
|
234
|
+
callee.object.type === "Identifier" &&
|
|
235
|
+
callee.object.name === "JSON" &&
|
|
236
|
+
callee.property.type === "Identifier" &&
|
|
237
|
+
callee.property.name === "parse"
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
const analyzeJsonParseCall = (node, { onInlineContentInfo }) => {
|
|
241
|
+
const firstArgNode = node.arguments[0]
|
|
242
|
+
const contentDetails = extractContentDetails(firstArgNode)
|
|
243
|
+
if (contentDetails) {
|
|
244
|
+
onInlineContentInfo({
|
|
245
|
+
node: firstArgNode,
|
|
246
|
+
...getNodePosition(firstArgNode),
|
|
247
|
+
type: "json_parse_first_arg",
|
|
248
|
+
contentType: "application/json",
|
|
249
|
+
...contentDetails,
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const getNodePosition = (node) => {
|
|
255
|
+
return {
|
|
256
|
+
start: node.start,
|
|
257
|
+
end: node.end,
|
|
258
|
+
line: node.loc.start.line,
|
|
259
|
+
column: node.loc.start.column,
|
|
260
|
+
lineEnd: node.loc.end.line,
|
|
261
|
+
columnEnd: node.loc.end.column,
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const getOriginalName = (path, name) => {
|
|
265
|
+
const binding = path.scope.getBinding(name)
|
|
266
|
+
if (!binding) {
|
|
267
|
+
return name
|
|
268
|
+
}
|
|
269
|
+
if (binding.path.type === "ImportSpecifier") {
|
|
270
|
+
const importedName = binding.path.node.imported.name
|
|
271
|
+
if (name === importedName) {
|
|
272
|
+
return name
|
|
273
|
+
}
|
|
274
|
+
return getOriginalName(path, importedName)
|
|
275
|
+
}
|
|
276
|
+
if (binding.path.type === "VariableDeclarator") {
|
|
277
|
+
if (binding.path.node.init.type === "Identifier") {
|
|
278
|
+
const previousName = binding.path.node.init.name
|
|
279
|
+
return getOriginalName(path, previousName)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return name
|
|
283
|
+
}
|
|
284
|
+
const getTypePropertyNode = (node) => {
|
|
285
|
+
if (node.type !== "ObjectExpression") {
|
|
286
|
+
return null
|
|
287
|
+
}
|
|
288
|
+
const { properties } = node
|
|
289
|
+
return properties.find((property) => {
|
|
290
|
+
return (
|
|
291
|
+
property.type === "ObjectProperty" &&
|
|
292
|
+
property.key.type === "Identifier" &&
|
|
293
|
+
property.key.name === "type"
|
|
294
|
+
)
|
|
295
|
+
})
|
|
296
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const jsenvPluginLeadingSlash = () => {
|
|
2
|
+
return {
|
|
3
|
+
name: "jsenv:leading_slash",
|
|
4
|
+
appliesDuring: "*",
|
|
5
|
+
resolveUrl: (reference, context) => {
|
|
6
|
+
if (reference.specifier[0] !== "/") {
|
|
7
|
+
return null
|
|
8
|
+
}
|
|
9
|
+
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl)
|
|
10
|
+
.href
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createRequire } from "node:module"
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url)
|
|
4
|
+
|
|
5
|
+
// https://github.com/kangax/html-minifier#options-quick-reference
|
|
6
|
+
export const minifyHtml = ({ htmlUrlInfo, options } = {}) => {
|
|
7
|
+
const { collapseWhitespace = true, removeComments = true } = options
|
|
8
|
+
|
|
9
|
+
const { minify } = require("html-minifier")
|
|
10
|
+
const htmlMinified = minify(htmlUrlInfo.content, {
|
|
11
|
+
collapseWhitespace,
|
|
12
|
+
removeComments,
|
|
13
|
+
})
|
|
14
|
+
return htmlMinified
|
|
15
|
+
}
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
// https://github.com/terser-js/terser#minify-options
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
sourcemap: urlInfo.sourcemap,
|
|
9
|
-
isJsModule: urlInfo.type === "js_module",
|
|
10
|
-
})
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
name: "jsenv:minify_js",
|
|
15
|
-
appliesDuring: {
|
|
16
|
-
build: true,
|
|
17
|
-
},
|
|
18
|
-
optimize: {
|
|
19
|
-
js_classic: applyTerser,
|
|
20
|
-
js_module: applyTerser,
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
}
|
|
3
|
+
export const minifyJs = async ({ jsUrlInfo, options }) => {
|
|
4
|
+
const url = jsUrlInfo.url
|
|
5
|
+
const content = jsUrlInfo.content
|
|
6
|
+
const sourcemap = jsUrlInfo.sourcemap
|
|
7
|
+
const isJsModule = jsUrlInfo.type === "js_module"
|
|
24
8
|
|
|
25
|
-
const minifyJs = async ({ url, content, sourcemap, isJsModule }) => {
|
|
26
9
|
const { minify } = await import("terser")
|
|
27
10
|
const terserResult = await minify(
|
|
28
11
|
{
|
|
@@ -38,6 +21,7 @@ const minifyJs = async ({ url, content, sourcemap, isJsModule }) => {
|
|
|
38
21
|
// We need to preserve "new InlineContent()" calls to be able to recognize them
|
|
39
22
|
// after minification in order to version urls inside inline content text
|
|
40
23
|
keep_fnames: /InlineContent/,
|
|
24
|
+
...options,
|
|
41
25
|
},
|
|
42
26
|
)
|
|
43
27
|
return {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { minifyHtml } from "./html/minify_html.js"
|
|
2
|
+
import { minifyCss } from "./css/minify_css.js"
|
|
3
|
+
import { minifyJs } from "./js/minify_js.js"
|
|
4
|
+
import { minifyJson } from "./json/minify_json.js"
|
|
5
|
+
|
|
6
|
+
export const jsenvPluginMinification = (minification) => {
|
|
7
|
+
if (typeof minification === "boolean") {
|
|
8
|
+
minification = {
|
|
9
|
+
html: minification,
|
|
10
|
+
css: minification,
|
|
11
|
+
js_classic: minification,
|
|
12
|
+
js_module: minification,
|
|
13
|
+
json: minification,
|
|
14
|
+
svg: minification,
|
|
15
|
+
}
|
|
16
|
+
} else if (typeof minification !== "object") {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`minification must be a boolean or an object, got ${minification}`,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
Object.keys(minification).forEach((key) => {
|
|
22
|
+
if (minification[key] === true) minification[key] = {}
|
|
23
|
+
})
|
|
24
|
+
const htmlOptimizer = minification.html
|
|
25
|
+
? (urlInfo, context) =>
|
|
26
|
+
minifyHtml({
|
|
27
|
+
htmlUrlInfo: urlInfo,
|
|
28
|
+
context,
|
|
29
|
+
options: minification.html,
|
|
30
|
+
})
|
|
31
|
+
: null
|
|
32
|
+
const jsonOptimizer = minification.json
|
|
33
|
+
? (urlInfo, context) =>
|
|
34
|
+
minifyJson({
|
|
35
|
+
jsonUrlInfo: urlInfo,
|
|
36
|
+
context,
|
|
37
|
+
options: minification.json,
|
|
38
|
+
})
|
|
39
|
+
: null
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
name: "jsenv:minification",
|
|
43
|
+
appliesDuring: {
|
|
44
|
+
build: true,
|
|
45
|
+
},
|
|
46
|
+
optimizeUrlContent: {
|
|
47
|
+
html: htmlOptimizer,
|
|
48
|
+
svg: htmlOptimizer,
|
|
49
|
+
css: minification.css
|
|
50
|
+
? (urlInfo, context) =>
|
|
51
|
+
minifyCss({
|
|
52
|
+
cssUrlInfo: urlInfo,
|
|
53
|
+
context,
|
|
54
|
+
options: minification.css,
|
|
55
|
+
})
|
|
56
|
+
: null,
|
|
57
|
+
js_classic: minification.js_classic
|
|
58
|
+
? (urlInfo, context) =>
|
|
59
|
+
minifyJs({
|
|
60
|
+
jsUrlInfo: urlInfo,
|
|
61
|
+
context,
|
|
62
|
+
options: minification.js_classic,
|
|
63
|
+
})
|
|
64
|
+
: null,
|
|
65
|
+
js_module: minification.js_module
|
|
66
|
+
? (urlInfo, context) =>
|
|
67
|
+
minifyJs({
|
|
68
|
+
jsUrlInfo: urlInfo,
|
|
69
|
+
context,
|
|
70
|
+
options: minification.js_module,
|
|
71
|
+
})
|
|
72
|
+
: null,
|
|
73
|
+
json: jsonOptimizer,
|
|
74
|
+
importmap: jsonOptimizer,
|
|
75
|
+
webmanifest: jsonOptimizer,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* - should I restore eventual search params lost during node esm resolution
|
|
3
|
+
* - what about symlinks?
|
|
4
|
+
* It feels like I should apply symlink (when we don't want to preserve them)
|
|
5
|
+
* once a file:/// url is found, regardless
|
|
6
|
+
* if that comes from node resolution or anything else (not even magic resolution)
|
|
7
|
+
* it should likely be an other plugin happening after the others
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { registerFileLifecycle } from "@jsenv/filesystem"
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
applyNodeEsmResolution,
|
|
14
|
+
defaultLookupPackageScope,
|
|
15
|
+
defaultReadPackageJson,
|
|
16
|
+
} from "@jsenv/node-esm-resolution"
|
|
17
|
+
|
|
18
|
+
export const jsenvPluginNodeEsmResolution = ({
|
|
19
|
+
rootDirectoryUrl,
|
|
20
|
+
// https://nodejs.org/api/esm.html#resolver-algorithm-specification
|
|
21
|
+
packageConditions = ["browser", "import"],
|
|
22
|
+
filesInvalidatingCache = ["package.json", "package-lock.json"],
|
|
23
|
+
}) => {
|
|
24
|
+
const packageScopesCache = new Map()
|
|
25
|
+
const lookupPackageScope = (url) => {
|
|
26
|
+
const fromCache = packageScopesCache.get(url)
|
|
27
|
+
if (fromCache) {
|
|
28
|
+
return fromCache
|
|
29
|
+
}
|
|
30
|
+
const packageScope = defaultLookupPackageScope(url)
|
|
31
|
+
packageScopesCache.set(url, packageScope)
|
|
32
|
+
return packageScope
|
|
33
|
+
}
|
|
34
|
+
const packageJsonsCache = new Map()
|
|
35
|
+
const readPackageJson = (url) => {
|
|
36
|
+
const fromCache = packageJsonsCache.get(url)
|
|
37
|
+
if (fromCache) {
|
|
38
|
+
return fromCache
|
|
39
|
+
}
|
|
40
|
+
const packageJson = defaultReadPackageJson(url)
|
|
41
|
+
packageJsonsCache.set(url, packageJson)
|
|
42
|
+
return packageJson
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const unregisters = []
|
|
46
|
+
filesInvalidatingCache.forEach((file) => {
|
|
47
|
+
const unregister = registerFileLifecycle(new URL(file, rootDirectoryUrl), {
|
|
48
|
+
added: () => {
|
|
49
|
+
packageScopesCache.clear()
|
|
50
|
+
packageJsonsCache.clear()
|
|
51
|
+
},
|
|
52
|
+
updated: () => {
|
|
53
|
+
packageScopesCache.clear()
|
|
54
|
+
packageJsonsCache.clear()
|
|
55
|
+
},
|
|
56
|
+
removed: () => {
|
|
57
|
+
packageScopesCache.clear()
|
|
58
|
+
packageJsonsCache.clear()
|
|
59
|
+
},
|
|
60
|
+
keepProcessAlive: false,
|
|
61
|
+
})
|
|
62
|
+
unregisters.push(unregister)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
jsenvPluginNodeEsmResolver({
|
|
67
|
+
packageConditions,
|
|
68
|
+
lookupPackageScope,
|
|
69
|
+
readPackageJson,
|
|
70
|
+
}),
|
|
71
|
+
jsenvPluginNodeModulesVersionInUrls({
|
|
72
|
+
lookupPackageScope,
|
|
73
|
+
readPackageJson,
|
|
74
|
+
}),
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const jsenvPluginNodeEsmResolver = ({
|
|
79
|
+
packageConditions,
|
|
80
|
+
lookupPackageScope,
|
|
81
|
+
readPackageJson,
|
|
82
|
+
}) => {
|
|
83
|
+
return {
|
|
84
|
+
name: "jsenv:node_esm_resolve",
|
|
85
|
+
appliesDuring: "*",
|
|
86
|
+
resolveUrl: {
|
|
87
|
+
js_import_export: (reference) => {
|
|
88
|
+
const { parentUrl, specifier } = reference
|
|
89
|
+
const { url } = applyNodeEsmResolution({
|
|
90
|
+
conditions: packageConditions,
|
|
91
|
+
parentUrl,
|
|
92
|
+
specifier,
|
|
93
|
+
lookupPackageScope,
|
|
94
|
+
readPackageJson,
|
|
95
|
+
})
|
|
96
|
+
return url
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
fetchUrlContent: (urlInfo) => {
|
|
100
|
+
if (urlInfo.url.startsWith("file:///@ignore/")) {
|
|
101
|
+
return {
|
|
102
|
+
content: "export default {}",
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const jsenvPluginNodeModulesVersionInUrls = ({
|
|
111
|
+
lookupPackageScope,
|
|
112
|
+
readPackageJson,
|
|
113
|
+
}) => {
|
|
114
|
+
return {
|
|
115
|
+
name: "jsenv:node_modules_version_in_urls",
|
|
116
|
+
appliesDuring: {
|
|
117
|
+
dev: true,
|
|
118
|
+
test: true,
|
|
119
|
+
},
|
|
120
|
+
transformUrlSearchParams: (reference, context) => {
|
|
121
|
+
if (!reference.url.startsWith("file:")) {
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
// without this check a file inside a project without package.json
|
|
125
|
+
// could be considered as a node module if there is a ancestor package.json
|
|
126
|
+
// but we want to version only node modules
|
|
127
|
+
if (!reference.url.includes("/node_modules/")) {
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
if (reference.searchParams.has("v")) {
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
const packageUrl = lookupPackageScope(reference.url)
|
|
134
|
+
if (!packageUrl) {
|
|
135
|
+
return null
|
|
136
|
+
}
|
|
137
|
+
if (packageUrl === context.rootDirectoryUrl) {
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
const packageVersion = readPackageJson(packageUrl).version
|
|
141
|
+
return {
|
|
142
|
+
v: packageVersion,
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
}
|