@massimo-cassandro/minimo 1.41.4 → 1.41.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 +12 -12
- package/charts/src/node-helpers/create-svg-canvas-node.mjs +2 -2
- package/charts/src/node-helpers/svg-text-to-path.js +9 -9
- package/charts/src/rating-display/index.js +1 -1
- package/charts/src/rating-display/ratindDisplayAnimation.js +3 -3
- package/design-tokens/README.md +2 -2
- package/design-tokens/_src/_readme.md +26 -26
- package/dev-tools/README.md +16 -16
- package/dev-tools/create-favicons/README.md +31 -31
- package/dev-tools/create-favicons/src/create-ico.mjs +2 -2
- package/dev-tools/create-favicons/src/default-params.mjs +1 -1
- package/dev-tools/create-favicons/src/init.mjs +1 -1
- package/dev-tools/design-tokens-builder/README.md +102 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/build-source-modes.mjs +85 -73
- package/dev-tools/design-tokens-builder/build-tokens-src/config.mjs +109 -85
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/css.mjs +113 -90
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/json.mjs +107 -95
- package/dev-tools/design-tokens-builder/build-tokens-src/legacy-tokens-parser.mjs +71 -64
- package/dev-tools/design-tokens-builder/build-tokens-src/light-dark.mjs +75 -65
- package/dev-tools/design-tokens-builder/build-tokens-src/merge-css.mjs +113 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/platforms.mjs +36 -30
- package/dev-tools/design-tokens-builder/build-tokens-src/resolve-source-paths.mjs +15 -13
- package/dev-tools/design-tokens-builder/build-tokens-src/source-prefixes.mjs +44 -42
- package/dev-tools/design-tokens-builder/build-tokens-src/source-transforms.mjs +89 -83
- package/dev-tools/design-tokens-builder/build-tokens-src/token-rename-parser.mjs +99 -86
- package/dev-tools/design-tokens-builder/build-tokens-src/transforms.mjs +64 -48
- package/dev-tools/design-tokens-builder/build-tokens.mjs +80 -68
- package/dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs +103 -77
- package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +275 -238
- package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +2 -2
- package/dev-tools/starter-kit/source_files/app/CLAUDE.md +4 -2
- package/dev-tools/starter-kit/source_files/app/{css/index.css → index.css} +2 -2
- package/dev-tools/starter-kit/source_files/app/index.js +1 -1
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ImgViewerController.php +3 -3
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ViewerController.php +2 -2
- package/dev-tools/starter-kit/source_files/root/stylelint.config.mjs +1 -1
- package/dev-tools/starter-kit/source_files/root/webpack-config-modules/css-rules.mjs +1 -1
- package/dev-tools/starter-kit/source_files/root/webpack.config.mjs +15 -1
- package/dev-tools/starter-kit/webpack-config-upg.md +12 -0
- package/dev-tools/stylelint-config/README.md +7 -7
- package/dev-tools/svg-icons-tools/README.md +32 -32
- package/dev-tools/svg-icons-tools/src/config-manager.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/default-config.mjs +118 -118
- package/dev-tools/svg-icons-tools/src/jsx-icon-file-builder.mjs +24 -24
- package/dev-tools/svg-icons-tools/src/parse-svg-filename.mjs +3 -3
- package/dev-tools/svg-icons-tools/src/parse-svg-files.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/parse-svg-markup.mjs +4 -4
- package/dev-tools/svg-icons-tools/src/svg-to-jsx.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-optimized.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-symbols.mjs +2 -2
- package/dev-tools/upd@m/README.md +1 -1
- package/dev-tools/upd@m/index.mjs +1 -1
- package/dev-tools/update-version/README.md +9 -9
- package/package.json +1 -1
- package/snippets/unsplash-browser-app/README.md +1 -1
- package/snippets/unsplash-browser-app/unsplash-utilities.js +9 -9
- package/src/components/autocomplete/README.md +3 -3
- package/src/components/autocomplete/autocomplete-engine.js +75 -63
- package/src/components/autocomplete/check-autocomplete.js +3 -3
- package/src/components/dismiss-alerts.js +3 -3
- package/src/components/form-reset-submit.js +6 -6
- package/src/components/inner-nav/inner-nav.js +2 -2
- package/src/components/modal-alert/modal-alert.js +67 -65
- package/src/components/modal-alert/modal-alert.minimo.tokens.mjs +1 -1
- package/src/components/modal-popup/modal-popup.js +56 -56
- package/src/components/overlay/overlay.js +3 -3
- package/src/components/sf-macro/readme.md +1 -1
- package/src/components/sf-macro/sf-macro.js +27 -23
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +83 -79
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +44 -44
- package/src/components/snackbar/snackbar.js +19 -19
- package/src/components/spinner/spinner.js +3 -3
- package/src/components/unsplash-page/README.md +8 -8
- package/src/components/unsplash-page/fetch-unsplash-data.js +3 -3
- package/src/components/unsplash-page/unsplash-page.js +33 -33
- package/src/components/unsplash-page/unsplash-page.module.css +1 -1
- package/src/css/alerts.css +2 -2
- package/src/css/forms/forms.css +4 -4
- package/src/css/forms/validation.css +1 -1
- package/src/css/margin-padding-media.css +4 -4
- package/src/css/margin-padding.css +4 -4
- package/src/css/reset.css +11 -11
- package/src/icons/read-me.md +1 -1
- package/src/minimo.css +3 -3
- package/src/utilities/better-text-with-places.js +22 -22
- package/src/utilities/better-text.js +42 -35
- package/src/utilities/classnames.js +8 -8
- package/src/utilities/cookies.js +6 -6
- package/src/utilities/create-id.js +3 -3
- package/src/utilities/disable-btns-on-submit.js +2 -2
- package/src/utilities/dom-builder/dom-builder.js +89 -86
- package/src/utilities/dom-builder/domBuilderBasicSetup.js +9 -9
- package/src/utilities/dom-builder/parseDomString.js +23 -23
- package/src/utilities/dom-builder-helpers/README.md +2 -2
- package/src/utilities/dom-builder-helpers/form-tags.js +100 -100
- package/src/utilities/dom-builder-helpers/picture-tag.js +39 -39
- package/src/utilities/enable-submit-btns.js +1 -1
- package/src/utilities/escape-html.js +2 -2
- package/src/utilities/generate-pwd.js +4 -4
- package/src/utilities/linked-dates.js +13 -13
- package/src/utilities/parse-file-size.js +6 -6
- package/src/utilities/random-id.js +3 -3
- package/src/utilities/relative-date.js +40 -40
- package/src/utilities/sentence-case.js +1 -1
- package/src/utilities/strip-tags.js +1 -1
- package/src/utilities/title-case.js +1 -1
- package/src/utilities/truncate-string.js +5 -5
- package/src/utilities/validation-error-class.js +12 -12
- package/src/web-components/json-table/json-table-component.js +123 -121
- package/src/web-components/json-table/json-table-component.module.css +6 -6
- package/src/web-components/json-table/json-table.minimo.tokens.mjs +6 -6
- package/src/web-components/json-table/jt-docs/parametri.md +124 -0
- package/src/web-components/json-table/jt-docs.md +622 -0
- package/src/web-components/json-table/readme.md +3 -763
- package/src/web-components/json-table/src/cell-content.js +25 -25
- package/src/web-components/json-table/src/content-utils.js +21 -21
- package/src/web-components/json-table/src/data-types.js +32 -32
- package/src/web-components/json-table/src/defaults.js +230 -191
- package/src/web-components/json-table/src/get-data.js +55 -38
- package/src/web-components/json-table/src/icons.js +17 -17
- package/src/web-components/json-table/src/info-section.js +18 -18
- package/src/web-components/json-table/src/main-builder.js +45 -45
- package/src/web-components/json-table/src/pagination.js +32 -32
- package/src/web-components/json-table/src/parse-cols.js +18 -18
- package/src/web-components/json-table/src/parse-rows.js +17 -17
- package/src/web-components/json-table/src/resolve-params.js +53 -41
- package/src/web-components/json-table/src/search.js +13 -13
- package/src/web-components/json-table/src/sorting.js +20 -20
- package/src/web-components/json-table/src/table-body.js +13 -13
- package/src/web-components/json-table/src/table-builder.js +34 -34
- package/src/web-components/json-table/src/table-tfoot.js +8 -8
- package/src/web-components/json-table/src/table-thead.js +21 -21
- package/src/web-components/json-table/src/update-info.js +11 -11
- package/types/classes.d.ts +2 -2
- package/types/global.d.ts +18 -12
|
@@ -1,69 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
/*
|
|
2
|
+
build-tokens-src/formats/json.mjs
|
|
3
|
+
Registra il format 'json/tokens' ed esporta buildJsonFiles() e
|
|
4
|
+
collectConcreteFilePaths().
|
|
5
|
+
|
|
6
|
+
Il format produce un file JSON(C) annidato W3C DTCG, indipendente da qualsiasi
|
|
7
|
+
strumento specifico (utilizzabile in Penpot, Figma tramite plugin, Token Studio,
|
|
8
|
+
Supernova o qualsiasi altro strumento compatibile con DTCG).
|
|
9
|
+
|
|
10
|
+
Il formato di output è controllato dall'opzione jsonFormat nella config del progetto:
|
|
11
|
+
'jsonc' -> estensione .jsonc + intestazione che segnala il file generato
|
|
12
|
+
'json' -> .json semplice, senza intestazione
|
|
13
|
+
|
|
14
|
+
buildJsonFiles() costruisce l'array `files` per la platform json:
|
|
15
|
+
jsonDestFile impostato -> singolo file aggregato
|
|
16
|
+
jsonDestFile null -> un file per ogni file sorgente concreto, tutti nella stessa
|
|
17
|
+
cartella jsonBuildPath (senza sottocartelle) — vedi il
|
|
18
|
+
controllo delle collisioni in buildJsonFiles()
|
|
19
|
+
|
|
20
|
+
── Gestione delle espressioni (opzione jsonExpression) ─────────────────────
|
|
21
|
+
|
|
22
|
+
I token dimension possono avere espressioni matematiche nel proprio $value, ad es.:
|
|
23
|
+
{ $type: "dimension", $value: "{size.base} * .25" }
|
|
24
|
+
|
|
25
|
+
L'opzione di config jsonExpression controlla come vengono gestite:
|
|
26
|
+
|
|
27
|
+
'keep' (default) — scrive l'espressione così com'è; si presume che lo
|
|
28
|
+
strumento che la usa la valuti.
|
|
29
|
+
'calc' — la racchiude in un calc() CSS: "calc({size.base} * .25)"
|
|
30
|
+
gli alias restano come {riferimenti} che lo strumento
|
|
31
|
+
che li usa dovrà risolvere.
|
|
32
|
+
'resolve' — valuta l'espressione numericamente e scrive un valore concreto.
|
|
33
|
+
L'unità è ereditata dal primo token dimension
|
|
34
|
+
referenziato nell'espressione (ad es. {size.base} = 16px
|
|
35
|
+
-> 16 * .25 = 4 -> "4px"). Se la valutazione fallisce
|
|
36
|
+
l'espressione originale viene mantenuta con un warning.
|
|
37
|
+
*/
|
|
36
38
|
|
|
37
39
|
import StyleDictionary from 'style-dictionary';
|
|
38
40
|
import path from 'node:path';
|
|
39
41
|
|
|
40
|
-
//
|
|
42
|
+
// Intestazione anteposta a ogni file generato quando jsonFormat è 'jsonc'
|
|
41
43
|
const DISCLAIMER = [
|
|
42
44
|
'// -----------------------------------------------------------------------',
|
|
43
|
-
'//
|
|
44
|
-
'//
|
|
45
|
-
'//
|
|
46
|
-
'//
|
|
45
|
+
'// File generato — non modificare a mano.',
|
|
46
|
+
'// Questo file è prodotto dalla pipeline di build dei design token.',
|
|
47
|
+
'// Fonte di verità: i file dei token nella directory sorgente del progetto.',
|
|
48
|
+
'// Per rigenerarlo: node build-tokens.mjs --config <path/to/config>',
|
|
47
49
|
'// -----------------------------------------------------------------------',
|
|
48
50
|
'',
|
|
49
51
|
].join('\n');
|
|
50
52
|
|
|
51
|
-
// ──
|
|
53
|
+
// ── Helper per le espressioni ─────────────────────────────────────────────────
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
/*
|
|
56
|
+
Restituisce true se la stringa contiene un'espressione matematica — cioè ha almeno
|
|
57
|
+
un operatore (+, -, *, /) fuori da un riferimento a token ({...}).
|
|
58
|
+
I valori negativi come "-0.5rem" o "-8px" NON sono espressioni.
|
|
59
|
+
*/
|
|
56
60
|
const isExpression = (str) => {
|
|
57
61
|
if (typeof str !== 'string') return false;
|
|
58
|
-
//
|
|
62
|
+
// Rimuove i riferimenti ai token, poi cerca gli operatori
|
|
59
63
|
const stripped = str.replace(/\{[^}]+\}/g, '0');
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
/*
|
|
65
|
+
Rimuove il meno iniziale (numero negativo) prima di cercare gli operatori.
|
|
66
|
+
Un operatore ha significato solo quando compare tra due operandi,
|
|
67
|
+
cioè è preceduto da una cifra, una parentesi chiusa o un carattere di parola.
|
|
68
|
+
*/
|
|
63
69
|
return /[\d)]\s*[+\-*/]/.test(stripped) || /[+*/]/.test(stripped.replace(/^-/, ''));
|
|
64
70
|
};
|
|
65
71
|
|
|
66
|
-
//
|
|
72
|
+
// Costruisce una mappa di lookup dei token (dot-path -> token) dal dizionario.
|
|
67
73
|
const makeTokenMap = (dictionary) => {
|
|
68
74
|
const map = {};
|
|
69
75
|
for (const token of dictionary.allTokens) {
|
|
@@ -72,23 +78,25 @@ const makeTokenMap = (dictionary) => {
|
|
|
72
78
|
return map;
|
|
73
79
|
};
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
/*
|
|
82
|
+
Risolve un'espressione dimension in una stringa di valore concreto (ad es. "4px").
|
|
83
|
+
|
|
84
|
+
Strategia:
|
|
85
|
+
1. Trova il primo {riferimento} nell'espressione.
|
|
86
|
+
2. Lo cerca nella mappa dei token per ottenerne il valore numerico risolto e l'unità.
|
|
87
|
+
3. Sostituisce TUTTI i {riferimenti} nell'espressione con i loro valori numerici.
|
|
88
|
+
4. Valuta con Function() l'espressione aritmetica risultante.
|
|
89
|
+
5. Riattacca l'unità del passo 2.
|
|
90
|
+
|
|
91
|
+
Restituisce null se la risoluzione fallisce (il chiamante ripiega sulla stringa originale).
|
|
92
|
+
*/
|
|
85
93
|
const resolveExpression = (orig, tokenMap) => {
|
|
86
|
-
//
|
|
94
|
+
// Raccoglie tutte le chiavi {reference} in ordine di comparsa
|
|
87
95
|
const refPattern = /\{([^}]+)\}/g;
|
|
88
96
|
const refs = [...orig.matchAll(refPattern)];
|
|
89
97
|
if (refs.length === 0) return null;
|
|
90
98
|
|
|
91
|
-
//
|
|
99
|
+
// Determina l'unità dal primo token dimension referenziato
|
|
92
100
|
const firstRef = tokenMap[refs[0][1]];
|
|
93
101
|
if (!firstRef) return null;
|
|
94
102
|
|
|
@@ -98,7 +106,7 @@ const resolveExpression = (orig, tokenMap) => {
|
|
|
98
106
|
const baseNum = parseFloat(firstVal);
|
|
99
107
|
if (isNaN(baseNum)) return null;
|
|
100
108
|
|
|
101
|
-
//
|
|
109
|
+
// Sostituisce ogni {ref} con il suo valore numerico
|
|
102
110
|
let expr = orig;
|
|
103
111
|
for (const match of refs) {
|
|
104
112
|
const refKey = match[1];
|
|
@@ -109,13 +117,13 @@ const resolveExpression = (orig, tokenMap) => {
|
|
|
109
117
|
expr = expr.replace(match[0], String(refVal));
|
|
110
118
|
}
|
|
111
119
|
|
|
112
|
-
//
|
|
120
|
+
// Valuta — consente solo cifre, spazi e operatori aritmetici
|
|
113
121
|
if (!/^[\d\s+\-*/.()]+$/.test(expr)) return null;
|
|
114
122
|
|
|
115
123
|
try {
|
|
116
124
|
const result = Function(`"use strict"; return (${expr})`)();
|
|
117
125
|
if (typeof result !== 'number' || !isFinite(result)) return null;
|
|
118
|
-
//
|
|
126
|
+
// Arrotonda a una precisione ragionevole per evitare il rumore della virgola mobile
|
|
119
127
|
const rounded = parseFloat(result.toPrecision(10));
|
|
120
128
|
return unit ? `${rounded}${unit}` : String(rounded);
|
|
121
129
|
} catch {
|
|
@@ -123,7 +131,7 @@ const resolveExpression = (orig, tokenMap) => {
|
|
|
123
131
|
}
|
|
124
132
|
};
|
|
125
133
|
|
|
126
|
-
//
|
|
134
|
+
// Racchiude un'espressione dimension in calc() CSS, lasciando intatti i {riferimenti}.
|
|
127
135
|
const toCalc = (orig) => `calc(${orig})`;
|
|
128
136
|
|
|
129
137
|
// ── Format ───────────────────────────────────────────────────────────────────
|
|
@@ -136,11 +144,11 @@ StyleDictionary.registerFormat({
|
|
|
136
144
|
const tokenMap = (expressionMode === 'resolve') ? makeTokenMap(dictionary) : null;
|
|
137
145
|
|
|
138
146
|
for (const token of dictionary.allTokens) {
|
|
139
|
-
//
|
|
140
|
-
//
|
|
147
|
+
// I token caricati tramite `include` (sourceModes: token della modalità base resi
|
|
148
|
+
// disponibili alle altre modalità per la risoluzione dei riferimenti) non vengono emessi.
|
|
141
149
|
if (token.isSource === false) continue;
|
|
142
150
|
|
|
143
|
-
//
|
|
151
|
+
// Ricostruisce l'albero annidato dal percorso del token
|
|
144
152
|
let node = root;
|
|
145
153
|
for (let i = 0; i < token.path.length - 1; i++) {
|
|
146
154
|
const segment = token.path[i];
|
|
@@ -152,7 +160,7 @@ StyleDictionary.registerFormat({
|
|
|
152
160
|
const type = token.$type ?? token.type;
|
|
153
161
|
const orig = token.original?.$value ?? token.original?.value;
|
|
154
162
|
|
|
155
|
-
// ──
|
|
163
|
+
// ── Risoluzione del valore ──────────────────────────────────────────────
|
|
156
164
|
let value;
|
|
157
165
|
|
|
158
166
|
if (
|
|
@@ -160,29 +168,31 @@ StyleDictionary.registerFormat({
|
|
|
160
168
|
typeof orig === 'string' &&
|
|
161
169
|
isExpression(orig)
|
|
162
170
|
) {
|
|
163
|
-
//
|
|
171
|
+
// Il $value originale è un'espressione matematica
|
|
164
172
|
if (expressionMode === 'resolve') {
|
|
165
173
|
const resolved = resolveExpression(orig, tokenMap);
|
|
166
174
|
if (resolved !== null) {
|
|
167
175
|
value = resolved;
|
|
168
176
|
} else {
|
|
169
|
-
//
|
|
177
|
+
// Risoluzione fallita — mantiene l'originale ed emette un warning
|
|
170
178
|
// eslint-disable-next-line no-console
|
|
171
179
|
console.warn(`[build-tokens] json: could not resolve expression "${orig}" for token "${token.path.join('.')}". Keeping original.`);
|
|
172
180
|
value = orig;
|
|
173
181
|
}
|
|
174
182
|
} else if (expressionMode === 'calc') {
|
|
175
|
-
//
|
|
183
|
+
// Sostituisce i {riferimenti} con la loro notazione alias e racchiude in calc()
|
|
176
184
|
value = toCalc(orig);
|
|
177
185
|
} else {
|
|
178
|
-
// 'keep' —
|
|
186
|
+
// 'keep' — scrive l'espressione invariata
|
|
179
187
|
value = orig;
|
|
180
188
|
}
|
|
181
189
|
} else {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
/*
|
|
191
|
+
Valore non espressione: conserva i {riferimenti} ovunque compaiano.
|
|
192
|
+
- Alias puro: "{some.token}" → mantenuto così com'è per preservare i collegamenti tra token
|
|
193
|
+
- Funzione CSS: "color-mix(in srgb, {some.token} 60%, #000)" → mantenuta così com'è
|
|
194
|
+
- Valore semplice: "#ff0000", "16px", … → usa il $value risolto
|
|
195
|
+
*/
|
|
186
196
|
const containsRef = typeof orig === 'string' && orig.includes('{');
|
|
187
197
|
value = containsRef ? orig : (token.$value ?? token.value);
|
|
188
198
|
}
|
|
@@ -201,9 +211,8 @@ StyleDictionary.registerFormat({
|
|
|
201
211
|
});
|
|
202
212
|
|
|
203
213
|
// ── collectConcreteFilePaths ──────────────────────────────────────────────────
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
// Must be called AFTER `await sd.hasInitialized`.
|
|
214
|
+
// Estrae i percorsi di file concreti univoci da un'istanza di Style Dictionary.
|
|
215
|
+
// Va chiamata DOPO `await sd.hasInitialized`.
|
|
207
216
|
|
|
208
217
|
export const collectConcreteFilePaths = async (sd) => {
|
|
209
218
|
await sd.hasInitialized;
|
|
@@ -215,16 +224,17 @@ export const collectConcreteFilePaths = async (sd) => {
|
|
|
215
224
|
};
|
|
216
225
|
|
|
217
226
|
// ── buildJsonFiles ──────────────────────────────────────────────────────────
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
/*
|
|
228
|
+
@param {string[]} concreteFilePaths Da collectConcreteFilePaths()
|
|
229
|
+
@param {string|null} jsonDestFile Nome base del file aggregato, oppure null
|
|
230
|
+
@param {'json'|'jsonc'} jsonFormat Formato di output
|
|
231
|
+
@param {'keep'|'calc'|'resolve'} jsonExpression Modalità di gestione delle espressioni
|
|
232
|
+
@param {string} [suffix] Aggiunto a ogni nome di file di
|
|
233
|
+
destinazione, prima dell'estensione — usato dalla build sourceModes
|
|
234
|
+
(build-source-modes.mjs) per produrre un set di file per modalità, ad es.
|
|
235
|
+
"-light" -> "tokens-light.jsonc" / "size-light.jsonc" (default: '')
|
|
236
|
+
@returns {object[]} Descrittori di file per la platform di Style Dictionary
|
|
237
|
+
*/
|
|
228
238
|
|
|
229
239
|
export const buildJsonFiles = (
|
|
230
240
|
concreteFilePaths,
|
|
@@ -244,11 +254,13 @@ export const buildJsonFiles = (
|
|
|
244
254
|
}];
|
|
245
255
|
}
|
|
246
256
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
/*
|
|
258
|
+
Un file per sorgente, tutti nella stessa cartella jsonBuildPath — senza sottocartelle
|
|
259
|
+
che replicano l'albero dei sorgenti. Dato che i file sorgente possono condividere il nome base in
|
|
260
|
+
directory diverse (ad es. due componenti ciascuno con il proprio
|
|
261
|
+
<name>.minimo.tokens.mjs), in caso di collisioni fallisce in modo esplicito invece di lasciare
|
|
262
|
+
che uno sovrascriva l'altro in silenzio.
|
|
263
|
+
*/
|
|
252
264
|
const pathsByDestName = new Map();
|
|
253
265
|
for (const filePath of concreteFilePaths) {
|
|
254
266
|
const destName = path.basename(filePath).replace(/\.[^.]+$/, '') + suffix + ext;
|
|
@@ -1,75 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
/*
|
|
2
|
+
build-tokens-src/legacy-tokens-parser.mjs
|
|
3
|
+
Registra un parser di Style Dictionary che fa da ponte tra i file di token "legacy"
|
|
4
|
+
(sintassi in stile Style Dictionary v3/v4: nessun prefisso `$` su `value`/`type`,
|
|
5
|
+
riferimenti scritti come `{group.token.value}`) e la sintassi W3C DTCG
|
|
6
|
+
(`$value`/`$type`, riferimenti come `{group.token}`) richiesta da Style
|
|
7
|
+
Dictionary v5.
|
|
8
|
+
|
|
9
|
+
Perché serve: Style Dictionary v5 decide se una build "usesDtcg"
|
|
10
|
+
UNA SOLA VOLTA per build, a partire dal primo file sorgente elaborato (vedi
|
|
11
|
+
detectDtcgSyntax() chiamata in combineJSON.js di style-dictionary) — è
|
|
12
|
+
un unico flag globale, non un controllo per file. Mescolare un file in sintassi
|
|
13
|
+
legacy (ad es. un file esportato da Open Props, o da un vecchio progetto
|
|
14
|
+
Style Dictionary v3/v4) con sorgenti DTCG fa quindi sì che i token del
|
|
15
|
+
file legacy vengano scartati in silenzio, qualunque sia l'ordine dei file: non hanno mai
|
|
16
|
+
la chiave `$value` che il tagging di combineJSON (e il resto della
|
|
17
|
+
pipeline) si aspetta.
|
|
18
|
+
|
|
19
|
+
Questo parser intercetta ogni file sorgente `.json` (non `.jsonc` — quell'
|
|
20
|
+
estensione è riservata in questo progetto alle sorgenti DTCG scritte a mano,
|
|
21
|
+
già gestite correttamente dal loader integrato di Style Dictionary) e
|
|
22
|
+
converte, nodo per nodo:
|
|
23
|
+
value -> $value, type -> $type, comment/description -> $description
|
|
24
|
+
"{group.token.value}" -> "{group.token}" dentro le stringhe di riferimento
|
|
25
|
+
I nodi che usano già `$value` (sintassi DTCG v5) restano intatti, quindi
|
|
26
|
+
il parser è un no-op sicuro per i file che non richiedono conversione — non serve
|
|
27
|
+
alcun flag di config né elenco di file, il rilevamento è completamente automatico.
|
|
28
|
+
|
|
29
|
+
I nodi "ibridi" (un token con un valore proprio che è anche un gruppo con
|
|
30
|
+
figli annidati, ad es. other.ease.out di Open Props) non possono essere rappresentati in
|
|
31
|
+
DTCG v5, dove un nodo con $value è una foglia. Il valore proprio viene spostato in un
|
|
32
|
+
token figlio chiamato `default` (oppure `base` se `default` è già il nome di un
|
|
33
|
+
figlio; la build fallisce se entrambi sono occupati) — vedi collectHybridNodes().
|
|
34
|
+
|
|
35
|
+
Limitazione: i file `.json` gestiti da questo parser vengono letti con un semplice
|
|
36
|
+
JSON.parse (niente commenti, niente trailing comma), a differenza del loader
|
|
37
|
+
integrato di Style Dictionary (che usa JSON5 per .json/.jsonc/.json5). Così il builder
|
|
38
|
+
resta privo di dipendenze — le esportazioni di token legacy (Open Props, vecchi progetti
|
|
39
|
+
Style Dictionary v3/v4) sono comunque quasi sempre JSON rigoroso. Usare
|
|
40
|
+
`.jsonc` o `.mjs` per le sorgenti DTCG scritte a mano che richiedono commenti.
|
|
41
|
+
*/
|
|
40
42
|
|
|
41
43
|
import StyleDictionary from 'style-dictionary';
|
|
42
44
|
|
|
43
45
|
export const LEGACY_TOKENS_PARSER_NAME = 'minimo/legacy-tokens';
|
|
44
46
|
|
|
45
|
-
//
|
|
47
|
+
// Corrisponde a "{some.token.path.value}" -> cattura "some.token.path"
|
|
46
48
|
const LEGACY_REF = /\{([^}]+)\.value\}/g;
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
/*
|
|
51
|
+
Nome del token figlio che riceve il valore proprio di un nodo "ibrido"
|
|
52
|
+
(vedi collectHybridNodes()); FALLBACK_LEAF viene usato quando esiste già un figlio
|
|
53
|
+
con il nome preferito.
|
|
54
|
+
*/
|
|
51
55
|
const PREFERRED_LEAF = 'default';
|
|
52
56
|
const FALLBACK_LEAF = 'base';
|
|
53
57
|
|
|
54
58
|
/** @param {unknown} node @returns {node is Record<string, unknown>} */
|
|
55
59
|
const isPlainObject = (node) => node !== null && typeof node === 'object' && !Array.isArray(node);
|
|
56
60
|
|
|
57
|
-
// True
|
|
61
|
+
// True se il nodo è (o contiene, a qualsiasi profondità) un token, legacy o DTCG.
|
|
58
62
|
/** @param {unknown} node @returns {boolean} */
|
|
59
63
|
const hasTokenDescendant = (node) => isPlainObject(node)
|
|
60
64
|
&& (Object.hasOwn(node, 'value') || Object.hasOwn(node, '$value')
|
|
61
65
|
|| Object.values(node).some(hasTokenDescendant));
|
|
62
66
|
|
|
63
67
|
/*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* dot.path ->
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
68
|
+
* Un nodo legacy "ibrido" è un token (con `value` proprio) che è anche un gruppo, cioè
|
|
69
|
+
* ha figli che sono token o gruppi di token (ad es. other.ease.out di Open Props,
|
|
70
|
+
* con un valore proprio più out.1 ... out.5). Il valore proprio viene
|
|
71
|
+
* spostato in un token figlio: `default`, oppure `base` se `default` è già il nome
|
|
72
|
+
* di un figlio. Se entrambi sono occupati la build fallisce. Restituisce una mappa
|
|
73
|
+
* dot.path -> nome del figlio scelto, usata per convertire il nodo stesso e per
|
|
74
|
+
* riscrivere i riferimenti che puntano a esso (i riferimenti vengono riscritti solo
|
|
75
|
+
* all'interno dello stesso file: un riferimento da un altro file a un nodo ibrido deve
|
|
76
|
+
* usare esplicitamente il nome del figlio).
|
|
73
77
|
*/
|
|
74
78
|
/**
|
|
75
79
|
* @param {unknown} node
|
|
@@ -130,7 +134,7 @@ const convertLegacyRefs = (value, hybrids) => {
|
|
|
130
134
|
const convertLegacyNode = (node, path, hybrids) => {
|
|
131
135
|
if (!isPlainObject(node)) return node;
|
|
132
136
|
|
|
133
|
-
//
|
|
137
|
+
// Già sintassi DTCG v5: lascia intatto.
|
|
134
138
|
if (Object.hasOwn(node, '$value')) return node;
|
|
135
139
|
|
|
136
140
|
if (Object.hasOwn(node, 'value')) {
|
|
@@ -145,7 +149,7 @@ const convertLegacyNode = (node, path, hybrids) => {
|
|
|
145
149
|
const hybridLeaf = hybrids.get(path.join('.'));
|
|
146
150
|
if (hybridLeaf === undefined) return token;
|
|
147
151
|
|
|
148
|
-
//
|
|
152
|
+
// Nodo ibrido: diventa un gruppo, il suo valore proprio si sposta in un token figlio.
|
|
149
153
|
return {
|
|
150
154
|
...Object.fromEntries(
|
|
151
155
|
Object.entries(rest).map(([key, child]) => [key, convertLegacyNode(child, [...path, key], hybrids)])
|
|
@@ -154,26 +158,29 @@ const convertLegacyNode = (node, path, hybrids) => {
|
|
|
154
158
|
};
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
//
|
|
161
|
+
// Nodo gruppo: ricorre nei figli.
|
|
158
162
|
return Object.fromEntries(
|
|
159
163
|
Object.entries(node).map(([key, child]) => [key, convertLegacyNode(child, [...path, key], hybrids)])
|
|
160
164
|
);
|
|
161
165
|
};
|
|
162
166
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
167
|
+
/*
|
|
168
|
+
Esportata per il riutilizzo da token-rename-parser.mjs, che richiede lo stesso
|
|
169
|
+
caricamento .json legacy-o-DTCG (gestione dei nodi ibridi inclusa) per il
|
|
170
|
+
sottoinsieme di file che hanno anche una mappa di rinomina `transform` registrata.
|
|
171
|
+
*/
|
|
166
172
|
/** @param {string} contents @param {string} filePath @returns {unknown} */
|
|
167
173
|
export const parseLegacyFile = (contents, filePath) => {
|
|
168
174
|
const tree = JSON.parse(contents);
|
|
169
175
|
return convertLegacyNode(tree, [], collectHybridNodes(tree, [], filePath));
|
|
170
176
|
};
|
|
171
177
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
/*
|
|
179
|
+
Registra il parser globalmente sulla classe StyleDictionary. Per eseguirlo
|
|
180
|
+
effettivamente, anche un'istanza di Style Dictionary deve aderire tramite
|
|
181
|
+
`parsers: [LEGACY_TOKENS_PARSER_NAME]` nella propria config (la sola registrazione
|
|
182
|
+
non lo attiva per ogni istanza — vedi la documentazione degli hook parser di Style Dictionary).
|
|
183
|
+
*/
|
|
177
184
|
export const registerLegacyTokensParser = () => {
|
|
178
185
|
StyleDictionary.registerParser({
|
|
179
186
|
name: LEGACY_TOKENS_PARSER_NAME,
|