@jsenv/core 40.7.2 → 40.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7645,6 +7645,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
7645
7645
  };
7646
7646
  };
7647
7647
 
7648
+ /**
7649
+ * Inline CSS would force to write the following boilerplate all the time:
7650
+ * ```js
7651
+ * const css = `body { color: red; }`;
7652
+ * const stylesheet = new CSSStyleSheet();
7653
+ * stylesheet.replaceSync(css);
7654
+ * document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
7655
+ * if (import.meta.hot) {
7656
+ * import.meta.hot.dispose(() => {
7657
+ * document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
7658
+ * (s) => s !== stylesheet,
7659
+ * );
7660
+ * });
7661
+ * }
7662
+ * ```
7663
+ *
7664
+ * It would be nice to have a plugin that does this automatically with the following syntax
7665
+ *
7666
+ * ```js
7667
+ * const css = `body { color: red; }`;
7668
+ * import.meta.css = css;
7669
+ * ```
7670
+ *
7671
+ */
7672
+
7673
+
7674
+ const jsenvPluginImportMetaCss = () => {
7675
+ const importMetaCssClientFileUrl = import.meta.resolve(
7676
+ "../js/import_meta_css.js",
7677
+ );
7678
+
7679
+ return {
7680
+ name: "jsenv:import_meta_css",
7681
+ appliesDuring: "*",
7682
+ transformUrlContent: {
7683
+ js_module: async (urlInfo) => {
7684
+ if (!urlInfo.content.includes("import.meta.css")) {
7685
+ return null;
7686
+ }
7687
+ const { metadata } = await applyBabelPlugins({
7688
+ babelPlugins: [babelPluginMetadataUsesImportMetaCss],
7689
+ input: urlInfo.content,
7690
+ inputIsJsModule: true,
7691
+ inputUrl: urlInfo.originalUrl,
7692
+ outputUrl: urlInfo.generatedUrl,
7693
+ });
7694
+ const { usesImportMetaCss } = metadata;
7695
+ if (!usesImportMetaCss) {
7696
+ return null;
7697
+ }
7698
+ return injectImportMetaCss(urlInfo, importMetaCssClientFileUrl);
7699
+ },
7700
+ },
7701
+ };
7702
+ };
7703
+
7704
+ const injectImportMetaCss = (urlInfo, importMetaCssClientFileUrl) => {
7705
+ const importMetaCssClientFileReference = urlInfo.dependencies.inject({
7706
+ parentUrl: urlInfo.url,
7707
+ type: "js_import",
7708
+ expectedType: "js_module",
7709
+ specifier: importMetaCssClientFileUrl,
7710
+ });
7711
+ let content = urlInfo.content;
7712
+ let prelude = `import { installImportMetaCss } from ${importMetaCssClientFileReference.generatedSpecifier};
7713
+
7714
+ const remove = installImportMetaCss(import.meta);
7715
+ if (import.meta.hot) {
7716
+ import.meta.hot.dispose(() => {
7717
+ remove();
7718
+ });
7719
+ }
7720
+
7721
+ `;
7722
+ return {
7723
+ content: `${prelude.replace(/\n/g, "")}${content}`,
7724
+ };
7725
+ };
7726
+
7727
+ const babelPluginMetadataUsesImportMetaCss = () => {
7728
+ return {
7729
+ name: "metadata-uses-import-meta-css",
7730
+ visitor: {
7731
+ Program(programPath, state) {
7732
+ let usesImportMetaCss = false;
7733
+ programPath.traverse({
7734
+ MemberExpression(path) {
7735
+ const { node } = path;
7736
+ const { object } = node;
7737
+ if (object.type !== "MetaProperty") {
7738
+ return;
7739
+ }
7740
+ const { property: objectProperty } = object;
7741
+ if (objectProperty.name !== "meta") {
7742
+ return;
7743
+ }
7744
+ const { property } = node;
7745
+ const { name } = property;
7746
+ if (name === "css") {
7747
+ usesImportMetaCss = true;
7748
+ path.stop();
7749
+ }
7750
+ },
7751
+ });
7752
+ state.file.metadata.usesImportMetaCss = usesImportMetaCss;
7753
+ },
7754
+ },
7755
+ };
7756
+ };
7757
+
7648
7758
  // https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
7649
7759
  // https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
7650
7760
  // https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
@@ -7656,13 +7766,13 @@ const babelPluginMetadataImportMetaHot = () => {
7656
7766
  Program(programPath, state) {
7657
7767
  Object.assign(
7658
7768
  state.file.metadata,
7659
- collectImportMetaProperties(programPath),
7769
+ collectImportMetaHotProperties(programPath),
7660
7770
  );
7661
7771
  },
7662
7772
  },
7663
7773
  };
7664
7774
  };
7665
- const collectImportMetaProperties = (programPath) => {
7775
+ const collectImportMetaHotProperties = (programPath) => {
7666
7776
  const importMetaHotPaths = [];
7667
7777
  let hotDecline = false;
7668
7778
  let hotAcceptSelf = false;
@@ -8942,6 +9052,7 @@ const getCorePlugins = ({
8942
9052
  ? [jsenvPluginAutoreloadOnServerRestart()]
8943
9053
  : []),
8944
9054
 
9055
+ jsenvPluginImportMetaCss(),
8945
9056
  jsenvPluginCommonJsGlobals(),
8946
9057
  jsenvPluginImportMetaScenarios(),
8947
9058
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
@@ -0,0 +1,38 @@
1
+ import "file:///Users/dmail/Documents/dev/jsenv/core/packages/internal/plugin-transpilation/src/babel/new_stylesheet/client/new_stylesheet.js";
2
+
3
+ const installImportMetaCss = importMeta => {
4
+ let cssText = "";
5
+ let stylesheet = new CSSStyleSheet();
6
+ let adopted = false;
7
+ const css = {
8
+ toString: () => cssText,
9
+ update: value => {
10
+ cssText = value;
11
+ stylesheet.replaceSync(cssText);
12
+ },
13
+ inject: () => {
14
+ if (!adopted) {
15
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
16
+ adopted = true;
17
+ }
18
+ },
19
+ remove: () => {
20
+ if (adopted) {
21
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter(s => s !== stylesheet);
22
+ adopted = false;
23
+ }
24
+ }
25
+ };
26
+ Object.defineProperty(importMeta, "css", {
27
+ get() {
28
+ return css;
29
+ },
30
+ set(value) {
31
+ css.update(value);
32
+ css.inject();
33
+ }
34
+ });
35
+ return css.remove;
36
+ };
37
+
38
+ export { installImportMetaCss };
@@ -7685,6 +7685,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
7685
7685
  };
7686
7686
  };
7687
7687
 
7688
+ /**
7689
+ * Inline CSS would force to write the following boilerplate all the time:
7690
+ * ```js
7691
+ * const css = `body { color: red; }`;
7692
+ * const stylesheet = new CSSStyleSheet();
7693
+ * stylesheet.replaceSync(css);
7694
+ * document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
7695
+ * if (import.meta.hot) {
7696
+ * import.meta.hot.dispose(() => {
7697
+ * document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
7698
+ * (s) => s !== stylesheet,
7699
+ * );
7700
+ * });
7701
+ * }
7702
+ * ```
7703
+ *
7704
+ * It would be nice to have a plugin that does this automatically with the following syntax
7705
+ *
7706
+ * ```js
7707
+ * const css = `body { color: red; }`;
7708
+ * import.meta.css = css;
7709
+ * ```
7710
+ *
7711
+ */
7712
+
7713
+
7714
+ const jsenvPluginImportMetaCss = () => {
7715
+ const importMetaCssClientFileUrl = import.meta.resolve(
7716
+ "../js/import_meta_css.js",
7717
+ );
7718
+
7719
+ return {
7720
+ name: "jsenv:import_meta_css",
7721
+ appliesDuring: "*",
7722
+ transformUrlContent: {
7723
+ js_module: async (urlInfo) => {
7724
+ if (!urlInfo.content.includes("import.meta.css")) {
7725
+ return null;
7726
+ }
7727
+ const { metadata } = await applyBabelPlugins({
7728
+ babelPlugins: [babelPluginMetadataUsesImportMetaCss],
7729
+ input: urlInfo.content,
7730
+ inputIsJsModule: true,
7731
+ inputUrl: urlInfo.originalUrl,
7732
+ outputUrl: urlInfo.generatedUrl,
7733
+ });
7734
+ const { usesImportMetaCss } = metadata;
7735
+ if (!usesImportMetaCss) {
7736
+ return null;
7737
+ }
7738
+ return injectImportMetaCss(urlInfo, importMetaCssClientFileUrl);
7739
+ },
7740
+ },
7741
+ };
7742
+ };
7743
+
7744
+ const injectImportMetaCss = (urlInfo, importMetaCssClientFileUrl) => {
7745
+ const importMetaCssClientFileReference = urlInfo.dependencies.inject({
7746
+ parentUrl: urlInfo.url,
7747
+ type: "js_import",
7748
+ expectedType: "js_module",
7749
+ specifier: importMetaCssClientFileUrl,
7750
+ });
7751
+ let content = urlInfo.content;
7752
+ let prelude = `import { installImportMetaCss } from ${importMetaCssClientFileReference.generatedSpecifier};
7753
+
7754
+ const remove = installImportMetaCss(import.meta);
7755
+ if (import.meta.hot) {
7756
+ import.meta.hot.dispose(() => {
7757
+ remove();
7758
+ });
7759
+ }
7760
+
7761
+ `;
7762
+ return {
7763
+ content: `${prelude.replace(/\n/g, "")}${content}`,
7764
+ };
7765
+ };
7766
+
7767
+ const babelPluginMetadataUsesImportMetaCss = () => {
7768
+ return {
7769
+ name: "metadata-uses-import-meta-css",
7770
+ visitor: {
7771
+ Program(programPath, state) {
7772
+ let usesImportMetaCss = false;
7773
+ programPath.traverse({
7774
+ MemberExpression(path) {
7775
+ const { node } = path;
7776
+ const { object } = node;
7777
+ if (object.type !== "MetaProperty") {
7778
+ return;
7779
+ }
7780
+ const { property: objectProperty } = object;
7781
+ if (objectProperty.name !== "meta") {
7782
+ return;
7783
+ }
7784
+ const { property } = node;
7785
+ const { name } = property;
7786
+ if (name === "css") {
7787
+ usesImportMetaCss = true;
7788
+ path.stop();
7789
+ }
7790
+ },
7791
+ });
7792
+ state.file.metadata.usesImportMetaCss = usesImportMetaCss;
7793
+ },
7794
+ },
7795
+ };
7796
+ };
7797
+
7688
7798
  // https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
7689
7799
  // https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
7690
7800
  // https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
@@ -7696,13 +7806,13 @@ const babelPluginMetadataImportMetaHot = () => {
7696
7806
  Program(programPath, state) {
7697
7807
  Object.assign(
7698
7808
  state.file.metadata,
7699
- collectImportMetaProperties(programPath),
7809
+ collectImportMetaHotProperties(programPath),
7700
7810
  );
7701
7811
  },
7702
7812
  },
7703
7813
  };
7704
7814
  };
7705
- const collectImportMetaProperties = (programPath) => {
7815
+ const collectImportMetaHotProperties = (programPath) => {
7706
7816
  const importMetaHotPaths = [];
7707
7817
  let hotDecline = false;
7708
7818
  let hotAcceptSelf = false;
@@ -8982,6 +9092,7 @@ const getCorePlugins = ({
8982
9092
  ? [jsenvPluginAutoreloadOnServerRestart()]
8983
9093
  : []),
8984
9094
 
9095
+ jsenvPluginImportMetaCss(),
8985
9096
  jsenvPluginCommonJsGlobals(),
8986
9097
  jsenvPluginImportMetaScenarios(),
8987
9098
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "40.7.2",
3
+ "version": "40.8.0",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -34,7 +34,7 @@
34
34
  "/src/"
35
35
  ],
36
36
  "volta": {
37
- "node": "23.11.0",
37
+ "node": "24.1.0",
38
38
  "npm": "11.3.0"
39
39
  },
40
40
  "packageManager": "npm@11.3.0",
@@ -52,7 +52,9 @@
52
52
  "./src/kitchen/client/inline_content.js",
53
53
  "./dist/client/new_stylesheet/new_stylesheet.js",
54
54
  "./dist/client/inline_content/inline_content.js",
55
- "./dist/client/directory_listing/jsenv_core_node_modules.js"
55
+ "./dist/client/directory_listing/jsenv_core_node_modules.js",
56
+ "./src/plugins/import_meta_css/client/import_meta_css.js",
57
+ "./dist/js/import_meta_css.js"
56
58
  ],
57
59
  "scripts": {
58
60
  "eslint": "npx eslint .",
@@ -140,4 +142,4 @@
140
142
  "prettier-plugin-sql": "0.19.0",
141
143
  "strip-ansi": "7.1.0"
142
144
  }
143
- }
145
+ }
@@ -0,0 +1,42 @@
1
+ export const installImportMetaCss = (importMeta) => {
2
+ let cssText = "";
3
+ let stylesheet = new CSSStyleSheet();
4
+ let adopted = false;
5
+
6
+ const css = {
7
+ toString: () => cssText,
8
+ update: (value) => {
9
+ cssText = value;
10
+ stylesheet.replaceSync(cssText);
11
+ },
12
+ inject: () => {
13
+ if (!adopted) {
14
+ document.adoptedStyleSheets = [
15
+ ...document.adoptedStyleSheets,
16
+ stylesheet,
17
+ ];
18
+ adopted = true;
19
+ }
20
+ },
21
+ remove: () => {
22
+ if (adopted) {
23
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
24
+ (s) => s !== stylesheet,
25
+ );
26
+ adopted = false;
27
+ }
28
+ },
29
+ };
30
+
31
+ Object.defineProperty(importMeta, "css", {
32
+ get() {
33
+ return css;
34
+ },
35
+ set(value) {
36
+ css.update(value);
37
+ css.inject();
38
+ },
39
+ });
40
+
41
+ return css.remove;
42
+ };
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Inline CSS would force to write the following boilerplate all the time:
3
+ * ```js
4
+ * const css = `body { color: red; }`;
5
+ * const stylesheet = new CSSStyleSheet();
6
+ * stylesheet.replaceSync(css);
7
+ * document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
8
+ * if (import.meta.hot) {
9
+ * import.meta.hot.dispose(() => {
10
+ * document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
11
+ * (s) => s !== stylesheet,
12
+ * );
13
+ * });
14
+ * }
15
+ * ```
16
+ *
17
+ * It would be nice to have a plugin that does this automatically with the following syntax
18
+ *
19
+ * ```js
20
+ * const css = `body { color: red; }`;
21
+ * import.meta.css = css;
22
+ * ```
23
+ *
24
+ */
25
+
26
+ import { applyBabelPlugins } from "@jsenv/ast";
27
+
28
+ export const jsenvPluginImportMetaCss = () => {
29
+ const importMetaCssClientFileUrl = import.meta.resolve(
30
+ "./client/import_meta_css.js",
31
+ );
32
+
33
+ return {
34
+ name: "jsenv:import_meta_css",
35
+ appliesDuring: "*",
36
+ transformUrlContent: {
37
+ js_module: async (urlInfo) => {
38
+ if (!urlInfo.content.includes("import.meta.css")) {
39
+ return null;
40
+ }
41
+ const { metadata } = await applyBabelPlugins({
42
+ babelPlugins: [babelPluginMetadataUsesImportMetaCss],
43
+ input: urlInfo.content,
44
+ inputIsJsModule: true,
45
+ inputUrl: urlInfo.originalUrl,
46
+ outputUrl: urlInfo.generatedUrl,
47
+ });
48
+ const { usesImportMetaCss } = metadata;
49
+ if (!usesImportMetaCss) {
50
+ return null;
51
+ }
52
+ return injectImportMetaCss(urlInfo, importMetaCssClientFileUrl);
53
+ },
54
+ },
55
+ };
56
+ };
57
+
58
+ const injectImportMetaCss = (urlInfo, importMetaCssClientFileUrl) => {
59
+ const importMetaCssClientFileReference = urlInfo.dependencies.inject({
60
+ parentUrl: urlInfo.url,
61
+ type: "js_import",
62
+ expectedType: "js_module",
63
+ specifier: importMetaCssClientFileUrl,
64
+ });
65
+ let content = urlInfo.content;
66
+ let prelude = `import { installImportMetaCss } from ${importMetaCssClientFileReference.generatedSpecifier};
67
+
68
+ const remove = installImportMetaCss(import.meta);
69
+ if (import.meta.hot) {
70
+ import.meta.hot.dispose(() => {
71
+ remove();
72
+ });
73
+ }
74
+
75
+ `;
76
+ return {
77
+ content: `${prelude.replace(/\n/g, "")}${content}`,
78
+ };
79
+ };
80
+
81
+ const babelPluginMetadataUsesImportMetaCss = () => {
82
+ return {
83
+ name: "metadata-uses-import-meta-css",
84
+ visitor: {
85
+ Program(programPath, state) {
86
+ let usesImportMetaCss = false;
87
+ programPath.traverse({
88
+ MemberExpression(path) {
89
+ const { node } = path;
90
+ const { object } = node;
91
+ if (object.type !== "MetaProperty") {
92
+ return;
93
+ }
94
+ const { property: objectProperty } = object;
95
+ if (objectProperty.name !== "meta") {
96
+ return;
97
+ }
98
+ const { property } = node;
99
+ const { name } = property;
100
+ if (name === "css") {
101
+ usesImportMetaCss = true;
102
+ path.stop();
103
+ }
104
+ },
105
+ });
106
+ state.file.metadata.usesImportMetaCss = usesImportMetaCss;
107
+ },
108
+ },
109
+ };
110
+ };
@@ -9,13 +9,13 @@ export const babelPluginMetadataImportMetaHot = () => {
9
9
  Program(programPath, state) {
10
10
  Object.assign(
11
11
  state.file.metadata,
12
- collectImportMetaProperties(programPath),
12
+ collectImportMetaHotProperties(programPath),
13
13
  );
14
14
  },
15
15
  },
16
16
  };
17
17
  };
18
- const collectImportMetaProperties = (programPath) => {
18
+ const collectImportMetaHotProperties = (programPath) => {
19
19
  const importMetaHotPaths = [];
20
20
  let hotDecline = false;
21
21
  let hotAcceptSelf = false;
@@ -16,6 +16,7 @@ import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_comm
16
16
  import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js";
17
17
  import { jsenvPluginGlobalScenarios } from "./global_scenarios/jsenv_plugin_global_scenarios.js";
18
18
  import { jsenvPluginNodeRuntime } from "./node_runtime/jsenv_plugin_node_runtime.js";
19
+ import { jsenvPluginImportMetaCss } from "./import_meta_css/jsenv_plugin_import_meta_css.js";
19
20
  // autoreload
20
21
  import { jsenvPluginImportMetaHot } from "./import_meta_hot/jsenv_plugin_import_meta_hot.js";
21
22
  import { jsenvPluginAutoreload } from "./autoreload/jsenv_plugin_autoreload.js";
@@ -126,6 +127,7 @@ export const getCorePlugins = ({
126
127
  ? [jsenvPluginAutoreloadOnServerRestart()]
127
128
  : []),
128
129
 
130
+ jsenvPluginImportMetaCss(),
129
131
  jsenvPluginCommonJsGlobals(),
130
132
  jsenvPluginImportMetaScenarios(),
131
133
  ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),