From d8dc66fd39d9ef1416fa1c962adc12f75ba04f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ria=20Jur=C4=8Dovi=C4=8Dov=C3=A1?= Date: Thu, 3 Jul 2014 10:33:15 +0200 Subject: [PATCH 1/4] Update detached-rulesets.md Added scoping details and small introduction with simplest possible example. --- content/features/detached-rulesets.md | 131 +++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/content/features/detached-rulesets.md b/content/features/detached-rulesets.md index 20a1903f..dc9d6793 100644 --- a/content/features/detached-rulesets.md +++ b/content/features/detached-rulesets.md @@ -2,7 +2,29 @@ Released [v1.7.0]({{ less.master }}CHANGELOG.md) -You may want to define a mixin that will abstract out either wrapping a piece of code in a media query or a non supported browser class name. You can now pass rulesets to mixins so that the mixin can wrap the content. E.g. +Detached ruleset is a group of css properties, nested rulestes, media declarations or anything else stored in a variable. You can include it into a ruleset or another structure and all its properties are going to be copied there. You can also use it as a mixin argument and pass it around as any other variable. + +Simple example: +````less +// declare detached ruleset +@detached-ruleset: { background: red; }; + +// use detached ruleset +.top { + @detached-ruleset(); +} +```` + +compiles into: +````css +.top { + background: red; +} +```` + +Parentheses after detached ruleset call are mandatory. The `@detached-ruleset;` call would NOT work. + +It is usefull when you want to define a mixin that abstracts out either wrapping a piece of code in a media query or a non supported browser class name. The rulesets can be passed to mixin so that the mixin can wrap the content. E.g. ```less .desktop-and-old-ie(@rules) { @@ -69,3 +91,110 @@ which will output } } ``` + +## Scoping +Detached ruleset can use all variables and mixins accessible on place where it is *defined* and where it is *called*. Otherwise said, both definition and caller scopes are available to it. If both scopes contains the same variable or mixin, declaration scope value takes precedence. + +*Declaration scope* is the one where detached ruleset body is defined. Copying detached ruleset from one variable into another can not modify its scope. Ruleset does not gain access to new scopes just by being referenced there. + +Lastly, detached ruleset can gain access to scope by being unlocked (imported) into it. + +#### Definition and Caller Scope Visibility +Detached mixin sees callers variables and mixins: +````less +@detached-ruleset: { + caller-variable: @callerVariable; // variable is undefined here + .callerMixin(); // mixin is undefined here +}; + +selector { + // use detached ruleset + @detached-ruleset(); + + // define variable and mixin needed inside the detached ruleset + @callerVariable: value; + .callerMixin() { + variable: declaration; + } +} +```` + +compiles into: +````css +selector { + caller-variable: value; + variable: declaration; +} +```` + +Variable and mixins accessible form definition win over those available in caller: +````less +@variable: global; +@detached-ruleset: { + //will use global variable, because it is accessible + //from detached-ruleset definition + variable: @variable; +}; + +selector { + @detached-ruleset(); + @variable: value; //variable defined in caller - will be ignored +} +```` + +compiles into: +````css +selector { + variable: global; +} +```` + +#### Referencing WONT Modify Detached Ruleset Scope +Ruleset does not gain access to new scopes just by being referenced there: +````less +@detached-1: { scope-detached: @one @two; }; +.one { + @one: visible; + .two { + @detached-2: @detached-1; // copying/renaming ruleset + @two: visible; // ruleset can not see this variable + } +} + +.usePlace { + .one > .two(); + @detached-2(); +} +```` + +throws an error: +```` +ERROR 1:32 The variable "@one" was not declared. +```` + +#### Unlocking WILL Modify Detached Ruleset Scope +Detached ruleset gains access by being unlocked (imported) inside a scope: +````less +#space { + .importer1() { + @detached: { scope-detached: @variable; }; // define detached ruleset + } +} + +.importer2() { + @variable: value; // unlocked detached ruleset CAN see this variable + #space > .importer1(); // unlock/import detached ruleset +} + +.usePlace { + .importer2(); // unlock/import detached ruleset second time + @detached(); +} +```` + +compiles into: +````css +.usePlace { + scope-detached: value; +} +```` From e4616420e3c9b55a524589cb7c26bd4c39fcf579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ria=20Jur=C4=8Dovi=C4=8Dov=C3=A1?= Date: Thu, 3 Jul 2014 10:45:42 +0200 Subject: [PATCH 2/4] Update mixins-as-functions.md Added details about scope protection and information about return mixins. --- content/features/mixins-as-functions.md | 50 +++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/content/features/mixins-as-functions.md b/content/features/mixins-as-functions.md index 80d626fa..2f505c1f 100644 --- a/content/features/mixins-as-functions.md +++ b/content/features/mixins-as-functions.md @@ -1,6 +1,6 @@ -> Return variables from mixins +> Return variables or mixins from mixins -All variables defined in a mixin are visible and can be used in caller's scope (unless the caller defines its own variable with the same name). +Variables and mixins defined in a mixin are visible and can be used in caller's scope. There is only one exception, variable is not copied if the caller defines its own variable with the same name. Only variables present in callers local scope are protected. Variables inherited from parent scopes are overridden. Example: @@ -47,4 +47,48 @@ Results in: div { padding: 33px; } -``` \ No newline at end of file +``` + +Variable defined directly in callers scope can not be overriden. However, variable defined in callers parent scope is not protected and be overriden. +````less +.mixin() { + @size: in-mixin; + @definedOnlyInMixin: in-mixin; +} + +.class { + margin: @size @definedOnlyInMixin; + .mixin(); +} + +@size: globaly-defined-value; // callers parent scope - no protection +```` + +Results in: +````css +.class { + margin: in-mixin in-mixin; +} +```` + +Finally, mixin defined in mixin acts as return value too: +````less +.unlock(@value) { // outer mixin + .doSomething() { // nested mixin + declaration: @value; + } +} + +#namespace { + .unlock(5); // unlock doSomething mixin + .doSomething(); //nested mixin was copied here and is usable +} +```` + +Results in: +````css +#namespace { + declaration: 5; +} +```` + From f5a194d462c12d3d2d6159e804c415665b9481a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ria=20Jur=C4=8Dovi=C4=8Dov=C3=A1?= Date: Thu, 3 Jul 2014 10:46:32 +0200 Subject: [PATCH 3/4] Update mixins-as-functions.md fixed typo --- content/features/mixins-as-functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/features/mixins-as-functions.md b/content/features/mixins-as-functions.md index 2f505c1f..9da57911 100644 --- a/content/features/mixins-as-functions.md +++ b/content/features/mixins-as-functions.md @@ -49,7 +49,7 @@ div { } ``` -Variable defined directly in callers scope can not be overriden. However, variable defined in callers parent scope is not protected and be overriden. +Variable defined directly in callers scope can not be overriden. However, variable defined in callers parent scope is not protected and will be overriden: ````less .mixin() { @size: in-mixin; From f945fa6948c69b5a84e402bc8eb8b2ead2735cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ria=20Jur=C4=8Dovi=C4=8Dov=C3=A1?= Date: Thu, 3 Jul 2014 10:50:51 +0200 Subject: [PATCH 4/4] Update detached-rulesets.md --- content/features/detached-rulesets.md | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/content/features/detached-rulesets.md b/content/features/detached-rulesets.md index dc9d6793..d9f2e70a 100644 --- a/content/features/detached-rulesets.md +++ b/content/features/detached-rulesets.md @@ -92,6 +92,40 @@ which will output } ``` +Detached ruleset call unlocks (returns) all its mixins into caller the same way as mixin calls do. However, it does NOT return variables. + +Returned mixin: +````less +// detached ruleset with a mixin +@detached-ruleset: { + .mixin() { + color:blue; + } +}; +// call detached ruleset +.caller { + @detached-ruleset(); + .mixin(); +} +```` + +Results in: +````css +.caller { + color: blue; +} +```` + +Private variables: +````less +detached-ruleset: { + @color:blue; //this variable is private +}; +.caller { + color: @color; //syntax error +} +```` + ## Scoping Detached ruleset can use all variables and mixins accessible on place where it is *defined* and where it is *called*. Otherwise said, both definition and caller scopes are available to it. If both scopes contains the same variable or mixin, declaration scope value takes precedence.