@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.
- package/charts/src/node-helpers/create-svg-canvas-node.mjs +37 -0
- package/dev-tools/README.md +1 -1
- package/dev-tools/create-favicons/src/init-start-text.txt +20 -0
- package/dev-tools/update-version/index.mjs +1 -1
- package/dev-tools/update-version/src/chooser-inquirer.mjs +1 -1
- package/dev-tools/webpack-setup/starter-install.sh +149 -0
- package/dev-tools/webpack-setup/templates/__project__.code-workspace +93 -0
- package/dev-tools/webpack-setup/templates/_browserslistrc +27 -0
- package/dev-tools/webpack-setup/templates/_editorconfig +17 -0
- package/dev-tools/webpack-setup/templates/_gitignore +21 -0
- package/dev-tools/webpack-setup/templates/_prettierrc +9 -0
- package/dev-tools/webpack-setup/templates/eslint.config.mjs +31 -0
- package/dev-tools/webpack-setup/templates/jsconfig.json +22 -0
- package/dev-tools/webpack-setup/templates/package-tpl.json +37 -0
- package/dev-tools/webpack-setup/templates/stylelint.config.mjs +32 -0
- package/dev-tools/webpack-setup/webpack-modules/css-rules.mjs +177 -0
- package/dev-tools/webpack-setup/webpack-modules/get-jsConfig-aliases.mjs +33 -0
- package/dev-tools/webpack-setup/webpack-modules/mini-svg-data-uri-loader.cjs +25 -0
- package/dev-tools/webpack-setup/webpack-modules/postcss.config.mjs +77 -0
- package/dev-tools/webpack-setup/webpack-modules/svg-rules.mjs +154 -0
- package/dev-tools/webpack-setup/webpack-modules/svgo.config.mjs +26 -0
- package/dev-tools/webpack-setup/webpack-template.ejs +20 -0
- package/dev-tools/webpack-setup/webpack.config.mjs +585 -0
- package/package.json +5 -4
- package/snippets/ImgViewerController.php +403 -0
- package/snippets/UnsplashController.php +74 -0
- package/snippets/build-chrome-custom-device-list.mjs +101 -0
- package/snippets/config-templates/_env.local +13 -0
- package/snippets/config-templates/_github/dependabot.yml +10 -0
- package/snippets/config-templates/_hintrc.cjs +35 -0
- package/snippets/config-templates/_htaccess +69 -0
- package/snippets/config-templates/_npmignore +8 -0
- package/snippets/config-templates/_npmrc +1 -0
- package/snippets/config-templates/_stylelintignore +5 -0
- package/snippets/config-templates/babel.config--react.json +20 -0
- package/snippets/config-templates/babel.config--solidJS.json +8 -0
- package/snippets/config-templates/react/offcanvas/offcanvas.jsx +89 -0
- package/snippets/config-templates/react/offcanvas/offcanvas.module.scss +109 -0
- package/snippets/config-templates/robots.txt +5 -0
- package/snippets/config-templates/rollup.config.mjs +115 -0
- package/snippets/controllo-codice-fiscale-IT.js +48 -0
- package/snippets/controllo-partita-iva-IT.js +32 -0
- package/snippets/email-antispam.js +108 -0
- package/snippets/error-pages/bundles/TwigBundle/Exception/error.html.twig +33 -0
- package/snippets/error-pages/error-pages.js +37 -0
- package/snippets/festivita.js +101 -0
- package/snippets/minimo-form-layout.html.twig +446 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
|
|
2
|
+
# no cache
|
|
3
|
+
# <IfModule mod_headers.c>
|
|
4
|
+
# Header set Cache-Control "no-cache, no-store, must-revalidate"
|
|
5
|
+
# Header set Pragma "no-cache"
|
|
6
|
+
# Header set Expires 0
|
|
7
|
+
# </IfModule>
|
|
8
|
+
|
|
9
|
+
# blocco iframe
|
|
10
|
+
# "deny" = tutti siti
|
|
11
|
+
# "sameorigin" tutti tranne quelli che vengono dalla stessa origine
|
|
12
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
|
13
|
+
Header set X-Frame-Options "sameorigin"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<IfModule mod_expires.c>
|
|
17
|
+
ExpiresActive On
|
|
18
|
+
AddType application/vnd.ms-fontobject .eot
|
|
19
|
+
AddType application/x-font-ttf .ttf
|
|
20
|
+
AddType application/x-font-opentype .otf
|
|
21
|
+
AddType application/x-font-woff .woff
|
|
22
|
+
AddType application/x-font-woff2 .woff2
|
|
23
|
+
AddType application/font-sfnt otf ttf
|
|
24
|
+
AddType application/font-woff woff
|
|
25
|
+
AddType application/font-woff2 woff2
|
|
26
|
+
AddType image/svg+xml .svg
|
|
27
|
+
|
|
28
|
+
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
|
|
29
|
+
ExpiresByType application/x-font-ttf "access plus 1 year"
|
|
30
|
+
ExpiresByType application/x-font-opentype "access plus 1 year"
|
|
31
|
+
ExpiresByType application/x-font-woff "access plus 1 year"
|
|
32
|
+
ExpiresByType application/x-font-woff2 "access plus 1 year"
|
|
33
|
+
ExpiresByType application/font-sfnt "access plus 1 year"
|
|
34
|
+
ExpiresByType application/font-woff "access plus 1 year"
|
|
35
|
+
ExpiresByType application/font-woff2 "access plus 1 year"
|
|
36
|
+
|
|
37
|
+
ExpiresByType text/html "access plus 1 hour"
|
|
38
|
+
ExpiresByType text/css "access plus 1 year"
|
|
39
|
+
ExpiresByType text/x-javascript "access plus 1 year"
|
|
40
|
+
ExpiresByType application/javascript "access plus 1 year"
|
|
41
|
+
ExpiresByType application/x-javascript "access plus 1 year"
|
|
42
|
+
|
|
43
|
+
ExpiresByType image/svg+xml "access plus 1 year"
|
|
44
|
+
ExpiresByType image/gif "access plus 1 year"
|
|
45
|
+
ExpiresByType image/png "access plus 1 year"
|
|
46
|
+
ExpiresByType image/jpeg "access plus 1 year"
|
|
47
|
+
ExpiresByType image/pjpeg "access plus 1 year"
|
|
48
|
+
ExpiresByType image/webp "access plus 1 year"
|
|
49
|
+
ExpiresByType image/avif "access plus 1 year"
|
|
50
|
+
|
|
51
|
+
ExpiresByType application/pdf "access plus 1 year"
|
|
52
|
+
|
|
53
|
+
ExpiresByType video/mp4 "access plus 1 year"
|
|
54
|
+
ExpiresByType video/webm "access plus 1 year"
|
|
55
|
+
ExpiresByType video/x-m4v "access plus 1 year"
|
|
56
|
+
ExpiresByType video/quicktime "access plus 1 year"
|
|
57
|
+
ExpiresByType audio/mpeg "access plus 1 year"
|
|
58
|
+
ExpiresByType audio/x-wav "access plus 1 year"
|
|
59
|
+
|
|
60
|
+
ExpiresByType image/x-icon "access plus 1 year"
|
|
61
|
+
ExpiresDefault "access plus 1 year"
|
|
62
|
+
</IfModule>
|
|
63
|
+
|
|
64
|
+
<IfModule !mod_expires.c>
|
|
65
|
+
<IfModule mod_headers.c>
|
|
66
|
+
# 1 year
|
|
67
|
+
Header set Cache-Control 'public, max-age 31536000'
|
|
68
|
+
</IfModule>
|
|
69
|
+
</IfModule>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
package-lock=false
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offcanvas
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import { useEffect } from 'react';
|
|
9
|
+
import PropTypes from 'prop-types';
|
|
10
|
+
import classnames from 'classnames';
|
|
11
|
+
import styles from './offcanvas.module.scss';
|
|
12
|
+
|
|
13
|
+
// https://react-icons.github.io/react-icons/icons/pi/
|
|
14
|
+
import { PiXCircleBold } from 'react-icons/pi';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function Offcanvas(props) {
|
|
18
|
+
const [isHiding, setIsHiding] = React.useState(false),
|
|
19
|
+
[isShowing, setIsShowing] = React.useState(props.show),
|
|
20
|
+
[content, setContent] = React.useState();
|
|
21
|
+
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
|
|
24
|
+
// disable body scroll
|
|
25
|
+
document.body.classList.toggle('no-scroll', props.show);
|
|
26
|
+
|
|
27
|
+
if(props.show) {
|
|
28
|
+
setIsShowing(true);
|
|
29
|
+
}
|
|
30
|
+
}, [props.show]);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
setContent(
|
|
34
|
+
<div
|
|
35
|
+
role="dialog"
|
|
36
|
+
aria-modal="true"
|
|
37
|
+
className={classnames(
|
|
38
|
+
styles.offcanvas,
|
|
39
|
+
props.className,
|
|
40
|
+
{
|
|
41
|
+
[styles.fullscreen]: props.fullscreen,
|
|
42
|
+
[styles.show]: props.show,
|
|
43
|
+
[styles.hiding]: isHiding,
|
|
44
|
+
[styles.showing]: isShowing
|
|
45
|
+
}
|
|
46
|
+
)}
|
|
47
|
+
tabIndex="-1"
|
|
48
|
+
onTransitionEnd={() => {setIsHiding(false); setIsShowing(false);}}
|
|
49
|
+
>
|
|
50
|
+
<div className={styles.offcanvasInner}>
|
|
51
|
+
<div className={styles.offcanvasHeader}>
|
|
52
|
+
<button
|
|
53
|
+
type="button"
|
|
54
|
+
className={styles.offcanvasClose}
|
|
55
|
+
aria-label="Close"
|
|
56
|
+
onClick={() => {
|
|
57
|
+
setIsHiding(true);
|
|
58
|
+
props.offcanvasShowHandler(props.handlerHideValue);
|
|
59
|
+
}}
|
|
60
|
+
><PiXCircleBold /></button>
|
|
61
|
+
</div>
|
|
62
|
+
<div className={styles.offcanvasBody}>
|
|
63
|
+
{props.children}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}, [isHiding, isShowing, props]);
|
|
69
|
+
|
|
70
|
+
return (content);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// https://www.npmjs.com/package/prop-types
|
|
74
|
+
|
|
75
|
+
Offcanvas.propTypes = {
|
|
76
|
+
className: PropTypes.string,
|
|
77
|
+
offcanvasShowHandler: PropTypes.func,
|
|
78
|
+
show: PropTypes.bool,
|
|
79
|
+
fullscreen: PropTypes.bool,
|
|
80
|
+
handlerHideValue: PropTypes.any
|
|
81
|
+
|
|
82
|
+
};
|
|
83
|
+
Offcanvas.defaultProps = {
|
|
84
|
+
show: false,
|
|
85
|
+
fullscreen: false,
|
|
86
|
+
handlerHideValue: false
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default Offcanvas;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// da bs
|
|
2
|
+
|
|
3
|
+
// @use '../scss/cfg/cfg-settings' as settings;
|
|
4
|
+
// @use '../scss/cfg/grid-breakpoints' as breakpoints;
|
|
5
|
+
// @use 'sass:map
|
|
6
|
+
|
|
7
|
+
@use '../scss/mixins/media-mixins' as mediaMixins;
|
|
8
|
+
@use '../scss/mixins/buttons-mixins' as buttonsMixins;
|
|
9
|
+
// @use '../scss/cfg/status-mixins' as statusMixins;
|
|
10
|
+
// @use '../scss/cfg/text-mixins' as textMixins;
|
|
11
|
+
|
|
12
|
+
.offcanvas {
|
|
13
|
+
--offcanvas-padding-x: 1.4rem;
|
|
14
|
+
--offcanvas-padding-y: 2rem;
|
|
15
|
+
|
|
16
|
+
position: fixed;
|
|
17
|
+
inset: 0;
|
|
18
|
+
z-index: 1045;
|
|
19
|
+
display: block;
|
|
20
|
+
visibility: hidden;
|
|
21
|
+
background-color: var(--overlay-color);
|
|
22
|
+
backdrop-filter: blur(1px);
|
|
23
|
+
|
|
24
|
+
&.show, &.hiding, &.showing {
|
|
25
|
+
visibility: visible;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.offcanvasInner {
|
|
31
|
+
position: fixed;
|
|
32
|
+
top: 0;
|
|
33
|
+
right: 0;
|
|
34
|
+
bottom: 0;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
width: 18rem;
|
|
38
|
+
min-width: 280px;
|
|
39
|
+
max-width: 100dvw;
|
|
40
|
+
// height: 100%;
|
|
41
|
+
color: var(--text-color);
|
|
42
|
+
background-color: var(--body-bg-color);
|
|
43
|
+
background-clip: padding-box;
|
|
44
|
+
border-left: var(--text-color);
|
|
45
|
+
outline: 0;
|
|
46
|
+
box-shadow: var(--shadow-3);
|
|
47
|
+
// opacity: 0;
|
|
48
|
+
// transition: transform, opacity .3s ease-in-out;
|
|
49
|
+
transition: transform .3s ease-in-out;
|
|
50
|
+
transform: translateX(100%);
|
|
51
|
+
|
|
52
|
+
.show & {
|
|
53
|
+
box-shadow: -.5rem 0 .5rem var(--text-color);
|
|
54
|
+
// opacity: 1;
|
|
55
|
+
transform: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.fullscreen & {
|
|
59
|
+
inset: 0;
|
|
60
|
+
width: auto;
|
|
61
|
+
border-left: none;
|
|
62
|
+
}
|
|
63
|
+
.fullscreen.show & {
|
|
64
|
+
box-shadow: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// @include mediaMixins.media-desktop-up() {}
|
|
68
|
+
@media screen and (min-width: __desktop_breakpoint__) {
|
|
69
|
+
.fullscreen & {
|
|
70
|
+
inset: 1.5rem;
|
|
71
|
+
}
|
|
72
|
+
.fullscreen.show & {
|
|
73
|
+
inset: 1.5rem;
|
|
74
|
+
box-shadow:
|
|
75
|
+
10px 10px 1rem var(--overlay),
|
|
76
|
+
-10px 10px 1rem var(--overlay),
|
|
77
|
+
10px -10px 1rem var(--overlay),
|
|
78
|
+
-10px -10px 1rem var(--overlay);
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.offcanvasHeader {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: space-between;
|
|
90
|
+
padding: var(--offcanvas-padding-y) var(--offcanvas-padding-x) calc(var(--offcanvas-padding-y) / 2);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.offcanvasClose {
|
|
94
|
+
@include buttonsMixins.reset-button();
|
|
95
|
+
font-size: 2rem;
|
|
96
|
+
color: var(--bz-primary);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.offcanvasBody {
|
|
100
|
+
flex-grow: 1;
|
|
101
|
+
padding: 0 var(--offcanvas-padding-x) var(--offcanvas-padding-y);
|
|
102
|
+
overflow-y: auto;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@media (prefers-reduced-motion: reduce) {
|
|
106
|
+
.offcanvas {
|
|
107
|
+
transition: none;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import terser from '@rollup/plugin-terser';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import node_resolve from '@rollup/plugin-node-resolve';
|
|
4
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
5
|
+
|
|
6
|
+
// https://github.com/hyhappy/rollup-plugin-string-html
|
|
7
|
+
// import htmlString from 'rollup-plugin-string-html';
|
|
8
|
+
|
|
9
|
+
// https://github.com/exuanbo/rollup-plugin-minify-html-template-literals
|
|
10
|
+
// https://github.com/asyncLiz/minify-html-literals
|
|
11
|
+
// https://github.com/kangax/html-minifier#options-quick-reference
|
|
12
|
+
// import minifyHTML from 'rollup-plugin-minify-html-template-literals';
|
|
13
|
+
|
|
14
|
+
import p from '../package.json'; // assert { type: 'json' };
|
|
15
|
+
|
|
16
|
+
const terserOptions = {
|
|
17
|
+
compress: {
|
|
18
|
+
passes: 2
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
anno = new Date().getFullYear(),
|
|
22
|
+
dirs = [
|
|
23
|
+
{source_dir: './front-end/js', output_dir: './AppBundle/Resources/public/js'}
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
let config = [];
|
|
27
|
+
|
|
28
|
+
// lettura subdir apps e aggiunta a `dirs`
|
|
29
|
+
fs.readdirSync('./front-end/apps').forEach(item => {
|
|
30
|
+
let stats = fs.statSync(`./front-end/apps/${item}`); // stats.isFile() / stats.isDirectory()
|
|
31
|
+
if(stats.isDirectory()) {
|
|
32
|
+
dirs.push({
|
|
33
|
+
source_dir: `./front-end/apps/${item}`,
|
|
34
|
+
output_dir: `./AppBundle/Resources/public/apps/${item}`
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
dirs.forEach(dir => {
|
|
40
|
+
|
|
41
|
+
fs.readdirSync(dir.source_dir)
|
|
42
|
+
.filter(f => /\.js$/.test(f))
|
|
43
|
+
.filter(f => /^[^_]/.test(f)) // ignore files starting with _
|
|
44
|
+
.forEach(file => {
|
|
45
|
+
|
|
46
|
+
let format = 'iife',
|
|
47
|
+
name = null;
|
|
48
|
+
|
|
49
|
+
if(/(-umd\.js)$/.test(file)) {
|
|
50
|
+
format = 'umd';
|
|
51
|
+
name = file.replace('-umd.js', '').replace(/-/g, '_');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
config.push(
|
|
55
|
+
{
|
|
56
|
+
// preserveEntrySignatures: false,
|
|
57
|
+
input: `${dir.source_dir}/${file}`,
|
|
58
|
+
plugins: [
|
|
59
|
+
// deve essere il primo
|
|
60
|
+
// minifyHTML({
|
|
61
|
+
// options: {
|
|
62
|
+
// minifyOptions: {
|
|
63
|
+
// html5: true,
|
|
64
|
+
// collapseWhitespace: true,
|
|
65
|
+
// collapseInlineTagWhitespace: true,
|
|
66
|
+
// conservativeCollapse: true,
|
|
67
|
+
// decodeEntities: true
|
|
68
|
+
// },
|
|
69
|
+
// shouldMinify: () => true
|
|
70
|
+
// },
|
|
71
|
+
// }),
|
|
72
|
+
node_resolve(),
|
|
73
|
+
commonjs(),
|
|
74
|
+
terser(terserOptions),
|
|
75
|
+
],
|
|
76
|
+
output: [{
|
|
77
|
+
file: `${dir.output_dir}/${file.replace('.js', '-min.js')}`,
|
|
78
|
+
format: format,
|
|
79
|
+
sourcemap: true,
|
|
80
|
+
name: name,
|
|
81
|
+
banner: `/*! xxxx v.${p.version} - Massimo Cassandro ${anno} */`,
|
|
82
|
+
// footer: `//! Released on ${new Date().toLocaleString('it-IT', { year: 'numeric', month: 'short', day: '2-digit', hour12: false, hour:'2-digit', minute:'2-digit' })}`
|
|
83
|
+
}]
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export default config;
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// versione statica
|
|
94
|
+
|
|
95
|
+
// export default [
|
|
96
|
+
// {
|
|
97
|
+
// input: 'input.js',
|
|
98
|
+
// plugins: [
|
|
99
|
+
// node_resolve(),
|
|
100
|
+
// // commonjs(),
|
|
101
|
+
// terser({ compress: { passes: 2 } }),
|
|
102
|
+
// ],
|
|
103
|
+
// output: [
|
|
104
|
+
// {
|
|
105
|
+
// file: 'output.min.js',
|
|
106
|
+
// format: 'iife',
|
|
107
|
+
// sourcemap: true,
|
|
108
|
+
|
|
109
|
+
// banner: `/*! xxxx v.${p.version} - Massimo Cassandro ${anno} */`,
|
|
110
|
+
// // footer: `//! Released on ${new Date().toLocaleString('it-IT', { year: 'numeric', month: 'short', day: '2-digit', hour12: false, hour:'2-digit', minute:'2-digit' })}`
|
|
111
|
+
// }
|
|
112
|
+
// ]
|
|
113
|
+
// },
|
|
114
|
+
// ...
|
|
115
|
+
// ];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// basato sulla classe `CodiceFiscale` di Umberto Salsi <salsi@icosaedro.it>
|
|
2
|
+
// http://www.icosaedro.it/cf-pi/index.html
|
|
3
|
+
|
|
4
|
+
import {controllo_partita_iva} from './controllo-partita-iva-IT.js';
|
|
5
|
+
|
|
6
|
+
export function controllo_codice_fiscale(cf) {
|
|
7
|
+
|
|
8
|
+
cf = cf.replace(/\s/g, '').toUpperCase();
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const controllo_cf = cf => {
|
|
12
|
+
if( ! /^[0-9A-Z]{16}$/.test(cf) )
|
|
13
|
+
return false;
|
|
14
|
+
|
|
15
|
+
var s = 0;
|
|
16
|
+
var even_map = 'BAFHJNPRTVCESULDGIMOQKWZYX';
|
|
17
|
+
for(var i = 0; i < 15; i++){
|
|
18
|
+
var c = cf[i];
|
|
19
|
+
var n = 0;
|
|
20
|
+
if( '0' <= c && c <= '9' ) {
|
|
21
|
+
n = c.charCodeAt(0) - '0'.charCodeAt(0);
|
|
22
|
+
} else {
|
|
23
|
+
n = c.charCodeAt(0) - 'A'.charCodeAt(0);
|
|
24
|
+
}
|
|
25
|
+
if( (i & 1) === 0 ) {
|
|
26
|
+
n = even_map.charCodeAt(n) - 'A'.charCodeAt(0);
|
|
27
|
+
}
|
|
28
|
+
s += n;
|
|
29
|
+
}
|
|
30
|
+
if( s % 26 + 'A'.charCodeAt(0) !== cf.charCodeAt(15) ) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if( cf.length === 11 ) {
|
|
39
|
+
return controllo_partita_iva(cf); // il codice fiscale può corrispondere alla partita IVA
|
|
40
|
+
|
|
41
|
+
} else if( cf.length === 16 )
|
|
42
|
+
return controllo_cf(cf);
|
|
43
|
+
|
|
44
|
+
else {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// basato sulla classe `PartitaIVA` di Umberto Salsi <salsi@icosaedro.it>
|
|
2
|
+
// http://www.icosaedro.it/cf-pi/index.html
|
|
3
|
+
|
|
4
|
+
export function controllo_partita_iva(piva='') {
|
|
5
|
+
|
|
6
|
+
piva = piva.replace(/\s/g, '');
|
|
7
|
+
|
|
8
|
+
if( piva.length !== 11 ) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if( !/^[0-9]{11}$/.test(piva) ) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let s = 0;
|
|
17
|
+
for(let i = 0; i < 11; i++ ){
|
|
18
|
+
let n = piva.charCodeAt(i) - '0'.charCodeAt(0);
|
|
19
|
+
|
|
20
|
+
if( (i & 1) === 1 ){
|
|
21
|
+
n *= 2;
|
|
22
|
+
if( n > 9 ) n -= 9;
|
|
23
|
+
}
|
|
24
|
+
s += n;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if( s % 10 !== 0 ) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* email_antispam
|
|
3
|
+
* Nasconde le email agli spammer
|
|
4
|
+
* sostituire i tag mailto con
|
|
5
|
+
*
|
|
6
|
+
* <span data-as-e="xxxx" data-as-d="xxxx/it">__argument__</span>
|
|
7
|
+
*
|
|
8
|
+
* dove:
|
|
9
|
+
* - `e` è la porzione utente dell'indirizzo email (prima della chiocciola)
|
|
10
|
+
* - `d` è il dominio (dopo la chiocciola). Se è indicato un dominio di default
|
|
11
|
+
* può essere omesso. È possibile sostituire i punti con lo slash ('/')
|
|
12
|
+
* per rendere meno riconoscibile il dominio
|
|
13
|
+
* - `__argument__` è il testo (opzionale) da mostrare. Se non è presente viene
|
|
14
|
+
* mostrato l'indirizzo email (offuscato)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export function obfuscate_email (email, hard = true) {
|
|
18
|
+
|
|
19
|
+
// const rand_string = () => {
|
|
20
|
+
// const chars='abcedefghjilmnopqestuvwxyz ABCEDEFGHJILMNOPQESTUVWXYZ 0123456789' +
|
|
21
|
+
// '\n\t“”"«»%$£&/()=?^*é§°çòàù+èùàò-_.:,;',
|
|
22
|
+
// lunghezza = 4;
|
|
23
|
+
|
|
24
|
+
// let str = '', i, pos;
|
|
25
|
+
|
|
26
|
+
// for( i = 0; i < lunghezza; i++ ) {
|
|
27
|
+
// pos = Math.floor(Math.random() * chars.length);
|
|
28
|
+
// str += chars.charAt(pos);
|
|
29
|
+
// }
|
|
30
|
+
// return str;
|
|
31
|
+
// };
|
|
32
|
+
|
|
33
|
+
let encoded_email = '';
|
|
34
|
+
|
|
35
|
+
email.split('').forEach((char, idx) => {
|
|
36
|
+
// if(hard && [2,5,6,79,10,13,15,20,22].indexOf(idx) !== -1) {
|
|
37
|
+
// encoded_email += `<span style="display:none" aria-hidden="true">${rand_string()}</span>`;
|
|
38
|
+
// }
|
|
39
|
+
if( char === '@') {
|
|
40
|
+
encoded_email += hard?'<span>@</span><wbr>' : '@';
|
|
41
|
+
|
|
42
|
+
} else if (char === '.') {
|
|
43
|
+
encoded_email += hard? '<span>.</span><wbr>' : '.';
|
|
44
|
+
|
|
45
|
+
} else if (char === '-') {
|
|
46
|
+
encoded_email += hard? '<span>‐</span><span></span>' : '‐';
|
|
47
|
+
|
|
48
|
+
} else if (char === '_') {
|
|
49
|
+
encoded_email += hard? '<span>_</span><span></span>' : '_';
|
|
50
|
+
|
|
51
|
+
} else if(idx % 2 === 0) {
|
|
52
|
+
encoded_email += `&#${email.charCodeAt(idx)};`;
|
|
53
|
+
|
|
54
|
+
} else {
|
|
55
|
+
encoded_email += char;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
});
|
|
59
|
+
return encoded_email;
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function email_antispam (options) {
|
|
64
|
+
|
|
65
|
+
const default_options = {
|
|
66
|
+
default_domain: null
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
options = Object.assign(default_options, options);
|
|
70
|
+
|
|
71
|
+
if( Object.assign && typeof Object.assign === 'function') {
|
|
72
|
+
options = Object.assign(default_options, options);
|
|
73
|
+
|
|
74
|
+
} else { // IE
|
|
75
|
+
let opts = {};
|
|
76
|
+
for(let i in default_options) {
|
|
77
|
+
opts[i] = options[i] ? options[i] : default_options[i];
|
|
78
|
+
}
|
|
79
|
+
options = opts;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
document.querySelectorAll('[data-as-e]').forEach(el => {
|
|
83
|
+
let domain = el.dataset.asD || options.default_domain;
|
|
84
|
+
if(domain) {
|
|
85
|
+
domain = domain.replace(/\//g, '.');
|
|
86
|
+
let email = el.dataset.asE + '@' + domain,
|
|
87
|
+
content = el.innerHTML || obfuscate_email(email);
|
|
88
|
+
|
|
89
|
+
// el.innerHTML = `<a href="mailto:${email}" target="_blank" rel="noopener noreferrer">${content}</a>`;
|
|
90
|
+
|
|
91
|
+
el.innerHTML = `<!--googleoff: all-->
|
|
92
|
+
<a href="#" target="_blank" rel="noopener noreferrer">${content}</a>
|
|
93
|
+
<!--googleon: all-->`;
|
|
94
|
+
if(el.dataset.addMicrodata !== undefined) {
|
|
95
|
+
|
|
96
|
+
el.insertAdjacentHTML('beforeend',
|
|
97
|
+
`<meta itemprop="email" content="${obfuscate_email(email, false)}">`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
el.querySelector('a').addEventListener('click', (e) => {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
window.location.href = `mailto:${email}`;
|
|
103
|
+
}, false);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{#-
|
|
2
|
+
https://symfony.com/doc/current/controller/error_pages.html#testing-error-pages-during-development
|
|
3
|
+
|
|
4
|
+
test errori: https://governance.local:8890/_error/<error code>
|
|
5
|
+
-#}
|
|
6
|
+
<!DOCTYPE html>
|
|
7
|
+
<html lang="it" data-err-code="{{ status_code }}" data-err-text="{{ status_text}}">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="utf-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
11
|
+
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
12
|
+
<title>Errore {{ status_code }}</title>
|
|
13
|
+
<meta name="robots" content="noindex, nofollow, noarchive">
|
|
14
|
+
{%- include 'incl/favicons.incl.html.twig'-%}
|
|
15
|
+
<link rel="preload" href="{{ asset('governance.css') }}" as="style">
|
|
16
|
+
<link rel="stylesheet" href="{{ asset('governance.css') }}" media="all">
|
|
17
|
+
<link rel="preload" href="{{ asset('error-pages.css') }}" as="style">
|
|
18
|
+
<link rel="stylesheet" href="{{ asset('error-pages.css') }}" media="all">
|
|
19
|
+
<link rel="preload" href="{{ asset('error-pages.js') }}" as="script">
|
|
20
|
+
|
|
21
|
+
<link rel="preload" href="{{ asset('vendors.js') }}" as="script">
|
|
22
|
+
<link rel="preload" href="{{ asset('runtime.js') }}" as="script">
|
|
23
|
+
<link rel="preload" href="{{ asset('vendors.css') }}" as="style">
|
|
24
|
+
<link rel="stylesheet" href="{{ asset('vendors.css') }}" type="text/css" media="all">
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<div id="root"></div>
|
|
28
|
+
|
|
29
|
+
<script src="{{ asset('runtime.js') }}"></script>
|
|
30
|
+
<script src="{{ asset('vendors.js') }}"></script>
|
|
31
|
+
<script src="{{ asset('error-pages.js') }}"></script>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|