Skip to content

Plannotator データモデル

本付録では、Plannotator で使用されるすべてのデータモデルを紹介します。これには、計画レビュー、コードレビュー、URL 共有などのコアデータ構造が含まれます。

コアデータモデル概要

Plannotator は TypeScript を使用して以下のコアデータモデルを定義しています:

モデル用途定義場所
Annotation計画レビューでのコメントpackages/ui/types.ts:11-33
BlockMarkdown 解析後のコンテンツブロックpackages/ui/types.ts:35-44
CodeAnnotationコードレビューでのコメントpackages/ui/types.ts:55-66
ShareableAnnotationURL 共有のための簡素化コメント形式packages/ui/utils/sharing.ts:14-19

Annotation(計画コメント)

Annotation は計画レビューでのコメントを表し、計画の削除、挿入、置換、またはコメントをマークするために使用されます。

完全定義

typescript
export interface Annotation {
  id: string;              // 一意識別子
  blockId: string;         // 関連する Block ID(非推奨、互換性のために保持)
  startOffset: number;     // 開始オフセット(非推奨、互換性のために保持)
  endOffset: number;       // 終了オフセット(非推奨、互換性のために保持)
  type: AnnotationType;     // コメントタイプ
  text?: string;           // コメント内容(INSERTION/REPLACEMENT/COMMENT 用)
  originalText: string;    // コメントされた元テキスト
  createdA: number;        // 作成タイムスタンプ
  author?: string;         // 協力者身份(URL 共有用)
  imagePaths?: string[];    // 追加画像パス
  startMeta?: {            // web-highlighter 跨要素選択メタデータ
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
  endMeta?: {              // web-highlighter 跨要素選択メタデータ
    parentTagName: string;
    parentIndex: number;
    textOffset: number;
  };
}

AnnotationType 列挙型

typescript
export enum AnnotationType {
  DELETION = 'DELETION',           // このコンテンツを削除
  INSERTION = 'INSERTION',         // このコンテンツを挿入
  REPLACEMENT = 'REPLACEMENT',     // このコンテンツを置換
  COMMENT = 'COMMENT',             // このコンテンツにコメント
  GLOBAL_COMMENT = 'GLOBAL_COMMENT', // グローバルコメント(特定テキストに紐付けない)
}

フィールド説明

フィールドタイプ必須説明
idstring一意識別子、通常は自動生成された UUID
blockIdstring関連する Block ID(非推奨、互換性のために保持)
startOffsetnumber開始文字オフセット(非推奨、互換性のために保持)
endOffsetnumber終了文字オフセット(非推奨、互換性のために保持)
typeAnnotationTypeコメントタイプ(DELETION/INSERTION/REPLACEMENT/COMMENT/GLOBAL_COMMENT)
textstringコメント内容(INSERTION/REPLACEMENT/COMMENT 時に記入)
originalTextstringコメントされた元テキスト
createdAnumber作成タイムスタンプ(ミリ秒)
authorstring協力者身份識別子(URL 共有時に作者を区別するため)
imagePathsstring[]追加画像パス配列
startMetaobjectweb-highlighter 跨要素選択の開始メタデータ
endMetaobjectweb-highlighter 跨要素選択の終了メタデータ

削除コメント

typescript
{
  id: "anno-001",
  blockId: "block-0",
  startOffset: 0,
  endOffset: 50,
  type: AnnotationType.DELETION,
  originalText: "この部分は不要",
  createdA: Date.now(),
}

置換コメント

typescript
{
  id: "anno-002",
  blockId: "block-0",
  startOffset: 0,
  endOffset: 50,
  type: AnnotationType.REPLACEMENT,
  text: "新しいコンテンツ",
  originalText: "元のコンテンツ",
  createdA: Date.now(),
  imagePaths: ["/tmp/plannotator/screenshot-001.png"],
}

グローバルコメント

typescript
{
  id: "anno-003",
  blockId: "",
  startOffset: 0,
  endOffset: 0,
  type: AnnotationType.GLOBAL_COMMENT,
  text: "全体として計画が明確です",
  originalText: "",
  createdA: Date.now(),
}

非推奨フィールドの説明

blockIdstartOffsetendOffset フィールドは旧バージョンで文字オフセットに基づくテキストハイライトに使用されていました。現在のバージョンでは web-highlighter ライブラリを使用し、startMetaendMeta を通して跨要素選択を実現しており、これらのフィールドは互換性のためにのみ保持されています。

Block(計画ブロック)

Block は Markdown テキスト解析後のコンテンツブロックを表し、計画内容を構造的に表示するために使用されます。

完全定義

typescript
export interface Block {
  id: string;              // 一意識別子
  type: BlockType;         // ブロックタイプ
  content: string;        // プレーンテキストコンテンツ
  level?: number;         // レベル(見出しやリスト用)
  language?: string;      // コード言語(コードブロック用)
  checked?: boolean;      // チェックボックス状態(リスト項目用)
  order: number;          // ソート順序
  startLine: number;      // 開始行番号(1-based)
}

BlockType タイプ

typescript
type BlockType =
  | 'paragraph'     // 段落
  | 'heading'       // 見出し
  | 'blockquote'    // 引用ブロック
|---|
  | 'code'          // コードブロック
  | 'hr'            // 区切り線
  | 'table';        // テーブル

フィールド説明

フィールドタイプ必須説明
idstring一意識別子、形式は block-{数字}
typeBlockTypeブロックタイプ(paragraph/heading/blockquote/list-item/code/hr/table)
contentstringブロックのプレーンテキストコンテンツ
levelnumberレベル:見出しは 1-6、リスト項目はインデントレベル
languagestringコードブロックの言語('typescript'、'rust' など)
checkedbooleanリスト項目のチェックボックス状態(true = チェック済み、false = 未チェック)
ordernumberソート番号、ブロックの順序を維持するため
startLinenumberソース Markdown での開始行番号(1 から開始)

見出しブロック

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

段落ブロック

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

コードブロック

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

リスト項目(チェックボックス付き)

typescript
{
  id: "block-3",
  type: "list-item",
  content: "認証モジュールを完成",
  level: 0,
  checked: true,
  order: 4,
  startLine: 10,
}

Markdown 解析

Plannotator はカスタムの簡素化 Markdown パーサー(parseMarkdownToBlocks)を使用して、ソース Markdown を Block[] 配列に変換します。パーサーは見出し、リスト、コードブロック、テーブル、引用ブロックなどの一般的な構文をサポートしています。

CodeAnnotation(コードコメント)

CodeAnnotation はコードレビューでの行レベルコメントを表し、Git diff の特定の行または範囲にフィードバックを追加するために使用されます。

完全定義

typescript
export interface CodeAnnotation {
  id: string;              // 一意識別子
  type: CodeAnnotationType;  // コメントタイプ
  filePath: string;         // ファイルパス
  lineStart: number;        // 開始行番号
  lineEnd: number;          // 終了行番号
  side: 'old' | 'new';     // 側('old' = 削除行、'new' = 新規行)
  text?: string;           // コメント内容
  suggestedCode?: string;    // 提案コード(suggestion タイプ用)
  createdAt: number;        // 作成タイムスタンプ
  author?: string;         // 協力者身份
}

CodeAnnotationType タイプ

typescript
export type CodeAnnotationType =
  | 'comment'      // 通常コメント
  | 'suggestion'  // 修正提案(suggestedCode が必要)
  | 'concern';     // 懸念点(重要事項の注意)

フィールド説明

フィールドタイプ必須説明
idstring一意識別子
typeCodeAnnotationTypeコメントタイプ(comment/suggestion/concern)
filePathstringコメントされたファイルの相対パス(src/auth.ts など)
lineStartnumber開始行番号(1 から開始)
lineEndnumber終了行番号(1 から開始)
side'old' | 'new'側:'old' = 削除行(旧バージョン)、'new' = 新規行(新バージョン)
textstringコメント内容
suggestedCodestring提案コード(type が 'suggestion' の場合必須)
createdAtnumber作成タイムスタンプ(ミリ秒)
authorstring協力者身份識別子

side フィールドの説明

side フィールドは @pierre/diffs ライブラリの diff ビューに対応しています:

side 値@pierre/diffs 対応説明
'old'deletions削除された行(旧バージョンのコンテンツ)
'new'additions新規追加された行(新バージョンのコンテンツ)

通常コメント(新規行)

typescript
{
  id: "code-anno-001",
  type: "comment",
  filePath: "src/auth.ts",
  lineStart: 15,
  lineEnd: 15,
  side: "new",
  text: "ここでエラー状況を処理する必要があります",
  createdAt: Date.now(),
}

修正提案(削除行)

typescript
{
  id: "code-anno-002",
  type: "suggestion",
  filePath: "src/auth.ts",
  lineStart: 10,
  lineEnd: 12,
  side: "old",
  text: "async/await を使用することをお勧めします",
  suggestedCode: "async function authenticate() {\n  const user = await fetchUser();\n  return user;\n}",
  createdAt: Date.now(),
}

ShareableAnnotation(共有コメント)

ShareableAnnotation は URL 共有のための簡素化コメント形式であり、配列タプルで表現することでペイロードサイズを削減します。

完全定義

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]

タイプ説明

タイプ先頭文字タプル構造説明
DELETION'D'['D', original, author?, images?]コンテンツを削除
REPLACEMENT'R'['R', original, replacement, author?, images?]コンテンツを置換
COMMENT'C'['C', original, comment, author?, images?]コンテンツにコメント
INSERTION'I'['I', context, newText, author?, images?]コンテンツを挿入
GLOBAL_COMMENT'G'['G', comment, author?, images?]グローバルコメント

typescript
// 削除
['D', '削除するコンテンツ', null, []]

// 置換
['R', '元テキスト', '置換後', null, ['/tmp/img.png']]

// コメント
['C', 'このコード', '最適化を提案', null, []]

// 挿入
['I', 'コンテキスト', '挿入する新コンテンツ', null, []]

// グローバルコメント
['G', '全体が良い', null, []]

なぜ簡素化形式を使用するのか?

配列タプルではなくオブジェクトを使用すると、ペイロードサイズを削減でき、圧縮後の URL が短くなります。例えば:

  • オブジェクト形式:{"type":"DELETION","originalText":"text"} → 38 バイト
  • 簡素化形式:["D","text",null,[]] → 18 バイト

SharePayload(共有ペイロード)

SharePayload は URL 共有の完全なデータ構造であり、計画コンテンツとコメントを含みます。

完全定義

typescript
export interface SharePayload {
  p: string;                  // 計画の Markdown テキスト
  a: ShareableAnnotation[];    // コメント配列(簡素化形式)
  g?: string[];              // グローバル添付ファイルパス(画像)
}

フィールド説明

フィールドタイプ必須説明
pstring元計画の Markdown コンテンツ
aShareableAnnotation[]コメント配列(ShareableAnnotation 簡素化形式を使用)
gstring[]グローバル添付ファイルパス(特定のコメントに紐付けない画像)

typescript
{
  p: "# Implementation Plan\n\n1. Add auth\n2. Add UI",
  a: [
    ['C', 'Add auth', 'OAuth のサポートが必要', null, []],
    ['G', '全体の計画が明確', null, []],
  ],
  g: ['/tmp/plannotator/diagram.png'],
}

Frontmatter(フロントメタデータ)

Frontmatter は Markdown ファイルの先頭にある YAML メタデータを表し、追加情報を保存するために使用されます。

完全定義

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

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

### Implementation Plan(例)
...

解析後:

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

フロントメタデータの用途

Plannotator は計画を Obsidian に保存する際に自動的に frontmatter を生成し、作成時間、ソースタグなどの情報を含め、ノートの管理と検索を容易にします。

関連補助タイプ

EditorMode(エディタモード)

typescript
export type EditorMode = 'selection' | 'comment' | 'redline';
  • 'selection':テキスト選択モード
  • 'comment':コメントモード
  • 'redline':赤線註釈モード

DiffResult(Diff 結果)

typescript
export interface DiffResult {
  original: string;    // 元コンテンツ
  modified: string;    // 修正後コンテンツ
  diffText: string;    // Unified diff テキスト
}

DiffAnnotationMetadata(Diff コメントメタデータ)

typescript
export interface DiffAnnotationMetadata {
  annotationId: string;      // 関連するコメント ID
  type: CodeAnnotationType;  // コメントタイプ
  text?: string;            // コメント内容
  suggestedCode?: string;   // 提案コード
  author?: string;          // 作者
}

SelectedLineRange(選択された行範囲)

typescript
export interface SelectedLineRange {
  start: number;                      // 開始行番号
  end: number;                        // 終了行番号
  side: 'deletions' | 'additions';   // 側(@pierre/diffs の diff ビューに対応)
  endSide?: 'deletions' | 'additions'; // 終了側(跨側選択用)
}

データ変換関係

Annotation ↔ ShareableAnnotation

typescript
// 完全 → 簡素化
function toShareable(annotations: Annotation[]): ShareableAnnotation[]

// 簡素化 → 完全
function fromShareable(data: ShareableAnnotation[]): Annotation[]

座標の喪失

fromShareable で生成された AnnotationblockIdstartOffsetendOffset フィールドは空または 0 であり、テキスト一致または web-highlighter を通じて正確な位置を復元する必要があります。

Markdown ↔ Block[]

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

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

本課のまとめ

本付録では Plannotator のすべてのコアデータモデルを紹介しました:

  • Annotation:計画レビューでのコメント、削除、挿入、置換、コメントなどのタイプをサポート
  • Block:Markdown 解析後のコンテンツブロック、計画を構造的に表示するため
  • CodeAnnotation:コードレビューでの行レベルコメント、コメントと提案をサポート
  • ShareableAnnotation:URL 共有のための簡素化形式、ペイロードサイズを削減
  • SharePayload:URL 共有の完全なデータ構造

これらのデータモデルは、計画レビュー、コードレビュー、URL 共有などの機能で広く使用されています。それらを理解することで、Plannotator のカスタマイズと拡張に役立ちます。

次回予告

次回のレッスンでは Plannotator ライセンス説明 を学びます。

次の内容が含まれます:

  • Business Source License 1.1 (BSL) のコア条項
  • 許可される使用方法と商業的制限
  • 2030 年に Apache 2.0 に転換されるスケジュール
  • 商業ライセンスの取得方法

付録:ソースコード参照

クリックしてソースコードの場所を表示

更新日時:2026-01-24

機能ファイルパス行番号
Annotation インターフェースpackages/ui/types.ts11-33
AnnotationType 列挙型packages/ui/types.ts1-7
Block インターフェースpackages/ui/types.ts35-44
CodeAnnotation インターフェースpackages/ui/types.ts55-66
CodeAnnotationType タイプpackages/ui/types.ts53
ShareableAnnotation タイプpackages/ui/utils/sharing.ts14-19
SharePayload インターフェースpackages/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

重要定数

  • なし

重要関数

  • toShareable(annotations: Annotation[]): ShareableAnnotation[]:完全コメントを簡素化形式に変換
  • fromShareable(data: ShareableAnnotation[]): Annotation[]:簡素化形式を完全コメントに復元
  • parseMarkdownToBlocks(markdown: string): Block[]:Markdown を Block 配列に解析
  • exportDiff(blocks: Block[], annotations: Annotation[]): string:コメントを Markdown 形式でエクスポート