@jsenv/core 40.7.2 → 40.8.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.
- package/dist/build/build.js +117 -2
- package/dist/build/jsenv_core_packages.js +4 -1
- package/dist/js/import_meta_css.js +38 -0
- package/dist/jsenv_core.js +3 -0
- package/dist/start_dev_server/jsenv_core_packages.js +4 -1
- package/dist/start_dev_server/start_dev_server.js +117 -2
- package/package.json +48 -46
- package/src/kitchen/kitchen.js +5 -1
- package/src/kitchen/url_graph/url_info_injections.js +3 -0
- package/src/plugins/import_meta_css/client/import_meta_css.js +42 -0
- package/src/plugins/import_meta_css/jsenv_plugin_import_meta_css.js +110 -0
- package/src/plugins/import_meta_hot/babel_plugin_metadata_import_meta_hot.js +2 -2
- package/src/plugins/plugins.js +2 -0
package/dist/build/build.js
CHANGED
|
@@ -2134,6 +2134,9 @@ const INJECTIONS = {
|
|
|
2134
2134
|
return { [injectionSymbol]: "global", value };
|
|
2135
2135
|
},
|
|
2136
2136
|
optional: (value) => {
|
|
2137
|
+
if (value && value[injectionSymbol] === "optional") {
|
|
2138
|
+
return value;
|
|
2139
|
+
}
|
|
2137
2140
|
return { [injectionSymbol]: "optional", value };
|
|
2138
2141
|
},
|
|
2139
2142
|
};
|
|
@@ -2949,6 +2952,7 @@ const createKitchen = ({
|
|
|
2949
2952
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
2950
2953
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
2951
2954
|
isPlaceholderInjection,
|
|
2955
|
+
INJECTIONS,
|
|
2952
2956
|
getPluginMeta: null,
|
|
2953
2957
|
sourcemaps,
|
|
2954
2958
|
outDirectoryUrl,
|
|
@@ -7645,6 +7649,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
|
|
|
7645
7649
|
};
|
|
7646
7650
|
};
|
|
7647
7651
|
|
|
7652
|
+
/**
|
|
7653
|
+
* Inline CSS would force to write the following boilerplate all the time:
|
|
7654
|
+
* ```js
|
|
7655
|
+
* const css = `body { color: red; }`;
|
|
7656
|
+
* const stylesheet = new CSSStyleSheet();
|
|
7657
|
+
* stylesheet.replaceSync(css);
|
|
7658
|
+
* document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
|
|
7659
|
+
* if (import.meta.hot) {
|
|
7660
|
+
* import.meta.hot.dispose(() => {
|
|
7661
|
+
* document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
|
|
7662
|
+
* (s) => s !== stylesheet,
|
|
7663
|
+
* );
|
|
7664
|
+
* });
|
|
7665
|
+
* }
|
|
7666
|
+
* ```
|
|
7667
|
+
*
|
|
7668
|
+
* It would be nice to have a plugin that does this automatically with the following syntax
|
|
7669
|
+
*
|
|
7670
|
+
* ```js
|
|
7671
|
+
* const css = `body { color: red; }`;
|
|
7672
|
+
* import.meta.css = css;
|
|
7673
|
+
* ```
|
|
7674
|
+
*
|
|
7675
|
+
*/
|
|
7676
|
+
|
|
7677
|
+
|
|
7678
|
+
const jsenvPluginImportMetaCss = () => {
|
|
7679
|
+
const importMetaCssClientFileUrl = import.meta.resolve(
|
|
7680
|
+
"../js/import_meta_css.js",
|
|
7681
|
+
);
|
|
7682
|
+
|
|
7683
|
+
return {
|
|
7684
|
+
name: "jsenv:import_meta_css",
|
|
7685
|
+
appliesDuring: "*",
|
|
7686
|
+
transformUrlContent: {
|
|
7687
|
+
js_module: async (urlInfo) => {
|
|
7688
|
+
if (!urlInfo.content.includes("import.meta.css")) {
|
|
7689
|
+
return null;
|
|
7690
|
+
}
|
|
7691
|
+
const { metadata } = await applyBabelPlugins({
|
|
7692
|
+
babelPlugins: [babelPluginMetadataUsesImportMetaCss],
|
|
7693
|
+
input: urlInfo.content,
|
|
7694
|
+
inputIsJsModule: true,
|
|
7695
|
+
inputUrl: urlInfo.originalUrl,
|
|
7696
|
+
outputUrl: urlInfo.generatedUrl,
|
|
7697
|
+
});
|
|
7698
|
+
const { usesImportMetaCss } = metadata;
|
|
7699
|
+
if (!usesImportMetaCss) {
|
|
7700
|
+
return null;
|
|
7701
|
+
}
|
|
7702
|
+
return injectImportMetaCss(urlInfo, importMetaCssClientFileUrl);
|
|
7703
|
+
},
|
|
7704
|
+
},
|
|
7705
|
+
};
|
|
7706
|
+
};
|
|
7707
|
+
|
|
7708
|
+
const injectImportMetaCss = (urlInfo, importMetaCssClientFileUrl) => {
|
|
7709
|
+
const importMetaCssClientFileReference = urlInfo.dependencies.inject({
|
|
7710
|
+
parentUrl: urlInfo.url,
|
|
7711
|
+
type: "js_import",
|
|
7712
|
+
expectedType: "js_module",
|
|
7713
|
+
specifier: importMetaCssClientFileUrl,
|
|
7714
|
+
});
|
|
7715
|
+
let content = urlInfo.content;
|
|
7716
|
+
let prelude = `import { installImportMetaCss } from ${importMetaCssClientFileReference.generatedSpecifier};
|
|
7717
|
+
|
|
7718
|
+
const remove = installImportMetaCss(import.meta);
|
|
7719
|
+
if (import.meta.hot) {
|
|
7720
|
+
import.meta.hot.dispose(() => {
|
|
7721
|
+
remove();
|
|
7722
|
+
});
|
|
7723
|
+
}
|
|
7724
|
+
|
|
7725
|
+
`;
|
|
7726
|
+
return {
|
|
7727
|
+
content: `${prelude.replace(/\n/g, "")}${content}`,
|
|
7728
|
+
};
|
|
7729
|
+
};
|
|
7730
|
+
|
|
7731
|
+
const babelPluginMetadataUsesImportMetaCss = () => {
|
|
7732
|
+
return {
|
|
7733
|
+
name: "metadata-uses-import-meta-css",
|
|
7734
|
+
visitor: {
|
|
7735
|
+
Program(programPath, state) {
|
|
7736
|
+
let usesImportMetaCss = false;
|
|
7737
|
+
programPath.traverse({
|
|
7738
|
+
MemberExpression(path) {
|
|
7739
|
+
const { node } = path;
|
|
7740
|
+
const { object } = node;
|
|
7741
|
+
if (object.type !== "MetaProperty") {
|
|
7742
|
+
return;
|
|
7743
|
+
}
|
|
7744
|
+
const { property: objectProperty } = object;
|
|
7745
|
+
if (objectProperty.name !== "meta") {
|
|
7746
|
+
return;
|
|
7747
|
+
}
|
|
7748
|
+
const { property } = node;
|
|
7749
|
+
const { name } = property;
|
|
7750
|
+
if (name === "css") {
|
|
7751
|
+
usesImportMetaCss = true;
|
|
7752
|
+
path.stop();
|
|
7753
|
+
}
|
|
7754
|
+
},
|
|
7755
|
+
});
|
|
7756
|
+
state.file.metadata.usesImportMetaCss = usesImportMetaCss;
|
|
7757
|
+
},
|
|
7758
|
+
},
|
|
7759
|
+
};
|
|
7760
|
+
};
|
|
7761
|
+
|
|
7648
7762
|
// https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
|
|
7649
7763
|
// https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
|
|
7650
7764
|
// https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
|
|
@@ -7656,13 +7770,13 @@ const babelPluginMetadataImportMetaHot = () => {
|
|
|
7656
7770
|
Program(programPath, state) {
|
|
7657
7771
|
Object.assign(
|
|
7658
7772
|
state.file.metadata,
|
|
7659
|
-
|
|
7773
|
+
collectImportMetaHotProperties(programPath),
|
|
7660
7774
|
);
|
|
7661
7775
|
},
|
|
7662
7776
|
},
|
|
7663
7777
|
};
|
|
7664
7778
|
};
|
|
7665
|
-
const
|
|
7779
|
+
const collectImportMetaHotProperties = (programPath) => {
|
|
7666
7780
|
const importMetaHotPaths = [];
|
|
7667
7781
|
let hotDecline = false;
|
|
7668
7782
|
let hotAcceptSelf = false;
|
|
@@ -8942,6 +9056,7 @@ const getCorePlugins = ({
|
|
|
8942
9056
|
? [jsenvPluginAutoreloadOnServerRestart()]
|
|
8943
9057
|
: []),
|
|
8944
9058
|
|
|
9059
|
+
jsenvPluginImportMetaCss(),
|
|
8945
9060
|
jsenvPluginCommonJsGlobals(),
|
|
8946
9061
|
jsenvPluginImportMetaScenarios(),
|
|
8947
9062
|
...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
|
|
@@ -2517,7 +2517,10 @@ const comparePathnames = (leftPathame, rightPathname) => {
|
|
|
2517
2517
|
const rightPart = rightPartArray[i];
|
|
2518
2518
|
i++;
|
|
2519
2519
|
// local comparison comes first
|
|
2520
|
-
const comparison = leftPart.localeCompare(rightPart
|
|
2520
|
+
const comparison = leftPart.localeCompare(rightPart, undefined, {
|
|
2521
|
+
numeric: true,
|
|
2522
|
+
sensitivity: "base",
|
|
2523
|
+
});
|
|
2521
2524
|
if (comparison !== 0) {
|
|
2522
2525
|
return comparison;
|
|
2523
2526
|
}
|
|
@@ -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 };
|
package/dist/jsenv_core.js
CHANGED
|
@@ -1822,7 +1822,10 @@ const comparePathnames = (leftPathame, rightPathname) => {
|
|
|
1822
1822
|
const rightPart = rightPartArray[i];
|
|
1823
1823
|
i++;
|
|
1824
1824
|
// local comparison comes first
|
|
1825
|
-
const comparison = leftPart.localeCompare(rightPart
|
|
1825
|
+
const comparison = leftPart.localeCompare(rightPart, undefined, {
|
|
1826
|
+
numeric: true,
|
|
1827
|
+
sensitivity: "base",
|
|
1828
|
+
});
|
|
1826
1829
|
if (comparison !== 0) {
|
|
1827
1830
|
return comparison;
|
|
1828
1831
|
}
|
|
@@ -2174,6 +2174,9 @@ const INJECTIONS = {
|
|
|
2174
2174
|
return { [injectionSymbol]: "global", value };
|
|
2175
2175
|
},
|
|
2176
2176
|
optional: (value) => {
|
|
2177
|
+
if (value && value[injectionSymbol] === "optional") {
|
|
2178
|
+
return value;
|
|
2179
|
+
}
|
|
2177
2180
|
return { [injectionSymbol]: "optional", value };
|
|
2178
2181
|
},
|
|
2179
2182
|
};
|
|
@@ -2989,6 +2992,7 @@ const createKitchen = ({
|
|
|
2989
2992
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
2990
2993
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
2991
2994
|
isPlaceholderInjection,
|
|
2995
|
+
INJECTIONS,
|
|
2992
2996
|
getPluginMeta: null,
|
|
2993
2997
|
sourcemaps,
|
|
2994
2998
|
outDirectoryUrl,
|
|
@@ -7685,6 +7689,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
|
|
|
7685
7689
|
};
|
|
7686
7690
|
};
|
|
7687
7691
|
|
|
7692
|
+
/**
|
|
7693
|
+
* Inline CSS would force to write the following boilerplate all the time:
|
|
7694
|
+
* ```js
|
|
7695
|
+
* const css = `body { color: red; }`;
|
|
7696
|
+
* const stylesheet = new CSSStyleSheet();
|
|
7697
|
+
* stylesheet.replaceSync(css);
|
|
7698
|
+
* document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
|
|
7699
|
+
* if (import.meta.hot) {
|
|
7700
|
+
* import.meta.hot.dispose(() => {
|
|
7701
|
+
* document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
|
|
7702
|
+
* (s) => s !== stylesheet,
|
|
7703
|
+
* );
|
|
7704
|
+
* });
|
|
7705
|
+
* }
|
|
7706
|
+
* ```
|
|
7707
|
+
*
|
|
7708
|
+
* It would be nice to have a plugin that does this automatically with the following syntax
|
|
7709
|
+
*
|
|
7710
|
+
* ```js
|
|
7711
|
+
* const css = `body { color: red; }`;
|
|
7712
|
+
* import.meta.css = css;
|
|
7713
|
+
* ```
|
|
7714
|
+
*
|
|
7715
|
+
*/
|
|
7716
|
+
|
|
7717
|
+
|
|
7718
|
+
const jsenvPluginImportMetaCss = () => {
|
|
7719
|
+
const importMetaCssClientFileUrl = import.meta.resolve(
|
|
7720
|
+
"../js/import_meta_css.js",
|
|
7721
|
+
);
|
|
7722
|
+
|
|
7723
|
+
return {
|
|
7724
|
+
name: "jsenv:import_meta_css",
|
|
7725
|
+
appliesDuring: "*",
|
|
7726
|
+
transformUrlContent: {
|
|
7727
|
+
js_module: async (urlInfo) => {
|
|
7728
|
+
if (!urlInfo.content.includes("import.meta.css")) {
|
|
7729
|
+
return null;
|
|
7730
|
+
}
|
|
7731
|
+
const { metadata } = await applyBabelPlugins({
|
|
7732
|
+
babelPlugins: [babelPluginMetadataUsesImportMetaCss],
|
|
7733
|
+
input: urlInfo.content,
|
|
7734
|
+
inputIsJsModule: true,
|
|
7735
|
+
inputUrl: urlInfo.originalUrl,
|
|
7736
|
+
outputUrl: urlInfo.generatedUrl,
|
|
7737
|
+
});
|
|
7738
|
+
const { usesImportMetaCss } = metadata;
|
|
7739
|
+
if (!usesImportMetaCss) {
|
|
7740
|
+
return null;
|
|
7741
|
+
}
|
|
7742
|
+
return injectImportMetaCss(urlInfo, importMetaCssClientFileUrl);
|
|
7743
|
+
},
|
|
7744
|
+
},
|
|
7745
|
+
};
|
|
7746
|
+
};
|
|
7747
|
+
|
|
7748
|
+
const injectImportMetaCss = (urlInfo, importMetaCssClientFileUrl) => {
|
|
7749
|
+
const importMetaCssClientFileReference = urlInfo.dependencies.inject({
|
|
7750
|
+
parentUrl: urlInfo.url,
|
|
7751
|
+
type: "js_import",
|
|
7752
|
+
expectedType: "js_module",
|
|
7753
|
+
specifier: importMetaCssClientFileUrl,
|
|
7754
|
+
});
|
|
7755
|
+
let content = urlInfo.content;
|
|
7756
|
+
let prelude = `import { installImportMetaCss } from ${importMetaCssClientFileReference.generatedSpecifier};
|
|
7757
|
+
|
|
7758
|
+
const remove = installImportMetaCss(import.meta);
|
|
7759
|
+
if (import.meta.hot) {
|
|
7760
|
+
import.meta.hot.dispose(() => {
|
|
7761
|
+
remove();
|
|
7762
|
+
});
|
|
7763
|
+
}
|
|
7764
|
+
|
|
7765
|
+
`;
|
|
7766
|
+
return {
|
|
7767
|
+
content: `${prelude.replace(/\n/g, "")}${content}`,
|
|
7768
|
+
};
|
|
7769
|
+
};
|
|
7770
|
+
|
|
7771
|
+
const babelPluginMetadataUsesImportMetaCss = () => {
|
|
7772
|
+
return {
|
|
7773
|
+
name: "metadata-uses-import-meta-css",
|
|
7774
|
+
visitor: {
|
|
7775
|
+
Program(programPath, state) {
|
|
7776
|
+
let usesImportMetaCss = false;
|
|
7777
|
+
programPath.traverse({
|
|
7778
|
+
MemberExpression(path) {
|
|
7779
|
+
const { node } = path;
|
|
7780
|
+
const { object } = node;
|
|
7781
|
+
if (object.type !== "MetaProperty") {
|
|
7782
|
+
return;
|
|
7783
|
+
}
|
|
7784
|
+
const { property: objectProperty } = object;
|
|
7785
|
+
if (objectProperty.name !== "meta") {
|
|
7786
|
+
return;
|
|
7787
|
+
}
|
|
7788
|
+
const { property } = node;
|
|
7789
|
+
const { name } = property;
|
|
7790
|
+
if (name === "css") {
|
|
7791
|
+
usesImportMetaCss = true;
|
|
7792
|
+
path.stop();
|
|
7793
|
+
}
|
|
7794
|
+
},
|
|
7795
|
+
});
|
|
7796
|
+
state.file.metadata.usesImportMetaCss = usesImportMetaCss;
|
|
7797
|
+
},
|
|
7798
|
+
},
|
|
7799
|
+
};
|
|
7800
|
+
};
|
|
7801
|
+
|
|
7688
7802
|
// https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
|
|
7689
7803
|
// https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
|
|
7690
7804
|
// https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
|
|
@@ -7696,13 +7810,13 @@ const babelPluginMetadataImportMetaHot = () => {
|
|
|
7696
7810
|
Program(programPath, state) {
|
|
7697
7811
|
Object.assign(
|
|
7698
7812
|
state.file.metadata,
|
|
7699
|
-
|
|
7813
|
+
collectImportMetaHotProperties(programPath),
|
|
7700
7814
|
);
|
|
7701
7815
|
},
|
|
7702
7816
|
},
|
|
7703
7817
|
};
|
|
7704
7818
|
};
|
|
7705
|
-
const
|
|
7819
|
+
const collectImportMetaHotProperties = (programPath) => {
|
|
7706
7820
|
const importMetaHotPaths = [];
|
|
7707
7821
|
let hotDecline = false;
|
|
7708
7822
|
let hotAcceptSelf = false;
|
|
@@ -8982,6 +9096,7 @@ const getCorePlugins = ({
|
|
|
8982
9096
|
? [jsenvPluginAutoreloadOnServerRestart()]
|
|
8983
9097
|
: []),
|
|
8984
9098
|
|
|
9099
|
+
jsenvPluginImportMetaCss(),
|
|
8985
9100
|
jsenvPluginCommonJsGlobals(),
|
|
8986
9101
|
jsenvPluginImportMetaScenarios(),
|
|
8987
9102
|
...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "40.
|
|
3
|
+
"version": "40.8.1",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": {
|
|
7
|
-
"name": "dmail",
|
|
8
|
-
"email": "dmaillard06@gmail.com"
|
|
9
|
-
},
|
|
10
5
|
"repository": {
|
|
11
6
|
"type": "git",
|
|
12
7
|
"url": "https://github.com/jsenv/core"
|
|
13
8
|
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"access": "public"
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "dmail",
|
|
12
|
+
"email": "dmaillard06@gmail.com"
|
|
19
13
|
},
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"./src/kitchen/client/inline_content.js",
|
|
16
|
+
"./dist/client/new_stylesheet/new_stylesheet.js",
|
|
17
|
+
"./dist/client/inline_content/inline_content.js",
|
|
18
|
+
"./dist/client/directory_listing/jsenv_core_node_modules.js"
|
|
19
|
+
],
|
|
20
20
|
"type": "module",
|
|
21
21
|
"imports": {},
|
|
22
22
|
"exports": {
|
|
@@ -33,11 +33,6 @@
|
|
|
33
33
|
"/dist/",
|
|
34
34
|
"/src/"
|
|
35
35
|
],
|
|
36
|
-
"volta": {
|
|
37
|
-
"node": "23.11.0",
|
|
38
|
-
"npm": "11.3.0"
|
|
39
|
-
},
|
|
40
|
-
"packageManager": "npm@11.3.0",
|
|
41
36
|
"workspaces": [
|
|
42
37
|
"./packages/backend/*",
|
|
43
38
|
"./packages/frontend/*",
|
|
@@ -48,49 +43,44 @@
|
|
|
48
43
|
"./packages/related/cli/*",
|
|
49
44
|
"./packages/tooling/*"
|
|
50
45
|
],
|
|
51
|
-
"sideEffects": [
|
|
52
|
-
"./src/kitchen/client/inline_content.js",
|
|
53
|
-
"./dist/client/new_stylesheet/new_stylesheet.js",
|
|
54
|
-
"./dist/client/inline_content/inline_content.js",
|
|
55
|
-
"./dist/client/directory_listing/jsenv_core_node_modules.js"
|
|
56
|
-
],
|
|
57
46
|
"scripts": {
|
|
58
|
-
"eslint": "npx eslint .",
|
|
59
|
-
"test": "node --conditions=dev:jsenv ./scripts/test/test.mjs",
|
|
60
|
-
"test:packages": "npm run test -- ./packages/",
|
|
61
47
|
"build": "node --conditions=dev:jsenv ./scripts/build/build.mjs",
|
|
48
|
+
"build:file_size": "node ./scripts/build/build_file_size.mjs --log",
|
|
62
49
|
"build:packages": "npm run build --workspaces --if-present --conditions=developement",
|
|
63
|
-
"
|
|
50
|
+
"database:install": "npx @jsenv/database install",
|
|
51
|
+
"database:manage": "node --conditions=dev:jsenv ./packages/backend/database/src/cli/manage.js",
|
|
52
|
+
"database:setup": "npm run database:setup --workspaces --if-present --conditions=dev:jsenv",
|
|
53
|
+
"database:start": "npx @jsenv/database start",
|
|
54
|
+
"database:stop": "npx @jsenv/database stop",
|
|
55
|
+
"dev": "node --watch --conditions=dev:jsenv ./scripts/dev/dev.mjs",
|
|
56
|
+
"dev:route-inspector": "node --watch --conditions=dev:jsenv ./packages/backend/server/tests/route_inspector/start_server.js",
|
|
57
|
+
"eslint": "npx eslint .",
|
|
58
|
+
"https:setup": "npx @jsenv/https-local setup",
|
|
59
|
+
"md:build": "node ./docs/build.js",
|
|
60
|
+
"monorepo:node_modules_clear": "npx @jsenv/filesystem clear **/node_modules/",
|
|
64
61
|
"monorepo:publish": "node ./scripts/monorepo/publish_packages.mjs",
|
|
62
|
+
"monorepo:sync_packages_versions": "node ./scripts/monorepo/sync_packages_versions.mjs",
|
|
65
63
|
"monorepo:upgrade_versions": "node ./scripts/monorepo/upgrade_external_versions.mjs",
|
|
66
|
-
"
|
|
67
|
-
"md:build": "node ./docs/build.js",
|
|
64
|
+
"oto:start": "npm run start -w oto",
|
|
68
65
|
"performances": "node --expose-gc ./scripts/performance/generate_performance_report.mjs --log --once",
|
|
69
|
-
"
|
|
66
|
+
"playwright:install": "npx playwright install-deps && npx playwright install",
|
|
67
|
+
"prepublishOnly": "npm run build",
|
|
70
68
|
"prettier": "prettier --write .",
|
|
71
|
-
"test
|
|
69
|
+
"test": "node --conditions=dev:jsenv ./scripts/test/test.mjs",
|
|
72
70
|
"test:ci": "CI=1 npm run test",
|
|
73
|
-
"test:packages:ci": "CI=1 npm run workspace:test",
|
|
74
71
|
"test:only_dev_server_errors": "node --conditions=dev:jsenv ./tests/dev_server/errors/dev_errors_snapshots.test.mjs",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"https:setup": "npx @jsenv/https-local setup",
|
|
79
|
-
"prepublishOnly": "npm run build",
|
|
80
|
-
"database:install": "npx @jsenv/database install",
|
|
81
|
-
"database:start": "npx @jsenv/database start",
|
|
82
|
-
"database:stop": "npx @jsenv/database stop",
|
|
83
|
-
"database:setup": "npx @jsenv/database setup",
|
|
84
|
-
"oto:start": "npm run start -w oto"
|
|
72
|
+
"test:packages": "npm run test -- ./packages/",
|
|
73
|
+
"test:packages:ci": "CI=1 npm run workspace:test",
|
|
74
|
+
"test:snapshot_clear": "npx @jsenv/filesystem clear **/tests/**/side_effects/"
|
|
85
75
|
},
|
|
86
76
|
"dependencies": {
|
|
87
77
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
88
|
-
"@jsenv/ast": "6.7.
|
|
89
|
-
"@jsenv/js-module-fallback": "1.4.
|
|
90
|
-
"@jsenv/plugin-bundling": "2.9.
|
|
78
|
+
"@jsenv/ast": "6.7.7",
|
|
79
|
+
"@jsenv/js-module-fallback": "1.4.19",
|
|
80
|
+
"@jsenv/plugin-bundling": "2.9.9",
|
|
91
81
|
"@jsenv/plugin-minification": "1.7.0",
|
|
92
|
-
"@jsenv/plugin-supervisor": "1.7.
|
|
93
|
-
"@jsenv/plugin-transpilation": "1.5.
|
|
82
|
+
"@jsenv/plugin-supervisor": "1.7.4",
|
|
83
|
+
"@jsenv/plugin-transpilation": "1.5.51",
|
|
94
84
|
"@jsenv/server": "16.1.2",
|
|
95
85
|
"@jsenv/sourcemap": "1.3.9",
|
|
96
86
|
"react-table": "7.8.0"
|
|
@@ -137,7 +127,19 @@
|
|
|
137
127
|
"prettier": "3.5.3",
|
|
138
128
|
"prettier-plugin-embed": "0.5.0",
|
|
139
129
|
"prettier-plugin-organize-imports": "4.1.0",
|
|
130
|
+
"prettier-plugin-packagejson": "2.5.15",
|
|
140
131
|
"prettier-plugin-sql": "0.19.0",
|
|
141
132
|
"strip-ansi": "7.1.0"
|
|
133
|
+
},
|
|
134
|
+
"packageManager": "npm@11.3.0",
|
|
135
|
+
"engines": {
|
|
136
|
+
"node": ">=20.8.0"
|
|
137
|
+
},
|
|
138
|
+
"volta": {
|
|
139
|
+
"node": "24.1.0",
|
|
140
|
+
"npm": "11.3.0"
|
|
141
|
+
},
|
|
142
|
+
"publishConfig": {
|
|
143
|
+
"access": "public"
|
|
142
144
|
}
|
|
143
145
|
}
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -17,7 +17,10 @@ import {
|
|
|
17
17
|
determineSourcemapFileUrl,
|
|
18
18
|
} from "./out_directory_url.js";
|
|
19
19
|
import { createUrlGraph } from "./url_graph/url_graph.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
INJECTIONS,
|
|
22
|
+
isPlaceholderInjection,
|
|
23
|
+
} from "./url_graph/url_info_injections.js";
|
|
21
24
|
import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js";
|
|
22
25
|
import { urlSpecifierEncoding } from "./url_graph/url_specifier_encoding.js";
|
|
23
26
|
|
|
@@ -104,6 +107,7 @@ export const createKitchen = ({
|
|
|
104
107
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
105
108
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
106
109
|
isPlaceholderInjection,
|
|
110
|
+
INJECTIONS,
|
|
107
111
|
getPluginMeta: null,
|
|
108
112
|
sourcemaps,
|
|
109
113
|
outDirectoryUrl,
|
|
@@ -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
|
-
|
|
12
|
+
collectImportMetaHotProperties(programPath),
|
|
13
13
|
);
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
|
-
const
|
|
18
|
+
const collectImportMetaHotProperties = (programPath) => {
|
|
19
19
|
const importMetaHotPaths = [];
|
|
20
20
|
let hotDecline = false;
|
|
21
21
|
let hotAcceptSelf = false;
|
package/src/plugins/plugins.js
CHANGED
|
@@ -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()] : []),
|