UNPKG

@designliquido/foles

Version:

Linguagem de folhas de estilo para documentos em geral em português

183 lines 8.41 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Resolvedor = void 0; const gerais_1 = require("../modificadores/atributos/gerais"); const seletores_1 = require("../seletores"); const seletor_espaco_reservado_1 = require("../seletores/seletor-espaco-reservado"); const metodo_1 = require("../valores/metodos/foles/metodo"); const estruturas_html_1 = __importDefault(require("../tradutores/estruturas-html")); const valores_1 = require("../valores"); const referencia_variavel_1 = require("../valores/referencia-variavel"); /** * A classe que efetivamente traduz FolEs para CSS. * * Normalmente o CSS traduzido é desaninhado por uma questão de compatibilidade * entre navegadores. Até então, CSS aninhado é uma funcionalidade nova, e * apenas navegadores mais recentes a implementam. */ class Resolvedor { constructor(resolverComAninhamentos = false) { this.resolverComAninhamentos = resolverComAninhamentos; this.variaveis = {}; } resolverValor(valor, valoresAceitos) { switch (valor.constructor) { case referencia_variavel_1.ReferenciaVariavel: const valorReferenciaVariavel = valor; const valoresVariavelCorrespondente = this.variaveis[valorReferenciaVariavel.nomeVariavel]; if (valoresVariavelCorrespondente === undefined) { throw new Error(`A variável '${valorReferenciaVariavel.nomeVariavel}' deve ser declarada antes da atribuição de valor.`); } let valoresVariavelResolvidos = ""; for (const valorVariavel of valoresVariavelCorrespondente) { const valorResolvido = this.resolverValor(valorVariavel); if (valorResolvido === ",") { valoresVariavelResolvidos = valoresVariavelResolvidos.slice(0, -1); } valoresVariavelResolvidos += valorResolvido + " "; } valoresVariavelResolvidos = valoresVariavelResolvidos.slice(0, -1); return valoresVariavelResolvidos; case valores_1.ValorAbreviacao: return "/"; case valores_1.ValorNumerico: const valorNumerico = valor; let literalNumerico = String(valorNumerico.literalNumerico); if ((valorNumerico.quantificador) && (valorNumerico.literalNumerico < 1 && valorNumerico.literalNumerico > 0)) { literalNumerico = literalNumerico.replace(/^0\./, '.'); } return `${literalNumerico}${valorNumerico.quantificador || ''}`; case valores_1.ValorQualitativo: const valorQualitativo = valor; let traducaoQualitativo = gerais_1.valoresGerais[valorQualitativo.qualitativo]; if (!traducaoQualitativo) traducaoQualitativo = valoresAceitos[valorQualitativo.qualitativo]; if (!traducaoQualitativo) traducaoQualitativo = valorQualitativo.qualitativo; return `${traducaoQualitativo}`; case valores_1.ValorTexto: const valorTexto = valor; return valorTexto.literalTexto; case valores_1.ValorVirgula: return ","; default: // Valor é RGB, RGBA, HSL, HSLA ou HEX, ou seja, um método. if (valor instanceof metodo_1.Metodo) { return valor.paraTexto(); } throw new Error(JSON.stringify(valor) + " não é um valor válido para resolução."); } } resolverModificador(modificador, indentacao = 0) { let valoresTraduzidos = ""; for (const valor of modificador.valores) { let valoresAceitos = null; if (modificador.valoresAceitos) valoresAceitos = modificador.valoresAceitos; const valorResolvido = this.resolverValor(valor, valoresAceitos); if (valorResolvido === ",") { valoresTraduzidos = valoresTraduzidos.slice(0, -1); } valoresTraduzidos += valorResolvido + " "; } valoresTraduzidos = valoresTraduzidos.slice(0, -1); return `${" ".repeat(indentacao)}${modificador.propriedadeCss}: ${valoresTraduzidos};\n`; } resolverBlocoDeclaracao(declaracao, indentacao, textoSeletorAnterior) { let resultado = ""; const prefixos = []; let deveImprimir = true; for (const seletor of declaracao.seletores) { // Espaços reservados não são escritos diretamente no CSS. if (seletor instanceof seletor_espaco_reservado_1.SeletorEspacoReservado) { deveImprimir = false; continue; } let prefixo; if (seletor instanceof seletores_1.SeletorEstrutura) { if (seletor.pseudoclasse) { const seletorLmht = seletor.paraTexto(); const seletorSemPseudoclasse = seletorLmht.split(":")[0]; const traducaoSeletor = estruturas_html_1.default[seletorSemPseudoclasse]; const traducaoPseudoclasse = seletor.pseudoclasse.pseudoclasseCss; prefixo = (textoSeletorAnterior + " " + `${traducaoSeletor}:${traducaoPseudoclasse}`).trimStart(); } else { const seletorLmht = seletor.paraTexto(); const traducaoSeletor = estruturas_html_1.default[seletorLmht]; prefixo = (textoSeletorAnterior + " " + traducaoSeletor).trimStart(); } } else { prefixo = (textoSeletorAnterior + " " + seletor.paraTexto()).trimStart(); } prefixos.push(prefixo); resultado += " ".repeat(indentacao) + prefixo + ", "; } if (!deveImprimir) { return resultado; } resultado = resultado.slice(0, -2); resultado += " {\n"; for (const modificador of declaracao.modificadores) { resultado += this.resolverModificador(modificador, indentacao + 4); } if (this.resolverComAninhamentos) { resultado += this.resolver(declaracao.declaracoesAninhadas, indentacao + 4); resultado += `${" ".repeat(indentacao)}}\n\n`; } else { resultado += `${" ".repeat(indentacao)}}\n\n`; for (const prefixo of prefixos) { resultado += this.resolver(declaracao.declaracoesAninhadas, indentacao, prefixo); } } return resultado; } /** * Esta função pode ter dois comportamentos, dependendo da configuração * do Resolvedor: * * - Acumula o valor da variável para ser usada por outras declarações; * - Escreve um `var()` no resultado. * @param declaracaoVariavel */ resolverDeclaracaoVariavel(declaracaoVariavel) { this.variaveis[declaracaoVariavel.nome] = declaracaoVariavel.valores; } /** * O processo de tradução. É recursivo. * @param declaracoes As declaracoes. * @returns Uma string com o resultado da tradução. */ resolver(declaracoes, indentacao = 0, seletorAnterior = undefined) { let resultado = ""; let textoSeletorAnterior = ""; if (seletorAnterior !== undefined) { textoSeletorAnterior = seletorAnterior; } for (const declaracao of declaracoes) { switch (declaracao.constructor.name) { case "BlocoDeclaracao": resultado += this.resolverBlocoDeclaracao(declaracao, indentacao, textoSeletorAnterior); break; case "DeclaracaoVariavel": this.resolverDeclaracaoVariavel(declaracao); break; } } return resultado; } } exports.Resolvedor = Resolvedor; //# sourceMappingURL=resolvedor.js.map