Contexto do projeto e análise de requisitos
Como desenvolvedor do ToolMi(gongjumi.com), esforço-me constantemente para oferecer aos usuários uma experiência online superior. Recentemente, ao atualizar o recurso de exibição de código do site, percebi que o componente nativo textarea
apresenta limitações claras de UX ao lidar com entrada e saída de código.
O Gongjumi oferece várias ferramentas relacionadas a código, como o Formatador YAML, o Gerador de entidade Java a partir de SQL e o Beautifier TypeScript. Todas essas ferramentas exigem que o usuário insira código e visualize o resultado processado. No entanto, as textarea
simples não oferecem realce de sintaxe, dificultando a localização de erros em códigos complexos e prejudicando a experiência geral.
Escolha tecnológica: por que highlight.js
Dentre as várias bibliotecas de realce de sintaxe disponíveis, escolhi highlight.js pelos seguintes motivos:
Amplo suporte de linguagens
highlight.js suporta mais de 190 linguagens de programação, desde as mais populares (JavaScript, Python, Java) até linguagens funcionais menos comuns. Essa cobertura é essencial para um site como o Gongjumi, que lida com diversos formatos de código.
Variedade de temas
A biblioteca oferece vários estilos de tema, como GitHub, VS Code e Atom. Isso permite escolher um tema que se alinhe à estética do Gongjumi.
Compatibilidade com o ecossistema
highlight.js se integra facilmente ao ecossistema Vue.js e sua configuração é relativamente simples. Além disso, possui detecção automática de linguagem, aplicando realce mesmo sem especificação pelo usuário.
Desempenho otimizado
Comparado a editores mais pesados como o Monaco Editor, highlight.js é mais leve e carrega mais rápido, ideal para as ferramentas online responsivas do Gongjumi.
Detalhes da implementação
Primeira abordagem: sobreposição em duas camadas
Inicialmente, tentei a abordagem comum de sobrepor um div
com o código realçado sobre um textarea
transparente:
<div class="editor-container">
<div class="code-highlight" v-html="highlightedCode"></div>
<textarea v-model="code" class="code-textarea"></textarea>
</div>
Essa configuração permitia digitar no textarea transparente enquanto a camada de fundo exibia o código realçado. Porém, apresentou falhas críticas:
- As camadas de realce e entrada frequentemente se desalinham em códigos longos ou com várias quebras de linha.
- Sincronizar a rolagem era difícil, pois uma camada não acompanhava a outra.
- Combinar fontes, espaçamento entre linhas e padding ficou muito complicado.
Otimização com CSS Grid
Para corrigir o alinhamento, utilizei CSS Grid colocando ambos os elementos na mesma área de grade:
.editor-container {
display: grid;
grid-template-areas: "editor";
}
.code-highlight, .code-textarea {
grid-area: editor;
}
Isso melhorou o alinhamento, mas sincronizar a rolagem e manter a consistência de estilo ainda era desafiador.
Solução final: div
contenteditable
Após várias tentativas, a melhor solução foi usar um div
com contenteditable
:
<div
contenteditable="true"
class="editable-code hljs"
v-html="highlightedCode"
@input="handleInput"
/>
Vantagens:
- Uso direto dos estilos nativos do highlight.js sem adaptações extras.
- Evita estruturas sobrepostas complexas, eliminando problemas de alinhamento e sincronização.
- UX mais consistente, com edição e exibição totalmente unificadas.
Implementação do código principal
Design da interface do componente
Para tornar o editor reutilizável em todas as ferramentas do Gongjumi, projetei esta interface:
interface Props {
modelValue: string // conteúdo de código com vínculo bidirecional
language?: string // especificação de linguagem opcional
readonly?: boolean // modo somente leitura
placeholder?: string // texto placeholder
rows?: number // número de linhas visíveis
}
Lógica de realce de sintaxe
O núcleo do realce consiste em chamar a API do highlight.js corretamente e tratar erros:
const updateHighlight = () => {
try {
if (props.language && hljs.getLanguage(props.language)) {
const result = hljs.highlight(localValue.value, { language: props.language });
highlightedCode.value = result.value;
} else {
const result = hljs.highlightAuto(localValue.value);
highlightedCode.value = result.value;
}
} catch (error) {
console.error('Erro ao realçar sintaxe:', error);
highlightedCode.value = escapeHtml(localValue.value);
}
};
Modo de edição vs modo somente leitura
Como o Gongjumi precisa de cenários de entrada e exibição, implementei dois modos:
<template>
<!-- Modo somente leitura para exibir resultados processados -->
<pre v-if="readonly" class="readonly-code hljs" v-html="highlightedCode"></pre>
<!-- Modo de edição para entrada de código -->
<div v-else contenteditable="true" class="editable-code hljs" @input="handleInput"></div>
</template>
Detalhes técnicos principais
Integração de temas
Para alinhar ao design do Gongjumi, escolhi o tema GitHub e fiz ajustes de cor:
// importar tema do highlight.js
import 'highlight.js/styles/github.css';
Melhorias na interação do usuário
- Tratamento da tecla Tab: insere espaços em vez de mudar o foco.
- Tratamento de colagem: remove formatação e mantém apenas texto puro.
- Debounce na entrada: evita atualizações excessivas em digitações rápidas.
Manutenção da posição do cursor
Para evitar que o cursor seja resetado, implementei lógica de salvar e restaurar posição:
const handleInput = () => {
// salvar posição atual do cursor
const cursorPosition = saveCursorPosition();
// atualizar conteúdo e realce
updateContent();
updateHighlight();
// restaurar cursor após atualização do DOM
nextTick(() => {
restoreCursorPosition(cursorPosition);
});
};
Impacto em aplicações reais
Atualização da ferramenta SQL → entidade Java
- Realce completo de sintaxe SQL na área de entrada.
- Realce profissional no código Java gerado.
- Interface mais polida e feedback muito positivo.
Melhoria do formatador JSON
O realce de sintaxe facilita a visualização da estrutura e acelera a identificação de erros.
Beautifier TypeScript
De simples <pre>
e <code>
para um componente completo com experiência de IDE.
Otimizações de desempenho e melhores práticas
Carregamento sob demanda
// importar núcleo e apenas as linguagens necessárias
import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
import python from 'highlight.js/lib/languages/python';
import java from 'highlight.js/lib/languages/java';
import sql from 'highlight.js/lib/languages/sql';
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('python', python);
hljs.registerLanguage('java', java);
hljs.registerLanguage('sql', sql);
Gerenciamento do ciclo de vida do componente
- Inicializar highlight.js ao montar o componente.
- Atualizar realce no momento de updates.
- Limpar recursos ao desmontar.
Design responsivo
- Fontes e espaçamento adaptados para dispositivos móveis.
- Interações touch-friendly.
- Rolagem e zoom otimizados.
Lições aprendidas
Problemas comuns e soluções
Desalinhamento de camadas
A solução foi abandonar a abordagem de duas camadas e usar um div
contenteditable
. Se necessário, prefira CSS Grid a posicionamento absoluto.
Pulo do cursor
Resolvido com salva/restaura cursor e debounce nas atualizações.
Conflitos de estilo
Use CSS Modules ou scoped CSS para isolar estilos do highlight.js.
Dicas de depuração
- Inspecione mudanças no DOM com as DevTools.
- Monitore erros do highlight.js no console.
- Teste diferentes linguagens e tamanhos de código.
- Valide em vários navegadores e dispositivos.
Perspectivas de evolução
Funcionalidades futuras
- Números de linha: facilita referência em trechos longos.
- Dobramento de código: collapse/expand de blocos.
- Busca e substituição: encontre e substitua texto rapidamente.
- Formatação integrada: um clique com Prettier.
Aprimoramentos de desempenho adicional
- Implementar scroll virtual para arquivos grandes.
- Otimizar algoritmos para reduzir latência.
- Adicionar cache para evitar parse redundante.
Resumo do projeto e reflexão
Conquistas técnicas
Esta integração do highlight.js me permitiu entender a fundo editores front-end modernos, dominar interações complexas e fortalecer práticas de desenvolvimento baseado em componentes.
Valor entregue ao usuário
O realce de sintaxe melhorou drasticamente a UX na detecção de erros e na compreensão de códigos complexos, conforme feedback dos usuários.
Perspectivas arquitetônicas
Um componente bem projetado não atende apenas às necessidades atuais, mas também forma uma base sólida para futuras evoluções e reutilização em outros projetos.
No Gongjumi, cada detalhe de UX importa. O realce de sintaxe, embora pequeno, simboliza nosso compromisso contínuo com a qualidade e a compreensão das necessidades dos usuários.