fix(importer-curl): join line continuations that have trailing whitespace (#644)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Gregory Schier
2026-09-12 23:33:54 -07:00
committed by GitHub
co-authored by Claude Fable 5.1
parent eff0c06cb0
commit ff7eebf3cd
2 changed files with 33 additions and 2 deletions
+6 -2
View File
@@ -98,8 +98,12 @@ export const plugin: PluginDefinition = {
* Handles line continuations, semicolons, and newline-separated curl commands. * Handles line continuations, semicolons, and newline-separated curl commands.
*/ */
function splitCommands(rawData: string): string[] { function splitCommands(rawData: string): string[] {
// Join line continuations (backslash-newline, and backslash-CRLF for Windows) // Join line continuations (backslash-newline, and backslash-CRLF for
const joined = rawData.replace(/\\\r?\n/g, " "); // Windows). Trailing spaces or tabs after the backslash are common when a
// command is copied from a terminal or a doc, and the shell treats
// "\ <newline>" as an escaped space rather than a continuation, so accept
// them here to keep the pasted command in one piece.
const joined = rawData.replace(/\\[ \t]*\r?\n/g, " ");
// Count consecutive backslashes immediately before position i. // Count consecutive backslashes immediately before position i.
// An even count means the quote at i is NOT escaped; odd means it IS escaped. // An even count means the quote at i is NOT escaped; odd means it IS escaped.
+27
View File
@@ -142,6 +142,33 @@ describe("importer-curl", () => {
}); });
}); });
// A trailing space after the continuation backslash is invisible in most
// editors but used to stop the join, so the quoted body split across
// lines and the parser failed with "Got EOF while in a quoted string".
test("Imports line continuations with trailing whitespace after the backslash", () => {
expect(
convertCurl(
"curl -X POST https://yaak.app \\ \n -H 'Content-Type: application/json' \\\t\n --data '{\"a\":1}' \\ \r\n -H 'Accept: application/json'",
),
).toEqual({
resources: {
workspaces: [baseWorkspace()],
httpRequests: [
baseRequest({
url: "https://yaak.app",
method: "POST",
headers: [
{ name: "Content-Type", value: "application/json", enabled: true },
{ name: "Accept", value: "application/json", enabled: true },
],
bodyType: "application/json",
body: { text: '{"a":1}' },
}),
],
},
});
});
test("Imports with Windows CRLF line endings", () => { test("Imports with Windows CRLF line endings", () => {
expect(convertCurl("curl \\\r\n -X POST \\\r\n https://yaak.app")).toEqual({ expect(convertCurl("curl \\\r\n -X POST \\\r\n https://yaak.app")).toEqual({
resources: { resources: {