[csswg-drafts] [css-values-5][various] Better handling of arguments with commas (#9539)

tabatkins has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-values-5][various] Better handling of arguments with commas ==
We've got several in-flight proposals for functions that can take "whole property value" arguments, like `mix()`, `random-item()`, etc. (And now custom functions and mixins, which @mirisuzanne and I are looking into more seriously again.)  Because these arguments can potentially contain commas (say, mixing between two background-image lists), we can't use commas as the argument separator, and the proposals currently all use *semicolons* as the separator instead, as this is guaranteed to never show up at the top-level of a property value.

Even tho I'm the one that started this trend, I don't like it. ^_^ I'd like to find a different solution. The problems are:

* It's obviously a bit inconsistent with existing functions. It's not *terrible*, but it's not good either.
* A lot of userland tools use very simplistic parsers, and divide properties by just splitting on semicolons. This'll break them until they rewrite to be aware of nesting levels for matched parens.
* *Most* uses of these functions don't need the special separator; it's only the rare uses that involve operating on an entire comma-separated list that do. Forcing people to do a weird thing for a case they'll rarely hit isn't great.
* It's not forward-compatible in some cases. We have to design this syntax into the function right from the beginning, and can't ever expand an existing comma-separated function into it (unless we do a grammar split, which is nasty in its own way).
* The `var()` function already lets you take this kind of argument, but because its syntax was designed to take only one, and as the final argument, it can continue to use comma separation. (That is, you can write `var(--foo, blue, red, black)` - that's two args, a `-foo` and a `blue, red, black` list.)

The obvious solution is to add an optional *wrapper* around arguments, which will "hide" the commas from the outer function. It would only be necessary when someone is *actually* passing a comma-separated argument.

I have two possible suggestions, and am happy with either:

* Use `[]`, like `background: mix(50%, url(start), [ url(foo), url(bar) ]);`
* Use a new, generically named function, like `item()`: `background: mix(50%, url(start), item( url(foo), url(bar) ));`

This notation would only be allowed in the functions that can take these problematic values, and if present, would be stripped for the purpose of the actual value. No nesting - if you were mixing a subgridded "line names only" value for grid-template-columns, for example, you'd write it as `grid-template-columns: mix(50%, [[foo bar]], [[baz qux]])`, so the outer `[]` gets stripped and the inner `[]` is part of the actual value.

(I'm rejecting using naked `()` for the same reason we ended up switching away from them for grid lines - it would mess up Sass syntax, and possibly others, *hardcore*, since in Sass it indicates math. I'm rejecting `{}` for "naive userland tools" reasons; again, many just split the text with regexes, and stray `{}` can screw them up. They're already potentially broken for custom props containing these chars, of course, but that's not an official Part Of CSS like this would be.)

Thoughts?

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9539 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Monday, 30 October 2023 18:30:20 UTC