@@ -8,7 +8,7 @@ class ScriptTextInput(io.ComfyNode):
|
||||
return io.Schema(
|
||||
node_id="mrmth_ScriptInput",
|
||||
category="More math",
|
||||
display_name="Script input",
|
||||
display_name="STEW",
|
||||
inputs=[
|
||||
io.String.Input(id="script", multiline=True),
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
+40
-134
@@ -1,10 +1,8 @@
|
||||
import { app } from "/scripts/app.js";
|
||||
|
||||
const NODE_IDS = new Set(["mrmth_ScriptInput"]);
|
||||
const NODE_NAMES = new Set(["Audio -> Spectrogram", "ScriptTextInput", "STEW"]);
|
||||
const NODE_NAMES = new Set(["ScriptTextInput"]);
|
||||
const STYLE_ID = "mrmth-script-line-numbers";
|
||||
const ACE_SCRIPT_SRC = "/extensions/more_math/ace/ace.js";
|
||||
let aceLoader = null;
|
||||
|
||||
function hasScriptInput(nodeData) {
|
||||
const input = nodeData?.input || {};
|
||||
@@ -68,169 +66,77 @@ function ensureStyles() {
|
||||
font-family: monospace;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.mrmth-ace-editor {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 4px;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function loadAce() {
|
||||
if (window.ace) {
|
||||
return Promise.resolve(window.ace);
|
||||
}
|
||||
if (aceLoader) {
|
||||
return aceLoader;
|
||||
}
|
||||
|
||||
aceLoader = new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = ACE_SCRIPT_SRC;
|
||||
script.async = true;
|
||||
script.onload = () => resolve(window.ace);
|
||||
script.onerror = () => reject(new Error("Failed to load Ace editor"));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
return aceLoader;
|
||||
}
|
||||
|
||||
function attachAceEditor(widget) {
|
||||
function attachLineNumbers(widget) {
|
||||
const inputEl = widget?.inputEl;
|
||||
if (!inputEl) {
|
||||
if (!inputEl || inputEl.dataset.mrmthLineNumbers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (widget.mrmthAceEditor) {
|
||||
if (widget.value !== undefined && widget.mrmthAceEditor.getValue() !== widget.value) {
|
||||
widget.mrmthAceEditor.setValue(String(widget.value), -1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const parent = inputEl.parentElement;
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ensureStyles();
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "mrmth-line-editor";
|
||||
|
||||
const gutter = document.createElement("div");
|
||||
gutter.className = "mrmth-line-numbers";
|
||||
|
||||
const gutterContent = document.createElement("div");
|
||||
gutterContent.className = "mrmth-line-numbers-content";
|
||||
|
||||
parent.replaceChild(wrapper, inputEl);
|
||||
wrapper.appendChild(gutter);
|
||||
gutter.appendChild(gutterContent);
|
||||
wrapper.appendChild(inputEl);
|
||||
|
||||
inputEl.classList.add("mrmth-line-input");
|
||||
inputEl.dataset.mrmthLineNumbers = "true";
|
||||
|
||||
const inputStyle = getComputedStyle(inputEl);
|
||||
const parentStyle = getComputedStyle(parent);
|
||||
gutter.style.fontFamily = inputStyle.fontFamily;
|
||||
gutter.style.fontSize = inputStyle.fontSize;
|
||||
gutter.style.lineHeight = inputStyle.lineHeight;
|
||||
gutter.style.paddingTop = inputStyle.paddingTop;
|
||||
gutter.style.paddingBottom = inputStyle.paddingBottom;
|
||||
|
||||
inputEl.style.display = "none";
|
||||
const updateNumbers = () => {
|
||||
const lineCount = Math.max(1, inputEl.value.split("\n").length);
|
||||
gutterContent.textContent = Array.from({ length: lineCount }, (_, i) => String(i + 1)).join("\n");
|
||||
gutter.style.height = `${inputEl.clientHeight}px`;
|
||||
gutterContent.style.transform = `translateY(${-inputEl.scrollTop}px)`;
|
||||
};
|
||||
|
||||
const editorEl = document.createElement("div");
|
||||
editorEl.className = "mrmth-ace-editor";
|
||||
editorEl.style.height = `${inputEl.offsetHeight}px`;
|
||||
editorEl.style.background = inputStyle.backgroundColor;
|
||||
editorEl.style.color = inputStyle.color;
|
||||
editorEl.style.borderColor = inputStyle.borderColor || parentStyle.borderColor;
|
||||
editorEl.style.borderRadius = inputStyle.borderRadius || parentStyle.borderRadius;
|
||||
editorEl.style.fontFamily = inputStyle.fontFamily;
|
||||
editorEl.style.fontSize = inputStyle.fontSize;
|
||||
editorEl.style.lineHeight = inputStyle.lineHeight;
|
||||
editorEl.style.letterSpacing = inputStyle.letterSpacing;
|
||||
parent.appendChild(editorEl);
|
||||
|
||||
const aceEditor = window.ace.edit(editorEl, {
|
||||
showLineNumbers: true,
|
||||
showGutter: true,
|
||||
wrap: true,
|
||||
useWorker: false,
|
||||
});
|
||||
|
||||
if (inputStyle.fontFamily) {
|
||||
aceEditor.setOption("fontFamily", inputStyle.fontFamily);
|
||||
}
|
||||
const fontSize = parseFloat(inputStyle.fontSize);
|
||||
const lineHeightPx = parseFloat(inputStyle.lineHeight);
|
||||
if (Number.isFinite(fontSize)) {
|
||||
aceEditor.setOption("fontSize", fontSize);
|
||||
}
|
||||
if (Number.isFinite(lineHeightPx) && Number.isFinite(fontSize) && fontSize > 0) {
|
||||
aceEditor.setOption("lineHeight", lineHeightPx / fontSize);
|
||||
}
|
||||
|
||||
const paddingLeft = parseFloat(inputStyle.paddingLeft);
|
||||
const paddingRight = parseFloat(inputStyle.paddingRight);
|
||||
if (Number.isFinite(paddingLeft)) {
|
||||
aceEditor.renderer.setPadding(paddingLeft, Number.isFinite(paddingRight) ? paddingRight : paddingLeft);
|
||||
}
|
||||
|
||||
const themeBackground = inputStyle.backgroundColor || parentStyle.backgroundColor;
|
||||
const themeForeground = inputStyle.color || parentStyle.color;
|
||||
const gutterBackground = parentStyle.backgroundColor || themeBackground;
|
||||
const gutterForeground = parentStyle.color || themeForeground;
|
||||
|
||||
aceEditor.renderer.setStyle(`
|
||||
.ace_editor {
|
||||
background: ${themeBackground} !important;
|
||||
color: ${themeForeground} !important;
|
||||
}
|
||||
.ace_scroller {
|
||||
background: ${themeBackground} !important;
|
||||
}
|
||||
.ace_gutter {
|
||||
background: ${gutterBackground} !important;
|
||||
color: ${gutterForeground} !important;
|
||||
}
|
||||
.ace_gutter-layer {
|
||||
background: ${gutterBackground} !important;
|
||||
}
|
||||
.ace_gutter-cell {
|
||||
background: ${gutterBackground} !important;
|
||||
color: ${gutterForeground} !important;
|
||||
}
|
||||
.ace_gutter-active-line {
|
||||
background: ${themeBackground} !important;
|
||||
}
|
||||
.ace_cursor {
|
||||
color: ${themeForeground} !important;
|
||||
}
|
||||
`);
|
||||
|
||||
aceEditor.renderer.updateFontSize();
|
||||
aceEditor.renderer.onResize(true);
|
||||
|
||||
aceEditor.setValue(String(widget.value ?? inputEl.value ?? ""), -1);
|
||||
aceEditor.on("change", () => {
|
||||
const value = aceEditor.getValue();
|
||||
widget.value = value;
|
||||
inputEl.value = value;
|
||||
inputEl.addEventListener("input", updateNumbers);
|
||||
inputEl.addEventListener("scroll", () => {
|
||||
gutterContent.style.transform = `translateY(${-inputEl.scrollTop}px)`;
|
||||
});
|
||||
|
||||
if (window.ResizeObserver) {
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
editorEl.style.height = `${inputEl.offsetHeight}px`;
|
||||
aceEditor.resize();
|
||||
});
|
||||
const resizeObserver = new ResizeObserver(() => updateNumbers());
|
||||
resizeObserver.observe(inputEl);
|
||||
}
|
||||
|
||||
widget.mrmthAceEditor = aceEditor;
|
||||
requestAnimationFrame(updateNumbers);
|
||||
return true;
|
||||
}
|
||||
|
||||
function attachLineNumbersWithRetry(node) {
|
||||
const widget = node.widgets?.find((w) => w.name === "script");
|
||||
if (!widget) {
|
||||
if (attachLineNumbers(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadAce()
|
||||
.then(() => attachAceEditor(widget))
|
||||
.catch(() => attachLineNumbers(widget));
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
if (widget.mrmthAceEditor) {
|
||||
return;
|
||||
}
|
||||
loadAce()
|
||||
.then(() => attachAceEditor(widget))
|
||||
.catch(() => attachLineNumbers(widget));
|
||||
const retryWidget = node.widgets?.find((w) => w.name === "script");
|
||||
attachLineNumbers(retryWidget);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user