Plugins de colaboração e revisão
Seis plugins que transformam o editor em um fluxo de trabalho real de documentos: comandos de barra (slash commands), @menções, controle de alterações, comentários em threads, histórico de revisões e presença baseada em Yjs. Todos vêm incluídos na licença padrão — nenhum SKU premium é necessário.
Comandos de barra
Digite / em uma linha vazia (ou após um espaço em branco) para abrir um seletor de comandos inline. São 15 blocos integrados (H1–H3, listas com marcadores / numeradas, citação, código, divisor, tabela, imagem, link, emoji, data de hoje), além de todas as ações registradas do AI Toolkit.
Configuração
{
slashCommandEnabled: true, // default when this plugin is loaded
slashCommandIncludeAi: true // pull aiToolkitActions into the menu
}API
editor.slashCommands.register({ id, label, keywords, run });
editor.slashCommands.remove(id);
editor.slashCommands.list();
editor.slashCommands.open(); / .close();@Menções
Framework de caracteres de disparo para @, #, [[wiki]] ou qualquer prefixo personalizado. Fontes de dados assíncronas (com debounce e estado de carregamento). Pills atômicas e não editáveis — o Backspace remove o chip inteiro.
Registre um caractere de disparo
editor.mentions.register({
trigger: "@",
insertClass: "rte-mention-person",
search: function (query, done) {
fetch("/api/users?q=" + encodeURIComponent(query))
.then(r => r.json())
.then(done); // Array<{ id, name, color? }>
},
renderItem: function (user) { return user.name; },
renderInsert: function (user) { return "@" + user.name; }
});Controle de alterações (modo de sugestão humana)
Sugestões no estilo do Word. As inserções aparecem sublinhadas na cor do usuário atual; as exclusões recebem tachado (e só são removidas quando aceitas). Exclusões sequenciais são mescladas em um único span; usar Backspace dentro de uma inserção que você acabou de digitar a encurta.
Configuração
{
trackChangesEnabled: true,
currentUser: { id: "maya", name: "Maya Patel", color: "#9333ea" },
reviewCanDecide: (entry, action, user) => user.role === "editor"
}Aceitar / rejeitar por autor a partir do painel Review. Use reviewCanDecide para aplicar a política de revisores da sua aplicação; decisões negadas deixam a sugestão pendente e disparam review_decision_denied. Sugestões aceitas e rejeitadas armazenam decidedBy para fins de auditoria. Funciona junto com as sugestões de IA — ambas vão parar no mesmo armazenamento editor.reviewLedger.
Histórico de revisões
Navegador de snapshots com um iframe de pré-visualização em sandbox e um diff de linhas baseado em LCS. Snapshots manuais ou automáticos com debounce. Usa localStorage por padrão, ou faz POST para um endpoint no servidor.
Configuração
{
revisionHistoryEnabled: true,
revisionHistoryMaxEntries: 50,
revisionHistoryAutoSnapshotMs: 10000,
revisionHistoryUrl: "/api/revisions", // optional
revisionHistoryRequestHeaders: () => ({
"X-CSRF-Token": readCsrfToken()
}),
onRevisionHistorySyncError: ({ reason, status }) => {
reportSyncProblem(reason, status);
}
}Use um endpoint de mesma origem, com a sua sessão e a proteção CSRF existentes. Os valores dos cabeçalhos podem ser fornecidos por uma função, para que um token antifalsificação de curta duração seja lido no momento da requisição. Não coloque chaves de API de longa duração na configuração do editor.
API
editor.revisionHistory.snapshot(label?, metadata?);
editor.revisionHistory.promptAndSnapshot(defaultLabel?); // native prompt + snapshot
editor.revisionHistory.rename(id, label);
editor.revisionHistory.list(); // all snapshots
editor.revisionHistory.listNamed(); // user-labeled only
editor.revisionHistory.diff(idA, idB); // { lines, oldText, newText }
editor.revisionHistory.restore(id);
editor.revisionHistory.delete(id);
editor.revisionHistory.openBrowser();Presença com Yjs e digitação simultânea
Cursores ao vivo, avatares de presença, registro de revisão compartilhado. O Yjs é uma peer dependency — o plugin nunca o inclui. Você carrega o Yjs + um provedor (WebSocket / WebRTC / Hocuspocus) e os passa para o plugin.
Conexão
import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";
const ydoc = new Y.Doc();
const provider = new WebsocketProvider("wss://collab.example.com", docId, ydoc);
editor.collab.attach({
doc: ydoc,
provider: provider,
user: { id: "alice", name: "Alice", color: "#2563eb" },
textSync: "crdt", // per-node Yjs CRDT; load crdt-engine.min.js first
requireCrdt: true // do not silently fall back to legacy snapshots
});textSync: "crdt". O binding por nó espelha o DOM editável em um Y.XmlFragment, preservando alterações simultâneas de texto e formatação sem o reset do corpo inteiro do modo legado. Chame editor.collab.getStatus() após o attach para registrar o modo ativo e o motivo de qualquer fallback.
Borda WebSocket em produção
O servidor de colaboração incluído oferece tokens assinados com escopo de sala, estado durável em LevelDB, lista de origens de navegador permitidas e um limite de conexões por sala. Use os quatro controles em produção; termine o TLS no seu proxy e não exponha um endpoint WebSocket aberto.
RTE_COLLAB_SECRET="use-a-long-random-secret"
RTE_COLLAB_PERSIST="/var/lib/rte-collab"
RTE_COLLAB_ALLOWED_ORIGINS="https://app.example.com,https://admin.example.com"
RTE_COLLAB_MAX_CONNECTIONS_PER_ROOM="100"
RTE_COLLAB_REDIS_URL="redis://redis:6379"
node server.jsO endpoint de tokens na nuvem verifica a propriedade do documento antes de emitir uma credencial de curta duração para uma sala. O servidor rejeita origens de navegador ausentes ou fora da lista com HTTP 403 e rejeita pares excedentes em uma sala muito movimentada com HTTP 429. Defina a mesma URL do Redis em todas as réplicas para repassar as atualizações de documento e de awareness sem sticky sessions; uma réplica que entra em uma sala ativa solicita um snapshot completo do estado CRDT antes de sincronizar seu primeiro cliente. Se o Redis configurado estiver indisponível, /healthz retorna HTTP 503 e status: "degraded". Após a reconexão, a prontidão continua degradada até que uma ida e volta interna de Pub/Sub comprove que a assinatura voltou a receber mensagens.
Cada par é uma entrada não confiável
Um CRDT aplica edições remotas gravando nós diretamente no documento ativo. Elas não passam pelo tratamento de colagem nem por setHTMLCode, então um editor que filtra apenas esses dois pontos de entrada executará sem problemas o <iframe srcdoc> de um colaborador no navegador de todos os outros participantes — e depois o replicará adiante. Trate um coautor de um documento compartilhado exatamente como você trata HTML colado.
sanitizer.js fecha esse caminho: ele observa a área editável em busca de nós e atributos inseridos e filtra qualquer coisa executável antes que ela possa rodar, seja qual for a origem. A digitação comum não tem custo, porque os nós de texto são ignorados e o filtro só entra em ação quando algo perigoso aparece. Desative com sanitizerGuardLiveDom: false se a sua camada de sincronização já sanitiza antes. Você mesmo pode executar essa verificação na página de verificação ao vivo.
O conjunto de testes de release inicia dois processos independentes de servidor WebSocket contra um processo real e isolado compatível com Redis e verifica a entrada tardia, conteúdo e presença bidirecionais, isolamento de sala/token, perda do backend, recuperação da prontidão e a primeira edição após a recuperação. Isso é evidência de integração executada pelo fornecedor, não um SLA de serviço gerenciado nem uma certificação externa de confiabilidade.
Registro de revisão compartilhado
Sugestões de IA, sugestões humanas do controle de alterações e comentários passam todos por um único armazenamento: editor.reviewLedger. É por isso que o painel Review consegue mostrá-los intercalados, e aceitar / rejeitar funciona da mesma forma, seja qual for a origem.
API
editor.reviewLedger.add(entry); // { id, changeType, author, text, replies[], ... }
editor.reviewLedger.update(id, patch);
editor.reviewLedger.remove(id);
editor.reviewLedger.get(id);
editor.reviewLedger.list();
editor.reviewLedger.refreshPanel();
Comentários em threads
Os comentários são ancorados em intervalos de seleção e renderizados como um realce + uma thread na barra lateral. Editor de comentário, respostas, resolver, excluir.
Configuração
API