@salty-css/core 0.1.0-alpha.2 → 0.1.0-alpha.21
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/README.md +83 -0
- package/astro-component-5hrNTCJ5.js +4 -0
- package/astro-component-Dj3enX6K.cjs +4 -0
- package/bin/commands/build.d.ts +2 -0
- package/bin/commands/generate.d.ts +2 -0
- package/bin/commands/init.d.ts +2 -0
- package/bin/commands/update.d.ts +2 -0
- package/bin/commands/version.d.ts +2 -0
- package/bin/confirm-install.d.ts +34 -0
- package/bin/context.d.ts +22 -0
- package/bin/detection/css-file.d.ts +5 -0
- package/bin/frameworks/astro.d.ts +4 -0
- package/bin/frameworks/index.d.ts +13 -0
- package/bin/frameworks/react.d.ts +2 -0
- package/bin/frameworks/types.d.ts +27 -0
- package/bin/integrations/astro.d.ts +11 -0
- package/bin/integrations/eslint.d.ts +6 -0
- package/bin/integrations/index.d.ts +21 -0
- package/bin/integrations/next.d.ts +9 -0
- package/bin/integrations/types.d.ts +29 -0
- package/bin/integrations/vite.d.ts +8 -0
- package/bin/main.cjs +653 -336
- package/bin/main.d.ts +8 -0
- package/bin/main.js +653 -336
- package/bin/package-json.d.ts +21 -0
- package/bin/saltyrc.d.ts +31 -0
- package/bin/templates.d.ts +14 -0
- package/{class-name-generator-B2Pb2obX.cjs → class-name-generator-DVuPkyrS.cjs} +1 -1
- package/{class-name-generator-YeSQe_Ik.js → class-name-generator-DkByUzHU.js} +1 -1
- package/compiler/salty-compiler.cjs +29 -8
- package/compiler/salty-compiler.d.ts +7 -1
- package/compiler/salty-compiler.js +29 -8
- package/config/index.cjs +2 -0
- package/config/index.js +3 -1
- package/css/dynamic-styles.cjs +15 -0
- package/css/dynamic-styles.d.ts +10 -0
- package/css/dynamic-styles.js +15 -0
- package/css/index.cjs +3 -0
- package/css/index.d.ts +1 -0
- package/css/index.js +3 -0
- package/css/keyframes.cjs +1 -1
- package/css/keyframes.js +1 -1
- package/factories/define-font.d.ts +28 -0
- package/factories/index.cjs +128 -0
- package/factories/index.d.ts +1 -0
- package/factories/index.js +128 -0
- package/generators/index.cjs +1 -1
- package/generators/index.js +2 -2
- package/instances/classname-instance.cjs +1 -1
- package/instances/classname-instance.js +1 -1
- package/package.json +5 -1
- package/{parse-styles-CA3TP5n1.cjs → parse-styles-CX1WjafO.cjs} +106 -7
- package/{parse-styles-BTIoYnBr.js → parse-styles-DIqJjXF3.js} +107 -8
- package/parsers/index.cjs +2 -1
- package/parsers/index.d.ts +1 -0
- package/parsers/index.js +4 -3
- package/parsers/parser-regexes.d.ts +3 -0
- package/parsers/strict.d.ts +2 -0
- package/runtime/index.cjs +1 -1
- package/runtime/index.js +1 -1
- package/{salty.config-cqavVm2t.cjs → salty.config-DogY_sSQ.cjs} +1 -1
- package/salty.config-GV37Q-D2.js +4 -0
- package/styled-file-BzmB9_Ez.cjs +12 -0
- package/{react-styled-file-U02jek-B.cjs → styled-file-CPd_rTW2.cjs} +2 -2
- package/{react-styled-file-B99mwk0w.js → styled-file-Cda3EeR6.js} +2 -2
- package/styled-file-DLcgYmGN.js +12 -0
- package/types/config-types.d.ts +10 -1
- package/types/font-types.d.ts +53 -0
- package/{react-vanilla-file-D9px70iK.js → vanilla-file-1kOqbCIM.js} +2 -2
- package/{react-vanilla-file-Bj6XC8GS.cjs → vanilla-file-r0fp2q_m.cjs} +2 -2
- package/salty.config-DjosWdPw.js +0 -4
package/factories/index.js
CHANGED
|
@@ -1,5 +1,131 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { d as dashCase } from "../dash-case-DblXvymC.js";
|
|
5
|
+
import { t as toHash } from "../to-hash-DAN2LcHK.js";
|
|
1
6
|
import { media } from "../css/media.js";
|
|
2
7
|
import { T, a, d } from "../define-templates-CVhhgPnd.js";
|
|
8
|
+
const FONT_FORMAT_BY_EXTENSION = {
|
|
9
|
+
woff2: "woff2",
|
|
10
|
+
woff: "woff",
|
|
11
|
+
ttf: "truetype",
|
|
12
|
+
otf: "opentype",
|
|
13
|
+
eot: "embedded-opentype",
|
|
14
|
+
svg: "svg",
|
|
15
|
+
ttc: "collection"
|
|
16
|
+
};
|
|
17
|
+
const detectFontFormat = (url) => {
|
|
18
|
+
const cleaned = url.split("?")[0].split("#")[0];
|
|
19
|
+
const dot = cleaned.lastIndexOf(".");
|
|
20
|
+
if (dot === -1) return void 0;
|
|
21
|
+
const ext = cleaned.slice(dot + 1).toLowerCase();
|
|
22
|
+
return FONT_FORMAT_BY_EXTENSION[ext];
|
|
23
|
+
};
|
|
24
|
+
const toFontSrc = (entry) => {
|
|
25
|
+
if (typeof entry === "string") return { url: entry, format: detectFontFormat(entry) };
|
|
26
|
+
return entry;
|
|
27
|
+
};
|
|
28
|
+
const normalizeSources = (src) => {
|
|
29
|
+
if (Array.isArray(src)) return src.map(toFontSrc);
|
|
30
|
+
return [toFontSrc(src)];
|
|
31
|
+
};
|
|
32
|
+
const normalizeVariable = (variable) => {
|
|
33
|
+
const trimmed = variable.trim();
|
|
34
|
+
const stripped = trimmed.replace(/^--/, "");
|
|
35
|
+
if (!stripped) throw new Error(`defineFont: invalid \`variable\` value "${variable}".`);
|
|
36
|
+
return `--${dashCase(stripped)}`;
|
|
37
|
+
};
|
|
38
|
+
const deriveVariable = (options) => {
|
|
39
|
+
const hashSource = [options.name, options.fallback, "variants" in options ? options.variants : void 0, "import" in options ? options.import : void 0];
|
|
40
|
+
return `--font-${dashCase(options.name)}-${toHash(hashSource, 6)}`;
|
|
41
|
+
};
|
|
42
|
+
const quoteFamily = (name) => {
|
|
43
|
+
if (/^["'].*["']$/.test(name)) return name;
|
|
44
|
+
if (/\s/.test(name)) return `"${name}"`;
|
|
45
|
+
return name;
|
|
46
|
+
};
|
|
47
|
+
const buildFontFamilyValue = (name, fallback) => {
|
|
48
|
+
const head = quoteFamily(name);
|
|
49
|
+
if (!fallback || fallback.length === 0) return head;
|
|
50
|
+
return [head, ...fallback].join(", ");
|
|
51
|
+
};
|
|
52
|
+
const formatSrc = (src) => {
|
|
53
|
+
const parts = [`url("${src.url}")`];
|
|
54
|
+
if (src.format) parts.push(`format("${src.format}")`);
|
|
55
|
+
if (src.tech) parts.push(`tech(${src.tech})`);
|
|
56
|
+
return parts.join(" ");
|
|
57
|
+
};
|
|
58
|
+
const variantToFontFace = (name, variant, defaultDisplay) => {
|
|
59
|
+
const sources = normalizeSources(variant.src);
|
|
60
|
+
if (sources.length === 0) {
|
|
61
|
+
throw new Error(`defineFont(${name}): variant must declare at least one \`src\`.`);
|
|
62
|
+
}
|
|
63
|
+
const lines = [`font-family: ${quoteFamily(name)};`, `src: ${sources.map(formatSrc).join(", ")};`, `font-display: ${variant.display ?? defaultDisplay};`];
|
|
64
|
+
if (variant.weight !== void 0) lines.push(`font-weight: ${variant.weight};`);
|
|
65
|
+
if (variant.style !== void 0) lines.push(`font-style: ${variant.style};`);
|
|
66
|
+
if (variant.stretch !== void 0) lines.push(`font-stretch: ${variant.stretch};`);
|
|
67
|
+
if (variant.unicodeRange !== void 0) lines.push(`unicode-range: ${variant.unicodeRange};`);
|
|
68
|
+
if (variant.ascentOverride !== void 0) lines.push(`ascent-override: ${variant.ascentOverride};`);
|
|
69
|
+
if (variant.descentOverride !== void 0) lines.push(`descent-override: ${variant.descentOverride};`);
|
|
70
|
+
if (variant.lineGapOverride !== void 0) lines.push(`line-gap-override: ${variant.lineGapOverride};`);
|
|
71
|
+
if (variant.sizeAdjust !== void 0) lines.push(`size-adjust: ${variant.sizeAdjust};`);
|
|
72
|
+
return `@font-face { ${lines.join(" ")} }`;
|
|
73
|
+
};
|
|
74
|
+
class FontFactory {
|
|
75
|
+
constructor(_options) {
|
|
76
|
+
__publicField(this, "variable");
|
|
77
|
+
__publicField(this, "fontFamily");
|
|
78
|
+
__publicField(this, "className");
|
|
79
|
+
this._options = _options;
|
|
80
|
+
if (!_options || !_options.name) {
|
|
81
|
+
throw new Error("defineFont: `name` is required.");
|
|
82
|
+
}
|
|
83
|
+
if ("variants" in _options && "import" in _options && _options.import !== void 0 && _options.variants !== void 0) {
|
|
84
|
+
throw new Error("defineFont: provide either `variants` or `import`, not both.");
|
|
85
|
+
}
|
|
86
|
+
if (!("variants" in _options && _options.variants) && !("import" in _options && _options.import)) {
|
|
87
|
+
throw new Error("defineFont: must provide either `variants` or `import`.");
|
|
88
|
+
}
|
|
89
|
+
this.variable = _options.variable ? normalizeVariable(_options.variable) : deriveVariable(_options);
|
|
90
|
+
this.fontFamily = buildFontFamilyValue(_options.name, _options.fallback);
|
|
91
|
+
this.className = `font-${dashCase(_options.name)}`;
|
|
92
|
+
}
|
|
93
|
+
get isDefineFont() {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/** Acts as a string equal to the resolved font-family value. */
|
|
97
|
+
toString() {
|
|
98
|
+
return this.fontFamily;
|
|
99
|
+
}
|
|
100
|
+
/** Inline-style helper: spread onto a React `style` prop. */
|
|
101
|
+
get style() {
|
|
102
|
+
return {
|
|
103
|
+
fontFamily: this.fontFamily,
|
|
104
|
+
[this.variable]: this.fontFamily
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Build the CSS pieces written to `_fonts.css`. */
|
|
108
|
+
_toCss() {
|
|
109
|
+
const imports = [];
|
|
110
|
+
const blocks = [];
|
|
111
|
+
if ("import" in this._options && this._options.import) {
|
|
112
|
+
imports.push(`@import url("${this._options.import}");`);
|
|
113
|
+
} else if ("variants" in this._options && this._options.variants) {
|
|
114
|
+
const display = this._options.display ?? "swap";
|
|
115
|
+
for (const variant of this._options.variants) {
|
|
116
|
+
blocks.push(variantToFontFace(this._options.name, variant, display));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
blocks.push(
|
|
120
|
+
`:root { ${this.variable}: ${this.fontFamily}; }`,
|
|
121
|
+
`.${this.className} { ${this.variable}: ${this.fontFamily}; font-family: var(${this.variable}); }`
|
|
122
|
+
);
|
|
123
|
+
return { imports, body: blocks.join(" ") };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const defineFont = (options) => {
|
|
127
|
+
return new FontFactory(options);
|
|
128
|
+
};
|
|
3
129
|
class GlobalStylesFactory {
|
|
4
130
|
constructor(_current) {
|
|
5
131
|
this._current = _current;
|
|
@@ -26,10 +152,12 @@ const defineVariables = (variables) => {
|
|
|
26
152
|
return new VariablesFactory(variables);
|
|
27
153
|
};
|
|
28
154
|
export {
|
|
155
|
+
FontFactory,
|
|
29
156
|
GlobalStylesFactory,
|
|
30
157
|
T as TemplateFactory,
|
|
31
158
|
a as TemplatesFactory,
|
|
32
159
|
VariablesFactory,
|
|
160
|
+
defineFont,
|
|
33
161
|
defineGlobalStyles,
|
|
34
162
|
defineMediaQuery,
|
|
35
163
|
d as defineTemplates,
|
package/generators/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const classNameGenerator = require("../class-name-generator-
|
|
3
|
+
const classNameGenerator = require("../class-name-generator-DVuPkyrS.cjs");
|
|
4
4
|
const dashCase = require("../dash-case-DIwKaYgE.cjs");
|
|
5
5
|
class StyledGenerator extends classNameGenerator.StylesGenerator {
|
|
6
6
|
constructor(tagName, _params) {
|
package/generators/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StylesGenerator } from "../class-name-generator-
|
|
2
|
-
import { C } from "../class-name-generator-
|
|
1
|
+
import { S as StylesGenerator } from "../class-name-generator-DkByUzHU.js";
|
|
2
|
+
import { C } from "../class-name-generator-DkByUzHU.js";
|
|
3
3
|
import { d as dashCase } from "../dash-case-DblXvymC.js";
|
|
4
4
|
class StyledGenerator extends StylesGenerator {
|
|
5
5
|
constructor(tagName, _params) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const classNameGenerator = require("../class-name-generator-
|
|
3
|
+
const classNameGenerator = require("../class-name-generator-DVuPkyrS.cjs");
|
|
4
4
|
const classNameInstance = (params) => {
|
|
5
5
|
const generator = new classNameGenerator.ClassNameGenerator(params);
|
|
6
6
|
const createClass = (classNameStr) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClassNameGenerator } from "../class-name-generator-
|
|
1
|
+
import { C as ClassNameGenerator } from "../class-name-generator-DkByUzHU.js";
|
|
2
2
|
const classNameInstance = (params) => {
|
|
3
3
|
const generator = new ClassNameGenerator(params);
|
|
4
4
|
const createClass = (classNameStr) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salty-css/core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.21",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"typings": "./dist/index.d.ts",
|
|
@@ -87,6 +87,10 @@
|
|
|
87
87
|
"import": "./css/merge.js",
|
|
88
88
|
"require": "./css/merge.cjs"
|
|
89
89
|
},
|
|
90
|
+
"./css/dynamic-styles": {
|
|
91
|
+
"import": "./css/dynamic-styles.js",
|
|
92
|
+
"require": "./css/dynamic-styles.cjs"
|
|
93
|
+
},
|
|
90
94
|
"./helpers": {
|
|
91
95
|
"import": "./helpers/index.js",
|
|
92
96
|
"require": "./helpers/index.cjs"
|
|
@@ -21,7 +21,7 @@ const parseValueTokens = (tokenNames) => (value) => {
|
|
|
21
21
|
const hasToken = /\{[^{}]+\}/g.test(value);
|
|
22
22
|
if (!hasToken) return void 0;
|
|
23
23
|
const transformed = value.replace(/\{([^{}]+)\}/g, (...args) => {
|
|
24
|
-
const variable = dashCase.dashCase(args[1].replaceAll(".", "-"));
|
|
24
|
+
const variable = dashCase.dashCase(args[1].trim().replaceAll(".", "-"));
|
|
25
25
|
if (tokenNames && !tokenNames.includes(variable)) console.warn(`Token ${variable} might not exist`);
|
|
26
26
|
if (variable.startsWith("-")) return `-${variable}`;
|
|
27
27
|
return `var(--${variable})`;
|
|
@@ -75,22 +75,44 @@ const addUnit = (key, value, config) => {
|
|
|
75
75
|
return `${value}`;
|
|
76
76
|
};
|
|
77
77
|
const vendorPrefixes = ["Webkit", "Moz", "ms", "O"];
|
|
78
|
+
const isVendorPrefixed = (key) => {
|
|
79
|
+
return vendorPrefixes.some((prefix) => {
|
|
80
|
+
if (!key.startsWith(prefix)) return false;
|
|
81
|
+
const next = key.charAt(prefix.length);
|
|
82
|
+
return next >= "A" && next <= "Z";
|
|
83
|
+
});
|
|
84
|
+
};
|
|
78
85
|
const propertyNameCheck = (key) => {
|
|
79
86
|
if (key.startsWith("-")) return key;
|
|
80
|
-
if (
|
|
87
|
+
if (isVendorPrefixed(key)) return `-${dashCase.dashCase(key)}`;
|
|
81
88
|
return dashCase.dashCase(key);
|
|
82
89
|
};
|
|
90
|
+
const reportParserIssue = (strict, message) => {
|
|
91
|
+
if (strict === true) throw new Error(`[salty-css] ${message}`);
|
|
92
|
+
if (strict === "warn") console.warn(`[salty-css] ${message}`);
|
|
93
|
+
};
|
|
94
|
+
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/;
|
|
95
|
+
const templateLiteralLeftoverRegex = /\$\{[^}]+\}/;
|
|
96
|
+
const bareAtRuleRegex = /^@(media|supports|container|layer)\s*$/;
|
|
83
97
|
const parseStyles = async (styles, currentScope = "", config, omitTemplates = false) => {
|
|
84
98
|
if (!styles) throw new Error("No styles provided to parseStyles function!");
|
|
85
99
|
const cssStyles = /* @__PURE__ */ new Set();
|
|
86
100
|
const entries = Object.entries(styles);
|
|
101
|
+
const strict = config == null ? void 0 : config.strict;
|
|
87
102
|
const processStyleEntry = async ([key, value]) => {
|
|
88
103
|
var _a, _b;
|
|
89
104
|
const _key = key.trim().replace(/^\?+/g, "");
|
|
90
105
|
const propertyName = propertyNameCheck(_key);
|
|
91
106
|
const toString = (val, eol = ";") => `${propertyName}:${val}${eol}`;
|
|
92
107
|
const context = { scope: currentScope, config };
|
|
93
|
-
if (typeof value === "function")
|
|
108
|
+
if (typeof value === "function") {
|
|
109
|
+
try {
|
|
110
|
+
return await processStyleEntry([key, value(context)]);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
reportParserIssue(strict, `Function value for "${_key}" threw: ${(error == null ? void 0 : error.message) ?? error}`);
|
|
113
|
+
return void 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
94
116
|
if (value instanceof Promise) return processStyleEntry([key, await value]);
|
|
95
117
|
if ((config == null ? void 0 : config.templates) && ((_a = config.templatePaths) == null ? void 0 : _a[_key])) {
|
|
96
118
|
try {
|
|
@@ -124,9 +146,14 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
|
|
|
124
146
|
console.warn(`Template "${_key}" with path of "${value}" was not found in config!`);
|
|
125
147
|
return void 0;
|
|
126
148
|
}
|
|
149
|
+
if (Array.isArray(value)) {
|
|
150
|
+
if (value.length === 0) return void 0;
|
|
151
|
+
return processStyleEntry([key, value.join(", ")]);
|
|
152
|
+
}
|
|
127
153
|
if (typeof value === "object") {
|
|
128
154
|
if (!value) return void 0;
|
|
129
155
|
if (value.isColor) return toString(value.toString());
|
|
156
|
+
if (value.isDefineFont) return toString(value.toString());
|
|
130
157
|
if (_key === "defaultVariants") return void 0;
|
|
131
158
|
if (_key === "variants") {
|
|
132
159
|
const variantEntries = Object.entries(value);
|
|
@@ -160,31 +187,62 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
|
|
|
160
187
|
return `.${prop}-${val}`;
|
|
161
188
|
});
|
|
162
189
|
const scope2 = `${currentScope}:where(${scopes.join(", ")})`;
|
|
163
|
-
console.log(`Union variant scope: ${scope2}`);
|
|
164
190
|
const results2 = await parseStyles(css2, scope2, config);
|
|
165
191
|
results2.forEach((res) => cssStyles.add(res));
|
|
166
192
|
}
|
|
167
193
|
return void 0;
|
|
168
194
|
}
|
|
169
195
|
if (_key.startsWith("@")) {
|
|
196
|
+
if (bareAtRuleRegex.test(_key)) reportParserIssue(strict, `At-rule "${_key}" is missing its condition (e.g. "@media (min-width: 600px)").`);
|
|
170
197
|
const mediaQuery = ((_b = config == null ? void 0 : config.mediaQueries) == null ? void 0 : _b[_key]) || _key;
|
|
171
198
|
const results2 = await parseAndJoinStyles(value, currentScope, config);
|
|
172
199
|
const query = `${mediaQuery} { ${results2} }`;
|
|
173
200
|
cssStyles.add(query);
|
|
174
201
|
return void 0;
|
|
175
202
|
}
|
|
176
|
-
|
|
203
|
+
if (Object.keys(value).length === 0) return void 0;
|
|
204
|
+
if (pseudoTypoRegex.test(_key)) {
|
|
205
|
+
reportParserIssue(strict, `Selector "${_key}" looks like a missing-colon typo (did you mean "&:${_key.slice(1)}"?).`);
|
|
206
|
+
}
|
|
207
|
+
const scope = combineSelectors(currentScope, _key);
|
|
177
208
|
const results = await parseStyles(value, scope, config);
|
|
178
209
|
results.forEach((result) => cssStyles.add(result));
|
|
179
210
|
return void 0;
|
|
180
211
|
}
|
|
212
|
+
if (_key.startsWith("$")) {
|
|
213
|
+
reportParserIssue(strict, `Property key "${_key}" looks like a SCSS variable — Salty does not support those.`);
|
|
214
|
+
return void 0;
|
|
215
|
+
}
|
|
216
|
+
if (_key.includes(":")) {
|
|
217
|
+
reportParserIssue(strict, `Property key "${_key}" contains a colon — did you accidentally paste a whole declaration as a key?`);
|
|
218
|
+
return void 0;
|
|
219
|
+
}
|
|
220
|
+
if (value === void 0 || value === null) {
|
|
221
|
+
reportParserIssue(strict, `Property "${_key}" has a ${value === void 0 ? "undefined" : "null"} value — skipping.`);
|
|
222
|
+
return void 0;
|
|
223
|
+
}
|
|
224
|
+
if (typeof value === "boolean") {
|
|
225
|
+
reportParserIssue(strict, `Property "${_key}" has a boolean value (${value}) — skipping.`);
|
|
226
|
+
return void 0;
|
|
227
|
+
}
|
|
228
|
+
if (value === "") return void 0;
|
|
181
229
|
if (typeof value === "number") {
|
|
230
|
+
if (!Number.isFinite(value)) {
|
|
231
|
+
reportParserIssue(strict, `Property "${_key}" has a non-finite numeric value (${value}) — skipping.`);
|
|
232
|
+
return void 0;
|
|
233
|
+
}
|
|
182
234
|
const withUnit = addUnit(propertyName, value, config);
|
|
183
235
|
return toString(withUnit);
|
|
184
236
|
}
|
|
185
237
|
if (typeof value !== "string") {
|
|
186
|
-
if ("toString" in value) value = value.toString();
|
|
187
|
-
else
|
|
238
|
+
if (value && typeof value === "object" && "toString" in value) value = value.toString();
|
|
239
|
+
else {
|
|
240
|
+
reportParserIssue(strict, `Property "${_key}" has an unsupported value type (${typeof value}) — skipping.`);
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (typeof value === "string" && templateLiteralLeftoverRegex.test(value)) {
|
|
245
|
+
reportParserIssue(strict, `Property "${_key}" value "${value}" contains an unresolved \`\${...}\` — did you forget to interpolate?`);
|
|
188
246
|
}
|
|
189
247
|
return toString(value);
|
|
190
248
|
};
|
|
@@ -224,8 +282,49 @@ const parseAndJoinStyles = async (styles, currentClass, config, omitTemplates =
|
|
|
224
282
|
const css = await parseStyles(styles, currentClass, config, omitTemplates);
|
|
225
283
|
return css.join("\n");
|
|
226
284
|
};
|
|
285
|
+
const splitTopLevelCommas = (selector) => {
|
|
286
|
+
const parts = [];
|
|
287
|
+
let depth = 0;
|
|
288
|
+
let buf = "";
|
|
289
|
+
for (const ch of selector) {
|
|
290
|
+
if (ch === "(" || ch === "[") depth++;
|
|
291
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
292
|
+
if (ch === "," && depth === 0) {
|
|
293
|
+
const trimmed2 = buf.trim();
|
|
294
|
+
if (trimmed2) parts.push(trimmed2);
|
|
295
|
+
buf = "";
|
|
296
|
+
} else {
|
|
297
|
+
buf += ch;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const trimmed = buf.trim();
|
|
301
|
+
if (trimmed) parts.push(trimmed);
|
|
302
|
+
return parts;
|
|
303
|
+
};
|
|
304
|
+
const joinSelector = (parent, child) => {
|
|
305
|
+
if (child.includes("&")) return child.replaceAll("&", parent);
|
|
306
|
+
if (child.startsWith(":")) return `${parent}${child}`;
|
|
307
|
+
return `${parent} ${child}`;
|
|
308
|
+
};
|
|
309
|
+
const combineSelectors = (currentScope, key) => {
|
|
310
|
+
if (!currentScope) return key;
|
|
311
|
+
const parents = splitTopLevelCommas(currentScope);
|
|
312
|
+
const children = splitTopLevelCommas(key);
|
|
313
|
+
if (!children.length) return currentScope;
|
|
314
|
+
if (parents.length <= 1 && children.length <= 1) {
|
|
315
|
+
return joinSelector(parents[0] ?? currentScope, children[0]);
|
|
316
|
+
}
|
|
317
|
+
const combos = [];
|
|
318
|
+
for (const p of parents) {
|
|
319
|
+
for (const c of children) {
|
|
320
|
+
combos.push(joinSelector(p, c));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return combos.join(", ");
|
|
324
|
+
};
|
|
227
325
|
exports.parseAndJoinStyles = parseAndJoinStyles;
|
|
228
326
|
exports.parseStyles = parseStyles;
|
|
229
327
|
exports.parseValueModifiers = parseValueModifiers;
|
|
230
328
|
exports.parseValueTokens = parseValueTokens;
|
|
231
329
|
exports.parseVariableTokens = parseVariableTokens;
|
|
330
|
+
exports.reportParserIssue = reportParserIssue;
|
|
@@ -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 (
|
|
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")
|
|
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,9 +145,14 @@ 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());
|
|
155
|
+
if (value.isDefineFont) return toString(value.toString());
|
|
129
156
|
if (_key === "defaultVariants") return void 0;
|
|
130
157
|
if (_key === "variants") {
|
|
131
158
|
const variantEntries = Object.entries(value);
|
|
@@ -159,31 +186,62 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
|
|
|
159
186
|
return `.${prop}-${val}`;
|
|
160
187
|
});
|
|
161
188
|
const scope2 = `${currentScope}:where(${scopes.join(", ")})`;
|
|
162
|
-
console.log(`Union variant scope: ${scope2}`);
|
|
163
189
|
const results2 = await parseStyles(css2, scope2, config);
|
|
164
190
|
results2.forEach((res) => cssStyles.add(res));
|
|
165
191
|
}
|
|
166
192
|
return void 0;
|
|
167
193
|
}
|
|
168
194
|
if (_key.startsWith("@")) {
|
|
195
|
+
if (bareAtRuleRegex.test(_key)) reportParserIssue(strict, `At-rule "${_key}" is missing its condition (e.g. "@media (min-width: 600px)").`);
|
|
169
196
|
const mediaQuery = ((_b = config == null ? void 0 : config.mediaQueries) == null ? void 0 : _b[_key]) || _key;
|
|
170
197
|
const results2 = await parseAndJoinStyles(value, currentScope, config);
|
|
171
198
|
const query = `${mediaQuery} { ${results2} }`;
|
|
172
199
|
cssStyles.add(query);
|
|
173
200
|
return void 0;
|
|
174
201
|
}
|
|
175
|
-
|
|
202
|
+
if (Object.keys(value).length === 0) return void 0;
|
|
203
|
+
if (pseudoTypoRegex.test(_key)) {
|
|
204
|
+
reportParserIssue(strict, `Selector "${_key}" looks like a missing-colon typo (did you mean "&:${_key.slice(1)}"?).`);
|
|
205
|
+
}
|
|
206
|
+
const scope = combineSelectors(currentScope, _key);
|
|
176
207
|
const results = await parseStyles(value, scope, config);
|
|
177
208
|
results.forEach((result) => cssStyles.add(result));
|
|
178
209
|
return void 0;
|
|
179
210
|
}
|
|
211
|
+
if (_key.startsWith("$")) {
|
|
212
|
+
reportParserIssue(strict, `Property key "${_key}" looks like a SCSS variable — Salty does not support those.`);
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
if (_key.includes(":")) {
|
|
216
|
+
reportParserIssue(strict, `Property key "${_key}" contains a colon — did you accidentally paste a whole declaration as a key?`);
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
if (value === void 0 || value === null) {
|
|
220
|
+
reportParserIssue(strict, `Property "${_key}" has a ${value === void 0 ? "undefined" : "null"} value — skipping.`);
|
|
221
|
+
return void 0;
|
|
222
|
+
}
|
|
223
|
+
if (typeof value === "boolean") {
|
|
224
|
+
reportParserIssue(strict, `Property "${_key}" has a boolean value (${value}) — skipping.`);
|
|
225
|
+
return void 0;
|
|
226
|
+
}
|
|
227
|
+
if (value === "") return void 0;
|
|
180
228
|
if (typeof value === "number") {
|
|
229
|
+
if (!Number.isFinite(value)) {
|
|
230
|
+
reportParserIssue(strict, `Property "${_key}" has a non-finite numeric value (${value}) — skipping.`);
|
|
231
|
+
return void 0;
|
|
232
|
+
}
|
|
181
233
|
const withUnit = addUnit(propertyName, value, config);
|
|
182
234
|
return toString(withUnit);
|
|
183
235
|
}
|
|
184
236
|
if (typeof value !== "string") {
|
|
185
|
-
if ("toString" in value) value = value.toString();
|
|
186
|
-
else
|
|
237
|
+
if (value && typeof value === "object" && "toString" in value) value = value.toString();
|
|
238
|
+
else {
|
|
239
|
+
reportParserIssue(strict, `Property "${_key}" has an unsupported value type (${typeof value}) — skipping.`);
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (typeof value === "string" && templateLiteralLeftoverRegex.test(value)) {
|
|
244
|
+
reportParserIssue(strict, `Property "${_key}" value "${value}" contains an unresolved \`\${...}\` — did you forget to interpolate?`);
|
|
187
245
|
}
|
|
188
246
|
return toString(value);
|
|
189
247
|
};
|
|
@@ -223,10 +281,51 @@ const parseAndJoinStyles = async (styles, currentClass, config, omitTemplates =
|
|
|
223
281
|
const css = await parseStyles(styles, currentClass, config, omitTemplates);
|
|
224
282
|
return css.join("\n");
|
|
225
283
|
};
|
|
284
|
+
const splitTopLevelCommas = (selector) => {
|
|
285
|
+
const parts = [];
|
|
286
|
+
let depth = 0;
|
|
287
|
+
let buf = "";
|
|
288
|
+
for (const ch of selector) {
|
|
289
|
+
if (ch === "(" || ch === "[") depth++;
|
|
290
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
291
|
+
if (ch === "," && depth === 0) {
|
|
292
|
+
const trimmed2 = buf.trim();
|
|
293
|
+
if (trimmed2) parts.push(trimmed2);
|
|
294
|
+
buf = "";
|
|
295
|
+
} else {
|
|
296
|
+
buf += ch;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const trimmed = buf.trim();
|
|
300
|
+
if (trimmed) parts.push(trimmed);
|
|
301
|
+
return parts;
|
|
302
|
+
};
|
|
303
|
+
const joinSelector = (parent, child) => {
|
|
304
|
+
if (child.includes("&")) return child.replaceAll("&", parent);
|
|
305
|
+
if (child.startsWith(":")) return `${parent}${child}`;
|
|
306
|
+
return `${parent} ${child}`;
|
|
307
|
+
};
|
|
308
|
+
const combineSelectors = (currentScope, key) => {
|
|
309
|
+
if (!currentScope) return key;
|
|
310
|
+
const parents = splitTopLevelCommas(currentScope);
|
|
311
|
+
const children = splitTopLevelCommas(key);
|
|
312
|
+
if (!children.length) return currentScope;
|
|
313
|
+
if (parents.length <= 1 && children.length <= 1) {
|
|
314
|
+
return joinSelector(parents[0] ?? currentScope, children[0]);
|
|
315
|
+
}
|
|
316
|
+
const combos = [];
|
|
317
|
+
for (const p of parents) {
|
|
318
|
+
for (const c of children) {
|
|
319
|
+
combos.push(joinSelector(p, c));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return combos.join(", ");
|
|
323
|
+
};
|
|
226
324
|
export {
|
|
227
325
|
parseStyles as a,
|
|
228
326
|
parseVariableTokens as b,
|
|
229
327
|
parseValueModifiers as c,
|
|
230
328
|
parseValueTokens as d,
|
|
231
|
-
parseAndJoinStyles as p
|
|
329
|
+
parseAndJoinStyles as p,
|
|
330
|
+
reportParserIssue as r
|
|
232
331
|
};
|
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-
|
|
3
|
+
const parseStyles = require("../parse-styles-CX1WjafO.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;
|
package/parsers/index.d.ts
CHANGED
package/parsers/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { p as parseAndJoinStyles } from "../parse-styles-
|
|
2
|
-
import { a, c, d, b } from "../parse-styles-
|
|
1
|
+
import { p as parseAndJoinStyles } from "../parse-styles-DIqJjXF3.js";
|
|
2
|
+
import { a, c, d, b, r } from "../parse-styles-DIqJjXF3.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
|
};
|
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-
|
|
3
|
+
const parseStyles = require("../parse-styles-CX1WjafO.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-
|
|
1
|
+
import { a as parseStyles } from "../parse-styles-DIqJjXF3.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
|
|
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;
|