UNPKG

2.76 kBJavaScriptView Raw
1/**
2 * Produces the value of a block string from its parsed raw value, similar to
3 * CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.
4 *
5 * This implements the GraphQL spec's BlockStringValue() static algorithm.
6 */
7export function dedentBlockStringValue(rawString) {
8 // Expand a block string's raw value into independent lines.
9 var lines = rawString.split(/\r\n|[\n\r]/g); // Remove common indentation from all lines but first.
10
11 var commonIndent = getBlockStringIndentation(lines);
12
13 if (commonIndent !== 0) {
14 for (var i = 1; i < lines.length; i++) {
15 lines[i] = lines[i].slice(commonIndent);
16 }
17 } // Remove leading and trailing blank lines.
18
19
20 while (lines.length > 0 && isBlank(lines[0])) {
21 lines.shift();
22 }
23
24 while (lines.length > 0 && isBlank(lines[lines.length - 1])) {
25 lines.pop();
26 } // Return a string of the lines joined with U+000A.
27
28
29 return lines.join('\n');
30} // @internal
31
32export function getBlockStringIndentation(lines) {
33 var commonIndent = null;
34
35 for (var i = 1; i < lines.length; i++) {
36 var line = lines[i];
37 var indent = leadingWhitespace(line);
38
39 if (indent === line.length) {
40 continue; // skip empty lines
41 }
42
43 if (commonIndent === null || indent < commonIndent) {
44 commonIndent = indent;
45
46 if (commonIndent === 0) {
47 break;
48 }
49 }
50 }
51
52 return commonIndent === null ? 0 : commonIndent;
53}
54
55function leadingWhitespace(str) {
56 var i = 0;
57
58 while (i < str.length && (str[i] === ' ' || str[i] === '\t')) {
59 i++;
60 }
61
62 return i;
63}
64
65function isBlank(str) {
66 return leadingWhitespace(str) === str.length;
67}
68/**
69 * Print a block string in the indented block form by adding a leading and
70 * trailing blank line. However, if a block string starts with whitespace and is
71 * a single-line, adding a leading blank line would strip that whitespace.
72 */
73
74
75export function printBlockString(value) {
76 var indentation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
77 var preferMultipleLines = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
78 var isSingleLine = value.indexOf('\n') === -1;
79 var hasLeadingSpace = value[0] === ' ' || value[0] === '\t';
80 var hasTrailingQuote = value[value.length - 1] === '"';
81 var printAsMultipleLines = !isSingleLine || hasTrailingQuote || preferMultipleLines;
82 var result = ''; // Format a multi-line block quote to account for leading space.
83
84 if (printAsMultipleLines && !(isSingleLine && hasLeadingSpace)) {
85 result += '\n' + indentation;
86 }
87
88 result += indentation ? value.replace(/\n/g, '\n' + indentation) : value;
89
90 if (printAsMultipleLines) {
91 result += '\n';
92 }
93
94 return '"""' + result.replace(/"""/g, '\\"""') + '"""';
95}