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