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

Refactor Copy/Paste #259

Closed
bantic opened this issue Dec 9, 2015 · 2 comments
Closed

Refactor Copy/Paste #259

bantic opened this issue Dec 9, 2015 · 2 comments
Assignees
Milestone

Comments

@bantic
Copy link
Collaborator

bantic commented Dec 9, 2015

Copy/Paste behavior is somewhat under-specced in mobiledoc-kit at the moment (and in general — I cannot find a general-purpose algorithm described online for pasting structured content into a document).
This issue attempts to define some declarative behaviors for copy-pasting that align with user expectations. It addresses #249 as well.

Paste Algorithm for mobiledoc-kit

  • pasting when in a blank section
    • replaces that section with the entirety of the pasted post
    • update cursor to end of pasted content
  • pasting when cursor is in non-markerable section
    • if cursor is at start of section
      • for each pasted section
        • insert if before the cursor section
        • update cursor to be end of inserted section
    • else
      • for each pasted section
        • insert it after the cursor section
        • update cursor to be end of inserted section
  • pasting when cursor is in non-nested markerable (e.g., MarkupSection)
    • if pasted post first leaf section is not markerable
      • if cursor position is at start of section
        • insert each pasted section before the cursor section except the last one
        • if the last one is markerable:
          • prepend its content to the cursor section
          • update cursor position to be the end of the prepended content
        • else
          • insert it before the cursor section
          • update cursor position to be the end of the inserted section
      • else if cursor position is in middle of section
        • split the cursor section into pre- and post-split
        • for each pasted section except the last:
          • insert it before the post-split section
          • update cursor position to be the end of the inserted section
        • if last section is markerable:
          • prepend its content to the cursor section
          • update the cursor position to be the end of the prepended content
        • else
          • insert it before the post-split section
          • update cursor position to be the end of the inserted section
      • else if cursor is at the end of the section
        • for each pasted section
          • insert it after the cursor section
          • update cursor position to be the end of the inserted section
    • else if pasted post first leaf section is non-nested markerable (e.g. MarkupSection)
      • insert leaf section markers at cursor position
      • update cursor position to be end of inserted content
      • if additional sections:
        • break cursor section at updated cursor position into pre- and post-split
        • for each section except the last:
          • insert it before post-split
          • update cursor position to be end of inserted section
        • for last section
          • if it is markerable:
            • insert its contents at start of post-split
            • update cursor position to be end of inserted content
          • else
            • insert it before post-split
            • update cursor position to be end of inserted section
    • else if pasted post first leaf section is nested markerable (e.g. ListItem)
      • insert content from 1st item at cursor position
      • update cursor position to be end of inserted content
      • if more items in the list or more sections to paste (aka “should insert linebreak”)
        • split the cursor section at updated position into pre- and post-split
        • if any remaining items:
          • create a new list with the remaining items
          • insert the list before post-split
          • update cursor position to be end of inserted list
        • if additional pasted sections:
          • for each section except the last
            • insert it before post-split
            • update cursor position to be end of inserted section
          • for last section
            • if it is markerable
              • insert its contents at start of post-split
              • update cursor position to be end of inserted content
            • else
              • insert it before post-split
              • update cursor position to be end of inserted section
  • pasting when cursor is in nested markerable (e.g. ListItem)
    • if pasted post first leaf section is not markerable
      • break list at list item/position (pre-split and post-split lists)
      • for each pasted section including the last:
        • insert it before post-split
        • update cursor position to be end of inserted section
    • if pasted post first leaf section is non-nested markerable (markup section)
      • insert contents of 1st section at cursor position
      • update cursor position to be end of inserted contents
      • if additional sections:
        • break list at list item/position (pre-split and post-split lists)
        • for each section except the last
          • insert it before post-split
          • update cursor position to be the end of the inserted section
        • for last section
          • if it is markerable
            • insert its contents at start of 1st item in post-split list
            • update cursor position to be end of inserted content
          • else
            • insert it before post-split
            • update cursor position to be end of inserted section
    • if pasted post first leaf section is nested markerable (ListItem):
      • insert contents of 1st item at cursor position
      • update cursor position to be end of inserted contents
      • let hasAdditionalSections be true if pasted content has sections after the list section
      • let sectionToInsertBefore be the section after the cursor’s list section if hasAdditionalSections
      • if additional list items
        • split cursor list item into pre- and post-split list items
        • for each list item except last
          • insert it before post-split list item
          • update cursor position to be end of inserted section
        • if hasAdditionalSections
          • break cursor list section between the last inserted item and the post-split list item (the post-split list section has the post-split list item and all remaining items)
          • insert the new list after existing list
          • update sectionToInsertBefore be the inserted list
        • else
          • insert contents of last list item at start of post-split list item
          • update cursor position to end of inserted content
      • if hasAdditionalSections
        • for each section including the last
          • insert it before sectionToInsertBefore
          • update cursor position to be end of inserted section
@bantic bantic self-assigned this Dec 9, 2015
@bantic bantic added this to the 0.8 milestone Dec 9, 2015
@bantic
Copy link
Collaborator Author

bantic commented Dec 9, 2015

Here's some research I did on how Google Docs does copy/paste in different scenarios, for reference:
https://www.evernote.com/shard/s62/sh/88f31509-54c7-4b39-a93a-2e0876f1bf73/a1d9b7be0fb28ef9

bantic added a commit that referenced this issue Dec 15, 2015
  * fix bug in post#cloneRange when range starts in list item
  * add assert.isPostSimilar, assert.isRenderTreeEqual, assert.isPositionEqual

Fix #249 #259
bantic added a commit that referenced this issue Dec 15, 2015
  * fix bug in post#cloneRange when range starts in list item
  * add assert.isPostSimilar, assert.isRenderTreeEqual, assert.isPositionEqual

Fix #249 #259
bantic added a commit that referenced this issue Dec 16, 2015
  * fix bug in post#cloneRange when range starts in list item
  * add assert.isPostSimilar, assert.isRenderTreeEqual, assert.isPositionEqual
  * fix ListSection#clone to use the same tagName for the clonee as the cloner
  * add PostEditor#insertMarkers method
  * add private/intimate methods for splitting list items and lists in postEditor

Fix #249 #259
@bantic
Copy link
Collaborator Author

bantic commented Dec 16, 2015

closed by #267

@bantic bantic closed this as completed Dec 16, 2015
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

1 participant