(function (I) { I.esc = function (s) { return String(s).replace(/&/g, '&').replace(//g, '>'); }; I.downloadBlob = function (blob, name) { const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = name; a.click(); URL.revokeObjectURL(a.href); }; I.dataUrlToBlob = function (dataUrl) { const parts = dataUrl.split(','); const mime = parts[0].match(/:(.*?);/)[1]; const bin = atob(parts[1]); const arr = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) arr[i] = bin.charCodeAt(i); return new Blob([arr], { type: mime }); }; I.readFileAsDataUrl = function (file) { return new Promise(resolve => { const fr = new FileReader(); fr.onload = () => resolve(fr.result); fr.readAsDataURL(file); }); }; I.formatDate = function (d) { if (!d || d.length !== 8) return d || '-'; return d.substring(6, 8) + '.' + d.substring(4, 6) + '.' + d.substring(0, 4); }; })(window.App.Infrastructure);