Persistência no Tiptap: JSON, HTML e estado colaborativo
JSON editável, HTML renderizado e estado colaborativo do Yjs resolvem problemas diferentes de persistência. Este guia do Tiptap baseado na documentação explica como escolher uma representação, verificar a compatibilidade das extensões, restaurar de forma deliberada e planejar testes de confirmações de salvamento e reconexões.
Um produto hipotético de notas com assistência de IA precisa reabrir notas editáveis. Mais tarde, sua equipe quer publicar páginas legíveis. A edição simultânea pode vir depois, mas essa é uma decisão separada. Qual representação salva atende a cada tarefa?
Para o Tiptap, comece com JSON para o documento editável. Use HTML quando um consumidor precisar de conteúdo renderizado ou de intercâmbio. Se o produto usar colaboração com Yjs, persista seu estado binário. Tratar esses formatos como cópias de segurança intercambiáveis deixa muitas questões sem resposta.
A pergunta mais difícil é o que precisa sobreviver à reabertura de um documento. Uma nota pode parecer correta e ainda assim perder uma relação da qual seu produto depende. Este guia do Tiptap 3.x usa uma tabela de decisão e a lista de verificação 3R proposta pela Optijara para definir esse contrato. As verificações devem ser feitas no seu próprio ambiente; este é um guia de decisão baseado na documentação, sem instalação executada nem experimento de colaboração realizado.
Escolha a representação de que seu produto precisa
JSON para documentos editáveis, HTML para renderização e intercâmbio
O Tiptap recomenda a persistência em JSON por sua flexibilidade e facilidade de análise. Ela também permite edições externas sem outro analisador de HTML. É possível salvar HTML. Sua legibilidade, porém, diz pouco sobre a capacidade do editor de destino de restaurar o conteúdo com fidelidade.
Segundo a API da instância do editor, editor.getJSON() e editor.getHTML() retornam o documento atual. O JSON fornece a árvore do documento. Ele não captura a sessão completa do editor, incluindo a seleção ou o histórico de desfazer, e não pode substituir o estado colaborativo. O HTML tem a mesma limitação entre documento e sessão.
| Representação | Uso adequado | Compatibilidade necessária | O que não preserva |
|---|---|---|---|
| JSON do Tiptap | Armazenamento de documentos editáveis e transformações estruturadas | Esquema das extensões do editor de destino | Estado completo de execução, histórico de desfazer ou estado do Yjs |
| HTML | Saída renderizada ou intercâmbio com um consumidor de HTML | Extensões de análise e renderização, além dos requisitos do destino | Fidelidade sem perdas no ciclo de salvar e restaurar ou uma sessão do editor |
| Estado binário do Yjs | Persistência de um documento colaborativo do Yjs | Documento colaborativo e integração com o armazenamento | Autorização da aplicação ou política de recuperação |
Para renderizar sem um editor, confira a importação do pacote. A referência do utilitário HTML documenta generateHTML de @tiptap/core como exclusivo do navegador. A versão de @tiptap/html funciona tanto no servidor quanto no navegador. Ambas exigem as extensões pertinentes. Avalie a segurança da saída separadamente; a geração de HTML não oferece uma garantia geral de sanitização.
Estado binário do Yjs para persistência colaborativa
Use o caminho de estado binário descrito abaixo se a edição simultânea for um requisito. Para um produto de notas que só precisa salvar e recarregar, mantenha o projeto mais simples de armazenamento de documentos. Um servidor de colaboração deve justificar seu lugar por uma necessidade do produto.
Trate o esquema das extensões como parte do contrato do conteúdo salvo
Verifique nós personalizados, marcas e documentos antigos
A documentação do esquema do Tiptap descreve um contrato construído a partir das extensões registradas. Essas extensões determinam quais nós e marcas são permitidos, junto com seus atributos e regras de aninhamento. Um JSON válido ainda pode conter uma estrutura que o editor de destino não consegue representar.
Voltemos ao produto hipotético de notas. Suponha que sua equipe remova uma extensão personalizada de anotações, enquanto notas antigas ainda contêm nós de anotação. Alguém precisa decidir o que acontece com essas notas antes de carregá-las com a lista reduzida de extensões. Manter o suporte é uma opção. Uma migração revisada ou a recusa de edição enquanto se aguarda a recuperação podem ser alternativas adequadas. Comparar texto simples não detectaria a relação da anotação.
Notas de pesquisa exigem cuidado semelhante. Decida quais identificadores de citação pertencem a atributos compatíveis e quais relações com as fontes precisam de registros separados na aplicação. O guia do Zotero para notas de pesquisa verificáveis ajuda a identificar essas relações, sem especificar uma integração com o Tiptap. O texto renderizado das referências, por si só, é uma base frágil para decidir o que preservar.
Entenda o que a verificação de conteúdo pode e não pode detectar
Na referência do esquema, enableContentCheck exige ativação explícita e tem false como padrão. A verificação de JSON é mais rigorosa; a verificação de HTML pode não detectar marcas sem suporte, que acabam removidas. Inclua essa limitação nos critérios de aceitação da restauração.
O tratamento na inicialização por meio de onContentError difere da opção de comando errorOnInvalidContent. O padrão de tratamento de erros de colaboração da documentação usa disableCollaboration() para remover a extensão de colaboração. Também usa editor.setEditable(false, false) para interromper a entrada sem emitir uma atualização. Isso impede a sincronização do conteúdo após a remoção de elementos, mas não reconstrói o que foi perdido.
Mantenha os dados originais fora do editor. Um schemaVersion gerenciado pela aplicação, associado a regras de migração revisadas, é uma escolha útil de projeto. O Tiptap não fornece essa garantia de versionamento de documentos para você. Preserve a origem antes de aceitar qualquer substituição transformada.
O roteiro 3R: Representação, Restauração, Recibo
3R é a lista de verificação editorial proposta pela Optijara para persistência sem colaboração. Não é um recurso oficial do Tiptap nem um método de implantação validado. Use-a para fazer perguntas separadas sobre o conteúdo que você armazena e a maneira como o carrega. Depois, estabeleça o que conta como um salvamento aceito.
Representação: capture o documento que pretende persistir
Escolha uma representação de referência e registre a configuração de extensões compatível com ela. A menos que sua aplicação modele explicitamente os metadados na árvore do Tiptap, mantenha a identidade do documento fora dela. A versão do esquema e a revisão do backend também pertencem ao contrato da aplicação. Uma revisão da aplicação tem uma função diferente da de um atributo de nó ou da versão de um pacote.
Para notas construídas a partir de documentos extraídos, mantenha a identidade da fonte separada do texto editável. O guia do Docling para conteúdo estruturado e proveniência das fontes aborda esse limite da etapa anterior de ingestão. Use-o para decidir de quais referências às fontes as notas precisam, em vez de usá-lo como uma especificação de persistência do editor.
Este JSON resume as escolhas propostas em um formato legível por máquina. É um resumo editorial, sem implicar uma solicitação executável de salvamento nem um teste concluído.
{
"framework": "3r",
"representation": "editable-json-compatible-extensions",
"restore": "reject-incompatible-content-retain-original",
"receipt": "acknowledge-applicable-backend-revision",
"collaboration": "persist-yjs-binary-when-required"
}Restauração: substitua o conteúdo de forma deliberada
A referência do comando setContent informa que o comando substitui o documento. Na versão 3.x, emitUpdate tem true como padrão; na v2, o padrão era false. Consulte essa referência do comando antes de copiar formas abreviadas da página geral sobre persistência.
O exemplo abaixo é ilustrativo e não foi executado. Ele pressupõe um editor existente do Tiptap 3.x com suporte a documentos, parágrafos e texto. Seus dados correspondem a essa configuração. Você ainda precisaria implementar as operações de rede e banco de dados.
const savedContent = {
type: 'doc',
content: [{
type: 'paragraph',
content: [{ type: 'text', text: 'saved-note' }],
}],
}
editor.commands.setContent(savedContent, {
emitUpdate: false,
errorOnInvalidContent: true,
})Definir emitUpdate: false pode evitar um salvamento automático acionado por atualização durante a restauração do conteúdo. Outros ouvintes de eventos da aplicação ainda precisam ser examinados, e a ordenação de gravações assíncronas continua sendo sua responsabilidade. Se a restauração for rejeitada, mantenha os dados originais disponíveis para recuperação. Não os sobrescreva com conteúdo parcialmente aceito.
A referência de eventos atribui significados diferentes a esses eventos. update se refere a alterações de conteúdo. selectionUpdate se refere à seleção, enquanto transaction abrange alterações de estado resultantes de qualquer operação. Use update ou a função de retorno documentada onUpdate para salvamentos acionados por alterações de conteúdo e confira o que seus outros ouvintes de eventos realmente fazem.
Recibo: diferencie edições locais de salvamentos aceitos
Um indicador de conteúdo salvo faz uma promessa. Segundo este contrato proposto para a aplicação, ele deve significar que o backend aceitou a revisão aplicável e que nenhuma edição local mais recente está aguardando. Serializar o conteúdo ou iniciar uma solicitação é cedo demais para fazer essa promessa.
Defina cada transição antes de implementar este fluxo de estados recomendado.
Uma confirmação de uma cópia anterior deve manter uma edição mais recente marcada como não salva. Caso contrário, a interface indicaria a aceitação de um conteúdo que o backend não confirmou.
Use verificações da revisão esperada no backend ou escolha outra política explícita de conflitos. O debounce ajuda a programar solicitações; ele não pode decidir qual revisão o servidor deve aceitar. Em caso de falha, preserve o conteúdo pendente. Torne o conflito visível e exija uma recuperação deliberada antes de substituir o trabalho local por uma cópia anterior já confirmada. Essas decisões pertencem à aplicação e vão além da API de eventos do Tiptap.
Mantenha o estado colaborativo do Yjs separado das projeções JSON
Persista o estado binário, em vez de reconstruir o documento a cada reconexão
A documentação de persistência do Hocuspocus exige que o estado do documento codificado pelo Yjs seja armazenado como dados binários Uint8Array. Seu aviso é específico. Armazenar um Y.Doc como JSON e recriar o estado binário do Yjs quando um usuário se conecta pode prejudicar a mesclagem e duplicar conteúdo em novas conexões.
Mantenha o JSON como uma projeção adicional se o produto precisar dela. Persista o estado colaborativo real para as reconexões e leve essa distinção para os procedimentos de backup e restauração.
O Hocuspocus documenta onStoreDocument para armazenamento e onLoadDocument para carregamento. As extensões de banco de dados oferecem outra abstração. Essas APIs identificam o limite da persistência; não constituem uma configuração completa de servidor. O fluxo de salvamento automático sem colaboração descrito acima é insuficiente para esse caminho.
Decida se a colaboração é realmente necessária
Se a colaboração for adicionada depois, planeje a conversão inicial explicitamente. Retenha a origem e teste o comportamento de reconexão no seu ambiente antes de substituir o formato de salvamento existente. Uma mudança silenciosa de formato não fornece critérios úteis de aceitação da migração.
Persistir o estado binário ainda deixa as decisões de autorização e retenção a cargo da aplicação. Teste os backups de forma independente. Revise as migrações de extensões mesmo após uma reconexão bem-sucedida, pois a reconexão não estabelece compatibilidade com um esquema alterado.
Erros das equipes: uma lista de verificação do ciclo de salvar e restaurar antes do lançamento
Teste a fidelidade do conteúdo e o comportamento da restauração
As verificações a seguir são testes propostos para o leitor. Elas não foram executadas para este artigo. Crie dados sintéticos de teste para o conteúdo que seu produto suporta, registrando a configuração das extensões e retendo todos os dados originais. Compare atributos relevantes, além da estrutura. O texto visível é apenas parte do documento.
| Erro | Teste proposto | Observação esperada |
|---|---|---|
| JSON válido significa conteúdo fiel | Salvar e restaurar nós personalizados, atributos, links e marcas | A estrutura e as relações compatíveis permanecem intactas |
| Documentos antigos não precisam de revisão de compatibilidade | Carregar dados de teste que exijam uma extensão removida | Rejeição explícita ou migração revisada, com o original retido |
| Atualizações no recarregamento são edições do usuário | Restaurar com emitUpdate: false; examinar os ouvintes de salvamento reais | Nenhuma gravação não intencional acionada pela restauração |
| A verificação de conteúdo torna o HTML seguro | Avaliar separadamente URLs não confiáveis, atributos e contextos de saída | As lacunas de segurança continuam explícitas, sem serem encobertas pela aprovação do esquema |
Para o produto hipotético de notas, comece com dados de teste contendo um parágrafo simples. Adicione uma referência com link e, depois, uma anotação personalizada com sua relação esperada descrita por escrito. Inclua dados de teste da configuração de esquema mais antiga ainda suportada. Se um atributo mudar, investigue-o mesmo quando a nota restaurada parecer idêntica.
Use a tabela como uma lista de verificação da implementação e atribua um responsável às observações não resolvidas. Uma migração pode produzir conteúdo válido e ainda descartar uma relação de que o produto precisa. Esse resultado deve reprovar nos critérios de aceitação do produto.
Teste condições de corrida no salvamento e reconexões colaborativas
Atrase e reordene as solicitações de salvamento no seu ambiente de teste. Se a aplicação usar revisões esperadas, verifique se as gravações desatualizadas são rejeitadas e se a interface informa um conflito. Confirme também que a aceitação de uma cópia anterior mantém uma edição local posterior marcada como não salva.
Com a colaboração ativada, reconecte vários clientes ao estado binário persistido. Examine o resultado da mesclagem e verifique se há duplicação. Registre as observações em vez de presumir que o formato de armazenamento documentado garante toda a integração.
O guia do Playwright para verificar estados da interface oferece uma abordagem relacionada para testar a interface. Adapte-a aos estados de salvamento e recuperação e, depois, acrescente uma leitura de conferência do backend. Seus dados de teste de acessibilidade não testam a persistência, e um rótulo visível de conteúdo salvo, por si só, comprova muito pouco.
Use este plano de medição proposto para manter evidências concretas. Ele define observações a coletar, sem alegar uma pontuação de desempenho ou um limite de precisão.
| Pergunta | Evidência a registrar | Acompanhamento |
|---|---|---|
| O conteúdo foi preservado? | Estruturas originais e restauradas, configuração das extensões | Investigar nós ou atributos ausentes |
| A restauração foi silenciosa como previsto? | Eventos observados e solicitações de gravação resultantes | Corrigir ouvintes de eventos não intencionais |
| Qual salvamento foi aceito? | Revisão da solicitação, confirmação do backend, leitura de conferência posterior | Resolver gravações desatualizadas e estados enganosos |
| A colaboração reconectou corretamente? | Identidade do estado persistido e resultado da mesclagem observado | Investigar a duplicação antes da disponibilização |
Limitações e compromissos operacionais
A validade do documento não equivale a segurança ou durabilidade
A compatibilidade do esquema abrange um limite. A autorização no servidor precisa de uma revisão própria, assim como a validação das solicitações recebidas. Examine separadamente o tratamento de conteúdo privado e os contextos de saída não confiáveis. A política de retenção, os backups e a recuperação de falhas de gravação também precisam de decisões específicas da aplicação. Este guia não fornece uma auditoria de segurança nem uma garantia de conformidade.
Uma renderização de HTML bem-sucedida não estabelece um ciclo de salvar e restaurar sem perdas. Considere a limitação documentada da verificação, junto com o aviso sobre o estado binário colaborativo. A serialização não pode fornecer a política de conflitos do backend nem a durabilidade do armazenamento.
Delimite o trabalho de implementação com honestidade
Extensões personalizadas exigem manutenção. Documentos antigos precisam de decisões de migração, e o tratamento de conflitos requer implementação e testes. Adicionar colaboração também significa operar sua infraestrutura. Reserve recursos para essas responsabilidades antes de escolher o projeto mais complexo.
Este guia não apresenta economia medida, melhoria de desempenho nem resultado de implantação. O trecho de código continua sem execução. Execute as verificações propostas com suas próprias dependências e dados de teste antes de afirmar que o comportamento foi verificado e registre os resultados não resolvidos. A revisão da documentação fornece uma base para os testes; não equivale a um teste aprovado da aplicação.
Escolha um contrato de persistência e depois teste o ciclo de salvar e restaurar
Mapeie seu formato atual de salvamento e a configuração das extensões. Em seguida, examine o comportamento da restauração e o que a interface trata como um salvamento aceito. Registre quais relações precisam ser preservadas. Teste um documento representativo e, depois, dados de teste antigos e um salvamento com falha. Amplie a cobertura quando entender esses resultados. Uma nota que renderiza corretamente é uma observação inicial, não um motivo para parar de testar.
Pontos principais
- 1Escolha JSON para documentos editáveis, HTML para renderização ou intercâmbio e estado binário persistido do Yjs para colaboração.
- 2O JSON do documento não é uma cópia completa da sessão do editor, do histórico de desfazer ou do estado colaborativo.
- 3Trate as extensões configuradas como parte do contrato de restauração e preserve os dados originais durante as migrações.
- 4No Tiptap 3.x, setContent emite uma atualização por padrão; suprima-a deliberadamente ao restaurar conteúdo em um fluxo de salvamento automático baseado em atualizações.
- 5Separe edições locais, gravações em andamento e confirmações do backend sob uma política explícita de conflitos.
- 6Execute verificações de fidelidade do conteúdo, gravações desatualizadas, recuperação e reconexões pertinentes no seu próprio ambiente antes de afirmar que a persistência foi verificada.
Conclusão
Comece pela representação de que seu produto precisa e torne explícito seu contrato de extensões. Use o 3R para revisar a restauração e a aceitação de salvamentos e, depois, teste essas decisões com seus próprios dados de teste e a política do backend. Se uma nota perder uma relação ou um indicador de conteúdo salvo se antecipar ao backend, resolva essa lacuna antes de adicionar mais recursos. Para obter ajuda na definição do escopo de uma revisão da persistência do editor ou dos limites de migração em um fluxo de escrita com assistência de IA, considere a Optijara.
Perguntas frequentes
Devo salvar o conteúdo do Tiptap como JSON ou HTML, e o JSON preserva o histórico do editor?
Use JSON para uma persistência flexível de documentos editáveis, como recomenda o Tiptap. Use HTML para renderização ou intercâmbio com extensões compatíveis. `editor.getJSON()` retorna o documento atual, não a sessão completa, a seleção, o histórico de desfazer ou o estado do Yjs. Nenhum dos formatos fornece tratamento de conflitos no backend.
Como restauro o conteúdo do Tiptap sem acionar um salvamento automático baseado em atualizações?
Use `editor.commands.setContent(savedContent, { emitUpdate: false, errorOnInvalidContent: true })` com um editor compatível já existente. Na versão 3.x, `emitUpdate` tem `true` como padrão, ao contrário da v2. Suprimir essa atualização não interrompe todos os ouvintes de eventos da aplicação nem todas as condições de corrida no salvamento. Retenha os dados originais e trate os erros de restauração explicitamente.
Por que nós ou marcas podem desaparecer quando o conteúdo salvo é carregado?
O esquema das extensões do editor de destino pode não oferecer suporte a eles. Revise as extensões ausentes e as migrações e preserve os dados originais. `enableContentCheck` tem `false` como padrão; a verificação de HTML pode não detectar marcas sem suporte. A verificação de conteúdo não é um mecanismo de migração nem um mecanismo universal de recuperação.
Posso gerar HTML a partir do JSON do Tiptap no servidor?
Sim. Use o utilitário documentado `generateHTML` de `@tiptap/html` com as extensões pertinentes para uso no servidor ou no navegador. A variante de `@tiptap/core` é exclusiva do navegador. A geração de HTML não fornece uma garantia geral de sanitização; avalie separadamente o contexto da saída e os valores não confiáveis.
Posso persistir um documento colaborativo do Yjs como JSON?
Não como substituto do estado colaborativo. O Hocuspocus exige dados binários `Uint8Array` codificados pelo Yjs. O JSON pode ser uma projeção adicional, mas recriar um `Y.Doc` a partir de JSON na reconexão pode prejudicar a mesclagem e duplicar conteúdo. Autorização, backups e migrações de esquema continuam sendo responsabilidades separadas.
Fontes
- https://tiptap.dev/docs/editor/core-concepts/persistence
- https://tiptap.dev/docs/editor/core-concepts/schema
- https://tiptap.dev/docs/editor/api/commands/content/set-content
- https://tiptap.dev/docs/editor/api/events
- https://tiptap.dev/docs/editor/api/utilities/html
- https://tiptap.dev/docs/hocuspocus/guides/persistence
- https://tiptap.dev/docs/editor/api/editor
Escrito por
Hamza DiazHamza Diaz é o fundador da Optijara, onde cria agentes de IA práticos, sistemas de automação e fluxos de trabalho do Copilot para empresas de serviços. Ele escreve sobre operações de IA, estratégia de agentes e implementação no mundo real para equipes que querem sistemas úteis em vez de exagero.
