@salty-css/eslint-plugin-core 0.1.0-refactor-add-additional-paths-to-config-cache.1 → 0.1.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.
Files changed (4) hide show
  1. package/README.md +355 -374
  2. package/index.cjs +1 -1
  3. package/index.js +25 -25
  4. package/package.json +3 -2
package/README.md CHANGED
@@ -1,554 +1,535 @@
1
1
  ![Salty CSS Banner](https://salty-css.dev/assets/banners/dvd.svg)
2
2
 
3
- # Salty CSS - CSS-in-JS library that is kinda sweet
3
+ # Salty CSS CSS-in-JS that compiles away
4
4
 
5
- Is there anything saltier than CSS in frontend web development? Salty CSS is built to provide better developer experience for developers looking for performant and feature rich CSS-in-JS solutions.
5
+ Salty CSS is a build-time, type-safe CSS-in-JS library. You author styles in `.css.ts` files; the compiler emits real CSS, your runtime ships zero styling logic.
6
6
 
7
- [Get started](#get-started) | [API](#api) | [Discord](https://discord.gg/R6kr4KxMhP) | [Website](https://salty-css.dev/) | [GitHub](https://github.com/margarita-form/salty-css) | [NPM](https://www.npmjs.com/package/@salty-css/core)
7
+ [Get started](#get-started) · [API index](#api-index) · [Docs](https://salty-css.dev/docs) · [Discord](https://discord.gg/R6kr4KxMhP) · [GitHub](https://github.com/margarita-form/salty-css) · [NPM](https://www.npmjs.com/package/@salty-css/core)
8
8
 
9
9
  ## Features
10
10
 
11
- - Build time compilation to achieve awesome runtime performance and minimal size
12
- - Next.js, React Server Components, Astro, Vite and Webpack support
13
- - Type safety with out of the box TypeScript and ESLint plugin
14
- - Advanced CSS variables configuration to allow smooth token usage
15
- - Style templates to create reusable styles easily
11
+ - **Build-time compilation** no runtime style injection, no FOUC, no client bundle cost.
12
+ - **Framework support** — Next.js (App + Pages, React Server Components, Webpack & Turbopack), React + Vite, React + Webpack, Astro.
13
+ - **Type safety** TypeScript-first authoring, generated token types, an [ESLint plugin](https://www.npmjs.com/package/@salty-css/eslint-plugin-core).
14
+ - **Design tokens & theming** static, responsive (media-bound), and conditional (data-attribute / class-bound) variables in one place.
15
+ - **Templates** reusable style bundles with their own variants.
16
+ - **Modifiers** — custom value transformers (`'space:3'` → `'12px'`) defined in config.
17
+ - **Variants, compound variants, anyOf variants, default variants** out of the box.
16
18
 
17
19
  ## Get started
18
20
 
19
- Fastest way to get started with any framework is
20
-
21
21
  ```bash
22
22
  npx salty-css init
23
23
  ```
24
24
 
25
- Other guides:
25
+ `init` detects your framework, installs the right packages, creates `salty.config.ts`, and wires the bundler plugin. Per-framework setup:
26
26
 
27
- - Next.js → [Next.js guide](#nextjs) + [Next.js example app](https://github.com/margarita-form/salty-css-website)
28
- - React + Vite → [React + Vite guide](#react--vite) + [React example code](#code-examples)
29
- - React + Webpack Guide coming soon
27
+ - **Next.js** → [salty-css.dev/docs/installation](https://salty-css.dev/docs/installation) `withSaltyCss(nextConfig)` in `next.config.ts`. Auto-detects Webpack vs Turbopack; React Server Components supported.
28
+ - **React + Vite** → [salty-css.dev/docs/installation](https://salty-css.dev/docs/installation) `saltyPlugin(__dirname)` in `vite.config.ts`.
29
+ - **Astro** [salty-css.dev/docs/installation](https://salty-css.dev/docs/installation) `saltyIntegration()` in `astro.config.mjs`.
30
30
 
31
- ## Useful commands
31
+ React + Webpack (without Next.js) is also supported via `@salty-css/webpack`.
32
32
 
33
- - Create component: `npx salty-css generate [filePath]`
34
- - Build: `npx salty-css build [directory]`
35
- - Update Salty CSS packages: `npx salty-css up`
33
+ ## CLI
36
34
 
37
- ## Good to know
35
+ | Command | Alias | What it does |
36
+ | ----------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------ |
37
+ | `npx salty-css init [directory]` | — | Detect framework, install packages, create `salty.config.ts`, wire the plugin. |
38
+ | `npx salty-css generate [filePath]` | `g` | Scaffold a new Salty component file. Flags: `--name`, `--className`, `--tag`. |
39
+ | `npx salty-css build [directory]` | `b` | Compile `*.css.ts` files into `saltygen/index.css`. Not needed when the bundler plugin is running. Flags: `--watch`, `--mode`. |
40
+ | `npx salty-css update [version]` | `up` | Update all `@salty-css/*` packages. Defaults to `latest`. Flags: `--dir`, `--yes`. |
41
+ | `npx salty-css --version` | — | Print CLI version. |
38
42
 
39
- 1. All Salty CSS functions (`styled`, `classNames`, `keyframes`, etc.) must be created in `*.css.ts` or `*.css.tsx` files. This is to ensure best build performance.
40
- 2. Salty CSS components created with styled function can extend non Salty CSS components (`export const CustomLink = styled(NextJSLink, { ... });`) but those components must take in `className` prop for styles to apply.
41
- 3. Among common types like `string` and `number`, CSS-in-JS properties in Salty CSS do support `functions` and `promises` as values (`styled('span', { base: { color: async () => 'red' } });`) but running asynchronous tasks or importing heavy 3rd party libraries into `*.css.ts` or `*.css.tsx` files can cause longer build times.
43
+ Full reference: [salty-css.dev/docs/cli](https://salty-css.dev/docs/cli).
42
44
 
43
- ## Get support
45
+ ## Good to know
44
46
 
45
- To get help with problems, [Join Salty CSS Discord server](https://discord.gg/R6kr4KxMhP).
47
+ 1. **File extensions matter.** `styled`, `className`, `keyframes`, and every `defineX(...)` call must live in a file ending `.css.ts`, `.css.tsx`, `.salty.ts`, `.styles.ts`, or `.styled.ts`. The compiler ignores everything else.
48
+ 2. **Extending non-Salty components is fine** — `styled(NextLink, { ... })` — as long as the wrapped component forwards `className` to a DOM element.
49
+ 3. **Async values & functions are allowed** (`base: { color: async () => 'red' }`), but heavy imports inside `*.css.ts` slow the build.
50
+ 4. **React Server Components are supported** via `@salty-css/next` — no `'use client'` needed for styled output.
46
51
 
47
- ## API
52
+ ## ESLint
48
53
 
49
- ### Component styling
54
+ Salty CSS ships a small ESLint plugin and matching shareable config. Two rules, both `error` by default, both autofixable, both scoped to Salty files (`.css.ts`, `.css.tsx`, `.salty.ts`, `.styles.ts`, `.styled.ts`):
50
55
 
51
- - [styled](#styled-function) (react only) - create React components that can be used anywhere easily
52
- - [className](#class-name-function) (framework agnostic) - create a CSS class string that can be applied to any element
56
+ - **`@salty-css/core/must-be-exported`** every `styled`, `className`, `keyframes`, and `defineX*` call must be exported; the compiler ignores anything else.
57
+ - **`@salty-css/core/no-variants-in-base`** `variants` must be a sibling of `base`, not nested inside it.
53
58
 
54
- ### Global styling
59
+ ```bash
60
+ npm i -D @salty-css/eslint-plugin-core @salty-css/eslint-config-core
61
+ ```
55
62
 
56
- - [defineGlobalStyles](#global-styles) - set global styles like `html` and `body`
57
- - [defineVariables](#variables) - create CSS variables (tokens) that can be used in any styling function
58
- - [defineMediaQuery](#media-queries) - create CSS media queries and use them in any styling function
59
- - [defineTemplates](#templates) - create reusable templates that can be applied when same styles are used over and over again
60
- - [keyframes](#keyframes-animations) - create CSS keyframes animation that can be used and imported in any styling function
63
+ **Flat config (ESLint 9+):**
61
64
 
62
- ### Styling helpers & utility
65
+ ```js
66
+ // eslint.config.mjs
67
+ import saltyConfig from '@salty-css/eslint-config-core/flat';
63
68
 
64
- - [defineViewportClamp](#viewport-clamp) - create CSS clamp functions that are based on user's viewport and can calculate relative values easily
65
- - [color](#color-function) - transform any valid color code or variable to be darker, lighter etc. easily (uses [color library by Qix-](https://github.com/Qix-/color))
69
+ export default [saltyConfig];
70
+ ```
66
71
 
67
- ### Salty CSS CLI
72
+ **Legacy (`.eslintrc`):**
68
73
 
69
- In your existing repository you can use `npx salty-css [command]` to initialize a project, generate components, update related packages and build required files.
74
+ ```js
75
+ module.exports = { extends: ['@salty-css/eslint-config-core'] };
76
+ ```
70
77
 
71
- - Initialize project `npx salty-css init [directory]` - Installs required packages, detects framework in use and creates project files to the provided directory. Directory can be left blank if you want files to be created to the current directory.
72
- - Generate component → `npx salty-css update [version]` - Update @salty-css packages in your repository. Default version is "latest". Additional options like `--dir`, `--tag`, `--name` and `--className` are also supported.
73
- - Build files → `npx salty-css build [directory/filename]` - Compile Salty CSS related files in your project. This should not be needed if you are using tools like Next.js or Vite
78
+ Full reference[salty-css.dev/docs/eslint](https://salty-css.dev/docs/eslint).
79
+
80
+ ## API index
81
+
82
+ | Symbol | Import | One-liner | Docs |
83
+ | ----------------------------------------------- | ------------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
84
+ | [`styled`](#styled) | `@salty-css/react/styled` | React component factory with variants & extension. | [api/styled](https://salty-css.dev/docs/api/styled) |
85
+ | [`className`](#classname) | `@salty-css/react/class-name` | CSS class string with `.variant()` chaining. | [api/classname](https://salty-css.dev/docs/api/classname) |
86
+ | [Variants](#variants) | — | `variants`, `compoundVariants`, `anyOfVariants`, `defaultVariants` semantics. | [variants](https://salty-css.dev/docs/variants) |
87
+ | [Overrides](#overrides) | — | Extend components, swap element, override per-instance via `style`. | [overrides](https://salty-css.dev/docs/overrides) |
88
+ | [ESLint plugin](#eslint) | `@salty-css/eslint-config-core` | Two rules: enforce `export` and correct `variants` placement on Salty files. | [eslint](https://salty-css.dev/docs/eslint) |
89
+ | [`defineConfig`](#defineconfig) | `@salty-css/core/config` | Top-level project config. | [api/config](https://salty-css.dev/docs/api/config) |
90
+ | [`defineVariables`](#definevariables) | `@salty-css/core/factories` | Static, responsive, and conditional CSS variables (tokens). | [variables](https://salty-css.dev/docs/variables) |
91
+ | [Theming](#theming) | — | `data-theme` switcher built on conditional variables. | [theming](https://salty-css.dev/docs/theming) |
92
+ | [`defineGlobalStyles`](#defineglobalstyles) | `@salty-css/core/factories` | Global rules (`html`, `body`, etc.). | [api/define-factories](https://salty-css.dev/docs/api/define-factories) |
93
+ | [`defineMediaQuery`](#definemediaquery) | `@salty-css/core/factories` | Named, reusable media queries. | [media-queries](https://salty-css.dev/docs/media-queries) |
94
+ | [`defineTemplates`](#definetemplates) | `@salty-css/core/factories` | Reusable style bundles, optionally with variants. | [templates](https://salty-css.dev/docs/templates) |
95
+ | [`defineFont`](#definefont) | `@salty-css/core/factories` | `@font-face` (or `@import`) + CSS variable in one. | [fonts](https://salty-css.dev/docs/fonts) |
96
+ | [`defineImport`](#defineimport) | `@salty-css/core/factories` | Pull external CSS into Salty's `imports` layer. | [imports](https://salty-css.dev/docs/imports) |
97
+ | [`keyframes`](#keyframes) | `@salty-css/react/keyframes` | Typed `@keyframes` with params and initial-state injection. | [animations](https://salty-css.dev/docs/animations) |
98
+ | [`defineViewportClamp`](#defineviewportclamp) | `@salty-css/core/helpers` | Fluid `clamp()` values that scale with the viewport. | [viewport-clamp](https://salty-css.dev/docs/viewport-clamp) |
99
+ | [`color`](#color) | `@salty-css/core/helpers` | Color manipulation (`alpha`, `darken`, …). | [color-function](https://salty-css.dev/docs/color-function) |
100
+ | [Modifiers](#modifiers) | (on `defineConfig`) | Custom value transformers, e.g. `'space:3'` → `'12px'`. | [modifiers](https://salty-css.dev/docs/modifiers) |
101
+ | [`withSaltyCss`](#withsaltycss-nextjs) | `@salty-css/next` | Next.js config wrapper (Webpack + Turbopack). | [installation](https://salty-css.dev/docs/installation) |
102
+ | [`saltyPlugin` (Vite)](#saltyplugin-vite) | `@salty-css/vite` | Vite plugin. | [installation](https://salty-css.dev/docs/installation) |
103
+ | [`saltyPlugin` (Webpack)](#saltyplugin-webpack) | `@salty-css/webpack` | Webpack loader + plugin. | [installation](https://salty-css.dev/docs/installation) |
104
+ | [`saltyIntegration`](#saltyintegration-astro) | `@salty-css/astro/integration` | Astro integration. | [installation](https://salty-css.dev/docs/installation) |
74
105
 
75
- ## Styled function
106
+ ---
76
107
 
77
- Styled function is the main way to use Salty CSS within React. Styled function creates a React component that then can be used anywhere in your app. All styled functions must be created in `.css.ts` or `.css.tsx` files
108
+ ## `styled`
78
109
 
79
110
  ```ts
80
- // /components/my-component.css.ts
111
+ // components/button.css.ts
81
112
  import { styled } from '@salty-css/react/styled';
82
113
 
83
- // Define a component with a styled function. First argument is the component name or existing component to extend and second argument is the object containing the styles and other options
84
- export const Component = styled('div', {
85
- className: 'wrapper', // Define optional custom class name that will be included for this component
86
- element: 'section', // Override the html element that will be rendered for this component
114
+ export const Button = styled('button', {
115
+ className: 'btn', // optional custom class
116
+ element: 'button', // optional element override
87
117
  base: {
88
- // 👉 Add your CSS-in-JS base styles here! 👈
118
+ padding: '0.6em 1.2em',
119
+ border: '1px solid currentColor',
120
+ '&:hover': { background: 'black', color: 'white' },
89
121
  },
90
122
  variants: {
91
- // Define conditional styles that will be applied to the component based on the variant prop values
123
+ variant: {
124
+ outlined: {},
125
+ solid: { background: 'black', color: 'white' },
126
+ },
92
127
  },
93
128
  compoundVariants: [
94
- // Define conditional styles that will be applied to the component based on the combination of variant prop values
129
+ /* { variant: 'solid', size: 'lg', css: { ... } } */
95
130
  ],
96
- defaultVariants: {
97
- // Set default variant prop values
98
- },
99
- defaultProps: {
100
- // Add additional default props for the component (eg, id and other html element attributes)
101
- },
102
- passProps: true, // Pass variant props to the rendered element / parent component (default: false)
103
- priority: 1, // Override automatic priotity layer with a custom value (0-8), higher is considered more important
131
+ defaultVariants: { variant: 'outlined' },
132
+ defaultProps: { type: 'button' },
133
+ passProps: false, // pass variant props through to the rendered element
134
+ priority: undefined, // 0–8, higher wins; usually leave to auto
104
135
  });
105
136
  ```
106
137
 
107
- Example usage:
108
-
109
138
  ```tsx
110
- import { Component } from './my-component.css';
111
-
112
- export const Page = () => {
113
- return <Component>Hello world</Component>;
114
- };
139
+ <Button variant="solid">Save</Button>
115
140
  ```
116
141
 
117
- ## Class name function
142
+ See full reference → [salty-css.dev/docs/api/styled](https://salty-css.dev/docs/api/styled).
118
143
 
119
- Create CSS class names with possibility to add scope and media queries etc. Function `className` is quite similar to `styled` but does not allow extending components or classes.
144
+ ## `className`
145
+
146
+ Framework-agnostic class-string factory. The return value is a `string` you can drop in `className=`, plus a `.variant(name, value)` method for chaining variant classes.
120
147
 
121
148
  ```ts
122
- // /components/my-class.css.ts
149
+ // components/card.css.ts
123
150
  import { className } from '@salty-css/react/class-name';
124
151
 
125
- // Define a CSS class with className function. First and only argument is the object containing the styles and other options
126
- export const myClass = className({
127
- className: 'wrapper', // Define optional custom class name that will be included to the scope
152
+ export const card = className({
153
+ className: 'card',
128
154
  base: {
129
- // 👉 Add your CSS-in-JS base styles here! 👈
155
+ padding: '1rem',
156
+ borderRadius: '8px',
157
+ },
158
+ variants: {
159
+ tone: {
160
+ neutral: { background: '#f6f6f6' },
161
+ brand: { background: '{colors.brand.main}' },
162
+ },
130
163
  },
131
164
  });
132
165
  ```
133
166
 
134
- Example usage:
135
-
136
167
  ```tsx
137
- import { myClass } from './my-class.css';
168
+ <div className={`${card.variant('tone', 'brand')}`}>Hello</div>
169
+ ```
138
170
 
139
- export const Page = () => {
140
- return <div className={myClass}>Hello world</div>;
141
- };
171
+ See full reference [salty-css.dev/docs/api/classname](https://salty-css.dev/docs/api/classname).
172
+
173
+ ## Variants
174
+
175
+ `styled` and `className` share the same variant shape:
176
+
177
+ - **`variants`** — named axes (e.g. `size: { sm, md, lg }`). Each axis becomes a prop.
178
+ - **`compoundVariants`** — array; styles applied only when **all** listed axes match.
179
+ - **`anyOfVariants`** — array; styles applied when **any** listed axis matches.
180
+ - **`defaultVariants`** — values used when the prop is omitted at the call site.
181
+
182
+ ```ts
183
+ styled('a', {
184
+ base: { textDecoration: 'none' },
185
+ variants: {
186
+ size: { sm: { fontSize: 14 }, lg: { fontSize: 18 } },
187
+ underline: { true: { textDecoration: 'underline' } },
188
+ },
189
+ compoundVariants: [{ size: 'lg', underline: true, css: { textUnderlineOffset: 4 } }],
190
+ defaultVariants: { size: 'sm' },
191
+ });
142
192
  ```
143
193
 
144
- ## Global styles
194
+ Boolean variants accept `true`/`false` keys; pass them as `<Link underline />` shorthand. See [salty-css.dev/docs/variants](https://salty-css.dev/docs/variants).
195
+
196
+ ## Overrides
197
+
198
+ - **Extend any component:** `styled(ExistingComponent, { ... })`. The wrapped component must accept `className`.
199
+ - **Swap the rendered element** for one instance: `<Button as="a" href="/x" />` (use `passProps` if you want variant props to reach the underlying element).
200
+ - **Per-instance style overrides:** `<Box style={{ ... }} />` and `<Box css={{ ... }} />` accept regular React `style` and Salty's `css` prop (overrides apply at the highest priority).
201
+
202
+ See [salty-css.dev/docs/overrides](https://salty-css.dev/docs/overrides) for `as`, `style`, CSS-variable overrides, and ref forwarding.
203
+
204
+ ## `defineConfig`
145
205
 
146
206
  ```ts
147
- // /styles/global.css.ts
148
- import { defineGlobalStyles } from '@salty-css/core/factories';
207
+ // salty.config.ts
208
+ import { defineConfig } from '@salty-css/core/config';
149
209
 
150
- export default defineGlobalStyles({
151
- html: {
152
- fontFamily: 'Arial, sans-serif',
210
+ export const config = defineConfig({
211
+ importStrategy: 'root', // 'root' | 'component'
212
+ variables: {
213
+ /* see defineVariables */
214
+ },
215
+ global: {
216
+ /* see defineGlobalStyles */
153
217
  },
154
- body: {
155
- backgroundColor: '#fff',
156
- margin: 0,
218
+ templates: {
219
+ /* see defineTemplates */
157
220
  },
158
- // Add more global styles as needed
221
+ modifiers: {
222
+ /* see Modifiers */
223
+ },
224
+ reset: 'default', // 'default' | 'none' | GlobalStyles
225
+ externalModules: ['react', 'react-dom'],
226
+ strict: true, // true | 'warn' | false
227
+ defaultUnit: 'px', // px, rem, em, vh, vw, % …
159
228
  });
160
229
  ```
161
230
 
162
- ## Variables
231
+ Full reference → [salty-css.dev/docs/api/config](https://salty-css.dev/docs/api/config).
232
+
233
+ ## `defineVariables`
234
+
235
+ Tokens come in three flavours — static, responsive (media-bound), conditional (class/data-attribute-bound):
163
236
 
164
237
  ```ts
165
- // /styles/variables.css.ts
238
+ // styles/variables.css.ts
166
239
  import { defineVariables } from '@salty-css/core/factories';
167
240
 
168
241
  export default defineVariables({
169
- /*
170
- Define static variable token (like colors, font sizes, etc.). and use them in your styles (e.g. color: '{colors.brand.highlight}').
171
- Variables can be nested (colors.brand.main) and can reference other variables.
172
- */
173
242
  colors: {
174
243
  dark: '#111',
175
244
  light: '#fefefe',
176
- brand: {
177
- main: '#0070f3',
178
- highlight: '#ff4081',
179
- },
180
- },
181
- fontFamily: {
182
- heading: 'Arial, sans-serif',
183
- body: 'Georgia, serif',
245
+ brand: { main: '#0070f3', highlight: '#ff4081' },
184
246
  },
185
-
186
- /*
187
- Define variables that are responsive to a media query (defined in media.css.ts) asn use them in your styles as normal (e.g. font-size: '{fontSize.heading.regular}').
188
- These variables will be automatically updated when the media query is matched. Base values are used when no media query is matched.
189
- */
190
247
  responsive: {
191
- base: {
192
- fontSize: {
193
- heading: {
194
- small: '32px',
195
- regular: '48px',
196
- large: '64px',
197
- },
198
- body: {
199
- small: '16px',
200
- regular: '20px',
201
- large: '24px',
202
- },
203
- },
204
- },
205
- '@largeMobileDown': {
206
- fontSize: {
207
- heading: {
208
- small: '20px',
209
- regular: '32px',
210
- large: '48px',
211
- },
212
- body: {
213
- small: '14px',
214
- regular: '16px',
215
- large: '20px',
216
- },
217
- },
218
- },
248
+ base: { fontSize: { heading: '48px', body: '16px' } },
249
+ '@largeMobileDown': { fontSize: { heading: '32px', body: '14px' } },
219
250
  },
220
-
221
- /*
222
- Conditional variables are used to define styles that depend on a class name (e.g. <div className="theme-dark">). or data-attribute (e.g. <div data-theme="dark">). Names for these variables will be "{theme.backgroundColor}" and "{theme.textColor}".
223
- */
224
251
  conditional: {
225
252
  theme: {
226
- dark: {
227
- backgroundColor: '{colors.dark}',
228
- textColor: '{colors.light}',
229
- },
230
- light: {
231
- backgroundColor: '{colors.light}',
232
- textColor: '{colors.dark}',
233
- },
253
+ dark: { backgroundColor: '{colors.dark}', textColor: '{colors.light}' },
254
+ light: { backgroundColor: '{colors.light}', textColor: '{colors.dark}' },
234
255
  },
235
256
  },
236
257
  });
237
258
  ```
238
259
 
239
- Example usage:
260
+ Use as string references: `{colors.brand.main}`, `{fontSize.heading}`, `{theme.textColor}`.
261
+
262
+ See [salty-css.dev/docs/variables](https://salty-css.dev/docs/variables).
263
+
264
+ ## Theming
265
+
266
+ The `conditional` bucket above wires up data-attribute / class-based themes with zero providers. Toggle a `data-theme` attribute on `<html>` (or any ancestor) and conditional variables resolve to the matching branch:
267
+
268
+ ```html
269
+ <html data-theme="dark">
270
+ <!-- '{theme.textColor}' resolves to '{colors.light}' -->
271
+ </html>
272
+ ```
273
+
274
+ See the dark-mode walkthrough (with SSR flash fix) → [salty-css.dev/docs/theming](https://salty-css.dev/docs/theming).
275
+
276
+ ## `defineGlobalStyles`
240
277
 
241
278
  ```ts
242
- styled('span', {
243
- base: {
244
- // Use of static font family variable
245
- fontFamily: '{fontFamily.heading}',
246
- // Use of responsive font size variable
247
- fontSize: '{fontSize.heading.regular}',
248
- // Use of conditional theme text color variable
249
- color: '{theme.textColor}',
250
- },
279
+ // styles/global.css.ts
280
+ import { defineGlobalStyles } from '@salty-css/core/factories';
281
+
282
+ export default defineGlobalStyles({
283
+ html: { fontFamily: 'Inter, system-ui, sans-serif' },
284
+ body: { margin: 0, background: '#fff' },
251
285
  });
252
286
  ```
253
287
 
254
- ## Media queries
255
-
256
- Create global media queries that can be either used directly as a scope (e.g. `'@MEDIA_QUERY_NAME': { color: 'blue' }`) or imported to be used in JS.
288
+ ## `defineMediaQuery`
257
289
 
258
290
  ```ts
259
- // /styles/media.css.ts
260
- import { defineMediaQuery } from '@salty-css/react/config';
291
+ // styles/media.css.ts
292
+ import { defineMediaQuery } from '@salty-css/core/factories';
261
293
 
262
- export const largePortraitUp = defineMediaQuery((media) => media.minWidth(600));
263
294
  export const largeMobileDown = defineMediaQuery((media) => media.maxWidth(600));
295
+ export const darkMode = defineMediaQuery((media) => media.prefersColorScheme('dark'));
264
296
  ```
265
297
 
266
- Example usage:
267
-
268
298
  ```ts
269
- styled('span', { base: { fontSize: '64px', '@largeMobileDown': { fontSize: '32px' } } });
299
+ styled('span', { base: { fontSize: 64, '@largeMobileDown': { fontSize: 32 } } });
270
300
  ```
271
301
 
272
- ## Templates
302
+ See [salty-css.dev/docs/media-queries](https://salty-css.dev/docs/media-queries).
273
303
 
274
- With templates you can create reusable styles that can be used in any styles function. Templates can be static (all values defined in the template) or functions (parameters can be passed to define values). Templates can be used in styles by using template's name (e.g. textStyle) as property name and for static a key as the value for functions any supported parameter value can be used as the value.
304
+ ## `defineTemplates`
305
+
306
+ Reusable style bundles. Static templates pick values by dot-path; function templates take a parameter.
275
307
 
276
308
  ```ts
277
- // /styles/templates.css.ts
309
+ // styles/templates.css.ts
278
310
  import { defineTemplates } from '@salty-css/core/factories';
279
311
 
280
312
  export default defineTemplates({
281
- // Static templates for text styles.
282
313
  textStyle: {
283
- headline: {
284
- small: {
285
- fontSize: '{fontSize.heading.small}',
286
- },
287
- regular: {
288
- fontSize: '{fontSize.heading.regular}',
289
- },
290
- large: {
291
- fontSize: '{fontSize.heading.large}',
314
+ heading: {
315
+ base: { fontFamily: '{fontFamily.heading}', lineHeight: 1.1 },
316
+ variants: {
317
+ weight: { regular: { fontWeight: 500 }, heavy: { fontWeight: 800 } },
292
318
  },
319
+ large: { fontSize: '{fontSize.heading.large}' },
320
+ small: { fontSize: '{fontSize.heading.small}' },
293
321
  },
294
- body: {
295
- small: {
296
- fontSize: '{fontSize.body.small}',
297
- lineHeight: '1.5em',
298
- },
299
- regular: {
300
- fontSize: '{fontSize.body.regular}',
301
- lineHeight: '1.33em',
302
- },
303
- },
304
- },
305
- // Dynamic function templates for card styles.
306
- card: (value: string) => {
307
- return {
308
- padding: value,
309
- borderRadius: '8px',
310
- boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)',
311
- };
312
322
  },
323
+ card: (padding: string) => ({
324
+ padding,
325
+ borderRadius: 8,
326
+ boxShadow: '0 0 10px rgba(0,0,0,0.1)',
327
+ }),
328
+ });
329
+ ```
330
+
331
+ ```ts
332
+ styled('h1', { base: { textStyle: 'heading.large@weight=heavy', card: '20px' } });
333
+ ```
334
+
335
+ Rich-node variants, inheritance, and the `compoundVariants`/`anyOfVariants` rules: [salty-css.dev/docs/templates](https://salty-css.dev/docs/templates).
336
+
337
+ ## `defineFont`
338
+
339
+ ```ts
340
+ // styles/fonts.css.ts
341
+ import { defineFont } from '@salty-css/core/factories';
342
+
343
+ export const Inter = defineFont({
344
+ name: 'Inter',
345
+ variable: '--font-inter',
346
+ display: 'swap',
347
+ fallback: 'system-ui, sans-serif',
348
+ variants: [
349
+ { weight: 400, style: 'normal', src: '/fonts/inter-400.woff2' },
350
+ { weight: 700, style: 'normal', src: ['/fonts/inter-700.woff2', '/fonts/inter-700.ttf'] },
351
+ ],
352
+ });
353
+
354
+ // Or pull a remote stylesheet (e.g. Google Fonts) — emits @import + variable.
355
+ export const InterCdn = defineFont({
356
+ name: 'Inter',
357
+ variable: '--font-inter',
358
+ import: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
313
359
  });
314
360
  ```
315
361
 
316
- Example usage:
362
+ `Inter.className`, `Inter.variable`, `Inter.fontFamily`, and `Inter.style` are available for explicit usage. See [salty-css.dev/docs/fonts](https://salty-css.dev/docs/fonts).
363
+
364
+ ## `defineImport`
365
+
366
+ Pull external CSS into Salty's `imports` cascade layer (which sits **before** `reset`, `global`, `templates`, and your component layers — so your styles always win).
317
367
 
318
368
  ```ts
319
- styled('div', { base: { textStyle: 'headline.large', card: '20px' } });
369
+ // styles/imports.css.ts
370
+ import { defineImport } from '@salty-css/core/factories';
371
+
372
+ export default defineImport(
373
+ './reset.css', // relative
374
+ 'modern-normalize/modern-normalize.css', // node_modules
375
+ '~normalize.css/normalize.css', // node_modules (~ form)
376
+ '/fonts/inter.css', // public/ folder
377
+ 'https://fonts.googleapis.com/css2?family=Inter', // URL
378
+ { url: './print.css', media: 'print' }, // media-conditional
379
+ { url: './p3.css', supports: 'color(display-p3 1 1 1)' } // supports-conditional
380
+ );
320
381
  ```
321
382
 
322
- ## Keyframes animations
383
+ Layer order: `@layer imports, reset, global, templates, fonts, l0…l8;`. See [salty-css.dev/docs/imports](https://salty-css.dev/docs/imports).
384
+
385
+ ## `keyframes`
323
386
 
324
387
  ```ts
325
- // /styles/animations.css.ts
388
+ // styles/animations.css.ts
326
389
  import { keyframes } from '@salty-css/react/keyframes';
327
390
 
328
391
  export const fadeIn = keyframes({
329
- // Name of the animation in final CSS
330
392
  animationName: 'fadeIn',
331
- // Add `from` or `0%` to the component's css making it the initial state.
332
- appendInitialStyles: true,
333
- // CSS animation default params used with the value
334
- params: {
335
- delay: '250ms',
336
- fillMode: 'forwards',
337
- },
338
- // Rest is animation timeline
339
- from: {
340
- opacity: 0,
341
- },
342
- to: {
343
- opacity: 1,
344
- },
393
+ appendInitialStyles: true, // injects `from`/`0%` as base styles on the component
394
+ params: { delay: '250ms', fillMode: 'forwards' },
395
+ from: { opacity: 0 },
396
+ to: { opacity: 1 },
345
397
  });
346
398
  ```
347
399
 
348
- Example usage:
349
-
350
400
  ```ts
351
- import { fadeIn } from 'path-to-animations.css.ts';
352
-
353
- export const Wrapper = styled('div', { base: { animation: fadeIn } });
401
+ styled('div', { base: { animation: fadeIn } });
354
402
  ```
355
403
 
356
- ## Viewport clamp
404
+ See [salty-css.dev/docs/animations](https://salty-css.dev/docs/animations).
357
405
 
358
- Create a CSS clamp function based on screen sizes. Useful when aiming to create font sizes or spacings that scale with the screen.
406
+ ## `defineViewportClamp`
359
407
 
360
408
  ```ts
361
- // /styles/clamp.css.ts
362
- import { defineViewportClamp } from '@salty-css/react/helpers';
409
+ // styles/clamp.css.ts
410
+ import { defineViewportClamp } from '@salty-css/core/helpers';
363
411
 
364
412
  export const fhdClamp = defineViewportClamp({ screenSize: 1920 });
365
- export const mobileClamp = defineViewportClamp({ screenSize: 640 });
413
+ export const mobileClamp = defineViewportClamp({ screenSize: 640, axis: 'horizontal' });
366
414
  ```
367
415
 
368
- Example usage:
369
-
370
416
  ```ts
371
417
  styled('span', { base: { fontSize: fhdClamp(96), '@largeMobileDown': { fontSize: mobileClamp(48) } } });
372
418
  ```
373
419
 
374
- ## Color function
375
-
376
- Modify any color easily, add opacity, darken...
420
+ Options: `screenSize`, `axis` (`'horizontal' | 'vertical'`), `minMultiplier`, `maxMultiplier`, `minMaxUnit`. See [salty-css.dev/docs/viewport-clamp](https://salty-css.dev/docs/viewport-clamp).
377
421
 
378
- Example usage:
422
+ ## `color`
379
423
 
380
424
  ```ts
381
425
  import { color } from '@salty-css/core/helpers';
426
+ import { styled } from '@salty-css/react/styled';
382
427
 
383
- export const Wrapper = styled('span', { base: { backgroundColor: color('#000').alpha(0.5) } });
428
+ export const Tint = styled('span', {
429
+ base: { backgroundColor: color('#000').alpha(0.5) },
430
+ });
384
431
  ```
385
432
 
386
- ## Usage
387
-
388
- ### Next.js
389
-
390
- ![salty-next](https://github.com/user-attachments/assets/2cf6a93f-cdd5-4f5f-ab2e-3bc8bcfb83e8)
391
-
392
- Salty CSS provides Next.js App & Pages router support with full React Server Components support.
393
-
394
- ### Add Salty CSS to Next.js
395
-
396
- 1. In your existing Next.js repository you can run `npx salty-css init` to automatically configure Salty CSS.
397
- 2. Create your first Salty CSS component with `npx salty-css generate [filePath]` (e.g. src/custom-wrapper)
398
- 3. Import your component for example to `page.tsx` and see it working!
399
-
400
- And note: steps 2 & 3 are just to show how get new components up and running, step 1 does all of the important stuff 🤯
433
+ Backed by the [Qix-/color](https://github.com/Qix-/color) library — `.alpha()`, `.darken()`, `.lighten()`, `.mix()`, etc. See [salty-css.dev/docs/color-function](https://salty-css.dev/docs/color-function).
401
434
 
402
- #### Manual configuration
435
+ ## Modifiers
403
436
 
404
- 1. For Next.js support install `npm i @salty-css/next @salty-css/core @salty-css/react`
405
- 2. Create `salty.config.ts` to your app directory
406
- 3. Add Salty CSS plugin to next.js config
437
+ Custom value transformers registered on `defineConfig`. Each modifier is a `{ pattern, transform }` pair: when Salty sees a string value matching `pattern`, it replaces it with `transform(match).value` (and optionally emits extra CSS via `transform(match).css`).
407
438
 
408
- - **Next.js 15:** In `next.config.ts` add import for salty plugin `import { withSaltyCss } from '@salty-css/next';` and then add `withSaltyCss` to wrap your nextConfig export like so `export default withSaltyCss(nextConfig);`
409
- - **Next.js 14 and older:** In `next.config.js` add import for salty plugin `const { withSaltyCss } = require('@salty-css/next');` and then add `withSaltyCss` to wrap your nextConfig export like so `module.exports = withSaltyCss(nextConfig);`
410
-
411
- 4. Make sure that `salty.config.ts` and `next.config.ts` are in the same folder!
412
- 5. Build `saltygen` directory by running your app once or with cli `npx salty-css build [directory]`
413
- 6. Import global styles from `saltygen/index.css` to some global css file with `@import 'insert_path_to_index_css';`.
414
-
415
- [Check out Next.js demo project](https://github.com/margarita-form/salty-css-website) or [react example code](#code-examples)
416
-
417
- ---
418
-
419
- ### React + Vite
420
-
421
- ![salty-vite-react](https://github.com/user-attachments/assets/12ec5b6a-0dcc-48fa-afc1-d337fc8f800c)
422
-
423
- ### Add Salty CSS to your React + Vite app
424
-
425
- 1. In your existing Vite repository you can run `npx salty-css init` to automatically configure Salty CSS.
426
- 2. Create your first Salty CSS component with `npx salty-css generate [filePath]` (e.g. src/custom-wrapper)
427
- 3. Import your component for example to `main.tsx` and see it working!
428
-
429
- And note: steps 2 & 3 are just to show how get new components up and running, step 1 does all of the important stuff 🤯
430
-
431
- ### Test it out
439
+ ```ts
440
+ // salty.config.ts
441
+ import { defineConfig } from '@salty-css/core/config';
432
442
 
433
- Check out React + Vite + Salty CSS demo repository at https://github.com/margarita-form/salty-css-react-vite-demo or view it in CodeSandbox:
443
+ export const config = defineConfig({
444
+ modifiers: {
445
+ spaceShorthand: {
446
+ pattern: /^space:(\d+)$/,
447
+ transform: (match) => {
448
+ const n = Number(match.replace('space:', ''));
449
+ return { value: `${n * 4}px` };
450
+ },
451
+ },
452
+ },
453
+ });
454
+ ```
434
455
 
435
- [![Edit margarita-form/salty-css-react-vite-demo/main](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/github/margarita-form/salty-css-react-vite-demo/main?import=true&embed=1)
456
+ ```ts
457
+ styled('div', { base: { padding: 'space:3' } }); // → padding: 12px
458
+ ```
436
459
 
437
- ### Manual configuration
460
+ See [salty-css.dev/docs/modifiers](https://salty-css.dev/docs/modifiers).
438
461
 
439
- 1. For Vite support install `npm i @salty-css/vite @salty-css/core`
440
- 2. In `vite.config` add import for salty plugin `import { saltyPlugin } from '@salty-css/vite';` and then add `saltyPlugin(__dirname)` to your vite configuration plugins
441
- 3. Make sure that `salty.config.ts` and `vite.config.ts` are in the same folder!
442
- 4. Build `saltygen` directory by running your app once or with cli `npx salty-css build [directory]`
443
- 5. Import global styles from `saltygen/index.css` to some global css file with `@import 'insert_path_to_index_css';`.
462
+ ## `withSaltyCss` (Next.js)
444
463
 
445
- [Check out react example code](#code-examples)
464
+ ```ts
465
+ // next.config.ts
466
+ import { withSaltyCss } from '@salty-css/next';
446
467
 
447
- ---
468
+ const nextConfig = {
469
+ /* your config */
470
+ };
471
+ export default withSaltyCss(nextConfig);
472
+ // Or pin a bundler: withSaltyCss(nextConfig, { bundler: 'webpack' })
473
+ ```
448
474
 
449
- ### Create components
475
+ Options: `mode` (build mode override), `bundler` (`'auto' | 'webpack' | 'turbopack'`, defaults to auto-detect via `process.env.TURBOPACK`), `dir` (project root for Turbopack — defaults to `nextConfig.turbopack.root` or `process.cwd()`).
450
476
 
451
- 1. Create salty components with styled only inside files that end with `.css.ts`, `.salty.ts` `.styled.ts` or `.styles.ts`
477
+ Next.js 14 CommonJS:
452
478
 
453
- ## Code examples
479
+ ```js
480
+ const { withSaltyCss } = require('@salty-css/next');
481
+ module.exports = withSaltyCss(nextConfig);
482
+ ```
454
483
 
455
- ### Basic usage example with Button
484
+ See [salty-css.dev/docs/installation](https://salty-css.dev/docs/installation).
456
485
 
457
- **Salty config**
486
+ ## `saltyPlugin` (Vite)
458
487
 
459
- ```tsx
460
- import { defineConfig } from '@salty-css/core/config';
488
+ ```ts
489
+ // vite.config.ts
490
+ import { defineConfig } from 'vite';
491
+ import { saltyPlugin } from '@salty-css/vite';
461
492
 
462
- export const config = defineConfig({
463
- variables: {
464
- colors: {
465
- brand: '#111',
466
- highlight: 'yellow',
467
- },
468
- },
469
- global: {
470
- html: {
471
- backgroundColor: '#f8f8f8',
472
- },
473
- },
493
+ export default defineConfig({
494
+ plugins: [saltyPlugin(__dirname)],
474
495
  });
475
496
  ```
476
497
 
477
- **Wrapper** (`components/wrapper/wrapper.css.ts`)
498
+ Options: `{ mode }`.
478
499
 
479
- ```tsx
480
- import { styled } from '@salty-css/react/styled';
500
+ ## `saltyPlugin` (Webpack)
481
501
 
482
- export const Wrapper = styled('div', {
483
- base: {
484
- display: 'block',
485
- padding: '2vw',
486
- },
487
- });
502
+ ```js
503
+ // webpack.config.js
504
+ const { saltyPlugin } = require('@salty-css/webpack');
505
+
506
+ module.exports = (env, argv) => {
507
+ const config = {
508
+ /* … */
509
+ };
510
+ saltyPlugin(config, __dirname);
511
+ return config;
512
+ };
488
513
  ```
489
514
 
490
- **Button** (`components/button/button.css.ts`)
515
+ Signature: `saltyPlugin(config, dir, isServer?, cjs?, { mode? })`.
491
516
 
492
- ```tsx
493
- import { styled } from '@salty-css/react/styled';
517
+ ## `saltyIntegration` (Astro)
494
518
 
495
- export const Button = styled('button', {
496
- base: {
497
- display: 'block',
498
- padding: `0.6em 1.2em`,
499
- border: '1px solid currentColor',
500
- background: 'transparent',
501
- color: 'currentColor',
502
- cursor: 'pointer',
503
- transition: '200ms',
504
- textDecoration: 'none',
505
- '&:hover': {
506
- background: 'black',
507
- borderColor: 'black',
508
- color: 'white',
509
- },
510
- '&:disabled': {
511
- opacity: 0.25,
512
- pointerEvents: 'none',
513
- },
514
- },
515
- variants: {
516
- variant: {
517
- outlined: {
518
- // same as default styles
519
- },
520
- solid: {
521
- '&:not(:hover)': {
522
- background: 'black',
523
- borderColor: 'black',
524
- color: 'white',
525
- },
526
- '&:hover': {
527
- background: 'transparent',
528
- borderColor: 'currentColor',
529
- color: 'currentColor',
530
- },
531
- },
532
- },
533
- },
519
+ ```ts
520
+ // astro.config.mjs
521
+ import { defineConfig } from 'astro/config';
522
+ import saltyIntegration from '@salty-css/astro/integration';
523
+
524
+ export default defineConfig({
525
+ integrations: [saltyIntegration()],
534
526
  });
535
527
  ```
536
528
 
537
- **Your React component file**
529
+ Options: `srcDir` (defaults to `'src'`), `rootDir` (defaults to the Astro config root).
538
530
 
539
- ```tsx
540
- import { Wrapper } from '../components/wrapper/wrapper.css';
541
- import { Button } from '../components/button/button.css';
542
-
543
- export const IndexPage = () => {
544
- return (
545
- <Wrapper>
546
- <Button variant="solid" onClick={() => alert('It is a button.')}>
547
- Outlined
548
- </Button>
549
- </Wrapper>
550
- );
551
- };
552
- ```
531
+ ---
532
+
533
+ ## Support
553
534
 
554
- More examples coming soon
535
+ Help, questions, or feedback → [Join the Salty CSS Discord](https://discord.gg/R6kr4KxMhP). Bug reports → [GitHub issues](https://github.com/margarita-form/salty-css/issues).
package/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";const m=require("@salty-css/core/compiler/helpers"),S={meta:{type:"problem",fixable:"code",docs:{description:"Ensure `variants` are not nested inside `base` in styled calls",category:"Errors",recommended:!0},messages:{nestedVariants:"`variants` should not be nested inside `base`."}},create(s){return m.isSaltyFile(s.filename)?{CallExpression:o=>{try{const{callee:a,arguments:l}=o;if(!(a.type==="Identifier"&&a.name==="styled"))return;const t=l[1];if(!t||!(t.type==="ObjectExpression"))return;const i=t.properties.find(r=>r.type==="Property"&&r.key.type==="Identifier"&&r.key.name==="base");if(!i)return;const{value:u}=i;if(!(u.type==="ObjectExpression"))return;const n=u.properties.find(r=>r.type==="Property"&&r.key.type==="Identifier"&&r.key.name==="variants");if(!n)return;s.report({node:n,messageId:"nestedVariants",fix:r=>{if(!n.range)return null;const{sourceCode:p}=s,b=p.getText(n),x=t.properties.indexOf(i),f=t.properties[x];if(!f.range)return null;const I=[f.range[1],f.range[1]],y=[n.range[0]-1,n.range[1]];if(u.properties.at(-1)===n){const d=p.text.slice(n.range[1]).match(/^\s*,/);d&&(y[1]+=d[0].length)}return[r.removeRange(y),r.insertTextAfterRange(I,`, ${b}`)]}})}catch(a){console.log("ESlint error",a);return}}}:{}}},v={meta:{type:"problem",fixable:"code",docs:{description:"Salty CSS related function calls or other values must be exported",category:"Errors",recommended:!0},messages:{mustBeExported:"ipsum"}},create(s){if(!m.isSaltyFile(s.filename))return{};function o(e){if(!e)return!1;if((e==null?void 0:e.type)!=="CallExpression")return;const t=["styled","keyframes","className"];if(e.callee.type==="Identifier"&&t.includes(e.callee.name))return!0;const c=/^define[A-Z]/;return!!(e.callee.type==="Identifier"&&c.test(e.callee.name))}function a(e){if(e.type==="VariableDeclaration"){const t=e.declarations[0];return t.type!=="VariableDeclarator"?void 0:o(t.init)}return!1}function l(e){const t=e.parent;return t.type==="ExportNamedDeclaration"||t.type==="ExportDefaultDeclaration"}return{VariableDeclaration:e=>{a(e)&&(l(e)||s.report({node:e,messageId:"mustBeExported",fix:t=>t.insertTextBefore(e,"export ")}))},ExpressionStatement(e){e.type!=="ExpressionStatement"||!o(e.expression)||!(e.parent.type==="Program")||s.report({node:e,messageId:"mustBeExported",fix:i=>i.insertTextBefore(e,"export default ")})}}}},h={rules:{"no-variants-in-base":S,"must-be-exported":v}};module.exports=h;
1
+ "use strict";const m=require("@salty-css/core/compiler/helpers"),I={meta:{type:"problem",fixable:"code",docs:{description:"Ensure `variants` are not nested inside `base` in styled calls",category:"Errors",recommended:!0},messages:{nestedVariants:"`variants` should not be nested inside `base`."}},create(n){return m.isSaltyFile(n.filename)?{CallExpression:o=>{try{const{callee:a,arguments:l}=o;if(!(a.type==="Identifier"&&a.name==="styled"))return;const t=l[1];if(!t||!(t.type==="ObjectExpression"))return;const i=t.properties.find(r=>r.type==="Property"&&r.key.type==="Identifier"&&r.key.name==="base");if(!i)return;const{value:u}=i;if(!(u.type==="ObjectExpression"))return;const s=u.properties.find(r=>r.type==="Property"&&r.key.type==="Identifier"&&r.key.name==="variants");if(!s)return;n.report({node:s,messageId:"nestedVariants",fix:r=>{if(!s.range)return null;const{sourceCode:y}=n,x=y.getText(s),b=t.properties.indexOf(i),f=t.properties[b];if(!f.range)return null;const S=[f.range[1],f.range[1]],p=[s.range[0]-1,s.range[1]];if(u.properties.at(-1)===s){const d=y.text.slice(s.range[1]).match(/^\s*,/);d&&(p[1]+=d[0].length)}return[r.removeRange(p),r.insertTextAfterRange(S,`, ${x}`)]}})}catch(a){console.log("ESlint error",a);return}}}:{}}},h={meta:{type:"problem",fixable:"code",docs:{description:"Salty CSS related function calls or other values must be exported",category:"Errors",recommended:!0},messages:{mustBeExported:"Salty CSS function calls (styled, className, keyframes, defineX) must be exported — the compiler only picks up exports from .css.ts / .salty.ts / .styles.ts / .styled.ts files."}},create(n){if(!m.isSaltyFile(n.filename))return{};function o(e){if(!e)return!1;if((e==null?void 0:e.type)!=="CallExpression")return;const t=["styled","keyframes","className"];if(e.callee.type==="Identifier"&&t.includes(e.callee.name))return!0;const c=/^define[A-Z]/;return!!(e.callee.type==="Identifier"&&c.test(e.callee.name))}function a(e){if(e.type==="VariableDeclaration"){const t=e.declarations[0];return t.type!=="VariableDeclarator"?void 0:o(t.init)}return!1}function l(e){const t=e.parent;return t.type==="ExportNamedDeclaration"||t.type==="ExportDefaultDeclaration"}return{VariableDeclaration:e=>{a(e)&&(l(e)||n.report({node:e,messageId:"mustBeExported",fix:t=>t.insertTextBefore(e,"export ")}))},ExpressionStatement(e){e.type!=="ExpressionStatement"||!o(e.expression)||!(e.parent.type==="Program")||n.report({node:e,messageId:"mustBeExported",fix:i=>i.insertTextBefore(e,"export default ")})}}}},v={rules:{"no-variants-in-base":I,"must-be-exported":h}};module.exports=v;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isSaltyFile as d } from "@salty-css/core/compiler/helpers";
2
- const v = {
2
+ const I = {
3
3
  meta: {
4
4
  type: "problem",
5
5
  fixable: "code",
@@ -16,45 +16,45 @@ const v = {
16
16
  return d(a.filename) ? {
17
17
  CallExpression: (o) => {
18
18
  try {
19
- const { callee: s, arguments: l } = o;
20
- if (!(s.type === "Identifier" && s.name === "styled")) return;
19
+ const { callee: n, arguments: l } = o;
20
+ if (!(n.type === "Identifier" && n.name === "styled")) return;
21
21
  const t = l[1];
22
22
  if (!t || !(t.type === "ObjectExpression")) return;
23
23
  const i = t.properties.find((r) => r.type === "Property" && r.key.type === "Identifier" && r.key.name === "base");
24
24
  if (!i) return;
25
25
  const { value: u } = i;
26
26
  if (!(u.type === "ObjectExpression")) return;
27
- const n = u.properties.find(
27
+ const s = u.properties.find(
28
28
  (r) => r.type === "Property" && r.key.type === "Identifier" && r.key.name === "variants"
29
29
  );
30
- if (!n) return;
30
+ if (!s) return;
31
31
  a.report({
32
- node: n,
32
+ node: s,
33
33
  messageId: "nestedVariants",
34
34
  fix: (r) => {
35
- if (!n.range) return null;
36
- const { sourceCode: p } = a, b = p.getText(n), x = t.properties.indexOf(i), f = t.properties[x];
35
+ if (!s.range) return null;
36
+ const { sourceCode: y } = a, x = y.getText(s), b = t.properties.indexOf(i), f = t.properties[b];
37
37
  if (!f.range) return null;
38
- const I = [f.range[1], f.range[1]], y = [
39
- n.range[0] - 1,
38
+ const S = [f.range[1], f.range[1]], p = [
39
+ s.range[0] - 1,
40
40
  // Include the preceding comma (if any)
41
- n.range[1]
41
+ s.range[1]
42
42
  ];
43
- if (u.properties.at(-1) === n) {
44
- const m = p.text.slice(n.range[1]).match(/^\s*,/);
45
- m && (y[1] += m[0].length);
43
+ if (u.properties.at(-1) === s) {
44
+ const m = y.text.slice(s.range[1]).match(/^\s*,/);
45
+ m && (p[1] += m[0].length);
46
46
  }
47
- return [r.removeRange(y), r.insertTextAfterRange(I, `, ${b}`)];
47
+ return [r.removeRange(p), r.insertTextAfterRange(S, `, ${x}`)];
48
48
  }
49
49
  });
50
- } catch (s) {
51
- console.log("ESlint error", s);
50
+ } catch (n) {
51
+ console.log("ESlint error", n);
52
52
  return;
53
53
  }
54
54
  }
55
55
  } : {};
56
56
  }
57
- }, S = {
57
+ }, v = {
58
58
  meta: {
59
59
  type: "problem",
60
60
  fixable: "code",
@@ -64,7 +64,7 @@ const v = {
64
64
  recommended: !0
65
65
  },
66
66
  messages: {
67
- mustBeExported: "ipsum"
67
+ mustBeExported: "Salty CSS function calls (styled, className, keyframes, defineX) must be exported — the compiler only picks up exports from .css.ts / .salty.ts / .styles.ts / .styled.ts files."
68
68
  }
69
69
  },
70
70
  create(a) {
@@ -77,7 +77,7 @@ const v = {
77
77
  const c = /^define[A-Z]/;
78
78
  return !!(e.callee.type === "Identifier" && c.test(e.callee.name));
79
79
  }
80
- function s(e) {
80
+ function n(e) {
81
81
  if (e.type === "VariableDeclaration") {
82
82
  const t = e.declarations[0];
83
83
  return t.type !== "VariableDeclarator" ? void 0 : o(t.init);
@@ -90,7 +90,7 @@ const v = {
90
90
  }
91
91
  return {
92
92
  VariableDeclaration: (e) => {
93
- s(e) && (l(e) || a.report({
93
+ n(e) && (l(e) || a.report({
94
94
  node: e,
95
95
  messageId: "mustBeExported",
96
96
  fix: (t) => t.insertTextBefore(e, "export ")
@@ -105,12 +105,12 @@ const v = {
105
105
  }
106
106
  };
107
107
  }
108
- }, V = {
108
+ }, k = {
109
109
  rules: {
110
- "no-variants-in-base": v,
111
- "must-be-exported": S
110
+ "no-variants-in-base": I,
111
+ "must-be-exported": v
112
112
  }
113
113
  };
114
114
  export {
115
- V as default
115
+ k as default
116
116
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salty-css/eslint-plugin-core",
3
- "version": "0.1.0-refactor-add-additional-paths-to-config-cache.1",
3
+ "version": "0.1.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "typings": "./dist/index.d.ts",
@@ -34,7 +34,8 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
- "@salty-css/core": "^0.1.0-refactor-add-additional-paths-to-config-cache.1",
37
+ "@salty-css/core": "0.1.0",
38
+ "@types/estree": "1.0.8",
38
39
  "eslint": ">=9.x || >=8.x || >=7.x"
39
40
  }
40
41
  }