Fix browser terminal paste for hosting clients.
Deploy Ladill Hosting / deploy (push) Successful in 42s
Deploy Ladill Hosting / deploy (push) Successful in 42s
Use bracketed paste, reliably bind paste capture, stop blocking mousedown focus, and give shells a short prompt with horizontal-scroll readline so long pasted commands do not wrap incorrectly. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -101,10 +101,11 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
this.queueInput(data);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Delay initial fit to ensure container has dimensions
|
||||
requestAnimationFrame(() => {
|
||||
this.fitAddon.fit();
|
||||
this.bindTerminalInputCapture();
|
||||
this.term.focus();
|
||||
});
|
||||
|
||||
@@ -113,7 +114,7 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
this.resizeObserver = new ResizeObserver(() => this.queueResize());
|
||||
this.resizeObserver.observe(this.$refs.terminal);
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('resize', () => this.queueResize());
|
||||
window.addEventListener('beforeunload', () => this.shutdown(true));
|
||||
|
||||
@@ -256,7 +257,23 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
},
|
||||
|
||||
handleTerminalPaste(event) {
|
||||
if (!this.shouldCaptureTerminalInput(event)) {
|
||||
if (!this.sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const terminalElement = this.$refs.terminal;
|
||||
const target = event.target;
|
||||
const inTerminal = Boolean(
|
||||
terminalElement
|
||||
&& target instanceof Node
|
||||
&& (terminalElement === target || terminalElement.contains(target))
|
||||
);
|
||||
const termFocused = Boolean(
|
||||
this.term?.textarea && document.activeElement === this.term.textarea
|
||||
);
|
||||
|
||||
// Panel paste often targets the wrapper/div, not the xterm textarea.
|
||||
if (!this.terminalActive && !inTerminal && !termFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -266,14 +283,21 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
return;
|
||||
}
|
||||
|
||||
this.terminalActive = true;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation?.();
|
||||
this.queueInput(text.replace(/\r?\n/g, '\r'));
|
||||
|
||||
// Bracketed paste keeps bash/readline from mangling long pasted commands.
|
||||
const normalized = text
|
||||
.replace(/\r\n/g, '\n')
|
||||
.replace(/\r/g, '\n')
|
||||
.replace(/\n/g, '\r');
|
||||
this.queueInput(`\x1b[200~${normalized}\x1b[201~`);
|
||||
},
|
||||
|
||||
shouldCaptureTerminalInput(event) {
|
||||
if (!this.sessionId || !this.terminalActive) {
|
||||
if (!this.sessionId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -281,9 +305,19 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
const terminalElement = this.$refs.terminal;
|
||||
|
||||
if (terminalElement && target instanceof Node && terminalElement.contains(target)) {
|
||||
this.terminalActive = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.term?.textarea && document.activeElement === this.term.textarea) {
|
||||
this.terminalActive = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.terminalActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(target instanceof HTMLElement)) {
|
||||
return false;
|
||||
}
|
||||
@@ -535,6 +569,7 @@ window.hostingInteractiveTerminal = (config = {}) => {
|
||||
console.log('[Terminal] focusTerminal called');
|
||||
if (this.term) {
|
||||
this.terminalActive = true;
|
||||
this.bindTerminalInputCapture();
|
||||
this.$refs.terminal?.focus();
|
||||
this.term.focus();
|
||||
console.log('[Terminal] terminalActive set to true');
|
||||
|
||||
Reference in New Issue
Block a user