@massimo-cassandro/minimo 1.33.0 → 1.33.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.
Files changed (84) hide show
  1. package/README.md +2 -1
  2. package/dev-tools/starter-kit/source_files/{CLAUDE-frontend.md → app/CLAUDE.md} +1 -1
  3. package/dev-tools/starter-kit/source_files/app/assets/api_htaccess +20 -0
  4. package/dev-tools/starter-kit/source_files/{layout-critical.css → app/css/layout.critical.css} +1 -1
  5. package/dev-tools/starter-kit/source_files/app/css/layout.css +0 -0
  6. package/dev-tools/starter-kit/source_files/app/index.js +1 -0
  7. package/dev-tools/starter-kit/source_files/root/webpack-config-modules/inline-critical-css.mjs +41 -0
  8. package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-setup.mjs +1 -1
  9. package/dev-tools/starter-kit/{webpack.config.mjs → source_files/root/webpack.config.mjs} +50 -24
  10. package/dev-tools/starter-kit/starter-install.sh +163 -82
  11. package/dev-tools/stylelint-config/test/test.module.scss +9 -0
  12. package/package.json +1 -1
  13. package/snippets/php/iviewer.php +488 -0
  14. package/snippets/twig-symfony/ViewerController.php +549 -0
  15. package/src/custom-properties.css +29 -0
  16. package/src/minimo.css +3 -0
  17. package/src/utilities/dom-builder/dom-builder.js +9 -5
  18. package/src/web-components/json-table/json-table-component.js +387 -38
  19. package/src/web-components/json-table/json-table-component.module.css +190 -0
  20. package/src/web-components/json-table/json-table.minimo.tokens.mjs +195 -0
  21. package/src/web-components/json-table/readme.md +603 -82
  22. package/src/web-components/json-table/src/cell-content.js +136 -0
  23. package/src/web-components/json-table/src/content-utils.js +103 -0
  24. package/src/web-components/json-table/src/data-types.js +280 -0
  25. package/src/web-components/json-table/src/defaults.js +377 -58
  26. package/src/web-components/json-table/src/get-data.js +105 -10
  27. package/src/web-components/json-table/src/icons.js +80 -0
  28. package/src/web-components/json-table/src/info-section.js +85 -50
  29. package/src/web-components/json-table/src/main-builder.js +175 -52
  30. package/src/web-components/json-table/src/pagination.js +253 -0
  31. package/src/web-components/json-table/src/parse-cols.js +113 -0
  32. package/src/web-components/json-table/src/parse-rows.js +81 -0
  33. package/src/web-components/json-table/src/resolve-params.js +102 -32
  34. package/src/web-components/json-table/src/search.js +71 -0
  35. package/src/web-components/json-table/src/sorting.js +111 -0
  36. package/src/web-components/json-table/src/table-body.js +109 -0
  37. package/src/web-components/json-table/src/table-builder.js +152 -0
  38. package/src/web-components/json-table/src/table-tfoot.js +56 -0
  39. package/src/web-components/json-table/src/table-thead.js +183 -0
  40. package/src/web-components/json-table/src/update-info.js +43 -24
  41. package/src/web-components/s-datatable-component/{docs.md → readme.md} +5 -3
  42. package/src/web-components/s-datatable-component/s-datatable-component.js +1 -1
  43. package/types/global.d.ts +17 -3
  44. package/dev-tools/starter-kit/source_files/app_index.js +0 -1
  45. package/snippets/config-templates/_htaccess +0 -69
  46. package/snippets/config-templates/robots.txt +0 -5
  47. package/snippets/config-templates/rollup.config.mjs +0 -115
  48. /package/dev-tools/starter-kit/source_files/{_root_robots.txt → app/assets/robots.txt} +0 -0
  49. /package/dev-tools/starter-kit/source_files/{_root_htaccess → app/assets/root_htaccess} +0 -0
  50. /package/{src → dev-tools/starter-kit/source_files/app/css}/fonts.css +0 -0
  51. /package/dev-tools/starter-kit/source_files/{favicons-readme.md → app/favicons/favicons-readme.md} +0 -0
  52. /package/dev-tools/starter-kit/{webpack-template.ejs → source_files/app/tpl/index.ejs} +0 -0
  53. /package/dev-tools/starter-kit/source_files/{__project__.code-workspace → root/__project__.code-workspace} +0 -0
  54. /package/dev-tools/starter-kit/source_files/{_browserslistrc → root/_browserslistrc} +0 -0
  55. /package/dev-tools/starter-kit/source_files/{_editorconfig → root/_editorconfig} +0 -0
  56. /package/dev-tools/starter-kit/source_files/{_gitignore → root/_gitignore} +0 -0
  57. /package/dev-tools/starter-kit/source_files/{_prettierrc → root/_prettierrc} +0 -0
  58. /package/dev-tools/starter-kit/source_files/{eslint.config.mjs → root/eslint.config.mjs} +0 -0
  59. /package/dev-tools/starter-kit/source_files/{jsconfig.json → root/jsconfig.json} +0 -0
  60. /package/dev-tools/starter-kit/{package-tpl.json → source_files/root/package-tpl.json} +0 -0
  61. /package/dev-tools/starter-kit/source_files/{stylelint.config.mjs → root/stylelint.config.mjs} +0 -0
  62. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/css-rules.mjs +0 -0
  63. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/get-jsConfig-aliases.mjs +0 -0
  64. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/mini-svg-data-uri-loader.cjs +0 -0
  65. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/postcss.config.mjs +0 -0
  66. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-variables-safelist.mjs +0 -0
  67. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svg-rules.mjs +0 -0
  68. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svgo.config.mjs +0 -0
  69. /package/snippets/{config-templates/_github → _github}/dependabot.yml +0 -0
  70. /package/snippets/{error-pages/error-pages.js → error-pages.js} +0 -0
  71. /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.jsx +0 -0
  72. /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.module.scss +0 -0
  73. /package/snippets/{config-templates → root}/_hintrc.cjs +0 -0
  74. /package/snippets/{config-templates → root}/_npmignore +0 -0
  75. /package/snippets/{config-templates → root}/_npmrc +0 -0
  76. /package/snippets/{config-templates → root}/_stylelintignore +0 -0
  77. /package/snippets/{config-templates → root}/babel.config--react.json +0 -0
  78. /package/snippets/{config-templates → root}/babel.config--solidJS.json +0 -0
  79. /package/snippets/{ImgViewerController.php → twig-symfony/ImgViewerController.php} +0 -0
  80. /package/snippets/{UnsplashController.php → twig-symfony/UnsplashController.php} +0 -0
  81. /package/snippets/{config-templates → twig-symfony}/_env.local +0 -0
  82. /package/snippets/{error-pages → twig-symfony}/bundles/TwigBundle/Exception/error.html.twig +0 -0
  83. /package/snippets/{flash-messages.html.twig → twig-symfony/flash-messages.html.twig} +0 -0
  84. /package/snippets/{minimo-form-layout.html.twig → twig-symfony/minimo-form-layout.html.twig} +0 -0
package/README.md CHANGED
@@ -9,9 +9,10 @@ npm i @massimo-cassandro/minimo
9
9
 
10
10
  # optional:
11
11
  npm i -D @massimo-cassandro/eslint-config
12
- npm i -D @massimo-cassandro/stylelint-config
13
12
  ```
14
13
 
14
+ > Note: a stylelint config is bundled with minimo itself (no separate install needed) — see [dev-tools/stylelint-config/README.md](dev-tools/stylelint-config/README.md).
15
+
15
16
  > Note: **minimo** is designed to be used with WebPack using the configuration you can find in the [starter-kit folder](./dev-tools/starter-kit/) of this repository. If changes are made (for example, to how SVG files are imported), things may not work as expected.
16
17
  >
17
18
 
@@ -9,7 +9,7 @@
9
9
  - Conferma la comprensione prima di agire su richieste ambigue
10
10
  - Il progetto usa ES modules (import/export), evitare soluzioni che utilizzano commonJs
11
11
  - In linea di massima non proporre soluzioni che richiedano modifiche alla parte back-end, se presente, a meno che non sia esplicitamente richiesto
12
- - nella chat evitare neologismi come parsare, committare ecc., usare i termini corrispondenti in italiano o il termine originale in inglese dove non sia possibile un equivalente in italiano. Non coniugare mai secondo le regole dell'italiano verbi di altre lingue
12
+ - nella chat evitare neologismi come inlinare, parsare, committare ecc., usare i termini corrispondenti in italiano o il termine originale in inglese dove non sia possibile un equivalente in italiano. Non coniugare mai secondo le regole dell'italiano verbi di altre lingue
13
13
  - nei commenti su più righe preferire `/* ... */` piuttosto che ripetere `//` ad igni inizio riga
14
14
  - a meno che non sia esplicitamente richiesto di eseguire subito una modifica, NON ESEGUIRE MAI nulla autonomamente ma mostra sempre un piano d'azione prima di procedere
15
15
  - nei commenti jsDoc aggiungere sempre dove possibile una sezione example che riepiloghi i vari parametri mostrando i valori di default
@@ -0,0 +1,20 @@
1
+ # Nega l'accesso diretto ai soli file di configurazione (contengono le
2
+ # credenziali OAuth). Gli altri file di questa cartella sono endpoint veri
3
+ # e propri (login.php, callback.php, whoami.php, ecc.) e devono restare
4
+ # raggiungibili normalmente: qui non c'è un "Require all denied" sull'intera
5
+ # cartella come quando cfg/ era isolata.
6
+ # I file restano comunque leggibili da PHP tramite require (accesso da
7
+ # filesystem, non passa da Apache), quindi l'app continua a funzionare.
8
+
9
+ <FilesMatch "^config(-template|-prod)?\.php$">
10
+ # Apache 2.4+ (praticamente tutti gli hosting attuali)
11
+ <IfModule mod_authz_core.c>
12
+ Require all denied
13
+ </IfModule>
14
+
15
+ # Fallback per Apache 2.2 (hosting più vecchi)
16
+ <IfModule !mod_authz_core.c>
17
+ Order deny,allow
18
+ Deny from all
19
+ </IfModule>
20
+ </FilesMatch>
@@ -3,7 +3,7 @@
3
3
  Per ulteriori entry critical specifiche di pagina, copiare e rinominare.
4
4
 
5
5
  Le entry con suffisso `.critical` generano asset destinati a essere
6
- INLINATI nei template html: devono restare AUTOSUFFICIENTI e minimi.
6
+ inseriti inline nei template html: devono restare AUTOSUFFICIENTI e minimi.
7
7
  Il suffisso attiva l'istanza PurgeCSS dedicata con purge stretto, in dev
8
8
  e in prod (vedi purgeCSSPluginCritical in webpack.config.mjs), e la regola
9
9
  dedicata in css-rules.mjs.
@@ -0,0 +1 @@
1
+ import '@css/index.css';
@@ -0,0 +1,41 @@
1
+ /* plugins/inline-critical-css.mjs */
2
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
3
+
4
+ export class InlineCriticalCssPlugin {
5
+ constructor({ match }) {
6
+ this.match = match;
7
+ }
8
+
9
+ apply(compiler) {
10
+ compiler.hooks.compilation.tap('InlineCriticalCssPlugin', (compilation) => {
11
+ HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(
12
+ 'InlineCriticalCssPlugin',
13
+ (data, callback) => {
14
+ const isTarget = (tag) =>
15
+ tag.tagName === 'link' && this.match(tag.attributes.href);
16
+
17
+ const linkTag = [...data.headTags, ...data.bodyTags].find(isTarget);
18
+
19
+ if (linkTag) {
20
+ const publicPath = compilation.outputOptions.publicPath || '';
21
+ const assetName = linkTag.attributes.href.replace(publicPath, '');
22
+ const source = compilation.assets[assetName]?.source();
23
+
24
+ if (source) {
25
+ const styleTag = {
26
+ tagName: 'style',
27
+ voidTag: false,
28
+ innerHTML: source,
29
+ attributes: {},
30
+ };
31
+ data.headTags = data.headTags.filter((t) => !isTarget(t)).concat(styleTag);
32
+ data.bodyTags = data.bodyTags.filter((t) => !isTarget(t));
33
+ }
34
+ }
35
+
36
+ callback(null, data);
37
+ }
38
+ );
39
+ });
40
+ }
41
+ }
@@ -5,7 +5,7 @@ import { purgecssVariablesSafelist } from './purgecss-variables-safelist.mjs';
5
5
 
6
6
  /*
7
7
  Istanzia i plugin PurgeCSS del progetto: un passaggio stretto sui css
8
- `.critical` (inlinati nei template, devono restare autosufficienti) e un
8
+ `.critical` (inline nei template, devono restare autosufficienti) e un
9
9
  passaggio generale su tutti gli altri asset (il purge è idempotente: il
10
10
  secondo passaggio sui critical non rimuove altro).
11
11
 
@@ -22,6 +22,8 @@ import { cssRules } from './webpack-config-modules/css-rules.mjs';
22
22
  import { createPurgeCSSPlugins } from './webpack-config-modules/purgecss-setup.mjs';
23
23
  import { getJsConfigAliases } from './webpack-config-modules/get-jsConfig-aliases.mjs';
24
24
  import { svgRules } from './webpack-config-modules/svg-rules.mjs';
25
+ // import { InlineCriticalCssPlugin } from './webpack-config-modules/inline-critical-css.mjs';
26
+
25
27
 
26
28
  // --- config ---
27
29
  const __filename = fileURLToPath(import.meta.url)
@@ -30,10 +32,10 @@ const __filename = fileURLToPath(import.meta.url)
30
32
  // Risolve un percorso a partire dalla root del progetto, che coincide con la dir
31
33
  // di questo file solo se il frontend NON è in una sottodirectory (es. ./app):
32
34
  // vengono provate entrambe le posizioni, in fallback la prima
33
- const fromProjectRoot = (relPath) => {
34
- const candidates = ['./', '../'].map(p => path.resolve(__dirname, p, relPath));
35
- return candidates.find(p => fs.existsSync(p)) ?? candidates[0];
36
- };
35
+ // const fromProjectRoot = (relPath) => {
36
+ // const candidates = ['./', '../'].map(p => path.resolve(__dirname, p, relPath));
37
+ // return candidates.find(p => fs.existsSync(p)) ?? candidates[0];
38
+ // };
37
39
 
38
40
  const isDevelopment = process.env.NODE_ENV === 'development'
39
41
  ,devServerPort = [[port5700]]
@@ -60,11 +62,11 @@ const isDevelopment = process.env.NODE_ENV === 'development'
60
62
  // NB: jsconfig.json va tenuto in questa stessa dir (gli alias sono risolti
61
63
  // a partire dalla sua posizione)
62
64
  ,jsConfigAliases = getJsConfigAliases(path.resolve(__dirname, './jsconfig.json'))
63
- ,packageJson = JSON.parse(fs.readFileSync(fromProjectRoot('package.json'), 'utf-8'))
65
+ ,packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf-8')) //JSON.parse(fs.readFileSync(fromProjectRoot('package.json'), 'utf-8'))
64
66
 
65
67
  // path del pacchetto minimo (il suo js genera markup con classi proprie e il
66
68
  // suo css dichiara custom properties: entrambi vanno visti da PurgeCSS)
67
- ,minimo_path = fromProjectRoot('node_modules/@massimo-cassandro/minimo')
69
+ ,minimo_path = './node_modules/@massimo-cassandro/minimo' // fromProjectRoot('node_modules/@massimo-cassandro/minimo')
68
70
 
69
71
  ,usePurgeCss = true // false per disattivare PurgeCSS (debug rapido di problemi legati al purge)
70
72
  ,purgeCSSOptions = {
@@ -78,7 +80,7 @@ const isDevelopment = process.env.NODE_ENV === 'development'
78
80
  // test del cacheGroup `shared` (splitChunks): i css restano SEMPRE FUORI dal
79
81
  // chunk condiviso e nel chunk della entry che li importa, così ogni asset css
80
82
  // resta autosufficiente (`variables: true` funziona per singolo asset, e i
81
- // critical css inlinati nei template devono restare autosufficienti). I
83
+ // critical css inline nei template devono restare autosufficienti). I
82
84
  // template (twig/altro) linkano solo il css della propria entry (e gli
83
85
  // eventuali `.critical.css`), MAI uno shared.css: se i css finissero nel
84
86
  // chunk condiviso, quella parte di stili sparirebbe silenziosamente dalla
@@ -120,24 +122,41 @@ const shared_chunk_paths = (module) => {
120
122
  const CopyWebpackPluginPatterns = [
121
123
 
122
124
  // {
123
- // from: '*.webp',
124
- // to: 'imgs/[name].[contenthash].[ext]',
125
- // context: './source/path/', // viene rimosso nella copia
125
+ // from: 'app/api',
126
+ // to: 'api',
126
127
  // globOptions: {
127
128
  // dot: true,
128
129
  // gitignore: true,
129
- // ignore: [ '**/.DS_Store' ]
130
+ // ignore: [
131
+ // '**/.DS_Store',
132
+ // // config.php e config-prod.php sono
133
+ // // gestiti a parte nei pattern successivi (config.php è sempre
134
+ // // scritto a mano per ambiente, mai copiato dalla build)
135
+ // // '**/config.php',
136
+ // // '**/config-prod.php',
137
+ // ]
130
138
  // }
131
139
  // },
132
140
  // {
133
- // from: 'app/php',
134
- // to: 'php',
135
- // globOptions: {
136
- // dot: true,
137
- // gitignore: true,
138
- // ignore: [ '**/.DS_Store', ...(isDevelopment ? [] : [ '**/init-dev.php' ]) ]
139
- // }
140
- // }
141
+ // from: 'app/api/config-prod.php',
142
+ // to: 'api/config.php'
143
+ // },
144
+ // {
145
+ // from: './app/assets/root_htaccess',
146
+ // to: '.htaccess',
147
+ // toType: 'file'
148
+ // },
149
+ // {
150
+ // from: './app/assets/robots.txt',
151
+ // to: 'robots.txt',
152
+ // toType: 'file'
153
+ // },
154
+ // {
155
+ // from: './app/assets/api_htaccess',
156
+ // to: 'api/.htaccess',
157
+ // toType: 'file',
158
+ // // context: 'app/api'
159
+ // },
141
160
  ];
142
161
 
143
162
  // =>> PurgeCSS
@@ -155,12 +174,13 @@ const CopyWebpackPluginPatterns = [
155
174
  // =>> entries
156
175
  // NB: percorsi dalla root del progetto
157
176
  const entries = {
158
- 'xxxxxx': './index.js'
177
+ 'index': './app/index.js',
159
178
 
160
- // css critici inlinati nei template html: il suffisso `.critical` nel nome
179
+ // css critici da includere inline nei template html: il suffisso `.critical` nel nome
161
180
  // della entry attiva l'istanza PurgeCSS dedicata con purge stretto
162
181
  // (vedi purgecss-setup.mjs) e la regola dedicata in css-rules.mjs
163
- // ,'xxxxxx.critical': './index-critical.css'
182
+ 'layout.critical': './app/css/layout.critical.css'
183
+
164
184
  };
165
185
 
166
186
 
@@ -195,7 +215,7 @@ const config = {
195
215
  path: output_dir,
196
216
  filename: '[name].[contenthash].js',
197
217
  publicPath: '/',
198
- // publicPath: isDevelopment? '/' : './', // per devServer, nel caso in cui l'output di produzione non sia sulla root
218
+ // publicPath: isDevelopment? '/' : './', // nel caso in cui l'output di produzione non sia sulla root
199
219
  clean: !isDevelopment
200
220
  },
201
221
 
@@ -350,6 +370,12 @@ const config = {
350
370
  ignoreOrder: true
351
371
  }),
352
372
 
373
+ // =>> plugins: InlineCriticalCssPlugin (solo prod)
374
+ // ...(isDevelopment
375
+ // ? []
376
+ // : [new InlineCriticalCssPlugin({ match: (href) => href?.includes('.critical') })]
377
+ // ),
378
+
353
379
  // =>> plugins: HtmlWebpackPlugin (manifest)
354
380
  new HtmlWebpackPlugin({
355
381
  filename: 'manifest.webmanifest',
@@ -425,7 +451,7 @@ const config = {
425
451
 
426
452
  },
427
453
  raw: true,
428
- // niente banner nei critical css: vengono inlinati nei template html
454
+ // niente banner nei critical css: vengono inseriti inline nei template html
429
455
  exclude: /\.critical/ // chunk name
430
456
  }),
431
457
 
@@ -2,15 +2,22 @@
2
2
 
3
3
  # IMPORTANTE: questo script è idempotente e deve restare tale.
4
4
  # Può essere rilanciato più volte sullo stesso progetto (anche via `npx starter-kit`
5
- # per aggiornare un setup esistente) senza sovrascrivere nulla né creare duplicati:
6
- # per i singoli file, se il contenuto esistente è identico al sorgente la copia
7
- # viene saltata; se è diverso e non esiste ancora un OLD- corrispondente, il
8
- # file esistente viene rinominato con prefisso OLD- (preservato da quel momento
9
- # in poi, non viene più toccato nelle esecuzioni successive) e il nuovo file
10
- # prende il nome originale; se l'OLD- corrispondente esiste già, viene invece
11
- # sovrascritto direttamente il file "nuovo", senza aggiungere ulteriori prefissi.
12
- # Stessa logica, a livello di intera cartella e senza diff sui singoli file
13
- # contenuti, per le cartelle installate (./app, ./webpack-config-modules).
5
+ # per aggiornare un setup esistente) senza sovrascrivere nulla né creare duplicati.
6
+ # Per i singoli file installati sulla root del progetto e dentro
7
+ # ./webpack-config-modules: se il contenuto esistente è identico al sorgente la
8
+ # copia viene saltata; se è diverso e non esiste ancora un OLD- corrispondente,
9
+ # il file esistente viene rinominato con prefisso OLD- (preservato da quel
10
+ # momento in poi, non viene più toccato nelle esecuzioni successive) e il nuovo
11
+ # file prende il nome originale; se l'OLD- corrispondente esiste già, viene
12
+ # invece sovrascritto direttamente il file "nuovo", senza aggiungere ulteriori
13
+ # prefissi. Stessa logica, a livello di intera cartella (senza diff sui
14
+ # singoli file contenuti al suo interno prima della prima installazione), per
15
+ # ./webpack-config-modules.
16
+ # ./app segue invece una logica più semplice: viene rinominata per intero in
17
+ # OLD-app solo la prima volta che esiste già (preservata da quel momento in
18
+ # poi, mai più toccata); i file al suo interno vengono sempre sovrascritti
19
+ # senza controllo né backup individuale (force_cat), dato che l'intera
20
+ # cartella precedente resta comunque disponibile in OLD-app.
14
21
  # Ogni modifica futura deve conservare questa proprietà.
15
22
 
16
23
  RED='\033[0;31m'
@@ -93,8 +100,6 @@ echo "BASE_URL: ${BASE_URL}"
93
100
  SOURCE_FILES_DIR="${BASE_URL}/source_files"
94
101
 
95
102
  # webpack
96
- WEBPACK_CONFIG_SOURCE_PATH="$BASE_URL"
97
- WEBPACK_MODULES_SOURCE_PATH="${BASE_URL}/webpack-config-modules"
98
103
  WEBPACK_MODULES_INSTALL_PATH="./webpack-config-modules"
99
104
 
100
105
  # protezione contro la sovrascrittura
@@ -147,11 +152,91 @@ safe_cat_with_ports() {
147
152
  return $rc
148
153
  }
149
154
 
155
+ # A differenza di safe_cat, sovrascrive sempre senza confrontare né
156
+ # backuppare (nessun OLD- a livello di singolo file). Usata per i file
157
+ # installati dentro FRONTEND_INSTALL_PATH (./app), la cui idempotenza è già
158
+ # garantita a livello di intera cartella (OLD-app, vedi più sotto): non ha
159
+ # senso ripetere il controllo su ogni singolo file al suo interno.
160
+ force_cat() {
161
+ local src="$1"
162
+ local dest="$2"
163
+ if [ ! -f "$src" ]; then
164
+ echo -e "${RED}Sorgente mancante: $src${NC}"
165
+ return 1
166
+ fi
167
+ cat "$src" >| "$dest"
168
+ }
169
+
170
+ # Copia ricorsivamente tutti i file di una struttura sorgente (source_files/root
171
+ # o source_files/app) in una destinazione, preservando la struttura delle
172
+ # sotto-cartelle così com'è in source_files: aggiungere, spostare o rinominare
173
+ # file lì non richiede modifiche a questo script.
174
+ # Il terzo argomento (opzionale) è il nome di una funzione di rename invocata
175
+ # su ogni singolo basename, per i casi in cui il nome del file sorgente non
176
+ # coincide con quello di destinazione (vedi rename_root_file).
177
+ # Il quarto argomento (opzionale, default: safe_cat_with_ports) è la funzione
178
+ # di copia da usare per ogni file: safe_cat_with_ports confronta e backuppa
179
+ # il singolo file (sostituzione porte no-op se non contiene placeholder);
180
+ # force_cat sovrascrive sempre senza controlli (vedi sopra, usata per ./app).
181
+ # Il quinto argomento (opzionale) è una lista di basename (separati da spazio,
182
+ # riferiti al nome del file sorgente, prima di un eventuale rename_fn) da
183
+ # saltare: usato per escludere package-tpl.json, già copiato a parte prima
184
+ # dell'installazione dei pacchetti npm (vedi più sotto).
185
+ install_tree() {
186
+ local src_root="$1"
187
+ local dest_root="$2"
188
+ local rename_fn="$3"
189
+ local copy_fn="${4:-safe_cat_with_ports}"
190
+ local exclude="$5"
191
+ local file rel dir base new_base dest
192
+ while IFS= read -r file; do
193
+ rel="${file#"$src_root"/}"
194
+ dir="$(dirname "$rel")"
195
+ base="$(basename "$rel")"
196
+ if [ -n "$exclude" ] && [[ " $exclude " == *" $base "* ]]; then
197
+ continue
198
+ fi
199
+ if [ -n "$rename_fn" ]; then
200
+ new_base="$("$rename_fn" "$base")"
201
+ else
202
+ new_base="$base"
203
+ fi
204
+ if [ "$dir" = "." ]; then
205
+ dest="${dest_root}/${new_base}"
206
+ else
207
+ mkdir -p "${dest_root}/${dir}"
208
+ dest="${dest_root}/${dir}/${new_base}"
209
+ fi
210
+ "$copy_fn" "$file" "$dest"
211
+ done < <(find "$src_root" -type f)
212
+ }
213
+
214
+ # Rename applicato ai file di source_files/root/ in fase di copia:
215
+ # - prefisso singolo underscore -> dotfile (es. _gitignore -> .gitignore);
216
+ # il doppio underscore (__project__.code-workspace) non viene toccato,
217
+ # il nome resta invariato
218
+ # - suffisso -tpl prima dell'estensione -> rimosso (es. package-tpl.json ->
219
+ # package.json), usato per i file template che altrimenti confliggerebbero
220
+ # con l'omonimo file dello starter-kit stesso
221
+ rename_root_file() {
222
+ local name="$1"
223
+ if [[ "$name" == _* && "$name" != __* ]]; then
224
+ echo ".${name#_}"
225
+ return
226
+ fi
227
+ if [[ "$name" == *-tpl.* ]]; then
228
+ echo "${name/-tpl./.}"
229
+ return
230
+ fi
231
+ echo "$name"
232
+ }
233
+
150
234
  FRONTEND_INSTALL_PATH="./app"
151
235
  # se la cartella esiste già: la prima volta viene rinominata per intero in
152
236
  # OLD-app (preservata, mai più toccata); se OLD-app esiste già, la cartella
153
- # esistente non viene rinominata e i file al suo interno vengono gestiti
154
- # singolarmente dalla stessa logica di safe_cat.
237
+ # esistente non viene rinominata. In entrambi i casi i file al suo interno
238
+ # vengono poi sempre sovrascritti senza controlli individuali (force_cat):
239
+ # l'idempotenza è garantita a livello di intera cartella, non di singolo file.
155
240
  if [ -d "$FRONTEND_INSTALL_PATH" ]; then
156
241
  OLD_FRONTEND_INSTALL_PATH="$(dirname "$FRONTEND_INSTALL_PATH")/OLD-$(basename "$FRONTEND_INSTALL_PATH")"
157
242
  if [ ! -e "$OLD_FRONTEND_INSTALL_PATH" ]; then
@@ -160,51 +245,20 @@ if [ -d "$FRONTEND_INSTALL_PATH" ]; then
160
245
  fi
161
246
 
162
247
  echo -e "${GREEN}Files will be installed in: '${FRONTEND_INSTALL_PATH}'${NC}"
163
- mkdir -p "${FRONTEND_INSTALL_PATH}"
164
-
165
-
166
-
167
- echo -e "${GREEN}...ROOT FILES${NC}"
168
- safe_cat_with_ports "${BASE_URL}/package-tpl.json" package.json
169
- safe_cat_with_ports "${WEBPACK_CONFIG_SOURCE_PATH}/webpack.config.mjs" webpack.config.mjs
170
-
171
- safe_cat "${SOURCE_FILES_DIR}/_gitignore" .gitignore
172
- safe_cat "${SOURCE_FILES_DIR}/_browserslistrc" .browserslistrc
173
- safe_cat "${SOURCE_FILES_DIR}/_editorconfig" .editorconfig
174
- safe_cat "${SOURCE_FILES_DIR}/_prettierrc" .prettierrc
175
- safe_cat "${SOURCE_FILES_DIR}/jsconfig.json" jsconfig.json
176
- safe_cat "${SOURCE_FILES_DIR}/__project__.code-workspace" __project__.code-workspace
177
- safe_cat "${SOURCE_FILES_DIR}/eslint.config.mjs" eslint.config.mjs
178
- safe_cat "${SOURCE_FILES_DIR}/stylelint.config.mjs" stylelint.config.mjs
179
-
180
- echo -e "${GREEN}...APP FILES${NC}"
181
- safe_cat "${SOURCE_FILES_DIR}/_root_htaccess" "${FRONTEND_INSTALL_PATH}/_root_htaccess"
182
- safe_cat "${SOURCE_FILES_DIR}/_root_robots.txt" "${FRONTEND_INSTALL_PATH}/_root_robots.txt"
183
- safe_cat "${SOURCE_FILES_DIR}/CLAUDE-frontend.md" "${FRONTEND_INSTALL_PATH}/CLAUDE.md"
184
- safe_cat "${WEBPACK_CONFIG_SOURCE_PATH}/webpack-template.ejs" "${FRONTEND_INSTALL_PATH}/tpl/index.ejs"
185
-
186
-
187
- echo -e "${GREEN}..WEBPACK CONFIG MODULES${NC}"
188
- # se la cartella esiste già: la prima volta viene rinominata per intero in
189
- # OLD-webpack-config-modules (preservata, mai più toccata); se l'OLD-
190
- # corrispondente esiste già, la cartella esistente non viene rinominata e i
191
- # file al suo interno vengono gestiti singolarmente dalla stessa logica di
192
- # safe_cat.
193
- if [ -d "$WEBPACK_MODULES_INSTALL_PATH" ]; then
194
- OLD_WEBPACK_MODULES_INSTALL_PATH="$(dirname "$WEBPACK_MODULES_INSTALL_PATH")/OLD-$(basename "$WEBPACK_MODULES_INSTALL_PATH")"
195
- if [ ! -e "$OLD_WEBPACK_MODULES_INSTALL_PATH" ]; then
196
- mv "$WEBPACK_MODULES_INSTALL_PATH" "$OLD_WEBPACK_MODULES_INSTALL_PATH"
197
- fi
198
- fi
199
-
200
- mkdir -p "$WEBPACK_MODULES_INSTALL_PATH"
201
248
 
202
- # copia tutti i file presenti in webpack-modules,
203
- for FILE in "${WEBPACK_MODULES_SOURCE_PATH}"/*; do
204
- [ -f "$FILE" ] || continue
205
- safe_cat "$FILE" "${WEBPACK_MODULES_INSTALL_PATH}/$(basename "$FILE")"
206
- done
207
249
 
250
+ # package.json va creato dal template PRIMA di installare qualunque pacchetto:
251
+ # se non esistesse ancora, i comandi `npm i` più sotto ne genererebbero uno
252
+ # "al volo" privo di scripts/metadati del template, e le dipendenze verrebbero
253
+ # registrate lì; alla successiva install_tree su source_files/root (più sotto)
254
+ # quel package.json risulterebbe diverso dal template e verrebbe spostato in
255
+ # OLD-package.json, perdendo le dipendenze appena installate. Per questo qui
256
+ # si usa safe_cat_with_ports (idempotente, con backup OLD- se il file esiste
257
+ # già con contenuto diverso) e poi si esclude package-tpl.json dalla
258
+ # install_tree sulla root, per non ripetere la copia dopo che npm l'ha
259
+ # già modificato.
260
+ echo -e "\n${GREEN}...package.json${NC}"
261
+ safe_cat_with_ports "${SOURCE_FILES_DIR}/root/package-tpl.json" "package.json"
208
262
 
209
263
  echo -e "\n${GREEN}...NODE MODULES${NC}"
210
264
 
@@ -271,6 +325,9 @@ done
271
325
 
272
326
  echo -e "\n${GREEN}...creating default folders${NC}"
273
327
  mkdir -p \
328
+ "_private" \
329
+ "${FRONTEND_INSTALL_PATH}" \
330
+ "${FRONTEND_INSTALL_PATH}/assets" \
274
331
  "${FRONTEND_INSTALL_PATH}/src" \
275
332
  "${FRONTEND_INSTALL_PATH}/css" \
276
333
  "${FRONTEND_INSTALL_PATH}/tpl" \
@@ -280,44 +337,68 @@ mkdir -p \
280
337
  "${FRONTEND_INSTALL_PATH}/error-pages"
281
338
 
282
339
 
283
- echo -e "${GREEN}...MINIMO FILES${NC}"
284
- # Sorgenti di minimo da copiare nel progetto: si usa il pacchetto appena
285
- # installato in node_modules (stessa versione che userà il progetto)
286
- MINIMO_PKG_DIR=./node_modules/@massimo-cassandro/minimo
287
-
288
- safe_cat "${MINIMO_PKG_DIR}/src/custom-properties.css" "${FRONTEND_INSTALL_PATH}/css/custom-properties.css"
289
- safe_cat "${MINIMO_PKG_DIR}/src/custom-media.css" "${FRONTEND_INSTALL_PATH}/css/custom-media.css"
290
- safe_cat "${MINIMO_PKG_DIR}/src/fonts.css" "${FRONTEND_INSTALL_PATH}/css/fonts.css"
291
-
292
- # config di build-tokens: collocato accanto al css generato (custom-properties.css).
293
- safe_cat "${MINIMO_PKG_DIR}/design-tokens/tokens-config-sample.mjs" "${FRONTEND_INSTALL_PATH}/css/tokens-config.mjs"
294
-
295
- # entry css principale del progetto: copia diretta di minimo.css, rinominato
296
- # index.css e collocato sulla root di installazione (non in /src)
297
- safe_cat "${MINIMO_PKG_DIR}/src/minimo.css" "${FRONTEND_INSTALL_PATH}/index.css"
298
340
 
299
- # favicons: config di default per `npx create-favicons`
300
- safe_cat "${MINIMO_PKG_DIR}/dev-tools/create-favicons/src/default-params.mjs" "${FRONTEND_INSTALL_PATH}/favicons/create-favicons-cfg.mjs"
301
- # favicons: istruzioni d'uso di `npx create-favicons`
302
- safe_cat "${SOURCE_FILES_DIR}/favicons-readme.md" "${FRONTEND_INSTALL_PATH}/favicons/readme.md"
303
341
 
342
+ echo -e "${GREEN}...FILES${NC}"
304
343
 
305
- # entry css critical (inline nei template html) e entry js, sulla root di
306
- # installazione accanto a index.css
307
- safe_cat "${SOURCE_FILES_DIR}/app_index.js" "${FRONTEND_INSTALL_PATH}/index.js"
344
+ echo -e "${DIM}...webpack config modules${NC}"
345
+ # se la cartella esiste già: la prima volta viene rinominata per intero in
346
+ # OLD-webpack-config-modules (preservata, mai più toccata); se l'OLD-
347
+ # corrispondente esiste già, la cartella esistente non viene rinominata e i
348
+ # file al suo interno vengono gestiti singolarmente dalla stessa logica di
349
+ # safe_cat (via install_tree, più sotto).
350
+ if [ -d "$WEBPACK_MODULES_INSTALL_PATH" ]; then
351
+ OLD_WEBPACK_MODULES_INSTALL_PATH="$(dirname "$WEBPACK_MODULES_INSTALL_PATH")/OLD-$(basename "$WEBPACK_MODULES_INSTALL_PATH")"
352
+ if [ ! -e "$OLD_WEBPACK_MODULES_INSTALL_PATH" ]; then
353
+ mv "$WEBPACK_MODULES_INSTALL_PATH" "$OLD_WEBPACK_MODULES_INSTALL_PATH"
354
+ fi
355
+ fi
308
356
 
309
- # layout critical css
310
- safe_cat "${SOURCE_FILES_DIR}/layout-critical.css" "${FRONTEND_INSTALL_PATH}/css/layout-critical.css"
357
+ mkdir -p "$WEBPACK_MODULES_INSTALL_PATH"
311
358
 
359
+ # copia tutti i file di source_files/root/ nella root del progetto (inclusa
360
+ # webpack-config-modules/, gestita sopra a livello di cartella) e tutti i
361
+ # file di source_files/app/ dentro FRONTEND_INSTALL_PATH: struttura e nomi
362
+ # di destinazione sono già quelli definiti in source_files (per root/ con
363
+ # l'unica eccezione del rename dei dotfile e dei template "-tpl", vedi
364
+ # rename_root_file), quindi aggiungere/spostare/rinominare file lì non
365
+ # richiede modifiche a questo script. Per app/ si usa force_cat (nessun
366
+ # controllo/backup per singolo file, vedi commento su FRONTEND_INSTALL_PATH).
367
+ # package-tpl.json è escluso: già copiato a parte prima dell'installazione
368
+ # dei pacchetti npm (vedi sezione NODE MODULES più sopra).
369
+ echo -e "${DIM}...root${NC}"
370
+ install_tree "${SOURCE_FILES_DIR}/root" "." rename_root_file "" "package-tpl.json"
371
+ echo -e "${DIM}...app${NC}"
372
+ install_tree "${SOURCE_FILES_DIR}/app" "${FRONTEND_INSTALL_PATH}" "" force_cat
312
373
 
313
374
  # copia tutti i file presenti in ${SOURCE_FILES_DIR}/_private,
314
- echo -e "${GREEN}..._PRIVATE FILES${NC}"
315
- mkdir -p "_private"
375
+ echo -e "${DIM}..._private${NC}"
316
376
  for FILE in "${SOURCE_FILES_DIR}/_private"/*; do
317
377
  [ -f "$FILE" ] || continue
318
378
  safe_cat_with_ports "$FILE" "_private/$(basename "$FILE")"
319
379
  done
320
380
 
381
+ #----------------------------------------------
382
+ # copia altri file dai sorgenti minimo
383
+ #----------------------------------------------
384
+ # Sorgenti di minimo da copiare nel progetto: si usa il pacchetto appena
385
+ # installato in node_modules (stessa versione che userà il progetto)
386
+ MINIMO_PKG_DIR=./node_modules/@massimo-cassandro/minimo
387
+
388
+ force_cat "${MINIMO_PKG_DIR}/src/custom-properties.css" "${FRONTEND_INSTALL_PATH}/css/custom-properties.css"
389
+ force_cat "${MINIMO_PKG_DIR}/src/custom-media.css" "${FRONTEND_INSTALL_PATH}/css/custom-media.css"
390
+
391
+ # entry css principale del progetto: copia diretta di minimo.css, rinominato
392
+ force_cat "${MINIMO_PKG_DIR}/src/minimo.css" "${FRONTEND_INSTALL_PATH}/css/index.css"
393
+
394
+ # config di build-tokens: collocato accanto al css generato (custom-properties.css).
395
+ force_cat "${MINIMO_PKG_DIR}/design-tokens/tokens-config-sample.mjs" "${FRONTEND_INSTALL_PATH}/css/tokens-config.mjs"
396
+
397
+
398
+
399
+ # favicons: config di default per `npx create-favicons`
400
+ force_cat "${MINIMO_PKG_DIR}/dev-tools/create-favicons/src/default-params.mjs" "${FRONTEND_INSTALL_PATH}/favicons/create-favicons-cfg.mjs"
401
+
321
402
 
322
403
  if [ ${#selectedOptionalPkgs[@]} -gt 0 ]; then
323
404
  echo -e "\n${YELLOW}Pacchetti opzionali installati:${NC}"
@@ -0,0 +1,9 @@
1
+ .moduleCss { // comment
2
+ color: #000;
3
+ // comment
4
+
5
+ }
6
+
7
+ :global(.non-module-class) {
8
+ font-weight: 500;
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "1.33.0",
3
+ "version": "1.33.2",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "main": "./index.js",