Skip to content

Modelos de Datos de Plannotator

Este apéndice presenta todos los modelos de datos utilizados por Plannotator, incluyendo las estructuras de datos principales para revisiones de planes, revisiones de código y compartición de URLs.

Resumen de los Modelos de Datos Principales

Plannotator define los siguientes modelos de datos principales utilizando TypeScript:

ModeloUsoUbicación de definición
AnnotationAnotaciones en revisiones de planespackages/ui/types.ts:11-33
BlockBloques de contenido después del análisis de Markdownpackages/ui/types.ts:35-44
CodeAnnotationAnotaciones en revisiones de códigopackages/ui/types.ts:55-66
ShareableAnnotationFormato reducido de anotaciones para compartir por URLpackages/ui/utils/sharing.ts:14-19

Annotation (Anotación de Plan)

Annotation representa una anotación en revisiones de planes, utilizada para marcar eliminaciones, inserciones, reemplazos o comentarios en el plan.

Definición Completa

typescript
export interface Annotation {
  id: string;              // Identificador único
  blockId: string;         // ID del Block asociado (obsoleto, mantenido por compatibilidad)
  startOffset: number;     // Desplazamiento inicial (obsoleto, mantenido por compatibilidad)
  endOffset: number;       // Desplazamiento final (obsoleto, mantenido por compatibilidad)
  type: AnnotationType;     // Tipo de anotación
  text?: string;           // Contenido del comentario (para INSERTION/REPLACEMENT/COMMENT)
  originalText: string;    // Texto original anotado
  createdA: number;        // Marca de tiempo de creación
  author?: string;         // Identidad del colaborador (para compartir por URL)
  imagePaths?: string[];    // Rutas de imágenes adjuntas
  startMeta?: {            // Metadatos de selección entre elementos de web-highlighter
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
  endMeta?: {              // Metadatos de selección final entre elementos de web-highlighter
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
}

Enumeración AnnotationType

typescript
export enum AnnotationType {
  DELETION = 'DELETION',           // Eliminar este contenido
  INSERTION = 'INSERTION',         // Insertar este contenido
  REPLACEMENT = 'REPLACEMENT',     // Reemplazar este contenido
  COMMENT = 'COMMENT',             // Comentar este contenido
  GLOBAL_COMMENT = 'GLOBAL_COMMENT', // Comentario global (sin asociación a texto específico)
}

Descripción de Campos

CampoTipoRequeridoDescripción
idstringIdentificador único, generalmente un UUID generado automáticamente
blockIdstringID del Block asociado (obsoleto, mantenido por compatibilidad)
startOffsetnumberDesplazamiento inicial del carácter (obsoleto, mantenido por compatibilidad)
endOffsetnumberDesplazamiento final del carácter (obsoleto, mantenido por compatibilidad)
typeAnnotationTypeTipo de anotación (DELETION/INSERTION/REPLACEMENT/COMMENT/GLOBAL_COMMENT)
textstringContenido del comentario (completar para INSERTION/REPLACEMENT/COMMENT)
originalTextstringTexto original anotado
createdAnumberMarca de tiempo de creación (milisegundos)
authorstringIdentificador de identidad del colaborador (para distinguir autores al compartir por URL)
imagePathsstring[]Arreglo de rutas de imágenes adjuntas
startMetaobjectMetadatos iniciales de selección entre elementos de web-highlighter
endMetaobjectMetadatos finales de selección entre elementos de web-highlighter

Ejemplos

Anotación de Eliminación

typescript
{
  id: "anno-001",
  blockId: "block-0",
  startOffset: 0,
  endOffset: 50,
  type: AnnotationType.DELETION,
  originalText: "Esta parte no es necesaria",
  createdA: Date.now(),
}

Anotación de Reemplazo

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

Comentario Global

typescript
{
  id: "anno-003",
  blockId: "",
  startOffset: 0,
  endOffset: 0,
  type: AnnotationType.GLOBAL_COMMENT,
  text: "En general, el plan es muy claro",
  originalText: "",
  createdA: Date.now(),
}

Descripción de Campos Obsoletos

Los campos blockId, startOffset y endOffset se utilizaban en versiones anteriores para resaltado de texto basado en desplazamiento de caracteres. La versión actual utiliza la biblioteca web-highlighter, que implementa selección entre elementos mediante startMeta y endMeta. Estos campos se mantienen únicamente por compatibilidad.

Block (Bloque de Plan)

Block representa un bloque de contenido después del análisis de texto Markdown, utilizado para mostrar el contenido del plan de forma estructurada.

Definición Completa

typescript
export interface Block {
  id: string;              // Identificador único
  type: BlockType;         // Tipo de bloque
  content: string;        // Contenido en texto plano
  level?: number;         // Nivel (para títulos o listas)
  language?: string;      // Lenguaje del código (para bloques de código)
  checked?: boolean;      // Estado de la casilla de verificación (para elementos de lista)
  order: number;          // Orden de clasificación
  startLine: number;      // Número de línea inicial (1-based)
}

Tipo BlockType

typescript
type BlockType =
  | 'paragraph'     // Párrafo
  | 'heading'       // Título
  | 'blockquote'    // Bloque de cita
  | 'code'          // Bloque de código
  | 'hr'            // Línea divisoria
  | 'table';        // Tabla

Descripción de Campos

CampoTipoRequeridoDescripción
idstringIdentificador único, formato block-{número}
typeBlockTypeTipo de bloque (paragraph/heading/blockquote/list-item/code/hr/table)
contentstringContenido en texto plano del bloque
levelnumberNivel: títulos son 1-6, elementos de lista son nivel de sangría
languagestringLenguaje del bloque de código (como 'typescript', 'rust')
checkedbooleanEstado de la casilla de verificación del elemento de lista (true = marcado, false = sin marcar)
ordernumberNúmero de orden, utilizado para mantener la secuencia de bloques
startLinenumberNúmero de línea inicial en el Markdown fuente (comenzando desde 1)

Ejemplos

Bloque de Título

typescript
{
  id: "block-0",
  type: "heading",
  content: "Plan de Implementación",
  level: 1,
  order: 1,
  startLine: 1,
}

Bloque de Párrafo

typescript
{
  id: "block-1",
  type: "paragraph",
  content: "Este es un párrafo con algo de texto.",
  order: 2,
  startLine: 3,
}

Bloque de Código

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

Elemento de Lista (con Casilla de Verificación)

typescript
{
  id: "block-3",
  type: "list-item",
  content: "Completar módulo de autenticación",
  level: 0,
  checked: true,
  order: 4,
  startLine: 10,
}

Análisis de Markdown

Plannotator utiliza un analizador de Markdown simplificado personalizado (parseMarkdownToBlocks) para convertir el Markdown fuente en un arreglo Block[]. El analizador soporta sintaxis común como títulos, listas, bloques de código, tablas y bloques de cita.

CodeAnnotation (Anotación de Código)

CodeAnnotation representa una anotación a nivel de línea en revisiones de código, utilizada para agregar retroalimentación a líneas o rangos específicos del diff de Git.

Definición Completa

typescript
export interface CodeAnnotation {
  id: string;              // Identificador único
  type: CodeAnnotationType;  // Tipo de anotación
  filePath: string;         // Ruta del archivo
  lineStart: number;        // Número de línea inicial
  lineEnd: number;          // Número de línea final
  side: 'old' | 'new';     // Lado ('old' = línea eliminada, 'new' = línea nueva)
  text?: string;           // Contenido del comentario
  suggestedCode?: string;    // Código sugerido (para tipo suggestion)
  createdAt: number;        // Marca de tiempo de creación
  author?: string;         // Identidad del colaborador
}

Tipo CodeAnnotationType

typescript
export type CodeAnnotationType =
  | 'comment'      // Comentario normal
  | 'suggestion'  // Sugerencia de modificación (requiere suggestedCode)
  | 'concern';     // Punto de atención (recordatorio de tema importante)

Descripción de Campos

CampoTipoRequeridoDescripción
idstringIdentificador único
typeCodeAnnotationTypeTipo de anotación (comment/suggestion/concern)
filePathstringRuta relativa del archivo anotado (como src/auth.ts)
lineStartnumberNúmero de línea inicial (comenzando desde 1)
lineEndnumberNúmero de línea final (comenzando desde 1)
side'old' | 'new'Lado: 'old' = línea eliminada (versión antigua), 'new' = línea nueva (versión nueva)
textstringContenido del comentario
suggestedCodestringCódigo sugerido (requerido cuando type es 'suggestion')
createdAtnumberMarca de tiempo de creación (milisegundos)
authorstringIdentificador de identidad del colaborador

Descripción del Campo side

El campo side corresponde a la vista de diff de la biblioteca @pierre/diffs:

Valor sideCorrespondencia @pierre/diffsDescripción
'old'deletionsLíneas eliminadas (contenido en versión antigua)
'new'additionsLíneas añadidas (contenido en versión nueva)

Ejemplos

Comentario Normal (Línea Nueva)

typescript
{
  id: "code-anno-001",
  type: "comment",
  filePath: "src/auth.ts",
  lineStart: 15,
  lineEnd: 15,
  side: "new",
  text: "Aquí es necesario manejar errores",
  createdAt: Date.now(),
}

Sugerencia de Modificación (Línea Eliminada)

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

ShareableAnnotation (Anotación Compartible)

ShareableAnnotation es un formato reducido de anotaciones para compartir por URL, representado mediante tuplas de arreglo para reducir el tamaño del payload.

Definición Completa

typescript
export type ShareableAnnotation =
  | ['D', string, string | null, string[]?]           // Deletion: [type, original, author, images]
  | ['R', string, string, string | null, string[]?]   // Replacement: [type, original, replacement, author, images]
  | ['C', string, string, string | null, string[]?]   // Comment: [type, original, comment, author, images]
  | ['I', string, string, string | null, string[]?]   // Insertion: [type, context, new text, author, images]
  | ['G', string, string | null, string[]?];          // Global Comment: [type, comment, author, images]

Descripción de Tipos

TipoPrimer carácterEstructura de tuplaDescripción
DELETION'D'['D', original, author?, images?]Contenido eliminado
REPLACEMENT'R'['R', original, replacement, author?, images?]Contenido reemplazado
COMMENT'C'['C', original, comment, author?, images?]Contenido del comentario
INSERTION'I'['I', context, newText, author?, images?]Contenido insertado
GLOBAL_COMMENT'G'['G', comment, author?, images?]Comentario global

Ejemplos

typescript
// Eliminación
['D', 'Contenido a eliminar', null, []]

// Reemplazo
['R', 'Texto original', 'Reemplazo por', null, ['/tmp/img.png']]

// Comentario
['C', 'Este código', 'Sugiero optimizar', null, []]

// Inserción
['I', 'Contexto', 'Nuevo contenido a insertar', null, []]

// Comentario global
['G', 'Muy bien en general', null, []]

¿Por qué usar formato reducido?

Usar tuplas de arreglo en lugar de objetos puede reducir el tamaño del payload, haciendo las URLs más cortas después de compresión. Por ejemplo:

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

SharePayload (Payload de Compartición)

SharePayload es la estructura de datos completa para compartir por URL, incluyendo contenido del plan y anotaciones.

Definición Completa

typescript
export interface SharePayload {
  p: string;                  // Texto Markdown del plan
  a: ShareableAnnotation[];    // Arreglo de anotaciones (formato reducido)
  g?: string[];              // Rutas de archivos adjuntos globales (imágenes)
}

Descripción de Campos

CampoTipoRequeridoDescripción
pstringContenido Markdown del plan original
aShareableAnnotation[]Arreglo de anotaciones (usando formato reducido ShareableAnnotation)
gstring[]Rutas de archivos adjuntos globales (imágenes no asociadas a anotaciones específicas)

Ejemplo

typescript
{
  p: "# Plan de Implementación\n\n1. Añadir autenticación\n2. Añadir UI",
  a: [
    ['C', 'Añadir autenticación', 'Necesario soportar OAuth', null, []],
    ['G', 'Plan general claro', null, []],
  ],
  g: ['/tmp/plannotator/diagram.png'],
}

Frontmatter (Metadatos Frontmatter)

Frontmatter representa los metadatos YAML en la parte superior del archivo Markdown, utilizados para almacenar información adicional.

Definición Completa

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

Ejemplo

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

### Plan de Implementación (ejemplo)
...

Después del análisis:

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

Usos del Frontmatter

Plannotator genera automáticamente frontmatter al guardar planes en Obsidian, incluyendo información como marca de tiempo de creación y etiquetas de origen, facilitando la gestión y búsqueda de notas.

Tipos Auxiliares Relacionados

EditorMode (Modo de Editor)

typescript
export type EditorMode = 'selection' | 'comment' | 'redline';
  • 'selection':Modo de selección de texto
  • 'comment':Modo de comentario
  • 'redline':Modo de anotación de línea roja

DiffResult (Resultado de Diff)

typescript
export interface DiffResult {
  original: string;    // Contenido original
  modified: string;    // Contenido modificado
  diffText: string;    // Texto de diff unificado
}

DiffAnnotationMetadata (Metadatos de Anotación de Diff)

typescript
export interface DiffAnnotationMetadata {
  annotationId: string;      // ID de la anotación asociada
  type: CodeAnnotationType;  // Tipo de anotación
  text?: string;            // Contenido del comentario
  suggestedCode?: string;   // Código sugerido
  author?: string;          // Autor
}

SelectedLineRange (Rango de Líneas Seleccionadas)

typescript
export interface SelectedLineRange {
  start: number;                      // Número de línea inicial
  end: number;                        // Número de línea final
  side: 'deletions' | 'additions';   // Lado (corresponde a la vista de diff de @pierre/diffs)
  endSide?: 'deletions' | 'additions'; // Lado final (para selección entre lados)
}

Relaciones de Conversión de Datos

Annotation ↔ ShareableAnnotation

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

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

Pérdida de Coordenadas

Los campos blockId, startOffset y endOffset en el Annotation generado por fromShareable están vacíos o son 0. Es necesario recuperar la posición exacta mediante coincidencia de texto o web-highlighter.

Markdown ↔ Block[]

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

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

Resumen de esta Lección

Este apéndice presentó todos los modelos de datos principales de Plannotator:

  • Annotation:Anotaciones en revisiones de planes, soportando tipos como eliminación, inserción, reemplazo y comentario
  • Block:Bloques de contenido después del análisis de Markdown, utilizados para mostrar planes de forma estructurada
  • CodeAnnotation:Anotaciones a nivel de línea en revisiones de código, soportando comentarios y sugerencias
  • ShareableAnnotation:Formato reducido para compartir por URL, reduciendo el tamaño del payload
  • SharePayload:Estructura de datos completa para compartir por URL

Estos modelos de datos se utilizan ampliamente en funciones como revisiones de planes, revisiones de código y compartición por URL. Comprenderlos ayuda a personalizar y extender Plannotator en profundidad.

Avance del Próximo Tema

En el próximo tema aprenderemos Explicación de Licencia de Plannotator.

Verás:

  • Cláusulas principales de Business Source License 1.1 (BSL)
  • Usos permitidos y restricciones comerciales
  • Cronograma de conversión a Apache 2.0 en 2030
  • Cómo obtener una licencia comercial

Apéndice: Referencia del Código Fuente

Haz clic para ver la ubicación del código fuente

Tiempo de actualización:2026-01-24

FunciónRuta del archivoNúmero de línea
Interfaz Annotationpackages/ui/types.ts11-33
Enumeración AnnotationTypepackages/ui/types.ts1-7
Interfaz Blockpackages/ui/types.ts35-44
Interfaz CodeAnnotationpackages/ui/types.ts55-66
Tipo CodeAnnotationTypepackages/ui/types.ts53
Tipo ShareableAnnotationpackages/ui/utils/sharing.ts14-19
Interfaz 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 clave

  • Ninguna

Funciones clave

  • toShareable(annotations: Annotation[]): ShareableAnnotation[]:Convierte anotaciones completas a formato reducido
  • fromShareable(data: ShareableAnnotation[]): Annotation[]:Recupera formato reducido a anotaciones completas
  • parseMarkdownToBlocks(markdown: string): Block[]:Analiza Markdown a arreglo Block
  • exportDiff(blocks: Block[], annotations: Annotation[]): string:Exporta anotaciones a formato Markdown