@designliquido/foles
Version:
Linguagem de folhas de estilo para documentos em geral em português
183 lines • 8.41 kB
JavaScript
;
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