# Markdown Editor

Source: https://developers.inkdrop.app/modules/markdown-editor

Inkdrop's Markdown editor is built on [CodeMirror](https://codemirror.net/). The editor instance a plugin interacts with is a CodeMirror [EditorView](https://codemirror.net/docs/ref/#view.EditorView)

---

## Getting the editor instance

The [Environment](https://developers.inkdrop.app/modules/environment) exposes the active editor:

- [`getActiveEditor()`](https://developers.inkdrop.app/modules/environment#get-active-editor) — returns the active [EditorView](https://codemirror.net/docs/ref/#view.EditorView), or `null` / `undefined` if none is active
- [`getActiveEditorOrThrowError()`](https://developers.inkdrop.app/modules/environment#get-active-editor-with-error-handling) — throws if no editor is active
- [`ensureEditorLoaded(callback)`](https://developers.inkdrop.app/modules/environment#ensure-editor-loaded) — runs the callback with the editor: immediately if one is already loaded, otherwise once the next one loads

Everything CodeMirror offers is available on the view — see the [CodeMirror reference](https://codemirror.net/docs/ref/).

```js
const view = env.getActiveEditorOrThrowError()

// Read the document
const doc = view.state.doc.toString()

// Move the cursor to the top
view.dispatch({ selection: { anchor: 0 } })
```

---

## Reacting to the editor lifecycle

An editor is created when a note is opened and torn down when it goes away, so don't hold on to a view reference — subscribe instead:

- [`ensureEditorLoaded(callback)`](https://developers.inkdrop.app/modules/environment#ensure-editor-loaded) — the usual entry point in `activate()`
- [`onEditorLoad(callback)`](https://developers.inkdrop.app/modules/environment#editor-load-event) / [`onEditorUnload(callback)`](https://developers.inkdrop.app/modules/environment#editor-unload-event) — fire on every subsequent load / unload; both return a [Disposable](https://developers.inkdrop.app/event-subscription/disposable)

```ts
import type { Environment } from '@inkdropapp/types'

class MyPlugin {
  activate(env: Environment) {
    env.ensureEditorLoaded(view => {
      // the editor is ready
    })
  }
}
```

---

## Extending the editor

Behavior is added declaratively as CodeMirror [extensions](https://codemirror.net/docs/ref/#state.Extension) through commands:

- [`editor:add-extension` / `editor:remove-extension`](https://developers.inkdrop.app/guides/list-of-commands#editor-add-extension) — register a CodeMirror extension
- [`editor:add-code-language` / `editor:remove-code-language`](https://developers.inkdrop.app/guides/list-of-commands#editor-add-code-language) — register a code-block language ([LanguageDescription](https://codemirror.net/docs/ref/#language.LanguageDescription))
- [`editor:add-markdown-extension` / `editor:remove-markdown-extension`](https://developers.inkdrop.app/guides/list-of-commands#editor-add-markdown-extension) — extend the Markdown parser with a `MarkdownExtension` from [@lezer/markdown](https://github.com/lezer-parser/markdown)

A registered extension is kept in the app state and applied to every editor, including ones created later — register once in `activate()`, remove in `deactivate()`. See [Customize the editor](https://developers.inkdrop.app/guides/customize-the-editor) for the full walkthrough.

---

## Styling and keymaps

The editor's root element is `.cm-editor`.
Use it for [keymap](https://developers.inkdrop.app/modules/keymap-manager) and [context menu](https://developers.inkdrop.app/modules/context-menu-manager) selectors and for CSS. Syntax highlighting emits `.tok-*` classes inside `.cm-editor` — see [Creating a theme](https://developers.inkdrop.app/guides/create-a-theme).
