mavoweb / mavo

Create web applications entirely by writing HTML and CSS!
https://mavo.io
MIT License
2.85k stars 178 forks source link

Ambiguous semantics for mv-list/mv-list-item #989

Open karger opened 1 year ago

karger commented 1 year ago

Playing around with the new vocabulary raised the following question: what happens when an mv-list has multiple mv-list-item children, that may have the same or different property names?

Trying it out revealed some surprises and what may be some bugs: https://codepen.io/karger/pen/GRzorWG?editors=1100

karger commented 1 year ago

Here's some thinking about the semantics. First, it seems clear that we have to permit multiple distinct sibling mv-list-item elements naming different properties ie different collections. Which is something we permitted with mv-multiple and is sometimes useful. Because certainly there can be two distinct collections that need to be siblings because parent elements are disallowed for some reason. But, the new rule that mv-list gets put on the parent means that both mv-list-items will have the same parent mv-list (explicit or inferred) Which leads to the conclusion that we should have semantics for what happens when there are two distinct (possibly different property) mv-list-item children of the same mv-list. Part of it is easy: we can say that any attributes on the mv-list apply to both collections. But we also have to think about the properties---on the mv-list and (possibly different) on the (say) two mv-list-items. One solution would be to say that each mv-list-item yields a distinct collection on its property, while the property on the mv-list represents the union of all the child collections.

LeaVerou commented 1 year ago

There is no spec (there should be!) but the current fixups are here: https://github.com/mavoweb/mavo/blob/main/src/mavo.js#L1060

Basically:

Looking at your code, the questions that arise seem to be:

karger commented 1 year ago

There is no spec (there should be!) but the current fixups are here: https://github.com/mavoweb/mavo/blob/main/src/mavo.js#L1060

Basically:

  • For mv-list elements that do not contain a direct child mv-list-item:

    • if they contain exactly one child, mv-list-item is added to that child
    • Otherwise, their contents are wrapped in a suitable mv-list-item element (usually a <div> but not always)

Can there be situations where it is impossible to legally add an intermediary element? and why even bother? why not just replicate the entire multi-node block of html for each item? is the issue losing track of item boundaries? because another way to do that would be to add e.g. mv-list-item-start to the first element representing an item and mv-list-item-end to the last.

  • For mv-list-item elements whose parent is not an mv-list element:

    • If their parent is a different Mavo node (i.e. contains mv-app, mv-list-item or property attributes) or contains multiple children, the element is wrapped with a suitable mv-list element (usually a <div> but not always

why is wrapping necessary? one of the things that seemed nice about the new syntax is that you could have mv-list and mv-list-item on the same element, indicating that the element represents one collection that is part of a collection of collections. we know that some of the attributes (e.g. mv-initial-items) apply to its identity as a collection, while others could apply to its identity as a member of the "outer" collection. the ambiguity of mv-multiple is gone.

Also, as above, are there ever cases where there is no legal way to add a wrapper? What do we do then?

If a wrapper can always be added legally, then it seems to me that there is a nice simplifying fix to a lot of this: require mv-list for defining a collection. force the author to add that wrapper if necessary. lower the importance of mv-list-item to only be pertinent to for cases where (i) you have more than one child of the mv-list or (ii) you want to put attributes on the individual elements. (actually it isn't necessary for 2; you could allow those attributes without adding mv-list-item.) But maybe it is useful for clarity.

  • Otherwise, the mv-list attribute is added to the parent

    • If mv-list and its corresponding mv-list-item do not have the same property name:
  • If one is present and the other one is missing, it is copied to the other one

  • If they are different, mv-list has priority

what exactly does priority mean? does the inner name get ignored? wouldn't it make more sense for both names to instantiate? in the simple case of one mv-list-item child both names would represent the same collection. in the more complex situation of two different-property children, i had suggested having one collection for each property plus a union collection for the mv-list property?

Looking at your code, the questions that arise seem to be:

  • What to do with multiple mv-list-item elements with the same name and the same parent?

    • Does it make a difference if they are adjacent or not?
    • Does it make a difference if their parent has mv-list?
    • I think the way this was handled with mv-multiple was a mistake and caused a great deal of internal complexity for little UX benefit. That said, it would be great if rendered Mavo code could be fed back to Mavo and create the same schema (idempotency), though since there is no way to guarantee that the adjacent items actually use the same template, I'm not sure it's worth it.
  • What to do with multiple mv-list-item elements with different names?
  • Any other questions?