@jsenv/core 35.0.5 → 36.0.1

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/js/inline_content.js +5 -4
  3. package/dist/jsenv_core.js +1127 -1497
  4. package/package.json +8 -8
  5. package/src/build/build.js +49 -41
  6. package/src/dev/file_service.js +7 -17
  7. package/src/dev/start_dev_server.js +12 -7
  8. package/src/kitchen/kitchen.js +38 -19
  9. package/src/kitchen/url_graph.js +1 -1
  10. package/src/plugins/autoreload/jsenv_plugin_hmr.js +2 -2
  11. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +4 -4
  12. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +1 -1
  13. package/src/plugins/importmap/jsenv_plugin_importmap.js +1 -1
  14. package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -1
  15. package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +13 -2
  16. package/src/plugins/plugin_controller.js +19 -10
  17. package/src/plugins/plugins.js +21 -25
  18. package/src/plugins/{url_analysis/css/css_urls.js → reference_analysis/css/jsenv_plugin_css_reference_analysis.js} +11 -1
  19. package/src/plugins/{inline_content_analysis/jsenv_plugin_data_urls.js → reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js} +19 -19
  20. package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +51 -0
  21. package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +429 -0
  22. package/src/plugins/reference_analysis/inline_content.js +7 -0
  23. package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +161 -0
  24. package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +120 -0
  25. package/src/plugins/{url_analysis → reference_analysis}/jsenv_plugin_reference_expected_types.js +19 -12
  26. package/src/plugins/{url_analysis/webmanifest/webmanifest_urls.js → reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js} +13 -1
  27. package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +74 -0
  28. package/src/plugins/{url_resolution → resolution_node_esm}/node_esm_resolver.js +8 -0
  29. package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +45 -0
  30. package/src/plugins/transpilation/as_js_module/jsenv_plugin_as_js_module.js +1 -1
  31. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
  32. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +4 -6
  33. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_conversion.js +1 -1
  34. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +4 -6
  35. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +1 -1
  36. package/src/plugins/url_type_from_reference.js +13 -0
  37. package/src/plugins/{url_version/jsenv_plugin_url_version.js → version_search_param/jsenv_plugin_version_search_param.js} +4 -4
  38. package/dist/html/explorer.html +0 -559
  39. package/dist/other/jsenv.png +0 -0
  40. package/src/plugins/explorer/client/explorer.html +0 -608
  41. package/src/plugins/explorer/client/jsenv.png +0 -0
  42. package/src/plugins/explorer/jsenv_plugin_explorer.js +0 -86
  43. package/src/plugins/inline_content_analysis/client/inline_content.js +0 -6
  44. package/src/plugins/inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js +0 -206
  45. package/src/plugins/inline_content_analysis/jsenv_plugin_inline_content_analysis.js +0 -34
  46. package/src/plugins/inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js +0 -314
  47. package/src/plugins/url_analysis/html/html_urls.js +0 -313
  48. package/src/plugins/url_analysis/js/js_urls.js +0 -65
  49. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +0 -116
  50. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +0 -140
@@ -0,0 +1,120 @@
1
+ import { URL_META } from "@jsenv/url-meta";
2
+
3
+ import { jsenvPluginReferenceExpectedTypes } from "./jsenv_plugin_reference_expected_types.js";
4
+ import { jsenvPluginDirectoryReferenceAnalysis } from "./directory/jsenv_plugin_directory_reference_analysis.js";
5
+ import { jsenvPluginDataUrlsAnalysis } from "./data_urls/jsenv_plugin_data_urls_analysis.js";
6
+ import { jsenvPluginHtmlReferenceAnalysis } from "./html/jsenv_plugin_html_reference_analysis.js";
7
+ import { jsenvPluginWebmanifestReferenceAnalysis } from "./webmanifest/jsenv_plugin_webmanifest_reference_analysis.js";
8
+ import { jsenvPluginCssReferenceAnalysis } from "./css/jsenv_plugin_css_reference_analysis.js";
9
+ import { jsenvPluginJsReferenceAnalysis } from "./js/jsenv_plugin_js_reference_analysis.js";
10
+
11
+ export const jsenvPluginReferenceAnalysis = ({
12
+ include,
13
+ supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
14
+
15
+ inlineContent = true,
16
+ inlineConvertedScript = false,
17
+ fetchInlineUrls = true,
18
+ allowEscapeForVersioning = false,
19
+ }) => {
20
+ return [
21
+ jsenvPluginReferenceAnalysisInclude({
22
+ include,
23
+ supportedProtocols,
24
+ }),
25
+ jsenvPluginDirectoryReferenceAnalysis(),
26
+ jsenvPluginHtmlReferenceAnalysis({
27
+ inlineContent,
28
+ inlineConvertedScript,
29
+ }),
30
+ jsenvPluginWebmanifestReferenceAnalysis(),
31
+ jsenvPluginCssReferenceAnalysis(),
32
+ jsenvPluginJsReferenceAnalysis({
33
+ inlineContent,
34
+ allowEscapeForVersioning,
35
+ }),
36
+ ...(inlineContent ? [jsenvPluginDataUrlsAnalysis()] : []),
37
+ ...(inlineContent && fetchInlineUrls
38
+ ? [jsenvPluginInlineContentFetcher()]
39
+ : []),
40
+ jsenvPluginReferenceExpectedTypes(),
41
+ ];
42
+ };
43
+
44
+ const jsenvPluginReferenceAnalysisInclude = ({
45
+ include,
46
+ supportedProtocols,
47
+ }) => {
48
+ // eslint-disable-next-line no-unused-vars
49
+ let getIncludeInfo = (url) => undefined;
50
+
51
+ return {
52
+ name: "jsenv:reference_analysis_include",
53
+ appliesDuring: "*",
54
+ init: ({ rootDirectoryUrl }) => {
55
+ if (include) {
56
+ const associations = URL_META.resolveAssociations(
57
+ { include },
58
+ rootDirectoryUrl,
59
+ );
60
+ getIncludeInfo = (url) => {
61
+ const { include } = URL_META.applyAssociations({
62
+ url,
63
+ associations,
64
+ });
65
+ return include;
66
+ };
67
+ }
68
+ },
69
+ redirectReference: (reference) => {
70
+ if (reference.shouldHandle !== undefined) {
71
+ return;
72
+ }
73
+ if (
74
+ reference.specifier[0] === "#" &&
75
+ // For Html, css and in general "#" refer to a resource in the page
76
+ // so that urls must be kept intact
77
+ // However for js import specifiers they have a different meaning and we want
78
+ // to resolve them (https://nodejs.org/api/packages.html#imports for instance)
79
+ reference.type !== "js_import"
80
+ ) {
81
+ reference.shouldHandle = false;
82
+ return;
83
+ }
84
+ const includeInfo = getIncludeInfo(reference.url);
85
+ if (includeInfo === true) {
86
+ reference.shouldHandle = true;
87
+ return;
88
+ }
89
+ if (includeInfo === false) {
90
+ reference.shouldHandle = false;
91
+ return;
92
+ }
93
+ const { protocol } = new URL(reference.url);
94
+ const protocolIsSupported = supportedProtocols.some(
95
+ (supportedProtocol) => protocol === supportedProtocol,
96
+ );
97
+ if (protocolIsSupported) {
98
+ reference.shouldHandle = true;
99
+ }
100
+ },
101
+ };
102
+ };
103
+
104
+ const jsenvPluginInlineContentFetcher = () => {
105
+ return {
106
+ name: "jsenv:inline_content_fetcher",
107
+ appliesDuring: "*",
108
+ fetchUrlContent: (urlInfo) => {
109
+ if (!urlInfo.isInline) {
110
+ return null;
111
+ }
112
+ return {
113
+ // we want to fetch the original content otherwise we might re-cook
114
+ // content already cooked
115
+ content: urlInfo.originalContent,
116
+ contentType: urlInfo.contentType,
117
+ };
118
+ },
119
+ };
120
+ };
@@ -1,7 +1,7 @@
1
1
  import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
2
2
 
3
3
  export const jsenvPluginReferenceExpectedTypes = () => {
4
- const redirectJsUrls = (reference) => {
4
+ const redirectJsReference = (reference) => {
5
5
  const urlObject = new URL(reference.url);
6
6
  const { searchParams } = urlObject;
7
7
 
@@ -10,23 +10,30 @@ export const jsenvPluginReferenceExpectedTypes = () => {
10
10
  }
11
11
  if (searchParams.has("js_classic")) {
12
12
  reference.expectedType = "js_classic";
13
- } else if (
13
+ } else if (searchParams.has("js_module")) {
14
+ reference.expectedType = "js_module";
15
+ }
16
+ // we need to keep these checks here because during versioning:
17
+ // - only reference anlysis plugin is executed
18
+ // -> plugin about js transpilation don't apply and can't set expectedType: 'js_classic'
19
+ // - query params like ?js_module_fallback are still there
20
+ // - without this check build would throw as reference could expect js module and find js classic
21
+ else if (
14
22
  searchParams.has("js_module_fallback") ||
15
23
  searchParams.has("as_js_classic")
16
24
  ) {
17
25
  reference.expectedType = "js_classic";
18
26
  } else if (searchParams.has("as_js_module")) {
19
27
  reference.expectedType = "js_module";
20
- } else if (searchParams.has("js_module")) {
21
- reference.expectedType = "js_module";
22
- } else if (
28
+ }
29
+ // by default, js referenced by new URL is considered as "js_module"
30
+ // in case this is not desired code must use "?js_classic" like
31
+ // new URL('./file.js?js_classic', import.meta.url)
32
+ else if (
23
33
  reference.type === "js_url" &&
24
34
  reference.expectedType === undefined &&
25
35
  CONTENT_TYPE.fromUrlExtension(reference.url) === "text/javascript"
26
36
  ) {
27
- // by default, js referenced by new URL is considered as "js_module"
28
- // in case this is not desired code must use "?js_classic" like
29
- // new URL('./file.js?js_classic', import.meta.url)
30
37
  reference.expectedType = "js_module";
31
38
  }
32
39
 
@@ -43,10 +50,10 @@ export const jsenvPluginReferenceExpectedTypes = () => {
43
50
  return {
44
51
  name: "jsenv:reference_expected_types",
45
52
  appliesDuring: "*",
46
- redirectUrl: {
47
- script: redirectJsUrls,
48
- js_url: redirectJsUrls,
49
- js_import: redirectJsUrls,
53
+ redirectReference: {
54
+ script: redirectJsReference,
55
+ js_url: redirectJsReference,
56
+ js_import: redirectJsReference,
50
57
  },
51
58
  };
52
59
  };
@@ -1,4 +1,16 @@
1
- export const parseAndTransformWebmanifestUrls = async (urlInfo, context) => {
1
+ // css: parseAndTransformCssUrls,
2
+
3
+ export const jsenvPluginWebmanifestReferenceAnalysis = () => {
4
+ return {
5
+ name: "jsenv:webmanifest_reference_analysis",
6
+ appliesDuring: "*",
7
+ transformUrlContent: {
8
+ webmanifest: parseAndTransformWebmanifestUrls,
9
+ },
10
+ };
11
+ };
12
+
13
+ const parseAndTransformWebmanifestUrls = async (urlInfo, context) => {
2
14
  const content = urlInfo.content;
3
15
  const manifest = JSON.parse(content);
4
16
  const actions = [];
@@ -0,0 +1,74 @@
1
+ import { urlTypeFromReference } from "../url_type_from_reference.js";
2
+ import { createNodeEsmResolver } from "./node_esm_resolver.js";
3
+
4
+ export const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
5
+ let nodeEsmResolverDefault;
6
+ const resolvers = {};
7
+ Object.keys(resolutionConfig).forEach((urlType) => {
8
+ const config = resolutionConfig[urlType];
9
+ if (config === true) {
10
+ resolvers[urlType] = (...args) => nodeEsmResolverDefault(...args);
11
+ } else if (config === false) {
12
+ resolvers[urlType] = () => null;
13
+ } else if (typeof config === "object") {
14
+ const { runtimeCompat, packageConditions, preservesSymlink, ...rest } =
15
+ config;
16
+ const unexpectedKeys = Object.keys(rest);
17
+ if (unexpectedKeys.length) {
18
+ throw new TypeError(
19
+ `${unexpectedKeys.join(
20
+ ",",
21
+ )}: there is no such configuration on "${urlType}"`,
22
+ );
23
+ }
24
+ resolvers[urlType] = createNodeEsmResolver({
25
+ runtimeCompat,
26
+ packageConditions,
27
+ preservesSymlink,
28
+ });
29
+ } else {
30
+ throw new TypeError(
31
+ `config must be true, false or an object, got ${config} on "${urlType}"`,
32
+ );
33
+ }
34
+ });
35
+
36
+ return {
37
+ name: "jsenv:node_esm_resolution",
38
+ appliesDuring: "*",
39
+ init: ({ runtimeCompat }) => {
40
+ nodeEsmResolverDefault = createNodeEsmResolver({
41
+ runtimeCompat,
42
+ preservesSymlink: true,
43
+ });
44
+ if (!resolvers.js_module) {
45
+ resolvers.js_module = nodeEsmResolverDefault;
46
+ }
47
+ if (!resolvers.js_classic) {
48
+ resolvers.js_classic = (reference, context) => {
49
+ if (reference.subtype === "self_import_scripts_arg") {
50
+ return nodeEsmResolverDefault(reference, context);
51
+ }
52
+ return null;
53
+ };
54
+ }
55
+ },
56
+ resolveReference: (reference, context) => {
57
+ const urlType = urlTypeFromReference(reference, context);
58
+ const resolver = resolvers[urlType];
59
+ return resolver ? resolver(reference, context) : null;
60
+ },
61
+ // when specifier is prefixed by "file:///@ignore/"
62
+ // we return an empty js module
63
+ fetchUrlContent: (urlInfo) => {
64
+ if (urlInfo.url.startsWith("file:///@ignore/")) {
65
+ return {
66
+ content: "export default {}",
67
+ contentType: "text/javascript",
68
+ type: "js_module",
69
+ };
70
+ }
71
+ return null;
72
+ },
73
+ };
74
+ };
@@ -33,6 +33,14 @@ export const createNodeEsmResolver = ({
33
33
  if (reference.type === "package_json") {
34
34
  return reference.specifier;
35
35
  }
36
+ if (reference.specifier === "/") {
37
+ const { mainFilePath, rootDirectoryUrl } = context;
38
+ return String(new URL(mainFilePath, rootDirectoryUrl));
39
+ }
40
+ if (reference.specifier[0] === "/") {
41
+ return new URL(reference.specifier.slice(1), context.rootDirectoryUrl)
42
+ .href;
43
+ }
36
44
  const parentUrl = reference.baseUrl || reference.parentUrl;
37
45
  if (!parentUrl.startsWith("file:")) {
38
46
  return new URL(reference.specifier, parentUrl).href;
@@ -0,0 +1,45 @@
1
+ import { urlTypeFromReference } from "../url_type_from_reference.js";
2
+
3
+ export const jsenvPluginWebResolution = (resolutionConfig = {}) => {
4
+ const resolvers = {};
5
+ const resolveUsingWebResolution = (reference, context) => {
6
+ if (reference.specifier === "/") {
7
+ const { mainFilePath, rootDirectoryUrl } = context;
8
+ return String(new URL(mainFilePath, rootDirectoryUrl));
9
+ }
10
+ if (reference.specifier[0] === "/") {
11
+ return new URL(reference.specifier.slice(1), context.rootDirectoryUrl)
12
+ .href;
13
+ }
14
+ return new URL(
15
+ reference.specifier,
16
+ // baseUrl happens second argument to new URL() is different from
17
+ // import.meta.url or document.currentScript.src
18
+ reference.baseUrl || reference.parentUrl,
19
+ ).href;
20
+ };
21
+ Object.keys(resolutionConfig).forEach((urlType) => {
22
+ const config = resolutionConfig[urlType];
23
+ if (config === true) {
24
+ resolvers[urlType] = resolveUsingWebResolution;
25
+ } else if (config === false) {
26
+ resolvers[urlType] = () => null;
27
+ } else {
28
+ throw new TypeError(
29
+ `config must be true or false, got ${config} on "${urlType}"`,
30
+ );
31
+ }
32
+ });
33
+
34
+ return {
35
+ name: "jsenv:web_resolution",
36
+ appliesDuring: "*",
37
+ resolveReference: (reference, context) => {
38
+ const urlType = urlTypeFromReference(reference, context);
39
+ const resolver = resolvers[urlType];
40
+ return resolver
41
+ ? resolver(reference, context)
42
+ : resolveUsingWebResolution(reference, context);
43
+ },
44
+ };
45
+ };
@@ -17,7 +17,7 @@ export const jsenvPluginAsJsModule = () => {
17
17
  return {
18
18
  name: "jsenv:as_js_module",
19
19
  appliesDuring: "*",
20
- redirectUrl: (reference) => {
20
+ redirectReference: (reference) => {
21
21
  if (reference.searchParams.has("as_js_module")) {
22
22
  reference.expectedType = "js_module";
23
23
  const filename = urlToFilename(reference.url);
@@ -92,7 +92,7 @@ export const jsenvPluginBabel = ({
92
92
  return {
93
93
  name: "jsenv:babel",
94
94
  appliesDuring: "*",
95
- finalizeUrlContent: {
95
+ transformUrlContent: {
96
96
  js_classic: transformWithBabel,
97
97
  js_module: transformWithBabel,
98
98
  },
@@ -78,7 +78,7 @@ export const jsenvPluginImportAssertions = ({
78
78
  transpilations.text = true;
79
79
  }
80
80
  },
81
- redirectUrl: (reference, context) => {
81
+ redirectReference: (reference, context) => {
82
82
  if (!reference.assert) {
83
83
  return null;
84
84
  }
@@ -103,7 +103,7 @@ export const jsenvPluginImportAssertions = ({
103
103
 
104
104
  const jsenvPluginAsModules = () => {
105
105
  const inlineContentClientFileUrl = new URL(
106
- "../../inline_content_analysis/client/inline_content.js",
106
+ "../../reference_analysis/inline_content.js",
107
107
  import.meta.url,
108
108
  ).href;
109
109
 
@@ -181,11 +181,9 @@ const jsenvPluginAsModules = () => {
181
181
  canUseTemplateString: true,
182
182
  });
183
183
  return {
184
- content: `import { InlineContent } from ${JSON.stringify(
185
- inlineContentClientFileUrl,
186
- )}
184
+ content: `import ${JSON.stringify(inlineContentClientFileUrl)}
187
185
 
188
- const inlineContent = new InlineContent(${cssText}, { type: "text/css" })
186
+ const inlineContent = new __InlineContent__(${cssText}, { type: "text/css" })
189
187
  const stylesheet = new CSSStyleSheet()
190
188
  stylesheet.replaceSync(inlineContent.text)
191
189
  export default stylesheet`,
@@ -55,7 +55,7 @@ export const jsenvPluginJsModuleConversion = ({
55
55
  return {
56
56
  name: "jsenv:js_module_conversion",
57
57
  appliesDuring: "*",
58
- redirectUrl: (reference, context) => {
58
+ redirectReference: (reference, context) => {
59
59
  if (reference.searchParams.has("js_module_fallback")) {
60
60
  markAsJsClassicProxy(reference);
61
61
  return null;
@@ -30,7 +30,7 @@ export const jsenvPluginJsModuleFallbackInsideHtml = ({
30
30
  return {
31
31
  name: "jsenv:js_module_fallback_inside_html",
32
32
  appliesDuring: "*",
33
- redirectUrl: {
33
+ redirectReference: {
34
34
  link_href: (reference, context) => {
35
35
  if (
36
36
  context.systemJsTranspilation &&
@@ -135,7 +135,6 @@ export const jsenvPluginJsModuleFallbackInsideHtml = ({
135
135
  }
136
136
  },
137
137
  });
138
-
139
138
  if (systemJsInjection) {
140
139
  let needsSystemJs = false;
141
140
  for (const reference of urlInfo.references) {
@@ -213,11 +212,10 @@ export const jsenvPluginJsModuleFallbackInsideHtml = ({
213
212
  });
214
213
  }
215
214
  }
216
- if (mutations.length === 0) {
217
- return null;
218
- }
219
215
  await Promise.all(mutations.map((mutation) => mutation()));
220
- return stringifyHtmlAst(htmlAst);
216
+ return stringifyHtmlAst(htmlAst, {
217
+ cleanupPositionAttributes: context.dev,
218
+ });
221
219
  },
222
220
  },
223
221
  };
@@ -28,7 +28,7 @@ export const jsenvPluginJsModuleFallbackOnWorkers = () => {
28
28
  return {
29
29
  name: "jsenv:js_module_fallback_on_workers",
30
30
  appliesDuring: "*",
31
- redirectUrl: {
31
+ redirectReference: {
32
32
  js_url: (reference, context) => {
33
33
  if (reference.expectedType !== "js_module") {
34
34
  return null;
@@ -0,0 +1,13 @@
1
+ export const urlTypeFromReference = (reference, context) => {
2
+ if (reference.type === "sourcemap_comment") {
3
+ return "sourcemap";
4
+ }
5
+ if (reference.injected) {
6
+ return reference.expectedType;
7
+ }
8
+ const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl);
9
+ if (parentUrlInfo) {
10
+ return parentUrlInfo.type;
11
+ }
12
+ return "entry_point";
13
+ };
@@ -1,8 +1,8 @@
1
- export const jsenvPluginUrlVersion = () => {
1
+ export const jsenvPluginVersionSearchParam = () => {
2
2
  return {
3
- name: "jsenv:url_version",
3
+ name: "jsenv:version_search_param",
4
4
  appliesDuring: "dev",
5
- redirectUrl: (reference) => {
5
+ redirectReference: (reference) => {
6
6
  // "v" search param goal is to enable long-term cache
7
7
  // for server response headers
8
8
  // it is also used by hmr to bypass browser cache
@@ -18,7 +18,7 @@ export const jsenvPluginUrlVersion = () => {
18
18
  }
19
19
  return null;
20
20
  },
21
- transformUrlSearchParams: (reference) => {
21
+ transformReferenceSearchParams: (reference) => {
22
22
  if (!reference.version) {
23
23
  return null;
24
24
  }