UNPKG

@fsegurai/ngx-codemirror

Version:

Angular library that uses codemirror to create a code editor

579 lines (572 loc) 29.6 kB
import * as i0 from '@angular/core'; import { inject, ElementRef, input, booleanAttribute, output, forwardRef, Input, ChangeDetectionStrategy, ViewEncapsulation, Component, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { MergeView } from '@codemirror/merge'; import { Compartment, StateEffect, Annotation, EditorState } from '@codemirror/state'; import { EditorView, placeholder, keymap, highlightWhitespace } from '@codemirror/view'; import { basicSetup, minimalSetup } from 'codemirror'; import { External as External$1 } from 'ngx-codemirror'; import { indentWithTab } from '@codemirror/commands'; import { indentUnit } from '@codemirror/language'; class CodeDiffEditorComponent { constructor() { this._elementRef = inject(ElementRef); /** The editor's theme. */ this.theme = input('light'); /** * The editor's built-in setup. The value can be set to * [`basic`](https://codemirror.net/docs/ref/#codemirror.basicSetup), * [`minimal`](https://codemirror.net/docs/ref/#codemirror.minimalSetup) or `null`. * * Don't support change dynamically! */ this.setup = input('basic'); /** The diff-editor's original value. */ this.originalValue = ''; /** * The MergeView original config's * [extensions](https://codemirror.net/docs/ref/#state.EditorStateConfig.extensions). * * Don't support change dynamically! */ this.originalExtensions = input([]); /** The diff-editor's modified value. */ this.modifiedValue = ''; /** * The MergeView modified config's * [extensions](https://codemirror.net/docs/ref/#state.EditorStateConfig.extensions). */ this.modifiedExtensions = input([]); /** Controls whether editor A or editor B is shown first. Defaults to `"a-b"`. */ this.orientation = input(); /** Controls whether revert controls are shown between changed chunks. */ this.revertControls = input(); /** When given, this function is called to render the button to revert a chunk. */ this.renderRevertControl = input(); /** * By default, the merge view will mark inserted and deleted text * in changed chunks. Set this to false in order to turn that off. */ this.highlightChanges = input(true, { transform: booleanAttribute }); /** Controls whether a gutter marker is shown next to changed lines. */ this.gutter = input(true, { transform: booleanAttribute }); /** Whether the diff-editor is disabled. */ this.disabled = false; /** * When given, long stretches of unchanged text are collapsed. * `margin` gives the number of lines to leave visible after/before * a change (default is 3), and `minSize` gives the minimum amount * of collapsible lines that need to be present (defaults to 4). */ this.collapseUnchanged = input(); /** Pass options to the diff algorithm. */ this.diffConfig = input(); /** Event emitted when the editor's original value changes. */ this.originalValueChange = output(); /** Event emitted when focus on the original editor. */ this.originalFocus = output(); /** Event emitted when blur on the original editor. */ this.originalBlur = output(); /** Event emitted when the editor's modified value changes. */ this.modifiedValueChange = output(); /** Event emitted when focus on the modified editor. */ this.modifiedFocus = output(); /** Event emitted when blur on the modified editor. */ this.modifiedBlur = output(); this._onChange = () => { // Intentionally left blank }; this._onTouched = () => { // Intentionally left blank }; this._updateListener = (editor) => { return EditorView.updateListener.of(vu => { if (vu.docChanged && !vu.transactions.some(tr => tr.annotation(External$1))) { const value = vu.state.doc.toString(); if (editor == 'a') { this._onChange({ original: value, modified: this.modifiedValue }); this.originalValue = value; this.originalValueChange.emit(value); } else { this._onChange({ original: this.originalValue, modified: value }); this.modifiedValue = value; this.modifiedValueChange.emit(value); } } }); }; this._editableConf = new Compartment(); this._themeConf = new Compartment(); } _getAllExtensions(editor) { const setup = this.setup(); return [ this._editableConf.of([]), this._themeConf.of([]), this._updateListener(editor), setup === 'basic' ? basicSetup : setup === 'minimal' ? minimalSetup : [], ...(editor === 'a' ? this.originalExtensions() : this.modifiedExtensions()), ]; } ngOnChanges(changes) { if (changes['originalValue']) { this.setValue('a', this.originalValue); } if (changes['modifiedValue']) { this.setValue('b', this.modifiedValue); } if (changes['disabled']) { this.setEditable(!this.disabled); } if (changes['theme']) { this.setTheme(this.theme()); } this.reconfigureMergeView(changes); } ngOnInit() { this.initializeMergeView(); this.addEventListeners(); this.setEditable(!this.disabled); this.setTheme(this.theme()); } ngOnDestroy() { this.mergeView?.destroy(); } writeValue(value) { if (this.mergeView && value != null && typeof value === 'object') { this.originalValue = value.original; this.modifiedValue = value.modified; this.setValue('a', value.original); this.setValue('b', value.modified); } } registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.setEditable(!isDisabled); } /** Sets diff-editor's value. */ setValue(editor, value) { this.mergeView?.[editor].dispatch({ changes: { from: 0, to: this.mergeView[editor].state.doc.length, insert: value }, }); } /** Sets editor's editable state. */ setEditable(value) { this._dispatchEffects(this._editableConf.reconfigure(EditorView.editable.of(value))); } /** Sets editor's theme. */ setTheme(value) { this._dispatchEffects(this._themeConf.reconfigure(value === 'light' ? [] : value)); } /** Sets the root extensions of the editor state. */ setExtensions(editor, value) { this.mergeView?.[editor].dispatch({ effects: StateEffect.reconfigure.of(value), }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any _dispatchEffects(effects) { this.mergeView?.a.dispatch({ effects }); this.mergeView?.b.dispatch({ effects }); } initializeMergeView() { this.mergeView = new MergeView({ parent: this._elementRef.nativeElement, a: { doc: this.originalValue, extensions: this._getAllExtensions('a'), }, b: { doc: this.modifiedValue, extensions: this._getAllExtensions('b'), }, orientation: this.orientation(), revertControls: this.revertControls(), renderRevertControl: this.renderRevertControl(), highlightChanges: this.highlightChanges(), gutter: this.gutter(), collapseUnchanged: this.collapseUnchanged(), diffConfig: this.diffConfig(), }); } addEventListeners() { this.mergeView?.a.contentDOM.addEventListener('focus', () => { this._onTouched(); this.originalFocus.emit(); }); this.mergeView?.a.contentDOM.addEventListener('blur', () => { this._onTouched(); this.originalBlur.emit(); }); this.mergeView?.b.contentDOM.addEventListener('focus', () => { this._onTouched(); this.modifiedFocus.emit(); }); this.mergeView?.b.contentDOM.addEventListener('blur', () => { this._onTouched(); this.modifiedBlur.emit(); }); } reconfigureMergeView(changes) { if (changes['orientation']) { this.mergeView?.reconfigure({ orientation: this.orientation() }); } if (changes['revertControls']) { this.mergeView?.reconfigure({ revertControls: this.revertControls() }); } if (changes['renderRevertControl']) { this.mergeView?.reconfigure({ renderRevertControl: this.renderRevertControl() }); } if (changes['highlightChanges']) { this.mergeView?.reconfigure({ highlightChanges: this.highlightChanges() }); } if (changes['gutter']) { this.mergeView?.reconfigure({ gutter: this.gutter() }); } if (changes['collapseUnchanged']) { this.mergeView?.reconfigure({ collapseUnchanged: this.collapseUnchanged() }); } if (changes['diffConfig']) { this.mergeView?.reconfigure({ diffConfig: this.diffConfig() }); } if (changes['setup'] || changes['originalExtensions'] || changes['modifiedExtensions']) { this.setExtensions('a', this._getAllExtensions('a')); this.setExtensions('b', this._getAllExtensions('b')); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeDiffEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.0", type: CodeDiffEditorComponent, isStandalone: true, selector: "ngx-code-diff-editor, code-diff-editor, [diff-editor]", inputs: { theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, setup: { classPropertyName: "setup", publicName: "setup", isSignal: true, isRequired: false, transformFunction: null }, originalValue: { classPropertyName: "originalValue", publicName: "originalValue", isSignal: false, isRequired: false, transformFunction: null }, originalExtensions: { classPropertyName: "originalExtensions", publicName: "originalExtensions", isSignal: true, isRequired: false, transformFunction: null }, modifiedValue: { classPropertyName: "modifiedValue", publicName: "modifiedValue", isSignal: false, isRequired: false, transformFunction: null }, modifiedExtensions: { classPropertyName: "modifiedExtensions", publicName: "modifiedExtensions", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, revertControls: { classPropertyName: "revertControls", publicName: "revertControls", isSignal: true, isRequired: false, transformFunction: null }, renderRevertControl: { classPropertyName: "renderRevertControl", publicName: "renderRevertControl", isSignal: true, isRequired: false, transformFunction: null }, highlightChanges: { classPropertyName: "highlightChanges", publicName: "highlightChanges", isSignal: true, isRequired: false, transformFunction: null }, gutter: { classPropertyName: "gutter", publicName: "gutter", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, collapseUnchanged: { classPropertyName: "collapseUnchanged", publicName: "collapseUnchanged", isSignal: true, isRequired: false, transformFunction: null }, diffConfig: { classPropertyName: "diffConfig", publicName: "diffConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { originalValueChange: "originalValueChange", originalFocus: "originalFocus", originalBlur: "originalBlur", modifiedValueChange: "modifiedValueChange", modifiedFocus: "modifiedFocus", modifiedBlur: "modifiedBlur" }, host: { classAttribute: "diff-editor" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CodeDiffEditorComponent), multi: true, }, ], usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [".diff-editor{display:block}.diff-editor .cm-mergeView,.diff-editor .cm-mergeViewEditors{height:100%}.diff-editor .cm-mergeView .cm-editor,.diff-editor .cm-mergeView .cm-scroller{height:100%!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeDiffEditorComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-code-diff-editor, code-diff-editor, [diff-editor]', imports: [], template: '', host: { class: 'diff-editor', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CodeDiffEditorComponent), multi: true, }, ], styles: [".diff-editor{display:block}.diff-editor .cm-mergeView,.diff-editor .cm-mergeViewEditors{height:100%}.diff-editor .cm-mergeView .cm-editor,.diff-editor .cm-mergeView .cm-scroller{height:100%!important}\n"] }] }], propDecorators: { originalValue: [{ type: Input }], modifiedValue: [{ type: Input }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); const External = Annotation.define(); class CodeEditorComponent { constructor() { this._elementRef = inject(ElementRef); /** * EditorView's [root](https://codemirror.net/docs/ref/#view.EditorView.root). * * Don't support change dynamically! */ this.root = input(); /** * Whether focus on the editor after init. * * Don't support change dynamically! */ this.autoFocus = input(false, { transform: booleanAttribute }); /** The editor's value. */ this.value = input(''); /** Whether the editor is disabled. */ this.disabled = false; /** Whether the editor is readonly. */ this.readonly = input(false, { transform: booleanAttribute }); /** The editor's theme. */ this.theme = input('light'); /** The editor's placeholder. */ this.placeholder = input(''); /** Whether indent with Tab key. */ this.indentWithTab = input(false, { transform: booleanAttribute }); /** Should be a string consisting either entirely of the same whitespace character. */ this.indentUnit = input(0); /** Whether the editor wraps lines. */ this.lineWrapping = input(false, { transform: booleanAttribute }); /** Whether highlight the whitespace. */ this.highlightWhitespace = input(false, { transform: booleanAttribute }); /** * An array of language descriptions for known * [language-data](https://github.com/codemirror/language-data/blob/main/src/language-data.ts). * * Don't support change dynamically! */ this.languages = input([]); /** The editor's language. You should set the `languages` prop at first. */ this.language = input(''); /** * The editor's built-in setup. The value can be set to * [`basic`](https://codemirror.net/docs/ref/#codemirror.basicSetup), * [`minimal`](https://codemirror.net/docs/ref/#codemirror.minimalSetup) or `null`. */ this.setup = input('basic'); /** * It will be appended to the root * [extensions](https://codemirror.net/docs/ref/#state.EditorStateConfig.extensions). */ this.extensions = input([]); /** Event emitted when the editor's value changes. */ this.change = output(); /** Event emitted when focus on the editor. */ this.focus = output(); /** Event emitted when the editor has lost focus. */ this.blur = output(); this._onChange = () => { // Intentionally left blank }; this._onTouched = () => { // Intentionally left blank }; this._updateListener = EditorView.updateListener.of(vu => { if (vu.docChanged && !vu.transactions.some(tr => tr.annotation(External))) { const value = vu.state.doc.toString(); this._onChange(value); this.change.emit(value); } }); // Extension compartments can be used to make a configuration dynamic. // https://codemirror.net/docs/ref/#state.Compartment this._editableConf = new Compartment(); this._readonlyConf = new Compartment(); this._themeConf = new Compartment(); this._placeholderConf = new Compartment(); this._indentWithTabConf = new Compartment(); this._indentUnitConf = new Compartment(); this._lineWrappingConf = new Compartment(); this._highlightWhitespaceConf = new Compartment(); this._languageConf = new Compartment(); } _getAllExtensions() { const setup = this.setup(); return [ this._updateListener, this._editableConf.of([]), this._readonlyConf.of([]), this._themeConf.of([]), this._placeholderConf.of([]), this._indentWithTabConf.of([]), this._indentUnitConf.of([]), this._lineWrappingConf.of([]), this._highlightWhitespaceConf.of([]), this._languageConf.of([]), setup === 'basic' ? basicSetup : setup === 'minimal' ? minimalSetup : [], ...this.extensions(), ]; } ngOnChanges(changes) { if (changes['value']) this.setValue(this.value()); if (changes['disabled']) this.setEditable(!this.disabled); if (changes['readonly']) this.setReadonly(this.readonly()); if (changes['theme']) this.setTheme(this.theme()); if (changes['placeholder']) this.setPlaceholder(this.placeholder()); if (changes['indentWithTab']) this.setIndentWithTab(this.indentWithTab()); if (changes['indentUnit']) this.setIndentUnit(this.indentUnit()); if (changes['lineWrapping']) this.setLineWrapping(this.lineWrapping()); if (changes['highlightWhitespace']) this.setHighlightWhitespace(this.highlightWhitespace()); if (changes['language']) this.setLanguage(this.language()); if (changes['setup'] || changes['extensions']) this.setExtensions(this._getAllExtensions()); } ngOnInit() { this.view = new EditorView({ root: this.root(), parent: this._elementRef.nativeElement, state: EditorState.create({ doc: this.value(), extensions: this._getAllExtensions(), }), }); if (this.autoFocus()) this.view?.focus(); this.addEventListeners(); this.setEditable(!this.disabled); this.setReadonly(this.readonly()); this.setTheme(this.theme()); this.setPlaceholder(this.placeholder()); this.setIndentWithTab(this.indentWithTab()); this.setIndentUnit(this.indentUnit()); this.setLineWrapping(this.lineWrapping()); this.setHighlightWhitespace(this.highlightWhitespace()); this.setLanguage(this.language()); } ngOnDestroy() { this.view?.destroy(); } writeValue(value) { if (this.view) this.setValue(value); } registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.setEditable(!isDisabled); } /** Sets editor's value. */ setValue(value) { this.view?.dispatch({ changes: { from: 0, to: this.view.state.doc.length, insert: value }, }); } /** Sets editor's editable state. */ setEditable(value) { this._dispatchEffects(this._editableConf.reconfigure(EditorView.editable.of(value))); } /** Sets editor's readonly state. */ setReadonly(value) { this._dispatchEffects(this._readonlyConf.reconfigure(EditorState.readOnly.of(value))); } /** Sets editor's theme. */ setTheme(value) { this._dispatchEffects(this._themeConf.reconfigure(value === 'light' ? [] : value)); } /** Sets editor's placeholder. */ setPlaceholder(value) { this._dispatchEffects(this._placeholderConf.reconfigure(value ? placeholder(value) : [])); } /** Sets editor' indentWithTab. */ setIndentWithTab(value) { this._dispatchEffects(this._indentWithTabConf.reconfigure(value ? keymap.of([indentWithTab]) : [])); } /** Sets editor's indentUnit. */ setIndentUnit(value) { const spaceCount = Array.from({ length: value }).map(() => ' ').join(''); this._dispatchEffects(this._indentUnitConf.reconfigure(value ? indentUnit.of(spaceCount) : [])); } /** Sets editor's lineWrapping. */ setLineWrapping(value) { this._dispatchEffects(this._lineWrappingConf.reconfigure(value ? EditorView.lineWrapping : [])); } /** Sets editor's highlightWhitespace. */ setHighlightWhitespace(value) { this._dispatchEffects(this._highlightWhitespaceConf.reconfigure(value ? highlightWhitespace() : [])); } /** Sets the root extensions of the editor. */ setExtensions(value) { this._dispatchEffects(StateEffect.reconfigure.of(value)); } /** Sets editor's language dynamically. */ setLanguage(lang) { if (!lang || lang === 'Plain Text') { this._dispatchEffects(this._languageConf.reconfigure([])); return; } if (this.languages().length === 0) { if (this.view) console.error('No supported languages. Please set the `languages` prop at first.'); return; } const langDesc = this._findLanguage(lang); if (langDesc) { langDesc.load().then(lang => { this._dispatchEffects(this._languageConf.reconfigure([lang])); }); } } /** Find the language's extension by its name. Case-insensitive. */ _findLanguage(name) { const normalizedInput = name.toLowerCase(); const lang = this.languages().find(lang => [lang.name, ...lang.alias].some(alias => normalizedInput === alias.toLowerCase())); if (!lang) { console.error('Language not found:', name); console.info('Supported language names:', this.languages().map(lang => lang.name).join(', ')); return null; } return lang; } // eslint-disable-next-line @typescript-eslint/no-explicit-any _dispatchEffects(effects) { return this.view?.dispatch({ effects }); } addEventListeners() { this.view?.contentDOM.addEventListener('focus', () => { this._onTouched(); this.focus.emit(); }); this.view?.contentDOM.addEventListener('blur', () => { this._onTouched(); this.blur.emit(); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.0", type: CodeEditorComponent, isStandalone: true, selector: "ngx-code-editor, code-editor, [code-editor]", inputs: { root: { classPropertyName: "root", publicName: "root", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, indentWithTab: { classPropertyName: "indentWithTab", publicName: "indentWithTab", isSignal: true, isRequired: false, transformFunction: null }, indentUnit: { classPropertyName: "indentUnit", publicName: "indentUnit", isSignal: true, isRequired: false, transformFunction: null }, lineWrapping: { classPropertyName: "lineWrapping", publicName: "lineWrapping", isSignal: true, isRequired: false, transformFunction: null }, highlightWhitespace: { classPropertyName: "highlightWhitespace", publicName: "highlightWhitespace", isSignal: true, isRequired: false, transformFunction: null }, languages: { classPropertyName: "languages", publicName: "languages", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, setup: { classPropertyName: "setup", publicName: "setup", isSignal: true, isRequired: false, transformFunction: null }, extensions: { classPropertyName: "extensions", publicName: "extensions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change", focus: "focus", blur: "blur" }, host: { classAttribute: "code-editor" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CodeEditorComponent), multi: true, }, ], usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [".code-editor{display:block}.code-editor .cm-editor{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-code-editor, code-editor, [code-editor]', imports: [], template: '', host: { class: 'code-editor', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CodeEditorComponent), multi: true, }, ], styles: [".code-editor{display:block}.code-editor .cm-editor{height:100%}\n"] }] }], propDecorators: { disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); const sharedDeclarations = [ CodeEditorComponent, CodeDiffEditorComponent, ]; class CodeEditorModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorModule, imports: [CodeEditorComponent, CodeDiffEditorComponent], exports: [CodeEditorComponent, CodeDiffEditorComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorModule }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CodeEditorModule, decorators: [{ type: NgModule, args: [{ imports: [...sharedDeclarations], exports: sharedDeclarations, }] }] }); /* * Public API Surface of code-editor */ /** * Generated bundle index. Do not edit. */ export { CodeDiffEditorComponent, CodeEditorComponent, CodeEditorModule, External }; //# sourceMappingURL=fsegurai-ngx-codemirror.mjs.map