{"version":3,"file":"blockString.js","sourceRoot":"","sources":["../../src/language/blockString.ts"],"names":[],"mappings":"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","sourcesContent":["import { isWhiteSpace } from './characterClasses.ts';\n\n/**\n * Produces the value of a block string from its parsed raw value, similar to\n * CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.\n *\n * This implements the GraphQL spec's BlockStringValue() static algorithm.\n *\n * @internal\n */\nexport function dedentBlockStringLines(\n  lines: ReadonlyArray<string>,\n): Array<string> {\n  let commonIndent = Number.MAX_SAFE_INTEGER;\n  let firstNonEmptyLine = null;\n  let lastNonEmptyLine = -1;\n\n  for (let i = 0; i < lines.length; ++i) {\n    const line = lines[i];\n    const indent = leadingWhitespace(line);\n\n    if (indent === line.length) {\n      continue; // skip empty lines\n    }\n\n    firstNonEmptyLine ??= i;\n    lastNonEmptyLine = i;\n\n    if (i !== 0 && indent < commonIndent) {\n      commonIndent = indent;\n    }\n  }\n\n  return (\n    lines\n      // Remove common indentation from all lines but first.\n      .map((line, i) => (i === 0 ? line : line.slice(commonIndent)))\n      // Remove leading and trailing blank lines.\n      .slice(firstNonEmptyLine ?? 0, lastNonEmptyLine + 1)\n  );\n}\n\nfunction leadingWhitespace(str: string): number {\n  let i = 0;\n  while (i < str.length && isWhiteSpace(str.charCodeAt(i))) {\n    ++i;\n  }\n  return i;\n}\n\n/** @internal */\nexport function isPrintableAsBlockString(value: string): boolean {\n  if (value === '') {\n    return true; // empty string is printable\n  }\n\n  let isEmptyLine = true;\n  let hasIndent = false;\n  let hasCommonIndent = true;\n  let seenNonEmptyLine = false;\n\n  for (let i = 0; i < value.length; ++i) {\n    switch (value.codePointAt(i)) {\n      case 0x0000:\n      case 0x0001:\n      case 0x0002:\n      case 0x0003:\n      case 0x0004:\n      case 0x0005:\n      case 0x0006:\n      case 0x0007:\n      case 0x0008:\n      case 0x000b:\n      case 0x000c:\n      case 0x000e:\n      case 0x000f:\n        return false; // Has non-printable characters\n\n      case 0x000d: //  \\r\n        return false; // Has \\r or \\r\\n which will be replaced as \\n\n\n      case 10: //  \\n\n        if (isEmptyLine && !seenNonEmptyLine) {\n          return false; // Has leading new line\n        }\n        seenNonEmptyLine = true;\n\n        isEmptyLine = true;\n        hasIndent = false;\n        break;\n      case 9: //   \\t\n      case 32: //  <space>\n        hasIndent ||= isEmptyLine;\n        break;\n      default:\n        hasCommonIndent &&= hasIndent;\n        isEmptyLine = false;\n    }\n  }\n\n  if (isEmptyLine) {\n    return false; // Has trailing empty lines\n  }\n\n  if (hasCommonIndent && seenNonEmptyLine) {\n    return false; // Has internal indent\n  }\n\n  return true;\n}\n\n/**\n * Print a block string in the indented block form by adding a leading and\n * trailing blank line. However, if a block string starts with whitespace and is\n * a single-line, adding a leading blank line would strip that whitespace.\n *\n * @internal\n */\nexport function printBlockString(\n  value: string,\n  options?: { minimize?: boolean },\n): string {\n  const escapedValue = value.replaceAll('\"\"\"', '\\\\\"\"\"');\n\n  // Expand a block string's raw value into independent lines.\n  const lines = escapedValue.split(/\\r\\n|[\\n\\r]/g);\n  const isSingleLine = lines.length === 1;\n\n  // If common indentation is found we can fix some of those cases by adding leading new line\n  const forceLeadingNewLine =\n    lines.length > 1 &&\n    lines\n      .slice(1)\n      .every((line) => line.length === 0 || isWhiteSpace(line.charCodeAt(0)));\n\n  // Trailing triple quotes just looks confusing but doesn't force trailing new line\n  const hasTrailingTripleQuotes = escapedValue.endsWith('\\\\\"\"\"');\n\n  // Trailing quote (single or double) or slash forces trailing new line\n  const hasTrailingQuote = value.endsWith('\"') && !hasTrailingTripleQuotes;\n  const hasTrailingSlash = value.endsWith('\\\\');\n  const forceTrailingNewline = hasTrailingQuote || hasTrailingSlash;\n\n  const printAsMultipleLines =\n    !options?.minimize &&\n    // add leading and trailing new lines only if it improves readability\n    (!isSingleLine ||\n      value.length > 70 ||\n      forceTrailingNewline ||\n      forceLeadingNewLine ||\n      hasTrailingTripleQuotes);\n\n  let result = '';\n\n  // Format a multi-line block quote to account for leading space.\n  const skipLeadingNewLine = isSingleLine && isWhiteSpace(value.charCodeAt(0));\n  if ((printAsMultipleLines && !skipLeadingNewLine) || forceLeadingNewLine) {\n    result += '\\n';\n  }\n\n  result += escapedValue;\n  if (printAsMultipleLines || forceTrailingNewline) {\n    result += '\\n';\n  }\n\n  return '\"\"\"' + result + '\"\"\"';\n}\n"]}