Skip splitting on escaped semicolons in splitCommands

A backslash-escaped semicolon (\;) outside quotes is a literal
character in shell syntax, not a command separator. Reuse the
existing isEscaped() helper to check delimiter parity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gregory Schier
2026-02-09 08:01:26 -08:00
parent 3190de289d
commit 3259071f7e
2 changed files with 22 additions and 2 deletions
+2 -2
View File
@@ -120,8 +120,8 @@ function splitCommands(rawData: string): string[] {
const inQuote = inSingleQuote || inDoubleQuote || inDollarQuote;
// Split on ;, newline, or CRLF when not inside quotes
if (!inQuote && (ch === ';' || ch === '\n' || (ch === '\r' && next === '\n'))) {
// Split on ;, newline, or CRLF when not inside quotes and not escaped
if (!inQuote && !isEscaped(i) && (ch === ';' || ch === '\n' || (ch === '\r' && next === '\n'))) {
if (ch === '\r') i++; // Skip the \n in \r\n
if (current.trim()) {
commands.push(current.trim());
+20
View File
@@ -599,6 +599,26 @@ describe('importer-curl', () => {
});
});
test('Does not split on escaped semicolon outside quotes', () => {
// In shell, \; is a literal semicolon and should not split commands.
// This should be treated as a single curl command with the URL "https://yaak.app?a=1;b=2"
expect(
convertCurl('curl https://yaak.app?a=1\\;b=2'),
).toEqual({
resources: {
workspaces: [baseWorkspace()],
httpRequests: [
baseRequest({
url: 'https://yaak.app',
urlParameters: [
{ name: 'a', value: '1;b=2', enabled: true },
],
}),
],
},
});
});
test('Imports multipart form data with text-only fields from --data-raw', () => {
const curlCommand = `curl 'http://example.com/api' \
-H 'Content-Type: multipart/form-data; boundary=----FormBoundary123' \