mgpanel-cli 1.0.4 → 1.0.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.
Files changed (2) hide show
  1. package/bin/mgpanel.js +133 -2
  2. package/package.json +1 -1
package/bin/mgpanel.js CHANGED
@@ -400,6 +400,76 @@ Cuando despliegues el proyecto en MGPanel:
400
400
  3. El contenido puede ser editado desde el panel de administración
401
401
  4. La estructura de archivos se mantiene compatible
402
402
 
403
+ ### Importante: compatibilidad Local Preview vs MGPanel (Nube)
404
+
405
+ En *preview local* (⁠ dev/preview.js ⁠) cada módulo se inserta envuelto en un contenedor como:
406
+
407
+ \`\`\`html
408
+ <div data-mgpanel-module="header">...contenido del módulo...</div>
409
+ \`\`\`
410
+
411
+ En *MGPanel (nube)* el CMS puede renderizar el HTML del módulo *sin ese wrapper, y además el HTML puede inyectarse **después** de que el archivo JS del módulo ya fue cargado.
412
+
413
+ Por eso, en los módulos con JS, sigue estas reglas para que funcionen *tanto local como en nube*:
414
+
415
+ •⁠ ⁠*Seleccionar root con fallback*:
416
+ - Primero intenta ⁠ \`document.querySelector('[data-mgpanel-module="<modulo>"]')\` ⁠ (preview).
417
+ - Si no existe, busca el nodo real del módulo, por ejemplo ⁠ \`.mg-<modulo>\` ⁠ (nube).
418
+ •⁠ ⁠*Inicialización tardía (cloud-safe)*:
419
+ - No asumas que el HTML existe cuando corre el JS.
420
+ - Implementa retry + ⁠ \`MutationObserver\` ⁠, y escucha ⁠ \`DOMContentLoaded\` ⁠ / ⁠ \`load\` ⁠.
421
+ •⁠ ⁠*Evitar doble init*:
422
+ - Marca el nodo root con ⁠ \`dataset\` ⁠ (por ejemplo ⁠ \`data-mg-init="1"\` ⁠) para no registrar listeners dos veces.
423
+ •⁠ ⁠*Rutas de assets*:
424
+ - En SPAs y en nube, usa rutas absolutas: ⁠ \`src="/assets/Logo.png"\` ⁠ en vez de ⁠ \`assets/Logo.png\` ⁠.
425
+ •⁠ ⁠*No ocultar contenido sin JS*:
426
+ - Si usas animaciones por clase (ej. ⁠ \`data-mg-animate\` ⁠), asegúrate que el contenido no quede invisible si el JS no corre.
427
+
428
+ #### Plantilla recomendada para JS de módulos (cloud-safe)
429
+
430
+ \`\`\`js
431
+ (() => {
432
+ const MODULE = "header"; // cambia por el nombre del módulo
433
+
434
+ const findRoot = () => {
435
+ const wrapped = document.querySelector(\`[data-mgpanel-module="\${MODULE}"]\`);
436
+ if (wrapped) return wrapped;
437
+ return document.querySelector(\`.mg-\${MODULE}\`);
438
+ };
439
+
440
+ const init = (rootOrEl) => {
441
+ if (!rootOrEl) return false;
442
+ const el = rootOrEl.classList?.contains(\`mg-\${MODULE}\`)
443
+ ? rootOrEl
444
+ : rootOrEl.querySelector?.(\`.mg-\${MODULE}\`);
445
+ if (!el) return false;
446
+
447
+ if (el.dataset.mgInit === "1") return true;
448
+ el.dataset.mgInit = "1";
449
+
450
+ // ... tu lógica aquí ...
451
+ return true;
452
+ };
453
+
454
+ const tryInit = () => init(findRoot());
455
+ if (tryInit()) return;
456
+
457
+ let tries = 0;
458
+ const t = window.setInterval(() => {
459
+ tries += 1;
460
+ if (tryInit() || tries > 200) window.clearInterval(t); // ~10s
461
+ }, 50);
462
+
463
+ const mo = new MutationObserver(() => {
464
+ if (tryInit()) mo.disconnect();
465
+ });
466
+ mo.observe(document.documentElement, { childList: true, subtree: true });
467
+
468
+ window.addEventListener("DOMContentLoaded", tryInit, { once: true });
469
+ window.addEventListener("load", tryInit, { once: true });
470
+ })();
471
+ \`\`\`
472
+
403
473
  ## Consejos para IDEs
404
474
 
405
475
  - Los archivos \`page.json\` definen la configuración de cada página
@@ -471,6 +541,17 @@ Este archivo contiene información detallada sobre:
471
541
  └── index.html # Preview local
472
542
  \`\`\`
473
543
 
544
+ ## ✅ Nota importante (Local vs Nube)
545
+
546
+ En local, \`dev/preview.js\` envuelve módulos en un contenedor \`data-mgpanel-module="..."\`, pero en MGPanel (nube) ese wrapper puede **no existir** y los módulos pueden inyectarse **después** de que el JS ya cargó.
547
+
548
+ Por eso, al crear nuevos módulos con JavaScript:
549
+ - No asumas que el HTML existe en el momento de ejecución.
550
+ - Usa un patrón "cloud-safe" (retry + MutationObserver) y un selector con fallback (\`[data-mgpanel-module="x"]\` o \`.mg-x\`).
551
+ - Usa rutas absolutas para assets (\`/assets/...\`) para evitar problemas de routing.
552
+
553
+ Para más detalles, consulta la sección de compatibilidad en \`dev/config.md\`.
554
+
474
555
  ## 🔗 Más Información
475
556
 
476
557
  - **Documentación de desarrollo:** Ver \`dev/config.md\`
@@ -546,7 +627,7 @@ function cmdMakeModule(moduleName) {
546
627
  const jsPath = path.join(moduleDir, `${moduleName}.js`);
547
628
 
548
629
  const htmlContent = `<!-- Module: ${moduleName} -->
549
- <section class="${moduleName}">
630
+ <section class="${moduleName} mg-${moduleName}">
550
631
  <h2>${moduleName}</h2>
551
632
  <p>Módulo creado con MGPanel ✅</p>
552
633
  </section>
@@ -559,7 +640,57 @@ function cmdMakeModule(moduleName) {
559
640
  `;
560
641
 
561
642
  const jsContent = `// Module: ${moduleName}
562
- console.log("[MGPanel] Module loaded:", "${moduleName}");
643
+ // Patrón cloud-safe: funciona tanto en preview local como en MGPanel (nube)
644
+
645
+ (() => {
646
+ const MODULE = "${moduleName}";
647
+
648
+ // Busca el root del módulo con fallback (local vs nube)
649
+ const findRoot = () => {
650
+ const wrapped = document.querySelector(\`[data-mgpanel-module="\${MODULE}"]\`);
651
+ if (wrapped) return wrapped;
652
+ return document.querySelector(\`.mg-\${MODULE}\`);
653
+ };
654
+
655
+ // Inicializa el módulo
656
+ const init = (rootOrEl) => {
657
+ if (!rootOrEl) return false;
658
+ const el = rootOrEl.classList?.contains(\`mg-\${MODULE}\`)
659
+ ? rootOrEl
660
+ : rootOrEl.querySelector?.(\`.mg-\${MODULE}\`);
661
+ if (!el) return false;
662
+
663
+ // Evitar doble inicialización
664
+ if (el.dataset.mgInit === "1") return true;
665
+ el.dataset.mgInit = "1";
666
+
667
+ // ... tu lógica aquí ...
668
+ console.log("[MGPanel] Module initialized:", MODULE);
669
+
670
+ return true;
671
+ };
672
+
673
+ // Intenta inicializar inmediatamente
674
+ const tryInit = () => init(findRoot());
675
+ if (tryInit()) return;
676
+
677
+ // Retry con intervalo (hasta ~10 segundos)
678
+ let tries = 0;
679
+ const intervalId = window.setInterval(() => {
680
+ tries += 1;
681
+ if (tryInit() || tries > 200) window.clearInterval(intervalId);
682
+ }, 50);
683
+
684
+ // Observar cambios en el DOM (para inyección tardía)
685
+ const mo = new MutationObserver(() => {
686
+ if (tryInit()) mo.disconnect();
687
+ });
688
+ mo.observe(document.documentElement, { childList: true, subtree: true });
689
+
690
+ // Escuchar eventos de carga
691
+ window.addEventListener("DOMContentLoaded", tryInit, { once: true });
692
+ window.addEventListener("load", tryInit, { once: true });
693
+ })();
563
694
  `;
564
695
 
565
696
  const created = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mgpanel-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "MGPanel CLI",
5
5
  "bin": {
6
6
  "mgpanel": "./bin/mgpanel.js"