Visão geral
Editor de texto rico WYSIWYG, modular e independente de projeto.
O ExpertEditor é um editor de texto rico (WYSIWYG) modular, reutilizável e independente de projeto, construído sobre Tiptap/ProseMirror. Você interage com uma única classe pública (ExpertRichEditor) — não precisa conhecer o funcionamento interno.
- ✍️ Formatação rica — títulos, listas, links, alinhamento, cor e highlight.
- 🖼️ Imagens (upload), tabelas (grade 10×10 + edição contextual), blockquote, código, divisor, callout e checklist.
- 🎛️ Slash commands (
/) nativos e configuráveis.
- 💾 Autosave com debounce e contadores de palavras/caracteres.
- 🧱 Três modos:
simple, advanced e readonly.
- 🧩 Agnóstico de UI e backend — você decide upload e sanitização.
- 🌐 Acessível, responsivo e com dark mode.
Modos de operação
| Modo | Uso típico | Features padrão |
simple | Observações, comentários, textos curtos | bold, italic, underline, strike, lists, undo, redo, clearFormatting |
advanced | Documentos, notícias, conteúdo institucional | heading, bold, italic, underline, strike, lists, link, align, color, highlight, image, table, slashCommand, blockquote, codeBlock, horizontalRule, callout, checkList, undo, redo, clearFormatting |
readonly | Exibição (sem controles de edição) | — (nenhuma) |
Instalação
Como obter o ExpertEditor conforme o seu tipo de projeto.
Requisitos
| Item | Detalhe |
| Navegador | Navegadores modernos (Chrome, Edge, Firefox, Safari). |
| Node.js (npm/tgz) | Node 18+ para instalar via npm ou .tgz. |
| Peer dependency | @tiptap/core@^2.6.0 (apenas para npm/.tgz). |
| Build | Não é obrigatório — há bundle standalone para HTML puro/WordPress. |
Formas de instalação
- Bundle standalone — HTML puro / WordPress / projetos sem build. Baixe o
.js + .css na página de Download.
- npm — projetos com build:
npm install expertbrazileditor.
.tgz local — para travar uma versão específica.
<link rel="stylesheet" href="expert-editor.css" />
<script src="expert-editor.umd.js"></script>
<div id="editor"></div>
<script>
const ed = window.ExpertEditor.ExpertRichEditor
? new window.ExpertEditor.ExpertRichEditor({ element: '#editor', mode: 'advanced' })
: null
</script>
Quickstart
Seu primeiro editor em 5 minutos.
HTML puro (bundle standalone)
- Baixe o pacote standalone na página de Download.
- Crie um HTML com o editor.
<link rel="stylesheet" href="expert-editor.css" />
<script src="expert-editor.umd.js"></script>
<div id="editor"></div>
<input type="hidden" id="conteudo" name="conteudo" />
<script>
const ed = new window.ExpertEditor.ExpertRichEditor({
element: '#editor', mode: 'advanced', placeholder: 'Digite seu conteúdo...',
})
ed.onUpdate(({ editor }) => {
document.getElementById('conteudo').value = editor.getHTML()
})
</script>
Via npm (Vite/Webpack)
npm install expertbrazileditor @tiptap/core@^2.6.0
import { ExpertRichEditor } from 'expertbrazileditor'
import 'expertbrazileditor/styles/editor.css'
const ed = new ExpertRichEditor({
element: '#editor', mode: 'advanced',
content: { html: '<p>Conteúdo inicial</p>' },
autosave: { enabled: true, debounce: 1200, callback: ({ html }) => console.log('auto-saved', html) },
})
Configuração
A classe ExpertRichEditor recebe um objeto EditorConfig.
| Campo | Descrição |
element (obrigatório) | Seletor CSS ou elemento DOM onde montar o editor. |
mode | 'simple' | 'advanced' | 'readonly' (padrão simple). |
placeholder | Texto exibido quando vazio. |
features | Lista de features habilitadas; se ausente, usa o padrão do modo. |
content | Conteúdo inicial ({ html } ou { json }). |
disabled | Cria o editor já desabilitado (readonly forçado). |
uploadAdapter | Adapter de upload de arquivos (imagens). |
slashCommands | Comandos customizados do menu slash. |
autosave | Salvamento automático com debounce (enabled, debounce, callback). |
Features disponíveis
heading | bold | italic | underline | strike | lists | undo | redo | clearFormatting | link | align | color | highlight | image | table | slashCommand | blockquote | codeBlock | horizontalRule | callout | checkList
Ativação do token
Ciclo de vida do token e página de ativação assistida.
O ExpertEditor usa um sistema de tokens para validar o domínio do seu projeto (a licença do editor). O ciclo de vida é:
- 🔑 O token nasce inativo — ao gerar no painel (
editor.expertbrazil.com), ele aparece como ○ Inativo.
- ⚡ Ativa no 1º uso — quando o editor do seu projeto valida no nosso servidor (via opção
apiKey), o token ativa automaticamente e registra a validação (data/hora + domínio).
- ✅ Ativação assistida — alternativa manual (ex.: sem o editor ainda instalado): abra a página de ativação com os parâmetros abaixo.
Página de ativação
Você (ou o responsável pelo projeto) abre este link com os parâmetros do token:
https://editor.expertbrazil.com/ativar?token=SEU_TOKEN&domain=SEU_DOMINIO&return=https://SEU_DOMINIO/caminho
| Parâmetro | Descrição |
token | O token gerado no painel (obrigatório). |
domain | Domínio do projeto (obrigatório). Aceito exato, subdomínio ou localhost (dev). |
return | Opcional — para onde voltar após ativar. Só é aceito se o host pertencer ao domínio do token (anti open-redirect). |
O que a página faz: cruza o domínio informado com o token — se pertencem e o token não está revogado, ativa o token (1º uso), registra o log e mostra o botão Voltar ao projeto. Domínio errado, token revogado ou inexistente → a página explica o motivo e aponta para o painel.
Fluxo normal: você não precisa da página de ativação na maioria dos casos — basta colocar o token na opção apiKey do editor; a validação na inicialização ativa o token automaticamente. A página /ativar é o fluxo assistido (botão/QR/link do fornecedor).
API de referência
Métodos da classe ExpertRichEditor e eventos.
Conteúdo
| Método | Descrição |
getHTML(): string | Retorna o conteúdo em HTML. |
getJSON(): object | Retorna o documento em JSON (ProseMirror). |
getText(): string | Retorna o texto puro. |
setHTML(html) / setJSON(json) | Substitui o conteúdo. |
clear() / isEmpty() | Limpa o documento / verifica se vazio. |
Controle
focus(), blur(), enable(), disable(), isEditable(), getMode(), hasFeature(), destroy().
Modo código (HTML)
toggleSourceMode(), isSourceMode(), setSourceMode(). No modo código você edita HTML num <textarea>; ao sair, o HTML é aplicado e validado pelo schema (inválido não quebra).
Formatação & links
toggleBold/Italic/Underline/Strike, toggleHeading(level), setParagraph(), toggleBulletList/OrderedList/TaskList, undo()/redo(), clearFormatting(), setLink(url), unsetLink(), isLinkActive().
Alinhamento, cor & highlight
setAlign(align), isAlignActive(), setColor(), isColorActive(), setHighlight(), isHighlightActive().
Imagens
setImage(url|File|UploadResult), setImageSize(), setImageAlign(), isImageActive(), deleteImage().
Tabelas
insertTable({rows, cols, withHeaderRow}), addRow/delRow, addRowBefore, mergeCells/splitCell, toggleHeaderRow, deleteTable, openTableInsertPopover(). A barra contextual aparece quando a seleção entra numa tabela (ícones + tooltip no desktop; action-sheet no mobile).
Blocos
toggleBlockquote(), toggleCodeBlock(), setHorizontalRule(), setCallout(type)/toggleCallout().
Contadores & utilidades
wordCount(), characterCount(), getSlashCommands(), slashActions(), isActive(name, attrs?), getInternalEditor().
Eventos
Registre com on(eventName, handler). Cada handler recebe { editor, state? }.
Guias por stack
Implantação passo a passo nas principais stacks.
Laravel / Blade (com upload + sanitização)
Instale o pacote, monte o editor copiando getHTML() para um input hidden, implemente um endpoint de upload com CSRF e purifique o HTML no backend.
Route::post('/admin/editor/upload', [EditorUploadController::class, 'upload']);
public function upload(Request $request)
{
$request->validate(['file' => ['required', 'file', 'image', 'max:5120']]);
$path = $request->file('file')->store('editor', 'public');
return response()->json(['url' => asset('storage/' . $path)]);
}
use Mews\Purifier\Facades\Purifier;
$dados['observacoes'] = Purifier::clean($request->input('observacoes'), 'expert_editor');
HTML puro (bundle standalone)
Sem build — baixe o pacote e carregue no HTML, sincronizando getHTML() num campo oculto.
React / Vue (ciclo de vida)
Monte no lifecycle e destrua o editor ao desmontar (ed.destroy()) para evitar vazamentos.
WordPress (plugin)
O plugin ExpertEditor (desenvolvedor ExpertBrazil WEB) substitui o editor clássico. Requer WordPress com Classic Editor ativo. O upload usa a mídia nativa; a sanitização aplica wp_kses_post.
| Stack | Instalação | Upload | Sanitização |
| Laravel/Blade | npm / .tgz | Endpoint com CSRF | Purifier allowlist |
| HTML puro | Standalone | Adapter próprio | Purifier/equivalente |
| React/Vue | npm / .tgz | Adapter próprio | Purifier/equivalente |
| WordPress | Plugin (ZIP) | Mídia WP | wp_kses_post |
Segurança
Boas práticas para usar o ExpertEditor com segurança.
1. Sanitize o HTML no backend (obrigatório). O editor produz HTML controlado, mas nunca confie no HTML vindo do cliente. Purifique antes de persistir e renderizar. Inclua na allowlist: table, thead, tbody, tr, th, td[colspan|rowspan] e div[class] (callout).
2. XSS: purifique antes de renderizar; links já usam rel="noopener noreferrer nofollow". Para origens confiáveis, use link.allowedProtocols.
3. Upload: valide tipo (imagens) e tamanho no servidor; não confie em name/type do cliente; re-derive do arquivo.
4. LGPD: o conteúdo pode conter dados pessoais — aplique retenção/anonimização e não envie a serviços externos sem base legal.
5. Boas práticas: tema via CSS variables; destrua o editor ao desmontar; trave a versão (--save-exact); revisite a allowlist ao atualizar.
Changelog
Histórico de versões do ExpertEditor.
- 0.5.2 — Modo código (HTML):
toggleSourceMode(), isSourceMode(), setSourceMode(), evento onSourceModeChange.
- 0.5.1 — Fix de tabela: redimensionar coluna para a esquerda não encolhia.
- 0.5.0 — Tabelas com grade 10×10 + barra contextual de edição (desktop) e action-sheet (mobile).
- 0.4.0 — Autosave com debounce + contadores de palavras/caracteres.
- 0.3.0 — Imagens, tabelas, blocos especiais, slash commands configuráveis.
- 0.2.0 — Links, alinhamento, cor, highlight e Bubble Menu.
- 0.1.0 — Fundação: core, playground, modos e formatação básica.
FAQ
Perguntas frequentes.
Funciona sem build (HTML puro / WordPress)? Sim. Há um bundle standalone (arquivo .js + .css) carregado direto no HTML.
Preciso conhecer Tiptap/ProseMirror? Não — você interage apenas com ExpertRichEditor.
Onde os arquivos são armazenados? Você decide via uploadAdapter (Laravel, S3, R2…).
Como evito XSS? Purifique o HTML no backend com uma allowlist (ver Segurança).
Por que minha tabela some após salvar? Sua allowlist provavelmente não inclui table/thead/tbody/tr/th/td[colspan|rowspan].
Como deixo somente leitura? Use mode: 'readonly' ou editor.disable()/enable().
Como coleto o HTML? Use editor.getHTML() no submit ou editor.onUpdate().
O que é o modo código? Alterna do WYSIWYG para um <textarea> de HTML pronto; inválido não quebra.
Preciso destruir o editor ao desmontar (React/Vue)? Sim — chame editor.destroy() no cleanup.