@massimo-cassandro/minimo 1.41.4 → 1.41.5
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/README.md +12 -12
- package/charts/src/node-helpers/create-svg-canvas-node.mjs +2 -2
- package/charts/src/node-helpers/svg-text-to-path.js +9 -9
- package/charts/src/rating-display/index.js +1 -1
- package/charts/src/rating-display/ratindDisplayAnimation.js +3 -3
- package/design-tokens/README.md +2 -2
- package/design-tokens/_src/_readme.md +26 -26
- package/dev-tools/README.md +16 -16
- package/dev-tools/create-favicons/README.md +31 -31
- package/dev-tools/create-favicons/src/create-ico.mjs +2 -2
- package/dev-tools/create-favicons/src/default-params.mjs +1 -1
- package/dev-tools/create-favicons/src/init.mjs +1 -1
- package/dev-tools/design-tokens-builder/README.md +102 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/build-source-modes.mjs +85 -73
- package/dev-tools/design-tokens-builder/build-tokens-src/config.mjs +109 -85
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/css.mjs +113 -90
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/json.mjs +107 -95
- package/dev-tools/design-tokens-builder/build-tokens-src/legacy-tokens-parser.mjs +71 -64
- package/dev-tools/design-tokens-builder/build-tokens-src/light-dark.mjs +75 -65
- package/dev-tools/design-tokens-builder/build-tokens-src/merge-css.mjs +113 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/platforms.mjs +36 -30
- package/dev-tools/design-tokens-builder/build-tokens-src/resolve-source-paths.mjs +15 -13
- package/dev-tools/design-tokens-builder/build-tokens-src/source-prefixes.mjs +44 -42
- package/dev-tools/design-tokens-builder/build-tokens-src/source-transforms.mjs +89 -83
- package/dev-tools/design-tokens-builder/build-tokens-src/token-rename-parser.mjs +99 -86
- package/dev-tools/design-tokens-builder/build-tokens-src/transforms.mjs +64 -48
- package/dev-tools/design-tokens-builder/build-tokens.mjs +80 -68
- package/dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs +103 -77
- package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +275 -238
- package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +2 -2
- package/dev-tools/starter-kit/source_files/app/CLAUDE.md +4 -2
- package/dev-tools/starter-kit/source_files/app/{css/index.css → index.css} +2 -2
- package/dev-tools/starter-kit/source_files/app/index.js +1 -1
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ImgViewerController.php +3 -3
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ViewerController.php +2 -2
- package/dev-tools/starter-kit/source_files/root/stylelint.config.mjs +1 -1
- package/dev-tools/starter-kit/source_files/root/webpack-config-modules/css-rules.mjs +1 -1
- package/dev-tools/stylelint-config/README.md +7 -7
- package/dev-tools/svg-icons-tools/README.md +32 -32
- package/dev-tools/svg-icons-tools/src/config-manager.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/default-config.mjs +118 -118
- package/dev-tools/svg-icons-tools/src/jsx-icon-file-builder.mjs +24 -24
- package/dev-tools/svg-icons-tools/src/parse-svg-filename.mjs +3 -3
- package/dev-tools/svg-icons-tools/src/parse-svg-files.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/parse-svg-markup.mjs +4 -4
- package/dev-tools/svg-icons-tools/src/svg-to-jsx.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-optimized.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-symbols.mjs +2 -2
- package/dev-tools/upd@m/README.md +1 -1
- package/dev-tools/upd@m/index.mjs +1 -1
- package/dev-tools/update-version/README.md +9 -9
- package/package.json +1 -1
- package/snippets/unsplash-browser-app/README.md +1 -1
- package/snippets/unsplash-browser-app/unsplash-utilities.js +9 -9
- package/src/components/autocomplete/README.md +3 -3
- package/src/components/autocomplete/autocomplete-engine.js +75 -63
- package/src/components/autocomplete/check-autocomplete.js +3 -3
- package/src/components/dismiss-alerts.js +3 -3
- package/src/components/form-reset-submit.js +6 -6
- package/src/components/inner-nav/inner-nav.js +2 -2
- package/src/components/modal-alert/modal-alert.js +67 -65
- package/src/components/modal-alert/modal-alert.minimo.tokens.mjs +1 -1
- package/src/components/modal-popup/modal-popup.js +56 -56
- package/src/components/overlay/overlay.js +3 -3
- package/src/components/sf-macro/readme.md +1 -1
- package/src/components/sf-macro/sf-macro.js +27 -23
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +83 -79
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +44 -44
- package/src/components/snackbar/snackbar.js +19 -19
- package/src/components/spinner/spinner.js +3 -3
- package/src/components/unsplash-page/README.md +8 -8
- package/src/components/unsplash-page/fetch-unsplash-data.js +3 -3
- package/src/components/unsplash-page/unsplash-page.js +33 -33
- package/src/components/unsplash-page/unsplash-page.module.css +1 -1
- package/src/css/alerts.css +2 -2
- package/src/css/forms/forms.css +4 -4
- package/src/css/forms/validation.css +1 -1
- package/src/css/margin-padding-media.css +4 -4
- package/src/css/margin-padding.css +4 -4
- package/src/css/reset.css +11 -11
- package/src/icons/read-me.md +1 -1
- package/src/minimo.css +3 -3
- package/src/utilities/better-text-with-places.js +22 -22
- package/src/utilities/better-text.js +42 -35
- package/src/utilities/classnames.js +8 -8
- package/src/utilities/cookies.js +6 -6
- package/src/utilities/create-id.js +3 -3
- package/src/utilities/disable-btns-on-submit.js +2 -2
- package/src/utilities/dom-builder/dom-builder.js +89 -86
- package/src/utilities/dom-builder/domBuilderBasicSetup.js +9 -9
- package/src/utilities/dom-builder/parseDomString.js +23 -23
- package/src/utilities/dom-builder-helpers/README.md +2 -2
- package/src/utilities/dom-builder-helpers/form-tags.js +100 -100
- package/src/utilities/dom-builder-helpers/picture-tag.js +39 -39
- package/src/utilities/enable-submit-btns.js +1 -1
- package/src/utilities/escape-html.js +2 -2
- package/src/utilities/generate-pwd.js +4 -4
- package/src/utilities/linked-dates.js +13 -13
- package/src/utilities/parse-file-size.js +6 -6
- package/src/utilities/random-id.js +3 -3
- package/src/utilities/relative-date.js +40 -40
- package/src/utilities/sentence-case.js +1 -1
- package/src/utilities/strip-tags.js +1 -1
- package/src/utilities/title-case.js +1 -1
- package/src/utilities/truncate-string.js +5 -5
- package/src/utilities/validation-error-class.js +12 -12
- package/src/web-components/json-table/json-table-component.js +123 -121
- package/src/web-components/json-table/json-table-component.module.css +6 -6
- package/src/web-components/json-table/json-table.minimo.tokens.mjs +6 -6
- package/src/web-components/json-table/readme.md +72 -108
- package/src/web-components/json-table/src/cell-content.js +25 -25
- package/src/web-components/json-table/src/content-utils.js +21 -21
- package/src/web-components/json-table/src/data-types.js +32 -32
- package/src/web-components/json-table/src/defaults.js +230 -191
- package/src/web-components/json-table/src/get-data.js +55 -38
- package/src/web-components/json-table/src/icons.js +17 -17
- package/src/web-components/json-table/src/info-section.js +18 -18
- package/src/web-components/json-table/src/main-builder.js +45 -45
- package/src/web-components/json-table/src/pagination.js +32 -32
- package/src/web-components/json-table/src/parse-cols.js +18 -18
- package/src/web-components/json-table/src/parse-rows.js +17 -17
- package/src/web-components/json-table/src/resolve-params.js +53 -41
- package/src/web-components/json-table/src/search.js +13 -13
- package/src/web-components/json-table/src/sorting.js +20 -20
- package/src/web-components/json-table/src/table-body.js +13 -13
- package/src/web-components/json-table/src/table-builder.js +34 -34
- package/src/web-components/json-table/src/table-tfoot.js +8 -8
- package/src/web-components/json-table/src/table-thead.js +21 -21
- package/src/web-components/json-table/src/update-info.js +11 -11
- package/types/classes.d.ts +2 -2
- package/types/global.d.ts +18 -12
package/src/utilities/cookies.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/*! minimo - Cookies */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Restituisce il valore di un cookie dal nome.
|
|
6
6
|
* @param {string} name
|
|
7
7
|
* @param {object} [options]
|
|
8
|
-
* @param {boolean} [options.parseJson=false] -
|
|
8
|
+
* @param {boolean} [options.parseJson=false] - Se true, esegue il parsing JSON del valore e restituisce un oggetto invece di una stringa (default: false)
|
|
9
9
|
* @returns {string | object | null}
|
|
10
10
|
*/
|
|
11
11
|
export function getCookie(name, {parseJson = false} = {}) {
|
|
@@ -21,19 +21,19 @@ export function getCookie(name, {parseJson = false} = {}) {
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Imposta un cookie.
|
|
25
25
|
* @param {object} params
|
|
26
26
|
* @param {string} params.name
|
|
27
27
|
* @param {string} params.value
|
|
28
28
|
* @param {string|null} [params.path=null] (default: null)
|
|
29
|
-
* @param {number|null} [params.expire=null] - Max-Age in
|
|
29
|
+
* @param {number|null} [params.expire=null] - Max-Age in secondi (default: null)
|
|
30
30
|
* @example
|
|
31
|
-
* // Cookie
|
|
31
|
+
* // Cookie limitato alla sola pagina corrente, con durata di 15 giorni
|
|
32
32
|
* setCookie({
|
|
33
33
|
* name: 'cookieName',
|
|
34
34
|
* value: 'cookieValue',
|
|
35
35
|
* path: window.location.pathname,
|
|
36
|
-
* expire: 15 * 24 * 60 * 60 // 15
|
|
36
|
+
* expire: 15 * 24 * 60 * 60 // 15 giorni
|
|
37
37
|
* });
|
|
38
38
|
*/
|
|
39
39
|
export function setCookie({name, value, path = null, expire = null}) {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { stripTags } from './strip-tags.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Crea un id a partire da una stringa (utile per generare ancore automatiche dal contenuto di un tag).
|
|
6
|
+
* Rimuove i tag HTML e normalizza caratteri accentati, punteggiatura e spazi.
|
|
7
7
|
* @param {string | null | undefined} str
|
|
8
8
|
* @returns {string}
|
|
9
9
|
*/
|
|
@@ -12,7 +12,7 @@ export function createId(str) {
|
|
|
12
12
|
.toLowerCase()
|
|
13
13
|
.normalize('NFD')
|
|
14
14
|
.replace(/[\u0300-\u036f]/g, '')
|
|
15
|
-
.replace(/[\p{P}\p{S}]+/gu, '') //
|
|
15
|
+
.replace(/[\p{P}\p{S}]+/gu, '') // rimuove tutta la punteggiatura e i simboli Unicode
|
|
16
16
|
.replace(/\s+/g, '-')
|
|
17
17
|
.replace(/^-+|-+$/g, '')
|
|
18
18
|
.replace(/-+/g, '-')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*! minimo - Disable Buttons On Submit */
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Disabilita tutti i pulsanti `[type=submit]` e `[type=button]` al submit del form.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Si applica a tutti gli elementi `<form>` del documento, tranne quelli con
|
|
6
6
|
* `data-disable-submit="false"`.
|
|
7
7
|
*
|
|
8
8
|
* @returns {void}
|
|
@@ -2,50 +2,51 @@
|
|
|
2
2
|
import { domBuilderBasicSetup } from './domBuilderBasicSetup.js';
|
|
3
3
|
import { parseDomString } from './parseDomString.js';
|
|
4
4
|
|
|
5
|
-
// TODO multi-
|
|
6
|
-
// TODO
|
|
5
|
+
// TODO sintassi stringa multi-riga in cui ogni riga corrisponde a un elemento
|
|
6
|
+
// TODO come sopra, con nidificazione opzionale tramite indentazione
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {Object} DomBuilderItem
|
|
10
|
-
* @property {string | string[]} [tag='div'] -
|
|
11
|
-
* @property {string | string[]} [tagName='div'] - Alias
|
|
12
|
-
* @property {string | string[]} [className] - CSS
|
|
13
|
-
* @property {string | string[]} [class] - Alias
|
|
14
|
-
* @property {string | string[]} [classname] - Alias
|
|
15
|
-
* @property {string | null} [id] -
|
|
16
|
-
* @property {[string, *] | [string, *][] | Object<string, *>} [attrs] -
|
|
17
|
-
* @property {string | number | Function | Node | DomBuilderItem[] | null} [content] -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* `DocumentFragment`, ...)
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* @property {
|
|
28
|
-
* @property {
|
|
10
|
+
* @property {string | string[]} [tag='div'] - Nome del tag HTML o array di tag annidati (ciascuno è il genitore del successivo). Anche `tagName` (default: 'div')
|
|
11
|
+
* @property {string | string[]} [tagName='div'] - Alias di `tag` (default: 'div')
|
|
12
|
+
* @property {string | string[]} [className] - Classe/i CSS: una singola stringa o un array (i valori falsy vengono scartati).
|
|
13
|
+
* @property {string | string[]} [class] - Alias di `className`.
|
|
14
|
+
* @property {string | string[]} [classname] - Alias di `className`.
|
|
15
|
+
* @property {string | null} [id] - ID univoco dell'elemento.
|
|
16
|
+
* @property {[string, *] | [string, *][] | Object<string, *>} [attrs] - Attributi: una coppia `[name, value]`, un array di coppie o un oggetto `{name: value}`.
|
|
17
|
+
* @property {string | number | Function | Node | DomBuilderItem[] | null} [content] - Contenuto dell'elemento.
|
|
18
|
+
* Una stringa o un numero viene impostato come testo semplice (`textContent`), a meno che contenga `<`:
|
|
19
|
+
* in tal caso viene trattato come markup, sanificato e inserito tramite la Sanitizer API nativa
|
|
20
|
+
* (`Element.setHTML`) dove supportata, con ripiego su `innerHTML` grezzo nei browser che non la hanno.
|
|
21
|
+
* Un `Node` (un `Element`, un `DocumentFragment`, ...) viene aggiunto così com'è, direttamente o
|
|
22
|
+
* restituito da una funzione.
|
|
23
|
+
* @property {string | number} [text] - Scorciatoia per un nodo di testo letterale: inserisce un nodo `Text` semplice (mai
|
|
24
|
+
* interpretato come markup) al posto di un elemento, così da poter essere fratello dei tag negli array
|
|
25
|
+
* `children`/`content`. Mutuamente esclusivo con `tag`/`content`/`children`: quando è impostato (e `tag` è assente),
|
|
26
|
+
* ogni altra proprietà tranne `condition` e `callback` viene ignorata.
|
|
27
|
+
* @property {boolean} [condition=true] - Se false, l'elemento (o il nodo di testo) viene saltato (default: true)
|
|
28
|
+
* @property {((el: HTMLElement|Text) => void) | null} [callback] - Callback invocata dopo la creazione dell'elemento (o del nodo di testo).
|
|
29
|
+
* @property {Array<DomBuilderItem|string|Node>} [children] - Array di configurazione degli elementi figli. Accetta stringhe (scorciatoia secondo `parseDomString`), oggetti di configurazione e/o `Node` (un `Element`, un `DocumentFragment`, ...) inseriti così come sono.
|
|
29
30
|
*/
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* domBuilder
|
|
33
|
-
*
|
|
34
|
+
* Costruisce una struttura DOM a partire da un array di configurazione.
|
|
34
35
|
*
|
|
35
|
-
*
|
|
36
|
+
* Analizza un array di oggetti di configurazione per creare elementi HTML.
|
|
36
37
|
*
|
|
37
|
-
* **
|
|
38
|
+
* **Formato della struttura di configurazione (structureArray):**
|
|
38
39
|
*
|
|
39
40
|
* ```javascript
|
|
40
41
|
* structure = [
|
|
41
42
|
* '#mainContainer.container',
|
|
42
43
|
* 'p#main-info.info.active{data-id:123,role=button} Lorem ipsum',
|
|
43
44
|
* {
|
|
44
|
-
* tag: 'div' | ['.divClass', 'h2#id', 'table.class1', 'thead', 'tr.class2.class3(attr1: attrValue)'], //
|
|
45
|
-
* className: 'xxx' | ['class1', 'class2'], //
|
|
45
|
+
* tag: 'div' | ['.divClass', 'h2#id', 'table.class1', 'thead', 'tr.class2.class3(attr1: attrValue)'], // anche tagName
|
|
46
|
+
* className: 'xxx' | ['class1', 'class2'], // anche `class`
|
|
46
47
|
* id: 'element-id',
|
|
47
48
|
* attrs: [attr_name, attr_value] | [[...], [...]] | {name: value},
|
|
48
|
-
* content: 'xxx' | 'xxx <strong>yyy</strong>' | 123 | domBuilder Array | function | Node, //
|
|
49
|
+
* content: 'xxx' | 'xxx <strong>yyy</strong>' | 123 | domBuilder Array | function | Node, // vedi DomBuilderItem.content sopra
|
|
49
50
|
* condition: true | false,
|
|
50
51
|
* callback: el => ...,
|
|
51
52
|
* children: [...]
|
|
@@ -58,9 +59,9 @@ import { parseDomString } from './parseDomString.js';
|
|
|
58
59
|
* ]
|
|
59
60
|
* ```
|
|
60
61
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* (
|
|
62
|
+
* Per mescolare testo letterale e tag come fratelli nello stesso elemento (es. `Lorem <strong>ipsum</strong> dolor`),
|
|
63
|
+
* usare la scorciatoia `text` in `children`/`content`, dato che una semplice stringa viene sempre interpretata come tag
|
|
64
|
+
* (vedi `parseDomString`), mai come nodo di testo:
|
|
64
65
|
*
|
|
65
66
|
* ```javascript
|
|
66
67
|
* children: [
|
|
@@ -70,39 +71,39 @@ import { parseDomString } from './parseDomString.js';
|
|
|
70
71
|
* ]
|
|
71
72
|
* ```
|
|
72
73
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
74
|
+
* ID e classi possono essere indicati come chiavi di primo livello dell'oggetto oppure dentro l'oggetto `attrs`.
|
|
75
|
+
* Quando sono presenti entrambi, le proprietà di primo livello hanno la precedenza.
|
|
75
76
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
77
|
+
* È disponibile anche una sintassi abbreviata a stringa, costruita secondo le convenzioni di `parseDomString`.
|
|
78
|
+
* Vedi `parseDomString` per i dettagli.
|
|
78
79
|
*
|
|
79
|
-
*
|
|
80
|
+
* La sintassi abbreviata non supporta `content`, `callback`, `condition` o `children`; per questi usare la sintassi a oggetto.
|
|
80
81
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* (className, callback,
|
|
84
|
-
*
|
|
85
|
-
*
|
|
82
|
+
* La sintassi abbreviata può essere usata anche per la proprietà `tag` nella sintassi a oggetto.
|
|
83
|
+
* Quando `tag` è un array, ogni elemento diventa il genitore del successivo. Tutte le altre proprietà dell'oggetto
|
|
84
|
+
* (className, callback, ecc.) vengono applicate solo all'ultimo elemento dell'array.
|
|
85
|
+
* Quando la stringa abbreviata e le proprietà a livello di oggetto sono in conflitto (classi, id o attributi),
|
|
86
|
+
* le proprietà a livello di oggetto hanno la precedenza.
|
|
86
87
|
*
|
|
87
88
|
* @function domBuilder
|
|
88
|
-
* @param {Array<DomBuilderItem|string|Node>} [structureArray=[]] -
|
|
89
|
-
* - `tag` / `tagName` {string | string[]} -
|
|
90
|
-
* - `className` / `class` / `classname` {string | string[]} - CSS
|
|
91
|
-
* - `id` {string | null} -
|
|
92
|
-
* - `attrs` {[string, *] | [string, *][] | Object<string, *>} -
|
|
93
|
-
* - `content` {string | number | Function | Node | DomBuilderItem[] | null} -
|
|
94
|
-
* - `text` {string | number} -
|
|
95
|
-
* - `condition` {boolean} -
|
|
96
|
-
* - `callback` {(function(HTMLElement|Text): void) | null} -
|
|
97
|
-
* - `children` {Array<DomBuilderItem|string|Node>} -
|
|
89
|
+
* @param {Array<DomBuilderItem|string|Node>} [structureArray=[]] - Array di configurazione. Accetta stringhe (scorciatoia secondo `parseDomString`), oggetti di configurazione e/o `Node` (un `Element`, un `DocumentFragment`, ...) inseriti così come sono; ogni oggetto di configurazione supporta:
|
|
90
|
+
* - `tag` / `tagName` {string | string[]} - Nome del tag HTML, o array di tag annidati (ciascuno è il genitore del successivo). Default `'div'`.
|
|
91
|
+
* - `className` / `class` / `classname` {string | string[]} - Classe/i CSS: una singola stringa o un array (i valori falsy vengono scartati).
|
|
92
|
+
* - `id` {string | null} - ID univoco dell'elemento.
|
|
93
|
+
* - `attrs` {[string, *] | [string, *][] | Object<string, *>} - Attributi: una coppia `[name, value]`, un array di coppie o un oggetto `{name: value}`.
|
|
94
|
+
* - `content` {string | number | Function | Node | DomBuilderItem[] | null} - Contenuto dell'elemento. Una stringa/numero viene impostato come `textContent`, a meno che contenga `<`: in tal caso viene sanificato e inserito come markup (`Element.setHTML`, con ripiego su `innerHTML`). Un `Node` (`Element`, `DocumentFragment`, ...), passato direttamente o restituito da una funzione, viene aggiunto così com'è.
|
|
95
|
+
* - `text` {string | number} - Scorciatoia per un nodo di testo letterale: inserisce un nodo `Text` semplice (mai interpretato come markup) come fratello degli altri elementi, al posto di un elemento. Mutuamente esclusivo con `tag`/`content`/`children`.
|
|
96
|
+
* - `condition` {boolean} - Se false, l'elemento (o il nodo di testo) viene saltato. Default `true`.
|
|
97
|
+
* - `callback` {(function(HTMLElement|Text): void) | null} - Invocata dopo la creazione dell'elemento (o del nodo di testo).
|
|
98
|
+
* - `children` {Array<DomBuilderItem|string|Node>} - Array di configurazione degli elementi figli (stesso formato, annidato; accetta anche `Node` inseriti così come sono).
|
|
98
99
|
*
|
|
99
|
-
*
|
|
100
|
-
* @param {HTMLElement} [parent] -
|
|
101
|
-
* @param {Object} [options={}] -
|
|
102
|
-
* @param {boolean} [options.emptyParent=false] -
|
|
103
|
-
* @param {'append'|'prepend'|'before'|'after'} [options.insertMode='append'] -
|
|
104
|
-
* @param {boolean} [options.debug=false] -
|
|
105
|
-
* @returns {HTMLElement|null}
|
|
100
|
+
* ID e classi possono essere indicati come chiavi di primo livello dell'oggetto o dentro `attrs`; le proprietà di primo livello hanno la precedenza (default: [])
|
|
101
|
+
* @param {HTMLElement} [parent] - Elemento genitore a cui viene agganciata la struttura (vedi `options.insertMode`).
|
|
102
|
+
* @param {Object} [options={}] - Opzioni di configurazione (default: {})
|
|
103
|
+
* @param {boolean} [options.emptyParent=false] - Se true, l'elemento genitore viene svuotato prima della costruzione (default: false)
|
|
104
|
+
* @param {'append'|'prepend'|'before'|'after'} [options.insertMode='append'] - Come ogni elemento radice di `structureArray` viene agganciato a `parent`: `append` lo inserisce come ultimo figlio (default), `prepend` come primo figlio, `before`/`after` lo inseriscono come fratello precedente/successivo di `parent`. In ogni modalità l'ordine di `structureArray` viene mantenuto. Si applica solo agli elementi prodotti da questa chiamata — le chiamate annidate a `domBuilder` (`content`, `children`) fanno sempre append (default: 'append')
|
|
105
|
+
* @param {boolean} [options.debug=false] - Se true, scrive `structureArray` in console dopo che ogni elemento stringa è stato analizzato con `parseDomString` (cioè l'array elaborato effettivamente usato per costruire il DOM) (default: false)
|
|
106
|
+
* @returns {HTMLElement|null} Il primo elemento creato, oppure null se non è stato creato nulla.
|
|
106
107
|
*/
|
|
107
108
|
|
|
108
109
|
|
|
@@ -119,17 +120,19 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
119
120
|
parent.innerHTML = '';
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
/*
|
|
124
|
+
Per le modalità di inserimento 'append'/'prepend', i fratelli di primo livello vengono accumulati in un
|
|
125
|
+
DocumentFragment e agganciati a `parent` con un solo appendChild/insertBefore alla
|
|
126
|
+
fine, invece di una chiamata per fratello. Le modalità 'before'/'after' richiedono che `target` resti
|
|
127
|
+
il vero nodo genitore attivo per tutto il ciclo per la risoluzione dell'ancora (vedi afterAnchors
|
|
128
|
+
più sotto), quindi per queste il raggruppamento viene saltato.
|
|
129
|
+
*/
|
|
127
130
|
const useFragment = !!parent && (options.insertMode === 'append' || options.insertMode === 'prepend');
|
|
128
131
|
|
|
129
132
|
/** @type {HTMLElement | DocumentFragment | null} */
|
|
130
133
|
let target = useFragment ? document.createDocumentFragment() : (parent ?? null);
|
|
131
134
|
|
|
132
|
-
/** @type {Map<HTMLElement | DocumentFragment, Node>}
|
|
135
|
+
/** @type {Map<HTMLElement | DocumentFragment, Node>} tiene traccia, per `insertMode: 'after'`, dell'ultimo fratello inserito per ogni nodo genitore */
|
|
133
136
|
const afterAnchors = new Map();
|
|
134
137
|
|
|
135
138
|
/** @type {HTMLElement | null} */
|
|
@@ -144,8 +147,8 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
144
147
|
|
|
145
148
|
structureArray.forEach(inputItem => {
|
|
146
149
|
|
|
147
|
-
//
|
|
148
|
-
//
|
|
150
|
+
// Un Node DOM (Element, DocumentFragment, ...) passato direttamente: inserito così com'è,
|
|
151
|
+
// saltando del tutto la creazione dell'elemento e l'analisi della configurazione.
|
|
149
152
|
if (inputItem instanceof Node) {
|
|
150
153
|
|
|
151
154
|
elaboratedStructureArray.push(/** @type {DomBuilderItem} */ (/** @type {unknown} */ (inputItem)));
|
|
@@ -184,10 +187,10 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
184
187
|
|
|
185
188
|
if (item != null && (item.condition ?? true)) {
|
|
186
189
|
|
|
187
|
-
const safeItem = item; // const
|
|
190
|
+
const safeItem = item; // binding const così che TypeScript tracci il tipo non nullo nelle closure annidate
|
|
188
191
|
|
|
189
|
-
// `{ text: '...' }
|
|
190
|
-
//
|
|
192
|
+
// scorciatoia `{ text: '...' }`: un nodo Text letterale, mai interpretato come markup, inserito
|
|
193
|
+
// al posto di un elemento così da poter essere fratello dei tag negli array `children`/`content`
|
|
191
194
|
if (safeItem.tag == null && (typeof safeItem.text === 'string' || typeof safeItem.text === 'number')) {
|
|
192
195
|
|
|
193
196
|
const textNode = document.createTextNode(String(safeItem.text));
|
|
@@ -214,8 +217,8 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
214
217
|
return;
|
|
215
218
|
}
|
|
216
219
|
|
|
217
|
-
//
|
|
218
|
-
//
|
|
220
|
+
// quando tag è un array, crea una serie di elementi annidati;
|
|
221
|
+
// l'ultimo riceve le restanti proprietà dell'oggetto
|
|
219
222
|
if (Array.isArray(safeItem.tag)) {
|
|
220
223
|
|
|
221
224
|
grand_parent = target;
|
|
@@ -226,7 +229,7 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
226
229
|
const isLast = idx === tags.length - 1;
|
|
227
230
|
const parsedItem = parseDomString(tagItem) ?? { tag: 'div', id: undefined, className: '', attrs: {}, content: undefined };
|
|
228
231
|
|
|
229
|
-
//
|
|
232
|
+
// per l'ultimo elemento, unisce con le opzioni proprie dell'oggetto; le proprietà a livello di oggetto hanno la precedenza
|
|
230
233
|
if(isLast) {
|
|
231
234
|
safeItem.attrs = {...parsedItem.attrs ?? {}, ...safeItem.attrs ?? {}};
|
|
232
235
|
}
|
|
@@ -235,7 +238,7 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
235
238
|
{...parsedItem, ...(isLast ? safeItem : {})}
|
|
236
239
|
);
|
|
237
240
|
|
|
238
|
-
if (!isLast) { //
|
|
241
|
+
if (!isLast) { // l'ultimo elemento viene gestito dal percorso standard qui sotto
|
|
239
242
|
if (target) {
|
|
240
243
|
target.appendChild(el);
|
|
241
244
|
}
|
|
@@ -255,8 +258,8 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
255
258
|
if (safeItem.content != null) {
|
|
256
259
|
|
|
257
260
|
if (Array.isArray(safeItem.content)) {
|
|
258
|
-
//
|
|
259
|
-
//
|
|
261
|
+
// costruisce direttamente dentro `el` (invece di non passare alcun genitore) così che ogni elemento
|
|
262
|
+
// dell'array venga effettivamente inserito, non solo il primo restituito come `mainElement`
|
|
260
263
|
domBuilder(safeItem.content, el);
|
|
261
264
|
|
|
262
265
|
} else {
|
|
@@ -274,29 +277,29 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
274
277
|
}
|
|
275
278
|
|
|
276
279
|
if (content instanceof Node) {
|
|
277
|
-
// Element, DocumentFragment, Text, ...
|
|
278
|
-
//
|
|
280
|
+
// Element, DocumentFragment, Text, ... aggiunti così come sono (i figli di un
|
|
281
|
+
// DocumentFragment vengono spostati dentro `el`, svuotando il fragment, come da comportamento nativo del DOM)
|
|
279
282
|
el.appendChild(content);
|
|
280
283
|
|
|
281
284
|
} else if (content != null) {
|
|
282
285
|
|
|
283
286
|
if (!content.includes('<')) {
|
|
284
|
-
//
|
|
287
|
+
// testo semplice: non serve il parsing HTML, textContent è più veloce e sicuro per costruzione
|
|
285
288
|
el.textContent = content;
|
|
286
289
|
|
|
287
290
|
} else if (typeof el.setHTML === 'function') {
|
|
288
|
-
/* markup:
|
|
289
|
-
|
|
291
|
+
/* markup: sanifica tramite la Sanitizer API nativa, eliminando <script>, attributi
|
|
292
|
+
di gestione eventi, URL javascript:, ecc. pur consentendo i tag di formattazione innocui
|
|
290
293
|
(<strong>, <em>, <a>, ...).
|
|
291
|
-
|
|
292
|
-
baseline:
|
|
293
|
-
`style`
|
|
294
|
-
|
|
294
|
+
La configurazione vuota del sanitizer mantiene ogni elemento/attributo che non rientra nella
|
|
295
|
+
baseline non sicura integrata: senza di essa la configurazione predefinita del browser rimuove anche
|
|
296
|
+
gli attributi `class`, `id`, `style` e `data-*` (osservato in Chrome 152), rompendo qualsiasi
|
|
297
|
+
stringa di markup che si affidi alle classi CSS */
|
|
295
298
|
el.setHTML(content, { sanitizer: {} });
|
|
296
299
|
|
|
297
300
|
} else {
|
|
298
|
-
// Sanitizer API
|
|
299
|
-
//
|
|
301
|
+
// Sanitizer API non supportata da questo browser: ripiega sul comportamento storico,
|
|
302
|
+
// non sanificato
|
|
300
303
|
el.innerHTML = content;
|
|
301
304
|
}
|
|
302
305
|
}
|
|
@@ -331,7 +334,7 @@ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ stru
|
|
|
331
334
|
}
|
|
332
335
|
}
|
|
333
336
|
|
|
334
|
-
// TODO
|
|
337
|
+
// TODO le callback che agiscono sui figli dell'elemento potrebbero non essere eseguite quando non è impostato alcun parent
|
|
335
338
|
if (safeItem.callback && typeof safeItem.callback === 'function') {
|
|
336
339
|
safeItem.callback(el);
|
|
337
340
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
//
|
|
3
|
-
//
|
|
2
|
+
// gli attributi booleani vengono omessi quando il loro valore è esplicitamente false;
|
|
3
|
+
// dichiarati una sola volta a livello di modulo (Set per lookup O(1)) dato che l'elenco non cambia tra le chiamate
|
|
4
4
|
const boolAttrs = new Set([
|
|
5
5
|
'allowfullscreen',
|
|
6
6
|
'async',
|
|
@@ -33,14 +33,14 @@ const boolAttrs = new Set([
|
|
|
33
33
|
]);
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @param {HTMLElement} element -
|
|
38
|
-
* @param {DomBuilderItem} domBuilderItem -
|
|
36
|
+
* Applica a un elemento la configurazione di base di domBuilder: classi, id e attributi.
|
|
37
|
+
* @param {HTMLElement} element - L'elemento da configurare.
|
|
38
|
+
* @param {DomBuilderItem} domBuilderItem - L'oggetto di configurazione di domBuilder.
|
|
39
39
|
* @returns {HTMLElement}
|
|
40
40
|
*/
|
|
41
41
|
export function domBuilderBasicSetup (element, domBuilderItem) {
|
|
42
42
|
|
|
43
|
-
//
|
|
43
|
+
// alias delle classi: accetta `class` e `classname`; `className` ha la precedenza su entrambi
|
|
44
44
|
if (domBuilderItem.class && !domBuilderItem.className) {
|
|
45
45
|
domBuilderItem.className = domBuilderItem.class;
|
|
46
46
|
}
|
|
@@ -48,11 +48,11 @@ export function domBuilderBasicSetup (element, domBuilderItem) {
|
|
|
48
48
|
domBuilderItem.className = domBuilderItem.classname;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
//
|
|
51
|
+
// normalizza attrs: un singolo array piatto viene trattato come una singola coppia [name, value]
|
|
52
52
|
if (domBuilderItem.attrs && Array.isArray(domBuilderItem.attrs) && !Array.isArray(domBuilderItem.attrs[0])) {
|
|
53
53
|
domBuilderItem.attrs = [ domBuilderItem.attrs ];
|
|
54
54
|
|
|
55
|
-
// attrs
|
|
55
|
+
// attrs può essere anche un oggetto semplice: {attr_name: attr_value}
|
|
56
56
|
} else if (typeof domBuilderItem.attrs === 'object' && !Array.isArray(domBuilderItem.attrs) && domBuilderItem.attrs !== null) {
|
|
57
57
|
domBuilderItem.attrs = Object.entries(domBuilderItem.attrs);
|
|
58
58
|
}
|
|
@@ -63,7 +63,7 @@ export function domBuilderBasicSetup (element, domBuilderItem) {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
//
|
|
66
|
+
// assegna classi e id dopo attrs così che le proprietà a livello di oggetto abbiano la precedenza
|
|
67
67
|
if(domBuilderItem.className) {
|
|
68
68
|
element.className = Array.isArray(domBuilderItem.className)
|
|
69
69
|
? domBuilderItem.className.filter(Boolean).join(' ')
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
//
|
|
1
|
+
// compilato una sola volta al caricamento del modulo, dato che il pattern non cambia tra le chiamate
|
|
2
2
|
const DOM_STRING_REGEX = new RegExp(
|
|
3
|
-
/^([a-zA-Z][a-zA-Z0-9-]*)?/.source + // tag (
|
|
4
|
-
/((?:[#.][a-zA-Z0-9_-]+)*)?/.source + // id
|
|
5
|
-
/([([{].*?[)\]}])?/.source + //
|
|
6
|
-
/(?: +(.*))?$/.source //
|
|
3
|
+
/^([a-zA-Z][a-zA-Z0-9-]*)?/.source + // tag (accetta anche i nomi dei web component)
|
|
4
|
+
/((?:[#.][a-zA-Z0-9_-]+)*)?/.source + // id e classi, in qualsiasi ordine
|
|
5
|
+
/([([{].*?[)\]}])?/.source + // attributi
|
|
6
|
+
/(?: +(.*))?$/.source // contenuto
|
|
7
7
|
);
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Analizza una stringa per estrarne nome del tag, ID, classi e attributi.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Formato atteso della stringa:
|
|
13
13
|
*
|
|
14
14
|
* `tag#id.class1.class2.classN(attr1: val1, attr2=val2) text content`
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* * `tag`
|
|
18
|
-
* * `#id`
|
|
19
|
-
* * `.class1, .class2...`
|
|
20
|
-
* * `#id`
|
|
21
|
-
* * `(...)`
|
|
22
|
-
*
|
|
23
|
-
* *
|
|
16
|
+
* Dove:
|
|
17
|
+
* * `tag` è il nome dell'elemento; se omesso vale `div`
|
|
18
|
+
* * `#id` è l'id opzionale dell'elemento, preceduto da `#`
|
|
19
|
+
* * `.class1, .class2...` sono classi CSS opzionali, ciascuna preceduta da `.`
|
|
20
|
+
* * i token `#id` e `.class` possono comparire in qualsiasi ordine e alternati (es. `.class1#id.class2`)
|
|
21
|
+
* * `(...)` è il blocco opzionale degli attributi; si possono usare anche `[...]` o `{...}`.
|
|
22
|
+
* Ogni coppia nome–valore è separata da `:` o `=`. Un nome senza valore vale `true`.
|
|
23
|
+
* * Il contenuto testuale segue dopo uno spazio
|
|
24
24
|
*
|
|
25
|
-
*
|
|
25
|
+
* Restituisce un oggetto figlio di domBuilder.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
27
|
+
* Esempi:
|
|
28
28
|
* > p#main-info.info.active{data-id:123,role=button} text content
|
|
29
29
|
*
|
|
30
30
|
* > input#search-field[type=text,disabled]
|
|
31
31
|
*
|
|
32
|
-
* @param {string} domString -
|
|
32
|
+
* @param {string} domString - La stringa domBuilder da analizzare.
|
|
33
33
|
* @returns {{tag: string, id: string|null, className: string, attrs: Object<string, string|true>, content: string|null}|null}
|
|
34
34
|
*/
|
|
35
35
|
export function parseDomString(domString) {
|
|
@@ -41,12 +41,12 @@ export function parseDomString(domString) {
|
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
//
|
|
45
|
-
// [0]:
|
|
44
|
+
// Indici dei gruppi di cattura:
|
|
45
|
+
// [0]: corrispondenza completa
|
|
46
46
|
// [1]: tag
|
|
47
|
-
// [2]: id
|
|
48
|
-
// [3]:
|
|
49
|
-
// [4]:
|
|
47
|
+
// [2]: id e classi (es. "#id.class1.class2" oppure ".class1#id.class2")
|
|
48
|
+
// [3]: attributi grezzi
|
|
49
|
+
// [4]: contenuto
|
|
50
50
|
|
|
51
51
|
const idAndClasses = matches[2] || '',
|
|
52
52
|
idMatch = idAndClasses.match(/#([a-zA-Z0-9_-]+)/),
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Raccolta di helper per costruire tag di base.
|
|
2
|
+
Tutte le funzioni restituiscono un array/oggetto domBuilder
|