Introduce codemirror6-editor

main
Clément FRÉVILLE 10 months ago
parent d95bb4acd6
commit 3cd97a4c23

@ -3,5 +3,38 @@
"version": 1,
"newProjectRoot": "projects",
"projects": {
"codemirror6-editor": {
"projectType": "library",
"root": "projects/codemirror6-editor",
"sourceRoot": "projects/codemirror6-editor/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"project": "projects/codemirror6-editor/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/codemirror6-editor/tsconfig.lib.prod.json"
},
"development": {
"tsConfig": "projects/codemirror6-editor/tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"tsConfig": "projects/codemirror6-editor/tsconfig.spec.json",
"polyfills": [
"zone.js",
"zone.js/testing"
]
}
}
}
}
}
}

@ -23,6 +23,7 @@
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.1.0",
"@angular/cli": "^17.1.0",
"@angular/compiler-cli": "^17.1.0",
"@types/jasmine": "~5.1.0",
@ -32,6 +33,7 @@
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^17.1.0",
"typescript": "~5.3.2"
}
}

@ -0,0 +1,50 @@
# 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
```
Import the component in either the `app.module.ts` file or the component:
```typescript
import { CodeMirrorComponent } from 'codemirror6';
```
## Examples
A code editor with JavaScript syntax highlighting:
```html
<codemirror6-editor
[(ngModel)]="editorContent"
[extensions]="[
basicSetup,
javascript()
]"
></codemirror6-editor>
```
A read-only code output:
```html
<codemirror6-editor
[(ngModel)]="editorContent"
[extensions]="[
EditorState.readOnly.of(true)
]"
></codemirror6-editor>
```

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/codemirror6-editor",
"lib": {
"entryFile": "src/public-api.ts"
}
}

@ -0,0 +1,14 @@
{
"name": "@sandkasten/codemirror6-editor",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^17.1.0",
"@angular/core": "^17.1.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.23.0"
},
"dependencies": {
"tslib": "^2.3.0"
},
"sideEffects": false
}

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AngularCodemirror6Component } from './codemirror6-editor.component';
describe('AngularCodemirror6Component', () => {
let component: AngularCodemirror6Component;
let fixture: ComponentFixture<AngularCodemirror6Component>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AngularCodemirror6Component]
})
.compileComponents();
fixture = TestBed.createComponent(AngularCodemirror6Component);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,77 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
ElementRef,
Input,
NgZone,
OnDestroy
} from '@angular/core';
import { EditorState, Extension, StateEffect } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
@Component({
selector: 'codemirror6-editor',
standalone: true,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: CodeMirrorComponent,
multi: true
},
],
template: `<div #host></div>`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CodeMirrorComponent implements AfterViewInit, OnDestroy, ControlValueAccessor {
@Input()
set extensions(extensions: Extension[]) {
this.editor?.dispatch({
effects: StateEffect.reconfigure.of(extensions),
});
}
private editor: EditorView | null = null;
private handleChange: (value: string) => void = () => {};
constructor(private host: ElementRef<HTMLElement>, private ngZone: NgZone) {}
ngAfterViewInit(): void {
const state = EditorState.create({
extensions: [
EditorView.updateListener.of((update) => {
this.ngZone.run(() => {
const value = update.state.doc.toString();
this.handleChange(value);
});
}),
],
});
this.editor = new EditorView({
state,
parent: this.host.nativeElement,
});
}
ngOnDestroy(): void {
this.editor?.destroy();
}
writeValue(value: string) {
this.editor?.dispatch({
changes: {
from: 0,
to: this.editor.state.doc.length,
insert: value,
},
});
}
registerOnChange(fn: (value: string) => void) {
this.handleChange = fn;
}
registerOnTouched() {}
}

@ -0,0 +1,5 @@
/*
* Public API Surface of codemirror6-editor
*/
export * from './lib/codemirror6-editor.component';

@ -0,0 +1,14 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": []
},
"exclude": [
"**/*.spec.ts"
]
}

@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"compilationMode": "partial"
}
}

@ -0,0 +1,14 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

@ -2,6 +2,11 @@
{
"compileOnSave": false,
"compilerOptions": {
"paths": {
"codemirror6-editor": [
"./dist/codemirror6-editor"
]
},
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,

Loading…
Cancel
Save