boss-css 0.0.24 → 0.0.25

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.
@@ -196,6 +196,12 @@ const POSTCSS_CONFIG_FILES = [
196
196
  ".postcssrc.cjs",
197
197
  ".postcssrc.mjs"
198
198
  ];
199
+ const VITE_CONFIG_FILES = [
200
+ "vite.config.ts",
201
+ "vite.config.js",
202
+ "vite.config.mjs",
203
+ "vite.config.cjs"
204
+ ];
199
205
  const ESLINT_CONFIG_FILES = [
200
206
  {
201
207
  file: "eslint.config.js",
@@ -371,6 +377,7 @@ const init = async (config) => {
371
377
  configDir: normalizedConfigDir,
372
378
  packageJson: packageData
373
379
  });
380
+ const nitroViteUpdate = await ensureNitroViteTraceDeps(cwd);
374
381
  const packageManager = await detectPackageManager(cwd, config.runtimeType);
375
382
  const installCommand = packageUpdate.bossCssAdded ? formatInstallCommand(packageManager) : null;
376
383
  logInitSummary({
@@ -386,7 +393,8 @@ const init = async (config) => {
386
393
  frameworkId: framework.id,
387
394
  selectedStrategyId,
388
395
  cssAutoLoad,
389
- installCommand
396
+ installCommand,
397
+ nitroUpdated: nitroViteUpdate.updated
390
398
  });
391
399
  return true;
392
400
  } }];
@@ -1257,6 +1265,93 @@ const ensureArrayEntry = (content, key, entry) => {
1257
1265
  content: `${content.slice(0, endIndex)}${insertion}${content.slice(endIndex)}`
1258
1266
  };
1259
1267
  };
1268
+ const updateNitroViteConfigContent = (content) => {
1269
+ const nitroPattern = /\bnitro\s*\(/g;
1270
+ let next = content;
1271
+ let updated = false;
1272
+ let hasNitro = false;
1273
+ let unsupported = false;
1274
+ let offset = 0;
1275
+ while (true) {
1276
+ nitroPattern.lastIndex = offset;
1277
+ const match = nitroPattern.exec(next);
1278
+ if (!match) break;
1279
+ hasNitro = true;
1280
+ const callStart = match.index + match[0].length - 1;
1281
+ const callEnd = findMatchingIndex(next, callStart, "(", ")");
1282
+ if (callEnd === -1) {
1283
+ unsupported = true;
1284
+ break;
1285
+ }
1286
+ const rawArgs = next.slice(callStart + 1, callEnd);
1287
+ if (!rawArgs.trim()) {
1288
+ next = `${next.slice(0, callStart + 1)}{ traceDeps: ['jsdom'] }${next.slice(callEnd)}`;
1289
+ updated = true;
1290
+ offset = callStart + 1 + 24;
1291
+ continue;
1292
+ }
1293
+ const firstArgOffset = rawArgs.search(/\S/);
1294
+ if (firstArgOffset === -1) {
1295
+ next = `${next.slice(0, callStart + 1)}{ traceDeps: ['jsdom'] }${next.slice(callEnd)}`;
1296
+ updated = true;
1297
+ offset = callStart + 1 + 24;
1298
+ continue;
1299
+ }
1300
+ const objectStart = callStart + 1 + firstArgOffset;
1301
+ if (next[objectStart] !== "{") {
1302
+ unsupported = true;
1303
+ offset = callEnd + 1;
1304
+ continue;
1305
+ }
1306
+ const objectEnd = findMatchingIndex(next, objectStart, "{", "}");
1307
+ if (objectEnd === -1 || next.slice(objectEnd + 1, callEnd).trim()) {
1308
+ unsupported = true;
1309
+ offset = callEnd + 1;
1310
+ continue;
1311
+ }
1312
+ const objectText = next.slice(objectStart, objectEnd + 1);
1313
+ const updatedObject = ensureNitroTraceDepsInObject(objectText, getIndentFromIndex(next, objectStart));
1314
+ if (updatedObject !== objectText) {
1315
+ next = `${next.slice(0, objectStart)}${updatedObject}${next.slice(objectEnd + 1)}`;
1316
+ updated = true;
1317
+ offset = objectStart + updatedObject.length;
1318
+ continue;
1319
+ }
1320
+ offset = callEnd + 1;
1321
+ }
1322
+ return {
1323
+ content: next,
1324
+ updated,
1325
+ hasNitro,
1326
+ unsupported
1327
+ };
1328
+ };
1329
+ const ensureNitroTraceDepsInObject = (objectText, baseIndent) => {
1330
+ if (!objectText.startsWith("{") || !objectText.endsWith("}")) return objectText;
1331
+ const traceMatch = objectText.match(/\btraceDeps\s*:\s*\[/);
1332
+ if (!traceMatch) {
1333
+ if (objectText.trim() === "{}") return "{ traceDeps: ['jsdom'] }";
1334
+ if (!objectText.includes("\n")) return `{ traceDeps: ['jsdom'], ${objectText.slice(1, -1).trim()} }`;
1335
+ const entryIndent = `${baseIndent} `;
1336
+ return objectText.replace("{", `{\n${entryIndent}traceDeps: ['jsdom'],`);
1337
+ }
1338
+ const arrayStart = (traceMatch.index ?? 0) + traceMatch[0].length - 1;
1339
+ const arrayEnd = findMatchingIndex(objectText, arrayStart, "[", "]");
1340
+ if (arrayEnd === -1) return objectText;
1341
+ const arrayBody = objectText.slice(arrayStart + 1, arrayEnd);
1342
+ if (/['"]jsdom['"]/.test(arrayBody)) return objectText;
1343
+ const updatedArrayBody = appendTraceDep(arrayBody, `${baseIndent} `);
1344
+ return `${objectText.slice(0, arrayStart + 1)}${updatedArrayBody}${objectText.slice(arrayEnd)}`;
1345
+ };
1346
+ const appendTraceDep = (arrayBody, indent) => {
1347
+ if (!arrayBody.trim()) {
1348
+ if (!arrayBody.includes("\n")) return "'jsdom'";
1349
+ return `\n${indent}'jsdom'\n${arrayBody.match(/\n([ \t]*)$/)?.[1] ?? indent.slice(0, -2)}`;
1350
+ }
1351
+ if (!arrayBody.includes("\n")) return `${arrayBody.trim()}, 'jsdom'`;
1352
+ const trimmedEnd = arrayBody.replace(/\s*$/, "");
1353
+ return `${trimmedEnd}${/,\s*$/.test(trimmedEnd) ? "" : ","}\n${indent}'jsdom'\n${arrayBody.match(/\n([ \t]*)$/)?.[1] ?? indent.slice(0, -2)}`;
1354
+ };
1260
1355
  const ensureAllowGlobalsRule = (rules) => {
1261
1356
  const existing = rules["react/jsx-no-undef"];
1262
1357
  if (Array.isArray(existing)) {
@@ -1710,6 +1805,31 @@ const ensureBossImport = (content, isEsm) => {
1710
1805
  if (content.includes("const boss = require")) return content;
1711
1806
  return `const boss = require('boss-css/postcss')\n${content}`;
1712
1807
  };
1808
+ const detectViteConfigPath = async (cwd) => {
1809
+ for (const file of VITE_CONFIG_FILES) {
1810
+ const fullPath = node_path.default.join(cwd, file);
1811
+ if (await exists(fullPath)) return fullPath;
1812
+ }
1813
+ return null;
1814
+ };
1815
+ const ensureNitroViteTraceDeps = async (cwd) => {
1816
+ const viteConfigPath = await detectViteConfigPath(cwd);
1817
+ if (!viteConfigPath) return {
1818
+ updated: false,
1819
+ hasNitro: false
1820
+ };
1821
+ const update = updateNitroViteConfigContent(await node_fs_promises.default.readFile(viteConfigPath, "utf8"));
1822
+ if (update.unsupported) _clack_prompts.log.warn("Nitro detected in vite.config.*, but init could not safely add traceDeps: ['jsdom'].");
1823
+ if (!update.updated) return {
1824
+ updated: false,
1825
+ hasNitro: update.hasNitro
1826
+ };
1827
+ await node_fs_promises.default.writeFile(viteConfigPath, update.content);
1828
+ return {
1829
+ updated: true,
1830
+ hasNitro: update.hasNitro
1831
+ };
1832
+ };
1713
1833
  const getIndentFromIndex = (content, index) => {
1714
1834
  const lineStart = content.lastIndexOf("\n", index);
1715
1835
  const match = content.slice(lineStart + 1).match(/^\s+/);
@@ -1816,7 +1936,7 @@ const exists = async (filePath) => {
1816
1936
  return false;
1817
1937
  }
1818
1938
  };
1819
- const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, configFolder, srcRoot, globalsEnabled, eslintUpdated, useEslintPlugin, frameworkId, selectedStrategyId, cssAutoLoad, installCommand }) => {
1939
+ const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, configFolder, srcRoot, globalsEnabled, eslintUpdated, useEslintPlugin, frameworkId, selectedStrategyId, cssAutoLoad, installCommand, nitroUpdated }) => {
1820
1940
  _clack_prompts.log.info("boss init complete.");
1821
1941
  _clack_prompts.log.message(`Generated Boss CSS config in ${configDir}`);
1822
1942
  if (selectedStrategyId === "classname-only") _clack_prompts.log.message("Classname-only does not auto-load styles. Import styles.css manually.");
@@ -1858,8 +1978,10 @@ const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, conf
1858
1978
  _clack_prompts.log.message("Stencil note:");
1859
1979
  _clack_prompts.log.message("- PostCSS setup is skipped; run `npx boss-css watch` for CSS generation.");
1860
1980
  }
1981
+ if (nitroUpdated) _clack_prompts.log.message("Updated vite.config.* Nitro plugin with traceDeps: ['jsdom'].");
1861
1982
  if (globalsEnabled) _clack_prompts.log.message("Global $$ enabled for JSX usage.");
1862
1983
  if (eslintUpdated) _clack_prompts.log.message(useEslintPlugin ? "ESLint updated with Boss CSS plugin." : "ESLint updated with $$ globals.");
1863
1984
  };
1864
1985
  //#endregion
1865
1986
  exports.default = init;
1987
+ exports.updateNitroViteConfigContent = updateNitroViteConfigContent;
@@ -192,6 +192,12 @@ const POSTCSS_CONFIG_FILES = [
192
192
  ".postcssrc.cjs",
193
193
  ".postcssrc.mjs"
194
194
  ];
195
+ const VITE_CONFIG_FILES = [
196
+ "vite.config.ts",
197
+ "vite.config.js",
198
+ "vite.config.mjs",
199
+ "vite.config.cjs"
200
+ ];
195
201
  const ESLINT_CONFIG_FILES = [
196
202
  {
197
203
  file: "eslint.config.js",
@@ -367,6 +373,7 @@ const init = async (config) => {
367
373
  configDir: normalizedConfigDir,
368
374
  packageJson: packageData
369
375
  });
376
+ const nitroViteUpdate = await ensureNitroViteTraceDeps(cwd);
370
377
  const packageManager = await detectPackageManager(cwd, config.runtimeType);
371
378
  const installCommand = packageUpdate.bossCssAdded ? formatInstallCommand(packageManager) : null;
372
379
  logInitSummary({
@@ -382,7 +389,8 @@ const init = async (config) => {
382
389
  frameworkId: framework.id,
383
390
  selectedStrategyId,
384
391
  cssAutoLoad,
385
- installCommand
392
+ installCommand,
393
+ nitroUpdated: nitroViteUpdate.updated
386
394
  });
387
395
  return true;
388
396
  } }];
@@ -1253,6 +1261,93 @@ const ensureArrayEntry = (content, key, entry) => {
1253
1261
  content: `${content.slice(0, endIndex)}${insertion}${content.slice(endIndex)}`
1254
1262
  };
1255
1263
  };
1264
+ const updateNitroViteConfigContent = (content) => {
1265
+ const nitroPattern = /\bnitro\s*\(/g;
1266
+ let next = content;
1267
+ let updated = false;
1268
+ let hasNitro = false;
1269
+ let unsupported = false;
1270
+ let offset = 0;
1271
+ while (true) {
1272
+ nitroPattern.lastIndex = offset;
1273
+ const match = nitroPattern.exec(next);
1274
+ if (!match) break;
1275
+ hasNitro = true;
1276
+ const callStart = match.index + match[0].length - 1;
1277
+ const callEnd = findMatchingIndex(next, callStart, "(", ")");
1278
+ if (callEnd === -1) {
1279
+ unsupported = true;
1280
+ break;
1281
+ }
1282
+ const rawArgs = next.slice(callStart + 1, callEnd);
1283
+ if (!rawArgs.trim()) {
1284
+ next = `${next.slice(0, callStart + 1)}{ traceDeps: ['jsdom'] }${next.slice(callEnd)}`;
1285
+ updated = true;
1286
+ offset = callStart + 1 + 24;
1287
+ continue;
1288
+ }
1289
+ const firstArgOffset = rawArgs.search(/\S/);
1290
+ if (firstArgOffset === -1) {
1291
+ next = `${next.slice(0, callStart + 1)}{ traceDeps: ['jsdom'] }${next.slice(callEnd)}`;
1292
+ updated = true;
1293
+ offset = callStart + 1 + 24;
1294
+ continue;
1295
+ }
1296
+ const objectStart = callStart + 1 + firstArgOffset;
1297
+ if (next[objectStart] !== "{") {
1298
+ unsupported = true;
1299
+ offset = callEnd + 1;
1300
+ continue;
1301
+ }
1302
+ const objectEnd = findMatchingIndex(next, objectStart, "{", "}");
1303
+ if (objectEnd === -1 || next.slice(objectEnd + 1, callEnd).trim()) {
1304
+ unsupported = true;
1305
+ offset = callEnd + 1;
1306
+ continue;
1307
+ }
1308
+ const objectText = next.slice(objectStart, objectEnd + 1);
1309
+ const updatedObject = ensureNitroTraceDepsInObject(objectText, getIndentFromIndex(next, objectStart));
1310
+ if (updatedObject !== objectText) {
1311
+ next = `${next.slice(0, objectStart)}${updatedObject}${next.slice(objectEnd + 1)}`;
1312
+ updated = true;
1313
+ offset = objectStart + updatedObject.length;
1314
+ continue;
1315
+ }
1316
+ offset = callEnd + 1;
1317
+ }
1318
+ return {
1319
+ content: next,
1320
+ updated,
1321
+ hasNitro,
1322
+ unsupported
1323
+ };
1324
+ };
1325
+ const ensureNitroTraceDepsInObject = (objectText, baseIndent) => {
1326
+ if (!objectText.startsWith("{") || !objectText.endsWith("}")) return objectText;
1327
+ const traceMatch = objectText.match(/\btraceDeps\s*:\s*\[/);
1328
+ if (!traceMatch) {
1329
+ if (objectText.trim() === "{}") return "{ traceDeps: ['jsdom'] }";
1330
+ if (!objectText.includes("\n")) return `{ traceDeps: ['jsdom'], ${objectText.slice(1, -1).trim()} }`;
1331
+ const entryIndent = `${baseIndent} `;
1332
+ return objectText.replace("{", `{\n${entryIndent}traceDeps: ['jsdom'],`);
1333
+ }
1334
+ const arrayStart = (traceMatch.index ?? 0) + traceMatch[0].length - 1;
1335
+ const arrayEnd = findMatchingIndex(objectText, arrayStart, "[", "]");
1336
+ if (arrayEnd === -1) return objectText;
1337
+ const arrayBody = objectText.slice(arrayStart + 1, arrayEnd);
1338
+ if (/['"]jsdom['"]/.test(arrayBody)) return objectText;
1339
+ const updatedArrayBody = appendTraceDep(arrayBody, `${baseIndent} `);
1340
+ return `${objectText.slice(0, arrayStart + 1)}${updatedArrayBody}${objectText.slice(arrayEnd)}`;
1341
+ };
1342
+ const appendTraceDep = (arrayBody, indent) => {
1343
+ if (!arrayBody.trim()) {
1344
+ if (!arrayBody.includes("\n")) return "'jsdom'";
1345
+ return `\n${indent}'jsdom'\n${arrayBody.match(/\n([ \t]*)$/)?.[1] ?? indent.slice(0, -2)}`;
1346
+ }
1347
+ if (!arrayBody.includes("\n")) return `${arrayBody.trim()}, 'jsdom'`;
1348
+ const trimmedEnd = arrayBody.replace(/\s*$/, "");
1349
+ return `${trimmedEnd}${/,\s*$/.test(trimmedEnd) ? "" : ","}\n${indent}'jsdom'\n${arrayBody.match(/\n([ \t]*)$/)?.[1] ?? indent.slice(0, -2)}`;
1350
+ };
1256
1351
  const ensureAllowGlobalsRule = (rules) => {
1257
1352
  const existing = rules["react/jsx-no-undef"];
1258
1353
  if (Array.isArray(existing)) {
@@ -1706,6 +1801,31 @@ const ensureBossImport = (content, isEsm) => {
1706
1801
  if (content.includes("const boss = require")) return content;
1707
1802
  return `const boss = require('boss-css/postcss')\n${content}`;
1708
1803
  };
1804
+ const detectViteConfigPath = async (cwd) => {
1805
+ for (const file of VITE_CONFIG_FILES) {
1806
+ const fullPath = path.join(cwd, file);
1807
+ if (await exists(fullPath)) return fullPath;
1808
+ }
1809
+ return null;
1810
+ };
1811
+ const ensureNitroViteTraceDeps = async (cwd) => {
1812
+ const viteConfigPath = await detectViteConfigPath(cwd);
1813
+ if (!viteConfigPath) return {
1814
+ updated: false,
1815
+ hasNitro: false
1816
+ };
1817
+ const update = updateNitroViteConfigContent(await fs.readFile(viteConfigPath, "utf8"));
1818
+ if (update.unsupported) log.warn("Nitro detected in vite.config.*, but init could not safely add traceDeps: ['jsdom'].");
1819
+ if (!update.updated) return {
1820
+ updated: false,
1821
+ hasNitro: update.hasNitro
1822
+ };
1823
+ await fs.writeFile(viteConfigPath, update.content);
1824
+ return {
1825
+ updated: true,
1826
+ hasNitro: update.hasNitro
1827
+ };
1828
+ };
1709
1829
  const getIndentFromIndex = (content, index) => {
1710
1830
  const lineStart = content.lastIndexOf("\n", index);
1711
1831
  const match = content.slice(lineStart + 1).match(/^\s+/);
@@ -1812,7 +1932,7 @@ const exists = async (filePath) => {
1812
1932
  return false;
1813
1933
  }
1814
1934
  };
1815
- const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, configFolder, srcRoot, globalsEnabled, eslintUpdated, useEslintPlugin, frameworkId, selectedStrategyId, cssAutoLoad, installCommand }) => {
1935
+ const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, configFolder, srcRoot, globalsEnabled, eslintUpdated, useEslintPlugin, frameworkId, selectedStrategyId, cssAutoLoad, installCommand, nitroUpdated }) => {
1816
1936
  log.info("boss init complete.");
1817
1937
  log.message(`Generated Boss CSS config in ${configDir}`);
1818
1938
  if (selectedStrategyId === "classname-only") log.message("Classname-only does not auto-load styles. Import styles.css manually.");
@@ -1854,8 +1974,9 @@ const logInitSummary = ({ configDir, isNext, postcssMode, postcssDetection, conf
1854
1974
  log.message("Stencil note:");
1855
1975
  log.message("- PostCSS setup is skipped; run `npx boss-css watch` for CSS generation.");
1856
1976
  }
1977
+ if (nitroUpdated) log.message("Updated vite.config.* Nitro plugin with traceDeps: ['jsdom'].");
1857
1978
  if (globalsEnabled) log.message("Global $$ enabled for JSX usage.");
1858
1979
  if (eslintUpdated) log.message(useEslintPlugin ? "ESLint updated with Boss CSS plugin." : "ESLint updated with $$ globals.");
1859
1980
  };
1860
1981
  //#endregion
1861
- export { init as default };
1982
+ export { init as default, updateNitroViteConfigContent };
@@ -1,5 +1,5 @@
1
1
  //#region src/use/token/propMap.d.ts
2
- declare const propMap: Map<string, string[] | Set<string>>;
2
+ declare const propMap: Map<string, Set<string> | string[]>;
3
3
  declare const getTokenGroupsForProp: (prop: string) => string[];
4
4
  declare const getTokenGroupForProp: (prop: string) => string;
5
5
  declare const setTokenPropGroups: (groups: Record<string, string[]>) => void;
@@ -1,5 +1,5 @@
1
1
  //#region src/use/token/propMap.d.ts
2
- declare const propMap: Map<string, string[] | Set<string>>;
2
+ declare const propMap: Map<string, Set<string> | string[]>;
3
3
  declare const getTokenGroupsForProp: (prop: string) => string[];
4
4
  declare const getTokenGroupForProp: (prop: string) => string;
5
5
  declare const setTokenPropGroups: (groups: Record<string, string[]>) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boss-css",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "description": "Polymorphic, usage-driven CSS-in-JS.",
5
5
  "bin": {
6
6
  "boss": "./dist/cli/index.cjs",