@massimo-cassandro/minimo 1.11.1 → 1.12.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 (47) hide show
  1. package/charts/src/node-helpers/create-svg-canvas-node.mjs +37 -0
  2. package/dev-tools/README.md +1 -1
  3. package/dev-tools/create-favicons/src/init-start-text.txt +20 -0
  4. package/dev-tools/update-version/index.mjs +1 -1
  5. package/dev-tools/update-version/src/chooser-inquirer.mjs +1 -1
  6. package/dev-tools/webpack-setup/starter-install.sh +149 -0
  7. package/dev-tools/webpack-setup/templates/__project__.code-workspace +93 -0
  8. package/dev-tools/webpack-setup/templates/_browserslistrc +27 -0
  9. package/dev-tools/webpack-setup/templates/_editorconfig +17 -0
  10. package/dev-tools/webpack-setup/templates/_gitignore +21 -0
  11. package/dev-tools/webpack-setup/templates/_prettierrc +9 -0
  12. package/dev-tools/webpack-setup/templates/eslint.config.mjs +31 -0
  13. package/dev-tools/webpack-setup/templates/jsconfig.json +22 -0
  14. package/dev-tools/webpack-setup/templates/package-tpl.json +37 -0
  15. package/dev-tools/webpack-setup/templates/stylelint.config.mjs +32 -0
  16. package/dev-tools/webpack-setup/webpack-modules/css-rules.mjs +177 -0
  17. package/dev-tools/webpack-setup/webpack-modules/get-jsConfig-aliases.mjs +33 -0
  18. package/dev-tools/webpack-setup/webpack-modules/mini-svg-data-uri-loader.cjs +25 -0
  19. package/dev-tools/webpack-setup/webpack-modules/postcss.config.mjs +77 -0
  20. package/dev-tools/webpack-setup/webpack-modules/svg-rules.mjs +154 -0
  21. package/dev-tools/webpack-setup/webpack-modules/svgo.config.mjs +26 -0
  22. package/dev-tools/webpack-setup/webpack-template.ejs +20 -0
  23. package/dev-tools/webpack-setup/webpack.config.mjs +585 -0
  24. package/package.json +5 -4
  25. package/snippets/ImgViewerController.php +403 -0
  26. package/snippets/UnsplashController.php +74 -0
  27. package/snippets/build-chrome-custom-device-list.mjs +101 -0
  28. package/snippets/config-templates/_env.local +13 -0
  29. package/snippets/config-templates/_github/dependabot.yml +10 -0
  30. package/snippets/config-templates/_hintrc.cjs +35 -0
  31. package/snippets/config-templates/_htaccess +69 -0
  32. package/snippets/config-templates/_npmignore +8 -0
  33. package/snippets/config-templates/_npmrc +1 -0
  34. package/snippets/config-templates/_stylelintignore +5 -0
  35. package/snippets/config-templates/babel.config--react.json +20 -0
  36. package/snippets/config-templates/babel.config--solidJS.json +8 -0
  37. package/snippets/config-templates/react/offcanvas/offcanvas.jsx +89 -0
  38. package/snippets/config-templates/react/offcanvas/offcanvas.module.scss +109 -0
  39. package/snippets/config-templates/robots.txt +5 -0
  40. package/snippets/config-templates/rollup.config.mjs +115 -0
  41. package/snippets/controllo-codice-fiscale-IT.js +48 -0
  42. package/snippets/controllo-partita-iva-IT.js +32 -0
  43. package/snippets/email-antispam.js +108 -0
  44. package/snippets/error-pages/bundles/TwigBundle/Exception/error.html.twig +33 -0
  45. package/snippets/error-pages/error-pages.js +37 -0
  46. package/snippets/festivita.js +101 -0
  47. package/snippets/minimo-form-layout.html.twig +446 -0
@@ -0,0 +1,177 @@
1
+ // import path from 'path';
2
+ // import { fileURLToPath } from 'url';
3
+ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
4
+
5
+ // const __filename = fileURLToPath(import.meta.url);
6
+ // const __dirname = path.dirname(__filename);
7
+
8
+
9
+
10
+ const postcssLoader = (isDevelopment, postcssConfig_path) => ({
11
+ loader: 'postcss-loader',
12
+ options: {
13
+ sourceMap: isDevelopment,
14
+ postcssOptions: {
15
+ // 'config' accetta un percorso assoluto (stringa) o un booleano
16
+ config: postcssConfig_path,
17
+ },
18
+ }
19
+ });
20
+
21
+ export function cssRules({
22
+ isDevelopment = false,
23
+ useSass = false,
24
+ inlineCssInDevMode = true,
25
+ postcssConfig_path
26
+ }) {
27
+ const configOptions = { isDevelopment, useSass, inlineCssInDevMode, postcssConfig_path };
28
+
29
+
30
+ return [
31
+ // CSS modules
32
+ {
33
+ test: /\.module\.(sass|scss|css)$/i,
34
+ oneOf: [
35
+
36
+ // inserimento critical css con tag style al momento della build
37
+ {
38
+ test: /\.critical\.module\./i,
39
+ use: css_loaders({ ...configOptions, critical: true, css_modules: true }),
40
+ },
41
+
42
+ // inserimento css con tag style nel runtime
43
+ {
44
+ resourceQuery: /inline/,
45
+ use: css_loaders({ ...configOptions, inline: true, css_modules: true }),
46
+ },
47
+ // comportamento standard
48
+ {
49
+ use: css_loaders({ ...configOptions, css_modules: true }),
50
+ },
51
+ ]
52
+ },
53
+ // CSS standard
54
+ {
55
+ test: /\.(sass|scss|css)$/i,
56
+ exclude: /\.module\.(sass|scss|css)$/i,
57
+ sideEffects: true,
58
+ oneOf: [
59
+
60
+ // raw content per web-components
61
+ {
62
+ resourceQuery: /raw/,
63
+ use: [
64
+ // exportType: 'string' sostituisce raw-loader deprecato
65
+ {
66
+ loader: 'css-loader',
67
+ options: {
68
+ exportType: 'string',
69
+ sourceMap: isDevelopment,
70
+ importLoaders: useSass? 2 : 1
71
+ }
72
+ },
73
+
74
+ postcssLoader(isDevelopment, postcssConfig_path),
75
+
76
+ ...(useSass ? [{
77
+ loader: 'sass-loader',
78
+ options: { sourceMap: isDevelopment }
79
+ }] : [])
80
+ ]
81
+ },
82
+
83
+ {
84
+ test: /\.critical\.(sass|scss|css)$/i,
85
+ use: css_loaders({ ...configOptions, critical: true }),
86
+ },
87
+ {
88
+ resourceQuery: /inline/,
89
+ use: css_loaders({ ...configOptions, inline: true }),
90
+ },
91
+ {
92
+
93
+ use: css_loaders({ ...configOptions }),
94
+ }
95
+ ]
96
+ }
97
+ ];
98
+ }
99
+
100
+ function css_loaders({
101
+ isDevelopment = false,
102
+ useSass = false,
103
+ inlineCssInDevMode = true,
104
+ postcssConfig_path = postcssConfig_path,
105
+ css_modules = false,
106
+ critical = false, // Iniezione statica nell'HTML
107
+ inline = false // Iniezione dinamica via JS
108
+ }) {
109
+
110
+ let mainLoader;
111
+
112
+ if (inline) {
113
+ // usa style-loader per la query string ?inline
114
+ mainLoader = {
115
+ loader: 'style-loader',
116
+ options: {
117
+ injectType: 'singletonStyleTag',
118
+ esModule: css_modules
119
+ }
120
+ };
121
+
122
+ } else if (critical) {
123
+ // usa MiniCssExtractPlugin per permettere al plugin HTML di leggerlo
124
+ mainLoader = MiniCssExtractPlugin.loader;
125
+
126
+ } else {
127
+ // compartamento standard
128
+ mainLoader = (isDevelopment && inlineCssInDevMode)
129
+ ? {
130
+ loader: 'style-loader',
131
+ options: {
132
+ injectType: 'singletonStyleTag',
133
+ // esModule: css_modules
134
+ }
135
+ }
136
+ : MiniCssExtractPlugin.loader;
137
+ }
138
+
139
+
140
+ return [
141
+ mainLoader,
142
+
143
+ {
144
+ loader: 'css-loader',
145
+ options: {
146
+ modules: css_modules
147
+ ? {
148
+ auto: true,
149
+ localIdentName: isDevelopment ? '[local]_[hash:base64:6]' : '[hash:base64:10]',
150
+ exportLocalsConvention: 'as-is',
151
+
152
+ // namedExport: false,
153
+ // exportOnlyLocals: false
154
+ }
155
+ : false,
156
+ sourceMap: isDevelopment,
157
+ importLoaders: useSass ? 2 : 1,
158
+ }
159
+ },
160
+
161
+ postcssLoader(isDevelopment, postcssConfig_path),
162
+
163
+ ...(useSass
164
+ ? [ {
165
+ loader: 'sass-loader',
166
+ options: {
167
+ sourceMap: isDevelopment,
168
+ sassOptions: {
169
+ quietDeps: true,
170
+ silenceDeprecations: [ 'legacy-js-api', 'mixed-decls', 'color-functions', 'global-builtin', 'import' ],
171
+ }
172
+ }
173
+ } ]
174
+ : []
175
+ )
176
+ ];
177
+ }
@@ -0,0 +1,33 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+
4
+ /**
5
+ * Funzione per ottenere gli alias direttamente leggendo il file jsconfig.json
6
+ * @param {string} jsconfigAbsPath - Il percorso assoluto del file jsconfig.json
7
+ * @returns {Record<string, string>}
8
+ */
9
+
10
+ export function getJsConfigAliases(jsconfigAbsPath) {
11
+
12
+ const baseDir = path.dirname(jsconfigAbsPath);
13
+
14
+ const fileContent = fs.readFileSync(jsconfigAbsPath, 'utf-8');
15
+ const jsconfig = JSON.parse(fileContent);
16
+
17
+ const aliases = {};
18
+ const paths = jsconfig.compilerOptions?.paths || {};
19
+
20
+ for (const item in paths) {
21
+ // Rimuove la wildcard /* alla fine della chiave (alias)
22
+ const key = item.replace(/(\/\*)$/, '');
23
+
24
+ // Prende il primo valore (path) e rimuove la wildcard /*
25
+ const targetPath = paths[item][0].replace(/(\/\*)$/, '');
26
+
27
+ const absolutePath = path.resolve(baseDir, targetPath);
28
+
29
+ aliases[key] = absolutePath;
30
+ }
31
+
32
+ return aliases;
33
+ }
@@ -0,0 +1,25 @@
1
+ // ./loaders/mini-svg-data-uri-loader.cjs
2
+ // Questo file USA la libreria 'mini-svg-data-uri', ma è un wrapper specifico per Webpack.
3
+
4
+ /* eslint-env node */
5
+ // Nota: require perché i Webpack Loaders sono tradizionalmente CommonJS,
6
+ // e Node.js li gestisce correttamente con l'estensione .cjs.
7
+ const svgToMiniDataURI = require('mini-svg-data-uri');
8
+
9
+ /**
10
+ * Webpack Loader che prende una stringa SVG e la converte in un
11
+ * Data URI compatto usando la libreria mini-svg-data-uri.
12
+ * @param {string} source - Contenuto SVG (già ottimizzato da svgo-loader)
13
+ * @returns {string} Il Data URI SVG compatto (formato stringa)
14
+ */
15
+ module.exports = function (source) {
16
+
17
+ // rimuove height e width nel svgo non fosse attivato
18
+ source = source.replace(/ width="\d+"/, '').replace(/ height="\d+"/, '');
19
+
20
+ // Richiama la funzione per ottenere l'URI compatto
21
+ const dataUri = svgToMiniDataURI(source);
22
+
23
+ // Ritorna la stringa Data URI
24
+ return dataUri;
25
+ };
@@ -0,0 +1,77 @@
1
+ // webpack-modules/postcss.config.mjs
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import globalData from '@csstools/postcss-global-data';
5
+ import customMedia from 'postcss-custom-media';
6
+ import autoprefixer from 'autoprefixer';
7
+ import cssnano from 'cssnano';
8
+ import jitProps from 'postcss-jit-props';
9
+ // import openProps from './modulo_cjs.cjs';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ export default (loaderContext) => {
15
+ const isDevelopment = loaderContext.mode === 'development';
16
+
17
+ const plugins = [
18
+ globalData({
19
+ files: [
20
+ // openProps.
21
+ path.resolve(__dirname, '../src/css/custom-properties.css'),
22
+ path.resolve(__dirname, '../src/css/custom-media.css'),
23
+ ]
24
+ }),
25
+
26
+ // https://github.com/GoogleChromeLabs/postcss-jit-props
27
+ // https://github.com/argyleink/open-props
28
+ // require('postcss-jit-props')(require('open-props')),
29
+ // require('postcss-jit-props')({
30
+ // ...require('open-props'),
31
+ // custom_selector: ':where(html)'
32
+ // }),
33
+ jitProps({
34
+ files: [
35
+ // ...openProps,
36
+ path.resolve(__dirname, '../src/css/custom-properties.css')
37
+ ],
38
+ custom_selector: ':where(html)'
39
+ }),
40
+
41
+ // per IOS < 17 (test)
42
+ // https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
43
+ // https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-light-dark-function#readme
44
+ // require('postcss-nesting')({
45
+ // edition: '2021',
46
+ // noIsPseudoSelector: true
47
+ //}),
48
+ // require('@csstools/postcss-light-dark-function')({preserve: false}), /* NB non funziona benissimo... */
49
+
50
+
51
+ // https://github.com/csstools/postcss-plugins/
52
+
53
+ customMedia({
54
+ preserve: isDevelopment
55
+ }),
56
+
57
+ // https://github.com/postcss/autoprefixer?tab=readme-ov-file#options
58
+ autoprefixer(),
59
+ ];
60
+
61
+ if (!isDevelopment) {
62
+ // per IOS < 17
63
+ // require('postcss-nesting')({
64
+ // edition: '2021',
65
+ // noIsPseudoSelector: true
66
+ //}),
67
+ // require('@csstools/postcss-light-dark-function'), /* NB non funziona benissimo... */
68
+
69
+
70
+ plugins.push(cssnano({ preset: 'default' }));
71
+ }
72
+
73
+
74
+ return {
75
+ plugins: plugins
76
+ };
77
+ };
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Funzione per definire le regole per SVG
3
+ * @returns {import('webpack').RuleSetRule[]}
4
+ */
5
+
6
+
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+
11
+ export function svgRules({
12
+ useSvgo = true,
13
+ useSvgr = false,
14
+ svgoConfig = null,
15
+ favicons_path_regexp = null,
16
+ }) {
17
+
18
+ const this_filename = fileURLToPath(import.meta.url)
19
+ ,this_dirname = path.dirname(this_filename);
20
+
21
+ if(svgoConfig == null) {
22
+ useSvgo = false;
23
+ }
24
+
25
+ /**
26
+ * Restituisce i loader SVGO tenendo conto sia dell'opzione globale `useSvgo`
27
+ * sia delle modalità di opt-out per singolo file/import:
28
+ *
29
+ * 1. resourceQuery `?noSVGO` (combinabile con altre query):
30
+ * import icon from './icon.svg?noSVGO';
31
+ * import icon from './icon.svg?cssInline&noSVGO';
32
+ *
33
+ * 2. Suffisso `-noSVGO` nel nome file (si applica a tutti gli import di quel file):
34
+ * import icon from './icon-noSVGO.svg';
35
+ *
36
+ * Il parametro `resourceQuery` è la stringa raw della query dell'import corrente
37
+ * (es. "?cssInline&noSVGO"). Quando non disponibile a compile-time, la verifica
38
+ * sul suffisso del file viene delegata a `test: /-noSVGO\.svg$/i` sulla regola.
39
+ *
40
+ * @param {boolean} [skipSvgo=false] - true se la regola ha già rilevato noSVGO
41
+ */
42
+ const svgoLoaders = (skipSvgo = false) =>
43
+ (useSvgo && !skipSvgo) ? [ { loader: 'svgo-loader', options: svgoConfig } ] : [];
44
+
45
+ /**
46
+ * Dato un set di condizioni (resourceQuery, test, ...) e i loader "core" della regola,
47
+ * restituisce una coppia di regole: una normale e una con `?noSVGO` che bypassa SVGO.
48
+ * Questo permette di combinare liberamente ?noSVGO con qualsiasi altra query.
49
+ *
50
+ * @param {object} baseRule - la regola senza i loader SVGO
51
+ * @param {function} makeUse - funzione (skipSvgo: bool) => loader array
52
+ */
53
+ const withNoSVGOVariant = (baseRule, makeUse) => [
54
+ // Variante con ?noSVGO: stessa regola ma senza SVGO.
55
+ // La resourceQuery combina il match originale con la presenza di noSVGO.
56
+ {
57
+ ...baseRule,
58
+ resourceQuery: {
59
+ and: [ baseRule.resourceQuery, /noSVGO/ ],
60
+ },
61
+ use: makeUse(true),
62
+ },
63
+ // Variante normale (senza ?noSVGO).
64
+ {
65
+ ...baseRule,
66
+ use: makeUse(false),
67
+ },
68
+ ];
69
+
70
+ return [{
71
+ test: /(\.svg)$/i,
72
+ exclude: favicons_path_regexp?? undefined,
73
+ oneOf: [
74
+
75
+ // 1. svg inline dataUri per css (con `?cssInline`)
76
+ // Supporta anche `?cssInline&noSVGO` per saltare SVGO su quel singolo import.
77
+ ...withNoSVGOVariant(
78
+ {
79
+ resourceQuery: /cssInline/, // ex inline-dataURI
80
+ type: 'asset/source',
81
+ },
82
+ (skipSvgo) => [
83
+ // Loader wrapper per Data URI compatto (Mini-SVG-Data-URI-Loader)
84
+ {
85
+ loader: path.resolve(this_dirname, './mini-svg-data-uri-loader.cjs'),
86
+ },
87
+ // Loader di ottimizzazione SVGO
88
+ ...svgoLoaders(skipSvgo),
89
+ ],
90
+ ),
91
+
92
+ // 2. as react component -> https://react-svgr.com/docs/webpack/
93
+ // Supporta anche `?react&noSVGO`.
94
+ ...(useSvgr
95
+ ? withNoSVGOVariant(
96
+ {
97
+ resourceQuery: /react/,
98
+ issuer: /\.[jt]sx?$/,
99
+ },
100
+ (skipSvgo) => [
101
+ {
102
+ loader: '@svgr/webpack',
103
+ options: {
104
+ ...((useSvgo && !skipSvgo)
105
+ ? {
106
+ svgo: true,
107
+ svgoConfig: svgoConfig,
108
+ }
109
+ : {
110
+ svgo: false,
111
+ }
112
+ ),
113
+ // Altre opzioni utili di SVGR
114
+ // titleProp: true,
115
+ // ref: true,
116
+ },
117
+ },
118
+ ],
119
+ )
120
+ : []
121
+ ),
122
+
123
+ // 3. svg inline (con `?inline`)
124
+ // Supporta anche `?inline&noSVGO`.
125
+ ...withNoSVGOVariant(
126
+ {
127
+ resourceQuery: /inline/,
128
+ type: 'asset/source',
129
+ },
130
+ (skipSvgo) => svgoLoaders(skipSvgo),
131
+ ),
132
+
133
+ // 4. svg file con suffisso `-noSVGO` nel nome (es. `icon-noSVGO.svg`).
134
+ // Si applica a tutti gli import di quel file, senza bisogno di ?noSVGO.
135
+ {
136
+ test: /-noSVGO\.svg$/i,
137
+ type: 'asset/resource',
138
+ generator: {
139
+ filename: 'imgs/[name].[contenthash][ext]'
140
+ },
141
+ },
142
+
143
+ // 5. svg file (copy image files to build folder)
144
+ {
145
+ type: 'asset/resource',
146
+ exclude: [ /cssInline/, /inline/ ],
147
+ sideEffects: true,
148
+ generator: {
149
+ filename: 'imgs/[name].[contenthash][ext]'
150
+ },
151
+ }
152
+ ]
153
+ }];
154
+ }
@@ -0,0 +1,26 @@
1
+ // svgo.config.js
2
+ import addViewBox from 'svgo-add-viewbox';
3
+
4
+ // https://svgo.dev/docs/plugins/
5
+ export default {
6
+ multipass: true,
7
+ plugins: [
8
+ 'removeDoctype'
9
+ , { ...addViewBox, params: { overwrite: false } }
10
+ , { name: 'cleanupIds', params: { remove: true, minify: true } }
11
+ , 'removeComments'
12
+ , 'removeTitle'
13
+ , 'removeDimensions'
14
+ , 'collapseGroups'
15
+ , { name: 'cleanupNumericValues', params: { floatPrecision: 4 } }
16
+ , { name: 'convertColors', params: { names2hex: true, rgb2hex: true } }
17
+ , 'removeStyleElement'
18
+ , 'removeEmptyContainers'
19
+ , { name: 'removeAttrs', params: { attrs: ['(filter|fill|stroke|class|style|data.*)'/* , 'svg:(width|height)' */] } }
20
+ // , { name: 'removeAttrs', params: { attrs: [ '(filter|fill|stroke|fill-rule|clip-rule|stroke-linecap|stroke-linejoin|stroke-width|transform|style|class|data.*)', 'svg:(width|height)' ] } }
21
+ , 'removeUselessDefs',
22
+ //, { name: 'addAttributesToSVGElement0, params: {attribute: "#{$attr}"}}
23
+ // , { name: 'addClassesToSVGElement', params: { className: 'line-icon' } }
24
+ 'removeUselessStrokeAndFill',
25
+ ]
26
+ };
@@ -0,0 +1,20 @@
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
+
8
+ <!-- favicons -->
9
+ <%= require('./favicons/output/favicons.incl.ejs')({}) %>
10
+ <!-- <%= require('./app/favicons/output/favicons.incl.ejs')({}) %> -->
11
+ <!-- <%= require('./frontend/favicons/output/favicons.incl.ejs')({}) %> -->
12
+
13
+ <title><%= htmlWebpackPlugin.options.title %></title>
14
+ <%= htmlWebpackPlugin.tags.headTags %> <!-- opzionale, param `inject: false` -->
15
+ </head>
16
+ <body>
17
+ <div id="root" class="wrapper"></div>
18
+ <%= htmlWebpackPlugin.tags.bodyTags %> <!-- opzionale, param `inject: false` -->
19
+ </body>
20
+ </html>