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.
- package/bin/mgpanel.js +133 -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
|
-
|
|
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 = [];
|