You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.1 KiB
195 lines
5.1 KiB
'use strict'; |
|
|
|
Object.defineProperty(exports, '__esModule', { |
|
value: true, |
|
}); |
|
exports.dedentBlockStringLines = dedentBlockStringLines; |
|
exports.isPrintableAsBlockString = isPrintableAsBlockString; |
|
exports.printBlockString = printBlockString; |
|
|
|
var _characterClasses = require('./characterClasses.js'); |
|
|
|
/** |
|
* Produces the value of a block string from its parsed raw value, similar to |
|
* CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc. |
|
* |
|
* This implements the GraphQL spec's BlockStringValue() static algorithm. |
|
* |
|
* @internal |
|
*/ |
|
function dedentBlockStringLines(lines) { |
|
var _firstNonEmptyLine2; |
|
|
|
let commonIndent = Number.MAX_SAFE_INTEGER; |
|
let firstNonEmptyLine = null; |
|
let lastNonEmptyLine = -1; |
|
|
|
for (let i = 0; i < lines.length; ++i) { |
|
var _firstNonEmptyLine; |
|
|
|
const line = lines[i]; |
|
const indent = leadingWhitespace(line); |
|
|
|
if (indent === line.length) { |
|
continue; // skip empty lines |
|
} |
|
|
|
firstNonEmptyLine = |
|
(_firstNonEmptyLine = firstNonEmptyLine) !== null && |
|
_firstNonEmptyLine !== void 0 |
|
? _firstNonEmptyLine |
|
: i; |
|
lastNonEmptyLine = i; |
|
|
|
if (i !== 0 && indent < commonIndent) { |
|
commonIndent = indent; |
|
} |
|
} |
|
|
|
return lines // Remove common indentation from all lines but first. |
|
.map((line, i) => (i === 0 ? line : line.slice(commonIndent))) // Remove leading and trailing blank lines. |
|
.slice( |
|
(_firstNonEmptyLine2 = firstNonEmptyLine) !== null && |
|
_firstNonEmptyLine2 !== void 0 |
|
? _firstNonEmptyLine2 |
|
: 0, |
|
lastNonEmptyLine + 1, |
|
); |
|
} |
|
|
|
function leadingWhitespace(str) { |
|
let i = 0; |
|
|
|
while ( |
|
i < str.length && |
|
(0, _characterClasses.isWhiteSpace)(str.charCodeAt(i)) |
|
) { |
|
++i; |
|
} |
|
|
|
return i; |
|
} |
|
/** |
|
* @internal |
|
*/ |
|
|
|
function isPrintableAsBlockString(value) { |
|
if (value === '') { |
|
return true; // empty string is printable |
|
} |
|
|
|
let isEmptyLine = true; |
|
let hasIndent = false; |
|
let hasCommonIndent = true; |
|
let seenNonEmptyLine = false; |
|
|
|
for (let i = 0; i < value.length; ++i) { |
|
switch (value.codePointAt(i)) { |
|
case 0x0000: |
|
case 0x0001: |
|
case 0x0002: |
|
case 0x0003: |
|
case 0x0004: |
|
case 0x0005: |
|
case 0x0006: |
|
case 0x0007: |
|
case 0x0008: |
|
case 0x000b: |
|
case 0x000c: |
|
case 0x000e: |
|
case 0x000f: |
|
return false; |
|
// Has non-printable characters |
|
|
|
case 0x000d: |
|
// \r |
|
return false; |
|
// Has \r or \r\n which will be replaced as \n |
|
|
|
case 10: |
|
// \n |
|
if (isEmptyLine && !seenNonEmptyLine) { |
|
return false; // Has leading new line |
|
} |
|
|
|
seenNonEmptyLine = true; |
|
isEmptyLine = true; |
|
hasIndent = false; |
|
break; |
|
|
|
case 9: // \t |
|
|
|
case 32: |
|
// <space> |
|
hasIndent || (hasIndent = isEmptyLine); |
|
break; |
|
|
|
default: |
|
hasCommonIndent && (hasCommonIndent = hasIndent); |
|
isEmptyLine = false; |
|
} |
|
} |
|
|
|
if (isEmptyLine) { |
|
return false; // Has trailing empty lines |
|
} |
|
|
|
if (hasCommonIndent && seenNonEmptyLine) { |
|
return false; // Has internal indent |
|
} |
|
|
|
return true; |
|
} |
|
/** |
|
* Print a block string in the indented block form by adding a leading and |
|
* trailing blank line. However, if a block string starts with whitespace and is |
|
* a single-line, adding a leading blank line would strip that whitespace. |
|
* |
|
* @internal |
|
*/ |
|
|
|
function printBlockString(value, options) { |
|
const escapedValue = value.replace(/"""/g, '\\"""'); // Expand a block string's raw value into independent lines. |
|
|
|
const lines = escapedValue.split(/\r\n|[\n\r]/g); |
|
const isSingleLine = lines.length === 1; // If common indentation is found we can fix some of those cases by adding leading new line |
|
|
|
const forceLeadingNewLine = |
|
lines.length > 1 && |
|
lines |
|
.slice(1) |
|
.every( |
|
(line) => |
|
line.length === 0 || |
|
(0, _characterClasses.isWhiteSpace)(line.charCodeAt(0)), |
|
); // Trailing triple quotes just looks confusing but doesn't force trailing new line |
|
|
|
const hasTrailingTripleQuotes = escapedValue.endsWith('\\"""'); // Trailing quote (single or double) or slash forces trailing new line |
|
|
|
const hasTrailingQuote = value.endsWith('"') && !hasTrailingTripleQuotes; |
|
const hasTrailingSlash = value.endsWith('\\'); |
|
const forceTrailingNewline = hasTrailingQuote || hasTrailingSlash; |
|
const printAsMultipleLines = |
|
!(options !== null && options !== void 0 && options.minimize) && // add leading and trailing new lines only if it improves readability |
|
(!isSingleLine || |
|
value.length > 70 || |
|
forceTrailingNewline || |
|
forceLeadingNewLine || |
|
hasTrailingTripleQuotes); |
|
let result = ''; // Format a multi-line block quote to account for leading space. |
|
|
|
const skipLeadingNewLine = |
|
isSingleLine && (0, _characterClasses.isWhiteSpace)(value.charCodeAt(0)); |
|
|
|
if ((printAsMultipleLines && !skipLeadingNewLine) || forceLeadingNewLine) { |
|
result += '\n'; |
|
} |
|
|
|
result += escapedValue; |
|
|
|
if (printAsMultipleLines || forceTrailingNewline) { |
|
result += '\n'; |
|
} |
|
|
|
return '"""' + result + '"""'; |
|
}
|
|
|