@levu/snap 0.3.3 → 0.3.5
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/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.5] - 2026-02-26
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Added an additional Ghostty/macOS fallback for `Shift+Enter` when emitted as plain `1`, `3`, `~` keypress chars (no modifier metadata).
|
|
12
|
+
- Added submit-time sanitation of residual Ghostty shift-enter tokens (`13~`, related escape variants) so pasted/echoed artifacts become real newlines in multiline prompts.
|
|
13
|
+
- Added regression coverage for plain-char `13~` keypress and residual token sanitation.
|
|
14
|
+
|
|
15
|
+
## [0.3.4] - 2026-02-26
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Fixed `picocolors` ESM/CJS interop in multiline and password adapters to prevent runtime errors like `pc.cyan is not a function`.
|
|
19
|
+
- Keeps Ghostty `Shift+Enter` (`13~`) fallback and custom password input fixes from `0.3.3`.
|
|
20
|
+
|
|
8
21
|
## [0.3.3] - 2026-02-26
|
|
9
22
|
|
|
10
23
|
### Fixed
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createInterface, emitKeypressEvents } from 'node:readline';
|
|
2
|
-
import
|
|
2
|
+
import pcModule from 'picocolors';
|
|
3
|
+
const pc = pcModule?.default ?? pcModule;
|
|
3
4
|
export const createMultilineTextPrompt = () => {
|
|
4
5
|
return async (opts) => {
|
|
5
6
|
const { message, initialValue = '', placeholder = '', validate, allowPaste = false, input = process.stdin, output = process.stdout, signal, } = opts;
|
|
@@ -97,6 +98,12 @@ export const createMultilineTextPrompt = () => {
|
|
|
97
98
|
}
|
|
98
99
|
return null;
|
|
99
100
|
};
|
|
101
|
+
const normalizeGhosttyInlineTokens = (raw) => {
|
|
102
|
+
return raw.replace(/(?:\u001b\[13;2u|\[13;2u|\u001b\[27;2;13~|\[27;2;13~|13~|~13)/g, '\n');
|
|
103
|
+
};
|
|
104
|
+
const buildSubmitValue = () => {
|
|
105
|
+
return normalizeGhosttyInlineTokens(lines.concat(getLiveLine()).join('\n'));
|
|
106
|
+
};
|
|
100
107
|
const insertNewline = () => {
|
|
101
108
|
lines.push(getLiveLine());
|
|
102
109
|
currentLine = '';
|
|
@@ -170,7 +177,7 @@ export const createMultilineTextPrompt = () => {
|
|
|
170
177
|
const now = Date.now();
|
|
171
178
|
// Check for double Enter to submit
|
|
172
179
|
if (line === '' && now - lastEnterTime < DOUBLE_ENTER_TIMEOUT) {
|
|
173
|
-
submit(
|
|
180
|
+
submit(buildSubmitValue());
|
|
174
181
|
return;
|
|
175
182
|
}
|
|
176
183
|
lastEnterTime = now;
|
|
@@ -209,6 +216,20 @@ export const createMultilineTextPrompt = () => {
|
|
|
209
216
|
keypressListener = async (str, key) => {
|
|
210
217
|
if (cancelled)
|
|
211
218
|
return;
|
|
219
|
+
// Some terminals emit Shift+Enter as literal chars "13~" with no key metadata.
|
|
220
|
+
// Readline may already have appended those chars into rl.line by the time we run.
|
|
221
|
+
if (!key?.ctrl && !key?.meta && key?.name !== 'enter' && key?.name !== 'return') {
|
|
222
|
+
const strippedLive = stripGhosttyShiftEnterSuffix(String(rl.line ?? ''));
|
|
223
|
+
if (strippedLive !== null) {
|
|
224
|
+
lines.push(strippedLive);
|
|
225
|
+
currentLine = '';
|
|
226
|
+
rl.line = '';
|
|
227
|
+
output.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
228
|
+
output.write(`${pc.dim('> ')}${strippedLive}`);
|
|
229
|
+
output.write(`\n${pc.dim('> ')}`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
212
233
|
// Detect Ctrl+V or Cmd+V for paste
|
|
213
234
|
if ((key.ctrl && key.name === 'v') || (key.meta && key.name === 'v')) {
|
|
214
235
|
const pasted = await handlePaste();
|
|
@@ -240,7 +261,7 @@ export const createMultilineTextPrompt = () => {
|
|
|
240
261
|
insertNewline();
|
|
241
262
|
return;
|
|
242
263
|
}
|
|
243
|
-
submit(
|
|
264
|
+
submit(buildSubmitValue());
|
|
244
265
|
}
|
|
245
266
|
else if (key.name === 'escape') {
|
|
246
267
|
doCancel();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { password as clackPassword } from '@clack/prompts';
|
|
2
2
|
import { emitKeypressEvents } from 'node:readline';
|
|
3
|
-
import
|
|
3
|
+
import pcModule from 'picocolors';
|
|
4
4
|
import { PromptCancelledError, unwrapClackResult } from './cancel.js';
|
|
5
|
+
const pc = pcModule?.default ?? pcModule;
|
|
5
6
|
export const runPasswordPrompt = async (input) => {
|
|
6
7
|
const inStream = (input.input ?? process.stdin);
|
|
7
8
|
const outStream = (input.output ?? process.stdout);
|