@massimo-cassandro/minimo 1.33.3 → 1.33.4

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.
@@ -147,7 +147,7 @@ const config = {
147
147
  ],
148
148
 
149
149
  // Directory containing the CSS files to scan for unresolved custom properties
150
- dirToCheck: '../../src',
150
+ dirToCheck: '../src',
151
151
 
152
152
  // Regular expressions for custom property names to exclude from the check.
153
153
  // Useful for intentionally private/internal props (e.g. prefixed with --_).
@@ -0,0 +1,26 @@
1
+ /* @import url(../src/css/custom-properties.css); */
2
+
3
+ :root {
4
+
5
+ --mail-font-size-xs: 13px;
6
+ --mail-font-size: 16px;
7
+ --mail-font-size-lg: 18px;
8
+ --mail-font-size-2lg: 21px;
9
+ --mail-font-size-3lg: 24px;
10
+ --mail-font-size-xl: 28px;
11
+
12
+ --mail-body-font: helvetica, arial, sans-serif;
13
+ --mail-body-bg: #efefef;
14
+ --mail-text-color: #333;
15
+ --mail-text-color-light: #373737;
16
+ --mail-gray: #4b4a4a;
17
+
18
+ --mail-content-bg: #fff;
19
+ --mail-spacing: 24px;
20
+ --mail-spacing-half: 12px; /* niente calc(): non supportato da Outlook */
21
+
22
+ --mail-alt-color: #036;
23
+ --mail-darken-alt-color: #010112;
24
+ --mail-link-color: #036;
25
+
26
+ }
@@ -0,0 +1,66 @@
1
+ /* stylelint-disable declaration-no-important */
2
+ @import './_mail-properties.css';
3
+
4
+ /* NB: niente selettore universale `*`: inline_css inlinerebbe la regola su ogni elemento */
5
+ body, table, td, p, a { text-size-adjust: 100%; }
6
+
7
+ .content {
8
+ &.body {
9
+ a {
10
+ font-weight: 700;
11
+ color: var(--mail-alt-color);
12
+ text-decoration: underline;
13
+ cursor: pointer;
14
+
15
+ &:hover {
16
+ color: var(--mail-darken-alt-color);
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ @media only screen and (max-width: 640px) {
23
+ body {
24
+ &[class='yahoo-fix'] {
25
+ .device-width {
26
+ width: 440px !important;
27
+ }
28
+ }
29
+ }
30
+
31
+ .content {
32
+ &.columns-wrapper {
33
+ td.column-spacer {
34
+ height: 0 !important;
35
+ }
36
+
37
+ td.column-width, td.column-spacer {
38
+ display: block !important;
39
+ width: 100% !important;
40
+ }
41
+ .column-content {
42
+ & td {
43
+ & h2 {
44
+ font-size: var(--mail-font-size-3lg) !important;
45
+ }
46
+ & .text {
47
+ font-size: var(--mail-font-size-lg) !important;
48
+ }
49
+ & .buttons {
50
+ font-size: var(--mail-font-size-2lg) !important;
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ @media only screen and (max-width: 479px) {
59
+ body {
60
+ &[class='yahoo-fix'] {
61
+ .device-width {
62
+ width: 280px !important;
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,214 @@
1
+ /* stylelint-disable max-nesting-depth */
2
+ /* stylelint-disable selector-max-compound-selectors */
3
+ /* stylelint-disable selector-max-id */
4
+ /* stylelint-disable property-no-unknown */
5
+ @import './_mail-properties.css';
6
+
7
+ body {
8
+ width: 100%;
9
+ padding: 0;
10
+ margin: 0;
11
+ font-family: var(--mail-body-font);
12
+ font-style: normal;
13
+ font-weight: 400;
14
+ line-height: 1.5;
15
+ color: var(--mail-text-color);
16
+ background-color: var(--mail-body-bg);
17
+ -webkit-font-smoothing: antialiased;
18
+
19
+ .device-width {
20
+ width: 600px;
21
+ padding: 0;
22
+ }
23
+
24
+ /* .full-width {
25
+ width: 100%;
26
+ padding: 0;
27
+ } */
28
+ }
29
+
30
+ /*
31
+ div.outerWrapper {
32
+ background-color: var(--mail-content-bg);
33
+ //border-radius:20px;
34
+ overflow: hidden;
35
+ margin: 0 auto;
36
+ }
37
+ */
38
+
39
+ table {
40
+ border-collapse: collapse;
41
+ }
42
+
43
+ p {
44
+ mso-table-lspace: 0;
45
+ mso-table-rspace: 0;
46
+ margin-top: var(--mail-spacing-half);
47
+ margin-bottom: var(--mail-spacing-half);
48
+ }
49
+
50
+ #wrapper{
51
+ width: 100%;
52
+ margin: 0 auto;
53
+ border: none;
54
+
55
+ /* &.full-page{
56
+ width: 95%;
57
+ } */
58
+
59
+ > tbody > tr > td {
60
+ width: 100%;
61
+ padding-top: 10px;
62
+ padding-right: 10px;
63
+ padding-bottom: 20px;
64
+ padding-left: 10px;
65
+ background-color: var(--mail-body-bg);
66
+ border: none;
67
+ }
68
+ }
69
+
70
+ .content {
71
+ margin: 0 auto;
72
+
73
+ &.header {
74
+ > tbody > tr > td {
75
+ padding: 10px;
76
+ text-align: center;
77
+ background: var(--mail-body-bg);
78
+
79
+ > img {
80
+ display: inline-block;
81
+ max-width: 100%;
82
+ height: auto;
83
+ }
84
+ }
85
+ .logo {
86
+ padding-top: 10px;
87
+ padding-bottom: 10px;
88
+ }
89
+ }
90
+
91
+ &.body {
92
+
93
+ > tbody > tr {
94
+ > td {
95
+
96
+ padding-top: 20px;
97
+ padding-right: 30px;
98
+ padding-bottom: 20px;
99
+ padding-left: 30px;
100
+ vertical-align: top;
101
+ color: var(--mail-text-color);
102
+ background-color: var(--mail-content-bg);
103
+
104
+ a {
105
+ font-weight: 700;
106
+ color: var(--mail-alt-color);
107
+ text-decoration: underline;
108
+ cursor: pointer;
109
+
110
+ &:hover {
111
+ color: var(--mail-darken-alt-color);
112
+ }
113
+ }
114
+
115
+ h1 {
116
+ margin-top: 0;
117
+ margin-bottom: var(--mail-spacing);
118
+ font-size: var(--mail-font-size-xl);
119
+ font-weight: 700;
120
+ }
121
+
122
+ p {
123
+ font-size: var(--mail-font-size-2lg);
124
+ }
125
+
126
+ img {
127
+ max-width: 100%;
128
+ height: auto;
129
+ }
130
+
131
+ }
132
+ }
133
+ }
134
+
135
+ &.footer {
136
+ td {
137
+ padding-top: 10px;
138
+ padding-bottom: 10px;
139
+ font-size: 80%;
140
+ color: var(--mail-text-color-light);
141
+ text-align: center;
142
+ background: var(--mail-body-bg);
143
+ }
144
+ }
145
+ }
146
+
147
+ .logo-network {
148
+ display: inline-block;
149
+ padding: 5px;
150
+ margin: 10px auto;
151
+ background-color: var(--mail-body-bg);
152
+ }
153
+ .network-info {
154
+ font-size: var(--mail-font-size-xs);
155
+ font-style: italic;
156
+ color: #888;
157
+ }
158
+
159
+
160
+ .text-center {
161
+ text-align: center;
162
+ }
163
+ .text-right {
164
+ text-align: right;
165
+ }
166
+ .text-left {
167
+ text-align: left;
168
+ }
169
+ .small, small {
170
+ font-size: var(--mail-font-size-xs);
171
+ }
172
+ .margin-top {
173
+ margin-top: var(--mail-spacing);
174
+ }
175
+ .margin-bottom {
176
+ margin-bottom: var(--mail-spacing);
177
+ }
178
+ .text-monospace {
179
+ font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
180
+ }
181
+ .text-muted {
182
+ color: #666;
183
+ }
184
+
185
+
186
+ em, i {
187
+ font-style: italic;
188
+ }
189
+ strong, b {
190
+ font-weight: 700;
191
+ }
192
+
193
+ /* body content table */
194
+ .table {
195
+ width: 100%;
196
+ margin: 12px 0 24px;
197
+ border-collapse: collapse;
198
+
199
+ th, td {
200
+ padding: 6px 10px;
201
+ vertical-align: top;
202
+ text-align: left;
203
+ border-bottom: 1px solid var(--mail-gray);
204
+ }
205
+ th {
206
+ font-weight: 600;
207
+ }
208
+
209
+ thead {
210
+ th {
211
+ border-bottom-width: 2px;
212
+ }
213
+ }
214
+ }
@@ -0,0 +1,41 @@
1
+ // config postcss per le CSS delle email (npm run "css email")
2
+ // NB: in ESM perché postcss-nested >= 8 è ESM-only
3
+ //
4
+ // https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-properties#readme
5
+
6
+ import postcssNested from 'postcss-nested';
7
+ import postcssImport from 'postcss-import';
8
+ import customProperties from 'postcss-custom-properties';
9
+ import autoprefixer from 'autoprefixer';
10
+ import cssnano from 'cssnano';
11
+
12
+ // postcss-custom-properties mantiene sempre le dichiarazioni `--*` in :root:
13
+ // una volta risolte le var() non servono più (e i client email non le supportano).
14
+ // Rimuove anche i commenti (finirebbero nel <style> dell'email) e le regole rimaste vuote.
15
+ const cleanup = {
16
+ postcssPlugin: 'email-css-cleanup',
17
+ OnceExit(root) {
18
+ root.walkComments(comment => comment.remove());
19
+ root.walkDecls(/^--/, decl => decl.remove());
20
+ root.walkRules(rule => { if (rule.nodes.length === 0) rule.remove(); });
21
+ }
22
+ };
23
+
24
+ export default () => {
25
+ const plugins = [
26
+ // gli @import vanno risolti prima del nesting e delle custom properties
27
+ postcssImport(),
28
+ postcssNested(),
29
+ // risolve le var(--mail-*) e rimuove il blocco :root
30
+ // (i client email non supportano le custom properties)
31
+ customProperties({ preserve: false }),
32
+ cleanup,
33
+ autoprefixer(),
34
+ // https://cssnano.github.io/cssnano/docs/what-are-optimisations/
35
+ // minifySelectors riscrive `.a td, .a th` in `.a :is(td,th)`,
36
+ // non supportato da Gmail/Outlook
37
+ cssnano({ preset: ['default', { minifySelectors: false }] }),
38
+ ];
39
+
40
+ return { plugins };
41
+ };
@@ -18,17 +18,17 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "progetto JS webpack DEV": "npm run 'launchChrome' && NODE_ENV=development webpack serve --config ./webpack.config.mjs #--open-app-name 'Google Chrome'",
21
- "progetto sf webpack DEV": "rm -rf ./public/_dev && NODE_ENV=development webpack --config ./webpack.config.mjs",
21
+ "php server": "php -S localhost:[[port8000]] # -t root_dir/",
22
+ "progetto sf webpack DEV": "rm -rf ./public/_dev && NODE_ENV=development webpack serve --config ./webpack.config.mjs # http://192.168.1.135:[[port5700]",
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`",
22
24
  "webpack PROD": "npm run 'UPD-version' && NODE_ENV=production webpack --config ./webpack.config.mjs --stats minimal",
23
25
  "eslint-check": "npx eslint app/",
24
26
  "create-favicons INIT": "npx create-favicons init",
25
27
  "create-favicons": "npx create-favicons --dir=./app/favicons",
26
28
  "UPD-version": "npx update-version --no-log-v0 --log-file=./changelog.md # --log-patch --pkg=alt/path/to/package.json",
27
29
  "upd@m": "npx upd@m",
28
- "launchChrome": "open -n -a 'Google Chrome' --args --profile-directory='Profile 3'",
30
+ "launchChrome": "open -n -a 'Google Chrome' --args --profile-directory='Profile 3' # mbn: 1 / mg2: 3",
29
31
  "python server": "python3 -m http.server [[port8000]] # --directory __dirname__ # 8000 = default port",
30
- "php server": "php -S localhost:[[port8000]] # -t root_dir/",
31
- "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`",
32
32
  "node server": "node serve # richiede ‘npm i serve’",
33
33
  "build tokens": "npx buildTokens --config ./app/css/tokens-config.mjs",
34
34
  "check unresolved props": "npx checkUnresolvedProps --config ./app/css/tokens-config.mjs",
@@ -0,0 +1,63 @@
1
+ {# template base per tutte le email #}
2
+ {% apply inline_css(source('email/css/mail-inline.css')) %}
3
+ <!DOCTYPE html>
4
+ <html lang="it">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <meta name="format-detection" content="telephone=no">
9
+ <title>{% block title %}{% endblock %}</title>
10
+ <style type="text/css">
11
+ {%- include 'email/css/mail-inline.css' -%}
12
+ {%- include 'email/css/mail-embed.css' -%}
13
+ </style>
14
+ </head>
15
+ <body class="yahoo-fix" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
16
+ {# Wrapper table #}
17
+ <table width="100%" border="0" cellpadding="0" cellspacing="0" align="center" id="wrapper">
18
+ <tbody>
19
+ <tr>
20
+ <td width="100%">
21
+ {# logo #}
22
+ <table class="content header device-width" width="600" border="0" cellpadding="0" cellspacing="0" align="center">
23
+ <tbody>
24
+ <tr>
25
+ <td class="logo" width="100%">
26
+ {% block logo %}
27
+ {# immagine allegata inline (cid:), vedi templates/email/imgs #}
28
+ <img src="{{ email.image('email/imgs/logo-ict-governance-email.png', 'image/png', 'logo-ict-governance.png') }}" alt="ICT Governance" width="200" height="54" border="0">
29
+ {%- endblock %}
30
+ </td>
31
+ </tr>
32
+ </tbody>
33
+ </table>
34
+
35
+ {# content #}
36
+ <table class="content body device-width" width="600" border="0" cellpadding="0" cellspacing="0" align="center">
37
+ <tbody>
38
+ <tr>
39
+ <td>
40
+ <h1 class="text-center">
41
+ {%- block title_h1 %}{{ block('title') }}{% endblock -%}
42
+ </h1>
43
+ {% block content %}{% endblock %}
44
+ </td>
45
+ </tr>
46
+ </tbody>
47
+ </table>
48
+
49
+ {# footer #}
50
+ <table class="content footer device-width" width="600" border="0" cellpadding="0" cellspacing="0" align="center">
51
+ <tbody>
52
+ <tr>
53
+ <td>{% block footer %}Bluvacanze{%- endblock %}</td>
54
+ </tr>
55
+ </tbody>
56
+ </table>
57
+ </td>
58
+ </tr>
59
+ </tbody>
60
+ </table>
61
+ </body>
62
+ </html>
63
+ {% endapply %}
@@ -0,0 +1 @@
1
+ a,body, p, table, td{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}.content.body a{font-weight:700;color:#036;text-decoration:underline;cursor:pointer}.content.body a:hover{color:#010112}@media only screen and (max-width:640px){body[class="yahoo-fix"] .device-width{width:440px!important}.content.columns-wrapper td.column-spacer{height:0!important} .content.columns-wrapper td.column-spacer,.content.columns-wrapper td.column-width{display:block!important;width:100%!important}.content.columns-wrapper .column-content td h2{font-size:24px!important}.content.columns-wrapper .column-content td .text{font-size:18px!important}.content.columns-wrapper .column-content td .buttons{font-size:21px!important}}@media only screen and (max-width:479px){body[class="yahoo-fix"] .device-width{width:280px!important}}
@@ -0,0 +1 @@
1
+ body{width:100%;padding:0;margin:0;font-family:helvetica,arial,sans-serif;font-style:normal;font-weight:400;line-height:1.5;color:#333;background-color:#efefef;-webkit-font-smoothing:antialiased}body .device-width{width:600px;padding:0}table{border-collapse:collapse}p{mso-table-lspace:0;mso-table-rspace:0;margin-top:12px;margin-bottom:12px}#wrapper{width:100%;margin:0 auto;border:none}#wrapper > tbody > tr > td{width:100%;padding:10px 10px 20px;background-color:#efefef;border:none}.content{margin:0 auto}.content.header > tbody > tr > td{padding:10px;text-align:center;background:#efefef}.content.header > tbody > tr > td > img{display:inline-block;max-width:100%;height:auto}.content.header .logo{padding-top:10px;padding-bottom:10px}.content.body > tbody > tr > td{padding:20px 30px;vertical-align:top;color:#333;background-color:#fff}.content.body > tbody > tr > td a{font-weight:700;color:#036;text-decoration:underline;cursor:pointer}.content.body > tbody > tr > td a:hover{color:#010112}.content.body > tbody > tr > td h1{margin-top:0;margin-bottom:24px;font-size:28px;font-weight:700}.content.body > tbody > tr > td p{font-size:21px}.content.body > tbody > tr > td img{max-width:100%;height:auto}.content.footer td{padding-top:10px;padding-bottom:10px;font-size:80%;color:#373737;text-align:center;background:#efefef}.logo-network{display:inline-block;padding:5px;margin:10px auto;background-color:#efefef}.network-info{font-size:13px;font-style:italic;color:#888}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.small, small{font-size:13px}.margin-top{margin-top:24px}.margin-bottom{margin-bottom:24px}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-muted{color:#666}em, i{font-style:italic} b,strong{font-weight:700}.table{width:100%;margin:12px 0 24px;border-collapse:collapse} .table td,.table th{padding:6px 10px;vertical-align:top;text-align:left;border-bottom:1px solid #4b4a4a}.table th{font-weight:600}.table thead th{border-bottom-width:2px}
@@ -39,9 +39,10 @@ const __filename = fileURLToPath(import.meta.url)
39
39
 
40
40
  const isDevelopment = process.env.NODE_ENV === 'development'
41
41
  ,devServerPort = [[port5700]]
42
- // ,apiPort = [[port8000]]
42
+ ,apiPort = [[port8000]] // eslint-disable-line no-unused-vars
43
43
  ,useSass = false
44
44
  ,inlineCssInDevMode = true
45
+ // sf: inlineCssInDevMode = false
45
46
  ,useSvgo = true
46
47
  ,useSvgr = false // svg per react
47
48
  ,svgoConfig = useSvgo? (await import('./webpack-config-modules/svgo.config.mjs')).default : null
@@ -59,6 +60,11 @@ const isDevelopment = process.env.NODE_ENV === 'development'
59
60
  ,favicons_path = path.resolve(__dirname, './app/favicons/output') // commentare se non usato
60
61
  ,favicons_path_regexp = /favicons\/output/ // source pattern per le favicons (regexp o null)
61
62
 
63
+ //sf:
64
+ //,favicons_path
65
+ // ,favicons_path_regexp = null
66
+
67
+
62
68
  // NB: jsconfig.json va tenuto in questa stessa dir (gli alias sono risolti
63
69
  // a partire dalla sua posizione)
64
70
  ,jsConfigAliases = getJsConfigAliases(path.resolve(__dirname, './jsconfig.json'))
@@ -91,8 +97,9 @@ const isDevelopment = process.env.NODE_ENV === 'development'
91
97
  // limitata tra le pagine. Da rivedere in futuro se la duplicazione dovesse
92
98
  // crescere.
93
99
  //
94
- // TODO: se in futuro la duplicazione di css tra le pagine dovesse crescere
95
- // (componenti importati dal js di più entry), valutare un cacheGroup `styles`
100
+ // TODO: shared.css -> attualmente non generato, ma se in futuro la duplicazione di css tra le pagine dovesse crescere
101
+ // e se si risolve un problema con purgeCSS
102
+ // (componenti importati dal js di più entry), valutare un cacheGroup `shared`
96
103
  // dedicato ai css condivisi: andranno escluse le entry `.critical` (devono
97
104
  // restare autosufficienti), gestite in safelist.variables le custom properties
98
105
  // definite/consumate tra asset diversi (vedi purgecss-variables-safelist.mjs),
@@ -104,8 +111,8 @@ const shared_chunk_paths = (module) => {
104
111
  const sep = '[\\\\/]'; // stringa che produce [\\/] nel pattern
105
112
  const pathsRegexp = new RegExp([
106
113
  'node_modules',
107
- 'app/js',
108
114
  'app/src',
115
+ 'app/src/js',
109
116
  'app/src/web-components',
110
117
  'app/src/components',
111
118
  ].map(p => `${sep}${p.replace(/\//g, sep)}${sep}`).join('|'));
@@ -441,8 +448,8 @@ const config = {
441
448
  start_year,
442
449
  ...(current_year > start_year? [current_year] : [])
443
450
  ].join('-')
444
- // ,vers = packageJson.version.split('.').slice(0,-1).join('.')
445
- ,vers = packageJson.version
451
+ ,vers = packageJson.version.split('.').slice(0,-1).join('.')
452
+ // ,vers = packageJson.version
446
453
  ;
447
454
 
448
455
  const author = packageJson.author?.name ?? (packageJson.author ?? '');
@@ -27,6 +27,11 @@ DIM='\033[2m' # Dim
27
27
  NC='\033[0m' # No Color
28
28
 
29
29
  DEBUG=FALSE
30
+ for arg in "$@"; do
31
+ case "$arg" in
32
+ --debug) DEBUG=TRUE ;;
33
+ esac
34
+ done
30
35
 
31
36
  # Questo script richiede zsh: se lanciato con sh/bash blocca l'esecuzione
32
37
  if [ -z "$ZSH_VERSION" ]; then
@@ -57,17 +62,22 @@ echo -e "${DIM}Porte: ${PORT_8000} (server), ${PORT_5700} (webpack dev server)${
57
62
  # aggiornato manualmente anche qui).
58
63
  # Ogni voce è "<pacchetto> | <dev> | <descrizione>" (pacchetto e colonna <dev>
59
64
  # allineati a colonna fissa solo per leggibilità, non richiesto dal parsing).
65
+ # La colonna <pacchetto> può contenere più pacchetti separati da spazio: in tal
66
+ # caso vengono proposti con un'unica domanda e, se confermati, installati tutti
67
+ # (uno per uno) con la stessa modalità indicata dalla colonna <dev>.
60
68
  # La colonna <dev> vale "dev" se il pacchetto va installato con `npm i -D`
61
69
  # (devDependency), stringa vuota se va installato con `npm i -S` (dependency
62
70
  # vera, es. peer dependency di minimo usata a runtime).
63
71
  optionalPackages=(
64
- "dotenv-webpack | dev | gestione variabili d'ambiente (.env) nel bundle webpack"
65
- "@principalstudio/html-webpack-inject-preload | dev | injection dei tag <link rel=preload> nell'html generato"
66
- "postcss-jit-props | dev | include nel CSS compilato solo le custom properties effettivamente usate"
67
- "@svgdotjs/svg.js | | richiesto da charts/ di minimo"
68
- "blurhash | | richiesto da unsplash-page di minimo (create-blurhash-canvas)"
69
- "simple-datatables | | richiesto da s-datatable-component di minimo"
70
- "style-dictionary | dev | richiesto da design-tokens/utilities di minimo (build-tokens)"
72
+ "dotenv-webpack | dev | gestione variabili d'ambiente (.env) nel bundle webpack"
73
+ "@principalstudio/html-webpack-inject-preload | dev | injection dei tag <link rel=preload> nell'html generato"
74
+ "postcss-jit-props | dev | include nel CSS compilato solo le custom properties effettivamente usate"
75
+ "@svgdotjs/svg.js | | richiesto da charts/"
76
+ "blurhash | | richiesto da unsplash-page (create-blurhash-canvas)"
77
+ "simple-datatables | | richiesto da s-datatable-component"
78
+ "style-dictionary | dev | richiesto da design-tokens/utilities (build-tokens)"
79
+ "@cybozu/eslint-config | dev | utilizzato da eslint per il check dei file css"
80
+ "postcss-cli postcss-import postcss-nested cssnano | dev | per css email"
71
81
  )
72
82
 
73
83
  # Rimuove spazi iniziali/finali da una stringa (usata per i campi estratti
@@ -81,8 +91,8 @@ ask_optional_pkg() {
81
91
  local pkg="$1"
82
92
  local desc="$2"
83
93
  local reply
84
- echo -e "\n${YELLOW}${pkg}{NC}"
85
- echo -e "${DIM}${desc}{NC}"
94
+ echo -e "\n${YELLOW}${pkg}${NC}"
95
+ echo -e "${DIM}${desc}${NC}"
86
96
  read "reply?Installare questo pacchetto opzionale? [y/N]: "
87
97
  [[ "$reply" =~ ^[Yy]$ ]]
88
98
  }
@@ -98,10 +108,11 @@ if [ "$DEBUG" != "TRUE" ]; then
98
108
  devFlag="$(trim "$devFlag")"
99
109
  desc="$(trim "$desc")"
100
110
  if ask_optional_pkg "$pkg" "$desc"; then
111
+ # ${=pkg}: word splitting di zsh, per le voci con più pacchetti
101
112
  if [ "$devFlag" = "dev" ]; then
102
- selectedOptionalDevPkgs+=("$pkg")
113
+ selectedOptionalDevPkgs+=(${=pkg})
103
114
  else
104
- selectedOptionalDepPkgs+=("$pkg")
115
+ selectedOptionalDepPkgs+=(${=pkg})
105
116
  fi
106
117
  fi
107
118
  done
@@ -196,6 +207,8 @@ force_cat() {
196
207
  # riferiti al nome del file sorgente, prima di un eventuale rename_fn) da
197
208
  # saltare: usato per escludere package-tpl.json, già copiato a parte prima
198
209
  # dell'installazione dei pacchetti npm (vedi più sotto).
210
+ # I file .DS_Store (macOS) vengono sempre ignorati: sono binari e farebbero
211
+ # fallire il sed di safe_cat_with_ports ("illegal byte sequence").
199
212
  install_tree() {
200
213
  local src_root="$1"
201
214
  local dest_root="$2"
@@ -222,7 +235,7 @@ install_tree() {
222
235
  dest="${dest_root}/${dir}/${new_base}"
223
236
  fi
224
237
  "$copy_fn" "$file" "$dest"
225
- done < <(find "$src_root" -type f)
238
+ done < <(find "$src_root" -type f ! -name .DS_Store)
226
239
  }
227
240
 
228
241
  # Rename applicato ai file di source_files/root/ in fase di copia:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "1.33.3",
3
+ "version": "1.33.4",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html lang="it">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7
+ <title>{%- block title -%}{%- endblock %} | Marketing</title>
8
+ <meta name="robots" content="noindex, nofollow, noarchive">
9
+ {%- include 'incl/favicons.incl.html.twig'-%}
10
+ {{- '' -}}
11
+ <link rel="preload" href="{{ asset('index.js') }}" as="script">
12
+ <link rel="preload" href="{{ asset('shared.js') }}" as="script">
13
+ <link rel="preload" href="{{ asset('runtime.js') }}" as="script">
14
+ {{- '' -}}
15
+ <link rel="preload" href="{{ asset('index.css') }}" as="style">
16
+ <link rel="stylesheet" href="{{ asset('index.css') }}" type="text/css" media="all">
17
+ <style>
18
+ {%- include '@public_path' ~ asset('layout.critical.css') -%}
19
+ </style>
20
+ {%- block head -%}{%- endblock -%}
21
+ </head>
22
+ <body>
23
+
24
+ <script src="{{ asset('runtime.js') }}"></script>
25
+ <script src="{{ asset('shared.js') }}"></script>
26
+ <script src="{{ asset('index.js') }}"></script>
27
+ {%- block js -%}{%- endblock -%}
28
+ </body>
29
+ </html>
@@ -1,10 +1,6 @@
1
- {#-
2
- https://symfony.com/doc/current/controller/error_pages.html#testing-error-pages-during-development
3
-
4
- test: https://project.local:8890/_error/500 (or 403, 404... )
5
- -#}
1
+ {#- https://symfony.com/doc/current/controller/error_pages.html#testing-error-pages-during-development -#}
6
2
  <!DOCTYPE html>
7
- <html lang="it" data-err-code="{{ status_code }}" data-err-text="{{ status_text }}">
3
+ <html lang="it" data-err-code="{{ status_code }}" data-err-text="{{ status_text}}">
8
4
  <head>
9
5
  <meta charset="utf-8">
10
6
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -12,16 +8,14 @@ test: https://project.local:8890/_error/500 (or 403, 404... )
12
8
  <title>Errore {{ status_code }}</title>
13
9
  <meta name="robots" content="noindex, nofollow, noarchive">
14
10
  {%- include 'incl/favicons.incl.html.twig'-%}
15
- <link rel="preload" href="{{ asset('project.css') }}" as="style">
16
- <link rel="stylesheet" href="{{ asset('project.css') }}" media="all">
11
+ <link rel="preload" href="{{ asset('marketing.css') }}" as="style">
12
+ <link rel="stylesheet" href="{{ asset('marketing.css') }}" media="all">
17
13
  <link rel="preload" href="{{ asset('error-pages.css') }}" as="style">
18
14
  <link rel="stylesheet" href="{{ asset('error-pages.css') }}" media="all">
19
15
  <link rel="preload" href="{{ asset('error-pages.js') }}" as="script">
20
16
 
21
- <link rel="preload" href="{{ asset('vendors.js') }}" as="script">
17
+ <link rel="preload" href="{{ asset('shared.js') }}" as="script">
22
18
  <link rel="preload" href="{{ asset('runtime.js') }}" as="script">
23
- <link rel="preload" href="{{ asset('shared.css') }}" as="style">
24
- <link rel="stylesheet" href="{{ asset('shared.css') }}" type="text/css" media="all">
25
19
  </head>
26
20
  <body>
27
21
  <div id="root"></div>
@@ -0,0 +1,71 @@
1
+ # symfony + webpack config
2
+
3
+
4
+ ## symfony config folder
5
+
6
+ ### `config/services.yaml`
7
+
8
+ ```
9
+ parameters:
10
+ assets_dir: '%env(ASSETS_DIR)%'
11
+ ```
12
+
13
+ ### `config/packages/framework.yaml`
14
+
15
+ ```
16
+ # see https://symfony.com/doc/current/reference/configuration/framework.html
17
+ framework:
18
+ # [...]
19
+
20
+ assets:
21
+ json_manifest_path: "%kernel.project_dir%/public/%env(ASSETS_DIR)%/manifest.json"
22
+ # base_path: '%env(ASSETS_DIR)%'
23
+
24
+ # manifest specifici
25
+ packages:
26
+ dashboard:
27
+ json_manifest_path: "%kernel.project_dir%/public/dashboard/manifest.json"
28
+ ```
29
+
30
+ ### `config/packages/twig.yaml`
31
+
32
+ ```
33
+ twig:
34
+ file_name_pattern: '*.twig'
35
+
36
+ form_themes:
37
+ - '_tpl/incl/bs5-form-layout.html.twig'
38
+ paths:
39
+ '%kernel.project_dir%/public/%env(ASSETS_DIR)%': assets_path
40
+ '%kernel.project_dir%/public': public_path
41
+ ```
42
+
43
+
44
+ ## .env e .env.dev (o .env.local o ...)
45
+
46
+ In `.env`:
47
+
48
+ ```
49
+ ###> supporto webpack
50
+ # cartella, dentro public, in cui webpack salva js, css immagini ecc
51
+ ASSETS_DIR=build
52
+ ###<
53
+ ```
54
+
55
+ In `.env.dev`:
56
+
57
+ ```
58
+ ###> supporto webpack
59
+ # cartella, dentro public, in cui webpack salva js, css immagini ecc
60
+ ASSETS_DIR=_dev
61
+ ###<
62
+ ```
63
+
64
+
65
+ ## .gitignore
66
+
67
+ Aggiungere
68
+
69
+ ```
70
+ public/_dev
71
+ ```
@@ -25,6 +25,10 @@ const legacyParamNames = {
25
25
  use_warning_icon: 'useAltIcon'
26
26
  };
27
27
 
28
+ // TODO aggiungere metodo setDefaults per cambiare a livello globale i valori di default
29
+ // senza doverli ripetere ad ogni istanza del modulo
30
+
31
+
28
32
  const defaults = {
29
33
 
30
34
  // settings applied to all dialog types; can be overridden per type
@@ -1,6 +1,10 @@
1
1
  /*! minimo - Validation Error */
2
- // usage:
3
- // throw new ValidationError('Duplicate values found', errorFields);
2
+ /*
3
+ usage:
4
+ throw new ValidationError('Duplicate values found');
5
+ throw new ValidationError('Duplicate values found', errorFields);
6
+ throw new ValidationError('Duplicate values found', errorFields, 'Each value can be used only once');
7
+ */
4
8
 
5
9
  /*
6
10
  example:
@@ -51,16 +55,29 @@ form.addEventListener('submit', e => {
51
55
 
52
56
  /**
53
57
  * Custom error class for form validation failures.
54
- * Extends the native Error with an array of invalid form fields.
58
+ * Extends the native Error with an optional array of invalid form fields
59
+ * and an optional extended description.
60
+ *
61
+ * @example
62
+ * throw new ValidationError('Duplicate values found', [field1, field2], 'Each value can be used only once');
63
+ *
64
+ * // parameters with default values
65
+ * throw new ValidationError(
66
+ * 'Duplicate values found', // message (required)
67
+ * null, // fields (default: null)
68
+ * null // description (default: null)
69
+ * );
55
70
  */
56
71
  export class ValidationError extends Error {
57
72
  /**
58
73
  * @param {string} message - Error message.
59
- * @param {Element[]} fields - Array of invalid form field elements.
74
+ * @param {Element[]|null} [fields] - Array of invalid form field elements (default: null)
75
+ * @param {string|null} [description] - Extended description of the error (default: null)
60
76
  */
61
- constructor(message, fields) {
77
+ constructor(message, fields = null, description = null) {
62
78
  super(message);
63
79
  this.name = 'ValidationError';
64
80
  this.fields = fields;
81
+ this.description = description;
65
82
  }
66
83
  }