Skip to content

Modelos de Dados do Plannotator

Este apêndice apresenta todos os modelos de dados utilizados pelo Plannotator, incluindo as estruturas de dados principais para revisão de planos, revisão de código e compartilhamento via URL.

Visão Geral dos Modelos de Dados Principais

O Plannotator define os seguintes modelos de dados principais em TypeScript:

ModeloFinalidadeLocalização da Definição
AnnotationAnotações em revisões de planospackages/ui/types.ts:11-33
BlockBlocos de conteúdo após análise do Markdownpackages/ui/types.ts:35-44
CodeAnnotationAnotações em revisões de códigopackages/ui/types.ts:55-66
ShareableAnnotationFormato compacto de anotações para compartilhamento via URLpackages/ui/utils/sharing.ts:14-19

Annotation (Anotação de Plano)

Annotation representa uma anotação em revisões de planos, usada para marcar exclusões, inserções, substituições ou comentários no plano.

Definição Completa

typescript
export interface Annotation {
  id: string;              // Identificador único
  blockId: string;         // ID do Block associado (obsoleto, mantido para compatibilidade)
  startOffset: number;     // Deslocamento inicial (obsoleto, mantido para compatibilidade)
  endOffset: number;       // Deslocamento final (obsoleto, mantido para compatibilidade)
  type: AnnotationType;     // Tipo de anotação
  text?: string;           // Conteúdo do comentário (para INSERTION/REPLACEMENT/COMMENT)
  originalText: string;    // Texto original anotado
  createdA: number;        // Timestamp de criação
  author?: string;         // Identidade do colaborador (para compartilhamento via URL)
  imagePaths?: string[];    // Caminhos das imagens anexadas
  startMeta?: {            // Metadados do web-highlighter para seleção entre elementos
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
  endMeta?: {              // Metadados do web-highlighter para seleção entre elementos
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
}

Enumeração AnnotationType

typescript
export enum AnnotationType {
  DELETION = 'DELETION',           // Excluir este conteúdo
  INSERTION = 'INSERTION',         // Inserir este conteúdo
  REPLACEMENT = 'REPLACEMENT',     // Substituir este conteúdo
  COMMENT = 'COMMENT',             // Comentar este conteúdo
  GLOBAL_COMMENT = 'GLOBAL_COMMENT', // Comentário global (não associado a texto específico)
}

Descrição dos Campos

CampoTipoObrigatórioDescrição
idstringIdentificador único, geralmente um UUID gerado automaticamente
blockIdstringID do Block associado (obsoleto, mantido para compatibilidade)
startOffsetnumberDeslocamento inicial em caracteres (obsoleto, mantido para compatibilidade)
endOffsetnumberDeslocamento final em caracteres (obsoleto, mantido para compatibilidade)
typeAnnotationTypeTipo de anotação (DELETION/INSERTION/REPLACEMENT/COMMENT/GLOBAL_COMMENT)
textstringConteúdo do comentário (preenchido para INSERTION/REPLACEMENT/COMMENT)
originalTextstringTexto original anotado
createdAnumberTimestamp de criação (milissegundos)
authorstringIdentificador do colaborador (para distinguir autores no compartilhamento via URL)
imagePathsstring[]Array de caminhos das imagens anexadas
startMetaobjectMetadados iniciais do web-highlighter para seleção entre elementos
endMetaobjectMetadados finais do web-highlighter para seleção entre elementos

Exemplos

Anotação de Exclusão

typescript
{
  id: "anno-001",
  blockId: "block-0",
  startOffset: 0,
  endOffset: 50,
  type: AnnotationType.DELETION,
  originalText: "Esta parte não é necessária",
  createdA: Date.now(),
}

Anotação de Substituição

typescript
{
  id: "anno-002",
  blockId: "block-0",
  startOffset: 0,
  endOffset: 50,
  type: AnnotationType.REPLACEMENT,
  text: "Novo conteúdo",
  originalText: "Conteúdo original",
  createdA: Date.now(),
  imagePaths: ["/tmp/plannotator/screenshot-001.png"],
}

Comentário Global

typescript
{
  id: "anno-003",
  blockId: "",
  startOffset: 0,
  endOffset: 0,
  type: AnnotationType.GLOBAL_COMMENT,
  text: "No geral, o plano está muito claro",
  originalText: "",
  createdA: Date.now(),
}

Nota sobre Campos Obsoletos

Os campos blockId, startOffset e endOffset eram usados em versões anteriores para destaque de texto baseado em deslocamento de caracteres. A versão atual utiliza a biblioteca web-highlighter, implementando seleção entre elementos através de startMeta e endMeta. Esses campos são mantidos apenas para compatibilidade.

Block (Bloco de Plano)

Block representa um bloco de conteúdo após a análise do texto Markdown, usado para exibição estruturada do conteúdo do plano.

Definição Completa

typescript
export interface Block {
  id: string;              // Identificador único
  type: BlockType;         // Tipo de bloco
  content: string;        // Conteúdo em texto puro
  level?: number;         // Nível (para títulos ou listas)
  language?: string;      // Linguagem do código (para blocos de código)
  checked?: boolean;      // Estado da caixa de seleção (para itens de lista)
  order: number;          // Ordem de classificação
  startLine: number;      // Número da linha inicial (base 1)
}

Tipo BlockType

typescript
type BlockType =
  | 'paragraph'     // Parágrafo
  | 'heading'       // Título
  | 'blockquote'    // Bloco de citação
  | 'list-item'     // Item de lista
  | 'code'          // Bloco de código
  | 'hr'            // Linha divisória
  | 'table';        // Tabela

Descrição dos Campos

CampoTipoObrigatórioDescrição
idstringIdentificador único, formato block-{número}
typeBlockTypeTipo de bloco (paragraph/heading/blockquote/list-item/code/hr/table)
contentstringConteúdo em texto puro do bloco
levelnumberNível: 1-6 para títulos, nível de indentação para itens de lista
languagestringLinguagem do bloco de código (ex: 'typescript', 'rust')
checkedbooleanEstado da caixa de seleção do item de lista (true = marcado, false = desmarcado)
ordernumberNúmero de ordem, usado para manter a sequência dos blocos
startLinenumberNúmero da linha inicial no Markdown fonte (começando em 1)

Exemplos

Bloco de Título

typescript
{
  id: "block-0",
  type: "heading",
  content: "Implementation Plan",
  level: 1,
  order: 1,
  startLine: 1,
}

Bloco de Parágrafo

typescript
{
  id: "block-1",
  type: "paragraph",
  content: "This is a paragraph with some text.",
  order: 2,
  startLine: 3,
}

Bloco de Código

typescript
{
  id: "block-2",
  type: "code",
  content: "function hello() {\n  return 'world';\n}",
  language: "typescript",
  order: 3,
  startLine: 5,
}

Item de Lista (com caixa de seleção)

typescript
{
  id: "block-3",
  type: "list-item",
  content: "Concluir módulo de autenticação",
  level: 0,
  checked: true,
  order: 4,
  startLine: 10,
}

Análise de Markdown

O Plannotator utiliza um analisador Markdown simplificado personalizado (parseMarkdownToBlocks), que converte o Markdown fonte em um array Block[]. O analisador suporta sintaxes comuns como títulos, listas, blocos de código, tabelas e blocos de citação.

CodeAnnotation (Anotação de Código)

CodeAnnotation representa anotações em nível de linha em revisões de código, usadas para adicionar feedback a linhas ou intervalos específicos de um diff Git.

Definição Completa

typescript
export interface CodeAnnotation {
  id: string;              // Identificador único
  type: CodeAnnotationType;  // Tipo de anotação
  filePath: string;         // Caminho do arquivo
  lineStart: number;        // Número da linha inicial
  lineEnd: number;          // Número da linha final
  side: 'old' | 'new';     // Lado ('old' = linha removida, 'new' = linha adicionada)
  text?: string;           // Conteúdo do comentário
  suggestedCode?: string;    // Código sugerido (para tipo suggestion)
  createdAt: number;        // Timestamp de criação
  author?: string;         // Identidade do colaborador
}

Tipo CodeAnnotationType

typescript
export type CodeAnnotationType =
  | 'comment'      // Comentário comum
  | 'suggestion'  // Sugestão de modificação (requer suggestedCode)
  | 'concern';     // Ponto de atenção (lembrete de assunto importante)

Descrição dos Campos

CampoTipoObrigatórioDescrição
idstringIdentificador único
typeCodeAnnotationTypeTipo de anotação (comment/suggestion/concern)
filePathstringCaminho relativo do arquivo anotado (ex: src/auth.ts)
lineStartnumberNúmero da linha inicial (começando em 1)
lineEndnumberNúmero da linha final (começando em 1)
side'old' | 'new'Lado: 'old' = linha removida (versão antiga), 'new' = linha adicionada (versão nova)
textstringConteúdo do comentário
suggestedCodestringCódigo sugerido (obrigatório quando type é 'suggestion')
createdAtnumberTimestamp de criação (milissegundos)
authorstringIdentificador do colaborador

Explicação do Campo side

O campo side corresponde à visualização de diff da biblioteca @pierre/diffs:

Valor de sideCorrespondência em @pierre/diffsDescrição
'old'deletionsLinhas removidas (conteúdo da versão antiga)
'new'additionsLinhas adicionadas (conteúdo da versão nova)

Exemplos

Comentário Comum (linha adicionada)

typescript
{
  id: "code-anno-001",
  type: "comment",
  filePath: "src/auth.ts",
  lineStart: 15,
  lineEnd: 15,
  side: "new",
  text: "É necessário tratar casos de erro aqui",
  createdAt: Date.now(),
}

Sugestão de Modificação (linha removida)

typescript
{
  id: "code-anno-002",
  type: "suggestion",
  filePath: "src/auth.ts",
  lineStart: 10,
  lineEnd: 12,
  side: "old",
  text: "Sugiro usar async/await",
  suggestedCode: "async function authenticate() {\n  const user = await fetchUser();\n  return user;\n}",
  createdAt: Date.now(),
}

ShareableAnnotation (Anotação Compartilhável)

ShareableAnnotation é um formato compacto de anotação para compartilhamento via URL, representado como tuplas de array para reduzir o tamanho do payload.

Definição Completa

typescript
export type ShareableAnnotation =
  | ['D', string, string | null, string[]?]           // Deletion: [tipo, original, autor, imagens]
  | ['R', string, string, string | null, string[]?]   // Replacement: [tipo, original, substituição, autor, imagens]
  | ['C', string, string, string | null, string[]?]   // Comment: [tipo, original, comentário, autor, imagens]
  | ['I', string, string, string | null, string[]?]   // Insertion: [tipo, contexto, novo texto, autor, imagens]
  | ['G', string, string | null, string[]?];          // Global Comment: [tipo, comentário, autor, imagens]

Explicação dos Tipos

TipoCaractere InicialEstrutura da TuplaDescrição
DELETION'D'['D', original, autor?, imagens?]Excluir conteúdo
REPLACEMENT'R'['R', original, substituição, autor?, imagens?]Substituir conteúdo
COMMENT'C'['C', original, comentário, autor?, imagens?]Comentar conteúdo
INSERTION'I'['I', contexto, novoTexto, autor?, imagens?]Inserir conteúdo
GLOBAL_COMMENT'G'['G', comentário, autor?, imagens?]Comentário global

Exemplos

typescript
// Exclusão
['D', 'conteúdo a excluir', null, []]

// Substituição
['R', 'texto original', 'substituir por', null, ['/tmp/img.png']]

// Comentário
['C', 'este código', 'sugiro otimizar', null, []]

// Inserção
['I', 'contexto', 'novo conteúdo a inserir', null, []]

// Comentário global
['G', 'muito bom no geral', null, []]

Por que usar formato compacto?

Usar tuplas de array em vez de objetos reduz o tamanho do payload, resultando em URLs mais curtas após compressão. Por exemplo:

  • Formato de objeto: {"type":"DELETION","originalText":"text"} → 38 bytes
  • Formato compacto: ["D","text",null,[]] → 18 bytes

SharePayload (Payload de Compartilhamento)

SharePayload é a estrutura de dados completa para compartilhamento via URL, contendo o conteúdo do plano e as anotações.

Definição Completa

typescript
export interface SharePayload {
  p: string;                  // Texto Markdown do plano
  a: ShareableAnnotation[];    // Array de anotações (formato compacto)
  g?: string[];              // Caminhos de anexos globais (imagens)
}

Descrição dos Campos

CampoTipoObrigatórioDescrição
pstringConteúdo Markdown do plano original
aShareableAnnotation[]Array de anotações (usando formato compacto ShareableAnnotation)
gstring[]Caminhos de anexos globais (imagens não associadas a anotações específicas)

Exemplo

typescript
{
  p: "# Implementation Plan\n\n1. Add auth\n2. Add UI",
  a: [
    ['C', 'Add auth', 'Precisa suportar OAuth', null, []],
    ['G', 'Plano geral está claro', null, []],
  ],
  g: ['/tmp/plannotator/diagram.png'],
}

Frontmatter (Metadados Iniciais)

Frontmatter representa os metadados YAML no topo do arquivo Markdown, usados para armazenar informações adicionais.

Definição Completa

typescript
export interface Frontmatter {
  [key: string]: string | string[];
}

Exemplo

markdown
---
created: 2026-01-24T14:30:00.000Z
source: plannotator
tags: [authentication, typescript]
author: John Doe
---

### Implementation Plan (Exemplo)
...

Após análise:

typescript
{
  created: "2026-01-24T14:30:00.000Z",
  source: "plannotator",
  tags: ["authentication", "typescript"],
  author: "John Doe",
}

Uso dos Metadados Iniciais

O Plannotator gera automaticamente o frontmatter ao salvar planos no Obsidian, incluindo informações como data de criação e tags de origem, facilitando o gerenciamento e a busca de notas.

Tipos Auxiliares Relacionados

EditorMode (Modo do Editor)

typescript
export type EditorMode = 'selection' | 'comment' | 'redline';
  • 'selection': Modo de seleção de texto
  • 'comment': Modo de comentário
  • 'redline': Modo de anotação em vermelho

DiffResult (Resultado do Diff)

typescript
export interface DiffResult {
  original: string;    // Conteúdo original
  modified: string;    // Conteúdo modificado
  diffText: string;    // Texto do diff unificado
}

DiffAnnotationMetadata (Metadados de Anotação de Diff)

typescript
export interface DiffAnnotationMetadata {
  annotationId: string;      // ID da anotação associada
  type: CodeAnnotationType;  // Tipo de anotação
  text?: string;            // Conteúdo do comentário
  suggestedCode?: string;   // Código sugerido
  author?: string;          // Autor
}

SelectedLineRange (Intervalo de Linhas Selecionadas)

typescript
export interface SelectedLineRange {
  start: number;                      // Número da linha inicial
  end: number;                        // Número da linha final
  side: 'deletions' | 'additions';   // Lado (corresponde à visualização de diff do @pierre/diffs)
  endSide?: 'deletions' | 'additions'; // Lado final (para seleção entre lados)
}

Relações de Conversão de Dados

Annotation ↔ ShareableAnnotation

typescript
// Completo → Compacto
function toShareable(annotations: Annotation[]): ShareableAnnotation[]

// Compacto → Completo
function fromShareable(data: ShareableAnnotation[]): Annotation[]

Perda de Coordenadas

Os campos blockId, startOffset e endOffset nas Annotation geradas por fromShareable estarão vazios ou com valor 0. É necessário recuperar a posição exata através de correspondência de texto ou web-highlighter.

Markdown ↔ Block[]

typescript
// Markdown → Block[]
function parseMarkdownToBlocks(markdown: string): Block[]

// Block[] + Annotation[] → Markdown
function exportDiff(blocks: Block[], annotations: Annotation[]): string

Resumo da Lição

Este apêndice apresentou todos os modelos de dados principais do Plannotator:

  • Annotation: Anotações em revisões de planos, suportando tipos como exclusão, inserção, substituição e comentário
  • Block: Blocos de conteúdo após análise do Markdown, para exibição estruturada do plano
  • CodeAnnotation: Anotações em nível de linha em revisões de código, suportando comentários e sugestões
  • ShareableAnnotation: Formato compacto para compartilhamento via URL, reduzindo o tamanho do payload
  • SharePayload: Estrutura de dados completa para compartilhamento via URL

Esses modelos de dados são amplamente utilizados em funcionalidades como revisão de planos, revisão de código e compartilhamento via URL. Compreendê-los ajuda a personalizar e estender o Plannotator de forma aprofundada.

Prévia da Próxima Lição

Na próxima lição, aprenderemos sobre a Explicação da Licença do Plannotator.

Você verá:

  • Os termos principais da Business Source License 1.1 (BSL)
  • Usos permitidos e restrições comerciais
  • O cronograma de conversão para Apache 2.0 em 2030
  • Como obter uma licença comercial

Apêndice: Referência do Código-Fonte

Clique para expandir e ver a localização do código-fonte

Data de atualização: 2026-01-24

FuncionalidadeCaminho do ArquivoLinhas
Interface Annotationpackages/ui/types.ts11-33
Enumeração AnnotationTypepackages/ui/types.ts1-7
Interface Blockpackages/ui/types.ts35-44
Interface CodeAnnotationpackages/ui/types.ts55-66
Tipo CodeAnnotationTypepackages/ui/types.ts53
Tipo ShareableAnnotationpackages/ui/utils/sharing.ts14-19
Interface SharePayloadpackages/ui/utils/sharing.ts21-25
toShareable()packages/ui/utils/sharing.ts76-95
fromShareable()packages/ui/utils/sharing.ts102-155
parseMarkdownToBlocks()packages/ui/utils/parser.ts70-244
exportDiff()packages/ui/utils/parser.ts246-323
extractFrontmatter()packages/ui/utils/parser.ts14-63

Constantes Principais:

  • Nenhuma

Funções Principais:

  • toShareable(annotations: Annotation[]): ShareableAnnotation[]: Converte anotações completas para formato compacto
  • fromShareable(data: ShareableAnnotation[]): Annotation[]: Restaura formato compacto para anotações completas
  • parseMarkdownToBlocks(markdown: string): Block[]: Analisa Markdown em array de Block
  • exportDiff(blocks: Block[], annotations: Annotation[]): string: Exporta anotações para formato Markdown