@jsenv/core 41.5.18 → 41.5.19

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.
@@ -1,5 +1,5 @@
1
- import { parseHtml, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, stringifyHtmlAst, applyBabelPlugins, generateUrlForInlineContent, injectJsenvScript, parseJsWithAcorn, visitHtmlNodes, analyzeScriptNode, getHtmlNodeText, getHtmlNodeAttribute, getHtmlNodePosition, getUrlForContentInsideHtml, setHtmlNodeAttributes, setHtmlNodeText, parseCssUrls, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, parseJsUrls, getUrlForContentInsideJs, renderCssTemplateLiteral, visitJsAst, getImportMetaPropertyName, visitJsAstUntil, analyzeLinkNode, findHtmlNode, removeHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
2
- import { lookupPackageDirectory, urlIsOrIsInsideOf, registerDirectoryLifecycle, urlToRelativeUrl, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, ensureWindowsDriveLetter, setUrlFilename, moveUrl, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, normalizeUrl, ANSI, RUNTIME_COMPAT, CONTENT_TYPE, readPackageAtOrNull, urlToFilename, DATA_URL, errorToHTML, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, readCustomConditionsFromProcessArgs, collectFiles, readEntryStatSync, applyFileSystemMagicResolution, getExtensionsToTry, ensurePathnameTrailingSlash, compareFileUrls, setUrlExtension, isSpecifierForNodeBuiltin, injectQueryParams, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringMemoryUsage, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog, createLookupPackageDirectory, ensureEmptyDirectory, updateJsonFileSync, createDynamicLog } from "./jsenv_core_packages.js";
1
+ import { parseHtml, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, stringifyHtmlAst, applyBabelPlugins, generateUrlForInlineContent, injectJsenvScript, parseJsWithAcorn, visitHtmlNodes, analyzeScriptNode, getHtmlNodeText, getHtmlNodeAttribute, getHtmlNodePosition, getUrlForContentInsideHtml, setHtmlNodeAttributes, setHtmlNodeText, parseCssUrls, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, parseJsUrls, hasCssOpaqueDirective, getUrlForContentInsideJs, renderCssTemplateLiteral, visitJsAst, getImportMetaPropertyName, visitJsAstUntil, analyzeLinkNode, findHtmlNode, removeHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
2
+ import { lookupPackageDirectory, urlIsOrIsInsideOf, registerDirectoryLifecycle, urlToRelativeUrl, createDetailedMessage, stringifyUrlSite, generateContentFrame, validateResponseIntegrity, ensureWindowsDriveLetter, setUrlFilename, moveUrl, getCallerPosition, urlToBasename, urlToExtension, asSpecifierWithoutSearch, asUrlWithoutSearch, injectQueryParamsIntoSpecifier, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, urlToFileSystemPath, writeFileSync, createLogger, URL_META, applyNodeEsmResolution, normalizeUrl, ANSI, RUNTIME_COMPAT, CONTENT_TYPE, readPackageAtOrNull, urlToFilename, DATA_URL, errorToHTML, normalizeImportMap, composeTwoImportMaps, resolveImport, UNICODE, JS_QUOTES, readCustomConditionsFromProcessArgs, collectFiles, readEntryStatSync, applyFileSystemMagicResolution, getExtensionsToTry, ensurePathnameTrailingSlash, compareFileUrls, setUrlExtension, isSpecifierForNodeBuiltin, injectQueryParams, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringMemoryUsage, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog, createLookupPackageDirectory, ensureEmptyDirectory, updateJsonFileSync, createDynamicLog } from "./jsenv_core_packages.js";
3
3
  import { bundleJsModules, jsenvPluginBundling } from "@jsenv/plugin-bundling";
4
4
  import { jsenvPluginMinification } from "@jsenv/plugin-minification";
5
5
  import { jsenvPluginTranspilation, jsenvPluginJsModuleFallback } from "@jsenv/plugin-transpilation";
@@ -5810,7 +5810,20 @@ const parseAndTransformJsReferences = async (
5810
5810
  renderCssTemplateLiteral(inlineUrlInfo.content, substitutions)
5811
5811
  : JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, { quote });
5812
5812
  if (replacement === null) {
5813
- // a placeholder did not survive: the source stays as it was written
5813
+ // a placeholder did not survive the css transformation: giving the
5814
+ // expressions back would not give back what the source said
5815
+ if (inlineReferenceInfo.alreadyBuilt) {
5816
+ return;
5817
+ }
5818
+ warnCssShippedAsWritten(urlInfo, {
5819
+ line: inlineReferenceInfo.line,
5820
+ column: inlineReferenceInfo.column,
5821
+ reason: `a "\${}" placeholder did not survive the css transformation`,
5822
+ templateSource: urlInfo.content.slice(
5823
+ inlineReferenceInfo.start,
5824
+ inlineReferenceInfo.end,
5825
+ ),
5826
+ });
5814
5827
  return;
5815
5828
  }
5816
5829
  magicSource.replace({
@@ -5918,7 +5931,13 @@ const parseAndTransformJsReferences = async (
5918
5931
  isNodeJs,
5919
5932
  });
5920
5933
  for (const jsReferenceInfo of jsReferenceInfos) {
5921
- if (jsReferenceInfo.isInline) {
5934
+ if (jsReferenceInfo.isOpaqueCss) {
5935
+ if (!jsReferenceInfo.alreadyBuilt) {
5936
+ // a dependency's built css is opaque in a source this build does not
5937
+ // have; its own build is where that is told
5938
+ warnCssShippedAsWritten(urlInfo, jsReferenceInfo);
5939
+ }
5940
+ } else if (jsReferenceInfo.isInline) {
5922
5941
  onInlineReference(jsReferenceInfo);
5923
5942
  } else {
5924
5943
  onExternalReference(jsReferenceInfo);
@@ -5933,6 +5952,38 @@ const parseAndTransformJsReferences = async (
5933
5952
  return magicSource.toContentAndSourcemap();
5934
5953
  };
5935
5954
 
5955
+ // An import.meta.css the build cannot parse is shipped exactly as written:
5956
+ // comments, indentation, untranspiled properties and unresolved url() included,
5957
+ // in this build and in every build of every consumer of what it produces.
5958
+ // Nothing downstream can undo it, so the only place it can be told is here.
5959
+ const warnCssShippedAsWritten = (
5960
+ urlInfo,
5961
+ { line, column, reason, templateSource },
5962
+ ) => {
5963
+ if (!urlInfo.context.build) {
5964
+ return;
5965
+ }
5966
+ if (hasCssOpaqueDirective(templateSource)) {
5967
+ return;
5968
+ }
5969
+ urlInfo.context.logger.warn(
5970
+ createDetailedMessage(
5971
+ `${UNICODE.WARNING} import.meta.css shipped as written: not parsed, not transpiled, not minified`,
5972
+ {
5973
+ // line/column are read from the content as analyzed, which is not the
5974
+ // file on disk once something transpiled it (jsx, babel helpers)
5975
+ "css template":
5976
+ urlInfo.content === urlInfo.originalContent
5977
+ ? `${urlInfo.url}:${line}:${column}`
5978
+ : urlInfo.url,
5979
+ reason,
5980
+ "suggestion": `only a "\${}" standing where a css value stands can be read; a custom property set from JS, a data attribute or a selector list covers nearly every other reason to interpolate`,
5981
+ "to silence": `write "jsenv-css-opaque" in a css comment inside that template`,
5982
+ },
5983
+ ),
5984
+ );
5985
+ };
5986
+
5936
5987
  const jsenvPluginReferenceExpectedTypes = () => {
5937
5988
  const redirectJsReference = (reference) => {
5938
5989
  const urlObject = new URL(reference.url);
@@ -7449,4 +7449,4 @@ const isResponseEligibleForIntegrityValidation = (response) => {
7449
7449
  return ["basic", "cors", "default"].includes(response.type);
7450
7450
  };
7451
7451
 
7452
- export { ANSI, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, bufferToEtag, collectFiles, compareFileUrls, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createLogger, createTaskLog, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, formatError, generateContentFrame, getCallerPosition, getExtensionsToTry, inferRuntimeCompatFromClosestPackage, injectQueryParams, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, moveUrl, normalizeImportMap, normalizeUrl, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, registerFileLifecycle, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, stringifyUrlSite, urlIsOrIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
7452
+ export { ANSI, CONTENT_TYPE, DATA_URL, JS_QUOTES, RUNTIME_COMPAT, UNICODE, URL_META, applyFileSystemMagicResolution, applyNodeEsmResolution, asSpecifierWithoutSearch, asUrlWithoutSearch, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, bufferToEtag, collectFiles, compareFileUrls, composeTwoImportMaps, createDetailedMessage$1 as createDetailedMessage, createLogger, createTaskLog, ensurePathnameTrailingSlash, ensureWindowsDriveLetter, errorToHTML, formatError, generateContentFrame, getCallerPosition, getExtensionsToTry, inferRuntimeCompatFromClosestPackage, injectQueryParams, injectQueryParamsIntoSpecifier, isFileSystemPath, isSpecifierForNodeBuiltin, lookupPackageDirectory, moveUrl, normalizeImportMap, normalizeUrl, readCustomConditionsFromProcessArgs, readEntryStatSync, readPackageAtOrNull, registerDirectoryLifecycle, registerFileLifecycle, resolveImport, setUrlBasename, setUrlExtension, setUrlFilename, stringifyUrlSite, urlIsOrIsInsideOf, urlToBasename, urlToExtension$1 as urlToExtension, urlToFileSystemPath, urlToFilename$1 as urlToFilename, urlToPathname$1 as urlToPathname, urlToRelativeUrl, validateResponseIntegrity, writeFileSync };
@@ -1,9 +1,9 @@
1
1
  import { WebSocketResponse, pickContentType, ServerEvents, serverPluginErrorHandler, fetchDirectory, composeTwoResponses, serverPluginCORS, jsenvAccessControlAllowedHeaders, startServer } from "@jsenv/server";
2
2
  import { existsSync, statSync, readFileSync, realpathSync, readdirSync, lstatSync } from "node:fs";
3
3
  import { pathToFileURL } from "node:url";
4
- import { urlToRelativeUrl, registerFileLifecycle, lookupPackageDirectory, readPackageAtOrNull, generateContentFrame, errorToHTML, DATA_URL, CONTENT_TYPE, normalizeImportMap, composeTwoImportMaps, resolveImport, JS_QUOTES, urlToExtension, urlToBasename, applyNodeEsmResolution, URL_META, readCustomConditionsFromProcessArgs, urlIsOrIsInsideOf, collectFiles, registerDirectoryLifecycle, readEntryStatSync, applyFileSystemMagicResolution, getExtensionsToTry, urlToFilename, asUrlWithoutSearch, ensurePathnameTrailingSlash, compareFileUrls, setUrlExtension, createDetailedMessage, stringifyUrlSite, injectQueryParamsIntoSpecifier, isSpecifierForNodeBuiltin, injectQueryParams, urlToFileSystemPath, writeFileSync, moveUrl, ensureWindowsDriveLetter, validateResponseIntegrity, setUrlFilename, getCallerPosition, asSpecifierWithoutSearch, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, createLogger, normalizeUrl, ANSI, RUNTIME_COMPAT, formatError, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, inferRuntimeCompatFromClosestPackage, createTaskLog } from "./jsenv_core_packages.js";
4
+ import { urlToRelativeUrl, registerFileLifecycle, lookupPackageDirectory, readPackageAtOrNull, generateContentFrame, errorToHTML, DATA_URL, CONTENT_TYPE, normalizeImportMap, composeTwoImportMaps, resolveImport, createDetailedMessage, UNICODE, JS_QUOTES, urlToExtension, urlToBasename, applyNodeEsmResolution, URL_META, readCustomConditionsFromProcessArgs, urlIsOrIsInsideOf, collectFiles, registerDirectoryLifecycle, readEntryStatSync, applyFileSystemMagicResolution, getExtensionsToTry, urlToFilename, asUrlWithoutSearch, ensurePathnameTrailingSlash, compareFileUrls, setUrlExtension, stringifyUrlSite, injectQueryParamsIntoSpecifier, isSpecifierForNodeBuiltin, injectQueryParams, urlToFileSystemPath, writeFileSync, moveUrl, ensureWindowsDriveLetter, validateResponseIntegrity, setUrlFilename, getCallerPosition, asSpecifierWithoutSearch, bufferToEtag, isFileSystemPath, urlToPathname, setUrlBasename, createLogger, normalizeUrl, ANSI, RUNTIME_COMPAT, formatError, assertAndNormalizeDirectoryUrl, browserDefaultRuntimeCompat, inferRuntimeCompatFromClosestPackage, createTaskLog } from "./jsenv_core_packages.js";
5
5
  import { createPluginsController } from "@jsenv/server/src/plugins_controller.js";
6
- import { parseHtml, injectJsenvScript, stringifyHtmlAst, parseCssUrls, getHtmlNodeAttribute, getHtmlNodePosition, getHtmlNodeAttributePosition, setHtmlNodeAttributes, parseSrcSet, getUrlForContentInsideHtml, removeHtmlNodeText, setHtmlNodeText, getHtmlNodeText, analyzeScriptNode, visitHtmlNodes, parseJsUrls, getUrlForContentInsideJs, renderCssTemplateLiteral, applyBabelPlugins, visitJsAst, getImportMetaPropertyName, visitJsAstUntil, analyzeLinkNode, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn } from "@jsenv/ast";
6
+ import { parseHtml, injectJsenvScript, stringifyHtmlAst, parseCssUrls, getHtmlNodeAttribute, getHtmlNodePosition, getHtmlNodeAttributePosition, setHtmlNodeAttributes, parseSrcSet, getUrlForContentInsideHtml, removeHtmlNodeText, setHtmlNodeText, getHtmlNodeText, analyzeScriptNode, visitHtmlNodes, parseJsUrls, hasCssOpaqueDirective, getUrlForContentInsideJs, renderCssTemplateLiteral, applyBabelPlugins, visitJsAst, getImportMetaPropertyName, visitJsAstUntil, analyzeLinkNode, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn } from "@jsenv/ast";
7
7
  import { jsenvPluginSupervisor } from "@jsenv/plugin-supervisor";
8
8
  import { jsenvPluginTranspilation } from "@jsenv/plugin-transpilation";
9
9
  import { createMagicSource, composeTwoSourcemaps, generateSourcemapFileUrl, generateSourcemapDataUrl, SOURCEMAP, applyContentEditsOnSourcemap, composeSourcemaps } from "@jsenv/sourcemap";
@@ -2392,7 +2392,20 @@ const parseAndTransformJsReferences = async (
2392
2392
  renderCssTemplateLiteral(inlineUrlInfo.content, substitutions)
2393
2393
  : JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, { quote });
2394
2394
  if (replacement === null) {
2395
- // a placeholder did not survive: the source stays as it was written
2395
+ // a placeholder did not survive the css transformation: giving the
2396
+ // expressions back would not give back what the source said
2397
+ if (inlineReferenceInfo.alreadyBuilt) {
2398
+ return;
2399
+ }
2400
+ warnCssShippedAsWritten(urlInfo, {
2401
+ line: inlineReferenceInfo.line,
2402
+ column: inlineReferenceInfo.column,
2403
+ reason: `a "\${}" placeholder did not survive the css transformation`,
2404
+ templateSource: urlInfo.content.slice(
2405
+ inlineReferenceInfo.start,
2406
+ inlineReferenceInfo.end,
2407
+ ),
2408
+ });
2396
2409
  return;
2397
2410
  }
2398
2411
  magicSource.replace({
@@ -2500,7 +2513,13 @@ const parseAndTransformJsReferences = async (
2500
2513
  isNodeJs,
2501
2514
  });
2502
2515
  for (const jsReferenceInfo of jsReferenceInfos) {
2503
- if (jsReferenceInfo.isInline) {
2516
+ if (jsReferenceInfo.isOpaqueCss) {
2517
+ if (!jsReferenceInfo.alreadyBuilt) {
2518
+ // a dependency's built css is opaque in a source this build does not
2519
+ // have; its own build is where that is told
2520
+ warnCssShippedAsWritten(urlInfo, jsReferenceInfo);
2521
+ }
2522
+ } else if (jsReferenceInfo.isInline) {
2504
2523
  onInlineReference(jsReferenceInfo);
2505
2524
  } else {
2506
2525
  onExternalReference(jsReferenceInfo);
@@ -2515,6 +2534,38 @@ const parseAndTransformJsReferences = async (
2515
2534
  return magicSource.toContentAndSourcemap();
2516
2535
  };
2517
2536
 
2537
+ // An import.meta.css the build cannot parse is shipped exactly as written:
2538
+ // comments, indentation, untranspiled properties and unresolved url() included,
2539
+ // in this build and in every build of every consumer of what it produces.
2540
+ // Nothing downstream can undo it, so the only place it can be told is here.
2541
+ const warnCssShippedAsWritten = (
2542
+ urlInfo,
2543
+ { line, column, reason, templateSource },
2544
+ ) => {
2545
+ if (!urlInfo.context.build) {
2546
+ return;
2547
+ }
2548
+ if (hasCssOpaqueDirective(templateSource)) {
2549
+ return;
2550
+ }
2551
+ urlInfo.context.logger.warn(
2552
+ createDetailedMessage(
2553
+ `${UNICODE.WARNING} import.meta.css shipped as written: not parsed, not transpiled, not minified`,
2554
+ {
2555
+ // line/column are read from the content as analyzed, which is not the
2556
+ // file on disk once something transpiled it (jsx, babel helpers)
2557
+ "css template":
2558
+ urlInfo.content === urlInfo.originalContent
2559
+ ? `${urlInfo.url}:${line}:${column}`
2560
+ : urlInfo.url,
2561
+ reason,
2562
+ "suggestion": `only a "\${}" standing where a css value stands can be read; a custom property set from JS, a data attribute or a selector list covers nearly every other reason to interpolate`,
2563
+ "to silence": `write "jsenv-css-opaque" in a css comment inside that template`,
2564
+ },
2565
+ ),
2566
+ );
2567
+ };
2568
+
2518
2569
  const jsenvPluginReferenceExpectedTypes = () => {
2519
2570
  const redirectJsReference = (reference) => {
2520
2571
  const urlObject = new URL(reference.url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "41.5.18",
3
+ "version": "41.5.19",
4
4
  "type": "module",
5
5
  "description": "Tool to develop, test and build js projects",
6
6
  "repository": {
@@ -73,12 +73,12 @@
73
73
  "test:snapshot_clear": "npx @jsenv/filesystem clear **/tests/**/side_effects/"
74
74
  },
75
75
  "dependencies": {
76
- "@jsenv/ast": "6.10.4",
77
- "@jsenv/js-module-fallback": "1.6.8",
76
+ "@jsenv/ast": "6.10.5",
77
+ "@jsenv/js-module-fallback": "1.6.9",
78
78
  "@jsenv/plugin-bundling": "2.10.28",
79
- "@jsenv/plugin-minification": "1.7.21",
80
- "@jsenv/plugin-supervisor": "1.8.23",
81
- "@jsenv/plugin-transpilation": "1.7.8",
79
+ "@jsenv/plugin-minification": "1.7.22",
80
+ "@jsenv/plugin-supervisor": "1.8.24",
81
+ "@jsenv/plugin-transpilation": "1.7.9",
82
82
  "@jsenv/server": "17.6.4",
83
83
  "@jsenv/sourcemap": "1.4.9",
84
84
  "react-table": "7.8.0"
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  getUrlForContentInsideJs,
3
+ hasCssOpaqueDirective,
3
4
  parseJsUrls,
4
5
  renderCssTemplateLiteral,
5
6
  } from "@jsenv/ast";
7
+ import { createDetailedMessage, UNICODE } from "@jsenv/humanize";
6
8
  import {
7
9
  isWebWorkerEntryPointReference,
8
10
  isWebWorkerUrlInfo,
@@ -82,7 +84,20 @@ const parseAndTransformJsReferences = async (
82
84
  renderCssTemplateLiteral(inlineUrlInfo.content, substitutions)
83
85
  : JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, { quote });
84
86
  if (replacement === null) {
85
- // a placeholder did not survive: the source stays as it was written
87
+ // a placeholder did not survive the css transformation: giving the
88
+ // expressions back would not give back what the source said
89
+ if (inlineReferenceInfo.alreadyBuilt) {
90
+ return;
91
+ }
92
+ warnCssShippedAsWritten(urlInfo, {
93
+ line: inlineReferenceInfo.line,
94
+ column: inlineReferenceInfo.column,
95
+ reason: `a "\${}" placeholder did not survive the css transformation`,
96
+ templateSource: urlInfo.content.slice(
97
+ inlineReferenceInfo.start,
98
+ inlineReferenceInfo.end,
99
+ ),
100
+ });
86
101
  return;
87
102
  }
88
103
  magicSource.replace({
@@ -190,7 +205,13 @@ const parseAndTransformJsReferences = async (
190
205
  isNodeJs,
191
206
  });
192
207
  for (const jsReferenceInfo of jsReferenceInfos) {
193
- if (jsReferenceInfo.isInline) {
208
+ if (jsReferenceInfo.isOpaqueCss) {
209
+ if (!jsReferenceInfo.alreadyBuilt) {
210
+ // a dependency's built css is opaque in a source this build does not
211
+ // have; its own build is where that is told
212
+ warnCssShippedAsWritten(urlInfo, jsReferenceInfo);
213
+ }
214
+ } else if (jsReferenceInfo.isInline) {
194
215
  onInlineReference(jsReferenceInfo);
195
216
  } else {
196
217
  onExternalReference(jsReferenceInfo);
@@ -204,3 +225,35 @@ const parseAndTransformJsReferences = async (
204
225
  }
205
226
  return magicSource.toContentAndSourcemap();
206
227
  };
228
+
229
+ // An import.meta.css the build cannot parse is shipped exactly as written:
230
+ // comments, indentation, untranspiled properties and unresolved url() included,
231
+ // in this build and in every build of every consumer of what it produces.
232
+ // Nothing downstream can undo it, so the only place it can be told is here.
233
+ const warnCssShippedAsWritten = (
234
+ urlInfo,
235
+ { line, column, reason, templateSource },
236
+ ) => {
237
+ if (!urlInfo.context.build) {
238
+ return;
239
+ }
240
+ if (hasCssOpaqueDirective(templateSource)) {
241
+ return;
242
+ }
243
+ urlInfo.context.logger.warn(
244
+ createDetailedMessage(
245
+ `${UNICODE.WARNING} import.meta.css shipped as written: not parsed, not transpiled, not minified`,
246
+ {
247
+ // line/column are read from the content as analyzed, which is not the
248
+ // file on disk once something transpiled it (jsx, babel helpers)
249
+ "css template":
250
+ urlInfo.content === urlInfo.originalContent
251
+ ? `${urlInfo.url}:${line}:${column}`
252
+ : urlInfo.url,
253
+ reason,
254
+ "suggestion": `only a "\${}" standing where a css value stands can be read; a custom property set from JS, a data attribute or a selector list covers nearly every other reason to interpolate`,
255
+ "to silence": `write "jsenv-css-opaque" in a css comment inside that template`,
256
+ },
257
+ ),
258
+ );
259
+ };