Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Create writer for non-semantic view manipulation #1503

Merged
merged 8 commits into from
Aug 31, 2018
Merged

Create writer for non-semantic view manipulation #1503

merged 8 commits into from
Aug 31, 2018

Conversation

f1ames
Copy link
Contributor

@f1ames f1ames commented Aug 16, 2018

Suggested merge commit message (convention)

Internal: Introduced writer for manipulating non-semantic view. Closes ckeditor/ckeditor5#4399.


Additional information

I'm still not sure about naming, the name I used is RawWriter, but we have discussed also Upcast/Downcast writer. Maybe looking at the code it will be easier to decide. I'm not in favor of any, upcast/downcast doesn't fit that much as this writer has basically nothing to do with upcasting/downcasting (apart from the fact that it touches view instance which may get upcasted eventually - but lots of classes do). And raw is somehow descriptive, but still you need to know the context well.

@pjasiun
Copy link

pjasiun commented Aug 23, 2018

With @Reinmar and @scofalik we just talked and agreed that UpcastWriter and DowncastWriter will be the best name. Also, I think that both will need to have improved documentation to explain cases where they should be used.

@pjasiun
Copy link

pjasiun commented Aug 23, 2018

Also, I disagree that the writer has nothing to do with downcasting, because if it used a lot during downcasting. It is as important for downcasting as converters, doing a big part of creating view during downcasting.

@f1ames
Copy link
Contributor Author

f1ames commented Aug 23, 2018

With @Reinmar and @scofalik we just talked and agreed that UpcastWriter and DowncastWriter will be the best name.

I'm fine with it, just one clarification - so the existing Writer should be UpcastWriter and the one introduced in this PR should be DowncastWriter?

Also, I disagree that the writer has nothing to do with downcasting, because if it used a lot during downcasting. It is as important for downcasting as converters, doing a big part of creating view during downcasting.

That's true for the current Writer. But when it comes to writer introduced in this PR it has nothing to do with model, it just manipulates the view - so basically it may work on a view instance which will be upcasted to model or which was downcasted from it, but it does not participate in any way in the process of upcasting/downcasting itself.

@pjasiun
Copy link

pjasiun commented Aug 23, 2018

I'm fine with it, just one clarification - so the existing Writer should be UpcastWriter and the one introduced in this PR should be DowncastWriter?

Nope. The existing one (Writer) should be DowncastWriter, the new one (RawWriter) should be UpcastWriter.

@pjasiun
Copy link

pjasiun commented Aug 23, 2018

That's true for the current Writer. But when it comes to writer introduced in this PR it has nothing to do with model, it just manipulates the view - so basically it may work on a view instance which will be upcasted to model or which was downcasted from it, but it does not participate in any way in the process of upcasting/downcasting itself.

That's true, but we could bend the definition a little for this case. How, upcasting is View -> Model, but it could be Data -> View -> Model (downcasting Model -> View -> Data). Then it will fit well.

@f1ames
Copy link
Contributor Author

f1ames commented Aug 24, 2018

That's true, but we could bend the definition a little for this case. How, upcasting is View -> Model, but it could be Data -> View -> Model (downcasting Model -> View -> Data). Then it will fit well.

Yes, it makes sense and makes it easier to understand with upcasting/downcasting defined in such way 👍

@f1ames
Copy link
Contributor Author

f1ames commented Aug 27, 2018

Also, I think that both will need to have improved documentation to explain cases where they should be used.

@pjasiun I will update the naming and docs and ping you when it's ready.

@coveralls
Copy link

coveralls commented Aug 27, 2018

Coverage Status

Coverage increased (+0.004%) to 98.621% when pulling 6712b25 on t/1501 into 7d8de56 on master.

@f1ames
Copy link
Contributor Author

f1ames commented Aug 27, 2018

@pjasiun I have renamed RawWriter to UpcastWriter. Now I'm working on renaming Writer to DowncastWriter, however I will put it in a separate PR as there will be plenty of changes.

So this PR is ready for R.

@pjasiun pjasiun requested a review from scofalik August 30, 2018 08:23
* @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element
* to which items will be appended.
* @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.
* @fires module:engine/view/node~Node#change
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We (at least I ;)) usually write event:change. Does the line above create proper docs?

BTW., those change events on view tree are so internal that I am not sure if it is worth documenting. @pjasiun ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I see, both produce the same link .../module_engine_view_node-Node.html#event:change but I will update it to make it consistent.

However, I just discovered it doesn't work properly in our docs 😱 The generated links are e.g. ...api/module_engine_conversion_upcastdispatcher-UpcastDispatcher.html#event:element, while to working one is ...api/module_engine_conversion_upcastdispatcher-UpcastDispatcher.html#event-element (so - instead of : in event name). I will report it.

* @see module:engine/view/element~Element#_insertChild
* @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element
* to which items will be inserted.
* @param {Number} index Position where nodes should be inserted.
Copy link
Contributor

@scofalik scofalik Aug 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset at which?

* @see module:engine/view/element~Element#_removeChildren
* @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element
* from which children will be removed.
* @param {Number} index Number of the first node to remove.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset from which?

* @param {Number} index Number of the first node to remove.
* @param {Number} [howMany=1] Number of nodes to remove.
* @fires module:engine/view/node~Node#change
* @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containing?

* Removes given element from the view structure. Will not have effect on detached elements.
*
* @param {module:engine/view/element~Element} element Element which will be removed.
* @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with removed nodes?

*/
remove( element ) {
const parent = element.parent;
if ( parent ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New line please? :)

* Replaces given element with the new one in the view structure. Will not have effect on detached elements.
*
* @param {module:engine/view/element~Element} oldElement Element which will be replaced.
* @param {module:engine/view/element~Element} newElement Element which will inserted in the place of the old element.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be

}

/**
* Adds or overwrite element's attribute with a specified key and value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overwrites (I see that this is a typo also at the place you copied from :P)

@scofalik
Copy link
Contributor

I have one overall issue: the parameters in methods in this class have a different order than the parameters in DowncastWriter. There we follow the rule that element is the last parameter. Here it is first. Sorry.

@pjasiun
Copy link

pjasiun commented Aug 30, 2018

Note that DOMConverter should now use this writer. In can be changed as a part of this ticket or reported as a follow-up.

@f1ames
Copy link
Contributor Author

f1ames commented Aug 30, 2018

I have one overall issue: the parameters in methods in this class have a different order than the parameters in DowncastWriter. There we follow the rule that element is the last parameter. Here it is first.

Yes... The reason I did it that way is that in a former Writer (DowncastWriter) class, the only methods which has element as a parameter are set/remove ones (the other usually have position or range, etc) and it is indeed the last parameter there.

However, in the UpcastWriter all methods have one parameter in common which is an element and the rest changes, e.g.:

  • clone( element, deep = false ) { ... }
  • appendChild( element, items ) { ... }
  • removeChildren( element, index, howMany = 1 ) { ... }
  • rename( element, newName ) { ... }

So:

  1. It makes it consistent internally, since all methods needs element and it is always the first parameter.
  2. To keep it consistent with DowncastWriter, element parameter should be the last parameter, but then for methods with default parameters it actually can't be the last keeping things inconsistent, like:
    • clone( element, deep = false ) { ... }
    • rename( newName, element ) { ... }
    • removeChildren( index, element, howMany = 1 ) { ... }
    • insertChild( index, items, element ) { ... }

From my perspective it is a choice between keeping it internally consistent or trying to make it consistent with some DowncastWriter methods by making it internally inconsistent. WDYT @scofalik ?


Btw. DowncastWriter has also a rename method with rename( viewElement, newName ) { ... } signature (I know it is viewElement not element but still).

@f1ames
Copy link
Contributor Author

f1ames commented Aug 30, 2018

Note that DOMConverter should now use this writer. In can be changed as a part of this ticket or reported as a follow-up.

I will propose a follow-up issue. 🤔 @pjasiun I don't see DOMConverter using Writer internally, could you elaborate a little where exactly UpcastWriter should be used?

@scofalik
Copy link
Contributor

Wasn't DOMConverter using Elements API? I think that's what PJ might have on his mind.

@pjasiun
Copy link

pjasiun commented Aug 30, 2018

Yep. DOM converter now is using protected elements API and it should use this writer instead.

@scofalik
Copy link
Contributor

scofalik commented Aug 30, 2018

@f1ames Correct me if I am wrong, but AFAICS the methods that are not available in DowncastWriter are:

  • clone( element, deep = false )
  • appendChild( element, items )
  • insertChild( element, index, items )
  • removeChildren( element, index, howMany = 1 )
  • remove( element )
  • replace( oldElement, newElement )
  • rename( element, newName )

So if we would change set/removes, those are which would be "inconsistent". Let's break them down.

  • clone() - can't do much here, but since deep really is an optional parameter, I think it is fine.
  • appendChild() and insertChild() make sense with a different parameters order too.
  • removeChildren looks bad, TBH, but I'd drop default value there and make element the last parameter. This is the only method that IMO will look bad.
  • remove() is inconsistent only because downcastWriter takes a range only. TBH, I'd change downcastWriter to accept both range and element and simply check if element is passed, if so, create a range on it (Range.createOn()). When this is done, the methods are consistent enough to get a thumbs up from me.
  • replace() is fine as it is as it takes two elements, however, to be consistent, oldElement probably should be the second parameter, but I don't like it that way. I'd leave it as it is.
  • rename() can be changed to be consistent and it will still look okay.

@scofalik
Copy link
Contributor

Sorry, rename() is available in DowncastWriter and has wrong order. I'd change the order there.

@f1ames
Copy link
Contributor Author

f1ames commented Aug 31, 2018

remove() is inconsistent only because downcastWriter takes a range only. TBH, I'd change downcastWriter to accept both range and element and simply check if element is passed, if so, create a range on it (Range.createOn()). When this is done, the methods are consistent enough to get a thumbs up from me.

rename() is available in DowncastWriter and has wrong order. I'd change the order there.

Makes sense. I will extract those changes to a separate issue to not block this PR for too long ;)

@f1ames
Copy link
Contributor Author

f1ames commented Aug 31, 2018

As I applied all requested changes, it is ready another R.

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

Successfully merging this pull request may close these issues.

Create writer for non-semantic view manipulation
4 participants