I have been playing with a proof of concept for Comments in Etherpad.
This wont be available as a free plugin but if you are interested in sponsoring development or using it please get in touch!
Founder, Inventor, Creator
I have been playing with a proof of concept for Comments in Etherpad.
This wont be available as a free plugin but if you are interested in sponsoring development or using it please get in touch!
In this blog post I’m going to explain the complexities of getting content ownership in a document right. All popular collaborative editors get this wrong, some more drastically than others.
Knowing who owns a certain piece of text in a document is an extremely important part of a collaborative editor, I will explain why later in the post.
Let’s start with a basic example.
John writes.
My dog ate the tree
Now Dave swaps the words tree and dog around. We get
My tree ate the dog
The actual sentiment of the sentence has changed a lot but that wasn’t John’s intention yet if we look at the sentence in all collaborative Editors there is no representation that Dave modified the text.
As you can imagine this is a huge problem as far as sentiment analysis, Etherpad suffers from this too. Sentiment is distorted without the viewer being aware, imagine now we are working on a legal document and we replace the word tree and dog with friend and zombie…
As text is modified in Etherpad new attributes IE underline/bold/strikethrough aren’t made clear to the viewer. IE if John writes
Hello world
Then Dave applies a strikethrough on this text we have no recollection that Dave made this modification. The viewer is under the impression that John struck this this piece of text, this is misleading.
Undo also falls into the trap of modifying someone elses text without it being clear, the same applies as the basic example, sentiment can be modified without the original Authors consent.
At current each piece of text in Etherpad has an author owner, I propose that on attribute modification (IE bold/strikethrough) additionally each additional author exists in an “editors” array. The original author would still be listed as the “creator/author”.
In the “tree ate the dog” example the original author(John) should still be maintained but additionally(this is the new bit) the editor(Dave) should be added to the “editors” array. Part of Etherpad’s design is that as text is Copy/Pasted the original Author is maintained, this is healthy and by adding the editors array we should be able to identify that Dave has modified John’s content.
John might delete Dave’s text then hit Undo but then we have to decide if the undone text is owned by Dave, John or if it’s owned by Dave with a modification from John. Again adding Dave as an editor of the content would make it clear that a second author has modified the content.
Sometimes stuff gets broken due to new commits, we need to know which commit broke functionality.
To do this
git pull git checkout develop
Ensure the bug exists then
git checkout master
Ensure the bug doesn’t exist. If it does checkout older versions IE git checkout release/1.2.8
Next begin the bisect process..
git bisect start
Tell bisect that master is fine
git bisect good
Tell bisect that develop is bad
git checkout develop git bisect bad
Bisect will then deliver you a commit state, test this new version..
bin/run.sh
Test, Control C.. Did it work? If so…
git bisect good
Did it not work? If so..
git bisect bad
Rinse repeat ‘git bisect good’ and/or ‘git bisect bad’ until it delivers you with a commit SHA then create an issue including the details from the SHA.
Basically bisect will tell you which commit introduced the bug.
I often have to test specific pull requests and tanks to this post on how to checkout git pull requests I was able to quickly bash together a script
I wrote this to ~/checkoutPR.sh
echo "Getting Pull request #$1" git fetch origin pull/$1/head:pr-$1 git checkout pr-$1
then
chmod 775 ~/checkoutPR.sh
Then jump into the repo folder
Grab the Pull request # from the URL, replacing %pullrqeuestnumber% with the pull request #
~/checkoutPR.sh %pullrqeuestnumber%
Simple but useful.
The output is something like this
jose@debian:~/etherpad-lite$ ~/./checkoutPR.sh 1672 Getting Pull request #1672 remote: Counting objects: 142, done. remote: Compressing objects: 100% (43/43), done. remote: Total 124 (delta 101), reused 104 (delta 81) Receiving objects: 100% (124/124), 13.58 KiB, done. Resolving deltas: 100% (101/101), completed with 15 local objects. From github.com:ether/etherpad-lite * [new branch] refs/pull/1672/head -> pr-1672 Switched to branch 'pr-1672'
Getting scrolling in an editor right is a complex task with various Gotchas. Getting scrolling right is in a collaborative editing environment is fraught with even more perils. Most editors, both collaborative and non collaborative get scrolling wrong, yours probably does too. But fear not! In this post I’m going to explain some edge case behaviours and how you should go about handling them.
I hold WordPress in really high regard yet WordPress as an example gets this very wrong(for example hitting page down in your editor will lose your caret if your document is greater than the height of your editor), TinyMCE is probably not to blame for this, WYSIWYG editors on the web in general are broken.
The behaviour for how editors scroll with documents has become a relatively normal experience. When you hit enter you expect to create a new line and for your browser to continue bringing that newline into your viewport.
When we talk about a viewport we mean something like this
-------------- | document | |----------------| | | | viewport | | | |----------------| | | --------------
As you can see the viewport shows a portion(or if the document is smaller than the viewport the whole) of the document and as a newline is created the viewport is moved down by the pixel height of the new line. If you are a WYSIWYG or Etherpad user think of it as the large white panel where you can edit text.
So we know that moving the Viewport Offset Top to the right location on a document in a non collaborative environment is really easy, yet there are some behaviours we take for granted.
Using left arrow key moves the caret one position left until it hits the beginning of a row then it goes to the last position on the row above
Using the up/down arrows move our caret up, maintaining X(IE 5) position, when the caret hits the Viewpoint offset minus the Above line height the viewport is moved by minus the Above line height. Similar happens for the down arrow. If there is no line X content the caret X position is 0. 0 is not retained though, if the user presses up/down again the caret maintains it’s original trajectory, IE 5
Using the page up/down arrows move our caret up to the first visible line in the viewport. Hitting page up again will take the current viewport height and move the first fully visible line in the new viewport position. Page down does similar.
Page up:
|----------------| | viewport | | | |----------------| | document | --------------
Page down:
-------------- | document | | | |----------------| | | | viewport | | | |----------------|
If your editor gets these wrong then you have serious problems.
It’s at this point that collaborative editing throws some gotchas in.
As you type this happens..
State a:
-------------- | document | | | |----------------| | | | viewport | | | |----------------|
State b:
-------------- | document | | | | | |----------------| | | | viewport | | | |----------------|
As you can see here another user has edited the content above our viewport which has left our viewport moved further down the document. This isn’t the default behaviour with collaborative editors, you will have to deal with this edge case specifically.
The same problem exists if content is resized/removed above your content, again knowing the caret position at modification is how we solve this however there is another gotcha..
So your author is reading content 5 lines above your current caret position and someone adds new content at the top of the document, you will not want to move the users caret position to the new location. I call this problem the “viewport war” problem.
Part 1: Is the caret in viewport range at all(If not we can assume the user is reading text elsewhere in the pad so don’t need to do anything)?
Part 2: If a new change above would modify the viewport to the point where the caret would no longer be visible for the user then always put the Offset Top at Caret Offset Top – (ViewPort height / 2). This means that the Caret is in the middle of the Y portion of the Viewport.
During highlight we should never allow the viewport to be moved by an edit event, only the user should be able to change it however this poses a new problem.. Imagine we are highlighting lines 5 to 10 and someone deletes lines 0, our editor would now look something like this..
|----------------| | |------------| | | | document | | | | | | |-| |-| |-|------------|-|
Note the line above the document, the document is now below the top of our viewport.
This is another issue you will have to deal with in your editor. The best way is to basically stop the viewport moving if the content is being highlighted, this means that you allow the document (note we say document and not viewport) Offset Top to actually be greater than 0.
* Don’t allow edits above the viewport to move the viewport out of the visible caret location unless the caret is already outside the visible caret location.
* Don’t allow user changes to move viewport when author is highlighting
Anyway I wrote this so I can refactor the caret and viewport in Etherpad, a free and open source really-real time collaborative editor.