or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bidi.mdbuiltin-extensions.mddecorations.mdeditor-view.mdextensions.mdgutters.mdindex.mdkeybindings.mdlayout.mdpanels.mdtooltips.md
tile.json

index.mddocs/

CodeMirror View

The @codemirror/view package provides the DOM view component for the CodeMirror code editor, implementing the visual rendering and user interaction layer. It handles DOM manipulation, event processing, input handling, decorations, themes, tooltips, panels, gutters, and various visual features like syntax highlighting, cursors, selections, and scroll management.

Package Information

  • Package Name: @codemirror/view
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @codemirror/view

Core Imports

import { EditorView, ViewPlugin, Decoration } from "@codemirror/view";

For CommonJS:

const { EditorView, ViewPlugin, Decoration } = require("@codemirror/view");

Basic Usage

import { EditorView } from "@codemirror/view";
import { EditorState } from "@codemirror/state";

// Create a basic editor
const state = EditorState.create({
  doc: "Hello, CodeMirror!",
});

const view = new EditorView({
  state,
  parent: document.getElementById("editor")
});

// Access editor content
console.log(view.state.doc.toString());

// Dispatch changes
view.dispatch({
  changes: { from: 0, to: view.state.doc.length, insert: "New content" }
});

Architecture

CodeMirror View is built around several key components:

  • EditorView: Main editor class that manages the DOM and coordinates all view operations
  • Extension System: Plugin architecture with ViewPlugin for extensibility and state management
  • Decoration System: Flexible system for styling text ranges, adding widgets, and custom rendering
  • Layout Engine: Height mapping and block-based layout system for efficient rendering of large documents
  • Event Handling: Comprehensive DOM event management with customizable key bindings and mouse interactions
  • Theme System: CSS-in-JS theming with support for light/dark modes and extensible styling

Capabilities

Core Editor View

Main EditorView class that provides the foundation for all editor functionality. Manages DOM rendering, viewport optimization, coordinate mapping, and state synchronization.

class EditorView {
  constructor(config?: EditorViewConfig);
  
  // Core state and properties
  readonly state: EditorState;
  readonly viewport: {from: number, to: number};
  readonly visibleRanges: readonly {from: number, to: number}[];
  readonly dom: HTMLElement;
  readonly contentDOM: HTMLElement;
  readonly scrollDOM: HTMLElement;
  readonly root: DocumentOrShadowRoot;
  readonly inView: boolean;
  readonly hasFocus: boolean;
  readonly composing: boolean;
  readonly compositionStarted: boolean;
  
  // Layout and measurement properties
  readonly defaultCharacterWidth: number;
  readonly defaultLineHeight: number;
  readonly textDirection: Direction;
  readonly lineWrapping: boolean;
  readonly contentHeight: number;
  readonly scaleX: number;
  readonly scaleY: number;
  readonly themeClasses: string;
  readonly documentTop: number;
  readonly documentPadding: {top: number, bottom: number};
  readonly viewportLineBlocks: readonly BlockInfo[];
  
  // State management and updates
  dispatch(tr: Transaction): void;
  dispatch(trs: readonly Transaction[]): void;
  dispatch(...specs: TransactionSpec[]): void;
  update(transactions: readonly Transaction[]): void;
  setState(newState: EditorState): void;
  
  // Lifecycle
  focus(): void;
  destroy(): void;
  
  // Coordinate mapping
  posAtCoords(coords: {x: number, y: number}, precise: false): number;
  posAtCoords(coords: {x: number, y: number}): number | null;
  coordsAtPos(pos: number, side?: -1 | 1): Rect | null;
  coordsForChar(pos: number): Rect | null;
  domAtPos(pos: number): {node: Node, offset: number};
  posAtDOM(node: Node, offset?: number): number;
  
  // Block and line information
  lineBlockAt(pos: number): BlockInfo;
  elementAtHeight(height: number): BlockInfo;
  textDirectionAt(pos: number): Direction;
  bidiSpans(line: Line): readonly BidiSpan[];
  
  // Movement and navigation
  moveByChar(start: SelectionRange, forward: boolean, by?: Function): SelectionRange;
  moveByGroup(start: SelectionRange, forward: boolean): SelectionRange;
  moveToLineBoundary(start: SelectionRange, forward: boolean, includeWrap?: boolean): SelectionRange;
  moveVertically(start: SelectionRange, forward: boolean, distance?: number): SelectionRange;
  visualLineSide(line: Line, end: boolean): SelectionRange;
  
  // Scrolling and view management
  scrollSnapshot(): StateEffect<unknown>;
  setRoot(root: Document | ShadowRoot): void;
  setTabFocusMode(to?: boolean | number): void;
  
  // Plugin and measurement
  plugin<T extends PluginValue>(plugin: ViewPlugin<T>): T | null;
  requestMeasure<T>(request?: MeasureRequest<T>): void;
  
  // Static methods
  static scrollIntoView(pos: number | SelectionRange, options?: ScrollIntoViewOptions): StateEffect<unknown>;
  static theme(spec: {[selector: string]: StyleSpec}, options?: {dark?: boolean}): Extension;
  static baseTheme(spec: {[selector: string]: StyleSpec}): Extension;
  static domEventHandlers(handlers: DOMEventHandlers): Extension;
  static domEventObservers(observers: DOMEventHandlers): Extension;
  static findFromDOM(dom: HTMLElement): EditorView | null;
  
  // Static facets
  static readonly styleModule: Facet<StyleModule>;
  static readonly inputHandler: Facet<InputHandler>;
  static readonly clipboardInputFilter: Facet<ClipboardFilter>;
  static readonly clipboardOutputFilter: Facet<ClipboardFilter>;
  static readonly scrollHandler: Facet<ScrollHandler>;
  static readonly focusChangeEffect: Facet<FocusChangeEffect>;
  static readonly perLineTextDirection: Facet<boolean, boolean>;
  static readonly exceptionSink: Facet<ExceptionSink>;
  static readonly updateListener: Facet<UpdateListener>;
  static readonly editable: Facet<boolean, boolean>;
  static readonly mouseSelectionStyle: Facet<MouseSelectionStyle>;
  static readonly dragMovesSelection: Facet<DragMovesSelection>;
  static readonly clickAddsSelectionRange: Facet<ClickAddsSelectionRange>;
  static readonly decorations: Facet<DecorationSource>;
  static readonly outerDecorations: Facet<DecorationSource>;
  static readonly atomicRanges: Facet<AtomicRangesSource>;
  static readonly bidiIsolatedRanges: Facet<DecorationSource>;
  static readonly scrollMargins: Facet<ScrollMarginsSource>;
  static readonly darkTheme: Facet<boolean, boolean>;
  static readonly cspNonce: Facet<string>;
  static readonly contentAttributes: Facet<AttrSource>;
  static readonly editorAttributes: Facet<AttrSource>;
  static readonly lineWrapping: Extension;
  static readonly announce: Facet<string>;
}

interface EditorViewConfig extends EditorStateConfig {
  state?: EditorState;
  parent?: Element | DocumentFragment;
  root?: Document | ShadowRoot;
  scrollTo?: StateEffect<any>;
  dispatchTransactions?: (trs: readonly Transaction[], view: EditorView) => void;
  dispatch?: (tr: Transaction, view: EditorView) => void;
}

Editor View Core

Extension System

Plugin architecture for extending editor functionality with lifecycle management, event handling, and state integration.

class ViewPlugin<V extends PluginValue, Arg = undefined> {
  static define<V extends PluginValue>(
    create: (view: EditorView) => V, 
    spec?: PluginSpec<V>
  ): ViewPlugin<V>;
  static fromClass<V extends PluginValue>(
    cls: {new(view: EditorView): V}, 
    spec?: PluginSpec<V>
  ): ViewPlugin<V>;
  
  readonly extension: Arg extends undefined ? Extension : null;
  of(arg: Arg): Extension;
  readonly id: number;
  readonly create: (view: EditorView, arg?: Arg) => V;
  readonly domEventHandlers: DOMEventHandlers<V> | undefined;
  readonly domEventObservers: DOMEventHandlers<V> | undefined;
}

interface PluginValue {
  update?(update: ViewUpdate): void;
  destroy?(): void;
  docViewUpdate?(view: EditorView): void;
}

interface PluginSpec<V extends PluginValue> {
  eventHandlers?: DOMEventHandlers<V>;
  eventObservers?: DOMEventHandlers<V>;
  provide?: (plugin: ViewPlugin<V>) => Extension;
  decorations?: (value: V) => DecorationSet;
}

class ViewUpdate {
  readonly view: EditorView;
  readonly state: EditorState;
  readonly transactions: readonly Transaction[];
  readonly changes: ChangeSet;
  readonly changedRanges: readonly ChangedRange[];
  readonly startState: EditorState;
  readonly docChanged: boolean;
  readonly focusChanged: boolean;
  readonly selectionSet: boolean;
  readonly viewportChanged: boolean;
  readonly viewportMoved: boolean;
  readonly heightChanged: boolean;
  readonly geometryChanged: boolean;
  readonly empty: boolean;
  
  static create(view: EditorView, state: EditorState, transactions: readonly Transaction[]): ViewUpdate;
}

type Command = (target: EditorView) => boolean;

function logException(state: EditorState, exception: any, context?: string): void;

Extension System

Decorations

Flexible decoration system for styling text ranges, adding widgets, replacing content, and creating custom visual elements.

abstract class Decoration extends RangeValue {
  static mark(spec: MarkDecorationSpec): Decoration;
  static widget(spec: WidgetDecorationSpec): Decoration;
  static replace(spec: ReplaceDecorationSpec): Decoration;
  static line(spec: LineDecorationSpec): Decoration;
  static set(of: Range<Decoration> | readonly Range<Decoration>[], sort?: boolean): DecorationSet;
  static none: DecorationSet;
  
  readonly spec: any;
  readonly widget: WidgetType | null;
  readonly heightRelevant: boolean;
  hasHeight(): boolean;
  abstract eq(other: Decoration): boolean;
  range(from: number, to?: number): Range<Decoration>;
}

class DecorationSet extends RangeSet<Decoration> {
  static readonly empty: DecorationSet;
  static create(view: EditorView, decorations: Range<Decoration>[]): DecorationSet;
  static of<T>(ranges: readonly Range<T>[] | Range<T>, sort?: boolean): RangeSet<T>;
  
  update(mapping: ChangeDesc, filterFrom?: number, filterTo?: number): DecorationSet;
  map(mapping: ChangeDesc, start?: number, end?: number): DecorationSet;
}

abstract class WidgetType {
  abstract toDOM(view: EditorView): HTMLElement;
  abstract eq(other: WidgetType): boolean;
  updateDOM?(dom: HTMLElement, view: EditorView): boolean;
  coordsAt?(dom: HTMLElement, pos: number, side: number): Rect | null;
  ignoreEvent?(event: Event): boolean;
  destroy?(dom: HTMLElement): void;
  
  readonly estimatedHeight: number;
  get lineBreaks(): number;
  get isHidden(): boolean;
  get editable(): boolean;
  compare(other: WidgetType): boolean;
}

Decorations

Key Bindings

Flexible key binding system with support for multi-stroke keys, platform-specific modifiers, and context-sensitive commands.

interface KeyBinding {
  key: string;
  run: Command;
  shift?: Command;
  scope?: string;
  preventDefault?: boolean;
  stopPropagation?: boolean;
  mac?: string;
  win?: string;
  linux?: string;
  any?: Command;
}

const keymap: Facet<readonly KeyBinding[]>;

function runScopeHandlers(view: EditorView, event: KeyboardEvent, scope: string): boolean;

Key Bindings

Tooltips

Rich tooltip system with positioning, hover support, and custom content rendering.

interface Tooltip {
  pos: number;
  end?: number;
  create(view: EditorView): TooltipView;
  above?: boolean;
  strictSide?: boolean;
  arrow?: boolean;
  clip?: boolean;
}

interface TooltipView {
  dom: HTMLElement;
  update?(update: ViewUpdate): void;
  destroy?(): void;
  mount?(view: EditorView): void;
  positioned?(): void;
  overlap?: boolean;
  resize?: boolean;
  offset?: {x: number, y: number};
  getCoords?(pos: number): {x: number, y: number};
}

interface TooltipConfig {
  position?: "absolute" | "fixed";
  parent?: () => HTMLElement;
  tooltipSpace?: (view: EditorView) => {left: number, top: number, right: number, bottom: number};
}

interface HoverTooltipOptions {
  hideOn?: (view: EditorView, pos: number, side: -1 | 1) => boolean;
  hideOnChange?: boolean;
  hoverTime?: number;
}

type HoverTooltipSource = (view: EditorView, pos: number, side: -1 | 1) => 
  Tooltip | readonly Tooltip[] | null | Promise<Tooltip | readonly Tooltip[] | null>;

const showTooltip: Facet<Tooltip | null>;
function tooltips(config?: TooltipConfig): Extension;
function hoverTooltip(source: HoverTooltipSource, options?: HoverTooltipOptions): Extension;
function getTooltip(view: EditorView, tooltip: Tooltip): TooltipView | null;
function hasHoverTooltips(state: EditorState): boolean;
function closeHoverTooltips(view: EditorView): boolean;
function repositionTooltips(view: EditorView): void;

Tooltips

Panels

UI panel system for adding persistent interface elements above or below the editor content.

interface Panel {
  dom: HTMLElement;
  mount?(): void;
  update?(update: ViewUpdate): void;
  destroy?(): void;
  top?: boolean;
}

interface PanelConfig {
  topContainer?: (view: EditorView) => HTMLElement;
  bottomContainer?: (view: EditorView) => HTMLElement;
}

type PanelConstructor = (view: EditorView) => Panel;

const showPanel: Facet<Panel | null>;
function panels(config?: PanelConfig): Extension;
function getPanel(view: EditorView, panel: PanelConstructor): Panel | null;

Panels

Gutters

Customizable gutter system for line numbers, folding controls, breakpoints, and other line-based information.

abstract class GutterMarker {
  toDOM?(view: EditorView): Node;
  abstract eq(other: GutterMarker): boolean;
  destroy?(dom: Node): void;
  readonly elementClass: string;
  readonly domAtPos: boolean;
}

interface GutterConfig {
  class?: string;
  renderEmptyElements?: boolean;
  markers?: (view: EditorView) => (RangeSet<GutterMarker> | readonly RangeSet<GutterMarker>[]);
  lineMarker?: (view: EditorView, line: BlockInfo, otherMarkers: readonly GutterMarker[]) => GutterMarker | null;
  widgetMarker?: (view: EditorView, widget: WidgetType, block: BlockInfo) => GutterMarker | null;
  lineMarkerChange?: null | ((update: ViewUpdate) => boolean);
  initialSpacer?: null | ((view: EditorView) => GutterMarker);
  updateSpacer?: null | ((spacer: GutterMarker, update: ViewUpdate) => GutterMarker);
  domEventHandlers?: DOMEventHandlers<GutterMarker>;
  side?: "before" | "after";
}

interface LineNumberConfig {
  formatNumber?: (lineNo: number, state: EditorState) => string;
  domEventHandlers?: DOMEventHandlers<LineNumberMarker>;
}

function lineNumbers(config?: LineNumberConfig): Extension;
function gutter(config: GutterConfig): Extension;
function gutters(config?: {fixed?: boolean}): Extension;
function highlightActiveLineGutter(): Extension;
function gutterLineClass(className: string): Extension;
function gutterWidgetClass(className: string): Extension;
function lineNumberWidgetMarker(marker: GutterMarker, side: -1 | 1): Extension;

const lineNumberMarkers: Facet<RangeSet<GutterMarker>>;

Gutters

Coordinate and Layout

Position mapping between document coordinates and screen coordinates, with block-based layout information.

interface BlockInfo {
  from: number;
  to: number;
  length: number;
  height: number;
  top: number;
  type: BlockType;
}

interface Rect {
  left: number;
  right: number;
  top: number;
  bottom: number;
}

// Methods on EditorView
posAtCoords(coords: {x: number, y: number}, precise?: boolean): number | null;
coordsAtPos(pos: number, side?: -1 | 1): Rect | null;
lineBlockAt(pos: number): BlockInfo;

Layout and Coordinates

Bidirectional Text

Support for bidirectional text rendering with proper Unicode handling and visual cursor movement.

interface BidiSpan {
  from: number;
  to: number;
  level: number;
  dir: Direction;
}

enum Direction {
  LTR = 0,
  RTL = 1
}

Bidirectional Text

Layers

Positioned overlay system for creating custom visual elements that float above or below the editor content.

function layer(config: LayerConfig): Extension;

interface LayerMarker {
  draw(): HTMLElement | null;
  update?(dom: HTMLElement, view: EditorView): boolean;
  eq(other: LayerMarker): boolean;
  destroy?(dom: HTMLElement): void;
}

class RectangleMarker implements LayerMarker {
  constructor(className: string, rect: Rect);
  draw(): HTMLElement;
  eq(other: LayerMarker): boolean;
}

Match Decorators

Automatic text matching and decoration system for finding and styling patterns in the editor content.

class MatchDecorator {
  constructor(config: MatchDecoratorConfig);
  createDeco(view: EditorView): DecorationSet;
}

interface MatchDecoratorConfig {
  regexp: RegExp;
  decoration?: Decoration | ((match: RegExpExecArray, view: EditorView, pos: number) => Decoration);
  decorate?: (add: (from: number, to: number, decoration: Decoration) => void, from: number, to: number, match: RegExpExecArray, view: EditorView) => void;
  boundary?: RegExp;
}

Dialogs

Simple dialog system for displaying modal or inline dialogs within the editor interface.

const showDialog: Facet<DialogSource | null>;
function getDialog(view: EditorView): DialogSource | null;

type DialogSource = (view: EditorView) => {dom: HTMLElement, pos?: number} | null;

Built-in Extensions

Collection of ready-to-use extensions for common editor features and visual enhancements.

function drawSelection(): Extension;
function getDrawSelectionConfig(state: EditorState): DrawSelectionConfig;
function dropCursor(config?: DropCursorConfig): Extension;
function highlightSpecialChars(config?: SpecialCharConfig): Extension;
function scrollPastEnd(): Extension;
function highlightActiveLine(): Extension;
function placeholder(content: string | HTMLElement): Extension;
function rectangularSelection(options?: RectangularSelectionOptions): Extension;
function crosshairCursor(options?: CrosshairCursorOptions): Extension;
function highlightWhitespace(config?: HighlightWhitespaceOptions): Extension;
function highlightTrailingWhitespace(config?: HighlightTrailingWhitespaceOptions): Extension;

Built-in Extensions

Layout Measurement

Request-based DOM measurement system for efficient layout operations.

interface MeasureRequest<T> {
  read(view: EditorView): T;
  write?(measure: T, view: EditorView): void;
  key?: any;
}

Change Tracking

Information about document changes and their mapping.

class ChangedRange {
  constructor(
    readonly fromA: number, 
    readonly toA: number, 
    readonly fromB: number, 
    readonly toB: number
  );
  
  join(other: ChangedRange): ChangedRange;
  addToSet(set: ChangedRange[]): ChangedRange[];
  
  static extendWithRanges(
    diff: readonly ChangedRange[], 
    ranges: number[]
  ): readonly ChangedRange[];
}

Scroll Management

Scroll target representation for programmatic scrolling.

class ScrollTarget {
  constructor(
    readonly range: SelectionRange,
    readonly y?: ScrollStrategy,
    readonly x?: ScrollStrategy,
    readonly yMargin?: number,
    readonly xMargin?: number,
    readonly isSnapshot?: boolean
  );
  
  map(changes: ChangeDesc): ScrollTarget;
  clip(state: EditorState): ScrollTarget;
}

enum ScrollStrategy {
  Start = 0,
  Center = 1,
  End = 2,
  Nearest = 3
}

Dialog System

Simple modal and inline dialog system.

const showDialog: Facet<DialogSource | null>;
function getDialog(view: EditorView): DialogSource | null;

type DialogSource = (view: EditorView) => {dom: HTMLElement, pos?: number} | null;

Match Decorations

Automatic pattern matching and decoration system.

class MatchDecorator {
  constructor(config: MatchDecoratorConfig);
  createDeco(view: EditorView): DecorationSet;
}

interface MatchDecoratorConfig {
  regexp: RegExp;
  decoration?: Decoration | ((match: RegExpExecArray, view: EditorView, pos: number) => Decoration);
  decorate?: (add: (from: number, to: number, decoration: Decoration) => void, from: number, to: number, match: RegExpExecArray, view: EditorView) => void;
  boundary?: RegExp;
}

Types

interface DOMEventMap {
  [eventName: string]: (view: EditorView, event: Event) => boolean;
}

type DOMEventHandlers<This = any> = {
  [K in keyof HTMLElementEventMap]?: (this: This, event: HTMLElementEventMap[K], view: EditorView) => boolean;
};

interface MouseSelectionStyle {
  get(event: MouseEvent, extend: boolean, multiple: boolean): Selection;
  update(selection: Selection, event: MouseEvent): Selection;
}

type AttrSource = Attrs | ((view: EditorView) => Attrs | null);
type Attrs = {[name: string]: string};

type DecorationSource = DecorationSet | ((view: EditorView) => DecorationSet);
type AtomicRangesSource = (view: EditorView) => RangeSet<any>;
type ScrollMarginsSource = (view: EditorView) => Partial<Rect> | null;

type InputHandler = (view: EditorView, from: number, to: number, text: string, insert: () => Transaction) => boolean;
type FocusChangeEffect = (state: EditorState, focusing: boolean) => StateEffect<any> | null;
type ScrollHandler = (view: EditorView, range: SelectionRange, options: ScrollIntoViewOptions) => boolean;
type ExceptionSink = (exception: any) => void;
type UpdateListener = (update: ViewUpdate) => void;
type ClipboardFilter = (text: string, view: EditorView) => string | null;

type DragMovesSelection = (event: MouseEvent) => boolean;
type ClickAddsSelectionRange = (event: MouseEvent) => boolean;

enum UpdateFlag {
  Focus = 1,
  Height = 2,
  Viewport = 4,
  ViewportMoved = 8,
  Geometry = 16
}

interface ScrollIntoViewOptions {
  y?: ScrollStrategy;
  x?: ScrollStrategy;
  yMargin?: number;
  xMargin?: number;
}

function logException(state: EditorState, exception: any, context?: string): void;