"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.serialization = exports["default"] = void 0;

var _react = _interopRequireDefault(require("react"));

var _slate = require("slate");

var _immutable = _interopRequireDefault(require("immutable"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _slateEditList = _interopRequireDefault(require("slate-edit-list"));

var _options = _interopRequireDefault(require("slate-edit-list/dist/options"));

var _debug = _interopRequireDefault(require("debug"));

var _this = void 0;

var log = (0, _debug["default"])('@pie-lib:editable-html:plugins:list');

var b = function b(type, next, childNodes) {
  return {
    object: 'block',
    type: type,
    nodes: next(childNodes)
  };
};

var serialization = {
  deserialize: function deserialize(el, next) {
    var name = el.tagName.toLowerCase();

    if (name === 'li') {
      return b('list_item', next, el.childNodes);
    }

    if (name === 'ul') {
      return b('ul_list', next, el.children.length ? Array.from(el.children) : el.childNodes);
    }

    if (name === 'ol') {
      return b('ol_list', next, el.children.length ? Array.from(el.children) : el.childNodes);
    }
  },
  serialize: function serialize(object, children) {
    if (object.object !== 'block') return;

    if (object.type === 'list_item') {
      return /*#__PURE__*/_react["default"].createElement("li", null, children);
    }

    if (object.type === 'ul_list') {
      return /*#__PURE__*/_react["default"].createElement("ul", null, children);
    }

    if (object.type === 'ol_list') {
      return /*#__PURE__*/_react["default"].createElement("ol", null, children);
    }
  }
};
exports.serialization = serialization;

var createEditList = function createEditList() {
  var core = (0, _slateEditList["default"])({
    typeDefault: 'span'
  });
  var listOptions = new _options["default"]({
    typeDefault: 'span'
  }); // fix outdated schema

  if (core.schema && core.schema.blocks) {
    Object.keys(core.schema.blocks).forEach(function (key) {
      var block = core.schema.blocks[key];

      if (block.parent) {
        return;
      }

      block.nodes[0] = {
        type: block.nodes[0].types[0]
      };
    });
  }
  /**
   * This override of the core.changes.wrapInList is needed because the version
   * of immutable that we have does not support getting the element at a specific
   * index with a square bracket (list[0]). We have to use the list.get function instead
   */

  /**
   * Returns the highest list of blocks that cover the current selection
   */


  var getHighestSelectedBlocks = function getHighestSelectedBlocks(value) {
    var range = value.selection;
    var document = value.document;
    var startBlock = document.getClosestBlock(range.startKey);
    var endBlock = document.getClosestBlock(range.endKey);

    if (startBlock === endBlock) {
      return _immutable["default"].List([startBlock]);
    }

    var ancestor = document.getCommonAncestor(startBlock.key, endBlock.key);
    var startPath = ancestor.getPath(startBlock.key);
    var endPath = ancestor.getPath(endBlock.key);
    return ancestor.nodes.slice(startPath.get(0), endPath.get(0) + 1);
  };
  /**
   * Wrap the blocks in the current selection in a new list. Selected
   * lists are merged together.
   */


  core.changes.wrapInList = function (change, type, data) {
    var selectedBlocks = getHighestSelectedBlocks(change.value); // Wrap in container

    change.wrapBlock({
      type: type,
      data: _slate.Data.create(data)
    }, {
      normalize: false
    }); // Wrap in list items

    selectedBlocks.forEach(function (node) {
      if (core.utils.isList(node)) {
        // Merge its items with the created list
        node.nodes.forEach(function (_ref) {
          var key = _ref.key;
          return change.unwrapNodeByKey(key, {
            normalize: false
          });
        });
      } else if (node.type !== 'list_item') {
        change.wrapBlockByKey(node.key, 'list_item', {
          normalize: false
        });
      }
    });
    return change.normalize();
  };

  core.changes.unwrapList = function unwrapList(opts, change) {
    var items = core.utils.getItemsAtRange(change.value);

    if (items.isEmpty()) {
      return change;
    } // Unwrap the items from their list


    items.forEach(function (item) {
      return change.unwrapNodeByKey(item.key, {
        normalize: false
      });
    }); // Parent of the list of the items

    var firstItem = items.first();
    var parent = change.value.document.getParent(firstItem.key);
    var index = parent.nodes.findIndex(function (node) {
      return node.key === firstItem.key;
    }); // Unwrap the items' children

    items.forEach(function (item) {
      item.nodes.forEach(function (node) {
        change.moveNodeByKey(node.key, parent.key, index, {
          normalize: false
        });
        index += 1;
      });
    }); // Finally, remove the now empty items

    items.forEach(function (item) {
      return change.removeNodeByKey(item.key, {
        normalize: false
      });
    });
    return change;
  }.bind(_this, listOptions);

  core.utils.getItemsAtRange = function (opts, value, range) {
    range = range || value.selection;

    if (!range.startKey) {
      return _immutable["default"].List();
    }

    var document = value.document;
    var startBlock = document.getClosestBlock(range.startKey);
    var endBlock = document.getClosestBlock(range.endKey);

    if (startBlock === endBlock) {
      var item = core.utils.getCurrentItem(value, startBlock);
      return item ? _immutable["default"].List([item]) : _immutable["default"].List();
    }

    var ancestor = document.getCommonAncestor(startBlock.key, endBlock.key);

    if (core.utils.isList(ancestor)) {
      var startPath = ancestor.getPath(startBlock.key);
      var endPath = ancestor.getPath(endBlock.key);
      return ancestor.nodes.slice(startPath.get(0), endPath.get(0) + 1);
    } else if (ancestor.type === opts.typeItem) {
      // The ancestor is the highest list item that covers the range
      return _immutable["default"].List([ancestor]);
    } // No list of items can cover the range


    return _immutable["default"].List();
  }.bind(_this, listOptions);

  core.utils.getListForItem = function (opts, value, item) {
    var document = value.document;
    var parent = document.getParent(item.key);
    return parent && core.utils.isList(parent) ? parent : null;
  }.bind(_this, listOptions);

  core.utils.isSelectionInList = function (opts, value, type) {
    var items = core.utils.getItemsAtRange(value);
    return !items.isEmpty() && ( // Check the type of the list if needed
    !type || core.utils.getListForItem(value, items.first()).get('type') === type);
  }.bind(_this, listOptions);

  return core;
};

var _default = function _default(options) {
  var type = options.type,
      icon = options.icon;
  var core = createEditList(); // eslint-disable-next-line react/display-name

  core.renderNode = function (props) {
    var node = props.node,
        attributes = props.attributes,
        children = props.children;

    switch (node.type) {
      case 'ul_list':
        return /*#__PURE__*/_react["default"].createElement("ul", attributes, children);

      case 'ol_list':
        return /*#__PURE__*/_react["default"].createElement("ol", attributes, children);

      case 'list_item':
        return /*#__PURE__*/_react["default"].createElement("li", attributes, children);
    }
  };

  core.toolbar = {
    isMark: false,
    ariaLabel: type == 'ul_list' ? 'bulleted list' : 'numbered-list',
    type: type,
    icon: icon,
    isActive: function isActive(value, type) {
      if (!core.utils.isSelectionInList(value)) {
        return false;
      }

      var current = core.utils.getCurrentList(value);
      return current ? current.type === type : false;
    },
    onClick: function onClick(value, onChange) {
      log('[onClick]', value);
      var inList = core.utils.isSelectionInList(value);

      if (inList) {
        var change = value.change().call(core.changes.unwrapList);
        onChange(change);
      } else {
        var _change = value.change().call(core.changes.wrapInList, type);

        onChange(_change);
      }
    }
  };

  core.normalizeNode = function (node) {
    if (node.object !== 'document' && node.object !== 'block') {
      return undefined;
    }

    var response = core.validateNode(node);
    var invalidListItems = [];
    node.forEachDescendant(function (d) {
      if (d.type === 'list_item' && d.nodes.size === 1 && d.nodes.first().object === 'text') {
        // if we have a list_item that has only a text inside, we need to add a block in it
        invalidListItems.push(d);
      }
    });

    if (!invalidListItems.length && !response) {
      return undefined;
    }

    return function (change) {
      if (response) {
        response(change);
      }

      if (invalidListItems.length) {
        change.withoutNormalization(function () {
          invalidListItems.forEach(function (node) {
            var textNode = node.nodes.first();
            var wrappedBlock = {
              object: 'block',
              type: 'div',
              nodes: [textNode.toJSON()]
            };
            change.removeNodeByKey(textNode.key);
            change.insertNodeByKey(node.key, 0, wrappedBlock);
          });
        });
      }
    };
  };

  core.renderNode.propTypes = {
    node: _propTypes["default"].object,
    attributes: _propTypes["default"].object,
    children: _propTypes["default"].func
  };
  core.name = type;
  return core;
};

exports["default"] = _default;
//# sourceMappingURL=index.js.map