2024-08-10 23:13:20 +02:00
|
|
|
const defaultBrush = `
|
2024-09-01 10:09:23 +02:00
|
|
|
-- This is your brush.
|
|
|
|
-- Try playing around with the numbers,
|
|
|
|
-- and see what happens!
|
|
|
|
|
2024-09-01 18:54:38 +02:00
|
|
|
stroke 8 #000 (vec 0 0)
|
2024-08-10 23:13:20 +02:00
|
|
|
`.trim();
|
|
|
|
|
|
|
|
export class BrushEditor extends HTMLElement {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
|
|
|
|
connectedCallback() {
|
|
|
|
this.classList.add("rkgk-panel");
|
|
|
|
|
2024-08-24 17:47:47 +02:00
|
|
|
this.textArea = this.appendChild(document.createElement("textarea"));
|
2024-08-10 23:13:20 +02:00
|
|
|
this.textArea.classList.add("text-area");
|
2024-08-24 17:47:47 +02:00
|
|
|
this.textArea.value = localStorage.getItem("rkgk.brushEditor.code") ?? defaultBrush;
|
2024-08-10 23:13:20 +02:00
|
|
|
this.textArea.spellcheck = false;
|
2024-08-24 17:47:47 +02:00
|
|
|
this.textArea.rows = 1;
|
2024-08-10 23:13:20 +02:00
|
|
|
this.textArea.addEventListener("input", () => {
|
2024-08-24 17:47:47 +02:00
|
|
|
this.#resizeTextArea();
|
|
|
|
|
2024-08-17 22:16:31 +02:00
|
|
|
localStorage.setItem("rkgk.brushEditor.code", this.code);
|
2024-08-10 23:13:20 +02:00
|
|
|
this.dispatchEvent(
|
|
|
|
Object.assign(new Event(".codeChanged"), {
|
2024-08-17 22:16:31 +02:00
|
|
|
newCode: this.code,
|
2024-08-10 23:13:20 +02:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
});
|
2024-08-24 20:09:52 +02:00
|
|
|
requestAnimationFrame(() => this.#resizeTextArea());
|
2024-08-27 14:13:03 +02:00
|
|
|
document.fonts.addEventListener("loadingdone", () => this.#resizeTextArea());
|
2024-09-03 23:12:31 +02:00
|
|
|
new ResizeObserver(() => this.#resizeTextArea()).observe(this);
|
2024-08-19 23:56:11 +02:00
|
|
|
|
|
|
|
this.errorHeader = this.appendChild(document.createElement("h1"));
|
|
|
|
this.errorHeader.classList.add("error-header");
|
|
|
|
|
|
|
|
this.errorArea = this.appendChild(document.createElement("pre"));
|
|
|
|
this.errorArea.classList.add("errors");
|
2024-08-10 23:13:20 +02:00
|
|
|
}
|
|
|
|
|
2024-08-24 17:47:47 +02:00
|
|
|
#resizeTextArea() {
|
|
|
|
this.textArea.style.height = "";
|
|
|
|
this.textArea.style.height = `${this.textArea.scrollHeight}px`;
|
|
|
|
}
|
|
|
|
|
2024-08-10 23:13:20 +02:00
|
|
|
get code() {
|
2024-08-24 17:47:47 +02:00
|
|
|
return this.textArea.value;
|
2024-08-10 23:13:20 +02:00
|
|
|
}
|
2024-08-19 23:56:11 +02:00
|
|
|
|
|
|
|
resetErrors() {
|
|
|
|
this.errorHeader.textContent = "";
|
|
|
|
this.errorArea.textContent = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
renderHakuResult(phase, result) {
|
|
|
|
this.resetErrors();
|
|
|
|
|
|
|
|
if (result.status != "error") return;
|
|
|
|
|
|
|
|
this.errorHeader.textContent = `${phase} failed`;
|
|
|
|
|
|
|
|
if (result.errorKind == "diagnostics") {
|
|
|
|
// This is kind of wooden; I'd prefer if the error spans were rendered inline in text,
|
|
|
|
// but I haven't integrated anything for syntax highlighting yet that would let me
|
|
|
|
// do that.
|
|
|
|
this.errorArea.textContent = result.diagnostics
|
|
|
|
.map(
|
|
|
|
(diagnostic) => `${diagnostic.start}..${diagnostic.end}: ${diagnostic.message}`,
|
|
|
|
)
|
|
|
|
.join("\n");
|
|
|
|
} else if (result.errorKind == "plain") {
|
|
|
|
this.errorHeader.textContent = result.message;
|
|
|
|
} else if (result.errorKind == "exception") {
|
|
|
|
// TODO: This should show a stack trace.
|
|
|
|
this.errorArea.textContent = `an exception occurred: ${result.message}`;
|
|
|
|
} else {
|
|
|
|
console.warn(`unknown error kind: ${result.errorKind}`);
|
|
|
|
this.errorHeader.textContent = "(unknown error kind)";
|
|
|
|
}
|
|
|
|
}
|
2024-08-10 23:13:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
customElements.define("rkgk-brush-editor", BrushEditor);
|