@seyuna/postcss 1.0.0-canary.6 → 1.0.0-canary.8

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/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # [1.0.0-canary.8](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.7...v1.0.0-canary.8) (2025-09-10)
2
+
3
+
4
+ ### Features
5
+
6
+ * added at-rule `each-fixed-color` ([699ee0d](https://github.com/seyuna-corp/seyuna-postcss/commit/699ee0defd1fbb0ff91a90c1e13358b1ef9832b2))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * at-rule `each-seyuna-color` renamed to `each-standard-color`
12
+
13
+ # [1.0.0-canary.7](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.6...v1.0.0-canary.7) (2025-09-10)
14
+
15
+
16
+ ### Features
17
+
18
+ * Added at-rule ([8a08289](https://github.com/seyuna-corp/seyuna-postcss/commit/8a08289023f4aa6f65d56e10697e64d02444f118))
19
+
1
20
  # [1.0.0-canary.6](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.5...v1.0.0-canary.6) (2025-09-09)
2
21
 
3
22
 
@@ -0,0 +1,34 @@
1
+ import { AtRule } from "postcss";
2
+ /**
3
+ * Custom PostCSS plugin handler for `@each-standard-color` at-rules.
4
+ *
5
+ * Example usage:
6
+ *
7
+ * @each-standard-color {
8
+ * color: white;
9
+ * }
10
+ *
11
+ * Will generate:
12
+ *
13
+ * .alpha { color: white; }
14
+ * .beta { color: white; }
15
+ * .gamma { color: white; }
16
+ * ...
17
+ */
18
+ export declare function eachStandardColor(atRule: AtRule): void;
19
+ /**
20
+ * Custom PostCSS plugin handler for `@each-fixed-color` at-rules.
21
+ *
22
+ * Example usage:
23
+ *
24
+ * @each-fixed-color {
25
+ * color: white;
26
+ * }
27
+ *
28
+ * Will generate:
29
+ *
30
+ * .primary { color: white; }
31
+ * .secondary { color: white; }
32
+ * ...
33
+ */
34
+ export declare function eachFixedColor(atRule: AtRule): void;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.eachStandardColor = eachStandardColor;
7
+ exports.eachFixedColor = eachFixedColor;
8
+ const postcss_1 = require("postcss");
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ /**
12
+ * Custom PostCSS plugin handler for `@each-standard-color` at-rules.
13
+ *
14
+ * Example usage:
15
+ *
16
+ * @each-standard-color {
17
+ * color: white;
18
+ * }
19
+ *
20
+ * Will generate:
21
+ *
22
+ * .alpha { color: white; }
23
+ * .beta { color: white; }
24
+ * .gamma { color: white; }
25
+ * ...
26
+ */
27
+ function eachStandardColor(atRule) {
28
+ // Read seyuna.json from project root
29
+ const jsonPath = path_1.default.resolve(process.cwd(), "seyuna.json");
30
+ const fileContents = fs_1.default.readFileSync(jsonPath, "utf-8");
31
+ const data = JSON.parse(fileContents);
32
+ const hues = data.ui.theme.hues;
33
+ const hueNamesSet = new Set(Object.keys(hues));
34
+ // Guard against atRule.nodes being undefined
35
+ const nodes = atRule.nodes ?? [];
36
+ const generatedRules = [];
37
+ // Helper to clone nodes and replace {name} placeholder
38
+ const cloneNodesWithName = (name) => nodes.map((node) => {
39
+ const cloned = node.clone();
40
+ // Only process declarations
41
+ if (cloned.type === "decl") {
42
+ const decl = cloned;
43
+ decl.value = decl.value.replace(/\{name\}/g, name);
44
+ }
45
+ return cloned;
46
+ });
47
+ // Generate rules for each hue
48
+ for (const hueName of hueNamesSet) {
49
+ const rule = new postcss_1.Rule({ selector: `.${hueName}` });
50
+ cloneNodesWithName(hueName).forEach((n) => rule.append(n));
51
+ generatedRules.push(rule);
52
+ }
53
+ // Replace the original @each-seyuna-color at-rule with all the generated rules
54
+ atRule.replaceWith(...generatedRules);
55
+ }
56
+ /**
57
+ * Custom PostCSS plugin handler for `@each-fixed-color` at-rules.
58
+ *
59
+ * Example usage:
60
+ *
61
+ * @each-fixed-color {
62
+ * color: white;
63
+ * }
64
+ *
65
+ * Will generate:
66
+ *
67
+ * .primary { color: white; }
68
+ * .secondary { color: white; }
69
+ * ...
70
+ */
71
+ function eachFixedColor(atRule) {
72
+ // Read seyuna.json from project root
73
+ const jsonPath = path_1.default.resolve(process.cwd(), "seyuna.json");
74
+ const fileContents = fs_1.default.readFileSync(jsonPath, "utf-8");
75
+ const data = JSON.parse(fileContents);
76
+ const light_colors = data.ui.theme.light;
77
+ const dark_colors = data.ui.theme.dark;
78
+ const lightColorNamesSet = new Set(Object.keys(light_colors));
79
+ const darkColorNamesSet = new Set(Object.keys(dark_colors));
80
+ const mergedColorNamesSet = new Set([
81
+ ...lightColorNamesSet,
82
+ ...darkColorNamesSet,
83
+ ]);
84
+ // Guard against atRule.nodes being undefined
85
+ const nodes = atRule.nodes ?? [];
86
+ const generatedRules = [];
87
+ // Helper to clone nodes and replace {name} placeholder
88
+ const cloneNodesWithName = (name) => nodes.map((node) => {
89
+ const cloned = node.clone();
90
+ // Only process declarations
91
+ if (cloned.type === "decl") {
92
+ const decl = cloned;
93
+ decl.value = decl.value.replace(/\{name\}/g, name);
94
+ }
95
+ return cloned;
96
+ });
97
+ // Generate rules for mergedColorNamesSet
98
+ for (const colorName of mergedColorNamesSet) {
99
+ const rule = new postcss_1.Rule({ selector: `.${colorName}` });
100
+ cloneNodesWithName(colorName).forEach((n) => rule.append(n));
101
+ generatedRules.push(rule);
102
+ }
103
+ // Replace the original @each-seyuna-color at-rule with all the generated rules
104
+ atRule.replaceWith(...generatedRules);
105
+ }
@@ -1,3 +1,6 @@
1
1
  import type { AtRule } from "postcss";
2
- export type AtRuleHandler = (atRule: AtRule) => void;
3
- export declare const atRuleHandlers: Record<string, AtRuleHandler>;
2
+ export interface AtRuleHandler {
3
+ name: string;
4
+ handler: (atRule: AtRule) => void;
5
+ }
6
+ export declare const atRuleHandlers: AtRuleHandler[];
@@ -4,12 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.atRuleHandlers = void 0;
7
+ // atRuleHandlers.ts
7
8
  const dark_1 = __importDefault(require("./dark"));
8
9
  const light_1 = __importDefault(require("./light"));
9
10
  const container_1 = __importDefault(require("./container"));
10
- exports.atRuleHandlers = {
11
- light: light_1.default,
12
- dark: dark_1.default,
13
- container: container_1.default,
11
+ const color_1 = require("./color");
12
+ // Ordered array ensures execution order
13
+ exports.atRuleHandlers = [
14
+ { name: "each-standard-color", handler: color_1.eachStandardColor }, // first
15
+ { name: "each-fixed-color", handler: color_1.eachFixedColor },
16
+ { name: "light", handler: light_1.default },
17
+ { name: "dark", handler: dark_1.default },
18
+ { name: "container", handler: container_1.default },
14
19
  // add more handlers here as needed
15
- };
20
+ ];
package/dist/plugin.js CHANGED
@@ -20,8 +20,14 @@ const dynamicFunctionsPlugin = (opts = {}) => {
20
20
  }
21
21
  decl.value = value;
22
22
  },
23
- AtRule: {
24
- ...at_rules_1.atRuleHandlers,
23
+ // Override AtRule handler to ensure ordered execution
24
+ AtRule(atRule) {
25
+ // Iterate over handlers in order (array) instead of object spread
26
+ for (const { name, handler } of at_rules_1.atRuleHandlers) {
27
+ if (atRule.name === name) {
28
+ handler(atRule);
29
+ }
30
+ }
25
31
  },
26
32
  };
27
33
  };
@@ -0,0 +1,19 @@
1
+ export interface SeyunaConfig {
2
+ ui: {
3
+ theme: {
4
+ hues: Record<string, number>;
5
+ light: {
6
+ colors: Record<string, Color>;
7
+ };
8
+ dark: {
9
+ colors: Record<string, Color>;
10
+ };
11
+ };
12
+ };
13
+ }
14
+ type Color = {
15
+ lightness: number;
16
+ chroma: number;
17
+ hue: number;
18
+ };
19
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seyuna/postcss",
3
- "version": "1.0.0-canary.6",
3
+ "version": "1.0.0-canary.8",
4
4
  "description": "Seyuna UI's postcss plugin",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,118 @@
1
+ import { AtRule, Rule, ChildNode, Declaration } from "postcss";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { SeyunaConfig } from "../types";
5
+
6
+ /**
7
+ * Custom PostCSS plugin handler for `@each-standard-color` at-rules.
8
+ *
9
+ * Example usage:
10
+ *
11
+ * @each-standard-color {
12
+ * color: white;
13
+ * }
14
+ *
15
+ * Will generate:
16
+ *
17
+ * .alpha { color: white; }
18
+ * .beta { color: white; }
19
+ * .gamma { color: white; }
20
+ * ...
21
+ */
22
+ export function eachStandardColor(atRule: AtRule) {
23
+ // Read seyuna.json from project root
24
+ const jsonPath = path.resolve(process.cwd(), "seyuna.json");
25
+ const fileContents = fs.readFileSync(jsonPath, "utf-8");
26
+ const data: SeyunaConfig = JSON.parse(fileContents);
27
+ const hues = data.ui.theme.hues;
28
+ const hueNamesSet = new Set(Object.keys(hues));
29
+
30
+ // Guard against atRule.nodes being undefined
31
+ const nodes = atRule.nodes ?? [];
32
+
33
+ const generatedRules: Rule[] = [];
34
+
35
+ // Helper to clone nodes and replace {name} placeholder
36
+ const cloneNodesWithName = (name: string) =>
37
+ nodes.map((node) => {
38
+ const cloned = node.clone();
39
+
40
+ // Only process declarations
41
+ if (cloned.type === "decl") {
42
+ const decl = cloned as Declaration;
43
+ decl.value = decl.value.replace(/\{name\}/g, name);
44
+ }
45
+
46
+ return cloned;
47
+ });
48
+
49
+ // Generate rules for each hue
50
+ for (const hueName of hueNamesSet) {
51
+ const rule = new Rule({ selector: `.${hueName}` });
52
+ cloneNodesWithName(hueName).forEach((n) => rule.append(n));
53
+ generatedRules.push(rule);
54
+ }
55
+
56
+ // Replace the original @each-seyuna-color at-rule with all the generated rules
57
+ atRule.replaceWith(...generatedRules);
58
+ }
59
+
60
+ /**
61
+ * Custom PostCSS plugin handler for `@each-fixed-color` at-rules.
62
+ *
63
+ * Example usage:
64
+ *
65
+ * @each-fixed-color {
66
+ * color: white;
67
+ * }
68
+ *
69
+ * Will generate:
70
+ *
71
+ * .primary { color: white; }
72
+ * .secondary { color: white; }
73
+ * ...
74
+ */
75
+ export function eachFixedColor(atRule: AtRule) {
76
+ // Read seyuna.json from project root
77
+ const jsonPath = path.resolve(process.cwd(), "seyuna.json");
78
+ const fileContents = fs.readFileSync(jsonPath, "utf-8");
79
+ const data: SeyunaConfig = JSON.parse(fileContents);
80
+ const light_colors = data.ui.theme.light;
81
+ const dark_colors = data.ui.theme.dark;
82
+ const lightColorNamesSet = new Set(Object.keys(light_colors));
83
+ const darkColorNamesSet = new Set(Object.keys(dark_colors));
84
+
85
+ const mergedColorNamesSet = new Set([
86
+ ...lightColorNamesSet,
87
+ ...darkColorNamesSet,
88
+ ]);
89
+
90
+ // Guard against atRule.nodes being undefined
91
+ const nodes = atRule.nodes ?? [];
92
+
93
+ const generatedRules: Rule[] = [];
94
+
95
+ // Helper to clone nodes and replace {name} placeholder
96
+ const cloneNodesWithName = (name: string) =>
97
+ nodes.map((node) => {
98
+ const cloned = node.clone();
99
+
100
+ // Only process declarations
101
+ if (cloned.type === "decl") {
102
+ const decl = cloned as Declaration;
103
+ decl.value = decl.value.replace(/\{name\}/g, name);
104
+ }
105
+
106
+ return cloned;
107
+ });
108
+
109
+ // Generate rules for mergedColorNamesSet
110
+ for (const colorName of mergedColorNamesSet) {
111
+ const rule = new Rule({ selector: `.${colorName}` });
112
+ cloneNodesWithName(colorName).forEach((n) => rule.append(n));
113
+ generatedRules.push(rule);
114
+ }
115
+
116
+ // Replace the original @each-seyuna-color at-rule with all the generated rules
117
+ atRule.replaceWith(...generatedRules);
118
+ }
@@ -1,13 +1,22 @@
1
+ // atRuleHandlers.ts
1
2
  import dark from "./dark";
2
3
  import light from "./light";
3
4
  import container from "./container";
5
+ import { eachStandardColor, eachFixedColor } from "./color";
4
6
  import type { AtRule } from "postcss";
5
7
 
6
- export type AtRuleHandler = (atRule: AtRule) => void;
8
+ // Each handler has a name (matches the at-rule) and the function
9
+ export interface AtRuleHandler {
10
+ name: string;
11
+ handler: (atRule: AtRule) => void;
12
+ }
7
13
 
8
- export const atRuleHandlers: Record<string, AtRuleHandler> = {
9
- light,
10
- dark,
11
- container,
14
+ // Ordered array ensures execution order
15
+ export const atRuleHandlers: AtRuleHandler[] = [
16
+ { name: "each-standard-color", handler: eachStandardColor }, // first
17
+ { name: "each-fixed-color", handler: eachFixedColor },
18
+ { name: "light", handler: light },
19
+ { name: "dark", handler: dark },
20
+ { name: "container", handler: container },
12
21
  // add more handlers here as needed
13
- };
22
+ ];
package/src/plugin.ts CHANGED
@@ -31,8 +31,14 @@ export const dynamicFunctionsPlugin: PluginCreator<PluginOptions> = (
31
31
  decl.value = value;
32
32
  },
33
33
 
34
- AtRule: {
35
- ...atRuleHandlers,
34
+ // Override AtRule handler to ensure ordered execution
35
+ AtRule(atRule) {
36
+ // Iterate over handlers in order (array) instead of object spread
37
+ for (const { name, handler } of atRuleHandlers) {
38
+ if (atRule.name === name) {
39
+ handler(atRule);
40
+ }
41
+ }
36
42
  },
37
43
  };
38
44
  };
package/src/types.ts ADDED
@@ -0,0 +1,19 @@
1
+ export interface SeyunaConfig {
2
+ ui: {
3
+ theme: {
4
+ hues: Record<string, number>;
5
+ light: {
6
+ colors: Record<string, Color>;
7
+ };
8
+ dark: {
9
+ colors: Record<string, Color>;
10
+ };
11
+ };
12
+ };
13
+ }
14
+
15
+ type Color = {
16
+ lightness: number;
17
+ chroma: number;
18
+ hue: number;
19
+ };