Programação Por Equipe DevBras

Capa do artigo: Editor rico que não carregou: a textarea que garante que a pessoa ainda escreve

Editor rico que não carregou: a textarea que garante que a pessoa ainda escreve

Comece o formulário com uma textarea funcional, deixe o editor rico assumir só se carregar e faça o servidor aceitar texto puro ou HTML, para um CDN fora do ar não impedir ninguém de salvar.

O CDN do editor rico ficou fora do ar por quarenta minutos numa quarta à tarde. Nesse intervalo, a área de escrever post do blog da empresa apareceu como um retângulo morto: não dava para digitar, e quem tinha começado antes clicou em Salvar e gravou vazio. A resposta curta: o HTML da página já traz uma textarea funcional com o conteúdo. O script do editor, se carregar, esconde a textarea e assume. Se não carregar, a pessoa escreve texto puro e envia normalmente, e o servidor aceita os dois formatos, limpando o HTML quando houver. A barra de ferramentas é melhoria; escrever e salvar é a função. Se o seu problema é o editor que salva vazio, veja também como sincronizar e sanitizar o HTML do editor rico.

Esse padrão tem nome antigo, melhoria progressiva, e continua sendo o jeito mais barato de não depender de um arquivo de terceiros para a tarefa principal da tela.

Por que noscript não resolve

A primeira ideia costuma ser um bloco noscript com a textarea. Ele só aparece quando o JavaScript está desligado no navegador, caso raro. Os casos reais são outros: o script está ligado, mas o arquivo não chegou. O CDN caiu, o firewall da empresa bloqueia o domínio, uma extensão de bloqueio barrou o arquivo, a conexão do celular cortou no meio, ou um erro em outro script da página interrompeu a execução antes do editor montar. Em todos esses casos, noscript fica invisível e a área de texto continua morta.

O problema de fundo é a ordem. Se a página nasce com uma div vazia esperando o editor, ela depende do editor para existir. Se nasce com uma textarea, o editor é um passo opcional por cima de algo que já funciona.

Como montar o formulário que funciona sem o editor

O exemplo continua o do post sobre editor rico que salva vazio, que mostra como sincronizar a div editável com o formulário. Aqui, o foco é o que acontece quando o editor nem chega a montar.


O HTML de partida

<form method="post" action="/posts">
  <label for="corpo">Texto do post</label>
  <textarea id="corpo" name="corpo" rows="14" required></textarea>
  <input type="hidden" id="formato" name="formato" value="texto">
  <button type="submit">Salvar</button>
</form>

<script type="module" src="/js/ativar-editor.js"></script>

Sem nenhum script, esse formulário já cumpre a tarefa: a pessoa escreve, clica e o servidor recebe corpo e formato=texto.

O script que assume só se puder

O módulo /js/editor-rico.js representa o seu editor; ele exporta criarEditor, que monta a área editável a partir da textarea e devolve um objeto com o método html().

// /js/ativar-editor.js
const area = document.getElementById('corpo');
const formato = document.getElementById('formato');

try {
  const { criarEditor } = await import('/js/editor-rico.js');
  const editor = criarEditor(area);

  area.required = false;
  area.hidden = true;
  formato.value = 'html';

  area.form.addEventListener('submit', () => {
    area.value = editor.html();
  });
} catch (erro) {
  console.warn('Editor rico indisponível, mantendo a textarea.', erro);
}

Dois detalhes evitam bugs difíceis. A textarea escondida com hidden continua sendo enviada no formulário, por isso ela segue como o campo que viaja. E uma textarea escondida que ainda tem required bloqueia o envio: o navegador tenta mostrar o erro num campo que não pode receber foco, e o botão Salvar parece não fazer nada.

Se o editor vem de CDN, servir o arquivo do seu próprio domínio reduz bastante o risco. Não elimina: um erro de JavaScript ou uma atualização quebrada ainda caem no catch, e é para isso que ele existe.

O servidor que aceita os dois formatos

const sanitizeHtml = require('sanitize-html');

const regras = {
  allowedTags: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'a', 'h2', 'h3', 'blockquote'],
  allowedAttributes: { a: ['href'] },
  allowedSchemes: ['http', 'https', 'mailto']
};

function escaparHtml(texto) {
  return texto
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;');
}

function textoParaHtml(texto) {
  return texto
    .split(/\r?\n\s*\r?\n/)
    .map((bloco) => bloco.trim())
    .filter((bloco) => bloco !== '')
    .map((bloco) => '<p>' + escaparHtml(bloco).split(/\r?\n/).join('<br>') + '</p>')
    .join('');
}

function corpoParaGravar(corpo, formato) {
  const entrada = typeof corpo === 'string' ? corpo : '';
  return formato === 'html' ? sanitizeHtml(entrada, regras) : textoParaHtml(entrada);
}

Linha em branco vira parágrafo e quebra simples vira br. Quem escreveu na textarea não precisa saber HTML, e o texto aparece no site com a mesma estrutura do que foi digitado. O campo formato é só uma dica: mesmo que alguém o altere à mão, os dois caminhos produzem HTML seguro.

Editando um post que já tem formatação

Na criação, a textarea começa vazia e não há dilema. Na edição de um post com negrito e links, o servidor preenche a textarea com o HTML guardado e o campo formato com html. Se o editor carregar, ele assume e ninguém vê as marcações. Se não carregar, a pessoa vê as tags, o que é feio, mas preserva toda a formatação e ainda permite corrigir uma palavra com urgência. Mostre uma linha de ajuda explicando isso só no modo de reserva.

Como testar a degradação

No Chrome ou no Edge, o DevTools tem um painel de bloqueio de requisições. Bloqueie o endereço do editor, recarregue a página, escreva dois parágrafos e salve. Depois confira no banco que o texto chegou como dois parágrafos. Repita com a rede em modo lento, para ver se a pessoa consegue começar a digitar antes de o editor montar. Para envios sem recarregar a página, o post enviar formulário sem recarregar mostra como não perder o erro no caminho.

Erros comuns


Checklist


Bloqueie hoje o domínio do editor no seu navegador e tente publicar um rascunho. Ainda dá para escrever e salvar? Se não dá, a tela não tem degradação, tem dependência.

Avalie este artigo

Referência: http://stackoverflow.com/questions/16941360/how-to-create-a-placeholder-for-div-that-act-like-textfield