@massimo-cassandro/minimo 0.5.0 → 0.5.2

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.
@@ -10,10 +10,6 @@
10
10
  "$type": "color",
11
11
  "$value": "#083865"
12
12
  },
13
- "080": {
14
- "$type": "color",
15
- "$value": "#0957A0"
16
- },
17
13
  "100-fg": {
18
14
  "$type": "color",
19
15
  "$value": "#fff"
@@ -68,14 +68,6 @@ export const penpotFormat = buildConfig.penpotFormat === 'jsonc' ? 'jsonc' : 'js
68
68
  // 'keep' (default) — write the expression as-is
69
69
  // 'calc' — wrap in CSS calc()
70
70
  // 'resolve' — evaluate numerically; unit inherited from the first referenced token
71
- // colorScalePrefixes: list of color token prefixes for which the numeric scale
72
- // segment is zero-padded to 3 digits (e.g. --neutral-80 -> --neutral-080).
73
- // Applied to both CSS custom property names and Penpot DTCG token keys.
74
- // Set to an empty array or omit to disable.
75
- export const colorScalePrefixes = Array.isArray(buildConfig.colorScalePrefixes)
76
- ? buildConfig.colorScalePrefixes
77
- : [];
78
-
79
71
  const VALID_EXPR_MODES = ['keep', 'calc', 'resolve'];
80
72
  export const penpotExpressions = VALID_EXPR_MODES.includes(buildConfig.penpotExpressions)
81
73
  ? buildConfig.penpotExpressions
@@ -6,7 +6,6 @@
6
6
  // - individual properties for letterSpacing, textTransform, textDecoration
7
7
 
8
8
  import StyleDictionary from 'style-dictionary';
9
- import { padColorName } from '../lib/color-scale.mjs';
10
9
 
11
10
  const BASE_FONT_SIZE = 16;
12
11
 
@@ -148,22 +147,15 @@ StyleDictionary.registerFormat({
148
147
 
149
148
  const resolveRefs = makeResolveRefs(tokenByPath);
150
149
 
151
- const colorScalePrefixes = options.colorScalePrefixes ?? [];
152
-
153
150
  const lines = dictionary.allTokens
154
151
  .slice()
155
- .sort((a, b) => a.name.localeCompare(b.name))
152
+ .sort((a, b) => a.name.localeCompare(b.name, 'en', {numeric: true, sensitivity: 'base'}))
156
153
  .flatMap((token) => {
157
154
  const type = token.$type ?? token.type;
158
155
  const orig = token.original?.$value ?? token.original?.value;
159
156
 
160
- // Apply zero-padding to color scale names (e.g. --neutral-80 -> --neutral-080)
161
- const tokenName = (type === 'color')
162
- ? padColorName(token.name, colorScalePrefixes)
163
- : token.name;
164
-
165
157
  if (type === 'typography') {
166
- return [buildTypography(tokenName, orig ?? {}, resolveRefs)];
158
+ return [buildTypography(token.name, orig ?? {}, resolveRefs)];
167
159
  }
168
160
 
169
161
  let value;
@@ -200,7 +192,7 @@ StyleDictionary.registerFormat({
200
192
  value = String(token.$value ?? token.value);
201
193
  }
202
194
 
203
- return [` --${tokenName}: ${value};`];
195
+ return [` --${token.name}: ${value};`];
204
196
  });
205
197
 
206
198
  customPropsCount = lines.length;
@@ -33,7 +33,6 @@
33
33
 
34
34
  import StyleDictionary from 'style-dictionary';
35
35
  import path from 'path';
36
- import { padTokenPath } from '../lib/color-scale.mjs';
37
36
 
38
37
  // Disclaimer prepended to every generated file when penpotFormat is 'jsonc'
39
38
  const DISCLAIMER = [
@@ -127,28 +126,20 @@ StyleDictionary.registerFormat({
127
126
  name: 'json/penpot',
128
127
  format: ({ dictionary, options }) => {
129
128
  const root = {};
130
- const expressionMode = options.penpotExpressions ?? 'keep';
131
- const colorScalePrefixes = options.colorScalePrefixes ?? [];
129
+ const expressionMode = options.penpotExpressions ?? 'keep'; // 'keep' | 'calc' | 'resolve'
132
130
  const tokenMap = (expressionMode === 'resolve') ? makeTokenMap(dictionary) : null;
133
131
 
134
132
  for (const token of dictionary.allTokens) {
135
- const type = token.$type ?? token.type;
136
-
137
- // Apply zero-padding to color scale path segments
138
- // e.g. ['neutral', '80'] -> ['neutral', '080']
139
- const tokenPath = (type === 'color')
140
- ? padTokenPath(token.path, colorScalePrefixes)
141
- : token.path;
142
-
143
- // Rebuild the nested tree from the (possibly padded) token path
133
+ // Rebuild the nested tree from the token path
144
134
  let node = root;
145
- for (let i = 0; i < tokenPath.length - 1; i++) {
146
- const segment = tokenPath[i];
135
+ for (let i = 0; i < token.path.length - 1; i++) {
136
+ const segment = token.path[i];
147
137
  node[segment] = node[segment] ?? {};
148
138
  node = node[segment];
149
139
  }
150
140
 
151
- const leafKey = tokenPath[tokenPath.length - 1];
141
+ const leafKey = token.path[token.path.length - 1];
142
+ const type = token.$type ?? token.type;
152
143
  const orig = token.original?.$value ?? token.original?.value;
153
144
 
154
145
  // ── Value resolution ────────────────────────────────────────────────────
@@ -232,15 +223,13 @@ export const collectConcreteFilePaths = async (sd) => {
232
223
  // @param {string|null} penpotDestFile Aggregated file base name, or null
233
224
  // @param {'json'|'jsonc'} penpotFormat Output format
234
225
  // @param {'keep'|'calc'|'resolve'} penpotExpressions Expression handling mode
235
- // @param {string[]} colorScalePrefixes Color token prefixes for numeric scale zero-padding
236
226
  // @returns {object[]} File descriptors for the Style Dictionary platform
237
227
 
238
228
  export const buildPenpotFiles = (
239
229
  concreteFilePaths,
240
230
  penpotDestFile,
241
231
  penpotFormat = 'json',
242
- penpotExpressions = 'keep',
243
- colorScalePrefixes = []
232
+ penpotExpressions = 'keep'
244
233
  ) => {
245
234
  const ext = penpotFormat === 'jsonc' ? '.jsonc' : '.json';
246
235
  const jsonc = penpotFormat === 'jsonc';
@@ -249,7 +238,7 @@ export const buildPenpotFiles = (
249
238
  return [{
250
239
  destination: penpotDestFile + ext,
251
240
  format: 'json/penpot',
252
- options: { jsonc, penpotExpressions, colorScalePrefixes },
241
+ options: { jsonc, penpotExpressions },
253
242
  }];
254
243
  }
255
244
 
@@ -263,7 +252,7 @@ export const buildPenpotFiles = (
263
252
  return {
264
253
  destination: destName,
265
254
  format: 'json/penpot',
266
- options: { jsonc, penpotExpressions, colorScalePrefixes },
255
+ options: { jsonc, penpotExpressions },
267
256
  filter: (token) => {
268
257
  const fp = token.filePath ? path.resolve(token.filePath) : '';
269
258
  return fp === absPath;
@@ -40,7 +40,6 @@ const PENPOT_TRANSFORMS = [
40
40
  * Collected from sd.allTokens after SD initialisation.
41
41
  * Ignored when penpotDestFile is set.
42
42
  * @param {'keep'|'calc'|'resolve'} opts.penpotExpressions How to handle math expressions in dimension tokens.
43
- * @param {string[]} opts.colorScalePrefixes Color token prefixes for numeric scale zero-padding.
44
43
  * @returns {object} platforms object ready for Style Dictionary config
45
44
  */
46
45
  export const buildPlatforms = ({
@@ -50,7 +49,6 @@ export const buildPlatforms = ({
50
49
  penpotDestFile,
51
50
  penpotFormat,
52
51
  penpotExpressions = 'keep',
53
- colorScalePrefixes = [],
54
52
  concreteFilePaths = [],
55
53
  }) => {
56
54
  const platforms = {
@@ -64,7 +62,6 @@ export const buildPlatforms = ({
64
62
  options: {
65
63
  outputReferences: true,
66
64
  showFileHeader: true,
67
- colorScalePrefixes,
68
65
  },
69
66
  },
70
67
  ],
@@ -75,7 +72,7 @@ export const buildPlatforms = ({
75
72
  platforms.penpot = {
76
73
  buildPath: penpotBuildPath + '/',
77
74
  transforms: PENPOT_TRANSFORMS,
78
- files: buildPenpotFiles(concreteFilePaths, penpotDestFile, penpotFormat, penpotExpressions, colorScalePrefixes),
75
+ files: buildPenpotFiles(concreteFilePaths, penpotDestFile, penpotFormat, penpotExpressions),
79
76
  };
80
77
  }
81
78
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ /* eslint-disable no-console */
2
3
 
3
4
  // build-tokens.mjs
4
5
  // Entry point: imports modules, runs the build, lints the CSS output, prints the log.
@@ -28,7 +29,6 @@ import {
28
29
  penpotDestFile,
29
30
  penpotFormat,
30
31
  penpotExpressions,
31
- colorScalePrefixes,
32
32
  source,
33
33
  } from './build-tokens-src/config.mjs';
34
34
 
@@ -72,7 +72,6 @@ const sd = new StyleDictionary({
72
72
  penpotDestFile,
73
73
  penpotFormat,
74
74
  penpotExpressions,
75
- colorScalePrefixes,
76
75
  concreteFilePaths,
77
76
  }),
78
77
  });
@@ -96,7 +95,7 @@ console.log(styleText(['yellow'], `[build-tokens] source : ${source.map(sho
96
95
  console.log(styleText(['yellow'], `[build-tokens] dest file : ${short(path.join(buildPath, destFile))}`));
97
96
 
98
97
  if (penpotBuildPath) {
99
- const penpotFiles = buildPenpotFiles(concreteFilePaths, penpotDestFile, penpotFormat, penpotExpressions, colorScalePrefixes);
98
+ const penpotFiles = buildPenpotFiles(concreteFilePaths, penpotDestFile, penpotFormat, penpotExpressions);
100
99
  if (penpotFiles.length === 1) {
101
100
  console.log(styleText(['yellow'],
102
101
  `[build-tokens] penpot json : ${short(path.join(penpotBuildPath, penpotFiles[0].destination))}`
@@ -108,7 +107,7 @@ if (penpotBuildPath) {
108
107
  }
109
108
  } else {
110
109
  console.log(styleText(['yellow'],
111
- `[build-tokens] penpot json : (disabled — penpotBuildPath not set)`
110
+ '[build-tokens] penpot json : (disabled — penpotBuildPath not set)'
112
111
  ));
113
112
  }
114
113
 
@@ -75,11 +75,7 @@ const config = {
75
75
  // e.g. {size.base} = 16px, "{size.base} * .25" -> "4px"
76
76
  penpotExpressions: 'resolve',
77
77
 
78
- // Color token prefixes for which the numeric scale segment is zero-padded
79
- // to 3 digits in both CSS output and Penpot token files.
80
- // e.g. --neutral-80 -> --neutral-080, --primary-5 -> --primary-005
81
- // Set to an empty array or omit to disable.
82
- colorScalePrefixes: ['primary', 'secondary', 'neutral'],
78
+
83
79
 
84
80
  // ---------------------------------------------------------------------------
85
81
  // check-unresolved-custom-props.mjs settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Light css framework",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/massimo-cassandro/minimo#readme",
@@ -171,7 +171,6 @@
171
171
  --overlay-color: rgb(0 0 0 / .6);
172
172
  --primary-100: #083865;
173
173
  --primary-100-fg: #fff;
174
- --primary-080: #0957a0;
175
174
  --radius-base: var(--size-base);
176
175
  --radius-lg: var(--size-lg);
177
176
  --radius-md: var(--size-md);
@@ -1,81 +0,0 @@
1
- // build-tokens-src/lib/color-scale.mjs
2
- // Shared helper for color scale zero-padding.
3
- //
4
- // When colorScalePrefixes is configured, color tokens whose name matches
5
- // --<prefix>-<number> (e.g. --primary-100, --neutral-80)
6
- // have the numeric segment zero-padded to 3 digits:
7
- // --primary-100 -> --primary-100 (unchanged, already 3 digits)
8
- // --neutral-80 -> --neutral-080
9
- // --secondary-5 -> --secondary-005
10
- //
11
- // The same transformation is applied to CSS custom property names and to
12
- // Penpot DTCG token keys, so both outputs stay in sync.
13
- //
14
- // Configuration (in the project config file):
15
- // colorScalePrefixes: ['primary', 'secondary', 'neutral']
16
- //
17
- // Set to an empty array or omit to disable the feature entirely.
18
-
19
- // ---------------------------------------------------------------------------
20
- // padColorName
21
- //
22
- // Given a full token name (kebab-case, no leading --) and the list of
23
- // configured prefixes, returns the name with the numeric segment zero-padded
24
- // if applicable, or the original name unchanged otherwise.
25
- //
26
- // Examples:
27
- // padColorName('primary-100', ['primary']) -> 'primary-100'
28
- // padColorName('neutral-80', ['neutral']) -> 'neutral-080'
29
- // padColorName('neutral-80', []) -> 'neutral-80'
30
- // padColorName('size-base', ['primary']) -> 'size-base'
31
- // ---------------------------------------------------------------------------
32
- export const padColorName = (name, prefixes) => {
33
- if (!prefixes || prefixes.length === 0) return name;
34
-
35
- // Match: <prefix>-<integer> optionally followed by more segments
36
- // The number must be a pure integer (no decimals, no units).
37
- const pattern = new RegExp(
38
- `^(${prefixes.map(p => escapeRegex(p)).join('|')})-([0-9]+)(-.+)?$`
39
- );
40
-
41
- const match = name.match(pattern);
42
- if (!match) return name;
43
-
44
- const [, prefix, num, rest = ''] = match;
45
- const padded = num.padStart(3, '0');
46
-
47
- return `${prefix}-${padded}${rest}`;
48
- };
49
-
50
- // ---------------------------------------------------------------------------
51
- // padTokenPath
52
- //
53
- // Applies the same zero-padding logic to a DTCG token path array.
54
- // Used by the Penpot format to rename leaf keys and intermediate path segments.
55
- //
56
- // The segment to pad is the one immediately following the matching prefix.
57
- // If the prefix occupies multiple path segments this function is intentionally
58
- // conservative: it only pads when the prefix is a single path segment.
59
- //
60
- // Examples (path arrays):
61
- // ['primary', '100'] -> ['primary', '100'] (unchanged)
62
- // ['neutral', '80'] -> ['neutral', '080']
63
- // ['color', 'neutral', '80'] with prefix 'neutral' -> ['color', 'neutral', '080']
64
- // ---------------------------------------------------------------------------
65
- export const padTokenPath = (pathArr, prefixes) => {
66
- if (!prefixes || prefixes.length === 0) return pathArr;
67
-
68
- return pathArr.map((segment, i) => {
69
- // Is this segment a pure integer and is the previous segment a prefix?
70
- if (i === 0) return segment;
71
- const prev = pathArr[i - 1];
72
- if (!prefixes.includes(prev)) return segment;
73
- if (!/^[0-9]+$/.test(segment)) return segment;
74
- return segment.padStart(3, '0');
75
- });
76
- };
77
-
78
- // ---------------------------------------------------------------------------
79
- // Internal: escape special regex characters in a prefix string
80
- // ---------------------------------------------------------------------------
81
- const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');