@salty-css/core 0.1.0-alpha.9 → 0.1.0-feat-define-font.0
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/bin/confirm-install.d.ts +34 -0
- package/bin/context.d.ts +3 -0
- package/bin/integrations/index.d.ts +11 -3
- package/bin/integrations/types.d.ts +14 -2
- package/bin/main.cjs +149 -48
- package/bin/main.js +149 -48
- package/{class-name-generator-YeSQe_Ik.js → class-name-generator-B2LriwKm.js} +1 -1
- package/{class-name-generator-B2Pb2obX.cjs → class-name-generator-BIYysuhW.cjs} +1 -1
- package/compiler/salty-compiler.cjs +28 -7
- package/compiler/salty-compiler.d.ts +7 -1
- package/compiler/salty-compiler.js +28 -7
- package/config/index.cjs +2 -0
- package/config/index.js +3 -1
- package/css/dynamic-styles.cjs +1 -1
- package/css/dynamic-styles.js +1 -1
- package/css/keyframes.cjs +1 -1
- package/css/keyframes.js +1 -1
- package/factories/define-font.d.ts +28 -0
- package/factories/index.cjs +125 -0
- package/factories/index.d.ts +1 -0
- package/factories/index.js +125 -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 +1 -1
- package/{parse-styles-BTIoYnBr.js → parse-styles--vHKY6Mw.js} +108 -8
- package/{parse-styles-CA3TP5n1.cjs → parse-styles-jPtMfgXH.cjs} +107 -7
- 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/types/config-types.d.ts +10 -1
- package/types/font-types.d.ts +53 -0
- package/salty.config-DjosWdPw.js +0 -4
|
@@ -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,15 @@ 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
|
+
const isVariantArrayKey = _key === "compoundVariants" || _key === "anyOfVariants";
|
|
150
|
+
if (!isVariantArrayKey && Array.isArray(value)) {
|
|
151
|
+
if (value.length === 0) return void 0;
|
|
152
|
+
return processStyleEntry([key, value.join(", ")]);
|
|
153
|
+
}
|
|
127
154
|
if (typeof value === "object") {
|
|
128
155
|
if (!value) return void 0;
|
|
129
156
|
if (value.isColor) return toString(value.toString());
|
|
157
|
+
if (value.isDefineFont) return toString(value.toString());
|
|
130
158
|
if (_key === "defaultVariants") return void 0;
|
|
131
159
|
if (_key === "variants") {
|
|
132
160
|
const variantEntries = Object.entries(value);
|
|
@@ -160,31 +188,62 @@ const parseStyles = async (styles, currentScope = "", config, omitTemplates = fa
|
|
|
160
188
|
return `.${prop}-${val}`;
|
|
161
189
|
});
|
|
162
190
|
const scope2 = `${currentScope}:where(${scopes.join(", ")})`;
|
|
163
|
-
console.log(`Union variant scope: ${scope2}`);
|
|
164
191
|
const results2 = await parseStyles(css2, scope2, config);
|
|
165
192
|
results2.forEach((res) => cssStyles.add(res));
|
|
166
193
|
}
|
|
167
194
|
return void 0;
|
|
168
195
|
}
|
|
169
196
|
if (_key.startsWith("@")) {
|
|
197
|
+
if (bareAtRuleRegex.test(_key)) reportParserIssue(strict, `At-rule "${_key}" is missing its condition (e.g. "@media (min-width: 600px)").`);
|
|
170
198
|
const mediaQuery = ((_b = config == null ? void 0 : config.mediaQueries) == null ? void 0 : _b[_key]) || _key;
|
|
171
199
|
const results2 = await parseAndJoinStyles(value, currentScope, config);
|
|
172
200
|
const query = `${mediaQuery} { ${results2} }`;
|
|
173
201
|
cssStyles.add(query);
|
|
174
202
|
return void 0;
|
|
175
203
|
}
|
|
176
|
-
|
|
204
|
+
if (Object.keys(value).length === 0) return void 0;
|
|
205
|
+
if (pseudoTypoRegex.test(_key)) {
|
|
206
|
+
reportParserIssue(strict, `Selector "${_key}" looks like a missing-colon typo (did you mean "&:${_key.slice(1)}"?).`);
|
|
207
|
+
}
|
|
208
|
+
const scope = combineSelectors(currentScope, _key);
|
|
177
209
|
const results = await parseStyles(value, scope, config);
|
|
178
210
|
results.forEach((result) => cssStyles.add(result));
|
|
179
211
|
return void 0;
|
|
180
212
|
}
|
|
213
|
+
if (_key.startsWith("$")) {
|
|
214
|
+
reportParserIssue(strict, `Property key "${_key}" looks like a SCSS variable — Salty does not support those.`);
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
if (_key.includes(":")) {
|
|
218
|
+
reportParserIssue(strict, `Property key "${_key}" contains a colon — did you accidentally paste a whole declaration as a key?`);
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
if (value === void 0 || value === null) {
|
|
222
|
+
reportParserIssue(strict, `Property "${_key}" has a ${value === void 0 ? "undefined" : "null"} value — skipping.`);
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
if (typeof value === "boolean") {
|
|
226
|
+
reportParserIssue(strict, `Property "${_key}" has a boolean value (${value}) — skipping.`);
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
if (value === "") return void 0;
|
|
181
230
|
if (typeof value === "number") {
|
|
231
|
+
if (!Number.isFinite(value)) {
|
|
232
|
+
reportParserIssue(strict, `Property "${_key}" has a non-finite numeric value (${value}) — skipping.`);
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
182
235
|
const withUnit = addUnit(propertyName, value, config);
|
|
183
236
|
return toString(withUnit);
|
|
184
237
|
}
|
|
185
238
|
if (typeof value !== "string") {
|
|
186
|
-
if ("toString" in value) value = value.toString();
|
|
187
|
-
else
|
|
239
|
+
if (value && typeof value === "object" && "toString" in value) value = value.toString();
|
|
240
|
+
else {
|
|
241
|
+
reportParserIssue(strict, `Property "${_key}" has an unsupported value type (${typeof value}) — skipping.`);
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (typeof value === "string" && templateLiteralLeftoverRegex.test(value)) {
|
|
246
|
+
reportParserIssue(strict, `Property "${_key}" value "${value}" contains an unresolved \`\${...}\` — did you forget to interpolate?`);
|
|
188
247
|
}
|
|
189
248
|
return toString(value);
|
|
190
249
|
};
|
|
@@ -224,8 +283,49 @@ const parseAndJoinStyles = async (styles, currentClass, config, omitTemplates =
|
|
|
224
283
|
const css = await parseStyles(styles, currentClass, config, omitTemplates);
|
|
225
284
|
return css.join("\n");
|
|
226
285
|
};
|
|
286
|
+
const splitTopLevelCommas = (selector) => {
|
|
287
|
+
const parts = [];
|
|
288
|
+
let depth = 0;
|
|
289
|
+
let buf = "";
|
|
290
|
+
for (const ch of selector) {
|
|
291
|
+
if (ch === "(" || ch === "[") depth++;
|
|
292
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
293
|
+
if (ch === "," && depth === 0) {
|
|
294
|
+
const trimmed2 = buf.trim();
|
|
295
|
+
if (trimmed2) parts.push(trimmed2);
|
|
296
|
+
buf = "";
|
|
297
|
+
} else {
|
|
298
|
+
buf += ch;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const trimmed = buf.trim();
|
|
302
|
+
if (trimmed) parts.push(trimmed);
|
|
303
|
+
return parts;
|
|
304
|
+
};
|
|
305
|
+
const joinSelector = (parent, child) => {
|
|
306
|
+
if (child.includes("&")) return child.replaceAll("&", parent);
|
|
307
|
+
if (child.startsWith(":")) return `${parent}${child}`;
|
|
308
|
+
return `${parent} ${child}`;
|
|
309
|
+
};
|
|
310
|
+
const combineSelectors = (currentScope, key) => {
|
|
311
|
+
if (!currentScope) return key;
|
|
312
|
+
const parents = splitTopLevelCommas(currentScope);
|
|
313
|
+
const children = splitTopLevelCommas(key);
|
|
314
|
+
if (!children.length) return currentScope;
|
|
315
|
+
if (parents.length <= 1 && children.length <= 1) {
|
|
316
|
+
return joinSelector(parents[0] ?? currentScope, children[0]);
|
|
317
|
+
}
|
|
318
|
+
const combos = [];
|
|
319
|
+
for (const p of parents) {
|
|
320
|
+
for (const c of children) {
|
|
321
|
+
combos.push(joinSelector(p, c));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return combos.join(", ");
|
|
325
|
+
};
|
|
227
326
|
exports.parseAndJoinStyles = parseAndJoinStyles;
|
|
228
327
|
exports.parseStyles = parseStyles;
|
|
229
328
|
exports.parseValueModifiers = parseValueModifiers;
|
|
230
329
|
exports.parseValueTokens = parseValueTokens;
|
|
231
330
|
exports.parseVariableTokens = parseVariableTokens;
|
|
331
|
+
exports.reportParserIssue = reportParserIssue;
|
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-jPtMfgXH.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--vHKY6Mw.js";
|
|
2
|
+
import { a, c, d, b, r } from "../parse-styles--vHKY6Mw.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-jPtMfgXH.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--vHKY6Mw.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;
|
package/types/config-types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseStyles, CssStyles, MediaQueryStyles } from '../types';
|
|
2
2
|
import { OrString } from '../types/util-types';
|
|
3
|
+
export * from './font-types';
|
|
3
4
|
export type GlobalStyles = Record<string, BaseStyles>;
|
|
4
5
|
export type CssVariableTokensObject = Record<string, unknown>;
|
|
5
6
|
export interface CssResponsiveVariables {
|
|
@@ -68,6 +69,14 @@ export interface SaltyConfig {
|
|
|
68
69
|
* 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
70
|
*/
|
|
70
71
|
externalModules?: ('react' | 'react-dom' | OrString)[];
|
|
72
|
+
/**
|
|
73
|
+
* Controls how the parser reacts to suspicious or malformed input
|
|
74
|
+
* (typos, invalid value types, malformed selectors, etc.).
|
|
75
|
+
* - `true` — throw on issues (recommended for new projects)
|
|
76
|
+
* - `'warn'` — log a warning and continue
|
|
77
|
+
* - `false` / undefined — silent, behave like prior versions
|
|
78
|
+
*/
|
|
79
|
+
strict?: boolean | 'warn';
|
|
71
80
|
/**
|
|
72
81
|
* default unit for px based properties when providing a number value. Default is 'px'.
|
|
73
82
|
*/
|
|
@@ -78,8 +87,8 @@ export interface CachedConfig {
|
|
|
78
87
|
staticVariables: Record<string, any>;
|
|
79
88
|
mediaQueries: Record<string, string>;
|
|
80
89
|
modifiers?: CssModifiers;
|
|
90
|
+
strict?: boolean | 'warn';
|
|
81
91
|
templatePaths: {
|
|
82
92
|
[key: string]: string;
|
|
83
93
|
};
|
|
84
94
|
}
|
|
85
|
-
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type FontDisplay = 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
|
|
2
|
+
export type FontFormat = 'woff2' | 'woff' | 'truetype' | 'opentype' | 'embedded-opentype' | 'svg' | 'collection';
|
|
3
|
+
export type FontStyle = 'normal' | 'italic' | 'oblique' | (string & {});
|
|
4
|
+
export type FontWeight = number | 'normal' | 'bold' | 'lighter' | 'bolder' | (string & {});
|
|
5
|
+
export interface FontSrc {
|
|
6
|
+
url: string;
|
|
7
|
+
format?: FontFormat;
|
|
8
|
+
/** Optional `tech(...)` descriptor passed straight through to @font-face. */
|
|
9
|
+
tech?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FontVariant {
|
|
12
|
+
weight?: FontWeight;
|
|
13
|
+
style?: FontStyle;
|
|
14
|
+
stretch?: string;
|
|
15
|
+
display?: FontDisplay;
|
|
16
|
+
unicodeRange?: string;
|
|
17
|
+
ascentOverride?: string;
|
|
18
|
+
descentOverride?: string;
|
|
19
|
+
lineGapOverride?: string;
|
|
20
|
+
sizeAdjust?: string;
|
|
21
|
+
/**
|
|
22
|
+
* One or more font sources. Strings are treated as URLs and the `format()`
|
|
23
|
+
* descriptor is auto-detected from the file extension when possible. Use
|
|
24
|
+
* the `{ url, format }` object form for CDN/extensionless URLs where the
|
|
25
|
+
* format must be set explicitly.
|
|
26
|
+
*/
|
|
27
|
+
src: string | FontSrc | (string | FontSrc)[];
|
|
28
|
+
}
|
|
29
|
+
interface DefineFontBase {
|
|
30
|
+
/** CSS `font-family` value users will see in styles. */
|
|
31
|
+
name: string;
|
|
32
|
+
/**
|
|
33
|
+
* CSS variable name. Accepts `--font-inter` or `font-inter`; we normalize.
|
|
34
|
+
* Optional — when omitted, a deterministic name is derived from the other
|
|
35
|
+
* inputs as `--font-<name>-<hash>`.
|
|
36
|
+
*/
|
|
37
|
+
variable?: string;
|
|
38
|
+
/** Default `font-display` applied to variants that don't set their own. */
|
|
39
|
+
display?: FontDisplay;
|
|
40
|
+
/** Family fallback(s) appended after `name` in the generated `font-family` string. */
|
|
41
|
+
fallback?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface DefineFontVariantsOptions extends DefineFontBase {
|
|
44
|
+
variants: FontVariant[];
|
|
45
|
+
import?: never;
|
|
46
|
+
}
|
|
47
|
+
export interface DefineFontImportOptions extends DefineFontBase {
|
|
48
|
+
/** Remote stylesheet URL (e.g. Google Fonts). Emitted as `@import url(...)`. */
|
|
49
|
+
import: string;
|
|
50
|
+
variants?: never;
|
|
51
|
+
}
|
|
52
|
+
export type DefineFontOptions = DefineFontVariantsOptions | DefineFontImportOptions;
|
|
53
|
+
export {};
|
package/salty.config-DjosWdPw.js
DELETED