@projectcaluma/ember-form-builder
Version:
Ember engine for building Caluma forms.
97 lines (77 loc) • 2.57 kB
JavaScript
import { action } from "@ember/object";
import { addObserver } from "@ember/object/observers";
import Component from "@glimmer/component";
import { CodeJar } from "codejar";
import { task, timeout } from "ember-concurrency";
import hljs from "highlight.js/lib/core";
import json from "highlight.js/lib/languages/json";
import markdown from "highlight.js/lib/languages/markdown";
import jexl from "highlightjs-jexl/src/languages/jexl";
import isEqual from "lodash.isequal";
import "highlight.js/styles/github.css";
hljs.configure({ ignoreUnescapedHTML: true });
hljs.registerLanguage("json", json);
hljs.registerLanguage("markdown", markdown);
hljs.registerLanguage("jexl", jexl);
const simplify = (value) => {
if (typeof value === "object") {
value = JSON.stringify(value?.unwrap?.() ?? value);
}
return value?.replace(/\s/g, "");
};
export default class CfbCodeEditorComponent extends Component {
_editor = null;
_lastValue = null;
get stringValue() {
if (this.args.language === "json" && typeof this.args.value === "object") {
return JSON.stringify(
this.args.value?.unwrap?.() ?? this.args.value,
null,
"\t",
);
}
return this.args.value;
}
_didChange(value) {
return !isEqual(this._lastValue, simplify(value));
}
onUpdate(value) {
if (this.args.language === "json") {
try {
value = JSON.parse(value);
} catch {
// update value directly
}
}
if (!this._didChange(value)) return;
this._lastValue = simplify(value);
this.args.update(value);
}
updateEditorContent = task({ restartable: true }, async () => {
// This function is called everytime `this.args.value` changes. In order to
// not trigger too many updates, we debounce it for 10ms.
await timeout(10);
if (!this._didChange(this.args.value)) return;
this._lastValue = simplify(this.args.value);
this._editor.updateCode(this.stringValue, false);
});
didInsertNode(element) {
this._editor = CodeJar(element, (editor) => {
editor.removeAttribute("data-highlighted");
hljs.highlightElement(editor);
});
// set initial value
this._editor.updateCode(this.stringValue, false);
this._lastValue = simplify(this.args.value);
// register update method
this._editor.onUpdate(this.onUpdate);
// eslint-disable-next-line ember/no-observers
addObserver(this.args, "value", this.updateEditorContent, "perform");
}
willDestroyNode() {
this._editor.destroy();
}
}