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

Copy and paste of ul list item results in ol list item #883

Open
2 tasks done
kiejo opened this issue Jan 10, 2019 · 2 comments
Open
2 tasks done

Copy and paste of ul list item results in ol list item #883

kiejo opened this issue Jan 10, 2019 · 2 comments

Comments

@kiejo
Copy link
Contributor

kiejo commented Jan 10, 2019

Issue details

Copying and pasting a list item wrapped in a ul results in a list item wrapped in a ol surrounded by two empty paragraphs instead of resulting in the copied content.

Steps to reproduce

  1. Go to https://gainful-baboon.glitch.me/
  2. Put the caret before "Item"
  3. Click the "Select parent node" button in the toolbar twice
  4. Press Ctrl+X to cut the selection
  5. Press Ctrl+V to paste the content

ProseMirror version

prosemirror-view 1.6.8
prosemirror-model 1.6.4

Affected platforms

  • Chrome
  • Firefox

Screenshots / Screencast (Optional)

Before cut
cut
After paste
paste

@ocavue
Copy link

ocavue commented Dec 9, 2022

I can explain this issue. When the listItem node is been selected (e.g. a NodeSelection), ProseMirror will only write <li> ... </li> into the clipboard when coping, so it loses the context about the outer node (orderedList or bulletList).

Here is the data ProseMirror write into clipboard:

image

@kiejo
Copy link
Contributor Author

kiejo commented Feb 10, 2023

I found a way to customize the default behavior and solve the issue by using a custom transformCopied function:

function transformCopied(slice, view) {
  // If a single list item node is copied, we want to wrap it in its parent so that
  // pasting the slice results in the correct list type (e.g. ordered vs unordered list)
  if (slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1) {
    const copiedNode = slice.content.firstChild
    if (copiedNode.type.spec.isListItem) {
      // Search for the parent of the copied list item
      let copiedNodeParent
      view.state.doc.descendants((node, pos, parent) => {
        if (copiedNodeParent)
          return false
        if (node == copiedNode) {
          copiedNodeParent = parent
          return false
        }
      })

      // Create a new Slice that includes the parent of the list item
      if (copiedNodeParent)
        return new Slice(Fragment.from(copiedNodeParent.type.create(null, slice.content)), 1, 1)
    }
  }

  return slice
}

Depending on the schema used for the list item, copiedNode.type.spec.isListItem needs to be adjusted (e.g. copiedNode.type.name == 'list_item'). In case the attributes of the parent list should be kept as part of the copy, one can use copiedNodeParent.copy(slice.content) instead of copiedNodeParent.type.create(null, slice.content).

I'm not sure if this is the best or recommended way to achieve this, but it solves the issue for me.

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

2 participants