Aplicar pendientes tras la integración

- render.js: botones y cards con urlBloqueada se pintan inertes.
- interactivity.js: sinFormato con la misma regla de marcadores que render.js; cita de documento con icono y nombre.
- Zoom manual (Ajustar / 100 % / 125 %) en #barra-movil, persistido en localStorage.
- Contador «Paso N/M» con estilo en iphone.css en lugar de estilos en línea.
- store/editor: campos opcionales tamano y headerTamano; editar la URL retira urlBloqueada;
  urlValida acepta URLs con forma de dominio; importar avisa de lo recortado.
- README y SPEC actualizados.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
urieljareth
2026-09-27 21:39:09 -06:00
co-authored by Claude Opus 5.5
parent a645056c00
commit 4fe8f73959
11 changed files with 136 additions and 28 deletions
+18 -3
View File
@@ -450,7 +450,10 @@
if (obj[k] === null || obj[k] === undefined) obj[k] = /^\d+$/.test(partes[i + 1]) ? [] : {};
obj = obj[k];
}
obj[partes[partes.length - 1]] = valor;
var clave = partes[partes.length - 1];
obj[clave] = valor;
// Editar la URL a mano retira la marca de enlace bloqueado (store.js)
if (clave === "url" && obj.urlBloqueada) delete obj.urlBloqueada;
if (typeof WAM.guardar === "function") WAM.guardar();
marcarEditado();
if (opts && opts.diferido) { programarRender(String(ruta)); return; }
@@ -978,6 +981,8 @@
} finally {
WAM.estado = previo;
}
// Se lee ya: cualquier normalización posterior sobrescribe el resumen
var recortes = typeof WAM.describirRecortes === "function" && datos ? WAM.describirRecortes(datos.__recortes) : "";
if (!datos || !Array.isArray(datos.mensajes)) throw new Error("sin mensajes");
snap();
WAM.estado = datos;
@@ -992,7 +997,7 @@
if (typeof WAM.render === "function") WAM.render();
WAM.renderEditor();
var n = WAM.estado.mensajes.length;
WAM.toast("Demo importada: " + n + " mensaje" + (n === 1 ? "" : "s"),
WAM.toast(recortes ? recortes + "." : "Demo importada: " + n + " mensaje" + (n === 1 ? "" : "s"),
typeof WAM.deshacer === "function" ? { accion: { texto: "Deshacer", fn: WAM.deshacer }, ms: 8000 } : null);
var primero = listaNodo() && listaNodo().querySelector(".ed-cab-principal");
if (primero) primero.focus();
@@ -1038,7 +1043,13 @@
------------------------------------------------------------------ */
function largo(v) { return String(v === undefined || v === null ? "" : v).length; }
function vacioTxt(v) { return !String(v === undefined || v === null ? "" : v).trim(); }
function urlValida(v) { return /^https?:\/\/[^\s/$.?#][^\s]*$/i.test(String(v || "").trim()); }
// Con esquema http(s) o con forma de dominio («www.cafe.com», «cafe.com/menu»):
// render.js abre estas últimas con https://, igual que WhatsApp.
function urlValida(v) {
var s = String(v || "").trim();
return /^https?:\/\/[^\s/$.?#][^\s]*$/i.test(s) ||
/^www\.[^\s]+$/i.test(s) || /^[\w-]+(\.[\w-]+)+(:\d+)?([\/?#][^\s]*)?$/.test(s);
}
// Botón de llamada de plantilla: tel: con al menos 3 dígitos (espacios, guiones y paréntesis permitidos)
function telValido(v) {
var s = String(v || "").trim();
@@ -1716,6 +1727,9 @@
caja.appendChild(edCampo("Nombre del documento (con extensión; define el icono)", ruta + ".headerTexto", m.headerTexto, {
max: 80, contar: true, placeholder: "catalogo.pdf", spell: false
}));
caja.appendChild(edCampo("Tamaño (opcional, p. ej. 243 KB)", ruta + ".headerTamano", m.headerTamano, {
max: 20, placeholder: "243 KB", spell: false
}));
}
caja.appendChild(edMedia("Media de cabecera", ruta + ".headerMedia", m.headerMedia, {
aceptar: tipo === "imagen" ? "image/*" : (tipo === "video" ? "video/*" : ""),
@@ -1801,6 +1815,7 @@
break;
case "document":
ap(edCampo("Nombre de archivo (con extensión; define el icono)", ruta + ".filename", m.filename, { max: 80, contar: true, placeholder: "menu.pdf" }));
ap(edCampo("Tamaño (opcional, p. ej. 243 KB)", ruta + ".tamano", m.tamano, { max: 20, placeholder: "243 KB", spell: false }));
ap(edTextarea("Caption (opcional)", ruta + ".caption", m.caption, { limite: 1024 }));
ap(edMedia("Archivo (opcional, no se muestra)", ruta + ".src", m.src, { tipoMedia: "doc", textoDrop: "Clic o arrastra un documento aquí" }));
break;