outdentListItemToParagraph function

Paragraph? outdentListItemToParagraph(
  1. Root root,
  2. FluentList listParent,
  3. ListItem currentItem, {
  4. FluentDocument? document,
})

Outdent of a ListItem at the first level: transforms into paragraph. Removes the item from the list, takes the first Paragraph as content, and promotes the other children (images, tables, sublists) to the parent level. Returns the created Paragraph or null if the operation fails.

Implementation

Paragraph? outdentListItemToParagraph(
  Root root,
  FluentList listParent,
  ListItem currentItem, {
  FluentDocument? document,
}) {
  final grandparent = document != null
      ? findParentCached(document, listParent)
      : findParent(root, listParent);
  if (grandparent == null) return null;

  final itemChildren = currentItem.children.toList();

  Paragraph? firstParagraph;
  final otherChildren = <FNode>[];
  for (final c in itemChildren) {
    if (firstParagraph == null && c is Paragraph) {
      firstParagraph = c;
    } else {
      otherChildren.add(c);
    }
  }

  final currentIndex = listParent.items.indexOf(currentItem);
  final itemsAfter = (currentIndex >= 0)
      ? listParent.items.sublist(currentIndex + 1).toList()
      : <ListItem>[];

  removeNode(root, currentItem);

  for (final item in itemsAfter) {
    removeNode(root, item);
  }

  currentItem.children.clear();

  final newParagraph = firstParagraph ?? Paragraph();

  insertAfter(grandparent, listParent, newParagraph);

  var insertAfterNode = newParagraph as FNode;
  for (final child in otherChildren) {
    if (child is FluentList) {
      _promoteSublistRecursive(root, grandparent, insertAfterNode, child);
    } else {
      insertAfter(grandparent, insertAfterNode, child);
    }
    insertAfterNode = child;
  }

  if (itemsAfter.isNotEmpty) {
    final newList = FluentList(listType: listParent.listType);
    for (final item in itemsAfter) {
      appendChild(newList, item);
    }
    insertAfter(grandparent, insertAfterNode, newList);
  }

  if (listParent.items.isEmpty) {
    removeNode(root, listParent);
  }

  mergeConsecutiveListsInContainer(grandparent, root);

  recalculateListIndicesFor(root, {if (listParent.items.isNotEmpty) listParent, if (grandparent is FluentList) grandparent});

  return newParagraph;
}