@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/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",
4
+ "version": "1.0.6",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
7
7
  "type": "module",
@@ -9,31 +9,29 @@
9
9
  ".": {
10
10
  "style": "./dist/grisso.css"
11
11
  },
12
- "./plugin": {
13
- "import": "./plugin.js",
14
- "require": "./plugin.cjs"
15
- },
16
12
  "./build": "./lib/build.js",
13
+ "./tokens": "./lib/tokens.js",
17
14
  "./config": "./lib/defaults.js",
18
15
  "./tokens-example.css": "./tokens-example.css"
19
16
  },
20
17
  "engines": {
21
18
  "node": ">=24"
22
19
  },
20
+ "bin": {
21
+ "grisso": "lib/cli.js"
22
+ },
23
23
  "files": [
24
24
  "dist/",
25
25
  "lib/",
26
- "plugin.js",
27
- "plugin.cjs",
28
26
  "tokens-example.css",
29
27
  "README.md"
30
28
  ],
31
29
  "scripts": {
32
- "build": "tsc && node scripts/build.js",
30
+ "build": "tsc && node lib/cli.js build --output dist/grisso.css",
33
31
  "typecheck": "tsc --noEmit",
34
32
  "lint": "biome check .",
35
33
  "lint:fix": "biome check --write .",
36
- "playground": "npm run build && node scripts/build.js --config playground/grisso.config.mjs --content playground/index.html --content playground/example.module.css --output playground/grisso.css && open playground/index.html",
34
+ "playground": "npm run build && node lib/cli.js build --config playground/grisso.config.mjs --content playground/index.html --content playground/example.module.css --output playground/grisso.css && open playground/index.html",
37
35
  "test": "vitest run",
38
36
  "test:watch": "vitest",
39
37
  "prepublishOnly": "npm run build",
@@ -50,13 +48,5 @@
50
48
  "release-it": "^19.2.4",
51
49
  "typescript": "^5.9.3",
52
50
  "vitest": "^4.0.18"
53
- },
54
- "peerDependencies": {
55
- "postcss": "^8.0.0"
56
- },
57
- "peerDependenciesMeta": {
58
- "postcss": {
59
- "optional": true
60
- }
61
51
  }
62
52
  }
package/plugin.cjs DELETED
@@ -1,5 +0,0 @@
1
- // CJS wrapper — require(esm) supported in Node 22+
2
- const mod = require("./plugin.js");
3
- module.exports = mod.default;
4
- module.exports.default = mod.default;
5
- module.exports.postcss = true;
package/plugin.js DELETED
@@ -1,43 +0,0 @@
1
- import { generateCSS } from "./lib/index.js";
2
- import { purgeCSS } from "./lib/purge.js";
3
-
4
- /**
5
- * PostCSS plugin de Grisso.
6
- * Genera CSS desde JS y aplica tree-shaking usando PurgeCSS
7
- * si se pasan rutas de contenido.
8
- *
9
- * No aplica optimización (el consumidor tiene su propio pipeline PostCSS).
10
- *
11
- * @param {Object} options
12
- * @param {string[]} [options.content] - Rutas glob de archivos a escanear para tree-shaking.
13
- * Si se omite, se incluye todo el CSS de Grisso (útil en desarrollo).
14
- * @param {string} [options.config] - Ruta a grisso.config.mjs del consumidor.
15
- *
16
- * @example
17
- * // postcss.config.js del proyecto consumidor
18
- * import grisso from "@hiscovega/grisso/plugin";
19
- * export default {
20
- * plugins: [
21
- * grisso({ content: ["./src/**\/*.{js,ts,jsx,tsx,css}"] })
22
- * ]
23
- * }
24
- */
25
- export default function grissoPlugin(options = {}) {
26
- const { content, config: configPath } = options;
27
-
28
- return {
29
- postcssPlugin: "postcss-grisso",
30
- async Once(root, { parse }) {
31
- let css = await generateCSS(configPath);
32
-
33
- if (content && content.length > 0) {
34
- css = await purgeCSS(css, { content });
35
- }
36
-
37
- const grissoRoot = parse(css);
38
- grissoRoot.each((node) => root.prepend(node.clone()));
39
- },
40
- };
41
- }
42
-
43
- grissoPlugin.postcss = true;