code-editor.ts

109 lines | 3.801 kB Blame History Raw Download
import { BaseElement } from "../../../shared/_base";
import './code-editor.less';
import * as monaco from 'monaco-editor';
import { OutputFrame } from "../output-frame/output-frame";
import { debounceManager } from "../../../shared/ensure-debounce";
import * as sessionApi from '../../../shared/session-api';
import { isSessionPage } from "../../../shared/page";
import { sanityConvert } from "../../../shared/sanity-code-check";

export class CodeEditor extends BaseElement {

    public input: string = "";
    public language: string = "";
    public editor!: monaco.editor.IStandaloneCodeEditor;
    public lastInputCache: any;

    onInit(): void {

        this.initWorkers();
        this.language = this.tagName.substring(0, this.tagName.indexOf("-")).toLocaleLowerCase();
        this.lastInputCache = localStorage.getItem(this.language + "LastInputCache");
        this.input = this.setInitInput();
        
        this.setInitSettings();

        const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

        this.editor = monaco.editor.create(this, {
            value: isSessionPage() ? "" : this.input,
            language: this.language,
            automaticLayout: true,
            contextmenu: false,
            readOnly: isSessionPage(),
            minimap: {
                enabled: false
            },
            autoIndent: "full",
            theme: prefersDarkScheme.matches ? 'vs-dark' : 'vs-light'
        });

        var debounce = debounceManager(1000);
        this.editor.onDidChangeModelContent((e) => {
            if (!isSessionPage()) {
                this.input = this.editor.getValue();
                this.lastInputCache = this.input;
                localStorage.setItem(this.language + "LastInputCache", this.input);
                debounce.ensureDebounce(() => {
                    sessionApi.setSessionData(this.language, this.input);
                    this.outputFrame.setContent(this.language, this.language.toLowerCase() === "javascript" ? sanityConvert(this.input) : this.input);
                });
            }
        });

        this.waitFor(this.outputFrame, () => {
            this.outputFrame.setContent(this.language, isSessionPage() ? "" : (this.language.toLowerCase() === "javascript" ? sanityConvert(this.input) : this.input));
        });

    }

    setInput(input: any) {
        if (this.input !== input) {
            this.input = input;
            this.lastInputCache = this.input;
            localStorage.setItem(this.language + "LastInputCache", this.input);
            this.editor.setValue(input);
            this.outputFrame.setContent(this.language, this.language.toLowerCase() === "javascript" ? sanityConvert(this.input) : this.input);
        }
    }

    setInitInput(): string {
        if (!isSessionPage() && sessionApi.hasSession()) {
            return this.lastInputCache;
        }
        else {
            return "";
        }

    }

    setInitSettings(): void {

    }


    initWorkers() {
        // @ts-ignore
        self.MonacoEnvironment = {
            getWorkerUrl: function (moduleId: any, label: string) {
                if (label === 'json') {
                    return './json.worker.bundle.js';
                }
                if (label === 'css' || label === 'scss' || label === 'less') {
                    return './css.worker.bundle.js';
                }
                if (label === 'html' || label === 'handlebars' || label === 'razor') {
                    return './html.worker.bundle.js';
                }
                if (label === 'typescript' || label === 'javascript') {
                    return './ts.worker.bundle.js';
                }
                return './editor.worker.bundle.js';
            }
        };
    }

    get outputFrame(): OutputFrame {
        return <OutputFrame>this.find("output-frame");
    }
}