From 13a38dc12e917b00f5e51bdae4baf90c1eb61e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Italo=20Brand=C3=A3o?= Date: Fri, 20 Jan 2023 11:04:07 -0500 Subject: [PATCH] Visoes parciais (#17) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Corrigindo erro em bodyParser * adicionando testes para parcial * Criando rota teste * Corrigindo bug em PreprocessadorLmhtParciais * Recebendo xmlContent da classe PreprocessadorLmhtParciais * Implementando logica alternativa para resolução do problema --- infraestrutura/formatadores/index.ts | 69 ++++++++++++++++--- .../preprocessadores/lmht-parciais.ts | 61 ++++++++-------- infraestrutura/roteador/index.ts | 13 ++++ liquido.ts | 13 ++-- package.json | 2 + parciais/inicial.delegua | 0 rotas/mvc/teste/inicial.delegua | 3 + .../preprocessadores/lmht-parciais.test.ts | 46 +++++++------ visoes/mvc/teste/inicial.lmht | 14 ++++ visoes/parciais/cabecalho.lmht | 3 + .../parciais}/minha-parcial.lmht | 0 yarn.lock | 4 +- 12 files changed, 157 insertions(+), 71 deletions(-) create mode 100644 parciais/inicial.delegua create mode 100644 rotas/mvc/teste/inicial.delegua create mode 100644 visoes/mvc/teste/inicial.lmht create mode 100644 visoes/parciais/cabecalho.lmht rename {parciais => visoes/parciais}/minha-parcial.lmht (100%) diff --git a/infraestrutura/formatadores/index.ts b/infraestrutura/formatadores/index.ts index 264e8ab..d1221cc 100644 --- a/infraestrutura/formatadores/index.ts +++ b/infraestrutura/formatadores/index.ts @@ -1,21 +1,24 @@ -import * as caminho from 'path'; import * as sistemaDeArquivos from 'node:fs'; +import * as caminho from 'path'; import Handlebars from 'handlebars'; -import { ConversorLmht } from "@designliquido/lmht-js"; -import { PreprocessadorFolEs, PreprocessadorHandlebars } from '../preprocessadores'; +import { ConversorLmht } from '@designliquido/lmht-js'; +import { PreprocessadorFolEs, PreprocessadorHandlebars, PreprocessadorLmhtParciais } from '../preprocessadores'; export class FormatadorLmht { conversorLmht: ConversorLmht; diretorioBase: string; preprocessadorFolEs: PreprocessadorFolEs; preprocessadorHandlebars: PreprocessadorHandlebars; + preprocessadorLmhtParciais: PreprocessadorLmhtParciais; + private readonly regexParcial = /|><\/parcial>)/g; constructor(diretorioBase: string) { this.conversorLmht = new ConversorLmht(); this.preprocessadorFolEs = new PreprocessadorFolEs(); this.preprocessadorHandlebars = new PreprocessadorHandlebars(); + this.preprocessadorLmhtParciais = new PreprocessadorLmhtParciais(); this.diretorioBase = diretorioBase; } @@ -27,20 +30,23 @@ export class FormatadorLmht { * @returns O resultado das duas conversões. */ async formatar(caminhoRota: string, valores: any): Promise { - let visaoCorrespondente: string = caminho.join(this.diretorioBase, "visoes", caminhoRota, ".lmht"); - const diretorioOuArquivo = caminho.join(this.diretorioBase, "visoes", caminhoRota); + let visaoCorrespondente: string = caminho.join(this.diretorioBase, 'visoes', caminhoRota, '.lmht'); + const diretorioOuArquivo = caminho.join(this.diretorioBase, 'visoes', caminhoRota); if (sistemaDeArquivos.existsSync(diretorioOuArquivo)) { // É diretório - if (visaoCorrespondente.endsWith(caminho.sep + ".lmht")) { - visaoCorrespondente = visaoCorrespondente.replace(caminho.sep + ".lmht", caminho.sep + "inicial.lmht"); + if (visaoCorrespondente.endsWith(caminho.sep + '.lmht')) { + visaoCorrespondente = visaoCorrespondente.replace(caminho.sep + '.lmht', caminho.sep + 'inicial.lmht'); } - } else if (sistemaDeArquivos.existsSync(diretorioOuArquivo + ".lmht")) { + } else if (sistemaDeArquivos.existsSync(diretorioOuArquivo + '.lmht')) { // É arquivo - visaoCorrespondente = visaoCorrespondente.replace(caminho.sep + ".lmht", ".lmht"); + visaoCorrespondente = visaoCorrespondente.replace(caminho.sep + '.lmht', '.lmht'); } else { // Caminho não existe return Promise.reject( - `Visão correspondente à rota ${caminhoRota} não existe. Caminhos tentados: ${diretorioOuArquivo}, ${diretorioOuArquivo + ".lmht"}`); + `Visão correspondente à rota ${caminhoRota} não existe. Caminhos tentados: ${diretorioOuArquivo}, ${ + diretorioOuArquivo + '.lmht' + }` + ); } const arquivoBase: Buffer = sistemaDeArquivos.readFileSync(visaoCorrespondente); @@ -48,6 +54,25 @@ export class FormatadorLmht { let textoBase = conteudoDoArquivo; if (valores) { + // Preprocessamento: Parciais + const parciaisResolvidos: string[] = []; + let parciais: string[] = []; + if (this.verificaTagParcial(textoBase)) { + parciais = this.DevolveParciais(textoBase); + const textoParcial = parciais.map((parcial) => { + return `${parcial}`; + }); + textoParcial.map((parcial) => { + const result = this.preprocessadorLmhtParciais.processarParciais(parcial); + if (result instanceof Error) { + throw result; + } + parciaisResolvidos.push(result.conteudo); + }); + } + + textoBase = this.FormataTextoBase(textoBase, parciais, parciaisResolvidos); + // Preprocessamento: Handlebars textoBase = this.preprocessadorHandlebars.processar(textoBase); const template = Handlebars.compile(textoBase); @@ -59,4 +84,26 @@ export class FormatadorLmht { return await this.conversorLmht.converterPorTexto(textoBase); } -} \ No newline at end of file + + private FormataTextoBase( + textoBase: string, + listaDeParciais: Array, + parciaisResolvidos: Array + ): string { + for (let i = 0; i < listaDeParciais.length; i++) { + textoBase = textoBase.replace(listaDeParciais[i], parciaisResolvidos[i]); + } + return textoBase; + } + + private DevolveParciais(textoLmht: string): string[] { + return textoLmht.match(this.regexParcial).map((parcial) => { + return parcial.toString(); + }); + } + + private verificaTagParcial(textoLmht: string): boolean { + const matches = textoLmht.match(this.regexParcial); + return matches?.length > 0 ? true : false; + } +} diff --git a/infraestrutura/preprocessadores/lmht-parciais.ts b/infraestrutura/preprocessadores/lmht-parciais.ts index cb30114..59ef868 100644 --- a/infraestrutura/preprocessadores/lmht-parciais.ts +++ b/infraestrutura/preprocessadores/lmht-parciais.ts @@ -1,17 +1,17 @@ -import { XMLBuilder, XMLParser } from "fast-xml-parser"; +import { XMLBuilder, XMLParser } from 'fast-xml-parser'; import * as fs from 'fs'; -import path from "path"; +import path from 'path'; export class PreprocessadorLmhtParciais { private readonly leitorLmht: XMLParser; - private readonly construtorLmht: XMLBuilder - private readonly DiretorioParcial = "parciais"; + private readonly construtorLmht: XMLBuilder; + private readonly DiretorioParcial = 'visoes/parciais'; private readonly DiretorioRaizCaminho = process.cwd(); private readonly opcoesLeitorLmht = { ignoreAttributes: false, - attributeNamePrefix : "" - } + attributeNamePrefix: '' + }; constructor() { this.leitorLmht = new XMLParser(this.opcoesLeitorLmht); @@ -22,19 +22,19 @@ export class PreprocessadorLmhtParciais { return this.DiretorioParcial; } - public processarParciais(texto: string): string | Error { + public processarParciais(texto: string) { const objetoVisao = this.leitorLmht.parse(texto); const corpo = objetoVisao.lmht?.corpo; - if (corpo || corpo === "") { - if (corpo.parcial || corpo.parcial === "") { + if (corpo || corpo === '') { + if (corpo.parcial || corpo.parcial === '') { const parcial = corpo.parcial; if (!parcial.nome) { - return new Error("Em Parcial o atributo nome não foi informado"); + return new Error('Em Parcial o atributo nome não foi informado'); } - parcial.nome = `${parcial.nome}.lmht` + parcial.nome = `${parcial.nome}.lmht`; if (!this.buscaDiretorioOuArquivo(this.DiretorioParcialGetter)) { return new Error(`O diretorio ${this.DiretorioParcialGetter} não foi encontrado`); @@ -46,53 +46,56 @@ export class PreprocessadorLmhtParciais { const caminho = path.join(this.DiretorioRaizCaminho, this.DiretorioParcialGetter, parcial.nome); - const xmlContent = this.construtorLmht.build(this.ConteudoDoArquivoParcial(caminho)); + const conteudo = this.ConteudoDoArquivoParcial(caminho); + + if (conteudo instanceof Error) { + return conteudo; + } - return xmlContent; + const xmlContent = this.construtorLmht.build(conteudo); + return { xmlContent, conteudo }; } - return new Error("Não foi encontrado a tag parcial") + return new Error('Não foi encontrado a tag parcial'); } - return new Error("Não foi encontrado a tag corpo") + return new Error('Não foi encontrado a tag corpo'); } private ConteudoDoArquivoParcial(caminho: string): string | Error { - let conteudo: string = ""; + let conteudo: string = ''; try { conteudo = fs.readFileSync(caminho, 'utf8'); - } catch(err) { + } catch (err) { return new Error(err); } return conteudo; } - private buscaDiretorioOuArquivo(directory: string, file?: string) { + private buscaDiretorioOuArquivo(directory: string, file?: string) { let files: string[] = []; if (!file) { if (!fs.existsSync(directory)) { - return false + return false; } - return true + return true; } try { - files = fs.readdirSync(path.join(this.DiretorioRaizCaminho, directory)) + files = fs.readdirSync(path.join(this.DiretorioRaizCaminho, directory)); - if(file) { - files = files.filter(f => f.includes(file)); + if (file) { + files = files.filter((f) => f.includes(file)); } } catch (err) { console.error(err); - return false + return false; } if (files.length === 0) { - return false + return false; } - return true + return true; } - - -} \ No newline at end of file +} diff --git a/infraestrutura/roteador/index.ts b/infraestrutura/roteador/index.ts index 1fe9c22..be4f64d 100644 --- a/infraestrutura/roteador/index.ts +++ b/infraestrutura/roteador/index.ts @@ -1,3 +1,4 @@ +import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import cors from 'cors'; import express, { Request, Response } from 'express'; @@ -15,6 +16,7 @@ export class Roteador { private helmet = false; private expressJson = false; private cookieParser = false; + private bodyParser = false; private cors = false; private passport = false; @@ -36,6 +38,9 @@ export class Roteador { case 'cookieParser': this.ativarDesativarCookieParser(informacoesVariavel.valor); break; + case 'bodyParser': + this.ativarDesativarBodyParser(informacoesVariavel.valor); + break; case 'json': this.ativarDesativarExpressJson(informacoesVariavel.valor); break; @@ -66,6 +71,10 @@ export class Roteador { this.aplicacao.use(helmet()); } + if (this.bodyParser) { + this.aplicacao.use(bodyParser.json()); + } + if (this.expressJson) { this.aplicacao.use(express.json()); } @@ -99,6 +108,10 @@ export class Roteador { this.expressJson = valor; } + ativarDesativarBodyParser(valor: boolean): void { + this.bodyParser = valor; + } + ativarDesativarHelmet(valor: boolean): void { this.helmet = valor; } diff --git a/liquido.ts b/liquido.ts index 4e04c1c..cab642a 100644 --- a/liquido.ts +++ b/liquido.ts @@ -75,12 +75,10 @@ export class Liquido implements LiquidoInterface { this.roteador.iniciar(); if (this.provedorLincones.configurado) { - this.interpretador.pilhaEscoposExecucao - .definirVariavel('lincones', await this.provedorLincones.resolver()); + this.interpretador.pilhaEscoposExecucao.definirVariavel('lincones', await this.provedorLincones.resolver()); } } - /** * Método de importação do arquivo `configuracao.delegua`. * @returns void. @@ -99,7 +97,7 @@ export class Liquido implements LiquidoInterface { for (const declaracao of retornoImportador.retornoAvaliadorSintatico.declaracoes) { const expressao: DefinirValor = (declaracao as Expressao).expressao as DefinirValor; const nomePropriedade: string = expressao.nome.lexema; - const informacoesVariavel: VariavelInterface = expressao.valor + const informacoesVariavel: VariavelInterface = expressao.valor; if (expressao.objeto.simbolo.lexema === 'roteador') { this.roteador.ativarMiddleware(nomePropriedade, informacoesVariavel); @@ -291,9 +289,10 @@ export class Liquido implements LiquidoInterface { } } - private async logicaComumResultadoInterpretador(caminhoRota: string, retornoInterpretador: RetornoInterpretador): - Promise<{ corpoRetorno: any, statusHttp: number }> - { + private async logicaComumResultadoInterpretador( + caminhoRota: string, + retornoInterpretador: RetornoInterpretador + ): Promise<{ corpoRetorno: any; statusHttp: number }> { // O resultado que interessa é sempre o último. // Ele vem como string, e precisa ser desserializado para ser usado. const { valor } = JSON.parse(retornoInterpretador.resultado.pop()); diff --git a/package.json b/package.json index 44666ee..cca86c3 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "dependencies": { "@designliquido/foles": "^0.2.0", "@designliquido/lmht-js": "^0.1.6", + "body-parser": "^1.20.1", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "delegua": "^0.11.0", @@ -44,6 +45,7 @@ }, "devDependencies": { "@designliquido/lincones-sqlite": "^0.0.2", + "@types/body-parser": "^1.19.2", "@types/cookie-parser": "^1.4.3", "@types/cors": "^2.8.12", "@types/dotenv": "^8.2.0", diff --git a/parciais/inicial.delegua b/parciais/inicial.delegua new file mode 100644 index 0000000..e69de29 diff --git a/rotas/mvc/teste/inicial.delegua b/rotas/mvc/teste/inicial.delegua new file mode 100644 index 0000000..0ffa33f --- /dev/null +++ b/rotas/mvc/teste/inicial.delegua @@ -0,0 +1,3 @@ +liquido.rotaGet(funcao(requisicao, resposta) { + resposta.lmht({ "fraseQualquer": "Olá Mundo!" }) +}) \ No newline at end of file diff --git a/testes/testes-unitarios/infraestrutura/preprocessadores/lmht-parciais.test.ts b/testes/testes-unitarios/infraestrutura/preprocessadores/lmht-parciais.test.ts index e82e7c3..f869e46 100644 --- a/testes/testes-unitarios/infraestrutura/preprocessadores/lmht-parciais.test.ts +++ b/testes/testes-unitarios/infraestrutura/preprocessadores/lmht-parciais.test.ts @@ -1,55 +1,57 @@ - -import { PreprocessadorLmhtParciais } from "../../../../infraestrutura/preprocessadores/lmht-parciais"; -import { VerificaXml } from "../../../ajudadores/VerificaXml"; +import { PreprocessadorLmhtParciais } from '../../../../infraestrutura/preprocessadores/lmht-parciais'; +import { VerificaXml } from '../../../ajudadores/VerificaXml'; describe('Preprocessador de parciais em LMHT', () => { let preProcessador: PreprocessadorLmhtParciais; beforeEach(() => { preProcessador = new PreprocessadorLmhtParciais(); - }) + }); it('Deve tratar o parcial e retorna o xmlContent', () => { const texto = ``; const resultado = preProcessador.processarParciais(texto); - expect(VerificaXml(resultado as string)).toBeTruthy(); + if (resultado instanceof Error) { + throw resultado; + } + expect(VerificaXml(resultado.xmlContent as string)).toBeTruthy(); }); - it('Deve retornar um Error por não encontrar a tag ' ,() => { + it('Deve retornar um Error por não encontrar a tag ', () => { const texto = ``; const resultado = preProcessador.processarParciais(texto); expect(resultado).toBeInstanceOf(Error); - expect((resultado as Error)?.message).toBe("Não foi encontrado a tag corpo"); - }) + expect((resultado as Error)?.message).toBe('Não foi encontrado a tag corpo'); + }); - it('Deve retornar um Error por não encontrar a tag ' ,() => { + it('Deve retornar um Error por não encontrar a tag ', () => { const texto = ``; const resultado = preProcessador.processarParciais(texto); expect(resultado).toBeInstanceOf(Error); - expect((resultado as Error)?.message).toBe("Não foi encontrado a tag parcial"); - }) + expect((resultado as Error)?.message).toBe('Não foi encontrado a tag parcial'); + }); - it('Deve retornar um Error por não encontrar o atributo nome' ,() => { + it('Deve retornar um Error por não encontrar o atributo nome', () => { const texto = ``; const resultado = preProcessador.processarParciais(texto); expect(resultado).toBeInstanceOf(Error); - expect((resultado as Error)?.message).toBe("Em Parcial o atributo nome não foi informado"); - }) + expect((resultado as Error)?.message).toBe('Em Parcial o atributo nome não foi informado'); + }); - it('Deve retornar um Error por não encontrar o diretorio error' ,() => { + it('Deve retornar um Error por não encontrar o diretorio error', () => { const texto = ``; - jest.spyOn(preProcessador, 'DiretorioParcialGetter', 'get').mockReturnValue('error') + jest.spyOn(preProcessador, 'DiretorioParcialGetter', 'get').mockReturnValue('error'); const resultado = preProcessador.processarParciais(texto); expect(resultado).toBeInstanceOf(Error); - expect((resultado as Error)?.message).toBe("O diretorio error não foi encontrado"); - }) + expect((resultado as Error)?.message).toBe('O diretorio error não foi encontrado'); + }); - it('Deve retornar um Error por não encontrar o arquivo parcial' ,() => { + it('Deve retornar um Error por não encontrar o arquivo parcial', () => { const texto = ``; const resultado = preProcessador.processarParciais(texto); expect(resultado).toBeInstanceOf(Error); - expect((resultado as Error)?.message).toBe("O arquivo error.lmht não foi encontrado"); - }) -}) \ No newline at end of file + expect((resultado as Error)?.message).toBe('O arquivo error.lmht não foi encontrado'); + }); +}); diff --git a/visoes/mvc/teste/inicial.lmht b/visoes/mvc/teste/inicial.lmht new file mode 100644 index 0000000..97b842e --- /dev/null +++ b/visoes/mvc/teste/inicial.lmht @@ -0,0 +1,14 @@ + + + + lmht { + tamanho-fonte: 12px; + } + + + + + Testando partial = {{fraseQualquer}} +

Teste de texto.

+
+
\ No newline at end of file diff --git a/visoes/parciais/cabecalho.lmht b/visoes/parciais/cabecalho.lmht new file mode 100644 index 0000000..2ddbfb1 --- /dev/null +++ b/visoes/parciais/cabecalho.lmht @@ -0,0 +1,3 @@ + + Isso é um Cabeçario Parcial + \ No newline at end of file diff --git a/parciais/minha-parcial.lmht b/visoes/parciais/minha-parcial.lmht similarity index 100% rename from parciais/minha-parcial.lmht rename to visoes/parciais/minha-parcial.lmht diff --git a/yarn.lock b/yarn.lock index 28ee7e8..9d01b62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -932,7 +932,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*": +"@types/body-parser@*", "@types/body-parser@^1.19.2": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== @@ -1504,7 +1504,7 @@ bl@^5.0.0: inherits "^2.0.4" readable-stream "^3.4.0" -body-parser@1.20.1: +body-parser@1.20.1, body-parser@^1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==