Skip to content

Instantly share code, notes, and snippets.

@calvinjuarez
Last active August 29, 2015 14:19
Show Gist options
  • Save calvinjuarez/5900c072b19e45677e98 to your computer and use it in GitHub Desktop.
Save calvinjuarez/5900c072b19e45677e98 to your computer and use it in GitHub Desktop.
Less Value Accessors: `@{}` & `${}`

Less Value Accessors: @{} & ${}

The files here provide examples of the variable and property accessor syntax currently being discussed at less.js#1848.

@{ #ns > var }
${ prop }
${ #ns > prop }

Roadmap for Implementation

  1. Enable accessing namespaced variables with @{#ns var} (see accessor.initial.less, #1848).
  2. Enable accessing local and namespaced properties with, $prop, ${prop} and ${#ns prop} (see #2433, #76, #6).
  3. In the next major version, enable syntax sugar #ns@var, and #ns$prop, allowed where plain variables (e.g. @var) are allowed.

Files

  • accessor.initial.less Summarizes the minimum feature, enabling accessing namespaced variables. Safe for immediate implementation.
  • accessor.summary.less The full proposed feature, including accessing namespaced variables as well as local and namespaced properties, and some syntax sugar.
/**
* Less Value Accessors | Initial Proposal: Extend `@{}`
*
* Proposed for immediate implementation, `@{}` is extended to allow
* referencing namespaced variables.
*/
#ns() {
@var: bar;
.kid {
@var: baz;
}
}
.selector {
@var: foo;
// BASIC USE
// -----
// accessing a locally available variable is the same as always
local-var: @var; // → foo
// accessing variables from namespaces (or mixins or basic rulesets)
ns-var: @{ #ns > var }; // → bar
ns-var: @{ #ns>var }; // → bar
ns-var: @{ #ns var }; // → bar
// accessing variables from child namespaces (or mixins or basic rulesets)
ns-kid-var: @{ #ns.kid var }; // → baz
// INTERPOLATION
// -----
// interpolating a locally available variable is the same as always
.@{var} { /* ... */ } // → .foo
// interpolating an accessed variable requires `${}`
.@{#ns var} { /* ... */ } // → .bar
// interpolation is allowed wherever variable interpolation is allowed
background: url("path/@{#ns var}/img.png"); // → url("path/bar/img.png")
}
// OVERRIDING
// -----
#ns() { // overriding is straight-forward
@var: qux;
}
.selector {
.@{#ns var} { /* ... */ } // → .qux
}
/**
* Less Value Accessors | Summary: Variable & Property Access + Sugar
*
* In addition to the extended variable reference syntax (`@{}`), a property
* reference syntax would be introduced to allow direct access to both local
* and namespaced properties. This syntax would be nearly identical to the
* variable reference syntax, but with a different symbol. `$` is proposed.
*
* The syntax sugar would have to wait for the next major version because of
* ambiguity concerning color hexes (`#abc@var` → `#aabbcc [value]` atm; see
* https://github.com/less/less.js/issues/1848#issuecomment-96118255).
*/
#ns() {
@var: bar;
prop: bar;
.kid {
@var: baz;
prop: baz;
}
}
.selector {
@var: foo;
prop: foo;
// BASIC USE
// -----
// accessing a locally available variable is the same as always
local-var: @var; // → foo
// accessing local properties
local-prop: ${ prop }; // → foo
local-prop: $prop; // → foo // alternate syntax (sugar)*
// accessing variables from namespaces (or mixins or rules)
ns-var: @{ #ns > var }; // → bar
ns-var: @{ #ns>var }; // → bar
ns-var: @{ #ns var }; // → bar // whitespace or `>` required**
ns-var: #ns@var; // → bar // alternate syntax (sugar)*
// accessing properties from namespaces (or mixins or rules)
ns-prop: ${ #ns > prop }; // → bar
ns-prop: ${ #ns>prop }; // → bar
ns-prop: ${ #ns prop }; // → bar // whitespace or `>` required**
ns-prop: #ns$prop; // → bar // alternate syntax (sugar)*
// accessing variables or properties from nested namespaces
ns-kid-var: @{ #ns.kid var }; // → baz
ns-kid-prop: ${ #ns.kid prop }; // → baz
// * Alternate syntaxes are allowed wherever `@var` is allowed.
// ** The ambiguity of `@{ #nsvar }` and `${ #nsprop }` make them impractical to implement;
// they should throw an error.
// INTERPOLATION
// -----
// interpolating a locally available variable is the same as always
.@{var} { /* ... */ } // → .foo
// interpolating a local property (always requires `${}`)
.${prop} { /* ... */ } // → .foo
// interpolating an accessed variable or property (always requires `@{}` or `${}`)
.@{#ns var} { /* ... */ } // → .bar
.${#ns prop} { /* ... */ } // → .bar
// interpolation is allowed wherever variable interpolation is allowed
background: url("path/@{#ns var}/img.png"); // → url("path/bar/img.png")
}
// OVERRIDING
// -----
#ns() { // overriding is straight-forward
@var: qux;
}
.selector {
.@{#ns var} { /* ... */ } // → .qux
}
@matthew-dean
Copy link

What if we allowed the interpolation form to return a reference to just the namespace?

@buttons: ${#ns.lib.ui.buttons};
.selector {
  color: @buttons$color;
  color: ${@buttons color};  // interpolation
}

Only thing is, this would serve this feature, but if you wanted to reference a selector for some other feature, element names vs. vars or props would be ambiguous. Unless we require explicit referencing within the interpolated form. e.g.

  ns-kid-var:  @{ #ns.kid @var };  
  ns-kid-prop: ${ #ns.kid $prop }; 

Of course, that makes it a bit redundant. OR maybe a different form to point to just the namespace?

@buttons: $[#ns.lib.ui.buttons];  // $[ ]  - selector reference
.selector {
  color-v1: @buttons$color;
  color-v2: @buttons > $color;
  color-v3: ${@buttons color}; 
}

@calvinjuarez
Copy link
Author

I don't know. It seems like it may overcomplicate things, using the same symbol for selector reference and property access. I do think it's important to be able to save selectors, though. I'm not sure how that'd be accomplished, though. But it seems like that could be just a function.

@buttons: selref(#ns.lib.ui.buttons)

The function could be a lot of things, and would provide a more semantic way to denote what's happening: sel(), selref(), sref(), selector(), etc. I think a function would be appropriate, since I think the readability benefit is worth the extra characters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment