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.
components/projects/codemirror6-editor
Clément FRÉVILLE ad9ced92ac
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
Force state redraw when editing the state array
1 year ago
..
src Force state redraw when editing the state array 1 year ago
README.md Allow accessing the inner editor state 1 year ago
ng-package.json Introduce codemirror6-editor 1 year ago
package.json Introduce codemirror6-editor 1 year ago
tsconfig.lib.json Introduce codemirror6-editor 1 year ago
tsconfig.lib.prod.json Introduce codemirror6-editor 1 year ago
tsconfig.spec.json Introduce codemirror6-editor 1 year ago

README.md

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))
  ];
}