CodeMirror View (@codemirror/view)

repository·main·Indexed 41 days ago

https://github.com/codemirror/view

The DOM view component for the CodeMirror code editor (v6.41.0). It handles the visual representation of the editor, including the EditorView class, ViewPlugins, decorations, gutters, tooltips, panels, and layers. It provides utilities for mapping document positions to DOM coordinates and managing the editor's user interface and interaction.

Tokens
14.4K
Snippets
49
Records
69
Agent score
51%

What's inside CodeMirror View

  1. Display Tooltips near document positions

    main
    Tooltips are DOM elements overlaid on the editor near a specific document position. The @codemirror/view package provides mechanisms to manage, position, and show these elements using Tooltip and showTooltip.
  2. Understand the core concept of the View

    main
    The @EditorView is the DOM component responsible for displaying the editor state and handling text input. It is the visual representation of the editor that the user interacts with directly.
  3. Use Decorations to influence editor rendering

    main
    Do not attempt to directly manipulate the DOM structure created by CodeMirror. Instead, use Decoration and DecorationSet to influence how content is drawn. Decorations allow you to add styling (like colors or backgrounds) or replace content with an alternative representation (like a WidgetType).
  4. Extend the View using ViewPlugins

    main
    To add custom behavior or visual logic to the editor, you should use the extension system. This involves creating a ViewPlugin (which implements PluginSpec) to react to ViewUpdate events. This allows you to manage state that is specific to the visual representation of the document rather than the document content itself.
  5. Implement Panels for UI elements like search dialogs

    main
    Panels are UI elements positioned above or below the editor (e.g., a search dialog). Unlike tooltips, panels take up space in the editor layout (if the editor has a fixed height) and remain visible even when the editor is scrolled.
  6. Add Gutters for line numbers or metadata

    main
    Gutters are areas on the side of the editor used for displaying line numbers, markers, or other metadata. You can use gutter and gutters to define these areas and GutterMarker to specify what is drawn within them.
  7. Use Layers for non-layout UI elements

    main

    Layers are sets of DOM elements drawn over or below the document text. They are useful for UI elements that should not take up space or influence line wrapping, such as additional cursors.

    Accessibility Note: Because layers are outside the regular DOM order, they are invisible to screen readers. You must provide any important information they convey in an accessible way (e.g., using EditorView.announce).

  8. Initialize an EditorView

    main

    To create a CodeMirror editor instance, import EditorView from @codemirror/view and instantiate it with a configuration object. You must provide a parent element (the DOM node where the editor will be rendered) and can optionally provide initial doc content and an array of extensions to configure behavior and appearance.

    To update the editor (e.g., to change text or move the cursor), use the view.dispatch() method.

    import {EditorView} from "@codemirror/view"
    import {basicSetup} from "codemirror"
    
    const view = new EditorView({
      parent: document.querySelector("#some-node"),
      doc: "Content text",
      extensions: [basicSetup /* ... */]
    })
  9. How gutters and markers work together

    main

    Gutters are vertical areas in the editor used to display metadata (like line numbers, error icons, or git blame info). They work through a combination of configuration and markers:

    1. Gutter Definition: You define a gutter using gutter(config). This registers a GutterConfig via a facet.
    2. Markers: Markers are GutterMarker instances associated with specific positions in the document. They are typically provided via a RangeSet<GutterMarker> in the markers config option.
    3. Rendering: The gutter plugin iterates through the visible viewport. For each line/block, it checks:
      • The markers provided by the gutter config.
      • The lineMarker function (for markers applied to every line).
      • The widgetMarker function (for markers associated with block widgets).
      • The gutterLineClass and gutterWidgetClass facets (for adding CSS classes).
    4. Lifecycle: When the document or viewport changes, the gutter plugin updates the DOM elements to reflect the new set of markers.
  10. Use MatchDecorator to highlight regex matches

    main

    The MatchDecorator class is a helper designed to be used within a ViewPlugin. It simplifies the process of maintaining decorations (like colors or styles) on text segments that match a specific regular expression. It handles viewport management, re-matching on document changes, and optimizes performance by only re-calculating decorations for visible ranges.

    To use it, you typically instantiate it in your plugin's create function and use its updateDeco method in the plugin's update lifecycle hook.

    import {EditorView, ViewPlugin} from "@codemirror/view";
    import {MatchDecorator} from "@codemirror/view";
    import {Decoration} from "@codemirror/view";
    
    const myPlugin = ViewPlugin.fromClass(class {
      decorations: DecorationSet
    
      constructor(view: EditorView) {
        const matcher = new MatchDecorator({
          regexp: /your-regex/g,
          decoration: Decoration.mark({class: "my-highlight"})
        });
        this.decorations = matcher.createDeco(view);
      }
    
      update(update: ViewUpdate) {
        // Note: You must keep track of the MatchDecorator instance 
        // to call updateDeco correctly here.
        this.decorations = matcher.updateDeco(update, this.decorations);
      }
    }, {
      decorations: v => v.decorations
    });
  11. Create markers using `LayerMarker`

    main

    A LayerMarker is an object that represents a visual element in a layer. Markers must be created during a measuring phase and must contain all necessary positioning information so they can be drawn without triggering further DOM layout reads.

    Required methods:

    • eq(other: LayerMarker): boolean: Used to compare markers of the same type to avoid unnecessary redraws.
    • draw(): HTMLElement: Returns the DOM element for the marker.

    Optional method:

    • update?(dom: HTMLElement, oldMarker: LayerMarker): boolean: Allows updating an existing DOM element instead of recreating it. Return true if the update was successful.