@massimo-cassandro/minimo 1.41.4 → 1.41.5

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.
Files changed (131) hide show
  1. package/README.md +12 -12
  2. package/charts/src/node-helpers/create-svg-canvas-node.mjs +2 -2
  3. package/charts/src/node-helpers/svg-text-to-path.js +9 -9
  4. package/charts/src/rating-display/index.js +1 -1
  5. package/charts/src/rating-display/ratindDisplayAnimation.js +3 -3
  6. package/design-tokens/README.md +2 -2
  7. package/design-tokens/_src/_readme.md +26 -26
  8. package/dev-tools/README.md +16 -16
  9. package/dev-tools/create-favicons/README.md +31 -31
  10. package/dev-tools/create-favicons/src/create-ico.mjs +2 -2
  11. package/dev-tools/create-favicons/src/default-params.mjs +1 -1
  12. package/dev-tools/create-favicons/src/init.mjs +1 -1
  13. package/dev-tools/design-tokens-builder/README.md +102 -102
  14. package/dev-tools/design-tokens-builder/build-tokens-src/build-source-modes.mjs +85 -73
  15. package/dev-tools/design-tokens-builder/build-tokens-src/config.mjs +109 -85
  16. package/dev-tools/design-tokens-builder/build-tokens-src/formats/css.mjs +113 -90
  17. package/dev-tools/design-tokens-builder/build-tokens-src/formats/json.mjs +107 -95
  18. package/dev-tools/design-tokens-builder/build-tokens-src/legacy-tokens-parser.mjs +71 -64
  19. package/dev-tools/design-tokens-builder/build-tokens-src/light-dark.mjs +75 -65
  20. package/dev-tools/design-tokens-builder/build-tokens-src/merge-css.mjs +113 -102
  21. package/dev-tools/design-tokens-builder/build-tokens-src/platforms.mjs +36 -30
  22. package/dev-tools/design-tokens-builder/build-tokens-src/resolve-source-paths.mjs +15 -13
  23. package/dev-tools/design-tokens-builder/build-tokens-src/source-prefixes.mjs +44 -42
  24. package/dev-tools/design-tokens-builder/build-tokens-src/source-transforms.mjs +89 -83
  25. package/dev-tools/design-tokens-builder/build-tokens-src/token-rename-parser.mjs +99 -86
  26. package/dev-tools/design-tokens-builder/build-tokens-src/transforms.mjs +64 -48
  27. package/dev-tools/design-tokens-builder/build-tokens.mjs +80 -68
  28. package/dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs +103 -77
  29. package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +275 -238
  30. package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +2 -2
  31. package/dev-tools/starter-kit/source_files/app/CLAUDE.md +4 -2
  32. package/dev-tools/starter-kit/source_files/app/{css/index.css → index.css} +2 -2
  33. package/dev-tools/starter-kit/source_files/app/index.js +1 -1
  34. package/dev-tools/starter-kit/source_files/root/_sf/controller/ImgViewerController.php +3 -3
  35. package/dev-tools/starter-kit/source_files/root/_sf/controller/ViewerController.php +2 -2
  36. package/dev-tools/starter-kit/source_files/root/stylelint.config.mjs +1 -1
  37. package/dev-tools/starter-kit/source_files/root/webpack-config-modules/css-rules.mjs +1 -1
  38. package/dev-tools/stylelint-config/README.md +7 -7
  39. package/dev-tools/svg-icons-tools/README.md +32 -32
  40. package/dev-tools/svg-icons-tools/src/config-manager.mjs +1 -1
  41. package/dev-tools/svg-icons-tools/src/default-config.mjs +118 -118
  42. package/dev-tools/svg-icons-tools/src/jsx-icon-file-builder.mjs +24 -24
  43. package/dev-tools/svg-icons-tools/src/parse-svg-filename.mjs +3 -3
  44. package/dev-tools/svg-icons-tools/src/parse-svg-files.mjs +1 -1
  45. package/dev-tools/svg-icons-tools/src/parse-svg-markup.mjs +4 -4
  46. package/dev-tools/svg-icons-tools/src/svg-to-jsx.mjs +2 -2
  47. package/dev-tools/svg-icons-tools/src/svg-to-optimized.mjs +2 -2
  48. package/dev-tools/svg-icons-tools/src/svg-to-symbols.mjs +2 -2
  49. package/dev-tools/upd@m/README.md +1 -1
  50. package/dev-tools/upd@m/index.mjs +1 -1
  51. package/dev-tools/update-version/README.md +9 -9
  52. package/package.json +1 -1
  53. package/snippets/unsplash-browser-app/README.md +1 -1
  54. package/snippets/unsplash-browser-app/unsplash-utilities.js +9 -9
  55. package/src/components/autocomplete/README.md +3 -3
  56. package/src/components/autocomplete/autocomplete-engine.js +75 -63
  57. package/src/components/autocomplete/check-autocomplete.js +3 -3
  58. package/src/components/dismiss-alerts.js +3 -3
  59. package/src/components/form-reset-submit.js +6 -6
  60. package/src/components/inner-nav/inner-nav.js +2 -2
  61. package/src/components/modal-alert/modal-alert.js +67 -65
  62. package/src/components/modal-alert/modal-alert.minimo.tokens.mjs +1 -1
  63. package/src/components/modal-popup/modal-popup.js +56 -56
  64. package/src/components/overlay/overlay.js +3 -3
  65. package/src/components/sf-macro/readme.md +1 -1
  66. package/src/components/sf-macro/sf-macro.js +27 -23
  67. package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +83 -79
  68. package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +44 -44
  69. package/src/components/snackbar/snackbar.js +19 -19
  70. package/src/components/spinner/spinner.js +3 -3
  71. package/src/components/unsplash-page/README.md +8 -8
  72. package/src/components/unsplash-page/fetch-unsplash-data.js +3 -3
  73. package/src/components/unsplash-page/unsplash-page.js +33 -33
  74. package/src/components/unsplash-page/unsplash-page.module.css +1 -1
  75. package/src/css/alerts.css +2 -2
  76. package/src/css/forms/forms.css +4 -4
  77. package/src/css/forms/validation.css +1 -1
  78. package/src/css/margin-padding-media.css +4 -4
  79. package/src/css/margin-padding.css +4 -4
  80. package/src/css/reset.css +11 -11
  81. package/src/icons/read-me.md +1 -1
  82. package/src/minimo.css +3 -3
  83. package/src/utilities/better-text-with-places.js +22 -22
  84. package/src/utilities/better-text.js +42 -35
  85. package/src/utilities/classnames.js +8 -8
  86. package/src/utilities/cookies.js +6 -6
  87. package/src/utilities/create-id.js +3 -3
  88. package/src/utilities/disable-btns-on-submit.js +2 -2
  89. package/src/utilities/dom-builder/dom-builder.js +89 -86
  90. package/src/utilities/dom-builder/domBuilderBasicSetup.js +9 -9
  91. package/src/utilities/dom-builder/parseDomString.js +23 -23
  92. package/src/utilities/dom-builder-helpers/README.md +2 -2
  93. package/src/utilities/dom-builder-helpers/form-tags.js +100 -100
  94. package/src/utilities/dom-builder-helpers/picture-tag.js +39 -39
  95. package/src/utilities/enable-submit-btns.js +1 -1
  96. package/src/utilities/escape-html.js +2 -2
  97. package/src/utilities/generate-pwd.js +4 -4
  98. package/src/utilities/linked-dates.js +13 -13
  99. package/src/utilities/parse-file-size.js +6 -6
  100. package/src/utilities/random-id.js +3 -3
  101. package/src/utilities/relative-date.js +40 -40
  102. package/src/utilities/sentence-case.js +1 -1
  103. package/src/utilities/strip-tags.js +1 -1
  104. package/src/utilities/title-case.js +1 -1
  105. package/src/utilities/truncate-string.js +5 -5
  106. package/src/utilities/validation-error-class.js +12 -12
  107. package/src/web-components/json-table/json-table-component.js +123 -121
  108. package/src/web-components/json-table/json-table-component.module.css +6 -6
  109. package/src/web-components/json-table/json-table.minimo.tokens.mjs +6 -6
  110. package/src/web-components/json-table/readme.md +72 -108
  111. package/src/web-components/json-table/src/cell-content.js +25 -25
  112. package/src/web-components/json-table/src/content-utils.js +21 -21
  113. package/src/web-components/json-table/src/data-types.js +32 -32
  114. package/src/web-components/json-table/src/defaults.js +230 -191
  115. package/src/web-components/json-table/src/get-data.js +55 -38
  116. package/src/web-components/json-table/src/icons.js +17 -17
  117. package/src/web-components/json-table/src/info-section.js +18 -18
  118. package/src/web-components/json-table/src/main-builder.js +45 -45
  119. package/src/web-components/json-table/src/pagination.js +32 -32
  120. package/src/web-components/json-table/src/parse-cols.js +18 -18
  121. package/src/web-components/json-table/src/parse-rows.js +17 -17
  122. package/src/web-components/json-table/src/resolve-params.js +53 -41
  123. package/src/web-components/json-table/src/search.js +13 -13
  124. package/src/web-components/json-table/src/sorting.js +20 -20
  125. package/src/web-components/json-table/src/table-body.js +13 -13
  126. package/src/web-components/json-table/src/table-builder.js +34 -34
  127. package/src/web-components/json-table/src/table-tfoot.js +8 -8
  128. package/src/web-components/json-table/src/table-thead.js +21 -21
  129. package/src/web-components/json-table/src/update-info.js +11 -11
  130. package/types/classes.d.ts +2 -2
  131. package/types/global.d.ts +18 -12
@@ -1,46 +1,50 @@
1
- // build-tokens-src/light-dark.mjs
2
- // Supports the `useLightDarkFunc` config option (see config.mjs): with a
3
- // sourceModes build (see build-source-modes.mjs) that defines both a `light`
4
- // and a `dark` mode, custom properties present in BOTH — matched by name —
5
- // are written once, as `--name: light-dark(<light-value>, <dark-value>);`,
6
- // instead of being split across the base mode's top-level `:root { ... }`
7
- // block and a `@media (prefers-color-scheme: dark) { ... }` block. If the two
8
- // values are identical, light-dark() would be redundant: the bare value is
9
- // written instead, e.g. `--name: <value>;`.
10
- //
11
- // Only `light` and `dark` are affected:
12
- // - a third mode (e.g. a custom `high-contrast` key in sourceModes) is left
13
- // completely untouched, still nested under its own
14
- // `@media (prefers-color-scheme: <mode>) { ... }` rule
15
- // - a property present in only one of `light`/`dark` is left in its own
16
- // mode's block — still behind that mode's `@media` rule, unless that mode
17
- // happens to be the configured base mode
18
- //
19
- // The shared `light-dark()` declarations always land in the configured base
20
- // mode's block (build-source-modes.mjs' `sourceModesBase`, whichever of
21
- // `light`, `dark`, or a third mode that is) — never specifically in `light`'s
22
- // or `dark`'s own block — since the light-dark() function resolves against
23
- // the effective `color-scheme`, regardless of whether the declaration itself
24
- // sits inside a `@media (prefers-color-scheme: ...)` rule or not.
25
- //
26
- // Interaction with `mergeCustomProps`: nothing special is needed here — the
27
- // per-mode merge with pre-existing custom properties (see ../merge-css.mjs)
28
- // already runs earlier, inside computeFinalProps() (formats/css.mjs), before
29
- // this module ever sees the props. So a pre-existing file written with the
30
- // classic `@media (prefers-color-scheme: dark)` split (i.e. built before
31
- // useLightDarkFunc was turned on) is reconciled into light-dark() calls just
32
- // like freshly generated values, matched by property name. As the values
33
- // merged in this way were never meant to be combined into light-dark() calls,
34
- // unexpected pre-existing content (e.g. a manually-added property whose name
35
- // happens to collide across modes) can produce an invalid combined value —
36
- // left for the user to fix, same as any other mergeCustomProps edge case.
1
+ /*
2
+ build-tokens-src/light-dark.mjs
3
+ Supporta l'opzione di config `useLightDarkFunc` (vedi config.mjs): con una
4
+ build sourceModes (vedi build-source-modes.mjs) che definisce sia una modalità `light`
5
+ sia una `dark`, le custom properties presenti in ENTRAMBE — individuate per nome —
6
+ vengono scritte una sola volta, come `--name: light-dark(<valore-light>, <valore-dark>);`,
7
+ invece di essere divise tra il blocco `:root { ... }` di primo livello della modalità base
8
+ e un blocco `@media (prefers-color-scheme: dark) { ... }`. Se i due
9
+ valori sono identici, light-dark() sarebbe ridondante: viene scritto invece
10
+ il valore semplice, ad es. `--name: <valore>;`.
11
+
12
+ Sono interessate solo `light` e `dark`:
13
+ - una terza modalità (ad es. una chiave personalizzata `high-contrast` in sourceModes) resta
14
+ del tutto intatta, sempre annidata nella propria regola
15
+ `@media (prefers-color-scheme: <modalità>) { ... }`
16
+ - una proprietà presente in una sola tra `light`/`dark` resta nel blocco della
17
+ propria modalità — sempre dietro la regola `@media` di quella modalità, a meno che quella
18
+ modalità non sia la modalità base configurata
19
+
20
+ Le dichiarazioni `light-dark()` condivise finiscono sempre nel blocco della modalità
21
+ base configurata (il `sourceModesBase` di build-source-modes.mjs, qualunque sia tra
22
+ `light`, `dark` o una terza modalità) — mai specificamente nel blocco di `light`
23
+ o di `dark` — dato che la funzione light-dark() si risolve in base al
24
+ `color-scheme` effettivo, indipendentemente dal fatto che la dichiarazione stessa
25
+ si trovi dentro una regola `@media (prefers-color-scheme: ...)` o meno.
26
+
27
+ Interazione con `mergeCustomProps`: qui non serve nulla di speciale — il merge
28
+ per modalità con le custom properties preesistenti (vedi ../merge-css.mjs)
29
+ viene già eseguito prima, dentro computeFinalProps() (formats/css.mjs), prima che
30
+ questo modulo veda le proprietà. Quindi un file preesistente scritto con la
31
+ classica divisione `@media (prefers-color-scheme: dark)` (cioè generato prima che
32
+ useLightDarkFunc fosse attivato) viene riconciliato in chiamate light-dark()
33
+ come i valori appena generati, individuando le proprietà per nome. Poiché i valori
34
+ uniti in questo modo non erano mai stati pensati per essere combinati in chiamate light-dark(),
35
+ contenuti preesistenti inattesi (ad es. una proprietà aggiunta a mano il cui nome
36
+ collide per caso tra le modalità) possono produrre un valore combinato non valido —
37
+ da correggere a cura dell'utente, come ogni altro caso limite di mergeCustomProps.
38
+ */
37
39
 
38
40
  import { buildCssBlock } from './formats/css.mjs';
39
41
 
40
- // Splits a declaration tail (as produced by computeFinalProps(): value +
41
- // terminating `;` + optional trailing comment) into its bare CSS value and
42
- // its trailing comment, so the value can be embedded as a light-dark()
43
- // argument without dragging the `;`/comment along.
42
+ /*
43
+ Divide la coda di una dichiarazione (come prodotta da computeFinalProps(): valore +
44
+ `;` finale + eventuale commento finale) nel suo valore CSS semplice e nel suo
45
+ commento finale, così che il valore possa essere inserito come argomento di light-dark()
46
+ senza trascinare con sé `;`/commento.
47
+ */
44
48
  /** @param {string} tail @returns {{value: string, comment: string}} */
45
49
  const splitTail = (tail) => {
46
50
  const match = /^(.*?);\s*(\/\*.*\*\/)?\s*$/.exec(tail.trim());
@@ -50,16 +54,16 @@ const splitTail = (tail) => {
50
54
 
51
55
  /**
52
56
  * @param {object} opts
53
- * @param {Record<string, Record<string,string>>} opts.modeFinalProps mode → (name → declaration tail) map, one entry per sourceModes key — as captured from computeFinalProps()/lastFinalProps (see formats/css.mjs) right after each per-mode sd.formatPlatform('css') call in build-source-modes.mjs
54
- * @param {string[]} opts.modeNames all sourceModes keys, in config order
55
- * @param {string} opts.baseMode mode whose block is printed as a top-level, unconditioned `:root` (or custom selector) — see sourceModesBase in config.mjs
56
- * @param {string} [opts.selector] customPropsSelector — passed through unchanged to buildCssBlock() (default: ':root')
57
+ * @param {Record<string, Record<string,string>>} opts.modeFinalProps mappa modalità → (nome → coda della dichiarazione), una voce per ogni chiave di sourceModes — come catturata da computeFinalProps()/lastFinalProps (vedi formats/css.mjs) subito dopo ogni chiamata per modalità a sd.formatPlatform('css') in build-source-modes.mjs
58
+ * @param {string[]} opts.modeNames tutte le chiavi di sourceModes, nell'ordine della config
59
+ * @param {string} opts.baseMode modalità il cui blocco viene stampato come `:root` (o selettore personalizzato) di primo livello, senza condizioni — vedi sourceModesBase in config.mjs
60
+ * @param {string} [opts.selector] customPropsSelector — passato invariato a buildCssBlock() (default: ':root')
57
61
  * @param {{name:string,prefixes:string[]}[]} [opts.customPropsGroups]
58
62
  * @returns {{blocks: Record<string,string>, counts: Record<string,number>}|null}
59
- * Rebuilt CSS block text + custom-prop count, keyed by mode, for every mode
60
- * touched by the reconciliation (`light`, `dark`, and `baseMode`, which may
61
- * coincide) — or null when sourceModes does not define both `light` and
62
- * `dark` (useLightDarkFunc then has no effect, see config.mjs)
63
+ * Testo del blocco CSS ricostruito + conteggio delle custom props, indicizzato per modalità, per ogni modalità
64
+ * toccata dalla riconciliazione (`light`, `dark` e `baseMode`, che possono
65
+ * coincidere) — oppure null quando sourceModes non definisce sia `light` sia
66
+ * `dark` (useLightDarkFunc non ha allora alcun effetto, vedi config.mjs)
63
67
  */
64
68
  export const applyLightDarkFunc = ({ modeFinalProps, modeNames, baseMode, selector, customPropsGroups }) => {
65
69
  if (!modeNames.includes('light') || !modeNames.includes('dark')) return null;
@@ -73,11 +77,11 @@ export const applyLightDarkFunc = ({ modeFinalProps, modeNames, baseMode, select
73
77
  for (const name of commonNames) {
74
78
  const light = splitTail(lightProps[name]);
75
79
  const dark = splitTail(darkProps[name]);
76
- // Prefers the light-side trailing comment (e.g. a token $description);
77
- // falls back to the dark-side one if light has none.
80
+ // Preferisce il commento finale lato light (ad es. una $description del token);
81
+ // ripiega su quello lato dark se light non ne ha.
78
82
  const comment = light.comment || dark.comment;
79
- // Equal light/dark values: light-dark(x, x) would be redundant — use the
80
- // bare value directly instead.
83
+ // Valori light/dark uguali: light-dark(x, x) sarebbe ridondante — usa
84
+ // direttamente il valore semplice.
81
85
  const value = light.value === dark.value
82
86
  ? light.value
83
87
  : `light-dark(${light.value}, ${dark.value})`;
@@ -94,24 +98,30 @@ export const applyLightDarkFunc = ({ modeFinalProps, modeNames, baseMode, select
94
98
  const updatedFinalProps = { ...modeFinalProps };
95
99
  updatedFinalProps.light = stripCommon(lightProps);
96
100
  updatedFinalProps.dark = stripCommon(darkProps);
97
- // The shared declarations always land in the base mode's own map — adding
98
- // them back in if the base mode happens to be `light` or `dark` itself
99
- // (whose map was just stripped above), or into a third mode's map.
101
+ /*
102
+ Le dichiarazioni condivise finiscono sempre nella mappa della modalità base — reinserendole
103
+ se la modalità base è proprio `light` o `dark` (la cui mappa è appena stata ripulita
104
+ qui sopra), oppure nella mappa di una terza modalità.
105
+ */
100
106
  updatedFinalProps[baseMode] = { ...updatedFinalProps[baseMode], ...sharedProps };
101
107
 
102
- // The base mode's `color-scheme` value is always normalised to read
103
- // "light dark [...other modes]", with `light` before `dark`, regardless of
104
- // the order sourceModes keys were declared in config or of which of the
105
- // two is the configured base — light-dark() itself is positional
106
- // (light-value first, dark-value second), so the accompanying
107
- // `color-scheme` declaration follows the same, predictable reading. Modes
108
- // other than light/dark, if any, are appended after, unaffected.
108
+ /*
109
+ Il valore `color-scheme` della modalità base viene sempre normalizzato in
110
+ "light dark [...altre modalità]", con `light` prima di `dark`, indipendentemente dall'
111
+ ordine in cui le chiavi di sourceModes sono dichiarate nella config o da quale delle
112
+ due sia la modalità base configurata — light-dark() stessa è posizionale
113
+ (prima il valore light, poi quello dark), quindi la dichiarazione
114
+ `color-scheme` che l'accompagna segue la stessa lettura prevedibile. Le modalità
115
+ diverse da light/dark, se presenti, vengono aggiunte dopo, senza modifiche.
116
+ */
109
117
  const restModes = modeNames.filter((mode) => mode !== 'light' && mode !== 'dark');
110
118
  const colorScheme = ['light', 'dark', ...restModes].join(' ');
111
119
 
112
- // Only `light`, `dark`, and the base mode (which may be one of the two, or
113
- // a third mode) need re-rendering: every other sourceModes key is
114
- // untouched and keeps its already-built block (see build-source-modes.mjs).
120
+ /*
121
+ Solo `light`, `dark` e la modalità base (che può essere una delle due, oppure
122
+ una terza modalità) devono essere renderizzate di nuovo: ogni altra chiave di sourceModes
123
+ non viene toccata e conserva il blocco già costruito (vedi build-source-modes.mjs).
124
+ */
115
125
  const modesToRebuild = new Set(['light', 'dark', baseMode]);
116
126
 
117
127
  /** @type {Record<string,string>} */
@@ -1,59 +1,63 @@
1
- // build-tokens-src/merge-css.mjs
2
- // Supports the `mergeCustomProps` config option: pre-existing custom
3
- // properties in the CSS destination file take priority over the ones
4
- // generated by the current build (manual overrides/additions survive rebuilds).
5
- //
6
- // Usage (single `source` build):
7
- // 1. Call loadExistingCustomProps(absDestPath) BEFORE Style Dictionary runs,
8
- // since it reads the file that is about to be overwritten.
9
- // 2. The css/variables-sorted format (see formats/css.mjs) calls
10
- // mergeCustomProps(generatedMap) while building the output, right before
11
- // serialising the final CSS text.
12
- //
13
- // `mergeCustomProps` may also be an array of strings/RegExps: in that case
14
- // only the generated properties whose token source file matches one of the
15
- // entries are merged (pre-existing value wins); the others are overwritten by
16
- // the generated value. Pre-existing properties that are no longer generated
17
- // (no token, hence no source file) are always kept. See matchesSource().
18
- //
19
- // Usage (sourceModes build, see build-source-modes.mjs):
20
- // 1. Call loadExistingCustomPropsScoped(absDestPath, baseMode) BEFORE any
21
- // of the per-mode Style Dictionary instances run.
22
- // 2. The css/variables-sorted format calls mergeCustomProps(generatedMap, mode)
23
- // once per mode. Declarations are matched only within the same mode's
24
- // scope (the base `:root { ... }` block, or the `:root { ... }` nested
25
- // inside that mode's `@media (prefers-color-scheme: <mode>) { ... }`),
26
- // so the same custom property name defined with different values across
27
- // modes is never mixed up.
1
+ /*
2
+ build-tokens-src/merge-css.mjs
3
+ Supporta l'opzione di config `mergeCustomProps`: le custom properties preesistenti
4
+ nel file CSS di destinazione hanno priorità su quelle generate dalla build
5
+ corrente (override/aggiunte manuali sopravvivono alle build successive).
6
+
7
+ Utilizzo (build a `source` singolo):
8
+ 1. Chiamare loadExistingCustomProps(absDestPath) PRIMA che Style Dictionary venga eseguito,
9
+ perché legge il file che sta per essere sovrascritto.
10
+ 2. Il format css/variables-sorted (vedi formats/css.mjs) chiama
11
+ mergeCustomProps(generatedMap) mentre costruisce l'output, subito prima di
12
+ serializzare il testo CSS finale.
13
+
14
+ `mergeCustomProps` può essere anche un array di stringhe/RegExp: in tal caso
15
+ vengono unite solo le proprietà generate il cui file sorgente di token corrisponde a una
16
+ delle voci (vince il valore preesistente); le altre vengono sovrascritte dal
17
+ valore generato. Le proprietà preesistenti non più generate
18
+ (nessun token, quindi nessun file sorgente) vengono sempre mantenute. Vedi matchesSource().
19
+
20
+ Utilizzo (build sourceModes, vedi build-source-modes.mjs):
21
+ 1. Chiamare loadExistingCustomPropsScoped(absDestPath, baseMode) PRIMA che venga eseguita
22
+ una qualsiasi delle istanze di Style Dictionary per modalità.
23
+ 2. Il format css/variables-sorted chiama mergeCustomProps(generatedMap, mode)
24
+ una volta per modalità. Le dichiarazioni vengono confrontate solo nell'ambito della stessa
25
+ modalità (il blocco base `:root { ... }`, oppure il `:root { ... }` annidato
26
+ dentro il `@media (prefers-color-scheme: <modalità>) { ... }` di quella modalità),
27
+ così che lo stesso nome di custom property definito con valori diversi tra le
28
+ modalità non venga mai confuso.
29
+ */
28
30
 
29
31
  import { existsSync, readFileSync } from 'node:fs';
30
32
 
31
33
  const CUSTOM_PROP_RE = /^\s*--([\w-]+):\s*(.+)$/gm;
32
34
 
33
35
  /**
34
- * Parses `--name: <tail>` declarations out of a CSS text block. <tail> is
35
- * captured verbatim (value, terminating `;`, and anything else on the same
36
- * line, e.g. a trailing comment) so it round-trips unchanged through a merge.
37
- * Only single-line declarations are supported.
36
+ * Estrae le dichiarazioni `--name: <tail>` da un blocco di testo CSS. <tail> viene
37
+ * catturato così com'è (valore, `;` finale e qualsiasi altra cosa sulla stessa
38
+ * riga, ad es. un commento finale) così da attraversare un merge senza modifiche.
39
+ * Sono supportate solo le dichiarazioni su una riga.
38
40
  * @param {string} cssText
39
- * @returns {Record<string,string>} name → declaration-tail map, in first-seen order
41
+ * @returns {Record<string,string>} mappa nome → coda della dichiarazione, in ordine di prima comparsa
40
42
  */
41
43
  export const parseCustomProps = (cssText) => {
42
44
  /** @type {Record<string,string>} */
43
45
  const map = {};
44
46
  for (const match of cssText.matchAll(CUSTOM_PROP_RE)) {
45
47
  let tail = match[2].trim();
46
- // A multi-line comment is cut at the end of the line (only single-line
47
- // declarations are parsed): close it, or the resulting CSS would be invalid
48
+ // Un commento su più righe viene troncato a fine riga (vengono lette solo le dichiarazioni
49
+ // su una riga): va chiuso, altrimenti il CSS risultante non sarebbe valido
48
50
  if (tail.lastIndexOf('/*') > tail.lastIndexOf('*/')) tail += ' */';
49
51
  map[match[1]] = tail;
50
52
  }
51
53
  return map;
52
54
  };
53
55
 
54
- // Returns the index of the closing brace matching the `{` at openIndex, by
55
- // simple depth counting. Braces inside comments/strings are not special-cased
56
- // — not expected to occur in generated custom-properties CSS.
56
+ /*
57
+ Restituisce l'indice della parentesi graffa di chiusura corrispondente alla `{` in openIndex, con un
58
+ semplice conteggio della profondità. Le graffe dentro commenti/stringhe non sono gestite in modo
59
+ speciale — non ci si aspetta che compaiano nel CSS delle custom properties generato.
60
+ */
57
61
  /** @param {string} text @param {number} openIndex */
58
62
  const matchBraces = (text, openIndex) => {
59
63
  let depth = 0;
@@ -67,23 +71,26 @@ const matchBraces = (text, openIndex) => {
67
71
  return -1;
68
72
  };
69
73
 
70
- // Escapes a string for literal use inside a RegExp — needed because
71
- // customPropsSelector (see config.mjs) can contain regex-special characters,
72
- // e.g. ':where(html)'.
74
+ /*
75
+ Esegue l'escape di una stringa per l'uso letterale dentro una RegExp — necessario perché
76
+ customPropsSelector (vedi config.mjs) può contenere caratteri speciali delle regex,
77
+ ad es. ':where(html)'.
78
+ */
73
79
  /** @param {string} str */
74
80
  const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
75
81
 
76
- // Finds every @media (prefers-color-scheme: <mode>) { ... } block in a
77
- // previously generated sourceModes CSS destFile, with absolute character
78
- // offsets into cssText. Used to split the file into per-mode scopes (see
79
- // splitModeScopes() below) and, by check-unresolved-custom-props.mjs, to
80
- // tell which mode a given custom property declaration belongs to.
81
- // An optional wrapping `@layer { ... }` (addLayer option) is transparent to
82
- // this search, since it only looks for the `@media (prefers-color-scheme: ...)`
83
- // pattern itself.
84
- // @param {string} cssText
85
- // @returns {{mode:string,start:number,end:number}[]} start/end are the
86
- // indices of the block's outer `{`/matching `}` (inclusive)
82
+ /*
83
+ Trova ogni blocco @media (prefers-color-scheme: <modalità>) { ... } in un file di
84
+ destinazione CSS sourceModes generato in precedenza, con offset assoluti dei caratteri in
85
+ cssText. Usato per dividere il file in ambiti per modalità (vedi
86
+ splitModeScopes() più sotto) e, da check-unresolved-custom-props.mjs, per
87
+ capire a quale modalità appartiene una data dichiarazione di custom property.
88
+ Un eventuale `@layer { ... }` che racchiude tutto (opzione addLayer) è trasparente per
89
+ questa ricerca, dato che cerca solo il pattern `@media (prefers-color-scheme: ...)` stesso.
90
+ @param {string} cssText
91
+ @returns {{mode:string,start:number,end:number}[]} start/end sono gli
92
+ indici della `{` esterna del blocco e della `}` corrispondente (inclusi)
93
+ */
87
94
  export const findMediaModeBlocks = (cssText) => {
88
95
  const MEDIA_RE = /@media\s*\(\s*prefers-color-scheme\s*:\s*([\w-]+)\s*\)\s*\{/g;
89
96
  /** @type {{mode:string,start:number,end:number}[]} */
@@ -97,23 +104,25 @@ export const findMediaModeBlocks = (cssText) => {
97
104
  return mediaBlocks;
98
105
  };
99
106
 
100
- // Splits a previously generated sourceModes CSS destFile into per-mode
101
- // scopes (see build-source-modes.mjs for the shape of the generated file):
102
- // - the base scope is the top-level `<selector> { ... }` block, i.e. the
103
- // one NOT nested inside a `@media (prefers-color-scheme: ...)` rule
104
- // - every other scope is the `<selector> { ... }` block nested inside its
105
- // own `@media (prefers-color-scheme: <mode>) { ... }` rule
106
- // @param {string} cssText
107
- // @param {string} [selector] the customPropsSelector the file was generated
108
- // with (default: ':root' — see config.mjs)
109
- // @returns {Record<string,string>} mode → CSS body text (base mode keyed as '__base__')
107
+ /*
108
+ Divide un file di destinazione CSS sourceModes generato in precedenza in ambiti
109
+ per modalità (vedi build-source-modes.mjs per la forma del file generato):
110
+ - l'ambito base è il blocco `<selector> { ... }` di primo livello, cioè
111
+ quello NON annidato dentro una regola `@media (prefers-color-scheme: ...)`
112
+ - ogni altro ambito è il blocco `<selector> { ... }` annidato dentro la propria
113
+ regola `@media (prefers-color-scheme: <modalità>) { ... }`
114
+ @param {string} cssText
115
+ @param {string} [selector] il customPropsSelector con cui è stato generato il file
116
+ (default: ':root' — vedi config.mjs)
117
+ @returns {Record<string,string>} modalità → testo del corpo CSS (la modalità base ha chiave '__base__')
118
+ */
110
119
  const splitModeScopes = (cssText, selector = ':root') => {
111
120
  /** @type {Record<string,string>} */
112
121
  const scopes = {};
113
122
  const selectorRe = new RegExp(`${escapeRegExp(selector)}\\s*\\{`);
114
123
 
115
- // 1. Every @media (prefers-color-scheme: <mode>) { ... } block, and the
116
- // <selector> { ... } body nested inside each one.
124
+ // 1. Ogni blocco @media (prefers-color-scheme: <modalità>) { ... } e il corpo
125
+ // <selector> { ... } annidato dentro ciascuno.
117
126
  const mediaBlocks = findMediaModeBlocks(cssText);
118
127
  for (const { mode, start, end } of mediaBlocks) {
119
128
  const body = cssText.slice(start + 1, end);
@@ -127,8 +136,8 @@ const splitModeScopes = (cssText, selector = ':root') => {
127
136
  }
128
137
  }
129
138
 
130
- // 2. The base <selector> { ... } block: the first one not nested inside
131
- // any of the media blocks found above.
139
+ // 2. Il blocco base <selector> { ... }: il primo non annidato dentro
140
+ // nessuno dei blocchi media trovati qui sopra.
132
141
  const ROOT_RE = new RegExp(`${escapeRegExp(selector)}\\s*\\{`, 'g');
133
142
  for (const match of cssText.matchAll(ROOT_RE)) {
134
143
  const openIdx = match.index + match[0].length - 1;
@@ -143,18 +152,20 @@ const splitModeScopes = (cssText, selector = ':root') => {
143
152
  return scopes;
144
153
  };
145
154
 
146
- // `true` = merge every source; an array = merge only the properties generated
147
- // by the token source files matching one of its entries. Set by the
148
- // loadExistingCustomProps*() functions.
155
+ /*
156
+ `true` = unisce ogni sorgente; un array = unisce solo le proprietà generate
157
+ dai file sorgente di token che corrispondono a una delle sue voci. Impostato
158
+ dalle funzioni loadExistingCustomProps*().
159
+ */
149
160
  /** @type {true|(string|RegExp)[]} */
150
161
  let mergeSources = true;
151
162
 
152
163
  /**
153
- * Whether a token source file matches one of the `mergeCustomProps` array
154
- * entries: a string matches if it is contained in the file path (path
155
- * separators normalised to `/`), a RegExp if it tests true against it.
164
+ * Indica se un file sorgente di token corrisponde a una delle voci dell'array
165
+ * `mergeCustomProps`: una stringa corrisponde se è contenuta nel percorso del file
166
+ * (separatori di percorso normalizzati in `/`), una RegExp se il test è positivo.
156
167
  * @param {(string|RegExp)[]} sources
157
- * @param {string|undefined} filePath token source file path
168
+ * @param {string|undefined} filePath percorso del file sorgente del token
158
169
  * @returns {boolean}
159
170
  */
160
171
  const matchesSource = (sources, filePath) => {
@@ -169,21 +180,21 @@ const matchesSource = (sources, filePath) => {
169
180
  });
170
181
  };
171
182
 
172
- // null = merge disabled, or destination file not found yet (first build)
183
+ // null = merge disattivato, oppure file di destinazione non ancora trovato (prima build)
173
184
  /** @type {Record<string,string>|null} */
174
185
  let existingCustomProps = null;
175
186
 
176
- // Per-mode equivalent of existingCustomProps, populated by
177
- // loadExistingCustomPropsScoped() for a sourceModes build.
187
+ // Equivalente per modalità di existingCustomProps, popolato da
188
+ // loadExistingCustomPropsScoped() per una build sourceModes.
178
189
  /** @type {Record<string, Record<string,string>>|null} */
179
190
  let scopedExistingCustomProps = null;
180
191
 
181
192
  /**
182
- * Reads the CSS destination file (if it exists) and stores a name → value
183
- * map of its current custom properties for later merging.
184
- * @param {string} absDestPath absolute path of the CSS file to read
185
- * @param {true|(string|RegExp)[]} [sources] `true` merges every source, an
186
- * array only the token source files matching one of its entries (default: true)
193
+ * Legge il file CSS di destinazione (se esiste) e memorizza una mappa nome → valore
194
+ * delle sue custom properties attuali per il merge successivo.
195
+ * @param {string} absDestPath percorso assoluto del file CSS da leggere
196
+ * @param {true|(string|RegExp)[]} [sources] `true` unisce ogni sorgente, un
197
+ * array solo i file sorgente dei token corrispondenti a una delle sue voci (default: true)
187
198
  * @returns {Record<string,string>|null}
188
199
  */
189
200
  export const loadExistingCustomProps = (absDestPath, sources = true) => {
@@ -195,17 +206,17 @@ export const loadExistingCustomProps = (absDestPath, sources = true) => {
195
206
  };
196
207
 
197
208
  /**
198
- * sourceModes equivalent of loadExistingCustomProps(): reads the CSS
199
- * destination file (if it exists) and stores a per-mode name → value map,
200
- * scoped to each mode's own `<selector> { ... }` block (see splitModeScopes()).
201
- * @param {string} absDestPath absolute path of the CSS file to read
202
- * @param {string} baseMode mode whose declarations live in the top-level,
203
- * non-nested `<selector> { ... }` block (no default — always passed explicitly
204
- * by build-source-modes.mjs, from the resolved sourceModesBase)
205
- * @param {true|(string|RegExp)[]} [sources] `true` merges every source, an
206
- * array only the token source files matching one of its entries (default: true)
207
- * @param {string} [selector] the customPropsSelector the pre-existing file was
208
- * generated with (default: ':root' — see config.mjs)
209
+ * Equivalente sourceModes di loadExistingCustomProps(): legge il file CSS di
210
+ * destinazione (se esiste) e memorizza una mappa nome → valore per modalità,
211
+ * limitata al blocco `<selector> { ... }` di ciascuna modalità (vedi splitModeScopes()).
212
+ * @param {string} absDestPath percorso assoluto del file CSS da leggere
213
+ * @param {string} baseMode modalità le cui dichiarazioni stanno nel blocco
214
+ * `<selector> { ... }` di primo livello, non annidato (nessun default — sempre passata esplicitamente
215
+ * da build-source-modes.mjs, a partire dal sourceModesBase risolto)
216
+ * @param {true|(string|RegExp)[]} [sources] `true` unisce ogni sorgente, un
217
+ * array solo i file sorgente dei token corrispondenti a una delle sue voci (default: true)
218
+ * @param {string} [selector] il customPropsSelector con cui è stato generato il file
219
+ * preesistente (default: ':root' — vedi config.mjs)
209
220
  * @returns {Record<string, Record<string,string>>|null}
210
221
  */
211
222
  export const loadExistingCustomPropsScoped = (absDestPath, baseMode, sources = true, selector = ':root') => {
@@ -227,17 +238,17 @@ export const loadExistingCustomPropsScoped = (absDestPath, baseMode, sources = t
227
238
  };
228
239
 
229
240
  /**
230
- * Merges freshly generated custom properties with the ones previously loaded
231
- * via loadExistingCustomProps() / loadExistingCustomPropsScoped(). Pre-existing
232
- * values take priority; custom properties found only in the pre-existing file
233
- * (no longer generated) are kept as well. When the merge is limited to some
234
- * token source files (array option), a generated property whose source file
235
- * does not match is not overridden by its pre-existing value.
236
- * @param {Record<string,string>} generated name → value map produced by this build
237
- * @param {string|null} [mode] when set (sourceModes build), looks up the
238
- * pre-existing props scoped to this mode instead of the flat/global map (default: null)
239
- * @param {Record<string,string>} [sourceFileMap] property name → token source
240
- * file path, used only when the merge is limited to some sources (default: {})
241
+ * Unisce le custom properties appena generate a quelle caricate in precedenza
242
+ * tramite loadExistingCustomProps() / loadExistingCustomPropsScoped(). I valori
243
+ * preesistenti hanno priorità; vengono mantenute anche le custom properties presenti
244
+ * solo nel file preesistente (non più generate). Quando il merge è limitato ad alcuni
245
+ * file sorgente dei token (opzione array), una proprietà generata il cui file sorgente
246
+ * non corrisponde non viene sovrascritta dal suo valore preesistente.
247
+ * @param {Record<string,string>} generated mappa nome → valore prodotta da questa build
248
+ * @param {string|null} [mode] se impostato (build sourceModes), cerca le props
249
+ * preesistenti limitate a questa modalità invece della mappa piatta/globale (default: null)
250
+ * @param {Record<string,string>} [sourceFileMap] nome della proprietà → percorso del file
251
+ * sorgente del token, usata solo quando il merge è limitato ad alcuni sorgenti (default: {})
241
252
  * @returns {Record<string,string>}
242
253
  */
243
254
  export const mergeCustomProps = (generated, mode = null, sourceFileMap = {}) => {