less.js icon indicating copy to clipboard operation
less.js copied to clipboard

Rulesets as property values (to be parsed as ~DRs).

Open seven-phases-max opened this issue 6 years ago • 1 comments

After a more relaxed parsing of property-value rules introduced in recent Less version the following code is now "valid" (i.e. compiles w/o errors):

@values: {
    bar: {a: b};
    baz: {c: d};
};

It would not be unexpected for someone to think this code is basically a map similar to:

@values: {
    @bar: {a: b};
    @baz: {c: d};
};

except the obvious property/variable difference.

So that the one would expect similar behavior of both structures in snippets like:

result: @values[bar][a];
// or
each(@values, ...

Currently however, everything inside @values (of the property-based snipped) results in a single anonymous-like value.


So the feature request is to parse bar: {a: b}; just like @bar: {a: b}; is parsed (Implementation details may vary, e.g. it does not have to be a DR, just whatever map/each compatible rule-value->ruleset structure would be fine I think).


(To illustrate the use-case) I stepped into this when writing an answer for this SO Q: https://stackoverflow.com/a/55304379/2712740 Basically there it would be reasonable (in a perfect world) to expect one (me for example) to prefer to use light/dark instead of @light/@dark just to minimize the @-noise and to get rid of the weird things like replace(@key, '@', '.');). But the primary idea is about consistency (it's not this or another specific use-case is really important).

seven-phases-max avatar Mar 22 '19 17:03 seven-phases-max

Yeah, the reasons for the relaxed parsing was essentially forwards-compatibility and less fragility of the parser. That is, to treat any chunk that was not explicitly Less-targeted to be something for the browser to either accept or discard. In other words, if Less can recover, it does recover, and not make Less the job of an up-to-spec linter, for which there are much better tools.

Mostly this came about when I refactored for custom properties, but there were some legacy issues where valid, newer (or experimental) syntax wouldn't parse. I think I also ran into issues with making stylesheets for SVG, I can't recall.

Maybe I was being over-cautious and it should still throw errors, but yeah, I'm inclined to agree that we could just treat those as maps, now that a ruleset can be used for output or used as data.

The difference between bar: {a: b}; and @bar: {a: b};, as you note, is that the latter attempts to parse the value as a Detached Ruleset (or anonymous mixin, whatever your terminology). A regular property value (including a custom property), doesn't have DetachedRuleset as one of its rules. Basically it tries to parse as an expression, and when that doesn't work, it bails and tries to parse the remainder of the value as an anonymous value, which is basically almost anything terminating in a semi-colon.

It would probably be a simple matter of adding the same rules as @bar:. Seems like we could align @bar: and bar:, but --bar: gets tricky because it's so loose. Buuuuut that said, all 3 could try a few valid expression paths first, then ruleset, and then bail to the --bar: logic, and then only if that fails, bail to the anonymous value logic.

I think it's a good callout that all prop / value declarations should probably be in sync at this point.

matthew-dean avatar Mar 22 '19 22:03 matthew-dean