Mapeate = function(entradas){ const self = this, configuracion_por_defecto = { nulos : false, valor_por_defecto : null, autoiniciar : true, archivos_de_configuracion_por_defecto : [ "/json/Mapeate.configuracion.json", "/json/Mapeate.configuracion.secretos.json" ], texto_por_defecto : "", configuracion_sobreescribir : false, i18n_sobreescribir : false, formato_terminal : "[{tipo}] {yyyy}{mm}{dd} {hh}{ii}{ss}: {mensaje}", terminal_tipos_por_defecto : [ ["unkn", "unknown", "desconocido"], [" ok ", "ok", "si", "correcto"], ["warn", "warning", "aviso", "advertencia"], ["erro", "error", "incrrecto"], ["fail", "failure", "fallo"], ["exce", "excepcion"] ] }, configuracion = {}, textos = {}, terminal_tipos = []; let iniciado = false, configuracion_sobreescribir = false, idioma_por_defecto = null, idioma = null, formato_terminal = "[{tipo}] {yyyy}{mm}{dd} {hh}{ii}{ss}: {mensaje}"; const constructor = () => { configuracion_por_defecto.terminal_tipos_por_defecto.forEach(entrada => terminal_tipos.push(entrada)); self.configuracion("autoiniciar") && self.iniciar(); }; const establecer_variables_comunes = () => { configuracion_sobreescribir = self.configuracion(["configuracion_sobreescribir", "sobreescribir"]); formato_terminal = self.configuracion("formato_terminal"); } this.iniciar = callback => { const terminar = estado => typeof callback == "function" && terminar(estado); if(iniciado){ terminar(false); return false; }; iniciado = true; establecer_variables_comunes(); self.configuracion_anadir(self.configuracion("archivos_de_configuracion_por_defecto"), null, () => { establecer_variables_comunes(); self.configuracion_anadir(self.configuracion("archivos_de_configuracion"), null, () => { establecer_variables_comunes(); self.terminal_tipos_anadir(self.configuracion("terminal_tipos_por_defecto"), () => { self.terminal_tipos_anadir(self.configuracion("terminal_tipos"), () => { i18n_sobreescribir = self.configuracion(["i18n_sobreescribir", "sobreescribir"]); idioma_por_defecto = self.configuracion(["idioma_por_defecto", "idioma"]); idioma = self.configuracion(["idioma", "idioma_por_defecto"]); self.i18n_anadir(self.configuracion("archivos_de_i18n_por_defecto"), null, () => { self.i18n_anadir(self.configuracion("archivos_de_i18n"), null,() => { terminar(true); console.log("PASA"); }); }); }); }); }); }); return true; }; this.nulos = nulos => typeof nulos != "boolean" ? self.configuracion("nulos", null, false, false) : nulos; this.valor_por_defecto = (valor_por_defecto, nulos) => ( valor_por_defecto !== undefined && (self.nulos(nulos) || valor_por_defecto !== null) ? valor_por_defecto : self.configuracion("valor_por_defecto", null, null, true) ); this.coger_array_de_diccionarios = valor => valor && typeof valor == "object" ? valor instanceof Array ? valor : [valor] : []; this.coger_array_de_strings = valor => ( valor && typeof valor == "object" && valor instanceof Array ? valor : [valor] ).filter(elemento => typeof elemento == "string" && elemento.trim()).map(elemento => elemento.trim()); this.configuracion = (claves, entradas, valor_por_defecto, nulos) => { const m = (claves = self.coger_array_de_strings(claves)).length; if(m){ const l = (entradas = [].concat( self.coger_array_de_diccionarios(entradas), [entradas, configuracion, configuracion_por_defecto] )).length; nulos = self.nulos(nulos); for(let i = 0; i < l; i ++) if(entradas[i] && typeof entradas[i] == "object") for(let j = 0; j < m; j ++) if(entradas[i][claves[j]] !== undefined && (nulos || entradas[i][claves[j]] !== null)) return entradas[i][claves[j]]; }; return self.valor_por_defecto(valor_por_defecto, nulos); }; this.leer_archivo = (url, entradas) => { let terminado = false; const ajax = new XMLHttpRequest(), callback = self.configuracion("callback", typeof entradas == "function" ? (entradas = {callback : entradas}) : entradas && typeof entradas == "object" ? entradas : {}), timeout = self.configuracion(["ajax_timeout", "timeout"], entradas), terminar = codigo => ( !terminado && (terminado = true) && typeof callback == "function" && callback(ajax.responseText, ajax.status, ajax.readyState, codigo) ), fecha = Date.now(); ajax.open("get", url, true); ajax.timeout = timeout; ajax.onreadystatechange = () => { if(terminado) return; if(ajax.readyState == 4) terminar( (ajax.status >= 200 && ajax.status < 300) || [301, 302, 304].includes(ajax.status) ? "OK" : "HTTP_ERROR"); else if(Date.now() - fecha > timeout) terminar("TIMEOUT_FORZADO"); }; ajax.send(null); ajax.onabort = () => terminar("ABORTADO"); ajax.onerror = () => terminar("ERROR"); ajax.ontimeout = () => terminar("TIMEOUT"); return ajax; }; const configuracion_anadir = (entradas, sobreescribir, callback, i) => { if(i >= entradas.length){ callback(); return; }; const terminar = () => configuracion_anadir(entradas, sobreescribir, callback, i + 1); if(!entradas[i]){ terminar(); return; }; if(typeof entradas[i] == "object"){ if(entradas[i] instanceof Array) configuracion_anadir(entradas[i], sobreescribir, terminar, 0); else{ for(const clave in entradas[i]) if(sobreescribir || configuracion[clave] === undefined) configuracion[clave] = entradas[i][clave]; terminar(); }; }else if(typeof entradas[i] == "string"){ if(!(entradas[i] = entradas[i].trim())){ terminar(); return; }; let json; if(entradas[i].match(/^(\{(.|[\r\n])+\}|\[(.|[\r\n])+\])$/)){ try{ json = JSON.parse(entradas[i]); }catch(excepcion){}; if(json) configuracion_anadir(json instanceof Array ? json : [json], sobreescribir, terminar, 0); else terminar(); }else self.leer_archivo(entradas[i], salida => { try{ json = JSON.parse(salida); }catch(excepcion){}; if(json) configuracion_anadir(json instanceof Array ? json : [json], sobreescribir, terminar, 0); else terminar(); }); }else terminar(); }; this.configuracion_anadir = (entradas, sobreescribir, callback) => configuracion_anadir( entradas && typeof entradas == "object" && entradas instanceof Array ? entradas : [entradas], typeof sobreescribir == "boolean" ? sobreescribir : configuracion_sobreescribir, callback, 0 ); this.string_variables = (string, variables, por_defecto) => { const l = (variables = self.coger_array_de_diccionarios(variables)).length; return (string || "" + string).replace(/\{([^\{\}]+)\}/g, (crudo, clave) => { for(let i = 0; i < l; i ++) if(variables[i][clave] !== undefined) return variables[i][clave]; return por_defecto === undefined ? crudo : por_defecto; }); }; const i18n = (claves, por_defecto) => { const m = (claves = self.coger_array_de_strings(claves)).length, idiomas = [idioma_por_defecto, idioma].concat(Object.keys(textos)), l = idiomas.length; for(let i = 0; i < l; i ++) if(typeof idiomas[i] == "string" && textos[idiomas[i]]) for(let j = 0; j < m; j ++) if(idiomas[i][claves[j]] !== undefined) return idiomas[i][claves[j]]; return ( por_defecto !== undefined ? por_defecto : m ? claves[0] : self.configuracion("texto_por_defecto")); }; this.i18n = (claves, variables, por_defecto) => self.string_variables(i18n(claves, por_defecto), variables); const i18n_anadir = (entradas, sobreescribir, callback, i) => { if(i >= entradas.length){ typeof callback == "function" && callback(); return; }; const terminar = () => i18n_anadir(entradas, sobreescribir, callback, i + 1); if(!entradas[i]){ terminar(); return; }; if(typeof entradas[i] == "object"){ if(entradas[i] instanceof Array) i18n_anadir(entradas[i], sobreescribir, terminar, 0); else{ for(const lenguage in entradas[i]){ textos[lenguage] === undefined && (textos[lenguage] = {}); if(entradas[i][lenguage] && typeof entradas[i][lenguage] == "object") for(const clave in entradas[i][lenguage]) if(sobreescribir || textos[lenguage][clave] !== undefined) textos[lenguage][clave] = entradas[i][lenguage][clave]; }; terminar(); }; }else if(typeof entradas[i] == "string"){ if(!(entradas[i] = entradas[i].trim())){ terminar(); return; }; let json; if(entradas[i].match(/^(\{(.|[\r\n])+\}|\[(.|[\r\n])+\])$/)){ try{ json = JSON.parse(entradas[i]); }catch(excepcion){}; if(json) i18n_anadir(json instanceof Array ? json : [json], sobreescribir, terminar, 0); else terminar(); }else self.leer_archivo(entradas[i], salida => { try{ json = JSON.parse(salida); }catch(excepcion){}; if(json) i18n_anadir(json instanceof Array ? json : [json], sobreescribir, terminar, 0); else terminar(); }); }else terminar(); }; this.i18n_anadir = (entradas, sobreescribir, callback) => i18n_anadir( entradas && typeof entradas == "object" && entradas instanceof Array ? entradas : [entradas], typeof sobreescribir == "boolean" ? sobreescribir : i18n_sobreescribir, callback, 0 ); const terminal_tipos_anadir = (entradas, callback, i, clave) => { if(i > 10) return; if(!entradas || i >= entradas.length){ typeof callback == "function" && callback(); return; }; const terminar = () => terminal_tipos_anadir(entradas, callback, i + 1, clave); if(!entradas[i]){ terminar(); return; }; if(typeof entradas[i] == "string"){ if(/^[a-z0-9]+$/i.test(entradas[i])){ if(clave === undefined && !terminal_tipos.some((tipos, j) => tipos.includes(entradas[i]) && !isNaN(clave = j))){ clave = terminal_tipos.length; terminal_tipos.push([entradas[i]]); }else !terminal_tipos[clave].includes(entradas[i]) && terminal_tipos[clave].push(entradas[i]); terminar(); return; }; let json; if(/^(\[(.|[\r\n])+\])$/.test(entradas[i])){ try{ json = JSON.parse(entradas[i]); }catch(excepcion){}; if(json) terminal_tipos_anadir(json, terminar, 0, clave); else terminar(); }else self.leer_archivo(entradas[i], salida => { try{ json = JSON.parse(salida); }catch(excepcion){}; if(json) terminal_tipos_anadir(json, terminar, 0, clave); else terminar(); }); }else if(typeof entradas[i] == "object" && entradas[i] instanceof Array) terminal_tipos_anadir(entradas[i], terminar, 0); else terminar(); }; this.terminal_tipos_anadir = (entradas, callback) => terminal_tipos_anadir(entradas, callback, 0); this.print = (tipo, mensaje, variables) => { const fecha = new Date(), conjunto = { tipo_crudo : tipo, tipo : tipo.upperCase().substring(0, 4), i18n : mensaje, ...(typeof variables == "object" ? variables : {}) }; ["year", "month", "date", "hours", "minutes", "seconds"].forEach(clave => { const k = clave.substring(0, 1), valor = fecha["get" + (clave == "year" ? "FullYear" : k.toUpperCase() + clave.substring(1))](); conjunto[clave == "date" ? "day" : clave] = valor; conjunto[k] = valor; conjunto[k + k] = ("00" + valor).slice(-2); }); conjunto["yyyy"] = conjunto["year"]; conjunto.mensaje = self.i18n(mensaje, conjunto); console.log(self.string_variables(formato_terminal, conjunto)); }; constructor(); };