@jsenv/core 40.7.1 → 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.
- package/dist/build/build.js +118 -2
- package/dist/js/import_meta_css.js +38 -0
- package/dist/start_dev_server/start_dev_server.js +118 -2
- package/package.json +6 -4
- package/src/kitchen/errors.js +5 -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
|
@@ -203,6 +203,7 @@ const createFetchUrlContentError = ({
|
|
|
203
203
|
const createFailedToFetchUrlContentError = ({
|
|
204
204
|
code = error.code || "FETCH_URL_CONTENT_ERROR",
|
|
205
205
|
reason,
|
|
206
|
+
parseErrorSourceType,
|
|
206
207
|
...details
|
|
207
208
|
}) => {
|
|
208
209
|
const reference = urlInfo.firstReference;
|
|
@@ -223,6 +224,7 @@ ${reason}`,
|
|
|
223
224
|
name: "FETCH_URL_CONTENT_ERROR",
|
|
224
225
|
code,
|
|
225
226
|
reason,
|
|
227
|
+
parseErrorSourceType,
|
|
226
228
|
url: urlInfo.url,
|
|
227
229
|
trace: code === "PARSE_ERROR" ? error.trace : reference.trace,
|
|
228
230
|
asResponse: error.asResponse,
|
|
@@ -257,6 +259,7 @@ ${reason}`,
|
|
|
257
259
|
return createFailedToFetchUrlContentError({
|
|
258
260
|
"code": "PARSE_ERROR",
|
|
259
261
|
"reason": error.reasonCode,
|
|
262
|
+
"parseErrorSourceType": error.parseErrorSourceType,
|
|
260
263
|
...(error.cause ? { "parse error message": error.cause.message } : {}),
|
|
261
264
|
"parse error trace": error.trace?.message,
|
|
262
265
|
});
|
|
@@ -306,6 +309,8 @@ ${error.message}`,
|
|
|
306
309
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
307
310
|
code: "PARSE_ERROR",
|
|
308
311
|
reason: error.message,
|
|
312
|
+
reasonCode: error.reasonCode,
|
|
313
|
+
parseErrorSourceType: error.parseErrorSourceType,
|
|
309
314
|
stack: transformError.stack,
|
|
310
315
|
trace,
|
|
311
316
|
asResponse: error.asResponse,
|
|
@@ -7640,6 +7645,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
|
|
|
7640
7645
|
};
|
|
7641
7646
|
};
|
|
7642
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
|
+
|
|
7643
7758
|
// https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
|
|
7644
7759
|
// https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
|
|
7645
7760
|
// https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
|
|
@@ -7651,13 +7766,13 @@ const babelPluginMetadataImportMetaHot = () => {
|
|
|
7651
7766
|
Program(programPath, state) {
|
|
7652
7767
|
Object.assign(
|
|
7653
7768
|
state.file.metadata,
|
|
7654
|
-
|
|
7769
|
+
collectImportMetaHotProperties(programPath),
|
|
7655
7770
|
);
|
|
7656
7771
|
},
|
|
7657
7772
|
},
|
|
7658
7773
|
};
|
|
7659
7774
|
};
|
|
7660
|
-
const
|
|
7775
|
+
const collectImportMetaHotProperties = (programPath) => {
|
|
7661
7776
|
const importMetaHotPaths = [];
|
|
7662
7777
|
let hotDecline = false;
|
|
7663
7778
|
let hotAcceptSelf = false;
|
|
@@ -8937,6 +9052,7 @@ const getCorePlugins = ({
|
|
|
8937
9052
|
? [jsenvPluginAutoreloadOnServerRestart()]
|
|
8938
9053
|
: []),
|
|
8939
9054
|
|
|
9055
|
+
jsenvPluginImportMetaCss(),
|
|
8940
9056
|
jsenvPluginCommonJsGlobals(),
|
|
8941
9057
|
jsenvPluginImportMetaScenarios(),
|
|
8942
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 };
|
|
@@ -262,6 +262,7 @@ const createFetchUrlContentError = ({
|
|
|
262
262
|
const createFailedToFetchUrlContentError = ({
|
|
263
263
|
code = error.code || "FETCH_URL_CONTENT_ERROR",
|
|
264
264
|
reason,
|
|
265
|
+
parseErrorSourceType,
|
|
265
266
|
...details
|
|
266
267
|
}) => {
|
|
267
268
|
const reference = urlInfo.firstReference;
|
|
@@ -282,6 +283,7 @@ ${reason}`,
|
|
|
282
283
|
name: "FETCH_URL_CONTENT_ERROR",
|
|
283
284
|
code,
|
|
284
285
|
reason,
|
|
286
|
+
parseErrorSourceType,
|
|
285
287
|
url: urlInfo.url,
|
|
286
288
|
trace: code === "PARSE_ERROR" ? error.trace : reference.trace,
|
|
287
289
|
asResponse: error.asResponse,
|
|
@@ -316,6 +318,7 @@ ${reason}`,
|
|
|
316
318
|
return createFailedToFetchUrlContentError({
|
|
317
319
|
"code": "PARSE_ERROR",
|
|
318
320
|
"reason": error.reasonCode,
|
|
321
|
+
"parseErrorSourceType": error.parseErrorSourceType,
|
|
319
322
|
...(error.cause ? { "parse error message": error.cause.message } : {}),
|
|
320
323
|
"parse error trace": error.trace?.message,
|
|
321
324
|
});
|
|
@@ -365,6 +368,8 @@ ${error.message}`,
|
|
|
365
368
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
366
369
|
code: "PARSE_ERROR",
|
|
367
370
|
reason: error.message,
|
|
371
|
+
reasonCode: error.reasonCode,
|
|
372
|
+
parseErrorSourceType: error.parseErrorSourceType,
|
|
368
373
|
stack: transformError.stack,
|
|
369
374
|
trace,
|
|
370
375
|
asResponse: error.asResponse,
|
|
@@ -7680,6 +7685,116 @@ const jsenvPluginNodeRuntime = ({ runtimeCompat }) => {
|
|
|
7680
7685
|
};
|
|
7681
7686
|
};
|
|
7682
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
|
+
|
|
7683
7798
|
// https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-stages-of-babel
|
|
7684
7799
|
// https://github.com/cfware/babel-plugin-bundled-import-meta/blob/master/index.js
|
|
7685
7800
|
// https://github.com/babel/babel/blob/f4edf62f6beeab8ae9f2b7f0b82f1b3b12a581af/packages/babel-helper-module-imports/src/index.js#L7
|
|
@@ -7691,13 +7806,13 @@ const babelPluginMetadataImportMetaHot = () => {
|
|
|
7691
7806
|
Program(programPath, state) {
|
|
7692
7807
|
Object.assign(
|
|
7693
7808
|
state.file.metadata,
|
|
7694
|
-
|
|
7809
|
+
collectImportMetaHotProperties(programPath),
|
|
7695
7810
|
);
|
|
7696
7811
|
},
|
|
7697
7812
|
},
|
|
7698
7813
|
};
|
|
7699
7814
|
};
|
|
7700
|
-
const
|
|
7815
|
+
const collectImportMetaHotProperties = (programPath) => {
|
|
7701
7816
|
const importMetaHotPaths = [];
|
|
7702
7817
|
let hotDecline = false;
|
|
7703
7818
|
let hotAcceptSelf = false;
|
|
@@ -8977,6 +9092,7 @@ const getCorePlugins = ({
|
|
|
8977
9092
|
? [jsenvPluginAutoreloadOnServerRestart()]
|
|
8978
9093
|
: []),
|
|
8979
9094
|
|
|
9095
|
+
jsenvPluginImportMetaCss(),
|
|
8980
9096
|
jsenvPluginCommonJsGlobals(),
|
|
8981
9097
|
jsenvPluginImportMetaScenarios(),
|
|
8982
9098
|
...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "40.
|
|
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": "
|
|
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
|
+
}
|
package/src/kitchen/errors.js
CHANGED
|
@@ -73,6 +73,7 @@ export const createFetchUrlContentError = ({
|
|
|
73
73
|
const createFailedToFetchUrlContentError = ({
|
|
74
74
|
code = error.code || "FETCH_URL_CONTENT_ERROR",
|
|
75
75
|
reason,
|
|
76
|
+
parseErrorSourceType,
|
|
76
77
|
...details
|
|
77
78
|
}) => {
|
|
78
79
|
const reference = urlInfo.firstReference;
|
|
@@ -93,6 +94,7 @@ ${reason}`,
|
|
|
93
94
|
name: "FETCH_URL_CONTENT_ERROR",
|
|
94
95
|
code,
|
|
95
96
|
reason,
|
|
97
|
+
parseErrorSourceType,
|
|
96
98
|
url: urlInfo.url,
|
|
97
99
|
trace: code === "PARSE_ERROR" ? error.trace : reference.trace,
|
|
98
100
|
asResponse: error.asResponse,
|
|
@@ -127,6 +129,7 @@ ${reason}`,
|
|
|
127
129
|
return createFailedToFetchUrlContentError({
|
|
128
130
|
"code": "PARSE_ERROR",
|
|
129
131
|
"reason": error.reasonCode,
|
|
132
|
+
"parseErrorSourceType": error.parseErrorSourceType,
|
|
130
133
|
...(error.cause ? { "parse error message": error.cause.message } : {}),
|
|
131
134
|
"parse error trace": error.trace?.message,
|
|
132
135
|
});
|
|
@@ -176,6 +179,8 @@ ${error.message}`,
|
|
|
176
179
|
name: "TRANSFORM_URL_CONTENT_ERROR",
|
|
177
180
|
code: "PARSE_ERROR",
|
|
178
181
|
reason: error.message,
|
|
182
|
+
reasonCode: error.reasonCode,
|
|
183
|
+
parseErrorSourceType: error.parseErrorSourceType,
|
|
179
184
|
stack: transformError.stack,
|
|
180
185
|
trace,
|
|
181
186
|
asResponse: error.asResponse,
|
|
@@ -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()] : []),
|