text: "use strict";
  
  var wcwidth = require('./width');
  
  var _require = require('./utils');
  
  var padRight = _require.padRight;
  var padCenter = _require.padCenter;
  var padLeft = _require.padLeft;
  var splitIntoLines = _require.splitIntoLines;
  var splitLongWords = _require.splitLongWords;
  var truncateString = _require.truncateString;
  
  var DEFAULT_HEADING_TRANSFORM = function DEFAULT_HEADING_TRANSFORM(key) {
    return key.toUpperCase();
  };
  
  var DEFAULT_DATA_TRANSFORM = function DEFAULT_DATA_TRANSFORM(cell, column, index) {
    return cell;
  };
  
  var DEFAULTS = Object.freeze({
    maxWidth: Infinity,
    minWidth: 0,
    columnSplitter: ' ',
    truncate: false,
    truncateMarker: '…',
    preserveNewLines: false,
    paddingChr: ' ',
    showHeaders: true,
    headingTransform: DEFAULT_HEADING_TRANSFORM,
    dataTransform: DEFAULT_DATA_TRANSFORM
  });
  
  module.exports = function (items) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  
    var columnConfigs = options.config || {};
    delete options.config; // remove config so doesn't appear on every column.
  
    var maxLineWidth = options.maxLineWidth || Infinity;
    if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity;
    delete options.maxLineWidth; // this is a line control option, don't pass it to column
  
    // Option defaults inheritance:
    // options.config[columnName] => options => DEFAULTS
    options = mixin({}, DEFAULTS, options);
  
    options.config = options.config || Object.create(null);
  
    options.spacing = options.spacing || '\n'; // probably useless
    options.preserveNewLines = !!options.preserveNewLines;
    options.showHeaders = !!options.showHeaders;
    options.columns = options.columns || options.include; // alias include/columns, prefer columns if supplied
    var columnNames = options.columns || []; // optional user-supplied columns to include
  
    items = toArray(items, columnNames);
  
    // if not suppled column names, automatically determine columns from data keys
    if (!columnNames.length) {
      items.forEach(function (item) {
        for (var columnName in item) {
          if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName);
        }
      });
    }
  
    // initialize column defaults (each column inherits from options.config)
    var columns = columnNames.reduce(function (columns, columnName) {
      var column = Object.create(options);
      columns[columnName] = mixin(column, columnConfigs[columnName]);
      return columns;
    }, Object.create(null));
  
    // sanitize column settings
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      column.name = columnName;
      column.maxWidth = Math.ceil(column.maxWidth);
      column.minWidth = Math.ceil(column.minWidth);
      column.truncate = !!column.truncate;
      column.align = column.align || 'left';
    });
  
    // sanitize data
    items = items.map(function (item) {
      var result = Object.create(null);
      columnNames.forEach(function (columnName) {
        // null/undefined -> ''
        result[columnName] = item[columnName] != null ? item[columnName] : '';
        // toString everything
        result[columnName] = '' + result[columnName];
        if (columns[columnName].preserveNewLines) {
          // merge non-newline whitespace chars
          result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' ');
        } else {
          // merge all whitespace chars
          result[columnName] = result[columnName].replace(/\s/gmi, ' ');
        }
      });
      return result;
    });
  
    // transform data cells
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      items = items.map(function (item, index) {
        var col = Object.create(column);
        item[columnName] = column.dataTransform(item[columnName], col, index);
  
        var changedKeys = Object.keys(col);
        // disable default heading transform if we wrote to column.name
        if (changedKeys.indexOf('name') !== -1) {
          if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return;
          column.headingTransform = function (heading) {
            return heading;
          };
        }
        changedKeys.forEach(function (key) {
          return column[key] = col[key];
        });
        return item;
      });
    });
  
    // add headers
    var headers = {};
    if (options.showHeaders) {
      columnNames.forEach(function (columnName) {
        var column = columns[columnName];
  
        if (!column.showHeaders) {
          headers[columnName] = '';
          return;
        }
  
        headers[columnName] = column.headingTransform(column.name);
      });
      items.unshift(headers);
    }
    // get actual max-width between min & max
    // based on length of data in columns
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      column.width = items.map(function (item) {
        return item[columnName];
      }).reduce(function (min, cur) {
        // if already at maxWidth don't bother testing
        if (min >= column.maxWidth) return min;
        return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))));
      }, 0);
    });
  
    // split long words so they can break onto multiple lines
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      items = items.map(function (item) {
        item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker);
        return item;
      });
    });
  
    // wrap long lines. each item is now an array of lines.
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      items = items.map(function (item, index) {
        var cell = item[columnName];
        item[columnName] = splitIntoLines(cell, column.width);
  
        // if truncating required, only include first line + add truncation char
        if (column.truncate && item[columnName].length > 1) {
          item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker));
          var firstLine = item[columnName][0];
          if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker;
          item[columnName] = item[columnName].slice(0, 1);
        }
        return item;
      });
    });
  
    // recalculate column widths from truncated output/lines
    columnNames.forEach(function (columnName) {
      var column = columns[columnName];
      column.width = items.map(function (item) {
        return item[columnName].reduce(function (min, cur) {
          if (min >= column.maxWidth) return min;
          return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))));
        }, 0);
      }).reduce(function (min, cur) {
        if (min >= column.maxWidth) return min;
        return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur)));
      }, 0);
    });
  
    var rows = createRows(items, columns, columnNames, options.paddingChr); // merge lines into rows
    // conceive output
    return rows.reduce(function (output, row) {
      return output.concat(row.reduce(function (rowOut, line) {
        return rowOut.concat(line.join(options.columnSplitter));
      }, []));
    }, []).map(function (line) {
      return truncateString(line, maxLineWidth);
    }).join(options.spacing);
  };
  
  /**
   * Convert wrapped lines into rows with padded values.
   *
   * @param Array items data to process
   * @param Array columns column width settings for wrapping
   * @param Array columnNames column ordering
   * @return Array items wrapped in arrays, corresponding to lines
   */
  
  function createRows(items, columns, columnNames, paddingChr) {
    return items.map(function (item) {
      var row = [];
      var numLines = 0;
      columnNames.forEach(function (columnName) {
        numLines = Math.max(numLines, item[columnName].length);
      });
      // combine matching lines of each rows
  
      var _loop = function _loop(i) {
        row[i] = row[i] || [];
        columnNames.forEach(function (columnName) {
          var column = columns[columnName];
          var val = item[columnName][i] || ''; // || '' ensures empty columns get padded
          if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr));else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr));else row[i].push(padRight(val, column.width, paddingChr));
        });
      };
  
      for (var i = 0; i < numLines; i++) {
        _loop(i);
      }
      return row;
    });
  }
  
  /**
   * Object.assign
   *
   * @return Object Object with properties mixed in.
   */
  
  function mixin() {
    var _Object;
  
    if (Object.assign) return (_Object = Object).assign.apply(_Object, arguments);
    return ObjectAssign.apply(undefined, arguments);
  }
  
  function ObjectAssign(target, firstSource) {
    "use strict";
  
    if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object");
  
    var to = Object(target);
  
    var hasPendingException = false;
    var pendingException;
  
    for (var i = 1; i < arguments.length; i++) {
      var nextSource = arguments[i];
      if (nextSource === undefined || nextSource === null) continue;
  
      var keysArray = Object.keys(Object(nextSource));
      for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
        var nextKey = keysArray[nextIndex];
        try {
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey];
        } catch (e) {
          if (!hasPendingException) {
            hasPendingException = true;
            pendingException = e;
          }
        }
      }
  
      if (hasPendingException) throw pendingException;
    }
    return to;
  }
  
  /**
   * Adapted from String.prototype.endsWith polyfill.
   */
  
  function endsWith(target, searchString, position) {
    position = position || target.length;
    position = position - searchString.length;
    var lastIndex = target.lastIndexOf(searchString);
    return lastIndex !== -1 && lastIndex === position;
  }
  
  function toArray(items, columnNames) {
    if (Array.isArray(items)) return items;
    var rows = [];
    for (var key in items) {
      var item = {};
      item[columnNames[0] || 'key'] = key;
      item[columnNames[1] || 'value'] = items[key];
      rows.push(item);
    }
    return rows;
  }
  
  