import m from 'mithril'; import CodeMirror from 'codemirror'; import 'codemirror/mode/meta'; import 'codemirror/mode/javascript/javascript'; import 'codemirror/mode/jsx/jsx'; import 'codemirror/mode/php/php'; import { SourceCode as SourceCodeEntity } from '../../../Entity/SourceCode'; import { SourceCode as SourceCodePresenter } from './SourceCode'; import { EventStore } from '../../../Infrastructure/Event/EventStore'; import { SelectMetrics } from '../../../Infrastructure/Event/SelectMetrics'; type Param = { sourceCode: SourceCodeEntity; }; export class SourceCode implements m.Component { private editor?: CodeMirror.EditorFromTextArea; oninit() { EventStore.get(SelectMetrics).listener((metrics) => { if (!this.editor) { return; } const element = document.getElementById('codemirrorStyle')!; element.innerText = ''; if (!metrics) { return; } // @fixme: dirty hack. I was using the addLineClass method of CodeMirror. However, since it is very slow, I decided to edit the style directly. element.textContent = `.CodeMirror-code div:nth-child(n+${metrics.getStartLineNumber()}) ~ div:nth-child(-n+${metrics.getEndLineNumber() + 1}) .CodeMirror-line {background-color: #ffdd57;}`; this.editor.scrollIntoView({ line: metrics.getStartLineNumber(), ch: 0, }); }); } onremove() { this.editor = null; } oncreate(vnode: m.VnodeDOM) { const { mime } = CodeMirror.findModeByExtension(vnode.attrs.sourceCode.extension); this.editor = CodeMirror.fromTextArea(vnode.dom.querySelector('textarea')!, { lineNumbers: true, lineWrapping: true, readOnly: true, viewportMargin: Infinity, mode: mime, }); } view(vnode: m.Vnode) { return [m(SourceCodePresenter, vnode.attrs), m('style', { id: 'codemirrorStyle' })]; } }