codemaxxing 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +70 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1745,61 +1745,99 @@ const pasteEvents = new EventEmitter();
|
|
|
1745
1745
|
// Enable bracketed paste mode — terminal wraps pastes in escape sequences
|
|
1746
1746
|
process.stdout.write("\x1b[?2004h");
|
|
1747
1747
|
// Intercept stdin to handle pasted content
|
|
1748
|
-
//
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1748
|
+
// Strategy: patch emit('data') instead of push() — this is the ONE path all data
|
|
1749
|
+
// must travel through to reach Ink's listeners, regardless of how the TTY/stream
|
|
1750
|
+
// delivers it internally.
|
|
1751
|
+
//
|
|
1752
|
+
// Two detection layers:
|
|
1753
|
+
// 1. Bracketed paste escape sequences (\x1b[200~ ... \x1b[201~)
|
|
1754
|
+
// 2. Burst buffering — accumulate rapid-fire chunks over a short window and check
|
|
1755
|
+
// whether the combined content looks like a multiline paste.
|
|
1756
|
+
let bracketedBuffer = "";
|
|
1757
|
+
let inBracketedPaste = false;
|
|
1758
|
+
let burstBuffer = "";
|
|
1759
|
+
let burstTimer = null;
|
|
1760
|
+
const BURST_WINDOW_MS = 25; // Short enough to feel instant, long enough to catch paste bursts
|
|
1761
|
+
const origEmit = process.stdin.emit.bind(process.stdin);
|
|
1762
|
+
function handlePasteContent(content) {
|
|
1752
1763
|
const normalized = content.replace(/\r\n/g, "\n").trim();
|
|
1753
1764
|
if (!normalized)
|
|
1754
|
-
return
|
|
1765
|
+
return;
|
|
1755
1766
|
const lineCount = normalized.split("\n").length;
|
|
1756
1767
|
if (lineCount > 2) {
|
|
1768
|
+
// Real multiline paste → badge it
|
|
1757
1769
|
pasteEvents.emit("paste", { content: normalized, lines: lineCount });
|
|
1758
|
-
return
|
|
1770
|
+
return;
|
|
1759
1771
|
}
|
|
1772
|
+
// Short paste (1-2 lines) → collapse to single line and forward as normal input
|
|
1760
1773
|
const sanitized = normalized.replace(/\n/g, " ");
|
|
1761
1774
|
if (sanitized) {
|
|
1762
|
-
|
|
1775
|
+
origEmit("data", sanitized);
|
|
1763
1776
|
}
|
|
1764
|
-
return true;
|
|
1765
1777
|
}
|
|
1766
|
-
function
|
|
1767
|
-
const
|
|
1768
|
-
const
|
|
1769
|
-
const
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1778
|
+
function looksLikeMultilinePaste(data) {
|
|
1779
|
+
const clean = data.replace(/\x1b\[[0-9;]*[A-Za-z]/g, ""); // Strip all ANSI escapes
|
|
1780
|
+
const newlines = (clean.match(/\r?\n/g) ?? []).length;
|
|
1781
|
+
const printable = clean.replace(/[\r\n]/g, "").trim().length;
|
|
1782
|
+
return newlines >= 2 || (newlines >= 1 && printable >= 40);
|
|
1783
|
+
}
|
|
1784
|
+
function flushBurst() {
|
|
1785
|
+
if (!burstBuffer)
|
|
1786
|
+
return;
|
|
1787
|
+
const buffered = burstBuffer;
|
|
1788
|
+
burstBuffer = "";
|
|
1789
|
+
if (looksLikeMultilinePaste(buffered)) {
|
|
1790
|
+
handlePasteContent(buffered);
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
// Normal typing — forward to Ink
|
|
1794
|
+
origEmit("data", buffered);
|
|
1795
|
+
}
|
|
1774
1796
|
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
if (
|
|
1778
|
-
return
|
|
1797
|
+
process.stdin.emit = function (event, ...args) {
|
|
1798
|
+
// Pass through non-data events untouched
|
|
1799
|
+
if (event !== "data") {
|
|
1800
|
+
return origEmit(event, ...args);
|
|
1801
|
+
}
|
|
1802
|
+
const chunk = args[0];
|
|
1779
1803
|
let data = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
|
|
1804
|
+
// ── Bracketed paste handling ──
|
|
1780
1805
|
const hasStart = data.includes("\x1b[200~");
|
|
1781
1806
|
const hasEnd = data.includes("\x1b[201~");
|
|
1782
1807
|
if (hasStart) {
|
|
1783
|
-
|
|
1808
|
+
// Flush any pending burst before entering bracketed mode
|
|
1809
|
+
if (burstTimer) {
|
|
1810
|
+
clearTimeout(burstTimer);
|
|
1811
|
+
burstTimer = null;
|
|
1812
|
+
}
|
|
1813
|
+
flushBurst();
|
|
1814
|
+
inBracketedPaste = true;
|
|
1784
1815
|
data = data.replace(/\x1b\[200~/g, "");
|
|
1785
1816
|
}
|
|
1786
1817
|
if (hasEnd) {
|
|
1787
1818
|
data = data.replace(/\x1b\[201~/g, "");
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
const content =
|
|
1791
|
-
|
|
1792
|
-
|
|
1819
|
+
bracketedBuffer += data;
|
|
1820
|
+
inBracketedPaste = false;
|
|
1821
|
+
const content = bracketedBuffer;
|
|
1822
|
+
bracketedBuffer = "";
|
|
1823
|
+
handlePasteContent(content);
|
|
1824
|
+
return true;
|
|
1793
1825
|
}
|
|
1794
|
-
if (
|
|
1795
|
-
|
|
1826
|
+
if (inBracketedPaste) {
|
|
1827
|
+
bracketedBuffer += data;
|
|
1796
1828
|
return true;
|
|
1797
1829
|
}
|
|
1830
|
+
// ── Burst buffering for non-bracketed paste ──
|
|
1831
|
+
// Strip stray bracketed paste markers that might appear outside a proper pair
|
|
1798
1832
|
data = data.replace(/\x1b\[20[01]~/g, "");
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1833
|
+
burstBuffer += data;
|
|
1834
|
+
if (burstTimer)
|
|
1835
|
+
clearTimeout(burstTimer);
|
|
1836
|
+
burstTimer = setTimeout(() => {
|
|
1837
|
+
burstTimer = null;
|
|
1838
|
+
flushBurst();
|
|
1839
|
+
}, BURST_WINDOW_MS);
|
|
1840
|
+
return true;
|
|
1803
1841
|
};
|
|
1804
1842
|
// Disable bracketed paste on exit
|
|
1805
1843
|
process.on("exit", () => {
|