You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.7 KiB

CodeMirror 6 editor for Angular

Installation

Use the CodeFirst NPM registry for @sandkasten packages in your ~/.npmrc file:

@sandkasten:registry=https://codefirst.iut.uca.fr/git/api/packages/sandkasten/npm/
npm install @sandkasten/codemirror6-editor codemirror @codemirror/state @codemirror/view

Install the language support you need, for example with JavaScript:

npm install @codemirror/lang-javascript

Don't forget to import the standalone component in either the app.module.ts file or in the component file.

Simple examples

Those examples use Angular's standalone API.

Editor with JavaScript syntax highlighting

<codemirror6-editor
  [(ngModel)]="editorContent"
  [extensions]="[
    basicSetup,
    javascript
  ]"
></codemirror6-editor>
import { Component } from '@angular/core';
import { basicSetup } from 'codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { CodeMirrorComponent } from '@sandkasten/codemirror6-editor';

@Component({
  selector: 'code-editor',
  standalone: true,
  templateUrl: './code-editor.component.html',
  imports: [CodeMirrorComponent],
})
export class CodeEditorComponent {
  protected readonly basicSetup = basicSetup;
  protected readonly javascript = javascript();
  editorContent: string = '';
}

Read-only editor

<codemirror6-editor
  [(ngModel)]="outputContent"
  [extensions]="[
    readOnlyState
  ]"
></codemirror6-editor>
import { Component } from '@angular/core';
import { EditorState } from '@codemirror/state';
import { CodeMirrorComponent } from '@sandkasten/codemirror6-editor';

@Component({
  selector: 'code-output',
  standalone: true,
  templateUrl: './code-output.component.html',
  imports: [CodeMirrorComponent],
})
export class CodeOutputComponent {
  protected readonly readOnlyState = EditorState.readOnly.of(true);
  outputContent: string = '';
}

Dynamic configuration

CodeMirror 6 uses a transaction-based API to update the editor state. See the CodeMirror 6 documentation for more information.

To access it programmatically, you can use the editor property of the component. Coupled with a CodeMirror's Compartment, you can dynamically replace the language extension used in the editor for example.

<codemirror6-editor
  [extensions]="extensions"
></codemirror6-editor>
import { Component } from '@angular/core';
import { javascript } from '@codemirror/lang-javascript';
import { CodeMirrorComponent } from '@sandkasten/codemirror6-editor';

type JavaScriptConfig = {
  jsx: boolean;
  typescript: boolean;
};

@Component({
  selector: 'code-editor',
  standalone: true,
  templateUrl: './code-editor.component.html',
  imports: [CodeMirrorComponent],
})
export class CodeEditorComponent {
  // Access the CodeMirror Angular component
  @ViewChild(CodeMirrorComponent) codemirror!: CodeMirrorComponent;
  // Create a new dynamic configuration compartment
  private readonly languageCompartment = new Compartment();

  // Represent the editor configuration for the UI
  private _config: JavaScriptConfig = {
    jsx: false,
    typescript: false,
  };
  get config(): JavaScriptConfig {
    return this._config;
  }
  set config(value: JavaScriptConfig) {
    this._config = value;
    // Update the editor according to the new configuration
    this.codemirror.editor?.dispatch({
      effects: this.languageCompartment.reconfigure(javascript(value))
    });
  }
  // Create the initial extensions array
  protected readonly extensions: Extension[] = [
    basicSetup,
    this.languageCompartment.of(javascript(this.config))
  ];
}