@hiscovega/grisso 1.0.5 → 1.0.6
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 +113 -45
- package/lib/build.d.ts +2 -0
- package/lib/build.js +15 -2
- package/lib/cli.js +67 -1
- package/lib/defaults.js +1 -0
- package/lib/purge.js +1 -1
- package/lib/resolve-config.d.ts +0 -1
- package/lib/resolve-config.js +5 -2
- package/lib/tokens.d.ts +14 -0
- package/lib/tokens.js +132 -0
- package/lib/types.d.ts +2 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Grisso
|
|
2
2
|
|
|
3
|
-
> Librería de utility CSS de Griddo
|
|
3
|
+
> Librería de utility CSS de Griddo con valores basados en CSS custom properties (design tokens).
|
|
4
4
|
|
|
5
5
|
## Instalación
|
|
6
6
|
|
|
@@ -10,24 +10,9 @@ npm install @hiscovega/grisso
|
|
|
10
10
|
|
|
11
11
|
## Uso
|
|
12
12
|
|
|
13
|
-
###
|
|
14
|
-
|
|
15
|
-
Importa el CSS pre-compilado directamente. Útil para desarrollo.
|
|
16
|
-
|
|
17
|
-
```css
|
|
18
|
-
/* En tu CSS global */
|
|
19
|
-
@import "@hiscovega/grisso";
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
O en HTML:
|
|
23
|
-
|
|
24
|
-
```html
|
|
25
|
-
<link rel="stylesheet" href="node_modules/@hiscovega/grisso/dist/grisso.css" />
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Opción B: CLI
|
|
13
|
+
### CLI
|
|
29
14
|
|
|
30
|
-
Genera CSS desde la terminal.
|
|
15
|
+
Genera CSS desde la terminal. Forma recomendada de usar Grisso, ideal para scripts de build y CI/CD.
|
|
31
16
|
|
|
32
17
|
```bash
|
|
33
18
|
# CSS completo a stdout
|
|
@@ -42,6 +27,9 @@ npx grisso build --config grisso.config.mjs --output dist/grisso.css
|
|
|
42
27
|
# Tree-shaking (solo clases usadas)
|
|
43
28
|
npx grisso build --content "src/**/*.tsx" --content "src/**/*.css" --output dist/grisso.css
|
|
44
29
|
|
|
30
|
+
# Proteger clases del tree-shaking
|
|
31
|
+
npx grisso build --content "src/**/*.tsx" --safelist "^p-" --safelist "^m-" --output dist/grisso.css
|
|
32
|
+
|
|
45
33
|
# Sin minificar (útil para depuración)
|
|
46
34
|
npx grisso build --no-minify --output dist/grisso.css
|
|
47
35
|
|
|
@@ -51,17 +39,61 @@ npx grisso build | pbcopy
|
|
|
51
39
|
|
|
52
40
|
**Flags de `grisso build`:**
|
|
53
41
|
|
|
54
|
-
| Flag
|
|
55
|
-
|
|
56
|
-
| `--config <ruta>`
|
|
57
|
-
| `--content <glob>`
|
|
58
|
-
| `--
|
|
59
|
-
| `--
|
|
60
|
-
| `--
|
|
42
|
+
| Flag | Descripción |
|
|
43
|
+
| -------------------- | ------------------------------------------- |
|
|
44
|
+
| `--config <ruta>` | Ruta a `grisso.config.mjs` |
|
|
45
|
+
| `--content <glob>` | Globs para tree-shaking (repetible) |
|
|
46
|
+
| `--safelist <regex>` | Patrones de clases a preservar (repetible) |
|
|
47
|
+
| `--output <ruta>` | Archivo de salida (sin `--output` → stdout) |
|
|
48
|
+
| `--no-minify` | Deshabilitar minificación |
|
|
49
|
+
| `--help, -h` | Ayuda del comando |
|
|
61
50
|
|
|
62
51
|
Sin `--output`, el CSS va a stdout y los mensajes de estado a stderr, siguiendo la convención Unix.
|
|
63
52
|
|
|
64
|
-
|
|
53
|
+
#### `grisso tokens`
|
|
54
|
+
|
|
55
|
+
Genera un scaffold con todas las CSS custom properties (design tokens) que necesitas definir. Extrae dinámicamente los tokens de la config resuelta.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Scaffold CSS a stdout
|
|
59
|
+
npx grisso tokens
|
|
60
|
+
|
|
61
|
+
# Escribir a archivo
|
|
62
|
+
npx grisso tokens --output tokens.css
|
|
63
|
+
|
|
64
|
+
# Con config personalizada (refleja extends/overrides)
|
|
65
|
+
npx grisso tokens --config grisso.config.mjs --output tokens.css
|
|
66
|
+
|
|
67
|
+
# Config resuelta como JSON
|
|
68
|
+
npx grisso tokens --format json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Flags de `grisso tokens`:**
|
|
72
|
+
|
|
73
|
+
| Flag | Descripción |
|
|
74
|
+
| ----------------- | ------------------------------------------------- |
|
|
75
|
+
| `--config <ruta>` | Ruta a `grisso.config.mjs` |
|
|
76
|
+
| `--format <fmt>` | Formato de salida: `css` (default) o `json` |
|
|
77
|
+
| `--output <ruta>` | Archivo de salida (sin `--output` → stdout) |
|
|
78
|
+
| `--help, -h` | Ayuda del comando |
|
|
79
|
+
|
|
80
|
+
El scaffold CSS genera un `:root { }` con todas las properties vacías, agrupadas por sección, listo para rellenar:
|
|
81
|
+
|
|
82
|
+
```css
|
|
83
|
+
:root {
|
|
84
|
+
/* ─── Spacing ─── */
|
|
85
|
+
--spc-4xs: ;
|
|
86
|
+
--spc-3xs: ;
|
|
87
|
+
/* ... */
|
|
88
|
+
|
|
89
|
+
/* ─── Colors: marca ─── */
|
|
90
|
+
--brand-1: ;
|
|
91
|
+
--brand-2: ;
|
|
92
|
+
/* ... */
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### API programática
|
|
65
97
|
|
|
66
98
|
Usa `buildCSS()` directamente desde Node.js. Genera, purga y optimiza CSS — ideal para scripts de build, herramientas custom o integración con cualquier bundler.
|
|
67
99
|
|
|
@@ -74,11 +106,12 @@ const css = await buildCSS();
|
|
|
74
106
|
|
|
75
107
|
**Opciones de `buildCSS()`:**
|
|
76
108
|
|
|
77
|
-
| Opción
|
|
78
|
-
|
|
79
|
-
| `config`
|
|
80
|
-
| `content`
|
|
81
|
-
| `
|
|
109
|
+
| Opción | Tipo | Default | Descripción |
|
|
110
|
+
| ---------- | ---------------------- | ------- | ---------------------------------------------------------------- |
|
|
111
|
+
| `config` | `string` | — | Ruta a `grisso.config.mjs` personalizado |
|
|
112
|
+
| `content` | `string[]` | — | Globs de archivos a escanear para tree-shaking |
|
|
113
|
+
| `safelist` | `(string \| RegExp)[]` | — | Patrones de clases a preservar (se mergea con `config.safelist`) |
|
|
114
|
+
| `minify` | `boolean` | `true` | Minificar el CSS de salida |
|
|
82
115
|
|
|
83
116
|
Sin `content`, se incluye todo el CSS. Con `content`, se eliminan las clases no usadas via PurgeCSS.
|
|
84
117
|
|
|
@@ -144,6 +177,30 @@ export default {
|
|
|
144
177
|
};
|
|
145
178
|
```
|
|
146
179
|
|
|
180
|
+
#### `extractTokens()` — scaffold de tokens
|
|
181
|
+
|
|
182
|
+
Usa `extractTokens()` para generar programáticamente el scaffold de custom properties (o JSON) desde la config resuelta.
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import { extractTokens } from "@hiscovega/grisso/tokens";
|
|
186
|
+
|
|
187
|
+
// Scaffold CSS con todas las custom properties
|
|
188
|
+
const css = await extractTokens();
|
|
189
|
+
|
|
190
|
+
// JSON con los token maps resueltos
|
|
191
|
+
const json = await extractTokens({
|
|
192
|
+
format: "json",
|
|
193
|
+
config: "./grisso.config.mjs",
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Opciones de `extractTokens()`:**
|
|
198
|
+
|
|
199
|
+
| Opción | Tipo | Default | Descripción |
|
|
200
|
+
| -------- | ---------------- | ------- | ----------------------------------------- |
|
|
201
|
+
| `config` | `string` | — | Ruta a `grisso.config.mjs` personalizado |
|
|
202
|
+
| `format` | `"css" \| "json"` | `"css"` | Formato de salida |
|
|
203
|
+
|
|
147
204
|
**Servidor de desarrollo** — generar CSS on-the-fly:
|
|
148
205
|
|
|
149
206
|
```js
|
|
@@ -161,7 +218,7 @@ app.get("/grisso.css", async (req, res) => {
|
|
|
161
218
|
|
|
162
219
|
## Configuración personalizada
|
|
163
220
|
|
|
164
|
-
Crea un `grisso.config.mjs` en la raíz de tu proyecto para extender o reemplazar los tokens por defecto.
|
|
221
|
+
Crea un `grisso.config.mjs` en la raíz de tu proyecto para extender o reemplazar los tokens por defecto.
|
|
165
222
|
|
|
166
223
|
```js
|
|
167
224
|
// grisso.config.mjs
|
|
@@ -173,7 +230,7 @@ export default {
|
|
|
173
230
|
lg: "24px",
|
|
174
231
|
},
|
|
175
232
|
|
|
176
|
-
// `extend` MERGEA con los defaults
|
|
233
|
+
// `extend` MERGEA con los defaults (arrays se concatenan)
|
|
177
234
|
extend: {
|
|
178
235
|
foregroundColors: {
|
|
179
236
|
5: "var(--text-5)",
|
|
@@ -181,17 +238,28 @@ export default {
|
|
|
181
238
|
shadows: {
|
|
182
239
|
"2xl": "var(--box-shadow-2xl)",
|
|
183
240
|
},
|
|
241
|
+
// Se concatena con el default []
|
|
242
|
+
safelist: [/^p-/],
|
|
184
243
|
},
|
|
185
244
|
};
|
|
186
245
|
```
|
|
187
246
|
|
|
247
|
+
La `safelist` controla qué clases se protegen del tree-shaking. Por defecto está vacía. En top-level reemplaza, en `extend` se concatena. Acepta `RegExp` y `string`.
|
|
248
|
+
|
|
188
249
|
Si no se pasa `config` a `buildCSS()`, busca automáticamente `grisso.config.mjs` en el directorio de trabajo. Si no existe, usa los defaults.
|
|
189
250
|
|
|
190
251
|
Los defaults se pueden consultar importando `@hiscovega/grisso/config`.
|
|
191
252
|
|
|
192
253
|
## Design Tokens (CSS custom properties)
|
|
193
254
|
|
|
194
|
-
Grisso usa CSS custom properties para todos los valores.
|
|
255
|
+
Grisso usa CSS custom properties para todos los valores. Genera un scaffold con todas las properties que necesitas definir:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Genera scaffold dinámico desde tu config resuelta
|
|
259
|
+
npx grisso tokens --output src/tokens.css
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Alternativamente, copia el ejemplo estático:
|
|
195
263
|
|
|
196
264
|
```bash
|
|
197
265
|
cp node_modules/@hiscovega/grisso/tokens-example.css src/tokens.css
|
|
@@ -236,17 +304,17 @@ Ejemplos: `flex`, `tablet-flex`, `p-md`, `desktop-mt-lg`, `text-center`, `w-1/2`
|
|
|
236
304
|
|
|
237
305
|
### Categorías
|
|
238
306
|
|
|
239
|
-
| Categoría | Ejemplos
|
|
240
|
-
| -------------- |
|
|
307
|
+
| Categoría | Ejemplos |
|
|
308
|
+
| -------------- | ----------------------------------------------------------------------------------------------------- |
|
|
241
309
|
| **Layout** | `flex`, `block`, `hidden`, `relative`, `absolute`, `overflow-hidden`, `inset-0`, `inset-x-sm`, `z-10` |
|
|
242
|
-
| **Flex/Grid** | `flex-col`, `flex-wrap`, `items-center`, `justify-between`, `gap-md`
|
|
243
|
-
| **Spacing** | `p-sm`, `pt-lg`, `mx-auto`, `mt-xs`, `mb-md`
|
|
244
|
-
| **Sizing** | `w-full`, `h-full`, `w-1/2`, `w-2/3`, `h-1/4`, `max-w-full`
|
|
245
|
-
| **Tipografía** | `text-1`, `text-center`, `font-bold`, `font-light`, `leading-snug`, `tracking-tight`
|
|
246
|
-
| **Fondos** | `bg-1`, `bg-ui`, `bg-cover`, `bg-center`
|
|
247
|
-
| **Bordes** | `border-sm`, `border-1`, `border-t-sm`, `divide-x`, `outline-none`
|
|
248
|
-
| **Efectos** | `shadow-md`, `opacity-3`, `overlay-2`
|
|
249
|
-
| **Iconos** | `icon-1`, `icon-3`
|
|
310
|
+
| **Flex/Grid** | `flex-col`, `flex-wrap`, `items-center`, `justify-between`, `gap-md` |
|
|
311
|
+
| **Spacing** | `p-sm`, `pt-lg`, `mx-auto`, `mt-xs`, `mb-md` |
|
|
312
|
+
| **Sizing** | `w-full`, `h-full`, `w-1/2`, `w-2/3`, `h-1/4`, `max-w-full` |
|
|
313
|
+
| **Tipografía** | `text-1`, `text-center`, `font-bold`, `font-light`, `leading-snug`, `tracking-tight` |
|
|
314
|
+
| **Fondos** | `bg-1`, `bg-ui`, `bg-cover`, `bg-center` |
|
|
315
|
+
| **Bordes** | `border-sm`, `border-1`, `border-t-sm`, `divide-x`, `outline-none` |
|
|
316
|
+
| **Efectos** | `shadow-md`, `opacity-3`, `overlay-2` |
|
|
317
|
+
| **Iconos** | `icon-1`, `icon-3` |
|
|
250
318
|
|
|
251
319
|
## Build
|
|
252
320
|
|
|
@@ -261,7 +329,7 @@ npm run playground # Build + tree-shake + abre playground/index.html
|
|
|
261
329
|
|
|
262
330
|
### CLI
|
|
263
331
|
|
|
264
|
-
El CLI se usa internamente y está disponible para consumidores via `npx grisso build`. Ver [
|
|
332
|
+
El CLI se usa internamente y está disponible para consumidores via `npx grisso build`. Ver [CLI](#cli) para detalles completos.
|
|
265
333
|
|
|
266
334
|
Con `--content`, se usa PurgeCSS para eliminar clases no usadas (~154 KB → ~4 KB en el playground).
|
|
267
335
|
|
package/lib/build.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface BuildOptions {
|
|
|
5
5
|
content?: string[];
|
|
6
6
|
/** Minificar el CSS de salida (default: true) */
|
|
7
7
|
minify?: boolean;
|
|
8
|
+
/** Patrones de clases protegidas del tree-shaking (se mergean con config.safelist) */
|
|
9
|
+
safelist?: (string | RegExp)[];
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* API principal de Grisso — genera, purga y optimiza CSS
|
package/lib/build.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { generateCSS } from "./index.js";
|
|
2
2
|
import { optimizeCSS } from "./optimize.js";
|
|
3
3
|
import { purgeCSS } from "./purge.js";
|
|
4
|
+
import { resolveConfig } from "./resolve-config.js";
|
|
5
|
+
/** Convierte strings a RegExp, deja RegExp intactos */
|
|
6
|
+
function toRegExpArray(list) {
|
|
7
|
+
if (!list)
|
|
8
|
+
return [];
|
|
9
|
+
return list.map((item) => (item instanceof RegExp ? item : new RegExp(item)));
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* API principal de Grisso — genera, purga y optimiza CSS
|
|
6
13
|
* sin depender de PostCSS.
|
|
@@ -16,12 +23,18 @@ import { purgeCSS } from "./purge.js";
|
|
|
16
23
|
* });
|
|
17
24
|
*/
|
|
18
25
|
export async function buildCSS(options = {}) {
|
|
19
|
-
const { config, content, minify = true } = options;
|
|
26
|
+
const { config, content, minify = true, safelist: optsSafelist } = options;
|
|
20
27
|
// 1. Generar CSS raw desde los generators
|
|
21
28
|
let css = await generateCSS(config);
|
|
22
29
|
// 2. Tree-shaking si hay rutas de contenido
|
|
23
30
|
if (content && content.length > 0) {
|
|
24
|
-
|
|
31
|
+
// Resolver config para extraer safelist configurada
|
|
32
|
+
const resolved = await resolveConfig(config);
|
|
33
|
+
const mergedSafelist = [
|
|
34
|
+
...toRegExpArray(resolved.safelist),
|
|
35
|
+
...toRegExpArray(optsSafelist),
|
|
36
|
+
];
|
|
37
|
+
css = await purgeCSS(css, { content, safelist: mergedSafelist });
|
|
25
38
|
}
|
|
26
39
|
// 3. Optimizar (nesting, autoprefixer, minificación)
|
|
27
40
|
css = await optimizeCSS(css, { minify });
|
package/lib/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ Uso:
|
|
|
19
19
|
|
|
20
20
|
Comandos:
|
|
21
21
|
build Genera CSS de utilidades
|
|
22
|
+
tokens Genera scaffold de tokens (custom properties)
|
|
22
23
|
|
|
23
24
|
Opciones globales:
|
|
24
25
|
--help, -h Muestra esta ayuda
|
|
@@ -34,6 +35,7 @@ Uso:
|
|
|
34
35
|
Opciones:
|
|
35
36
|
--config <ruta> Ruta a grisso.config.mjs
|
|
36
37
|
--content <glob> Globs para tree-shaking (repetible)
|
|
38
|
+
--safelist <regex> Patrones de clases a preservar (repetible)
|
|
37
39
|
--output <ruta> Archivo de salida (sin --output → stdout)
|
|
38
40
|
--no-minify Deshabilitar minificación
|
|
39
41
|
--help, -h Muestra esta ayuda
|
|
@@ -42,6 +44,7 @@ Ejemplos:
|
|
|
42
44
|
grisso build # CSS completo a stdout
|
|
43
45
|
grisso build --output dist/grisso.css # Escribir a archivo
|
|
44
46
|
grisso build --content "src/**/*.tsx" --output out.css # Tree-shaking
|
|
47
|
+
grisso build --safelist "^p-" --safelist "^m-" # Proteger clases
|
|
45
48
|
grisso build --no-minify # Sin minificar`);
|
|
46
49
|
}
|
|
47
50
|
/** Comando build: genera CSS */
|
|
@@ -51,6 +54,7 @@ async function runBuild(argv) {
|
|
|
51
54
|
options: {
|
|
52
55
|
config: { type: "string" },
|
|
53
56
|
content: { type: "string", multiple: true },
|
|
57
|
+
safelist: { type: "string", multiple: true },
|
|
54
58
|
output: { type: "string" },
|
|
55
59
|
minify: { type: "boolean", default: true },
|
|
56
60
|
help: { type: "boolean", short: "h", default: false },
|
|
@@ -65,6 +69,7 @@ async function runBuild(argv) {
|
|
|
65
69
|
// Import dinámico para que --help sea instantáneo
|
|
66
70
|
const { buildCSS } = await import("./build.js");
|
|
67
71
|
const content = values.content && values.content.length > 0 ? values.content : undefined;
|
|
72
|
+
const safelist = values.safelist && values.safelist.length > 0 ? values.safelist : undefined;
|
|
68
73
|
if (values.output) {
|
|
69
74
|
const label = content
|
|
70
75
|
? "Generando CSS con tree-shaking..."
|
|
@@ -75,6 +80,7 @@ async function runBuild(argv) {
|
|
|
75
80
|
config: values.config,
|
|
76
81
|
content,
|
|
77
82
|
minify: values.minify,
|
|
83
|
+
safelist,
|
|
78
84
|
});
|
|
79
85
|
if (values.output) {
|
|
80
86
|
const outputPath = path.resolve(values.output);
|
|
@@ -90,6 +96,63 @@ async function runBuild(argv) {
|
|
|
90
96
|
process.stdout.write(css);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
99
|
+
/** Texto de ayuda del comando tokens */
|
|
100
|
+
function printTokensHelp() {
|
|
101
|
+
console.log(`grisso tokens — Genera scaffold de tokens (custom properties)
|
|
102
|
+
|
|
103
|
+
Uso:
|
|
104
|
+
grisso tokens [opciones]
|
|
105
|
+
|
|
106
|
+
Opciones:
|
|
107
|
+
--config <ruta> Ruta a grisso.config.mjs
|
|
108
|
+
--format <fmt> Formato de salida: css (default) o json
|
|
109
|
+
--output <ruta> Archivo de salida (sin --output → stdout)
|
|
110
|
+
--help, -h Muestra esta ayuda
|
|
111
|
+
|
|
112
|
+
Ejemplos:
|
|
113
|
+
grisso tokens # Scaffold CSS a stdout
|
|
114
|
+
grisso tokens --output tokens.css # Escribir a archivo
|
|
115
|
+
grisso tokens --config grisso.config.mjs # Usa config custom
|
|
116
|
+
grisso tokens --format json # Config como JSON`);
|
|
117
|
+
}
|
|
118
|
+
/** Comando tokens: genera scaffold de tokens */
|
|
119
|
+
async function runTokens(argv) {
|
|
120
|
+
const { values } = parseArgs({
|
|
121
|
+
args: argv,
|
|
122
|
+
options: {
|
|
123
|
+
config: { type: "string" },
|
|
124
|
+
format: { type: "string" },
|
|
125
|
+
output: { type: "string" },
|
|
126
|
+
help: { type: "boolean", short: "h", default: false },
|
|
127
|
+
},
|
|
128
|
+
strict: true,
|
|
129
|
+
});
|
|
130
|
+
if (values.help) {
|
|
131
|
+
printTokensHelp();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const format = values.format;
|
|
135
|
+
if (format && format !== "css" && format !== "json") {
|
|
136
|
+
console.error(`Formato no soportado: ${format} (usa "css" o "json")`);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
// Import dinámico para que --help sea instantáneo
|
|
140
|
+
const { extractTokens } = await import("./tokens.js");
|
|
141
|
+
const output = await extractTokens({ config: values.config, format });
|
|
142
|
+
if (values.output) {
|
|
143
|
+
const outputPath = path.resolve(values.output);
|
|
144
|
+
const dir = path.dirname(outputPath);
|
|
145
|
+
if (!fs.existsSync(dir)) {
|
|
146
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
147
|
+
}
|
|
148
|
+
fs.writeFileSync(outputPath, output);
|
|
149
|
+
const kb = (Buffer.byteLength(output, "utf8") / 1024).toFixed(1);
|
|
150
|
+
console.error(`Generado ${path.relative(process.cwd(), outputPath)} (${kb} KB)`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
process.stdout.write(output);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
93
156
|
/** Punto de entrada */
|
|
94
157
|
async function main() {
|
|
95
158
|
const { values, positionals } = parseArgs({
|
|
@@ -116,9 +179,12 @@ async function main() {
|
|
|
116
179
|
}
|
|
117
180
|
switch (command) {
|
|
118
181
|
case "build":
|
|
119
|
-
// Pasar solo los args después
|
|
182
|
+
// Pasar solo los args después del comando
|
|
120
183
|
await runBuild(process.argv.slice(3));
|
|
121
184
|
break;
|
|
185
|
+
case "tokens":
|
|
186
|
+
await runTokens(process.argv.slice(3));
|
|
187
|
+
break;
|
|
122
188
|
default:
|
|
123
189
|
console.error(`Comando desconocido: ${command}`);
|
|
124
190
|
printHelp();
|
package/lib/defaults.js
CHANGED
package/lib/purge.js
CHANGED
package/lib/resolve-config.d.ts
CHANGED
package/lib/resolve-config.js
CHANGED
|
@@ -3,7 +3,6 @@ import { pathToFileURL } from "node:url";
|
|
|
3
3
|
import defaults from "./defaults.js";
|
|
4
4
|
/**
|
|
5
5
|
* Resuelve la configuración de Grisso.
|
|
6
|
-
* Patrón Tailwind v3:
|
|
7
6
|
* - Top-level keys reemplazan los defaults completamente
|
|
8
7
|
* - `extend` mergea superficialmente con defaults
|
|
9
8
|
*/
|
|
@@ -36,7 +35,11 @@ export async function resolveConfig(configPath) {
|
|
|
36
35
|
if (extend && typeof extend === "object" && !Array.isArray(extend)) {
|
|
37
36
|
for (const [key, value] of Object.entries(extend)) {
|
|
38
37
|
const current = config[key];
|
|
39
|
-
if (key in config &&
|
|
38
|
+
if (key in config && Array.isArray(current) && Array.isArray(value)) {
|
|
39
|
+
// Arrays se concatenan (e.g. safelist)
|
|
40
|
+
config[key] = [...current, ...value];
|
|
41
|
+
}
|
|
42
|
+
else if (key in config &&
|
|
40
43
|
typeof current === "object" &&
|
|
41
44
|
current !== null &&
|
|
42
45
|
!Array.isArray(current)) {
|
package/lib/tokens.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface TokensOptions {
|
|
2
|
+
/** Ruta a grisso.config.mjs del consumidor */
|
|
3
|
+
config?: string;
|
|
4
|
+
/** Formato de salida: CSS scaffold o JSON (default: "css") */
|
|
5
|
+
format?: "css" | "json";
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Extrae tokens de la config resuelta y genera un scaffold CSS o JSON.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const css = await extractTokens();
|
|
12
|
+
* const json = await extractTokens({ format: "json" });
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractTokens(options?: TokensOptions): Promise<string>;
|
package/lib/tokens.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { resolveConfig } from "./resolve-config.js";
|
|
2
|
+
/** Orden fijo de secciones — matchea defaults.ts y tokens-example.css */
|
|
3
|
+
const TOKEN_MAP_KEYS = [
|
|
4
|
+
"spacing",
|
|
5
|
+
"brandColors",
|
|
6
|
+
"foregroundColors",
|
|
7
|
+
"iconColors",
|
|
8
|
+
"supportColors",
|
|
9
|
+
"backgroundColors",
|
|
10
|
+
"overlayColors",
|
|
11
|
+
"borderWidth",
|
|
12
|
+
"opacity",
|
|
13
|
+
"shadows",
|
|
14
|
+
"borderColors",
|
|
15
|
+
];
|
|
16
|
+
/** Labels para los headers CSS de cada sección */
|
|
17
|
+
const SECTION_LABELS = {
|
|
18
|
+
spacing: "Spacing",
|
|
19
|
+
brandColors: "Colors: marca",
|
|
20
|
+
foregroundColors: "Colors: texto",
|
|
21
|
+
iconColors: "Colors: iconos",
|
|
22
|
+
supportColors: "Colors: soporte",
|
|
23
|
+
backgroundColors: "Colors: fondo",
|
|
24
|
+
overlayColors: "Colors: overlays",
|
|
25
|
+
borderWidth: "Border widths",
|
|
26
|
+
opacity: "Opacidad",
|
|
27
|
+
shadows: "Sombras",
|
|
28
|
+
borderColors: "Colors: bordes",
|
|
29
|
+
};
|
|
30
|
+
/** Keys que NO son token maps */
|
|
31
|
+
const NON_TOKEN_KEYS = new Set([
|
|
32
|
+
"columns",
|
|
33
|
+
"breakpoints",
|
|
34
|
+
"safelist",
|
|
35
|
+
"extend",
|
|
36
|
+
]);
|
|
37
|
+
const VAR_RE = /var\(--([\w-]+)\)/g;
|
|
38
|
+
/** Extrae nombres de custom properties de un token map, deduplicados y en orden */
|
|
39
|
+
function extractVarNames(tokenMap) {
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
const result = [];
|
|
42
|
+
for (const value of Object.values(tokenMap)) {
|
|
43
|
+
for (const match of value.matchAll(VAR_RE)) {
|
|
44
|
+
const name = match[1];
|
|
45
|
+
if (!seen.has(name)) {
|
|
46
|
+
seen.add(name);
|
|
47
|
+
result.push(name);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/** Genera scaffold CSS con todas las custom properties */
|
|
54
|
+
function formatCSS(config) {
|
|
55
|
+
const lines = [];
|
|
56
|
+
lines.push("/* @hiscovega/grisso — tokens scaffold", " Define estas variables en :root o en el scope que prefieras.", " Generado desde la config resuelta de Grisso.", "*/", "", ":root {");
|
|
57
|
+
let hasSections = false;
|
|
58
|
+
// Secciones conocidas en orden fijo
|
|
59
|
+
for (const key of TOKEN_MAP_KEYS) {
|
|
60
|
+
const map = config[key];
|
|
61
|
+
if (!map || typeof map !== "object")
|
|
62
|
+
continue;
|
|
63
|
+
const vars = extractVarNames(map);
|
|
64
|
+
if (vars.length === 0)
|
|
65
|
+
continue;
|
|
66
|
+
const label = SECTION_LABELS[key] || key;
|
|
67
|
+
if (hasSections)
|
|
68
|
+
lines.push("");
|
|
69
|
+
lines.push(`\t/* ─── ${label} ${"─".repeat(Math.max(1, 55 - label.length))} */`);
|
|
70
|
+
for (const name of vars) {
|
|
71
|
+
lines.push(`\t--${name}: ;`);
|
|
72
|
+
}
|
|
73
|
+
hasSections = true;
|
|
74
|
+
}
|
|
75
|
+
// Secciones custom del consumidor (keys desconocidas que sean objetos)
|
|
76
|
+
for (const [key, value] of Object.entries(config)) {
|
|
77
|
+
if (NON_TOKEN_KEYS.has(key))
|
|
78
|
+
continue;
|
|
79
|
+
if (TOKEN_MAP_KEYS.includes(key))
|
|
80
|
+
continue;
|
|
81
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
82
|
+
continue;
|
|
83
|
+
const vars = extractVarNames(value);
|
|
84
|
+
if (vars.length === 0)
|
|
85
|
+
continue;
|
|
86
|
+
if (hasSections)
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push(`\t/* ─── ${key} ${"─".repeat(Math.max(1, 55 - key.length))} */`);
|
|
89
|
+
for (const name of vars) {
|
|
90
|
+
lines.push(`\t--${name}: ;`);
|
|
91
|
+
}
|
|
92
|
+
hasSections = true;
|
|
93
|
+
}
|
|
94
|
+
lines.push("}", "");
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
/** Genera JSON con los token maps de la config resuelta */
|
|
98
|
+
function formatJSON(config) {
|
|
99
|
+
const result = {};
|
|
100
|
+
for (const key of TOKEN_MAP_KEYS) {
|
|
101
|
+
const map = config[key];
|
|
102
|
+
if (map && typeof map === "object") {
|
|
103
|
+
result[key] = map;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Incluir token maps custom del consumidor
|
|
107
|
+
for (const [key, value] of Object.entries(config)) {
|
|
108
|
+
if (NON_TOKEN_KEYS.has(key))
|
|
109
|
+
continue;
|
|
110
|
+
if (TOKEN_MAP_KEYS.includes(key))
|
|
111
|
+
continue;
|
|
112
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
113
|
+
continue;
|
|
114
|
+
result[key] = value;
|
|
115
|
+
}
|
|
116
|
+
return JSON.stringify(result, null, "\t");
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Extrae tokens de la config resuelta y genera un scaffold CSS o JSON.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* const css = await extractTokens();
|
|
123
|
+
* const json = await extractTokens({ format: "json" });
|
|
124
|
+
*/
|
|
125
|
+
export async function extractTokens(options = {}) {
|
|
126
|
+
const { config: configPath, format = "css" } = options;
|
|
127
|
+
const config = await resolveConfig(configPath);
|
|
128
|
+
if (format === "json") {
|
|
129
|
+
return formatJSON(config);
|
|
130
|
+
}
|
|
131
|
+
return formatCSS(config);
|
|
132
|
+
}
|
package/lib/types.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export interface GrissoConfig {
|
|
|
19
19
|
opacity: TokenMap;
|
|
20
20
|
shadows: TokenMap;
|
|
21
21
|
borderColors: TokenMap;
|
|
22
|
+
/** Patrones de clases protegidas del tree-shaking */
|
|
23
|
+
safelist: (string | RegExp)[];
|
|
22
24
|
[key: string]: unknown;
|
|
23
25
|
}
|
|
24
26
|
/** Función parcial que genera CSS a partir de la config */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hiscovega/grisso",
|
|
3
3
|
"description": "Griddo CSS utility class library",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.6",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"style": "./dist/grisso.css"
|
|
11
11
|
},
|
|
12
12
|
"./build": "./lib/build.js",
|
|
13
|
+
"./tokens": "./lib/tokens.js",
|
|
13
14
|
"./config": "./lib/defaults.js",
|
|
14
15
|
"./tokens-example.css": "./tokens-example.css"
|
|
15
16
|
},
|