@massimo-cassandro/minimo 1.39.2 → 1.40.1

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 (29) hide show
  1. package/dev-tools/create-favicons/src/default-params.mjs +5 -5
  2. package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +1 -1
  3. package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +451 -0
  4. package/dev-tools/find-orphan-css-classes/orphan-css-classes.config.mjs +44 -0
  5. package/dev-tools/starter-kit/source_files/app/css/fonts.css +2 -2
  6. package/dev-tools/starter-kit/source_files/root/__project__.code-workspace +4 -0
  7. package/dev-tools/starter-kit/source_files/root/_editorconfig +10 -1
  8. package/dev-tools/starter-kit/source_files/root/_gitignore +1 -0
  9. package/dev-tools/starter-kit/source_files/root/_sf/controller/UnsplashController.php +2 -1
  10. package/dev-tools/starter-kit/source_files/root/_sf/symfony-webpack-setup.md +1 -1
  11. package/dev-tools/starter-kit/source_files/root/_sf/templates/_main-tpl.html.twig +9 -2
  12. package/dev-tools/starter-kit/source_files/root/_sf/templates/bundles/TwigBundle/Exception/error.html.twig +5 -1
  13. package/dev-tools/starter-kit/source_files/root/_sf/templates/home.html.twig +17 -0
  14. package/dev-tools/starter-kit/source_files/root/package-tpl.json +5 -4
  15. package/dev-tools/starter-kit/source_files/root/webpack-config-modules/custom-props-purgecss-plugin.mjs +30 -6
  16. package/dev-tools/starter-kit/source_files/root/webpack.config.mjs +140 -58
  17. package/dev-tools/starter-kit/starter-install.sh +24 -13
  18. package/dev-tools/starter-kit/webpack-config-upg.md +99 -5
  19. package/package.json +2 -1
  20. package/src/components/unsplash-page/unsplash-page.module.css +6 -5
  21. package/src/minimo.css +3 -6
  22. package/types/classes.d.ts +0 -525
  23. package/dev-tools/starter-kit/source_files/app/api/.gitkeep +0 -0
  24. package/dev-tools/starter-kit/source_files/app/src/components/.gitkeep +0 -0
  25. package/dev-tools/starter-kit/source_files/app/src/js/.gitkeep +0 -0
  26. package/dev-tools/starter-kit/source_files/app/src/pagine/.gitkeep +0 -0
  27. package/dev-tools/starter-kit/source_files/app/src/web-components/.gitkeep +0 -0
  28. package/src/css/margin-padding-bootstrap-media.css +0 -1845
  29. package/src/css/margin-padding-bootstrap.css +0 -465
@@ -19,23 +19,24 @@
19
19
  "scripts": {
20
20
  "webpack DEV (js)": "NODE_ENV=development webpack serve --config ./webpack.config.mjs #--open-app-name 'Google Chrome'",
21
21
  "php server": "php -S localhost:[[port8000]] # -t root_dir/",
22
- "webpack DEV (sf)": "rm -rf ./public/_dev && NODE_ENV=development webpack serve --config ./webpack.config.mjs # http://192.168.1.135:[[port5700]",
22
+ "webpack DEV (sf)": "rm -rf ./public/_dev && NODE_ENV=development webpack serve --config ./webpack.config.mjs # http://192.168.1.135:[[port5700]]",
23
23
  "symfony server": "symfony serve --port=[[port8000]] --listen-ip=0.0.0.0 # http://192.168.1.135:[[port8000]] # -d (deamon): rimane aperto anche dopo la chiusura del terminale, terminare con `symfony server:stop`",
24
+ "launchChrome": "open -n -a 'Google Chrome' --args --profile-directory='Profile 3' # mbn: 1 / mg2: 3",
24
25
  "webpack PROD": "npm run 'UPD-version' && NODE_ENV=production webpack --config ./webpack.config.mjs --stats minimal",
26
+ "UPD-version": "npx update-version --no-log-v0 --log-file=./changelog.md # --log-patch --pkg=alt/path/to/package.json",
25
27
  "email sass": "npx sass ./app/email:./templates/email/css --no-source-map --style=compressed --watch",
26
28
  "postcss email": "postcss ./app/email/[!_]*.css --dir ./templates/email/css --no-map --verbose --config ./app/email --watch",
27
29
  "eslint-check": "npx eslint app/",
28
30
  "stylelint-check": "npx stylelint 'app/**/*.css'",
29
31
  "create-favicons INIT": "npx create-favicons init",
30
32
  "create-favicons": "npx create-favicons --dir=./app/favicons",
31
- "UPD-version": "npx update-version --no-log-v0 --log-file=./changelog.md # --log-patch --pkg=alt/path/to/package.json",
32
- "upd@m": "npx upd@m",
33
- "launchChrome": "open -n -a 'Google Chrome' --args --profile-directory='Profile 3' # mbn: 1 / mg2: 3",
34
33
  "python server": "python3 -m http.server [[port8000]] # --directory __dirname__ # 8000 = default port",
35
34
  "node server": "node serve # richiede ‘npm i serve’",
36
35
  "build tokens": "npx buildTokens --config ./app/css/tokens-config.mjs",
37
36
  "check unresolved props": "npx checkUnresolvedProps --config ./app/css/tokens-config.mjs",
37
+ "find orphan css classes": "npx findOrphanCssClasses --config ./app/css/orphan-css-classes.config.mjs",
38
38
  "npm-outdated": "npm outdated",
39
+ "upd@m": "npx upd@m",
39
40
  "npm-upd": "npm update --save"
40
41
  },
41
42
  "allowScripts": {
@@ -1,5 +1,5 @@
1
1
  // webpack-config-modules/custom-props-purgecss-plugin.mjs
2
- // v.3
2
+ // v.3.1
3
3
  import fs from 'fs';
4
4
  import postcss from 'postcss';
5
5
  import { globSync } from 'glob';
@@ -11,7 +11,10 @@ import { globSync } from 'glob';
11
11
  custom properties disponibili. I css compilati da webpack contengono invece
12
12
  solo *usi* (`var(--nome)`), mai definizioni. Dopo la minificazione degli
13
13
  asset, il plugin:
14
- 1. scansiona i css di ogni "set" per trovare le custom properties usate;
14
+ 1. scansiona i css di ogni "set" per trovare le custom properties usate, e
15
+ anche i js dei chunk che contengono quei css (i css importati con `?raw`,
16
+ es. shadow DOM dei web components, sono stringhe nel bundle js: vengono
17
+ così rilevati solo per i componenti realmente importati);
15
18
  2. risolve le dipendenze transitive (`--a: calc(var(--b) * 2)` => anche
16
19
  `--b`, fino al fixed point, fallback `var(--x, var(--y))` inclusi);
17
20
  3. estrae dal master le sole definizioni necessarie, PRESERVANDO l'ordine
@@ -137,8 +140,9 @@ export class CustomPropsPurgeCssPlugin {
137
140
  * @param {string} [options.selector=':root'] - Selettore con cui sostituire i blocchi
138
141
  * `:root` del master (es. `':where(html)'`); gli altri selettori (temi, ecc.) restano invariati (default: ':root')
139
142
  * @param {string[]} [options.extraUsageGlobs=[]] - Glob di file css i cui usi di var()
140
- * contano come usati in TUTTI i set: css caricati fuori dagli asset (shadow DOM dei
141
- * web components, import `?raw`) (default: [])
143
+ * contano come usati in TUTTI i set: serve solo per css caricati fuori dal bundle
144
+ * (i css `?raw` sono già rilevati nei js dei chunk del set). Un glob troppo largo
145
+ * porta nel css anche le props di componenti non importati (default: [])
142
146
  * @param {(string|RegExp)[]} [options.seeds=[]] - Props da includere comunque in tutti i
143
147
  * set (nomi esatti o pattern risolti sui nomi dichiarati nel master), es. override
144
148
  * consumati da un altro asset (default: [])
@@ -248,9 +252,29 @@ export class CustomPropsPurgeCssPlugin {
248
252
  continue;
249
253
  }
250
254
 
251
- // props usate nei css del set
255
+ /*
256
+ asset da scansire: i css del set + i js dei chunk che li contengono
257
+ (e dei chunk da essi raggiunti). I css importati con `?raw` (shadow DOM
258
+ dei web components) sono stringhe nel bundle js: vengono quindi
259
+ rilevati solo per i componenti realmente importati
260
+ */
261
+ const scanned = new Set(sourceNames);
262
+ for (const chunk of compilation.chunks) {
263
+ if (![...chunk.files].some(file => sourceNames.includes(file))) {
264
+ continue;
265
+ }
266
+ for (const referenced of chunk.getAllReferencedChunks()) {
267
+ for (const file of referenced.files) {
268
+ if (/\.m?js$/i.test(file)) {
269
+ scanned.add(file);
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ // props usate negli asset scansionati
252
276
  const used = new Set(commonUsages);
253
- for (const name of sourceNames) {
277
+ for (const name of scanned) {
254
278
  varRefs(compilation.getAsset(name).source.source().toString()).forEach(ref => used.add(ref));
255
279
  }
256
280
 
@@ -1,5 +1,5 @@
1
1
  // webpack.config.mjs __project_name__
2
- // v.3
2
+ // v.3.1
3
3
  import path from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import webpack from 'webpack';
@@ -8,17 +8,21 @@ import * as process from 'process'; // Rende 'process' disponibile nel contesto
8
8
  // import { styleText } from 'node:util';
9
9
  // import { createRequire } from 'node:module';
10
10
 
11
+ // SETUP symfony -> commentare HtmlWebpackPlugin e HtmlWebpackInjectPreload
11
12
  import HtmlWebpackPlugin from 'html-webpack-plugin';
12
13
  import HtmlWebpackInjectPreload from '@principalstudio/html-webpack-inject-preload';
14
+
13
15
  import TerserPlugin from 'terser-webpack-plugin';
14
16
  import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
15
17
  import MiniCssExtractPlugin from 'mini-css-extract-plugin';
16
18
  import CopyWebpackPlugin from 'copy-webpack-plugin';
17
19
  // import Dotenv from 'dotenv-webpack';
18
20
  import RemoveEmptyScriptsPlugin from 'webpack-remove-empty-scripts';
19
- // import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
20
21
  // import HtmlWebpackInjectAttributesPlugin from 'html-webpack-inject-attributes-plugin';
21
22
 
23
+ // NB: symfony -> decommentare WebpackManifestPlugin
24
+ // import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
25
+
22
26
  import { cssRules } from './webpack-config-modules/css-rules.mjs';
23
27
  import { createPurgeCSSPlugins } from './webpack-config-modules/purgecss-setup.mjs';
24
28
  import { getJsConfigAliases } from './webpack-config-modules/get-jsConfig-aliases.mjs';
@@ -40,7 +44,8 @@ const __filename = fileURLToPath(import.meta.url)
40
44
 
41
45
  const isDevelopment = process.env.NODE_ENV === 'development'
42
46
  ,devServerPort = [[port5700]]
43
- ,apiPort = [[port8000]] // eslint-disable-line no-unused-vars
47
+ // SETUP symfony
48
+ // ,apiPort = [[port8000]]
44
49
  ,useSass = false
45
50
 
46
51
  // css in dev: true = iniettato con style-loader (veloce, nessun asset css);
@@ -48,7 +53,9 @@ const isDevelopment = process.env.NODE_ENV === 'development'
48
53
  // NB: con `purgeCssInDev: true` (vedi sotto) viene comunque forzato a false,
49
54
  // perché il purge e il plugin delle custom properties lavorano sugli asset css
50
55
  ,inlineCssInDevMode = true
51
- // sf: inlineCssInDevMode = false
56
+ // SETUP symfony
57
+ // ,inlineCssInDevMode = false
58
+
52
59
  ,useSvgo = true
53
60
  ,useSvgr = false // svg per react
54
61
  ,svgoConfig = useSvgo? (await import('./webpack-config-modules/svgo.config.mjs')).default : null
@@ -57,7 +64,8 @@ const isDevelopment = process.env.NODE_ENV === 'development'
57
64
  // dir di output: relativa a QUESTO file ('../build' se il frontend è in una
58
65
  // sottodirectory, './build' se webpack.config.mjs è nella root del progetto)
59
66
  ,output_dir = path.resolve(__dirname, './build')
60
- // ,output_dir = isDevelopment? '_dev' : 'build' // symfony
67
+ // SETUP symfony
68
+ // ,output_dir = isDevelopment? '_dev' : 'build'
61
69
 
62
70
  // dir delle favicons generate da `npx create-favicons` (vedi package.json):
63
71
  // il path assoluto serve a CopyWebpackPlugin/HtmlWebpackPlugin (i path
@@ -66,8 +74,8 @@ const isDevelopment = process.env.NODE_ENV === 'development'
66
74
  ,favicons_path = path.resolve(__dirname, './app/favicons/output') // commentare se non usato
67
75
  ,favicons_path_regexp = /favicons\/output/ // source pattern per le favicons (regexp o null)
68
76
 
69
- //sf:
70
- //,favicons_path
77
+ // SETUP symfony
78
+ // // ,favicons_path = path.resolve(__dirname, './app/favicons/output') // commentare se non usato
71
79
  // ,favicons_path_regexp = null
72
80
 
73
81
 
@@ -98,6 +106,29 @@ const isDevelopment = process.env.NODE_ENV === 'development'
98
106
  // (copiato da minimo da starter-install.sh, generato da `npm run 'build tokens'`)
99
107
  ,customPropsFile = path.resolve(__dirname, './app/css/custom-properties.css')
100
108
 
109
+ /*
110
+ chunk `shared` (splitChunks + runtimeChunk 'single'): true = js e css comuni
111
+ in `shared.js` / `shared.css` + `runtime.js` (vedi `shared_chunk_paths`);
112
+ false = nessun chunk condiviso, utile nei progetti con una sola pagina (più al
113
+ massimo una pagina di errore): la entry principale (`mainEntry`) è sempre
114
+ caricata e contiene da sola tutto il js/css comune e le definizioni delle
115
+ custom properties per tutti i css.
116
+ NB: con `false` i template NON devono più linkare shared.js, shared.css e
117
+ runtime.js (vedi _sf/templates/_main-tpl.html.twig e la pagina di errore)
118
+ */
119
+ ,useSharedChunk = true
120
+ /*
121
+ entry principale, sempre caricata: con `useSharedChunk: false` riceve le
122
+ definizioni delle custom properties per tutti i css delle altre entry
123
+ */
124
+ ,mainEntry = 'index'
125
+ /*
126
+ solo con `useSharedChunk: false`: entry NON `.critical` che non caricano il css
127
+ di `mainEntry`. Restano fuori dal set principale del plugin custom properties
128
+ e ricevono un set proprio, con le proprie definizioni (default: [])
129
+ */
130
+ ,standaloneEntries = []
131
+
101
132
  // PurgeCSS e plugin custom properties lavorano sugli asset css finali:
102
133
  // in dev, con `false`, sono entrambi disattivati (build più veloce, css
103
134
  // iniettato con style-loader; se `useCustomPropsPlugin` è true le definizioni
@@ -106,8 +137,6 @@ const isDevelopment = process.env.NODE_ENV === 'development'
106
137
  // rispettivi flag `usePurgeCss` / `useCustomPropsPlugin`) e `inlineCssInDevMode`
107
138
  // viene forzato a false
108
139
  ,purgeCssInDev = false
109
- ,inlineCssInDev = inlineCssInDevMode && !purgeCssInDev // valore effettivo passato a cssRules
110
- ,runPurgeCss = usePurgeCss && (!isDevelopment || purgeCssInDev)
111
140
  ,runCustomPropsPlugin = useCustomPropsPlugin && (!isDevelopment || purgeCssInDev)
112
141
  // ,manifest_shared_seed = {}
113
142
  ;
@@ -116,6 +145,7 @@ const { CustomPropsPurgeCssPlugin } = runCustomPropsPlugin
116
145
  ? await import('./webpack-config-modules/custom-props-purgecss-plugin.mjs')
117
146
  : {};
118
147
 
148
+ // (solo con `useSharedChunk: true`, vedi sopra)
119
149
  // cacheGroup `shared` (splitChunks): raccoglie in `shared.js` / `shared.css` i
120
150
  // moduli js e css provenienti da node_modules e dalle directory condivise del
121
151
  // progetto (vedi `pathsRegexp` sotto), così non vengono duplicati in ogni entry.
@@ -217,6 +247,8 @@ const CopyWebpackPluginPatterns = [
217
247
  const projectEntries = {
218
248
  'index': './app/index.js',
219
249
 
250
+ 'error-pages': './app/error-pages/error-pages.js',
251
+
220
252
  // css critici da includere inline nei template html: il suffisso `.critical` nel nome
221
253
  // della entry attiva l'istanza PurgeCSS dedicata con purge stretto
222
254
  // (vedi purgecss-setup.mjs) e la regola dedicata in css-rules.mjs
@@ -237,6 +269,41 @@ const entries = (useCustomPropsPlugin && isDevelopment && !purgeCssInDev)
237
269
  : projectEntries;
238
270
 
239
271
 
272
+ // regexp per gli asset css compilati di una entry: corrisponde a `nome.css` (dev con
273
+ // WEBPACK_SERVE, senza hash) e a `nome.<hash>.css`, ma NON a `nome.critical.<hash>.css`
274
+ // (il wildcard `*` di una stringa, invece, non corrisponde a `nome.css` e corrisponde
275
+ // anche a `nome.critical.<hash>.css`)
276
+ const cssAssetRegexp = (entryName) =>
277
+ new RegExp(`^${entryName.replace(/[.+?^${}()|[\]\\]/g, '\\$&')}(\\.[^./]+)?\\.css$`);
278
+
279
+ // set del CustomPropsPurgeCssPlugin (vedi `sets` nei `plugins`). L'elenco delle entry
280
+ // css è derivato da `projectEntries`: aggiungere una entry lì è sufficiente
281
+ const cssEntries = Object.keys(projectEntries).filter(name => !/\.critical/.test(name))
282
+ ,criticalEntries = Object.keys(projectEntries).filter(name => /\.critical/.test(name))
283
+ ,customPropsSets = [
284
+
285
+ // i critical css sono inline nei template: restano autosufficienti
286
+ ...criticalEntries.map(name => ({ sources: [cssAssetRegexp(name)] })),
287
+
288
+ ...(useSharedChunk
289
+ // shared.css è linkato in tutte le pagine: contiene le definizioni per tutti i
290
+ // css delle entry (le definizioni non sono duplicate negli altri asset)
291
+ ? [{
292
+ sources: [cssAssetRegexp('shared'), ...cssEntries.map(cssAssetRegexp)],
293
+ target: cssAssetRegexp('shared')
294
+ }]
295
+ // senza shared: le definizioni sono iniettate solo nel css di `mainEntry`
296
+ // (sempre caricato); le entry che non lo caricano hanno un set proprio
297
+ : [
298
+ {
299
+ sources: cssEntries.filter(name => !standaloneEntries.includes(name)).map(cssAssetRegexp),
300
+ target: cssAssetRegexp(mainEntry)
301
+ },
302
+ ...standaloneEntries.map(name => ({ sources: [cssAssetRegexp(name)] }))
303
+ ]
304
+ )
305
+ ];
306
+
240
307
  const config = {
241
308
  mode: isDevelopment ? 'development' : 'production',
242
309
 
@@ -272,7 +339,7 @@ const config = {
272
339
  clean: !isDevelopment
273
340
  },
274
341
 
275
- /* SYMFONY:
342
+ /* SETUP symfony
276
343
  output: {
277
344
  path: path.resolve(__dirname, `./public/${output_dir}` ),
278
345
  // filename: '[name].js',
@@ -302,20 +369,25 @@ const config = {
302
369
  extractComments: false
303
370
  })
304
371
  ],
305
- runtimeChunk: 'single', // true
306
- splitChunks: {
307
- cacheGroups: {
308
-
309
- shared: {
310
- // vedi shared_chunk_paths sopra per la logica completa del test
311
- test: shared_chunk_paths,
312
- name: 'shared',
313
- enforce: true,
314
- // le entry `.critical` restano autosufficienti (css inline nei template)
315
- chunks: (chunk) => !/\.critical/.test(chunk.name)
316
- }
372
+ // chunk `shared` e runtime: solo con `useSharedChunk: true`
373
+ ...(useSharedChunk
374
+ ? {
375
+ runtimeChunk: 'single', // true
376
+ splitChunks: {
377
+ cacheGroups: {
378
+
379
+ shared: {
380
+ // vedi shared_chunk_paths sopra per la logica completa del test
381
+ test: shared_chunk_paths,
382
+ name: 'shared',
383
+ enforce: true,
384
+ // le entry `.critical` restano autosufficienti (css inline nei template)
385
+ chunks: (chunk) => !/\.critical/.test(chunk.name)
386
+ }
387
+ }
388
+ },
317
389
  }
318
- },
390
+ : {})
319
391
  },
320
392
 
321
393
  // =>> performance
@@ -339,6 +411,7 @@ const config = {
339
411
  client: { overlay: true, },
340
412
  },
341
413
 
414
+ // SETUP symfony
342
415
  // =>> devServer (con symfony)
343
416
  // reverse proxy davanti a `symfony serve` (porta 8102, vedi package.json):
344
417
  // il browser va aperto su questo dev server (non su :8102). Le richieste per
@@ -358,7 +431,10 @@ const config = {
358
431
  // // di servire una versione stale in cache su reload manuale
359
432
  // headers: { 'Cache-Control': 'no-store' },
360
433
  // hot: true,
361
- // open: { app: { name: 'Google Chrome' } }, // apertura automatica del browser all'avvio
434
+ // open: {
435
+ // app: { name: 'Google Chrome' }, // apertura automatica del browser all'avvio
436
+ // // target: ['page1', 'page2'], // pafine da aprire all'avvio
437
+ // },
362
438
  // static: false, // niente static serving proprio: tutto il resto passa dal proxy verso Symfony
363
439
  // devMiddleware: { writeToDisk: true, },
364
440
  // client: { overlay: true, },
@@ -405,10 +481,10 @@ const config = {
405
481
  : []
406
482
  ),
407
483
 
484
+ // SETUP symfony (decommentare)
408
485
  // =>> plugins: WebpackManifestPlugin
409
486
  // new WebpackManifestPlugin({
410
- // fileName: path.join(output_dir, 'manifest.json'),
411
- // sf: fileName: 'manifest.json', // scrive in output.path
487
+ // fileName: path.join(output_dir, 'manifest.json'), // NB: symfony -> fileName: 'manifest.json', // scrive in output.path
412
488
  // // basePath: item.source_dirname
413
489
  // // removeKeyHash: /\?.*$/, // /([a-f0-9]{32}\.?)/gi, // /(\?as_asset)$/,
414
490
  // // rimuove i font dal manifest. Non necessari, rendono il file inutilmente grande
@@ -418,13 +494,6 @@ const config = {
418
494
  // sort: isDevelopment? undefined : (a, b) => a.name.localeCompare(b.name)
419
495
  // }),
420
496
 
421
- // =>> plugins: MiniCssExtractPlugin
422
- new MiniCssExtractPlugin({
423
- filename: '[name].[contenthash].css',
424
- chunkFilename: '[id].[contenthash].css',
425
- ignoreOrder: true
426
- }),
427
-
428
497
  // =>> plugins: MiniCssExtractPlugin
429
498
  // contenthash solo se non si usa Dev Server
430
499
  new MiniCssExtractPlugin({
@@ -440,6 +509,7 @@ const config = {
440
509
  // : [new InlineCriticalCssPlugin({ match: (href) => href?.includes('.critical') })]
441
510
  // ),
442
511
 
512
+ // SETUP symfony (rimuovere)
443
513
  // =>> plugins: HtmlWebpackPlugin (manifest)
444
514
  new HtmlWebpackPlugin({
445
515
  filename: 'manifest.webmanifest',
@@ -448,6 +518,7 @@ const config = {
448
518
  minify: false //!isDevelopment
449
519
  }),
450
520
 
521
+ // SETUP symfony (rimuovere)
451
522
  // =>> plugins: HtmlWebpackPlugin
452
523
  new HtmlWebpackPlugin({
453
524
  filename: 'index.html',
@@ -458,6 +529,7 @@ const config = {
458
529
  // base: isDevelopment ? '/' : '/xxxxx/',
459
530
  }),
460
531
 
532
+ // SETUP symfony (rimuovere)
461
533
  // =>> plugins: HtmlWebpackInjectAttributesPlugin
462
534
  // new HtmlWebpackInjectAttributesPlugin({
463
535
  // // La funzione riceve un oggetto con gli attributi del tag corrente
@@ -471,6 +543,8 @@ const config = {
471
543
  // }
472
544
  // }),
473
545
 
546
+
547
+ // SETUP symfony (rimuovere)
474
548
  // =>> plugins: HtmlWebpackInjectPreload
475
549
  // https://github.com/principalstudio/html-webpack-inject-preload
476
550
  ...(isDevelopment
@@ -515,8 +589,8 @@ const config = {
515
589
 
516
590
  },
517
591
  raw: true,
518
- // niente banner nei critical css: vengono inseriti inline nei template html
519
- exclude: /\.critical/ // chunk name
592
+ // niente banner nei critical css ( vengono inseriti inline nei template html), nelle immagini e nei font
593
+ exclude: /\.critical|\.(svg|png|jpe?g|gif|webp|avif|ico|woff2?|eot|ttf|otf)$/i
520
594
  }),
521
595
 
522
596
  // =>> plugins: PurgeCSSPlugin (solo classi/keyframes, le custom properties sono
@@ -531,7 +605,7 @@ const config = {
531
605
  // watch mode i template twig NON sono osservati da webpack: dopo aver
532
606
  // aggiunto una classe solo in un twig occorre rilanciare la build (o toccare
533
607
  // un file js/css) per aggiornare il purge
534
- ...(runPurgeCss
608
+ ...(usePurgeCss && (!isDevelopment || purgeCssInDev)
535
609
  ? createPurgeCSSPlugins({
536
610
 
537
611
  // SOLO file che generano markup o classi (twig, php, js);
@@ -591,27 +665,25 @@ const config = {
591
665
  definitionsFile: customPropsFile,
592
666
 
593
667
  // set di asset css elaborati in modo indipendente: `sources` sono i nomi
594
- // degli asset compilati (con l'hash nel nome: usare `*`, oppure una
595
- // RegExp), `target` l'asset in cui iniettare le definizioni (se omesso
596
- // è il primo asset del set; se non corrisponde ad alcun asset e non ha
597
- // `*` viene emesso come nuovo asset, che va poi linkato nei template).
598
- // NB: `*` corrisponde a qualsiasi carattere: 'layout.*.css' corrisponde
599
- // anche a 'layout.critical.<hash>.css'
600
- sets: [
601
- // il critical css è inline nei template: deve restare autosufficiente
602
- { sources: ['layout.critical.*.css'] },
603
-
604
- // shared.css è linkato in tutte le pagine: contiene le definizioni
605
- // per tutti i css delle entry (le definizioni non sono duplicate
606
- // negli altri asset). Ogni css delle entry va elencato qui
607
- { sources: ['shared.*.css', 'index.*.css'], target: 'shared.*.css' },
608
- ],
609
-
610
- // css usati fuori dagli asset purgati (shadow DOM dei web components,
611
- // import `?raw`): tutti i loro usi di var() contano per tutti i set
668
+ // degli asset compilati (con l'hash nel nome: usare una RegExp, vedi
669
+ // `cssAssetRegexp`), `target` l'asset in cui iniettare le definizioni (se
670
+ // omesso è il primo asset del set; se non corrisponde ad alcun asset e non
671
+ // è una stringa senza `*` non viene emesso nulla).
672
+ // NB: evitare i wildcard `*`: 'index.*.css' non corrisponde a 'index.css'
673
+ // (dev con WEBPACK_SERVE) e corrisponde invece a 'index.critical.<hash>.css'.
674
+ // I set sono costruiti in `customPropsSets` (sopra) a partire da
675
+ // `projectEntries`, in base a `useSharedChunk`: aggiungendo una entry
676
+ // non serve modificare nulla qui
677
+ sets: customPropsSets,
678
+
679
+ // css usati fuori dal bundle: tutti i loro usi di var() contano per tutti i
680
+ // set. I css importati con `?raw` (shadow DOM dei web components) sono
681
+ // rilevati automaticamente nei js dei chunk, solo per i componenti
682
+ // realmente importati: un glob largo qui porterebbe nel css anche le
683
+ // props di componenti non importati
612
684
  extraUsageGlobs: [
613
- path.resolve(__dirname, './app/src/web-components/**/*.css'),
614
- `${minimo_path}/src/web-components/**/*.css`,
685
+ // path.resolve(__dirname, './app/src/web-components/**/*.css'),
686
+ // `${minimo_path}/src/web-components/**/*.css`,
615
687
  ],
616
688
 
617
689
  // props da includere comunque in tutti i set (nomi esatti o RegExp),
@@ -708,7 +780,12 @@ const config = {
708
780
  },
709
781
 
710
782
  // =>> rules: svg
711
- ...svgRules({useSvgo: useSvgo, svgoConfig: svgoConfig, useSvgr: useSvgr, favicons_path_regexp: favicons_path_regexp?? null }),
783
+ ...svgRules({
784
+ useSvgo: useSvgo,
785
+ svgoConfig: svgoConfig,
786
+ useSvgr: useSvgr,
787
+ favicons_path_regexp: favicons_path_regexp?? null
788
+ }),
712
789
 
713
790
  // =>> rules: Images / pdf
714
791
  {
@@ -771,7 +848,12 @@ const config = {
771
848
  },
772
849
 
773
850
  // =>> rules: css / scss
774
- ...cssRules({isDevelopment: isDevelopment, useSass: useSass, inlineCssInDevMode: inlineCssInDev, postcssConfig_path: postcssConfig_path})
851
+ ...cssRules({
852
+ isDevelopment: isDevelopment,
853
+ useSass: useSass,
854
+ inlineCssInDevMode: inlineCssInDevMode && !purgeCssInDev,
855
+ postcssConfig_path: postcssConfig_path
856
+ })
775
857
  ] // end rules
776
858
  }, // end module
777
859
 
@@ -198,8 +198,10 @@ force_cat() {
198
198
  # sotto-cartelle così com'è in source_files: aggiungere, spostare o rinominare
199
199
  # file lì non richiede modifiche a questo script.
200
200
  # Il terzo argomento (opzionale) è il nome di una funzione di rename invocata
201
- # su ogni singolo basename, per i casi in cui il nome del file sorgente non
202
- # coincide con quello di destinazione (vedi rename_root_file).
201
+ # solo sui file posti direttamente nella root di src_root (non su quelli nelle
202
+ # sotto-cartelle, i cui nomi restano invariati: es. _sf/templates/_main-tpl.html.twig,
203
+ # referenziato così da home.html.twig), per i casi in cui il nome del file
204
+ # sorgente non coincide con quello di destinazione (vedi rename_root_file).
203
205
  # Il quarto argomento (opzionale, default: safe_cat_with_ports) è la funzione
204
206
  # di copia da usare per ogni file: safe_cat_with_ports confronta e backuppa
205
207
  # il singolo file (sostituzione porte no-op se non contiene placeholder);
@@ -210,6 +212,9 @@ force_cat() {
210
212
  # dell'installazione dei pacchetti npm (vedi più sotto).
211
213
  # I file .DS_Store (macOS) vengono sempre ignorati: sono binari e farebbero
212
214
  # fallire il sed di safe_cat_with_ports ("illegal byte sequence").
215
+ # I file .gitkeep non vengono copiati, ma la cartella che li contiene viene
216
+ # comunque creata nella destinazione (servono solo a mantenere la cartella nel
217
+ # repo di minimo).
213
218
  install_tree() {
214
219
  local src_root="$1"
215
220
  local dest_root="$2"
@@ -221,10 +226,14 @@ install_tree() {
221
226
  rel="${file#"$src_root"/}"
222
227
  dir="$(dirname "$rel")"
223
228
  base="$(basename "$rel")"
229
+ if [ "$base" = ".gitkeep" ]; then
230
+ [ "$dir" = "." ] || mkdir -p "${dest_root}/${dir}"
231
+ continue
232
+ fi
224
233
  if [ -n "$exclude" ] && [[ " $exclude " == *" $base "* ]]; then
225
234
  continue
226
235
  fi
227
- if [ -n "$rename_fn" ]; then
236
+ if [ -n "$rename_fn" ] && [ "$dir" = "." ]; then
228
237
  new_base="$("$rename_fn" "$base")"
229
238
  else
230
239
  new_base="$base"
@@ -239,7 +248,8 @@ install_tree() {
239
248
  done < <(find "$src_root" -type f ! -name .DS_Store)
240
249
  }
241
250
 
242
- # Rename applicato ai file di source_files/root/ in fase di copia:
251
+ # Rename applicato ai soli file posti direttamente in source_files/root/ (non alle
252
+ # sotto-cartelle) in fase di copia:
243
253
  # - prefisso singolo underscore -> dotfile (es. _gitignore -> .gitignore);
244
254
  # il doppio underscore (__project__.code-workspace) non viene toccato,
245
255
  # il nome resta invariato
@@ -357,14 +367,20 @@ echo -e "\n${GREEN}...creating default folders${NC}"
357
367
  mkdir -p \
358
368
  "_private" \
359
369
  "${FRONTEND_INSTALL_PATH}" \
370
+ "${FRONTEND_INSTALL_PATH}/api" \
360
371
  "${FRONTEND_INSTALL_PATH}/assets" \
361
- "${FRONTEND_INSTALL_PATH}/src" \
362
372
  "${FRONTEND_INSTALL_PATH}/css" \
363
- "${FRONTEND_INSTALL_PATH}/tpl" \
373
+ "${FRONTEND_INSTALL_PATH}/email" \
374
+ "${FRONTEND_INSTALL_PATH}/error-pages" \
375
+ "${FRONTEND_INSTALL_PATH}/favicons" \
364
376
  "${FRONTEND_INSTALL_PATH}/icons" \
365
377
  "${FRONTEND_INSTALL_PATH}/imgs" \
366
- "${FRONTEND_INSTALL_PATH}/favicons" \
367
- "${FRONTEND_INSTALL_PATH}/error-pages"
378
+ "${FRONTEND_INSTALL_PATH}/src" \
379
+ "${FRONTEND_INSTALL_PATH}/src/components" \
380
+ "${FRONTEND_INSTALL_PATH}/src/js" \
381
+ "${FRONTEND_INSTALL_PATH}/src/pages" \
382
+ "${FRONTEND_INSTALL_PATH}/src/web-components" \
383
+ "${FRONTEND_INSTALL_PATH}/tpl"
368
384
 
369
385
 
370
386
 
@@ -425,11 +441,6 @@ force_cat "${MINIMO_PKG_DIR}/src/minimo.css" "${FRONTEND_INSTALL_PATH}/css/index
425
441
  force_cat "${MINIMO_PKG_DIR}/dev-tools/design-tokens-builder/tokens-config-sample.mjs" "${FRONTEND_INSTALL_PATH}/css/tokens-config.mjs"
426
442
 
427
443
 
428
-
429
- # favicons: config di default per `npx create-favicons`
430
- force_cat "${MINIMO_PKG_DIR}/dev-tools/create-favicons/src/default-params.mjs" "${FRONTEND_INSTALL_PATH}/favicons/create-favicons-cfg.mjs"
431
-
432
-
433
444
  if [ ${#selectedOptionalDevPkgs[@]} -gt 0 ] || [ ${#selectedOptionalDepPkgs[@]} -gt 0 ]; then
434
445
  echo -e "\n${YELLOW}Pacchetti opzionali installati:${NC}"
435
446
  for pkg in "${selectedOptionalDevPkgs[@]}" "${selectedOptionalDepPkgs[@]}"; do