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.

144 lines
3.7 KiB

# CodeMirror 6 editor for Angular
## Installation
Use the CodeFirst NPM registry for `@sandkasten` packages in your `~/.npmrc` file:
```env
@sandkasten:registry=https://codefirst.iut.uca.fr/git/api/packages/sandkasten/npm/
```
```bash
npm install @sandkasten/codemirror6-editor codemirror @codemirror/state @codemirror/view
```
Install the language support you need, for example with JavaScript:
```bash
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](https://angular.io/guide/standalone-migration).
### Editor with JavaScript syntax highlighting
```html
<codemirror6-editor
[(ngModel)]="editorContent"
[extensions]="[
basicSetup,
javascript
]"
></codemirror6-editor>
```
```ts
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
```html
<codemirror6-editor
[(ngModel)]="outputContent"
[extensions]="[
readOnlyState
]"
></codemirror6-editor>
```
```ts
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](https://codemirror.net/examples/config/#dynamic-configuration) 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.
```html
<codemirror6-editor
[extensions]="extensions"
></codemirror6-editor>
```
```ts
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))
];
}
```