Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in wrapList() if selection is inside a table cell. #42

Open
FarbrorGarbo opened this issue Jun 27, 2019 · 3 comments
Open

Bug in wrapList() if selection is inside a table cell. #42

FarbrorGarbo opened this issue Jun 27, 2019 · 3 comments

Comments

@FarbrorGarbo
Copy link

The whole table becomes a list item instead of the selection in the table cell.

Here is a CodeSandbox example: https://codesandbox.io/s/slate-1evfo

Perhaps I'm the only one using an online editor that allows editing of tables and lists inside of them :-O

@brendancarney
Copy link
Collaborator

Thanks for filing the issue! I don't use tables, so I'm unlikely to spend a bunch of time looking into this, but if you have any ideas, I'm definitely open to a PR.

@FarbrorGarbo
Copy link
Author

The problem is this line in the wrapList funktion that doesn't choose the immetiate parant of the selection.

var rootBlocks = editor.value.document.getRootBlocksAtRange(editor.value.selection);

I'm yet not so familiar with all available select commands in SlateJS, but there is probably a better way to find the parent. Not sure what edge cases must be handled, and perhaps it's not obvious what should be a valid parent.

@meeshkah
Copy link

I have tried re-writing the wrapList function to get the groups of blocks in the selection, and wrap them into list items. This is what is working for me:

const isList = (blocks, block) =>
  block.type == blocks.unordered_list || block.type == blocks.ordered_list;

export default ({ blocks }, editor, options = {}) => {
  const type = options.type || blocks.unordered_list;

  const blocksAtRange = editor.value.document
    .getDescendantsAtRange(editor.value.selection)
    .filter((node) => {
      return node.object === 'text';
    })
    .map((node) => {
      return editor.value.document.getClosestBlock(node.key);
    })
    .toSet()
    .toList();

  if (blocksAtRange.size > 0) {
    const groupedByParent = blocksAtRange.reduce((agg, node) => {
      const parent = editor.value.document.getParent(node.key);

      return parent
        ? {
            ...agg,
            [parent.key]: agg.hasOwnProperty(parent.key)
              ? [...agg[parent.key], ...[node]]
              : [node],
          }
        : agg;
    }, {});

    editor.withoutNormalizing(() => {
      Object.keys(groupedByParent).forEach((groupId) => {
        groupedByParent[groupId].forEach((block) => {
          if (isList(blocks, block)) return;
          editor.wrapBlockByKey(block.key, type);
          editor.wrapBlockByKey(block.key, blocks.list_item);
          editor.setNodeByKey(block.key, blocks.list_item_child);
        });
      });
    });
  }
};

I figured we need all the text nodes' distinct parents in the selection (hence toSet > toList operation), group the blocks up by parent, and wrap them up.
It probably needs more testing, of course.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants