Files
eden/apps/api/src/documents/merge-engine.ts
Matheus (Handix) 1545666f17 feat(documents): editor de texto rico (Tiptap) para templates de documento
Substitui o textarea de texto puro por um editor visual real, seguindo o
print de referência do usuário do editor "Contrato de Software" do
OrçaFácil legado: toolbar completa (negrito/itálico/sublinhado/tachado,
alinhamento, listas, tabela, imagem, quebra de página), variáveis inseridas
como chip inline via catálogo fechado (nunca {{texto livre}}), painel
"Variáveis usadas neste modelo" (com badge obrigatório ao vivo) e
"Histórico de versões".

Backend: editor-content-renderer.ts e merge-engine.ts portados/reescritos
a partir do renderEditorContent.js/variableRegistry.js reais do legado
(achados em .tmp/orcafacil-reference) — resolve a árvore Tiptap
diretamente em vez de regex sobre HTML cacheado. Novo catálogo de
variáveis + GET /documents/variable-catalog.

Fora de escopo desta leva (documentado em docs/progress.md): nó
`conditional`, repetição de linha de tabela, bloqueio por variável
obrigatória ausente, e auto-resolução de dados reais do cadastro na hora
de gerar o documento.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 19:49:42 -03:00

30 lines
1.5 KiB
TypeScript

/**
* Motor de resolução de variáveis — opera direto sobre a árvore Tiptap
* (`editor_content`), não mais sobre `{{variavel}}` em texto puro (essa era
* a versão stand-in de uma leva anterior, antes do editor visual real
* existir). Inspirado em `resolveDocument()` do legado (eden.md §3.2), mas
* simplificado: sem nó `conditional`, sem expansão de `tableRow.attrs.repeat`
* (fora de escopo — o editor/catálogo desta leva nunca produz nenhum dos
* dois) e sem bloquear com `MISSING_REQUIRED_FIELDS`/`UNRESOLVED_VARIABLES`
* (HTTP 422) — uma `mergeField` sem valor em `context` vira string vazia e é
* só reportada em `missingVariables` (deduplicada, ordem da primeira
* ocorrência); o chamador decide o que fazer com isso.
*/
import { collectMergeFieldKeys, renderToHtml } from "./editor-content-renderer";
export interface ResolveDocumentResult {
/** HTML final, com toda `mergeField` já substituída pelo valor do contexto (ou string vazia, quando ausente). */
html: string;
/** Chaves referenciadas no documento mas ausentes de `context`, deduplicadas, na ordem de `collectMergeFieldKeys`. */
missingVariables: string[];
}
export function resolveDocument(editorContent: unknown, context: Record<string, string>): ResolveDocumentResult {
const keys = collectMergeFieldKeys(editorContent);
const missingVariables = keys.filter((key) => !Object.prototype.hasOwnProperty.call(context, key));
const html = renderToHtml(editorContent, (key) => context[key] ?? "");
return { html, missingVariables };
}