Add syntax highlighting to textbox
This commit is contained in:
+114
-10
@@ -14,29 +14,135 @@ app.registerExtension({
|
||||
|
||||
nodeType.prototype.populate = function() {
|
||||
this.inputEl = this.widgets[0];
|
||||
console.log(nodeType.prototype)
|
||||
console.log(this.inputEl)
|
||||
|
||||
// Implement copy functionality with proper callback
|
||||
this.addWidget("button", "Copy", "Copy", () => {
|
||||
navigator.clipboard.writeText(this.getTextboxText());
|
||||
}, { serialize: false });
|
||||
|
||||
// Implement paste functionality with proper callback handling asynchronous operation
|
||||
this.addWidget("button", "Paste", "Paste", () => {
|
||||
navigator.clipboard.readText().then(text => {
|
||||
this.inputEl.value = text;
|
||||
syncText(this.inputEl.inputEl, this.overlayEl);
|
||||
}).catch(error => {
|
||||
console.error('Failed to read clipboard contents:', error);
|
||||
});
|
||||
}, { serialize: false });
|
||||
|
||||
// Ensure the input element's parent exists
|
||||
if (this.inputEl && this.inputEl.inputEl && this.inputEl.inputEl.parentNode) {
|
||||
// Create overlay div for highlighting
|
||||
this.overlayEl = document.createElement('div');
|
||||
this.overlayEl.className = 'input-overlay';
|
||||
this.inputEl.inputEl.parentNode.insertBefore(this.overlayEl, this.inputEl.inputEl);
|
||||
|
||||
this.inputEl.inputEl.style.background = 'transparent';
|
||||
this.overlayEl.style.background = getComputedStyle(document.documentElement).getPropertyValue('--comfy-input-bg').trim();
|
||||
|
||||
// Sync text initially and on input
|
||||
this.inputEl.inputEl.addEventListener('input', () => {
|
||||
syncText(this.inputEl.inputEl, this.overlayEl);
|
||||
});
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
setOverlayPosition(this.inputEl, this.overlayEl);
|
||||
});
|
||||
|
||||
observer.observe(this.inputEl.inputEl, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style'],
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: true,
|
||||
});
|
||||
|
||||
this.inputEl.inputEl.addEventListener('keydown', (event) => {
|
||||
if (event.ctrlKey && (event.key === 'ArrowUp' || event.key === 'ArrowDown')) {
|
||||
setTimeout(() => {
|
||||
syncText(this.inputEl, this.overlayEl);
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
syncText(this.inputEl, this.overlayEl);
|
||||
setOverlayPosition(this.inputEl, this.overlayEl);
|
||||
}, 10);
|
||||
} else {
|
||||
console.error('Parent node of input element is not available.');
|
||||
}
|
||||
};
|
||||
|
||||
function syncText(inputEl, overlayEl) {
|
||||
const text = inputEl.value;
|
||||
overlayEl.textContent = text;
|
||||
|
||||
// Apply styles directly
|
||||
overlayEl.style.color = 'transparent';
|
||||
overlayEl.style.overflow = 'hidden';
|
||||
overlayEl.style.whiteSpace = 'pre-wrap';
|
||||
overlayEl.style.wordWrap = 'break-word';
|
||||
|
||||
// Colors for nested parentheses
|
||||
const colors = ['rgba(0, 255, 0, 0.5)', 'rgba(0, 0, 255, 0.5)', 'rgba(255, 0, 0, 0.5)', 'rgba(255, 255, 0, 0.5)'];
|
||||
|
||||
let nestingLevel = 0;
|
||||
let highlightedText = '';
|
||||
let lastIndex = 0;
|
||||
|
||||
const regex = /(\()|(\))/g;
|
||||
let match;
|
||||
while ((match = regex.exec(text)) !== null) {
|
||||
if (match[0] === '(') {
|
||||
const color = colors[nestingLevel % colors.length];
|
||||
nestingLevel++;
|
||||
highlightedText += text.slice(lastIndex, match.index) + `<span style="background-color: ${color};">${match[0]}`;
|
||||
} else if (match[0] === ')') {
|
||||
nestingLevel--;
|
||||
const color = colors[nestingLevel % colors.length];
|
||||
highlightedText += text.slice(lastIndex, match.index) + `${match[0]}</span>`;
|
||||
}
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
highlightedText += text.slice(lastIndex);
|
||||
|
||||
overlayEl.innerHTML = highlightedText;
|
||||
}
|
||||
|
||||
function setOverlayPosition(inputEl, overlayEl) {
|
||||
// Set the overlay's position and size to match the textarea
|
||||
const textareaStyle = window.getComputedStyle(inputEl.inputEl);
|
||||
overlayEl.style.position = 'absolute';
|
||||
overlayEl.style.left = textareaStyle.left;
|
||||
overlayEl.style.top = textareaStyle.top;
|
||||
overlayEl.style.width = textareaStyle.width;
|
||||
overlayEl.style.height = textareaStyle.height;
|
||||
overlayEl.style.zIndex = '1'; // Ensure it's just below the textarea
|
||||
overlayEl.style.pointerEvents = 'none'; // Allow clicks to pass through
|
||||
overlayEl.style.display = textareaStyle.display;
|
||||
|
||||
// Copy font and other relevant styles
|
||||
overlayEl.style.fontFamily = textareaStyle.fontFamily;
|
||||
overlayEl.style.fontSize = textareaStyle.fontSize;
|
||||
overlayEl.style.fontWeight = textareaStyle.fontWeight;
|
||||
overlayEl.style.lineHeight = textareaStyle.lineHeight;
|
||||
overlayEl.style.letterSpacing = textareaStyle.letterSpacing;
|
||||
overlayEl.style.whiteSpace = textareaStyle.whiteSpace;
|
||||
overlayEl.style.color = textareaStyle.color;
|
||||
overlayEl.style.padding = textareaStyle.padding;
|
||||
overlayEl.style.boxSizing = textareaStyle.boxSizing;
|
||||
overlayEl.style.transform = textareaStyle.transform;
|
||||
overlayEl.style.transformOrigin = textareaStyle.transformOrigin;
|
||||
}
|
||||
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
this.populate();
|
||||
// Bind the getTextboxText to this instance
|
||||
this.getTextboxText = this.getTextboxText.bind(this);
|
||||
|
||||
api.addEventListener('textbox', (event) => {
|
||||
const data = event.detail
|
||||
const data = event.detail;
|
||||
console.log("ID:", data.id);
|
||||
const outputText = this.getTextboxText();
|
||||
api.fetchApi(`${SettingUtils.API_PREFIX}/textbox_string`, {
|
||||
@@ -44,14 +150,12 @@ app.registerExtension({
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
node_id: data.id,
|
||||
outputs: {
|
||||
output: outputText
|
||||
}
|
||||
body: JSON.stringify({
|
||||
node_id: data.id,
|
||||
outputs: {
|
||||
output: outputText
|
||||
}
|
||||
),
|
||||
}),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user