No se encontraron protocolos.
* generarWord(protocolo, configuracion);
*/
// ════════════════════════════════════════════════════
// 1. MOTOR ZIP PURO EN JS
// ════════════════════════════════════════════════════
function crc32(data) {
let crc = 0xFFFFFFFF;
for (let i = 0; i < data.length; i++) {
crc ^= data[i];
for (let j = 0; j < 8; j++) crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
}
return (crc ^ 0xFFFFFFFF) >>> 0;
}
function strToBytes(str) {
return new TextEncoder().encode(str);
}
function concatBytes(arrays) {
const total = arrays.reduce((s, a) => s + a.length, 0);
const out = new Uint8Array(total);
let off = 0;
for (const a of arrays) { out.set(a, off); off += a.length; }
return out;
}
function writeUint16LE(buf, val, off) { buf[off] = val & 0xFF; buf[off+1] = (val >> 8) & 0xFF; }
function writeUint32LE(buf, val, off) {
buf[off] = val & 0xFF; buf[off+1] = (val>>8)&0xFF;
buf[off+2] = (val>>16)&0xFF; buf[off+3] = (val>>24)&0xFF;
}
function buildZip(files) {
const entries = [];
const centralDir = [];
let offset = 0;
for (const [name, content] of Object.entries(files)) {
const nameBytes = strToBytes(name);
const dataBytes = typeof content === 'string' ? strToBytes(content) : content;
const crc = crc32(dataBytes);
const lh = new Uint8Array(30 + nameBytes.length);
writeUint32LE(lh, 0x04034b50, 0);
writeUint16LE(lh, 20, 4);
writeUint16LE(lh, 0, 6);
writeUint16LE(lh, 0, 8);
writeUint16LE(lh, 0, 10);
writeUint16LE(lh, 0, 12);
writeUint32LE(lh, crc, 14);
writeUint32LE(lh, dataBytes.length, 18);
writeUint32LE(lh, dataBytes.length, 22);
writeUint16LE(lh, nameBytes.length, 26);
writeUint16LE(lh, 0, 28);
lh.set(nameBytes, 30);
const cd = new Uint8Array(46 + nameBytes.length);
writeUint32LE(cd, 0x02014b50, 0);
writeUint16LE(cd, 20, 4); writeUint16LE(cd, 20, 6);
writeUint16LE(cd, 0, 8); writeUint16LE(cd, 0, 10);
writeUint16LE(cd, 0, 12); writeUint16LE(cd, 0, 14);
writeUint32LE(cd, crc, 16);
writeUint32LE(cd, dataBytes.length, 20);
writeUint32LE(cd, dataBytes.length, 24);
writeUint16LE(cd, nameBytes.length, 28);
writeUint16LE(cd, 0, 30); writeUint16LE(cd, 0, 32);
writeUint16LE(cd, 0, 34); writeUint16LE(cd, 0, 36);
writeUint32LE(cd, 0, 38); writeUint32LE(cd, offset, 42);
cd.set(nameBytes, 46);
entries.push(lh, dataBytes);
centralDir.push(cd);
offset += lh.length + dataBytes.length;
}
const cdBytes = concatBytes(centralDir);
const eocd = new Uint8Array(22);
writeUint32LE(eocd, 0x06054b50, 0);
writeUint16LE(eocd, 0, 4); writeUint16LE(eocd, 0, 6);
writeUint16LE(eocd, Object.keys(files).length, 8);
writeUint16LE(eocd, Object.keys(files).length, 10);
writeUint32LE(eocd, cdBytes.length, 12);
writeUint32LE(eocd, offset, 16);
writeUint16LE(eocd, 0, 20);
return concatBytes([...entries, cdBytes, eocd]);
}
// ════════════════════════════════════════════════════
// 2. MOTOR XML DOCX
// ════════════════════════════════════════════════════
function x(s) {
return String(s || '').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');
}
function hexColor(h) {
return h.replace('#','').toUpperCase();
}
// Párrafo de texto justificado con narrativa
function pJust(text, sz=22, color='000000', bold=false, italic=false, spaceBefore=80, spaceAfter=100) {
return `
Normativa: ${p.normativa}
${p.alerta}
${sectHtml}
`;
list.appendChild(card);
});
updateGlobalStats();
}
renderAll();