text: 'use strict';
  
  Object.defineProperty(exports, '__esModule', {
    value: true,
  });
  exports.print = print;
  
  var _visitor = require('./visitor.js');
  
  var _blockString = require('./blockString.js');
  
  var _printString = require('./printString.js');
  
  /**
   * Converts an AST into a string, using one set of reasonable
   * formatting rules.
   */
  function print(ast) {
    return (0, _visitor.visit)(ast, printDocASTReducer);
  }
  
  const MAX_LINE_LENGTH = 80;
  const printDocASTReducer = {
    Name: {
      leave: (node) => node.value,
    },
    Variable: {
      leave: (node) => '$' + node.name,
    },
    // Document
    Document: {
      leave: (node) => join(node.definitions, '\n\n'),
    },
    OperationDefinition: {
      leave(node) {
        const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
        const prefix = join(
          [
            node.operation,
            join([node.name, varDefs]),
            join(node.directives, ' '),
          ],
          ' ',
        ); // Anonymous queries with no directives or variable definitions can use
        // the query short form.
  
        return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet;
      },
    },
    VariableDefinition: {
      leave: ({ variable, type, defaultValue, directives }) =>
        variable +
        ': ' +
        type +
        wrap(' = ', defaultValue) +
        wrap(' ', join(directives, ' ')),
    },
    SelectionSet: {
      leave: ({ selections }) => block(selections),
    },
    Field: {
      leave({ alias, name, arguments: args, directives, selectionSet }) {
        const prefix = wrap('', alias, ': ') + name;
        let argsLine = prefix + wrap('(', join(args, ', '), ')');
  
        if (argsLine.length > MAX_LINE_LENGTH) {
          argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)');
        }
  
        return join([argsLine, join(directives, ' '), selectionSet], ' ');
      },
    },
    Argument: {
      leave: ({ name, value }) => name + ': ' + value,
    },
    // Fragments
    FragmentSpread: {
      leave: ({ name, directives }) =>
        '...' + name + wrap(' ', join(directives, ' ')),
    },
    InlineFragment: {
      leave: ({ typeCondition, directives, selectionSet }) =>
        join(
          [
            '...',
            wrap('on ', typeCondition),
            join(directives, ' '),
            selectionSet,
          ],
          ' ',
        ),
    },
    FragmentDefinition: {
      leave: (
        { name, typeCondition, variableDefinitions, directives, selectionSet }, // Note: fragment variable definitions are experimental and may be changed
      ) =>
        // or removed in the future.
        `fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` +
        `on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` +
        selectionSet,
    },
    // Value
    IntValue: {
      leave: ({ value }) => value,
    },
    FloatValue: {
      leave: ({ value }) => value,
    },
    StringValue: {
      leave: ({ value, block: isBlockString }) =>
        isBlockString
          ? (0, _blockString.printBlockString)(value)
          : (0, _printString.printString)(value),
    },
    BooleanValue: {
      leave: ({ value }) => (value ? 'true' : 'false'),
    },
    NullValue: {
      leave: () => 'null',
    },
    EnumValue: {
      leave: ({ value }) => value,
    },
    ListValue: {
      leave: ({ values }) => '[' + join(values, ', ') + ']',
    },
    ObjectValue: {
      leave: ({ fields }) => '{' + join(fields, ', ') + '}',
    },
    ObjectField: {
      leave: ({ name, value }) => name + ': ' + value,
    },
    // Directive
    Directive: {
      leave: ({ name, arguments: args }) =>
        '@' + name + wrap('(', join(args, ', '), ')'),
    },
    // Type
    NamedType: {
      leave: ({ name }) => name,
    },
    ListType: {
      leave: ({ type }) => '[' + type + ']',
    },
    NonNullType: {
      leave: ({ type }) => type + '!',
    },
    // Type System Definitions
    SchemaDefinition: {
      leave: ({ description, directives, operationTypes }) =>
        wrap('', description, '\n') +
        join(['schema', join(directives, ' '), block(operationTypes)], ' '),
    },
    OperationTypeDefinition: {
      leave: ({ operation, type }) => operation + ': ' + type,
    },
    ScalarTypeDefinition: {
      leave: ({ description, name, directives }) =>
        wrap('', description, '\n') +
        join(['scalar', name, join(directives, ' ')], ' '),
    },
    ObjectTypeDefinition: {
      leave: ({ description, name, interfaces, directives, fields }) =>
        wrap('', description, '\n') +
        join(
          [
            'type',
            name,
            wrap('implements ', join(interfaces, ' & ')),
            join(directives, ' '),
            block(fields),
          ],
          ' ',
        ),
    },
    FieldDefinition: {
      leave: ({ description, name, arguments: args, type, directives }) =>
        wrap('', description, '\n') +
        name +
        (hasMultilineItems(args)
          ? wrap('(\n', indent(join(args, '\n')), '\n)')
          : wrap('(', join(args, ', '), ')')) +
        ': ' +
        type +
        wrap(' ', join(directives, ' ')),
    },
    InputValueDefinition: {
      leave: ({ description, name, type, defaultValue, directives }) =>
        wrap('', description, '\n') +
        join(
          [name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')],
          ' ',
        ),
    },
    InterfaceTypeDefinition: {
      leave: ({ description, name, interfaces, directives, fields }) =>
        wrap('', description, '\n') +
        join(
          [
            'interface',
            name,
            wrap('implements ', join(interfaces, ' & ')),
            join(directives, ' '),
            block(fields),
          ],
          ' ',
        ),
    },
    UnionTypeDefinition: {
      leave: ({ description, name, directives, types }) =>
        wrap('', description, '\n') +
        join(
          ['union', name, join(directives, ' '), wrap('= ', join(types, ' | '))],
          ' ',
        ),
    },
    EnumTypeDefinition: {
      leave: ({ description, name, directives, values }) =>
        wrap('', description, '\n') +
        join(['enum', name, join(directives, ' '), block(values)], ' '),
    },
    EnumValueDefinition: {
      leave: ({ description, name, directives }) =>
        wrap('', description, '\n') + join([name, join(directives, ' ')], ' '),
    },
    InputObjectTypeDefinition: {
      leave: ({ description, name, directives, fields }) =>
        wrap('', description, '\n') +
        join(['input', name, join(directives, ' '), block(fields)], ' '),
    },
    DirectiveDefinition: {
      leave: ({ description, name, arguments: args, repeatable, locations }) =>
        wrap('', description, '\n') +
        'directive @' +
        name +
        (hasMultilineItems(args)
          ? wrap('(\n', indent(join(args, '\n')), '\n)')
          : wrap('(', join(args, ', '), ')')) +
        (repeatable ? ' repeatable' : '') +
        ' on ' +
        join(locations, ' | '),
    },
    SchemaExtension: {
      leave: ({ directives, operationTypes }) =>
        join(
          ['extend schema', join(directives, ' '), block(operationTypes)],
          ' ',
        ),
    },
    ScalarTypeExtension: {
      leave: ({ name, directives }) =>
        join(['extend scalar', name, join(directives, ' ')], ' '),
    },
    ObjectTypeExtension: {
      leave: ({ name, interfaces, directives, fields }) =>
        join(
          [
            'extend type',
            name,
            wrap('implements ', join(interfaces, ' & ')),
            join(directives, ' '),
            block(fields),
          ],
          ' ',
        ),
    },
    InterfaceTypeExtension: {
      leave: ({ name, interfaces, directives, fields }) =>
        join(
          [
            'extend interface',
            name,
            wrap('implements ', join(interfaces, ' & ')),
            join(directives, ' '),
            block(fields),
          ],
          ' ',
        ),
    },
    UnionTypeExtension: {
      leave: ({ name, directives, types }) =>
        join(
          [
            'extend union',
            name,
            join(directives, ' '),
            wrap('= ', join(types, ' | ')),
          ],
          ' ',
        ),
    },
    EnumTypeExtension: {
      leave: ({ name, directives, values }) =>
        join(['extend enum', name, join(directives, ' '), block(values)], ' '),
    },
    InputObjectTypeExtension: {
      leave: ({ name, directives, fields }) =>
        join(['extend input', name, join(directives, ' '), block(fields)], ' '),
    },
  };
  /**
   * Given maybeArray, print an empty string if it is null or empty, otherwise
   * print all items together separated by separator if provided
   */
  
  function join(maybeArray, separator = '') {
    var _maybeArray$filter$jo;
  
    return (_maybeArray$filter$jo =
      maybeArray === null || maybeArray === void 0
        ? void 0
        : maybeArray.filter((x) => x).join(separator)) !== null &&
      _maybeArray$filter$jo !== void 0
      ? _maybeArray$filter$jo
      : '';
  }
  /**
   * Given array, print each item on its own line, wrapped in an indented `{ }` block.
   */
  
  function block(array) {
    return wrap('{\n', indent(join(array, '\n')), '\n}');
  }
  /**
   * If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string.
   */
  
  function wrap(start, maybeString, end = '') {
    return maybeString != null && maybeString !== ''
      ? start + maybeString + end
      : '';
  }
  
  function indent(str) {
    return wrap('  ', str.replace(/\n/g, '\n  '));
  }
  
  function hasMultilineItems(maybeArray) {
    var _maybeArray$some;
  
    // FIXME: https://github.com/graphql/graphql-js/issues/2203
  
    /* c8 ignore next */
    return (_maybeArray$some =
      maybeArray === null || maybeArray === void 0
        ? void 0
        : maybeArray.some((str) => str.includes('\n'))) !== null &&
      _maybeArray$some !== void 0
      ? _maybeArray$some
      : false;
  }
  