All files / lib code-editor.view.ts

0% Statements 0/25
0% Branches 0/3
0% Functions 0/6
0% Lines 0/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78                                                                                                                                                           
import { BehaviorSubject, combineLatest, ReplaySubject } from 'rxjs'
import { HTMLElement$, VirtualDOM } from '@youwol/flux-view'
import CodeMirror from 'codemirror'
import { distinctUntilChanged } from 'rxjs/operators'
import { SourceCode } from './common'
 
export class CodeEditorView {
    public readonly config = {
        value: '',
        lineNumbers: true,
        theme: 'blackboard',
        lineWrapping: false,
        indentUnit: 4,
    }
    public readonly language: string
    public readonly class = 'w-100 h-100 d-flex flex-column overflow-auto'
    public readonly style = {
        'font-size': 'initial',
    }
    public readonly file$: BehaviorSubject<SourceCode>
    public readonly change$ = new ReplaySubject<CodeMirror.EditorChange[]>(1)
    public readonly cursor$ = new ReplaySubject<CodeMirror.Position>(1)
    public readonly children: VirtualDOM[]
 
    public readonly nativeEditor$ = new ReplaySubject<CodeMirror.Editor>(1)
 
    constructor(params: {
        file$: BehaviorSubject<SourceCode>
        language: string
        config?: unknown
    }) {
        Object.assign(this, params)
        const config = {
            ...this.config,
            mode: this.language,
            value: this.file$.getValue().content,
        }
        combineLatest([
            this.file$.pipe(
                distinctUntilChanged((f1, f2) => f1.path == f2.path),
            ),
            this.nativeEditor$,
        ]).subscribe(([file, nativeEditor]) => {
            nativeEditor.setValue(file.content)
        })
        this.children = [
            {
                id: 'code-mirror-editor',
                class: 'w-100 h-100',
                connectedCallback: (elem: HTMLElement$ & HTMLDivElement) => {
                    const editor: CodeMirror.Editor = window['CodeMirror'](
                        elem,
                        config,
                    )
                    this.nativeEditor$.next(editor)
                    editor.on('changes', (_, changeObj) => {
                        this.change$.next(changeObj)
                        Iif (
                            changeObj.length == 1 &&
                            changeObj[0].origin == 'setValue'
                        ) {
                            return
                        }
                        this.file$.next({
                            content: editor.getValue(),
                            path: this.file$.getValue().path,
                        })
                    })
                    elem.querySelector('.CodeMirror').classList.add('h-100')
                    editor.on('cursorActivity', () => {
                        this.cursor$.next(editor.getCursor())
                    })
                },
            },
        ]
    }
}