@massimo-cassandro/minimo 1.25.0 → 1.26.0

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.
@@ -139,6 +139,7 @@ safe_cat "${TEMPLATES_DIR}/_editorconfig" .editorconfig new
139
139
  safe_cat "${TEMPLATES_DIR}/_prettierrc" .prettierrc new
140
140
  safe_cat "${TEMPLATES_DIR}/_root_htaccess" "${FRONTEND_INSTALL_PATH}/_root_htaccess"
141
141
  safe_cat "${TEMPLATES_DIR}/_root_robots.txt" "${FRONTEND_INSTALL_PATH}/_root_robots.txt"
142
+ safe_cat "${TEMPLATES_DIR}/CLAUDE-frontend.md" "${FRONTEND_INSTALL_PATH}/CLAUDE.md"
142
143
 
143
144
  # jsconfig.json: sta SEMPRE nella root del progetto (è anche il file di
144
145
  # riferimento di vscode). I suoi path sono quindi relativi alla root: il
@@ -0,0 +1,13 @@
1
+ # CLAUDE.md - frontend
2
+
3
+ ## Contesto di dominio
4
+
5
+
6
+
7
+ ## Stile di lavoro
8
+
9
+ - Conferma la comprensione prima di agire su richieste ambigue
10
+ - Il progetto usa ES modules (import/export), evitare sioluzioni che utilizzano commonJs
11
+ - In linea di massima non proporre soluzioni che richiedano modifiche alla parte back-end, a meno che non sia esplicitamente richiesto
12
+ - nella chat evitare neologismi come parsare, committare ecc., usare i termini corrispondi in italiano o il termine originale in inglese dove non sia possibile un equivalente in italiano
13
+ - nei commenti su più righe preferire `/* ... */` piuttosto che ripetere `//` ad igni inizio riga
@@ -252,6 +252,19 @@ const config = {
252
252
  directory: path.join(__dirname, '/'),
253
253
  serveIndex: true
254
254
  },
255
+ /*
256
+ proxy: [
257
+ {
258
+ // /login, /logout (redirect Google) e /api/... (fetch AJAX) vanno
259
+ // inoltrati al server PHP reale (npm run "php server", vedi
260
+ // package.json e app/router.php), che webpack-dev-server non può
261
+ // eseguire da solo.
262
+ context: ['/api', '/login', '/logout'],
263
+ target: process.env.PHP_BASE_URL || 'http://localhost:8000'
264
+ }
265
+ ],
266
+ static: false,
267
+ */
255
268
  open: { app: { name: 'Google Chrome' } },
256
269
  compress: true,
257
270
  hot: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -25,7 +25,7 @@ import { parseDomString } from './parseDomString.js';
25
25
  * property except `condition` and `callback` is ignored.
26
26
  * @property {boolean} [condition=true] - When false, the element (or text node) is skipped.
27
27
  * @property {(function(HTMLElement|Text): void) | null} [callback] - Callback invoked after the element (or text node) is created.
28
- * @property {Array<DomBuilderItem|string>} [children] - Configuration array for child elements. Accepts strings (shorthand per `parseDomString`) and/or configuration objects.
28
+ * @property {Array<DomBuilderItem|string|Node>} [children] - Configuration array for child elements. Accepts strings (shorthand per `parseDomString`), configuration objects, and/or `Node`s (an `Element`, a `DocumentFragment`, ...) inserted as-is.
29
29
  */
30
30
 
31
31
  /**
@@ -85,7 +85,7 @@ import { parseDomString } from './parseDomString.js';
85
85
  * object-level properties take precedence.
86
86
  *
87
87
  * @function domBuilder
88
- * @param {Array<DomBuilderItem|string>} [structureArray=[]] - Configuration array. Accepts strings (shorthand per `parseDomString`) and/or configuration objects, each supporting:
88
+ * @param {Array<DomBuilderItem|string|Node>} [structureArray=[]] - Configuration array. Accepts strings (shorthand per `parseDomString`), configuration objects, and/or `Node`s (an `Element`, a `DocumentFragment`, ...) inserted as-is; each configuration object supports:
89
89
  * - `tag` / `tagName` {string | string[]} - HTML tag name, or array of nested tags (each is parent of the next). Default `'div'`.
90
90
  * - `className` / `class` / `classname` {string | string[]} - CSS class(es): a single string or an array (falsy values filtered out).
91
91
  * - `id` {string | null} - Unique element ID.
@@ -94,7 +94,7 @@ import { parseDomString } from './parseDomString.js';
94
94
  * - `text` {string | number} - Literal text node shorthand: inserts a plain `Text` node (never parsed as markup) as a sibling of other items, in place of an element. Mutually exclusive with `tag`/`content`/`children`.
95
95
  * - `condition` {boolean} - When false, the element (or text node) is skipped. Default `true`.
96
96
  * - `callback` {(function(HTMLElement|Text): void) | null} - Invoked after the element (or text node) is created.
97
- * - `children` {Array<DomBuilderItem|string>} - Configuration array for child elements (same format, nested).
97
+ * - `children` {Array<DomBuilderItem|string|Node>} - Configuration array for child elements (same format, nested; also accepts `Node`s inserted as-is).
98
98
  *
99
99
  * IDs and classes can be specified either as top-level object keys or inside `attrs`; top-level properties take precedence.
100
100
  * @param {HTMLElement} [parent] - Parent element the structure is attached to (see `options.insertMode`).
@@ -106,7 +106,7 @@ import { parseDomString } from './parseDomString.js';
106
106
  */
107
107
 
108
108
 
109
- export function domBuilder(structureArray = [], parent, options = {}) {
109
+ export function domBuilder(/** @type {Array<DomBuilderItem|string|Node>} */ structureArray = [], parent, options = {}) {
110
110
 
111
111
  options = {
112
112
  emptyParent: false,
@@ -144,6 +144,34 @@ export function domBuilder(structureArray = [], parent, options = {}) {
144
144
 
145
145
  structureArray.forEach(inputItem => {
146
146
 
147
+ // A DOM Node (Element, DocumentFragment, ...) passed directly: inserted as-is,
148
+ // bypassing element creation and config parsing entirely.
149
+ if (inputItem instanceof Node) {
150
+
151
+ elaboratedStructureArray.push(/** @type {DomBuilderItem} */ (/** @type {unknown} */ (inputItem)));
152
+
153
+ if (target) {
154
+ if (options.insertMode === 'before') {
155
+ const anchor = /** @type {HTMLElement} */ (target);
156
+ anchor.parentNode?.insertBefore(inputItem, anchor);
157
+
158
+ } else if (options.insertMode === 'after') {
159
+ const anchor = afterAnchors.get(/** @type {HTMLElement} */ (target)) ?? /** @type {HTMLElement} */ (target);
160
+ anchor.parentNode?.insertBefore(inputItem, anchor.nextSibling);
161
+ afterAnchors.set(/** @type {HTMLElement} */ (target), inputItem);
162
+
163
+ } else {
164
+ target.appendChild(inputItem);
165
+ }
166
+ }
167
+
168
+ if (mainElement == null && inputItem instanceof Element) {
169
+ mainElement = /** @type {HTMLElement} */ (inputItem);
170
+ }
171
+
172
+ return;
173
+ }
174
+
147
175
  /** @type {DomBuilderItem | null} */
148
176
  let item;
149
177
  if (inputItem != null && typeof inputItem === 'string' && inputItem !== '') {