mavo
mavo copied to clipboard
Allow for multiple properties per element
Allowing multiple properties per element is a common ask.
One idea for syntax is to replace property
and mv-attribute
with:
Instead of | I'd have |
---|---|
<E property="foo"> (default) |
<E mv-name="foo"> OR <E mv-data="as foo"> |
<E property="foo" mv-attribute="none"> |
<E mv-name="foo" mv-data="content"> OR <E mv-data="content as foo"> |
<E property="foo" mv-attribute="bar"> |
<E mv-name="foo" mv-data="@bar"> OR <E mv-data="@bar as foo"> |
<E property="foo" mv-attribute="jsProp"> |
<E mv-name="foo" mv-data=".jsProp"> OR <E mv-data=".jsProp as foo"> |
The benefit of this syntax, besides being more explicit and not having any weird property
attributes, is that it can generalize to holding multiple bits of data per element, a common need:
<a mv-data="content as name, @href as url"></a>
Alternatively, we could introduce a microsyntax like expressions, that goes right in the place where data will go, akin to templating languages:
Instead of | Maybe |
---|---|
<E property="foo"> (default) |
<E mv-value="{{foo}}"> |
<E property="foo" mv-attribute="none"></E> |
<E>{{foo}}</E> |
<E property="foo" mv-attribute="bar"></E> |
<E bar="{{ bar }}"> |
<E property="foo" mv-attribute="jsProp"></E> |
<E .jsProp="{{ bar }}"> |
Note that both syntaxes also allow for JS properties to be observed (and there should be a way to optionally specify how to observe changes to them).
Both of these syntaxes have the same problem: how do you specify other metadata about each property (e.g. mv-default
, mv-edit
, mv-edit-*
etc)? Currently we use attributes on the element. When there are multiple properties on it, how will that work?
- The attributes could only specify metadata for the first property, which will be seen as a "main" one
- The attributes can extend to comma-separated lists, akin to how CSS properties become list-ified.
- Dmitry’s proposal:
<a mv-data="content as name, @href as URL" mv-edit="#foo for URL"></a>
- Something else?
As for me, I would stick to the first variant: the code looks much more like native HTML, and if an author decides to integrate Mavo with other third-party libraries that already use similar templating language (e.g., 11ty), they will not conflict with each other. However, we can always provide something similar to mv-expressions
for such cases.
The attributes can extend to comma-separated lists, akin to how CSS properties become list-ified
I vote for letting an author control each property of a multi-properties-elements. One thought. Suppose I have an element with 3 properties. I wonder, what if I want to set metadata for the last property? Should I explicitly specify two commas before the value for the third property? What if we have something similar to the destructuring assignment in JS? I am not sure about the easy to follow syntax, though.
Or we can use the idea implemented in CSS Grid for areas that need to be skipped in the grid-template-areas
: use some special character for properties that must be skipped?
Suddenly I came up with this: <a mv-data="content as name, @href as URL" mv-edit="#foo for URL"></a>
.
I suppose, in that case, we won't have to invent special symbols for “gaps” and a new syntax for destructuring, and we won't be limited by specifying metadata only for a “main” property.
I like that idea, though it can get repetitive. Perhaps a combination would be best.
A while ago, we had a discussion with @karger where I explored the idea of whether it would be possible to somehow merge expressions and property definitions. Many Mavo novices confuse the two, and things like <a href="[foo]" property="foo">
are also quite common. I also don't like the indirectness of mv-attribute="foo"
instead of being able to directly put something in the attribute to say "here, my data goes here!".
Here's what @karger said, including it here for posterity:
I was thinking more about your interesting ideas for mavo data. Lots of complex facets but here are thoughts on a couple.
We discussed the tension that in the location of a property you sometimes want to name the property but other times you want to specify its value. So let's allow both. Consider using colon as a "property definition" syntax. Any place that allows a mavo expression will also allow x:foo where x is a symbol and foo is an expression. The expression evaluates to the value of foo but it also defines x as a property of the current object with initial value foo. So I can write
<div property="a"> <a href="[x: 3+12]"> ...
which defines x as a property of object a with initial value 15
Note this is also consistent with your current group(x: 17, y: 10) syntax if you just think of group as specifying the creation of a new object/scope . It's also consistent with json.
I can also just use the syntax
[x:]
to define a property with no (default) value.Turning to the idea of being able to edit a property in multiple places. We already have the ability to refer to an entity in multiple places. E.g. if I write [a.b.c] it refers to the c entity in the a.b scope. c might be an object or a primitive (but we've talked about unifying primitives with objects). So the only issue is enriching the syntax to specify whether (i) what is here is a reference to the original object or a copy (or a deep copy) and (ii) whether it is editable. Of course if the object (and its parts) is not editable then it doesn't matter whether it is the same object or a copy. But if it editable I need to know whether I'm editing the original or a copy. We already have mv-mode to specify edit vs. read. If we want the default to be a copy then I can use e.g. xref(x) to indicate a cross-reference to x. Alternatively if I want to default to a reference I can use copy(x) to indicate a copy.
One issue with that syntax is that it's unclear whether the expression after the colon declares a default value or a computed property. I suppose the actual difference between the two is editability: computed properties are not editable, whereas properties with a computed default value are. So perhaps we should just decouple editability.
A few more issues:
- we currently we have two bits of data that make sense to go in the data attribute: property name, default/computed value. In the future however we may have more e.g. #260
- A pattern like this would force us to have different syntax for groups, when we are hoping to merge them (#590)
It also needs to be unambiguous. Can I use it where there are other colons, like
<div property="a"> <a href="http://domain/[x: 3+12]">