@hiscovega/grisso 1.0.4 → 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 +135 -70
- package/dist/grisso.css +1 -1
- package/lib/build.d.ts +2 -0
- package/lib/build.js +15 -2
- package/lib/cli.d.ts +2 -0
- package/lib/cli.js +197 -0
- package/lib/defaults.js +1 -0
- package/lib/generators.d.ts +0 -4
- package/lib/generators.js +13 -6
- package/lib/partials/borders.js +7 -0
- package/lib/partials/layout.js +13 -9
- package/lib/partials/sizing.js +33 -5
- package/lib/partials/typography.js +10 -3
- package/lib/purge.js +3 -3
- 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 +7 -17
- package/plugin.cjs +0 -5
- package/plugin.js +0 -43
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.d.ts
ADDED
package/lib/cli.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseArgs } from "node:util";
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
/** Lee la versión desde package.json */
|
|
8
|
+
function getVersion() {
|
|
9
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf8"));
|
|
10
|
+
return pkg.version;
|
|
11
|
+
}
|
|
12
|
+
/** Texto de ayuda general */
|
|
13
|
+
function printHelp() {
|
|
14
|
+
const version = getVersion();
|
|
15
|
+
console.log(`grisso v${version} — Griddo CSS utility class library
|
|
16
|
+
|
|
17
|
+
Uso:
|
|
18
|
+
grisso <comando> [opciones]
|
|
19
|
+
|
|
20
|
+
Comandos:
|
|
21
|
+
build Genera CSS de utilidades
|
|
22
|
+
tokens Genera scaffold de tokens (custom properties)
|
|
23
|
+
|
|
24
|
+
Opciones globales:
|
|
25
|
+
--help, -h Muestra esta ayuda
|
|
26
|
+
--version, -v Muestra la versión`);
|
|
27
|
+
}
|
|
28
|
+
/** Texto de ayuda del comando build */
|
|
29
|
+
function printBuildHelp() {
|
|
30
|
+
console.log(`grisso build — Genera CSS de utilidades
|
|
31
|
+
|
|
32
|
+
Uso:
|
|
33
|
+
grisso build [opciones]
|
|
34
|
+
|
|
35
|
+
Opciones:
|
|
36
|
+
--config <ruta> Ruta a grisso.config.mjs
|
|
37
|
+
--content <glob> Globs para tree-shaking (repetible)
|
|
38
|
+
--safelist <regex> Patrones de clases a preservar (repetible)
|
|
39
|
+
--output <ruta> Archivo de salida (sin --output → stdout)
|
|
40
|
+
--no-minify Deshabilitar minificación
|
|
41
|
+
--help, -h Muestra esta ayuda
|
|
42
|
+
|
|
43
|
+
Ejemplos:
|
|
44
|
+
grisso build # CSS completo a stdout
|
|
45
|
+
grisso build --output dist/grisso.css # Escribir a archivo
|
|
46
|
+
grisso build --content "src/**/*.tsx" --output out.css # Tree-shaking
|
|
47
|
+
grisso build --safelist "^p-" --safelist "^m-" # Proteger clases
|
|
48
|
+
grisso build --no-minify # Sin minificar`);
|
|
49
|
+
}
|
|
50
|
+
/** Comando build: genera CSS */
|
|
51
|
+
async function runBuild(argv) {
|
|
52
|
+
const { values } = parseArgs({
|
|
53
|
+
args: argv,
|
|
54
|
+
options: {
|
|
55
|
+
config: { type: "string" },
|
|
56
|
+
content: { type: "string", multiple: true },
|
|
57
|
+
safelist: { type: "string", multiple: true },
|
|
58
|
+
output: { type: "string" },
|
|
59
|
+
minify: { type: "boolean", default: true },
|
|
60
|
+
help: { type: "boolean", short: "h", default: false },
|
|
61
|
+
},
|
|
62
|
+
strict: true,
|
|
63
|
+
allowNegative: true,
|
|
64
|
+
});
|
|
65
|
+
if (values.help) {
|
|
66
|
+
printBuildHelp();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Import dinámico para que --help sea instantáneo
|
|
70
|
+
const { buildCSS } = await import("./build.js");
|
|
71
|
+
const content = values.content && values.content.length > 0 ? values.content : undefined;
|
|
72
|
+
const safelist = values.safelist && values.safelist.length > 0 ? values.safelist : undefined;
|
|
73
|
+
if (values.output) {
|
|
74
|
+
const label = content
|
|
75
|
+
? "Generando CSS con tree-shaking..."
|
|
76
|
+
: "Generando CSS...";
|
|
77
|
+
console.error(label);
|
|
78
|
+
}
|
|
79
|
+
const css = await buildCSS({
|
|
80
|
+
config: values.config,
|
|
81
|
+
content,
|
|
82
|
+
minify: values.minify,
|
|
83
|
+
safelist,
|
|
84
|
+
});
|
|
85
|
+
if (values.output) {
|
|
86
|
+
const outputPath = path.resolve(values.output);
|
|
87
|
+
const dir = path.dirname(outputPath);
|
|
88
|
+
if (!fs.existsSync(dir)) {
|
|
89
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
fs.writeFileSync(outputPath, css);
|
|
92
|
+
const kb = (Buffer.byteLength(css, "utf8") / 1024).toFixed(1);
|
|
93
|
+
console.error(`Generado ${path.relative(process.cwd(), outputPath)} (${kb} KB)`);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
process.stdout.write(css);
|
|
97
|
+
}
|
|
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
|
+
}
|
|
156
|
+
/** Punto de entrada */
|
|
157
|
+
async function main() {
|
|
158
|
+
const { values, positionals } = parseArgs({
|
|
159
|
+
args: process.argv.slice(2),
|
|
160
|
+
options: {
|
|
161
|
+
help: { type: "boolean", short: "h", default: false },
|
|
162
|
+
version: { type: "boolean", short: "v", default: false },
|
|
163
|
+
},
|
|
164
|
+
strict: false,
|
|
165
|
+
allowPositionals: true,
|
|
166
|
+
});
|
|
167
|
+
if (values.version) {
|
|
168
|
+
console.log(getVersion());
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const command = positionals[0];
|
|
172
|
+
if (values.help && !command) {
|
|
173
|
+
printHelp();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!command) {
|
|
177
|
+
printHelp();
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
switch (command) {
|
|
181
|
+
case "build":
|
|
182
|
+
// Pasar solo los args después del comando
|
|
183
|
+
await runBuild(process.argv.slice(3));
|
|
184
|
+
break;
|
|
185
|
+
case "tokens":
|
|
186
|
+
await runTokens(process.argv.slice(3));
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
console.error(`Comando desconocido: ${command}`);
|
|
190
|
+
printHelp();
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
main().catch((err) => {
|
|
195
|
+
console.error(err);
|
|
196
|
+
process.exit(1);
|
|
197
|
+
});
|
package/lib/defaults.js
CHANGED
package/lib/generators.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import type { Breakpoints, Declarations, TokenMap } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Generadores de clases CSS utility.
|
|
4
|
-
* Replican los mixins grisso_simple_class, grisso_complex_class de SCSS.
|
|
5
|
-
*/
|
|
6
2
|
/**
|
|
7
3
|
* Genera una clase simple con variantes responsive.
|
|
8
4
|
* Equivalente al mixin grisso_simple_class.
|
package/lib/generators.js
CHANGED
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
* Generadores de clases CSS utility.
|
|
3
3
|
* Replican los mixins grisso_simple_class, grisso_complex_class de SCSS.
|
|
4
4
|
*/
|
|
5
|
+
/** Escapa caracteres especiales en classNames para selectores CSS válidos. */
|
|
6
|
+
function escapeCSS(name) {
|
|
7
|
+
return name.replace(/\//g, "\\/");
|
|
8
|
+
}
|
|
5
9
|
/**
|
|
6
10
|
* Genera una clase simple con variantes responsive.
|
|
7
11
|
* Equivalente al mixin grisso_simple_class.
|
|
8
12
|
*/
|
|
9
13
|
export function simpleClass(className, property, value, breakpoints) {
|
|
10
|
-
|
|
14
|
+
const escaped = escapeCSS(className);
|
|
15
|
+
let css = `.${escaped} { ${property}: ${value}; }\n`;
|
|
11
16
|
for (const [bp, mq] of Object.entries(breakpoints)) {
|
|
12
|
-
css += `@media ${mq} { .${bp}-${
|
|
17
|
+
css += `@media ${mq} { .${bp}-${escaped} { ${property}: ${value}; } }\n`;
|
|
13
18
|
}
|
|
14
19
|
return css;
|
|
15
20
|
}
|
|
@@ -21,12 +26,13 @@ export function complexClass(prefix, properties, tokens, breakpoints) {
|
|
|
21
26
|
const props = Array.isArray(properties) ? properties : [properties];
|
|
22
27
|
let css = "";
|
|
23
28
|
for (const [name, value] of Object.entries(tokens)) {
|
|
29
|
+
const escaped = escapeCSS(`${prefix}${name}`);
|
|
24
30
|
for (const prop of props) {
|
|
25
|
-
css += `.${
|
|
31
|
+
css += `.${escaped} { ${prop}: ${value}; }\n`;
|
|
26
32
|
}
|
|
27
33
|
for (const [bp, mq] of Object.entries(breakpoints)) {
|
|
28
34
|
for (const prop of props) {
|
|
29
|
-
css += `@media ${mq} { .${bp}-${
|
|
35
|
+
css += `@media ${mq} { .${bp}-${escaped} { ${prop}: ${value}; } }\n`;
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
38
|
}
|
|
@@ -37,13 +43,14 @@ export function complexClass(prefix, properties, tokens, breakpoints) {
|
|
|
37
43
|
* Para casos especiales: divide >*+*, truncate, smoothing, outline-none, etc.
|
|
38
44
|
*/
|
|
39
45
|
export function customClass(className, declarations, breakpoints, selectorSuffix) {
|
|
46
|
+
const escaped = escapeCSS(className);
|
|
40
47
|
const suffix = selectorSuffix || "";
|
|
41
48
|
const decls = Object.entries(declarations)
|
|
42
49
|
.map(([p, v]) => `${p}: ${v}`)
|
|
43
50
|
.join("; ");
|
|
44
|
-
let css = `.${
|
|
51
|
+
let css = `.${escaped}${suffix} { ${decls}; }\n`;
|
|
45
52
|
for (const [bp, mq] of Object.entries(breakpoints)) {
|
|
46
|
-
css += `@media ${mq} { .${bp}-${
|
|
53
|
+
css += `@media ${mq} { .${bp}-${escaped}${suffix} { ${decls}; } }\n`;
|
|
47
54
|
}
|
|
48
55
|
return css;
|
|
49
56
|
}
|
package/lib/partials/borders.js
CHANGED
|
@@ -19,6 +19,13 @@ export default function borders(config) {
|
|
|
19
19
|
};
|
|
20
20
|
// border-width
|
|
21
21
|
css += complexClass("border-", "border-width", borderWidth, breakpoints);
|
|
22
|
+
// border-{side}-width
|
|
23
|
+
css += complexClass("border-t-", "border-top-width", borderWidth, breakpoints);
|
|
24
|
+
css += complexClass("border-r-", "border-right-width", borderWidth, breakpoints);
|
|
25
|
+
css += complexClass("border-b-", "border-bottom-width", borderWidth, breakpoints);
|
|
26
|
+
css += complexClass("border-l-", "border-left-width", borderWidth, breakpoints);
|
|
27
|
+
// border-color
|
|
28
|
+
css += complexClass("border-", "border-color", extendedColors, breakpoints);
|
|
22
29
|
// border-style
|
|
23
30
|
css += complexClass("border-", "border-style", borderStyle, breakpoints);
|
|
24
31
|
// divide-color
|
package/lib/partials/layout.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { complexClass, simpleClass } from "../generators.js";
|
|
1
|
+
import { complexClass, customClass, simpleClass } from "../generators.js";
|
|
2
2
|
export default function layout(config) {
|
|
3
3
|
const { columns, breakpoints, spacing } = config;
|
|
4
4
|
let css = "";
|
|
@@ -31,8 +31,6 @@ export default function layout(config) {
|
|
|
31
31
|
for (let i = 1; i <= columns; i++) {
|
|
32
32
|
css += simpleClass(`columns-${i}`, "columns", String(i), breakpoints);
|
|
33
33
|
}
|
|
34
|
-
// columns (spacing tokens)
|
|
35
|
-
css += complexClass("columns-", "columns", spacing, breakpoints);
|
|
36
34
|
// float
|
|
37
35
|
const float = {
|
|
38
36
|
left: "left",
|
|
@@ -98,14 +96,14 @@ export default function layout(config) {
|
|
|
98
96
|
const zIndex = {
|
|
99
97
|
auto: "auto",
|
|
100
98
|
"0": "0",
|
|
101
|
-
"
|
|
99
|
+
"10": "10",
|
|
102
100
|
"20": "20",
|
|
103
101
|
"30": "30",
|
|
104
102
|
"40": "40",
|
|
105
103
|
"50": "50",
|
|
106
104
|
};
|
|
107
105
|
const zIndexNeg = {
|
|
108
|
-
"
|
|
106
|
+
"10": "-10",
|
|
109
107
|
"20": "-20",
|
|
110
108
|
"30": "-30",
|
|
111
109
|
"40": "-40",
|
|
@@ -114,13 +112,19 @@ export default function layout(config) {
|
|
|
114
112
|
css += complexClass("z-", "z-index", zIndex, breakpoints);
|
|
115
113
|
css += complexClass("-z-", "z-index", zIndexNeg, breakpoints);
|
|
116
114
|
// top/right/bottom/left
|
|
117
|
-
css += simpleClass("top-0", "top", "0", breakpoints);
|
|
118
|
-
css += simpleClass("right-0", "right", "0", breakpoints);
|
|
119
|
-
css += simpleClass("bottom-0", "bottom", "0", breakpoints);
|
|
120
|
-
css += simpleClass("left-0", "left", "0", breakpoints);
|
|
121
115
|
css += complexClass("top-", "top", spacing, breakpoints);
|
|
122
116
|
css += complexClass("right-", "right", spacing, breakpoints);
|
|
123
117
|
css += complexClass("bottom-", "bottom", spacing, breakpoints);
|
|
124
118
|
css += complexClass("left-", "left", spacing, breakpoints);
|
|
119
|
+
// inset (top + right + bottom + left)
|
|
120
|
+
css += complexClass("inset-", "inset", spacing, breakpoints);
|
|
121
|
+
// inset-x (left + right)
|
|
122
|
+
for (const [key, value] of Object.entries(spacing)) {
|
|
123
|
+
css += customClass(`inset-x-${key}`, { left: value, right: value }, breakpoints);
|
|
124
|
+
}
|
|
125
|
+
// inset-y (top + bottom)
|
|
126
|
+
for (const [key, value] of Object.entries(spacing)) {
|
|
127
|
+
css += customClass(`inset-y-${key}`, { top: value, bottom: value }, breakpoints);
|
|
128
|
+
}
|
|
125
129
|
return css;
|
|
126
130
|
}
|
package/lib/partials/sizing.js
CHANGED
|
@@ -1,7 +1,35 @@
|
|
|
1
1
|
import { complexClass, simpleClass } from "../generators.js";
|
|
2
2
|
import { fractionPercent } from "../utils.js";
|
|
3
|
+
const fractions = [
|
|
4
|
+
[1, 2],
|
|
5
|
+
[1, 3],
|
|
6
|
+
[2, 3],
|
|
7
|
+
[1, 4],
|
|
8
|
+
[2, 4],
|
|
9
|
+
[3, 4],
|
|
10
|
+
[1, 5],
|
|
11
|
+
[2, 5],
|
|
12
|
+
[3, 5],
|
|
13
|
+
[4, 5],
|
|
14
|
+
[1, 6],
|
|
15
|
+
[2, 6],
|
|
16
|
+
[3, 6],
|
|
17
|
+
[4, 6],
|
|
18
|
+
[5, 6],
|
|
19
|
+
[1, 12],
|
|
20
|
+
[2, 12],
|
|
21
|
+
[3, 12],
|
|
22
|
+
[4, 12],
|
|
23
|
+
[5, 12],
|
|
24
|
+
[6, 12],
|
|
25
|
+
[7, 12],
|
|
26
|
+
[8, 12],
|
|
27
|
+
[9, 12],
|
|
28
|
+
[10, 12],
|
|
29
|
+
[11, 12],
|
|
30
|
+
];
|
|
3
31
|
export default function sizing(config) {
|
|
4
|
-
const {
|
|
32
|
+
const { breakpoints } = config;
|
|
5
33
|
let css = "";
|
|
6
34
|
// width
|
|
7
35
|
const width = {
|
|
@@ -14,8 +42,8 @@ export default function sizing(config) {
|
|
|
14
42
|
fit: "fit-content",
|
|
15
43
|
};
|
|
16
44
|
css += complexClass("w-", "width", width, breakpoints);
|
|
17
|
-
for (
|
|
18
|
-
css += simpleClass(`w-${
|
|
45
|
+
for (const [n, d] of fractions) {
|
|
46
|
+
css += simpleClass(`w-${n}/${d}`, "width", fractionPercent(n, d), breakpoints);
|
|
19
47
|
}
|
|
20
48
|
css += complexClass("min-w-", "min-width", width, breakpoints);
|
|
21
49
|
css += complexClass("max-w-", "max-width", width, breakpoints);
|
|
@@ -30,8 +58,8 @@ export default function sizing(config) {
|
|
|
30
58
|
fit: "fit-content",
|
|
31
59
|
};
|
|
32
60
|
css += complexClass("h-", "height", height, breakpoints);
|
|
33
|
-
for (
|
|
34
|
-
css += simpleClass(`h-${
|
|
61
|
+
for (const [n, d] of fractions) {
|
|
62
|
+
css += simpleClass(`h-${n}/${d}`, "height", fractionPercent(n, d), breakpoints);
|
|
35
63
|
}
|
|
36
64
|
css += complexClass("min-h-", "min-height", height, breakpoints);
|
|
37
65
|
css += complexClass("max-h-", "max-height", height, breakpoints);
|
|
@@ -83,7 +83,7 @@ export default function typography(config) {
|
|
|
83
83
|
const fontWeight = {
|
|
84
84
|
thin: "100",
|
|
85
85
|
extralight: "200",
|
|
86
|
-
light: "
|
|
86
|
+
light: "300",
|
|
87
87
|
normal: "400",
|
|
88
88
|
medium: "500",
|
|
89
89
|
semibold: "600",
|
|
@@ -93,7 +93,14 @@ export default function typography(config) {
|
|
|
93
93
|
};
|
|
94
94
|
css += complexClass("font-", "font-weight", fontWeight, breakpoints);
|
|
95
95
|
// letter-spacing
|
|
96
|
-
const letterSpacing =
|
|
96
|
+
const letterSpacing = {
|
|
97
|
+
tighter: "-0.05em",
|
|
98
|
+
tight: "-0.025em",
|
|
99
|
+
normal: "0em",
|
|
100
|
+
wide: "0.025em",
|
|
101
|
+
wider: "0.05em",
|
|
102
|
+
widest: "0.1em",
|
|
103
|
+
};
|
|
97
104
|
css += complexClass("tracking-", "letter-spacing", letterSpacing, breakpoints);
|
|
98
105
|
// line-height
|
|
99
106
|
const lineHeight = omit(spacing, "auto", "zero");
|
|
@@ -101,7 +108,7 @@ export default function typography(config) {
|
|
|
101
108
|
...lineHeight,
|
|
102
109
|
none: "1",
|
|
103
110
|
tight: "1.25",
|
|
104
|
-
snug: "1.
|
|
111
|
+
snug: "1.375",
|
|
105
112
|
normal: "1.5",
|
|
106
113
|
relaxed: "1.625",
|
|
107
114
|
loose: "2",
|
package/lib/purge.js
CHANGED
|
@@ -11,8 +11,8 @@ export async function purgeCSS(css, options) {
|
|
|
11
11
|
css: [{ raw: css }],
|
|
12
12
|
extractors: [
|
|
13
13
|
{
|
|
14
|
-
// Extractor para uso directo en HTML/JSX: class="flex gap-md"
|
|
15
|
-
extractor: (content) => content.match(/[A-Za-z0-9_
|
|
14
|
+
// Extractor para uso directo en HTML/JSX: class="flex gap-md w-1/2"
|
|
15
|
+
extractor: (content) => content.match(/[A-Za-z0-9_/.-]+/g) || [],
|
|
16
16
|
extensions: ["html", "jsx", "tsx", "js", "ts"],
|
|
17
17
|
},
|
|
18
18
|
{
|
|
@@ -32,7 +32,7 @@ export async function purgeCSS(css, options) {
|
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
safelist: {
|
|
35
|
-
greedy:
|
|
35
|
+
greedy: options.safelist ?? [],
|
|
36
36
|
},
|
|
37
37
|
});
|
|
38
38
|
return result ? result.css : css;
|
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>;
|