summaryrefslogtreecommitdiffhomepage
path: root/.rules/docs/obsidian/editor-api.md
blob: 8db6463ce69ac2a13b6290d46d969362e693b29d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Obsidian Editor API

## Editor Class

Access via `MarkdownView.editor` or through editor commands. Abstracts CodeMirror 5/6.

```typescript
// Get editor from active view
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
if (view) {
  const editor = view.editor;
  // ...
}

// Or use editorCallback in commands
this.addCommand({
  id: 'my-cmd',
  name: 'My Command',
  editorCallback: (editor: Editor, ctx: MarkdownView | MarkdownFileInfo) => {
    // editor is available here
  },
});
```

### Cursor & Selection

| Method | Returns | Description |
|--------|---------|-------------|
| `getCursor(side?)` | `EditorPosition` | Get cursor position. `side`: `'from'`, `'to'`, `'head'`, `'anchor'` |
| `setCursor(pos)` | `void` | Set cursor position |
| `getSelection()` | `string` | Get selected text |
| `setSelection(anchor, head?)` | `void` | Set selection range |
| `setSelections(ranges, main?)` | `void` | Set multiple selections |
| `listSelections()` | `EditorSelection[]` | Get all selections |
| `somethingSelected()` | `boolean` | Check if anything is selected |
| `wordAt(pos)` | `EditorRange \| null` | Get word boundaries at position |

### EditorPosition

```typescript
interface EditorPosition {
  line: number;  // 0-based line number
  ch: number;    // 0-based character offset in line
}
```

### Reading Content

| Method | Returns | Description |
|--------|---------|-------------|
| `getValue()` | `string` | Entire document content |
| `getLine(line)` | `string` | Text at line (0-indexed) |
| `getRange(from, to)` | `string` | Text in range |
| `lineCount()` | `number` | Total lines |
| `lastLine()` | `number` | Last line number |

### Modifying Content

| Method | Description |
|--------|-------------|
| `setValue(content)` | Replace entire document |
| `setLine(n, text)` | Replace line content |
| `replaceRange(text, from, to?, origin?)` | Replace text in range. If only `from`, inserts at position. |
| `replaceSelection(text, origin?)` | Replace current selection |
| `transaction(tx, origin?)` | Batch multiple changes atomically |
| `processLines(read, write, ignoreEmpty?)` | Process each line |

### Navigation

| Method | Description |
|--------|-------------|
| `scrollTo(x, y)` | Scroll to position |
| `scrollIntoView(range, center?)` | Scroll range into view |
| `getScrollInfo()` | Get current scroll info |
| `posToOffset(pos)` | Convert position to character offset |
| `offsetToPos(offset)` | Convert character offset to position |

### Other

| Method | Description |
|--------|-------------|
| `focus()` / `blur()` | Focus/blur editor |
| `hasFocus()` | Check if editor has focus |
| `undo()` / `redo()` | Undo/redo |
| `exec(command)` | Execute an editor command |
| `refresh()` | Refresh editor display |

### Common Patterns

**Insert at cursor:**
```typescript
editor.replaceRange(text, editor.getCursor());
```

**Replace selection:**
```typescript
const sel = editor.getSelection();
editor.replaceSelection(sel.toUpperCase());
```

**Insert at end of document:**
```typescript
const lastLine = editor.lastLine();
const lastLineText = editor.getLine(lastLine);
editor.replaceRange('\nNew content', { line: lastLine, ch: lastLineText.length });
```

## Markdown Post Processing

Change how markdown renders in Reading view.

### Post Processor

```typescript
this.registerMarkdownPostProcessor((element: HTMLElement, context: MarkdownPostProcessorContext) => {
  // element = rendered HTML fragment
  // Modify DOM as needed
  const codeblocks = element.findAll('code');
  for (const block of codeblocks) {
    // Transform code blocks
  }
});
```

### Code Block Processor

Register custom fenced code block handlers (like Mermaid):

```typescript
this.registerMarkdownCodeBlockProcessor('csv', (source: string, el: HTMLElement, ctx) => {
  // source = raw text inside the code block
  // el = container div (replaces <pre><code>)
  const rows = source.split('\n').filter(r => r.length > 0);
  const table = el.createEl('table');
  // Build table from CSV data...
});
```

Usage in markdown:
````
```csv
Name,Age
Alice,30
Bob,25
```
````

## MarkdownRenderer

Static utility for rendering markdown to HTML:

```typescript
import { MarkdownRenderer } from 'obsidian';

// Render markdown string to element
await MarkdownRenderer.render(
  this.app,        // App instance
  '**bold** text', // Markdown string
  containerEl,     // Target HTMLElement
  sourcePath,      // Source file path (for link resolution)
  this             // Component (for lifecycle management)
);

// Alternative (older API)
await MarkdownRenderer.renderMarkdown(markdown, el, sourcePath, component);
```