Skip to content

Commit b4a021a

Browse files
authored
Add heredoc support for cURL JSON body (#3790)
1 parent 1d92dc1 commit b4a021a

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

.changeset/big-jeans-press.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@gitbook/react-openapi': patch
3+
---
4+
5+
Add heredoc support for cURL JSON body

packages/react-openapi/src/code-samples.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ ${headerString}${bodyString}`;
8181
label: 'cURL',
8282
syntax: 'bash',
8383
generate: ({ method, url: { origin, path }, headers, body }) => {
84-
const separator = ' \\\n';
85-
8684
const lines: string[] = ['curl -L'];
8785

8886
if (method.toUpperCase() !== 'GET') {
@@ -114,7 +112,7 @@ ${headerString}${bodyString}`;
114112
}
115113
}
116114

117-
return lines.map((line, index) => (index > 0 ? indent(line, 2) : line)).join(separator);
115+
return buildHeredoc(lines);
118116
},
119117
},
120118
{
@@ -262,7 +260,15 @@ const BodyGenerators = {
262260
} else if (isYAML(contentType)) {
263261
body = `--data-binary $'${yaml.dump(body).replace(/'/g, '').replace(/\\n/g, '\n')}'`;
264262
} else {
265-
body = `--data '${stringifyOpenAPI(body, null, 2).replace(/\\n/g, '\n')}'`;
263+
// For JSON, check if it contains single quotes, if so, use heredoc to avoid single quote issues
264+
const jsonString = stringifyOpenAPI(body, null, 2).replace(/\\n/g, '\n');
265+
if (jsonString.includes("'")) {
266+
// Use heredoc format: return array with --data @- <<'EOF', JSON lines, and EOF
267+
const jsonLines = jsonString.split('\n');
268+
body = ["--data @- <<'EOF'", ...jsonLines, 'EOF'];
269+
} else {
270+
body = `--data '${jsonString}'`;
271+
}
266272
}
267273

268274
return {
@@ -447,3 +453,37 @@ function convertBodyToXML(body: any): string {
447453

448454
return json2xml(body).replace(/"/g, '').replace(/\\n/g, '\n').replace(/\\t/g, '\t');
449455
}
456+
457+
/**
458+
* Builds a heredoc string from an array of lines
459+
*/
460+
function buildHeredoc(lines: string[]): string {
461+
const separator = ' \\\n';
462+
let result = '';
463+
let inHeredoc = false;
464+
465+
for (let i = 0; i < lines.length; i++) {
466+
const line = lines[i];
467+
if (!line) continue;
468+
469+
const isHeredocStart = line.includes("<<'EOF'");
470+
const isHeredocEnd = inHeredoc && line === 'EOF';
471+
472+
if (isHeredocStart) {
473+
inHeredoc = true;
474+
// Heredoc start: indent with backslash continuation from previous line, then newline
475+
result += `${i > 0 ? indent(line, 2) : line}\n`;
476+
} else if (isHeredocEnd) {
477+
inHeredoc = false;
478+
// EOF: no indent, no backslash, no separator
479+
result += line;
480+
} else if (inHeredoc) {
481+
// Inside heredoc: indent JSON lines, no backslash, newline
482+
result += `${indent(line, 2)}\n`;
483+
} else {
484+
// Normal line: indent and add separator (backslash) if not last line
485+
result += `${i > 0 ? indent(line, 2) : line}${i < lines.length - 1 ? separator : ''}`;
486+
}
487+
}
488+
return result;
489+
}

0 commit comments

Comments
 (0)