@salty-css/core 0.1.0-alpha.2 → 0.1.0-alpha.20

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 (63) hide show
  1. package/astro-component-5hrNTCJ5.js +4 -0
  2. package/astro-component-Dj3enX6K.cjs +4 -0
  3. package/bin/commands/build.d.ts +2 -0
  4. package/bin/commands/generate.d.ts +2 -0
  5. package/bin/commands/init.d.ts +2 -0
  6. package/bin/commands/update.d.ts +2 -0
  7. package/bin/commands/version.d.ts +2 -0
  8. package/bin/confirm-install.d.ts +34 -0
  9. package/bin/context.d.ts +22 -0
  10. package/bin/detection/css-file.d.ts +5 -0
  11. package/bin/frameworks/astro.d.ts +4 -0
  12. package/bin/frameworks/index.d.ts +13 -0
  13. package/bin/frameworks/react.d.ts +2 -0
  14. package/bin/frameworks/types.d.ts +27 -0
  15. package/bin/integrations/astro.d.ts +11 -0
  16. package/bin/integrations/eslint.d.ts +6 -0
  17. package/bin/integrations/index.d.ts +21 -0
  18. package/bin/integrations/next.d.ts +9 -0
  19. package/bin/integrations/types.d.ts +29 -0
  20. package/bin/integrations/vite.d.ts +8 -0
  21. package/bin/main.cjs +653 -336
  22. package/bin/main.d.ts +8 -0
  23. package/bin/main.js +653 -336
  24. package/bin/package-json.d.ts +21 -0
  25. package/bin/saltyrc.d.ts +31 -0
  26. package/bin/templates.d.ts +14 -0
  27. package/{class-name-generator-YeSQe_Ik.js → class-name-generator-BKMSRP7N.js} +1 -1
  28. package/{class-name-generator-B2Pb2obX.cjs → class-name-generator-CYgwnxnZ.cjs} +1 -1
  29. package/compiler/salty-compiler.cjs +7 -4
  30. package/compiler/salty-compiler.d.ts +6 -1
  31. package/compiler/salty-compiler.js +7 -4
  32. package/css/dynamic-styles.cjs +15 -0
  33. package/css/dynamic-styles.d.ts +10 -0
  34. package/css/dynamic-styles.js +15 -0
  35. package/css/index.cjs +3 -0
  36. package/css/index.d.ts +1 -0
  37. package/css/index.js +3 -0
  38. package/css/keyframes.cjs +1 -1
  39. package/css/keyframes.js +1 -1
  40. package/generators/index.cjs +1 -1
  41. package/generators/index.js +2 -2
  42. package/instances/classname-instance.cjs +1 -1
  43. package/instances/classname-instance.js +1 -1
  44. package/package.json +5 -1
  45. package/{parse-styles-CA3TP5n1.cjs → parse-styles-DWQ4UQCp.cjs} +105 -7
  46. package/{parse-styles-BTIoYnBr.js → parse-styles-g4NPgqhh.js} +106 -8
  47. package/parsers/index.cjs +2 -1
  48. package/parsers/index.d.ts +1 -0
  49. package/parsers/index.js +4 -3
  50. package/parsers/parser-regexes.d.ts +3 -0
  51. package/parsers/strict.d.ts +2 -0
  52. package/runtime/index.cjs +1 -1
  53. package/runtime/index.js +1 -1
  54. package/{salty.config-cqavVm2t.cjs → salty.config-DogY_sSQ.cjs} +1 -1
  55. package/salty.config-GV37Q-D2.js +4 -0
  56. package/styled-file-BzmB9_Ez.cjs +12 -0
  57. package/{react-styled-file-U02jek-B.cjs → styled-file-CPd_rTW2.cjs} +2 -2
  58. package/{react-styled-file-B99mwk0w.js → styled-file-Cda3EeR6.js} +2 -2
  59. package/styled-file-DLcgYmGN.js +12 -0
  60. package/types/config-types.d.ts +9 -0
  61. package/{react-vanilla-file-D9px70iK.js → vanilla-file-1kOqbCIM.js} +2 -2
  62. package/{react-vanilla-file-Bj6XC8GS.cjs → vanilla-file-r0fp2q_m.cjs} +2 -2
  63. package/salty.config-DjosWdPw.js +0 -4
@@ -20,7 +20,7 @@ const parseValueTokens = (tokenNames) => (value) => {
20
20
  const hasToken = /\{[^{}]+\}/g.test(value);
21
21
  if (!hasToken) return void 0;
22
22
  const transformed = value.replace(/\{([^{}]+)\}/g, (...args) => {
23
- const variable = dashCase(args[1].replaceAll(".", "-"));
23
+ const variable = dashCase(args[1].trim().replaceAll(".", "-"));
24
24
  if (tokenNames && !tokenNames.includes(variable)) console.warn(`Token ${variable} might not exist`);
25
25
  if (variable.startsWith("-")) return `-${variable}`;
26
26
  return `var(--${variable})`;
@@ -74,22 +74,44 @@ const addUnit = (key, value, config) => {
74
74
  return `${value}`;
75
75
  };
76
76
  const vendorPrefixes = ["Webkit", "Moz", "ms", "O"];
77
+ const isVendorPrefixed = (key) => {
78
+ return vendorPrefixes.some((prefix) => {
79
+ if (!key.startsWith(prefix)) return false;
80
+ const next = key.charAt(prefix.length);
81
+ return next >= "A" && next <= "Z";
82
+ });
83
+ };
77
84
  const propertyNameCheck = (key) => {
78
85
  if (key.startsWith("-")) return key;
79
- if (vendorPrefixes.some((prefix) => key.startsWith(prefix))) return `-${dashCase(key)}`;
86
+ if (isVendorPrefixed(key)) return `-${dashCase(key)}`;
80
87
  return dashCase(key);
81
88
  };
89
+ const reportParserIssue = (strict, message) => {
90
+ if (strict === true) throw new Error(`[salty-css] ${message}`);
91
+ if (strict === "warn") console.warn(`[salty-css] ${message}`);
92
+ };
93
+ const pseudoTypoRegex = /^&(hover|focus(-(visible|within))?|active|visited|checked|disabled|enabled|empty|target|first-child|last-child|first-of-type|last-of-type|placeholder|placeholder-shown|root)\b/;
94
+ const templateLiteralLeftoverRegex = /\$\{[^}]+\}/;
95
+ const bareAtRuleRegex = /^@(media|supports|container|layer)\s*$/;
82
96
  const parseStyles = async (styles, currentScope = "", config, omitTemplates = false) => {
83
97
  if (!styles) throw new Error("No styles provided to parseStyles function!");
84
98
  const cssStyles = /* @__PURE__ */ new Set();
85
99
  const entries = Object.entries(styles);
100
+ const strict = config == null ? void 0 : config.strict;
86
101
  const processStyleEntry = async ([key, value]) => {
87
102
  var _a, _b;
88
103
  const _key = key.trim().replace(/^\?+/g, "");
89
104
  const propertyName = propertyNameCheck(_key);
90
105
  const toString = (val, eol = ";") => `${propertyName}:${val}${eol}`;
91
106
  const context = { scope: currentScope, config };
92
- if (typeof value === "function") return processStyleEntry([key, value(context)]);
107
+ if (typeof value === "function") {
108
+ try {
109
+ return await processStyleEntry([key, value(context)]);
110
+ } catch (error) {
111
+ reportParserIssue(strict, `Function value for "${_key}" threw: ${(error == null ? void 0 : error.message) ?? error}`);
112
+ return void 0;
113
+ }
114
+ }
93
115
  if (value instanceof Promise) return processStyleEntry([key, await value]);
94
116
  if ((config == null ? void 0 : config.templates) && ((_a = config.templatePaths) == null ? void 0 : _a[_key])) {
95
117
  try {
@@ -123,6 +145,10 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
123
145
  console.warn(`Template "${_key}" with path of "${value}" was not found in config!`);
124
146
  return void 0;
125
147
  }
148
+ if (Array.isArray(value)) {
149
+ if (value.length === 0) return void 0;
150
+ return processStyleEntry([key, value.join(", ")]);
151
+ }
126
152
  if (typeof value === "object") {
127
153
  if (!value) return void 0;
128
154
  if (value.isColor) return toString(value.toString());
@@ -159,31 +185,62 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
159
185
  return `.${prop}-${val}`;
160
186
  });
161
187
  const scope2 = `${currentScope}:where(${scopes.join(", ")})`;
162
- console.log(`Union variant scope: ${scope2}`);
163
188
  const results2 = await parseStyles(css2, scope2, config);
164
189
  results2.forEach((res) => cssStyles.add(res));
165
190
  }
166
191
  return void 0;
167
192
  }
168
193
  if (_key.startsWith("@")) {
194
+ if (bareAtRuleRegex.test(_key)) reportParserIssue(strict, `At-rule "${_key}" is missing its condition (e.g. "@media (min-width: 600px)").`);
169
195
  const mediaQuery = ((_b = config == null ? void 0 : config.mediaQueries) == null ? void 0 : _b[_key]) || _key;
170
196
  const results2 = await parseAndJoinStyles(value, currentScope, config);
171
197
  const query = `${mediaQuery} { ${results2} }`;
172
198
  cssStyles.add(query);
173
199
  return void 0;
174
200
  }
175
- const scope = key.includes("&") ? _key.replaceAll("&", currentScope) : _key.startsWith(":") ? `${currentScope}${_key}` : `${currentScope} ${_key}`;
201
+ if (Object.keys(value).length === 0) return void 0;
202
+ if (pseudoTypoRegex.test(_key)) {
203
+ reportParserIssue(strict, `Selector "${_key}" looks like a missing-colon typo (did you mean "&:${_key.slice(1)}"?).`);
204
+ }
205
+ const scope = combineSelectors(currentScope, _key);
176
206
  const results = await parseStyles(value, scope, config);
177
207
  results.forEach((result) => cssStyles.add(result));
178
208
  return void 0;
179
209
  }
210
+ if (_key.startsWith("$")) {
211
+ reportParserIssue(strict, `Property key "${_key}" looks like a SCSS variable — Salty does not support those.`);
212
+ return void 0;
213
+ }
214
+ if (_key.includes(":")) {
215
+ reportParserIssue(strict, `Property key "${_key}" contains a colon — did you accidentally paste a whole declaration as a key?`);
216
+ return void 0;
217
+ }
218
+ if (value === void 0 || value === null) {
219
+ reportParserIssue(strict, `Property "${_key}" has a ${value === void 0 ? "undefined" : "null"} value — skipping.`);
220
+ return void 0;
221
+ }
222
+ if (typeof value === "boolean") {
223
+ reportParserIssue(strict, `Property "${_key}" has a boolean value (${value}) — skipping.`);
224
+ return void 0;
225
+ }
226
+ if (value === "") return void 0;
180
227
  if (typeof value === "number") {
228
+ if (!Number.isFinite(value)) {
229
+ reportParserIssue(strict, `Property "${_key}" has a non-finite numeric value (${value}) — skipping.`);
230
+ return void 0;
231
+ }
181
232
  const withUnit = addUnit(propertyName, value, config);
182
233
  return toString(withUnit);
183
234
  }
184
235
  if (typeof value !== "string") {
185
- if ("toString" in value) value = value.toString();
186
- else throw new Error(`Invalid value type for property ${propertyName}`);
236
+ if (value && typeof value === "object" && "toString" in value) value = value.toString();
237
+ else {
238
+ reportParserIssue(strict, `Property "${_key}" has an unsupported value type (${typeof value}) — skipping.`);
239
+ return void 0;
240
+ }
241
+ }
242
+ if (typeof value === "string" && templateLiteralLeftoverRegex.test(value)) {
243
+ reportParserIssue(strict, `Property "${_key}" value "${value}" contains an unresolved \`\${...}\` — did you forget to interpolate?`);
187
244
  }
188
245
  return toString(value);
189
246
  };
@@ -223,10 +280,51 @@ const parseAndJoinStyles = async (styles, currentClass, config, omitTemplates =
223
280
  const css = await parseStyles(styles, currentClass, config, omitTemplates);
224
281
  return css.join("\n");
225
282
  };
283
+ const splitTopLevelCommas = (selector) => {
284
+ const parts = [];
285
+ let depth = 0;
286
+ let buf = "";
287
+ for (const ch of selector) {
288
+ if (ch === "(" || ch === "[") depth++;
289
+ else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
290
+ if (ch === "," && depth === 0) {
291
+ const trimmed2 = buf.trim();
292
+ if (trimmed2) parts.push(trimmed2);
293
+ buf = "";
294
+ } else {
295
+ buf += ch;
296
+ }
297
+ }
298
+ const trimmed = buf.trim();
299
+ if (trimmed) parts.push(trimmed);
300
+ return parts;
301
+ };
302
+ const joinSelector = (parent, child) => {
303
+ if (child.includes("&")) return child.replaceAll("&", parent);
304
+ if (child.startsWith(":")) return `${parent}${child}`;
305
+ return `${parent} ${child}`;
306
+ };
307
+ const combineSelectors = (currentScope, key) => {
308
+ if (!currentScope) return key;
309
+ const parents = splitTopLevelCommas(currentScope);
310
+ const children = splitTopLevelCommas(key);
311
+ if (!children.length) return currentScope;
312
+ if (parents.length <= 1 && children.length <= 1) {
313
+ return joinSelector(parents[0] ?? currentScope, children[0]);
314
+ }
315
+ const combos = [];
316
+ for (const p of parents) {
317
+ for (const c of children) {
318
+ combos.push(joinSelector(p, c));
319
+ }
320
+ }
321
+ return combos.join(", ");
322
+ };
226
323
  export {
227
324
  parseStyles as a,
228
325
  parseVariableTokens as b,
229
326
  parseValueModifiers as c,
230
327
  parseValueTokens as d,
231
- parseAndJoinStyles as p
328
+ parseAndJoinStyles as p,
329
+ reportParserIssue as r
232
330
  };
package/parsers/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-CA3TP5n1.cjs");
3
+ const parseStyles = require("../parse-styles-DWQ4UQCp.cjs");
4
4
  const dashCase = require("../dash-case-DIwKaYgE.cjs");
5
5
  const toHash = require("../to-hash-C05Y906F.cjs");
6
6
  const parseTemplates = async (obj, path = []) => {
@@ -52,6 +52,7 @@ exports.parseStyles = parseStyles.parseStyles;
52
52
  exports.parseValueModifiers = parseStyles.parseValueModifiers;
53
53
  exports.parseValueTokens = parseStyles.parseValueTokens;
54
54
  exports.parseVariableTokens = parseStyles.parseVariableTokens;
55
+ exports.reportParserIssue = parseStyles.reportParserIssue;
55
56
  exports.getTemplateKeys = getTemplateKeys;
56
57
  exports.getTemplateTokens = getTemplateTokens;
57
58
  exports.getTemplateTypes = getTemplateTypes;
@@ -3,3 +3,4 @@ export * from './parse-styles';
3
3
  export * from './parse-templates';
4
4
  export * from './parse-tokens';
5
5
  export * from './parser-types';
6
+ export * from './strict';
package/parsers/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { p as parseAndJoinStyles } from "../parse-styles-BTIoYnBr.js";
2
- import { a, c, d, b } from "../parse-styles-BTIoYnBr.js";
1
+ import { p as parseAndJoinStyles } from "../parse-styles-g4NPgqhh.js";
2
+ import { a, c, d, b, r } from "../parse-styles-g4NPgqhh.js";
3
3
  import { d as dashCase } from "../dash-case-DblXvymC.js";
4
4
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
5
5
  const parseTemplates = async (obj, path = []) => {
@@ -55,5 +55,6 @@ export {
55
55
  parseTemplates,
56
56
  c as parseValueModifiers,
57
57
  d as parseValueTokens,
58
- b as parseVariableTokens
58
+ b as parseVariableTokens,
59
+ r as reportParserIssue
59
60
  };
@@ -0,0 +1,3 @@
1
+ export declare const pseudoTypoRegex: RegExp;
2
+ export declare const templateLiteralLeftoverRegex: RegExp;
3
+ export declare const bareAtRuleRegex: RegExp;
@@ -0,0 +1,2 @@
1
+ export type StrictMode = boolean | 'warn' | undefined;
2
+ export declare const reportParserIssue: (strict: StrictMode, message: string) => void;
package/runtime/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-CA3TP5n1.cjs");
3
+ const parseStyles = require("../parse-styles-DWQ4UQCp.cjs");
4
4
  const defineRuntime = (config) => {
5
5
  const getDynamicStylesCss = async (styles, scope) => {
6
6
  const parsed = await parseStyles.parseStyles(styles, scope, config);
package/runtime/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as parseStyles } from "../parse-styles-BTIoYnBr.js";
1
+ import { a as parseStyles } from "../parse-styles-g4NPgqhh.js";
2
2
  const defineRuntime = (config) => {
3
3
  const getDynamicStylesCss = async (styles, scope) => {
4
4
  const parsed = await parseStyles(styles, scope, config);
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const salty_config = "import { defineConfig } from '@salty-css/core/config';\n\nexport const config = defineConfig({\n // Add your custom config here\n externalModules: ['react', 'react-dom']\n});\n";
3
+ const salty_config = "import { defineConfig } from '@salty-css/core/config';\n\nexport const config = defineConfig({\n strict: true,\n externalModules: ['react', 'react-dom']\n});\n";
4
4
  exports.default = salty_config;
@@ -0,0 +1,4 @@
1
+ const salty_config = "import { defineConfig } from '@salty-css/core/config';\n\nexport const config = defineConfig({\n strict: true,\n externalModules: ['react', 'react-dom']\n});\n";
2
+ export {
3
+ salty_config as default
4
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const styledFile = `import { styled } from "@salty-css/astro/styled";
4
+
5
+ export const <%- name %> = styled('<%- tag %>', {
6
+ <% if(className) { %>className: '<%- className %>',<% } %>
7
+ base: {
8
+ // Add your styles here
9
+ }
10
+ })
11
+ `;
12
+ exports.default = styledFile;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const reactStyledFile = `import { styled } from "@salty-css/react/styled";
3
+ const styledFile = `import { styled } from "@salty-css/react/styled";
4
4
 
5
5
  export const <%- name %> = styled('<%- tag %>', {
6
6
  <% if(className) { %>className: '<%- className %>',<% } %>
@@ -8,4 +8,4 @@ export const <%- name %> = styled('<%- tag %>', {
8
8
  // Add your styles here
9
9
  }
10
10
  })`;
11
- exports.default = reactStyledFile;
11
+ exports.default = styledFile;
@@ -1,4 +1,4 @@
1
- const reactStyledFile = `import { styled } from "@salty-css/react/styled";
1
+ const styledFile = `import { styled } from "@salty-css/react/styled";
2
2
 
3
3
  export const <%- name %> = styled('<%- tag %>', {
4
4
  <% if(className) { %>className: '<%- className %>',<% } %>
@@ -7,5 +7,5 @@ export const <%- name %> = styled('<%- tag %>', {
7
7
  }
8
8
  })`;
9
9
  export {
10
- reactStyledFile as default
10
+ styledFile as default
11
11
  };
@@ -0,0 +1,12 @@
1
+ const styledFile = `import { styled } from "@salty-css/astro/styled";
2
+
3
+ export const <%- name %> = styled('<%- tag %>', {
4
+ <% if(className) { %>className: '<%- className %>',<% } %>
5
+ base: {
6
+ // Add your styles here
7
+ }
8
+ })
9
+ `;
10
+ export {
11
+ styledFile as default
12
+ };
@@ -68,6 +68,14 @@ export interface SaltyConfig {
68
68
  * Define modules that should not be bundled when generating the css file. This improves the performance of the css generation and can help with issues relared to external packages being imported in an environment that does not support them.
69
69
  */
70
70
  externalModules?: ('react' | 'react-dom' | OrString)[];
71
+ /**
72
+ * Controls how the parser reacts to suspicious or malformed input
73
+ * (typos, invalid value types, malformed selectors, etc.).
74
+ * - `true` — throw on issues (recommended for new projects)
75
+ * - `'warn'` — log a warning and continue
76
+ * - `false` / undefined — silent, behave like prior versions
77
+ */
78
+ strict?: boolean | 'warn';
71
79
  /**
72
80
  * default unit for px based properties when providing a number value. Default is 'px'.
73
81
  */
@@ -78,6 +86,7 @@ export interface CachedConfig {
78
86
  staticVariables: Record<string, any>;
79
87
  mediaQueries: Record<string, string>;
80
88
  modifiers?: CssModifiers;
89
+ strict?: boolean | 'warn';
81
90
  templatePaths: {
82
91
  [key: string]: string;
83
92
  };
@@ -1,4 +1,4 @@
1
- const reactVanillaFile = `import { <%- styledComponentName %> } from "./<%- fileName %>.css";
1
+ const vanillaFile = `import { <%- styledComponentName %> } from "./<%- fileName %>.css";
2
2
 
3
3
  interface <%- componentName %>Props {
4
4
  text?: string;
@@ -14,5 +14,5 @@ export const <%- componentName %> = ({ text = 'Lorem ipsum' }: <%- componentName
14
14
 
15
15
  export default <%- componentName %>;`;
16
16
  export {
17
- reactVanillaFile as default
17
+ vanillaFile as default
18
18
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const reactVanillaFile = `import { <%- styledComponentName %> } from "./<%- fileName %>.css";
3
+ const vanillaFile = `import { <%- styledComponentName %> } from "./<%- fileName %>.css";
4
4
 
5
5
  interface <%- componentName %>Props {
6
6
  text?: string;
@@ -15,4 +15,4 @@ export const <%- componentName %> = ({ text = 'Lorem ipsum' }: <%- componentName
15
15
  };
16
16
 
17
17
  export default <%- componentName %>;`;
18
- exports.default = reactVanillaFile;
18
+ exports.default = vanillaFile;
@@ -1,4 +0,0 @@
1
- const salty_config = "import { defineConfig } from '@salty-css/core/config';\n\nexport const config = defineConfig({\n // Add your custom config here\n externalModules: ['react', 'react-dom']\n});\n";
2
- export {
3
- salty_config as default
4
- };