@salty-css/core 0.0.1-alpha.30 → 0.0.1-alpha.301

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.
Files changed (118) hide show
  1. package/.saltyrc.schema.json +48 -0
  2. package/README.md +469 -26
  3. package/bin/index.cjs +3 -1
  4. package/bin/index.js +2 -2
  5. package/bin/main.cjs +445 -8
  6. package/bin/main.js +424 -121
  7. package/cache/resolve-dynamic-config-cache.cjs +13 -0
  8. package/cache/resolve-dynamic-config-cache.d.ts +1 -0
  9. package/cache/resolve-dynamic-config-cache.js +13 -0
  10. package/compiler/get-files.d.ts +3 -0
  11. package/compiler/get-function-range.d.ts +1 -0
  12. package/compiler/helpers.d.ts +2 -0
  13. package/compiler/index.cjs +774 -11
  14. package/compiler/index.d.ts +22 -11
  15. package/compiler/index.js +735 -153
  16. package/config/define-config.d.ts +1 -1
  17. package/config/index.cjs +16 -1
  18. package/config/index.d.ts +2 -1
  19. package/config/index.js +14 -2
  20. package/css/index.cjs +12 -1
  21. package/css/index.d.ts +4 -1
  22. package/css/index.js +10 -2
  23. package/css/keyframes.cjs +49 -0
  24. package/css/keyframes.d.ts +22 -0
  25. package/css/keyframes.js +49 -0
  26. package/css/media.cjs +93 -0
  27. package/css/media.d.ts +87 -0
  28. package/css/media.js +93 -0
  29. package/css/merge.cjs +15 -0
  30. package/css/merge.d.ts +7 -0
  31. package/css/merge.js +15 -0
  32. package/css/token.cjs +4 -0
  33. package/css/token.d.ts +1 -0
  34. package/css/token.js +4 -0
  35. package/dash-case-Cz8wwE9a.cjs +32 -0
  36. package/dash-case-NMk0mXyT.js +33 -0
  37. package/define-templates-CVhhgPnd.js +60 -0
  38. package/define-templates-Deq1aCbN.cjs +59 -0
  39. package/factories/define-global-styles.d.ts +7 -0
  40. package/factories/define-media-query.d.ts +8 -0
  41. package/factories/define-templates.d.ts +27 -0
  42. package/factories/define-variables.d.ts +12 -0
  43. package/factories/index.cjs +37 -0
  44. package/factories/index.d.ts +4 -0
  45. package/factories/index.js +37 -0
  46. package/generators/class-name-generator.d.ts +6 -0
  47. package/generators/index.cjs +121 -0
  48. package/generators/index.d.ts +2 -0
  49. package/generators/index.js +121 -0
  50. package/generators/styled-generator.d.ts +20 -0
  51. package/generators/styles-generator.d.ts +22 -0
  52. package/helpers/color.d.ts +18 -0
  53. package/helpers/index.cjs +53 -0
  54. package/helpers/index.d.ts +2 -0
  55. package/helpers/index.js +53 -0
  56. package/helpers/viewport-clamp.d.ts +9 -0
  57. package/helpers-DM2fbDDz.js +18 -0
  58. package/helpers-wv74jTRI.cjs +18 -0
  59. package/index-ByR0nfaf.cjs +4 -0
  60. package/index-DKz1QXqs.js +4 -0
  61. package/package.json +54 -6
  62. package/parse-styles-CqBQc3eQ.js +232 -0
  63. package/parse-styles-D-p_guRO.cjs +231 -0
  64. package/parsers/index.cjs +57 -0
  65. package/parsers/index.d.ts +5 -0
  66. package/parsers/index.js +58 -0
  67. package/parsers/parse-modifiers.d.ts +3 -0
  68. package/parsers/parse-styles.d.ts +13 -0
  69. package/parsers/parse-templates.d.ts +4 -0
  70. package/parsers/parse-tokens.d.ts +3 -0
  71. package/parsers/parser-types.d.ts +8 -0
  72. package/parsers/property-name-check.d.ts +1 -0
  73. package/parsers/unit-check.d.ts +7 -0
  74. package/pascal-case-By_l58S-.cjs +7 -0
  75. package/pascal-case-F3Usi5Wf.js +8 -0
  76. package/{react-styled-file-CGVf5n1B.js → react-styled-file-B99mwk0w.js} +2 -2
  77. package/react-styled-file-U02jek-B.cjs +11 -0
  78. package/react-vanilla-file-Bj6XC8GS.cjs +18 -0
  79. package/react-vanilla-file-D9px70iK.js +18 -0
  80. package/salty.config-DjosWdPw.js +4 -0
  81. package/salty.config-cqavVm2t.cjs +4 -0
  82. package/server/index.cjs +4 -0
  83. package/server/index.d.ts +1 -0
  84. package/server/index.js +4 -0
  85. package/server/should-restart.d.ts +1 -0
  86. package/should-restart-5jI-bzz0.js +18 -0
  87. package/should-restart-DoaGoD5T.cjs +17 -0
  88. package/templates/salty-reset.d.ts +2 -0
  89. package/types/cli-types.d.ts +10 -0
  90. package/types/config-types.d.ts +85 -0
  91. package/types/index.d.ts +57 -23
  92. package/util/dot-case.d.ts +1 -0
  93. package/util/index.cjs +13 -1
  94. package/util/index.js +10 -8
  95. package/util/module-type.d.ts +1 -0
  96. package/viewport-clamp-CEmzmcSj.cjs +10 -0
  97. package/viewport-clamp-K553uXu3.js +11 -0
  98. package/config/config-types.d.ts +0 -59
  99. package/dash-case-DKzpenwY.cjs +0 -1
  100. package/dash-case-DMQMcCO6.js +0 -19
  101. package/generator/index.cjs +0 -1
  102. package/generator/index.d.ts +0 -1
  103. package/generator/index.js +0 -61
  104. package/generator/parse-modifiers.d.ts +0 -3
  105. package/generator/parse-styles.d.ts +0 -2
  106. package/generator/parse-templates.d.ts +0 -2
  107. package/generator/parse-tokens.d.ts +0 -2
  108. package/generator/parser-types.d.ts +0 -4
  109. package/generator/style-generator.d.ts +0 -28
  110. package/index-84Wroia-.cjs +0 -1
  111. package/index-D_732b92.js +0 -4
  112. package/parse-templates-D4p3pgQR.js +0 -92
  113. package/parse-templates-W0YfTmOT.cjs +0 -8
  114. package/pascal-case-BQpR5PdN.js +0 -6
  115. package/pascal-case-iWoaJWwT.cjs +0 -1
  116. package/react-styled-file-Dkubsz-U.cjs +0 -8
  117. package/salty.config-BupieCfE.cjs +0 -6
  118. package/salty.config-D9ANEDiH.js +0 -9
package/bin/main.js CHANGED
@@ -1,141 +1,444 @@
1
- import { Command as T } from "commander";
2
- import { mkdir as _, readFile as m, writeFile as y } from "fs/promises";
3
- import { join as o, relative as z, parse as W, format as B } from "path";
4
- import { render as G } from "ejs";
5
- import { generateCss as R } from "../compiler/index.js";
6
- import { p as M } from "../pascal-case-BQpR5PdN.js";
7
- import { createLogger as U, format as N, transports as V } from "winston";
8
- import { existsSync as q } from "fs";
9
- import { exec as K } from "child_process";
10
- import Q from "ora";
11
- const n = U({
12
- level: "debug",
13
- format: N.combine(N.colorize(), N.cli()),
14
- transports: [new V.Console({})]
15
- }), $ = (e) => {
16
- n.error(e);
17
- }, L = (e) => new Promise((c, g) => {
18
- K(e, (w) => {
19
- if (w) return g(w);
20
- c();
1
+ import { Command } from "commander";
2
+ import { existsSync, watch } from "fs";
3
+ import { mkdir, readFile, writeFile } from "fs/promises";
4
+ import { join, relative, parse, format } from "path";
5
+ import { render } from "ejs";
6
+ import { l as logger, a as logError, generateCss, isSaltyFile, generateFile } from "../compiler/index.js";
7
+ import { p as pascalCase } from "../pascal-case-F3Usi5Wf.js";
8
+ import { exec } from "child_process";
9
+ import ora from "ora";
10
+ import { c as checkShouldRestart } from "../should-restart-5jI-bzz0.js";
11
+ const execAsync = (command) => {
12
+ return new Promise((resolve, reject) => {
13
+ exec(command, (error) => {
14
+ if (error) return reject(error);
15
+ resolve();
16
+ });
21
17
  });
22
- }), A = async (...e) => {
23
- const c = e.map((I) => I.replace("-D", "").split("@").slice(0, -1).join("@").trim()).join(", "), g = Q(`Installing packages: ${c}`).start(), w = e.join(" ");
24
- await L(`npm install ${w}`), g.succeed(`Installed packages: ${c}`);
25
- }, X = () => q(o(process.cwd(), "node_modules", ".bin", "prettier"));
26
- async function b(e) {
18
+ };
19
+ const npmInstall = async (...packages) => {
20
+ const packageNames = packages.map((p) => p.replace("-D", "").split("@").slice(0, -1).join("@").trim()).join(", ");
21
+ const spinner = ora(`Installing packages: ${packageNames}`).start();
22
+ const asString = packages.join(" ");
23
+ await execAsync(`npm install ${asString}`);
24
+ spinner.succeed(`Installed packages: ${packageNames}`);
25
+ };
26
+ const hasPrettierInstalled = () => {
27
+ return existsSync(join(process.cwd(), "node_modules", ".bin", "prettier"));
28
+ };
29
+ async function formatWithPrettier(filePath) {
27
30
  try {
28
- if (!X()) return;
29
- await L(`./node_modules/.bin/prettier --write "${e}"`), n.info(`Formatted ${e} with Prettier`);
30
- } catch (c) {
31
- n.error(`Error formatting ${e} with Prettier:`, c);
31
+ const hasPrettier = hasPrettierInstalled();
32
+ if (!hasPrettier) return;
33
+ await execAsync(`./node_modules/.bin/prettier --write "${filePath}"`);
34
+ logger.info(`Formatted ${filePath} with Prettier`);
35
+ } catch (error) {
36
+ logger.error(`Error formatting ${filePath} with Prettier:`, error);
32
37
  }
33
38
  }
34
- async function lt() {
35
- const e = new T();
36
- e.name("salty-css").description("Salty-CSS CLI tool to help with annoying configuration tasks.");
37
- const c = {
39
+ async function main() {
40
+ const program = new Command();
41
+ program.name("salty-css").description("Salty-CSS CLI tool to help with annoying configuration tasks.");
42
+ const files = {
38
43
  // Core files
39
- "salty.config.ts": import("../salty.config-D9ANEDiH.js"),
40
- "saltygen/index.css": import("../index-D_732b92.js"),
44
+ "salty.config.ts": import("../salty.config-DjosWdPw.js"),
45
+ "saltygen/index.css": import("../index-DKz1QXqs.js"),
41
46
  // React
42
- "react/react-styled-file.ts": import("../react-styled-file-CGVf5n1B.js")
43
- }, g = async (a, s) => {
44
- const { default: l } = await c[a], u = G(l, s);
45
- return { fileName: a, content: u };
46
- }, w = async () => {
47
- const a = o(process.cwd(), ".saltyrc");
48
- return await m(a, "utf-8").then(JSON.parse).catch(() => ({}));
49
- }, I = async () => {
50
- const a = new URL("../package.json", import.meta.url);
51
- return await m(a, "utf-8").then(JSON.parse).catch(() => ({}));
52
- }, O = await (async () => (await w()).defaultProject)(), C = await I(), j = {
53
- core: `@salty-css/core@${C.version}`,
54
- react: `@salty-css/react@${C.version}`,
55
- eslintPluginCore: `@salty-css/eslint-plugin-core@${C.version}`,
56
- vite: `@salty-css/vite@${C.version}`
47
+ "react/react-styled-file.ts": import("../react-styled-file-B99mwk0w.js"),
48
+ "react/react-vanilla-file.ts": import("../react-vanilla-file-D9px70iK.js")
49
+ };
50
+ const readTemplate = async (fileName, options) => {
51
+ const { default: file } = await files[fileName];
52
+ const content = render(file, options);
53
+ return { fileName, content };
54
+ };
55
+ const readRCFile = async () => {
56
+ const rcPath = join(process.cwd(), ".saltyrc.json");
57
+ const rcContent = await readFile(rcPath, "utf-8").then(JSON.parse).catch(() => ({}));
58
+ return rcContent;
59
+ };
60
+ const defaultPackageJsonPath = join(process.cwd(), "package.json");
61
+ const readPackageJson = async (filePath = defaultPackageJsonPath) => {
62
+ const packageJsonContent = await readFile(filePath, "utf-8").then(JSON.parse).catch(() => void 0);
63
+ if (!packageJsonContent) throw "Could not read package.json file!";
64
+ return packageJsonContent;
65
+ };
66
+ const updatePackageJson = async (content, filePath = defaultPackageJsonPath) => {
67
+ if (typeof content === "object") content = JSON.stringify(content, null, 2);
68
+ await writeFile(filePath, content);
69
+ };
70
+ const readThisPackageJson = async () => {
71
+ const packageJsonPath = new URL("../package.json", import.meta.url);
72
+ return readPackageJson(packageJsonPath);
73
+ };
74
+ const getDefaultProject = async () => {
75
+ const rcContent = await readRCFile();
76
+ return rcContent.defaultProject;
77
+ };
78
+ const defaultProject = await getDefaultProject();
79
+ const currentPackageJson = await readThisPackageJson();
80
+ const packages = {
81
+ core: `@salty-css/core@${currentPackageJson.version}`,
82
+ react: `@salty-css/react@${currentPackageJson.version}`,
83
+ eslintConfigCore: `@salty-css/eslint-config-core@${currentPackageJson.version}`,
84
+ vite: `@salty-css/vite@${currentPackageJson.version}`,
85
+ next: `@salty-css/next@${currentPackageJson.version}`
86
+ };
87
+ const resolveProjectDir = (dir) => {
88
+ const dirName = dir === "." ? "" : dir;
89
+ const rootDir = process.cwd();
90
+ const projectDir = join(rootDir, dirName);
91
+ return projectDir;
57
92
  };
58
- e.command("init [directory]").description("Initialize a new Salty-CSS project.").option("-d, --dir <dir>", "Project directory to initialize the project in.").option("--css-file <css-file>", "Existing CSS file where to import the generated CSS. Path must be relative to the given project directory.").option("--skip-install", "Skip installing dependencies.").action(async function(a) {
59
- n.info("Initializing a new Salty-CSS project!");
60
- const { dir: s = a, cssFile: l, skipInstall: u } = this.opts();
61
- if (!s) return $("Project directory must be provided. Add it as the first argument after init command or use the --dir option.");
62
- u || (await A(j.core, j.react), await A(`-D ${j.eslintPluginCore}`));
63
- const h = process.cwd(), d = o(h, s), k = await Promise.all([g("salty.config.ts"), g("saltygen/index.css")]);
64
- await _(d, { recursive: !0 });
65
- const J = k.map(async ({ fileName: t, content: r }) => {
66
- const p = o(d, t);
67
- if (await m(p, "utf-8").catch(() => {
68
- }) !== void 0) {
69
- n.debug("File already exists: " + p);
93
+ program.command("init [directory]").description("Initialize a new Salty-CSS project.").option("-d, --dir <dir>", "Project directory to initialize the project in.").option("--css-file <css-file>", "Existing CSS file where to import the generated CSS. Path must be relative to the given project directory.").option("--skip-install", "Skip installing dependencies.").action(async function(_dir = ".") {
94
+ const packageJson = await readPackageJson().catch(() => void 0);
95
+ if (!packageJson) return logError("Salty CSS project must be initialized in a directory with a package.json file.");
96
+ logger.info("Initializing a new Salty-CSS project!");
97
+ const { dir = _dir, cssFile, skipInstall } = this.opts();
98
+ if (!dir) return logError("Project directory must be provided. Add it as the first argument after init command or use the --dir option.");
99
+ if (!skipInstall) await npmInstall(packages.core, packages.react);
100
+ const rootDir = process.cwd();
101
+ const projectDir = resolveProjectDir(dir);
102
+ const projectFiles = await Promise.all([readTemplate("salty.config.ts"), readTemplate("saltygen/index.css")]);
103
+ await mkdir(projectDir, { recursive: true });
104
+ const writeFiles = projectFiles.map(async ({ fileName, content }) => {
105
+ const filePath = join(projectDir, fileName);
106
+ const existingContent = await readFile(filePath, "utf-8").catch(() => void 0);
107
+ if (existingContent !== void 0) {
108
+ logger.debug("File already exists: " + filePath);
70
109
  return;
71
110
  }
72
- const E = t.split("/").slice(0, -1).join("/");
73
- E && await _(o(d, E), { recursive: !0 }), n.info("Writing file: " + p), await y(p, r), await b(p);
111
+ const additionalFolders = fileName.split("/").slice(0, -1).join("/");
112
+ if (additionalFolders) await mkdir(join(projectDir, additionalFolders), { recursive: true });
113
+ logger.info("Creating file: " + filePath);
114
+ await writeFile(filePath, content);
115
+ await formatWithPrettier(filePath);
74
116
  });
75
- await Promise.all(J);
76
- const S = z(h, d), i = o(h, ".saltyrc"), f = await m(i, "utf-8").catch(() => {
77
- });
78
- if (f === void 0) {
79
- n.info("Creating file: " + i);
80
- const r = JSON.stringify({
81
- defaultProject: S,
82
- projects: [S]
83
- }, null, 2);
84
- await y(i, r);
117
+ await Promise.all(writeFiles);
118
+ const relativeProjectPath = relative(rootDir, projectDir) || ".";
119
+ const saltyrcPath = join(rootDir, ".saltyrc.json");
120
+ const existingSaltyrc = await readFile(saltyrcPath, "utf-8").catch(() => void 0);
121
+ if (existingSaltyrc === void 0) {
122
+ logger.info("Creating file: " + saltyrcPath);
123
+ const rcContent = {
124
+ $schema: "./node_modules/@salty-css/core/.saltyrc.schema.json",
125
+ info: "This file is used to define projects and their configurations for Salty CSS cli. Do not delete, modify or add this file to .gitignore.",
126
+ defaultProject: relativeProjectPath,
127
+ projects: [
128
+ {
129
+ dir: relativeProjectPath,
130
+ framework: "react"
131
+ }
132
+ ]
133
+ };
134
+ const content = JSON.stringify(rcContent, null, 2);
135
+ await writeFile(saltyrcPath, content);
136
+ await formatWithPrettier(saltyrcPath);
85
137
  } else {
86
- n.info("Edit file: " + i);
87
- const t = JSON.parse(f), r = new Set((t == null ? void 0 : t.projects) || []);
88
- r.add(S), t.projects = [...r];
89
- const p = JSON.stringify(t, null, 2);
90
- await y(i, p);
138
+ const rcContent = JSON.parse(existingSaltyrc);
139
+ const projects = (rcContent == null ? void 0 : rcContent.projects) || [];
140
+ const projectIndex = projects.findIndex((p) => p.dir === relativeProjectPath);
141
+ if (projectIndex === -1) {
142
+ projects.push({ dir: relativeProjectPath, framework: "react" });
143
+ rcContent.projects = [...projects];
144
+ const content = JSON.stringify(rcContent, null, 2);
145
+ if (content !== existingSaltyrc) {
146
+ logger.info("Edit file: " + saltyrcPath);
147
+ await writeFile(saltyrcPath, content);
148
+ await formatWithPrettier(saltyrcPath);
149
+ }
150
+ }
91
151
  }
92
- const x = o(h, ".gitignore"), v = await m(x, "utf-8").catch(() => {
93
- });
94
- if (v !== void 0 && (v.includes("saltygen") || (n.info("Edit file: " + x), await y(x, v + `
95
-
96
- # Salty-CSS
97
- saltygen
98
- `))), l) {
99
- const t = o(d, l), r = await m(t, "utf-8").catch(() => {
100
- });
101
- if (r !== void 0 && !r.includes("saltygen")) {
102
- const F = o(t, ".."), H = `@import '${z(F, o(d, "saltygen/index.css"))}';`;
103
- n.info("Edit file: " + t), await y(t, H + `
104
- ` + r), await b(t);
152
+ const gitIgnorePath = join(rootDir, ".gitignore");
153
+ const gitIgnoreContent = await readFile(gitIgnorePath, "utf-8").catch(() => void 0);
154
+ if (gitIgnoreContent !== void 0) {
155
+ const alreadyIgnoresSaltygen = gitIgnoreContent.includes("saltygen");
156
+ if (!alreadyIgnoresSaltygen) {
157
+ logger.info("Edit file: " + gitIgnorePath);
158
+ await writeFile(gitIgnorePath, gitIgnoreContent + "\n\n# Salty-CSS\nsaltygen\n");
159
+ }
160
+ }
161
+ const cssFileFoldersToLookFor = ["src", "public", "assets", "styles", "css", "app"];
162
+ const secondLevelFolders = ["styles", "css", "app", "pages"];
163
+ const cssFilesToLookFor = ["index", "styles", "main", "app", "global", "globals"];
164
+ const cssFileExtensions = [".css", ".scss", ".sass"];
165
+ const getTargetCssFile = async () => {
166
+ if (cssFile) return cssFile;
167
+ for (const folder of cssFileFoldersToLookFor) {
168
+ for (const file of cssFilesToLookFor) {
169
+ for (const ext of cssFileExtensions) {
170
+ const filePath = join(projectDir, folder, file + ext);
171
+ const fileContent = await readFile(filePath, "utf-8").catch(() => void 0);
172
+ if (fileContent !== void 0) return relative(projectDir, filePath);
173
+ for (const secondLevelFolder of secondLevelFolders) {
174
+ const filePath2 = join(projectDir, folder, secondLevelFolder, file + ext);
175
+ const fileContent2 = await readFile(filePath2, "utf-8").catch(() => void 0);
176
+ if (fileContent2 !== void 0) return relative(projectDir, filePath2);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ return void 0;
182
+ };
183
+ const targetCSSFile = await getTargetCssFile();
184
+ if (targetCSSFile) {
185
+ const cssFilePath = join(projectDir, targetCSSFile);
186
+ const cssFileContent = await readFile(cssFilePath, "utf-8").catch(() => void 0);
187
+ if (cssFileContent !== void 0) {
188
+ const alreadyImportsSaltygen = cssFileContent.includes("saltygen");
189
+ if (!alreadyImportsSaltygen) {
190
+ const cssFileFolder = join(cssFilePath, "..");
191
+ const relativePath = relative(cssFileFolder, join(projectDir, "saltygen/index.css"));
192
+ const importStatement = `@import '${relativePath}';`;
193
+ logger.info("Adding global import statement to CSS file: " + cssFilePath);
194
+ await writeFile(cssFilePath, importStatement + "\n" + cssFileContent);
195
+ await formatWithPrettier(cssFilePath);
196
+ }
197
+ }
198
+ } else {
199
+ logger.warn("Could not find a CSS file to import the generated CSS. Please add it manually.");
200
+ }
201
+ const eslintConfigs = {
202
+ projectJs: join(projectDir, "eslint.config.js"),
203
+ rootJs: join(rootDir, "eslint.config.js"),
204
+ projectMjs: join(projectDir, "eslint.config.mjs"),
205
+ rootMjs: join(rootDir, "eslint.config.mjs"),
206
+ projectJson: join(projectDir, ".eslintrc.json"),
207
+ rootJson: join(rootDir, ".eslintrc.json")
208
+ };
209
+ const eslintConfigToUse = Object.values(eslintConfigs).find((path) => existsSync(path));
210
+ if (eslintConfigToUse) {
211
+ if (!skipInstall) await npmInstall(packages.eslintConfigCore);
212
+ const eslintConfigContent = await readFile(eslintConfigToUse, "utf-8").catch(() => void 0);
213
+ if (!eslintConfigContent) return logError("Could not read ESLint config file.");
214
+ const alreadyHasSaltyConfig = eslintConfigContent.includes("salty-css");
215
+ if (!alreadyHasSaltyConfig) {
216
+ logger.info("Edit file: " + eslintConfigToUse);
217
+ if (eslintConfigToUse.endsWith("js")) {
218
+ const importStatement = 'import saltyCss from "@salty-css/eslint-config-core/flat";';
219
+ let newContent = `${importStatement}
220
+ ${eslintConfigContent}`;
221
+ const isTsEslint = eslintConfigContent.includes("typescript-eslint");
222
+ if (isTsEslint) {
223
+ if (newContent.includes(".config(")) newContent = newContent.replace(".config(", ".config(saltyCss,");
224
+ else logger.warn("Could not find the correct place to add the Salty-CSS config for ESLint. Please add it manually.");
225
+ } else {
226
+ if (newContent.includes("export default [")) newContent = newContent.replace("export default [", "export default [ saltyCss,");
227
+ else if (newContent.includes("eslintConfig = [")) newContent = newContent.replace("eslintConfig = [", "eslintConfig = [ saltyCss,");
228
+ else logger.warn("Could not find the correct place to add the Salty-CSS config for ESLint. Please add it manually.");
229
+ }
230
+ await writeFile(eslintConfigToUse, newContent);
231
+ await formatWithPrettier(eslintConfigToUse);
232
+ } else {
233
+ const eslintConfigJson = JSON.parse(eslintConfigContent);
234
+ if (!eslintConfigJson.extends) eslintConfigJson.extends = [];
235
+ eslintConfigJson.extends.push("@salty-css/core");
236
+ const modifiedEslintConfigContent = JSON.stringify(eslintConfigJson, null, 2);
237
+ await writeFile(eslintConfigToUse, modifiedEslintConfigContent);
238
+ await formatWithPrettier(eslintConfigToUse);
239
+ }
240
+ }
241
+ }
242
+ const viteConfigPath = join(projectDir, "vite.config.ts");
243
+ const viteConfigContent = await readFile(viteConfigPath, "utf-8").catch(() => void 0);
244
+ if (viteConfigContent !== void 0) {
245
+ const alreadyHasPlugin = viteConfigContent.includes("saltyPlugin");
246
+ if (!alreadyHasPlugin) {
247
+ logger.info("Edit file: " + viteConfigPath);
248
+ const pluginImport = "import { saltyPlugin } from '@salty-css/vite';\n";
249
+ const pluginConfig = "saltyPlugin(__dirname),";
250
+ const newContent = viteConfigContent.replace(/(plugins: \[)/, `$1
251
+ ${pluginConfig}`);
252
+ if (!skipInstall) await npmInstall(`-D ${packages.vite}`);
253
+ logger.info("Adding Salty-CSS plugin to Vite config...");
254
+ await writeFile(viteConfigPath, pluginImport + newContent);
255
+ await formatWithPrettier(viteConfigPath);
105
256
  }
106
257
  }
107
- const P = o(d, "vite.config.ts"), D = await m(P, "utf-8").catch(() => {
258
+ const nextConfigFiles = ["next.config.js", "next.config.cjs", "next.config.ts", "next.config.mjs"];
259
+ const nextConfigPath = nextConfigFiles.map((file) => join(projectDir, file)).find((path) => existsSync(path));
260
+ if (nextConfigPath) {
261
+ let nextConfigContent = await readFile(nextConfigPath, "utf-8").catch(() => void 0);
262
+ if (nextConfigContent !== void 0) {
263
+ const alreadyHasPlugin = nextConfigContent.includes("withSaltyCss");
264
+ if (!alreadyHasPlugin) {
265
+ let saltyCssAppended = false;
266
+ const hasPluginsArray = /\splugins([^=]*)=[^[]\[/.test(nextConfigContent);
267
+ if (hasPluginsArray && !saltyCssAppended) {
268
+ nextConfigContent = nextConfigContent.replace(/\splugins([^=]*)=[^[]\[/, (_, config) => {
269
+ return ` plugins${config}= [withSaltyCss,`;
270
+ });
271
+ saltyCssAppended = true;
272
+ }
273
+ const useRequire = nextConfigContent.includes("module.exports");
274
+ const pluginImport = useRequire ? "const { withSaltyCss } = require('@salty-css/next');\n" : "import { withSaltyCss } from '@salty-css/next';\n";
275
+ if (useRequire && !saltyCssAppended) {
276
+ nextConfigContent = nextConfigContent.replace(/module.exports = ([^;]+)/, (_, config) => {
277
+ return `module.exports = withSaltyCss(${config})`;
278
+ });
279
+ saltyCssAppended = true;
280
+ } else if (!saltyCssAppended) {
281
+ nextConfigContent = nextConfigContent.replace(/export default ([^;]+)/, (_, config) => {
282
+ return `export default withSaltyCss(${config})`;
283
+ });
284
+ }
285
+ if (!skipInstall) await npmInstall(`-D ${packages.next}`);
286
+ logger.info("Adding Salty-CSS plugin to Next.js config...");
287
+ await writeFile(nextConfigPath, pluginImport + nextConfigContent);
288
+ await formatWithPrettier(nextConfigPath);
289
+ }
290
+ }
291
+ }
292
+ const packageJsonContent = await readPackageJson().catch(() => logError("Could not read package.json file.")).then((content) => {
293
+ if (!content.scripts) content.scripts = {};
294
+ if (content.scripts.prepare) {
295
+ const alreadyHasSaltyCss = content.scripts.prepare.includes("salty-css");
296
+ if (!alreadyHasSaltyCss) {
297
+ logger.info("Edit file: " + defaultPackageJsonPath);
298
+ content.scripts.prepare = content.scripts.prepare + " && npx salty-css build";
299
+ }
300
+ } else {
301
+ logger.info("Edit file: " + defaultPackageJsonPath);
302
+ content.scripts.prepare = "npx salty-css build";
303
+ }
304
+ return content;
108
305
  });
109
- if (D !== void 0 && !D.includes("saltyPlugin")) {
110
- n.info("Edit file: " + P);
111
- const r = `import { saltyPlugin } from '@salty-css/vite';
112
- `, F = D.replace(/(plugins: \[)/, `$1
113
- saltyPlugin(__dirname),`);
114
- n.info("Installing @salty-css/vite"), u || await A(`-D ${j.vite}`), n.info("Adding Salty-CSS plugin to Vite config..."), await y(P, r + F), await b(P);
115
- }
116
- }), e.command("build [directory]").alias("b").description("Build the Salty-CSS project.").option("-d, --dir <dir>", "Project directory to build the project in.").action(async function(a = O) {
117
- n.info("Building the Salty-CSS project...");
118
- const { dir: s = a } = this.opts();
119
- if (!s) return $("Project directory must be provided. Add it as the first argument after build command or use the --dir option.");
120
- const l = o(process.cwd(), s);
121
- await R(l);
122
- }), e.command("generate [file] [directory]").alias("g").description("Generate a new component file.").option("-f, --file <file>", "File to generate.").option("-d, --dir <dir>", "Project directory to generate the file in.").option("-t, --tag <tag>", "HTML tag of the component.", "div").option("-n, --name <name>", "Name of the component.").option("-c, --className <className>", "CSS class of the component.").action(async function(a, s = O) {
123
- const { file: l = a, dir: u = s, tag: h, name: d, className: k } = this.opts();
124
- if (!l) return $("File to generate must be provided. Add it as the first argument after generate command or use the --file option.");
125
- if (!u) return $("Project directory must be provided. Add it as the second argument after generate command or use the --dir option.");
126
- const J = o(process.cwd(), u), S = o(J, l), i = W(S);
127
- i.ext || (i.ext = ".ts"), i.name.endsWith(".css") || (i.name = i.name + ".css"), i.base = i.name + i.ext;
128
- const f = B(i);
129
- if (await m(f, "utf-8").catch(() => {
130
- }) !== void 0) {
131
- n.error("File already exists:", f);
306
+ await updatePackageJson(packageJsonContent);
307
+ logger.info("Running the build to generate initial CSS...");
308
+ await generateCss(projectDir);
309
+ logger.info("🎉 Salty CSS project initialized successfully!");
310
+ logger.info("Next steps:");
311
+ logger.info("1. Configure variables and templates in `salty.config.ts`");
312
+ logger.info("2. Create a new component with `npx salty-css generate [component-name]`");
313
+ logger.info("3. Run `npx salty-css build` to generate the CSS");
314
+ logger.info("4. Read about the features in the documentation: https://salty-css.dev");
315
+ logger.info("5. Star the project on GitHub: https://github.com/margarita-form/salty-css ⭐");
316
+ });
317
+ program.command("build [directory]").alias("b").description("Build the Salty-CSS project.").option("-d, --dir <dir>", "Project directory to build the project in.").option("--watch", "Watch for changes and rebuild the project.").action(async function(_dir = defaultProject) {
318
+ logger.info("Building the Salty-CSS project...");
319
+ const { dir = _dir, watch: watch$1 } = this.opts();
320
+ if (!dir) return logError("Project directory must be provided. Add it as the first argument after build command or use the --dir option.");
321
+ const projectDir = resolveProjectDir(dir);
322
+ await generateCss(projectDir);
323
+ if (watch$1) {
324
+ logger.info("Watching for changes in the project directory...");
325
+ watch(projectDir, { recursive: true }, async (event, filePath) => {
326
+ const shouldRestart = await checkShouldRestart(filePath);
327
+ if (shouldRestart) {
328
+ await generateCss(projectDir, false, false);
329
+ } else {
330
+ const saltyFile = isSaltyFile(filePath);
331
+ if (saltyFile) await generateFile(projectDir, filePath);
332
+ }
333
+ });
334
+ }
335
+ });
336
+ program.command("generate [file] [directory]").alias("g").description("Generate a new component file.").option("-f, --file <file>", "File to generate.").option("-d, --dir <dir>", "Project directory to generate the file in.").option("-t, --tag <tag>", "HTML tag of the component.", "div").option("-n, --name <name>", "Name of the component.").option("-c, --className <className>", "CSS class of the component.").option("-r, --reactComponent", "Generate a React component as well.").action(async function(_file, _dir = defaultProject) {
337
+ const { file = _file, dir = _dir, tag, name, className, reactComponent = false } = this.opts();
338
+ if (!file) return logError("File to generate must be provided. Add it as the first argument after generate command or use the --file option.");
339
+ if (!dir) return logError("Project directory must be provided. Add it as the second argument after generate command or use the --dir option.");
340
+ const projectDir = resolveProjectDir(dir);
341
+ const additionalFolders = file.split("/").slice(0, -1).join("/");
342
+ if (additionalFolders) await mkdir(join(projectDir, additionalFolders), { recursive: true });
343
+ const filePath = join(projectDir, file);
344
+ const parsedFilePath = parse(filePath);
345
+ if (!parsedFilePath.ext) {
346
+ parsedFilePath.ext = ".ts";
347
+ }
348
+ if (!parsedFilePath.name.endsWith(".css")) {
349
+ parsedFilePath.name = parsedFilePath.name + ".css";
350
+ }
351
+ parsedFilePath.base = parsedFilePath.name + parsedFilePath.ext;
352
+ const formattedStyledFilePath = format(parsedFilePath);
353
+ const alreadyExists = await readFile(formattedStyledFilePath, "utf-8").catch(() => void 0);
354
+ if (alreadyExists !== void 0) {
355
+ logger.error("File already exists:", formattedStyledFilePath);
132
356
  return;
133
357
  }
134
- n.info("Generating a new file: " + f);
135
- const v = M(d || i.base.replace(/\.css\.\w+$/, "")), { content: P } = await g("react/react-styled-file.ts", { tag: h, name: v, className: k });
136
- await y(f, P), await b(f);
137
- }), e.parseAsync(process.argv);
358
+ let styledComponentName = pascalCase(name || parsedFilePath.base.replace(/\.css\.\w+$/, ""));
359
+ if (reactComponent) {
360
+ const componentName = styledComponentName + "Component";
361
+ styledComponentName = styledComponentName + "Wrapper";
362
+ const fileName = parsedFilePath.base.replace(/\.css\.\w+$/, "");
363
+ const { content: reactContent } = await readTemplate("react/react-vanilla-file.ts", { tag, componentName, styledComponentName, className, fileName });
364
+ parsedFilePath.name = fileName.replace(/\.css$/, "");
365
+ parsedFilePath.ext = ".tsx";
366
+ parsedFilePath.base = parsedFilePath.name + parsedFilePath.ext;
367
+ const formattedReactFilePath = format(parsedFilePath);
368
+ logger.info("Generating a new file: " + formattedReactFilePath);
369
+ await writeFile(formattedReactFilePath, reactContent);
370
+ await formatWithPrettier(formattedReactFilePath);
371
+ }
372
+ const { content } = await readTemplate("react/react-styled-file.ts", { tag, name: styledComponentName, className });
373
+ logger.info("Generating a new file: " + formattedStyledFilePath);
374
+ await writeFile(formattedStyledFilePath, content);
375
+ await formatWithPrettier(formattedStyledFilePath);
376
+ });
377
+ const getSaltyCssPackages = async () => {
378
+ const packageJSONPath = join(process.cwd(), "package.json");
379
+ const packageJson = await readPackageJson(packageJSONPath).catch((err) => logError(err));
380
+ if (!packageJson) return logError("Could not read package.json file.");
381
+ const allDependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
382
+ const saltyCssPackages = Object.entries(allDependencies).filter(([name]) => name === "salty-css" || name.startsWith("@salty-css/"));
383
+ if (!saltyCssPackages.length) {
384
+ return logError(
385
+ "No Salty-CSS packages found in package.json. Make sure you are running update command in the same directory! Used package.json path: " + packageJSONPath
386
+ );
387
+ }
388
+ return saltyCssPackages;
389
+ };
390
+ program.command("update [version]").alias("up").description("Update Salty-CSS packages to the latest or specified version.").option("-v, --version <version>", "Version to update to.").option("--legacy-peer-deps <legacyPeerDeps>", "Use legacy peer dependencies (not recommended).", false).action(async function(_version = "latest") {
391
+ const { legacyPeerDeps, version = _version } = this.opts();
392
+ const saltyCssPackages = await getSaltyCssPackages();
393
+ if (!saltyCssPackages) return logError("Could not update Salty-CSS packages as any were found in package.json.");
394
+ const packagesToUpdate = saltyCssPackages.map(([name]) => {
395
+ if (version === "@") return `${name}@${currentPackageJson.version}`;
396
+ return `${name}@${version.replace(/^@/, "")}`;
397
+ });
398
+ if (legacyPeerDeps) {
399
+ logger.warn("Using legacy peer dependencies to update packages.");
400
+ await npmInstall(...packagesToUpdate, "--legacy-peer-deps");
401
+ } else {
402
+ await npmInstall(...packagesToUpdate);
403
+ }
404
+ const updatedPackages = await getSaltyCssPackages();
405
+ if (!updatedPackages) return logError("Something went wrong while reading the updated packages.");
406
+ const mappedByVersions = updatedPackages.reduce((acc, [name, version2]) => {
407
+ if (!acc[version2]) acc[version2] = [];
408
+ acc[version2].push(name);
409
+ return acc;
410
+ }, {});
411
+ const versionsCount = Object.keys(mappedByVersions).length;
412
+ if (versionsCount === 1) {
413
+ const version2 = Object.keys(mappedByVersions)[0];
414
+ const versionString = version2.replace(/^\^/, "");
415
+ logger.info(`Updated to all Salty CSS packages successfully to ${versionString}`);
416
+ } else {
417
+ for (const [version2, names] of Object.entries(mappedByVersions)) {
418
+ const versionString = version2.replace(/^\^/, "");
419
+ logger.info(`Updated to ${versionString}: ${names.join(", ")}`);
420
+ }
421
+ }
422
+ });
423
+ program.option("-v, --version", "Show the current version of Salty-CSS.").action(async function() {
424
+ const currentPackageJson2 = await readThisPackageJson();
425
+ logger.info("CLI is running: " + currentPackageJson2.version);
426
+ const packageJSONPath = join(process.cwd(), "package.json");
427
+ const packageJson = await readPackageJson(packageJSONPath).catch((err) => logError(err));
428
+ if (!packageJson) return;
429
+ const allDependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
430
+ const saltyCssPackages = Object.keys(allDependencies).filter((dep) => dep === "salty-css" || dep.startsWith("@salty-css/"));
431
+ if (!saltyCssPackages.length) {
432
+ return logError(
433
+ "No Salty-CSS packages found in package.json. Make sure you are running update command in the same directory! Used package.json path: " + packageJSONPath
434
+ );
435
+ }
436
+ for (const dep of saltyCssPackages) {
437
+ logger.info(`${dep}: ${allDependencies[dep]}`);
438
+ }
439
+ });
440
+ program.parseAsync(process.argv);
138
441
  }
139
442
  export {
140
- lt as main
443
+ main
141
444
  };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const promises = require("fs/promises");
4
+ const path = require("path");
5
+ const helpers = require("../helpers-wv74jTRI.cjs");
6
+ const resolveDynamicConfigCache = async () => {
7
+ const corePackageRoot = helpers.getCorePackageRoot();
8
+ const coreConfigDest = path.join(corePackageRoot, "cache/config-cache.json");
9
+ const contents = await promises.readFile(coreConfigDest, "utf8");
10
+ if (!contents) throw new Error("Could not find config cache file");
11
+ return JSON.parse(contents);
12
+ };
13
+ exports.resolveDynamicConfigCache = resolveDynamicConfigCache;
@@ -0,0 +1 @@
1
+ export declare const resolveDynamicConfigCache: () => Promise<any>;
@@ -0,0 +1,13 @@
1
+ import { readFile } from "fs/promises";
2
+ import { join } from "path";
3
+ import { g as getCorePackageRoot } from "../helpers-DM2fbDDz.js";
4
+ const resolveDynamicConfigCache = async () => {
5
+ const corePackageRoot = getCorePackageRoot();
6
+ const coreConfigDest = join(corePackageRoot, "cache/config-cache.json");
7
+ const contents = await readFile(coreConfigDest, "utf8");
8
+ if (!contents) throw new Error("Could not find config cache file");
9
+ return JSON.parse(contents);
10
+ };
11
+ export {
12
+ resolveDynamicConfigCache
13
+ };
@@ -0,0 +1,3 @@
1
+ export declare const getSaltyRcPath: (dirname: string) => string;
2
+ export declare const getPackageJsonPath: (dirname: string) => string;
3
+ export declare const getPackageJson: (dirname: string) => Promise<any>;
@@ -0,0 +1 @@
1
+ export declare const getFunctionRange: (contents: string, name: string) => Promise<[number, number]>;
@@ -0,0 +1,2 @@
1
+ export declare const getCorePackageRoot: () => string;
2
+ export declare const resolveExportValue: <T>(value: unknown, maxLevel?: number, _level?: number) => Promise<T>;