function printTernaryOperator(path, options, print, operatorOptions) {
  var node = path.getValue();
  var testNode = node[operatorOptions.testNodePropertyName];
  var consequentNode = node[operatorOptions.consequentNodePropertyName];
  var alternateNode = node[operatorOptions.alternateNodePropertyName];
  var parts = []; // We print a ConditionalExpression in either "JSX mode" or "normal mode".
  // See tests/jsx/conditional-expression.js for more info.

  var jsxMode = false;
  var parent = path.getParentNode();
  var forceNoIndent = parent.type === operatorOptions.conditionalNodeType; // Find the outermost non-ConditionalExpression parent, and the outermost
  // ConditionalExpression parent. We'll use these to determine if we should
  // print in JSX mode.

  var currentParent;
  var previousParent;
  var i = 0;

  do {
    previousParent = currentParent || node;
    currentParent = path.getParentNode(i);
    i++;
  } while (currentParent && currentParent.type === operatorOptions.conditionalNodeType);

  var firstNonConditionalParent = currentParent || parent;
  var lastConditionalParent = previousParent;

  if (operatorOptions.shouldCheckJsx && (isJSXNode(testNode) || isJSXNode(consequentNode) || isJSXNode(alternateNode) || conditionalExpressionChainContainsJSX(lastConditionalParent))) {
    jsxMode = true;
    forceNoIndent = true; // Even though they don't need parens, we wrap (almost) everything in
    // parens when using ?: within JSX, because the parens are analogous to
    // curly braces in an if statement.

    var wrap = function wrap(doc$$2) {
      return concat$12([ifBreak$6("(", ""), indent$6(concat$12([softline$5, doc$$2])), softline$5, ifBreak$6(")", "")]);
    }; // The only things we don't wrap are:
    // * Nested conditional expressions in alternates
    // * null


    var isNull = function isNull(node) {
      return node.type === "NullLiteral" || node.type === "Literal" && node.value === null;
    };

    parts.push(" ? ", isNull(consequentNode) ? path.call(print, operatorOptions.consequentNodePropertyName) : wrap(path.call(print, operatorOptions.consequentNodePropertyName)), " : ", alternateNode.type === operatorOptions.conditionalNodeType || isNull(alternateNode) ? path.call(print, operatorOptions.alternateNodePropertyName) : wrap(path.call(print, operatorOptions.alternateNodePropertyName)));
  } else {
    // normal mode
    var part = concat$12([line$8, "? ", consequentNode.type === operatorOptions.conditionalNodeType ? ifBreak$6("", "(") : "", align$1(2, path.call(print, operatorOptions.consequentNodePropertyName)), consequentNode.type === operatorOptions.conditionalNodeType ? ifBreak$6("", ")") : "", line$8, ": ", alternateNode.type === operatorOptions.conditionalNodeType ? path.call(print, operatorOptions.alternateNodePropertyName) : align$1(2, path.call(print, operatorOptions.alternateNodePropertyName))]);
    parts.push(parent.type !== operatorOptions.conditionalNodeType || parent[operatorOptions.alternateNodePropertyName] === node ? part : options.useTabs ? dedent$3(indent$6(part)) : align$1(Math.max(0, options.tabWidth - 2), part));
  } // We want a whole chain of ConditionalExpressions to all
  // break if any of them break. That means we should only group around the
  // outer-most ConditionalExpression.


  var maybeGroup = function maybeGroup(doc$$2) {
    return operatorOptions.breakNested ? parent === firstNonConditionalParent ? group$10(doc$$2) : doc$$2 : group$10(doc$$2);
  }; // Break the closing paren to keep the chain right after it:
  // (a
  //   ? b
  //   : c
  // ).call()


  var breakClosingParen = !jsxMode && (parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression") && !parent.computed;
  return maybeGroup(concat$12([].concat(function (testDoc) {
    return (
      /**
       *     a
       *       ? b
       *       : multiline
       *         test
       *         node
       *       ^^ align(2)
       *       ? d
       *       : e
       */
      parent.type === operatorOptions.conditionalNodeType && parent[operatorOptions.alternateNodePropertyName] === node ? align$1(2, testDoc) : testDoc
    );
  }(concat$12(operatorOptions.beforeParts())), forceNoIndent ? concat$12(parts) : indent$6(concat$12(parts)), operatorOptions.afterParts(breakClosingParen))));
}
The following is the shared logic for
ternary operators, namely ConditionalExpression
and TSConditionalType
@typedef {Object} OperatorOptions
@property {() => Array<string | Doc>} beforeParts - Parts to print before the `?`.
@property {(breakClosingParen: boolean) => Array<string | Doc>} afterParts - Parts to print after the conditional expression.
@property {boolean} shouldCheckJsx - Whether to check for and print in JSX mode.
@property {string} conditionalNodeType - The type of the conditional expression node, ie "ConditionalExpression" or "TSConditionalType".
@property {string} consequentNodePropertyName - The property at which the consequent node can be found on the main node, eg "consequent".
@property {string} alternateNodePropertyName - The property at which the alternate node can be found on the main node, eg "alternate".
@property {string} testNodePropertyName - The property at which the test node can be found on the main node, eg "test".
@property {boolean} breakNested - Whether to break all nested ternaries when one breaks.
@param {FastPath} path - The path to the ConditionalExpression/TSConditionalType node.
@param {Options} options - Prettier options
@param {Function} print - Print function to call recursively
@param {OperatorOptions} operatorOptions
@returns Doc